Add account context menu actions
This commit is contained in:
@@ -23,6 +23,7 @@ public enum FolderSynchronizerOperation
|
|||||||
MarkFolderRead,
|
MarkFolderRead,
|
||||||
DeleteFolder,
|
DeleteFolder,
|
||||||
CreateSubFolder,
|
CreateSubFolder,
|
||||||
|
CreateRootFolder,
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum CalendarSynchronizerOperation
|
public enum CalendarSynchronizerOperation
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public interface IMailShellClient : IShellClient
|
|||||||
Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true);
|
Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true);
|
||||||
Task PerformFolderOperationAsync(FolderOperation operation, IBaseFolderMenuItem folderMenuItem);
|
Task PerformFolderOperationAsync(FolderOperation operation, IBaseFolderMenuItem folderMenuItem);
|
||||||
Task PerformMoveOperationAsync(IEnumerable<MailCopy> items, IBaseFolderMenuItem targetFolderMenuItem);
|
Task PerformMoveOperationAsync(IEnumerable<MailCopy> items, IBaseFolderMenuItem targetFolderMenuItem);
|
||||||
|
Task CreateRootFolderAsync(IAccountMenuItem accountMenuItem);
|
||||||
Task CreateNewMailForAsync(MailAccount account);
|
Task CreateNewMailForAsync(MailAccount account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -315,6 +315,7 @@
|
|||||||
"DialogMessage_PrintingSuccessMessage": "Mail is sent to printer.",
|
"DialogMessage_PrintingSuccessMessage": "Mail is sent to printer.",
|
||||||
"DialogMessage_PrintingSuccessTitle": "Success",
|
"DialogMessage_PrintingSuccessTitle": "Success",
|
||||||
"DialogMessage_RenameFolderMessage": "Enter new name for this folder",
|
"DialogMessage_RenameFolderMessage": "Enter new name for this folder",
|
||||||
|
"DialogMessage_CreateFolderMessage": "Enter name for the new folder",
|
||||||
"DialogMessage_RenameFolderTitle": "Rename Folder",
|
"DialogMessage_RenameFolderTitle": "Rename Folder",
|
||||||
"DialogMessage_RenameLinkedAccountsMessage": "Enter new name for linked account",
|
"DialogMessage_RenameLinkedAccountsMessage": "Enter new name for linked account",
|
||||||
"DialogMessage_RenameLinkedAccountsTitle": "Rename Linked Account",
|
"DialogMessage_RenameLinkedAccountsTitle": "Rename Linked Account",
|
||||||
@@ -1534,5 +1535,7 @@
|
|||||||
"AccountSetup_GoBackButton": "Go Back",
|
"AccountSetup_GoBackButton": "Go Back",
|
||||||
"AccountSetup_TryAgainButton": "Try Again",
|
"AccountSetup_TryAgainButton": "Try Again",
|
||||||
"Exception_FailedToSynchronizeCategories": "Failed to synchronize categories",
|
"Exception_FailedToSynchronizeCategories": "Failed to synchronize categories",
|
||||||
"ImapCalDavSettings_AutoDiscoveryFailed": "Auto-discovery failed. Please enter settings manually in the Advanced tab."
|
"ImapCalDavSettings_AutoDiscoveryFailed": "Auto-discovery failed. Please enter settings manually in the Advanced tab.",
|
||||||
|
"AccountContextMenu_ManageAccountSettings": "Manage account settings",
|
||||||
|
"AccountContextMenu_CreateFolder": "Create folder"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ public static class SynchronizationActionHelper
|
|||||||
MarkFolderAsReadRequest => Translator.SyncAction_MarkingFolderAsRead,
|
MarkFolderAsReadRequest => Translator.SyncAction_MarkingFolderAsRead,
|
||||||
DeleteFolderRequest => Translator.FolderOperation_Delete,
|
DeleteFolderRequest => Translator.FolderOperation_Delete,
|
||||||
CreateSubFolderRequest => Translator.FolderOperation_CreateSubFolder,
|
CreateSubFolderRequest => Translator.FolderOperation_CreateSubFolder,
|
||||||
|
CreateRootFolderRequest => Translator.AccountContextMenu_CreateFolder,
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using Wino.Core.Domain.Entities.Mail;
|
||||||
|
using Wino.Core.Domain.Enums;
|
||||||
|
using Wino.Core.Domain.Models.Requests;
|
||||||
|
|
||||||
|
namespace Wino.Core.Requests.Folder;
|
||||||
|
|
||||||
|
public record CreateRootFolderRequest(MailItemFolder Folder, string NewFolderName) : FolderRequestBase(Folder, FolderSynchronizerOperation.CreateRootFolder)
|
||||||
|
{
|
||||||
|
public override void ApplyUIChanges() { }
|
||||||
|
public override void RevertUIChanges() { }
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ using Wino.Core.Domain.Models.MailItem;
|
|||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
using Wino.Core.Helpers;
|
using Wino.Core.Helpers;
|
||||||
using Wino.Core.Requests.Calendar;
|
using Wino.Core.Requests.Calendar;
|
||||||
|
using Wino.Core.Requests.Folder;
|
||||||
using Wino.Core.Requests.Mail;
|
using Wino.Core.Requests.Mail;
|
||||||
using Wino.Messaging.Server;
|
using Wino.Messaging.Server;
|
||||||
using Wino.Messaging.UI;
|
using Wino.Messaging.UI;
|
||||||
@@ -220,6 +221,11 @@ public class WinoRequestDelegator : IWinoRequestDelegator
|
|||||||
|
|
||||||
await SendSyncActionsAddedAsync(requestList, accountId).ConfigureAwait(false);
|
await SendSyncActionsAddedAsync(requestList, accountId).ConfigureAwait(false);
|
||||||
await QueueSynchronizationAsync(accountId).ConfigureAwait(false);
|
await QueueSynchronizationAsync(accountId).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (requestList.Any(r => r is DeleteFolderRequest or CreateSubFolderRequest or CreateRootFolderRequest))
|
||||||
|
{
|
||||||
|
await QueueFoldersOnlySynchronizationAsync(accountId).ConfigureAwait(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<IRequestBase> CreateCalendarEventRequestAsync(CalendarOperationPreparationRequest calendarPreparationRequest)
|
private async Task<IRequestBase> CreateCalendarEventRequestAsync(CalendarOperationPreparationRequest calendarPreparationRequest)
|
||||||
|
|||||||
@@ -1724,6 +1724,17 @@ public class GmailSynchronizer : WinoSynchronizer<IClientServiceRequest, Message
|
|||||||
return [new HttpRequestBundle<IClientServiceRequest>(networkCall, request, request)];
|
return [new HttpRequestBundle<IClientServiceRequest>(networkCall, request, request)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<IRequestBundle<IClientServiceRequest>> CreateRootFolder(CreateRootFolderRequest request)
|
||||||
|
{
|
||||||
|
var label = new Label()
|
||||||
|
{
|
||||||
|
Name = request.NewFolderName
|
||||||
|
};
|
||||||
|
|
||||||
|
var networkCall = _gmailService.Users.Labels.Create(label, "me");
|
||||||
|
return [new HttpRequestBundle<IClientServiceRequest>(networkCall, request, request)];
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Request Execution
|
#region Request Execution
|
||||||
|
|||||||
@@ -317,6 +317,15 @@ public class ImapSynchronizer : WinoSynchronizer<ImapRequest, ImapMessageCreatio
|
|||||||
}, request, request);
|
}, request, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<IRequestBundle<ImapRequest>> CreateRootFolder(CreateRootFolderRequest request)
|
||||||
|
{
|
||||||
|
return CreateSingleTaskBundle(async (client, item) =>
|
||||||
|
{
|
||||||
|
var rootFolder = client.GetFolder(client.PersonalNamespaces[0]);
|
||||||
|
await rootFolder.CreateAsync(request.NewFolderName, true).ConfigureAwait(false);
|
||||||
|
}, request, request);
|
||||||
|
}
|
||||||
|
|
||||||
public override List<IRequestBundle<ImapRequest>> CreateCalendarEvent(CreateCalendarEventRequest request)
|
public override List<IRequestBundle<ImapRequest>> CreateCalendarEvent(CreateCalendarEventRequest request)
|
||||||
{
|
{
|
||||||
var handler = ResolveCalendarOperationHandler();
|
var handler = ResolveCalendarOperationHandler();
|
||||||
|
|||||||
@@ -2003,6 +2003,17 @@ public class OutlookSynchronizer : WinoSynchronizer<RequestInformation, Message,
|
|||||||
return [new HttpRequestBundle<RequestInformation>(networkCall, request)];
|
return [new HttpRequestBundle<RequestInformation>(networkCall, request)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override List<IRequestBundle<RequestInformation>> CreateRootFolder(CreateRootFolderRequest request)
|
||||||
|
{
|
||||||
|
var requestBody = new MailFolder
|
||||||
|
{
|
||||||
|
DisplayName = request.NewFolderName
|
||||||
|
};
|
||||||
|
|
||||||
|
var networkCall = _graphClient.Me.MailFolders.ToPostRequestInformation(requestBody);
|
||||||
|
return [new HttpRequestBundle<RequestInformation>(networkCall, request)];
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<RequestInformation>> batchedRequests, CancellationToken cancellationToken = default)
|
public override async Task ExecuteNativeRequestsAsync(List<IRequestBundle<RequestInformation>> batchedRequests, CancellationToken cancellationToken = default)
|
||||||
|
|||||||
@@ -222,6 +222,9 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
|||||||
case FolderSynchronizerOperation.CreateSubFolder:
|
case FolderSynchronizerOperation.CreateSubFolder:
|
||||||
nativeRequests.AddRange(CreateSubFolder(group.ElementAt(0) as CreateSubFolderRequest));
|
nativeRequests.AddRange(CreateSubFolder(group.ElementAt(0) as CreateSubFolderRequest));
|
||||||
break;
|
break;
|
||||||
|
case FolderSynchronizerOperation.CreateRootFolder:
|
||||||
|
nativeRequests.AddRange(CreateRootFolder(group.ElementAt(0) as CreateRootFolderRequest));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -658,6 +661,7 @@ public abstract class WinoSynchronizer<TBaseRequest, TMessageType, TCalendarEven
|
|||||||
public virtual List<IRequestBundle<TBaseRequest>> MarkFolderAsRead(MarkFolderAsReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> MarkFolderAsRead(MarkFolderAsReadRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
public virtual List<IRequestBundle<TBaseRequest>> DeleteFolder(DeleteFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> DeleteFolder(DeleteFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
public virtual List<IRequestBundle<TBaseRequest>> CreateSubFolder(CreateSubFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> CreateSubFolder(CreateSubFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
|
public virtual List<IRequestBundle<TBaseRequest>> CreateRootFolder(CreateRootFolderRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
public virtual List<IRequestBundle<TBaseRequest>> UpdateCategories(BatchMailCategoryAssignmentRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> UpdateCategories(BatchMailCategoryAssignmentRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
public virtual List<IRequestBundle<TBaseRequest>> CreateCategory(MailCategoryCreateRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> CreateCategory(MailCategoryCreateRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
public virtual List<IRequestBundle<TBaseRequest>> UpdateCategory(MailCategoryUpdateRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
public virtual List<IRequestBundle<TBaseRequest>> UpdateCategory(MailCategoryUpdateRequest request) => throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedSynchronizerOperation, this.GetType()));
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ using Wino.Core.Domain.Models.Launch;
|
|||||||
using Wino.Core.Domain.Models.MailItem;
|
using Wino.Core.Domain.Models.MailItem;
|
||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
using Wino.Core.Domain.Models.Synchronization;
|
using Wino.Core.Domain.Models.Synchronization;
|
||||||
|
using Wino.Core.Requests.Folder;
|
||||||
using Wino.Core.Services;
|
using Wino.Core.Services;
|
||||||
using Wino.Mail.ViewModels.Data;
|
using Wino.Mail.ViewModels.Data;
|
||||||
using Wino.Messaging.Client.Accounts;
|
using Wino.Messaging.Client.Accounts;
|
||||||
@@ -624,6 +625,29 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task CreateRootFolderAsync(IAccountMenuItem accountMenuItem)
|
||||||
|
{
|
||||||
|
var account = accountMenuItem?.HoldingAccounts?.FirstOrDefault();
|
||||||
|
if (account == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var folderName = await _dialogService.ShowTextInputDialogAsync(
|
||||||
|
string.Empty,
|
||||||
|
Translator.AccountContextMenu_CreateFolder,
|
||||||
|
Translator.DialogMessage_CreateFolderMessage,
|
||||||
|
Translator.Buttons_Create);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(folderName))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var placeholderFolder = new MailItemFolder
|
||||||
|
{
|
||||||
|
MailAccountId = account.Id
|
||||||
|
};
|
||||||
|
|
||||||
|
await _winoRequestDelegator.ExecuteAsync(account.Id, [new CreateRootFolderRequest(placeholderFolder, folderName.Trim())]);
|
||||||
|
}
|
||||||
|
|
||||||
public Task HandleAccountAttentionAsync(MailAccount account)
|
public Task HandleAccountAttentionAsync(MailAccount account)
|
||||||
=> FixAccountIssuesAsync(account);
|
=> FixAccountIssuesAsync(account);
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
<DataTemplate x:Key="ClickableAccountMenuTemplate" x:DataType="menu:AccountMenuItem">
|
<DataTemplate x:Key="ClickableAccountMenuTemplate" x:DataType="menu:AccountMenuItem">
|
||||||
<controls:AccountNavigationItem
|
<controls:AccountNavigationItem
|
||||||
x:Name="AccountItem"
|
x:Name="AccountItem"
|
||||||
|
ContextRequested="AccountMenuItemContextRequested"
|
||||||
Height="50"
|
Height="50"
|
||||||
HorizontalContentAlignment="Stretch"
|
HorizontalContentAlignment="Stretch"
|
||||||
VerticalContentAlignment="Stretch"
|
VerticalContentAlignment="Stretch"
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ using Wino.Calendar.ViewModels;
|
|||||||
using Wino.Mail.ViewModels;
|
using Wino.Mail.ViewModels;
|
||||||
using Wino.Mail.ViewModels.Data;
|
using Wino.Mail.ViewModels.Data;
|
||||||
using Wino.Mail.WinUI.ViewModels;
|
using Wino.Mail.WinUI.ViewModels;
|
||||||
|
using Wino.Controls;
|
||||||
using Wino.Mail.WinUI.Controls;
|
using Wino.Mail.WinUI.Controls;
|
||||||
using Wino.Mail.WinUI.Helpers;
|
using Wino.Mail.WinUI.Helpers;
|
||||||
using Wino.Helpers;
|
using Wino.Helpers;
|
||||||
@@ -36,6 +37,7 @@ using Wino.Messaging.Client.Accounts;
|
|||||||
using Wino.Messaging.Client.Calendar;
|
using Wino.Messaging.Client.Calendar;
|
||||||
using Wino.Messaging.Client.Contacts;
|
using Wino.Messaging.Client.Contacts;
|
||||||
using Wino.Messaging.Client.Mails;
|
using Wino.Messaging.Client.Mails;
|
||||||
|
using Wino.Messaging.Client.Navigation;
|
||||||
using Wino.Messaging.Client.Shell;
|
using Wino.Messaging.Client.Shell;
|
||||||
using Wino.Messaging.UI;
|
using Wino.Messaging.UI;
|
||||||
using Wino.Views;
|
using Wino.Views;
|
||||||
@@ -518,6 +520,65 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void AccountMenuItemContextRequested(UIElement sender, ContextRequestedEventArgs args)
|
||||||
|
{
|
||||||
|
if (!ViewModel.IsMailMode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sender is not AccountNavigationItem accountNavigationItem ||
|
||||||
|
accountNavigationItem.DataContext is not AccountMenuItem accountMenuItem ||
|
||||||
|
!args.TryGetPosition(sender, out Point p))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
args.Handled = true;
|
||||||
|
|
||||||
|
var flyout = new MenuFlyout();
|
||||||
|
|
||||||
|
var manageAccountSettingsItem = new MenuFlyoutItem
|
||||||
|
{
|
||||||
|
Text = Translator.AccountContextMenu_ManageAccountSettings
|
||||||
|
};
|
||||||
|
manageAccountSettingsItem.Icon = new WinoFontIcon { Icon = WinoIconGlyph.ManageAccounts };
|
||||||
|
manageAccountSettingsItem.Click += (_, _) => NavigateToAccountSettings(accountMenuItem);
|
||||||
|
flyout.Items.Add(manageAccountSettingsItem);
|
||||||
|
|
||||||
|
var createFolderItem = new MenuFlyoutItem
|
||||||
|
{
|
||||||
|
Text = Translator.AccountContextMenu_CreateFolder
|
||||||
|
};
|
||||||
|
createFolderItem.Icon = new WinoFontIcon { Icon = WinoIconGlyph.CreateFolder };
|
||||||
|
createFolderItem.Click += async (_, _) => await ViewModel.MailClient.CreateRootFolderAsync(accountMenuItem);
|
||||||
|
flyout.Items.Add(createFolderItem);
|
||||||
|
|
||||||
|
flyout.ShowAt(accountNavigationItem, new FlyoutShowOptions
|
||||||
|
{
|
||||||
|
ShowMode = FlyoutShowMode.Standard,
|
||||||
|
Position = new Point(p.X + 30, p.Y - 20)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void NavigateToAccountSettings(AccountMenuItem accountMenuItem)
|
||||||
|
{
|
||||||
|
ViewModel.NavigationService.ChangeApplicationMode(
|
||||||
|
WinoApplicationMode.Settings,
|
||||||
|
new ShellModeActivationContext
|
||||||
|
{
|
||||||
|
Parameter = WinoPage.ManageAccountsPage,
|
||||||
|
SuppressStartupFlows = true
|
||||||
|
});
|
||||||
|
|
||||||
|
_ = DispatcherQueue.EnqueueAsync(() =>
|
||||||
|
{
|
||||||
|
WeakReferenceMessenger.Default.Send(new SettingsRootNavigationRequested(WinoPage.ManageAccountsPage));
|
||||||
|
WeakReferenceMessenger.Default.Send(new BreadcrumbNavigationRequested(
|
||||||
|
accountMenuItem.AccountName,
|
||||||
|
WinoPage.AccountDetailsPage,
|
||||||
|
accountMenuItem.AccountId));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public void Receive(CreateNewMailWithMultipleAccountsRequested message)
|
public void Receive(CreateNewMailWithMultipleAccountsRequested message)
|
||||||
{
|
{
|
||||||
if (!ViewModel.IsMailMode)
|
if (!ViewModel.IsMailMode)
|
||||||
|
|||||||
Reference in New Issue
Block a user