Speeding up the UI by changing the flip view orientation at correct moment.

This commit is contained in:
Burak Kaan Köse
2025-01-07 20:51:10 +01:00
parent dfb83cc1f7
commit 12d87be106
6 changed files with 70 additions and 49 deletions

View File

@@ -31,9 +31,7 @@ namespace Wino.Calendar.ViewModels
IRecipient<CalendarSettingsUpdatedMessage>, IRecipient<CalendarSettingsUpdatedMessage>,
IRecipient<CalendarItemTappedMessage>, IRecipient<CalendarItemTappedMessage>,
IRecipient<CalendarItemDoubleTappedMessage>, IRecipient<CalendarItemDoubleTappedMessage>,
IRecipient<CalendarItemRightTappedMessage>, IRecipient<CalendarItemRightTappedMessage>
IRecipient<CalendarDisplayTypeChangedMessage>
{ {
#region Quick Event Creation #region Quick Event Creation
@@ -94,7 +92,8 @@ namespace Wino.Calendar.ViewModels
#region Data Initialization #region Data Initialization
public bool IsVerticalCalendar => StatePersistanceService.CalendarDisplayType == CalendarDisplayType.Month; [ObservableProperty]
private CalendarOrientation _calendarOrientation = CalendarOrientation.Horizontal;
[ObservableProperty] [ObservableProperty]
private DayRangeCollection _dayRanges = []; private DayRangeCollection _dayRanges = [];
@@ -331,6 +330,8 @@ namespace Wino.Calendar.ViewModels
!(message.DisplayDate >= DayRanges.DisplayRange.StartDate && message.DisplayDate <= DayRanges.DisplayRange.EndDate)); !(message.DisplayDate >= DayRanges.DisplayRange.StartDate && message.DisplayDate <= DayRanges.DisplayRange.EndDate));
} }
public async void Receive(LoadCalendarMessage message) public async void Receive(LoadCalendarMessage message)
{ {
await _calendarLoadingSemaphore.WaitAsync(); await _calendarLoadingSemaphore.WaitAsync();
@@ -343,6 +344,23 @@ namespace Wino.Calendar.ViewModels
{ {
Debug.WriteLine("Will reset day ranges."); Debug.WriteLine("Will reset day ranges.");
await ClearDayRangeModelsAsync(); await ClearDayRangeModelsAsync();
// Orientation only changes when we should reset.
// Handle the FlipView orientation here.
// We don't want to change the orientation while the item manipulation is going on.
// That causes a glitch in the UI.
bool isRequestedVerticalCalendar = StatePersistanceService.CalendarDisplayType == CalendarDisplayType.Month;
bool isLastRenderedVerticalCalendar = _currentDisplayType == CalendarDisplayType.Month;
if (isRequestedVerticalCalendar && !isLastRenderedVerticalCalendar)
{
CalendarOrientation = CalendarOrientation.Vertical;
}
else
{
CalendarOrientation = CalendarOrientation.Horizontal;
}
} }
else if (ShouldScrollToItem(message)) else if (ShouldScrollToItem(message))
{ {
@@ -490,7 +508,7 @@ namespace Wino.Calendar.ViewModels
CalendarLoadDirection animationDirection = calendarLoadDirection; CalendarLoadDirection animationDirection = calendarLoadDirection;
bool removeCurrent = calendarLoadDirection == CalendarLoadDirection.Replace; //bool removeCurrent = calendarLoadDirection == CalendarLoadDirection.Replace;
if (calendarLoadDirection == CalendarLoadDirection.Replace) if (calendarLoadDirection == CalendarLoadDirection.Replace)
{ {
@@ -524,7 +542,7 @@ namespace Wino.Calendar.ViewModels
// Wait for the animation to finish. // Wait for the animation to finish.
// Otherwise it somehow shutters a little, which is annoying. // Otherwise it somehow shutters a little, which is annoying.
if (!removeCurrent) await Task.Delay(350); // if (!removeCurrent) await Task.Delay(350);
// Insert each render model in reverse order. // Insert each render model in reverse order.
for (int i = renderModels.Count - 1; i >= 0; i--) for (int i = renderModels.Count - 1; i >= 0; i--)
@@ -540,10 +558,10 @@ namespace Wino.Calendar.ViewModels
Debug.WriteLine($"- {item.CalendarRenderOptions.DateRange.ToString()}"); Debug.WriteLine($"- {item.CalendarRenderOptions.DateRange.ToString()}");
} }
if (removeCurrent) //if (removeCurrent)
{ //{
await RemoveDayRangeModelAsync(SelectedDayRange); // await RemoveDayRangeModelAsync(SelectedDayRange);
} //}
// TODO... // TODO...
// await TryConsolidateItemsAsync(); // await TryConsolidateItemsAsync();
@@ -737,14 +755,14 @@ namespace Wino.Calendar.ViewModels
// Therefore we wait for semaphore to be released before we continue. // Therefore we wait for semaphore to be released before we continue.
// There is no need to load more if the current index is not in ideal position. // There is no need to load more if the current index is not in ideal position.
if (SelectedDateRangeIndex == DayRanges.Count - 1) if (SelectedDateRangeIndex == 0)
{
await RenderDatesAsync(CalendarInitInitiative.App, calendarLoadDirection: CalendarLoadDirection.Next);
}
else if (SelectedDateRangeIndex == 0)
{ {
await RenderDatesAsync(CalendarInitInitiative.App, calendarLoadDirection: CalendarLoadDirection.Previous); await RenderDatesAsync(CalendarInitInitiative.App, calendarLoadDirection: CalendarLoadDirection.Previous);
} }
else if (SelectedDateRangeIndex == DayRanges.Count - 1)
{
await RenderDatesAsync(CalendarInitInitiative.App, calendarLoadDirection: CalendarLoadDirection.Next);
}
} }
catch (Exception) catch (Exception)
{ {
@@ -839,7 +857,5 @@ namespace Wino.Calendar.ViewModels
// var calendarItems = GetCalendarItems(deletedItem.Id); // var calendarItems = GetCalendarItems(deletedItem.Id);
}); });
} }
public void Receive(CalendarDisplayTypeChangedMessage message) => OnPropertyChanged(nameof(IsVerticalCalendar));
} }
} }

