From 42049f130f86f64dba92aff29eb7d2579caf1a17 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Sat, 27 Jan 2024 15:56:04 +0200 Subject: [PATCH 1/2] fix: Fix CalendarView infinite loop --- src/Uno.UI.Tests/Windows_Globalization/When_Calendar.cs | 2 +- src/Uno.UI/DirectUI/DateComparer.cs | 9 ++++++++- .../Controls/CalendarView/CalendarViewGeneratorHost.cs | 9 +++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Uno.UI.Tests/Windows_Globalization/When_Calendar.cs b/src/Uno.UI.Tests/Windows_Globalization/When_Calendar.cs index ef93ff33c4ea..4784bd0d8258 100644 --- a/src/Uno.UI.Tests/Windows_Globalization/When_Calendar.cs +++ b/src/Uno.UI.Tests/Windows_Globalization/When_Calendar.cs @@ -26,7 +26,7 @@ public void When_DateTimeOffset_Is_Next_Day_If_Converted_To_Utc() var comparer = new DirectUI.DateComparer(); comparer.SetCalendarForComparison(calendar); var result = comparer.CompareDay(offset, new DateTimeOffset(year: 2023, month: 5, day: 1, hour: 4, minute: 0, second: 0, TimeSpan.FromHours(0))); - Assert.AreEqual(0, result); + Assert.AreEqual(1, result); } [TestMethod] diff --git a/src/Uno.UI/DirectUI/DateComparer.cs b/src/Uno.UI/DirectUI/DateComparer.cs index 8fbb3aa90745..0af7e57fe913 100644 --- a/src/Uno.UI/DirectUI/DateComparer.cs +++ b/src/Uno.UI/DirectUI/DateComparer.cs @@ -103,7 +103,14 @@ private int CompareDate( global::System.Diagnostics.Debug.Assert(m_spCalendar is { }); - long delta = lhs.ToUniversalTime().Ticks - rhs.ToUniversalTime().Ticks; + // Uno specific: In WinUI, wf::DateTime is a struct that only has "UniversalTime" field. + // So, we need to call ToUniversalTime here. + // Failure to do so can cause issues when comparing dates like 2024/01/01 10:00:00 PM UTC+2 and 2024/01/02 12:00:00 AM UTC + // Both dates should be equal, but getUnit will return 1 and 2 indicating that the first date is smaller. + lhs = lhs.ToUniversalTime(); + rhs = rhs.ToUniversalTime(); + + long delta = lhs.Ticks - rhs.Ticks; if (delta < 0) { delta = -delta; diff --git a/src/Uno.UI/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.cs b/src/Uno.UI/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.cs index 6505fd1d6e3a..e7ca7328e81d 100644 --- a/src/Uno.UI/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.cs +++ b/src/Uno.UI/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.cs @@ -281,7 +281,7 @@ internal void ComputeSize() { int index = 0; - m_lastVisitedDateAndIndex.first = Owner.MinDate; + m_lastVisitedDateAndIndex.first = Owner.MinDate.ToUniversalTime(); m_lastVisitedDateAndIndex.second = 0; global::System.Diagnostics.Debug.Assert(!Owner.DateComparer.LessThan(Owner.MaxDate, Owner.MinDate)); @@ -332,10 +332,10 @@ internal DateTime GetDateAt(uint index) pCalendar.SetDateTime(m_lastVisitedDateAndIndex.first); AddUnits((int)(index) - m_lastVisitedDateAndIndex.second); - date = pCalendar.GetDateTime(); + date = pCalendar.GetDateTime().ToUniversalTime(); m_lastVisitedDateAndIndex.first = date; m_lastVisitedDateAndIndex.second = (int)(index); - var pDate = date; // .ToUniversalTime() - UNO + var pDate = date; return pDate; } @@ -350,7 +350,8 @@ internal DateTime GetDateAt(uint index) internal int CalculateOffsetFromMinDate(DateTime date) { var pIndex = 0; - DateTime estimatedDate = m_lastVisitedDateAndIndex.first; //.ToUniversalTime(); - UNO + DateTime estimatedDate = m_lastVisitedDateAndIndex.first.ToUniversalTime(); + var pCalendar = GetCalendar(); global::System.Diagnostics.Debug.Assert(m_lastVisitedDateAndIndex.second != -1); From 62d492e53cf3b5f2b15d03ce3e54002d27f3e8c3 Mon Sep 17 00:00:00 2001 From: Youssef Victor Date: Thu, 1 Feb 2024 18:56:07 +0200 Subject: [PATCH 2/2] test: Add test for infinite loop issue --- .../Windows_UI_Xaml_Controls/Given_CalendarView.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_CalendarView.cs b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_CalendarView.cs index dce7f8d8b009..b7327016f973 100644 --- a/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_CalendarView.cs +++ b/src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_CalendarView.cs @@ -22,6 +22,16 @@ namespace Uno.UI.RuntimeTests.Tests.Windows_UI_Xaml_Controls; [RunsOnUIThread] public class Given_CalendarView { + [TestMethod] + public async Task When_MinDate_Has_Different_Offset() + { + var calendarView = new CalendarView(); + calendarView.MinDate = new DateTimeOffset(new DateTime(2010, 1, 1, 22, 0, 0), TimeSpan.Zero); + calendarView.MaxDate = new DateTimeOffset(new DateTime(2010, 1, 31), TimeSpan.FromHours(2)); + + await UITestHelper.Load(calendarView); + } + #if __WASM__ [TestMethod] public async Task When_ItemCornerRadius()