Sign in , out ,register.
This commit is contained in:
@@ -255,6 +255,7 @@ public partial class App : WinoApplication,
|
||||
// Initialize theme service after window creation.
|
||||
// Theme service requires the window to exist to properly load and apply themes.
|
||||
await NewThemeService.InitializeAsync();
|
||||
await LoadInitialWinoAccountAsync();
|
||||
LogActivation("Theme service initialized.");
|
||||
|
||||
// If startup task launch, keep window hidden (system tray only).
|
||||
@@ -826,6 +827,17 @@ public partial class App : WinoApplication,
|
||||
_autoSynchronizationLoopCts = null;
|
||||
}
|
||||
|
||||
private async Task LoadInitialWinoAccountAsync()
|
||||
{
|
||||
var winoAccountProfileService = Services.GetRequiredService<IWinoAccountProfileService>();
|
||||
var winoAccount = await winoAccountProfileService.GetActiveAccountAsync().ConfigureAwait(false);
|
||||
|
||||
if (winoAccount != null)
|
||||
{
|
||||
WeakReferenceMessenger.Default.Send(new WinoAccountSignedInMessage(winoAccount));
|
||||
}
|
||||
}
|
||||
|
||||
private async Task RunAutoSynchronizationLoopAsync(TimeSpan interval, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.WinoAccountLoginDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{x:Bind domain:Translator.WinoAccount_LoginDialog_Title}"
|
||||
PrimaryButtonClick="LoginClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_SignIn}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">440</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">440</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_LoginDialog_Description}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
|
||||
<TextBox
|
||||
x:Name="EmailTextBox"
|
||||
Header="{x:Bind domain:Translator.WinoAccount_EmailLabel}"
|
||||
PlaceholderText="{x:Bind domain:Translator.WinoAccount_EmailPlaceholder}"
|
||||
TextChanging="InputChanged" />
|
||||
|
||||
<PasswordBox
|
||||
x:Name="PasswordBox"
|
||||
Header="{x:Bind domain:Translator.WinoAccount_PasswordLabel}"
|
||||
PasswordChanged="InputChanged" />
|
||||
|
||||
<ProgressRing
|
||||
x:Name="BusyRing"
|
||||
Width="20"
|
||||
Height="20"
|
||||
HorizontalAlignment="Left"
|
||||
IsActive="False"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<TextBlock
|
||||
x:Name="ErrorTextBlock"
|
||||
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="Collapsed" />
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,97 @@
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Mail.WinUI.Services;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class WinoAccountLoginDialog : ContentDialog
|
||||
{
|
||||
private readonly IWinoAccountProfileService _profileService;
|
||||
|
||||
public WinoAccountLoginDialog(IWinoAccountProfileService profileService)
|
||||
{
|
||||
_profileService = profileService;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public WinoAccount? Result { get; private set; }
|
||||
|
||||
private async void LoginClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
args.Cancel = true;
|
||||
|
||||
var validationError = ValidateInput();
|
||||
if (!string.IsNullOrWhiteSpace(validationError))
|
||||
{
|
||||
ShowError(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
var deferral = args.GetDeferral();
|
||||
|
||||
try
|
||||
{
|
||||
SetBusyState(true);
|
||||
HideError();
|
||||
|
||||
var result = await _profileService.LoginAsync(EmailTextBox.Text.Trim(), PasswordBox.Password);
|
||||
|
||||
if (!result.IsSuccess || result.Account == null)
|
||||
{
|
||||
ShowError(WinoAccountAuthErrorTranslator.Translate(result.ErrorCode));
|
||||
return;
|
||||
}
|
||||
|
||||
Result = result.Account;
|
||||
args.Cancel = false;
|
||||
Hide();
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetBusyState(false);
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private string ValidateInput()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(EmailTextBox.Text))
|
||||
{
|
||||
return Translator.WinoAccount_Validation_EmailRequired;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(PasswordBox.Password))
|
||||
{
|
||||
return Translator.WinoAccount_Validation_PasswordRequired;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private void InputChanged(TextBox sender, TextBoxTextChangingEventArgs args) => HideError();
|
||||
|
||||
private void InputChanged(object sender, RoutedEventArgs e) => HideError();
|
||||
|
||||
private void SetBusyState(bool isBusy)
|
||||
{
|
||||
IsPrimaryButtonEnabled = !isBusy;
|
||||
IsSecondaryButtonEnabled = !isBusy;
|
||||
BusyRing.IsActive = isBusy;
|
||||
BusyRing.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void ShowError(string message)
|
||||
{
|
||||
ErrorTextBlock.Text = message;
|
||||
ErrorTextBlock.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideError()
|
||||
{
|
||||
ErrorTextBlock.Text = string.Empty;
|
||||
ErrorTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.WinoAccountRegistrationDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
Title="{x:Bind domain:Translator.WinoAccount_RegisterDialog_Title}"
|
||||
PrimaryButtonClick="RegisterClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.WinoAccount_RegisterDialog_PrimaryButton}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Cancel}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<ContentDialog.Resources>
|
||||
<x:Double x:Key="ContentDialogMinWidth">440</x:Double>
|
||||
<x:Double x:Key="ContentDialogMaxWidth">440</x:Double>
|
||||
</ContentDialog.Resources>
|
||||
|
||||
<StackPanel Spacing="12">
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_RegisterDialog_Description}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
|
||||
<TextBox
|
||||
x:Name="EmailTextBox"
|
||||
Header="{x:Bind domain:Translator.WinoAccount_EmailLabel}"
|
||||
PlaceholderText="{x:Bind domain:Translator.WinoAccount_EmailPlaceholder}"
|
||||
TextChanging="InputChanged" />
|
||||
|
||||
<PasswordBox
|
||||
x:Name="PasswordBox"
|
||||
Header="{x:Bind domain:Translator.WinoAccount_PasswordLabel}"
|
||||
PasswordChanged="InputChanged" />
|
||||
|
||||
<PasswordBox
|
||||
x:Name="ConfirmPasswordBox"
|
||||
Header="{x:Bind domain:Translator.WinoAccount_ConfirmPasswordLabel}"
|
||||
PasswordChanged="InputChanged" />
|
||||
|
||||
<ProgressRing
|
||||
x:Name="BusyRing"
|
||||
Width="20"
|
||||
Height="20"
|
||||
HorizontalAlignment="Left"
|
||||
IsActive="False"
|
||||
Visibility="Collapsed" />
|
||||
|
||||
<TextBlock
|
||||
x:Name="ErrorTextBlock"
|
||||
Foreground="{ThemeResource SystemFillColorCriticalBrush}"
|
||||
TextWrapping="WrapWholeWords"
|
||||
Visibility="Collapsed" />
|
||||
</StackPanel>
|
||||
</ContentDialog>
|
||||
@@ -0,0 +1,103 @@
|
||||
using System;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Mail.WinUI.Services;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class WinoAccountRegistrationDialog : ContentDialog
|
||||
{
|
||||
private readonly IWinoAccountProfileService _profileService;
|
||||
|
||||
public WinoAccountRegistrationDialog(IWinoAccountProfileService profileService)
|
||||
{
|
||||
_profileService = profileService;
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
public WinoAccount? Result { get; private set; }
|
||||
|
||||
private async void RegisterClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
args.Cancel = true;
|
||||
|
||||
var validationError = ValidateInput();
|
||||
if (!string.IsNullOrWhiteSpace(validationError))
|
||||
{
|
||||
ShowError(validationError);
|
||||
return;
|
||||
}
|
||||
|
||||
var deferral = args.GetDeferral();
|
||||
|
||||
try
|
||||
{
|
||||
SetBusyState(true);
|
||||
HideError();
|
||||
|
||||
var result = await _profileService.RegisterAsync(EmailTextBox.Text.Trim(), PasswordBox.Password);
|
||||
|
||||
if (!result.IsSuccess || result.Account == null)
|
||||
{
|
||||
ShowError(WinoAccountAuthErrorTranslator.Translate(result.ErrorCode));
|
||||
return;
|
||||
}
|
||||
|
||||
Result = result.Account;
|
||||
args.Cancel = false;
|
||||
Hide();
|
||||
}
|
||||
finally
|
||||
{
|
||||
SetBusyState(false);
|
||||
deferral.Complete();
|
||||
}
|
||||
}
|
||||
|
||||
private string ValidateInput()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(EmailTextBox.Text))
|
||||
{
|
||||
return Translator.WinoAccount_Validation_EmailRequired;
|
||||
}
|
||||
|
||||
if (string.IsNullOrWhiteSpace(PasswordBox.Password))
|
||||
{
|
||||
return Translator.WinoAccount_Validation_PasswordRequired;
|
||||
}
|
||||
|
||||
if (!string.Equals(PasswordBox.Password, ConfirmPasswordBox.Password, StringComparison.Ordinal))
|
||||
{
|
||||
return Translator.WinoAccount_Validation_PasswordMismatch;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private void InputChanged(TextBox sender, TextBoxTextChangingEventArgs args) => HideError();
|
||||
|
||||
private void InputChanged(object sender, RoutedEventArgs e) => HideError();
|
||||
|
||||
private void SetBusyState(bool isBusy)
|
||||
{
|
||||
IsPrimaryButtonEnabled = !isBusy;
|
||||
IsSecondaryButtonEnabled = !isBusy;
|
||||
BusyRing.IsActive = isBusy;
|
||||
BusyRing.Visibility = isBusy ? Visibility.Visible : Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private void ShowError(string message)
|
||||
{
|
||||
ErrorTextBlock.Text = message;
|
||||
ErrorTextBlock.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideError()
|
||||
{
|
||||
ErrorTextBlock.Text = string.Empty;
|
||||
ErrorTextBlock.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
@@ -27,11 +27,15 @@ namespace Wino.Services;
|
||||
|
||||
public class DialogService : DialogServiceBase, IMailDialogService
|
||||
{
|
||||
private readonly IWinoAccountProfileService _winoAccountProfileService;
|
||||
|
||||
public DialogService(INewThemeService themeService,
|
||||
IConfigurationService configurationService,
|
||||
IApplicationResourceManager<ResourceDictionary> applicationResourceManager,
|
||||
IUpdateManager updateManager) : base(themeService, configurationService, applicationResourceManager, updateManager)
|
||||
IUpdateManager updateManager,
|
||||
IWinoAccountProfileService winoAccountProfileService) : base(themeService, configurationService, applicationResourceManager, updateManager)
|
||||
{
|
||||
_winoAccountProfileService = winoAccountProfileService;
|
||||
}
|
||||
|
||||
public async Task<ICreateAccountAliasDialog> ShowCreateAccountAliasDialogAsync()
|
||||
@@ -213,4 +217,32 @@ public class DialogService : DialogServiceBase, IMailDialogService
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<WinoAccount?> ShowWinoAccountRegistrationDialogAsync()
|
||||
{
|
||||
var dialog = new WinoAccountRegistrationDialog(_winoAccountProfileService)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
var result = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
return result == ContentDialogResult.Primary
|
||||
? dialog.Result
|
||||
: null;
|
||||
}
|
||||
|
||||
public async Task<WinoAccount?> ShowWinoAccountLoginDialogAsync()
|
||||
{
|
||||
var dialog = new WinoAccountLoginDialog(_winoAccountProfileService)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
var result = await HandleDialogPresentationAsync(dialog);
|
||||
|
||||
return result == ContentDialogResult.Primary
|
||||
? dialog.Result
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Mail.Api.Contracts.Common;
|
||||
|
||||
namespace Wino.Mail.WinUI.Services;
|
||||
|
||||
public static class WinoAccountAuthErrorTranslator
|
||||
{
|
||||
public static string Translate(string? errorCode)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(errorCode))
|
||||
{
|
||||
return Translator.GeneralTitle_Error;
|
||||
}
|
||||
|
||||
return errorCode switch
|
||||
{
|
||||
ApiErrorCodes.InvalidCredentials => Translator.WinoAccount_Error_InvalidCredentials,
|
||||
ApiErrorCodes.AccountLocked => Translator.WinoAccount_Error_AccountLocked,
|
||||
ApiErrorCodes.AccountBanned => Translator.WinoAccount_Error_AccountBanned,
|
||||
ApiErrorCodes.AccountSuspended => Translator.WinoAccount_Error_AccountSuspended,
|
||||
ApiErrorCodes.RefreshTokenInvalid => Translator.WinoAccount_Error_RefreshTokenInvalid,
|
||||
ApiErrorCodes.EmailAlreadyRegistered => Translator.WinoAccount_Error_EmailAlreadyRegistered,
|
||||
ApiErrorCodes.ExternalLoginEmailRequired => Translator.WinoAccount_Error_ExternalLoginEmailRequired,
|
||||
ApiErrorCodes.ExternalLoginInvalid => Translator.WinoAccount_Error_ExternalLoginInvalid,
|
||||
ApiErrorCodes.ExternalAuthStateInvalid => Translator.WinoAccount_Error_ExternalAuthStateInvalid,
|
||||
ApiErrorCodes.ExternalAuthCodeInvalid => Translator.WinoAccount_Error_ExternalAuthCodeInvalid,
|
||||
ApiErrorCodes.Forbidden => Translator.WinoAccount_Error_Forbidden,
|
||||
ApiErrorCodes.ValidationFailed => Translator.WinoAccount_Error_ValidationFailed,
|
||||
_ => errorCode
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -86,6 +86,68 @@
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="WinoAccountButton"
|
||||
Background="Transparent"
|
||||
BorderBrush="Transparent">
|
||||
<Button.Flyout>
|
||||
<Flyout Placement="Bottom">
|
||||
<Grid MinWidth="320" MaxWidth="360">
|
||||
<StackPanel
|
||||
x:Name="WinoAccountSignedOutView"
|
||||
Spacing="12">
|
||||
<TextBlock
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Titlebar_SignedOutTitle}" />
|
||||
<TextBlock
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
Text="{x:Bind domain:Translator.WinoAccount_Titlebar_SignedOutDescription}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Button
|
||||
Click="RegisterWinoAccountClicked"
|
||||
Content="{x:Bind domain:Translator.WinoAccount_RegisterButton_Action}" />
|
||||
<Button
|
||||
Click="LoginWinoAccountClicked"
|
||||
Content="{x:Bind domain:Translator.WinoAccount_LoginButton_Action}" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel
|
||||
x:Name="WinoAccountSignedInView"
|
||||
Spacing="12"
|
||||
Visibility="Collapsed">
|
||||
<StackPanel Orientation="Horizontal" Spacing="12">
|
||||
<PersonPicture
|
||||
x:Name="WinoAccountFlyoutPicture"
|
||||
Width="40"
|
||||
Height="40"
|
||||
Initials="W" />
|
||||
<StackPanel Spacing="2">
|
||||
<TextBlock
|
||||
x:Name="WinoAccountFlyoutEmailText"
|
||||
Style="{StaticResource BodyStrongTextBlockStyle}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
<TextBlock
|
||||
x:Name="WinoAccountFlyoutStatusText"
|
||||
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
|
||||
TextWrapping="WrapWholeWords" />
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
<Button
|
||||
HorizontalAlignment="Left"
|
||||
Click="SignOutWinoAccountClicked"
|
||||
Content="{x:Bind domain:Translator.WinoAccount_SignOutButton_Action}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
<PersonPicture
|
||||
x:Name="WinoAccountButtonPicture"
|
||||
Width="30"
|
||||
Height="30"
|
||||
Initials="W" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</TitleBar.RightHeader>
|
||||
</TitleBar>
|
||||
|
||||
@@ -10,11 +10,13 @@ using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Controls;
|
||||
using Windows.UI;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Synchronization;
|
||||
using Wino.Extensions;
|
||||
using Wino.Mail.WinUI.Activation;
|
||||
using Wino.Mail.WinUI.Extensions;
|
||||
using Wino.Mail.WinUI.Interfaces;
|
||||
using Wino.Mail.WinUI.Views;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
@@ -28,11 +30,15 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
IRecipient<InfoBarMessageRequested>,
|
||||
IRecipient<TitleBarShellContentUpdated>,
|
||||
IRecipient<SynchronizationActionsAdded>,
|
||||
IRecipient<SynchronizationActionsCompleted>
|
||||
IRecipient<SynchronizationActionsCompleted>,
|
||||
IRecipient<WinoAccountSignedInMessage>,
|
||||
IRecipient<WinoAccountSignedOutMessage>
|
||||
{
|
||||
public IStatePersistanceService StatePersistanceService { get; } = WinoApplication.Current.Services.GetService<IStatePersistanceService>() ?? throw new Exception("StatePersistanceService not registered in DI container.");
|
||||
public IPreferencesService PreferencesService { get; } = WinoApplication.Current.Services.GetService<IPreferencesService>() ?? throw new Exception("PreferencesService not registered in DI container.");
|
||||
public INavigationService NavigationService { get; } = WinoApplication.Current.Services.GetService<INavigationService>() ?? throw new Exception("NavigationService not registered in DI container.");
|
||||
private IMailDialogService MailDialogService { get; } = WinoApplication.Current.Services.GetRequiredService<IMailDialogService>();
|
||||
private IWinoAccountProfileService WinoAccountProfileService { get; } = WinoApplication.Current.Services.GetRequiredService<IWinoAccountProfileService>();
|
||||
|
||||
public ICommand ShowWinoCommand { get; set; }
|
||||
public ICommand ShowWinoCalendarCommand { get; set; }
|
||||
@@ -180,26 +186,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
|
||||
public void Receive(InfoBarMessageRequested message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.ActionButtonTitle) || message.Action == null)
|
||||
{
|
||||
ShellInfoBar.ActionButton = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellInfoBar.ActionButton = new Button()
|
||||
{
|
||||
Content = message.ActionButtonTitle,
|
||||
Command = new RelayCommand(message.Action)
|
||||
};
|
||||
}
|
||||
|
||||
ShellInfoBar.Message = message.Message;
|
||||
ShellInfoBar.Title = message.Title;
|
||||
ShellInfoBar.Severity = message.Severity.AsMUXCInfoBarSeverity();
|
||||
ShellInfoBar.IsOpen = true;
|
||||
});
|
||||
ShowInfoBarMessage(message);
|
||||
}
|
||||
|
||||
public void Receive(SynchronizationActionsAdded message)
|
||||
@@ -226,6 +213,16 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(WinoAccountSignedInMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() => UpdateWinoAccountState(message.Account));
|
||||
}
|
||||
|
||||
public void Receive(WinoAccountSignedOutMessage message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() => UpdateWinoAccountState(null));
|
||||
}
|
||||
|
||||
private void UpdateSyncStatusVisibility()
|
||||
{
|
||||
SyncStatusButton.Visibility = SyncActionItems.Any()
|
||||
@@ -329,6 +326,8 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
WeakReferenceMessenger.Default.Register<InfoBarMessageRequested>(this);
|
||||
WeakReferenceMessenger.Default.Register<SynchronizationActionsAdded>(this);
|
||||
WeakReferenceMessenger.Default.Register<SynchronizationActionsCompleted>(this);
|
||||
WeakReferenceMessenger.Default.Register<WinoAccountSignedInMessage>(this);
|
||||
WeakReferenceMessenger.Default.Register<WinoAccountSignedOutMessage>(this);
|
||||
}
|
||||
|
||||
private void UnregisterRecipients()
|
||||
@@ -338,6 +337,118 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
|
||||
WeakReferenceMessenger.Default.Unregister<InfoBarMessageRequested>(this);
|
||||
WeakReferenceMessenger.Default.Unregister<SynchronizationActionsAdded>(this);
|
||||
WeakReferenceMessenger.Default.Unregister<SynchronizationActionsCompleted>(this);
|
||||
WeakReferenceMessenger.Default.Unregister<WinoAccountSignedInMessage>(this);
|
||||
WeakReferenceMessenger.Default.Unregister<WinoAccountSignedOutMessage>(this);
|
||||
}
|
||||
|
||||
private void ShowInfoBarMessage(InfoBarMessageRequested message)
|
||||
{
|
||||
DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
if (string.IsNullOrEmpty(message.ActionButtonTitle) || message.Action == null)
|
||||
{
|
||||
ShellInfoBar.ActionButton = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShellInfoBar.ActionButton = new Button()
|
||||
{
|
||||
Content = message.ActionButtonTitle,
|
||||
Command = new RelayCommand(message.Action)
|
||||
};
|
||||
}
|
||||
|
||||
ShellInfoBar.Message = message.Message;
|
||||
ShellInfoBar.Title = message.Title;
|
||||
ShellInfoBar.Severity = message.Severity.AsMUXCInfoBarSeverity();
|
||||
ShellInfoBar.IsOpen = true;
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateWinoAccountState(WinoAccount? account)
|
||||
{
|
||||
var isSignedIn = account != null;
|
||||
|
||||
WinoAccountSignedOutView.Visibility = isSignedIn ? Visibility.Collapsed : Visibility.Visible;
|
||||
WinoAccountSignedInView.Visibility = isSignedIn ? Visibility.Visible : Visibility.Collapsed;
|
||||
|
||||
var initials = GetInitials(account?.Email);
|
||||
|
||||
WinoAccountButtonPicture.Initials = initials;
|
||||
WinoAccountFlyoutPicture.Initials = initials;
|
||||
WinoAccountButtonPicture.DisplayName = account?.Email ?? Translator.WinoAccount_Titlebar_SignedOutTitle;
|
||||
WinoAccountFlyoutPicture.DisplayName = account?.Email ?? Translator.WinoAccount_Titlebar_SignedOutTitle;
|
||||
|
||||
WinoAccountFlyoutEmailText.Text = account?.Email ?? string.Empty;
|
||||
WinoAccountFlyoutStatusText.Text = account == null
|
||||
? string.Empty
|
||||
: string.Format(Translator.WinoAccount_Titlebar_SignedInStatus, account.AccountStatus);
|
||||
}
|
||||
|
||||
private static string GetInitials(string? email)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(email))
|
||||
{
|
||||
return "W";
|
||||
}
|
||||
|
||||
var localPart = email.Split('@')[0];
|
||||
var segments = localPart
|
||||
.Split(['.', '_', '-', ' '], StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(segment => !string.IsNullOrWhiteSpace(segment))
|
||||
.Take(2)
|
||||
.ToArray();
|
||||
|
||||
if (segments.Length == 0)
|
||||
{
|
||||
return email[..1].ToUpperInvariant();
|
||||
}
|
||||
|
||||
return string.Concat(segments.Select(segment => char.ToUpperInvariant(segment[0])));
|
||||
}
|
||||
|
||||
private async void RegisterWinoAccountClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var account = await MailDialogService.ShowWinoAccountRegistrationDialogAsync();
|
||||
if (account != null)
|
||||
{
|
||||
ShowInfoBarMessage(new InfoBarMessageRequested(
|
||||
InfoBarMessageType.Success,
|
||||
Translator.GeneralTitle_Info,
|
||||
string.Format(Translator.WinoAccount_RegisterSuccessMessage, account.Email)));
|
||||
}
|
||||
}
|
||||
|
||||
private async void LoginWinoAccountClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var account = await MailDialogService.ShowWinoAccountLoginDialogAsync();
|
||||
if (account != null)
|
||||
{
|
||||
ShowInfoBarMessage(new InfoBarMessageRequested(
|
||||
InfoBarMessageType.Success,
|
||||
Translator.GeneralTitle_Info,
|
||||
string.Format(Translator.WinoAccount_LoginSuccessMessage, account.Email)));
|
||||
}
|
||||
}
|
||||
|
||||
private async void SignOutWinoAccountClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
var activeAccount = await WinoAccountProfileService.GetActiveAccountAsync();
|
||||
if (activeAccount == null)
|
||||
{
|
||||
ShowInfoBarMessage(new InfoBarMessageRequested(
|
||||
InfoBarMessageType.Warning,
|
||||
Translator.GeneralTitle_Info,
|
||||
Translator.WinoAccount_SignOut_NoAccountMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
await WinoAccountProfileService.SignOutAsync();
|
||||
|
||||
ShowInfoBarMessage(new InfoBarMessageRequested(
|
||||
InfoBarMessageType.Success,
|
||||
Translator.GeneralTitle_Info,
|
||||
string.Format(Translator.WinoAccount_SignOut_SuccessMessage, activeAccount.Email)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -226,6 +226,7 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Wino.Calendar.ViewModels\Wino.Calendar.ViewModels.csproj" />
|
||||
<ProjectReference Include="..\Wino.Mail.Contracts\Wino.Mail.Contracts.csproj" />
|
||||
<ProjectReference Include="..\Wino.Core.Domain\Wino.Core.Domain.csproj" />
|
||||
<ProjectReference Include="..\Wino.Core.ViewModels\Wino.Core.ViewModels.csproj" />
|
||||
<ProjectReference Include="..\Wino.Mail.ViewModels\Wino.Mail.ViewModels.csproj" />
|
||||
|
||||
Reference in New Issue
Block a user