Calendar page and shell improvements to support navigations. Enabled page caching.
This commit is contained in:
@@ -21,9 +21,7 @@ namespace Wino.Calendar.ViewModels
|
||||
public partial class AppShellViewModel : CalendarBaseViewModel,
|
||||
IRecipient<VisibleDateRangeChangedMessage>,
|
||||
IRecipient<CalendarEnableStatusChangedMessage>,
|
||||
IRecipient<CalendarInitializedMessage>,
|
||||
IRecipient<NavigateManageAccountsRequested>,
|
||||
IRecipient<GoToCalendarDayMessage>
|
||||
IRecipient<NavigateManageAccountsRequested>
|
||||
{
|
||||
public event EventHandler<CalendarDisplayType> DisplayTypeChanged;
|
||||
public IPreferencesService PreferencesService { get; }
|
||||
@@ -61,13 +59,10 @@ namespace Wino.Calendar.ViewModels
|
||||
[ObservableProperty]
|
||||
private int _selectedDateNavigationHeaderIndex;
|
||||
|
||||
private readonly IAccountService _accountService;
|
||||
|
||||
public bool IsVerticalCalendar => StatePersistenceService.CalendarDisplayType == CalendarDisplayType.Month;
|
||||
|
||||
public AppShellViewModel(IPreferencesService preferencesService,
|
||||
IStatePersistanceService statePersistanceService,
|
||||
IAccountService accountService,
|
||||
INavigationService navigationService,
|
||||
IWinoServerConnectionManager serverConnectionManager)
|
||||
{
|
||||
@@ -76,7 +71,6 @@ namespace Wino.Calendar.ViewModels
|
||||
PreferencesService = preferencesService;
|
||||
|
||||
StatePersistenceService = statePersistanceService;
|
||||
_accountService = accountService;
|
||||
StatePersistenceService.StatePropertyChanged += PrefefencesChanged;
|
||||
}
|
||||
|
||||
@@ -99,12 +93,32 @@ namespace Wino.Calendar.ViewModels
|
||||
UpdateDateNavigationHeaderItems();
|
||||
}
|
||||
|
||||
private void ForceNavigateCalendarDate()
|
||||
{
|
||||
if (SelectedMenuItemIndex == -1)
|
||||
{
|
||||
var args = new CalendarPageNavigationArgs()
|
||||
{
|
||||
NavigationDate = _navigationDate ?? DateTime.Now.Date
|
||||
};
|
||||
|
||||
// Already on calendar. Just navigate.
|
||||
NavigationService.Navigate(WinoPage.CalendarPage, args);
|
||||
|
||||
_navigationDate = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedMenuItemIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
partial void OnSelectedMenuItemIndexChanged(int oldValue, int newValue)
|
||||
{
|
||||
switch (newValue)
|
||||
{
|
||||
case -1:
|
||||
NavigationService.Navigate(WinoPage.CalendarPage);
|
||||
ForceNavigateCalendarDate();
|
||||
break;
|
||||
case 0:
|
||||
NavigationService.Navigate(WinoPage.AccountManagementPage);
|
||||
@@ -162,20 +176,24 @@ namespace Wino.Calendar.ViewModels
|
||||
return DateTime.Today.Date;
|
||||
}
|
||||
|
||||
private DateTime? _navigationDate;
|
||||
|
||||
public override void OnPageLoaded()
|
||||
{
|
||||
base.OnPageLoaded();
|
||||
|
||||
NavigationService.Navigate(WinoPage.CalendarPage, new CalendarPageNavigationArgs()
|
||||
{
|
||||
RequestDefaultNavigation = true
|
||||
});
|
||||
TodayClicked();
|
||||
}
|
||||
|
||||
#region Commands
|
||||
|
||||
[RelayCommand]
|
||||
private void TodayClicked() => Messenger.Send(new GoToCalendarDayMessage(DateTime.Now.Date));
|
||||
private void TodayClicked()
|
||||
{
|
||||
_navigationDate = DateTime.Now.Date;
|
||||
|
||||
ForceNavigateCalendarDate();
|
||||
}
|
||||
|
||||
[RelayCommand]
|
||||
public void ManageAccounts() => NavigationService.Navigate(WinoPage.AccountManagementPage);
|
||||
@@ -184,8 +202,12 @@ namespace Wino.Calendar.ViewModels
|
||||
private Task ReconnectServerAsync() => ServerConnectionManager.ConnectAsync();
|
||||
|
||||
[RelayCommand]
|
||||
private void DateClicked(CalendarViewDayClickedEventArgs clickedDate)
|
||||
=> Messenger.Send(new CalendarInitializeMessage(clickedDate.ClickedDate, CalendarInitInitiative.User));
|
||||
private void DateClicked(CalendarViewDayClickedEventArgs clickedDateArgs)
|
||||
{
|
||||
_navigationDate = clickedDateArgs.ClickedDate;
|
||||
|
||||
ForceNavigateCalendarDate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -238,11 +260,8 @@ namespace Wino.Calendar.ViewModels
|
||||
public async void Receive(CalendarEnableStatusChangedMessage message)
|
||||
=> await ExecuteUIThread(() => IsCalendarEnabled = message.IsEnabled);
|
||||
|
||||
// Calendar page is loaded and calendar is ready to recieve render requests.
|
||||
public void Receive(CalendarInitializedMessage message) => Messenger.Send(new GoToCalendarDayMessage(DateTime.Now.Date));
|
||||
|
||||
public void Receive(NavigateManageAccountsRequested message) => SelectedMenuItemIndex = 1;
|
||||
|
||||
public void Receive(GoToCalendarDayMessage message) => SelectedMenuItemIndex = -1;
|
||||
//public void Receive(GoToCalendarDayMessage message) => SelectedMenuItemIndex = -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,13 @@ using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
using Wino.Core.Domain.Models.Calendar.CalendarTypeStrategies;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.ViewModels;
|
||||
using Wino.Messaging.Client.Calendar;
|
||||
|
||||
namespace Wino.Calendar.ViewModels
|
||||
{
|
||||
public partial class CalendarPageViewModel : CalendarBaseViewModel,
|
||||
IRecipient<CalendarInitializeMessage>
|
||||
IRecipient<LoadCalendarMessage>
|
||||
{
|
||||
[ObservableProperty]
|
||||
private ObservableRangeCollection<DayRangeRenderModel> _dayRanges = [];
|
||||
@@ -56,13 +55,6 @@ namespace Wino.Calendar.ViewModels
|
||||
_currentSettings = _preferencesService.GetCurrentCalendarSettings();
|
||||
}
|
||||
|
||||
public override void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
|
||||
Messenger.Send(new CalendarInitializedMessage());
|
||||
}
|
||||
|
||||
// TODO: Replace when calendar settings are updated.
|
||||
// Should be a field ideally.
|
||||
private BaseCalendarTypeDrawingStrategy GetDrawingStrategy(CalendarDisplayType displayType)
|
||||
@@ -77,7 +69,7 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
partial void OnIsCalendarEnabledChanging(bool oldValue, bool newValue) => Messenger.Send(new CalendarEnableStatusChangedMessage(newValue));
|
||||
|
||||
private bool ShouldResetDayRanges(CalendarInitializeMessage message)
|
||||
private bool ShouldResetDayRanges(LoadCalendarMessage message)
|
||||
{
|
||||
// Never reset if the initiative is from the app.
|
||||
if (message.CalendarInitInitiative == CalendarInitInitiative.App) return false;
|
||||
@@ -86,13 +78,17 @@ namespace Wino.Calendar.ViewModels
|
||||
// 2. Day display count is different.
|
||||
// 3. Display date is not in the visible range.
|
||||
|
||||
var loadedRange = GetLoadedDateRange();
|
||||
|
||||
if (loadedRange == null) return false;
|
||||
|
||||
return
|
||||
(_currentDisplayType != StatePersistanceService.CalendarDisplayType ||
|
||||
_displayDayCount != StatePersistanceService.DayDisplayCount ||
|
||||
(DayRanges != null && !DayRanges.Select(a => a.CalendarRenderOptions).Any(b => b.DateRange.IsInRange(message.DisplayDate))));
|
||||
!(message.DisplayDate >= loadedRange.StartDate && message.DisplayDate <= loadedRange.EndDate));
|
||||
}
|
||||
|
||||
public async void Receive(CalendarInitializeMessage message)
|
||||
public async void Receive(LoadCalendarMessage message)
|
||||
{
|
||||
await _calendarLoadingSemaphore.WaitAsync();
|
||||
|
||||
@@ -132,6 +128,16 @@ namespace Wino.Calendar.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private DateRange GetLoadedDateRange()
|
||||
{
|
||||
if (DayRanges.Count == 0) return null;
|
||||
|
||||
var minimumLoadedDate = DayRanges[0].CalendarRenderOptions.DateRange.StartDate;
|
||||
var maximumLoadedDate = DayRanges[DayRanges.Count - 1].CalendarRenderOptions.DateRange.EndDate;
|
||||
|
||||
return new DateRange(minimumLoadedDate, maximumLoadedDate);
|
||||
}
|
||||
|
||||
private async Task RenderDatesAsync(CalendarInitInitiative calendarInitInitiative,
|
||||
DateTime? loadingDisplayDate = null,
|
||||
CalendarLoadDirection calendarLoadDirection = CalendarLoadDirection.Replace)
|
||||
@@ -165,10 +171,7 @@ namespace Wino.Calendar.ViewModels
|
||||
}
|
||||
else
|
||||
{
|
||||
var minimumLoadedDate = DayRanges[0].CalendarRenderOptions.DateRange.StartDate;
|
||||
var maximumLoadedDate = DayRanges[DayRanges.Count - 1].CalendarRenderOptions.DateRange.EndDate;
|
||||
|
||||
var currentInitializedDateRange = new DateRange(minimumLoadedDate, maximumLoadedDate);
|
||||
var initializedDateRange = GetLoadedDateRange();
|
||||
|
||||
// App is trying to load.
|
||||
// This should be based on direction. We'll load the next or previous range.
|
||||
@@ -176,11 +179,11 @@ namespace Wino.Calendar.ViewModels
|
||||
|
||||
if (calendarLoadDirection == CalendarLoadDirection.Previous)
|
||||
{
|
||||
flipLoadRange = strategy.GetPreviousDateRange(currentInitializedDateRange, StatePersistanceService.DayDisplayCount);
|
||||
flipLoadRange = strategy.GetPreviousDateRange(initializedDateRange, StatePersistanceService.DayDisplayCount);
|
||||
}
|
||||
else
|
||||
{
|
||||
flipLoadRange = strategy.GetNextDateRange(currentInitializedDateRange, StatePersistanceService.DayDisplayCount);
|
||||
flipLoadRange = strategy.GetNextDateRange(initializedDateRange, StatePersistanceService.DayDisplayCount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -310,7 +313,7 @@ namespace Wino.Calendar.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
private bool ShouldScrollToItem(CalendarInitializeMessage message)
|
||||
private bool ShouldScrollToItem(LoadCalendarMessage message)
|
||||
{
|
||||
// Never scroll if the initiative is from the app.
|
||||
if (message.CalendarInitInitiative == CalendarInitInitiative.App) return false;
|
||||
@@ -318,36 +321,34 @@ namespace Wino.Calendar.ViewModels
|
||||
// Nothing to scroll.
|
||||
if (DayRanges.Count == 0) return false;
|
||||
|
||||
var minimumLoadedDate = DayRanges[0].CalendarRenderOptions.DateRange.StartDate;
|
||||
var maximumLoadedDate = DayRanges[DayRanges.Count - 1].CalendarRenderOptions.DateRange.EndDate;
|
||||
var initializedDateRange = GetLoadedDateRange();
|
||||
|
||||
var selectedDate = message.DisplayDate;
|
||||
|
||||
return selectedDate >= minimumLoadedDate && selectedDate <= maximumLoadedDate;
|
||||
return selectedDate >= initializedDateRange.StartDate && selectedDate <= initializedDateRange.EndDate;
|
||||
}
|
||||
|
||||
partial void OnSelectedDayRangeChanged(DayRangeRenderModel value)
|
||||
{
|
||||
if (DayRanges.Count == 0 || SelectedDateRangeIndex < 0) return;
|
||||
|
||||
if (isLoadMoreBlocked) return;
|
||||
|
||||
var selectedRange = DayRanges[SelectedDateRangeIndex];
|
||||
|
||||
if (selectedRange != null)
|
||||
{
|
||||
// Send the loading message initiated by the app.
|
||||
if (SelectedDateRangeIndex == DayRanges.Count - 1)
|
||||
{
|
||||
// Load next, starting from the end date.
|
||||
_ = LoadMoreAsync(CalendarLoadDirection.Next);
|
||||
}
|
||||
else if (SelectedDateRangeIndex == 0)
|
||||
{
|
||||
// Load previous, starting from the start date.
|
||||
Messenger.Send(new VisibleDateRangeChangedMessage(new DateRange(selectedRange.Period.Start, selectedRange.Period.End)));
|
||||
|
||||
_ = LoadMoreAsync(CalendarLoadDirection.Previous);
|
||||
}
|
||||
if (isLoadMoreBlocked) return;
|
||||
|
||||
// Send the loading message initiated by the app.
|
||||
if (SelectedDateRangeIndex == DayRanges.Count - 1)
|
||||
{
|
||||
// Load next, starting from the end date.
|
||||
_ = LoadMoreAsync(CalendarLoadDirection.Next);
|
||||
}
|
||||
else if (SelectedDateRangeIndex == 0)
|
||||
{
|
||||
// Load previous, starting from the start date.
|
||||
|
||||
_ = LoadMoreAsync(CalendarLoadDirection.Previous);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace Wino.Calendar
|
||||
private void RegisterViewModels(IServiceCollection services)
|
||||
{
|
||||
services.AddSingleton(typeof(AppShellViewModel));
|
||||
services.AddTransient(typeof(CalendarPageViewModel));
|
||||
services.AddSingleton(typeof(CalendarPageViewModel));
|
||||
services.AddTransient(typeof(CalendarSettingsPageViewModel));
|
||||
services.AddTransient(typeof(AccountManagementViewModel));
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using System.Diagnostics;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Calendar.Args;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
using Wino.Messaging.Client.Calendar;
|
||||
|
||||
namespace Wino.Calendar.Controls
|
||||
{
|
||||
@@ -21,6 +20,7 @@ namespace Wino.Calendar.Controls
|
||||
public static readonly DependencyProperty DayRangesProperty = DependencyProperty.Register(nameof(DayRanges), typeof(ObservableCollection<DayRangeRenderModel>), typeof(WinoCalendarControl), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty SelectedFlipViewIndexProperty = DependencyProperty.Register(nameof(SelectedFlipViewIndex), typeof(int), typeof(WinoCalendarControl), new PropertyMetadata(-1));
|
||||
public static readonly DependencyProperty SelectedFlipViewDayRangeProperty = DependencyProperty.Register(nameof(SelectedFlipViewDayRange), typeof(DayRangeRenderModel), typeof(WinoCalendarControl), new PropertyMetadata(null));
|
||||
public static readonly DependencyProperty ActiveCanvasProperty = DependencyProperty.Register(nameof(ActiveCanvas), typeof(WinoDayTimelineCanvas), typeof(WinoCalendarControl), new PropertyMetadata(null, new PropertyChangedCallback(OnActiveCanvasChanged)));
|
||||
|
||||
public DayRangeRenderModel SelectedFlipViewDayRange
|
||||
{
|
||||
@@ -28,6 +28,12 @@ namespace Wino.Calendar.Controls
|
||||
set { SetValue(SelectedFlipViewDayRangeProperty, value); }
|
||||
}
|
||||
|
||||
public WinoDayTimelineCanvas ActiveCanvas
|
||||
{
|
||||
get { return (WinoDayTimelineCanvas)GetValue(ActiveCanvasProperty); }
|
||||
set { SetValue(ActiveCanvasProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the collection of day ranges to render.
|
||||
/// Each day range usually represents a week, but it may support other ranges.
|
||||
@@ -46,38 +52,6 @@ namespace Wino.Calendar.Controls
|
||||
|
||||
#endregion
|
||||
|
||||
private WinoDayTimelineCanvas _activeCanvas;
|
||||
|
||||
public WinoDayTimelineCanvas ActiveCanvas
|
||||
{
|
||||
get { return _activeCanvas; }
|
||||
set
|
||||
{
|
||||
// FlipView's timeline is changing.
|
||||
// Make sure to unregister from the old one.
|
||||
|
||||
if (_activeCanvas != null)
|
||||
{
|
||||
// Dismiss any selection on the old canvas.
|
||||
|
||||
_activeCanvas.SelectedDateTime = null;
|
||||
_activeCanvas.TimelineCellSelected -= ActiveTimelineCellSelected;
|
||||
_activeCanvas.TimelineCellUnselected -= ActiveTimelineCellUnselected;
|
||||
}
|
||||
|
||||
_activeCanvas = value;
|
||||
|
||||
if (_activeCanvas != null)
|
||||
{
|
||||
_activeCanvas.TimelineCellSelected += ActiveTimelineCellSelected;
|
||||
_activeCanvas.TimelineCellUnselected += ActiveTimelineCellUnselected;
|
||||
|
||||
// Raise visible date range change to shell.
|
||||
WeakReferenceMessenger.Default.Send(new VisibleDateRangeChangedMessage(_activeCanvas.RenderOptions.DateRange));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private WinoCalendarFlipView InternalFlipView;
|
||||
|
||||
public WinoCalendarControl()
|
||||
@@ -86,6 +60,59 @@ namespace Wino.Calendar.Controls
|
||||
SizeChanged += CalendarSizeChanged;
|
||||
}
|
||||
|
||||
private static void OnActiveCanvasChanged(DependencyObject calendar, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (calendar is WinoCalendarControl calendarControl)
|
||||
{
|
||||
if (e.OldValue is WinoDayTimelineCanvas oldCanvas)
|
||||
{
|
||||
// Dismiss any selection on the old canvas.
|
||||
calendarControl.DeregisterCanvas(oldCanvas);
|
||||
}
|
||||
|
||||
if (e.NewValue is WinoDayTimelineCanvas newCanvas)
|
||||
{
|
||||
calendarControl.RegisterCanvas(newCanvas);
|
||||
}
|
||||
|
||||
calendarControl.ManageHighlightedDateRange();
|
||||
}
|
||||
}
|
||||
|
||||
private void ManageHighlightedDateRange()
|
||||
{
|
||||
if (ActiveCanvas == null)
|
||||
{
|
||||
SelectedFlipViewDayRange = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
SelectedFlipViewDayRange = InternalFlipView.SelectedItem as DayRangeRenderModel;
|
||||
}
|
||||
}
|
||||
|
||||
private void DeregisterCanvas(WinoDayTimelineCanvas canvas)
|
||||
{
|
||||
if (canvas == null) return;
|
||||
|
||||
Debug.WriteLine("Deregister active canvas.");
|
||||
|
||||
canvas.SelectedDateTime = null;
|
||||
canvas.TimelineCellSelected -= ActiveTimelineCellSelected;
|
||||
canvas.TimelineCellUnselected -= ActiveTimelineCellUnselected;
|
||||
}
|
||||
|
||||
private void RegisterCanvas(WinoDayTimelineCanvas canvas)
|
||||
{
|
||||
if (canvas == null) return;
|
||||
|
||||
Debug.WriteLine("Register new canvas.");
|
||||
|
||||
canvas.SelectedDateTime = null;
|
||||
canvas.TimelineCellSelected += ActiveTimelineCellSelected;
|
||||
canvas.TimelineCellUnselected += ActiveTimelineCellUnselected;
|
||||
}
|
||||
|
||||
private void CalendarSizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
if (ActiveCanvas == null) return;
|
||||
@@ -98,11 +125,6 @@ namespace Wino.Calendar.Controls
|
||||
base.OnApplyTemplate();
|
||||
|
||||
InternalFlipView = GetTemplateChild(PART_WinoFlipView) as WinoCalendarFlipView;
|
||||
|
||||
// Each FlipViewItem will have 1 timeline canvas to draw hour cells in the background that supports selection of them.
|
||||
// When the selection changes, we need to stop listening to the old canvas and start listening to the new one to catch events.
|
||||
|
||||
InternalFlipView.ActiveTimelineCanvasChanged += FlipViewsActiveTimelineCanvasChanged;
|
||||
}
|
||||
|
||||
private void FlipViewsActiveTimelineCanvasChanged(object sender, WinoDayTimelineCanvas e)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Collections;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
@@ -10,29 +11,42 @@ namespace Wino.Calendar.Controls
|
||||
{
|
||||
public class WinoCalendarFlipView : CustomCalendarFlipView
|
||||
{
|
||||
public event EventHandler<WinoDayTimelineCanvas> ActiveTimelineCanvasChanged;
|
||||
public WinoDayTimelineCanvas ActiveCanvas
|
||||
{
|
||||
get { return (WinoDayTimelineCanvas)GetValue(ActiveCanvasProperty); }
|
||||
set { SetValue(ActiveCanvasProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ActiveCanvasProperty = DependencyProperty.Register(nameof(ActiveCanvas), typeof(WinoDayTimelineCanvas), typeof(WinoCalendarFlipView), new PropertyMetadata(null));
|
||||
|
||||
public WinoCalendarFlipView()
|
||||
{
|
||||
SelectionChanged += CalendarDisplayRangeChanged;
|
||||
RegisterPropertyChangedCallback(SelectedIndexProperty, new DependencyPropertyChangedCallback(OnSelectedIndexUpdated));
|
||||
}
|
||||
|
||||
private async void CalendarDisplayRangeChanged(object sender, SelectionChangedEventArgs e)
|
||||
private static void OnSelectedIndexUpdated(DependencyObject d, DependencyProperty e)
|
||||
{
|
||||
if (d is WinoCalendarFlipView flipView)
|
||||
{
|
||||
flipView.UpdateActiveCanvas();
|
||||
}
|
||||
}
|
||||
|
||||
public async void UpdateActiveCanvas()
|
||||
{
|
||||
if (SelectedIndex < 0)
|
||||
ActiveTimelineCanvasChanged?.Invoke(this, null);
|
||||
ActiveCanvas = null;
|
||||
else
|
||||
{
|
||||
// TODO: Refactor this mechanism by listening to PrepareContainerForItemOverride and Loaded events together.
|
||||
while (ContainerFromIndex(SelectedIndex) == null)
|
||||
{
|
||||
await Task.Delay(250);
|
||||
await Task.Delay(100);
|
||||
}
|
||||
|
||||
if (ContainerFromIndex(SelectedIndex) is FlipViewItem flipViewItem)
|
||||
{
|
||||
var canvas = flipViewItem.FindDescendant<WinoDayTimelineCanvas>();
|
||||
ActiveTimelineCanvasChanged?.Invoke(this, canvas);
|
||||
ActiveCanvas = flipViewItem.FindDescendant<WinoDayTimelineCanvas>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -43,42 +57,46 @@ namespace Wino.Calendar.Controls
|
||||
/// <param name="dateTime">Date to navigate.</param>
|
||||
public async void NavigateToDay(DateTime dateTime)
|
||||
{
|
||||
// Find the day range that contains the date.
|
||||
var dayRange = GetItemsSource()?.FirstOrDefault(a => a.CalendarDays.Any(b => b.RepresentingDate.Date == dateTime.Date));
|
||||
await Task.Yield();
|
||||
|
||||
if (dayRange != null)
|
||||
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
|
||||
{
|
||||
var navigationItemIndex = GetItemsSource().IndexOf(dayRange);
|
||||
// Find the day range that contains the date.
|
||||
var dayRange = GetItemsSource()?.FirstOrDefault(a => a.CalendarDays.Any(b => b.RepresentingDate.Date == dateTime.Date));
|
||||
|
||||
if (Math.Abs(navigationItemIndex - SelectedIndex) > 4)
|
||||
if (dayRange != null)
|
||||
{
|
||||
// Difference between dates are high.
|
||||
// No need to animate this much, just go without animating.
|
||||
var navigationItemIndex = GetItemsSource().IndexOf(dayRange);
|
||||
|
||||
SelectedIndex = navigationItemIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Until we reach the day in the flip, simulate next-prev button clicks.
|
||||
// This will make sure the FlipView animations are triggered.
|
||||
// Setting SelectedIndex directly doesn't trigger the animations.
|
||||
|
||||
while (SelectedIndex != navigationItemIndex)
|
||||
if (Math.Abs(navigationItemIndex - SelectedIndex) > 4)
|
||||
{
|
||||
if (SelectedIndex > navigationItemIndex)
|
||||
// Difference between dates are high.
|
||||
// No need to animate this much, just go without animating.
|
||||
|
||||
SelectedIndex = navigationItemIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Until we reach the day in the flip, simulate next-prev button clicks.
|
||||
// This will make sure the FlipView animations are triggered.
|
||||
// Setting SelectedIndex directly doesn't trigger the animations.
|
||||
|
||||
while (SelectedIndex != navigationItemIndex)
|
||||
{
|
||||
GoPreviousFlip();
|
||||
}
|
||||
else
|
||||
{
|
||||
GoNextFlip();
|
||||
if (SelectedIndex > navigationItemIndex)
|
||||
{
|
||||
GoPreviousFlip();
|
||||
}
|
||||
else
|
||||
{
|
||||
GoNextFlip();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public void NavigateHour(TimeSpan hourTimeSpan)
|
||||
{
|
||||
// Total height of the FlipViewItem is the same as vertical ScrollViewer to position day headers.
|
||||
|
||||
@@ -109,6 +109,7 @@
|
||||
x:Name="PART_WinoFlipView"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
ActiveCanvas="{x:Bind ActiveCanvas, Mode=TwoWay}"
|
||||
IsTabStop="False"
|
||||
ItemTemplate="{StaticResource FlipTemplate}"
|
||||
ItemsSource="{TemplateBinding DayRanges}"
|
||||
|
||||
@@ -169,6 +169,7 @@
|
||||
|
||||
<calendarControls:WinoCalendarView
|
||||
x:Name="CalendarView"
|
||||
|
||||
HorizontalAlignment="Center"
|
||||
DateClickedCommand="{x:Bind ViewModel.DateClickedCommand}"
|
||||
HighlightedDateRange="{x:Bind ViewModel.HighlightedDateRange, Mode=OneWay}" />
|
||||
|
||||
@@ -6,8 +6,7 @@ using Wino.Messaging.Client.Calendar;
|
||||
|
||||
namespace Wino.Calendar.Views
|
||||
{
|
||||
public sealed partial class AppShell : AppShellAbstract,
|
||||
IRecipient<GoToCalendarDayMessage>
|
||||
public sealed partial class AppShell : AppShellAbstract
|
||||
{
|
||||
private const string STATE_HorizontalCalendar = "HorizontalCalendar";
|
||||
private const string STATE_VerticalCalendar = "VerticalCalendar";
|
||||
@@ -45,10 +44,10 @@ namespace Wino.Calendar.Views
|
||||
|
||||
}
|
||||
|
||||
public void Receive(GoToCalendarDayMessage message)
|
||||
{
|
||||
CalendarView.GoToDay(message.DateTime);
|
||||
}
|
||||
//public void Receive(GoToCalendarDayMessage message)
|
||||
//{
|
||||
// CalendarView.GoToDay(message.DateTime);
|
||||
//}
|
||||
|
||||
private void PreviousDateClicked(object sender, RoutedEventArgs e) => WeakReferenceMessenger.Default.Send(new GoPreviousDateRequestedMessage());
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using Wino.Calendar.Args;
|
||||
using Wino.Calendar.Views.Abstract;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Calendar;
|
||||
using Wino.Messaging.Client.Calendar;
|
||||
|
||||
namespace Wino.Calendar.Views
|
||||
@@ -17,6 +20,7 @@ namespace Wino.Calendar.Views
|
||||
public CalendarPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
NavigationCacheMode = Windows.UI.Xaml.Navigation.NavigationCacheMode.Enabled;
|
||||
}
|
||||
|
||||
public void Receive(ScrollToDateMessage message) => CalendarControl.NavigateToDay(message.Date);
|
||||
@@ -25,6 +29,25 @@ namespace Wino.Calendar.Views
|
||||
|
||||
public void Receive(GoPreviousDateRequestedMessage message) => CalendarControl.GoPreviousRange();
|
||||
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
|
||||
if (e.Parameter is CalendarPageNavigationArgs args)
|
||||
{
|
||||
if (args.RequestDefaultNavigation)
|
||||
{
|
||||
// Go today.
|
||||
WeakReferenceMessenger.Default.Send(new LoadCalendarMessage(DateTime.Now.Date, CalendarInitInitiative.App));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Go specified date.
|
||||
WeakReferenceMessenger.Default.Send(new LoadCalendarMessage(args.NavigationDate, CalendarInitInitiative.User));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CellSelected(object sender, TimelineCellSelectedArgs e)
|
||||
{
|
||||
selectedDateTime = e.ClickedDate;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Wino.Core.Domain.Models.Calendar
|
||||
using System;
|
||||
|
||||
namespace Wino.Core.Domain.Models.Calendar
|
||||
{
|
||||
public class CalendarPageNavigationArgs
|
||||
{
|
||||
@@ -6,5 +8,10 @@
|
||||
/// When the app launches, automatically request the default calendar navigation options.
|
||||
/// </summary>
|
||||
public bool RequestDefaultNavigation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Display the calendar view for the specified date.
|
||||
/// </summary>
|
||||
public DateTime NavigationDate { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Wino.Core.Domain.Models.Calendar
|
||||
/// </summary>
|
||||
public class DayRangeRenderModel
|
||||
{
|
||||
ITimePeriod Period { get; }
|
||||
public ITimePeriod Period { get; }
|
||||
public List<CalendarDayModel> CalendarDays { get; } = new List<CalendarDayModel>();
|
||||
public List<DayHeaderRenderModel> DayHeaders { get; } = new List<DayHeaderRenderModel>();
|
||||
public CalendarRenderOptions CalendarRenderOptions { get; }
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Wino.Messaging.Client.Calendar
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised when OnNavigatedTo of CalendarPage is called.
|
||||
/// </summary>
|
||||
public record CalendarInitializedMessage;
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Messaging.Client.Calendar
|
||||
{
|
||||
/// <summary>
|
||||
/// Raised when specific date is requested to be clicked on CalendarView.
|
||||
/// </summary>
|
||||
/// <param name="DateTime">Date to be navigated.</param>
|
||||
public record GoToCalendarDayMessage(DateTime DateTime);
|
||||
}
|
||||
@@ -9,5 +9,5 @@ namespace Wino.Messaging.Client.Calendar
|
||||
/// <param name="DisplayType">Type of the calendar.</param>
|
||||
/// <param name="DisplayDate">Exact date to highlight.</param>
|
||||
/// <param name="DayDisplayCount">How many days to load with Day calendar display type.</param>
|
||||
public record CalendarInitializeMessage(DateTime DisplayDate, CalendarInitInitiative CalendarInitInitiative);
|
||||
public record LoadCalendarMessage(DateTime DisplayDate, CalendarInitInitiative CalendarInitInitiative);
|
||||
}
|
||||
Reference in New Issue
Block a user