Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bba3523ec6 |
@@ -178,6 +178,18 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
|
||||
await InitializeAccountCalendarsAsync();
|
||||
ValidateConfiguredNewEventCalendar();
|
||||
|
||||
if (activationContext?.Parameter is CalendarItemTarget calendarItemTarget)
|
||||
{
|
||||
NavigationService.Navigate(WinoPage.EventDetailsPage, calendarItemTarget);
|
||||
return;
|
||||
}
|
||||
|
||||
if (activationContext?.Parameter is CalendarPageNavigationArgs calendarPageNavigationArgs)
|
||||
{
|
||||
NavigationService.Navigate(WinoPage.CalendarPage, calendarPageNavigationArgs);
|
||||
return;
|
||||
}
|
||||
|
||||
TodayClicked();
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ public static class Constants
|
||||
public const string ToastCalendarJoinOnlineAction = nameof(ToastCalendarJoinOnlineAction);
|
||||
public const string ToastCalendarSnoozeAction = nameof(ToastCalendarSnoozeAction);
|
||||
public const string ToastCalendarSnoozeDurationInputId = nameof(ToastCalendarSnoozeDurationInputId);
|
||||
public const string ToastCalendarSnoozeDurationMinutesKey = nameof(ToastCalendarSnoozeDurationMinutesKey);
|
||||
public const string ToastModeKey = nameof(ToastModeKey);
|
||||
public const string ToastModeMail = nameof(ToastModeMail);
|
||||
public const string ToastModeCalendar = nameof(ToastModeCalendar);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Microsoft.Windows.AppNotifications;
|
||||
using System;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
@@ -49,8 +49,31 @@ internal static class ToastActivationResolver
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryResolveMode(NotificationArguments toastArguments, out WinoApplicationMode mode)
|
||||
{
|
||||
mode = WinoApplicationMode.Mail;
|
||||
|
||||
if (!toastArguments.TryGetValue(Constants.ToastModeKey, out string toastMode))
|
||||
return false;
|
||||
|
||||
if (string.Equals(toastMode, Constants.ToastModeCalendar, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mode = WinoApplicationMode.Calendar;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (string.Equals(toastMode, Constants.ToastModeMail, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
mode = WinoApplicationMode.Mail;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool ContainsKnownToastKey(NotificationArguments toastArguments)
|
||||
=> toastArguments.TryGetValue(Constants.ToastStoreUpdateActionKey, out string _) ||
|
||||
toastArguments.TryGetValue(Constants.ToastModeKey, out string _) ||
|
||||
toastArguments.TryGetValue(Constants.ToastCalendarActionKey, out string _) ||
|
||||
toastArguments.TryGetValue(Constants.ToastActionKey, out string _);
|
||||
}
|
||||
|
||||
+111
-43
@@ -4,8 +4,8 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.UI.Dispatching;
|
||||
@@ -16,7 +16,6 @@ using Microsoft.Windows.AppNotifications;
|
||||
using MimeKit.Cryptography;
|
||||
using Windows.ApplicationModel.Activation;
|
||||
using Windows.ApplicationModel.DataTransfer;
|
||||
using Windows.ApplicationModel.DataTransfer.ShareTarget;
|
||||
using Windows.Storage;
|
||||
using Wino.Calendar.ViewModels;
|
||||
using Wino.Calendar.ViewModels.Interfaces;
|
||||
@@ -543,23 +542,20 @@ public partial class App : WinoApplication,
|
||||
{
|
||||
var activationArgs = AppInstance.GetCurrent().GetActivatedEventArgs();
|
||||
|
||||
if (activationArgs.Kind != ExtendedActivationKind.AppNotification ||
|
||||
activationArgs.Data is not AppNotificationActivatedEventArgs toastArgs ||
|
||||
!TryMarkInitialNotificationActivationHandled())
|
||||
if (activationArgs.Kind == ExtendedActivationKind.Launch &&
|
||||
activationArgs.Data is ILaunchActivatedEventArgs launchArgs &&
|
||||
ToastActivationResolver.TryParse(launchArgs.Arguments, out var launchToastArguments) &&
|
||||
TryMarkInitialNotificationActivationHandled())
|
||||
{
|
||||
return;
|
||||
LogActivation($"Processing initial toast launch activation from application startup. Arguments: {launchArgs.Arguments}");
|
||||
|
||||
await EnsureActivationInfrastructureAsync();
|
||||
await HandleToastActivationAsync(launchToastArguments);
|
||||
}
|
||||
|
||||
LogActivation($"Processing initial notification activation from application startup. Arguments: {toastArgs.Argument}");
|
||||
|
||||
await EnsureActivationInfrastructureAsync();
|
||||
await HandleToastActivationAsync(toastArgs.Argument, toastArgs.UserInput);
|
||||
}
|
||||
|
||||
private void AppNotificationInvoked(AppNotificationManager sender, AppNotificationActivatedEventArgs args)
|
||||
{
|
||||
// AppNotification callbacks are not guaranteed to run on the UI thread.
|
||||
// Marshal toast handling to the window dispatcher before touching window APIs.
|
||||
if (MainWindow?.DispatcherQueue?.TryEnqueue(() => _ = HandleToastActivationAsync(args.Argument, args.UserInput)) == true)
|
||||
return;
|
||||
|
||||
@@ -569,19 +565,7 @@ public partial class App : WinoApplication,
|
||||
|
||||
private void TryRegisterAppNotifications()
|
||||
{
|
||||
var notificationManager = AppNotificationManager.Default;
|
||||
|
||||
notificationManager.NotificationInvoked -= AppNotificationInvoked;
|
||||
notificationManager.NotificationInvoked += AppNotificationInvoked;
|
||||
|
||||
try
|
||||
{
|
||||
notificationManager.Register();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogActivation($"App notification registration failed: {ex.GetType().Name} - {ex.Message}");
|
||||
}
|
||||
// Classic targeted toasts use normal launch activation instead of COM toast activators.
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -611,7 +595,7 @@ public partial class App : WinoApplication,
|
||||
|
||||
if (calendarAction == Constants.ToastCalendarSnoozeAction)
|
||||
{
|
||||
await HandleCalendarToastSnoozeAsync(userInput, calendarItemId);
|
||||
await HandleCalendarToastSnoozeAsync(toastArguments, userInput, calendarItemId);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -656,6 +640,26 @@ public partial class App : WinoApplication,
|
||||
return HandleToastActivationAsync(toastArguments, userInput);
|
||||
}
|
||||
|
||||
private static int? GetToastSnoozeDurationMinutes(NotificationArguments toastArguments, IDictionary<string, string>? userInput)
|
||||
{
|
||||
if (toastArguments.TryGetValue(Constants.ToastCalendarSnoozeDurationMinutesKey, out var snoozeDurationValue) &&
|
||||
int.TryParse(snoozeDurationValue, out var snoozeDurationMinutes) &&
|
||||
snoozeDurationMinutes > 0)
|
||||
{
|
||||
return snoozeDurationMinutes;
|
||||
}
|
||||
|
||||
if (userInput != null &&
|
||||
userInput.TryGetValue(Constants.ToastCalendarSnoozeDurationInputId, out var selectedValue) &&
|
||||
int.TryParse(selectedValue, out snoozeDurationMinutes) &&
|
||||
snoozeDurationMinutes > 0)
|
||||
{
|
||||
return snoozeDurationMinutes;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<bool> HandleShareTargetActivationAsync(AppActivationArguments activationArgs, bool activateWindow)
|
||||
{
|
||||
if (activationArgs.Kind != ExtendedActivationKind.ShareTarget ||
|
||||
@@ -810,9 +814,59 @@ public partial class App : WinoApplication,
|
||||
navigationService.Navigate(WinoPage.EventDetailsPage, target);
|
||||
}
|
||||
|
||||
private async Task HandleCalendarToastSnoozeAsync(IDictionary<string, string>? userInput, Guid calendarItemId)
|
||||
private async Task<object?> TryCreateToastNavigationParameterAsync(NotificationArguments toastArguments)
|
||||
{
|
||||
if (!TryGetSnoozeDurationMinutes(userInput, out var snoozeDurationMinutes))
|
||||
if (toastArguments.TryGetValue(Constants.ToastCalendarActionKey, out string calendarAction) &&
|
||||
calendarAction == Constants.ToastCalendarNavigateAction &&
|
||||
toastArguments.TryGetValue(Constants.ToastCalendarItemIdKey, out string calendarItemIdString) &&
|
||||
Guid.TryParse(calendarItemIdString, out Guid calendarItemId))
|
||||
{
|
||||
var calendarService = Services.GetRequiredService<ICalendarService>();
|
||||
var calendarItem = await calendarService.GetCalendarItemAsync(calendarItemId);
|
||||
|
||||
if (calendarItem != null)
|
||||
{
|
||||
return new CalendarItemTarget(calendarItem, CalendarEventTargetType.Single);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task<(WinoApplicationMode Mode, object? Parameter)?> TryResolveToastActivationTargetAsync(AppActivationArguments activationArgs)
|
||||
{
|
||||
NotificationArguments? toastArguments = null;
|
||||
|
||||
if (activationArgs.Kind == ExtendedActivationKind.Launch &&
|
||||
activationArgs.Data is ILaunchActivatedEventArgs launchArgs &&
|
||||
ToastActivationResolver.TryParse(launchArgs.Arguments, out var launchToastArguments))
|
||||
{
|
||||
toastArguments = launchToastArguments;
|
||||
}
|
||||
else if (activationArgs.Kind == ExtendedActivationKind.AppNotification &&
|
||||
activationArgs.Data is AppNotificationActivatedEventArgs appNotificationArgs &&
|
||||
ToastActivationResolver.TryParse(appNotificationArgs.Argument, out var appNotificationToastArguments))
|
||||
{
|
||||
toastArguments = appNotificationToastArguments;
|
||||
}
|
||||
else if (activationArgs.Data is ToastNotificationActivatedEventArgs classicToastArgs &&
|
||||
ToastActivationResolver.TryParse(classicToastArgs.Argument, out var classicToastArguments))
|
||||
{
|
||||
toastArguments = classicToastArguments;
|
||||
}
|
||||
|
||||
if (toastArguments == null ||
|
||||
!ToastActivationResolver.TryResolveMode(toastArguments, out var mode))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return (mode, await TryCreateToastNavigationParameterAsync(toastArguments));
|
||||
}
|
||||
|
||||
private async Task HandleCalendarToastSnoozeAsync(NotificationArguments toastArguments, IDictionary<string, string>? userInput, Guid calendarItemId)
|
||||
{
|
||||
if (!TryGetSnoozeDurationMinutes(toastArguments, userInput, out var snoozeDurationMinutes))
|
||||
return;
|
||||
|
||||
var calendarService = Services.GetRequiredService<ICalendarService>();
|
||||
@@ -836,20 +890,13 @@ public partial class App : WinoApplication,
|
||||
await nativeAppService.LaunchUriAsync(joinUri);
|
||||
}
|
||||
|
||||
private bool TryGetSnoozeDurationMinutes(IDictionary<string, string>? userInput, out int snoozeDurationMinutes)
|
||||
private bool TryGetSnoozeDurationMinutes(NotificationArguments toastArguments, IDictionary<string, string>? userInput, out int snoozeDurationMinutes)
|
||||
{
|
||||
snoozeDurationMinutes = _preferencesService?.DefaultSnoozeDurationInMinutes ?? 0;
|
||||
snoozeDurationMinutes = GetToastSnoozeDurationMinutes(toastArguments, userInput)
|
||||
?? _preferencesService?.DefaultSnoozeDurationInMinutes
|
||||
?? 0;
|
||||
|
||||
if (userInput == null ||
|
||||
!userInput.TryGetValue(Constants.ToastCalendarSnoozeDurationInputId, out var selectedValue) ||
|
||||
selectedValue == null)
|
||||
{
|
||||
return snoozeDurationMinutes > 0;
|
||||
}
|
||||
|
||||
var selectedText = selectedValue.ToString();
|
||||
|
||||
return int.TryParse(selectedText, out snoozeDurationMinutes) && snoozeDurationMinutes > 0;
|
||||
return snoozeDurationMinutes > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1584,7 +1631,22 @@ public partial class App : WinoApplication,
|
||||
}
|
||||
else if (TryResolveActivationMode(args, _preferencesService?.DefaultApplicationMode ?? WinoApplicationMode.Mail, out var redirectedMode))
|
||||
{
|
||||
shellWindow.HandleAppActivation(AppEntryConstants.GetModeLaunchArgument(redirectedMode));
|
||||
var navigationService = Services.GetRequiredService<INavigationService>();
|
||||
var toastActivationTarget = await TryResolveToastActivationTargetAsync(args);
|
||||
|
||||
if (toastActivationTarget is { Parameter: CalendarItemTarget calendarTarget })
|
||||
{
|
||||
navigationService.ChangeApplicationMode(toastActivationTarget.Value.Mode, new ShellModeActivationContext
|
||||
{
|
||||
SuppressStartupFlows = true,
|
||||
Parameter = calendarTarget
|
||||
});
|
||||
navigationService.Navigate(WinoPage.EventDetailsPage, calendarTarget);
|
||||
}
|
||||
else
|
||||
{
|
||||
shellWindow.HandleAppActivation(AppEntryConstants.GetModeLaunchArgument(redirectedMode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1597,7 +1659,6 @@ public partial class App : WinoApplication,
|
||||
}
|
||||
}
|
||||
|
||||
// Dispatch to UI thread since this is called from Program.OnActivated.
|
||||
if (MainWindow?.DispatcherQueue.TryEnqueue(() => _ = HandleRedirectedActivationAsync()) == true)
|
||||
return;
|
||||
|
||||
@@ -1642,6 +1703,13 @@ public partial class App : WinoApplication,
|
||||
return true;
|
||||
}
|
||||
|
||||
if (activationArgs.Data is ToastNotificationActivatedEventArgs classicToastArgs &&
|
||||
ToastActivationResolver.TryParse(classicToastArgs.Argument, out var classicToastArguments) &&
|
||||
ToastActivationResolver.TryResolveMode(classicToastArguments, out mode))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (activationArgs.Kind == ExtendedActivationKind.File &&
|
||||
activationArgs.Data is IFileActivatedEventArgs fileArgs)
|
||||
{
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5"
|
||||
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
|
||||
xmlns:com="http://schemas.microsoft.com/appx/manifest/com/windows10"
|
||||
xmlns:desktop="http://schemas.microsoft.com/appx/manifest/desktop/windows10"
|
||||
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
|
||||
IgnorableNamespaces="uap uap10 rescap com desktop">
|
||||
IgnorableNamespaces="uap uap10 rescap">
|
||||
|
||||
<!-- Publisher Cache Folders -->
|
||||
<Extensions>
|
||||
@@ -47,16 +45,15 @@
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$"
|
||||
uap10:Parameters="--wino-mail">
|
||||
<uap:VisualElements
|
||||
<uap:VisualElements
|
||||
DisplayName="Wino Mail"
|
||||
Description="Wino.Mail.WinUI"
|
||||
Description="Wino Mail"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\AppEntries\MailAssets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\AppEntries\MailAssets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\AppEntries\MailAssets\Wide310x150Logo.png" Square71x71Logo="Assets\AppEntries\MailAssets\SmallTile.png" Square310x310Logo="Assets\AppEntries\MailAssets\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Assets\AppEntries\MailAssets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
<uap5:Extension Category="windows.startupTask">
|
||||
<uap5:StartupTask
|
||||
@@ -65,19 +62,6 @@
|
||||
DisplayName="Wino Startup Service" />
|
||||
</uap5:Extension>
|
||||
|
||||
<!-- App notification activation -->
|
||||
<desktop:Extension Category="windows.toastNotificationActivation">
|
||||
<desktop:ToastNotificationActivation ToastActivatorCLSID="72c6d2d0-2538-44fe-a1b1-499f47bb1181" />
|
||||
</desktop:Extension>
|
||||
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:ExeServer Executable="Wino.Mail.WinUI.exe" Arguments="----AppNotificationActivated:" DisplayName="Toast activator">
|
||||
<com:Class Id="72c6d2d0-2538-44fe-a1b1-499f47bb1181" DisplayName="Toast activator"/>
|
||||
</com:ExeServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
|
||||
<!-- Protocol activation: mailto -->
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="mailto" />
|
||||
@@ -118,55 +102,43 @@
|
||||
</Extensions>
|
||||
</Application>
|
||||
|
||||
<Application Id="CalendarApp"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$"
|
||||
uap10:Parameters="--wino-calendar">
|
||||
<uap:VisualElements
|
||||
DisplayName="Wino Calendar"
|
||||
Description="Wino.Mail.WinUI.Calendar"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\AppEntries\CalendarAssets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\AppEntries\CalendarAssets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\AppEntries\CalendarAssets\Wide310x150Logo.png" Square71x71Logo="Assets\AppEntries\CalendarAssets\SmallTile.png" Square310x310Logo="Assets\AppEntries\CalendarAssets\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Assets\AppEntries\CalendarAssets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
<Application Id="CalendarApp"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="$targetentrypoint$"
|
||||
uap10:Parameters="--wino-calendar">
|
||||
<uap:VisualElements
|
||||
DisplayName="Wino Calendar"
|
||||
Description="Wino Calendar"
|
||||
BackgroundColor="transparent"
|
||||
Square150x150Logo="Assets\AppEntries\CalendarAssets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\AppEntries\CalendarAssets\Square44x44Logo.png">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\AppEntries\CalendarAssets\Wide310x150Logo.png" Square71x71Logo="Assets\AppEntries\CalendarAssets\SmallTile.png" Square310x310Logo="Assets\AppEntries\CalendarAssets\LargeTile.png"/>
|
||||
<uap:SplashScreen Image="Assets\AppEntries\CalendarAssets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
|
||||
<Extensions>
|
||||
<desktop:Extension Category="windows.toastNotificationActivation">
|
||||
<desktop:ToastNotificationActivation ToastActivatorCLSID="44c05d2b-aa1d-4e59-9d7d-8b4c8607cb8d" />
|
||||
</desktop:Extension>
|
||||
<Extensions>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="webcal">
|
||||
<uap:DisplayName>Calendar Protocol</uap:DisplayName>
|
||||
</uap:Protocol>
|
||||
</uap:Extension>
|
||||
|
||||
<com:Extension Category="windows.comServer">
|
||||
<com:ComServer>
|
||||
<com:ExeServer Executable="Wino.Mail.WinUI.exe" Arguments="----AppNotificationActivated:" DisplayName="Calendar toast activator">
|
||||
<com:Class Id="44c05d2b-aa1d-4e59-9d7d-8b4c8607cb8d" DisplayName="Calendar toast activator"/>
|
||||
</com:ExeServer>
|
||||
</com:ComServer>
|
||||
</com:Extension>
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="webcals">
|
||||
<uap:DisplayName>Calendar Protocol (Secure)</uap:DisplayName>
|
||||
</uap:Protocol>
|
||||
</uap:Extension>
|
||||
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="webcal">
|
||||
<uap:DisplayName>Calendar Protocol</uap:DisplayName>
|
||||
</uap:Protocol>
|
||||
</uap:Extension>
|
||||
|
||||
<uap:Extension Category="windows.protocol">
|
||||
<uap:Protocol Name="webcals">
|
||||
<uap:DisplayName>Calendar Protocol (Secure)</uap:DisplayName>
|
||||
</uap:Protocol>
|
||||
</uap:Extension>
|
||||
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="ics">
|
||||
<uap:Logo>Assets\AppEntries\CalendarAssets\Square44x44Logo.png</uap:Logo>
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.ics</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
<uap:Extension Category="windows.fileTypeAssociation">
|
||||
<uap:FileTypeAssociation Name="ics">
|
||||
<uap:Logo>Assets\AppEntries\CalendarAssets\Square44x44Logo.png</uap:Logo>
|
||||
<uap:SupportedFileTypes>
|
||||
<uap:FileType>.ics</uap:FileType>
|
||||
</uap:SupportedFileTypes>
|
||||
</uap:FileTypeAssociation>
|
||||
</uap:Extension>
|
||||
</Extensions>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
|
||||
@@ -207,6 +207,13 @@ public class Program
|
||||
: true;
|
||||
}
|
||||
|
||||
if (args.Data is Windows.ApplicationModel.Activation.ToastNotificationActivatedEventArgs classicToastArgs)
|
||||
{
|
||||
return ToastActivationResolver.TryParse(classicToastArgs.Argument, out var toastArguments)
|
||||
? ToastActivationResolver.ShouldBringToForeground(toastArguments)
|
||||
: true;
|
||||
}
|
||||
|
||||
if (args.Kind == ExtendedActivationKind.Launch &&
|
||||
args.Data is Windows.ApplicationModel.Activation.ILaunchActivatedEventArgs launchArgs &&
|
||||
ToastActivationResolver.TryParse(launchArgs.Arguments, out var launchToastArguments))
|
||||
|
||||
@@ -5,8 +5,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Windows.AppNotifications;
|
||||
using Microsoft.Windows.AppNotifications.Builder;
|
||||
using CommunityToolkit.WinUI.Notifications;
|
||||
using Serilog;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI.Notifications;
|
||||
@@ -76,9 +75,9 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddText(Translator.Notifications_MultipleNotificationsTitle);
|
||||
builder.AddText(string.Format(Translator.Notifications_MultipleNotificationsMessage, mailCount));
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
builder.SetAudioUri(new Uri("ms-winsoundevent:Notification.Mail"));
|
||||
builder.AddAudio(new Uri("ms-winsoundevent:Notification.Mail"));
|
||||
|
||||
ShowNotification(builder);
|
||||
ShowNotification(builder, WinoApplicationMode.Mail);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -146,9 +145,9 @@ public class NotificationBuilder : INotificationBuilder
|
||||
{
|
||||
try
|
||||
{
|
||||
AppNotificationManager.Default.RemoveByTagAsync(mailUniqueId.ToString()).AsTask().GetAwaiter().GetResult();
|
||||
ToastNotificationManager.History.Remove(mailUniqueId.ToString());
|
||||
}
|
||||
catch (ArgumentException)
|
||||
catch (Exception ex) when (ex is ArgumentException or InvalidOperationException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -164,11 +163,12 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddText(string.Format(Translator.Exception_AccountNeedsAttention_Message, account.Name));
|
||||
builder.AddArgument(Constants.ToastMailAccountIdKey, account.Id.ToString());
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
builder.AddButton(new AppNotificationButton(Translator.Buttons_FixAccount)
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(Translator.Buttons_FixAccount)
|
||||
.AddArgument(Constants.ToastMailAccountIdKey, account.Id.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail));
|
||||
|
||||
ShowNotification(builder);
|
||||
ShowNotification(builder, WinoApplicationMode.Mail);
|
||||
}
|
||||
|
||||
public void CreateWebView2RuntimeMissingNotification()
|
||||
@@ -178,7 +178,7 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddText(Translator.Exception_WebView2RuntimeMissing_Message);
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
|
||||
ShowNotification(builder);
|
||||
ShowNotification(builder, WinoApplicationMode.Mail);
|
||||
}
|
||||
|
||||
public void CreateStoreUpdateNotification()
|
||||
@@ -189,7 +189,7 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddArgument(Constants.ToastStoreUpdateActionKey, Constants.ToastStoreUpdateActionInstall);
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
|
||||
ShowNotification(builder, "store-update-available");
|
||||
ShowNotification(builder, WinoApplicationMode.Mail, "store-update-available");
|
||||
}
|
||||
|
||||
public Task CreateCalendarReminderNotificationAsync(CalendarItem calendarItem, long reminderDurationInSeconds)
|
||||
@@ -197,7 +197,7 @@ public class NotificationBuilder : INotificationBuilder
|
||||
if (calendarItem == null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
var builder = CreateBuilder(AppNotificationScenario.Reminder);
|
||||
var builder = CreateBuilder(ToastScenario.Reminder);
|
||||
var localStart = calendarItem.GetLocalStartDate();
|
||||
var reminderContext = GetCalendarReminderContext(localStart, DateTime.Now);
|
||||
|
||||
@@ -210,7 +210,7 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarNavigateAction);
|
||||
builder.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString());
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar);
|
||||
builder.SetAudioUri(new Uri("ms-winsoundevent:Notification.Reminder"));
|
||||
builder.AddAudio(new Uri("ms-winsoundevent:Notification.Reminder"));
|
||||
|
||||
var allowedSnoozeMinutes = CalendarReminderSnoozeOptions.GetAllowedSnoozeMinutes(
|
||||
reminderDurationInSeconds,
|
||||
@@ -223,40 +223,33 @@ public class NotificationBuilder : INotificationBuilder
|
||||
? preferredSnoozeMinutes
|
||||
: allowedSnoozeMinutes[0];
|
||||
|
||||
var selectionBox = new AppNotificationComboBox(Constants.ToastCalendarSnoozeDurationInputId)
|
||||
.SetSelectedItem(defaultSnoozeMinutes.ToString());
|
||||
|
||||
foreach (var snoozeMinutes in allowedSnoozeMinutes)
|
||||
{
|
||||
selectionBox.AddItem(
|
||||
snoozeMinutes.ToString(),
|
||||
string.Format(Translator.CalendarReminder_SnoozeMinutesOption, snoozeMinutes));
|
||||
}
|
||||
|
||||
builder.AddComboBox(selectionBox);
|
||||
builder.AddButton(new AppNotificationButton(Translator.CalendarReminder_SnoozeAction)
|
||||
.SetIcon(GetNotificationIconUri("calendar-snooze"))
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(Translator.CalendarReminder_SnoozeAction)
|
||||
.SetImageUri(GetNotificationIconUri("calendar-snooze"))
|
||||
.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarSnoozeAction)
|
||||
.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString())
|
||||
.AddArgument(Constants.ToastCalendarSnoozeDurationMinutesKey, defaultSnoozeMinutes.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar));
|
||||
}
|
||||
|
||||
builder.AddButton(new AppNotificationButton(Translator.Buttons_Open)
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(Translator.Buttons_Open)
|
||||
.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarNavigateAction)
|
||||
.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar));
|
||||
|
||||
if (Uri.TryCreate(calendarItem.HtmlLink, UriKind.Absolute, out _))
|
||||
{
|
||||
builder.AddButton(new AppNotificationButton(Translator.CalendarEventDetails_JoinOnline)
|
||||
.SetIcon(GetNotificationIconUri("calendar-join"))
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(Translator.CalendarEventDetails_JoinOnline)
|
||||
.SetImageUri(GetNotificationIconUri("calendar-join"))
|
||||
.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarJoinOnlineAction)
|
||||
.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar));
|
||||
}
|
||||
|
||||
var tag = $"calendar-reminder-{calendarItem.Id:N}-{reminderDurationInSeconds}";
|
||||
ShowNotification(builder, tag);
|
||||
ShowNotification(builder, WinoApplicationMode.Calendar, tag);
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
@@ -278,10 +271,10 @@ public class NotificationBuilder : INotificationBuilder
|
||||
await stream.WriteAsync(bytes);
|
||||
}
|
||||
|
||||
builder.SetAppLogoOverride(new Uri($"ms-appdata:///temp/{tempFile.Name}"), AppNotificationImageCrop.Default);
|
||||
builder.AddAppLogoOverride(new Uri($"ms-appdata:///temp/{tempFile.Name}"), ToastGenericAppLogoCrop.Default);
|
||||
}
|
||||
|
||||
builder.SetTimeStamp(mailItem.CreationDate.ToLocalTime());
|
||||
builder.AddCustomTimeStamp(mailItem.CreationDate.ToLocalTime());
|
||||
builder.AddText(mailItem.FromName);
|
||||
builder.AddText(mailItem.Subject);
|
||||
builder.AddText(mailItem.PreviewText);
|
||||
@@ -291,9 +284,9 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddButton(GetMarkAsReadButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetDeleteButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetArchiveButton(mailItem.UniqueId));
|
||||
builder.SetAudioUri(new Uri("ms-winsoundevent:Notification.Mail"));
|
||||
builder.AddAudio(new Uri("ms-winsoundevent:Notification.Mail"));
|
||||
|
||||
ShowNotification(builder, mailItem.UniqueId.ToString());
|
||||
ShowNotification(builder, WinoApplicationMode.Mail, mailItem.UniqueId.ToString());
|
||||
}
|
||||
|
||||
private void UpdateBadge(string applicationId, int? badgeCount)
|
||||
@@ -347,40 +340,43 @@ public class NotificationBuilder : INotificationBuilder
|
||||
return string.Format(Translator.CalendarReminder_StartedMinutesAgo, minutesAgo);
|
||||
}
|
||||
|
||||
private AppNotificationButton GetArchiveButton(Guid mailUniqueId)
|
||||
=> new AppNotificationButton(Translator.MailOperation_Archive)
|
||||
.SetIcon(GetNotificationIconUri("mail-archive"))
|
||||
private ToastButton GetArchiveButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Archive)
|
||||
.SetImageUri(GetNotificationIconUri("mail-archive"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.Archive.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
|
||||
private AppNotificationButton GetDeleteButton(Guid mailUniqueId)
|
||||
=> new AppNotificationButton(Translator.MailOperation_Delete)
|
||||
.SetIcon(GetNotificationIconUri("mail-delete"))
|
||||
private ToastButton GetDeleteButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Delete)
|
||||
.SetImageUri(GetNotificationIconUri("mail-delete"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.SoftDelete.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
|
||||
private AppNotificationButton GetMarkAsReadButton(Guid mailUniqueId)
|
||||
=> new AppNotificationButton(Translator.MailOperation_MarkAsRead)
|
||||
.SetIcon(GetNotificationIconUri("mail-markread"))
|
||||
private ToastButton GetMarkAsReadButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_MarkAsRead)
|
||||
.SetImageUri(GetNotificationIconUri("mail-markread"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.MarkAsRead.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail);
|
||||
|
||||
private static AppNotificationBuilder CreateBuilder(AppNotificationScenario scenario = AppNotificationScenario.Default)
|
||||
=> new AppNotificationBuilder().SetScenario(scenario);
|
||||
private static ToastContentBuilder CreateBuilder(ToastScenario scenario = ToastScenario.Default)
|
||||
=> new ToastContentBuilder().SetToastScenario(scenario);
|
||||
|
||||
private static void ShowNotification(AppNotificationBuilder builder, string? tag = null)
|
||||
private static void ShowNotification(ToastContentBuilder builder, WinoApplicationMode mode, string? tag = null)
|
||||
{
|
||||
var notification = builder.BuildNotification();
|
||||
var notification = new ToastNotification(builder.GetXml());
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(tag))
|
||||
{
|
||||
notification.Tag = tag;
|
||||
}
|
||||
|
||||
AppNotificationManager.Default.Show(notification);
|
||||
ToastNotificationManager.CreateToastNotifier(AppEntryConstants.GetAppUserModelId(mode)).Show(notification);
|
||||
}
|
||||
|
||||
private static Uri GetNotificationIconUri(string iconName)
|
||||
|
||||
@@ -210,12 +210,12 @@
|
||||
Background="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
|
||||
<!-- Test Notification -->
|
||||
<!--<Button Command="{x:Bind ViewModel.CreateTestNotificationCommand}" Style="{StaticResource TransparentActionButtonStyle}">
|
||||
<Button Command="{x:Bind ViewModel.CreateTestNotificationCommand}" Style="{StaticResource TransparentActionButtonStyle}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<coreControls:WinoFontIcon FontSize="16" Icon="Reminder" />
|
||||
<TextBlock VerticalAlignment="Center" Text="Test notification" />
|
||||
</StackPanel>
|
||||
</Button>-->
|
||||
</Button>
|
||||
|
||||
<!-- Edit Series -->
|
||||
<Border
|
||||
|
||||
@@ -185,6 +185,7 @@
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Controls.TokenizingTextBox" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Extensions" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Lottie" />
|
||||
<PackageReference Include="CommunityToolkit.WinUI.Notifications" />
|
||||
|
||||
<PackageReference Include="Microsoft.Graphics.Win2D" />
|
||||
<PackageReference Include="Microsoft.Windows.SDK.BuildTools" />
|
||||
|
||||
Reference in New Issue
Block a user