Some issues with changing the app mode and notifications have been fixed.
This commit is contained in:
@@ -31,6 +31,7 @@ using Wino.Messaging.Client.Accounts;
|
|||||||
using Wino.Messaging.Server;
|
using Wino.Messaging.Server;
|
||||||
using Wino.Messaging.UI;
|
using Wino.Messaging.UI;
|
||||||
using Wino.Services;
|
using Wino.Services;
|
||||||
|
using WinUIEx;
|
||||||
namespace Wino.Mail.WinUI;
|
namespace Wino.Mail.WinUI;
|
||||||
|
|
||||||
public partial class App : WinoApplication,
|
public partial class App : WinoApplication,
|
||||||
@@ -186,8 +187,13 @@ public partial class App : WinoApplication,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void AppNotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
|
private void AppNotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
|
||||||
=> await HandleToastActivationAsync(args);
|
{
|
||||||
|
if (MainWindow?.DispatcherQueue?.TryEnqueue(() => _ = HandleToastActivationAsync(args)) == true)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ = HandleToastActivationAsync(args);
|
||||||
|
}
|
||||||
|
|
||||||
private void TryRegisterAppNotifications()
|
private void TryRegisterAppNotifications()
|
||||||
{
|
{
|
||||||
@@ -247,7 +253,7 @@ public partial class App : WinoApplication,
|
|||||||
var calendarService = Services.GetRequiredService<ICalendarService>();
|
var calendarService = Services.GetRequiredService<ICalendarService>();
|
||||||
var navigationService = Services.GetRequiredService<INavigationService>();
|
var navigationService = Services.GetRequiredService<INavigationService>();
|
||||||
|
|
||||||
var calendarItem = await calendarService.GetCalendarItemAsync(calendarItemId).ConfigureAwait(false);
|
var calendarItem = await calendarService.GetCalendarItemAsync(calendarItemId);
|
||||||
if (calendarItem == null)
|
if (calendarItem == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -259,8 +265,7 @@ public partial class App : WinoApplication,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MainWindow?.BringToFront();
|
EnsureMainWindowVisibleAndForeground();
|
||||||
MainWindow?.Activate();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Calendar);
|
navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Calendar);
|
||||||
@@ -276,10 +281,10 @@ public partial class App : WinoApplication,
|
|||||||
var mailService = Services.GetRequiredService<IMailService>();
|
var mailService = Services.GetRequiredService<IMailService>();
|
||||||
var navigationService = Services.GetRequiredService<INavigationService>();
|
var navigationService = Services.GetRequiredService<INavigationService>();
|
||||||
|
|
||||||
var account = await mailService.GetMailAccountByUniqueIdAsync(mailItemUniqueId).ConfigureAwait(false);
|
var account = await mailService.GetMailAccountByUniqueIdAsync(mailItemUniqueId);
|
||||||
if (account == null) return;
|
if (account == null) return;
|
||||||
|
|
||||||
var mailItem = await mailService.GetSingleMailItemAsync(mailItemUniqueId).ConfigureAwait(false);
|
var mailItem = await mailService.GetSingleMailItemAsync(mailItemUniqueId);
|
||||||
if (mailItem == null) return;
|
if (mailItem == null) return;
|
||||||
|
|
||||||
var message = new AccountMenuItemExtended(mailItem.AssignedFolder.Id, mailItem);
|
var message = new AccountMenuItemExtended(mailItem.AssignedFolder.Id, mailItem);
|
||||||
@@ -300,7 +305,7 @@ public partial class App : WinoApplication,
|
|||||||
// App is already running - send message and bring window to front.
|
// App is already running - send message and bring window to front.
|
||||||
navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Mail);
|
navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Mail);
|
||||||
WeakReferenceMessenger.Default.Send(message);
|
WeakReferenceMessenger.Default.Send(message);
|
||||||
MainWindow?.BringToFront();
|
EnsureMainWindowVisibleAndForeground();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -418,6 +423,7 @@ public partial class App : WinoApplication,
|
|||||||
LogActivation("Creating main window.");
|
LogActivation("Creating main window.");
|
||||||
|
|
||||||
MainWindow = new ShellWindow();
|
MainWindow = new ShellWindow();
|
||||||
|
InitializeNavigationDispatcher();
|
||||||
|
|
||||||
var nativeAppService = Services.GetRequiredService<INativeAppService>();
|
var nativeAppService = Services.GetRequiredService<INativeAppService>();
|
||||||
nativeAppService.GetCoreWindowHwnd = () => WinRT.Interop.WindowNative.GetWindowHandle(MainWindow);
|
nativeAppService.GetCoreWindowHwnd = () => WinRT.Interop.WindowNative.GetWindowHandle(MainWindow);
|
||||||
@@ -450,6 +456,27 @@ public partial class App : WinoApplication,
|
|||||||
shellWindow.HandleAppActivation(args?.Arguments, GetCurrentLaunchTileId(), Environment.CommandLine);
|
shellWindow.HandleAppActivation(args?.Arguments, GetCurrentLaunchTileId(), Environment.CommandLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void InitializeNavigationDispatcher()
|
||||||
|
{
|
||||||
|
if (MainWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (Services.GetService<IDispatcher>() is WinUIDispatcher dispatcher)
|
||||||
|
{
|
||||||
|
dispatcher.Initialize(MainWindow.DispatcherQueue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureMainWindowVisibleAndForeground()
|
||||||
|
{
|
||||||
|
if (MainWindow == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
MainWindow.Show();
|
||||||
|
MainWindow.BringToFront();
|
||||||
|
MainWindow.Activate();
|
||||||
|
}
|
||||||
|
|
||||||
private void RegisterRecipients()
|
private void RegisterRecipients()
|
||||||
{
|
{
|
||||||
WeakReferenceMessenger.Default.Register<NewMailSynchronizationRequested>(this);
|
WeakReferenceMessenger.Default.Register<NewMailSynchronizationRequested>(this);
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ public static class CoreUWPContainerSetup
|
|||||||
public static void RegisterCoreUWPServices(this IServiceCollection services)
|
public static void RegisterCoreUWPServices(this IServiceCollection services)
|
||||||
{
|
{
|
||||||
services.AddSingleton<IApplicationResourceManager<ResourceDictionary>, ApplicationResourceManager>();
|
services.AddSingleton<IApplicationResourceManager<ResourceDictionary>, ApplicationResourceManager>();
|
||||||
|
services.AddSingleton<WinUIDispatcher>();
|
||||||
|
services.AddSingleton<IDispatcher>(provider => provider.GetRequiredService<WinUIDispatcher>());
|
||||||
|
|
||||||
services.AddSingleton<IUnderlyingThemeService, UnderlyingThemeService>();
|
services.AddSingleton<IUnderlyingThemeService, UnderlyingThemeService>();
|
||||||
services.AddSingleton<INativeAppService, NativeAppService>();
|
services.AddSingleton<INativeAppService, NativeAppService>();
|
||||||
|
|||||||
@@ -8,12 +8,38 @@ namespace Wino.Mail.WinUI;
|
|||||||
|
|
||||||
public class WinUIDispatcher : IDispatcher
|
public class WinUIDispatcher : IDispatcher
|
||||||
{
|
{
|
||||||
private readonly DispatcherQueue _coreDispatcher;
|
private DispatcherQueue? _coreDispatcher;
|
||||||
|
|
||||||
|
public WinUIDispatcher()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
public WinUIDispatcher(DispatcherQueue coreDispatcher)
|
public WinUIDispatcher(DispatcherQueue coreDispatcher)
|
||||||
{
|
{
|
||||||
_coreDispatcher = coreDispatcher;
|
_coreDispatcher = coreDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task ExecuteOnUIThread(Action action) => _coreDispatcher.EnqueueAsync(action, DispatcherQueuePriority.Normal);
|
public bool HasThreadAccess => _coreDispatcher?.HasThreadAccess == true;
|
||||||
|
|
||||||
|
public void Initialize(DispatcherQueue coreDispatcher)
|
||||||
|
{
|
||||||
|
_coreDispatcher ??= coreDispatcher ?? throw new ArgumentNullException(nameof(coreDispatcher));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task ExecuteOnUIThread(Action action)
|
||||||
|
{
|
||||||
|
if (action == null)
|
||||||
|
throw new ArgumentNullException(nameof(action));
|
||||||
|
|
||||||
|
if (_coreDispatcher == null)
|
||||||
|
throw new InvalidOperationException("UI dispatcher is not initialized.");
|
||||||
|
|
||||||
|
if (_coreDispatcher.HasThreadAccess)
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _coreDispatcher.EnqueueAsync(action, DispatcherQueuePriority.Normal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ namespace Wino.Services;
|
|||||||
public class NavigationService : NavigationServiceBase, INavigationService
|
public class NavigationService : NavigationServiceBase, INavigationService
|
||||||
{
|
{
|
||||||
private readonly IStatePersistanceService _statePersistanceService;
|
private readonly IStatePersistanceService _statePersistanceService;
|
||||||
|
private readonly IDispatcher _dispatcher;
|
||||||
|
|
||||||
private WinoPage[] _renderingPageTypes = new WinoPage[]
|
private WinoPage[] _renderingPageTypes = new WinoPage[]
|
||||||
{
|
{
|
||||||
@@ -50,9 +51,34 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
WinoPage.EventDetailsPage
|
WinoPage.EventDetailsPage
|
||||||
];
|
];
|
||||||
|
|
||||||
public NavigationService(IStatePersistanceService statePersistanceService)
|
public NavigationService(IStatePersistanceService statePersistanceService, IDispatcher dispatcher)
|
||||||
{
|
{
|
||||||
_statePersistanceService = statePersistanceService;
|
_statePersistanceService = statePersistanceService;
|
||||||
|
_dispatcher = dispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsOnNavigationThread()
|
||||||
|
=> _dispatcher is WinUIDispatcher winUiDispatcher && winUiDispatcher.HasThreadAccess;
|
||||||
|
|
||||||
|
private T ExecuteOnNavigationThread<T>(Func<T> action)
|
||||||
|
{
|
||||||
|
if (IsOnNavigationThread())
|
||||||
|
return action();
|
||||||
|
|
||||||
|
T result = default!;
|
||||||
|
_dispatcher.ExecuteOnUIThread(() => result = action()).GetAwaiter().GetResult();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ExecuteOnNavigationThread(Action action)
|
||||||
|
{
|
||||||
|
if (IsOnNavigationThread())
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dispatcher.ExecuteOnUIThread(action).GetAwaiter().GetResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Type? GetPageType(WinoPage winoPage)
|
public Type? GetPageType(WinoPage winoPage)
|
||||||
@@ -94,6 +120,9 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Frame GetCoreFrame(NavigationReferenceFrame frameType)
|
public Frame GetCoreFrame(NavigationReferenceFrame frameType)
|
||||||
|
=> ExecuteOnNavigationThread(() => GetCoreFrameInternal(frameType));
|
||||||
|
|
||||||
|
private Frame GetCoreFrameInternal(NavigationReferenceFrame frameType)
|
||||||
{
|
{
|
||||||
if (WinoApplication.MainWindow is not IWinoShellWindow shellWindow) throw new ArgumentException("MainWindow must implement IWinoShellWindow");
|
if (WinoApplication.MainWindow is not IWinoShellWindow shellWindow) throw new ArgumentException("MainWindow must implement IWinoShellWindow");
|
||||||
if (shellWindow.GetMainFrame() is not Frame mainFrame) throw new ArgumentException("MainFrame cannot be null.");
|
if (shellWindow.GetMainFrame() is not Frame mainFrame) throw new ArgumentException("MainFrame cannot be null.");
|
||||||
@@ -107,8 +136,11 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public bool ChangeApplicationMode(WinoApplicationMode mode)
|
public bool ChangeApplicationMode(WinoApplicationMode mode)
|
||||||
|
=> ExecuteOnNavigationThread(() => ChangeApplicationModeInternal(mode));
|
||||||
|
|
||||||
|
private bool ChangeApplicationModeInternal(WinoApplicationMode mode)
|
||||||
{
|
{
|
||||||
var coreFrame = GetCoreFrame(NavigationReferenceFrame.ShellFrame);
|
var coreFrame = GetCoreFrameInternal(NavigationReferenceFrame.ShellFrame);
|
||||||
|
|
||||||
if (coreFrame == null) return false;
|
if (coreFrame == null) return false;
|
||||||
|
|
||||||
@@ -154,6 +186,12 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
object? parameter = null,
|
object? parameter = null,
|
||||||
NavigationReferenceFrame frame = NavigationReferenceFrame.InnerShellFrame,
|
NavigationReferenceFrame frame = NavigationReferenceFrame.InnerShellFrame,
|
||||||
NavigationTransitionType transition = NavigationTransitionType.None)
|
NavigationTransitionType transition = NavigationTransitionType.None)
|
||||||
|
=> ExecuteOnNavigationThread(() => NavigateInternal(page, parameter, frame, transition));
|
||||||
|
|
||||||
|
private bool NavigateInternal(WinoPage page,
|
||||||
|
object? parameter = null,
|
||||||
|
NavigationReferenceFrame frame = NavigationReferenceFrame.InnerShellFrame,
|
||||||
|
NavigationTransitionType transition = NavigationTransitionType.None)
|
||||||
{
|
{
|
||||||
var pageType = GetPageType(page);
|
var pageType = GetPageType(page);
|
||||||
if (pageType == null) return false;
|
if (pageType == null) return false;
|
||||||
@@ -173,7 +211,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
_statePersistanceService.IsReadingMail = _renderingPageTypes.Contains(page);
|
_statePersistanceService.IsReadingMail = _renderingPageTypes.Contains(page);
|
||||||
_statePersistanceService.IsEventDetailsVisible = page == WinoPage.EventDetailsPage;
|
_statePersistanceService.IsEventDetailsVisible = page == WinoPage.EventDetailsPage;
|
||||||
|
|
||||||
Frame innerShellFrame = GetCoreFrame(NavigationReferenceFrame.InnerShellFrame);
|
Frame innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
||||||
|
|
||||||
if (innerShellFrame != null)
|
if (innerShellFrame != null)
|
||||||
{
|
{
|
||||||
@@ -227,8 +265,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
// This page must be opened in the Frame placed in MailListingPage.
|
// This page must be opened in the Frame placed in MailListingPage.
|
||||||
if (isMailListingPageActive && frame == NavigationReferenceFrame.RenderingFrame)
|
if (isMailListingPageActive && frame == NavigationReferenceFrame.RenderingFrame)
|
||||||
{
|
{
|
||||||
var listingFrame = GetCoreFrame(NavigationReferenceFrame.RenderingFrame);
|
var listingFrame = GetCoreFrameInternal(NavigationReferenceFrame.RenderingFrame);
|
||||||
|
|
||||||
if (listingFrame == null) return false;
|
if (listingFrame == null) return false;
|
||||||
|
|
||||||
// Active page is mail list page and we are opening a mail item.
|
// Active page is mail list page and we are opening a mail item.
|
||||||
@@ -294,6 +331,9 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void GoBack(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
|
public void GoBack(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
|
||||||
|
=> ExecuteOnNavigationThread(() => GoBackInternal(slideEffect));
|
||||||
|
|
||||||
|
private void GoBackInternal(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
|
||||||
{
|
{
|
||||||
// Check if we're navigating within ManageAccountsPage (applies to both modes)
|
// Check if we're navigating within ManageAccountsPage (applies to both modes)
|
||||||
// Check if we're navigating within SettingsPage (applies to both modes)
|
// Check if we're navigating within SettingsPage (applies to both modes)
|
||||||
@@ -304,7 +344,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var innerShellFrame = GetCoreFrame(NavigationReferenceFrame.InnerShellFrame);
|
var innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
||||||
|
|
||||||
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && innerShellFrame?.CanGoBack == true)
|
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && innerShellFrame?.CanGoBack == true)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
|||||||
ViewModel.ExecuteHoverActionCommand.Execute(e);
|
ViewModel.ExecuteHoverActionCommand.Execute(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void FolderPivotChanged(object sender, SelectionChangedEventArgs e)
|
private async void FolderPivotChanged(object sender, SelectionChangedEventArgs e)
|
||||||
{
|
{
|
||||||
foreach (var addedItem in e.AddedItems)
|
foreach (var addedItem in e.AddedItems)
|
||||||
{
|
{
|
||||||
@@ -144,6 +144,11 @@ public sealed partial class MailListPage : MailListPageAbstract,
|
|||||||
SelectAllCheckbox.IsChecked = false;
|
SelectAllCheckbox.IsChecked = false;
|
||||||
SelectionModeToggle.IsChecked = false;
|
SelectionModeToggle.IsChecked = false;
|
||||||
|
|
||||||
|
if (ViewModel.MailCollection.SelectedItemsCount > 0)
|
||||||
|
{
|
||||||
|
await ViewModel.MailCollection.UnselectAllAsync();
|
||||||
|
}
|
||||||
|
|
||||||
UpdateSelectAllButtonStatus();
|
UpdateSelectAllButtonStatus();
|
||||||
ViewModel.SelectedPivotChangedCommand.Execute(null);
|
ViewModel.SelectedPivotChangedCommand.Execute(null);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user