Files
Wino-Mail/Wino.Core.ViewModels/SettingOptionsPageViewModel.cs
2026-04-29 18:53:17 +02:00

334 lines
12 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
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.Navigation;
using Wino.Core.Domain.Models.Personalization;
using Wino.Core.Domain.Models.Settings;
using Wino.Core.Domain.Models.Translations;
using Wino.Core.Extensions;
using Wino.Core.ViewModels.Data;
using Wino.Mail.ViewModels.Data;
using Wino.Messaging.Client.Navigation;
namespace Wino.Core.ViewModels;
public partial class SettingOptionsPageViewModel : CoreBaseViewModel
{
private readonly INativeAppService _nativeAppService;
private readonly IAccountService _accountService;
private readonly IMimeStorageService _mimeStorageService;
private readonly ITranslationService _translationService;
private readonly INewThemeService _newThemeService;
private readonly IPreferencesService _preferencesService;
private readonly IProviderService _providerService;
private bool _isInitializingSettings;
public string WebsiteUrl => AppUrls.Website;
public string PrivacyPolicyUrl => AppUrls.PrivacyPolicy;
public ObservableCollection<SettingsNavigationItemInfo> SearchSuggestions { get; } = [];
public ObservableCollection<IAccountProviderDetailViewModel> Accounts { get; } = [];
public ObservableCollection<AppColorViewModel> Colors { get; } = [];
public List<ElementThemeContainer> ElementThemes { get; } =
[
new(ApplicationElementTheme.Default, Translator.ElementTheme_Default),
new(ApplicationElementTheme.Light, Translator.ElementTheme_Light),
new(ApplicationElementTheme.Dark, Translator.ElementTheme_Dark),
];
public bool HasAccounts => Accounts.Count > 0;
[ObservableProperty]
public partial string VersionText { get; set; } = string.Empty;
[ObservableProperty]
public partial string AccountSummaryText { get; set; } = string.Empty;
[ObservableProperty]
public partial int AccountCount { get; set; }
[ObservableProperty]
public partial string StorageSummaryText { get; set; } = string.Empty;
[ObservableProperty]
public partial string SearchQuery { get; set; } = string.Empty;
[ObservableProperty]
public partial List<AppLanguageModel> AvailableLanguages { get; set; } = [];
[ObservableProperty]
public partial AppLanguageModel SelectedLanguage { get; set; }
[ObservableProperty]
public partial ElementThemeContainer SelectedElementTheme { get; set; }
[ObservableProperty]
public partial AppColorViewModel SelectedAppColor { get; set; }
[ObservableProperty]
public partial bool UseAccentColor { get; set; }
public SettingOptionsPageViewModel(INativeAppService nativeAppService,
IAccountService accountService,
IMimeStorageService mimeStorageService,
ITranslationService translationService,
INewThemeService newThemeService,
IPreferencesService preferencesService,
IProviderService providerService)
{
_nativeAppService = nativeAppService;
_accountService = accountService;
_mimeStorageService = mimeStorageService;
_translationService = translationService;
_newThemeService = newThemeService;
_preferencesService = preferencesService;
_providerService = providerService;
}
public override void OnNavigatedTo(NavigationMode mode, object parameters)
{
base.OnNavigatedTo(mode, parameters);
VersionText = string.Format("{0}{1}", Translator.SettingsAboutVersion, _nativeAppService.GetFullAppVersion());
SearchQuery = string.Empty;
SearchSuggestions.Clear();
StorageSummaryText = Translator.SettingsHome_StorageLoading;
InitializeQuickSettings();
_ = LoadDashboardAsync();
}
public void UpdateSearchSuggestions(string query)
{
SearchQuery = query;
SearchSuggestions.Clear();
foreach (var result in SettingsNavigationInfoProvider.Search(query, AccountSummaryText).Take(6))
{
SearchSuggestions.Add(result);
}
}
public SettingsNavigationItemInfo GetBestSearchSuggestion(string query)
=> SettingsNavigationInfoProvider.Search(query, AccountSummaryText).FirstOrDefault();
public void NavigateToSetting(SettingsNavigationItemInfo item)
{
if (item?.PageType is not WinoPage pageType)
{
return;
}
Messenger.Send(new BreadcrumbNavigationRequested(
SettingsNavigationInfoProvider.GetPageTitle(pageType),
pageType));
}
public void NavigateToAccount(IAccountProviderDetailViewModel account)
{
if (account == null)
{
return;
}
Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAccountSettings_Title, WinoPage.ManageAccountsPage));
switch (account)
{
case AccountProviderDetailViewModel accountDetails:
Messenger.Send(new BreadcrumbNavigationRequested(GetAccountDetailsTitle(accountDetails.Account), WinoPage.AccountDetailsPage, accountDetails.Account.Id));
break;
case MergedAccountProviderDetailViewModel mergedAccount:
Messenger.Send(new BreadcrumbNavigationRequested(mergedAccount.MergedInbox.Name, WinoPage.MergedAccountDetailsPage, mergedAccount));
break;
}
}
public void NavigateToAddAccount()
{
Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAccountSettings_Title, WinoPage.ManageAccountsPage));
Messenger.Send(new BreadcrumbNavigationRequested(
Translator.WelcomeWizard_Step2Title,
WinoPage.ProviderSelectionPage,
ProviderSelectionNavigationContext.CreateForSettingsAddAccount()));
}
public void NavigateToManageAccounts()
{
Messenger.Send(new BreadcrumbNavigationRequested(Translator.SettingsManageAccountSettings_Title, WinoPage.ManageAccountsPage));
}
private async Task LoadDashboardAsync()
{
var accounts = (await _accountService.GetAccountsAsync().ConfigureAwait(false) ?? []).ToList();
var count = accounts.Count;
Dictionary<Guid, long> storageSizeMap = count == 0
? []
: await _mimeStorageService.GetAccountsMimeStorageSizesAsync(accounts.Select(account => account.Id)).ConfigureAwait(false);
var totalStorageBytes = storageSizeMap.Values.Sum();
var groupedAccountItems = CreateAccountItems(accounts);
await ExecuteUIThread(() =>
{
AccountCount = count;
AccountSummaryText = string.Format(Translator.SettingsOptions_AccountsSummary, count);
Accounts.Clear();
foreach (var account in groupedAccountItems)
{
Accounts.Add(account);
}
OnPropertyChanged(nameof(HasAccounts));
StorageSummaryText = totalStorageBytes == 0
? Translator.SettingsHome_StorageEmptySummary
: string.Format(Translator.SettingsStorage_TotalUsage, totalStorageBytes.GetBytesReadable());
if (!string.IsNullOrWhiteSpace(SearchQuery))
{
UpdateSearchSuggestions(SearchQuery);
}
});
}
private static string GetAccountDetailsTitle(MailAccount account)
=> !string.IsNullOrWhiteSpace(account?.Address)
? string.Format(Translator.SettingsAccountDetails_NavigationTitle, account.Address)
: account?.Name ?? Translator.AccountDetailsPage_Title;
private void InitializeQuickSettings()
{
_isInitializingSettings = true;
InitializeColors();
InitializeLanguageOptions();
InitializeAppearanceOptions();
_isInitializingSettings = false;
}
private void InitializeColors()
{
Colors.Clear();
var fixedColors = new[]
{
"#0078d7", "#00838c", "#e3008c", "#ca4f07", "#e81123",
"#00819e", "#10893e", "#881798", "#c239b3", "#767676",
"#e1b12c", "#16a085", "#0984e3", "#4a69bd", "#05c46b"
};
foreach (var color in fixedColors)
{
Colors.Add(new AppColorViewModel(color));
}
Colors.Add(new AppColorViewModel(_newThemeService.GetSystemAccentColorHex(), true));
var currentAccentColor = _newThemeService.AccentColor;
var useSystemAccent = string.IsNullOrEmpty(currentAccentColor);
UseAccentColor = useSystemAccent;
SelectedAppColor = useSystemAccent
? Colors.LastOrDefault()
: Colors.FirstOrDefault(color => color.Hex == currentAccentColor) ?? Colors.FirstOrDefault();
}
private void InitializeLanguageOptions()
{
AvailableLanguages = _translationService.GetAvailableLanguages();
SelectedLanguage = AvailableLanguages.FirstOrDefault(language => language.Language == _preferencesService.CurrentLanguage)
?? AvailableLanguages.FirstOrDefault();
}
private void InitializeAppearanceOptions()
{
SelectedElementTheme = ElementThemes.FirstOrDefault(theme => theme.NativeTheme == _newThemeService.RootTheme)
?? ElementThemes[0];
}
partial void OnSelectedLanguageChanged(AppLanguageModel value)
{
if (_isInitializingSettings || value == null)
return;
_ = _translationService.InitializeLanguageAsync(value.Language);
}
partial void OnSelectedElementThemeChanged(ElementThemeContainer value)
{
if (_isInitializingSettings || value == null)
return;
_newThemeService.RootTheme = value.NativeTheme;
}
partial void OnSelectedAppColorChanged(AppColorViewModel value)
{
if (_isInitializingSettings || value == null)
return;
_newThemeService.AccentColor = UseAccentColor ? string.Empty : value.Hex;
}
partial void OnUseAccentColorChanged(bool value)
{
if (_isInitializingSettings)
return;
if (value)
{
SelectedAppColor = Colors.LastOrDefault();
_newThemeService.AccentColor = string.Empty;
}
else if (SelectedAppColor?.IsAccentColor == true)
{
SelectedAppColor = Colors.FirstOrDefault();
_newThemeService.AccentColor = SelectedAppColor?.Hex ?? string.Empty;
}
}
[RelayCommand]
private Task NavigateExternalAsync(string url)
{
if (string.IsNullOrWhiteSpace(url))
return Task.CompletedTask;
return _nativeAppService.LaunchUriAsync(new Uri(url));
}
private List<IAccountProviderDetailViewModel> CreateAccountItems(List<MailAccount> accounts)
{
return accounts
.GroupBy(account => account.MergedInboxId)
.SelectMany(group =>
{
if (group.Key == null)
{
return group.Select(account => (IAccountProviderDetailViewModel)new AccountProviderDetailViewModel(
_providerService.GetProviderDetail(account.ProviderType),
account));
}
var mergedInbox = group.First().MergedInbox;
var holdingAccounts = group
.Select(account => new AccountProviderDetailViewModel(_providerService.GetProviderDetail(account.ProviderType), account))
.ToList();
return
[
(IAccountProviderDetailViewModel)new MergedAccountProviderDetailViewModel(mergedInbox, holdingAccounts)
];
})
.ToList();
}
}