Range thing.

This commit is contained in:
Burak Kaan Köse
2026-03-21 00:58:01 +01:00
parent 01f7a09cb7
commit 51fef043ee
45 changed files with 1327 additions and 3753 deletions
@@ -131,13 +131,26 @@
Text="{x:Bind domain:Translator.CalendarEventCompose_NewEventButton, Mode=OneTime}" />
</coreControls:WinoNavigationViewItem>
<calendarControls:WinoCalendarView
x:Name="CalendarView"
<Border
x:Name="RangeSummaryCard"
Grid.Row="1"
HorizontalAlignment="Center"
DateClickedCommand="{x:Bind ViewModel.DateClickedCommand}"
HighlightedDateRange="{x:Bind ViewModel.HighlightedDateRange, Mode=OneWay}"
TodayBackgroundColor="{ThemeResource SystemAccentColor}" />
Margin="16,0,16,12"
Padding="12"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
CornerRadius="8">
<StackPanel Spacing="12">
<TextBlock
FontWeight="SemiBold"
Text="{x:Bind ViewModel.VisibleDateRangeText, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<muxc:CalendarView
x:Name="VisibleDateRangeCalendarView"
HorizontalAlignment="Stretch"
SelectionMode="Multiple"
SelectedDatesChanged="VisibleDateRangeCalendarViewSelectedDatesChanged" />
</StackPanel>
</Border>
<!-- Account Calendars Host -->
<ListView
@@ -261,8 +274,6 @@
</VisualState>
<VisualState x:Name="SmallScreen">
<VisualState.Setters>
<Setter Target="NavigationTitleStack.Visibility" Value="Collapsed" />
<Setter Target="SearchBox.(Grid.ColumnSpan)" Value="2" />
<Setter Target="navigationView.IsPaneOpen" Value="False" />
</VisualState.Setters>
<VisualState.StateTriggers>
@@ -273,28 +284,14 @@
<VisualStateGroup x:Name="CalendarOrientationStates">
<VisualState x:Name="HorizontalCalendar" />
<VisualState x:Name="VerticalCalendar">
<VisualState.Setters>
<Setter Target="DayHeaderNavigationItemsFlipView.ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VirtualizingStackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Target="PreviousDateButtonPathIcon.Data" Value="F1 M 3.2 10.52 C 2.986666 10.733333 2.92 10.98 3 11.259999 C 3.08 11.54 3.266666 11.713333 3.56 11.78 C 3.853333 11.846666 4.093333 11.773333 4.28 11.559999 L 9.24 6.32 L 9.24 19.039999 C 9.24 19.253332 9.313333 19.433332 9.46 19.58 C 9.606666 19.726665 9.786666 19.799999 10 19.799999 C 10.213333 19.799999 10.393332 19.726665 10.54 19.58 C 10.686666 19.433332 10.76 19.253332 10.76 19.039999 L 10.76 6.32 L 15.719999 11.559999 C 15.906666 11.773333 16.139999 11.846666 16.42 11.78 C 16.700001 11.713333 16.886665 11.54 16.98 11.259999 C 17.073332 10.98 17.013332 10.733333 16.799999 10.52 L 10.719999 4.119999 C 10.559999 3.959999 10.373333 3.853333 10.16 3.799999 C 10.053333 3.799999 9.946667 3.799999 9.84 3.799999 C 9.626666 3.853333 9.439999 3.959999 9.28 4.119999 Z " />
<Setter Target="NextDateButtonPathIcon.Data" Value="F1 M 16.799999 13.079999 C 16.933332 12.92 16.993332 12.74 16.98 12.539999 C 16.966665 12.34 16.886665 12.166667 16.74 12.02 C 16.593334 11.873333 16.42 11.799999 16.219999 11.799999 C 16.02 11.799999 15.853333 11.879999 15.719999 12.039999 L 10.76 17.279999 L 10.76 4.559999 C 10.76 4.346666 10.686666 4.166668 10.54 4.02 C 10.393332 3.873333 10.213333 3.799999 10 3.799999 C 9.786666 3.799999 9.606666 3.873333 9.46 4.02 C 9.313333 4.166668 9.24 4.346666 9.24 4.559999 L 9.24 17.279999 L 4.28 12.039999 C 4.146667 11.879999 3.98 11.799999 3.78 11.799999 C 3.58 11.799999 3.4 11.873333 3.24 12.02 C 3.08 12.166667 3 12.34 3 12.539999 C 3 12.74 3.066667 12.92 3.2 13.079999 L 9.28 19.48 C 9.439999 19.639999 9.626666 19.746666 9.84 19.799999 C 9.946667 19.799999 10.053333 19.799999 10.16 19.799999 C 10.373333 19.746666 10.559999 19.639999 10.719999 19.48 Z " />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="VerticalCalendar" />
</VisualStateGroup>
<VisualStateGroup x:Name="ShellStateContentGroup">
<VisualState x:Name="DefaultShellContentState" />
<VisualState x:Name="EventDetailsContentState">
<VisualState.Setters>
<Setter Target="ShellContentArea.Visibility" Value="Collapsed" />
<Setter Target="CalendarTypeSelector.Visibility" Value="Collapsed" />
<Setter Target="CalendarView.IsEnabled" Value="False" />
<Setter Target="RangeSummaryCard.IsEnabled" Value="False" />
<Setter Target="CalendarHostListView.IsEnabled" Value="False" />
</VisualState.Setters>
<VisualState.StateTriggers>
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.ComponentModel;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
@@ -11,6 +12,7 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.MenuItems;
using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.Calendar;
using Wino.Mail.Views.Abstract;
using Wino.Messaging.Client.Calendar;
using Windows.System;
@@ -22,6 +24,7 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
{
private const string STATE_HorizontalCalendar = "HorizontalCalendar";
private const string STATE_VerticalCalendar = "VerticalCalendar";
private bool _isSynchronizingVisibleDateRangeCalendar;
public Frame GetShellFrame() => InnerShellFrame;
@@ -29,12 +32,14 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
{
InitializeComponent();
ViewModel.PropertyChanged += ViewModelPropertyChanged;
ManageCalendarDisplayType(ViewModel.StatePersistenceService.CalendarDisplayType);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
UpdateNavigationPaneLayout(navigationView.DisplayMode);
SynchronizeVisibleDateRangeCalendar();
}
private void ManageCalendarDisplayType(Core.Domain.Enums.CalendarDisplayType displayType)
@@ -49,9 +54,11 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
}
}
private void PreviousDateClicked(object sender, RoutedEventArgs e) => WeakReferenceMessenger.Default.Send(new GoPreviousDateRequestedMessage());
private void PreviousDateClicked(object sender, RoutedEventArgs e)
=> ViewModel.PreviousDateRangeCommand.Execute(null);
private void NextDateClicked(object sender, RoutedEventArgs e) => WeakReferenceMessenger.Default.Send(new GoNextDateRequestedMessage());
private void NextDateClicked(object sender, RoutedEventArgs e)
=> ViewModel.NextDateRangeCommand.Execute(null);
private async void NewCalendarEventNavigationItemTapped(object sender, TappedRoutedEventArgs e)
{
@@ -59,6 +66,33 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
await InvokeNewCalendarEventAsync();
}
private void VisibleDateRangeCalendarViewSelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
{
if (_isSynchronizingVisibleDateRangeCalendar)
return;
DateTimeOffset? interactedDate = null;
if (args.AddedDates.Count > 0)
{
interactedDate = args.AddedDates[0];
}
else if (args.RemovedDates.Count > 0)
{
interactedDate = args.RemovedDates[0];
}
if (interactedDate is null)
return;
var clickedArgs = new CalendarViewDayClickedEventArgs(interactedDate.Value.DateTime);
if (ViewModel.DateClickedCommand.CanExecute(clickedArgs))
{
ViewModel.DateClickedCommand.Execute(clickedArgs);
}
}
private async void NewCalendarEventNavigationItemKeyDown(object sender, KeyRoutedEventArgs e)
{
if (e.Key is not (VirtualKey.Enter or VirtualKey.Space))
@@ -102,6 +136,15 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
public void Receive(CalendarDisplayTypeChangedMessage message)
{
ManageCalendarDisplayType(message.NewDisplayType);
SynchronizeVisibleDateRangeCalendar();
}
private void ViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(ViewModel.CurrentVisibleRange) or nameof(ViewModel.VisibleDateRangeText))
{
SynchronizeVisibleDateRangeCalendar();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
@@ -226,4 +269,39 @@ public sealed partial class CalendarAppShell : CalendarAppShellAbstract,
_ => key.ToString()
};
}
private void SynchronizeVisibleDateRangeCalendar()
{
if (!DispatcherQueue.HasThreadAccess)
{
var enqueued = DispatcherQueue.TryEnqueue(SynchronizeVisibleDateRangeCalendar);
if (!enqueued)
throw new InvalidOperationException("Could not marshal visible date range calendar synchronization onto the UI thread.");
return;
}
_isSynchronizingVisibleDateRangeCalendar = true;
try
{
VisibleDateRangeCalendarView.SelectedDates.Clear();
var currentRange = ViewModel.CurrentVisibleRange;
if (currentRange == null)
return;
foreach (var date in currentRange.Dates)
{
VisibleDateRangeCalendarView.SelectedDates.Add(new DateTimeOffset(date.ToDateTime(TimeOnly.MinValue)));
}
VisibleDateRangeCalendarView.SetDisplayDate(new DateTimeOffset(currentRange.AnchorDate.ToDateTime(TimeOnly.MinValue)));
}
finally
{
_isSynchronizingVisibleDateRangeCalendar = false;
}
}
}
File diff suppressed because one or more lines are too long
@@ -1,210 +1,42 @@
using System;
using System;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.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;
public sealed partial class CalendarPage : CalendarPageAbstract,
IRecipient<ScrollToDateMessage>,
IRecipient<ScrollToHourMessage>,
IRecipient<GoNextDateRequestedMessage>,
IRecipient<GoPreviousDateRequestedMessage>
public sealed partial class CalendarPage : CalendarPageAbstract
{
private const int PopupDialogOffset = 12;
public CalendarPage()
{
InitializeComponent();
ViewModel.DetailsShowCalendarItemChanged += CalendarItemDetailContextChanged;
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
base.OnNavigatingFrom(e);
ViewModel.DetailsShowCalendarItemChanged -= CalendarItemDetailContextChanged;
QuickEventPopupDialog.IsOpen = false;
EventDetailsPopup.IsOpen = false;
EventDetailsPopup.PlacementTarget = null;
CalendarControl.ResetTimelineSelection();
if (CalendarControl is IDisposable disposableCalendarControl)
{
disposableCalendarControl.Dispose();
}
Bindings.StopTracking();
}
private void CalendarItemDetailContextChanged(object? sender, EventArgs e)
{
if (ViewModel.DisplayDetailsCalendarItemViewModel != null)
{
var control = CalendarControl.GetCalendarItemControl(ViewModel.DisplayDetailsCalendarItemViewModel);
if (control != null)
{
EventDetailsPopup.PlacementTarget = control;
}
}
}
protected override void RegisterRecipients()
{
base.RegisterRecipients();
WeakReferenceMessenger.Default.Register<ScrollToDateMessage>(this);
WeakReferenceMessenger.Default.Register<ScrollToHourMessage>(this);
WeakReferenceMessenger.Default.Register<GoNextDateRequestedMessage>(this);
WeakReferenceMessenger.Default.Register<GoPreviousDateRequestedMessage>(this);
}
protected override void UnregisterRecipients()
{
base.UnregisterRecipients();
WeakReferenceMessenger.Default.Unregister<ScrollToDateMessage>(this);
WeakReferenceMessenger.Default.Unregister<ScrollToHourMessage>(this);
WeakReferenceMessenger.Default.Unregister<GoNextDateRequestedMessage>(this);
WeakReferenceMessenger.Default.Unregister<GoPreviousDateRequestedMessage>(this);
}
public void Receive(ScrollToHourMessage message) => DispatcherQueue.TryEnqueue(() => CalendarControl.NavigateToHour(message.TimeSpan));
public void Receive(ScrollToDateMessage message) => DispatcherQueue.TryEnqueue(() => CalendarControl.NavigateToDay(message.Date));
public void Receive(GoNextDateRequestedMessage message) => DispatcherQueue.TryEnqueue(() => CalendarControl.GoNextRange());
public void Receive(GoPreviousDateRequestedMessage message) => DispatcherQueue.TryEnqueue(() => CalendarControl.GoPreviousRange());
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.Back)
if (e.NavigationMode == NavigationMode.Back && ViewModel.RestoreVisibleState())
{
if (ViewModel.RestoreVisibleState())
{
var restoreDate = ViewModel.GetRestoreDate();
DispatcherQueue.TryEnqueue(() => CalendarControl.NavigateToDay(restoreDate));
}
else
{
WeakReferenceMessenger.Default.Send(new LoadCalendarMessage(DateTime.Now.Date, CalendarInitInitiative.App));
}
return;
}
if (e.Parameter is CalendarPageNavigationArgs args)
var anchorDate = DateOnly.FromDateTime(DateTime.Now.Date);
if (e.Parameter is CalendarPageNavigationArgs args && !args.RequestDefaultNavigation)
{
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)
{
// Dismiss event details if exists and cancel the selection.
// This is to prevent the event details from being displayed when the user clicks somewhere else.
if (EventDetailsPopup.IsOpen)
{
CalendarControl.UnselectActiveTimelineCell();
ViewModel.DisplayDetailsCalendarItemViewModel = null;
return;
anchorDate = DateOnly.FromDateTime(args.NavigationDate.Date);
}
ViewModel.SelectedQuickEventDate = e.ClickedDate;
TeachingTipPositionerGrid.Width = e.CellSize.Width;
TeachingTipPositionerGrid.Height = e.CellSize.Height;
Canvas.SetLeft(TeachingTipPositionerGrid, e.PositionerPoint.X);
Canvas.SetTop(TeachingTipPositionerGrid, e.PositionerPoint.Y);
// Adjust the start and end time in the flyout.
var startTime = ViewModel.SelectedQuickEventDate.Value.TimeOfDay;
var endTime = startTime.Add(TimeSpan.FromMinutes(30));
ViewModel.SelectQuickEventTimeRange(startTime, endTime);
QuickEventPopupDialog.IsOpen = true;
}
private void CellUnselected(object sender, TimelineCellUnselectedArgs e)
{
QuickEventPopupDialog.IsOpen = false;
}
private void QuickEventAccountSelectorSelectionChanged(object sender, SelectionChangedEventArgs e)
{
QuickEventAccountSelectorFlyout.Hide();
}
private void QuickEventPopupClosed(object sender, object e)
{
// Reset the timeline selection when the tip is closed.
CalendarControl.ResetTimelineSelection();
}
private void PopupPlacementChanged(object sender, object e)
{
if (sender is Popup senderPopup)
{
// When the quick event Popup is positioned for different calendar types,
// we must adjust the offset to make sure the tip is not hidden and has nice
// spacing from the cell.
switch (senderPopup.ActualPlacement)
{
case PopupPlacementMode.Top:
senderPopup.VerticalOffset = PopupDialogOffset * -1;
break;
case PopupPlacementMode.Bottom:
senderPopup.VerticalOffset = PopupDialogOffset;
break;
case PopupPlacementMode.Left:
senderPopup.HorizontalOffset = PopupDialogOffset * -1;
break;
case PopupPlacementMode.Right:
senderPopup.HorizontalOffset = PopupDialogOffset;
break;
default:
break;
}
}
}
private void StartTimeDurationSubmitted(ComboBox sender, ComboBoxTextSubmittedEventArgs args)
=> ViewModel.SelectedStartTimeString = args.Text;
private void EndTimeDurationSubmitted(ComboBox sender, ComboBoxTextSubmittedEventArgs args)
=> ViewModel.SelectedEndTimeString = args.Text;
private void EventDetailsPopupClosed(object sender, object e)
{
ViewModel.DisplayDetailsCalendarItemViewModel = null;
}
private void CalendarScrolling(object sender, EventArgs e)
{
// In case of scrolling, we must dismiss the event details dialog.
ViewModel.DisplayDetailsCalendarItemViewModel = null;
var request = new CalendarDisplayRequest(ViewModel.StatePersistanceService.CalendarDisplayType, anchorDate);
WeakReferenceMessenger.Default.Send(new LoadCalendarMessage(request));
}
}
@@ -1,6 +1,6 @@
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using CommunityToolkit.WinUI.Controls;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Settings;
using Wino.Core.ViewModels.Data;
@@ -51,11 +51,6 @@ public sealed partial class SettingOptionsPage : SettingOptionsPageAbstract
ViewModel.NavigateToAddAccount();
}
private void WinoAccountManagementClicked(object sender, RoutedEventArgs e)
{
ViewModel.NavigateToWinoAccountManagementCommand.Execute(null);
}
private void SettingsSearchTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
{
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput || string.IsNullOrWhiteSpace(sender.Text))
+7 -3
View File
@@ -3,7 +3,6 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstract="using:Wino.Views.Abstract"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
@@ -93,8 +92,13 @@
Grid.Column="1"
VerticalAlignment="Center"
Spacing="8">
<controls:MarkdownTextBlock Text="{x:Bind Title, Mode=OneTime}" />
<controls:MarkdownTextBlock Foreground="{ThemeResource TextFillColorSecondaryBrush}" Text="{x:Bind Description, Mode=OneTime}" />
<TextBlock
Text="{x:Bind Title, Mode=OneTime}"
TextWrapping="WrapWholeWords" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Description, Mode=OneTime}"
TextWrapping="WrapWholeWords" />
</StackPanel>
</Grid>
</DataTemplate>
+20 -5
View File
@@ -568,11 +568,26 @@
Text="{x:Bind domain:Translator.CalendarEventCompose_NewEventButton, Mode=OneTime}" />
</coreControls:WinoNavigationViewItem>
<calendarControls:WinoCalendarView
x:Name="CalendarView"
<Border
x:Name="RangeSummaryCard"
Grid.Row="1"
HorizontalAlignment="Center"
TodayBackgroundColor="{ThemeResource SystemAccentColor}" />
Margin="16,0,16,12"
Padding="12"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
CornerRadius="8">
<StackPanel Spacing="12">
<TextBlock
FontWeight="SemiBold"
Text="{x:Bind ViewModel.CalendarClient.VisibleDateRangeText, Mode=OneWay}"
TextWrapping="WrapWholeWords" />
<muxc:CalendarView
x:Name="VisibleDateRangeCalendarView"
HorizontalAlignment="Stretch"
SelectionMode="Multiple"
SelectedDatesChanged="VisibleDateRangeCalendarViewSelectedDatesChanged" />
</StackPanel>
</Border>
<ListView
x:Name="CalendarHostListView"
@@ -764,7 +779,7 @@
<VisualState.Setters>
<Setter Target="ShellContentArea.Visibility" Value="Collapsed" />
<Setter Target="CalendarTypeSelector.Visibility" Value="Collapsed" />
<Setter Target="CalendarView.IsEnabled" Value="False" />
<Setter Target="RangeSummaryCard.IsEnabled" Value="False" />
<Setter Target="CalendarHostListView.IsEnabled" Value="False" />
</VisualState.Setters>
</VisualState>
+74 -13
View File
@@ -12,19 +12,18 @@ using Microsoft.UI.Xaml.Controls.Primitives;
using Microsoft.UI.Xaml.Input;
using Microsoft.UI.Xaml.Navigation;
using Windows.Foundation;
using Windows.System;
using Wino.Calendar.Controls;
using Wino.Calendar.Views;
using Wino.Calendar.ViewModels;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.MenuItems;
using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Folders;
using Wino.Core.Domain.Models.MailItem;
using Wino.Core.Domain.Models.Navigation;
using Wino.Mail.ViewModels;
using Wino.Mail.ViewModels.Data;
using Wino.Mail.WinUI.Controls;
using Wino.MenuFlyouts;
@@ -34,10 +33,7 @@ using Wino.Messaging.Client.Calendar;
using Wino.Messaging.Client.Mails;
using Wino.Messaging.Client.Shell;
using Wino.Messaging.UI;
using Wino.Views.Mail;
using Wino.Views;
using Wino.Views.Settings;
using Windows.System;
namespace Wino.Mail.WinUI.Views;
@@ -55,6 +51,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
private const string StateEventDetailsContent = "EventDetailsContentState";
private WinoApplicationMode? _activeMode;
private bool _isSyncingNavigationViewSelection;
private bool _isSynchronizingVisibleDateRangeCalendar;
public WinoAppShell()
{
@@ -203,7 +200,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
if (ViewModel.IsCalendarMode)
{
ViewModel.StatePersistenceService.CoreWindowTitle = string.Empty;
ViewModel.StatePersistenceService.CoreWindowTitle = ViewModel.CalendarClient.VisibleDateRangeText ?? string.Empty;
return;
}
@@ -227,7 +224,6 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
private void InitializeCalendarControls()
{
CalendarTypeSelector.TodayClickedCommand = ViewModel.CalendarClient.TodayClickedCommand;
CalendarView.DateClickedCommand = ViewModel.CalendarClient.DateClickedCommand;
DayHeaderNavigationItemsFlipView.ItemsSource = ViewModel.CalendarClient.DateNavigationHeaderItems;
CalendarHostListView.ItemsSource = ViewModel.CalendarClient.GroupedAccountCalendars;
@@ -239,8 +235,8 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
DayHeaderNavigationItemsFlipView.ItemsSource = ViewModel.CalendarClient.DateNavigationHeaderItems;
DayHeaderNavigationItemsFlipView.SelectedIndex = ViewModel.CalendarClient.SelectedDateNavigationHeaderIndex;
CalendarTypeSelector.DisplayDayCount = ViewModel.CalendarClient.StatePersistenceService.DayDisplayCount;
CalendarView.HighlightedDateRange = ViewModel.CalendarClient.HighlightedDateRange;
CalendarHostListView.ItemsSource = ViewModel.CalendarClient.GroupedAccountCalendars;
SynchronizeVisibleDateRangeCalendar();
}
private void RefreshNavigationViewBindings(bool syncMailSelection = true)
@@ -283,9 +279,11 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
await InvokeNewCalendarEventAsync();
}
private void PreviousDateClicked(object sender, RoutedEventArgs e) => WeakReferenceMessenger.Default.Send(new GoPreviousDateRequestedMessage());
private void PreviousDateClicked(object sender, RoutedEventArgs e)
=> ViewModel.CalendarClient.PreviousDateRangeCommand.Execute(null);
private void NextDateClicked(object sender, RoutedEventArgs e) => WeakReferenceMessenger.Default.Send(new GoNextDateRequestedMessage());
private void NextDateClicked(object sender, RoutedEventArgs e)
=> ViewModel.CalendarClient.NextDateRangeCommand.Execute(null);
private Task InvokeNewCalendarEventAsync()
=> ViewModel.CalendarClient.HandleNavigationItemInvokedAsync(new NewCalendarEventMenuItem());
@@ -512,13 +510,76 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
return;
}
if (e.PropertyName == nameof(ICalendarShellClient.HighlightedDateRange))
if (e.PropertyName == nameof(ICalendarShellClient.CurrentVisibleRange) ||
e.PropertyName == nameof(ICalendarShellClient.VisibleDateRangeText))
{
CalendarView.HighlightedDateRange = ViewModel.CalendarClient.HighlightedDateRange;
SynchronizeVisibleDateRangeCalendar();
UpdateTitleBarSubtitle();
}
}
private void VisibleDateRangeCalendarViewSelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
{
if (_isSynchronizingVisibleDateRangeCalendar)
return;
DateTimeOffset? interactedDate = null;
if (args.AddedDates.Count > 0)
{
interactedDate = args.AddedDates[0];
}
else if (args.RemovedDates.Count > 0)
{
interactedDate = args.RemovedDates[0];
}
if (interactedDate is null)
return;
var clickedArgs = new CalendarViewDayClickedEventArgs(interactedDate.Value.DateTime);
if (ViewModel.CalendarClient.DateClickedCommand.CanExecute(clickedArgs))
{
ViewModel.CalendarClient.DateClickedCommand.Execute(clickedArgs);
}
}
private void SynchronizeVisibleDateRangeCalendar()
{
if (!DispatcherQueue.HasThreadAccess)
{
var enqueued = DispatcherQueue.TryEnqueue(SynchronizeVisibleDateRangeCalendar);
if (!enqueued)
throw new InvalidOperationException("Could not marshal visible date range calendar synchronization onto the UI thread.");
return;
}
_isSynchronizingVisibleDateRangeCalendar = true;
try
{
VisibleDateRangeCalendarView.SelectedDates.Clear();
var currentRange = ViewModel.CalendarClient.CurrentVisibleRange;
if (currentRange == null)
return;
foreach (var date in currentRange.Dates)
{
VisibleDateRangeCalendarView.SelectedDates.Add(new DateTimeOffset(date.ToDateTime(TimeOnly.MinValue)));
}
VisibleDateRangeCalendarView.SetDisplayDate(new DateTimeOffset(currentRange.AnchorDate.ToDateTime(TimeOnly.MinValue)));
}
finally
{
_isSynchronizingVisibleDateRangeCalendar = false;
}
}
private void ViewModelPropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName != nameof(ViewModel.SelectedMenuItem) || !ViewModel.CurrentClient.HandlesNavigationSelection)