using System.Collections.ObjectModel; using System.Linq; using System.Threading.Tasks; using CommunityToolkit.Mvvm.Messaging; using Microsoft.UI.Xaml.Media.Animation; using Microsoft.UI.Xaml.Navigation; using Wino.Core.Domain; using Wino.Core.Domain.Entities.Shared; using Wino.Core.Domain.Enums; using Wino.Core.Domain.Models.Settings; using Wino.Helpers; using Wino.Mail.ViewModels.Data; using Wino.Mail.WinUI.Interfaces; using Wino.Mail.WinUI.Models; using Wino.Messaging.Client.Navigation; using Wino.Messaging.UI; using Wino.Views.Abstract; using Wino.Views.Settings; namespace Wino.Views; public sealed partial class SettingsPage : SettingsPageAbstract, IRecipient, IRecipient, IRecipient, IRecipient, IRecipient, ITitleBarSearchHost { public ObservableCollection PageHistory { get; set; } = []; public ObservableCollection SearchSuggestions { get; } = []; public string SearchText { get; set; } = string.Empty; public string SearchPlaceholderText => Translator.SettingsHome_SearchPlaceholder; public SettingsPage() { InitializeComponent(); } protected override void OnNavigatedTo(NavigationEventArgs e) { base.OnNavigatedTo(e); // Register for frame navigation events to track back button visibility SettingsFrame.Navigated -= SettingsFrameNavigated; SettingsFrame.Navigated += SettingsFrameNavigated; var initialPage = e.Parameter as WinoPage? ?? WinoPage.SettingOptionsPage; NavigateToRootPage(initialPage); } public override void OnLanguageChanged() { base.OnLanguageChanged(); // Update Settings header in breadcrumb. var settingsHeader = PageHistory.FirstOrDefault(); if (settingsHeader == null) return; settingsHeader.Title = Translator.MenuSettings; var manageAccountsEntry = PageHistory.FirstOrDefault(a => a.Request.PageType == WinoPage.ManageAccountsPage || a.Request.PageType == WinoPage.AccountManagementPage); if (manageAccountsEntry != null) { manageAccountsEntry.Title = Translator.SettingsManageAccountSettings_Title; } var winoAccountEntry = PageHistory.FirstOrDefault(a => a.Request.PageType == WinoPage.WinoAccountManagementPage); if (winoAccountEntry != null) { winoAccountEntry.Title = Translator.WinoAccount_SettingsSection_Title; } _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); } protected override void OnNavigatingFrom(NavigatingCancelEventArgs e) { // Unregister frame navigation event SettingsFrame.Navigated -= SettingsFrameNavigated; base.OnNavigatingFrom(e); } protected override void RegisterRecipients() { base.RegisterRecipients(); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); WeakReferenceMessenger.Default.Register(this); } protected override void UnregisterRecipients() { base.UnregisterRecipients(); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); WeakReferenceMessenger.Default.Unregister(this); } void IRecipient.Receive(BreadcrumbNavigationRequested message) { NavigateBreadcrumb(message); } private void SettingsFrameNavigated(object sender, NavigationEventArgs e) { UpdateBackNavigationState(); _ = RefreshCurrentPageStateAsync(); } private void GoBackFrame(Core.Domain.Enums.NavigationTransitionEffect slideEffect) { if (!BreadcrumbNavigationHelper.GoBack(SettingsFrame, PageHistory, slideEffect)) return; UpdateBackNavigationState(); _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); } private void BreadItemClicked(Microsoft.UI.Xaml.Controls.BreadcrumbBar sender, Microsoft.UI.Xaml.Controls.BreadcrumbBarItemClickedEventArgs args) { if (!BreadcrumbNavigationHelper.NavigateTo(SettingsFrame, PageHistory, args.Index)) return; UpdateBackNavigationState(); _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); } public void Receive(BackBreadcrumNavigationRequested message) { GoBackFrame(message.SlideEffect); } public void Receive(SettingsRootNavigationRequested message) { var activePage = PageHistory.LastOrDefault()?.Request.PageType ?? WinoPage.SettingOptionsPage; var currentRootPage = SettingsNavigationInfoProvider.GetRootPage(activePage); if (message.PageType == currentRootPage) { if (activePage == currentRootPage) return; var currentRootIndex = PageHistory .Select((item, index) => new { item.Request.PageType, Index = index }) .FirstOrDefault(item => item.PageType == currentRootPage)?.Index ?? -1; if (TryNavigateToBreadcrumbIndex(currentRootIndex)) return; } if (message.PageType == WinoPage.SettingOptionsPage) { if (activePage == WinoPage.SettingOptionsPage) return; NavigateToSettingsHome(); return; } NavigateToRootPage(message.PageType); } public void Receive(AccountUpdatedMessage message) { var activePage = PageHistory.LastOrDefault(a => a.Request.PageType == WinoPage.AccountDetailsPage); if (activePage == null) return; DispatcherQueue.TryEnqueue(() => { activePage.Title = GetAccountDetailsTitle(message.Account); _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); }); } public void Receive(MergedInboxRenamed message) { var activePage = PageHistory.LastOrDefault(a => a.Request.PageType == WinoPage.MergedAccountDetailsPage); if (activePage == null) return; DispatcherQueue.TryEnqueue(() => { activePage.Title = message.NewName; _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); }); } private void NavigateBreadcrumb(BreadcrumbNavigationRequested message) { if (!BreadcrumbNavigationHelper.Navigate(SettingsFrame, PageHistory, message, ViewModel.NavigationService.GetPageType)) return; UpdateBackNavigationState(); _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); } private void NavigateToRootPage(WinoPage targetPage) { NavigateToSettingsHome(); if (targetPage != WinoPage.SettingOptionsPage) { NavigateBreadcrumb(new BreadcrumbNavigationRequested( SettingsNavigationInfoProvider.GetPageTitle(targetPage), targetPage)); return; } UpdateWindowTitle(); } private void NavigateToSettingsHome() { if (PageHistory.Count == 0 || SettingsFrame.Content == null) { ResetToSettingsHome(); return; } if (PageHistory.Count == 1) return; if (!TryNavigateToBreadcrumbIndex(0)) { ResetToSettingsHome(); } } private bool TryNavigateToBreadcrumbIndex(int targetIndex) { if (!BreadcrumbNavigationHelper.NavigateTo(SettingsFrame, PageHistory, targetIndex)) return false; UpdateBackNavigationState(); _ = RefreshCurrentPageStateAsync(); UpdateWindowTitle(); return true; } private void ResetToSettingsHome() { PageHistory.Clear(); SettingsFrame.BackStack.Clear(); SettingsFrame.ForwardStack.Clear(); NavigateBreadcrumb(new BreadcrumbNavigationRequested(Translator.MenuSettings, WinoPage.SettingOptionsPage)); } 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() { WeakReferenceMessenger.Default.Send(new TitleBarShellContentUpdated()); } public bool CanNavigateBack => PageHistory.Count > 1 && SettingsFrame.CanGoBack; private async Task RefreshCurrentPageStateAsync() { var activePage = PageHistory.LastOrDefault()?.Request.PageType ?? WinoPage.SettingOptionsPage; var rootPage = SettingsNavigationInfoProvider.GetRootPage(activePage); await ViewModel.UpdateActivePageAsync(rootPage); WeakReferenceMessenger.Default.Send(new ActiveSettingsPageChanged(rootPage)); } private void UpdateWindowTitle() { var activeTitle = PageHistory.LastOrDefault()?.Title; ViewModel.StatePersistenceService.CoreWindowTitle = string.IsNullOrWhiteSpace(activeTitle) ? Translator.MenuSettings : activeTitle; } private static string GetAccountDetailsTitle(MailAccount account) => !string.IsNullOrWhiteSpace(account?.Address) ? string.Format(Translator.SettingsAccountDetails_NavigationTitle, account.Address) : account?.Name ?? Translator.AccountDetailsPage_Title; public Task OnTitleBarSearchTextChangedAsync() { SearchSuggestions.Clear(); foreach (var item in SettingsNavigationInfoProvider.Search(SearchText, ViewModel.ManageAccountsDescription).Take(6)) { SearchSuggestions.Add(new TitleBarSearchSuggestion(item.Title, item.Description, item)); } return Task.CompletedTask; } public void OnTitleBarSearchSuggestionChosen(TitleBarSearchSuggestion suggestion) { SearchText = suggestion.Title; } public Task OnTitleBarSearchSubmittedAsync(string queryText, TitleBarSearchSuggestion? chosenSuggestion) { SearchText = queryText; var selectedSetting = chosenSuggestion?.Tag as SettingsNavigationItemInfo ?? SettingsNavigationInfoProvider.Search(queryText, ViewModel.ManageAccountsDescription).FirstOrDefault(); if (selectedSetting?.PageType is WinoPage pageType) { Receive(new SettingsRootNavigationRequested(pageType)); } return Task.CompletedTask; } }