View File

@@ -71,6 +71,8 @@ namespace Wino.Calendar.Controls
bool isToday = DayModel.RepresentingDate.Date == DateTime.Now.Date; bool isToday = DayModel.RepresentingDate.Date == DateTime.Now.Date;
VisualStateManager.GoToState(this, isToday ? TodayState : NotTodayState, false); VisualStateManager.GoToState(this, isToday ? TodayState : NotTodayState, false);
UpdateLayout();
} }
} }
} }

View File

@@ -31,16 +31,28 @@ namespace Wino.Calendar.Controls
public static readonly DependencyProperty IsFlipIdleProperty = DependencyProperty.Register(nameof(IsFlipIdle), typeof(bool), typeof(WinoCalendarControl), new PropertyMetadata(true, new PropertyChangedCallback(OnIdleStateChanged))); public static readonly DependencyProperty IsFlipIdleProperty = DependencyProperty.Register(nameof(IsFlipIdle), typeof(bool), typeof(WinoCalendarControl), new PropertyMetadata(true, new PropertyChangedCallback(OnIdleStateChanged)));
public static readonly DependencyProperty ActiveScrollViewerProperty = DependencyProperty.Register(nameof(ActiveScrollViewer), typeof(ScrollViewer), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnActiveVerticalScrollViewerChanged))); public static readonly DependencyProperty ActiveScrollViewerProperty = DependencyProperty.Register(nameof(ActiveScrollViewer), typeof(ScrollViewer), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnActiveVerticalScrollViewerChanged)));
public static readonly DependencyProperty VerticalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(VerticalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); public static readonly DependencyProperty VerticalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(VerticalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnCalendarOrientationPropertiesUpdated)));
public static readonly DependencyProperty HorizontalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(HorizontalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); public static readonly DependencyProperty HorizontalItemsPanelTemplateProperty = DependencyProperty.Register(nameof(HorizontalItemsPanelTemplate), typeof(ItemsPanelTemplate), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnCalendarOrientationPropertiesUpdated)));
public static readonly DependencyProperty DisplayTypeProperty = DependencyProperty.Register(nameof(DisplayType), typeof(CalendarDisplayType), typeof(WinoCalendarControl), new PropertyMetadata(CalendarDisplayType.Day, new PropertyChangedCallback(OnIsVerticalCalendarChanged))); public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register(nameof(Orientation), typeof(CalendarOrientation), typeof(WinoCalendarControl), new PropertyMetadata(CalendarOrientation.Horizontal, new PropertyChangedCallback(OnCalendarOrientationPropertiesUpdated)));
public static readonly DependencyProperty DisplayTypeProperty = DependencyProperty.Register(nameof(DisplayType), typeof(CalendarDisplayType), typeof(WinoCalendarControl), new PropertyMetadata(CalendarDisplayType.Day));
/// <summary>
/// Gets or sets the day-week-month-year display type.
/// Orientation is not determined by this property, but Orientation property.
/// This property is used to determine the template to use for the calendar.
/// </summary>
public CalendarDisplayType DisplayType public CalendarDisplayType DisplayType
{ {
get { return (CalendarDisplayType)GetValue(DisplayTypeProperty); } get { return (CalendarDisplayType)GetValue(DisplayTypeProperty); }
set { SetValue(DisplayTypeProperty, value); } set { SetValue(DisplayTypeProperty, value); }
} }
public CalendarOrientation Orientation
{
get { return (CalendarOrientation)GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
public ItemsPanelTemplate VerticalItemsPanelTemplate public ItemsPanelTemplate VerticalItemsPanelTemplate
{ {
get { return (ItemsPanelTemplate)GetValue(VerticalItemsPanelTemplateProperty); } get { return (ItemsPanelTemplate)GetValue(VerticalItemsPanelTemplateProperty); }
@@ -104,7 +116,7 @@ namespace Wino.Calendar.Controls
SizeChanged += CalendarSizeChanged; SizeChanged += CalendarSizeChanged;
} }
private static void OnIsVerticalCalendarChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) private static void OnCalendarOrientationPropertiesUpdated(DependencyObject calendar, DependencyPropertyChangedEventArgs e)
{ {
if (calendar is WinoCalendarControl control) if (calendar is WinoCalendarControl control)
{ {
@@ -134,9 +146,12 @@ namespace Wino.Calendar.Controls
{ {
calendarControl.RegisterScrollChanges(newScrollViewer); calendarControl.RegisterScrollChanges(newScrollViewer);
} }
calendarControl.ManageHighlightedDateRange();
} }
} }
private static void OnActiveCanvasChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e) private static void OnActiveCanvasChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e)
{ {
if (calendar is WinoCalendarControl calendarControl) if (calendar is WinoCalendarControl calendarControl)
@@ -160,29 +175,11 @@ namespace Wino.Calendar.Controls
{ {
if (InternalFlipView == null || HorizontalItemsPanelTemplate == null || VerticalItemsPanelTemplate == null) return; if (InternalFlipView == null || HorizontalItemsPanelTemplate == null || VerticalItemsPanelTemplate == null) return;
bool isHorizontalCalendar = DisplayType == CalendarDisplayType.Day || DisplayType == CalendarDisplayType.Week || DisplayType == CalendarDisplayType.WorkWeek; InternalFlipView.ItemsPanel = Orientation == CalendarOrientation.Horizontal ? HorizontalItemsPanelTemplate : VerticalItemsPanelTemplate;
if (isHorizontalCalendar)
{
InternalFlipView.ItemsPanel = HorizontalItemsPanelTemplate;
}
else
{
InternalFlipView.ItemsPanel = VerticalItemsPanelTemplate;
}
} }
private void ManageHighlightedDateRange() private void ManageHighlightedDateRange()
{ => SelectedFlipViewDayRange = InternalFlipView.SelectedItem as DayRangeRenderModel;
if (ActiveCanvas == null)
{
SelectedFlipViewDayRange = null;
}
else
{
SelectedFlipViewDayRange = InternalFlipView.SelectedItem as DayRangeRenderModel;
}
}
private void DeregisterCanvas(WinoDayTimelineCanvas canvas) private void DeregisterCanvas(WinoDayTimelineCanvas canvas)
{ {

View File

@@ -35,6 +35,7 @@
DayRanges="{x:Bind ViewModel.DayRanges}" DayRanges="{x:Bind ViewModel.DayRanges}"
DisplayType="{x:Bind ViewModel.StatePersistanceService.CalendarDisplayType, Mode=OneWay}" DisplayType="{x:Bind ViewModel.StatePersistanceService.CalendarDisplayType, Mode=OneWay}"
IsHitTestVisible="{x:Bind ViewModel.IsCalendarEnabled, Mode=OneWay}" IsHitTestVisible="{x:Bind ViewModel.IsCalendarEnabled, Mode=OneWay}"
Orientation="{x:Bind ViewModel.CalendarOrientation, Mode=OneWay}"
ScrollPositionChanging="CalendarScrolling" ScrollPositionChanging="CalendarScrolling"
SelectedFlipViewDayRange="{x:Bind ViewModel.SelectedDayRange, Mode=TwoWay}" SelectedFlipViewDayRange="{x:Bind ViewModel.SelectedDayRange, Mode=TwoWay}"
SelectedFlipViewIndex="{x:Bind ViewModel.SelectedDateRangeIndex, Mode=TwoWay}" SelectedFlipViewIndex="{x:Bind ViewModel.SelectedDateRangeIndex, Mode=TwoWay}"

View File

@@ -0,0 +1,8 @@
namespace Wino.Core.Domain.Enums
{
public enum CalendarOrientation
{
Horizontal,
Vertical
}
}

View File

@@ -13,22 +13,19 @@ namespace Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies
public override DateRange GetNextDateRange(DateRange CurrentDateRange, int DayDisplayCount) public override DateRange GetNextDateRange(DateRange CurrentDateRange, int DayDisplayCount)
{ {
return DateTimeExtensions.GetMonthDateRangeStartingWeekday(CurrentDateRange.EndDate, Settings.FirstDayOfWeek); return new DateRange(CurrentDateRange.EndDate, CurrentDateRange.EndDate.AddDays(35));
} }
public override DateRange GetPreviousDateRange(DateRange CurrentDateRange, int DayDisplayCount) public override DateRange GetPreviousDateRange(DateRange CurrentDateRange, int DayDisplayCount)
{ {
return DateTimeExtensions.GetMonthDateRangeStartingWeekday(CurrentDateRange.StartDate, Settings.FirstDayOfWeek); return new DateRange(CurrentDateRange.StartDate.AddDays(-35), CurrentDateRange.StartDate);
} }
public override DateRange GetRenderDateRange(DateTime DisplayDate, int DayDisplayCount) public override DateRange GetRenderDateRange(DateTime DisplayDate, int DayDisplayCount)
{ {
// Load 2 months at first. // Get the first day of the month.
var initialRange = DateTimeExtensions.GetMonthDateRangeStartingWeekday(DisplayDate.Date, Settings.FirstDayOfWeek); var firstDayOfMonth = new DateTime(DisplayDate.Year, DisplayDate.Month, 1);
return DateTimeExtensions.GetMonthDateRangeStartingWeekday(firstDayOfMonth, Settings.FirstDayOfWeek);
var nextRange = GetNextDateRange(initialRange, DayDisplayCount);
return new DateRange(initialRange.StartDate, nextRange.EndDate);
} }
public override int GetRenderDayCount(DateTime DisplayDate, int DayDisplayCount) => 35; public override int GetRenderDayCount(DateTime DisplayDate, int DayDisplayCount) => 35;