Settings page and manage accounts navigation options.

This commit is contained in:
Burak Kaan Köse
2026-01-06 17:23:58 +01:00
parent 7cc201f423
commit f105c2f8f0
29 changed files with 874 additions and 197 deletions
+1
View File
@@ -95,6 +95,7 @@ public partial class App : WinoApplication,
services.AddTransient(typeof(CalendarPageViewModel));
services.AddTransient(typeof(CalendarSettingsPageViewModel));
services.AddTransient(typeof(CalendarAccountSettingsPageViewModel));
services.AddTransient(typeof(EventDetailsPageViewModel));
}
+1
View File
@@ -42,6 +42,7 @@ public static class XamlHelpers
public static Visibility ReverseBoolToVisibilityConverter(bool value) => value ? Visibility.Collapsed : Visibility.Visible;
public static Visibility ReverseVisibilityConverter(Visibility visibility) => visibility == Visibility.Visible ? Visibility.Collapsed : Visibility.Visible;
public static bool ReverseBoolConverter(bool value) => !value;
public static bool AreEqual(int value1, int value2) => value1 == value2;
public static bool ShouldDisplayPreview(string text) => text == null ? false : text.Any(x => char.IsLetter(x));
public static bool CountToBooleanConverter(int value) => value > 0;
public static bool ObjectEquals(object obj1, object obj2) => object.Equals(obj1, obj2);
@@ -8,7 +8,7 @@ namespace Wino.Selectors;
/// <summary>
/// DataTemplateSelector that selects the appropriate stripe template based on CalendarItemShowAs status.
/// </summary>
public class CalendarItemShowAsStripeTemplateSelector : DataTemplateSelector
public partial class CalendarItemShowAsStripeTemplateSelector : DataTemplateSelector
{
public DataTemplate FreeTemplate { get; set; }
public DataTemplate TentativeTemplate { get; set; }
+12 -1
View File
@@ -15,6 +15,7 @@ using Wino.Mail.WinUI.Interfaces;
using Wino.Mail.WinUI.Services;
using Wino.Mail.WinUI.Views.Calendar;
using Wino.Messaging.Client.Mails;
using Wino.Messaging.Client.Navigation;
using Wino.Views;
using Wino.Views.Account;
using Wino.Views.Mail;
@@ -68,6 +69,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
WinoPage.CalendarPage => typeof(CalendarPage),
WinoPage.EventDetailsPage => typeof(EventDetailsPage),
WinoPage.CalendarSettingsPage => typeof(CalendarSettingsPage),
WinoPage.CalendarAccountSettingsPage => typeof(CalendarAccountSettingsPage),
_ => null,
};
}
@@ -208,8 +210,17 @@ public class NavigationService : NavigationServiceBase, INavigationService
return false;
}
public void GoBack()
public void GoBack(Core.Domain.Enums.NavigationTransitionEffect slideEffect = Core.Domain.Enums.NavigationTransitionEffect.FromRight)
{
// Check if we're navigating within ManageAccountsPage (applies to both modes)
// Check if we're navigating within SettingsPage (applies to both modes)
if (_statePersistanceService.IsManageAccountsNavigating || _statePersistanceService.IsSettingsNavigating)
{
// Send message to ManageAccountsPage to go back within its AccountPagesFrame
WeakReferenceMessenger.Default.Send(new BackBreadcrumNavigationRequested(slideEffect));
return;
}
if (_statePersistanceService.ApplicationMode == WinoApplicationMode.Calendar)
{
var innerShellFrame = GetCoreFrame(NavigationReferenceFrame.InnerShellFrame);
@@ -32,8 +32,8 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
public bool IsBackButtonVisible =>
ApplicationMode == WinoApplicationMode.Mail
? IsReadingMail && IsReaderNarrowed
: IsEventDetailsVisible;
? (IsReadingMail && IsReaderNarrowed) || IsManageAccountsNavigating || IsSettingsNavigating
: IsEventDetailsVisible || IsManageAccountsNavigating || IsSettingsNavigating;
private WinoApplicationMode applicationMode = WinoApplicationMode.Mail;
@@ -66,6 +66,34 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
}
}
private bool isManageAccountsNavigating;
public bool IsManageAccountsNavigating
{
get => isManageAccountsNavigating;
set
{
if (SetProperty(ref isManageAccountsNavigating, value))
{
OnPropertyChanged(nameof(IsBackButtonVisible));
}
}
}
private bool isSettingsNavigating;
public bool IsSettingsNavigating
{
get => isSettingsNavigating;
set
{
if (SetProperty(ref isSettingsNavigating, value))
{
OnPropertyChanged(nameof(IsBackButtonVisible));
}
}
}
private bool isReadingMail;
public bool IsReadingMail
@@ -0,0 +1,6 @@
using Wino.Calendar.ViewModels;
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class CalendarAccountSettingsPageAbstract : BasePage<CalendarAccountSettingsPageViewModel> { }
File diff suppressed because one or more lines are too long
@@ -1,4 +1,7 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
using Wino.Core.Domain.Entities.Calendar;
using Wino.Core.Domain.Models.Folders;
using Wino.Views.Abstract;
@@ -9,9 +12,16 @@ public sealed partial class AccountDetailsPage : AccountDetailsPageAbstract
public AccountDetailsPage()
{
InitializeComponent();
NavigationCacheMode = NavigationCacheMode.Enabled;
}
private async void SyncFolderToggled(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
private void OnTabSelectionChanged(SelectorBar sender, SelectorBarSelectionChangedEventArgs e)
{
ViewModel.SelectedTabIndex = TabSelector.SelectedItem == null ? 1 : TabSelector.Items.IndexOf(TabSelector.SelectedItem);
}
private async void SyncFolderToggled(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkBox && checkBox.Tag is IMailItemFolder folder)
{
@@ -19,11 +29,30 @@ public sealed partial class AccountDetailsPage : AccountDetailsPageAbstract
}
}
private async void UnreadBadgeCheckboxToggled(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
private async void UnreadBadgeCheckboxToggled(object sender, RoutedEventArgs e)
{
if (sender is CheckBox checkBox && checkBox.Tag is IMailItemFolder folder)
{
await ViewModel.FolderShowUnreadToggled(folder, checkBox.IsChecked.GetValueOrDefault());
}
}
private void CalendarItemClicked(object sender, RoutedEventArgs e)
{
if (sender is CommunityToolkit.WinUI.Controls.SettingsCard settingsCard && settingsCard.CommandParameter is AccountCalendar calendar)
{
ViewModel.CalendarItemClickedCommand?.Execute(calendar);
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
if (e.NavigationMode == NavigationMode.New)
{
// Set initial tab to Mail (index 1)
TabSelector.SelectedItem = TabSelector.Items[1];
}
}
}
@@ -230,7 +230,6 @@
<PathIcon Data="F1 M 8.613281 17.5 C 8.75 17.942709 8.945312 18.359375 9.199219 18.75 L 4.921875 18.75 C 4.433594 18.75 3.966471 18.650717 3.520508 18.452148 C 3.074544 18.25358 2.683919 17.986654 2.348633 17.651367 C 2.013346 17.31608 1.746419 16.925455 1.547852 16.479492 C 1.349284 16.033529 1.25 15.566406 1.25 15.078125 L 1.25 4.921875 C 1.25 4.433594 1.349284 3.966473 1.547852 3.520508 C 1.746419 3.074545 2.013346 2.68392 2.348633 2.348633 C 2.683919 2.013348 3.074544 1.74642 3.520508 1.547852 C 3.966471 1.349285 4.433594 1.25 4.921875 1.25 L 15.078125 1.25 C 15.566406 1.25 16.033527 1.349285 16.479492 1.547852 C 16.925455 1.74642 17.31608 2.013348 17.651367 2.348633 C 17.986652 2.68392 18.25358 3.074545 18.452148 3.520508 C 18.650715 3.966473 18.75 4.433594 18.75 4.921875 L 18.75 6.572266 C 18.580729 6.344402 18.390299 6.132813 18.178711 5.9375 C 17.967121 5.742188 17.740885 5.566407 17.5 5.410156 L 17.5 4.951172 C 17.5 4.625651 17.433268 4.314779 17.299805 4.018555 C 17.16634 3.722332 16.987305 3.461914 16.762695 3.237305 C 16.538086 3.012695 16.277668 2.83366 15.981445 2.700195 C 15.685221 2.566732 15.374349 2.5 15.048828 2.5 L 4.951172 2.5 C 4.619141 2.5 4.303385 2.568359 4.003906 2.705078 C 3.704427 2.841797 3.44401 3.02409 3.222656 3.251953 C 3.001302 3.479818 2.825521 3.745117 2.695312 4.047852 C 2.565104 4.350587 2.5 4.66797 2.5 5 L 13.310547 5 C 12.60091 5.266928 11.998697 5.683594 11.503906 6.25 L 2.5 6.25 L 2.5 15.048828 C 2.5 15.38737 2.568359 15.704753 2.705078 16.000977 C 2.841797 16.297201 3.024088 16.55599 3.251953 16.777344 C 3.479818 16.998697 3.745117 17.174479 4.047852 17.304688 C 4.350586 17.434896 4.667969 17.5 5 17.5 Z M 18.125 9.443359 C 18.125 9.866537 18.040363 10.263672 17.871094 10.634766 C 17.701822 11.005859 17.473957 11.329753 17.1875 11.606445 C 16.901041 11.883139 16.56901 12.101237 16.191406 12.260742 C 15.813802 12.420248 15.416666 12.5 15 12.5 C 14.563802 12.5 14.1569 12.41862 13.779297 12.255859 C 13.401691 12.0931 13.071288 11.870117 12.788086 11.586914 C 12.504882 11.303711 12.2819 10.973308 12.119141 10.595703 C 11.95638 10.2181 11.875 9.811198 11.875 9.375 C 11.875 8.938803 11.95638 8.531901 12.119141 8.154297 C 12.2819 7.776693 12.504882 7.446289 12.788086 7.163086 C 13.071288 6.879883 13.401691 6.656901 13.779297 6.494141 C 14.1569 6.331381 14.563802 6.25 15 6.25 C 15.449218 6.25 15.864257 6.333008 16.245117 6.499023 C 16.625977 6.665039 16.956379 6.892904 17.236328 7.182617 C 17.516275 7.472331 17.734375 7.810873 17.890625 8.198242 C 18.046875 8.585612 18.125 9.000651 18.125 9.443359 Z M 20 16.25 C 20 16.666666 19.926758 17.049154 19.780273 17.397461 C 19.633789 17.745768 19.435221 18.058268 19.18457 18.334961 C 18.933918 18.611654 18.642578 18.854166 18.310547 19.0625 C 17.978516 19.270834 17.626953 19.444986 17.255859 19.584961 C 16.884766 19.724936 16.505533 19.829102 16.118164 19.897461 C 15.730794 19.96582 15.358072 20 15 20 C 14.654947 20 14.291992 19.96582 13.911133 19.897461 C 13.530273 19.829102 13.154297 19.726562 12.783203 19.589844 C 12.412109 19.453125 12.058919 19.282227 11.723633 19.077148 C 11.388346 18.87207 11.092122 18.632812 10.834961 18.359375 C 10.577799 18.085938 10.374349 17.779947 10.224609 17.441406 C 10.074869 17.102865 10 16.731771 10 16.328125 L 10 15.78125 C 10 15.501303 10.052083 15.237631 10.15625 14.990234 C 10.260416 14.742839 10.405273 14.526367 10.59082 14.34082 C 10.776367 14.155273 10.991211 14.010417 11.235352 13.90625 C 11.479492 13.802084 11.744791 13.75 12.03125 13.75 L 17.96875 13.75 C 18.248697 13.75 18.512369 13.803711 18.759766 13.911133 C 19.00716 14.018555 19.222004 14.163412 19.404297 14.345703 C 19.586588 14.527995 19.731445 14.742839 19.838867 14.990234 C 19.946289 15.237631 20 15.501303 20 15.78125 Z " />
</winuiControls:SettingsCard.HeaderIcon>
</winuiControls:SettingsCard>
<winuiControls:SettingsCard
Command="{x:Bind ViewModel.ReorderAccountsCommand}"
Description="{x:Bind domain:Translator.SettingsReorderAccounts_Description}"
@@ -1,6 +1,5 @@
using CommunityToolkit.WinUI.Controls;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Navigation;
using Wino.Core.ViewModels.Data;
using Wino.Mail.ViewModels.Data;
using Wino.Views.Abstract;
@@ -12,8 +11,6 @@ public sealed partial class AccountManagementPage : AccountManagementPageAbstrac
public AccountManagementPage()
{
InitializeComponent();
NavigationCacheMode = NavigationCacheMode.Enabled;
}
private void EditMergedAccounts_Click(object sender, RoutedEventArgs e)
@@ -0,0 +1,86 @@
<abstract:CalendarAccountSettingsPageAbstract
x:Class="Wino.Mail.WinUI.Views.Calendar.CalendarAccountSettingsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:abstract="using:Wino.Mail.WinUI.Views.Abstract"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Style="{StaticResource PageStyle}"
mc:Ignorable="d">
<Grid Padding="20" RowSpacing="20">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Page Header -->
<StackPanel Grid.Row="0" Spacing="4">
<TextBlock
Style="{StaticResource TitleTextBlockStyle}"
Text="{x:Bind domain:Translator.CalendarAccountSettings_Title, Mode=OneTime}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind ViewModel.Account.Name, Mode=OneWay}"
TextWrapping="Wrap" />
</StackPanel>
<!-- Settings Cards -->
<ScrollViewer Grid.Row="1">
<StackPanel MaxWidth="900" Spacing="4">
<!-- Account Color -->
<controls:SettingsCard
Description="{x:Bind domain:Translator.CalendarAccountSettings_AccountColorDescription, Mode=OneTime}"
Header="{x:Bind domain:Translator.CalendarAccountSettings_AccountColor, Mode=OneTime}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE790;" />
</controls:SettingsCard.HeaderIcon>
<Border
Width="40"
Height="40"
Background="{x:Bind ViewModel.AccountColorHex, Mode=OneWay}"
CornerRadius="4" />
</controls:SettingsCard>
<!-- Enable Synchronization -->
<controls:SettingsCard
Description="{x:Bind domain:Translator.CalendarAccountSettings_SyncEnabledDescription, Mode=OneTime}"
Header="{x:Bind domain:Translator.CalendarAccountSettings_SyncEnabled, Mode=OneTime}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE895;" />
</controls:SettingsCard.HeaderIcon>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsSyncEnabled, Mode=TwoWay}" />
</controls:SettingsCard>
<!-- Primary Calendar -->
<controls:SettingsCard
Description="{x:Bind domain:Translator.CalendarAccountSettings_PrimaryCalendarDescription, Mode=OneTime}"
Header="{x:Bind domain:Translator.CalendarAccountSettings_PrimaryCalendar, Mode=OneTime}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE735;" />
</controls:SettingsCard.HeaderIcon>
<ToggleSwitch IsOn="{x:Bind ViewModel.IsPrimaryCalendar, Mode=TwoWay}" />
</controls:SettingsCard>
<!-- Default Show As Status -->
<controls:SettingsCard
Description="{x:Bind domain:Translator.CalendarAccountSettings_DefaultShowAsDescription, Mode=OneTime}"
Header="{x:Bind domain:Translator.CalendarAccountSettings_DefaultShowAs, Mode=OneTime}">
<controls:SettingsCard.HeaderIcon>
<FontIcon Glyph="&#xE163;" />
</controls:SettingsCard.HeaderIcon>
<ComboBox
MinWidth="150"
DisplayMemberPath="DisplayText"
ItemsSource="{x:Bind ViewModel.ShowAsOptions, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedDefaultShowAsOption, Mode=TwoWay}" />
</controls:SettingsCard>
</StackPanel>
</ScrollViewer>
</Grid>
</abstract:CalendarAccountSettingsPageAbstract>
@@ -0,0 +1,11 @@
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Mail.WinUI.Views.Calendar;
public sealed partial class CalendarAccountSettingsPage : CalendarAccountSettingsPageAbstract
{
public CalendarAccountSettingsPage()
{
InitializeComponent();
}
}
@@ -7,8 +7,10 @@
xmlns:controls1="using:Microsoft.UI.Xaml.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:entities="using:Wino.Core.Domain.Entities.Shared"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitExt="using:CommunityToolkit.WinUI"
x:Name="Root"
mc:Ignorable="d">
<Grid>
@@ -178,7 +180,52 @@
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>
<!-- Calendar Accounts -->
<!--<controls:SettingsExpander
Description="Manage calendar settings for each account"
Header="Calendar Accounts"
IsExpanded="True">
<controls:SettingsExpander.HeaderIcon>
<FontIcon Glyph="&#xE77B;" />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
ContentAlignment="Vertical">
<ItemsControl ItemsSource="{x:Bind ViewModel.Accounts, Mode=OneWay}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="entities:MailAccount">
<Button
Padding="12,8"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Left"
Command="{Binding ElementName=Root, Path=ViewModel.NavigateToAccountSettingsCommand}"
CommandParameter="{x:Bind}"
Style="{StaticResource SubtleButtonStyle}">
<StackPanel Orientation="Horizontal" Spacing="12">
<FontIcon FontSize="20" Glyph="&#xE8D8;" />
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind Name}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Address}" />
</StackPanel>
<FontIcon
Margin="0,0,8,0"
HorizontalAlignment="Right"
FontSize="12"
Glyph="&#xE76C;" />
</StackPanel>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</controls:SettingsCard>
</controls:SettingsExpander.Items>
</controls:SettingsExpander>-->
<!-- Default reminder -->
<controls:SettingsCard Description="Set a default reminder for all new calendar events." Header="Default reminder">
<controls:SettingsCard.HeaderIcon>
@@ -43,7 +43,10 @@
</winuiControls:BreadcrumbBar.ItemTemplate>
</winuiControls:BreadcrumbBar>
<Frame x:Name="AccountPagesFrame" Grid.Row="1" />
<Frame
x:Name="AccountPagesFrame"
Grid.Row="1"
Navigated="AccountPagesFrameNavigated" />
</Grid>
</Border>
</abstract:ManageAccountsPageAbstract>
@@ -6,8 +6,8 @@ using Microsoft.UI.Xaml.Navigation;
using MoreLinq;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Mail.WinUI.Views.Abstract;
using Wino.Mail.ViewModels.Data;
using Wino.Mail.WinUI.Views.Abstract;
using Wino.Messaging.Client.Navigation;
using Wino.Messaging.UI;
@@ -37,6 +37,10 @@ public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
WeakReferenceMessenger.Default.Register<MergedInboxRenamed>(this);
WeakReferenceMessenger.Default.Register<AccountUpdatedMessage>(this);
// Register for frame navigation events to track back button visibility
AccountPagesFrame.Navigated -= AccountPagesFrameNavigated;
AccountPagesFrame.Navigated += AccountPagesFrameNavigated;
var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuManageAccounts, WinoPage.AccountManagementPage);
PageHistory.Add(new BreadcrumbNavigationItemViewModel(initialRequest, true));
@@ -53,6 +57,12 @@ public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
WeakReferenceMessenger.Default.Unregister<MergedInboxRenamed>(this);
WeakReferenceMessenger.Default.Unregister<AccountUpdatedMessage>(this);
// Unregister frame navigation event
AccountPagesFrame.Navigated -= AccountPagesFrameNavigated;
// Reset navigation state when leaving ManageAccountsPage
ViewModel.StatePersistenceService.IsManageAccountsNavigating = false;
base.OnNavigatingFrom(e);
}
@@ -62,20 +72,42 @@ public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
if (pageType == null) return;
AccountPagesFrame.Navigate(pageType, message.Parameter, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
AccountPagesFrame.Navigate(pageType, message.Parameter, new SlideNavigationTransitionInfo() { Effect = Microsoft.UI.Xaml.Media.Animation.SlideNavigationTransitionEffect.FromRight });
PageHistory.ForEach(a => a.IsActive = false);
PageHistory.Add(new BreadcrumbNavigationItemViewModel(message, true));
}
private void GoBackFrame()
private void AccountPagesFrameNavigated(object sender, NavigationEventArgs e)
{
// Update back button visibility based on whether we can go back within the frame
ViewModel.StatePersistenceService.IsManageAccountsNavigating = AccountPagesFrame.CanGoBack;
}
private void GoBackFrame(Core.Domain.Enums.NavigationTransitionEffect slideEffect)
{
if (AccountPagesFrame.CanGoBack)
{
PageHistory.RemoveAt(PageHistory.Count - 1);
AccountPagesFrame.GoBack(new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
var winuiEffect = slideEffect switch
{
Core.Domain.Enums.NavigationTransitionEffect.FromLeft => Microsoft.UI.Xaml.Media.Animation.SlideNavigationTransitionEffect.FromLeft,
_ => Microsoft.UI.Xaml.Media.Animation.SlideNavigationTransitionEffect.FromRight,
};
AccountPagesFrame.GoBack(new SlideNavigationTransitionInfo() { Effect = winuiEffect });
// Set the new last item as active
if (PageHistory.Count > 0)
{
PageHistory.ForEach(a => a.IsActive = false);
PageHistory[PageHistory.Count - 1].IsActive = true;
}
// Update back button visibility after navigation
ViewModel.StatePersistenceService.IsManageAccountsNavigating = AccountPagesFrame.CanGoBack;
}
}
@@ -83,17 +115,16 @@ public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
{
var clickedPageHistory = PageHistory[args.Index];
// Trigger GoBack repeatedly until we reach the clicked breadcrumb item
while (PageHistory.FirstOrDefault(a => a.IsActive) != clickedPageHistory)
{
AccountPagesFrame.GoBack(new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
PageHistory.RemoveAt(PageHistory.Count - 1);
PageHistory[PageHistory.Count - 1].IsActive = true;
ViewModel.NavigationService.GoBack();
}
}
public void Receive(BackBreadcrumNavigationRequested message)
{
GoBackFrame();
GoBackFrame(message.SlideEffect);
}
public void Receive(AccountUpdatedMessage message)
@@ -43,7 +43,7 @@
Text="{x:Bind ViewModel.SenderName, Mode=TwoWay}" />
</controls:SettingsCard>
<controls:SettingsCard HorizontalContentAlignment="Stretch" Header="{x:Bind domain:Translator.Buttons_Save}">
<controls:SettingsCard HorizontalContentAlignment="Stretch">
<Button
Command="{x:Bind ViewModel.SaveChangesCommand}"
Content="{x:Bind domain:Translator.Buttons_Save}"
+57 -8
View File
@@ -1,9 +1,9 @@
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging;
using MoreLinq;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.UI.Xaml.Navigation;
using MoreLinq;
using Wino.Core.Domain;
using Wino.Core.Domain.Enums;
using Wino.Mail.ViewModels.Data;
@@ -13,7 +13,9 @@ using Wino.Views.Settings;
namespace Wino.Views;
public sealed partial class SettingsPage : SettingsPageAbstract, IRecipient<BreadcrumbNavigationRequested>
public sealed partial class SettingsPage : SettingsPageAbstract,
IRecipient<BreadcrumbNavigationRequested>,
IRecipient<BackBreadcrumNavigationRequested>
{
public ObservableCollection<BreadcrumbNavigationItemViewModel> PageHistory { get; set; } = [];
@@ -26,6 +28,10 @@ public sealed partial class SettingsPage : SettingsPageAbstract, IRecipient<Brea
{
base.OnNavigatedTo(e);
// Register for frame navigation events to track back button visibility
SettingsFrame.Navigated -= SettingsFrameNavigated;
SettingsFrame.Navigated += SettingsFrameNavigated;
SettingsFrame.Navigate(typeof(SettingOptionsPage), null, new SuppressNavigationTransitionInfo());
var initialRequest = new BreadcrumbNavigationRequested(Translator.MenuSettings, WinoPage.SettingOptionsPage);
@@ -60,21 +66,29 @@ public sealed partial class SettingsPage : SettingsPageAbstract, IRecipient<Brea
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
// Unregister frame navigation event
SettingsFrame.Navigated -= SettingsFrameNavigated;
// Reset navigation state when leaving SettingsPage
ViewModel.StatePersistenceService.IsSettingsNavigating = false;
base.OnNavigatingFrom(e);
}
protected override void RegisterRecipients()
{
base.RegisterRecipients();
WeakReferenceMessenger.Default.Register<BreadcrumbNavigationRequested>(this);
WeakReferenceMessenger.Default.Register<BackBreadcrumNavigationRequested>(this);
}
protected override void UnregisterRecipients()
{
base.UnregisterRecipients();
WeakReferenceMessenger.Default.Unregister<BreadcrumbNavigationRequested>(this);
WeakReferenceMessenger.Default.Unregister<BackBreadcrumNavigationRequested>(this);
}
void IRecipient<BreadcrumbNavigationRequested>.Receive(BreadcrumbNavigationRequested message)
@@ -90,16 +104,51 @@ public sealed partial class SettingsPage : SettingsPageAbstract, IRecipient<Brea
PageHistory.Add(new BreadcrumbNavigationItemViewModel(message, true));
}
private void SettingsFrameNavigated(object sender, NavigationEventArgs e)
{
// Update back button visibility based on whether we can go back within the frame
ViewModel.StatePersistenceService.IsSettingsNavigating = SettingsFrame.CanGoBack;
}
private void GoBackFrame(Core.Domain.Enums.NavigationTransitionEffect slideEffect)
{
if (SettingsFrame.CanGoBack)
{
PageHistory.RemoveAt(PageHistory.Count - 1);
var winuiEffect = slideEffect switch
{
Core.Domain.Enums.NavigationTransitionEffect.FromLeft => Microsoft.UI.Xaml.Media.Animation.SlideNavigationTransitionEffect.FromLeft,
_ => Microsoft.UI.Xaml.Media.Animation.SlideNavigationTransitionEffect.FromRight,
};
SettingsFrame.GoBack(new SlideNavigationTransitionInfo() { Effect = winuiEffect });
// Set the new last item as active
if (PageHistory.Count > 0)
{
PageHistory.ForEach(a => a.IsActive = false);
PageHistory[PageHistory.Count - 1].IsActive = true;
}
// Update back button visibility after navigation
ViewModel.StatePersistenceService.IsSettingsNavigating = SettingsFrame.CanGoBack;
}
}
private void BreadItemClicked(Microsoft.UI.Xaml.Controls.BreadcrumbBar sender, Microsoft.UI.Xaml.Controls.BreadcrumbBarItemClickedEventArgs args)
{
var clickedPageHistory = PageHistory[args.Index];
var activeIndex = PageHistory.IndexOf(PageHistory.FirstOrDefault(a => a.IsActive));
// Trigger GoBack repeatedly until we reach the clicked breadcrumb item
while (PageHistory.FirstOrDefault(a => a.IsActive) != clickedPageHistory)
{
SettingsFrame.GoBack(new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
PageHistory.RemoveAt(PageHistory.Count - 1);
PageHistory[PageHistory.Count - 1].IsActive = true;
ViewModel.NavigationService.GoBack();
}
}
public void Receive(BackBreadcrumNavigationRequested message)
{
GoBackFrame(message.SlideEffect);
}
}