Add snooze support for calendar reminders (toast UI, service, DB) (#825)
* Filter reminder snooze options by default reminder * Some updates. * Fixing empty welcome page issue and attendee loading. * Icon system for notifications and snooze options etc.
@@ -192,6 +192,8 @@ public partial class App : WinoApplication,
|
||||
|
||||
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)) == true)
|
||||
return;
|
||||
|
||||
@@ -224,12 +226,20 @@ public partial class App : WinoApplication,
|
||||
|
||||
// Check calendar reminder toast activation first.
|
||||
if (toastArguments.TryGetValue(Constants.ToastCalendarActionKey, out string calendarAction) &&
|
||||
calendarAction == Constants.ToastCalendarNavigateAction &&
|
||||
toastArguments.TryGetValue(Constants.ToastCalendarItemIdKey, out string calendarItemIdString) &&
|
||||
Guid.TryParse(calendarItemIdString, out Guid calendarItemId))
|
||||
{
|
||||
await HandleCalendarToastNavigationAsync(calendarItemId);
|
||||
return;
|
||||
if (calendarAction == Constants.ToastCalendarNavigateAction)
|
||||
{
|
||||
await HandleCalendarToastNavigationAsync(calendarItemId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (calendarAction == Constants.ToastCalendarSnoozeAction)
|
||||
{
|
||||
await HandleCalendarToastSnoozeAsync(toastArgs, calendarItemId);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if this is a navigation toast (user clicked the notification).
|
||||
@@ -275,6 +285,33 @@ public partial class App : WinoApplication,
|
||||
navigationService.Navigate(WinoPage.EventDetailsPage, target);
|
||||
}
|
||||
|
||||
private async Task HandleCalendarToastSnoozeAsync(AppNotificationActivatedEventArgs toastArgs, Guid calendarItemId)
|
||||
{
|
||||
if (!TryGetSnoozeDurationMinutes(toastArgs, out var snoozeDurationMinutes))
|
||||
return;
|
||||
|
||||
var calendarService = Services.GetRequiredService<ICalendarService>();
|
||||
var snoozedUntilLocal = DateTime.Now.AddMinutes(snoozeDurationMinutes);
|
||||
|
||||
await calendarService.SnoozeCalendarItemAsync(calendarItemId, snoozedUntilLocal).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private static bool TryGetSnoozeDurationMinutes(AppNotificationActivatedEventArgs toastArgs, out int snoozeDurationMinutes)
|
||||
{
|
||||
snoozeDurationMinutes = 0;
|
||||
|
||||
if (toastArgs.UserInput == null ||
|
||||
!toastArgs.UserInput.TryGetValue(Constants.ToastCalendarSnoozeDurationInputId, out var selectedValue) ||
|
||||
selectedValue == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var selectedText = selectedValue.ToString();
|
||||
|
||||
return int.TryParse(selectedText, out snoozeDurationMinutes) && snoozeDurationMinutes > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles toast notification click for navigation.
|
||||
/// Creates window if not running, sets up navigation parameter.
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 459 B |
|
After Width: | Height: | Size: 545 B |
|
After Width: | Height: | Size: 669 B |
|
After Width: | Height: | Size: 887 B |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 434 B |
|
After Width: | Height: | Size: 507 B |
|
After Width: | Height: | Size: 615 B |
|
After Width: | Height: | Size: 817 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 351 B |
|
After Width: | Height: | Size: 445 B |
|
After Width: | Height: | Size: 495 B |
|
After Width: | Height: | Size: 685 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 323 B |
|
After Width: | Height: | Size: 417 B |
|
After Width: | Height: | Size: 459 B |
|
After Width: | Height: | Size: 636 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 180 B |
|
After Width: | Height: | Size: 234 B |
|
After Width: | Height: | Size: 230 B |
|
After Width: | Height: | Size: 283 B |
|
After Width: | Height: | Size: 521 B |
|
After Width: | Height: | Size: 174 B |
|
After Width: | Height: | Size: 226 B |
|
After Width: | Height: | Size: 229 B |
|
After Width: | Height: | Size: 275 B |
|
After Width: | Height: | Size: 509 B |
|
After Width: | Height: | Size: 279 B |
|
After Width: | Height: | Size: 359 B |
|
After Width: | Height: | Size: 383 B |
|
After Width: | Height: | Size: 371 B |
|
After Width: | Height: | Size: 805 B |
|
After Width: | Height: | Size: 272 B |
|
After Width: | Height: | Size: 324 B |
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 328 B |
|
After Width: | Height: | Size: 706 B |
|
After Width: | Height: | Size: 303 B |
|
After Width: | Height: | Size: 426 B |
|
After Width: | Height: | Size: 496 B |
|
After Width: | Height: | Size: 541 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 289 B |
|
After Width: | Height: | Size: 408 B |
|
After Width: | Height: | Size: 465 B |
|
After Width: | Height: | Size: 527 B |
|
After Width: | Height: | Size: 989 B |
|
After Width: | Height: | Size: 336 B |
|
After Width: | Height: | Size: 418 B |
|
After Width: | Height: | Size: 458 B |
|
After Width: | Height: | Size: 595 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 308 B |
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 447 B |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 31 KiB |
@@ -38,6 +38,8 @@ public sealed partial class MailAppShell : MailAppShellAbstract,
|
||||
IRecipient<CreateNewMailWithMultipleAccountsRequested>,
|
||||
IRecipient<InfoBarMessageRequested>
|
||||
{
|
||||
public Frame GetShellFrame() => InnerShellFrame;
|
||||
|
||||
[GeneratedDependencyProperty]
|
||||
public partial UIElement? TopShellContent { get; set; }
|
||||
|
||||
|
||||
@@ -129,6 +129,19 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
||||
|
||||
if (frameType == NavigationReferenceFrame.ShellFrame) return shellWindow.GetMainFrame();
|
||||
|
||||
if (frameType == NavigationReferenceFrame.InnerShellFrame)
|
||||
{
|
||||
if (mainFrame.Content is MailAppShell mailAppShell)
|
||||
{
|
||||
return mailAppShell.GetShellFrame();
|
||||
}
|
||||
|
||||
if (mainFrame.Content is CalendarAppShell calendarAppShell)
|
||||
{
|
||||
return calendarAppShell.GetShellFrame();
|
||||
}
|
||||
}
|
||||
|
||||
var contentRoot = mainFrame.Content as UIElement;
|
||||
if (contentRoot == null) return mainFrame;
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Microsoft.Toolkit.Uwp.Notifications;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Serilog;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI.Notifications;
|
||||
@@ -12,6 +14,7 @@ using Wino.Core.Domain.Entities.Calendar;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Extensions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
@@ -20,21 +23,29 @@ namespace Wino.Mail.WinUI.Services;
|
||||
public class NotificationBuilder : INotificationBuilder
|
||||
{
|
||||
private const string MailApplicationId = "App";
|
||||
private const string NotificationIconRootUri = "ms-appx:///Assets/NotificationIcons/";
|
||||
private static readonly int[] SupportedIconScales = [100, 125, 150, 200, 400];
|
||||
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IMailService _mailService;
|
||||
private readonly IThumbnailService _thumbnailService;
|
||||
private readonly IPreferencesService _preferencesService;
|
||||
private readonly IUnderlyingThemeService _underlyingThemeService;
|
||||
|
||||
public NotificationBuilder(IAccountService accountService,
|
||||
IFolderService folderService,
|
||||
IMailService mailService,
|
||||
IThumbnailService thumbnailService)
|
||||
IThumbnailService thumbnailService,
|
||||
IPreferencesService preferencesService,
|
||||
IUnderlyingThemeService underlyingThemeService)
|
||||
{
|
||||
_accountService = accountService;
|
||||
_folderService = folderService;
|
||||
_mailService = mailService;
|
||||
_thumbnailService = thumbnailService;
|
||||
_preferencesService = preferencesService;
|
||||
_underlyingThemeService = underlyingThemeService;
|
||||
|
||||
WeakReferenceMessenger.Default.Register<MailReadStatusChanged>(this, (r, msg) =>
|
||||
{
|
||||
@@ -156,12 +167,12 @@ public class NotificationBuilder : INotificationBuilder
|
||||
private ToastButton GetDismissButton()
|
||||
=> new ToastButton()
|
||||
.SetDismissActivation()
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/dismiss.png"));
|
||||
.SetImageUri(GetNotificationIconUri("dismiss"));
|
||||
|
||||
private static ToastButton GetArchiveButton(Guid mailUniqueId)
|
||||
private ToastButton GetArchiveButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Archive)
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/archive.png"))
|
||||
.SetImageUri(GetNotificationIconUri("mail-archive"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.Archive)
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail)
|
||||
@@ -170,16 +181,16 @@ public class NotificationBuilder : INotificationBuilder
|
||||
private ToastButton GetDeleteButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_Delete)
|
||||
.SetImageUri(new Uri("ms-appx:///Assets/NotificationIcons/delete.png"))
|
||||
.SetImageUri(GetNotificationIconUri("mail-delete"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.SoftDelete)
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail)
|
||||
.SetBackgroundActivation();
|
||||
|
||||
private static ToastButton GetMarkAsReadButton(Guid mailUniqueId)
|
||||
private ToastButton GetMarkAsReadButton(Guid mailUniqueId)
|
||||
=> new ToastButton()
|
||||
.SetContent(Translator.MailOperation_MarkAsRead)
|
||||
.SetImageUri(new System.Uri("ms-appx:///Assets/NotificationIcons/markread.png"))
|
||||
.SetImageUri(GetNotificationIconUri("mail-markread"))
|
||||
.AddArgument(Constants.ToastMailUniqueIdKey, mailUniqueId.ToString())
|
||||
.AddArgument(Constants.ToastActionKey, MailOperation.MarkAsRead)
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeMail)
|
||||
@@ -290,11 +301,9 @@ public class NotificationBuilder : INotificationBuilder
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Reminder);
|
||||
|
||||
var localStart = calendarItem.LocalStartDate;
|
||||
var reminderMinutes = (int)Math.Max(0, reminderDurationInSeconds / 60);
|
||||
var reminderContext = reminderMinutes > 0
|
||||
? $"Starts in {reminderMinutes} minute{(reminderMinutes == 1 ? string.Empty : "s")}"
|
||||
: "Starting now";
|
||||
var localStart = calendarItem.GetLocalStartDate();
|
||||
var nowLocal = DateTime.Now;
|
||||
var reminderContext = GetCalendarReminderContext(localStart, nowLocal);
|
||||
|
||||
builder.AddText(calendarItem.Title);
|
||||
builder.AddText($"{reminderContext} - {localStart:g}");
|
||||
@@ -305,7 +314,54 @@ public class NotificationBuilder : INotificationBuilder
|
||||
builder.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarNavigateAction);
|
||||
builder.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString());
|
||||
builder.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar);
|
||||
builder.AddButton(GetDismissButton());
|
||||
|
||||
var allowedSnoozeMinutes = CalendarReminderSnoozeOptions.GetAllowedSnoozeMinutes(
|
||||
reminderDurationInSeconds,
|
||||
_preferencesService.DefaultReminderDurationInSeconds);
|
||||
|
||||
if (allowedSnoozeMinutes.Count > 0)
|
||||
{
|
||||
var preferredSnoozeMinutes = _preferencesService.DefaultSnoozeDurationInMinutes;
|
||||
var defaultSnoozeMinutes = allowedSnoozeMinutes.Contains(preferredSnoozeMinutes)
|
||||
? preferredSnoozeMinutes
|
||||
: allowedSnoozeMinutes[0];
|
||||
|
||||
var selectionBox = new ToastSelectionBox(Constants.ToastCalendarSnoozeDurationInputId)
|
||||
{
|
||||
DefaultSelectionBoxItemId = defaultSnoozeMinutes.ToString()
|
||||
};
|
||||
|
||||
foreach (var snoozeMinutes in allowedSnoozeMinutes)
|
||||
{
|
||||
selectionBox.Items.Add(new ToastSelectionBoxItem(
|
||||
snoozeMinutes.ToString(),
|
||||
string.Format(Translator.CalendarReminder_SnoozeMinutesOption, snoozeMinutes)));
|
||||
}
|
||||
|
||||
builder.AddToastInput(selectionBox);
|
||||
var snoozeButton = new ToastButton()
|
||||
.SetContent(Translator.CalendarReminder_SnoozeAction)
|
||||
.SetImageUri(GetNotificationIconUri("calendar-snooze"))
|
||||
.SetBackgroundActivation();
|
||||
|
||||
builder.AddButton(snoozeButton)
|
||||
.AddArgument(Constants.ToastCalendarActionKey, Constants.ToastCalendarSnoozeAction)
|
||||
.AddArgument(Constants.ToastCalendarItemIdKey, calendarItem.Id.ToString())
|
||||
.AddArgument(Constants.ToastModeKey, Constants.ToastModeCalendar);
|
||||
}
|
||||
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetDismissActivation()
|
||||
.SetImageUri(GetNotificationIconUri("dismiss")));
|
||||
|
||||
if (Uri.TryCreate(calendarItem.HtmlLink, UriKind.Absolute, out var joinUri))
|
||||
{
|
||||
builder.AddButton(new ToastButton()
|
||||
.SetContent(Translator.CalendarEventDetails_JoinOnline)
|
||||
.SetImageUri(GetNotificationIconUri("calendar-join"))
|
||||
.SetProtocolActivation(joinUri));
|
||||
}
|
||||
|
||||
builder.AddAudio(new ToastAudio()
|
||||
{
|
||||
Src = new Uri("ms-winsoundevent:Notification.Reminder")
|
||||
@@ -317,6 +373,36 @@ public class NotificationBuilder : INotificationBuilder
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static string GetCalendarReminderContext(DateTime localStart, DateTime nowLocal)
|
||||
{
|
||||
var delta = localStart - nowLocal;
|
||||
var absDelta = delta.Duration();
|
||||
|
||||
if (absDelta < TimeSpan.FromMinutes(1))
|
||||
return delta.TotalSeconds >= 0 ? Translator.CalendarReminder_StartingNow : Translator.CalendarReminder_StartedNow;
|
||||
|
||||
if (delta.TotalSeconds > 0)
|
||||
{
|
||||
if (delta.TotalHours >= 1)
|
||||
{
|
||||
var hours = Math.Max(1, (int)Math.Floor(delta.TotalHours));
|
||||
return string.Format(Translator.CalendarReminder_StartsInHours, hours);
|
||||
}
|
||||
|
||||
var minutes = Math.Max(1, (int)Math.Floor(delta.TotalMinutes));
|
||||
return string.Format(Translator.CalendarReminder_StartsInMinutes, minutes);
|
||||
}
|
||||
|
||||
if (absDelta.TotalHours >= 1)
|
||||
{
|
||||
var hoursAgo = Math.Max(1, (int)Math.Floor(absDelta.TotalHours));
|
||||
return string.Format(Translator.CalendarReminder_StartedHoursAgo, hoursAgo);
|
||||
}
|
||||
|
||||
var minutesAgo = Math.Max(1, (int)Math.Floor(absDelta.TotalMinutes));
|
||||
return string.Format(Translator.CalendarReminder_StartedMinutesAgo, minutesAgo);
|
||||
}
|
||||
|
||||
private static void ShowToast(ToastContentBuilder builder, string? tag = null)
|
||||
{
|
||||
var toastNotification = new ToastNotification(builder.GetToastContent().GetXml());
|
||||
@@ -329,4 +415,25 @@ public class NotificationBuilder : INotificationBuilder
|
||||
var notifier = ToastNotificationManager.CreateToastNotifier();
|
||||
notifier.Show(toastNotification);
|
||||
}
|
||||
|
||||
private Uri GetNotificationIconUri(string iconName)
|
||||
{
|
||||
var theme = _underlyingThemeService.IsUnderlyingThemeDark() ? "dark" : "light";
|
||||
var scale = GetClosestAvailableScale();
|
||||
return new($"{NotificationIconRootUri}{iconName}.theme-{theme}.scale-{scale}.png");
|
||||
}
|
||||
|
||||
private static int GetClosestAvailableScale()
|
||||
{
|
||||
var rasterScale = 1.0;
|
||||
|
||||
if (WinoApplication.MainWindow?.Content is FrameworkElement rootElement &&
|
||||
rootElement.XamlRoot != null)
|
||||
{
|
||||
rasterScale = rootElement.XamlRoot.RasterizationScale;
|
||||
}
|
||||
|
||||
var requestedScale = (int)Math.Round(rasterScale * 100);
|
||||
return SupportedIconScales.OrderBy(s => Math.Abs(s - requestedScale)).First();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,6 +284,12 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
|
||||
set => SaveProperty(propertyName: nameof(DefaultReminderDurationInSeconds), value);
|
||||
}
|
||||
|
||||
public int DefaultSnoozeDurationInMinutes
|
||||
{
|
||||
get => _configurationService.Get(nameof(DefaultSnoozeDurationInMinutes), 5);
|
||||
set => SaveProperty(propertyName: nameof(DefaultSnoozeDurationInMinutes), value);
|
||||
}
|
||||
|
||||
public int EmailSyncIntervalMinutes
|
||||
{
|
||||
get => _configurationService.Get(nameof(EmailSyncIntervalMinutes), 3);
|
||||
|
||||
@@ -235,6 +235,17 @@
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.ReminderOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultReminderIndex, Mode=TwoWay}" />
|
||||
</controls:SettingsCard.Content>
|
||||
</controls:SettingsCard>
|
||||
|
||||
<controls:SettingsCard
|
||||
Description="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Description}"
|
||||
Header="{x:Bind domain:Translator.CalendarSettings_DefaultSnoozeDuration_Header}">
|
||||
<controls:SettingsCard.HeaderIcon>
|
||||
<PathIcon Data="F1 M 10 1.25 C 10.456706 1.25 10.889486 1.337565 11.298339 1.512695 C 11.707192 1.687826 12.072591 1.927409 12.394531 2.231445 C 12.716471 2.535482 12.97656 2.892253 13.173828 3.301758 C 13.371096 3.711263 13.481771 4.146484 13.505859 4.607422 L 13.505859 5 C 13.969401 5.028646 14.386068 5.16276 14.755859 5.402344 C 15.125651 5.641927 15.414713 5.947917 15.623047 6.320312 C 15.83138 6.692709 15.9349 7.096355 15.933594 7.53125 L 15.933594 8.75 L 16.25 8.75 C 16.822917 8.75 17.317057 8.95638 17.732422 9.369141 C 18.147787 9.781901 18.357422 10.273437 18.359375 10.84375 L 18.359375 16.40625 C 18.359375 16.979167 18.153971 17.473308 17.743164 17.888672 C 17.332357 18.304037 16.839844 18.511719 16.265625 18.511719 L 3.734375 18.511719 C 3.164062 18.511719 2.671549 18.304037 2.256836 17.888672 C 1.842122 17.473308 1.634114 16.979167 1.630859 16.40625 L 1.630859 10.84375 C 1.630859 10.273437 1.837565 9.781901 2.250977 9.369141 C 2.664388 8.95638 3.156901 8.75 3.728516 8.75 L 4.0625 8.75 L 4.0625 7.53125 C 4.0625 7.09375 4.166341 6.689453 4.374023 6.314453 C 4.581706 5.939453 4.86914 5.632486 5.236328 5.393555 C 5.603516 5.154623 6.019532 5.021485 6.484375 4.994141 L 6.484375 4.607422 C 6.506511 4.148438 6.617838 3.714518 6.818359 3.305664 C 7.01888 2.896811 7.282877 2.539063 7.610352 2.232422 C 7.937826 1.92578 8.308268 1.685222 8.721679 1.510742 C 9.135091 1.336264 9.56575 1.249024 10.013672 1.249024 Z M 10.013672 2.5 C 9.441406 2.5 8.947916 2.706381 8.533203 3.119141 C 8.118489 3.531901 7.911459 4.023437 7.912109 4.59375 L 7.912109 6.25 L 12.089844 6.25 L 12.089844 4.59375 C 12.089844 4.023438 11.882161 3.531902 11.466797 3.119141 C 11.051433 2.706382 10.557292 2.5 9.984375 2.5 Z M 5.3125 7.53125 L 5.3125 8.75 L 14.6875 8.75 L 14.6875 7.53125 C 14.6875 7.303385 14.605144 7.107747 14.440429 6.944336 C 14.275714 6.780925 14.080729 6.69987 13.855469 6.703125 L 6.142578 6.703125 C 5.914713 6.703125 5.71875 6.785482 5.552734 6.950195 C 5.386719 7.114909 5.30339 7.310547 5.300781 7.537109 Z M 16.25 10 L 3.75 10 C 3.540365 10 3.361328 10.071615 3.212891 10.214844 C 3.064453 10.358073 2.989258 10.534505 2.986328 10.744141 L 2.986328 16.40625 C 2.986328 16.618489 3.058595 16.797526 3.203125 16.943359 C 3.347656 17.089193 3.526693 17.161458 3.740234 17.15625 L 16.25 17.15625 C 16.458333 17.15625 16.636067 17.082683 16.783203 16.935547 C 16.930339 16.788411 17.003906 16.609375 17.003906 16.398437 L 17.003906 10.742187 C 17.003906 10.536459 16.932942 10.359049 16.791016 10.209961 C 16.64909 10.060873 16.469401 9.986328 16.257812 9.986328 Z M 10 11.5625 C 10.227865 11.5625 10.423502 11.644856 10.586914 11.809571 C 10.750325 11.974285 10.83138 12.16862 10.830078 12.393555 L 10.830078 13.427734 L 11.855469 13.427734 C 12.080404 13.427734 12.273437 13.509115 12.434571 13.671875 C 12.595704 13.834636 12.675781 14.026693 12.675781 14.248047 C 12.675781 14.46224 12.596354 14.653321 12.4375 14.813477 C 12.278646 14.973633 12.089192 15.053711 11.869141 15.053711 L 10.830078 15.053711 L 10.830078 16.074219 C 10.830078 16.296224 10.748372 16.486981 10.584961 16.646484 C 10.42155 16.805989 10.229818 16.885742 10.005859 16.885742 C 9.781901 16.885742 9.590495 16.806315 9.431641 16.647461 C 9.272786 16.488607 9.193359 16.296875 9.193359 16.072266 L 9.193359 15.053711 L 8.15625 15.053711 C 7.931314 15.053711 7.738934 14.972331 7.579102 14.80957 C 7.419269 14.646809 7.339192 14.454753 7.338867 14.233399 C 7.338867 14.008464 7.419921 13.815755 7.582031 13.655274 C 7.744141 13.494793 7.935872 13.414551 8.157227 13.414551 L 9.193359 13.414551 L 9.193359 12.394531 C 9.193359 12.166667 9.275715 11.971029 9.440429 11.807618 C 9.605144 11.644206 9.799479 11.562825 10.023437 11.5625 Z" />
|
||||
</controls:SettingsCard.HeaderIcon>
|
||||
<controls:SettingsCard.Content>
|
||||
<ComboBox ItemsSource="{x:Bind ViewModel.SnoozeOptions, Mode=OneWay}" SelectedIndex="{x:Bind ViewModel.SelectedDefaultSnoozeIndex, Mode=TwoWay}" />
|
||||
</controls:SettingsCard.Content>
|
||||
</controls:SettingsCard>
|
||||
</StackPanel>
|
||||
<VisualStateManager.VisualStateGroups>
|
||||
<VisualStateGroup x:Name="ClockIdentifierStates">
|
||||
|
||||
@@ -207,6 +207,23 @@
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
<Border
|
||||
Width="1"
|
||||
Height="24"
|
||||
Margin="4,0"
|
||||
VerticalAlignment="Center"
|
||||
Background="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||
|
||||
<!-- Test Notification -->
|
||||
<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>
|
||||
|
||||
<!-- Edit Series -->
|
||||
<Border
|
||||
Width="1"
|
||||
|
||||
@@ -98,6 +98,66 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Assets\CalendarWide310x150Logo.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-join.theme-light.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\calendar-snooze.theme-light.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\dismiss.theme-light.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-archive.theme-light.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-delete.theme-light.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-dark.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-dark.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-dark.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-dark.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-dark.scale-400.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-light.scale-100.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-light.scale-125.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-light.scale-150.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-light.scale-200.png" />
|
||||
<None Remove="Assets\NotificationIcons\mail-markread.theme-light.scale-400.png" />
|
||||
<None Remove="BackgroundImages\Acrylic.jpg" />
|
||||
<None Remove="BackgroundImages\Clouds.jpg" />
|
||||
<None Remove="BackgroundImages\Forest.jpg" />
|
||||
|
||||