Merge pull request #329 from bkaankose/feature/NewStartup
Handling app termination and reworked dialog messages.
This commit is contained in:
10
Wino.Core.Domain/Enums/WinoCustomMessageDialogIcon.cs
Normal file
10
Wino.Core.Domain/Enums/WinoCustomMessageDialogIcon.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Wino.Core.Domain.Enums
|
||||
{
|
||||
public enum WinoCustomMessageDialogIcon
|
||||
{
|
||||
Information,
|
||||
Warning,
|
||||
Error,
|
||||
Question
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces
|
||||
{
|
||||
public interface IConfirmationDialog
|
||||
{
|
||||
Task<bool> ShowDialogAsync(string title, string message, string approveButtonTitle);
|
||||
}
|
||||
}
|
||||
@@ -15,11 +15,10 @@ namespace Wino.Core.Domain.Interfaces
|
||||
Task<byte[]> PickWindowsFileContentAsync(params object[] typeFilters);
|
||||
Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle);
|
||||
Task<bool> ShowHardDeleteConfirmationAsync();
|
||||
Task<IStoreRatingDialog> ShowRatingDialogAsync();
|
||||
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
|
||||
Task<bool> ShowCustomThemeBuilderDialogAsync();
|
||||
|
||||
Task ShowMessageAsync(string message, string title);
|
||||
Task ShowMessageAsync(string message, string title, WinoCustomMessageDialogIcon icon);
|
||||
void InfoBarMessage(string title, string message, InfoBarMessageType messageType);
|
||||
void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action);
|
||||
|
||||
@@ -53,6 +52,17 @@ namespace Wino.Core.Domain.Interfaces
|
||||
/// </summary>
|
||||
/// <returns>Signature information. Null if canceled.</returns>
|
||||
Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature signatureModel = null);
|
||||
|
||||
/// <summary>
|
||||
/// Presents a dialog to the user for account alias creation/modification.
|
||||
/// </summary>
|
||||
/// <returns>Created alias model if not canceled.</returns>
|
||||
Task<ICreateAccountAliasDialog> ShowCreateAccountAliasDialogAsync();
|
||||
Task<bool> ShowWinoCustomMessageDialogAsync(string title,
|
||||
string description,
|
||||
string approveButtonText,
|
||||
WinoCustomMessageDialogIcon? icon,
|
||||
string cancelButtonText = "",
|
||||
string dontAskAgainConfigurationKey = "");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Wino.Core.Domain.Interfaces
|
||||
{
|
||||
public interface IStoreRatingDialog
|
||||
{
|
||||
bool DontAskAgain { get; }
|
||||
bool RateWinoClicked { get; }
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,13 @@
|
||||
"AccountSettingsDialog_AccountNamePlaceholder": "eg. John Doe",
|
||||
"AddHyperlink": "Add",
|
||||
"AutoDiscoveryProgressMessage": "Searching for mail settings...",
|
||||
"AppCloseBackgroundSynchronizationWarningTitle": "Background Synchronization",
|
||||
"AppCloseTerminateBehaviorWarningMessageFirstLine": "You are terminating Wino Mail and your app close behavior is set to 'Terminate'.",
|
||||
"AppCloseTerminateBehaviorWarningMessageSecondLine": "This will stop all background synchronizations and notifications.",
|
||||
"AppCloseTerminateBehaviorWarningMessageThirdLine": "Do you want to go to App Preferences to set Wino Mail to run minimized or in the background?",
|
||||
"AppCloseStartupLaunchDisabledWarningMessageFirstLine": "Application has not been set to launch on Windows startup.",
|
||||
"AppCloseStartupLaunchDisabledWarningMessageSecondLine": "This will cause you to miss notifications when you restart your computer.",
|
||||
"AppCloseStartupLaunchDisabledWarningMessageThirdLine": "Do you want to go to App Preferences page to enable it?",
|
||||
"BasicIMAPSetupDialog_AdvancedConfiguration": "Advanced Configuration",
|
||||
"BasicIMAPSetupDialog_CredentialLocalMessage": "Your credentials will only be stored locally on your computer.",
|
||||
"BasicIMAPSetupDialog_Description": "Some accounts require additional steps to sign in",
|
||||
@@ -105,6 +112,9 @@
|
||||
"DialogMessage_UnsubscribeConfirmationGoToWebsiteMessage": "To stop getting messages from {0}, go to their website to unsubscribe.",
|
||||
"DialogMessage_UnsubscribeConfirmationGoToWebsiteConfirmButton": "Go to website",
|
||||
"DialogMessage_UnsubscribeConfirmationMailtoMessage": "Do you want to stop getting messages from {0}? Wino will unsubscribe for you by sending an email from your email account to {1}.",
|
||||
"DialogMessage_EnableStartupLaunchTitle": "Enable Startup Launch",
|
||||
"DialogMessage_EnableStartupLaunchMessage": "Let Wino Mail automatically launch minimized on Windows startup to not miss any notifications.\n\nDo you want to enable startup launch?",
|
||||
"DialogMessage_EnableStartupLaunchDeniedMessage": "You can enable startup launch from Settings -> App Preferences.",
|
||||
"Dialog_DontAskAgain": "Don't ask again",
|
||||
"CreateAccountAliasDialog_Title": "Create Account Alias",
|
||||
"CreateAccountAliasDialog_Description": "Make sure your outgoing server allows sending mails from this alias.",
|
||||
|
||||
50
Wino.Core.Domain/Translator.Designer.cs
generated
50
Wino.Core.Domain/Translator.Designer.cs
generated
@@ -78,6 +78,41 @@ namespace Wino.Core.Domain
|
||||
/// </summary>
|
||||
public static string AutoDiscoveryProgressMessage => Resources.GetTranslatedString(@"AutoDiscoveryProgressMessage");
|
||||
|
||||
/// <summary>
|
||||
/// Background Synchronization
|
||||
/// </summary>
|
||||
public static string AppCloseBackgroundSynchronizationWarningTitle => Resources.GetTranslatedString(@"AppCloseBackgroundSynchronizationWarningTitle");
|
||||
|
||||
/// <summary>
|
||||
/// You are terminating Wino Mail and your app close behavior is set to 'Terminate'.
|
||||
/// </summary>
|
||||
public static string AppCloseTerminateBehaviorWarningMessageFirstLine => Resources.GetTranslatedString(@"AppCloseTerminateBehaviorWarningMessageFirstLine");
|
||||
|
||||
/// <summary>
|
||||
/// This will stop all background synchronizations and notifications.
|
||||
/// </summary>
|
||||
public static string AppCloseTerminateBehaviorWarningMessageSecondLine => Resources.GetTranslatedString(@"AppCloseTerminateBehaviorWarningMessageSecondLine");
|
||||
|
||||
/// <summary>
|
||||
/// Do you want to go to App Preferences to set Wino Mail to run minimized or in the background?
|
||||
/// </summary>
|
||||
public static string AppCloseTerminateBehaviorWarningMessageThirdLine => Resources.GetTranslatedString(@"AppCloseTerminateBehaviorWarningMessageThirdLine");
|
||||
|
||||
/// <summary>
|
||||
/// Application has not been set to launch on Windows startup.
|
||||
/// </summary>
|
||||
public static string AppCloseStartupLaunchDisabledWarningMessageFirstLine => Resources.GetTranslatedString(@"AppCloseStartupLaunchDisabledWarningMessageFirstLine");
|
||||
|
||||
/// <summary>
|
||||
/// This will cause you to miss notifications when you restart your computer.
|
||||
/// </summary>
|
||||
public static string AppCloseStartupLaunchDisabledWarningMessageSecondLine => Resources.GetTranslatedString(@"AppCloseStartupLaunchDisabledWarningMessageSecondLine");
|
||||
|
||||
/// <summary>
|
||||
/// Do you want to go to App Preferences page to enable it?
|
||||
/// </summary>
|
||||
public static string AppCloseStartupLaunchDisabledWarningMessageThirdLine => Resources.GetTranslatedString(@"AppCloseStartupLaunchDisabledWarningMessageThirdLine");
|
||||
|
||||
/// <summary>
|
||||
/// Advanced Configuration
|
||||
/// </summary>
|
||||
@@ -548,6 +583,21 @@ namespace Wino.Core.Domain
|
||||
/// </summary>
|
||||
public static string DialogMessage_UnsubscribeConfirmationMailtoMessage => Resources.GetTranslatedString(@"DialogMessage_UnsubscribeConfirmationMailtoMessage");
|
||||
|
||||
/// <summary>
|
||||
/// Enable Startup Launch
|
||||
/// </summary>
|
||||
public static string DialogMessage_EnableStartupLaunchTitle => Resources.GetTranslatedString(@"DialogMessage_EnableStartupLaunchTitle");
|
||||
|
||||
/// <summary>
|
||||
/// Let Wino Mail automatically launch minimized on Windows startup to not miss any notifications. Do you want to enable startup launch?
|
||||
/// </summary>
|
||||
public static string DialogMessage_EnableStartupLaunchMessage => Resources.GetTranslatedString(@"DialogMessage_EnableStartupLaunchMessage");
|
||||
|
||||
/// <summary>
|
||||
/// You can enable startup launch from Settings -> App Preferences.
|
||||
/// </summary>
|
||||
public static string DialogMessage_EnableStartupLaunchDeniedMessage => Resources.GetTranslatedString(@"DialogMessage_EnableStartupLaunchDeniedMessage");
|
||||
|
||||
/// <summary>
|
||||
/// Don't ask again
|
||||
/// </summary>
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.WinUI.Notifications;
|
||||
using Serilog;
|
||||
using Windows.Data.Xml.Dom;
|
||||
using Windows.UI.Notifications;
|
||||
using Wino.Core.Domain;
|
||||
@@ -38,83 +39,90 @@ namespace Wino.Core.UWP.Services
|
||||
{
|
||||
var mailCount = downloadedMailItems.Count();
|
||||
|
||||
// If there are more than 3 mails, just display 1 general toast.
|
||||
if (mailCount > 3)
|
||||
try
|
||||
{
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
builder.AddText(Translator.Notifications_MultipleNotificationsTitle);
|
||||
builder.AddText(string.Format(Translator.Notifications_MultipleNotificationsMessage, mailCount));
|
||||
|
||||
builder.AddButton(GetDismissButton());
|
||||
|
||||
builder.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
var validItems = new List<IMailItem>();
|
||||
|
||||
// Fetch mails again to fill up assigned folder data and latest statuses.
|
||||
// They've been marked as read by executing synchronizer tasks until inital sync finishes.
|
||||
|
||||
foreach (var item in downloadedMailItems)
|
||||
// If there are more than 3 mails, just display 1 general toast.
|
||||
if (mailCount > 3)
|
||||
{
|
||||
var mailItem = await _mailService.GetSingleMailItemAsync(item.UniqueId);
|
||||
|
||||
if (mailItem != null && mailItem.AssignedFolder != null)
|
||||
{
|
||||
validItems.Add(mailItem);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mailItem in validItems)
|
||||
{
|
||||
//if (mailItem.IsRead)
|
||||
// continue;
|
||||
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
var host = ThumbnailService.GetHost(mailItem.FromAddress);
|
||||
builder.AddText(Translator.Notifications_MultipleNotificationsTitle);
|
||||
builder.AddText(string.Format(Translator.Notifications_MultipleNotificationsMessage, mailCount));
|
||||
|
||||
var knownTuple = ThumbnailService.CheckIsKnown(host);
|
||||
|
||||
bool isKnown = knownTuple.Item1;
|
||||
host = knownTuple.Item2;
|
||||
|
||||
if (isKnown)
|
||||
builder.AddAppLogoOverride(new System.Uri(ThumbnailService.GetKnownHostImage(host)), hintCrop: ToastGenericAppLogoCrop.Default);
|
||||
else
|
||||
{
|
||||
// TODO: https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=toolkit
|
||||
// Follow official guides for icons/theme.
|
||||
|
||||
bool isOSDarkTheme = _underlyingThemeService.IsUnderlyingThemeDark();
|
||||
string profileLogoName = isOSDarkTheme ? "profile-dark.png" : "profile-light.png";
|
||||
|
||||
builder.AddAppLogoOverride(new System.Uri($"ms-appx:///Assets/NotificationIcons/{profileLogoName}"), hintCrop: ToastGenericAppLogoCrop.Circle);
|
||||
}
|
||||
|
||||
// Override system notification timetamp with received date of the mail.
|
||||
// It may create confusion for some users, but still it's the truth...
|
||||
builder.AddCustomTimeStamp(mailItem.CreationDate.ToLocalTime());
|
||||
|
||||
builder.AddText(mailItem.FromName);
|
||||
builder.AddText(mailItem.Subject);
|
||||
builder.AddText(mailItem.PreviewText);
|
||||
|
||||
builder.AddArgument(Constants.ToastMailUniqueIdKey, mailItem.UniqueId.ToString());
|
||||
builder.AddArgument(Constants.ToastActionKey, MailOperation.Navigate);
|
||||
|
||||
builder.AddButton(GetMarkedAsRead(mailItem.UniqueId));
|
||||
builder.AddButton(GetDeleteButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetDismissButton());
|
||||
|
||||
builder.Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
var validItems = new List<IMailItem>();
|
||||
|
||||
await UpdateTaskbarIconBadgeAsync();
|
||||
// Fetch mails again to fill up assigned folder data and latest statuses.
|
||||
// They've been marked as read by executing synchronizer tasks until inital sync finishes.
|
||||
|
||||
foreach (var item in downloadedMailItems)
|
||||
{
|
||||
var mailItem = await _mailService.GetSingleMailItemAsync(item.UniqueId);
|
||||
|
||||
if (mailItem != null && mailItem.AssignedFolder != null)
|
||||
{
|
||||
validItems.Add(mailItem);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var mailItem in validItems)
|
||||
{
|
||||
if (mailItem.IsRead)
|
||||
continue;
|
||||
|
||||
var builder = new ToastContentBuilder();
|
||||
builder.SetToastScenario(ToastScenario.Default);
|
||||
|
||||
var host = ThumbnailService.GetHost(mailItem.FromAddress);
|
||||
|
||||
var knownTuple = ThumbnailService.CheckIsKnown(host);
|
||||
|
||||
bool isKnown = knownTuple.Item1;
|
||||
host = knownTuple.Item2;
|
||||
|
||||
if (isKnown)
|
||||
builder.AddAppLogoOverride(new System.Uri(ThumbnailService.GetKnownHostImage(host)), hintCrop: ToastGenericAppLogoCrop.Default);
|
||||
else
|
||||
{
|
||||
// TODO: https://learn.microsoft.com/en-us/windows/apps/design/shell/tiles-and-notifications/adaptive-interactive-toasts?tabs=toolkit
|
||||
// Follow official guides for icons/theme.
|
||||
|
||||
bool isOSDarkTheme = _underlyingThemeService.IsUnderlyingThemeDark();
|
||||
string profileLogoName = isOSDarkTheme ? "profile-dark.png" : "profile-light.png";
|
||||
|
||||
builder.AddAppLogoOverride(new System.Uri($"ms-appx:///Assets/NotificationIcons/{profileLogoName}"), hintCrop: ToastGenericAppLogoCrop.Circle);
|
||||
}
|
||||
|
||||
// Override system notification timetamp with received date of the mail.
|
||||
// It may create confusion for some users, but still it's the truth...
|
||||
builder.AddCustomTimeStamp(mailItem.CreationDate.ToLocalTime());
|
||||
|
||||
builder.AddText(mailItem.FromName);
|
||||
builder.AddText(mailItem.Subject);
|
||||
builder.AddText(mailItem.PreviewText);
|
||||
|
||||
builder.AddArgument(Constants.ToastMailUniqueIdKey, mailItem.UniqueId.ToString());
|
||||
builder.AddArgument(Constants.ToastActionKey, MailOperation.Navigate);
|
||||
|
||||
builder.AddButton(GetMarkedAsRead(mailItem.UniqueId));
|
||||
builder.AddButton(GetDeleteButton(mailItem.UniqueId));
|
||||
builder.AddButton(GetDismissButton());
|
||||
|
||||
builder.Show();
|
||||
}
|
||||
|
||||
await UpdateTaskbarIconBadgeAsync();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to create notifications.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +150,10 @@ namespace Wino.Core.UWP.Services
|
||||
public async Task UpdateTaskbarIconBadgeAsync()
|
||||
{
|
||||
int totalUnreadCount = 0;
|
||||
var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication();
|
||||
|
||||
try
|
||||
{
|
||||
var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication();
|
||||
var accounts = await _accountService.GetAccountsAsync();
|
||||
|
||||
foreach (var account in accounts)
|
||||
@@ -178,11 +186,9 @@ namespace Wino.Core.UWP.Services
|
||||
else
|
||||
badgeUpdater.Clear();
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
catch (Exception ex)
|
||||
{
|
||||
// TODO: Log exceptions.
|
||||
|
||||
badgeUpdater.Clear();
|
||||
Log.Error(ex, "Error while updating taskbar badge.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,9 +23,6 @@ namespace Wino.Core.UWP.Services
|
||||
_dialogService = dialogService;
|
||||
}
|
||||
|
||||
private void SetRated()
|
||||
=> _configurationService.SetRoaming(RatedStorageKey, true);
|
||||
|
||||
private bool IsAskingThresholdExceeded()
|
||||
{
|
||||
var latestAskedDate = _configurationService.Get(LatestAskedKey, DateTime.MinValue);
|
||||
@@ -62,15 +59,14 @@ namespace Wino.Core.UWP.Services
|
||||
{
|
||||
if (!IsAskingThresholdExceeded()) return;
|
||||
|
||||
var ratingDialogResult = await _dialogService.ShowRatingDialogAsync();
|
||||
var isRateWinoApproved = await _dialogService.ShowWinoCustomMessageDialogAsync(Translator.StoreRatingDialog_Title,
|
||||
Translator.StoreRatingDialog_MessageFirstLine,
|
||||
Translator.Buttons_RateWino,
|
||||
Domain.Enums.WinoCustomMessageDialogIcon.Question,
|
||||
Translator.Buttons_No,
|
||||
RatedStorageKey);
|
||||
|
||||
if (ratingDialogResult == null)
|
||||
return;
|
||||
|
||||
if (ratingDialogResult.DontAskAgain)
|
||||
SetRated();
|
||||
|
||||
if (ratingDialogResult.RateWinoClicked)
|
||||
if (isRateWinoApproved)
|
||||
{
|
||||
// In case of failure of this call, we will navigate users to Store page directly.
|
||||
|
||||
@@ -107,7 +103,7 @@ namespace Wino.Core.UWP.Services
|
||||
else
|
||||
_dialogService.InfoBarMessage(Translator.Info_ReviewSuccessTitle, Translator.Info_ReviewNewMessage, Domain.Enums.InfoBarMessageType.Success);
|
||||
|
||||
SetRated();
|
||||
_configurationService.Set(RatedStorageKey, true);
|
||||
break;
|
||||
case StoreRateAndReviewStatus.CanceledByUser:
|
||||
break;
|
||||
|
||||
@@ -151,15 +151,12 @@ namespace Wino.Core.MenuItems
|
||||
return accountMenuItem;
|
||||
}
|
||||
|
||||
public async Task ReplaceFoldersAsync(IEnumerable<IMenuItem> folders)
|
||||
public void ReplaceFolders(IEnumerable<IMenuItem> folders)
|
||||
{
|
||||
await _dispatcher.ExecuteOnUIThread(() =>
|
||||
{
|
||||
ClearFolderAreaMenuItems();
|
||||
ClearFolderAreaMenuItems();
|
||||
|
||||
Items.Add(new SeperatorItem());
|
||||
AddRange(folders);
|
||||
});
|
||||
Items.Add(new SeperatorItem());
|
||||
AddRange(folders);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -194,9 +191,11 @@ namespace Wino.Core.MenuItems
|
||||
{
|
||||
item.IsExpanded = false;
|
||||
item.IsSelected = false;
|
||||
|
||||
Remove(item);
|
||||
});
|
||||
|
||||
RemoveRange(itemsToRemove);
|
||||
// RemoveRange(itemsToRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ namespace Wino.Core.Services
|
||||
|
||||
public class DatabaseService : IDatabaseService
|
||||
{
|
||||
private const string DatabaseName = "Wino172.db";
|
||||
private const string DatabaseName = "Wino180.db";
|
||||
|
||||
private bool _isInitialized = false;
|
||||
private readonly IApplicationConfiguration _folderConfiguration;
|
||||
|
||||
@@ -387,11 +387,6 @@ namespace Wino.Core.Services
|
||||
if (configuration == null)
|
||||
throw new ArgumentNullException(nameof(configuration));
|
||||
|
||||
var account = await _accountService.GetAccountAsync(accountId);
|
||||
|
||||
if (account == null)
|
||||
throw new ArgumentNullException(nameof(account));
|
||||
|
||||
// Update system folders for this account.
|
||||
|
||||
await Task.WhenAll(UpdateSystemFolderInternalAsync(configuration.SentFolder, SpecialFolderType.Sent),
|
||||
@@ -400,9 +395,8 @@ namespace Wino.Core.Services
|
||||
UpdateSystemFolderInternalAsync(configuration.TrashFolder, SpecialFolderType.Deleted),
|
||||
UpdateSystemFolderInternalAsync(configuration.ArchiveFolder, SpecialFolderType.Archive));
|
||||
|
||||
await _accountService.UpdateAccountAsync(account);
|
||||
|
||||
return account;
|
||||
return await _accountService.GetAccountAsync(accountId).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private Task UpdateSystemFolderInternalAsync(MailItemFolder folder, SpecialFolderType assignedSpecialFolderType)
|
||||
@@ -492,13 +486,6 @@ namespace Wino.Core.Services
|
||||
return;
|
||||
}
|
||||
|
||||
var account = await _accountService.GetAccountAsync(folder.MailAccountId).ConfigureAwait(false);
|
||||
if (account == null)
|
||||
{
|
||||
_logger.Warning("Account with id {MailAccountId} does not exist. Cannot update folder.", folder.MailAccountId);
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.Debug("Updating folder {FolderName}", folder.Id, folder.FolderName);
|
||||
|
||||
await Connection.UpdateAsync(folder).ConfigureAwait(false);
|
||||
|
||||
@@ -785,6 +785,7 @@ namespace Wino.Core.Synchronizers
|
||||
EventHandler<MessageFlagsChangedEventArgs> MessageFlagsChangedHandler = async (s, e) =>
|
||||
{
|
||||
if (imapFolder == null) return;
|
||||
if (e.UniqueId == null) return;
|
||||
|
||||
var localMailCopyId = MailkitClientExtensions.CreateUid(folder.Id, e.UniqueId.Value.Id);
|
||||
|
||||
|
||||
@@ -95,7 +95,9 @@ namespace Wino.Mail.ViewModels
|
||||
{
|
||||
// Discord disclaimer message about server.
|
||||
if (stringUrl == DiscordChannelUrl)
|
||||
await DialogService.ShowMessageAsync(Translator.DiscordChannelDisclaimerMessage, Translator.DiscordChannelDisclaimerTitle);
|
||||
await DialogService.ShowMessageAsync(Translator.DiscordChannelDisclaimerMessage,
|
||||
Translator.DiscordChannelDisclaimerTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
|
||||
await _nativeAppService.LaunchUriAsync(new Uri(stringUrl));
|
||||
}
|
||||
|
||||
@@ -98,14 +98,18 @@ namespace Wino.Mail.ViewModels
|
||||
// Check existence.
|
||||
if (AccountAliases.Any(a => a.AliasAddress == newAlias.AliasAddress))
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_AliasExistsTitle, Translator.DialogMessage_AliasExistsMessage);
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_AliasExistsTitle,
|
||||
Translator.DialogMessage_AliasExistsMessage,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate all addresses.
|
||||
if (!EmailValidator.Validate(newAlias.AliasAddress) || (!string.IsNullOrEmpty(newAlias.ReplyToAddress) && !EmailValidator.Validate(newAlias.ReplyToAddress)))
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_InvalidAliasMessage, Translator.DialogMessage_InvalidAliasTitle);
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_InvalidAliasMessage,
|
||||
Translator.DialogMessage_InvalidAliasTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -125,14 +129,18 @@ namespace Wino.Mail.ViewModels
|
||||
// Primary aliases can't be deleted.
|
||||
if (alias.IsPrimary)
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.Info_CantDeletePrimaryAliasMessage, Translator.GeneralTitle_Warning);
|
||||
await DialogService.ShowMessageAsync(Translator.Info_CantDeletePrimaryAliasMessage,
|
||||
Translator.GeneralTitle_Warning,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
// Root aliases can't be deleted.
|
||||
if (alias.IsRootAlias)
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_CantDeleteRootAliasTitle, Translator.DialogMessage_CantDeleteRootAliasMessage);
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_CantDeleteRootAliasTitle,
|
||||
Translator.DialogMessage_CantDeleteRootAliasMessage,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,9 @@ namespace Wino.Mail.ViewModels
|
||||
IRecipient<MergedInboxRenamed>,
|
||||
IRecipient<LanguageChanged>,
|
||||
IRecipient<AccountMenuItemsReordered>,
|
||||
IRecipient<AccountSynchronizationProgressUpdatedMessage>
|
||||
IRecipient<AccountSynchronizationProgressUpdatedMessage>,
|
||||
IRecipient<NavigateAppPreferencesRequested>,
|
||||
IRecipient<AccountFolderConfigurationUpdated>
|
||||
{
|
||||
#region Menu Items
|
||||
|
||||
@@ -59,12 +61,16 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
#endregion
|
||||
|
||||
private const string IsActivateStartupLaunchAskedKey = nameof(IsActivateStartupLaunchAskedKey);
|
||||
|
||||
public IStatePersistanceService StatePersistenceService { get; }
|
||||
public IWinoServerConnectionManager ServerConnectionManager { get; }
|
||||
public IPreferencesService PreferencesService { get; }
|
||||
public IWinoNavigationService NavigationService { get; }
|
||||
|
||||
private readonly IFolderService _folderService;
|
||||
private readonly IConfigurationService _configurationService;
|
||||
private readonly IStartupBehaviorService _startupBehaviorService;
|
||||
private readonly IAccountService _accountService;
|
||||
private readonly IContextMenuItemService _contextMenuItemService;
|
||||
private readonly IStoreRatingService _storeRatingService;
|
||||
@@ -98,7 +104,9 @@ namespace Wino.Mail.ViewModels
|
||||
IWinoRequestDelegator winoRequestDelegator,
|
||||
IFolderService folderService,
|
||||
IStatePersistanceService statePersistanceService,
|
||||
IWinoServerConnectionManager serverConnectionManager) : base(dialogService)
|
||||
IWinoServerConnectionManager serverConnectionManager,
|
||||
IConfigurationService configurationService,
|
||||
IStartupBehaviorService startupBehaviorService) : base(dialogService)
|
||||
{
|
||||
StatePersistenceService = statePersistanceService;
|
||||
ServerConnectionManager = serverConnectionManager;
|
||||
@@ -115,6 +123,8 @@ namespace Wino.Mail.ViewModels
|
||||
PreferencesService = preferencesService;
|
||||
NavigationService = navigationService;
|
||||
|
||||
_configurationService = configurationService;
|
||||
_startupBehaviorService = startupBehaviorService;
|
||||
_backgroundTaskService = backgroundTaskService;
|
||||
_mimeFileService = mimeFileService;
|
||||
_nativeAppService = nativeAppService;
|
||||
@@ -229,16 +239,56 @@ namespace Wino.Mail.ViewModels
|
||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
|
||||
await CreateFooterItemsAsync();
|
||||
|
||||
await RecreateMenuItemsAsync();
|
||||
await ProcessLaunchOptionsAsync();
|
||||
|
||||
await ForceAllAccountSynchronizationsAsync();
|
||||
await MakeSureEnableStartupLaunchAsync();
|
||||
ConfigureBackgroundTasks();
|
||||
}
|
||||
|
||||
private async Task MakeSureEnableStartupLaunchAsync()
|
||||
{
|
||||
if (!_configurationService.Get<bool>(IsActivateStartupLaunchAskedKey, false))
|
||||
{
|
||||
var currentBehavior = await _startupBehaviorService.GetCurrentStartupBehaviorAsync();
|
||||
|
||||
// User somehow already enabled Wino before the first launch.
|
||||
if (currentBehavior == StartupBehaviorResult.Enabled)
|
||||
{
|
||||
_configurationService.Set(IsActivateStartupLaunchAskedKey, true);
|
||||
return;
|
||||
}
|
||||
|
||||
bool isAccepted = await DialogService.ShowWinoCustomMessageDialogAsync(Translator.DialogMessage_EnableStartupLaunchTitle,
|
||||
Translator.DialogMessage_EnableStartupLaunchMessage,
|
||||
Translator.Buttons_Yes,
|
||||
WinoCustomMessageDialogIcon.Information,
|
||||
Translator.Buttons_No);
|
||||
|
||||
bool shouldDisplayLaterOnMessage = !isAccepted;
|
||||
|
||||
if (isAccepted)
|
||||
{
|
||||
var behavior = await _startupBehaviorService.ToggleStartupBehavior(true);
|
||||
|
||||
shouldDisplayLaterOnMessage = behavior != StartupBehaviorResult.Enabled;
|
||||
}
|
||||
|
||||
if (shouldDisplayLaterOnMessage)
|
||||
{
|
||||
await DialogService.ShowWinoCustomMessageDialogAsync(Translator.DialogMessage_EnableStartupLaunchTitle,
|
||||
Translator.DialogMessage_EnableStartupLaunchDeniedMessage,
|
||||
Translator.Buttons_Close,
|
||||
WinoCustomMessageDialogIcon.Information);
|
||||
}
|
||||
|
||||
_configurationService.Set(IsActivateStartupLaunchAskedKey, true);
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureBackgroundTasks()
|
||||
{
|
||||
try
|
||||
@@ -527,7 +577,7 @@ namespace Wino.Mail.ViewModels
|
||||
StatePersistenceService.CoreWindowTitle = "Wino Mail";
|
||||
}
|
||||
|
||||
public async Task MenuItemInvokedOrSelectedAsync(IMenuItem clickedMenuItem)
|
||||
public async Task MenuItemInvokedOrSelectedAsync(IMenuItem clickedMenuItem, object parameter = null)
|
||||
{
|
||||
if (clickedMenuItem == null) return;
|
||||
|
||||
@@ -561,11 +611,11 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
else if (clickedMenuItem is SettingsItem)
|
||||
{
|
||||
NavigationService.Navigate(WinoPage.SettingsPage);
|
||||
NavigationService.Navigate(WinoPage.SettingsPage, parameter, NavigationReferenceFrame.ShellFrame, NavigationTransitionType.None);
|
||||
}
|
||||
else if (clickedMenuItem is ManageAccountsMenuItem)
|
||||
{
|
||||
NavigationService.Navigate(WinoPage.AccountManagementPage);
|
||||
NavigationService.Navigate(WinoPage.AccountManagementPage, parameter, NavigationReferenceFrame.ShellFrame, NavigationTransitionType.None);
|
||||
}
|
||||
else if (clickedMenuItem is IAccountMenuItem clickedAccountMenuItem && latestSelectedAccountMenuItem != clickedAccountMenuItem)
|
||||
{
|
||||
@@ -582,6 +632,9 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(false);
|
||||
|
||||
// Load account folder structure and replace the visible folders.
|
||||
var folders = await _folderService.GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||
|
||||
await ExecuteUIThread(() =>
|
||||
{
|
||||
clickedBaseAccountMenuItem.IsEnabled = false;
|
||||
@@ -594,12 +647,10 @@ namespace Wino.Mail.ViewModels
|
||||
clickedBaseAccountMenuItem.IsSelected = true;
|
||||
|
||||
latestSelectedAccountMenuItem = clickedBaseAccountMenuItem;
|
||||
|
||||
MenuItems.ReplaceFolders(folders);
|
||||
});
|
||||
|
||||
// Load account folder structure and replace the visible folders.
|
||||
var folders = await _folderService.GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||
|
||||
await MenuItems.ReplaceFoldersAsync(folders);
|
||||
await UpdateUnreadItemCountAsync();
|
||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(true);
|
||||
|
||||
@@ -721,7 +772,19 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (!accounts.Any())
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_NoAccountsForCreateMailMessage, Translator.DialogMessage_NoAccountsForCreateMailTitle);
|
||||
var isManageAccountClicked = await DialogService.ShowWinoCustomMessageDialogAsync(Translator.DialogMessage_NoAccountsForCreateMailMessage,
|
||||
Translator.DialogMessage_NoAccountsForCreateMailTitle,
|
||||
Translator.MenuManageAccounts,
|
||||
WinoCustomMessageDialogIcon.Information,
|
||||
string.Empty);
|
||||
|
||||
|
||||
|
||||
if (isManageAccountClicked)
|
||||
{
|
||||
SelectedMenuItem = ManageAccountsMenuItem;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -850,7 +913,9 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (!accounts.Any())
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_NoAccountsForCreateMailMessage, Translator.DialogMessage_NoAccountsForCreateMailTitle);
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_NoAccountsForCreateMailMessage,
|
||||
Translator.DialogMessage_NoAccountsForCreateMailTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
}
|
||||
else if (accounts.Count == 1)
|
||||
{
|
||||
@@ -892,6 +957,16 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(AccountFolderConfigurationUpdated message)
|
||||
{
|
||||
// Reloading of folders is needed to re-create folder tree if the account is loaded.
|
||||
|
||||
if (MenuItems.TryGetAccountMenuItem(message.AccountId, out IAccountMenuItem accountMenuItem))
|
||||
{
|
||||
await ChangeLoadedAccountAsync(accountMenuItem, true);
|
||||
}
|
||||
}
|
||||
|
||||
public async void Receive(MergedInboxRenamed message)
|
||||
{
|
||||
var mergedInboxMenuItem = MenuItems.FirstOrDefault(a => a.EntityId == message.MergedInboxId);
|
||||
@@ -961,5 +1036,10 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
await ExecuteUIThread(() => { accountMenuItem.SynchronizationProgress = message.Progress; });
|
||||
}
|
||||
|
||||
public async void Receive(NavigateAppPreferencesRequested message)
|
||||
{
|
||||
await MenuItemInvokedOrSelectedAsync(SettingsItem, WinoPage.AppPreferencesPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,9 @@ namespace Wino.Mail.ViewModels
|
||||
|
||||
if (!ToItems.Any())
|
||||
{
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_ComposerMissingRecipientMessage, Translator.DialogMessage_ComposerValidationFailedTitle);
|
||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_ComposerMissingRecipientMessage,
|
||||
Translator.DialogMessage_ComposerValidationFailedTitle,
|
||||
WinoCustomMessageDialogIcon.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -202,17 +204,7 @@ namespace Wino.Mail.ViewModels
|
||||
await _worker.ExecuteAsync(draftSendPreparationRequest);
|
||||
}
|
||||
|
||||
public async Task IncludeAttachmentAsync(MailAttachmentViewModel viewModel)
|
||||
{
|
||||
//if (bodyBuilder == null) return;
|
||||
|
||||
//bodyBuilder.Attachments.Add(viewModel.FileName, new MemoryStream(viewModel.Content));
|
||||
|
||||
//LoadAttachments();
|
||||
IncludedAttachments.Add(viewModel);
|
||||
}
|
||||
|
||||
private async Task UpdateMimeChangesAsync()
|
||||
public async Task UpdateMimeChangesAsync()
|
||||
{
|
||||
if (isUpdatingMimeBlocked || CurrentMimeMessage == null || ComposingAccount == null || CurrentMailDraftItem == null) return;
|
||||
|
||||
@@ -336,13 +328,12 @@ namespace Wino.Mail.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public override async void OnNavigatedFrom(NavigationMode mode, object parameters)
|
||||
public override void OnNavigatedFrom(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnNavigatedFrom(mode, parameters);
|
||||
|
||||
await UpdateMimeChangesAsync().ConfigureAwait(false);
|
||||
|
||||
Messenger.Send(new KillChromiumRequested());
|
||||
/// Do not put any code here.
|
||||
/// Make sure to use Page's OnNavigatedTo instead.
|
||||
}
|
||||
|
||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
|
||||
@@ -6,13 +6,6 @@ namespace Wino.Mail.ViewModels.Messages
|
||||
/// When the rendering page is active, but new item is requested to be rendered.
|
||||
/// To not trigger navigation again and re-use existing Chromium.
|
||||
/// </summary>
|
||||
public class NewMailItemRenderingRequestedEvent
|
||||
{
|
||||
public NewMailItemRenderingRequestedEvent(MailItemViewModel mailItemViewModel)
|
||||
{
|
||||
MailItemViewModel = mailItemViewModel;
|
||||
}
|
||||
|
||||
public MailItemViewModel MailItemViewModel { get; }
|
||||
}
|
||||
/// <param name="MailItemViewModel"></param>
|
||||
public record NewMailItemRenderingRequestedEvent(MailItemViewModel MailItemViewModel);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="using:Wino.Controls"
|
||||
xmlns:selectors="using:Wino.Selectors"
|
||||
xmlns:wino="using:Wino">
|
||||
xmlns:wino="using:Wino"
|
||||
xmlns:dialogs="using:Wino.Core.Domain.Models.Dialogs"
|
||||
xmlns:styles="using:Wino.Styles">
|
||||
|
||||
<Application.Resources>
|
||||
<ResourceDictionary>
|
||||
@@ -18,6 +20,7 @@
|
||||
<ResourceDictionary Source="/Styles/CommandBarItems.xaml" />
|
||||
<ResourceDictionary Source="/Styles/ItemContainerStyles.xaml" />
|
||||
<ResourceDictionary Source="/Styles/WinoInfoBar.xaml" />
|
||||
<styles:CustomMessageDialogStyles />
|
||||
|
||||
<ResourceDictionary>
|
||||
|
||||
@@ -166,6 +169,10 @@
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
|
||||
|
||||
<!-- Attachment Icon Templates -->
|
||||
|
||||
<DataTemplate x:Key="NoneTemplate">
|
||||
<Image Source="/Assets/FileTypes/type_none.png" />
|
||||
</DataTemplate>
|
||||
|
||||
@@ -21,6 +21,7 @@ using Windows.Foundation.Metadata;
|
||||
using Windows.Storage;
|
||||
using Windows.System.Profile;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Core.Preview;
|
||||
using Windows.UI.Notifications;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Windows.UI.Xaml;
|
||||
@@ -38,6 +39,7 @@ using Wino.Core.UWP;
|
||||
using Wino.Core.UWP.Services;
|
||||
using Wino.Mail.ViewModels;
|
||||
using Wino.Messaging.Client.Connection;
|
||||
using Wino.Messaging.Client.Navigation;
|
||||
using Wino.Messaging.Server;
|
||||
using Wino.Services;
|
||||
|
||||
@@ -107,6 +109,78 @@ namespace Wino
|
||||
WeakReferenceMessenger.Default.Register(this);
|
||||
}
|
||||
|
||||
private async void ApplicationCloseRequested(object sender, SystemNavigationCloseRequestedPreviewEventArgs e)
|
||||
{
|
||||
var deferral = e.GetDeferral();
|
||||
|
||||
// Wino should notify user on app close if:
|
||||
// 1. User has at least 1 registered account.
|
||||
// 2. Startup behavior is not Enabled.
|
||||
// 3. Server terminate behavior is set to Terminate.
|
||||
|
||||
var accountService = Services.GetService<IAccountService>();
|
||||
|
||||
var accounts = await accountService.GetAccountsAsync();
|
||||
|
||||
if (accounts.Count > 0)
|
||||
{
|
||||
// User has some accounts. Check if Wino Server runs on system startup.
|
||||
|
||||
var dialogService = Services.GetService<IDialogService>();
|
||||
var startupBehaviorService = Services.GetService<IStartupBehaviorService>();
|
||||
var preferencesService = Services.GetService<IPreferencesService>();
|
||||
|
||||
var currentStartupBehavior = await startupBehaviorService.GetCurrentStartupBehaviorAsync();
|
||||
|
||||
bool? isGoToAppPreferencesRequested = null;
|
||||
|
||||
if (preferencesService.ServerTerminationBehavior == ServerBackgroundMode.Terminate)
|
||||
{
|
||||
// Starting the server is fine, but check if server termination behavior is set to terminate.
|
||||
// This state will kill the server once the app is terminated.
|
||||
|
||||
isGoToAppPreferencesRequested = await _dialogService.ShowWinoCustomMessageDialogAsync(Translator.AppCloseBackgroundSynchronizationWarningTitle,
|
||||
$"{Translator.AppCloseTerminateBehaviorWarningMessageFirstLine}\n{Translator.AppCloseTerminateBehaviorWarningMessageSecondLine}\n\n{Translator.AppCloseTerminateBehaviorWarningMessageThirdLine}",
|
||||
Translator.Buttons_Yes,
|
||||
WinoCustomMessageDialogIcon.Warning,
|
||||
Translator.Buttons_No,
|
||||
"DontAskTerminateServerBehavior");
|
||||
}
|
||||
|
||||
if (isGoToAppPreferencesRequested == null && currentStartupBehavior != StartupBehaviorResult.Enabled)
|
||||
{
|
||||
// Startup behavior is not enabled.
|
||||
|
||||
isGoToAppPreferencesRequested = await dialogService.ShowWinoCustomMessageDialogAsync(Translator.AppCloseBackgroundSynchronizationWarningTitle,
|
||||
$"{Translator.AppCloseStartupLaunchDisabledWarningMessageFirstLine}\n{Translator.AppCloseStartupLaunchDisabledWarningMessageSecondLine}\n\n{Translator.AppCloseStartupLaunchDisabledWarningMessageThirdLine}",
|
||||
Translator.Buttons_Yes,
|
||||
WinoCustomMessageDialogIcon.Warning,
|
||||
Translator.Buttons_No,
|
||||
"DontAskDisabledStartup");
|
||||
}
|
||||
|
||||
if (isGoToAppPreferencesRequested == true)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new NavigateAppPreferencesRequested());
|
||||
e.Handled = true;
|
||||
}
|
||||
else if (preferencesService.ServerTerminationBehavior == ServerBackgroundMode.Terminate)
|
||||
{
|
||||
try
|
||||
{
|
||||
var isServerKilled = await _appServiceConnectionManager.GetResponseAsync<bool, TerminateServerRequested>(new TerminateServerRequested());
|
||||
Log.Information("Server is killed.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Failed to kill server.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deferral.Complete();
|
||||
}
|
||||
|
||||
private async void OnResuming(object sender, object e)
|
||||
{
|
||||
// App Service connection was lost on suspension.
|
||||
@@ -233,6 +307,7 @@ namespace Wino
|
||||
LogActivation("Window is created.");
|
||||
|
||||
ConfigureTitleBar();
|
||||
TryRegisterAppCloseChange();
|
||||
}
|
||||
|
||||
protected override async void OnLaunched(LaunchActivatedEventArgs args)
|
||||
@@ -245,6 +320,18 @@ namespace Wino
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRegisterAppCloseChange()
|
||||
{
|
||||
try
|
||||
{
|
||||
var systemNavigationManagerPreview = SystemNavigationManagerPreview.GetForCurrentView();
|
||||
|
||||
systemNavigationManagerPreview.CloseRequested -= ApplicationCloseRequested;
|
||||
systemNavigationManagerPreview.CloseRequested += ApplicationCloseRequested;
|
||||
}
|
||||
catch { }
|
||||
}
|
||||
|
||||
protected override async void OnFileActivated(FileActivatedEventArgs args)
|
||||
{
|
||||
base.OnFileActivated(args);
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.ConfirmationDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
Title="{x:Bind DialogTitle, Mode=OneWay}"
|
||||
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
Closed="DialogClosed"
|
||||
PrimaryButtonText="{x:Bind ApproveButtonTitle, Mode=OneWay}"
|
||||
DefaultButton="Primary"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
PrimaryButtonClick="ApproveClicked"
|
||||
SecondaryButtonClick="CancelClicked"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">250</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">500</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">200</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<TextBlock Text="{x:Bind Message, Mode=OneWay}" TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
@@ -1,80 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Dialogs
|
||||
{
|
||||
public sealed partial class ConfirmationDialog : ContentDialog, IConfirmationDialog
|
||||
{
|
||||
private TaskCompletionSource<bool> _completionSource;
|
||||
|
||||
#region Dependency Properties
|
||||
|
||||
public string DialogTitle
|
||||
{
|
||||
get { return (string)GetValue(DialogTitleProperty); }
|
||||
set { SetValue(DialogTitleProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DialogTitleProperty = DependencyProperty.Register(nameof(DialogTitle), typeof(string), typeof(ConfirmationDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
public string Message
|
||||
{
|
||||
get { return (string)GetValue(MessageProperty); }
|
||||
set { SetValue(MessageProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(nameof(Message), typeof(string), typeof(ConfirmationDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
public string ApproveButtonTitle
|
||||
{
|
||||
get { return (string)GetValue(ApproveButtonTitleProperty); }
|
||||
set { SetValue(ApproveButtonTitleProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty ApproveButtonTitleProperty = DependencyProperty.Register(nameof(ApproveButtonTitle), typeof(string), typeof(ConfirmationDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
#endregion
|
||||
|
||||
private bool _isApproved;
|
||||
public ConfirmationDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public async Task<bool> ShowDialogAsync(string title, string message, string approveButtonTitle)
|
||||
{
|
||||
_completionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
DialogTitle = title;
|
||||
Message = message;
|
||||
ApproveButtonTitle = approveButtonTitle;
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
ShowAsync();
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
return await _completionSource.Task;
|
||||
}
|
||||
|
||||
private void DialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args)
|
||||
{
|
||||
_completionSource.TrySetResult(_isApproved);
|
||||
}
|
||||
|
||||
private void ApproveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
_isApproved = true;
|
||||
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
_isApproved = false;
|
||||
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
24
Wino.Mail/Dialogs/CustomMessageDialogInformationContainer.cs
Normal file
24
Wino.Mail/Dialogs/CustomMessageDialogInformationContainer.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Dialogs
|
||||
{
|
||||
public partial class CustomMessageDialogInformationContainer : ObservableObject
|
||||
{
|
||||
[ObservableProperty]
|
||||
private bool isDontAskChecked;
|
||||
|
||||
public CustomMessageDialogInformationContainer(string title, string description, WinoCustomMessageDialogIcon icon, bool isDontAskAgainEnabled)
|
||||
{
|
||||
Title = title;
|
||||
Description = description;
|
||||
Icon = icon;
|
||||
IsDontAskAgainEnabled = isDontAskAgainEnabled;
|
||||
}
|
||||
|
||||
public string Title { get; }
|
||||
public string Description { get; }
|
||||
public WinoCustomMessageDialogIcon Icon { get; }
|
||||
public bool IsDontAskAgainEnabled { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.StoreRatingDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Wino.Dialogs"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_RateWino}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_No}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="RateClicked"
|
||||
Title="{x:Bind domain:Translator.StoreRatingDialog_Title}"
|
||||
Style="{StaticResource WinoDialogStyle}">
|
||||
|
||||
<Grid>
|
||||
<StackPanel Spacing="6">
|
||||
<TextBlock Text="{x:Bind domain:Translator.StoreRatingDialog_MessageFirstLine}" />
|
||||
<TextBlock Text="{x:Bind domain:Translator.StoreRatingDialog_MessageSecondLine}" />
|
||||
<CheckBox IsChecked="{x:Bind DontAskAgain, Mode=TwoWay}" Content="{x:Bind domain:Translator.Dialog_DontAskAgain}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -1,21 +0,0 @@
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Dialogs
|
||||
{
|
||||
public sealed partial class StoreRatingDialog : ContentDialog, IStoreRatingDialog
|
||||
{
|
||||
public bool DontAskAgain { get; set; }
|
||||
public bool RateWinoClicked { get; set; }
|
||||
|
||||
public StoreRatingDialog()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void RateClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
RateWinoClicked = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.WinoMessageDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{x:Bind DialogTitle, Mode=OneWay}"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
HorizontalContentAlignment="Stretch"
|
||||
VerticalContentAlignment="Stretch"
|
||||
CloseButtonText="{x:Bind domain:Translator.Buttons_Close}"
|
||||
DefaultButton="Close"
|
||||
Closed="DialogClosed"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">250</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">900</x:Double>
|
||||
<x:Double x:Key="ContentDialogMinHeight">200</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxHeight">756</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<TextBlock Text="{x:Bind Message, Mode=OneWay}" TextWrapping="Wrap" />
|
||||
</ContentDialog>
|
||||
@@ -1,60 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
|
||||
namespace Wino.Dialogs
|
||||
{
|
||||
public sealed partial class WinoMessageDialog : ContentDialog
|
||||
{
|
||||
private TaskCompletionSource<bool> _completionSource;
|
||||
|
||||
#region Dependency Properties
|
||||
|
||||
public string DialogTitle
|
||||
{
|
||||
get { return (string)GetValue(DialogTitleProperty); }
|
||||
set { SetValue(DialogTitleProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty DialogTitleProperty = DependencyProperty.Register(nameof(DialogTitle), typeof(string), typeof(ConfirmationDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
public string Message
|
||||
{
|
||||
get { return (string)GetValue(MessageProperty); }
|
||||
set { SetValue(MessageProperty, value); }
|
||||
}
|
||||
|
||||
public static readonly DependencyProperty MessageProperty = DependencyProperty.Register(nameof(Message), typeof(string), typeof(ConfirmationDialog), new PropertyMetadata(string.Empty));
|
||||
|
||||
#endregion
|
||||
|
||||
public WinoMessageDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public async Task<bool> ShowDialogAsync(string title, string message)
|
||||
{
|
||||
_completionSource = new TaskCompletionSource<bool>();
|
||||
|
||||
DialogTitle = title;
|
||||
Message = message;
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
ShowAsync();
|
||||
#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
|
||||
return await _completionSource.Task;
|
||||
}
|
||||
|
||||
private void ApproveClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void DialogClosed(ContentDialog sender, ContentDialogClosedEventArgs args)
|
||||
{
|
||||
_completionSource.TrySetResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
38
Wino.Mail/Selectors/CustomWinoMessageDialogIconSelector.cs
Normal file
38
Wino.Mail/Selectors/CustomWinoMessageDialogIconSelector.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
|
||||
namespace Wino.Selectors
|
||||
{
|
||||
public class CustomWinoMessageDialogIconSelector : DataTemplateSelector
|
||||
{
|
||||
public DataTemplate InfoIconTemplate { get; set; }
|
||||
public DataTemplate WarningIconTemplate { get; set; }
|
||||
public DataTemplate QuestionIconTemplate { get; set; }
|
||||
public DataTemplate ErrorIconTemplate { get; set; }
|
||||
|
||||
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
|
||||
{
|
||||
if (item == null) return null;
|
||||
|
||||
if (item is WinoCustomMessageDialogIcon icon)
|
||||
{
|
||||
switch (icon)
|
||||
{
|
||||
case WinoCustomMessageDialogIcon.Information:
|
||||
return InfoIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Warning:
|
||||
return WarningIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Error:
|
||||
return ErrorIconTemplate;
|
||||
case WinoCustomMessageDialogIcon.Question:
|
||||
return QuestionIconTemplate;
|
||||
default:
|
||||
throw new Exception("Unknown custom message dialog icon.");
|
||||
}
|
||||
}
|
||||
return base.SelectTemplateCore(item, container);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using Microsoft.Toolkit.Uwp.Helpers;
|
||||
using Serilog;
|
||||
using Windows.Storage;
|
||||
using Windows.Storage.Pickers;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities;
|
||||
@@ -18,9 +19,9 @@ using Wino.Core.Domain.Models.Folders;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Core.UWP.Extensions;
|
||||
using Wino.Dialogs;
|
||||
using Wino.Messaging.Client.Accounts;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
using Wino.Messaging.Server;
|
||||
using Wino.Messaging.UI;
|
||||
|
||||
namespace Wino.Services
|
||||
{
|
||||
@@ -29,26 +30,21 @@ namespace Wino.Services
|
||||
private SemaphoreSlim _presentationSemaphore = new SemaphoreSlim(1);
|
||||
|
||||
private readonly IThemeService _themeService;
|
||||
private readonly IConfigurationService _configurationService;
|
||||
|
||||
public DialogService(IThemeService themeService)
|
||||
public DialogService(IThemeService themeService, IConfigurationService configurationService)
|
||||
{
|
||||
_themeService = themeService;
|
||||
_configurationService = configurationService;
|
||||
}
|
||||
|
||||
public void ShowNotSupportedMessage()
|
||||
{
|
||||
InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle, Translator.Info_UnsupportedFunctionalityDescription, InfoBarMessageType.Error);
|
||||
}
|
||||
=> InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle,
|
||||
Translator.Info_UnsupportedFunctionalityDescription,
|
||||
InfoBarMessageType.Error);
|
||||
|
||||
public async Task ShowMessageAsync(string message, string title)
|
||||
{
|
||||
var dialog = new WinoMessageDialog()
|
||||
{
|
||||
RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentation(() => dialog.ShowDialogAsync(title, message));
|
||||
}
|
||||
public Task ShowMessageAsync(string message, string title, WinoCustomMessageDialogIcon icon = WinoCustomMessageDialogIcon.Information)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, message, Translator.Buttons_Close, icon);
|
||||
|
||||
/// <summary>
|
||||
/// Waits for PopupRoot to be available before presenting the dialog and returns the result after presentation.
|
||||
@@ -75,40 +71,8 @@ namespace Wino.Services
|
||||
return ContentDialogResult.None;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Waits for PopupRoot to be available before executing the given Task that returns customized result.
|
||||
/// </summary>
|
||||
/// <param name="executionTask">Task that presents the dialog and returns result.</param>
|
||||
/// <returns>Dialog result from the custom dialog.</returns>
|
||||
private async Task<bool> HandleDialogPresentation(Func<Task<bool>> executionTask)
|
||||
{
|
||||
await _presentationSemaphore.WaitAsync();
|
||||
|
||||
try
|
||||
{
|
||||
return await executionTask();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex, "Handling dialog service failed.");
|
||||
}
|
||||
finally
|
||||
{
|
||||
_presentationSemaphore.Release();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public async Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle)
|
||||
{
|
||||
var dialog = new ConfirmationDialog()
|
||||
{
|
||||
RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
return await HandleDialogPresentation(() => dialog.ShowDialogAsync(title, question, confirmationButtonTitle));
|
||||
}
|
||||
public Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle)
|
||||
=> ShowWinoCustomMessageDialogAsync(title, question, confirmationButtonTitle, WinoCustomMessageDialogIcon.Question, Translator.Buttons_Cancel, string.Empty);
|
||||
|
||||
public async Task<AccountCreationDialogResult> ShowNewAccountMailProviderDialogAsync(List<IProviderDetail> availableProviders)
|
||||
{
|
||||
@@ -204,18 +168,6 @@ namespace Wino.Services
|
||||
return editAccountDialog.IsSaved ? editAccountDialog.Account : null;
|
||||
}
|
||||
|
||||
public async Task<IStoreRatingDialog> ShowRatingDialogAsync()
|
||||
{
|
||||
var storeDialog = new StoreRatingDialog()
|
||||
{
|
||||
RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(storeDialog);
|
||||
|
||||
return storeDialog;
|
||||
}
|
||||
|
||||
public async Task<ICreateAccountAliasDialog> ShowCreateAccountAliasDialogAsync()
|
||||
{
|
||||
var createAccountAliasDialog = new CreateAccountAliasDialog()
|
||||
@@ -245,24 +197,18 @@ namespace Wino.Services
|
||||
|
||||
if (configuration != null)
|
||||
{
|
||||
var updatedAccount = await folderService.UpdateSystemFolderConfigurationAsync(accountId, configuration);
|
||||
InfoBarMessage(Translator.SystemFolderConfigSetupSuccess_Title, Translator.SystemFolderConfigSetupSuccess_Message, InfoBarMessageType.Success);
|
||||
|
||||
// Update account menu item and force re-synchronization.
|
||||
WeakReferenceMessenger.Default.Send(new AccountUpdatedMessage(updatedAccount));
|
||||
WeakReferenceMessenger.Default.Send(new AccountFolderConfigurationUpdated(accountId));
|
||||
|
||||
var options = new SynchronizationOptions()
|
||||
{
|
||||
AccountId = updatedAccount.Id,
|
||||
AccountId = accountId,
|
||||
Type = SynchronizationType.Full,
|
||||
};
|
||||
|
||||
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
|
||||
}
|
||||
|
||||
if (configuration != null)
|
||||
{
|
||||
InfoBarMessage(Translator.SystemFolderConfigSetupSuccess_Title, Translator.SystemFolderConfigSetupSuccess_Message, InfoBarMessageType.Success);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -331,7 +277,12 @@ namespace Wino.Services
|
||||
return await file.ReadBytesAsync();
|
||||
}
|
||||
|
||||
public Task<bool> ShowHardDeleteConfirmationAsync() => ShowConfirmationDialogAsync(Translator.DialogMessage_HardDeleteConfirmationMessage, Translator.DialogMessage_HardDeleteConfirmationTitle, Translator.Buttons_Yes);
|
||||
public Task<bool> ShowHardDeleteConfirmationAsync()
|
||||
=> ShowWinoCustomMessageDialogAsync(Translator.DialogMessage_HardDeleteConfirmationMessage,
|
||||
Translator.DialogMessage_HardDeleteConfirmationTitle,
|
||||
Translator.Buttons_Yes,
|
||||
WinoCustomMessageDialogIcon.Warning,
|
||||
Translator.Buttons_No);
|
||||
|
||||
public async Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts)
|
||||
{
|
||||
@@ -377,5 +328,48 @@ namespace Wino.Services
|
||||
|
||||
await HandleDialogPresentationAsync(accountReorderDialog);
|
||||
}
|
||||
|
||||
public async Task<bool> ShowWinoCustomMessageDialogAsync(string title,
|
||||
string description,
|
||||
string approveButtonText,
|
||||
WinoCustomMessageDialogIcon? icon,
|
||||
string cancelButtonText = "",
|
||||
string dontAskAgainConfigurationKey = "")
|
||||
|
||||
{
|
||||
// This config key has been marked as don't ask again already.
|
||||
// Return immidiate result without presenting the dialog.
|
||||
|
||||
bool isDontAskEnabled = !string.IsNullOrEmpty(dontAskAgainConfigurationKey);
|
||||
|
||||
if (isDontAskEnabled && _configurationService.Get(dontAskAgainConfigurationKey, false)) return false;
|
||||
|
||||
var informationContainer = new CustomMessageDialogInformationContainer(title, description, icon.Value, isDontAskEnabled);
|
||||
|
||||
var dialog = new ContentDialog
|
||||
{
|
||||
Style = (Style)App.Current.Resources["WinoDialogStyle"],
|
||||
RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme(),
|
||||
DefaultButton = ContentDialogButton.Primary,
|
||||
PrimaryButtonText = approveButtonText,
|
||||
ContentTemplate = (DataTemplate)App.Current.Resources["CustomWinoContentDialogContentTemplate"],
|
||||
Content = informationContainer
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(cancelButtonText))
|
||||
{
|
||||
dialog.SecondaryButtonText = cancelButtonText;
|
||||
}
|
||||
|
||||
var dialogResult = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
// Mark this key to not ask again if user checked the checkbox.
|
||||
if (informationContainer.IsDontAskChecked)
|
||||
{
|
||||
_configurationService.Set(dontAskAgainConfigurationKey, true);
|
||||
}
|
||||
|
||||
return dialogResult == ContentDialogResult.Primary;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
89
Wino.Mail/Styles/CustomMessageDialogStyles.xaml
Normal file
89
Wino.Mail/Styles/CustomMessageDialogStyles.xaml
Normal file
@@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:local="using:Wino.Styles"
|
||||
x:Class="Wino.Styles.CustomMessageDialogStyles"
|
||||
xmlns:dialogs="using:Wino.Dialogs"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
xmlns:selectors="using:Wino.Selectors">
|
||||
|
||||
<!-- Icon templates -->
|
||||
<DataTemplate x:Key="WinoCustomMessageDialogInformationIconTemplate">
|
||||
<Path
|
||||
Fill="#0f80d7"
|
||||
Data="F1 M 0 9.375 C 0 8.509115 0.110677 7.677409 0.332031 6.879883 C 0.553385 6.082357 0.867513 5.335287 1.274414 4.638672 C 1.681315 3.942059 2.169596 3.30892 2.739258 2.739258 C 3.308919 2.169598 3.942057 1.681316 4.638672 1.274414 C 5.335286 0.867514 6.082356 0.553387 6.879883 0.332031 C 7.677409 0.110678 8.509114 0 9.375 0 C 10.240885 0 11.072591 0.110678 11.870117 0.332031 C 12.667643 0.553387 13.414713 0.867514 14.111328 1.274414 C 14.807942 1.681316 15.44108 2.169598 16.010742 2.739258 C 16.580402 3.30892 17.068684 3.942059 17.475586 4.638672 C 17.882486 5.335287 18.196613 6.082357 18.417969 6.879883 C 18.639322 7.677409 18.75 8.509115 18.75 9.375 C 18.75 10.240886 18.637695 11.072592 18.413086 11.870117 C 18.188477 12.667644 17.872721 13.413086 17.46582 14.106445 C 17.058918 14.799805 16.570637 15.431315 16.000977 16.000977 C 15.431314 16.570639 14.799804 17.05892 14.106445 17.46582 C 13.413085 17.872721 12.666015 18.188477 11.865234 18.413086 C 11.064453 18.637695 10.234375 18.75 9.375 18.75 C 8.509114 18.75 7.675781 18.639322 6.875 18.417969 C 6.074219 18.196615 5.327148 17.882486 4.633789 17.475586 C 3.94043 17.068686 3.308919 16.580404 2.739258 16.010742 C 2.169596 15.441081 1.681315 14.80957 1.274414 14.116211 C 0.867513 13.422852 0.553385 12.675781 0.332031 11.875 C 0.110677 11.074219 0 10.240886 0 9.375 Z M 17.5 9.375 C 17.5 8.626303 17.403971 7.905273 17.211914 7.211914 C 17.019855 6.518556 16.746418 5.87077 16.391602 5.268555 C 16.036783 4.666342 15.613606 4.119467 15.12207 3.62793 C 14.630533 3.136395 14.083658 2.713217 13.481445 2.358398 C 12.879231 2.003582 12.231445 1.730145 11.538086 1.538086 C 10.844727 1.346029 10.123697 1.25 9.375 1.25 C 8.626302 1.25 7.905273 1.346029 7.211914 1.538086 C 6.518555 1.730145 5.870768 2.003582 5.268555 2.358398 C 4.666341 2.713217 4.119466 3.136395 3.62793 3.62793 C 3.136393 4.119467 2.713216 4.666342 2.358398 5.268555 C 2.003581 5.87077 1.730143 6.518556 1.538086 7.211914 C 1.346029 7.905273 1.25 8.626303 1.25 9.375 C 1.25 10.123698 1.346029 10.844727 1.538086 11.538086 C 1.730143 12.231445 2.001953 12.879232 2.353516 13.481445 C 2.705078 14.083659 3.128255 14.632162 3.623047 15.126953 C 4.117838 15.621745 4.666341 16.044922 5.268555 16.396484 C 5.870768 16.748047 6.518555 17.019857 7.211914 17.211914 C 7.905273 17.403971 8.626302 17.5 9.375 17.5 C 10.123697 17.5 10.844727 17.403971 11.538086 17.211914 C 12.231445 17.019857 12.879231 16.748047 13.481445 16.396484 C 14.083658 16.044922 14.63216 15.621745 15.126953 15.126953 C 15.621744 14.632162 16.044922 14.083659 16.396484 13.481445 C 16.748047 12.879232 17.019855 12.231445 17.211914 11.538086 C 17.403971 10.844727 17.5 10.123698 17.5 9.375 Z M 8.4375 5.625 C 8.4375 5.364584 8.528646 5.14323 8.710938 4.960938 C 8.893229 4.778646 9.114583 4.6875 9.375 4.6875 C 9.635416 4.6875 9.856771 4.778646 10.039062 4.960938 C 10.221354 5.14323 10.3125 5.364584 10.3125 5.625 C 10.3125 5.885417 10.221354 6.106771 10.039062 6.289062 C 9.856771 6.471354 9.635416 6.5625 9.375 6.5625 C 9.114583 6.5625 8.893229 6.471354 8.710938 6.289062 C 8.528646 6.106771 8.4375 5.885417 8.4375 5.625 Z M 8.75 13.125 L 8.75 8.125 C 8.75 7.95573 8.811849 7.809246 8.935547 7.685547 C 9.059244 7.56185 9.205729 7.5 9.375 7.5 C 9.544271 7.5 9.690755 7.56185 9.814453 7.685547 C 9.93815 7.809246 10 7.95573 10 8.125 L 10 13.125 C 10 13.294271 9.93815 13.440756 9.814453 13.564453 C 9.690755 13.688151 9.544271 13.75 9.375 13.75 C 9.205729 13.75 9.059244 13.688151 8.935547 13.564453 C 8.811849 13.440756 8.75 13.294271 8.75 13.125 Z "
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="WinoCustomMessageDialogQuestionIconTemplate">
|
||||
<Path
|
||||
Fill="#0984e3"
|
||||
Data="M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8m8-6.5a6.5 6.5 0 1 0 0 13a6.5 6.5 0 0 0 0-13M6.92 6.085h.001a.749.749 0 1 1-1.342-.67c.169-.339.436-.701.849-.977C6.845 4.16 7.369 4 8 4a2.76 2.76 0 0 1 1.637.525c.503.377.863.965.863 1.725c0 .448-.115.83-.329 1.15c-.205.307-.47.513-.692.662c-.109.072-.22.138-.313.195l-.006.004a6 6 0 0 0-.26.16a1 1 0 0 0-.276.245a.75.75 0 0 1-1.248-.832c.184-.264.42-.489.692-.661q.154-.1.313-.195l.007-.004c.1-.061.182-.11.258-.161a1 1 0 0 0 .277-.245C8.96 6.514 9 6.427 9 6.25a.61.61 0 0 0-.262-.525A1.27 1.27 0 0 0 8 5.5c-.369 0-.595.09-.74.187a1 1 0 0 0-.34.398M9 11a1 1 0 1 1-2 0a1 1 0 0 1 2 0"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="WinoCustomMessageDialogWarningIconTemplate">
|
||||
<Path
|
||||
Fill="#fdcb6e"
|
||||
Data="F1 M 2.021484 18.769531 C 1.767578 18.769531 1.52832 18.720703 1.303711 18.623047 C 1.079102 18.525391 0.880534 18.391928 0.708008 18.222656 C 0.535482 18.053385 0.398763 17.856445 0.297852 17.631836 C 0.19694 17.407227 0.146484 17.167969 0.146484 16.914062 C 0.146484 16.614584 0.211589 16.328125 0.341797 16.054688 L 7.695312 1.347656 C 7.851562 1.035156 8.082682 0.784506 8.388672 0.595703 C 8.694661 0.406902 9.023438 0.3125 9.375 0.3125 C 9.726562 0.3125 10.055338 0.406902 10.361328 0.595703 C 10.667317 0.784506 10.898438 1.035156 11.054688 1.347656 L 18.408203 16.054688 C 18.53841 16.328125 18.603516 16.614584 18.603516 16.914062 C 18.603516 17.167969 18.553059 17.407227 18.452148 17.631836 C 18.351236 17.856445 18.216145 18.053385 18.046875 18.222656 C 17.877604 18.391928 17.679035 18.525391 17.451172 18.623047 C 17.223307 18.720703 16.982422 18.769531 16.728516 18.769531 Z M 16.728516 17.519531 C 16.884766 17.519531 17.027994 17.460938 17.158203 17.34375 C 17.28841 17.226562 17.353516 17.086588 17.353516 16.923828 C 17.353516 16.806641 17.330729 16.702475 17.285156 16.611328 L 9.931641 1.904297 C 9.879557 1.793621 9.80306 1.708984 9.702148 1.650391 C 9.601236 1.591797 9.492188 1.5625 9.375 1.5625 C 9.257812 1.5625 9.148763 1.593426 9.047852 1.655273 C 8.946939 1.717123 8.870442 1.800131 8.818359 1.904297 L 1.464844 16.611328 C 1.419271 16.702475 1.396484 16.803387 1.396484 16.914062 C 1.396484 17.083334 1.459961 17.226562 1.586914 17.34375 C 1.713867 17.460938 1.858724 17.519531 2.021484 17.519531 Z M 8.75 11.875 L 8.75 6.875 C 8.75 6.705729 8.811849 6.559245 8.935547 6.435547 C 9.059244 6.31185 9.205729 6.25 9.375 6.25 C 9.544271 6.25 9.690755 6.31185 9.814453 6.435547 C 9.93815 6.559245 10 6.705729 10 6.875 L 10 11.875 C 10 12.044271 9.93815 12.190756 9.814453 12.314453 C 9.690755 12.438151 9.544271 12.5 9.375 12.5 C 9.205729 12.5 9.059244 12.438151 8.935547 12.314453 C 8.811849 12.190756 8.75 12.044271 8.75 11.875 Z M 8.4375 14.375 C 8.4375 14.114584 8.528646 13.893229 8.710938 13.710938 C 8.893229 13.528646 9.114583 13.4375 9.375 13.4375 C 9.635416 13.4375 9.856771 13.528646 10.039062 13.710938 C 10.221354 13.893229 10.3125 14.114584 10.3125 14.375 C 10.3125 14.635417 10.221354 14.856771 10.039062 15.039062 C 9.856771 15.221354 9.635416 15.3125 9.375 15.3125 C 9.114583 15.3125 8.893229 15.221354 8.710938 15.039062 C 8.528646 14.856771 8.4375 14.635417 8.4375 14.375 Z "
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center" />
|
||||
</DataTemplate>
|
||||
<DataTemplate x:Key="WinoCustomMessageDialogErrorIconTemplate">
|
||||
<Path
|
||||
Fill="#d63031"
|
||||
Data="F1 M 18.75 9.375 C 18.75 10.240886 18.639322 11.072592 18.417969 11.870117 C 18.196613 12.667644 17.882486 13.414714 17.475586 14.111328 C 17.068684 14.807943 16.580402 15.441081 16.010742 16.010742 C 15.44108 16.580404 14.807942 17.068686 14.111328 17.475586 C 13.414713 17.882486 12.667643 18.196615 11.870117 18.417969 C 11.072591 18.639322 10.240885 18.75 9.375 18.75 C 8.509114 18.75 7.675781 18.639322 6.875 18.417969 C 6.074219 18.196615 5.327148 17.882486 4.633789 17.475586 C 3.94043 17.068686 3.308919 16.580404 2.739258 16.010742 C 2.169596 15.441081 1.681315 14.80957 1.274414 14.116211 C 0.867513 13.422852 0.553385 12.675781 0.332031 11.875 C 0.110677 11.074219 0 10.240886 0 9.375 C 0 8.509115 0.110677 7.677409 0.332031 6.879883 C 0.553385 6.082357 0.867513 5.335287 1.274414 4.638672 C 1.681315 3.942059 2.169596 3.30892 2.739258 2.739258 C 3.308919 2.169598 3.942057 1.681316 4.638672 1.274414 C 5.335286 0.867514 6.082356 0.553387 6.879883 0.332031 C 7.677409 0.110678 8.509114 0 9.375 0 C 10.234375 0 11.062825 0.112305 11.860352 0.336914 C 12.657877 0.561523 13.404947 0.877279 14.101562 1.28418 C 14.798176 1.691082 15.431314 2.179363 16.000977 2.749023 C 16.570637 3.318686 17.058918 3.951824 17.46582 4.648438 C 17.872721 5.345053 18.188477 6.092123 18.413086 6.889648 C 18.637695 7.687175 18.75 8.515625 18.75 9.375 Z M 17.5 9.375 C 17.5 8.626303 17.403971 7.905273 17.211914 7.211914 C 17.019855 6.518556 16.746418 5.87077 16.391602 5.268555 C 16.036783 4.666342 15.613606 4.119467 15.12207 3.62793 C 14.630533 3.136395 14.083658 2.713217 13.481445 2.358398 C 12.879231 2.003582 12.231445 1.730145 11.538086 1.538086 C 10.844727 1.346029 10.123697 1.25 9.375 1.25 C 8.626302 1.25 7.905273 1.346029 7.211914 1.538086 C 6.518555 1.730145 5.870768 2.003582 5.268555 2.358398 C 4.666341 2.713217 4.119466 3.136395 3.62793 3.62793 C 3.136393 4.119467 2.713216 4.666342 2.358398 5.268555 C 2.003581 5.87077 1.730143 6.518556 1.538086 7.211914 C 1.346029 7.905273 1.25 8.626303 1.25 9.375 C 1.25 10.123698 1.346029 10.844727 1.538086 11.538086 C 1.730143 12.231445 2.001953 12.879232 2.353516 13.481445 C 2.705078 14.083659 3.128255 14.632162 3.623047 15.126953 C 4.117838 15.621745 4.666341 16.044922 5.268555 16.396484 C 5.870768 16.748047 6.518555 17.019857 7.211914 17.211914 C 7.905273 17.403971 8.626302 17.5 9.375 17.5 C 10.123697 17.5 10.844727 17.403971 11.538086 17.211914 C 12.231445 17.019857 12.879231 16.74642 13.481445 16.391602 C 14.083658 16.036783 14.630533 15.613607 15.12207 15.12207 C 15.613606 14.630534 16.036783 14.083659 16.391602 13.481445 C 16.746418 12.879232 17.019855 12.231445 17.211914 11.538086 C 17.403971 10.844727 17.5 10.123698 17.5 9.375 Z M 13.4375 5.9375 C 13.4375 6.106771 13.37565 6.253256 13.251953 6.376953 L 10.253906 9.375 L 13.251953 12.373047 C 13.37565 12.496745 13.4375 12.643229 13.4375 12.8125 C 13.4375 12.981771 13.37565 13.128256 13.251953 13.251953 C 13.128254 13.375651 12.98177 13.4375 12.8125 13.4375 C 12.643229 13.4375 12.496744 13.375651 12.373047 13.251953 L 9.375 10.253906 L 6.376953 13.251953 C 6.253255 13.375651 6.106771 13.4375 5.9375 13.4375 C 5.768229 13.4375 5.621745 13.375651 5.498047 13.251953 C 5.374349 13.128256 5.3125 12.981771 5.3125 12.8125 C 5.3125 12.643229 5.374349 12.496745 5.498047 12.373047 L 8.496094 9.375 L 5.498047 6.376953 C 5.374349 6.253256 5.3125 6.106771 5.3125 5.9375 C 5.3125 5.768229 5.374349 5.621745 5.498047 5.498047 C 5.621745 5.37435 5.768229 5.3125 5.9375 5.3125 C 6.106771 5.3125 6.253255 5.37435 6.376953 5.498047 L 9.375 8.496094 L 12.373047 5.498047 C 12.496744 5.37435 12.643229 5.3125 12.8125 5.3125 C 12.98177 5.3125 13.128254 5.37435 13.251953 5.498047 C 13.37565 5.621745 13.4375 5.768229 13.4375 5.9375 Z "
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center" />
|
||||
</DataTemplate>
|
||||
|
||||
<selectors:CustomWinoMessageDialogIconSelector
|
||||
x:Key="CustomWinoMessageDialogIconSelector"
|
||||
InfoIconTemplate="{StaticResource WinoCustomMessageDialogInformationIconTemplate}"
|
||||
QuestionIconTemplate="{StaticResource WinoCustomMessageDialogQuestionIconTemplate}"
|
||||
WarningIconTemplate="{StaticResource WinoCustomMessageDialogWarningIconTemplate}"
|
||||
ErrorIconTemplate="{StaticResource WinoCustomMessageDialogErrorIconTemplate}" />
|
||||
|
||||
<DataTemplate x:DataType="dialogs:CustomMessageDialogInformationContainer" x:Key="CustomWinoContentDialogTitleTemplate">
|
||||
<Grid />
|
||||
</DataTemplate>
|
||||
|
||||
<DataTemplate x:DataType="dialogs:CustomMessageDialogInformationContainer" x:Key="CustomWinoContentDialogContentTemplate">
|
||||
<Grid RowSpacing="12">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Title -->
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<Viewbox Width="28" HorizontalAlignment="Left">
|
||||
<ContentControl ContentTemplateSelector="{StaticResource CustomWinoMessageDialogIconSelector}" Content="{x:Bind Icon}" />
|
||||
</Viewbox>
|
||||
|
||||
<TextBlock
|
||||
Text="{x:Bind Title}"
|
||||
HorizontalAlignment="Center"
|
||||
Style="{StaticResource SubtitleTextBlockStyle}"
|
||||
VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
|
||||
<!-- Description -->
|
||||
<TextBlock
|
||||
Text="{x:Bind Description}"
|
||||
Grid.Row="1"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
|
||||
<CheckBox
|
||||
Grid.Row="2"
|
||||
Content="{x:Bind domain:Translator.Dialog_DontAskAgain}"
|
||||
Visibility="{x:Bind IsDontAskAgainEnabled}"
|
||||
IsChecked="{x:Bind IsDontAskChecked, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
|
||||
</ResourceDictionary>
|
||||
12
Wino.Mail/Styles/CustomMessageDialogStyles.xaml.cs
Normal file
12
Wino.Mail/Styles/CustomMessageDialogStyles.xaml.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace Wino.Styles
|
||||
{
|
||||
partial class CustomMessageDialogStyles : ResourceDictionary
|
||||
{
|
||||
public CustomMessageDialogStyles()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -39,8 +39,7 @@ namespace Wino.Views
|
||||
public sealed partial class ComposePage : ComposePageAbstract,
|
||||
IRecipient<NavigationPaneModeChanged>,
|
||||
IRecipient<CreateNewComposeMailRequested>,
|
||||
IRecipient<ApplicationThemeChanged>,
|
||||
IRecipient<KillChromiumRequested>
|
||||
IRecipient<ApplicationThemeChanged>
|
||||
{
|
||||
public bool IsComposerDarkMode
|
||||
{
|
||||
@@ -240,7 +239,7 @@ namespace Wino.Views
|
||||
{
|
||||
var attachmentViewModel = await file.ToAttachmentViewModelAsync();
|
||||
|
||||
await ViewModel.IncludeAttachmentAsync(attachmentViewModel);
|
||||
ViewModel.IncludedAttachments.Add(attachmentViewModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -415,7 +414,6 @@ namespace Wino.Views
|
||||
return await ExecuteScriptFunctionAsync("initializeJodit", fonts, composerFont, composerFontSize, readerFont, readerFontSize);
|
||||
}
|
||||
|
||||
|
||||
private void DisposeWebView2()
|
||||
{
|
||||
if (Chromium == null) return;
|
||||
@@ -692,8 +690,12 @@ namespace Wino.Views
|
||||
}
|
||||
}
|
||||
|
||||
public void Receive(KillChromiumRequested message)
|
||||
protected override async void OnNavigatingFrom(NavigatingCancelEventArgs e)
|
||||
{
|
||||
base.OnNavigatingFrom(e);
|
||||
|
||||
await ViewModel.UpdateMimeChangesAsync();
|
||||
|
||||
DisposeDisposables();
|
||||
DisposeWebView2();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,16 @@ namespace Wino.Views
|
||||
|
||||
var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuSettings, WinoPage.SettingOptionsPage);
|
||||
PageHistory.Add(new BreadcrumbNavigationItemViewModel(initialRequest, true));
|
||||
|
||||
if (e.Parameter is WinoPage parameterPage)
|
||||
{
|
||||
switch (parameterPage)
|
||||
{
|
||||
case WinoPage.AppPreferencesPage:
|
||||
WeakReferenceMessenger.Default.Send(new BreadcrumbNavigationRequested(Translator.SettingsAppPreferences_Title, WinoPage.AppPreferencesPage));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnLanguageChanged()
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<LangVersion>8.0</LangVersion>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
<!-- UWP WAM Authentication on Xbox needs this. -->
|
||||
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||
<!-- UWP WAM Authentication on Xbox needs this. -->
|
||||
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
@@ -89,7 +89,7 @@
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
||||
<Use64BitCompiler>true</Use64BitCompiler>
|
||||
<ShortcutGenericAnalysis>true</ShortcutGenericAnalysis>
|
||||
<ShortcutGenericAnalysis>true</ShortcutGenericAnalysis>
|
||||
<OutOfProcPDB>true</OutOfProcPDB>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
@@ -119,7 +119,6 @@
|
||||
<Use64BitCompiler>true</Use64BitCompiler>
|
||||
<OutOfProcPDB>true</OutOfProcPDB>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AdaptiveTriggerLibrary">
|
||||
<Version>1.2.2</Version>
|
||||
@@ -230,6 +229,7 @@
|
||||
<DependentUpon>AccountReorderDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\BaseAccountCreationDialog.cs" />
|
||||
<Compile Include="Dialogs\CustomMessageDialogInformationContainer.cs" />
|
||||
<Compile Include="Dialogs\CustomThemeBuilderDialog.xaml.cs">
|
||||
<DependentUpon>CustomThemeBuilderDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -245,15 +245,9 @@
|
||||
<Compile Include="Dialogs\CreateAccountAliasDialog.xaml.cs">
|
||||
<DependentUpon>CreateAccountAliasDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\StoreRatingDialog.xaml.cs">
|
||||
<DependentUpon>StoreRatingDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\SystemFolderConfigurationDialog.xaml.cs">
|
||||
<DependentUpon>SystemFolderConfigurationDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\WinoMessageDialog.xaml.cs">
|
||||
<DependentUpon>WinoMessageDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\TextInputDialog.xaml.cs">
|
||||
<DependentUpon>TextInputDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -290,9 +284,6 @@
|
||||
<Compile Include="Controls\WinoInfoBar.cs" />
|
||||
<Compile Include="Controls\WinoNavigationViewItem.cs" />
|
||||
<Compile Include="Converters\ReverseBooleanToVisibilityConverter.cs" />
|
||||
<Compile Include="Dialogs\ConfirmationDialog.xaml.cs">
|
||||
<DependentUpon>ConfirmationDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Dialogs\NewAccountDialog.xaml.cs">
|
||||
<DependentUpon>NewAccountDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
@@ -302,6 +293,7 @@
|
||||
<Compile Include="Selectors\AccountProviderViewModelTemplateSelector.cs" />
|
||||
<Compile Include="Selectors\AccountReorderTemplateSelector.cs" />
|
||||
<Compile Include="Selectors\AppThemePreviewTemplateSelector.cs" />
|
||||
<Compile Include="Selectors\CustomWinoMessageDialogIconSelector.cs" />
|
||||
<Compile Include="Selectors\FileAttachmentTypeSelector.cs" />
|
||||
<Compile Include="Selectors\MailItemContainerStyleSelector.cs" />
|
||||
<Compile Include="Selectors\MailItemDisplayModePreviewTemplateSelector.cs" />
|
||||
@@ -314,6 +306,9 @@
|
||||
<Compile Include="Styles\CommandBarItems.xaml.cs">
|
||||
<DependentUpon>CommandBarItems.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Styles\CustomMessageDialogStyles.xaml.cs">
|
||||
<DependentUpon>CustomMessageDialogStyles.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Views\Abstract\AboutPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\AccountDetailsPageAbstract.cs" />
|
||||
<Compile Include="Views\Abstract\AccountManagementPageAbstract.cs" />
|
||||
@@ -494,26 +489,14 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Dialogs\StoreRatingDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Dialogs\SystemFolderConfigurationDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Dialogs\WinoMessageDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Dialogs\TextInputDialog.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Include="Dialogs\ConfirmationDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Dialogs\NewAccountDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
@@ -530,6 +513,10 @@
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Styles\CustomMessageDialogStyles.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
<Page Include="Styles\FontIcons.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -814,4 +801,4 @@
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
</Project>
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Wino.Messaging.Client.Accounts
|
||||
{
|
||||
/// <summary>
|
||||
/// When account's special folder configuration is updated.
|
||||
/// </summary>
|
||||
public record AccountFolderConfigurationUpdated(Guid AccountId);
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Wino.Messaging.Client.Mails
|
||||
{
|
||||
/// <summary>
|
||||
/// Terminates all chromum instances.
|
||||
/// </summary>
|
||||
public record KillChromiumRequested;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Wino.Messaging.Client.Navigation
|
||||
{
|
||||
/// <summary>
|
||||
/// Navigates user to Settings -> App Preferences.
|
||||
/// </summary>
|
||||
public record NavigateAppPreferencesRequested;
|
||||
}
|
||||
9
Wino.Messages/Server/TerminateServerRequested.cs
Normal file
9
Wino.Messages/Server/TerminateServerRequested.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
|
||||
namespace Wino.Messaging.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// This message is sent to server to kill itself when UWP app is terminating.
|
||||
/// </summary>
|
||||
public record TerminateServerRequested : IClientMessage;
|
||||
}
|
||||
@@ -110,5 +110,6 @@
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<rescap:Capability Name="runFullTrust" />
|
||||
<rescap:Capability Name="confirmAppClose" />
|
||||
</Capabilities>
|
||||
</Package>
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace Wino.Server.Core
|
||||
nameof(ProtocolAuthorizationCallbackReceived) => App.Current.Services.GetService<ProtocolAuthActivationHandler>(),
|
||||
nameof(SynchronizationExistenceCheckRequest) => App.Current.Services.GetService<SyncExistenceHandler>(),
|
||||
nameof(ServerTerminationModeChanged) => App.Current.Services.GetService<ServerTerminationModeHandler>(),
|
||||
nameof(TerminateServerRequested) => App.Current.Services.GetService<TerminateServerRequestHandler>(),
|
||||
_ => throw new Exception($"Server handler for {typeName} is not registered."),
|
||||
};
|
||||
}
|
||||
@@ -36,6 +37,7 @@ namespace Wino.Server.Core
|
||||
serviceCollection.AddTransient<ProtocolAuthActivationHandler>();
|
||||
serviceCollection.AddTransient<SyncExistenceHandler>();
|
||||
serviceCollection.AddTransient<ServerTerminationModeHandler>();
|
||||
serviceCollection.AddTransient<TerminateServerRequestHandler>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
Wino.Server/MessageHandlers/TerminateServerRequestHandler.cs
Normal file
26
Wino.Server/MessageHandlers/TerminateServerRequestHandler.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Serilog;
|
||||
using Wino.Core.Domain.Models.Server;
|
||||
using Wino.Messaging.Server;
|
||||
using Wino.Server.Core;
|
||||
|
||||
namespace Wino.Server.MessageHandlers
|
||||
{
|
||||
public class TerminateServerRequestHandler : ServerMessageHandler<TerminateServerRequested, bool>
|
||||
{
|
||||
public override WinoServerResponse<bool> FailureDefaultResponse(Exception ex) => WinoServerResponse<bool>.CreateErrorResponse(ex.Message);
|
||||
|
||||
protected override Task<WinoServerResponse<bool>> HandleAsync(TerminateServerRequested message, CancellationToken cancellationToken = default)
|
||||
{
|
||||
// This handler is only doing the logging right now.
|
||||
// Client will always expect success response.
|
||||
// Server will be terminated in the server context once the client gets the response.
|
||||
|
||||
Log.Information("Terminate server is requested by client. Killing server.");
|
||||
|
||||
return Task.FromResult(WinoServerResponse<bool>.CreateSuccessResponse(true));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Diagnostics;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using Serilog;
|
||||
using Windows.ApplicationModel;
|
||||
@@ -308,12 +309,28 @@ namespace Wino.Server
|
||||
case nameof(ServerTerminationModeChanged):
|
||||
await ExecuteServerMessageSafeAsync(args, JsonSerializer.Deserialize<ServerTerminationModeChanged>(messageJson, _jsonSerializerOptions));
|
||||
break;
|
||||
|
||||
case nameof(TerminateServerRequested):
|
||||
await ExecuteServerMessageSafeAsync(args, JsonSerializer.Deserialize<TerminateServerRequested>(messageJson, _jsonSerializerOptions));
|
||||
|
||||
KillServer();
|
||||
break;
|
||||
default:
|
||||
Debug.WriteLine($"Missing handler for {typeName} in the server. Check ServerContext.cs - HandleServerMessageAsync.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void KillServer()
|
||||
{
|
||||
DisposeConnection();
|
||||
|
||||
Application.Current.Dispatcher.Invoke(() =>
|
||||
{
|
||||
Application.Current.Shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Executes ServerMessage coming from the UWP.
|
||||
/// These requests are awaited and expected to return a response.
|
||||
|
||||
Reference in New Issue
Block a user