Fixed an issue where local draft is deleted via hover over action or delete button instead of discard button. Disabled discarding local drafts in compose page.

This commit is contained in:
Burak Kaan Köse
2024-06-21 02:11:18 +02:00
parent d3d190989d
commit e009bebfaf
6 changed files with 53 additions and 33 deletions

View File

@@ -107,6 +107,12 @@ namespace Wino.Core.Domain.Entities
/// </summary>
public string DraftId { get; set; }
/// <summary>
/// Whether this mail is only created locally.
/// </summary>
[Ignore]
public bool IsLocalDraft => !string.IsNullOrEmpty(DraftId) && DraftId.StartsWith(Constants.LocalDraftStartPrefix);
/// <summary>
/// Whether this copy is draft or not.
/// </summary>

View File

@@ -44,6 +44,7 @@
DarkEditor,
LightEditor,
Print,
DiscardLocalDraft,
Navigate // For toast activation
}
}

View File

@@ -25,6 +25,7 @@ namespace Wino.Core.Services
private readonly IPreferencesService _preferencesService;
private readonly IAccountService _accountService;
private readonly IDialogService _dialogService;
private readonly IMailService _mailService;
/// <summary>
/// Set of rules that defines which action should be executed if user wants to toggle an action.
@@ -42,13 +43,15 @@ namespace Wino.Core.Services
IKeyPressService keyPressService,
IPreferencesService preferencesService,
IAccountService accountService,
IDialogService dialogService) : base(databaseService)
IDialogService dialogService,
IMailService mailService) : base(databaseService)
{
_folderService = folderService;
_keyPressService = keyPressService;
_preferencesService = preferencesService;
_accountService = accountService;
_dialogService = dialogService;
_mailService = mailService;
}
public async Task<List<IRequest>> PrepareRequestsAsync(MailOperationPreperationRequest preperationRequest)
@@ -91,7 +94,11 @@ namespace Wino.Core.Services
foreach (var item in preperationRequest.MailItems)
{
requests.Add(await GetSingleRequestAsync(item, action, moveTargetStructure, preperationRequest.ToggleExecution));
var singleRequest = await GetSingleRequestAsync(item, action, moveTargetStructure, preperationRequest.ToggleExecution);
if (singleRequest == null) continue;
requests.Add(singleRequest);
}
return requests;
@@ -110,6 +117,10 @@ namespace Wino.Core.Services
if (action == MailOperation.SoftDelete && mailItem.IsDraft)
action = MailOperation.HardDelete;
// Rule: Soft/Hard deletes on local drafts are always discard local draft.
if ((action == MailOperation.SoftDelete || action == MailOperation.HardDelete) && mailItem.IsLocalDraft)
action = MailOperation.DiscardLocalDraft;
// Rule: Toggle actions must be reverted if ToggleExecution is passed true.
if (shouldToggleActions)
{
@@ -179,8 +190,12 @@ namespace Wino.Core.Services
}
else if (action == MailOperation.AlwaysMoveToFocused || action == MailOperation.AlwaysMoveToOther)
return new AlwaysMoveToRequest(mailItem, action == MailOperation.AlwaysMoveToFocused);
else if (action == MailOperation.DiscardLocalDraft)
await _mailService.DeleteMailAsync(mailItem.AssignedAccount.Id, mailItem.Id);
else
throw new NotSupportedException(string.Format(Translator.Exception_UnsupportedAction, action));
return null;
}
public async Task<IRequest> PrepareFolderRequestAsync(FolderOperation operation, IMailItemFolder mailItemFolder)

View File

