Removed migrations. New onboarding screen and wizard like steps.

This commit is contained in:
Burak Kaan Köse
2026-03-06 03:42:08 +01:00
parent db5ecd60e4
commit aaa6e8a2c9
56 changed files with 1843 additions and 554 deletions
@@ -0,0 +1,8 @@
using Wino.Mail.ViewModels;
using Wino.Mail.WinUI;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class AccountSetupProgressPageAbstract : BasePage<AccountSetupProgressPageViewModel>
{
}
@@ -0,0 +1,8 @@
using Wino.Mail.ViewModels;
using Wino.Mail.WinUI;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class ProviderSelectionPageAbstract : BasePage<ProviderSelectionPageViewModel>
{
}
@@ -0,0 +1,8 @@
using Wino.Mail.ViewModels;
using Wino.Mail.WinUI;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class SpecialImapCredentialsPageAbstract : BasePage<SpecialImapCredentialsPageViewModel>
{
}
@@ -0,0 +1,8 @@
using Wino.Core.ViewModels;
using Wino.Mail.WinUI;
namespace Wino.Mail.WinUI.Views.Abstract;
public abstract class WelcomeHostPageAbstract : BasePage<WelcomeHostPageViewModel>
{
}
@@ -78,13 +78,9 @@
Text="{x:Bind ViewModel.EmailAddress, Mode=TwoWay}" />
</Grid>
<PasswordBox
Header="{x:Bind ViewModel.PasswordHeaderText, Mode=OneWay}"
Password="{x:Bind ViewModel.Password, Mode=TwoWay}" />
<PasswordBox Header="{x:Bind ViewModel.PasswordHeaderText, Mode=OneWay}" Password="{x:Bind ViewModel.Password, Mode=TwoWay}" />
<CheckBox
Content="{x:Bind ViewModel.EnableCalendarSupportText, Mode=OneWay}"
IsChecked="{x:Bind ViewModel.IsCalendarSupportEnabled, Mode=TwoWay}" />
<CheckBox Content="{x:Bind ViewModel.EnableCalendarSupportText, Mode=OneWay}" IsChecked="{x:Bind ViewModel.IsCalendarSupportEnabled, Mode=TwoWay}" />
<Button
HorizontalAlignment="Left"
@@ -131,18 +127,10 @@
<FontIcon FontSize="14" Glyph="&#xE896;" />
<TextBlock FontWeight="SemiBold" Text="{x:Bind ViewModel.IncomingSectionTitleText, Mode=OneWay}" />
</StackPanel>
<TextBox
Header="{x:Bind ViewModel.IncomingServerHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.IncomingServer, Mode=TwoWay}" />
<TextBox
Header="{x:Bind ViewModel.PortHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.IncomingServerPort, Mode=TwoWay}" />
<TextBox
Header="{x:Bind ViewModel.IncomingUsernameHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.IncomingServerUsername, Mode=TwoWay}" />
<PasswordBox
Header="{x:Bind ViewModel.IncomingPasswordHeaderText, Mode=OneWay}"
Password="{x:Bind ViewModel.IncomingServerPassword, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.IncomingServerHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.IncomingServer, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.PortHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.IncomingServerPort, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.IncomingUsernameHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.IncomingServerUsername, Mode=TwoWay}" />
<PasswordBox Header="{x:Bind ViewModel.IncomingPasswordHeaderText, Mode=OneWay}" Password="{x:Bind ViewModel.IncomingServerPassword, Mode=TwoWay}" />
<ComboBox
HorizontalAlignment="Stretch"
Header="{x:Bind ViewModel.ConnectionSecurityHeaderText, Mode=OneWay}"
@@ -167,18 +155,10 @@
<FontIcon FontSize="14" Glyph="&#xE898;" />
<TextBlock FontWeight="SemiBold" Text="{x:Bind ViewModel.OutgoingSectionTitleText, Mode=OneWay}" />
</StackPanel>
<TextBox
Header="{x:Bind ViewModel.OutgoingServerHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.OutgoingServer, Mode=TwoWay}" />
<TextBox
Header="{x:Bind ViewModel.PortHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.OutgoingServerPort, Mode=TwoWay}" />
<TextBox
Header="{x:Bind ViewModel.OutgoingUsernameHeaderText, Mode=OneWay}"
Text="{x:Bind ViewModel.OutgoingServerUsername, Mode=TwoWay}" />
<PasswordBox
Header="{x:Bind ViewModel.OutgoingPasswordHeaderText, Mode=OneWay}"
Password="{x:Bind ViewModel.OutgoingServerPassword, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.OutgoingServerHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.OutgoingServer, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.PortHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.OutgoingServerPort, Mode=TwoWay}" />
<TextBox Header="{x:Bind ViewModel.OutgoingUsernameHeaderText, Mode=OneWay}" Text="{x:Bind ViewModel.OutgoingServerUsername, Mode=TwoWay}" />
<PasswordBox Header="{x:Bind ViewModel.OutgoingPasswordHeaderText, Mode=OneWay}" Password="{x:Bind ViewModel.OutgoingServerPassword, Mode=TwoWay}" />
<ComboBox
HorizontalAlignment="Stretch"
Header="{x:Bind ViewModel.ConnectionSecurityHeaderText, Mode=OneWay}"
@@ -0,0 +1,131 @@
<abstract:AccountSetupProgressPageAbstract
x:Class="Wino.Views.AccountSetupProgressPage"
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:accounts="using:Wino.Core.Domain.Models.Accounts"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:helpers="using:Wino.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winuiControls="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Grid Padding="0,8">
<StackPanel
MaxWidth="500"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Spacing="24">
<!-- Title -->
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource SubtitleTextBlockStyle}"
Text="{x:Bind domain:Translator.AccountSetup_Title}" />
<!-- Steps List -->
<ListView
IsItemClickEnabled="False"
ItemsSource="{x:Bind ViewModel.Steps, Mode=OneWay}"
SelectionMode="None">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Padding" Value="0,6" />
<Setter Property="MinHeight" Value="0" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
<DataTemplate x:DataType="accounts:AccountSetupStepModel">
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="28" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Status indicator -->
<Grid
Width="20"
Height="20"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<!-- Pending: gray circle -->
<FontIcon
FontSize="16"
Foreground="{ThemeResource TextFillColorDisabledBrush}"
Glyph="&#xEA3A;"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(IsPending), Mode=OneWay}" />
<!-- InProgress: progress ring -->
<winuiControls:ProgressRing
Width="16"
Height="16"
IsActive="{x:Bind IsInProgress, Mode=OneWay}"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(IsInProgress), Mode=OneWay}" />
<!-- Succeeded: green check -->
<FontIcon
FontSize="16"
Foreground="#107C10"
Glyph="&#xE73E;"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(IsSucceeded), Mode=OneWay}" />
<!-- Failed: red error -->
<FontIcon
FontSize="16"
Foreground="#D13438"
Glyph="&#xEA39;"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(IsFailed), Mode=OneWay}" />
</Grid>
<!-- Step text -->
<StackPanel Grid.Column="1" VerticalAlignment="Center">
<TextBlock Text="{x:Bind Title}" />
<TextBlock
Foreground="#D13438"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind ErrorMessage, Mode=OneWay}"
TextWrapping="Wrap"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(IsFailed), Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!-- Success InfoBar -->
<winuiControls:InfoBar
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsSetupComplete, Mode=OneWay}"
Message="{x:Bind domain:Translator.AccountSetup_SuccessMessage}"
Severity="Success" />
<!-- Failure InfoBar + Buttons -->
<StackPanel
Spacing="12"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(ViewModel.IsSetupFailed), Mode=OneWay}">
<winuiControls:InfoBar
IsClosable="False"
IsOpen="True"
Message="{x:Bind ViewModel.FailureMessage, Mode=OneWay}"
Severity="Error" />
<StackPanel
HorizontalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<Button
Command="{x:Bind ViewModel.GoBackCommand}"
Content="{x:Bind domain:Translator.AccountSetup_GoBackButton}" />
<Button
Command="{x:Bind ViewModel.TryAgainCommand}"
Content="{x:Bind domain:Translator.AccountSetup_TryAgainButton}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</StackPanel>
</StackPanel>
</Grid>
</abstract:AccountSetupProgressPageAbstract>
@@ -0,0 +1,11 @@
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Views;
public sealed partial class AccountSetupProgressPage : AccountSetupProgressPageAbstract
{
public AccountSetupProgressPage()
{
InitializeComponent();
}
}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,125 @@
<abstract:ProviderSelectionPageAbstract
x:Class="Wino.Views.ProviderSelectionPage"
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:accounts="using:Wino.Core.Domain.Models.Accounts"
xmlns:coreViewModelData="using:Wino.Core.ViewModels.Data"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:helpers="using:Wino.Helpers"
xmlns:interfaces="using:Wino.Core.Domain.Interfaces"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer
HorizontalAlignment="Center"
VerticalAlignment="Center"
VerticalScrollBarVisibility="Auto">
<StackPanel
MaxWidth="480"
Margin="0,24,0,24"
HorizontalAlignment="Center"
Spacing="20">
<!-- Title -->
<StackPanel Spacing="4">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind domain:Translator.ProviderSelection_Title}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind domain:Translator.ProviderSelection_Subtitle}" />
</StackPanel>
<!-- Account Name + Color Picker -->
<Grid ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBox
Header="{x:Bind domain:Translator.ProviderSelection_AccountNameHeader}"
PlaceholderText="{x:Bind domain:Translator.ProviderSelection_AccountNamePlaceholder}"
Text="{x:Bind ViewModel.AccountName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<Button Grid.Column="1" VerticalAlignment="Bottom">
<Grid>
<!-- No color selected placeholder -->
<FontIcon
FontSize="16"
Glyph="&#xE771;"
Visibility="{x:Bind helpers:XamlHelpers.ReverseBoolToVisibilityConverter(ViewModel.IsColorSelected), Mode=OneWay}" />
<!-- Color swatch -->
<Ellipse
Width="16"
Height="16"
Fill="{x:Bind helpers:XamlHelpers.GetSolidColorBrushFromHex(ViewModel.SelectedColor.Hex), Mode=OneWay}"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(ViewModel.IsColorSelected), Mode=OneWay}" />
</Grid>
<Button.Flyout>
<Flyout Placement="TopEdgeAlignedLeft">
<StackPanel Spacing="8">
<GridView
Width="150"
ItemTemplate="{StaticResource AccountColorTemplate}"
ItemsSource="{x:Bind ViewModel.AvailableColors, Mode=OneWay}"
SelectedItem="{x:Bind ViewModel.SelectedColor, Mode=TwoWay}" />
<HyperlinkButton
HorizontalAlignment="Center"
Command="{x:Bind ViewModel.ClearColorCommand}"
Content="{x:Bind domain:Translator.ProviderSelection_ClearColor}"
Visibility="{x:Bind helpers:XamlHelpers.BoolToVisibilityConverter(ViewModel.IsColorSelected), Mode=OneWay}" />
</StackPanel>
</Flyout>
</Button.Flyout>
</Button>
</Grid>
<!-- Provider List -->
<ItemsView
ItemsSource="{x:Bind ViewModel.Providers, Mode=OneWay}"
SelectionChanged="ProviderSelectionChanged"
SelectionMode="Single">
<ItemsView.Layout>
<UniformGridLayout Orientation="Vertical" />
</ItemsView.Layout>
<ItemsView.ItemTemplate>
<DataTemplate x:DataType="interfaces:IProviderDetail">
<ItemContainer Padding="12,10">
<Grid Padding="16" ColumnSpacing="12">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
Width="32"
Height="32"
Source="{x:Bind ProviderImage}" />
<StackPanel
Grid.Column="1"
VerticalAlignment="Center"
Spacing="2">
<TextBlock FontWeight="SemiBold" Text="{x:Bind Name}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Description}" />
</StackPanel>
</Grid>
</ItemContainer>
</DataTemplate>
</ItemsView.ItemTemplate>
</ItemsView>
<!-- Continue Button -->
<Button
HorizontalAlignment="Stretch"
Command="{x:Bind ViewModel.ProceedCommand}"
Content="{x:Bind domain:Translator.ProviderSelection_ContinueButton}"
IsEnabled="{x:Bind ViewModel.CanProceed, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</ScrollViewer>
</abstract:ProviderSelectionPageAbstract>
@@ -0,0 +1,17 @@
using Microsoft.UI.Xaml.Controls;
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Views;
public sealed partial class ProviderSelectionPage : ProviderSelectionPageAbstract
{
public ProviderSelectionPage()
{
InitializeComponent();
}
private void ProviderSelectionChanged(ItemsView sender, ItemsViewSelectionChangedEventArgs args)
{
ViewModel.SelectedProvider = sender.SelectedItem as Wino.Core.Domain.Interfaces.IProviderDetail;
}
}
@@ -0,0 +1,147 @@
<abstract:SpecialImapCredentialsPageAbstract
x:Class="Wino.Views.SpecialImapCredentialsPage"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:domain="using:Wino.Core.Domain"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<ScrollViewer
HorizontalAlignment="Center"
VerticalAlignment="Center"
VerticalScrollBarVisibility="Auto">
<StackPanel
MaxWidth="440"
Margin="0,24,0,24"
HorizontalAlignment="Center"
Spacing="20">
<!-- Provider logo -->
<Image
Height="48"
HorizontalAlignment="Center"
Source="{x:Bind ViewModel.WizardContext.SelectedProvider.ProviderImage, Mode=OneWay}"
Stretch="Uniform" />
<!-- Title / subtitle -->
<StackPanel Spacing="4">
<TextBlock Style="{StaticResource SubtitleTextBlockStyle}" Text="{x:Bind ViewModel.WizardContext.SelectedProvider.Name, Mode=OneWay}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind domain:Translator.ProviderSelection_SpecialImap_Subtitle}" />
</StackPanel>
<!-- Display Name -->
<TextBox
Header="{x:Bind domain:Translator.ProviderSelection_DisplayNameHeader}"
PlaceholderText="{x:Bind domain:Translator.ProviderSelection_DisplayNamePlaceholder}"
Text="{x:Bind ViewModel.DisplayName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!-- Email -->
<TextBox
Header="{x:Bind domain:Translator.ProviderSelection_EmailHeader}"
PlaceholderText="{x:Bind domain:Translator.ProviderSelection_EmailPlaceholder}"
Text="{x:Bind ViewModel.EmailAddress, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
<!-- App-Specific Password -->
<PasswordBox
x:Name="AppPasswordBox"
Header="{x:Bind domain:Translator.ProviderSelection_AppPasswordHeader}"
PasswordChanged="AppPasswordChanged" />
<HyperlinkButton
HorizontalAlignment="Right"
Command="{x:Bind ViewModel.OpenAppPasswordHelpCommand}"
Content="{x:Bind domain:Translator.ProviderSelection_AppPasswordHelp}" />
<!-- Divider -->
<Rectangle Height="1" Fill="{ThemeResource CardStrokeColorDefaultBrush}" />
<!-- Calendar Mode -->
<TextBlock Style="{StaticResource BodyStrongTextBlockStyle}" Text="{x:Bind domain:Translator.ProviderSelection_CalendarModeHeader}" />
<ListView
x:Name="CalendarModeListView"
IsItemClickEnabled="False"
SelectionChanged="CalendarModeSelectionChanged"
SelectionMode="Single">
<!-- Disabled -->
<ListViewItem>
<Grid Padding="12" ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<FontIcon
VerticalAlignment="Center"
FontSize="18"
Glyph="&#xEA67;" />
<StackPanel Grid.Column="1" Spacing="2">
<TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.ProviderSelection_CalendarMode_DisabledTitle}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind domain:Translator.ProviderSelection_CalendarMode_DisabledDescription}"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</ListViewItem>
<!-- CalDAV -->
<ListViewItem>
<Grid Padding="12" ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<FontIcon
VerticalAlignment="Center"
FontSize="18"
Glyph="&#xE753;" />
<StackPanel Grid.Column="1" Spacing="2">
<TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.ProviderSelection_CalendarMode_CalDavTitle}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind ViewModel.CalendarModeCalDavDescription, Mode=OneWay}"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</ListViewItem>
<!-- Local -->
<ListViewItem>
<Grid Padding="12" ColumnSpacing="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<FontIcon
VerticalAlignment="Center"
FontSize="18"
Glyph="&#xE7F8;" />
<StackPanel Grid.Column="1" Spacing="2">
<TextBlock FontWeight="SemiBold" Text="{x:Bind domain:Translator.ProviderSelection_CalendarMode_LocalTitle}" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind domain:Translator.ProviderSelection_CalendarMode_LocalDescription}"
TextWrapping="Wrap" />
</StackPanel>
</Grid>
</ListViewItem>
</ListView>
<!-- Continue Button -->
<Button
HorizontalAlignment="Stretch"
Command="{x:Bind ViewModel.ProceedCommand}"
Content="{x:Bind domain:Translator.ProviderSelection_ContinueButton}"
IsEnabled="{x:Bind ViewModel.CanProceed, Mode=OneWay}"
Style="{StaticResource AccentButtonStyle}" />
</StackPanel>
</ScrollViewer>
</abstract:SpecialImapCredentialsPageAbstract>
@@ -0,0 +1,25 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Wino.Mail.WinUI.Views.Abstract;
namespace Wino.Views;
public sealed partial class SpecialImapCredentialsPage : SpecialImapCredentialsPageAbstract
{
public SpecialImapCredentialsPage()
{
InitializeComponent();
}
private void CalendarModeSelectionChanged(object sender, SelectionChangedEventArgs args)
{
if (sender is ListView lv)
ViewModel.SelectedCalendarModeIndex = lv.SelectedIndex;
}
private void AppPasswordChanged(object sender, RoutedEventArgs e)
{
if (sender is PasswordBox pb)
ViewModel.AppSpecificPassword = pb.Password;
}
}
@@ -0,0 +1,69 @@
<abstract:WelcomeHostPageAbstract
x:Class="Wino.Views.WelcomeHostPage"
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:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="using:Wino.Helpers"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewModelData="using:Wino.Mail.ViewModels.Data"
xmlns:winuiControls="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Grid RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Wizard step indicator bar -->
<Border
Padding="24,20"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="0,0,0,1">
<winuiControls:BreadcrumbBar
x:Name="Breadcrumb"
HorizontalAlignment="Center"
ItemClicked="BreadItemClicked"
ItemsSource="{x:Bind PageHistory, Mode=OneWay}">
<winuiControls:BreadcrumbBar.ItemTemplate>
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
<winuiControls:BreadcrumbBarItem>
<winuiControls:BreadcrumbBarItem.ContentTemplate>
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
<StackPanel
Margin="8,0"
Orientation="Horizontal"
Spacing="8">
<Border
Width="24"
Height="24"
Background="{x:Bind helpers:XamlHelpers.GetWizardStepBadgeBrush(IsActive), Mode=OneWay}"
CornerRadius="12">
<TextBlock
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="11"
FontWeight="SemiBold"
Foreground="{x:Bind helpers:XamlHelpers.GetWizardStepNumberForeground(IsActive), Mode=OneWay}"
Text="{x:Bind StepNumber, Mode=OneWay}" />
</Border>
<TextBlock
VerticalAlignment="Center"
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightBySyncState(IsActive), Mode=OneWay}"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind Title, Mode=OneWay}" />
</StackPanel>
</DataTemplate>
</winuiControls:BreadcrumbBarItem.ContentTemplate>
</winuiControls:BreadcrumbBarItem>
</DataTemplate>
</winuiControls:BreadcrumbBar.ItemTemplate>
</winuiControls:BreadcrumbBar>
</Border>
<Frame
x:Name="WizardFrame"
Grid.Row="1" />
</Grid>
</abstract:WelcomeHostPageAbstract>
@@ -0,0 +1,96 @@
using System.Collections.ObjectModel;
using System.Linq;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.UI.Xaml.Media.Animation;
using Microsoft.UI.Xaml.Navigation;
using MoreLinq;
using Wino.Core.Domain.Enums;
using Wino.Mail.ViewModels.Data;
using Wino.Mail.WinUI.Views.Abstract;
using Wino.Messaging.Client.Navigation;
namespace Wino.Views;
public sealed partial class WelcomeHostPage : WelcomeHostPageAbstract,
IRecipient<BreadcrumbNavigationRequested>,
IRecipient<BackBreadcrumNavigationRequested>
{
public ObservableCollection<BreadcrumbNavigationItemViewModel> PageHistory { get; set; } = [];
public WelcomeHostPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
WeakReferenceMessenger.Default.Register<BreadcrumbNavigationRequested>(this);
WeakReferenceMessenger.Default.Register<BackBreadcrumNavigationRequested>(this);
// Navigate to the welcome/get-started page without adding it to the wizard breadcrumb.
// Breadcrumb steps only start after the user clicks "Get Started".
var welcomePageType = ViewModel.NavigationService.GetPageType(WinoPage.WelcomePageV2);
WizardFrame.Navigate(welcomePageType, null, new SuppressNavigationTransitionInfo());
}
protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
{
WeakReferenceMessenger.Default.Unregister<BreadcrumbNavigationRequested>(this);
WeakReferenceMessenger.Default.Unregister<BackBreadcrumNavigationRequested>(this);
base.OnNavigatingFrom(e);
}
public void Receive(BreadcrumbNavigationRequested message)
{
var pageType = ViewModel.NavigationService.GetPageType(message.PageType);
if (pageType == null) return;
WizardFrame.Navigate(pageType, message.Parameter, new SlideNavigationTransitionInfo
{
Effect = SlideNavigationTransitionEffect.FromRight
});
PageHistory.ForEach(a => a.IsActive = false);
PageHistory.Add(new BreadcrumbNavigationItemViewModel(message, isActive: true, stepNumber: PageHistory.Count + 1));
}
public void Receive(BackBreadcrumNavigationRequested message)
{
GoBackFrame();
}
private void GoBackFrame()
{
if (!WizardFrame.CanGoBack) return;
PageHistory.RemoveAt(PageHistory.Count - 1);
WizardFrame.GoBack(new SlideNavigationTransitionInfo
{
Effect = SlideNavigationTransitionEffect.FromLeft
});
if (PageHistory.Count > 0)
{
PageHistory.ForEach(a => a.IsActive = false);
PageHistory[PageHistory.Count - 1].IsActive = true;
}
}
private void BreadItemClicked(Microsoft.UI.Xaml.Controls.BreadcrumbBar sender, Microsoft.UI.Xaml.Controls.BreadcrumbBarItemClickedEventArgs args)
{
var clickedItem = PageHistory[args.Index];
var currentActive = PageHistory.FirstOrDefault(a => a.IsActive);
// Only allow navigating backwards (clicking items before current)
if (currentActive == null || args.Index >= PageHistory.IndexOf(currentActive))
return;
while (PageHistory.FirstOrDefault(a => a.IsActive) != clickedItem && WizardFrame.CanGoBack)
{
GoBackFrame();
}
}
}