334 lines
12 KiB
C#
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();
|
|
}
|
|
} |