@@ -32,21 +32,23 @@ namespace Wino.Mail.ViewModels
// Update is triggered when we leave the page.
private bool isUpdatingMimeBlocked = false;
public bool CanSendMail => ComposingAccount != null && !IsLocalDraft && currentMimeMessage != null;
private bool canSendMail => ComposingAccount != null && !IsLocalDraft && CurrentMimeMessage != null;
[NotifyCanExecuteChangedFor(nameof(DiscardCommand))]
[NotifyCanExecuteChangedFor(nameof(SendCommand))]
[ObservableProperty]
private MimeMessage currentMimeMessage = null;
private readonly BodyBuilder bodyBuilder = new BodyBuilder();
public bool IsLocalDraft => CurrentMailDraftItem != null
&& !string.IsNullOrEmpty(CurrentMailDraftItem.DraftId)
&& CurrentMailDraftItem.DraftId.StartsWith(Constants.LocalDraftStartPrefix);
public bool IsLocalDraft => CurrentMailDraftItem?.MailCopy?.IsLocalDraft ?? true;
#region Properties
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(IsLocalDraft))]
[NotifyPropertyChangedFor(nameof(CanSendMail))]
[NotifyCanExecuteChangedFor(nameof(DiscardCommand))]
[NotifyCanExecuteChangedFor(nameof(SendCommand))]
private MailItemViewModel currentMailDraftItem;
[ObservableProperty]
@@ -62,6 +64,8 @@ namespace Wino.Mail.ViewModels
private string subject;
[ObservableProperty]
[NotifyCanExecuteChangedFor(nameof(DiscardCommand))]
[NotifyCanExecuteChangedFor(nameof(SendCommand))]
private MailAccount composingAccount;
[ObservableProperty]
@@ -136,7 +140,7 @@ namespace Wino.Mail.ViewModels
private void RemoveAttachment(MailAttachmentViewModel attachmentViewModel)
=> IncludedAttachments.Remove(attachmentViewModel);
[RelayCommand]
[RelayCommand(CanExecute = nameof(canSendMail))]
private async Task SendAsync()
{
// TODO: More detailed mail validations.
@@ -161,20 +165,20 @@ namespace Wino.Mail.ViewModels
var assignedAccount = CurrentMailDraftItem.AssignedAccount;
var sentFolder = await _folderService.GetSpecialFolderByAccountIdAsync(assignedAccount.Id, SpecialFolderType.Sent);
var draftSendPreparationRequest = new SendDraftPreparationRequest(CurrentMailDraftItem.MailCopy, currentMimeMessage, CurrentMailDraftItem.AssignedFolder, sentFolder, CurrentMailDraftItem.AssignedAccount.Preferences);
var draftSendPreparationRequest = new SendDraftPreparationRequest(CurrentMailDraftItem.MailCopy, CurrentMimeMessage, CurrentMailDraftItem.AssignedFolder, sentFolder, CurrentMailDraftItem.AssignedAccount.Preferences);
await _worker.ExecuteAsync(draftSendPreparationRequest);
}
private async Task UpdateMimeChangesAsync()
{
if (isUpdatingMimeBlocked || currentMimeMessage == null || ComposingAccount == null || CurrentMailDraftItem == null) return;
if (isUpdatingMimeBlocked || CurrentMimeMessage == null || ComposingAccount == null || CurrentMailDraftItem == null) return;
// Save recipients.
SaveAddressInfo(ToItems, currentMimeMessage.To);
SaveAddressInfo(CCItemsItems, currentMimeMessage.Cc);
SaveAddressInfo(BCCItems, currentMimeMessage.Bcc);
SaveAddressInfo(ToItems, CurrentMimeMessage.To);
SaveAddressInfo(CCItemsItems, CurrentMimeMessage.Cc);
SaveAddressInfo(BCCItems, CurrentMimeMessage.Bcc);
SaveImportance();
SaveSubject();
@@ -184,13 +188,13 @@ namespace Wino.Mail.ViewModels
await UpdateMailCopyAsync();
// Save mime file.
await _mimeFileService.SaveMimeMessageAsync(CurrentMailDraftItem.MailCopy.FileId, currentMimeMessage, ComposingAccount.Id).ConfigureAwait(false);
await _mimeFileService.SaveMimeMessageAsync(CurrentMailDraftItem.MailCopy.FileId, CurrentMimeMessage, ComposingAccount.Id).ConfigureAwait(false);
}
private async Task UpdateMailCopyAsync()
{
CurrentMailDraftItem.Subject = currentMimeMessage.Subject;
CurrentMailDraftItem.PreviewText = currentMimeMessage.TextBody;
CurrentMailDraftItem.Subject = CurrentMimeMessage.Subject;
CurrentMailDraftItem.PreviewText = CurrentMimeMessage.TextBody;
// Update database.
await _mailService.UpdateMailAsync(CurrentMailDraftItem.MailCopy);
@@ -208,13 +212,13 @@ namespace Wino.Mail.ViewModels
}
}
private void SaveImportance() { currentMimeMessage.Importance = IsImportanceSelected ? SelectedMessageImportance : MessageImportance.Normal; }
private void SaveImportance() { CurrentMimeMessage.Importance = IsImportanceSelected ? SelectedMessageImportance : MessageImportance.Normal; }
private void SaveSubject()
{
if (Subject != null)
{
currentMimeMessage.Subject = Subject;
CurrentMimeMessage.Subject = Subject;
}
}
@@ -227,10 +231,10 @@ namespace Wino.Mail.ViewModels
bodyBuilder.TextBody = HtmlAgilityPackExtensions.GetPreviewText(bodyBuilder.HtmlBody);
if (bodyBuilder.HtmlBody != null && bodyBuilder.TextBody != null)
currentMimeMessage.Body = bodyBuilder.ToMessageBody();
CurrentMimeMessage.Body = bodyBuilder.ToMessageBody();
}
[RelayCommand]
[RelayCommand(CanExecute = nameof(canSendMail))]
private async Task DiscardAsync()
{
if (ComposingAccount == null)
@@ -248,7 +252,7 @@ namespace Wino.Mail.ViewModels
isUpdatingMimeBlocked = true;
// Don't send delete request for local drafts. Just delete the record and mime locally.
if (CurrentMailDraftItem.IsLocalDraft)
if (CurrentMailDraftItem.MailCopy.IsLocalDraft)
{
await _mailService.DeleteMailAsync(ComposingAccount.Id, CurrentMailDraftItem.Id);
}
@@ -413,9 +417,8 @@ namespace Wino.Mail.ViewModels
Subject = replyingMime.Subject;
currentMimeMessage = replyingMime;
CurrentMimeMessage = replyingMime;
OnPropertyChanged(nameof(CanSendMail));
Messenger.Send(new CreateNewComposeMailRequested(renderModel));
});
}
@@ -484,7 +487,9 @@ namespace Wino.Mail.ViewModels
await ExecuteUIThread(() =>
{
CurrentMailDraftItem.Update(updatedMail);
OnPropertyChanged(nameof(CanSendMail));
DiscardCommand.NotifyCanExecuteChanged();
SendCommand.NotifyCanExecuteChanged();
});
}
}

