diff --git a/Wino.Calendar.ViewModels/CalendarAppShellViewModel.cs b/Wino.Calendar.ViewModels/CalendarAppShellViewModel.cs index 8f656180..d7a4ba58 100644 --- a/Wino.Calendar.ViewModels/CalendarAppShellViewModel.cs +++ b/Wino.Calendar.ViewModels/CalendarAppShellViewModel.cs @@ -111,6 +111,8 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel, { base.OnNavigatedTo(mode, parameters); + if (mode == NavigationMode.Back) return; + UpdateDateNavigationHeaderItems(); await InitializeAccountCalendarsAsync(); diff --git a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs index 22012b17..14a8c916 100644 --- a/Wino.Calendar.ViewModels/CalendarPageViewModel.cs +++ b/Wino.Calendar.ViewModels/CalendarPageViewModel.cs @@ -161,6 +161,29 @@ public partial class CalendarPageViewModel : CalendarBaseViewModel, AccountCalendarStateService.CollectiveAccountGroupSelectionStateChanged += AccountCalendarStateCollectivelyChanged; } + protected override void RegisterRecipients() + { + base.RegisterRecipients(); + + Messenger.Register(this); + Messenger.Register(this); + Messenger.Register(this); + Messenger.Register(this); + Messenger.Register(this); + Messenger.Register(this); + } + protected override void UnregisterRecipients() + { + base.UnregisterRecipients(); + + Messenger.Unregister(this); + Messenger.Unregister(this); + Messenger.Unregister(this); + Messenger.Unregister(this); + Messenger.Unregister(this); + Messenger.Unregister(this); + } + private void AccountCalendarStateCollectivelyChanged(object sender, GroupedAccountCalendarViewModel e) => FilterActiveCalendars(DayRanges); diff --git a/Wino.Calendar/Controls/WinoCalendarControl.cs b/Wino.Calendar/Controls/WinoCalendarControl.cs index e2930e6c..11a37109 100644 --- a/Wino.Calendar/Controls/WinoCalendarControl.cs +++ b/Wino.Calendar/Controls/WinoCalendarControl.cs @@ -255,7 +255,7 @@ public partial class WinoCalendarControl : Control // Total height of the FlipViewItem is the same as vertical ScrollViewer to position day headers. await Task.Yield(); - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => + await DispatcherQueue.EnqueueAsync(() => { double hourHeght = 60; double totalHeight = ActiveScrollViewer.ScrollableHeight; diff --git a/Wino.Calendar/Controls/WinoCalendarFlipView.cs b/Wino.Calendar/Controls/WinoCalendarFlipView.cs index 679490d4..b838dd75 100644 --- a/Wino.Calendar/Controls/WinoCalendarFlipView.cs +++ b/Wino.Calendar/Controls/WinoCalendarFlipView.cs @@ -104,7 +104,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { var flipViewItem = task.Result; - _ = Dispatcher.TryRunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + _ = DispatcherQueue.TryEnqueue(() => { ActiveVerticalScrollViewer = flipViewItem.FindDescendant(); }); @@ -125,7 +125,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { var flipViewItem = task.Result; - _ = Dispatcher.TryRunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + _ = DispatcherQueue.TryEnqueue(() => { ActiveCanvas = flipViewItem.FindDescendant(); }); @@ -142,7 +142,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { await Task.Yield(); - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => + await DispatcherQueue.EnqueueAsync(() => { // Find the day range that contains the date. var dayRange = GetItemsSource()?.FirstOrDefault(a => a.CalendarDays.Any(b => b.RepresentingDate.Date == dateTime.Date)); diff --git a/Wino.Core.ViewModels/CoreBaseViewModel.cs b/Wino.Core.ViewModels/CoreBaseViewModel.cs index 4c3ec6c4..0650bd60 100644 --- a/Wino.Core.ViewModels/CoreBaseViewModel.cs +++ b/Wino.Core.ViewModels/CoreBaseViewModel.cs @@ -29,6 +29,7 @@ public class CoreBaseViewModel : ObservableRecipient, INavigationAware public virtual void OnNavigatedTo(NavigationMode mode, object parameters) { + UnregisterRecipients(); RegisterRecipients(); } diff --git a/Wino.Mail.ViewModels/MailAppShellViewModel.cs b/Wino.Mail.ViewModels/MailAppShellViewModel.cs index b3c81ca4..3bc57be2 100644 --- a/Wino.Mail.ViewModels/MailAppShellViewModel.cs +++ b/Wino.Mail.ViewModels/MailAppShellViewModel.cs @@ -220,6 +220,9 @@ public partial class MailAppShellViewModel : MailBaseViewModel, public override async void OnNavigatedTo(NavigationMode mode, object parameters) { base.OnNavigatedTo(mode, parameters); + + if (mode == NavigationMode.Back) return; + await CreateFooterItemsAsync(); await RecreateMenuItemsAsync(); diff --git a/Wino.Mail.WinUI/App.xaml.cs b/Wino.Mail.WinUI/App.xaml.cs index 10e8722b..b90e2ec1 100644 --- a/Wino.Mail.WinUI/App.xaml.cs +++ b/Wino.Mail.WinUI/App.xaml.cs @@ -341,7 +341,7 @@ public partial class App : WinoApplication, /// Creates the main window without activating it. /// Used for both normal launch and startup task launch (tray only). /// - private void CreateWindow(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) + private void CreateWindow(LaunchActivatedEventArgs args) { LogActivation("Creating main window."); diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs index eb32d8bb..6de17e97 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarControl.cs @@ -2,6 +2,7 @@ using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; +using CommunityToolkit.WinUI; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Wino.Calendar.Args; @@ -255,7 +256,7 @@ public partial class WinoCalendarControl : Control // Total height of the FlipViewItem is the same as vertical ScrollViewer to position day headers. await Task.Yield(); - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => + await DispatcherQueue.EnqueueAsync(() => { double hourHeght = 60; double totalHeight = ActiveScrollViewer.ScrollableHeight; diff --git a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs index 0270b002..de9ba8ad 100644 --- a/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs +++ b/Wino.Mail.WinUI/Controls/Calendar/WinoCalendarFlipView.cs @@ -88,8 +88,6 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView } return ContainerFromIndex(SelectedIndex) as FlipViewItem; - - } private void UpdateActiveScrollViewer() @@ -104,7 +102,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { var flipViewItem = task.Result; - _ = Dispatcher.TryRunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + _ = DispatcherQueue.TryEnqueue(() => { ActiveVerticalScrollViewer = flipViewItem.FindDescendant(); }); @@ -125,7 +123,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { var flipViewItem = task.Result; - _ = Dispatcher.TryRunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () => + _ = DispatcherQueue.TryEnqueue(() => { ActiveCanvas = flipViewItem.FindDescendant(); }); @@ -142,7 +140,7 @@ public partial class WinoCalendarFlipView : CustomCalendarFlipView { await Task.Yield(); - await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => + await DispatcherQueue.EnqueueAsync(() => { // Find the day range that contains the date. var dayRange = GetItemsSource()?.FirstOrDefault(a => a.CalendarDays.Any(b => b.RepresentingDate.Date == dateTime.Date)); diff --git a/Wino.Mail.WinUI/MailAppShell.xaml.cs b/Wino.Mail.WinUI/MailAppShell.xaml.cs index 7b3e992d..81d0eb2d 100644 --- a/Wino.Mail.WinUI/MailAppShell.xaml.cs +++ b/Wino.Mail.WinUI/MailAppShell.xaml.cs @@ -9,6 +9,7 @@ using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; using Microsoft.UI.Xaml.Input; +using Microsoft.UI.Xaml.Navigation; using Windows.Foundation; using Wino.Core.Domain; using Wino.Core.Domain.Entities.Mail; @@ -45,6 +46,13 @@ public sealed partial class MailAppShell : MailAppShellAbstract, InitializeComponent(); } + protected override void OnNavigatedFrom(NavigationEventArgs e) + { + base.OnNavigatedFrom(e); + + Bindings.StopTracking(); + } + private async void ItemDroppedOnFolder(object sender, DragEventArgs e) { // Validate package content. diff --git a/Wino.Mail.WinUI/Services/AccountCalendarStateService.cs b/Wino.Mail.WinUI/Services/AccountCalendarStateService.cs index a0bb5212..9dc8ab03 100644 --- a/Wino.Mail.WinUI/Services/AccountCalendarStateService.cs +++ b/Wino.Mail.WinUI/Services/AccountCalendarStateService.cs @@ -73,9 +73,9 @@ public partial class AccountCalendarStateService : ObservableObject, IAccountCal public void ClearGroupedAccountCalendar() { - foreach (var groupedAccountCalendar in _internalGroupedAccountCalendars) + while (_internalGroupedAccountCalendars.Any()) { - RemoveGroupedAccountCalendar(groupedAccountCalendar); + RemoveGroupedAccountCalendar(_internalGroupedAccountCalendars[0]); } } diff --git a/Wino.Mail.WinUI/Services/NavigationService.cs b/Wino.Mail.WinUI/Services/NavigationService.cs index 76da25d8..0942267d 100644 --- a/Wino.Mail.WinUI/Services/NavigationService.cs +++ b/Wino.Mail.WinUI/Services/NavigationService.cs @@ -87,15 +87,38 @@ public class NavigationService : NavigationServiceBase, INavigationService if (coreFrame == null) return false; - if (mode == WinoApplicationMode.Mail) + var targetPageType = mode == WinoApplicationMode.Mail ? typeof(MailAppShell) : typeof(CalendarAppShell); + var currentPageType = coreFrame.Content?.GetType(); + var transitionInfo = GetNavigationTransitionInfo(NavigationTransitionType.DrillIn); + + // If already on the target page, do nothing + if (currentPageType == targetPageType) + return true; + + // Check if we can go back to the target page + if (coreFrame.CanGoBack && coreFrame.BackStack.Count > 0) { - coreFrame.Navigate(typeof(MailAppShell), null); - } - else - { - coreFrame.Navigate(typeof(CalendarAppShell), null); + var previousPage = coreFrame.BackStack[coreFrame.BackStack.Count - 1]; + if (previousPage.SourcePageType == targetPageType) + { + coreFrame.GoBack(transitionInfo); + return true; + } } + // Check if we can go forward to the target page + if (coreFrame.CanGoForward && coreFrame.ForwardStack.Count > 0) + { + var nextPage = coreFrame.ForwardStack[coreFrame.ForwardStack.Count - 1]; + if (nextPage.SourcePageType == targetPageType) + { + coreFrame.GoForward(); + return true; + } + } + + // Navigate to the target page only if it's not in the navigation stack + coreFrame.Navigate(targetPageType, null, transitionInfo); return true; } @@ -112,7 +135,11 @@ public class NavigationService : NavigationServiceBase, INavigationService if (shellFrame != null) { var currentFrameType = GetCurrentFrameType(ref shellFrame); - + bool isCalendarShellActive = shellFrame.Content != null && shellFrame.Content.GetType() == typeof(CalendarAppShell); + if (isCalendarShellActive) + { + return shellFrame.Navigate(pageType, parameter); + } bool isMailListingPageActive = currentFrameType != null && currentFrameType == typeof(MailListPage); // Active page is mail list page and we are refreshing the folder. diff --git a/Wino.Mail.WinUI/ShellWindow.xaml b/Wino.Mail.WinUI/ShellWindow.xaml index 7bf5173a..3ae6a173 100644 --- a/Wino.Mail.WinUI/ShellWindow.xaml +++ b/Wino.Mail.WinUI/ShellWindow.xaml @@ -25,7 +25,7 @@ - + ShellTitleBar; @@ -88,7 +120,12 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow, IRecipient private void MainFrameNavigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e) { - if (e.Content is BasePage basePage) + // Mail shell has shell content only for mail list page + // Thus, we check if the current content is MailAppShell + + if (sender is Frame mainFrame && mainFrame.Content is MailAppShell mailAppShellPage) + ShellTitleBar.Content = mailAppShellPage.TopShellContent; + else if (e.Content is BasePage basePage) ShellTitleBar.Content = basePage.ShellContent; } diff --git a/Wino.Mail.WinUI/Views/Abstract/CalendarAppShellAbstract .cs b/Wino.Mail.WinUI/Views/Abstract/CalendarAppShellAbstract .cs index 9a92e942..a2613d09 100644 --- a/Wino.Mail.WinUI/Views/Abstract/CalendarAppShellAbstract .cs +++ b/Wino.Mail.WinUI/Views/Abstract/CalendarAppShellAbstract .cs @@ -3,4 +3,10 @@ using Wino.Mail.WinUI; namespace Wino.Mail.Views.Abstract; -public abstract class CalendarAppShellAbstract : BasePage { } +public abstract class CalendarAppShellAbstract : BasePage +{ + protected CalendarAppShellAbstract() + { + NavigationCacheMode = Microsoft.UI.Xaml.Navigation.NavigationCacheMode.Enabled; + } +} diff --git a/Wino.Mail.WinUI/Views/Abstract/MailAppShellAbstract.cs b/Wino.Mail.WinUI/Views/Abstract/MailAppShellAbstract.cs index f48ceae9..91f40020 100644 --- a/Wino.Mail.WinUI/Views/Abstract/MailAppShellAbstract.cs +++ b/Wino.Mail.WinUI/Views/Abstract/MailAppShellAbstract.cs @@ -5,4 +5,8 @@ namespace Wino.Views.Abstract; public abstract class MailAppShellAbstract : BasePage { + protected MailAppShellAbstract() + { + NavigationCacheMode = Microsoft.UI.Xaml.Navigation.NavigationCacheMode.Enabled; + } } diff --git a/Wino.Mail.WinUI/Views/Calendar/CalendarAppShell.xaml b/Wino.Mail.WinUI/Views/Calendar/CalendarAppShell.xaml index 919878c8..051afacb 100644 --- a/Wino.Mail.WinUI/Views/Calendar/CalendarAppShell.xaml +++ b/Wino.Mail.WinUI/Views/Calendar/CalendarAppShell.xaml @@ -37,6 +37,86 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - @@ -164,9 +146,8 @@ IsPaneOpen="{x:Bind ViewModel.PreferencesService.IsNavigationPaneOpened, Mode=TwoWay}" PaneBackground="Transparent"> - + -