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<byte[]> PickWindowsFileContentAsync(params object[] typeFilters);
|
||||||
Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle);
|
Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle);
|
||||||
Task<bool> ShowHardDeleteConfirmationAsync();
|
Task<bool> ShowHardDeleteConfirmationAsync();
|
||||||
Task<IStoreRatingDialog> ShowRatingDialogAsync();
|
|
||||||
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
|
Task HandleSystemFolderConfigurationDialogAsync(Guid accountId, IFolderService folderService);
|
||||||
Task<bool> ShowCustomThemeBuilderDialogAsync();
|
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);
|
||||||
void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action);
|
void InfoBarMessage(string title, string message, InfoBarMessageType messageType, string actionButtonText, Action action);
|
||||||
|
|
||||||
@@ -53,6 +52,17 @@ namespace Wino.Core.Domain.Interfaces
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>Signature information. Null if canceled.</returns>
|
/// <returns>Signature information. Null if canceled.</returns>
|
||||||
Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature signatureModel = null);
|
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<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",
|
"AccountSettingsDialog_AccountNamePlaceholder": "eg. John Doe",
|
||||||
"AddHyperlink": "Add",
|
"AddHyperlink": "Add",
|
||||||
"AutoDiscoveryProgressMessage": "Searching for mail settings...",
|
"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_AdvancedConfiguration": "Advanced Configuration",
|
||||||
"BasicIMAPSetupDialog_CredentialLocalMessage": "Your credentials will only be stored locally on your computer.",
|
"BasicIMAPSetupDialog_CredentialLocalMessage": "Your credentials will only be stored locally on your computer.",
|
||||||
"BasicIMAPSetupDialog_Description": "Some accounts require additional steps to sign in",
|
"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_UnsubscribeConfirmationGoToWebsiteMessage": "To stop getting messages from {0}, go to their website to unsubscribe.",
|
||||||
"DialogMessage_UnsubscribeConfirmationGoToWebsiteConfirmButton": "Go to website",
|
"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_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",
|
"Dialog_DontAskAgain": "Don't ask again",
|
||||||
"CreateAccountAliasDialog_Title": "Create Account Alias",
|
"CreateAccountAliasDialog_Title": "Create Account Alias",
|
||||||
"CreateAccountAliasDialog_Description": "Make sure your outgoing server allows sending mails from this 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>
|
/// </summary>
|
||||||
public static string AutoDiscoveryProgressMessage => Resources.GetTranslatedString(@"AutoDiscoveryProgressMessage");
|
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>
|
/// <summary>
|
||||||
/// Advanced Configuration
|
/// Advanced Configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -548,6 +583,21 @@ namespace Wino.Core.Domain
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string DialogMessage_UnsubscribeConfirmationMailtoMessage => Resources.GetTranslatedString(@"DialogMessage_UnsubscribeConfirmationMailtoMessage");
|
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>
|
/// <summary>
|
||||||
/// Don't ask again
|
/// Don't ask again
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommunityToolkit.WinUI.Notifications;
|
using CommunityToolkit.WinUI.Notifications;
|
||||||
|
using Serilog;
|
||||||
using Windows.Data.Xml.Dom;
|
using Windows.Data.Xml.Dom;
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using Wino.Core.Domain;
|
using Wino.Core.Domain;
|
||||||
@@ -38,83 +39,90 @@ namespace Wino.Core.UWP.Services
|
|||||||
{
|
{
|
||||||
var mailCount = downloadedMailItems.Count();
|
var mailCount = downloadedMailItems.Count();
|
||||||
|
|
||||||
// If there are more than 3 mails, just display 1 general toast.
|
try
|
||||||
if (mailCount > 3)
|
|
||||||
{
|
{
|
||||||
var builder = new ToastContentBuilder();
|
// If there are more than 3 mails, just display 1 general toast.
|
||||||
builder.SetToastScenario(ToastScenario.Default);
|
if (mailCount > 3)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
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();
|
var builder = new ToastContentBuilder();
|
||||||
builder.SetToastScenario(ToastScenario.Default);
|
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.AddButton(GetDismissButton());
|
||||||
|
|
||||||
builder.Show();
|
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()
|
public async Task UpdateTaskbarIconBadgeAsync()
|
||||||
{
|
{
|
||||||
int totalUnreadCount = 0;
|
int totalUnreadCount = 0;
|
||||||
var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication();
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
var badgeUpdater = BadgeUpdateManager.CreateBadgeUpdaterForApplication();
|
||||||
var accounts = await _accountService.GetAccountsAsync();
|
var accounts = await _accountService.GetAccountsAsync();
|
||||||
|
|
||||||
foreach (var account in accounts)
|
foreach (var account in accounts)
|
||||||
@@ -178,11 +186,9 @@ namespace Wino.Core.UWP.Services
|
|||||||
else
|
else
|
||||||
badgeUpdater.Clear();
|
badgeUpdater.Clear();
|
||||||
}
|
}
|
||||||
catch (System.Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// TODO: Log exceptions.
|
Log.Error(ex, "Error while updating taskbar badge.");
|
||||||
|
|
||||||
badgeUpdater.Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ namespace Wino.Core.UWP.Services
|
|||||||
_dialogService = dialogService;
|
_dialogService = dialogService;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetRated()
|
|
||||||
=> _configurationService.SetRoaming(RatedStorageKey, true);
|
|
||||||
|
|
||||||
private bool IsAskingThresholdExceeded()
|
private bool IsAskingThresholdExceeded()
|
||||||
{
|
{
|
||||||
var latestAskedDate = _configurationService.Get(LatestAskedKey, DateTime.MinValue);
|
var latestAskedDate = _configurationService.Get(LatestAskedKey, DateTime.MinValue);
|
||||||
@@ -62,15 +59,14 @@ namespace Wino.Core.UWP.Services
|
|||||||
{
|
{
|
||||||
if (!IsAskingThresholdExceeded()) return;
|
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)
|
if (isRateWinoApproved)
|
||||||
return;
|
|
||||||
|
|
||||||
if (ratingDialogResult.DontAskAgain)
|
|
||||||
SetRated();
|
|
||||||
|
|
||||||
if (ratingDialogResult.RateWinoClicked)
|
|
||||||
{
|
{
|
||||||
// In case of failure of this call, we will navigate users to Store page directly.
|
// 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
|
else
|
||||||
_dialogService.InfoBarMessage(Translator.Info_ReviewSuccessTitle, Translator.Info_ReviewNewMessage, Domain.Enums.InfoBarMessageType.Success);
|
_dialogService.InfoBarMessage(Translator.Info_ReviewSuccessTitle, Translator.Info_ReviewNewMessage, Domain.Enums.InfoBarMessageType.Success);
|
||||||
|
|
||||||
SetRated();
|
_configurationService.Set(RatedStorageKey, true);
|
||||||
break;
|
break;
|
||||||
case StoreRateAndReviewStatus.CanceledByUser:
|
case StoreRateAndReviewStatus.CanceledByUser:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -151,15 +151,12 @@ namespace Wino.Core.MenuItems
|
|||||||
return accountMenuItem;
|
return accountMenuItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ReplaceFoldersAsync(IEnumerable<IMenuItem> folders)
|
public void ReplaceFolders(IEnumerable<IMenuItem> folders)
|
||||||
{
|
{
|
||||||
await _dispatcher.ExecuteOnUIThread(() =>
|
ClearFolderAreaMenuItems();
|
||||||
{
|
|
||||||
ClearFolderAreaMenuItems();
|
|
||||||
|
|
||||||
Items.Add(new SeperatorItem());
|
Items.Add(new SeperatorItem());
|
||||||
AddRange(folders);
|
AddRange(folders);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -194,9 +191,11 @@ namespace Wino.Core.MenuItems
|
|||||||
{
|
{
|
||||||
item.IsExpanded = false;
|
item.IsExpanded = false;
|
||||||
item.IsSelected = false;
|
item.IsSelected = false;
|
||||||
|
|
||||||
|
Remove(item);
|
||||||
});
|
});
|
||||||
|
|
||||||
RemoveRange(itemsToRemove);
|
// RemoveRange(itemsToRemove);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ namespace Wino.Core.Services
|
|||||||
|
|
||||||
public class DatabaseService : IDatabaseService
|
public class DatabaseService : IDatabaseService
|
||||||
{
|
{
|
||||||
private const string DatabaseName = "Wino172.db";
|
private const string DatabaseName = "Wino180.db";
|
||||||
|
|
||||||
private bool _isInitialized = false;
|
private bool _isInitialized = false;
|
||||||
private readonly IApplicationConfiguration _folderConfiguration;
|
private readonly IApplicationConfiguration _folderConfiguration;
|
||||||
|
|||||||
@@ -387,11 +387,6 @@ namespace Wino.Core.Services
|
|||||||
if (configuration == null)
|
if (configuration == null)
|
||||||
throw new ArgumentNullException(nameof(configuration));
|
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.
|
// Update system folders for this account.
|
||||||
|
|
||||||
await Task.WhenAll(UpdateSystemFolderInternalAsync(configuration.SentFolder, SpecialFolderType.Sent),
|
await Task.WhenAll(UpdateSystemFolderInternalAsync(configuration.SentFolder, SpecialFolderType.Sent),
|
||||||
@@ -400,9 +395,8 @@ namespace Wino.Core.Services
|
|||||||
UpdateSystemFolderInternalAsync(configuration.TrashFolder, SpecialFolderType.Deleted),
|
UpdateSystemFolderInternalAsync(configuration.TrashFolder, SpecialFolderType.Deleted),
|
||||||
UpdateSystemFolderInternalAsync(configuration.ArchiveFolder, SpecialFolderType.Archive));
|
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)
|
private Task UpdateSystemFolderInternalAsync(MailItemFolder folder, SpecialFolderType assignedSpecialFolderType)
|
||||||
@@ -492,13 +486,6 @@ namespace Wino.Core.Services
|
|||||||
return;
|
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);
|
_logger.Debug("Updating folder {FolderName}", folder.Id, folder.FolderName);
|
||||||
|
|
||||||
await Connection.UpdateAsync(folder).ConfigureAwait(false);
|
await Connection.UpdateAsync(folder).ConfigureAwait(false);
|
||||||
|
|||||||
@@ -785,6 +785,7 @@ namespace Wino.Core.Synchronizers
|
|||||||
EventHandler<MessageFlagsChangedEventArgs> MessageFlagsChangedHandler = async (s, e) =>
|
EventHandler<MessageFlagsChangedEventArgs> MessageFlagsChangedHandler = async (s, e) =>
|
||||||
{
|
{
|
||||||
if (imapFolder == null) return;
|
if (imapFolder == null) return;
|
||||||
|
if (e.UniqueId == null) return;
|
||||||
|
|
||||||
var localMailCopyId = MailkitClientExtensions.CreateUid(folder.Id, e.UniqueId.Value.Id);
|
var localMailCopyId = MailkitClientExtensions.CreateUid(folder.Id, e.UniqueId.Value.Id);
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
{
|
{
|
||||||
// Discord disclaimer message about server.
|
// Discord disclaimer message about server.
|
||||||
if (stringUrl == DiscordChannelUrl)
|
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));
|
await _nativeAppService.LaunchUriAsync(new Uri(stringUrl));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,14 +98,18 @@ namespace Wino.Mail.ViewModels
|
|||||||
// Check existence.
|
// Check existence.
|
||||||
if (AccountAliases.Any(a => a.AliasAddress == newAlias.AliasAddress))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate all addresses.
|
// Validate all addresses.
|
||||||
if (!EmailValidator.Validate(newAlias.AliasAddress) || (!string.IsNullOrEmpty(newAlias.ReplyToAddress) && !EmailValidator.Validate(newAlias.ReplyToAddress)))
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,14 +129,18 @@ namespace Wino.Mail.ViewModels
|
|||||||
// Primary aliases can't be deleted.
|
// Primary aliases can't be deleted.
|
||||||
if (alias.IsPrimary)
|
if (alias.IsPrimary)
|
||||||
{
|
{
|
||||||
await DialogService.ShowMessageAsync(Translator.Info_CantDeletePrimaryAliasMessage, Translator.GeneralTitle_Warning);
|
await DialogService.ShowMessageAsync(Translator.Info_CantDeletePrimaryAliasMessage,
|
||||||
|
Translator.GeneralTitle_Warning,
|
||||||
|
WinoCustomMessageDialogIcon.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Root aliases can't be deleted.
|
// Root aliases can't be deleted.
|
||||||
if (alias.IsRootAlias)
|
if (alias.IsRootAlias)
|
||||||
{
|
{
|
||||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_CantDeleteRootAliasTitle, Translator.DialogMessage_CantDeleteRootAliasMessage);
|
await DialogService.ShowMessageAsync(Translator.DialogMessage_CantDeleteRootAliasTitle,
|
||||||
|
Translator.DialogMessage_CantDeleteRootAliasMessage,
|
||||||
|
WinoCustomMessageDialogIcon.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
IRecipient<MergedInboxRenamed>,
|
IRecipient<MergedInboxRenamed>,
|
||||||
IRecipient<LanguageChanged>,
|
IRecipient<LanguageChanged>,
|
||||||
IRecipient<AccountMenuItemsReordered>,
|
IRecipient<AccountMenuItemsReordered>,
|
||||||
IRecipient<AccountSynchronizationProgressUpdatedMessage>
|
IRecipient<AccountSynchronizationProgressUpdatedMessage>,
|
||||||
|
IRecipient<NavigateAppPreferencesRequested>,
|
||||||
|
IRecipient<AccountFolderConfigurationUpdated>
|
||||||
{
|
{
|
||||||
#region Menu Items
|
#region Menu Items
|
||||||
|
|
||||||
@@ -59,12 +61,16 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
private const string IsActivateStartupLaunchAskedKey = nameof(IsActivateStartupLaunchAskedKey);
|
||||||
|
|
||||||
public IStatePersistanceService StatePersistenceService { get; }
|
public IStatePersistanceService StatePersistenceService { get; }
|
||||||
public IWinoServerConnectionManager ServerConnectionManager { get; }
|
public IWinoServerConnectionManager ServerConnectionManager { get; }
|
||||||
public IPreferencesService PreferencesService { get; }
|
public IPreferencesService PreferencesService { get; }
|
||||||
public IWinoNavigationService NavigationService { get; }
|
public IWinoNavigationService NavigationService { get; }
|
||||||
|
|
||||||
private readonly IFolderService _folderService;
|
private readonly IFolderService _folderService;
|
||||||
|
private readonly IConfigurationService _configurationService;
|
||||||
|
private readonly IStartupBehaviorService _startupBehaviorService;
|
||||||
private readonly IAccountService _accountService;
|
private readonly IAccountService _accountService;
|
||||||
private readonly IContextMenuItemService _contextMenuItemService;
|
private readonly IContextMenuItemService _contextMenuItemService;
|
||||||
private readonly IStoreRatingService _storeRatingService;
|
private readonly IStoreRatingService _storeRatingService;
|
||||||
@@ -98,7 +104,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
IWinoRequestDelegator winoRequestDelegator,
|
IWinoRequestDelegator winoRequestDelegator,
|
||||||
IFolderService folderService,
|
IFolderService folderService,
|
||||||
IStatePersistanceService statePersistanceService,
|
IStatePersistanceService statePersistanceService,
|
||||||
IWinoServerConnectionManager serverConnectionManager) : base(dialogService)
|
IWinoServerConnectionManager serverConnectionManager,
|
||||||
|
IConfigurationService configurationService,
|
||||||
|
IStartupBehaviorService startupBehaviorService) : base(dialogService)
|
||||||
{
|
{
|
||||||
StatePersistenceService = statePersistanceService;
|
StatePersistenceService = statePersistanceService;
|
||||||
ServerConnectionManager = serverConnectionManager;
|
ServerConnectionManager = serverConnectionManager;
|
||||||
@@ -115,6 +123,8 @@ namespace Wino.Mail.ViewModels
|
|||||||
PreferencesService = preferencesService;
|
PreferencesService = preferencesService;
|
||||||
NavigationService = navigationService;
|
NavigationService = navigationService;
|
||||||
|
|
||||||
|
_configurationService = configurationService;
|
||||||
|
_startupBehaviorService = startupBehaviorService;
|
||||||
_backgroundTaskService = backgroundTaskService;
|
_backgroundTaskService = backgroundTaskService;
|
||||||
_mimeFileService = mimeFileService;
|
_mimeFileService = mimeFileService;
|
||||||
_nativeAppService = nativeAppService;
|
_nativeAppService = nativeAppService;
|
||||||
@@ -229,16 +239,56 @@ namespace Wino.Mail.ViewModels
|
|||||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||||
{
|
{
|
||||||
base.OnNavigatedTo(mode, parameters);
|
base.OnNavigatedTo(mode, parameters);
|
||||||
|
|
||||||
await CreateFooterItemsAsync();
|
await CreateFooterItemsAsync();
|
||||||
|
|
||||||
await RecreateMenuItemsAsync();
|
await RecreateMenuItemsAsync();
|
||||||
await ProcessLaunchOptionsAsync();
|
await ProcessLaunchOptionsAsync();
|
||||||
|
|
||||||
await ForceAllAccountSynchronizationsAsync();
|
await ForceAllAccountSynchronizationsAsync();
|
||||||
|
await MakeSureEnableStartupLaunchAsync();
|
||||||
ConfigureBackgroundTasks();
|
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()
|
private void ConfigureBackgroundTasks()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@@ -527,7 +577,7 @@ namespace Wino.Mail.ViewModels
|
|||||||
StatePersistenceService.CoreWindowTitle = "Wino Mail";
|
StatePersistenceService.CoreWindowTitle = "Wino Mail";
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task MenuItemInvokedOrSelectedAsync(IMenuItem clickedMenuItem)
|
public async Task MenuItemInvokedOrSelectedAsync(IMenuItem clickedMenuItem, object parameter = null)
|
||||||
{
|
{
|
||||||
if (clickedMenuItem == null) return;
|
if (clickedMenuItem == null) return;
|
||||||
|
|
||||||
@@ -561,11 +611,11 @@ namespace Wino.Mail.ViewModels
|
|||||||
}
|
}
|
||||||
else if (clickedMenuItem is SettingsItem)
|
else if (clickedMenuItem is SettingsItem)
|
||||||
{
|
{
|
||||||
NavigationService.Navigate(WinoPage.SettingsPage);
|
NavigationService.Navigate(WinoPage.SettingsPage, parameter, NavigationReferenceFrame.ShellFrame, NavigationTransitionType.None);
|
||||||
}
|
}
|
||||||
else if (clickedMenuItem is ManageAccountsMenuItem)
|
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)
|
else if (clickedMenuItem is IAccountMenuItem clickedAccountMenuItem && latestSelectedAccountMenuItem != clickedAccountMenuItem)
|
||||||
{
|
{
|
||||||
@@ -582,6 +632,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(false);
|
await MenuItems.SetAccountMenuItemEnabledStatusAsync(false);
|
||||||
|
|
||||||
|
// Load account folder structure and replace the visible folders.
|
||||||
|
var folders = await _folderService.GetAccountFoldersForDisplayAsync(clickedBaseAccountMenuItem);
|
||||||
|
|
||||||
await ExecuteUIThread(() =>
|
await ExecuteUIThread(() =>
|
||||||
{
|
{
|
||||||
clickedBaseAccountMenuItem.IsEnabled = false;
|
clickedBaseAccountMenuItem.IsEnabled = false;
|
||||||
@@ -594,12 +647,10 @@ namespace Wino.Mail.ViewModels
|
|||||||
clickedBaseAccountMenuItem.IsSelected = true;
|
clickedBaseAccountMenuItem.IsSelected = true;
|
||||||
|
|
||||||
latestSelectedAccountMenuItem = clickedBaseAccountMenuItem;
|
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 UpdateUnreadItemCountAsync();
|
||||||
await MenuItems.SetAccountMenuItemEnabledStatusAsync(true);
|
await MenuItems.SetAccountMenuItemEnabledStatusAsync(true);
|
||||||
|
|
||||||
@@ -721,7 +772,19 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
if (!accounts.Any())
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,7 +913,9 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
if (!accounts.Any())
|
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)
|
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)
|
public async void Receive(MergedInboxRenamed message)
|
||||||
{
|
{
|
||||||
var mergedInboxMenuItem = MenuItems.FirstOrDefault(a => a.EntityId == message.MergedInboxId);
|
var mergedInboxMenuItem = MenuItems.FirstOrDefault(a => a.EntityId == message.MergedInboxId);
|
||||||
@@ -961,5 +1036,10 @@ namespace Wino.Mail.ViewModels
|
|||||||
|
|
||||||
await ExecuteUIThread(() => { accountMenuItem.SynchronizationProgress = message.Progress; });
|
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())
|
if (!ToItems.Any())
|
||||||
{
|
{
|
||||||
await DialogService.ShowMessageAsync(Translator.DialogMessage_ComposerMissingRecipientMessage, Translator.DialogMessage_ComposerValidationFailedTitle);
|
await DialogService.ShowMessageAsync(Translator.DialogMessage_ComposerMissingRecipientMessage,
|
||||||
|
Translator.DialogMessage_ComposerValidationFailedTitle,
|
||||||
|
WinoCustomMessageDialogIcon.Warning);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,17 +204,7 @@ namespace Wino.Mail.ViewModels
|
|||||||
await _worker.ExecuteAsync(draftSendPreparationRequest);
|
await _worker.ExecuteAsync(draftSendPreparationRequest);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task IncludeAttachmentAsync(MailAttachmentViewModel viewModel)
|
public async Task UpdateMimeChangesAsync()
|
||||||
{
|
|
||||||
//if (bodyBuilder == null) return;
|
|
||||||
|
|
||||||
//bodyBuilder.Attachments.Add(viewModel.FileName, new MemoryStream(viewModel.Content));
|
|
||||||
|
|
||||||
//LoadAttachments();
|
|
||||||
IncludedAttachments.Add(viewModel);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task UpdateMimeChangesAsync()
|
|
||||||
{
|
{
|
||||||
if (isUpdatingMimeBlocked || CurrentMimeMessage == null || ComposingAccount == null || CurrentMailDraftItem == null) return;
|
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);
|
base.OnNavigatedFrom(mode, parameters);
|
||||||
|
|
||||||
await UpdateMimeChangesAsync().ConfigureAwait(false);
|
/// Do not put any code here.
|
||||||
|
/// Make sure to use Page's OnNavigatedTo instead.
|
||||||
Messenger.Send(new KillChromiumRequested());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
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.
|
/// When the rendering page is active, but new item is requested to be rendered.
|
||||||
/// To not trigger navigation again and re-use existing Chromium.
|
/// To not trigger navigation again and re-use existing Chromium.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class NewMailItemRenderingRequestedEvent
|
/// <param name="MailItemViewModel"></param>
|
||||||
{
|
public record NewMailItemRenderingRequestedEvent(MailItemViewModel MailItemViewModel);
|
||||||
public NewMailItemRenderingRequestedEvent(MailItemViewModel mailItemViewModel)
|
|
||||||
{
|
|
||||||
MailItemViewModel = mailItemViewModel;
|
|
||||||
}
|
|
||||||
|
|
||||||
public MailItemViewModel MailItemViewModel { get; }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:controls="using:Wino.Controls"
|
xmlns:controls="using:Wino.Controls"
|
||||||
xmlns:selectors="using:Wino.Selectors"
|
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>
|
<Application.Resources>
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
@@ -18,6 +20,7 @@
|
|||||||
<ResourceDictionary Source="/Styles/CommandBarItems.xaml" />
|
<ResourceDictionary Source="/Styles/CommandBarItems.xaml" />
|
||||||
<ResourceDictionary Source="/Styles/ItemContainerStyles.xaml" />
|
<ResourceDictionary Source="/Styles/ItemContainerStyles.xaml" />
|
||||||
<ResourceDictionary Source="/Styles/WinoInfoBar.xaml" />
|
<ResourceDictionary Source="/Styles/WinoInfoBar.xaml" />
|
||||||
|
<styles:CustomMessageDialogStyles />
|
||||||
|
|
||||||
<ResourceDictionary>
|
<ResourceDictionary>
|
||||||
|
|
||||||
@@ -166,6 +169,10 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</Style>
|
</Style>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Attachment Icon Templates -->
|
||||||
|
|
||||||
<DataTemplate x:Key="NoneTemplate">
|
<DataTemplate x:Key="NoneTemplate">
|
||||||
<Image Source="/Assets/FileTypes/type_none.png" />
|
<Image Source="/Assets/FileTypes/type_none.png" />
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ using Windows.Foundation.Metadata;
|
|||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.System.Profile;
|
using Windows.System.Profile;
|
||||||
using Windows.UI;
|
using Windows.UI;
|
||||||
|
using Windows.UI.Core.Preview;
|
||||||
using Windows.UI.Notifications;
|
using Windows.UI.Notifications;
|
||||||
using Windows.UI.ViewManagement;
|
using Windows.UI.ViewManagement;
|
||||||
using Windows.UI.Xaml;
|
using Windows.UI.Xaml;
|
||||||
@@ -38,6 +39,7 @@ using Wino.Core.UWP;
|
|||||||
using Wino.Core.UWP.Services;
|
using Wino.Core.UWP.Services;
|
||||||
using Wino.Mail.ViewModels;
|
using Wino.Mail.ViewModels;
|
||||||
using Wino.Messaging.Client.Connection;
|
using Wino.Messaging.Client.Connection;
|
||||||
|
using Wino.Messaging.Client.Navigation;
|
||||||
using Wino.Messaging.Server;
|
using Wino.Messaging.Server;
|
||||||
using Wino.Services;
|
using Wino.Services;
|
||||||
|
|
||||||
@@ -107,6 +109,78 @@ namespace Wino
|
|||||||
WeakReferenceMessenger.Default.Register(this);
|
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)
|
private async void OnResuming(object sender, object e)
|
||||||
{
|
{
|
||||||
// App Service connection was lost on suspension.
|
// App Service connection was lost on suspension.
|
||||||
@@ -233,6 +307,7 @@ namespace Wino
|
|||||||
LogActivation("Window is created.");
|
LogActivation("Window is created.");
|
||||||
|
|
||||||
ConfigureTitleBar();
|
ConfigureTitleBar();
|
||||||
|
TryRegisterAppCloseChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override async void OnLaunched(LaunchActivatedEventArgs args)
|
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)
|
protected override async void OnFileActivated(FileActivatedEventArgs args)
|
||||||
{
|
{
|
||||||
base.OnFileActivated(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 Serilog;
|
||||||
using Windows.Storage;
|
using Windows.Storage;
|
||||||
using Windows.Storage.Pickers;
|
using Windows.Storage.Pickers;
|
||||||
|
using Windows.UI.Xaml;
|
||||||
using Windows.UI.Xaml.Controls;
|
using Windows.UI.Xaml.Controls;
|
||||||
using Wino.Core.Domain;
|
using Wino.Core.Domain;
|
||||||
using Wino.Core.Domain.Entities;
|
using Wino.Core.Domain.Entities;
|
||||||
@@ -18,9 +19,9 @@ using Wino.Core.Domain.Models.Folders;
|
|||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
using Wino.Core.UWP.Extensions;
|
using Wino.Core.UWP.Extensions;
|
||||||
using Wino.Dialogs;
|
using Wino.Dialogs;
|
||||||
|
using Wino.Messaging.Client.Accounts;
|
||||||
using Wino.Messaging.Client.Shell;
|
using Wino.Messaging.Client.Shell;
|
||||||
using Wino.Messaging.Server;
|
using Wino.Messaging.Server;
|
||||||
using Wino.Messaging.UI;
|
|
||||||
|
|
||||||
namespace Wino.Services
|
namespace Wino.Services
|
||||||
{
|
{
|
||||||
@@ -29,26 +30,21 @@ namespace Wino.Services
|
|||||||
private SemaphoreSlim _presentationSemaphore = new SemaphoreSlim(1);
|
private SemaphoreSlim _presentationSemaphore = new SemaphoreSlim(1);
|
||||||
|
|
||||||
private readonly IThemeService _themeService;
|
private readonly IThemeService _themeService;
|
||||||
|
private readonly IConfigurationService _configurationService;
|
||||||
|
|
||||||
public DialogService(IThemeService themeService)
|
public DialogService(IThemeService themeService, IConfigurationService configurationService)
|
||||||
{
|
{
|
||||||
_themeService = themeService;
|
_themeService = themeService;
|
||||||
|
_configurationService = configurationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ShowNotSupportedMessage()
|
public void ShowNotSupportedMessage()
|
||||||
{
|
=> InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle,
|
||||||
InfoBarMessage(Translator.Info_UnsupportedFunctionalityTitle, Translator.Info_UnsupportedFunctionalityDescription, InfoBarMessageType.Error);
|
Translator.Info_UnsupportedFunctionalityDescription,
|
||||||
}
|
InfoBarMessageType.Error);
|
||||||
|
|
||||||
public async Task ShowMessageAsync(string message, string title)
|
public Task ShowMessageAsync(string message, string title, WinoCustomMessageDialogIcon icon = WinoCustomMessageDialogIcon.Information)
|
||||||
{
|
=> ShowWinoCustomMessageDialogAsync(title, message, Translator.Buttons_Close, icon);
|
||||||
var dialog = new WinoMessageDialog()
|
|
||||||
{
|
|
||||||
RequestedTheme = _themeService.RootTheme.ToWindowsElementTheme()
|
|
||||||
};
|
|
||||||
|
|
||||||
await HandleDialogPresentation(() => dialog.ShowDialogAsync(title, message));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Waits for PopupRoot to be available before presenting the dialog and returns the result after presentation.
|
/// 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;
|
return ContentDialogResult.None;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
public Task<bool> ShowConfirmationDialogAsync(string question, string title, string confirmationButtonTitle)
|
||||||
/// Waits for PopupRoot to be available before executing the given Task that returns customized result.
|
=> ShowWinoCustomMessageDialogAsync(title, question, confirmationButtonTitle, WinoCustomMessageDialogIcon.Question, Translator.Buttons_Cancel, string.Empty);
|
||||||
/// </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 async Task<AccountCreationDialogResult> ShowNewAccountMailProviderDialogAsync(List<IProviderDetail> availableProviders)
|
public async Task<AccountCreationDialogResult> ShowNewAccountMailProviderDialogAsync(List<IProviderDetail> availableProviders)
|
||||||
{
|
{
|
||||||
@@ -204,18 +168,6 @@ namespace Wino.Services
|
|||||||
return editAccountDialog.IsSaved ? editAccountDialog.Account : null;
|
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()
|
public async Task<ICreateAccountAliasDialog> ShowCreateAccountAliasDialogAsync()
|
||||||
{
|
{
|
||||||
var createAccountAliasDialog = new CreateAccountAliasDialog()
|
var createAccountAliasDialog = new CreateAccountAliasDialog()
|
||||||
@@ -245,24 +197,18 @@ namespace Wino.Services
|
|||||||
|
|
||||||
if (configuration != null)
|
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 AccountFolderConfigurationUpdated(accountId));
|
||||||
WeakReferenceMessenger.Default.Send(new AccountUpdatedMessage(updatedAccount));
|
|
||||||
|
|
||||||
var options = new SynchronizationOptions()
|
var options = new SynchronizationOptions()
|
||||||
{
|
{
|
||||||
AccountId = updatedAccount.Id,
|
AccountId = accountId,
|
||||||
Type = SynchronizationType.Full,
|
Type = SynchronizationType.Full,
|
||||||
};
|
};
|
||||||
|
|
||||||
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
|
WeakReferenceMessenger.Default.Send(new NewSynchronizationRequested(options, SynchronizationSource.Client));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (configuration != null)
|
|
||||||
{
|
|
||||||
InfoBarMessage(Translator.SystemFolderConfigSetupSuccess_Title, Translator.SystemFolderConfigSetupSuccess_Message, InfoBarMessageType.Success);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -331,7 +277,12 @@ namespace Wino.Services
|
|||||||
return await file.ReadBytesAsync();
|
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)
|
public async Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts)
|
||||||
{
|
{
|
||||||
@@ -377,5 +328,48 @@ namespace Wino.Services
|
|||||||
|
|
||||||
await HandleDialogPresentationAsync(accountReorderDialog);
|
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,
|
public sealed partial class ComposePage : ComposePageAbstract,
|
||||||
IRecipient<NavigationPaneModeChanged>,
|
IRecipient<NavigationPaneModeChanged>,
|
||||||
IRecipient<CreateNewComposeMailRequested>,
|
IRecipient<CreateNewComposeMailRequested>,
|
||||||
IRecipient<ApplicationThemeChanged>,
|
IRecipient<ApplicationThemeChanged>
|
||||||
IRecipient<KillChromiumRequested>
|
|
||||||
{
|
{
|
||||||
public bool IsComposerDarkMode
|
public bool IsComposerDarkMode
|
||||||
{
|
{
|
||||||
@@ -240,7 +239,7 @@ namespace Wino.Views
|
|||||||
{
|
{
|
||||||
var attachmentViewModel = await file.ToAttachmentViewModelAsync();
|
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);
|
return await ExecuteScriptFunctionAsync("initializeJodit", fonts, composerFont, composerFontSize, readerFont, readerFontSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void DisposeWebView2()
|
private void DisposeWebView2()
|
||||||
{
|
{
|
||||||
if (Chromium == null) return;
|
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();
|
DisposeDisposables();
|
||||||
DisposeWebView2();
|
DisposeWebView2();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,16 @@ namespace Wino.Views
|
|||||||
|
|
||||||
var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuSettings, WinoPage.SettingOptionsPage);
|
var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuSettings, WinoPage.SettingOptionsPage);
|
||||||
PageHistory.Add(new BreadcrumbNavigationItemViewModel(initialRequest, true));
|
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()
|
public override void OnLanguageChanged()
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>8.0</LangVersion>
|
||||||
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
|
||||||
<!-- UWP WAM Authentication on Xbox needs this. -->
|
<!-- UWP WAM Authentication on Xbox needs this. -->
|
||||||
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||||
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
<UseDotNetNativeSharedAssemblyFrameworkPackage>false</UseDotNetNativeSharedAssemblyFrameworkPackage>
|
||||||
<Use64BitCompiler>true</Use64BitCompiler>
|
<Use64BitCompiler>true</Use64BitCompiler>
|
||||||
<ShortcutGenericAnalysis>true</ShortcutGenericAnalysis>
|
<ShortcutGenericAnalysis>true</ShortcutGenericAnalysis>
|
||||||
<OutOfProcPDB>true</OutOfProcPDB>
|
<OutOfProcPDB>true</OutOfProcPDB>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||||
@@ -119,7 +119,6 @@
|
|||||||
<Use64BitCompiler>true</Use64BitCompiler>
|
<Use64BitCompiler>true</Use64BitCompiler>
|
||||||
<OutOfProcPDB>true</OutOfProcPDB>
|
<OutOfProcPDB>true</OutOfProcPDB>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AdaptiveTriggerLibrary">
|
<PackageReference Include="AdaptiveTriggerLibrary">
|
||||||
<Version>1.2.2</Version>
|
<Version>1.2.2</Version>
|
||||||
@@ -230,6 +229,7 @@
|
|||||||
<DependentUpon>AccountReorderDialog.xaml</DependentUpon>
|
<DependentUpon>AccountReorderDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Dialogs\BaseAccountCreationDialog.cs" />
|
<Compile Include="Dialogs\BaseAccountCreationDialog.cs" />
|
||||||
|
<Compile Include="Dialogs\CustomMessageDialogInformationContainer.cs" />
|
||||||
<Compile Include="Dialogs\CustomThemeBuilderDialog.xaml.cs">
|
<Compile Include="Dialogs\CustomThemeBuilderDialog.xaml.cs">
|
||||||
<DependentUpon>CustomThemeBuilderDialog.xaml</DependentUpon>
|
<DependentUpon>CustomThemeBuilderDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -245,15 +245,9 @@
|
|||||||
<Compile Include="Dialogs\CreateAccountAliasDialog.xaml.cs">
|
<Compile Include="Dialogs\CreateAccountAliasDialog.xaml.cs">
|
||||||
<DependentUpon>CreateAccountAliasDialog.xaml</DependentUpon>
|
<DependentUpon>CreateAccountAliasDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Dialogs\StoreRatingDialog.xaml.cs">
|
|
||||||
<DependentUpon>StoreRatingDialog.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Dialogs\SystemFolderConfigurationDialog.xaml.cs">
|
<Compile Include="Dialogs\SystemFolderConfigurationDialog.xaml.cs">
|
||||||
<DependentUpon>SystemFolderConfigurationDialog.xaml</DependentUpon>
|
<DependentUpon>SystemFolderConfigurationDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Dialogs\WinoMessageDialog.xaml.cs">
|
|
||||||
<DependentUpon>WinoMessageDialog.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Dialogs\TextInputDialog.xaml.cs">
|
<Compile Include="Dialogs\TextInputDialog.xaml.cs">
|
||||||
<DependentUpon>TextInputDialog.xaml</DependentUpon>
|
<DependentUpon>TextInputDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -290,9 +284,6 @@
|
|||||||
<Compile Include="Controls\WinoInfoBar.cs" />
|
<Compile Include="Controls\WinoInfoBar.cs" />
|
||||||
<Compile Include="Controls\WinoNavigationViewItem.cs" />
|
<Compile Include="Controls\WinoNavigationViewItem.cs" />
|
||||||
<Compile Include="Converters\ReverseBooleanToVisibilityConverter.cs" />
|
<Compile Include="Converters\ReverseBooleanToVisibilityConverter.cs" />
|
||||||
<Compile Include="Dialogs\ConfirmationDialog.xaml.cs">
|
|
||||||
<DependentUpon>ConfirmationDialog.xaml</DependentUpon>
|
|
||||||
</Compile>
|
|
||||||
<Compile Include="Dialogs\NewAccountDialog.xaml.cs">
|
<Compile Include="Dialogs\NewAccountDialog.xaml.cs">
|
||||||
<DependentUpon>NewAccountDialog.xaml</DependentUpon>
|
<DependentUpon>NewAccountDialog.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
@@ -302,6 +293,7 @@
|
|||||||
<Compile Include="Selectors\AccountProviderViewModelTemplateSelector.cs" />
|
<Compile Include="Selectors\AccountProviderViewModelTemplateSelector.cs" />
|
||||||
<Compile Include="Selectors\AccountReorderTemplateSelector.cs" />
|
<Compile Include="Selectors\AccountReorderTemplateSelector.cs" />
|
||||||
<Compile Include="Selectors\AppThemePreviewTemplateSelector.cs" />
|
<Compile Include="Selectors\AppThemePreviewTemplateSelector.cs" />
|
||||||
|
<Compile Include="Selectors\CustomWinoMessageDialogIconSelector.cs" />
|
||||||
<Compile Include="Selectors\FileAttachmentTypeSelector.cs" />
|
<Compile Include="Selectors\FileAttachmentTypeSelector.cs" />
|
||||||
<Compile Include="Selectors\MailItemContainerStyleSelector.cs" />
|
<Compile Include="Selectors\MailItemContainerStyleSelector.cs" />
|
||||||
<Compile Include="Selectors\MailItemDisplayModePreviewTemplateSelector.cs" />
|
<Compile Include="Selectors\MailItemDisplayModePreviewTemplateSelector.cs" />
|
||||||
@@ -314,6 +306,9 @@
|
|||||||
<Compile Include="Styles\CommandBarItems.xaml.cs">
|
<Compile Include="Styles\CommandBarItems.xaml.cs">
|
||||||
<DependentUpon>CommandBarItems.xaml</DependentUpon>
|
<DependentUpon>CommandBarItems.xaml</DependentUpon>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
<Compile Include="Styles\CustomMessageDialogStyles.xaml.cs">
|
||||||
|
<DependentUpon>CustomMessageDialogStyles.xaml</DependentUpon>
|
||||||
|
</Compile>
|
||||||
<Compile Include="Views\Abstract\AboutPageAbstract.cs" />
|
<Compile Include="Views\Abstract\AboutPageAbstract.cs" />
|
||||||
<Compile Include="Views\Abstract\AccountDetailsPageAbstract.cs" />
|
<Compile Include="Views\Abstract\AccountDetailsPageAbstract.cs" />
|
||||||
<Compile Include="Views\Abstract\AccountManagementPageAbstract.cs" />
|
<Compile Include="Views\Abstract\AccountManagementPageAbstract.cs" />
|
||||||
@@ -494,26 +489,14 @@
|
|||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Dialogs\StoreRatingDialog.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Dialogs\SystemFolderConfigurationDialog.xaml">
|
<Page Include="Dialogs\SystemFolderConfigurationDialog.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Dialogs\WinoMessageDialog.xaml">
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Dialogs\TextInputDialog.xaml">
|
<Page Include="Dialogs\TextInputDialog.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
</Page>
|
</Page>
|
||||||
<Page Include="Dialogs\ConfirmationDialog.xaml">
|
|
||||||
<SubType>Designer</SubType>
|
|
||||||
<Generator>MSBuild:Compile</Generator>
|
|
||||||
</Page>
|
|
||||||
<Page Include="Dialogs\NewAccountDialog.xaml">
|
<Page Include="Dialogs\NewAccountDialog.xaml">
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
@@ -530,6 +513,10 @@
|
|||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
</Page>
|
</Page>
|
||||||
|
<Page Include="Styles\CustomMessageDialogStyles.xaml">
|
||||||
|
<SubType>Designer</SubType>
|
||||||
|
<Generator>MSBuild:Compile</Generator>
|
||||||
|
</Page>
|
||||||
<Page Include="Styles\FontIcons.xaml">
|
<Page Include="Styles\FontIcons.xaml">
|
||||||
<Generator>MSBuild:Compile</Generator>
|
<Generator>MSBuild:Compile</Generator>
|
||||||
<SubType>Designer</SubType>
|
<SubType>Designer</SubType>
|
||||||
@@ -814,4 +801,4 @@
|
|||||||
<Target Name="AfterBuild">
|
<Target Name="AfterBuild">
|
||||||
</Target>
|
</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>
|
<Capabilities>
|
||||||
<Capability Name="internetClient" />
|
<Capability Name="internetClient" />
|
||||||
<rescap:Capability Name="runFullTrust" />
|
<rescap:Capability Name="runFullTrust" />
|
||||||
|
<rescap:Capability Name="confirmAppClose" />
|
||||||
</Capabilities>
|
</Capabilities>
|
||||||
</Package>
|
</Package>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ namespace Wino.Server.Core
|
|||||||
nameof(ProtocolAuthorizationCallbackReceived) => App.Current.Services.GetService<ProtocolAuthActivationHandler>(),
|
nameof(ProtocolAuthorizationCallbackReceived) => App.Current.Services.GetService<ProtocolAuthActivationHandler>(),
|
||||||
nameof(SynchronizationExistenceCheckRequest) => App.Current.Services.GetService<SyncExistenceHandler>(),
|
nameof(SynchronizationExistenceCheckRequest) => App.Current.Services.GetService<SyncExistenceHandler>(),
|
||||||
nameof(ServerTerminationModeChanged) => App.Current.Services.GetService<ServerTerminationModeHandler>(),
|
nameof(ServerTerminationModeChanged) => App.Current.Services.GetService<ServerTerminationModeHandler>(),
|
||||||
|
nameof(TerminateServerRequested) => App.Current.Services.GetService<TerminateServerRequestHandler>(),
|
||||||
_ => throw new Exception($"Server handler for {typeName} is not registered."),
|
_ => throw new Exception($"Server handler for {typeName} is not registered."),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -36,6 +37,7 @@ namespace Wino.Server.Core
|
|||||||
serviceCollection.AddTransient<ProtocolAuthActivationHandler>();
|
serviceCollection.AddTransient<ProtocolAuthActivationHandler>();
|
||||||
serviceCollection.AddTransient<SyncExistenceHandler>();
|
serviceCollection.AddTransient<SyncExistenceHandler>();
|
||||||
serviceCollection.AddTransient<ServerTerminationModeHandler>();
|
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.Diagnostics;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using System.Windows;
|
||||||
using CommunityToolkit.Mvvm.Messaging;
|
using CommunityToolkit.Mvvm.Messaging;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Windows.ApplicationModel;
|
using Windows.ApplicationModel;
|
||||||
@@ -308,12 +309,28 @@ namespace Wino.Server
|
|||||||
case nameof(ServerTerminationModeChanged):
|
case nameof(ServerTerminationModeChanged):
|
||||||
await ExecuteServerMessageSafeAsync(args, JsonSerializer.Deserialize<ServerTerminationModeChanged>(messageJson, _jsonSerializerOptions));
|
await ExecuteServerMessageSafeAsync(args, JsonSerializer.Deserialize<ServerTerminationModeChanged>(messageJson, _jsonSerializerOptions));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case nameof(TerminateServerRequested):
|
||||||
|
await ExecuteServerMessageSafeAsync(args, JsonSerializer.Deserialize<TerminateServerRequested>(messageJson, _jsonSerializerOptions));
|
||||||
|
|
||||||
|
KillServer();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
Debug.WriteLine($"Missing handler for {typeName} in the server. Check ServerContext.cs - HandleServerMessageAsync.");
|
Debug.WriteLine($"Missing handler for {typeName} in the server. Check ServerContext.cs - HandleServerMessageAsync.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void KillServer()
|
||||||
|
{
|
||||||
|
DisposeConnection();
|
||||||
|
|
||||||
|
Application.Current.Dispatcher.Invoke(() =>
|
||||||
|
{
|
||||||
|
Application.Current.Shutdown();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Executes ServerMessage coming from the UWP.
|
/// Executes ServerMessage coming from the UWP.
|
||||||
/// These requests are awaited and expected to return a response.
|
/// These requests are awaited and expected to return a response.
|
||||||
|
|||||||
Reference in New Issue
Block a user