View File

@@ -1,6 +1,5 @@
using System;
using CommunityToolkit.Mvvm.ComponentModel;
using Wino.Core.Domain;
using Wino.Core.Domain.Entities;
using Wino.Core.Domain.Models.MailItem;
@@ -13,8 +12,6 @@ namespace Wino.Mail.ViewModels.Data
{
public MailCopy MailCopy { get; private set; } = mailCopy;
public bool IsLocalDraft => !string.IsNullOrEmpty(DraftId) && DraftId.StartsWith(Constants.LocalDraftStartPrefix);
public Guid UniqueId => ((IMailItem)MailCopy).UniqueId;
public string ThreadId => ((IMailItem)MailCopy).ThreadId;
public string MessageId => ((IMailItem)MailCopy).MessageId;
@@ -96,7 +93,6 @@ namespace Wino.Mail.ViewModels.Data
OnPropertyChanged(nameof(DraftId));
OnPropertyChanged(nameof(Subject));
OnPropertyChanged(nameof(PreviewText));
OnPropertyChanged(nameof(IsLocalDraft));
}
}
}

View File

@@ -152,10 +152,7 @@
<controls:WinoFontIcon Icon="Delete" />
</AppBarButton.Icon>
</AppBarButton>
<AppBarButton
Label="Send"
IsEnabled="{x:Bind ViewModel.CanSendMail, Mode=OneWay}"
Command="{x:Bind ViewModel.SendCommand}">
<AppBarButton Label="Send" Command="{x:Bind ViewModel.SendCommand}">
<AppBarButton.Icon>
<controls:WinoFontIcon Icon="Send" />
</AppBarButton.Icon>