navigation improvements

This commit is contained in:
Burak Kaan Köse
2026-03-14 14:14:58 +01:00
parent 4ba7d5fd07
commit 56b0f79edc
20 changed files with 605 additions and 153 deletions
@@ -20,7 +20,7 @@ public interface IMailDialogService : IDialogServiceBase
// Custom dialogs
Task<IMailItemFolder> ShowMoveMailFolderDialogAsync(List<IMailItemFolder> availableFolders);
Task<MailAccount> ShowAccountPickerDialogAsync(List<MailAccount> availableAccounts);
Task<AccountCalendar> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups);
Task<AccountCalendarPickingResult> ShowSingleCalendarPickerDialogAsync(List<CalendarPickerAccountGroup> availableCalendarGroups);
/// <summary>
/// Displays a dialog to the user for reordering accounts.
@@ -36,6 +36,7 @@ public interface IMailShellClient : IShellClient
IMenuItem CreatePrimaryMenuItem { get; }
IEnumerable<FolderOperationMenuItem> GetFolderContextMenuActions(IBaseFolderMenuItem folder);
Task HandleAccountCreatedAsync(MailAccount createdAccount);
Task NavigateFolderAsync(IBaseFolderMenuItem baseFolderMenuItem, TaskCompletionSource<bool>? folderInitAwaitTask = null);
Task ChangeLoadedAccountAsync(IAccountMenuItem clickedBaseAccountMenuItem, bool navigateInbox = true);
Task PerformFolderOperationAsync(FolderOperation operation, IBaseFolderMenuItem folderMenuItem);
@@ -45,9 +45,9 @@ public interface IStatePersistanceService : INotifyPropertyChanged
bool IsEventDetailsVisible { get; set; }
/// <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>
bool IsSettingsNavigating { get; set; }
bool HasCurrentModeBackStack { get; set; }
/// <summary>
/// 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.Linq;
using Wino.Core.Domain.Enums;
@@ -9,13 +10,15 @@ public sealed class SettingsNavigationItemInfo(
string title,
string description,
string glyph = "",
bool isSeparator = false)
bool isSeparator = false,
string searchKeywords = "")
{
public WinoPage? PageType { get; } = pageType;
public string Title { get; } = title;
public string Description { get; } = description;
public string Glyph { get; } = glyph;
public bool IsSeparator { get; } = isSeparator;
public string SearchKeywords { get; } = searchKeywords;
}
public static class SettingsNavigationInfoProvider
@@ -31,53 +34,90 @@ public static class SettingsNavigationInfoProvider
new(WinoPage.ManageAccountsPage,
Translator.SettingsManageAccountSettings_Title,
manageAccountsDescription,
"\uE77B"),
"\uE77B",
searchKeywords: Translator.SettingsSearch_ManageAccounts_Keywords),
new(null, Translator.SettingsOptions_GeneralSection, string.Empty, "\uE713", isSeparator: true),
new(WinoPage.AppPreferencesPage,
Translator.SettingsAppPreferences_Title,
Translator.SettingsAppPreferences_Description,
"\uE770"),
"\uE770",
searchKeywords: Translator.SettingsSearch_AppPreferences_Keywords),
new(WinoPage.LanguageTimePage,
Translator.SettingsLanguageTime_Title,
Translator.SettingsLanguageTime_Description,
"\uE775"),
"\uE775",
searchKeywords: Translator.SettingsSearch_LanguageTime_Keywords),
new(WinoPage.PersonalizationPage,
Translator.SettingsPersonalization_Title,
Translator.SettingsPersonalization_Description,
"\uE771"),
"\uE771",
searchKeywords: Translator.SettingsSearch_Personalization_Keywords),
new(WinoPage.AboutPage,
Translator.SettingsAbout_Title,
Translator.SettingsAbout_Description,
"\uE946"),
"\uE946",
searchKeywords: Translator.SettingsSearch_About_Keywords),
new(null, Translator.SettingsOptions_MailSection, string.Empty, "\uE715", isSeparator: true),
new(WinoPage.KeyboardShortcutsPage,
Translator.Settings_KeyboardShortcuts_Title,
Translator.Settings_KeyboardShortcuts_Description,
"\uE765"),
"\uE765",
searchKeywords: Translator.SettingsSearch_KeyboardShortcuts_Keywords),
new(WinoPage.MessageListPage,
Translator.SettingsMessageList_Title,
Translator.SettingsMessageList_Description,
"\uE8C4"),
"\uE8C4",
searchKeywords: Translator.SettingsSearch_MessageList_Keywords),
new(WinoPage.ReadComposePanePage,
Translator.SettingsReadComposePane_Title,
Translator.SettingsReadComposePane_Description,
"\uE8BD"),
"\uE8BD",
searchKeywords: Translator.SettingsSearch_ReadComposePane_Keywords),
new(WinoPage.SignatureAndEncryptionPage,
Translator.SettingsSignatureAndEncryption_Title,
Translator.SettingsSignatureAndEncryption_Description,
"\uE8D7"),
"\uE8D7",
searchKeywords: Translator.SettingsSearch_SignatureAndEncryption_Keywords),
new(WinoPage.StoragePage,
Translator.SettingsStorage_Title,
Translator.SettingsStorage_Description,
"\uE81C"),
"\uE81C",
searchKeywords: Translator.SettingsSearch_Storage_Keywords),
new(null, Translator.SettingsOptions_CalendarSection, string.Empty, "\uE787", isSeparator: true),
new(WinoPage.CalendarSettingsPage,
Translator.SettingsCalendarSettings_Title,
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 = "")
{
var rootPage = GetRootPage(pageType);
@@ -119,4 +159,58 @@ public static class SettingsNavigationInfoProvider
WinoPage.CalendarAccountSettingsPage => WinoPage.CalendarSettingsPage,
_ => 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_LocationPlaceholder": "Add a location",
"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_NoCalendarsTitle": "No calendars available",
"CalendarEventCompose_NoEndDate": "No end date",
@@ -816,6 +818,22 @@
"SettingsNotificationsAndTaskbar_Description": "Change whether notifications should be displayed and taskbar badge for this account.",
"SettingsNotificationsAndTaskbar_Title": "Notifications & Taskbar",
"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_GeneralSection": "General",
"SettingsOptions_MailSection": "Mail",
@@ -823,6 +841,17 @@
"SettingsOptions_MoreComingSoon": "More options coming soon",
"SettingsOptions_HeroDescription": "Customize your Wino Mail experience",
"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_Title": "Reset Mail List Size",
"SettingsPaypal_Description": "Show much more love ❤️ All donations are appreciated.",