diff --git a/Wino.Core.Domain/Enums/WinoPage.cs b/Wino.Core.Domain/Enums/WinoPage.cs
index fd3bd7d4..9837a3c8 100644
--- a/Wino.Core.Domain/Enums/WinoPage.cs
+++ b/Wino.Core.Domain/Enums/WinoPage.cs
@@ -41,7 +41,6 @@ public enum WinoPage
EmailTemplatesPage,
CreateEmailTemplatePage,
StoragePage,
- WinoAccountManagementPage,
WelcomePageV2,
WelcomeHostPage,
ProviderSelectionPage,
diff --git a/Wino.Core.Domain/Interfaces/IMailDialogService.cs b/Wino.Core.Domain/Interfaces/IMailDialogService.cs
index 0e070f15..7b688bd4 100644
--- a/Wino.Core.Domain/Interfaces/IMailDialogService.cs
+++ b/Wino.Core.Domain/Interfaces/IMailDialogService.cs
@@ -87,9 +87,4 @@ public interface IMailDialogService : IDialogServiceBase
/// Contact information. Null if canceled.
Task ShowEditContactDialogAsync(AccountContact? contact = null);
- Task ShowWinoAccountRegistrationDialogAsync();
-
- Task ShowWinoAccountLoginDialogAsync();
-
- Task ShowWinoAccountExportDialogAsync();
}
diff --git a/Wino.Core.Domain/Interfaces/IPreferencesService.cs b/Wino.Core.Domain/Interfaces/IPreferencesService.cs
index 12363ff2..adc931a2 100644
--- a/Wino.Core.Domain/Interfaces/IPreferencesService.cs
+++ b/Wino.Core.Domain/Interfaces/IPreferencesService.cs
@@ -70,12 +70,10 @@ public interface IPreferencesService : INotifyPropertyChanged
///
/// Setting: Whether the Wino account profile button in the shell title bar should be hidden.
///
- bool IsWinoAccountButtonHidden { get; set; }
///
/// Setting: Whether AI actions panels and their toggle buttons should be hidden.
///
- bool IsAiActionsPanelHidden { get; set; }
///
/// Setting: Default target language code used for AI translation actions.
diff --git a/Wino.Core.Domain/Models/Settings/SettingsNavigationItemInfo.cs b/Wino.Core.Domain/Models/Settings/SettingsNavigationItemInfo.cs
index 6c135fa0..ef04994e 100644
--- a/Wino.Core.Domain/Models/Settings/SettingsNavigationItemInfo.cs
+++ b/Wino.Core.Domain/Models/Settings/SettingsNavigationItemInfo.cs
@@ -36,11 +36,6 @@ public static class SettingsNavigationInfoProvider
manageAccountsDescription,
"\uE77B",
searchKeywords: Translator.SettingsSearch_ManageAccounts_Keywords),
- new(WinoPage.WinoAccountManagementPage,
- Translator.WinoAccount_SettingsSection_Title,
- Translator.WinoAccount_SettingsSection_Description,
- "\uE77B",
- searchKeywords: string.Empty),
new(null, Translator.SettingsOptions_GeneralSection, string.Empty, "\uE713", isSeparator: true),
new(WinoPage.AppPreferencesPage,
Translator.SettingsAppPreferences_Title,
@@ -152,7 +147,6 @@ public static class SettingsNavigationInfoProvider
WinoPage.SettingOptionsPage => Translator.MenuSettings,
WinoPage.ManageAccountsPage => Translator.SettingsManageAccountSettings_Title,
WinoPage.AccountManagementPage => Translator.SettingsManageAccountSettings_Title,
- WinoPage.WinoAccountManagementPage => Translator.WinoAccount_SettingsSection_Title,
WinoPage.PersonalizationPage => Translator.SettingsPersonalization_Title,
WinoPage.AboutPage => Translator.SettingsAbout_Title,
WinoPage.MessageListPage => Translator.SettingsMessageList_Title,
diff --git a/Wino.Core.ViewModels/WinoAccountManagementPageViewModel.cs b/Wino.Core.ViewModels/WinoAccountManagementPageViewModel.cs
deleted file mode 100644
index 2631579f..00000000
--- a/Wino.Core.ViewModels/WinoAccountManagementPageViewModel.cs
+++ /dev/null
@@ -1,632 +0,0 @@
-#nullable enable
-using System;
-using System.Collections.ObjectModel;
-using System.Threading.Tasks;
-using CommunityToolkit.Mvvm.ComponentModel;
-using CommunityToolkit.Mvvm.Input;
-using CommunityToolkit.Mvvm.Messaging;
-using Wino.Core.Domain;
-using Wino.Core.Domain.Entities.Shared;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Accounts;
-using Wino.Core.Domain.Models.Navigation;
-using Wino.Core.ViewModels.Data;
-using Wino.Mail.Api.Contracts.Common;
-using Wino.Messaging.UI;
-
-namespace Wino.Core.ViewModels;
-
-public partial class WinoAccountManagementPageViewModel : CoreBaseViewModel,
- IRecipient,
- IRecipient,
- IRecipient
-{
- private readonly IWinoAccountProfileService _profileService;
- private readonly IWinoAccountDataSyncService _syncService;
- private readonly IMailDialogService _dialogService;
- private readonly IStoreManagementService _storeManagementService;
- private readonly WinoAddOnItemViewModel _aiPackAddOn;
- private readonly WinoAddOnItemViewModel _unlimitedAccountsAddOn;
-
- public ObservableCollection AddOns { get; } = [];
-
- [ObservableProperty]
- public partial bool IsBusy { get; set; }
-
- [ObservableProperty]
- [NotifyPropertyChangedFor(nameof(IsSignedOut))]
- public partial bool IsSignedIn { get; set; }
-
- [ObservableProperty]
- public partial string AccountEmail { get; set; } = string.Empty;
-
- [ObservableProperty]
- public partial string AccountStatusText { get; set; } = string.Empty;
-
- [ObservableProperty]
- [NotifyCanExecuteChangedFor(nameof(PurchaseAddOnCommand))]
- public partial bool IsCheckoutInProgress { get; set; }
-
- public bool IsSignedOut => !IsSignedIn;
-
- public WinoAccountManagementPageViewModel(IWinoAccountProfileService profileService,
- IWinoAccountDataSyncService syncService,
- IMailDialogService dialogService,
- IStoreManagementService storeManagementService)
- {
- _profileService = profileService;
- _syncService = syncService;
- _dialogService = dialogService;
- _storeManagementService = storeManagementService;
-
- _aiPackAddOn = CreateAddOnItem(WinoAddOnProductType.AI_PACK);
- _unlimitedAccountsAddOn = CreateAddOnItem(WinoAddOnProductType.UNLIMITED_ACCOUNTS);
- AddOns.Add(_aiPackAddOn);
- AddOns.Add(_unlimitedAccountsAddOn);
- }
-
- public override void OnNavigatedTo(NavigationMode mode, object parameters)
- {
- base.OnNavigatedTo(mode, parameters);
- _ = InitializeAsync();
- }
-
- [RelayCommand]
- private async Task RegisterAsync()
- {
- var account = await _dialogService.ShowWinoAccountRegistrationDialogAsync();
- if (account == null)
- {
- return;
- }
-
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_RegisterSuccessMessage, account.Email),
- InfoBarMessageType.Success);
- }
-
- [RelayCommand]
- private async Task SignInAsync()
- {
- var account = await _dialogService.ShowWinoAccountLoginDialogAsync();
- if (account == null)
- {
- return;
- }
-
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_LoginSuccessMessage, account.Email),
- InfoBarMessageType.Success);
- }
-
- [RelayCommand]
- private async Task SignOutAsync()
- {
- var account = await _profileService.GetActiveAccountAsync().ConfigureAwait(false);
- if (account == null)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Warning,
- Translator.WinoAccount_SignOut_NoAccountMessage,
- InfoBarMessageType.Warning);
- return;
- }
-
- await _profileService.SignOutAsync().ConfigureAwait(false);
-
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_SignOut_SuccessMessage, account.Email),
- InfoBarMessageType.Success);
- }
-
- [RelayCommand]
- private async Task ChangePasswordAsync()
- {
- var account = await _profileService.GetActiveAccountAsync();
- if (account == null)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Warning,
- Translator.WinoAccount_SignOut_NoAccountMessage,
- InfoBarMessageType.Warning);
- return;
- }
-
- var shouldContinue = await _dialogService.ShowConfirmationDialogAsync(
- string.Format(Translator.WinoAccount_ChangePassword_ConfirmationMessage, account.Email),
- Translator.WinoAccount_ChangePassword_Title,
- Translator.WinoAccount_ChangePassword_Action);
-
- if (!shouldContinue)
- {
- return;
- }
-
- var response = await _profileService.ForgotPasswordAsync(account.Email);
- if (!response.IsSuccess)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
- TranslateForgotPasswordError(response.ErrorCode),
- InfoBarMessageType.Error);
- return;
- }
-
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_ForgotPasswordDialog_SuccessMessage, account.Email),
- InfoBarMessageType.Success);
- }
-
- private static string TranslateForgotPasswordError(string? errorCode)
- => errorCode switch
- {
- ApiErrorCodes.EmailNotRegistered => Translator.WinoAccount_Error_EmailNotRegistered,
- ApiErrorCodes.ValidationFailed => Translator.WinoAccount_Error_ValidationFailed,
- _ when string.IsNullOrWhiteSpace(errorCode) => Translator.GeneralTitle_Error,
- _ => errorCode!
- };
-
- [RelayCommand(CanExecute = nameof(CanPurchaseAddOn))]
- private async Task PurchaseAddOnAsync(WinoAddOnItemViewModel? addOn)
- {
- if (addOn == null)
- {
- return;
- }
-
- await ExecuteUIThread(() =>
- {
- IsCheckoutInProgress = true;
- addOn.IsPurchaseInProgress = true;
- });
-
- try
- {
- var purchaseResult = await _storeManagementService.PurchaseAsync(addOn.ProductType);
-
- if (purchaseResult == StorePurchaseResult.NotPurchased)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
- Translator.WinoAccount_Management_PurchaseStartFailed,
- InfoBarMessageType.Error);
- return;
- }
-
- var syncResult = await _profileService.SyncStoreEntitlementsAsync().ConfigureAwait(false);
- if (!syncResult.IsSuccess && !string.Equals(syncResult.ErrorCode, "MissingAccessToken", StringComparison.Ordinal))
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
- TranslateStoreSyncError(syncResult.ErrorCode),
- InfoBarMessageType.Error);
- return;
- }
-
- await HandleAddOnPurchasedAsync().ConfigureAwait(false);
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
- Translator.WinoAccount_Management_PurchaseStartFailed,
- InfoBarMessageType.Error);
- }
- finally
- {
- await ExecuteUIThread(() =>
- {
- IsCheckoutInProgress = false;
- addOn.IsPurchaseInProgress = false;
- });
- }
- }
-
- private bool CanPurchaseAddOn(WinoAddOnItemViewModel? addOn)
- => addOn != null && !addOn.IsPurchased && !addOn.IsLoading && !IsCheckoutInProgress;
-
- [RelayCommand]
- private async Task ExportSettingsAsync()
- {
- try
- {
- var result = await _dialogService.ShowWinoAccountExportDialogAsync().ConfigureAwait(false);
- if (result == null)
- {
- return;
- }
-
- _dialogService.InfoBarMessage(
- Translator.GeneralTitle_Info,
- BuildExportSuccessMessage(result),
- InfoBarMessageType.Success);
- }
- catch (Exception ex)
- {
- _dialogService.InfoBarMessage(
- Translator.GeneralTitle_Error,
- ex.Message,
- InfoBarMessageType.Error);
- }
- }
-
- [RelayCommand]
- private async Task ImportSettingsAsync()
- {
- await ExecuteUIThread(() => IsBusy = true);
-
- try
- {
- var result = await _syncService.ImportAsync(new WinoAccountSyncSelection());
-
- if (!result.HasAnyRemoteData)
- {
- _dialogService.InfoBarMessage(
- Translator.GeneralTitle_Info,
- Translator.WinoAccount_Management_NoRemoteSettings,
- InfoBarMessageType.Information);
- return;
- }
-
- var messageType = result.FailedPreferenceCount > 0
- ? InfoBarMessageType.Warning
- : InfoBarMessageType.Success;
-
- _dialogService.InfoBarMessage(
- result.FailedPreferenceCount > 0 ? Translator.GeneralTitle_Warning : Translator.GeneralTitle_Info,
- BuildImportMessage(result),
- messageType);
- }
- catch (Exception ex)
- {
- _dialogService.InfoBarMessage(
- Translator.GeneralTitle_Error,
- ex.Message,
- InfoBarMessageType.Error);
- }
- finally
- {
- await ExecuteUIThread(() => IsBusy = false);
- }
- }
-
- protected override void RegisterRecipients()
- {
- base.RegisterRecipients();
-
- Messenger.Register(this);
- Messenger.Register(this);
- Messenger.Register(this);
- }
-
- protected override void UnregisterRecipients()
- {
- base.UnregisterRecipients();
-
- Messenger.Unregister(this);
- Messenger.Unregister(this);
- Messenger.Unregister(this);
- }
-
- public void Receive(WinoAccountProfileUpdatedMessage message)
- => _ = LoadAsync();
-
- public void Receive(WinoAccountProfileDeletedMessage message)
- => _ = LoadAsync();
-
- public void Receive(WinoAccountAddOnPurchasedMessage message)
- => _ = HandleAddOnPurchasedAsync();
-
- private async Task InitializeAsync()
- {
- await LoadAsync().ConfigureAwait(false);
- }
-
- private async Task LoadAsync()
- {
- WinoAccount? cachedAccount = null;
-
- try
- {
- cachedAccount = await _profileService.GetActiveAccountAsync().ConfigureAwait(false);
-
- if (cachedAccount != null)
- {
- await ApplyAccountStateAsync(cachedAccount).ConfigureAwait(false);
- }
-
- await ExecuteUIThread(() => IsBusy = true);
- await ResetAddOnStatesAsync().ConfigureAwait(false);
- var loadAiPackTask = LoadAiPackAddOnAsync();
- var loadUnlimitedAccountsTask = LoadUnlimitedAccountsAddOnAsync();
-
- var resolvedAccount = cachedAccount;
-
- if (cachedAccount == null || IsAccessTokenExpired(cachedAccount))
- {
- try
- {
- var account = await _profileService.GetAuthenticatedAccountAsync().ConfigureAwait(false);
- if (account != null)
- {
- resolvedAccount = account;
-
- var refreshedProfileResult = await _profileService.RefreshProfileAsync().ConfigureAwait(false);
- if (refreshedProfileResult.IsSuccess && refreshedProfileResult.Account != null)
- {
- resolvedAccount = refreshedProfileResult.Account;
- }
- }
- }
- catch (Exception)
- {
- resolvedAccount ??= cachedAccount;
- }
- }
-
- await ApplyAccountStateAsync(resolvedAccount).ConfigureAwait(false);
- await Task.WhenAll(loadAiPackTask, loadUnlimitedAccountsTask).ConfigureAwait(false);
- }
- catch (Exception)
- {
- if (cachedAccount == null)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error,
- Translator.WinoAccount_Management_LoadFailed,
- InfoBarMessageType.Error);
- await ResetStateAsync().ConfigureAwait(false);
- }
- }
- finally
- {
- await ExecuteUIThread(() => IsBusy = false);
- }
- }
-
- private async Task ApplyAccountStateAsync(Wino.Core.Domain.Entities.Shared.WinoAccount? account)
- {
- await ExecuteUIThread(() =>
- {
- IsSignedIn = account != null;
- AccountEmail = account?.Email ?? string.Empty;
- AccountStatusText = account == null
- ? string.Empty
- : string.Format(Translator.WinoAccount_Management_StatusLabel, account.AccountStatus);
- });
- }
-
- private async Task HandleAddOnPurchasedAsync()
- {
- await LoadAsync().ConfigureAwait(false);
-
- _dialogService.InfoBarMessage(Translator.Info_PurchaseThankYouTitle,
- Translator.Info_PurchaseThankYouMessage,
- InfoBarMessageType.Success);
- }
-
- private async Task ResetStateAsync()
- {
- await ExecuteUIThread(() =>
- {
- IsSignedIn = false;
- AccountEmail = string.Empty;
- AccountStatusText = string.Empty;
- IsCheckoutInProgress = false;
- PurchaseAddOnCommand.NotifyCanExecuteChanged();
- });
-
- await ResetAddOnStatesAsync().ConfigureAwait(false);
- }
-
- private WinoAddOnItemViewModel CreateAddOnItem(WinoAddOnProductType productType)
- {
- return new WinoAddOnItemViewModel(productType)
- {
- PurchaseCommand = PurchaseAddOnCommand,
- UsageLimit = 1
- };
- }
-
- private async Task ResetAddOnStatesAsync()
- {
- await ExecuteUIThread(() =>
- {
- ResetAddOnItem(_aiPackAddOn);
- ResetAddOnItem(_unlimitedAccountsAddOn);
- PurchaseAddOnCommand.NotifyCanExecuteChanged();
- });
- }
-
- private static void ResetAddOnItem(WinoAddOnItemViewModel addOn)
- {
- addOn.IsLoading = true;
- addOn.IsPurchased = false;
- addOn.IsPurchaseInProgress = false;
- addOn.HasUsageData = false;
- addOn.ErrorText = string.Empty;
- addOn.UsageCount = 0;
- addOn.UsageLimit = 1;
- addOn.UsagePercentage = 0;
- addOn.RenewalText = string.Empty;
- addOn.UsageResetText = string.Empty;
- }
-
- private static string TranslateStoreSyncError(string? errorCode)
- => errorCode switch
- {
- _ => Translator.WinoAccount_Management_StoreSyncFailed
- };
-
- private static string BuildExportSuccessMessage(WinoAccountSyncExportResult result)
- {
- var parts = new Collection();
-
- if (result.IncludedPreferences)
- {
- parts.Add(Translator.WinoAccount_Management_ExportPreferencesSucceeded);
- }
-
- if (result.IncludedAccounts)
- {
- parts.Add(string.Format(Translator.WinoAccount_Management_ExportAccountsSucceeded, result.ExportedMailboxCount));
- }
-
- if (parts.Count == 0)
- {
- parts.Add(Translator.WinoAccount_Management_ExportSucceeded);
- }
-
- return string.Join(" ", parts);
- }
-
- private static string BuildImportMessage(WinoAccountSyncImportResult result)
- {
- var parts = new Collection();
-
- if (result.HadRemotePreferences)
- {
- parts.Add(result.FailedPreferenceCount > 0
- ? string.Format(Translator.WinoAccount_Management_ImportPartial, result.AppliedPreferenceCount, result.FailedPreferenceCount)
- : string.Format(Translator.WinoAccount_Management_ImportPreferencesSucceeded, result.AppliedPreferenceCount));
- }
-
- if (result.ImportedMailboxCount > 0)
- {
- parts.Add(string.Format(Translator.WinoAccount_Management_ImportAccountsSucceeded, result.ImportedMailboxCount));
- }
-
- if (result.SkippedDuplicateMailboxCount > 0)
- {
- parts.Add(string.Format(Translator.WinoAccount_Management_ImportDuplicateAccountsSkipped, result.SkippedDuplicateMailboxCount));
- }
-
- if (parts.Count == 0)
- {
- parts.Add(Translator.WinoAccount_Management_ImportEmpty);
- }
-
- if (result.ImportedMailboxCount > 0)
- {
- parts.Add(Translator.WinoAccount_Management_ImportReloginReminder);
- }
-
- return string.Join(" ", parts);
- }
-
- private static bool IsAccessTokenExpired(WinoAccount account)
- => string.IsNullOrWhiteSpace(account.AccessToken) || account.AccessTokenExpiresAtUtc <= DateTime.UtcNow;
-
- private async Task LoadUnlimitedAccountsAddOnAsync()
- {
- try
- {
- var hasUnlimitedAccounts = await _storeManagementService.HasProductAsync(WinoAddOnProductType.UNLIMITED_ACCOUNTS).ConfigureAwait(false);
- await ExecuteUIThread(() =>
- {
- _unlimitedAccountsAddOn.IsPurchased = hasUnlimitedAccounts;
- _unlimitedAccountsAddOn.ErrorText = string.Empty;
- });
- }
- catch (Exception)
- {
- await ExecuteUIThread(() =>
- {
- _unlimitedAccountsAddOn.ErrorText = Translator.WinoAccount_Management_AddOnLoadFailed;
- });
- }
- finally
- {
- await ExecuteUIThread(() =>
- {
- _unlimitedAccountsAddOn.IsLoading = false;
- PurchaseAddOnCommand.NotifyCanExecuteChanged();
- });
- }
- }
-
- private async Task LoadAiPackAddOnAsync()
- {
- try
- {
- var hasAiPack = await _storeManagementService.HasProductAsync(WinoAddOnProductType.AI_PACK).ConfigureAwait(false);
-
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.IsPurchased = hasAiPack;
- _aiPackAddOn.ErrorText = string.Empty;
- });
-
- if (!hasAiPack)
- {
- return;
- }
-
- var aiStatusResponse = await _profileService.GetAiStatusAsync().ConfigureAwait(false);
- if (!aiStatusResponse.IsSuccess || aiStatusResponse.Result == null)
- {
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.HasUsageData = false;
- _aiPackAddOn.ErrorText = Translator.WinoAccount_Management_AiPackUsageLoadFailed;
- });
- return;
- }
-
- var aiStatus = aiStatusResponse.Result;
- if (IsExpiredAiEntitlement(aiStatus.EntitlementStatus))
- {
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.IsPurchased = false;
- _aiPackAddOn.HasUsageData = false;
- _aiPackAddOn.ErrorText = string.Empty;
- _aiPackAddOn.RenewalText = string.Empty;
- _aiPackAddOn.UsageResetText = string.Empty;
- });
- return;
- }
-
- if (aiStatus.MonthlyLimit is not int usageLimit || usageLimit <= 0 || aiStatus.Used is not int usageCount)
- {
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.HasUsageData = false;
- _aiPackAddOn.ErrorText = Translator.WinoAccount_Management_AiPackUsageLoadFailed;
- });
- return;
- }
-
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.HasUsageData = true;
- _aiPackAddOn.ErrorText = string.Empty;
- _aiPackAddOn.UsageCount = usageCount;
- _aiPackAddOn.UsageLimit = usageLimit;
- _aiPackAddOn.UsagePercentage = usageLimit > 0 ? (double)usageCount / usageLimit * 100 : 0;
- _aiPackAddOn.RenewalText = aiStatus.CurrentPeriodEndUtc is DateTimeOffset renewalDateUtc
- ? string.Format(Translator.WinoAccount_Management_AiPackRenews, renewalDateUtc.LocalDateTime)
- : string.Empty;
- _aiPackAddOn.UsageResetText = aiStatus.CurrentPeriodEndUtc is DateTimeOffset resetDateUtc
- ? string.Format(Translator.WinoAccount_Management_AiPackResets, resetDateUtc.LocalDateTime)
- : string.Empty;
- });
- }
- catch (Exception)
- {
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.HasUsageData = false;
- _aiPackAddOn.ErrorText = Translator.WinoAccount_Management_AddOnLoadFailed;
- });
- }
- finally
- {
- await ExecuteUIThread(() =>
- {
- _aiPackAddOn.IsLoading = false;
- PurchaseAddOnCommand.NotifyCanExecuteChanged();
- });
- }
- }
-
- private static bool IsExpiredAiEntitlement(string? entitlementStatus)
- => string.Equals(entitlementStatus, "Expired", StringComparison.OrdinalIgnoreCase);
-}
diff --git a/Wino.Mail.ViewModels/WelcomePageV2ViewModel.cs b/Wino.Mail.ViewModels/WelcomePageV2ViewModel.cs
index a3021e8d..12c872fc 100644
--- a/Wino.Mail.ViewModels/WelcomePageV2ViewModel.cs
+++ b/Wino.Mail.ViewModels/WelcomePageV2ViewModel.cs
@@ -73,40 +73,6 @@ public partial class WelcomePageV2ViewModel : MailBaseViewModel
ProviderSelectionNavigationContext.CreateForWizard()));
}
- [RelayCommand(CanExecute = nameof(CanOpenWelcomeActions))]
- private async Task ImportFromWinoAccountAsync()
- {
- await ExecuteUIThread(() => ImportStatusMessage = string.Empty);
-
- try
- {
- var account = await _dialogService.ShowWinoAccountLoginDialogAsync().ConfigureAwait(false);
- if (account == null)
- {
- return;
- }
-
- await ExecuteUIThread(() => IsImportInProgress = true);
-
- var result = await _syncService.ImportAsync(new WinoAccountSyncSelection()).ConfigureAwait(false);
- if (result.ImportedMailboxCount > 0)
- {
- ReportUIChange(new WelcomeImportCompletedMessage(result.ImportedMailboxCount));
- return;
- }
-
- await ExecuteUIThread(() => ImportStatusMessage = BuildInlineImportMessage(result));
- }
- catch (Exception ex)
- {
- await _dialogService.ShowMessageAsync(ex.Message, Translator.GeneralTitle_Error, WinoCustomMessageDialogIcon.Error);
- }
- finally
- {
- await ExecuteUIThread(() => IsImportInProgress = false);
- }
- }
-
[RelayCommand(CanExecute = nameof(CanOpenWelcomeActions))]
private async Task ImportFromJsonAsync()
{
diff --git a/Wino.Mail.WinUI/App.xaml.cs b/Wino.Mail.WinUI/App.xaml.cs
index 82ee2f5f..918469ca 100644
--- a/Wino.Mail.WinUI/App.xaml.cs
+++ b/Wino.Mail.WinUI/App.xaml.cs
@@ -413,7 +413,6 @@ public partial class App : WinoApplication,
services.AddTransient(typeof(MergedAccountDetailsPageViewModel));
services.AddTransient(typeof(AppPreferencesPageViewModel));
services.AddTransient(typeof(StoragePageViewModel));
- services.AddTransient(typeof(WinoAccountManagementPageViewModel));
services.AddTransient(typeof(AliasManagementPageViewModel));
services.AddTransient(typeof(MailCategoryManagementPageViewModel));
services.AddTransient(typeof(ContactsPageViewModel));
@@ -1656,15 +1655,9 @@ public partial class App : WinoApplication,
_autoSynchronizationLoopCts = null;
}
- private async Task LoadInitialWinoAccountAsync()
+ private Task LoadInitialWinoAccountAsync()
{
- var winoAccountProfileService = Services.GetRequiredService();
- var winoAccount = await winoAccountProfileService.GetActiveAccountAsync();
-
- if (winoAccount != null)
- {
- WeakReferenceMessenger.Default.Send(new WinoAccountProfileUpdatedMessage(winoAccount));
- }
+ return Task.CompletedTask;
}
private async Task RunAutoSynchronizationLoopAsync(TimeSpan interval, CancellationToken cancellationToken)
diff --git a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml
deleted file mode 100644
index dafe36a9..00000000
--- a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml
+++ /dev/null
@@ -1,328 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs b/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs
deleted file mode 100644
index 19b4a71a..00000000
--- a/Wino.Mail.WinUI/Controls/AiActionsPanel.xaml.cs
+++ /dev/null
@@ -1,760 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using CommunityToolkit.WinUI;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Media;
-using Wino.Core.Domain;
-using Wino.Core.Domain.Enums;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Ai;
-using Wino.Mail.Api.Contracts.Ai;
-using Wino.Mail.Api.Contracts.Common;
-using Wino.Mail.WinUI.Services;
-
-namespace Wino.Mail.WinUI.Controls;
-
-public sealed partial class AiActionsPanel : UserControl, IDisposable
-{
- public event EventHandler? CloseRequested;
- private readonly IWinoAccountProfileService _profileService = App.Current.Services.GetRequiredService();
- private readonly IStoreManagementService _storeManagementService = App.Current.Services.GetRequiredService();
- private readonly IMailDialogService _dialogService = App.Current.Services.GetRequiredService();
- private readonly IAiActionOptionsService _optionsService = App.Current.Services.GetRequiredService();
- private readonly IPreferencesService _preferencesService = App.Current.Services.GetRequiredService();
-
- private bool _disposedValue;
- private bool _isRefreshing;
- private bool _isBusy;
- private AiActionType _lastConfigurableAction = AiActionType.Translate;
- private bool _hasCachedSummary;
- private CancellationTokenSource? _actionCancellationTokenSource;
- private IReadOnlyList _translateOptions = Array.Empty();
- private IReadOnlyList _rewriteOptions = Array.Empty();
-
- [GeneratedDependencyProperty(DefaultValue = AiActionType.None)]
- public partial AiActionType AvailableActions { get; set; }
-
- [GeneratedDependencyProperty]
- public partial IAiHtmlActionHost? HtmlHost { get; set; }
-
- public AiTranslateLanguageOption? SelectedTranslateLanguageOption { get; set; }
-
- public AiTranslateLanguageOption? SelectedSummarizeLanguageOption { get; set; }
-
- public AiRewriteModeOption? SelectedRewriteModeOption { get; set; }
-
- public AiActionsPanel()
- {
- InitializeComponent();
- }
-
- public void CancelPendingOperation()
- {
- _actionCancellationTokenSource?.Cancel();
- }
-
- public void Dispose()
- {
- if (_disposedValue)
- {
- return;
- }
-
- _disposedValue = true;
- CancelAndDisposeActionCancellationToken();
- }
-
- partial void OnAvailableActionsChanged(AiActionType newValue)
- {
- UpdateActionAvailability();
- ApplySelectedAction(SelectDefaultAction());
- _ = RefreshCachedSummaryStateAsync();
- }
-
- private void OnLoaded(object sender, RoutedEventArgs e)
- {
- LoadOptions();
- UpdateActionAvailability();
- ApplySelectedAction(SelectDefaultAction());
- _ = RefreshAvailabilityAsync();
- }
-
- private void OnUnloaded(object sender, RoutedEventArgs e)
- {
- CancelPendingOperation();
- }
-
- private void LoadOptions()
- {
- // Save current selections before replacing ItemsSource (which clears SelectedItem).
- var previousTranslateCode = SelectedTranslateLanguageOption?.Code;
- var previousSummarizeCode = SelectedSummarizeLanguageOption?.Code;
- var previousRewriteMode = SelectedRewriteModeOption?.Mode;
- var preferredTranslateCode = string.IsNullOrWhiteSpace(previousTranslateCode)
- ? _preferencesService.AiDefaultTranslationLanguageCode
- : previousTranslateCode;
- var preferredSummarizeCode = string.IsNullOrWhiteSpace(previousSummarizeCode)
- ? _preferencesService.AiSummarizeLanguageCode
- : previousSummarizeCode;
-
- _translateOptions = _optionsService.GetTranslateLanguageOptions();
- _rewriteOptions = _optionsService.GetRewriteModeOptions();
-
- TranslateLanguageComboBox.ItemsSource = _translateOptions;
- SummarizeLanguageComboBox.ItemsSource = _translateOptions;
- RewriteModeComboBox.ItemsSource = _rewriteOptions;
-
- // Restore selection by matching on value, falling back to first item.
- SelectedTranslateLanguageOption = FindOption(_translateOptions, o => o.Code == preferredTranslateCode)
- ?? FindOption(_translateOptions, o => o.Code == "en-US")
- ?? (_translateOptions.Count > 0 ? _translateOptions[0] : null);
- SelectedSummarizeLanguageOption = FindOption(_translateOptions, o => o.Code == preferredSummarizeCode)
- ?? FindOption(_translateOptions, o => o.Code == "en-US")
- ?? (_translateOptions.Count > 0 ? _translateOptions[0] : null);
- SelectedRewriteModeOption = FindOption(_rewriteOptions, o => o.Mode == previousRewriteMode) ?? (_rewriteOptions.Count > 0 ? _rewriteOptions[0] : null);
-
- TranslateLanguageComboBox.SelectedItem = SelectedTranslateLanguageOption;
- SummarizeLanguageComboBox.SelectedItem = SelectedSummarizeLanguageOption;
- RewriteModeComboBox.SelectedItem = SelectedRewriteModeOption;
- UpdateRewriteOptionState();
- }
-
- private static T? FindOption(IReadOnlyList options, Func predicate) where T : class
- {
- foreach (var option in options)
- {
- if (predicate(option))
- {
- return option;
- }
- }
-
- return null;
- }
-
- private void UpdateActionAvailability()
- {
- TranslateSegment.Visibility = HasAction(AiActionType.Translate) ? Visibility.Visible : Visibility.Collapsed;
- RewriteSegment.Visibility = HasAction(AiActionType.Rewrite) ? Visibility.Visible : Visibility.Collapsed;
- SummarizeSegment.Visibility = HasAction(AiActionType.Summarize) ? Visibility.Visible : Visibility.Collapsed;
- SummarizeCachedIndicator.Visibility = HasAction(AiActionType.Summarize) && _hasCachedSummary ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private bool HasAction(AiActionType action) => (AvailableActions & action) == action;
-
- private AiActionType SelectDefaultAction()
- {
- if (HasAction(AiActionType.Translate))
- {
- return AiActionType.Translate;
- }
-
- if (HasAction(AiActionType.Rewrite))
- {
- return AiActionType.Rewrite;
- }
-
- if (HasAction(AiActionType.Summarize))
- {
- return AiActionType.Summarize;
- }
-
- return AiActionType.None;
- }
-
- private void ApplySelectedAction(AiActionType action)
- {
- if (action is AiActionType.Translate or AiActionType.Rewrite)
- {
- _lastConfigurableAction = action;
- }
-
- ActionSelector.SelectedItem = action switch
- {
- AiActionType.Translate => TranslateSegment,
- AiActionType.Rewrite => RewriteSegment,
- AiActionType.Summarize => SummarizeSegment,
- _ => null
- };
-
- TranslateOptionsPanel.Visibility = action == AiActionType.Translate ? Visibility.Visible : Visibility.Collapsed;
- RewriteOptionsPanel.Visibility = action == AiActionType.Rewrite ? Visibility.Visible : Visibility.Collapsed;
- SummarizeOptionsPanel.Visibility = action == AiActionType.Summarize ? Visibility.Visible : Visibility.Collapsed;
- }
-
- public async Task RefreshAvailabilityAsync()
- {
- if (_isRefreshing || _disposedValue)
- {
- return;
- }
-
- _isRefreshing = true;
- SetBusyUi(isBusy: false, showLoading: true);
-
- try
- {
- var account = await _profileService.GetAuthenticatedAccountAsync().ConfigureAwait(true);
- if (account == null)
- {
- UpdateUsageSummary(string.Empty);
- UpdatePanelState(showSignedOut: true);
- return;
- }
-
- var hasAiPack = await _storeManagementService.HasProductAsync(WinoAddOnProductType.AI_PACK).ConfigureAwait(true);
- if (!hasAiPack)
- {
- UpdateUsageSummary(string.Empty);
- UpdatePanelState(showPurchase: true);
- return;
- }
-
- var aiStatusResponse = await _profileService.GetAiStatusAsync().ConfigureAwait(true);
- if (aiStatusResponse.IsSuccess && aiStatusResponse.Result != null)
- {
- UpdateUsageSummary(
- CreateUsageSummary(aiStatusResponse.Result),
- GetUsedCount(aiStatusResponse.Result),
- GetUsageLimit(aiStatusResponse.Result));
- }
- else
- {
- UpdateUsageSummary(Translator.WinoAccount_Management_AiPackUsageLoadFailed);
- }
-
- await RefreshCachedSummaryStateAsync().ConfigureAwait(true);
- ApplySelectedAction(SelectDefaultAction());
- UpdatePanelState(showReady: true);
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception)
- {
- UpdateUsageSummary(Translator.WinoAccount_Management_AiPackUsageLoadFailed);
- UpdatePanelState(showReady: true);
- }
- finally
- {
- _isRefreshing = false;
- SetBusyUi(_isBusy, showLoading: false);
- }
- }
-
- private static string CreateUsageSummary(AiStatusResultDto aiStatus)
- {
- if (aiStatus.Used is int used && aiStatus.MonthlyLimit is int limit && limit > 0)
- {
- return string.Format(Translator.AiActions_UsageSummary, used, limit);
- }
-
- return Translator.WinoAccount_Management_AiPackUsageLoadFailed;
- }
-
- private static int GetUsedCount(AiStatusResultDto aiStatus)
- => aiStatus.Used is int used ? used : 0;
-
- private static string CreateUsageSummary(QuotaInfoDto quotaInfo)
- {
- if (quotaInfo.Used is int used && quotaInfo.MonthlyLimit is int limit && limit > 0)
- {
- return string.Format(Translator.AiActions_UsageSummary, used, limit);
- }
-
- return Translator.WinoAccount_Management_AiPackUsageLoadFailed;
- }
-
- private static int GetUsedCount(QuotaInfoDto quotaInfo)
- => quotaInfo.Used is int used ? used : 0;
-
- private static int GetUsageLimit(QuotaInfoDto quotaInfo)
- => quotaInfo.MonthlyLimit is int limit && limit > 0 ? limit : 1000;
-
- private static int GetUsageLimit(AiStatusResultDto aiStatus)
- => aiStatus.MonthlyLimit is int limit && limit > 0 ? limit : 1000;
-
-
- private void UpdatePanelState(bool showLoading = false, bool showSignedOut = false, bool showPurchase = false, bool showReady = false)
- {
- LoadingPanel.Visibility = showLoading ? Visibility.Visible : Visibility.Collapsed;
- SignedOutPanel.Visibility = showSignedOut ? Visibility.Visible : Visibility.Collapsed;
- PurchasePanel.Visibility = showPurchase ? Visibility.Visible : Visibility.Collapsed;
- ReadyPanel.Visibility = showReady ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private void UpdateUsageSummary(string usageText, int usedCount = 0)
- {
- UsageSummaryTextBlock.Text = usageText;
- UsageProgressBar.Maximum = 1000;
- UsageProgressBar.Value = Math.Min(usedCount, 1000);
- }
-
- private void UpdateUsageSummary(string usageText, int usedCount, int usageLimit)
- {
- var normalizedLimit = usageLimit > 0 ? usageLimit : 1000;
- UsageSummaryTextBlock.Text = usageText;
- UsageProgressBar.Maximum = normalizedLimit;
- UsageProgressBar.Value = Math.Min(usedCount, normalizedLimit);
- }
-
- private void SetBusyUi(bool isBusy, bool showLoading)
- {
- _isBusy = isBusy;
-
- BusyProgressBar.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
- ActionSelector.IsEnabled = !isBusy;
- TranslateLanguageComboBox.IsEnabled = !isBusy;
- SummarizeLanguageComboBox.IsEnabled = !isBusy;
- RewriteModeComboBox.IsEnabled = !isBusy;
- CustomRewriteTextBox.IsEnabled = !isBusy;
- RunTranslateButton.IsEnabled = !isBusy;
- RunRewriteButton.IsEnabled = !isBusy;
- RunSummarizeButton.IsEnabled = !isBusy;
- SignedOutPanel.IsHitTestVisible = !isBusy;
- PurchasePanel.IsHitTestVisible = !isBusy;
-
- if (showLoading)
- {
- UpdatePanelState(showLoading: true);
- }
- else if (ReadyPanel.Visibility == Visibility.Visible)
- {
- UpdatePanelState(showReady: true);
- }
- else if (SignedOutPanel.Visibility == Visibility.Visible)
- {
- UpdatePanelState(showSignedOut: true);
- }
- else if (PurchasePanel.Visibility == Visibility.Visible)
- {
- UpdatePanelState(showPurchase: true);
- }
- }
-
- private async void SignInButton_Click(object sender, RoutedEventArgs e)
- {
- if (_isBusy)
- {
- return;
- }
-
- var account = await _dialogService.ShowWinoAccountLoginDialogAsync();
- if (account != null)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info, string.Format(Translator.WinoAccount_LoginSuccessMessage, account.Email), InfoBarMessageType.Success);
- }
-
- await RefreshAvailabilityAsync();
- }
-
- private async void CreateAccountButton_Click(object sender, RoutedEventArgs e)
- {
- if (_isBusy)
- {
- return;
- }
-
- var account = await _dialogService.ShowWinoAccountRegistrationDialogAsync();
- if (account != null)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info, string.Format(Translator.WinoAccount_RegisterSuccessMessage, account.Email), InfoBarMessageType.Success);
- }
-
- await RefreshAvailabilityAsync();
- }
-
- private async void PurchaseButton_Click(object sender, RoutedEventArgs e)
- {
- if (_isBusy)
- {
- return;
- }
-
- SetBusyUi(isBusy: true, showLoading: false);
-
- try
- {
- var purchaseResult = await _storeManagementService.PurchaseAsync(WinoAddOnProductType.AI_PACK).ConfigureAwait(true);
-
- if (purchaseResult == StorePurchaseResult.NotPurchased)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error, Translator.WinoAccount_Management_PurchaseStartFailed, InfoBarMessageType.Error);
- return;
- }
-
- var syncResult = await _profileService.SyncStoreEntitlementsAsync().ConfigureAwait(true);
- if (!syncResult.IsSuccess && !string.Equals(syncResult.ErrorCode, "MissingAccessToken", StringComparison.Ordinal))
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error, Translator.WinoAccount_Management_StoreSyncFailed, InfoBarMessageType.Error);
- return;
- }
-
- if (purchaseResult == StorePurchaseResult.AlreadyPurchased)
- {
- _dialogService.InfoBarMessage(Translator.Info_PurchaseExistsTitle, Translator.Info_PurchaseExistsMessage, InfoBarMessageType.Warning);
- }
- else
- {
- _dialogService.InfoBarMessage(Translator.Info_PurchaseThankYouTitle, Translator.Info_PurchaseThankYouMessage, InfoBarMessageType.Success);
- }
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception)
- {
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error, Translator.WinoAccount_Management_PurchaseStartFailed, InfoBarMessageType.Error);
- }
- finally
- {
- SetBusyUi(isBusy: false, showLoading: false);
- await RefreshAvailabilityAsync();
- }
- }
-
- private void ActionSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (ReferenceEquals(ActionSelector.SelectedItem, TranslateSegment))
- {
- ApplySelectedAction(AiActionType.Translate);
- return;
- }
-
- if (ReferenceEquals(ActionSelector.SelectedItem, RewriteSegment))
- {
- ApplySelectedAction(AiActionType.Rewrite);
- return;
- }
-
- if (ReferenceEquals(ActionSelector.SelectedItem, SummarizeSegment))
- {
- ApplySelectedAction(AiActionType.Summarize);
- _ = RefreshCachedSummaryStateAsync();
- }
- }
-
- private void TranslateLanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (TranslateLanguageComboBox.SelectedItem is AiTranslateLanguageOption option)
- {
- SelectedTranslateLanguageOption = option;
- _preferencesService.AiDefaultTranslationLanguageCode = option.Code;
- }
- }
-
- private void RewriteModeComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (RewriteModeComboBox.SelectedItem is AiRewriteModeOption option)
- {
- SelectedRewriteModeOption = option;
- UpdateRewriteOptionState();
- }
- }
-
- private void SummarizeLanguageComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
- {
- if (SummarizeLanguageComboBox.SelectedItem is AiTranslateLanguageOption option)
- {
- SelectedSummarizeLanguageOption = option;
- _preferencesService.AiSummarizeLanguageCode = option.Code;
- }
- }
-
- private void UpdateRewriteOptionState()
- {
- var isCustom = SelectedRewriteModeOption?.IsCustom ?? false;
- RewriteDescriptionTextBlock.Text = SelectedRewriteModeOption?.Description ?? string.Empty;
- RewriteDescriptionTextBlock.Visibility = string.IsNullOrWhiteSpace(RewriteDescriptionTextBlock.Text) ? Visibility.Collapsed : Visibility.Visible;
- CustomRewriteTextBox.Visibility = isCustom ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private async void RunTranslateButton_Click(object sender, RoutedEventArgs e)
- {
- await ExecuteAiActionAsync(AiActionType.Translate);
- }
-
- private async void RunRewriteButton_Click(object sender, RoutedEventArgs e)
- {
- await ExecuteAiActionAsync(AiActionType.Rewrite);
- }
-
- private async void RunSummarizeButton_Click(object sender, RoutedEventArgs e)
- {
- await ExecuteAiActionAsync(AiActionType.Summarize);
- }
-
- private void CloseButton_Click(object sender, RoutedEventArgs e)
- {
- CancelPendingOperation();
- CloseRequested?.Invoke(this, EventArgs.Empty);
- }
-
- private async Task ExecuteAiActionAsync(AiActionType action)
- {
- if (_isBusy)
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiBusyTitle, Translator.Composer_AiBusyMessage, InfoBarMessageType.Warning);
- return;
- }
-
- if (HtmlHost == null)
- {
- return;
- }
-
- CancelAndDisposeActionCancellationToken();
- _actionCancellationTokenSource = new CancellationTokenSource();
- var cancellationToken = _actionCancellationTokenSource.Token;
-
- SetBusyUi(isBusy: true, showLoading: false);
-
- try
- {
- if (action == AiActionType.Translate && SelectedTranslateLanguageOption == null)
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, Translator.WinoAccount_Error_ValidationFailed, InfoBarMessageType.Error);
- return;
- }
-
- if (action == AiActionType.Rewrite && string.IsNullOrWhiteSpace(ResolveRewriteMode()))
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, Translator.WinoAccount_Error_ValidationFailed, InfoBarMessageType.Error);
- return;
- }
-
- if (action == AiActionType.Summarize && SelectedSummarizeLanguageOption == null)
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, Translator.WinoAccount_Error_ValidationFailed, InfoBarMessageType.Error);
- return;
- }
-
- if (action == AiActionType.Translate)
- {
- var cachedTranslation = await HtmlHost.TryGetCachedTranslationHtmlAsync(SelectedTranslateLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
-
- if (!string.IsNullOrWhiteSpace(cachedTranslation))
- {
- await HtmlHost.ApplyHtmlResultAsync(cachedTranslation, cancellationToken).ConfigureAwait(true);
- return;
- }
- }
-
- if (action == AiActionType.Summarize)
- {
- var cachedSummary = await HtmlHost.TryGetCachedSummaryTextAsync(cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
-
- if (!string.IsNullOrWhiteSpace(cachedSummary))
- {
- _hasCachedSummary = true;
- UpdateActionAvailability();
- await ShowSummaryDialogAsync(cachedSummary).ConfigureAwait(true);
- return;
- }
- }
-
- var html = await HtmlHost.GetCurrentHtmlAsync(cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
-
- if (string.IsNullOrWhiteSpace(html))
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, Translator.WinoAccount_Error_AiHtmlEmpty, InfoBarMessageType.Error);
- return;
- }
-
- var response = action switch
- {
- AiActionType.Translate => await _profileService.TranslateAsync(html, SelectedTranslateLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true),
- AiActionType.Rewrite => await _profileService.RewriteAsync(html, ResolveRewriteMode(), cancellationToken).ConfigureAwait(true),
- AiActionType.Summarize => await _profileService.SummarizeAsync(html, SelectedSummarizeLanguageOption?.Code ?? string.Empty, cancellationToken).ConfigureAwait(true),
- _ => ApiEnvelope.Failure(ApiErrorCodes.ValidationFailed)
- };
-
- cancellationToken.ThrowIfCancellationRequested();
-
- if (!response.IsSuccess || response.Result == null || string.IsNullOrWhiteSpace(response.Result.Html))
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, WinoAccountAiErrorTranslator.Format(response.ErrorCode, null), InfoBarMessageType.Error);
- return;
- }
-
- if (response.Quota != null)
- {
- UpdateUsageSummary(
- CreateUsageSummary(response.Quota),
- GetUsedCount(response.Quota),
- GetUsageLimit(response.Quota));
- }
-
- if (action == AiActionType.Translate)
- {
- await HtmlHost.SaveCachedTranslationHtmlAsync(SelectedTranslateLanguageOption?.Code ?? string.Empty, response.Result.Html, cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
- await HtmlHost.ApplyHtmlResultAsync(response.Result.Html, cancellationToken).ConfigureAwait(true);
- return;
- }
-
- if (action == AiActionType.Summarize)
- {
- await HtmlHost.SaveCachedSummaryTextAsync(response.Result.Html, cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
-
- _hasCachedSummary = true;
- UpdateActionAvailability();
-
- var savedSummary = await HtmlHost.TryGetCachedSummaryTextAsync(cancellationToken).ConfigureAwait(true);
- cancellationToken.ThrowIfCancellationRequested();
-
- await ShowSummaryDialogAsync(string.IsNullOrWhiteSpace(savedSummary) ? response.Result.Html : savedSummary).ConfigureAwait(true);
- return;
- }
-
- await HtmlHost.ApplyHtmlResultAsync(response.Result.Html, cancellationToken).ConfigureAwait(true);
- }
- catch (OperationCanceledException)
- {
- }
- catch (Exception ex)
- {
- _dialogService.InfoBarMessage(Translator.Composer_AiErrorTitle, WinoAccountAiErrorTranslator.Format(null, ex.Message), InfoBarMessageType.Error);
- }
- finally
- {
- SetBusyUi(isBusy: false, showLoading: false);
-
- if (_actionCancellationTokenSource != null)
- {
- _actionCancellationTokenSource.Dispose();
- _actionCancellationTokenSource = null;
- }
-
- // Summarize no longer auto-switches back; the user explicitly selected the tab.
- }
- }
-
- private string ResolveRewriteMode()
- {
- if (SelectedRewriteModeOption == null)
- {
- return string.Empty;
- }
-
- if (!SelectedRewriteModeOption.IsCustom)
- {
- return SelectedRewriteModeOption.Mode;
- }
-
- return CustomRewriteTextBox.Text?.Trim() ?? string.Empty;
- }
-
- private async Task RefreshCachedSummaryStateAsync()
- {
- if (HtmlHost == null || !HasAction(AiActionType.Summarize))
- {
- _hasCachedSummary = false;
- UpdateActionAvailability();
- return;
- }
-
- try
- {
- var cachedSummary = await HtmlHost.TryGetCachedSummaryTextAsync(CancellationToken.None).ConfigureAwait(true);
- _hasCachedSummary = !string.IsNullOrWhiteSpace(cachedSummary);
- }
- catch (Exception)
- {
- _hasCachedSummary = false;
- }
-
- UpdateActionAvailability();
- }
-
- private async Task ShowSummaryDialogAsync(string summary)
- {
- if (HtmlHost == null)
- {
- await _dialogService.ShowMessageAsync(summary, Translator.Composer_AiSummarize, WinoCustomMessageDialogIcon.Information);
- return;
- }
-
- var summaryTextBox = new TextBox
- {
- Text = summary,
- IsReadOnly = true,
- AcceptsReturn = true,
- TextWrapping = TextWrapping.Wrap,
- MinHeight = 240,
- MaxHeight = 420,
- BorderThickness = new Thickness(0),
- Background = new SolidColorBrush(Windows.UI.Color.FromArgb(0, 0, 0, 0))
- };
-
- var dialog = new ContentDialog
- {
- XamlRoot = XamlRoot,
- RequestedTheme = ActualTheme,
- Title = Translator.Composer_AiSummarize,
- PrimaryButtonText = Translator.Buttons_Save,
- SecondaryButtonText = Translator.Buttons_Close,
- DefaultButton = ContentDialogButton.Secondary,
- Content = new ScrollViewer
- {
- Content = summaryTextBox,
- VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
- HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled
- }
- };
-
- dialog.PrimaryButtonClick += async (sender, args) =>
- {
- var deferral = args.GetDeferral();
-
- try
- {
- var configuredSummarySavePath = _preferencesService.AiSummarySavePath;
- var path = !string.IsNullOrWhiteSpace(configuredSummarySavePath) && Directory.Exists(configuredSummarySavePath)
- ? Path.Combine(configuredSummarySavePath, HtmlHost.GetSuggestedSummaryFileName())
- : await _dialogService.PickFilePathAsync(HtmlHost.GetSuggestedSummaryFileName());
-
- if (string.IsNullOrWhiteSpace(path))
- {
- args.Cancel = true;
- return;
- }
-
- await File.WriteAllTextAsync(path, summary);
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Info, string.Format(Translator.ClipboardTextCopied_Message, Path.GetFileName(path)), InfoBarMessageType.Success);
- }
- catch (Exception ex)
- {
- args.Cancel = true;
- _dialogService.InfoBarMessage(Translator.GeneralTitle_Error, ex.Message, InfoBarMessageType.Error);
- }
- finally
- {
- deferral.Complete();
- }
- };
-
- await dialog.ShowAsync();
- }
-
- private void CancelAndDisposeActionCancellationToken()
- {
- if (_actionCancellationTokenSource == null)
- {
- return;
- }
-
- _actionCancellationTokenSource.Cancel();
- _actionCancellationTokenSource.Dispose();
- _actionCancellationTokenSource = null;
- }
-}
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml b/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml
deleted file mode 100644
index 61abaae1..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
- 520
- 520
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml.cs
deleted file mode 100644
index f839afcc..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountEmailConfirmationRequiredDialog.xaml.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using System;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Wino.Core.Domain;
-using Wino.Core.Domain.Interfaces;
-using Wino.Mail.Api.Contracts.Auth;
-using Wino.Mail.WinUI.Services;
-
-namespace Wino.Dialogs;
-
-public sealed partial class WinoAccountEmailConfirmationRequiredDialog : ContentDialog
-{
- private readonly IWinoAccountProfileService _profileService;
- private readonly DispatcherTimer _countdownTimer;
- private readonly string _email;
- private readonly string _endpoint;
- private readonly string _ticket;
- private DateTimeOffset _resendAvailableAtUtc;
-
- public WinoAccountEmailConfirmationRequiredDialog(IWinoAccountProfileService profileService, string email, EmailConfirmationRequiredDetailsDto details)
- {
- _profileService = profileService;
- _email = email;
- _endpoint = details.ResendConfirmationEndpoint;
- _ticket = details.ResendConfirmationTicket;
- _resendAvailableAtUtc = details.ResendAvailableAtUtc;
-
- InitializeComponent();
-
- MessageTextBlock.Text = string.Format(Translator.WinoAccount_EmailConfirmationPendingDialog_Message, email);
-
- _countdownTimer = new DispatcherTimer
- {
- Interval = TimeSpan.FromSeconds(1)
- };
- _countdownTimer.Tick += CountdownTimer_Tick;
-
- Closing += DialogClosing;
-
- UpdateCountdown();
- _countdownTimer.Start();
- }
-
- public bool ResendSucceeded { get; private set; }
-
- private async void ResendClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
- {
- args.Cancel = true;
-
- if (DateTimeOffset.UtcNow < _resendAvailableAtUtc)
- {
- UpdateCountdown();
- return;
- }
-
- var deferral = args.GetDeferral();
-
- try
- {
- SetBusyState(true);
- HideError();
-
- var response = await _profileService.ResendEmailConfirmationAsync(_endpoint, _ticket);
- if (!response.IsSuccess)
- {
- ShowError(WinoAccountAuthErrorTranslator.Translate(response.ErrorCode));
- return;
- }
-
- ResendSucceeded = true;
- Hide();
- }
- finally
- {
- SetBusyState(false);
- deferral.Complete();
- }
- }
-
- private void CountdownTimer_Tick(object? sender, object e) => UpdateCountdown();
-
- private void UpdateCountdown()
- {
- var remaining = _resendAvailableAtUtc - DateTimeOffset.UtcNow;
- if (remaining <= TimeSpan.Zero)
- {
- IsPrimaryButtonEnabled = true;
- CountdownTextBlock.Text = Translator.WinoAccount_EmailConfirmationPendingDialog_ReadyToResend;
- return;
- }
-
- IsPrimaryButtonEnabled = false;
- CountdownTextBlock.Text = string.Format(
- Translator.WinoAccount_EmailConfirmationPendingDialog_Countdown,
- $"{Math.Max(0, (int)remaining.TotalMinutes):00}:{Math.Max(0, remaining.Seconds):00}");
- }
-
- private void SetBusyState(bool isBusy)
- {
- IsPrimaryButtonEnabled = !isBusy && DateTimeOffset.UtcNow >= _resendAvailableAtUtc;
- IsSecondaryButtonEnabled = !isBusy;
- BusyRing.IsActive = isBusy;
- BusyRing.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private void ShowError(string message)
- {
- ErrorTextBlock.Text = message;
- ErrorTextBlock.Visibility = Visibility.Visible;
- }
-
- private void HideError()
- {
- ErrorTextBlock.Text = string.Empty;
- ErrorTextBlock.Visibility = Visibility.Collapsed;
- }
-
- private void DialogClosing(ContentDialog sender, ContentDialogClosingEventArgs args)
- {
- _countdownTimer.Stop();
- _countdownTimer.Tick -= CountdownTimer_Tick;
- Closing -= DialogClosing;
- }
-}
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml b/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml
deleted file mode 100644
index 23485a6a..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml
+++ /dev/null
@@ -1,273 +0,0 @@
-
-
-
- 520
- 520
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml.cs
deleted file mode 100644
index de1102f4..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountLoginDialog.xaml.cs
+++ /dev/null
@@ -1,201 +0,0 @@
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Input;
-using Windows.System;
-using Wino.Core.Domain;
-using Wino.Core.Domain.Entities.Shared;
-using Wino.Core.Domain.Interfaces;
-using Wino.Mail.Api.Contracts.Auth;
-using Wino.Mail.WinUI.Services;
-
-namespace Wino.Dialogs;
-
-public sealed partial class WinoAccountLoginDialog : ContentDialog
-{
- private readonly IWinoAccountProfileService _profileService;
- private bool _isForgotPasswordMode;
-
- public WinoAccountLoginDialog(IWinoAccountProfileService profileService)
- {
- _profileService = profileService;
- InitializeComponent();
- UpdateMode();
- }
-
- public WinoAccount? Result { get; private set; }
- public string? PendingConfirmationEmailAddress { get; private set; }
- public EmailConfirmationRequiredDetailsDto? EmailConfirmationRequiredDetails { get; private set; }
- public string? PasswordResetEmailAddress { get; private set; }
-
- private async void LoginClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
- {
- args.Cancel = true;
-
- var validationError = ValidateInput();
- if (!string.IsNullOrWhiteSpace(validationError))
- {
- ShowError(validationError);
- return;
- }
-
- var deferral = args.GetDeferral();
-
- try
- {
- await PerformPrimaryActionAsync();
- }
- finally
- {
- deferral.Complete();
- }
- }
-
- private async System.Threading.Tasks.Task PerformPrimaryActionAsync()
- {
- var validationError = ValidateInput();
- if (!string.IsNullOrWhiteSpace(validationError))
- {
- ShowError(validationError);
- return;
- }
-
- try
- {
- SetBusyState(true);
- HideError();
-
- if (_isForgotPasswordMode)
- {
- var forgotPasswordResponse = await _profileService.ForgotPasswordAsync(EmailTextBox.Text.Trim());
- if (!forgotPasswordResponse.IsSuccess)
- {
- ShowError(WinoAccountAuthErrorTranslator.Translate(forgotPasswordResponse.ErrorCode));
- return;
- }
-
- PasswordResetEmailAddress = EmailTextBox.Text.Trim();
- Hide();
- return;
- }
-
- var result = await _profileService.LoginAsync(EmailTextBox.Text.Trim(), PasswordBox.Password);
-
- if (!result.IsSuccess || result.Account == null)
- {
- var confirmationDetails = WinoAccountEmailConfirmationHelper.Parse(result.ErrorDetails);
- if (WinoAccountEmailConfirmationHelper.IsEmailConfirmationRequiredError(result.ErrorCode) && confirmationDetails != null)
- {
- PendingConfirmationEmailAddress = EmailTextBox.Text.Trim();
- EmailConfirmationRequiredDetails = confirmationDetails;
- Hide();
- return;
- }
-
- ShowError(WinoAccountAuthErrorTranslator.Format(result.ErrorCode, result.ErrorMessage));
- return;
- }
-
- Result = result.Account;
- Hide();
- }
- finally
- {
- SetBusyState(false);
- }
- }
-
- private string ValidateInput()
- {
- if (string.IsNullOrWhiteSpace(EmailTextBox.Text))
- {
- return Translator.WinoAccount_Validation_EmailRequired;
- }
-
- if (_isForgotPasswordMode)
- {
- return string.Empty;
- }
-
- if (string.IsNullOrWhiteSpace(PasswordBox.Password))
- {
- return Translator.WinoAccount_Validation_PasswordRequired;
- }
-
- return string.Empty;
- }
-
- private async void EmailTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key == VirtualKey.Enter)
- {
- if (_isForgotPasswordMode)
- {
- e.Handled = true;
- await PerformPrimaryActionAsync();
- return;
- }
-
- PasswordBox.Focus(FocusState.Programmatic);
- e.Handled = true;
- }
- }
-
- private async void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key == VirtualKey.Enter)
- {
- e.Handled = true;
- await PerformPrimaryActionAsync();
- }
- }
-
- private void ModeToggleButton_Click(object sender, RoutedEventArgs e)
- {
- _isForgotPasswordMode = !_isForgotPasswordMode;
- PasswordBox.Password = string.Empty;
- HideError();
- UpdateMode();
- }
-
- private void InputChanged(TextBox sender, TextBoxTextChangingEventArgs args) => HideError();
-
- private void InputChanged(object sender, RoutedEventArgs e) => HideError();
-
- private void SetBusyState(bool isBusy)
- {
- IsPrimaryButtonEnabled = !isBusy;
- IsSecondaryButtonEnabled = !isBusy;
- BusyRing.IsActive = isBusy;
- BusyRing.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private void ShowError(string message)
- {
- ErrorTextBlock.Text = message;
- ErrorTextBlock.Visibility = Visibility.Visible;
- }
-
- private void HideError()
- {
- ErrorTextBlock.Text = string.Empty;
- ErrorTextBlock.Visibility = Visibility.Collapsed;
- }
-
- private void UpdateMode()
- {
- Title = _isForgotPasswordMode
- ? Translator.WinoAccount_ForgotPasswordDialog_Title
- : Translator.WinoAccount_LoginDialog_Title;
-
- PrimaryButtonText = _isForgotPasswordMode
- ? Translator.WinoAccount_ForgotPasswordDialog_PrimaryButton
- : Translator.Buttons_SignIn;
-
- BenefitsPanel.Visibility = _isForgotPasswordMode ? Visibility.Collapsed : Visibility.Visible;
- PasswordPanel.Visibility = _isForgotPasswordMode ? Visibility.Collapsed : Visibility.Visible;
- ForgotPasswordInfoPanel.Visibility = _isForgotPasswordMode ? Visibility.Visible : Visibility.Collapsed;
- ModeToggleButton.Content = _isForgotPasswordMode
- ? Translator.WinoAccount_ForgotPasswordDialog_BackToSignIn
- : Translator.WinoAccount_LoginDialog_ForgotPasswordLink;
- }
-}
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml b/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml
deleted file mode 100644
index a36ba89c..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml
+++ /dev/null
@@ -1,300 +0,0 @@
-
-
-
- 560
- 560
- 900
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml.cs
deleted file mode 100644
index 50d43ec1..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountRegistrationDialog.xaml.cs
+++ /dev/null
@@ -1,161 +0,0 @@
-using System;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Microsoft.UI.Xaml.Input;
-using Windows.System;
-using Wino.Core.Domain;
-using Wino.Core.Domain.Entities.Shared;
-using Wino.Core.Domain.Interfaces;
-using Wino.Mail.WinUI.Services;
-
-namespace Wino.Dialogs;
-
-public sealed partial class WinoAccountRegistrationDialog : ContentDialog
-{
- private const string PrivacyPolicyUrl = "https://www.winomail.app/accounts_policy.html";
- private readonly IWinoAccountProfileService _profileService;
-
- public WinoAccountRegistrationDialog(IWinoAccountProfileService profileService)
- {
- _profileService = profileService;
- InitializeComponent();
- }
-
- public WinoAccount? Result { get; private set; }
- public string? ConfirmationEmailAddress { get; private set; }
-
- private async void RegisterClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
- {
- args.Cancel = true;
-
- var validationError = ValidateInput();
- if (!string.IsNullOrWhiteSpace(validationError))
- {
- ShowError(validationError);
- return;
- }
-
- var deferral = args.GetDeferral();
-
- try
- {
- await PerformRegistrationAsync();
- }
- finally
- {
- deferral.Complete();
- }
- }
-
- private async System.Threading.Tasks.Task PerformRegistrationAsync()
- {
- var validationError = ValidateInput();
- if (!string.IsNullOrWhiteSpace(validationError))
- {
- ShowError(validationError);
- return;
- }
-
- try
- {
- SetBusyState(true);
- HideError();
-
- var result = await _profileService.RegisterAsync(EmailTextBox.Text.Trim(), PasswordBox.Password);
-
- if (!result.IsSuccess || result.Account == null)
- {
- ShowError(WinoAccountAuthErrorTranslator.Format(result.ErrorCode, result.ErrorMessage));
- return;
- }
-
- ConfirmationEmailAddress = result.Account.Email;
- Hide();
- }
- finally
- {
- SetBusyState(false);
- }
- }
-
- private string ValidateInput()
- {
- if (string.IsNullOrWhiteSpace(EmailTextBox.Text))
- {
- return Translator.WinoAccount_Validation_EmailRequired;
- }
-
- if (string.IsNullOrWhiteSpace(PasswordBox.Password))
- {
- return Translator.WinoAccount_Validation_PasswordRequired;
- }
-
- if (!string.Equals(PasswordBox.Password, ConfirmPasswordBox.Password, StringComparison.Ordinal))
- {
- return Translator.WinoAccount_Validation_PasswordMismatch;
- }
-
- if (PrivacyPolicyCheckBox.IsChecked != true)
- {
- return Translator.WinoAccount_Validation_PrivacyConsentRequired;
- }
-
- return string.Empty;
- }
-
- private void EmailTextBox_KeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key == VirtualKey.Enter)
- {
- PasswordBox.Focus(FocusState.Programmatic);
- e.Handled = true;
- }
- }
-
- private void PasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key == VirtualKey.Enter)
- {
- ConfirmPasswordBox.Focus(FocusState.Programmatic);
- e.Handled = true;
- }
- }
-
- private async void ConfirmPasswordBox_KeyDown(object sender, KeyRoutedEventArgs e)
- {
- if (e.Key == VirtualKey.Enter)
- {
- e.Handled = true;
- await PerformRegistrationAsync();
- }
- }
-
- private async void PrivacyPolicyLink_Click(object sender, RoutedEventArgs e)
- {
- await Launcher.LaunchUriAsync(new Uri(PrivacyPolicyUrl));
- }
-
- private void InputChanged(TextBox sender, TextBoxTextChangingEventArgs args) => HideError();
-
- private void InputChanged(object sender, RoutedEventArgs e) => HideError();
-
- private void SetBusyState(bool isBusy)
- {
- IsPrimaryButtonEnabled = !isBusy;
- IsSecondaryButtonEnabled = !isBusy;
- BusyRing.IsActive = isBusy;
- BusyRing.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
- }
-
- private void ShowError(string message)
- {
- ErrorTextBlock.Text = message;
- ErrorTextBlock.Visibility = Visibility.Visible;
- }
-
- private void HideError()
- {
- ErrorTextBlock.Text = string.Empty;
- ErrorTextBlock.Visibility = Visibility.Collapsed;
- }
-}
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml b/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml
deleted file mode 100644
index ce3a3231..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml
+++ /dev/null
@@ -1,76 +0,0 @@
-
-
-
- 520
- 520
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml.cs b/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml.cs
deleted file mode 100644
index 4c5a07ad..00000000
--- a/Wino.Mail.WinUI/Dialogs/WinoAccountSyncExportDialog.xaml.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-using System;
-using Microsoft.UI.Xaml;
-using Microsoft.UI.Xaml.Controls;
-using Wino.Core.Domain.Interfaces;
-using Wino.Core.Domain.Models.Accounts;
-
-namespace Wino.Dialogs;
-
-public sealed partial class WinoAccountSyncExportDialog : ContentDialog
-{
- private readonly IWinoAccountDataSyncService _syncService;
- private bool _isBusy;
-
- public WinoAccountSyncExportDialog(IWinoAccountDataSyncService syncService)
- {
- _syncService = syncService;
- InitializeComponent();
- UpdateButtonState();
- }
-
- public WinoAccountSyncExportResult? Result { get; private set; }
-
- public Exception? FailureException { get; private set; }
-
- private async void ExportClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
- {
- args.Cancel = true;
-
- if (!HasSelection())
- {
- return;
- }
-
- var deferral = args.GetDeferral();
-
- try
- {
- SetBusyState(true);
- FailureException = null;
- Result = await _syncService.ExportAsync(new WinoAccountSyncSelection(
- PreferencesCheckBox.IsChecked == true,
- AccountsCheckBox.IsChecked == true));
- Hide();
- }
- catch (Exception ex)
- {
- FailureException = ex;
- Hide();
- }
- finally
- {
- SetBusyState(false);
- deferral.Complete();
- }
- }
-
- private void SelectionChanged(object sender, RoutedEventArgs e)
- => UpdateButtonState();
-
- private void SetBusyState(bool isBusy)
- {
- _isBusy = isBusy;
- ProgressPanel.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
- IsSecondaryButtonEnabled = !isBusy;
- UpdateButtonState();
- }
-
- private void UpdateButtonState()
- => IsPrimaryButtonEnabled = !_isBusy && HasSelection();
-
- private bool HasSelection()
- => PreferencesCheckBox.IsChecked == true || AccountsCheckBox.IsChecked == true;
-}
diff --git a/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs b/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs
index 6bfa1bbf..1d86168e 100644
--- a/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs
+++ b/Wino.Mail.WinUI/Selectors/NavigationMenuTemplateSelector.cs
@@ -17,7 +17,6 @@ public partial class NavigationMenuTemplateSelector : DataTemplateSelector
public DataTemplate SettingsItemTemplate { get; set; } = null!;
public DataTemplate SettingsShellPageItemTemplate { get; set; } = null!;
public DataTemplate SettingsShellSectionItemTemplate { get; set; } = null!;
- public DataTemplate WinoAccountSettingsShellPageItemTemplate { get; set; } = null!;
public DataTemplate StoreUpdateItemTemplate { get; set; } = null!;
public DataTemplate MoreItemsFolderTemplate { get; set; } = null!;
public DataTemplate RatingItemTemplate { get; set; } = null!;
@@ -40,10 +39,8 @@ public partial class NavigationMenuTemplateSelector : DataTemplateSelector
return ContactsMenuItemTemplate;
else if (item is SettingsItem)
return SettingsItemTemplate;
- else if (item is SettingsShellPageMenuItem settingsShellPageMenuItem)
- return string.Equals(settingsShellPageMenuItem.Title, Translator.WinoAccount_SettingsSection_Title, System.StringComparison.Ordinal)
- ? WinoAccountSettingsShellPageItemTemplate
- : SettingsShellPageItemTemplate;
+ else if (item is SettingsShellPageMenuItem)
+ return SettingsShellPageItemTemplate;
else if (item is SettingsShellSectionMenuItem)
return SettingsShellSectionItemTemplate;
else if (item is StoreUpdateMenuItem)
diff --git a/Wino.Mail.WinUI/Services/DialogService.cs b/Wino.Mail.WinUI/Services/DialogService.cs
index 61cd9fe3..52f0bfc6 100644
--- a/Wino.Mail.WinUI/Services/DialogService.cs
+++ b/Wino.Mail.WinUI/Services/DialogService.cs
@@ -27,17 +27,10 @@ namespace Wino.Services;
public class DialogService : DialogServiceBase, IMailDialogService
{
- private readonly IWinoAccountProfileService _winoAccountProfileService;
- private readonly IWinoAccountDataSyncService _winoAccountDataSyncService;
-
public DialogService(INewThemeService themeService,
IConfigurationService configurationService,
- IApplicationResourceManager applicationResourceManager,
- IWinoAccountProfileService winoAccountProfileService,
- IWinoAccountDataSyncService winoAccountDataSyncService) : base(themeService, configurationService, applicationResourceManager)
+ IApplicationResourceManager applicationResourceManager) : base(themeService, configurationService, applicationResourceManager)
{
- _winoAccountProfileService = winoAccountProfileService;
- _winoAccountDataSyncService = winoAccountDataSyncService;
}
public void ShowReadOnlyCalendarMessage()
@@ -274,82 +267,4 @@ public class DialogService : DialogServiceBase, IMailDialogService
return null;
}
- public async Task ShowWinoAccountRegistrationDialogAsync()
- {
- var dialog = new WinoAccountRegistrationDialog(_winoAccountProfileService)
- {
- RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
- };
-
- await HandleDialogPresentationAsync(dialog);
-
- if (!string.IsNullOrWhiteSpace(dialog.ConfirmationEmailAddress))
- {
- await ShowMessageAsync(
- string.Format(Translator.WinoAccount_EmailConfirmationSentDialog_Message, dialog.ConfirmationEmailAddress),
- Translator.WinoAccount_EmailConfirmationSentDialog_Title);
- }
-
- return null;
- }
-
- public async Task ShowWinoAccountLoginDialogAsync()
- {
- var dialog = new WinoAccountLoginDialog(_winoAccountProfileService)
- {
- RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
- };
-
- var result = await HandleDialogPresentationAsync(dialog);
-
- if (dialog.EmailConfirmationRequiredDetails != null && !string.IsNullOrWhiteSpace(dialog.PendingConfirmationEmailAddress))
- {
- var confirmationDialog = new WinoAccountEmailConfirmationRequiredDialog(
- _winoAccountProfileService,
- dialog.PendingConfirmationEmailAddress,
- dialog.EmailConfirmationRequiredDetails)
- {
- RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
- };
-
- await HandleDialogPresentationAsync(confirmationDialog);
-
- if (confirmationDialog.ResendSucceeded)
- {
- await ShowMessageAsync(
- string.Format(Translator.WinoAccount_EmailConfirmationResentDialog_Message, dialog.PendingConfirmationEmailAddress),
- Translator.WinoAccount_EmailConfirmationResentDialog_Title);
- }
-
- return null;
- }
-
- if (!string.IsNullOrWhiteSpace(dialog.PasswordResetEmailAddress))
- {
- await ShowMessageAsync(
- string.Format(Translator.WinoAccount_ForgotPasswordDialog_SuccessMessage, dialog.PasswordResetEmailAddress),
- Translator.WinoAccount_ForgotPasswordDialog_SuccessTitle);
-
- return null;
- }
-
- return dialog.Result;
- }
-
- public async Task ShowWinoAccountExportDialogAsync()
- {
- var dialog = new WinoAccountSyncExportDialog(_winoAccountDataSyncService)
- {
- RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
- };
-
- await HandleDialogPresentationAsync(dialog);
-
- if (dialog.FailureException != null)
- {
- throw dialog.FailureException;
- }
-
- return dialog.Result;
- }
}
diff --git a/Wino.Mail.WinUI/Services/NavigationService.cs b/Wino.Mail.WinUI/Services/NavigationService.cs
index f2e21a9a..84aaec1f 100644
--- a/Wino.Mail.WinUI/Services/NavigationService.cs
+++ b/Wino.Mail.WinUI/Services/NavigationService.cs
@@ -91,7 +91,6 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.EmailTemplatesPage,
WinoPage.CreateEmailTemplatePage,
WinoPage.StoragePage,
- WinoPage.WinoAccountManagementPage,
WinoPage.CalendarSettingsPage,
WinoPage.CalendarRenderingSettingsPage,
WinoPage.CalendarNotificationSettingsPage,
@@ -163,7 +162,6 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.EmailTemplatesPage => typeof(EmailTemplatesPage),
WinoPage.CreateEmailTemplatePage => typeof(CreateEmailTemplatePage),
WinoPage.StoragePage => typeof(StoragePage),
- WinoPage.WinoAccountManagementPage => typeof(WinoAccountManagementPage),
WinoPage.WelcomeHostPage => typeof(WelcomeHostPage),
WinoPage.ProviderSelectionPage => typeof(ProviderSelectionPage),
WinoPage.AccountSetupProgressPage => typeof(AccountSetupProgressPage),
diff --git a/Wino.Mail.WinUI/Services/PreferencesService.cs b/Wino.Mail.WinUI/Services/PreferencesService.cs
index 9a368132..0d84eefe 100644
--- a/Wino.Mail.WinUI/Services/PreferencesService.cs
+++ b/Wino.Mail.WinUI/Services/PreferencesService.cs
@@ -405,17 +405,6 @@ public class PreferencesService(IConfigurationService configurationService) : Ob
set => SetPropertyAndSave(nameof(IsSystemTrayIconEnabled), value);
}
- public bool IsWinoAccountButtonHidden
- {
- get => _configurationService.Get(nameof(IsWinoAccountButtonHidden), false);
- set => SetPropertyAndSave(nameof(IsWinoAccountButtonHidden), value);
- }
-
- public bool IsAiActionsPanelHidden
- {
- get => _configurationService.Get(nameof(IsAiActionsPanelHidden), false);
- set => SetPropertyAndSave(nameof(IsAiActionsPanelHidden), value);
- }
public string AiDefaultTranslationLanguageCode
{
diff --git a/Wino.Mail.WinUI/ShellWindow.xaml b/Wino.Mail.WinUI/ShellWindow.xaml
index c35d9eda..70ae335e 100644
--- a/Wino.Mail.WinUI/ShellWindow.xaml
+++ b/Wino.Mail.WinUI/ShellWindow.xaml
@@ -119,194 +119,6 @@
-
diff --git a/Wino.Mail.WinUI/ShellWindow.xaml.cs b/Wino.Mail.WinUI/ShellWindow.xaml.cs
index c11f9344..9506c733 100644
--- a/Wino.Mail.WinUI/ShellWindow.xaml.cs
+++ b/Wino.Mail.WinUI/ShellWindow.xaml.cs
@@ -34,16 +34,12 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
IRecipient,
IRecipient,
IRecipient,
- IRecipient,
- IRecipient,
- IRecipient
+ IRecipient
{
private bool _allowClose;
public IStatePersistanceService StatePersistanceService { get; } = WinoApplication.Current.Services.GetService() ?? throw new Exception("StatePersistanceService not registered in DI container.");
public IPreferencesService PreferencesService { get; } = WinoApplication.Current.Services.GetService() ?? throw new Exception("PreferencesService not registered in DI container.");
public INavigationService NavigationService { get; } = WinoApplication.Current.Services.GetService() ?? throw new Exception("NavigationService not registered in DI container.");
- private IMailDialogService MailDialogService { get; } = WinoApplication.Current.Services.GetRequiredService();
- private IWinoAccountProfileService WinoAccountProfileService { get; } = WinoApplication.Current.Services.GetRequiredService();
public ObservableCollection SyncActionItems { get; } = new();
private bool _calendarReminderServerStartAttempted;
@@ -210,15 +206,6 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
});
}
- public void Receive(WinoAccountProfileUpdatedMessage message)
- {
- DispatcherQueue.TryEnqueue(() => UpdateWinoAccountState(message.Account));
- }
-
- public void Receive(WinoAccountProfileDeletedMessage message)
- {
- DispatcherQueue.TryEnqueue(() => UpdateWinoAccountState(null));
- }
private void UpdateSyncStatusVisibility()
{
@@ -426,8 +413,6 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
WeakReferenceMessenger.Default.Register(this);
WeakReferenceMessenger.Default.Register(this);
WeakReferenceMessenger.Default.Register(this);
- WeakReferenceMessenger.Default.Register(this);
- WeakReferenceMessenger.Default.Register(this);
}
private void UnregisterRecipients()
@@ -437,8 +422,6 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
WeakReferenceMessenger.Default.Unregister(this);
WeakReferenceMessenger.Default.Unregister(this);
WeakReferenceMessenger.Default.Unregister(this);
- WeakReferenceMessenger.Default.Unregister(this);
- WeakReferenceMessenger.Default.Unregister(this);
}
private void ShowInfoBarMessage(InfoBarMessageRequested message)
@@ -465,29 +448,6 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
});
}
- private void UpdateWinoAccountState(WinoAccount? account)
- {
- var isSignedIn = account != null;
-
- WinoAccountSignedOutView.Visibility = isSignedIn ? Visibility.Collapsed : Visibility.Visible;
- WinoAccountSignedInView.Visibility = isSignedIn ? Visibility.Visible : Visibility.Collapsed;
-
- WinoAccountButtonPicture.Visibility = isSignedIn ? Visibility.Visible : Visibility.Collapsed;
- WinoAccountSignedOutIcon.Visibility = isSignedIn ? Visibility.Collapsed : Visibility.Visible;
-
- var initials = GetInitials(account?.Email);
-
- WinoAccountButtonPicture.Initials = initials;
- WinoAccountFlyoutPicture.Initials = initials;
- WinoAccountButtonPicture.DisplayName = account?.Email ?? Translator.WinoAccount_Titlebar_SignedOutTitle;
- WinoAccountFlyoutPicture.DisplayName = account?.Email ?? Translator.WinoAccount_Titlebar_SignedOutTitle;
-
- WinoAccountFlyoutEmailText.Text = account?.Email ?? string.Empty;
- WinoAccountFlyoutStatusText.Text = account == null
- ? string.Empty
- : string.Format(Translator.WinoAccount_Titlebar_SignedInStatus, account.AccountStatus);
- }
-
private static string GetInitials(string? email)
{
if (string.IsNullOrWhiteSpace(email))
@@ -510,50 +470,5 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
return string.Concat(segments.Select(segment => char.ToUpperInvariant(segment[0])));
}
- private async void RegisterWinoAccountClicked(object sender, RoutedEventArgs e)
- {
- WinoAccountFlyout.Hide();
- var account = await MailDialogService.ShowWinoAccountRegistrationDialogAsync();
- if (account != null)
- {
- ShowInfoBarMessage(new InfoBarMessageRequested(
- InfoBarMessageType.Success,
- Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_RegisterSuccessMessage, account.Email)));
- }
- }
-
- private async void LoginWinoAccountClicked(object sender, RoutedEventArgs e)
- {
- WinoAccountFlyout.Hide();
- var account = await MailDialogService.ShowWinoAccountLoginDialogAsync();
- if (account != null)
- {
- ShowInfoBarMessage(new InfoBarMessageRequested(
- InfoBarMessageType.Success,
- Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_LoginSuccessMessage, account.Email)));
- }
- }
-
- private async void SignOutWinoAccountClicked(object sender, RoutedEventArgs e)
- {
- var activeAccount = await WinoAccountProfileService.GetActiveAccountAsync();
- if (activeAccount == null)
- {
- ShowInfoBarMessage(new InfoBarMessageRequested(
- InfoBarMessageType.Warning,
- Translator.GeneralTitle_Info,
- Translator.WinoAccount_SignOut_NoAccountMessage));
- return;
- }
-
- await WinoAccountProfileService.SignOutAsync();
-
- ShowInfoBarMessage(new InfoBarMessageRequested(
- InfoBarMessageType.Success,
- Translator.GeneralTitle_Info,
- string.Format(Translator.WinoAccount_SignOut_SuccessMessage, activeAccount.Email)));
- }
}
diff --git a/Wino.Mail.WinUI/Views/Abstract/WinoAccountManagementPageAbstract.cs b/Wino.Mail.WinUI/Views/Abstract/WinoAccountManagementPageAbstract.cs
deleted file mode 100644
index ee436e61..00000000
--- a/Wino.Mail.WinUI/Views/Abstract/WinoAccountManagementPageAbstract.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-using Wino.Core.ViewModels;
-
-namespace Wino.Views.Abstract;
-
-public abstract class WinoAccountManagementPageAbstract : SettingsPageBase
-{
-}
diff --git a/Wino.Mail.WinUI/Views/Mail/ComposePage.xaml b/Wino.Mail.WinUI/Views/Mail/ComposePage.xaml
index 011fa126..2429d5bf 100644
--- a/Wino.Mail.WinUI/Views/Mail/ComposePage.xaml
+++ b/Wino.Mail.WinUI/Views/Mail/ComposePage.xaml
@@ -160,18 +160,6 @@
Visibility="{x:Bind ViewModel.IsDraftBusy, Mode=OneWay}">
-
-
-
-
-
-
WebViewEditor.GetUnderlyingWebView();
- public Visibility GetAiActionsToggleVisibility(bool isHidden) => isHidden ? Visibility.Collapsed : Visibility.Visible;
public Visibility GetPopOutButtonVisibility() => SupportsPopOut ? Visibility.Visible : Visibility.Collapsed;
- public Visibility GetAiActionsPanelVisibility(bool? isChecked, bool isHidden)
- => !isHidden && isChecked == true ? Visibility.Visible : Visibility.Collapsed;
-
private readonly List _disposables = [];
public ComposePage()
@@ -343,11 +339,6 @@ public sealed partial class ComposePage : ComposePageAbstract,
HostActionRequested?.Invoke(this, new PopoutHostActionRequestedEventArgs(PopoutHostActionKind.CloseHostedInstance));
}
- private async void ComposeAiActionsToggleButton_Checked(object sender, RoutedEventArgs e)
- {
- await ComposeAiActionsPanel.RefreshAvailabilityAsync();
- }
-
private async void TokenItemAdding(TokenizingTextBox sender, TokenItemAddingEventArgs args)
{
var deferral = args.GetDeferral();
@@ -504,7 +495,6 @@ public sealed partial class ComposePage : ComposePageAbstract,
base.OnNavigatingFrom(e);
FocusManager.GotFocus -= GlobalFocusManagerGotFocus;
- ComposeAiActionsPanel.CancelPendingOperation();
await ViewModel.UpdateMimeChangesAsync();
ViewModel.SaveHTMLasPDFFunc = null;
ViewModel.RenderHtmlBodyAsyncFunc = null;
diff --git a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml
index 4f6cdccb..7d9233f1 100644
--- a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml
+++ b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml
@@ -269,7 +269,7 @@
Grid.Row="1"
HorizontalContentAlignment="Stretch"
DefaultLabelPosition="Right"
- IsAIActionsPaneToggleVisible="{x:Bind GetAiActionsToggleVisible(ViewModel.PreferencesService.IsAiActionsPanelHidden), Mode=OneWay}"
+ IsAIActionsPaneToggleVisible="False"
IsEditorThemeDark="{x:Bind ViewModel.IsDarkWebviewRenderer, Mode=TwoWay}"
IsEditorThemeToggleVisible="True"
IsPopOutButtonVisible="{x:Bind SupportsPopOut, Mode=OneWay}"
@@ -411,13 +411,6 @@
-
diff --git a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs
index 31b7fcdb..bea07abe 100644
--- a/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs
+++ b/Wino.Mail.WinUI/Views/Mail/MailRenderingPage.xaml.cs
@@ -49,9 +49,6 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
public event EventHandler? HostActionRequested;
public WebView2 GetWebView() => Chromium;
- public bool GetAiActionsToggleVisible(bool isHidden) => !isHidden;
- public Visibility GetAiActionsPanelVisibility(bool isEnabled, bool isHidden)
- => !isHidden && isEnabled ? Visibility.Visible : Visibility.Collapsed;
public MailRenderingPage()
{
@@ -179,7 +176,6 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
RendererCommandBar.AIActionsEnabledChanged -= RendererCommandBar_AIActionsEnabledChanged;
RendererCommandBar.PopOutClicked -= RendererCommandBar_PopOutClicked;
RendererCommandBar.IsAIActionsEnabled = false;
- ReaderAiActionsPanel.CancelPendingOperation();
DisposeWebView2();
}
@@ -206,7 +202,6 @@ public sealed partial class MailRenderingPage : MailRenderingPageAbstract,
{
if (isEnabled)
{
- await ReaderAiActionsPanel.RefreshAvailabilityAsync();
}
}
diff --git a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
index aae7fdd3..5d3201e8 100644
--- a/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
+++ b/Wino.Mail.WinUI/Views/Settings/AppPreferencesPage.xaml
@@ -137,19 +137,6 @@
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml b/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml
deleted file mode 100644
index daeb3d4c..00000000
--- a/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml
+++ /dev/null
@@ -1,398 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml.cs b/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml.cs
deleted file mode 100644
index f2c28075..00000000
--- a/Wino.Mail.WinUI/Views/Settings/WinoAccountManagementPage.xaml.cs
+++ /dev/null
@@ -1,11 +0,0 @@
-using Wino.Views.Abstract;
-
-namespace Wino.Views.Settings;
-
-public sealed partial class WinoAccountManagementPage : WinoAccountManagementPageAbstract
-{
- public WinoAccountManagementPage()
- {
- InitializeComponent();
- }
-}
diff --git a/Wino.Mail.WinUI/Views/SettingsPage.xaml.cs b/Wino.Mail.WinUI/Views/SettingsPage.xaml.cs
index a4757f95..85854a15 100644
--- a/Wino.Mail.WinUI/Views/SettingsPage.xaml.cs
+++ b/Wino.Mail.WinUI/Views/SettingsPage.xaml.cs
@@ -68,13 +68,6 @@ public sealed partial class SettingsPage : SettingsPageAbstract,
manageAccountsEntry.Title = Translator.SettingsManageAccountSettings_Title;
}
- var winoAccountEntry = PageHistory.FirstOrDefault(a => a.Request.PageType == WinoPage.WinoAccountManagementPage);
-
- if (winoAccountEntry != null)
- {
- winoAccountEntry.Title = Translator.WinoAccount_SettingsSection_Title;
- }
-
_ = RefreshCurrentPageStateAsync();
UpdateWindowTitle();
}
diff --git a/Wino.Mail.WinUI/Views/WelcomePageV2.xaml b/Wino.Mail.WinUI/Views/WelcomePageV2.xaml
index 70ffe950..c4eb3bab 100644
--- a/Wino.Mail.WinUI/Views/WelcomePageV2.xaml
+++ b/Wino.Mail.WinUI/Views/WelcomePageV2.xaml
@@ -127,11 +127,6 @@
Grid.Row="3"
MaxWidth="600"
HorizontalAlignment="Center">
-
-
+ StoreUpdateItemTemplate="{StaticResource StoreUpdateItemTemplate}" />
diff --git a/Wino.Services/ApplicationConfiguration.cs b/Wino.Services/ApplicationConfiguration.cs
index f98722e4..982e92ee 100644
--- a/Wino.Services/ApplicationConfiguration.cs
+++ b/Wino.Services/ApplicationConfiguration.cs
@@ -10,5 +10,5 @@ public class ApplicationConfiguration : IApplicationConfiguration
public string PublisherSharedFolderPath { get; set; }
public string ApplicationTempFolderPath { get; set; }
- public string SentryDNS => "https://81365d32d74c6f223a0674a2fb7bade5@o4509722249134080.ingest.de.sentry.io/4509722259095632";
+ public string SentryDNS => string.Empty;
}
diff --git a/Wino.Services/CloudFreeServices.cs b/Wino.Services/CloudFreeServices.cs
new file mode 100644
index 00000000..3f0b47ac
--- /dev/null
+++ b/Wino.Services/CloudFreeServices.cs
@@ -0,0 +1,124 @@
+#nullable enable
+using System;
+using System.Collections.Generic;
+using System.Text.Json;
+using System.Threading;
+using System.Threading.Tasks;
+using Wino.Core.Domain.Entities.Shared;
+using Wino.Core.Domain.Interfaces;
+using Wino.Core.Domain.Models.Accounts;
+using Wino.Mail.Api.Contracts.Ai;
+using Wino.Mail.Api.Contracts.Auth;
+using Wino.Mail.Api.Contracts.Common;
+using Wino.Mail.Api.Contracts.Users;
+
+namespace Wino.Services;
+
+public sealed class NullWinoLogger : IWinoLogger
+{
+ public void SetupLogger(string fullLogFilePath) { }
+ public void RefreshLoggingLevel() { }
+ public void TrackEvent(string eventName, Dictionary? properties = null) { }
+}
+
+public sealed class LocalOnlyWinoAccountApiClient : IWinoAccountApiClient
+{
+ private static WinoAccountApiResult AuthDisabled() => WinoAccountApiResult.Failure("CloudDisabled", "Cloud features are disabled in this build.");
+ private static ApiEnvelope Disabled() => ApiEnvelope.Failure("CloudDisabled", "Cloud features are disabled in this build.");
+
+ public Task> RegisterAsync(string email, string password, CancellationToken cancellationToken = default) => Task.FromResult(AuthDisabled());
+ public Task> LoginAsync(string email, string password, CancellationToken cancellationToken = default) => Task.FromResult(AuthDisabled());
+ public Task> RefreshAsync(string refreshToken, CancellationToken cancellationToken = default) => Task.FromResult(AuthDisabled());
+ public Task> ResendEmailConfirmationAsync(string endpoint, string ticket, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> ForgotPasswordAsync(string email, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> LogoutAsync(string refreshToken, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> GetCurrentUserAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> GetAiStatusAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> RewriteAsync(string html, string mode, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> CreateCollectionsIdTicketAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> CreatePurchaseIdTicketAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> SyncStoreEntitlementsAsync(string? storeIdKey, string? purchaseIdKey, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task GetSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null);
+ public Task SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default) => Task.CompletedTask;
+ public Task GetMailboxesAsync(CancellationToken cancellationToken = default) => Task.FromResult(new UserMailboxSyncListDto([]));
+ public Task ReplaceMailboxesAsync(ReplaceUserMailboxesRequestDto request, CancellationToken cancellationToken = default) => Task.CompletedTask;
+}
+
+public sealed class LocalOnlyWinoAccountProfileService : IWinoAccountProfileService
+{
+ private static WinoAccountOperationResult OperationDisabled() => WinoAccountOperationResult.Failure("CloudDisabled", "Cloud features are disabled in this build.");
+ private static ApiEnvelope Disabled() => ApiEnvelope.Failure("CloudDisabled", "Cloud features are disabled in this build.");
+
+ public Task RegisterAsync(string email, string password, CancellationToken cancellationToken = default) => Task.FromResult(OperationDisabled());
+ public Task LoginAsync(string email, string password, CancellationToken cancellationToken = default) => Task.FromResult(OperationDisabled());
+ public Task RefreshAsync(CancellationToken cancellationToken = default) => Task.FromResult(OperationDisabled());
+ public Task RefreshProfileAsync(CancellationToken cancellationToken = default) => Task.FromResult(OperationDisabled());
+ public Task> ResendEmailConfirmationAsync(string endpoint, string ticket, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> ForgotPasswordAsync(string email, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task GetActiveAccountAsync() => Task.FromResult(null);
+ public Task GetAuthenticatedAccountAsync(CancellationToken cancellationToken = default) => Task.FromResult(null);
+ public Task HasActiveAccountAsync() => Task.FromResult(false);
+ public Task> GetCurrentUserAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> GetAiStatusAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> SummarizeAsync(string html, string targetLanguage, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> RewriteAsync(string html, string mode, CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task> SyncStoreEntitlementsAsync(CancellationToken cancellationToken = default) => Task.FromResult(Disabled());
+ public Task GetSettingsAsync(CancellationToken cancellationToken = default) => Task.FromResult(null);
+ public Task SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default) => Task.CompletedTask;
+ public Task GetMailboxesAsync(CancellationToken cancellationToken = default) => Task.FromResult(new UserMailboxSyncListDto([]));
+ public Task ReplaceMailboxesAsync(ReplaceUserMailboxesRequestDto request, CancellationToken cancellationToken = default) => Task.CompletedTask;
+ public Task ProcessBillingCallbackAsync(Uri callbackUri, CancellationToken cancellationToken = default) => Task.FromResult(false);
+ public Task SignOutAsync(CancellationToken cancellationToken = default) => Task.CompletedTask;
+}
+
+public sealed class LocalOnlyWinoAccountDataSyncService : IWinoAccountDataSyncService
+{
+ public Task ExportAsync(WinoAccountSyncSelection selection, CancellationToken cancellationToken = default)
+ => Task.FromResult(new WinoAccountSyncExportResult
+ {
+ IncludedPreferences = selection.IncludePreferences,
+ IncludedAccounts = selection.IncludeAccounts,
+ ExportedMailboxCount = 0
+ });
+
+ public Task ExportToJsonAsync(WinoAccountSyncSelection selection, CancellationToken cancellationToken = default)
+ => Task.FromResult(new WinoAccountSyncFileExportResult
+ {
+ JsonContent = "{}",
+ ExportResult = new WinoAccountSyncExportResult
+ {
+ IncludedPreferences = selection.IncludePreferences,
+ IncludedAccounts = selection.IncludeAccounts,
+ ExportedMailboxCount = 0
+ }
+ });
+
+ public Task ImportAsync(WinoAccountSyncSelection selection, CancellationToken cancellationToken = default)
+ => Task.FromResult(new WinoAccountSyncImportResult
+ {
+ IncludedPreferences = selection.IncludePreferences,
+ IncludedAccounts = selection.IncludeAccounts,
+ HadRemotePreferences = false,
+ AppliedPreferenceCount = 0,
+ FailedPreferenceCount = 0,
+ ImportedMailboxCount = 0,
+ SkippedDuplicateMailboxCount = 0,
+ RemoteMailboxCount = 0
+ });
+
+ public Task ImportFromJsonAsync(string jsonContent, CancellationToken cancellationToken = default)
+ => Task.FromResult(new WinoAccountSyncImportResult
+ {
+ IncludedPreferences = false,
+ IncludedAccounts = false,
+ HadRemotePreferences = false,
+ AppliedPreferenceCount = 0,
+ FailedPreferenceCount = 0,
+ ImportedMailboxCount = 0,
+ SkippedDuplicateMailboxCount = 0,
+ RemoteMailboxCount = 0
+ });
+}
diff --git a/Wino.Services/ServicesContainerSetup.cs b/Wino.Services/ServicesContainerSetup.cs
index b999b42d..b3a09965 100644
--- a/Wino.Services/ServicesContainerSetup.cs
+++ b/Wino.Services/ServicesContainerSetup.cs
@@ -11,7 +11,7 @@ public static class ServicesContainerSetup
services.AddSingleton();
services.AddSingleton();
- services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
services.AddSingleton();
@@ -31,9 +31,9 @@ public static class ServicesContainerSetup
services.AddTransient();
services.AddTransient();
services.AddTransient();
- services.AddSingleton();
- services.AddSingleton();
- services.AddTransient();
+ services.AddSingleton();
+ services.AddSingleton();
+ services.AddSingleton();
services.AddSingleton();
services.AddTransient();