Import functionality for wino accounts, calendar sync UI, bunch of shell improvements

This commit is contained in:
Burak Kaan Köse
2026-04-04 20:23:20 +02:00
parent 1667aa34db
commit 1d0fcfb5b0
68 changed files with 2792 additions and 519 deletions
@@ -5,6 +5,7 @@ public enum CalendarSynchronizationType
ExecuteRequests, // Execute all requests in the queue.
CalendarMetadata, // Sync calendar metadata.
CalendarEvents, // Sync all events for all calendars.
Strict, // Run metadata and event synchronization in sequence.
SingleCalendar, // Sync events for only specified calendars.
UpdateProfile // Update profile information only.
}
@@ -5,7 +5,6 @@ using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Common;
using Wino.Core.Domain.Models.Printing;
using Wino.Core.Domain.Models.Updates;
namespace Wino.Core.Domain.Interfaces;
@@ -32,10 +31,4 @@ public interface IDialogServiceBase
Task<List<PickedFileMetadata>> PickFilesMetadataAsync(params object[] typeFilters);
Task<string> PickFilePathAsync(string saveFileName);
Task<WebView2PrintSettingsModel> ShowPrintDialogAsync(WebView2PrintSettingsModel initialSettings = null);
/// <summary>
/// Presents the "What's New" dialog for the current version.
/// This dialog is undismissable and runs any pending migrations when the user clicks "Get Started".
/// </summary>
Task ShowWhatIsNewDialogAsync(UpdateNotes notes);
}
@@ -8,6 +8,7 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Models.Calendar;
using Wino.Core.Domain.Models.Folders;
@@ -74,4 +75,6 @@ public interface IMailDialogService : IDialogServiceBase
Task<WinoAccount?> ShowWinoAccountRegistrationDialogAsync();
Task<WinoAccount?> ShowWinoAccountLoginDialogAsync();
Task<WinoAccountSyncExportResult?> ShowWinoAccountExportDialogAsync();
}
@@ -51,6 +51,8 @@ public interface ICalendarShellClient : IShellClient
int SelectedDateNavigationHeaderIndex { get; }
VisibleDateRange? CurrentVisibleRange { get; }
string VisibleDateRangeText { get; }
bool CanSynchronizeCalendars { get; }
ICommand SyncCommand { get; }
ICommand TodayClickedCommand { get; }
ICommand DateClickedCommand { get; }
ICommand PreviousDateRangeCommand { get; }
@@ -6,6 +6,7 @@ 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.Core.Domain.Interfaces;
@@ -26,5 +27,7 @@ public interface IWinoAccountApiClient
Task<ApiEnvelope<WinoStoreCollectionsIdTicketInfo>> CreatePurchaseIdTicketAsync(CancellationToken cancellationToken = default);
Task<ApiEnvelope<JsonElement>> SyncStoreEntitlementsAsync(string? storeIdKey, string? purchaseIdKey, CancellationToken cancellationToken = default);
Task<string?> GetSettingsAsync(CancellationToken cancellationToken = default);
Task<bool> SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default);
Task SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default);
Task<UserMailboxSyncListDto> GetMailboxesAsync(CancellationToken cancellationToken = default);
Task ReplaceMailboxesAsync(ReplaceUserMailboxesRequestDto request, CancellationToken cancellationToken = default);
}
@@ -0,0 +1,11 @@
using System.Threading;
using System.Threading.Tasks;
using Wino.Core.Domain.Models.Accounts;
namespace Wino.Core.Domain.Interfaces;
public interface IWinoAccountDataSyncService
{
Task<WinoAccountSyncExportResult> ExportAsync(WinoAccountSyncSelection selection, CancellationToken cancellationToken = default);
Task<WinoAccountSyncImportResult> ImportAsync(WinoAccountSyncSelection selection, CancellationToken cancellationToken = default);
}
@@ -8,6 +8,7 @@ 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.Core.Domain.Interfaces;
@@ -28,6 +29,10 @@ public interface IWinoAccountProfileService
Task<ApiEnvelope<AiTextResultDto>> TranslateAsync(string html, string targetLanguage, CancellationToken cancellationToken = default);
Task<ApiEnvelope<AiTextResultDto>> RewriteAsync(string html, string mode, CancellationToken cancellationToken = default);
Task<ApiEnvelope<JsonElement>> SyncStoreEntitlementsAsync(CancellationToken cancellationToken = default);
Task<string?> GetSettingsAsync(CancellationToken cancellationToken = default);
Task SaveSettingsAsync(string settingsJson, CancellationToken cancellationToken = default);
Task<UserMailboxSyncListDto> GetMailboxesAsync(CancellationToken cancellationToken = default);
Task ReplaceMailboxesAsync(ReplaceUserMailboxesRequestDto request, CancellationToken cancellationToken = default);
Task<bool> ProcessBillingCallbackAsync(Uri callbackUri, CancellationToken cancellationToken = default);
Task SignOutAsync(CancellationToken cancellationToken = default);
}
@@ -13,6 +13,7 @@ public interface INavigationService
Type GetPageType(WinoPage winoPage);
bool ChangeApplicationMode(WinoApplicationMode mode);
bool ChangeApplicationMode(WinoApplicationMode mode, ShellModeActivationContext activationContext);
bool CanGoBack();
void GoBack(NavigationTransitionEffect slideEffect = NavigationTransitionEffect.FromRight);
}
@@ -111,6 +111,7 @@ public partial class AccountMenuItem : MenuItemBase<MailAccount, MenuItemBase<IM
public void UpdateAccount(MailAccount account)
{
Parameter = account;
AttentionReason = account.AttentionReason;
OnPropertyChanged(nameof(AccountName));
OnPropertyChanged(nameof(Base64ProfilePicture));
+10 -6
View File
@@ -8,12 +8,16 @@ public static class CalendarColorPalette
{
private static readonly string[] FlatUiColorPalette =
[
"#E53935", "#D81B60", "#8E24AA", "#5E35B1", "#3949AB", "#1E88E5", "#039BE5", "#00ACC1", "#00897B", "#43A047",
"#7CB342", "#C0CA33", "#FDD835", "#FFB300", "#FB8C00", "#F4511E", "#6D4C41", "#757575", "#546E7A", "#C62828",
"#AD1457", "#6A1B9A", "#4527A0", "#283593", "#1565C0", "#0277BD", "#00838F", "#00695C", "#2E7D32", "#558B2F",
"#9E9D24", "#F9A825", "#FF8F00", "#EF6C00", "#D84315", "#4E342E", "#616161", "#455A64", "#EF5350", "#EC407A",
"#AB47BC", "#7E57C2", "#5C6BC0", "#42A5F5", "#29B6F6", "#26C6DA", "#26A69A", "#66BB6A", "#9CCC65", "#D4E157",
"#FFEE58", "#FFCA28", "#FFA726", "#FF7043", "#8D6E63", "#BDBDBD", "#78909C", "#F06292", "#BA68C8", "#9575CD"
"#E53935", "#D81B60", "#C2185B", "#AD1457", "#8E24AA", "#7B1FA2", "#6A1B9A", "#5E35B1", "#512DA8", "#4527A0",
"#3949AB", "#303F9F", "#283593", "#1E88E5", "#1976D2", "#1565C0", "#039BE5", "#0288D1", "#0277BD", "#00ACC1",
"#0097A7", "#00838F", "#00897B", "#00796B", "#00695C", "#43A047", "#388E3C", "#2E7D32", "#7CB342", "#689F38",
"#558B2F", "#9CCC65", "#8BC34A", "#AED581", "#C0CA33", "#AFB42B", "#9E9D24", "#D4E157", "#CDDC39", "#FDD835",
"#FBC02D", "#F9A825", "#FFB300", "#FFA000", "#FF8F00", "#FB8C00", "#F57C00", "#EF6C00", "#F4511E", "#E64A19",
"#D84315", "#FF7043", "#FF8A65", "#FFAB91", "#6D4C41", "#5D4037", "#4E342E", "#8D6E63", "#795548", "#A1887F",
"#546E7A", "#455A64", "#37474F", "#607D8B", "#78909C", "#90A4AE", "#757575", "#616161", "#424242", "#9E9E9E",
"#BDBDBD", "#EC407A", "#F06292", "#F48FB1", "#BA68C8", "#CE93D8", "#9575CD", "#B39DDB", "#7986CB", "#9FA8DA",
"#64B5F6", "#90CAF9", "#4FC3F7", "#81D4FA", "#4DD0E1", "#80DEEA", "#4DB6AC", "#80CBC4", "#81C784", "#A5D6A7",
"#C5E1A5", "#E6EE9C", "#FFF176", "#FFD54F", "#FFCC80", "#FFB74D", "#FFAB40", "#FF9E80", "#BCAAA4", "#A1887F"
];
public static IReadOnlyList<string> GetColors() => FlatUiColorPalette;
@@ -0,0 +1,8 @@
namespace Wino.Core.Domain.Models.Accounts;
public sealed class WinoAccountSyncExportResult
{
public bool IncludedPreferences { get; init; }
public bool IncludedAccounts { get; init; }
public int ExportedMailboxCount { get; init; }
}
@@ -0,0 +1,15 @@
namespace Wino.Core.Domain.Models.Accounts;
public sealed class WinoAccountSyncImportResult
{
public bool IncludedPreferences { get; init; }
public bool IncludedAccounts { get; init; }
public bool HadRemotePreferences { get; init; }
public int AppliedPreferenceCount { get; init; }
public int FailedPreferenceCount { get; init; }
public int ImportedMailboxCount { get; init; }
public int SkippedDuplicateMailboxCount { get; init; }
public int RemoteMailboxCount { get; init; }
public bool HasAnyRemoteData => HadRemotePreferences || RemoteMailboxCount > 0;
}
@@ -0,0 +1,5 @@
namespace Wino.Core.Domain.Models.Accounts;
public sealed record WinoAccountSyncSelection(
bool IncludePreferences = true,
bool IncludeAccounts = true);
@@ -1,7 +1,10 @@
#nullable enable
namespace Wino.Core.Domain.Models.Navigation;
public sealed class ShellModeActivationContext
{
public bool IsInitialActivation { get; init; }
public object Parameter { get; init; }
public bool SuppressStartupFlows { get; init; }
public object? Parameter { get; init; }
}
@@ -104,6 +104,9 @@
"SyncAction_SettingFlag": "Flagging {0} mail(s)",
"SyncAction_SynchronizingAccount": "Synchronizing {0}",
"SyncAction_SynchronizingAccounts": "Synchronizing {0} account(s)",
"SyncAction_SynchronizingCalendarData": "Synchronizing calendar data",
"SyncAction_SynchronizingCalendarEvents": "Synchronizing calendar events",
"SyncAction_SynchronizingCalendarMetadata": "Synchronizing calendar metadata",
"SyncAction_Unarchiving": "Unarchiving {0} mail(s)",
"CalendarAllDayEventSummary": "all-day events",
"CalendarDisplayOptions_Color": "Color",
@@ -313,6 +316,8 @@
"Exception_CustomThemeMissingName": "You must provide a name.",
"Exception_CustomThemeMissingWallpaper": "You must provide a custom background image.",
"Exception_FailedToSynchronizeAliases": "Failed to synchronize aliases",
"Exception_FailedToSynchronizeCalendarData": "Failed to synchronize calendar data",
"Exception_FailedToSynchronizeCalendarEvents": "Failed to synchronize calendar events",
"Exception_FailedToSynchronizeCalendarMetadata": "Failed to synchronize calendar details",
"Exception_FailedToSynchronizeFolders": "Failed to synchronize folders",
"Exception_FailedToSynchronizeProfileInformation": "Failed to synchronize profile information",
@@ -505,6 +510,11 @@
"Info_AccountDeletedMessage": "{0} is successfuly deleted.",
"Info_AccountDeletedTitle": "Account Deleted",
"Info_AccountIssueFixFailedTitle": "Failed",
"Info_AccountIssueFixImapMessage": "Open the IMAP and calendar settings page to enter your server credentials again.",
"Info_AccountAttentionRequiredMessage": "This account needs your attention.",
"Info_AccountAttentionRequiredClickableMessage": "Click to fix this account and resynchronize it.",
"Info_AccountAttentionRequiredAction": "Fix",
"Info_AccountAttentionRequiredActionHint": "Click Fix to resolve this account issue.",
"Info_AccountIssueFixSuccessMessage": "Fixed all account issues.",
"Info_AccountIssueFixSuccessTitle": "Success",
"Info_AttachmentOpenFailedMessage": "Can't open this attachment.",
@@ -678,6 +688,9 @@
"SettingConfigureSpecialFolders_Button": "Configure",
"SettingsEditAccountDetails_IMAPConfiguration_Title": "IMAP/SMTP Configuration",
"SettingsEditAccountDetails_IMAPConfiguration_Description": "Change your incoming/outgoing server settings.",
"SettingsEditAccountDetails_ImapCalDavSettings_Title": "IMAP and calendar settings",
"SettingsEditAccountDetails_ImapCalDavSettings_Description": "Open the dedicated IMAP, SMTP, and CalDAV settings page for this account.",
"SettingsEditAccountDetails_ImapCalDavSettings_Action": "Open settings",
"SettingsAbout_Description": "Learn more about Wino.",
"SettingsAbout_Title": "About",
"SettingsAboutGithub_Description": "Go to issue tracker GitHub repository.",
@@ -1222,6 +1235,10 @@
"WelcomeWindow_FeaturesTab": "Features",
"WelcomeWindow_GetStartedButton": "Get started by adding an account",
"WelcomeWindow_GetStartedDescription": "Add your Outlook, Gmail, or IMAP account to get started with Wino Mail.",
"WelcomeWindow_ImportFromWinoAccount": "Import from your Wino Account",
"WelcomeWindow_ImportInProgress": "Importing your synchronized preferences and accounts...",
"WelcomeWindow_ImportNoAccountsFound": "No synced accounts were found in your Wino Account. If preferences were available, they were restored. Use Get started to add an account manually.",
"WelcomeWindow_ImportDuplicateAccountsSkipped": "{0} synced accounts are already available on this device. Use Get started to add another account manually if needed.",
"WelcomeWindow_SetupTitle": "Set up your account",
"WelcomeWindow_SetupSubtitle": "Choose your email provider to get started",
"WelcomeWindow_AddAccountButton": "Add account",
@@ -1233,7 +1250,7 @@
"WinoAccount_Titlebar_SyncBenefitDescription": "Keep your Wino preferences in sync across devices.",
"WinoAccount_Titlebar_AddonsBenefitTitle": "Unlock add-ons",
"WinoAccount_Titlebar_AddonsBenefitDescription": "Access premium features like Wino AI Pack.",
"WinoAccount_Management_Description": "Manage your Wino Account, AI Pack access, and synchronized settings.",
"WinoAccount_Management_Description": "Manage your Wino Account, AI Pack access, and synchronized preferences and account details.",
"WinoAccount_Management_SignedOutTitle": "Sign in to Wino Mail",
"WinoAccount_Management_SignedOutDescription": "Sign in or create an account to sync your email, access AI features, and manage your settings across devices.",
"WinoAccount_Management_ProfileSectionHeader": "Profile",
@@ -1273,18 +1290,31 @@
"WinoAccount_Management_AiPackFeatureRewrite": "Rewrite",
"WinoAccount_Management_AiPackFeatureSummarize": "Summarize",
"WinoAccount_Management_AddOnLoadFailed": "We had issues loading this add-on.",
"WinoAccount_Management_SyncPreferencesTitle": "Synchronize Preferences",
"WinoAccount_Management_SyncPreferencesDescription": "Import or export your preferences to cloud. Import them across devices.",
"WinoAccount_Management_SyncPreferencesTitle": "Synchronize Preferences and Accounts",
"WinoAccount_Management_SyncPreferencesDescription": "Import or export your Wino preferences and mailbox details across devices. Passwords, tokens, and other sensitive information are never synced.",
"WinoAccount_Management_SignOutTitle": "Sign out",
"WinoAccount_Management_SignOutDescription": "Sign out of your account on this device",
"WinoAccount_Management_StatusLabel": "Status: {0}",
"WinoAccount_Management_NoRemoteSettings": "There are no synchronized settings stored for this account yet.",
"WinoAccount_Management_ExportSucceeded": "Your settings were exported to your Wino Account.",
"WinoAccount_Management_ImportSucceeded": "Imported {0} settings from your Wino Account.",
"WinoAccount_Management_ImportPartial": "Imported {0} settings. {1} settings could not be restored.",
"WinoAccount_Management_NoRemoteSettings": "There is no synchronized data stored for this account yet.",
"WinoAccount_Management_ExportSucceeded": "Your selected Wino data was exported successfully.",
"WinoAccount_Management_ExportPreferencesSucceeded": "Your preferences were exported to your Wino Account.",
"WinoAccount_Management_ExportAccountsSucceeded": "Exported {0} account details to your Wino Account.",
"WinoAccount_Management_ImportSucceeded": "Imported synchronized data from your Wino Account.",
"WinoAccount_Management_ImportPreferencesSucceeded": "Applied {0} synchronized preferences.",
"WinoAccount_Management_ImportAccountsSucceeded": "Imported {0} accounts.",
"WinoAccount_Management_ImportDuplicateAccountsSkipped": "Skipped {0} accounts that already exist on this device.",
"WinoAccount_Management_ImportPartial": "Applied {0} synchronized preferences. {1} preferences could not be restored.",
"WinoAccount_Management_ImportReloginReminder": "Passwords, tokens, and other sensitive information were not imported. Sign in again for each account on this device before using it.",
"WinoAccount_Management_SerializeFailed": "Wino could not serialize your current preferences.",
"WinoAccount_Management_EmptyExport": "There are no preference values to export.",
"WinoAccount_Management_ImportEmpty": "The synchronized settings payload does not contain any values to restore.",
"WinoAccount_Management_ImportEmpty": "The synchronized data payload does not contain anything new to restore.",
"WinoAccount_Management_ExportDialog_Title": "Export to your Wino Account",
"WinoAccount_Management_ExportDialog_Description": "Choose what you want to sync to your Wino Account.",
"WinoAccount_Management_ExportDialog_IncludePreferences": "Preferences",
"WinoAccount_Management_ExportDialog_IncludeAccounts": "Accounts",
"WinoAccount_Management_ExportDialog_AccountsDisclaimer": "Passwords, tokens, and other sensitive information are not synced.",
"WinoAccount_Management_ExportDialog_AccountsRelogin": "Imported accounts on another PC will still need you to sign in again before they can be used.",
"WinoAccount_Management_ExportDialog_InProgress": "Exporting your selected Wino data...",
"WinoAccount_Management_LoadFailed": "Wino could not load the latest Wino Account information.",
"WinoAccount_Management_ActionFailed": "The Wino Account request could not be completed.",
"WinoAccount_SettingsSection_Title": "Wino Account",