add account summary card

This commit is contained in:
2026-04-30 10:00:32 +02:00
parent 14d5ce4583
commit 8a0b1f740e
3 changed files with 210 additions and 16 deletions

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
@@ -20,27 +21,47 @@ using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Navigation;
using Wino.Core.Domain.Models.Synchronization;
using Wino.Core.Extensions;
using Wino.Core.Services;
using Wino.Core.ViewModels;
using Wino.Core.ViewModels.Data;
using Wino.Mail.ViewModels.Data;
using Wino.Messaging.Client.Navigation;
using Wino.Messaging.UI;
using Wino.Services;
namespace Wino.Mail.ViewModels;
public partial class AccountManagementViewModel : AccountManagementPageViewModelBase
{
private const string LocalExportFileName = "wino-data-export.json";
private const string SummaryUnavailable = "—";
private static readonly UTF8Encoding Utf8WithoutBom = new(false);
private readonly IWinoAccountDataSyncService _syncService;
private readonly IWinoLogger _winoLogger;
private readonly ISpecialImapProviderConfigResolver _specialImapProviderConfigResolver;
private readonly ICalDavClient _calDavClient;
private readonly IMimeStorageService _mimeStorageService;
private readonly ICalendarService _calendarService;
public IMailDialogService MailDialogService { get; }
[ObservableProperty]
public partial string SummaryAccountCountText { get; set; } = SummaryUnavailable;
[ObservableProperty]
public partial string SummaryEmailCountText { get; set; } = SummaryUnavailable;
[ObservableProperty]
public partial string SummaryStorageText { get; set; } = SummaryUnavailable;
[ObservableProperty]
public partial string SummaryCalendarCountText { get; set; } = SummaryUnavailable;
[ObservableProperty]
public partial string SummaryDefaultAccountText { get; set; } = string.Format(Translator.WinoAccount_Management_SummaryDefaultAccountLabel, SummaryUnavailable);
public AccountManagementViewModel(IMailDialogService dialogService,
INavigationService navigationService,
IAccountService accountService,
@@ -50,6 +71,8 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
IWinoLogger winoLogger,
ISpecialImapProviderConfigResolver specialImapProviderConfigResolver,
ICalDavClient calDavClient,
IMimeStorageService mimeStorageService,
ICalendarService calendarService,
IAuthenticationProvider authenticationProvider,
IPreferencesService preferencesService) : base(dialogService, navigationService, accountService, providerService, winoAccountProfileService, authenticationProvider, preferencesService)
{
@@ -58,6 +81,8 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
_winoLogger = winoLogger;
_specialImapProviderConfigResolver = specialImapProviderConfigResolver;
_calDavClient = calDavClient;
_mimeStorageService = mimeStorageService;
_calendarService = calendarService;
}
[ObservableProperty]
@@ -398,7 +423,90 @@ public partial class AccountManagementViewModel : AccountManagementPageViewModel
}
});
await RefreshAccountSummaryAsync(accounts).ConfigureAwait(false);
}
private async Task RefreshAccountSummaryAsync(List<MailAccount> accounts)
{
await ExecuteUIThread(() =>
{
SummaryAccountCountText = accounts.Count.ToString(CultureInfo.CurrentCulture);
SummaryEmailCountText = SummaryUnavailable;
SummaryStorageText = SummaryUnavailable;
SummaryCalendarCountText = SummaryUnavailable;
SummaryDefaultAccountText = string.Format(
Translator.WinoAccount_Management_SummaryDefaultAccountLabel,
GetDefaultAccountName(accounts));
});
try
{
var accountIds = accounts.Select(a => a.Id).ToList();
if (accountIds.Count > 0)
{
var storageSizes = await _mimeStorageService.GetAccountsMimeStorageSizesAsync(accountIds).ConfigureAwait(false);
var totalStorageBytes = storageSizes.Values.DefaultIfEmpty(0L).Sum();
var totalCalendarCount = 0;
foreach (var account in accounts)
{
try
{
var calendars = await _calendarService.GetAccountCalendarsAsync(account.Id).ConfigureAwait(false);
totalCalendarCount += calendars?.Count ?? 0;
}
catch
{
// Keep partial summary data if a specific account calendar lookup fails.
}
}
await ExecuteUIThread(() =>
{
SummaryEmailCountText = SummaryUnavailable;
SummaryStorageText = totalStorageBytes > 0
? totalStorageBytes.GetBytesReadable()
: "0 B";
SummaryCalendarCountText = totalCalendarCount.ToString(CultureInfo.CurrentCulture);
});
}
}
catch
{
// Leave graceful placeholders if summary data can't be gathered.
}
}
private string GetDefaultAccountName(List<MailAccount> accounts)
{
var startupEntityId = PreferencesService.StartupEntityId;
if (startupEntityId != null)
{
var startupAccount = accounts.FirstOrDefault(a => a.Id == startupEntityId)
?? accounts.FirstOrDefault(a => a.MergedInboxId == startupEntityId)
?? accounts.FirstOrDefault(a => a.MergedInbox?.Id == startupEntityId);
if (startupAccount?.MergedInbox != null)
return startupAccount.MergedInbox.Name;
if (!string.IsNullOrWhiteSpace(startupAccount?.Name))
return startupAccount.Name;
if (!string.IsNullOrWhiteSpace(startupAccount?.Address))
return startupAccount.Address;
}
var firstAccount = accounts.FirstOrDefault();
if (!string.IsNullOrWhiteSpace(firstAccount?.Name))
return firstAccount.Name;
if (!string.IsNullOrWhiteSpace(firstAccount?.Address))
return firstAccount.Address;
return SummaryUnavailable;
}
private static string BuildExportSuccessMessage(Wino.Core.Domain.Models.Accounts.WinoAccountSyncExportResult result)