navigation improvements
This commit is contained in:
@@ -416,7 +416,15 @@ public partial class CalendarAppShellViewModel : CalendarBaseViewModel,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pickedCalendar = await _dialogService.ShowSingleCalendarPickerDialogAsync(availableGroups);
|
var pickingResult = await _dialogService.ShowSingleCalendarPickerDialogAsync(availableGroups);
|
||||||
|
|
||||||
|
if (pickingResult.ShouldNavigateToCalendarSettings)
|
||||||
|
{
|
||||||
|
NavigationService.Navigate(WinoPage.CalendarSettingsPage);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pickedCalendar = pickingResult.PickedCalendar;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pickedCalendar == null)
|
if (pickedCalendar == null)
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public interface IMailDialogService : IDialogServiceBase
|
|||||||
// Custom dialogs
|
// Custom dialogs
|
||||||
Task<IMailItemFolder> ShowMoveMailFolderDialogAsync(List<IMailItemFolder> availableFolders);
|
Task<IMailItemFolder> ShowMoveMailFolderDialogAsync(List<IMailItemFolder> availableFolders);
|
||||||
Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts);
|
Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts);
|
||||||
Task<AccountCalendar> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups);
|
Task<AccountCalendarPickingResult> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Displays a dialog to the user for reordering accounts.
|
/// Displays a dialog to the user for reordering accounts.
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ public interface IMailShellClient : IShellClient
|
|||||||
IMenuItem CreatePrimaryMenuItem { get; }
|
IMenuItem CreatePrimaryMenuItem { get; }
|
||||||
|
|
||||||
IEnumerable<FolderOperationMenuItem> GetFolderContextMenuActions(IBaseFolderMenuItem folder);
|
IEnumerable<FolderOperationMenuItem> GetFolderContextMenuActions(IBaseFolderMenuItem folder);
|
||||||
|
Task HandleAccountCreatedAsync(MailAccount createdAccount);
|
||||||
Task NavigateFolderAsync(IBaseFolderMenuItem baseFolderMenuItem, TaskCompletionSource<bool>? folderInitAwaitTask = null);
|
Task NavigateFolderAsync(IBaseFolderMenuItem baseFolderMenuItem, TaskCompletionSource<bool>? folderInitAwaitTask = null);
|
||||||
Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true);
|
Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true);
|
||||||
Task PerformFolderOperationAsync(FolderOperation operation, IBaseFolderMenuItem folderMenuItem);
|
Task PerformFolderOperationAsync(FolderOperation operation, IBaseFolderMenuItem folderMenuItem);
|
||||||
|
|||||||
@@ -45,9 +45,9 @@ public interface IStatePersistanceService : INotifyPropertyChanged
|
|||||||
bool IsEventDetailsVisible { get; set; }
|
bool IsEventDetailsVisible { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether SettingsPage has navigated to a sub-page and can go back.
|
/// Whether the current application mode has an active backstack that can be navigated.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsSettingsNavigating { get; set; }
|
bool HasCurrentModeBackStack { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Setting: Opened pane length for the navigation view.
|
/// Setting: Opened pane length for the navigation view.
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
#nullable enable
|
||||||
|
|
||||||
|
using Wino.Core.Domain.Entities.Calendar;
|
||||||
|
|
||||||
|
namespace Wino.Core.Domain.Models.Calendar;
|
||||||
|
|
||||||
|
public sealed record AccountCalendarPickingResult(AccountCalendar? PickedCalendar, bool ShouldNavigateToCalendarSettings);
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
@@ -9,13 +10,15 @@ public sealed class SettingsNavigationItemInfo(
|
|||||||
string title,
|
string title,
|
||||||
string description,
|
string description,
|
||||||
string glyph = "",
|
string glyph = "",
|
||||||
bool isSeparator = false)
|
bool isSeparator = false,
|
||||||
|
string searchKeywords = "")
|
||||||
{
|
{
|
||||||
public WinoPage? PageType { get; } = pageType;
|
public WinoPage? PageType { get; } = pageType;
|
||||||
public string Title { get; } = title;
|
public string Title { get; } = title;
|
||||||
public string Description { get; } = description;
|
public string Description { get; } = description;
|
||||||
public string Glyph { get; } = glyph;
|
public string Glyph { get; } = glyph;
|
||||||
public bool IsSeparator { get; } = isSeparator;
|
public bool IsSeparator { get; } = isSeparator;
|
||||||
|
public string SearchKeywords { get; } = searchKeywords;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SettingsNavigationInfoProvider
|
public static class SettingsNavigationInfoProvider
|
||||||
@@ -31,53 +34,90 @@ public static class SettingsNavigationInfoProvider
|
|||||||
new(WinoPage.ManageAccountsPage,
|
new(WinoPage.ManageAccountsPage,
|
||||||
Translator.SettingsManageAccountSettings_Title,
|
Translator.SettingsManageAccountSettings_Title,
|
||||||
manageAccountsDescription,
|
manageAccountsDescription,
|
||||||
"\uE77B"),
|
"\uE77B",
|
||||||
|
searchKeywords: Translator.SettingsSearch_ManageAccounts_Keywords),
|
||||||
new(null, Translator.SettingsOptions_GeneralSection, string.Empty, "\uE713", isSeparator: true),
|
new(null, Translator.SettingsOptions_GeneralSection, string.Empty, "\uE713", isSeparator: true),
|
||||||
new(WinoPage.AppPreferencesPage,
|
new(WinoPage.AppPreferencesPage,
|
||||||
Translator.SettingsAppPreferences_Title,
|
Translator.SettingsAppPreferences_Title,
|
||||||
Translator.SettingsAppPreferences_Description,
|
Translator.SettingsAppPreferences_Description,
|
||||||
"\uE770"),
|
"\uE770",
|
||||||
|
searchKeywords: Translator.SettingsSearch_AppPreferences_Keywords),
|
||||||
new(WinoPage.LanguageTimePage,
|
new(WinoPage.LanguageTimePage,
|
||||||
Translator.SettingsLanguageTime_Title,
|
Translator.SettingsLanguageTime_Title,
|
||||||
Translator.SettingsLanguageTime_Description,
|
Translator.SettingsLanguageTime_Description,
|
||||||
"\uE775"),
|
"\uE775",
|
||||||
|
searchKeywords: Translator.SettingsSearch_LanguageTime_Keywords),
|
||||||
new(WinoPage.PersonalizationPage,
|
new(WinoPage.PersonalizationPage,
|
||||||
Translator.SettingsPersonalization_Title,
|
Translator.SettingsPersonalization_Title,
|
||||||
Translator.SettingsPersonalization_Description,
|
Translator.SettingsPersonalization_Description,
|
||||||
"\uE771"),
|
"\uE771",
|
||||||
|
searchKeywords: Translator.SettingsSearch_Personalization_Keywords),
|
||||||
new(WinoPage.AboutPage,
|
new(WinoPage.AboutPage,
|
||||||
Translator.SettingsAbout_Title,
|
Translator.SettingsAbout_Title,
|
||||||
Translator.SettingsAbout_Description,
|
Translator.SettingsAbout_Description,
|
||||||
"\uE946"),
|
"\uE946",
|
||||||
|
searchKeywords: Translator.SettingsSearch_About_Keywords),
|
||||||
new(null, Translator.SettingsOptions_MailSection, string.Empty, "\uE715", isSeparator: true),
|
new(null, Translator.SettingsOptions_MailSection, string.Empty, "\uE715", isSeparator: true),
|
||||||
new(WinoPage.KeyboardShortcutsPage,
|
new(WinoPage.KeyboardShortcutsPage,
|
||||||
Translator.Settings_KeyboardShortcuts_Title,
|
Translator.Settings_KeyboardShortcuts_Title,
|
||||||
Translator.Settings_KeyboardShortcuts_Description,
|
Translator.Settings_KeyboardShortcuts_Description,
|
||||||
"\uE765"),
|
"\uE765",
|
||||||
|
searchKeywords: Translator.SettingsSearch_KeyboardShortcuts_Keywords),
|
||||||
new(WinoPage.MessageListPage,
|
new(WinoPage.MessageListPage,
|
||||||
Translator.SettingsMessageList_Title,
|
Translator.SettingsMessageList_Title,
|
||||||
Translator.SettingsMessageList_Description,
|
Translator.SettingsMessageList_Description,
|
||||||
"\uE8C4"),
|
"\uE8C4",
|
||||||
|
searchKeywords: Translator.SettingsSearch_MessageList_Keywords),
|
||||||
new(WinoPage.ReadComposePanePage,
|
new(WinoPage.ReadComposePanePage,
|
||||||
Translator.SettingsReadComposePane_Title,
|
Translator.SettingsReadComposePane_Title,
|
||||||
Translator.SettingsReadComposePane_Description,
|
Translator.SettingsReadComposePane_Description,
|
||||||
"\uE8BD"),
|
"\uE8BD",
|
||||||
|
searchKeywords: Translator.SettingsSearch_ReadComposePane_Keywords),
|
||||||
new(WinoPage.SignatureAndEncryptionPage,
|
new(WinoPage.SignatureAndEncryptionPage,
|
||||||
Translator.SettingsSignatureAndEncryption_Title,
|
Translator.SettingsSignatureAndEncryption_Title,
|
||||||
Translator.SettingsSignatureAndEncryption_Description,
|
Translator.SettingsSignatureAndEncryption_Description,
|
||||||
"\uE8D7"),
|
"\uE8D7",
|
||||||
|
searchKeywords: Translator.SettingsSearch_SignatureAndEncryption_Keywords),
|
||||||
new(WinoPage.StoragePage,
|
new(WinoPage.StoragePage,
|
||||||
Translator.SettingsStorage_Title,
|
Translator.SettingsStorage_Title,
|
||||||
Translator.SettingsStorage_Description,
|
Translator.SettingsStorage_Description,
|
||||||
"\uE81C"),
|
"\uE81C",
|
||||||
|
searchKeywords: Translator.SettingsSearch_Storage_Keywords),
|
||||||
new(null, Translator.SettingsOptions_CalendarSection, string.Empty, "\uE787", isSeparator: true),
|
new(null, Translator.SettingsOptions_CalendarSection, string.Empty, "\uE787", isSeparator: true),
|
||||||
new(WinoPage.CalendarSettingsPage,
|
new(WinoPage.CalendarSettingsPage,
|
||||||
Translator.SettingsCalendarSettings_Title,
|
Translator.SettingsCalendarSettings_Title,
|
||||||
Translator.SettingsCalendarSettings_Description,
|
Translator.SettingsCalendarSettings_Description,
|
||||||
"\uE787")
|
"\uE787",
|
||||||
|
searchKeywords: Translator.SettingsSearch_CalendarSettings_Keywords)
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IReadOnlyList<SettingsNavigationItemInfo> Search(string query, string manageAccountsDescription = "")
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(query))
|
||||||
|
return [];
|
||||||
|
|
||||||
|
var normalizedQuery = NormalizeSearchText(query);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(normalizedQuery))
|
||||||
|
return [];
|
||||||
|
|
||||||
|
var queryTerms = normalizedQuery.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
|
||||||
|
return GetNavigationItems(manageAccountsDescription)
|
||||||
|
.Where(item => item.PageType.HasValue && !item.IsSeparator && item.PageType.Value != WinoPage.SettingOptionsPage)
|
||||||
|
.Select(item => new
|
||||||
|
{
|
||||||
|
Item = item,
|
||||||
|
Score = CalculateSearchScore(item, normalizedQuery, queryTerms)
|
||||||
|
})
|
||||||
|
.Where(x => x.Score > 0)
|
||||||
|
.OrderByDescending(x => x.Score)
|
||||||
|
.ThenBy(x => x.Item.Title)
|
||||||
|
.Select(x => x.Item)
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
public static SettingsNavigationItemInfo GetInfo(WinoPage pageType, string manageAccountsDescription = "")
|
public static SettingsNavigationItemInfo GetInfo(WinoPage pageType, string manageAccountsDescription = "")
|
||||||
{
|
{
|
||||||
var rootPage = GetRootPage(pageType);
|
var rootPage = GetRootPage(pageType);
|
||||||
@@ -119,4 +159,58 @@ public static class SettingsNavigationInfoProvider
|
|||||||
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarSettingsPage,
|
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarSettingsPage,
|
||||||
_ => pageType
|
_ => pageType
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static int CalculateSearchScore(SettingsNavigationItemInfo item, string normalizedQuery, IReadOnlyList<string> queryTerms)
|
||||||
|
{
|
||||||
|
var title = NormalizeSearchText(item.Title);
|
||||||
|
var description = NormalizeSearchText(item.Description);
|
||||||
|
var keywords = NormalizeSearchText(item.SearchKeywords);
|
||||||
|
var combinedText = string.Join(' ', new[] { title, description, keywords }.Where(text => !string.IsNullOrWhiteSpace(text)));
|
||||||
|
|
||||||
|
if (!combinedText.Contains(normalizedQuery, StringComparison.Ordinal) &&
|
||||||
|
!queryTerms.All(term => combinedText.Contains(term, StringComparison.Ordinal)))
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var score = 0;
|
||||||
|
|
||||||
|
if (title.StartsWith(normalizedQuery, StringComparison.Ordinal))
|
||||||
|
score += 500;
|
||||||
|
else if (title.Contains(normalizedQuery, StringComparison.Ordinal))
|
||||||
|
score += 360;
|
||||||
|
|
||||||
|
if (keywords.Contains(normalizedQuery, StringComparison.Ordinal))
|
||||||
|
score += 280;
|
||||||
|
|
||||||
|
if (description.Contains(normalizedQuery, StringComparison.Ordinal))
|
||||||
|
score += 180;
|
||||||
|
|
||||||
|
foreach (var term in queryTerms)
|
||||||
|
{
|
||||||
|
if (title.Contains(term, StringComparison.Ordinal))
|
||||||
|
score += 70;
|
||||||
|
|
||||||
|
if (keywords.Contains(term, StringComparison.Ordinal))
|
||||||
|
score += 50;
|
||||||
|
|
||||||
|
if (description.Contains(term, StringComparison.Ordinal))
|
||||||
|
score += 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
return score;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeSearchText(string value)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(value))
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
var sanitized = value
|
||||||
|
.ToLowerInvariant()
|
||||||
|
.Select(character => char.IsLetterOrDigit(character) ? character : ' ')
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
return string.Join(' ', new string(sanitized).Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -143,6 +143,8 @@
|
|||||||
"CalendarEventCompose_Location": "Location",
|
"CalendarEventCompose_Location": "Location",
|
||||||
"CalendarEventCompose_LocationPlaceholder": "Add a location",
|
"CalendarEventCompose_LocationPlaceholder": "Add a location",
|
||||||
"CalendarEventCompose_NewEventButton": "New Event",
|
"CalendarEventCompose_NewEventButton": "New Event",
|
||||||
|
"CalendarEventCompose_DefaultCalendarHint": "You can choose a default calendar for new events in Calendar settings.",
|
||||||
|
"CalendarEventCompose_DefaultCalendarSettingsLink": "Open Calendar settings",
|
||||||
"CalendarEventCompose_NoCalendarsMessage": "There are no calendars available for event creation yet.",
|
"CalendarEventCompose_NoCalendarsMessage": "There are no calendars available for event creation yet.",
|
||||||
"CalendarEventCompose_NoCalendarsTitle": "No calendars available",
|
"CalendarEventCompose_NoCalendarsTitle": "No calendars available",
|
||||||
"CalendarEventCompose_NoEndDate": "No end date",
|
"CalendarEventCompose_NoEndDate": "No end date",
|
||||||
@@ -816,6 +818,22 @@
|
|||||||
"SettingsNotificationsAndTaskbar_Description": "Change whether notifications should be displayed and taskbar badge for this account.",
|
"SettingsNotificationsAndTaskbar_Description": "Change whether notifications should be displayed and taskbar badge for this account.",
|
||||||
"SettingsNotificationsAndTaskbar_Title": "Notifications & Taskbar",
|
"SettingsNotificationsAndTaskbar_Title": "Notifications & Taskbar",
|
||||||
"SettingsHome_Title": "Home",
|
"SettingsHome_Title": "Home",
|
||||||
|
"SettingsHome_SearchTitle": "Find a setting",
|
||||||
|
"SettingsHome_SearchDescription": "Search by feature, topic, or keyword to jump straight to the right settings page.",
|
||||||
|
"SettingsHome_SearchPlaceholder": "Search settings",
|
||||||
|
"SettingsHome_SearchExamples": "Try: theme, storage, language, signature",
|
||||||
|
"SettingsHome_QuickLinks_Title": "Quick links",
|
||||||
|
"SettingsHome_QuickLinks_Description": "Jump into the settings people reach for most often.",
|
||||||
|
"SettingsHome_StorageCard_Description": "See how much local MIME content Wino keeps on this device and clean it up when needed.",
|
||||||
|
"SettingsHome_StorageEmptySummary": "No cached MIME content detected yet.",
|
||||||
|
"SettingsHome_StorageLoading": "Checking local MIME usage...",
|
||||||
|
"SettingsHome_Tips_Title": "Tips & tricks",
|
||||||
|
"SettingsHome_Tips_Description": "A few small changes can make Wino feel much more personal.",
|
||||||
|
"SettingsHome_Tip_Theme": "Want dark mode or accent changes? Open Personalization.",
|
||||||
|
"SettingsHome_Tip_Background": "Use App Preferences to control startup behavior and background sync.",
|
||||||
|
"SettingsHome_Tip_Shortcuts": "Keyboard Shortcuts helps you move through mail faster.",
|
||||||
|
"SettingsHome_Resources_Title": "Helpful links",
|
||||||
|
"SettingsHome_Resources_Description": "Open project resources, support info, and release channels.",
|
||||||
"SettingsOptions_Title": "Settings",
|
"SettingsOptions_Title": "Settings",
|
||||||
"SettingsOptions_GeneralSection": "General",
|
"SettingsOptions_GeneralSection": "General",
|
||||||
"SettingsOptions_MailSection": "Mail",
|
"SettingsOptions_MailSection": "Mail",
|
||||||
@@ -823,6 +841,17 @@
|
|||||||
"SettingsOptions_MoreComingSoon": "More options coming soon",
|
"SettingsOptions_MoreComingSoon": "More options coming soon",
|
||||||
"SettingsOptions_HeroDescription": "Customize your Wino Mail experience",
|
"SettingsOptions_HeroDescription": "Customize your Wino Mail experience",
|
||||||
"SettingsOptions_AccountsSummary": "{0} account(s) configured",
|
"SettingsOptions_AccountsSummary": "{0} account(s) configured",
|
||||||
|
"SettingsSearch_ManageAccounts_Keywords": "account;accounts;mailbox;mailboxes;alias;aliases;profile;address;addresses",
|
||||||
|
"SettingsSearch_AppPreferences_Keywords": "startup;background;launch;sync;notification;notifications;search;tray;defaults",
|
||||||
|
"SettingsSearch_LanguageTime_Keywords": "language;time;clock;locale;region;format;24 hour;24h",
|
||||||
|
"SettingsSearch_Personalization_Keywords": "theme;dark;light;appearance;accent;color;colour;mode;layout;density",
|
||||||
|
"SettingsSearch_About_Keywords": "about;version;website;privacy;github;donate;store;support",
|
||||||
|
"SettingsSearch_KeyboardShortcuts_Keywords": "shortcut;shortcuts;hotkey;hotkeys;keyboard;keys",
|
||||||
|
"SettingsSearch_MessageList_Keywords": "message;messages;list;threading;threads;avatar;preview;sender",
|
||||||
|
"SettingsSearch_ReadComposePane_Keywords": "reader;compose;composer;font;fonts;external content;display;reading",
|
||||||
|
"SettingsSearch_SignatureAndEncryption_Keywords": "signature;signatures;encryption;certificate;certificates;s mime;smime;security",
|
||||||
|
"SettingsSearch_Storage_Keywords": "storage;cache;caching;mime;disk;space;cleanup;clean up;local data",
|
||||||
|
"SettingsSearch_CalendarSettings_Keywords": "calendar;week;hours;schedule;event;events",
|
||||||
"SettingsPaneLengthReset_Description": "Reset the size of the mail list to original if you have issues with it.",
|
"SettingsPaneLengthReset_Description": "Reset the size of the mail list to original if you have issues with it.",
|
||||||
"SettingsPaneLengthReset_Title": "Reset Mail List Size",
|
"SettingsPaneLengthReset_Title": "Reset Mail List Size",
|
||||||
"SettingsPaypal_Description": "Show much more love ❤️ All donations are appreciated.",
|
"SettingsPaypal_Description": "Show much more love ❤️ All donations are appreciated.",
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using CommunityToolkit.Mvvm.ComponentModel;
|
using CommunityToolkit.Mvvm.ComponentModel;
|
||||||
using CommunityToolkit.Mvvm.Input;
|
using CommunityToolkit.Mvvm.Input;
|
||||||
@@ -8,6 +11,7 @@ using Wino.Core.Domain.Enums;
|
|||||||
using Wino.Core.Domain.Interfaces;
|
using Wino.Core.Domain.Interfaces;
|
||||||
using Wino.Core.Domain.Models.Navigation;
|
using Wino.Core.Domain.Models.Navigation;
|
||||||
using Wino.Core.Domain.Models.Settings;
|
using Wino.Core.Domain.Models.Settings;
|
||||||
|
using Wino.Core.Extensions;
|
||||||
using Wino.Messaging.Client.Navigation;
|
using Wino.Messaging.Client.Navigation;
|
||||||
|
|
||||||
namespace Wino.Core.ViewModels;
|
namespace Wino.Core.ViewModels;
|
||||||
@@ -16,10 +20,15 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
|
|||||||
{
|
{
|
||||||
private readonly INativeAppService _nativeAppService;
|
private readonly INativeAppService _nativeAppService;
|
||||||
private readonly IAccountService _accountService;
|
private readonly IAccountService _accountService;
|
||||||
|
private readonly IMimeStorageService _mimeStorageService;
|
||||||
private readonly IStoreRatingService _storeRatingService;
|
private readonly IStoreRatingService _storeRatingService;
|
||||||
|
|
||||||
public string GitHubUrl => AppUrls.GitHub;
|
public string GitHubUrl => AppUrls.GitHub;
|
||||||
public string PaypalUrl => AppUrls.Paypal;
|
public string PaypalUrl => AppUrls.Paypal;
|
||||||
|
public string WebsiteUrl => AppUrls.Website;
|
||||||
|
public string PrivacyPolicyUrl => AppUrls.PrivacyPolicy;
|
||||||
|
|
||||||
|
public ObservableCollection<SettingsNavigationItemInfo> SearchSuggestions { get; } = [];
|
||||||
|
|
||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial string VersionText { get; set; } = string.Empty;
|
public partial string VersionText { get; set; } = string.Empty;
|
||||||
@@ -30,12 +39,20 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
|
|||||||
[ObservableProperty]
|
[ObservableProperty]
|
||||||
public partial int AccountCount { get; set; }
|
public partial int AccountCount { get; set; }
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string StorageSummaryText { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
[ObservableProperty]
|
||||||
|
public partial string SearchQuery { get; set; } = string.Empty;
|
||||||
|
|
||||||
public SettingOptionsPageViewModel(INativeAppService nativeAppService,
|
public SettingOptionsPageViewModel(INativeAppService nativeAppService,
|
||||||
IAccountService accountService,
|
IAccountService accountService,
|
||||||
|
IMimeStorageService mimeStorageService,
|
||||||
IStoreRatingService storeRatingService)
|
IStoreRatingService storeRatingService)
|
||||||
{
|
{
|
||||||
_nativeAppService = nativeAppService;
|
_nativeAppService = nativeAppService;
|
||||||
_accountService = accountService;
|
_accountService = accountService;
|
||||||
|
_mimeStorageService = mimeStorageService;
|
||||||
_storeRatingService = storeRatingService;
|
_storeRatingService = storeRatingService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,18 +61,57 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
|
|||||||
base.OnNavigatedTo(mode, parameters);
|
base.OnNavigatedTo(mode, parameters);
|
||||||
|
|
||||||
VersionText = string.Format("{0}{1}", Translator.SettingsAboutVersion, _nativeAppService.GetFullAppVersion());
|
VersionText = string.Format("{0}{1}", Translator.SettingsAboutVersion, _nativeAppService.GetFullAppVersion());
|
||||||
_ = LoadAccountSummaryAsync();
|
SearchQuery = string.Empty;
|
||||||
|
SearchSuggestions.Clear();
|
||||||
|
StorageSummaryText = Translator.SettingsHome_StorageLoading;
|
||||||
|
|
||||||
|
_ = LoadDashboardAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task LoadAccountSummaryAsync()
|
public void UpdateSearchSuggestions(string query)
|
||||||
{
|
{
|
||||||
var accounts = await _accountService.GetAccountsAsync();
|
SearchQuery = query;
|
||||||
int count = accounts?.Count ?? 0;
|
|
||||||
|
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 WinoPage pageType)
|
||||||
|
{
|
||||||
|
NavigateSubDetail(pageType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadDashboardAsync()
|
||||||
|
{
|
||||||
|
var accounts = await _accountService.GetAccountsAsync().ConfigureAwait(false) ?? [];
|
||||||
|
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();
|
||||||
|
|
||||||
await ExecuteUIThread(() =>
|
await ExecuteUIThread(() =>
|
||||||
{
|
{
|
||||||
AccountCount = count;
|
AccountCount = count;
|
||||||
AccountSummaryText = string.Format(Translator.SettingsOptions_AccountsSummary, count);
|
AccountSummaryText = string.Format(Translator.SettingsOptions_AccountsSummary, count);
|
||||||
|
StorageSummaryText = totalStorageBytes == 0
|
||||||
|
? Translator.SettingsHome_StorageEmptySummary
|
||||||
|
: string.Format(Translator.SettingsStorage_TotalUsage, totalStorageBytes.GetBytesReadable());
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(SearchQuery))
|
||||||
|
{
|
||||||
|
UpdateSearchSuggestions(SearchQuery);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,8 +40,7 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
|||||||
IRecipient<NavigateAppPreferencesRequested>,
|
IRecipient<NavigateAppPreferencesRequested>,
|
||||||
IRecipient<AccountFolderConfigurationUpdated>,
|
IRecipient<AccountFolderConfigurationUpdated>,
|
||||||
IRecipient<AccountRemovedMessage>,
|
IRecipient<AccountRemovedMessage>,
|
||||||
IRecipient<AccountUpdatedMessage>,
|
IRecipient<AccountUpdatedMessage>
|
||||||
IRecipient<AccountCreatedMessage>
|
|
||||||
{
|
{
|
||||||
#region Menu Items
|
#region Menu Items
|
||||||
|
|
||||||
@@ -1154,7 +1153,6 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
|||||||
{
|
{
|
||||||
base.RegisterRecipients();
|
base.RegisterRecipients();
|
||||||
|
|
||||||
Messenger.Register<AccountCreatedMessage>(this);
|
|
||||||
Messenger.Register<AccountRemovedMessage>(this);
|
Messenger.Register<AccountRemovedMessage>(this);
|
||||||
Messenger.Register<AccountUpdatedMessage>(this);
|
Messenger.Register<AccountUpdatedMessage>(this);
|
||||||
Messenger.Register<MailtoProtocolMessageRequested>(this);
|
Messenger.Register<MailtoProtocolMessageRequested>(this);
|
||||||
@@ -1172,7 +1170,6 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
|||||||
{
|
{
|
||||||
base.UnregisterRecipients();
|
base.UnregisterRecipients();
|
||||||
|
|
||||||
Messenger.Unregister<AccountCreatedMessage>(this);
|
|
||||||
Messenger.Unregister<AccountRemovedMessage>(this);
|
Messenger.Unregister<AccountRemovedMessage>(this);
|
||||||
Messenger.Unregister<AccountUpdatedMessage>(this);
|
Messenger.Unregister<AccountUpdatedMessage>(this);
|
||||||
Messenger.Unregister<MailtoProtocolMessageRequested>(this);
|
Messenger.Unregister<MailtoProtocolMessageRequested>(this);
|
||||||
@@ -1198,14 +1195,17 @@ public partial class MailAppShellViewModel : MailBaseViewModel,
|
|||||||
await RestoreSelectedAccountAfterMenuRefreshAsync(false);
|
await RestoreSelectedAccountAfterMenuRefreshAsync(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async void Receive(AccountCreatedMessage message)
|
public async Task HandleAccountCreatedAsync(MailAccount createdAccount)
|
||||||
{
|
{
|
||||||
var createdAccount = message.Account;
|
|
||||||
latestSelectedAccountMenuItem = null;
|
latestSelectedAccountMenuItem = null;
|
||||||
|
|
||||||
await RecreateMenuItemsAsync();
|
await RecreateMenuItemsAsync();
|
||||||
|
|
||||||
if (!MenuItems.TryGetAccountMenuItem(createdAccount.Id, out IAccountMenuItem createdMenuItem)) return;
|
if (!MenuItems.TryGetAccountMenuItem(createdAccount.Id, out IAccountMenuItem createdMenuItem))
|
||||||
|
{
|
||||||
|
Log.Warning("Created account {AccountId} could not be found in menu items after refresh.", createdAccount.Id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await ChangeLoadedAccountAsync(createdMenuItem);
|
await ChangeLoadedAccountAsync(createdMenuItem);
|
||||||
|
|
||||||
|
|||||||
@@ -722,6 +722,7 @@ public partial class App : WinoApplication,
|
|||||||
public void Receive(AccountCreatedMessage message)
|
public void Receive(AccountCreatedMessage message)
|
||||||
{
|
{
|
||||||
var windowManager = Services.GetRequiredService<IWinoWindowManager>();
|
var windowManager = Services.GetRequiredService<IWinoWindowManager>();
|
||||||
|
var navigationService = Services.GetRequiredService<INavigationService>();
|
||||||
|
|
||||||
// Only transition when the account was created from the WelcomeWindow.
|
// Only transition when the account was created from the WelcomeWindow.
|
||||||
if (windowManager.GetWindow(WinoWindowKind.Welcome) == null)
|
if (windowManager.GetWindow(WinoWindowKind.Welcome) == null)
|
||||||
@@ -732,6 +733,7 @@ public partial class App : WinoApplication,
|
|||||||
// Create and activate ShellWindow — ActiveWindowChanged fires and rebinds the dispatcher.
|
// Create and activate ShellWindow — ActiveWindowChanged fires and rebinds the dispatcher.
|
||||||
CreateWindow(null);
|
CreateWindow(null);
|
||||||
windowManager.HideWindow(WinoWindowKind.Welcome);
|
windowManager.HideWindow(WinoWindowKind.Welcome);
|
||||||
|
navigationService.ChangeApplicationMode(Core.Domain.Enums.WinoApplicationMode.Mail);
|
||||||
await NewThemeService.ApplyThemeToActiveWindowAsync();
|
await NewThemeService.ApplyThemeToActiveWindowAsync();
|
||||||
MainWindow?.Activate();
|
MainWindow?.Activate();
|
||||||
RestartAutoSynchronizationLoop();
|
RestartAutoSynchronizationLoop();
|
||||||
|
|||||||
@@ -25,49 +25,62 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</ContentDialog.Resources>
|
</ContentDialog.Resources>
|
||||||
|
|
||||||
<ScrollViewer Margin="0,8,0,0">
|
<StackPanel Margin="0,8,0,0" Spacing="12">
|
||||||
<ItemsControl ItemsSource="{x:Bind AvailableGroups}">
|
<TextBlock
|
||||||
<ItemsControl.ItemTemplate>
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
<DataTemplate x:DataType="calendar:CalendarPickerAccountGroup">
|
Text="{x:Bind domain:Translator.CalendarEventCompose_DefaultCalendarHint, Mode=OneWay}"
|
||||||
<StackPanel Margin="0,0,0,12" Spacing="6">
|
TextWrapping="WrapWholeWords" />
|
||||||
<TextBlock FontWeight="SemiBold">
|
|
||||||
<Run Text="{x:Bind Account.Name}" />
|
|
||||||
<Run Text=" (" />
|
|
||||||
<Run Text="{x:Bind Account.Address}" />
|
|
||||||
<Run Text=")" />
|
|
||||||
</TextBlock>
|
|
||||||
|
|
||||||
<ListView
|
<HyperlinkButton
|
||||||
IsItemClickEnabled="True"
|
HorizontalAlignment="Left"
|
||||||
ItemClick="CalendarClicked"
|
Click="OpenCalendarSettingsClicked"
|
||||||
ItemContainerStyle="{StaticResource CalendarPickerListItemStyle}"
|
Content="{x:Bind domain:Translator.CalendarEventCompose_DefaultCalendarSettingsLink, Mode=OneWay}"
|
||||||
ItemsSource="{x:Bind Calendars}"
|
Padding="0" />
|
||||||
SelectionMode="None">
|
|
||||||
<ListView.ItemTemplate>
|
|
||||||
<DataTemplate x:DataType="sharedCalendar:AccountCalendar">
|
|
||||||
<Grid ColumnSpacing="10">
|
|
||||||
<Grid.ColumnDefinitions>
|
|
||||||
<ColumnDefinition Width="Auto" />
|
|
||||||
<ColumnDefinition Width="*" />
|
|
||||||
</Grid.ColumnDefinitions>
|
|
||||||
|
|
||||||
<Ellipse
|
<ScrollViewer MaxHeight="400">
|
||||||
Width="14"
|
<ItemsControl ItemsSource="{x:Bind AvailableGroups}">
|
||||||
Height="14"
|
<ItemsControl.ItemTemplate>
|
||||||
VerticalAlignment="Center"
|
<DataTemplate x:DataType="calendar:CalendarPickerAccountGroup">
|
||||||
Fill="{x:Bind helpers:XamlHelpers.GetSolidColorBrushFromHex(BackgroundColorHex), Mode=OneWay}" />
|
<StackPanel Margin="0,0,0,12" Spacing="6">
|
||||||
|
<TextBlock FontWeight="SemiBold">
|
||||||
|
<Run Text="{x:Bind Account.Name}" />
|
||||||
|
<Run Text=" (" />
|
||||||
|
<Run Text="{x:Bind Account.Address}" />
|
||||||
|
<Run Text=")" />
|
||||||
|
</TextBlock>
|
||||||
|
|
||||||
<TextBlock
|
<ListView
|
||||||
Grid.Column="1"
|
IsItemClickEnabled="True"
|
||||||
VerticalAlignment="Center"
|
ItemClick="CalendarClicked"
|
||||||
Text="{x:Bind Name}" />
|
ItemContainerStyle="{StaticResource CalendarPickerListItemStyle}"
|
||||||
</Grid>
|
ItemsSource="{x:Bind Calendars}"
|
||||||
</DataTemplate>
|
SelectionMode="None">
|
||||||
</ListView.ItemTemplate>
|
<ListView.ItemTemplate>
|
||||||
</ListView>
|
<DataTemplate x:DataType="sharedCalendar:AccountCalendar">
|
||||||
</StackPanel>
|
<Grid ColumnSpacing="10">
|
||||||
</DataTemplate>
|
<Grid.ColumnDefinitions>
|
||||||
</ItemsControl.ItemTemplate>
|
<ColumnDefinition Width="Auto" />
|
||||||
</ItemsControl>
|
<ColumnDefinition Width="*" />
|
||||||
</ScrollViewer>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Ellipse
|
||||||
|
Width="14"
|
||||||
|
Height="14"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Fill="{x:Bind helpers:XamlHelpers.GetSolidColorBrushFromHex(BackgroundColorHex), Mode=OneWay}" />
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Text="{x:Bind Name}" />
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</ListView.ItemTemplate>
|
||||||
|
</ListView>
|
||||||
|
</StackPanel>
|
||||||
|
</DataTemplate>
|
||||||
|
</ItemsControl.ItemTemplate>
|
||||||
|
</ItemsControl>
|
||||||
|
</ScrollViewer>
|
||||||
|
</StackPanel>
|
||||||
</ContentDialog>
|
</ContentDialog>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Wino.Core.Domain.Entities.Calendar;
|
using Wino.Core.Domain.Entities.Calendar;
|
||||||
using Wino.Core.Domain.Models.Calendar;
|
using Wino.Core.Domain.Models.Calendar;
|
||||||
@@ -8,6 +9,7 @@ namespace Wino.Dialogs;
|
|||||||
public sealed partial class SingleCalendarPickerDialog : ContentDialog
|
public sealed partial class SingleCalendarPickerDialog : ContentDialog
|
||||||
{
|
{
|
||||||
public AccountCalendar? PickedCalendar { get; private set; }
|
public AccountCalendar? PickedCalendar { get; private set; }
|
||||||
|
public bool ShouldNavigateToCalendarSettings { get; private set; }
|
||||||
|
|
||||||
public List<CalendarPickerAccountGroup> AvailableGroups { get; } = [];
|
public List<CalendarPickerAccountGroup> AvailableGroups { get; } = [];
|
||||||
|
|
||||||
@@ -23,4 +25,10 @@ public sealed partial class SingleCalendarPickerDialog : ContentDialog
|
|||||||
PickedCalendar = e.ClickedItem as AccountCalendar;
|
PickedCalendar = e.ClickedItem as AccountCalendar;
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OpenCalendarSettingsClicked(object sender, RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
ShouldNavigateToCalendarSettings = true;
|
||||||
|
Hide();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -124,7 +124,7 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
|||||||
return accountPicker.PickedAccount ?? null!;
|
return accountPicker.PickedAccount ?? null!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AccountCalendar> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups)
|
public async Task<AccountCalendarPickingResult> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups)
|
||||||
{
|
{
|
||||||
var calendarPicker = new SingleCalendarPickerDialog(availableCalendarGroups)
|
var calendarPicker = new SingleCalendarPickerDialog(availableCalendarGroups)
|
||||||
{
|
{
|
||||||
@@ -133,7 +133,7 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
|||||||
|
|
||||||
await HandleDialogPresentationAsync(calendarPicker);
|
await HandleDialogPresentationAsync(calendarPicker);
|
||||||
|
|
||||||
return calendarPicker.PickedCalendar ?? null!;
|
return new AccountCalendarPickingResult(calendarPicker.PickedCalendar, calendarPicker.ShouldNavigateToCalendarSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature? signatureModel = null)
|
public async Task<AccountSignature> ShowSignatureEditorDialog(AccountSignature? signatureModel = null)
|
||||||
|
|||||||
@@ -247,6 +247,8 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
IsInitialActivation = isInitialShellNavigation,
|
IsInitialActivation = isInitialShellNavigation,
|
||||||
Parameter = activationParameter
|
Parameter = activationParameter
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ResetCurrentModeBackStackState();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,6 +325,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
if (innerShellFrame.CanGoBack && lastBackStackEntry?.SourcePageType == pageType)
|
if (innerShellFrame.CanGoBack && lastBackStackEntry?.SourcePageType == pageType)
|
||||||
{
|
{
|
||||||
innerShellFrame.GoBack();
|
innerShellFrame.GoBack();
|
||||||
|
UpdateCurrentModeBackStackState(innerShellFrame);
|
||||||
WeakReferenceMessenger.Default.Send(loadCalendarMessage);
|
WeakReferenceMessenger.Default.Send(loadCalendarMessage);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -483,7 +486,14 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
private bool NavigateInnerShellFrame(Frame frame, Type pageType, object? parameter, NavigationTransitionType transition)
|
private bool NavigateInnerShellFrame(Frame frame, Type pageType, object? parameter, NavigationTransitionType transition)
|
||||||
{
|
{
|
||||||
var transitionInfo = ConsumeInnerShellTransitionOrDefault(transition);
|
var transitionInfo = ConsumeInnerShellTransitionOrDefault(transition);
|
||||||
return frame.Navigate(pageType, parameter, transitionInfo);
|
var navigationResult = frame.Navigate(pageType, parameter, transitionInfo);
|
||||||
|
|
||||||
|
if (navigationResult)
|
||||||
|
{
|
||||||
|
UpdateCurrentModeBackStackState(frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigationResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private NavigationTransitionInfo ConsumeInnerShellTransitionOrDefault(NavigationTransitionType transition)
|
private NavigationTransitionInfo ConsumeInnerShellTransitionOrDefault(NavigationTransitionType transition)
|
||||||
@@ -503,36 +513,67 @@ public class NavigationService : NavigationServiceBase, INavigationService
|
|||||||
|
|
||||||
private void GoBackInternal(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
|
private void GoBackInternal(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
|
||||||
{
|
{
|
||||||
if (_statePersistanceService.IsSettingsNavigating)
|
var innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
||||||
|
|
||||||
|
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Settings &&
|
||||||
|
_statePersistanceService.HasCurrentModeBackStack)
|
||||||
{
|
{
|
||||||
WeakReferenceMessenger.Default.Send(new BackBreadcrumNavigationRequested(slideEffect));
|
WeakReferenceMessenger.Default.Send(new BackBreadcrumNavigationRequested(slideEffect));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Settings &&
|
||||||
|
innerShellFrame?.Content is SettingsPage)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && innerShellFrame?.CanGoBack == true)
|
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar && innerShellFrame?.CanGoBack == true)
|
||||||
{
|
{
|
||||||
innerShellFrame.GoBack();
|
innerShellFrame.GoBack();
|
||||||
|
UpdateCurrentModeBackStackState(innerShellFrame);
|
||||||
|
|
||||||
// Calendar mode: Navigate back from EventDetailsPage
|
// Calendar mode: Navigate back from EventDetailsPage
|
||||||
_statePersistanceService.IsEventDetailsVisible = false;
|
_statePersistanceService.IsEventDetailsVisible = false;
|
||||||
}
|
}
|
||||||
else
|
else if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Mail)
|
||||||
{
|
{
|
||||||
if (_statePersistanceService.IsReadingMail && _statePersistanceService.IsReaderNarrowed)
|
if (_statePersistanceService.IsReadingMail && _statePersistanceService.IsReaderNarrowed)
|
||||||
{
|
{
|
||||||
// Mail mode: Clear selections and dispose rendering frame
|
// Mail mode: Clear selections and dispose rendering frame
|
||||||
_statePersistanceService.IsReadingMail = false;
|
_statePersistanceService.IsReadingMail = false;
|
||||||
|
_statePersistanceService.HasCurrentModeBackStack = false;
|
||||||
|
|
||||||
WeakReferenceMessenger.Default.Send(new ClearMailSelectionsRequested());
|
WeakReferenceMessenger.Default.Send(new ClearMailSelectionsRequested());
|
||||||
WeakReferenceMessenger.Default.Send(new DisposeRenderingFrameRequested());
|
WeakReferenceMessenger.Default.Send(new DisposeRenderingFrameRequested());
|
||||||
}
|
}
|
||||||
else if (innerShellFrame != null && innerShellFrame.CanGoBack)
|
|
||||||
{
|
|
||||||
innerShellFrame.GoBack();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateCurrentModeBackStackState(innerShellFrame);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ResetCurrentModeBackStackState()
|
||||||
|
{
|
||||||
|
var innerShellFrame = GetCoreFrameInternal(NavigationReferenceFrame.InnerShellFrame);
|
||||||
|
|
||||||
|
if (innerShellFrame != null)
|
||||||
|
{
|
||||||
|
innerShellFrame.BackStack.Clear();
|
||||||
|
innerShellFrame.ForwardStack.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
_statePersistanceService.HasCurrentModeBackStack = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateCurrentModeBackStackState(Frame? innerShellFrame)
|
||||||
|
{
|
||||||
|
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Settings)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_statePersistanceService.HasCurrentModeBackStack = _statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar &&
|
||||||
|
innerShellFrame?.CanGoBack == true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Standalone EML viewer.
|
// Standalone EML viewer.
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
|
|||||||
|
|
||||||
public bool IsBackButtonVisible =>
|
public bool IsBackButtonVisible =>
|
||||||
ApplicationMode == WinoApplicationMode.Mail
|
ApplicationMode == WinoApplicationMode.Mail
|
||||||
? (IsReadingMail && IsReaderNarrowed) || IsSettingsNavigating
|
? (IsReadingMail && IsReaderNarrowed) || HasCurrentModeBackStack
|
||||||
: IsEventDetailsVisible || IsSettingsNavigating;
|
: IsEventDetailsVisible || HasCurrentModeBackStack;
|
||||||
|
|
||||||
private WinoApplicationMode applicationMode = WinoApplicationMode.Mail;
|
private WinoApplicationMode applicationMode = WinoApplicationMode.Mail;
|
||||||
|
|
||||||
@@ -68,14 +68,14 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool isSettingsNavigating;
|
private bool hasCurrentModeBackStack;
|
||||||
|
|
||||||
public bool IsSettingsNavigating
|
public bool HasCurrentModeBackStack
|
||||||
{
|
{
|
||||||
get => isSettingsNavigating;
|
get => hasCurrentModeBackStack;
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (SetProperty(ref isSettingsNavigating, value))
|
if (SetProperty(ref hasCurrentModeBackStack, value))
|
||||||
{
|
{
|
||||||
OnPropertyChanged(nameof(IsBackButtonVisible));
|
OnPropertyChanged(nameof(IsBackButtonVisible));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,23 +64,51 @@
|
|||||||
|
|
||||||
<DataTemplate x:Key="SettingsShellSectionItemTemplate" x:DataType="menu:SettingsShellSectionMenuItem">
|
<DataTemplate x:Key="SettingsShellSectionItemTemplate" x:DataType="menu:SettingsShellSectionMenuItem">
|
||||||
<coreControls:WinoNavigationViewItem
|
<coreControls:WinoNavigationViewItem
|
||||||
Margin="0,10,0,2"
|
Margin="0,12,0,4"
|
||||||
HorizontalContentAlignment="Center"
|
HorizontalContentAlignment="Stretch"
|
||||||
DataContext="{x:Bind}"
|
DataContext="{x:Bind}"
|
||||||
IsEnabled="False"
|
IsEnabled="False"
|
||||||
SelectsOnInvoked="False">
|
SelectsOnInvoked="False">
|
||||||
<muxc:NavigationViewItem.Icon>
|
<Grid ColumnSpacing="10">
|
||||||
<FontIcon
|
<Grid.ColumnDefinitions>
|
||||||
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
<ColumnDefinition Width="Auto" />
|
||||||
FontSize="12"
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<Border
|
||||||
|
Width="24"
|
||||||
|
Height="24"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorSecondaryBrush}"
|
||||||
|
BorderBrush="{ThemeResource DividerStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="12">
|
||||||
|
<FontIcon
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
|
FontSize="12"
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Glyph="{x:Bind Glyph}" />
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Grid.Column="1"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
CharacterSpacing="40"
|
||||||
|
FontWeight="SemiBold"
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
Glyph="{x:Bind Glyph}" />
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
</muxc:NavigationViewItem.Icon>
|
Text="{x:Bind Title}"
|
||||||
<TextBlock
|
TextWrapping="NoWrap" />
|
||||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
|
||||||
Style="{StaticResource CaptionTextBlockStyle}"
|
<Border
|
||||||
Text="{x:Bind Title}"
|
Grid.Column="2"
|
||||||
TextWrapping="NoWrap" />
|
Height="1"
|
||||||
|
Margin="2,0,0,0"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Background="{ThemeResource DividerStrokeColorDefaultBrush}" />
|
||||||
|
</Grid>
|
||||||
</coreControls:WinoNavigationViewItem>
|
</coreControls:WinoNavigationViewItem>
|
||||||
</DataTemplate>
|
</DataTemplate>
|
||||||
|
|
||||||
|
|||||||
@@ -3,43 +3,85 @@
|
|||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:abstract="using:Wino.Views.Abstract"
|
xmlns:abstract="using:Wino.Views.Abstract"
|
||||||
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
|
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:domain="using:Wino.Core.Domain"
|
xmlns:domain="using:Wino.Core.Domain"
|
||||||
xmlns:enums="using:Wino.Core.Domain.Enums"
|
xmlns:enums="using:Wino.Core.Domain.Enums"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
|
xmlns:settingsModels="using:Wino.Core.Domain.Models.Settings"
|
||||||
x:Name="root"
|
x:Name="root"
|
||||||
Title="{x:Bind domain:Translator.SettingsHome_Title}"
|
Title="{x:Bind domain:Translator.SettingsHome_Title}"
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
|
|
||||||
<ScrollViewer Padding="0,0,16,0" VerticalScrollBarVisibility="Auto">
|
<ScrollViewer Padding="0,0,16,0" VerticalScrollBarVisibility="Auto">
|
||||||
<StackPanel Margin="0,8,0,24" Spacing="12">
|
<StackPanel Margin="0,8,0,24" Spacing="16">
|
||||||
<StackPanel.ChildrenTransitions>
|
<StackPanel.ChildrenTransitions>
|
||||||
<TransitionCollection>
|
<TransitionCollection>
|
||||||
<EntranceThemeTransition FromVerticalOffset="50" IsStaggeringEnabled="True" />
|
<EntranceThemeTransition FromVerticalOffset="50" IsStaggeringEnabled="True" />
|
||||||
</TransitionCollection>
|
</TransitionCollection>
|
||||||
</StackPanel.ChildrenTransitions>
|
</StackPanel.ChildrenTransitions>
|
||||||
|
|
||||||
<Grid
|
<Border
|
||||||
Margin="0,0,0,12"
|
Padding="24"
|
||||||
Padding="24,28"
|
|
||||||
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||||
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||||
BorderThickness="1"
|
BorderThickness="1"
|
||||||
CornerRadius="8">
|
CornerRadius="8">
|
||||||
<Grid.ColumnDefinitions>
|
<StackPanel Spacing="8">
|
||||||
<ColumnDefinition Width="Auto" />
|
<AutoSuggestBox
|
||||||
<ColumnDefinition Width="*" />
|
x:Name="SettingsSearchBox"
|
||||||
</Grid.ColumnDefinitions>
|
ItemsSource="{x:Bind ViewModel.SearchSuggestions, Mode=OneWay}"
|
||||||
|
PlaceholderText="{x:Bind domain:Translator.SettingsHome_SearchPlaceholder, Mode=OneTime}"
|
||||||
|
QueryIcon="Find"
|
||||||
|
QuerySubmitted="SettingsSearchQuerySubmitted"
|
||||||
|
SuggestionChosen="SettingsSearchSuggestionChosen"
|
||||||
|
Text="{x:Bind ViewModel.SearchQuery, Mode=TwoWay}"
|
||||||
|
TextChanged="SettingsSearchTextChanged">
|
||||||
|
<AutoSuggestBox.ItemTemplate>
|
||||||
|
<DataTemplate x:DataType="settingsModels:SettingsNavigationItemInfo">
|
||||||
|
<Grid Padding="0,4" ColumnSpacing="10">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<Grid
|
<FontIcon
|
||||||
Grid.Column="1"
|
VerticalAlignment="Top"
|
||||||
Margin="8,0,0,0"
|
FontFamily="{StaticResource SymbolThemeFontFamily}"
|
||||||
VerticalAlignment="Center"
|
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||||
ColumnSpacing="12">
|
Glyph="{x:Bind Glyph}" />
|
||||||
<Grid.RowDefinitions>
|
|
||||||
<RowDefinition Height="*" />
|
<StackPanel Grid.Column="1" Spacing="2">
|
||||||
</Grid.RowDefinitions>
|
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}" Text="{x:Bind Title}" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind Description}"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
</StackPanel>
|
||||||
|
</Grid>
|
||||||
|
</DataTemplate>
|
||||||
|
</AutoSuggestBox.ItemTemplate>
|
||||||
|
</AutoSuggestBox>
|
||||||
|
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind domain:Translator.SettingsHome_SearchExamples, Mode=OneTime}"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
|
<Border
|
||||||
|
Padding="24,20"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||||
|
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8">
|
||||||
|
<Grid ColumnSpacing="16" RowSpacing="16">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
@@ -65,14 +107,11 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
|
|
||||||
<StackPanel
|
<StackPanel
|
||||||
Grid.RowSpan="2"
|
Grid.Column="1"
|
||||||
Grid.Column="2"
|
|
||||||
Margin="0,12,0,0"
|
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Orientation="Horizontal"
|
Orientation="Horizontal"
|
||||||
Spacing="12">
|
Spacing="12">
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
CommandParameter="{x:Bind ViewModel.PaypalUrl, Mode=OneWay}"
|
CommandParameter="{x:Bind ViewModel.PaypalUrl, Mode=OneWay}"
|
||||||
@@ -87,23 +126,19 @@
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Grid.Column="1"
|
|
||||||
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
CommandParameter="{x:Bind ViewModel.GitHubUrl, Mode=OneWay}"
|
CommandParameter="{x:Bind ViewModel.GitHubUrl, Mode=OneWay}"
|
||||||
Style="{StaticResource DefaultButtonStyle}"
|
Style="{StaticResource DefaultButtonStyle}"
|
||||||
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsAboutGithub_Title}">
|
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsAboutGithub_Title}">
|
||||||
<StackPanel HorizontalAlignment="Center" Spacing="6">
|
<Viewbox Width="18" Height="18">
|
||||||
<Viewbox Width="18" Height="18">
|
<Path
|
||||||
<Path
|
Data="m 12.2135 0 c -6.7538 0 -12.2135 5.5 -12.2135 12.3042 c 0 5.439 3.4983 10.043 8.3513 11.6725 c 0.6067 0.1225 0.829 -0.2647 0.829 -0.5905 c 0 -0.2853 -0.02 -1.263 -0.02 -2.2817 c -3.3975 0.7335 -4.105 -1.4668 -4.105 -1.4668 c -0.546 -1.426 -1.355 -1.7925 -1.355 -1.7925 c -1.112 -0.7538 0.081 -0.7538 0.081 -0.7538 c 1.2335 0.0815 1.8807 1.263 1.8807 1.263 c 1.0918 1.874 2.851 1.3445 3.5587 1.0185 c 0.101 -0.7945 0.4247 -1.3445 0.7685 -1.65 c -2.7097 -0.2853 -5.5607 -1.3445 -5.5607 -6.0708 c 0 -1.3445 0.485 -2.4445 1.2535 -3.3 c -0.1212 -0.3055 -0.546 -1.5687 0.1215 -3.2595 c 0 0 1.0313 -0.326 3.3565 1.263 a 11.7425 11.7425 90 0 1 3.0535 -0.4075 c 1.0313 0 2.0825 0.1428 3.0533 0.4075 c 2.3255 -1.589 3.3567 -1.263 3.3567 -1.263 c 0.6675 1.6908 0.2425 2.954 0.1212 3.2595 c 0.7888 0.8555 1.2538 1.9555 1.2538 3.3 c 0 4.7263 -2.851 5.765 -5.581 6.0708 c 0.445 0.387 0.829 1.1202 0.829 2.2815 c 0 1.65 -0.02 2.9743 -0.02 3.3815 c 0 0.326 0.2225 0.7132 0.829 0.591 c 4.853 -1.63 8.3513 -6.2338 8.3513 -11.6728 c 0.02 -6.8043 -5.4598 -12.3043 -12.1933 -12.3043 z"
|
||||||
Data="m 12.2135 0 c -6.7538 0 -12.2135 5.5 -12.2135 12.3042 c 0 5.439 3.4983 10.043 8.3513 11.6725 c 0.6067 0.1225 0.829 -0.2647 0.829 -0.5905 c 0 -0.2853 -0.02 -1.263 -0.02 -2.2817 c -3.3975 0.7335 -4.105 -1.4668 -4.105 -1.4668 c -0.546 -1.426 -1.355 -1.7925 -1.355 -1.7925 c -1.112 -0.7538 0.081 -0.7538 0.081 -0.7538 c 1.2335 0.0815 1.8807 1.263 1.8807 1.263 c 1.0918 1.874 2.851 1.3445 3.5587 1.0185 c 0.101 -0.7945 0.4247 -1.3445 0.7685 -1.65 c -2.7097 -0.2853 -5.5607 -1.3445 -5.5607 -6.0708 c 0 -1.3445 0.485 -2.4445 1.2535 -3.3 c -0.1212 -0.3055 -0.546 -1.5687 0.1215 -3.2595 c 0 0 1.0313 -0.326 3.3565 1.263 a 11.7425 11.7425 90 0 1 3.0535 -0.4075 c 1.0313 0 2.0825 0.1428 3.0533 0.4075 c 2.3255 -1.589 3.3567 -1.263 3.3567 -1.263 c 0.6675 1.6908 0.2425 2.954 0.1212 3.2595 c 0.7888 0.8555 1.2538 1.9555 1.2538 3.3 c 0 4.7263 -2.851 5.765 -5.581 6.0708 c 0.445 0.387 0.829 1.1202 0.829 2.2815 c 0 1.65 -0.02 2.9743 -0.02 3.3815 c 0 0.326 0.2225 0.7132 0.829 0.591 c 4.853 -1.63 8.3513 -6.2338 8.3513 -11.6728 c 0.02 -6.8043 -5.4598 -12.3043 -12.1933 -12.3043 z"
|
Fill="{ThemeResource TextFillColorPrimaryBrush}"
|
||||||
Fill="{ThemeResource TextFillColorPrimaryBrush}"
|
Stretch="Uniform" />
|
||||||
Stretch="Uniform" />
|
</Viewbox>
|
||||||
</Viewbox>
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
Grid.Column="2"
|
|
||||||
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
CommandParameter="Store"
|
CommandParameter="Store"
|
||||||
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsStore_Title}">
|
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsStore_Title}">
|
||||||
@@ -116,28 +151,102 @@
|
|||||||
</Button>
|
</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Border>
|
||||||
|
|
||||||
<controls:SettingsCard
|
<StackPanel Spacing="12">
|
||||||
Margin="0,0,0,12"
|
|
||||||
Click="SettingOptionClicked"
|
|
||||||
Description="{x:Bind ViewModel.AccountSummaryText, Mode=OneWay}"
|
|
||||||
Header="{x:Bind domain:Translator.SettingsManageAccountSettings_Title}"
|
|
||||||
IsClickEnabled="True"
|
|
||||||
Tag="{x:Bind enums:WinoPage.ManageAccountsPage}">
|
|
||||||
<controls:SettingsCard.HeaderIcon>
|
|
||||||
<FontIcon Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}" Glyph="" />
|
|
||||||
</controls:SettingsCard.HeaderIcon>
|
|
||||||
<Button
|
<Button
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
Click="SettingOptionClicked"
|
Click="SettingOptionClicked"
|
||||||
Style="{StaticResource AccentButtonStyle}"
|
|
||||||
Tag="{x:Bind enums:WinoPage.ManageAccountsPage}">
|
Tag="{x:Bind enums:WinoPage.ManageAccountsPage}">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
<Grid ColumnSpacing="12">
|
||||||
<TextBlock Text="{x:Bind domain:Translator.Buttons_Manage}" />
|
<Grid.ColumnDefinitions>
|
||||||
<FontIcon FontSize="12" Glyph="" />
|
<ColumnDefinition Width="Auto" />
|
||||||
</StackPanel>
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<FontIcon
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||||
|
Glyph="" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Column="1" Spacing="2">
|
||||||
|
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsManageAccountSettings_Title, Mode=OneTime}" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.AccountSummaryText, Mode=OneWay}"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<FontIcon
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Glyph="" />
|
||||||
|
</Grid>
|
||||||
</Button>
|
</Button>
|
||||||
</controls:SettingsCard>
|
|
||||||
|
<Button
|
||||||
|
HorizontalContentAlignment="Stretch"
|
||||||
|
Click="SettingOptionClicked"
|
||||||
|
Tag="{x:Bind enums:WinoPage.StoragePage}">
|
||||||
|
<Grid ColumnSpacing="12">
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
<ColumnDefinition Width="*" />
|
||||||
|
<ColumnDefinition Width="Auto" />
|
||||||
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
|
<FontIcon
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
|
||||||
|
Glyph="" />
|
||||||
|
|
||||||
|
<StackPanel Grid.Column="1" Spacing="2">
|
||||||
|
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsStorage_Title, Mode=OneTime}" />
|
||||||
|
<TextBlock
|
||||||
|
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||||
|
Style="{StaticResource CaptionTextBlockStyle}"
|
||||||
|
Text="{x:Bind ViewModel.StorageSummaryText, Mode=OneWay}"
|
||||||
|
TextWrapping="WrapWholeWords" />
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<FontIcon
|
||||||
|
Grid.Column="2"
|
||||||
|
VerticalAlignment="Center"
|
||||||
|
Glyph="" />
|
||||||
|
</Grid>
|
||||||
|
</Button>
|
||||||
|
</StackPanel>
|
||||||
|
|
||||||
|
<Border
|
||||||
|
Padding="24"
|
||||||
|
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
|
||||||
|
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
|
||||||
|
BorderThickness="1"
|
||||||
|
CornerRadius="8">
|
||||||
|
<StackPanel Spacing="10">
|
||||||
|
<TextBlock Style="{StaticResource TitleTextBlockStyle}" Text="{x:Bind domain:Translator.SettingsHome_Resources_Title, Mode=OneTime}" />
|
||||||
|
<StackPanel Spacing="2">
|
||||||
|
<HyperlinkButton
|
||||||
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
|
CommandParameter="{x:Bind ViewModel.WebsiteUrl, Mode=OneWay}"
|
||||||
|
Content="{x:Bind domain:Translator.SettingsWebsite_Title}" />
|
||||||
|
<HyperlinkButton
|
||||||
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
|
CommandParameter="{x:Bind ViewModel.PrivacyPolicyUrl, Mode=OneWay}"
|
||||||
|
Content="{x:Bind domain:Translator.SettingsPrivacyPolicy_Title}" />
|
||||||
|
<HyperlinkButton
|
||||||
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
|
CommandParameter="{x:Bind ViewModel.GitHubUrl, Mode=OneWay}"
|
||||||
|
Content="{x:Bind domain:Translator.SettingsAboutGithub_Title}" />
|
||||||
|
<HyperlinkButton
|
||||||
|
Command="{x:Bind ViewModel.NavigateExternalCommand}"
|
||||||
|
CommandParameter="Store"
|
||||||
|
Content="{x:Bind domain:Translator.SettingsStore_Title}" />
|
||||||
|
</StackPanel>
|
||||||
|
</StackPanel>
|
||||||
|
</Border>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</ScrollViewer>
|
</ScrollViewer>
|
||||||
</abstract:SettingOptionsPageAbstract>
|
</abstract:SettingOptionsPageAbstract>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using CommunityToolkit.WinUI.Controls;
|
|
||||||
using Microsoft.UI.Xaml;
|
using Microsoft.UI.Xaml;
|
||||||
using Microsoft.UI.Xaml.Controls;
|
using Microsoft.UI.Xaml.Controls;
|
||||||
using Wino.Core.Domain.Enums;
|
using Wino.Core.Domain.Enums;
|
||||||
|
using Wino.Core.Domain.Models.Settings;
|
||||||
using Wino.Views.Abstract;
|
using Wino.Views.Abstract;
|
||||||
|
|
||||||
namespace Wino.Views.Settings;
|
namespace Wino.Views.Settings;
|
||||||
@@ -18,7 +18,6 @@ public sealed partial class SettingOptionsPage : SettingOptionsPageAbstract
|
|||||||
WinoPage? page = sender switch
|
WinoPage? page = sender switch
|
||||||
{
|
{
|
||||||
Button button when button.Tag is WinoPage p => p,
|
Button button when button.Tag is WinoPage p => p,
|
||||||
SettingsCard card when card.Tag is WinoPage p => p,
|
|
||||||
_ => null
|
_ => null
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -27,4 +26,28 @@ public sealed partial class SettingOptionsPage : SettingOptionsPageAbstract
|
|||||||
ViewModel.NavigateSubDetailCommand.Execute(page.Value);
|
ViewModel.NavigateSubDetailCommand.Execute(page.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SettingsSearchTextChanged(AutoSuggestBox sender, AutoSuggestBoxTextChangedEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.Reason == AutoSuggestionBoxTextChangeReason.UserInput || string.IsNullOrWhiteSpace(sender.Text))
|
||||||
|
{
|
||||||
|
ViewModel.UpdateSearchSuggestions(sender.Text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingsSearchSuggestionChosen(AutoSuggestBox sender, AutoSuggestBoxSuggestionChosenEventArgs args)
|
||||||
|
{
|
||||||
|
if (args.SelectedItem is SettingsNavigationItemInfo selectedSetting)
|
||||||
|
{
|
||||||
|
ViewModel.SearchQuery = selectedSetting.Title;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SettingsSearchQuerySubmitted(AutoSuggestBox sender, AutoSuggestBoxQuerySubmittedEventArgs args)
|
||||||
|
{
|
||||||
|
var selectedSetting = args.ChosenSuggestion as SettingsNavigationItemInfo
|
||||||
|
?? ViewModel.GetBestSearchSuggestion(args.QueryText);
|
||||||
|
|
||||||
|
ViewModel.NavigateToSetting(selectedSetting);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ public sealed partial class SettingsPage : SettingsPageAbstract,
|
|||||||
SettingsFrame.Navigated -= SettingsFrameNavigated;
|
SettingsFrame.Navigated -= SettingsFrameNavigated;
|
||||||
|
|
||||||
// Reset navigation state when leaving SettingsPage
|
// Reset navigation state when leaving SettingsPage
|
||||||
ViewModel.StatePersistenceService.IsSettingsNavigating = false;
|
ViewModel.StatePersistenceService.HasCurrentModeBackStack = false;
|
||||||
|
|
||||||
base.OnNavigatingFrom(e);
|
base.OnNavigatingFrom(e);
|
||||||
}
|
}
|
||||||
@@ -202,9 +202,23 @@ public sealed partial class SettingsPage : SettingsPageAbstract,
|
|||||||
UpdateWindowTitle();
|
UpdateWindowTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ResetForModeSwitch()
|
||||||
|
{
|
||||||
|
while (PageHistory.Count > 1 && SettingsFrame.CanGoBack)
|
||||||
|
{
|
||||||
|
if (!BreadcrumbNavigationHelper.GoBack(SettingsFrame, PageHistory, Core.Domain.Enums.NavigationTransitionEffect.FromRight))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsFrame.ForwardStack.Clear();
|
||||||
|
UpdateBackNavigationState();
|
||||||
|
_ = RefreshCurrentPageStateAsync();
|
||||||
|
UpdateWindowTitle();
|
||||||
|
}
|
||||||
|
|
||||||
private void UpdateBackNavigationState()
|
private void UpdateBackNavigationState()
|
||||||
{
|
{
|
||||||
ViewModel.StatePersistenceService.IsSettingsNavigating = PageHistory.Count > 1 && SettingsFrame.CanGoBack;
|
ViewModel.StatePersistenceService.HasCurrentModeBackStack = PageHistory.Count > 1 && SettingsFrame.CanGoBack;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task RefreshCurrentPageStateAsync()
|
private async Task RefreshCurrentPageStateAsync()
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ using Wino.Messaging.Client.Accounts;
|
|||||||
using Wino.Messaging.Client.Calendar;
|
using Wino.Messaging.Client.Calendar;
|
||||||
using Wino.Messaging.Client.Mails;
|
using Wino.Messaging.Client.Mails;
|
||||||
using Wino.Messaging.Client.Shell;
|
using Wino.Messaging.Client.Shell;
|
||||||
|
using Wino.Messaging.UI;
|
||||||
using Wino.Views.Mail;
|
using Wino.Views.Mail;
|
||||||
using Wino.Views;
|
using Wino.Views;
|
||||||
using Wino.Views.Settings;
|
using Wino.Views.Settings;
|
||||||
@@ -45,7 +46,8 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
IRecipient<AccountMenuItemExtended>,
|
IRecipient<AccountMenuItemExtended>,
|
||||||
IRecipient<NavigateMailFolderEvent>,
|
IRecipient<NavigateMailFolderEvent>,
|
||||||
IRecipient<CreateNewMailWithMultipleAccountsRequested>,
|
IRecipient<CreateNewMailWithMultipleAccountsRequested>,
|
||||||
IRecipient<CalendarDisplayTypeChangedMessage>
|
IRecipient<CalendarDisplayTypeChangedMessage>,
|
||||||
|
IRecipient<AccountCreatedMessage>
|
||||||
{
|
{
|
||||||
private const string StateHorizontalCalendar = "HorizontalCalendar";
|
private const string StateHorizontalCalendar = "HorizontalCalendar";
|
||||||
private const string StateVerticalCalendar = "VerticalCalendar";
|
private const string StateVerticalCalendar = "VerticalCalendar";
|
||||||
@@ -97,6 +99,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
UpdateTitleBarSubtitle();
|
UpdateTitleBarSubtitle();
|
||||||
|
|
||||||
ViewModel.CurrentClient.Activate(activationContext);
|
ViewModel.CurrentClient.Activate(activationContext);
|
||||||
|
ResetShellModeNavigationState();
|
||||||
|
|
||||||
ApplyTitleBarContent();
|
ApplyTitleBarContent();
|
||||||
}
|
}
|
||||||
@@ -158,6 +161,11 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
}
|
}
|
||||||
else if (_activeMode == WinoApplicationMode.Settings)
|
else if (_activeMode == WinoApplicationMode.Settings)
|
||||||
{
|
{
|
||||||
|
if (InnerShellFrame.Content is SettingsPage settingsPage)
|
||||||
|
{
|
||||||
|
settingsPage.ResetForModeSwitch();
|
||||||
|
}
|
||||||
|
|
||||||
ViewModel.CurrentClient.Deactivate();
|
ViewModel.CurrentClient.Deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,7 +174,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
|
|
||||||
private void ResetShellModeNavigationState()
|
private void ResetShellModeNavigationState()
|
||||||
{
|
{
|
||||||
ViewModel.StatePersistenceService.IsSettingsNavigating = false;
|
ViewModel.StatePersistenceService.HasCurrentModeBackStack = false;
|
||||||
InnerShellFrame.BackStack.Clear();
|
InnerShellFrame.BackStack.Clear();
|
||||||
InnerShellFrame.ForwardStack.Clear();
|
InnerShellFrame.ForwardStack.Clear();
|
||||||
}
|
}
|
||||||
@@ -284,6 +292,15 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
|
|
||||||
public void Receive(CalendarDisplayTypeChangedMessage message) => ManageCalendarDisplayType(message.NewDisplayType);
|
public void Receive(CalendarDisplayTypeChangedMessage message) => ManageCalendarDisplayType(message.NewDisplayType);
|
||||||
|
|
||||||
|
public void Receive(AccountCreatedMessage message)
|
||||||
|
{
|
||||||
|
_ = DispatcherQueue.EnqueueAsync(async () =>
|
||||||
|
{
|
||||||
|
ViewModel.NavigationService.ChangeApplicationMode(WinoApplicationMode.Mail);
|
||||||
|
await ViewModel.MailClient.HandleAccountCreatedAsync(message.Account);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private async void NavigationViewItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
private async void NavigationViewItemInvoked(NavigationView sender, NavigationViewItemInvokedEventArgs args)
|
||||||
{
|
{
|
||||||
if (_isSyncingNavigationViewSelection)
|
if (_isSyncingNavigationViewSelection)
|
||||||
@@ -758,6 +775,7 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
WeakReferenceMessenger.Default.Register<CreateNewMailWithMultipleAccountsRequested>(this);
|
WeakReferenceMessenger.Default.Register<CreateNewMailWithMultipleAccountsRequested>(this);
|
||||||
WeakReferenceMessenger.Default.Register<NavigateMailFolderEvent>(this);
|
WeakReferenceMessenger.Default.Register<NavigateMailFolderEvent>(this);
|
||||||
WeakReferenceMessenger.Default.Register<CalendarDisplayTypeChangedMessage>(this);
|
WeakReferenceMessenger.Default.Register<CalendarDisplayTypeChangedMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Register<AccountCreatedMessage>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void UnregisterRecipients()
|
protected override void UnregisterRecipients()
|
||||||
@@ -768,5 +786,6 @@ public sealed partial class WinoAppShell : Views.Abstract.WinoAppShellAbstract,
|
|||||||
WeakReferenceMessenger.Default.Unregister<CreateNewMailWithMultipleAccountsRequested>(this);
|
WeakReferenceMessenger.Default.Unregister<CreateNewMailWithMultipleAccountsRequested>(this);
|
||||||
WeakReferenceMessenger.Default.Unregister<NavigateMailFolderEvent>(this);
|
WeakReferenceMessenger.Default.Unregister<NavigateMailFolderEvent>(this);
|
||||||
WeakReferenceMessenger.Default.Unregister<CalendarDisplayTypeChangedMessage>(this);
|
WeakReferenceMessenger.Default.Unregister<CalendarDisplayTypeChangedMessage>(this);
|
||||||
|
WeakReferenceMessenger.Default.Unregister<AccountCreatedMessage>(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user