Account colors + edit account details. (#592)
* Remove account rename dialog. Implement edit account details page. * Remove unused folder definition. * Adressing theming issues and adding reset button. Changing the UI a bit. * Enable auto indent in initializer. Use service from the application. * Adding color picker to acc setup dialog. Changing UI of edit acc details page.
This commit is contained in:
80
Wino.Core.UWP/Converters/HexToColorBrushConverter.cs
Normal file
80
Wino.Core.UWP/Converters/HexToColorBrushConverter.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using Windows.UI;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Data;
|
||||
using Windows.UI.Xaml.Media;
|
||||
|
||||
namespace Wino.Core.UWP.Converters;
|
||||
|
||||
public partial class HexToColorBrushConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string hexColor && !string.IsNullOrEmpty(hexColor))
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove # if present
|
||||
hexColor = hexColor.Replace("#", "");
|
||||
|
||||
// Parse hex to color
|
||||
byte r = byte.Parse(hexColor.Substring(0, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
byte g = byte.Parse(hexColor.Substring(2, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
byte b = byte.Parse(hexColor.Substring(4, 2), System.Globalization.NumberStyles.HexNumber);
|
||||
|
||||
return new SolidColorBrush(Color.FromArgb(255, r, g, b));
|
||||
}
|
||||
catch
|
||||
{
|
||||
return GetDefaultBrush();
|
||||
}
|
||||
}
|
||||
|
||||
return GetDefaultBrush();
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is string hexColor)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Remove # if present
|
||||
hexColor = hexColor.Replace("#", string.Empty);
|
||||
|
||||
// Parse ARGB values
|
||||
byte a = 255; // Default to fully opaque
|
||||
byte r = byte.Parse(hexColor.Substring(0, 2), NumberStyles.HexNumber);
|
||||
byte g = byte.Parse(hexColor.Substring(2, 2), NumberStyles.HexNumber);
|
||||
byte b = byte.Parse(hexColor.Substring(4, 2), NumberStyles.HexNumber);
|
||||
|
||||
// If 8-digit hex (with alpha), parse alpha value
|
||||
if (hexColor.Length == 8)
|
||||
{
|
||||
a = byte.Parse(hexColor.Substring(6, 2), NumberStyles.HexNumber);
|
||||
}
|
||||
|
||||
return Color.FromArgb(a, r, g, b);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
private SolidColorBrush GetDefaultBrush()
|
||||
{
|
||||
// Get current theme's foreground brush.
|
||||
// Bug: This should be ThemeResource to react to theme changes, but it's not.
|
||||
// So if user changes the dark/light theme, this won't update.
|
||||
|
||||
if (WinoApplication.Current.UnderlyingThemeService.IsUnderlyingThemeDark())
|
||||
return new SolidColorBrush(Colors.White);
|
||||
else
|
||||
return new SolidColorBrush(Colors.Black);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<ContentDialog
|
||||
x:Class="Wino.Dialogs.AccountEditDialog"
|
||||
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.AccountEditDialog_Title}"
|
||||
DefaultButton="Primary"
|
||||
PrimaryButtonClick="SaveClicked"
|
||||
PrimaryButtonText="{x:Bind domain:Translator.Buttons_Save}"
|
||||
SecondaryButtonText="{x:Bind domain:Translator.Buttons_Discard}"
|
||||
Style="{StaticResource WinoDialogStyle}"
|
||||
mc:Ignorable="d">
|
||||
|
||||
<Grid>
|
||||
<TextBox Header="{x:Bind domain:Translator.AccountEditDialog_Message}" Text="{x:Bind Account.Name, Mode=TwoWay}" />
|
||||
</Grid>
|
||||
</ContentDialog>
|
||||
@@ -1,21 +0,0 @@
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Entities.Shared;
|
||||
|
||||
namespace Wino.Dialogs;
|
||||
|
||||
public sealed partial class AccountEditDialog : ContentDialog
|
||||
{
|
||||
public MailAccount Account { get; private set; }
|
||||
public bool IsSaved { get; set; }
|
||||
|
||||
public AccountEditDialog(MailAccount account)
|
||||
{
|
||||
InitializeComponent();
|
||||
Account = account;
|
||||
}
|
||||
|
||||
private void SaveClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
IsSaved = true;
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
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:muxc="using:Microsoft.UI.Xaml.Controls"
|
||||
Title="{x:Bind domain:Translator.NewAccountDialog_Title}"
|
||||
@@ -45,30 +46,47 @@
|
||||
<Grid MinWidth="400" RowSpacing="12">
|
||||
<Grid Visibility="{x:Bind IsProviderSelectionVisible, Mode=OneWay}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- Account Name -->
|
||||
<TextBox
|
||||
x:Name="AccountNameTextbox"
|
||||
Header="{x:Bind domain:Translator.NewAccountDialog_AccountName}"
|
||||
PlaceholderText="{x:Bind domain:Translator.NewAccountDialog_AccountNamePlaceholder}"
|
||||
TextChanged="InputChanged" />
|
||||
|
||||
<!--
|
||||
TODO: Move Name, Sender Name and Color Picker to another Frame.
|
||||
Provider selection should be first, then account details.
|
||||
-->
|
||||
<!--<Grid Grid.Row="1">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Color" />
|
||||
<muxc:ColorPicker x:Name="AccountColorPicker" Grid.Column="1" />
|
||||
</Grid>-->
|
||||
<Grid ColumnSpacing="12">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
|
||||
<TextBox
|
||||
x:Name="AccountNameTextbox"
|
||||
Header="{x:Bind domain:Translator.NewAccountDialog_AccountName}"
|
||||
PlaceholderText="{x:Bind domain:Translator.NewAccountDialog_AccountNamePlaceholder}"
|
||||
TextChanged="InputChanged" />
|
||||
|
||||
<Button Grid.Column="1" VerticalAlignment="Bottom">
|
||||
<Grid>
|
||||
<Ellipse
|
||||
x:Name="SelectedColorEllipse"
|
||||
Width="16"
|
||||
Height="16" />
|
||||
|
||||
<TextBlock x:Name="PickColorTextblock" Text="{x:Bind domain:Translator.CalendarDisplayOptions_Color}" />
|
||||
</Grid>
|
||||
|
||||
<Button.Flyout>
|
||||
<Flyout Placement="TopEdgeAlignedLeft">
|
||||
<GridView
|
||||
Width="150"
|
||||
ItemTemplate="{StaticResource AccountColorTemplate}"
|
||||
ItemsSource="{x:Bind AvailableColors, Mode=OneWay}"
|
||||
SelectedItem="{x:Bind SelectedColor, Mode=TwoWay}" />
|
||||
</Flyout>
|
||||
</Button.Flyout>
|
||||
</Button>
|
||||
|
||||
</Grid>
|
||||
|
||||
|
||||
<ListView
|
||||
Grid.Row="2"
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Windows.System;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Accounts;
|
||||
using Wino.Core.ViewModels.Data;
|
||||
using Wino.Helpers;
|
||||
|
||||
namespace Wino.Core.UWP.Dialogs;
|
||||
|
||||
@@ -20,8 +23,15 @@ public sealed partial class NewAccountDialog : ContentDialog
|
||||
public static readonly DependencyProperty IsProviderSelectionVisibleProperty = DependencyProperty.Register(nameof(IsProviderSelectionVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(true));
|
||||
public static readonly DependencyProperty IsSpecialImapServerPartVisibleProperty = DependencyProperty.Register(nameof(IsSpecialImapServerPartVisible), typeof(bool), typeof(NewAccountDialog), new PropertyMetadata(false));
|
||||
public static readonly DependencyProperty SelectedMailProviderProperty = DependencyProperty.Register(nameof(SelectedMailProvider), typeof(ProviderDetail), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedProviderChanged)));
|
||||
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register(nameof(SelectedColor), typeof(AppColorViewModel), typeof(NewAccountDialog), new PropertyMetadata(null, new PropertyChangedCallback(OnSelectedColorChanged)));
|
||||
|
||||
|
||||
public AppColorViewModel SelectedColor
|
||||
{
|
||||
get { return (AppColorViewModel)GetValue(SelectedColorProperty); }
|
||||
set { SetValue(SelectedColorProperty, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets current selected mail provider in the dialog.
|
||||
/// </summary>
|
||||
@@ -48,13 +58,19 @@ public sealed partial class NewAccountDialog : ContentDialog
|
||||
|
||||
public List<IProviderDetail> Providers { get; set; }
|
||||
|
||||
public List<AppColorViewModel> AvailableColors { get; set; }
|
||||
|
||||
|
||||
public AccountCreationDialogResult Result = null;
|
||||
|
||||
public NewAccountDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
// AccountColorPicker.Color = Colors.Blue;
|
||||
var themeService = WinoApplication.Current.ThemeService.GetAvailableAccountColors();
|
||||
AvailableColors = themeService.Select(a => new AppColorViewModel(a)).ToList();
|
||||
|
||||
UpdateSelectedColor();
|
||||
}
|
||||
|
||||
private static void OnSelectedProviderChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
@@ -63,6 +79,19 @@ public sealed partial class NewAccountDialog : ContentDialog
|
||||
dialog.Validate();
|
||||
}
|
||||
|
||||
private static void OnSelectedColorChanged(DependencyObject obj, DependencyPropertyChangedEventArgs args)
|
||||
{
|
||||
if (obj is NewAccountDialog dialog)
|
||||
dialog.UpdateSelectedColor();
|
||||
}
|
||||
|
||||
private void UpdateSelectedColor()
|
||||
{
|
||||
PickColorTextblock.Visibility = SelectedColor == null ? Visibility.Visible : Visibility.Collapsed;
|
||||
SelectedColorEllipse.Fill = SelectedColor == null ? null : XamlHelpers.GetSolidColorBrushFromHex(SelectedColor.Hex);
|
||||
}
|
||||
|
||||
|
||||
private void CancelClicked(ContentDialog sender, ContentDialogButtonClickEventArgs args)
|
||||
{
|
||||
Hide();
|
||||
@@ -75,7 +104,7 @@ public sealed partial class NewAccountDialog : ContentDialog
|
||||
// Special imap detail input.
|
||||
|
||||
var details = new SpecialImapProviderDetails(SpecialImapAddress.Text.Trim(), AppSpecificPassword.Password.Trim(), DisplayNameTextBox.Text.Trim(), SelectedMailProvider.SpecialImapProvider);
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), details);
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), details, SelectedColor?.Hex ?? string.Empty);
|
||||
Hide();
|
||||
|
||||
return;
|
||||
@@ -97,7 +126,7 @@ public sealed partial class NewAccountDialog : ContentDialog
|
||||
}
|
||||
else
|
||||
{
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), null);
|
||||
Result = new AccountCreationDialogResult(SelectedMailProvider.Type, AccountNameTextbox.Text.Trim(), null, SelectedColor?.Hex ?? string.Empty);
|
||||
Hide();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ using Windows.Storage.Pickers;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
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.Accounts;
|
||||
@@ -38,18 +37,6 @@ public class DialogServiceBase : IDialogServiceBase
|
||||
ApplicationResourceManager = applicationResourceManager;
|
||||
}
|
||||
|
||||
public async Task<MailAccount> ShowEditAccountDialogAsync(MailAccount account)
|
||||
{
|
||||
var editAccountDialog = new AccountEditDialog(account)
|
||||
{
|
||||
RequestedTheme = ThemeService.RootTheme.ToWindowsElementTheme()
|
||||
};
|
||||
|
||||
await HandleDialogPresentationAsync(editAccountDialog);
|
||||
|
||||
return editAccountDialog.IsSaved ? editAccountDialog.Account : null;
|
||||
}
|
||||
|
||||
public async Task<string> PickFilePathAsync(string saveFileName)
|
||||
{
|
||||
var picker = new FolderPicker()
|
||||
|
||||
@@ -458,4 +458,59 @@ public class ThemeService : IThemeService
|
||||
|
||||
public string GetSystemAccentColorHex()
|
||||
=> uiSettings.GetColorValue(UIColorType.Accent).ToHex();
|
||||
|
||||
public List<string> GetAvailableAccountColors()
|
||||
{
|
||||
return new List<string>()
|
||||
{
|
||||
"#e74c3c",
|
||||
"#c0392b",
|
||||
"#e53935",
|
||||
"#d81b60",
|
||||
|
||||
// Pinks
|
||||
"#e91e63",
|
||||
"#ec407a",
|
||||
"#ff4081",
|
||||
|
||||
// Purples
|
||||
"#9b59b6",
|
||||
"#8e44ad",
|
||||
"#673ab7",
|
||||
|
||||
// Blues
|
||||
"#3498db",
|
||||
"#2980b9",
|
||||
"#2196f3",
|
||||
"#03a9f4",
|
||||
"#00bcd4",
|
||||
|
||||
// Teals
|
||||
"#009688",
|
||||
"#1abc9c",
|
||||
"#16a085",
|
||||
|
||||
// Greens
|
||||
"#2ecc71",
|
||||
"#27ae60",
|
||||
"#4caf50",
|
||||
"#8bc34a",
|
||||
|
||||
// Yellows & Oranges
|
||||
"#f1c40f",
|
||||
"#f39c12",
|
||||
"#ff9800",
|
||||
"#ff5722",
|
||||
|
||||
// Browns
|
||||
"#795548",
|
||||
"#a0522d",
|
||||
|
||||
// Grays
|
||||
"#9e9e9e",
|
||||
"#607d8b",
|
||||
"#34495e",
|
||||
"#2c3e50",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,6 @@ public class UnderlyingThemeService : IUnderlyingThemeService
|
||||
_configurationService = configurationService;
|
||||
}
|
||||
|
||||
// This should not rely on application window to be present.
|
||||
// Check theme from the settings, rely on UISettings background color if Default.
|
||||
|
||||
public bool IsUnderlyingThemeDark()
|
||||
{
|
||||
var currentTheme = _configurationService.Get(SelectedAppThemeKey, ApplicationElementTheme.Default);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:animatedvisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
|
||||
xmlns:coreControls="using:Wino.Core.UWP.Controls"
|
||||
xmlns:coreSelectors="using:Wino.Core.UWP.Selectors"
|
||||
xmlns:coreViewModelData="using:Wino.Core.ViewModels.Data"
|
||||
xmlns:domain="using:Wino.Core.Domain"
|
||||
xmlns:helpers="using:Wino.Helpers"
|
||||
xmlns:local="using:Wino.Core.UWP.Styles"
|
||||
@@ -202,6 +203,19 @@
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<!-- Account Color Picker Template -->
|
||||
<DataTemplate x:Key="AccountColorTemplate" x:DataType="coreViewModelData:AppColorViewModel">
|
||||
<Grid
|
||||
Width="32"
|
||||
Height="32"
|
||||
Margin="2">
|
||||
<Rectangle
|
||||
Fill="{x:Bind helpers:XamlHelpers.GetSolidColorBrushFromHex(Hex)}"
|
||||
RadiusX="4"
|
||||
RadiusY="4" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
|
||||
<coreSelectors:AppThemePreviewTemplateSelector
|
||||
x:Key="AppThemePreviewTemplateSelector"
|
||||
CustomAppTemplate="{StaticResource CustomAppThemeTemplate}"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using MoreLinq;
|
||||
@@ -16,7 +17,8 @@ namespace Wino.Views;
|
||||
public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
|
||||
IRecipient<BackBreadcrumNavigationRequested>,
|
||||
IRecipient<BreadcrumbNavigationRequested>,
|
||||
IRecipient<MergedInboxRenamed>
|
||||
IRecipient<MergedInboxRenamed>,
|
||||
IRecipient<AccountUpdatedMessage>
|
||||
{
|
||||
public ObservableCollection<BreadcrumbNavigationItemViewModel> PageHistory { get; set; } = new ObservableCollection<BreadcrumbNavigationItemViewModel>();
|
||||
|
||||
@@ -79,14 +81,16 @@ public sealed partial class ManageAccountsPage : ManageAccountsPageAbstract,
|
||||
GoBackFrame();
|
||||
}
|
||||
|
||||
public void Receive(AccountUpdatedMessage message)
|
||||
public async void Receive(AccountUpdatedMessage message)
|
||||
{
|
||||
// TODO: Find better way to retrieve page history from the stack for the account.
|
||||
var activePage = PageHistory.LastOrDefault();
|
||||
var activePage = PageHistory.FirstOrDefault(a => a.Request.PageType == WinoPage.AccountDetailsPage);
|
||||
|
||||
if (activePage == null) return;
|
||||
|
||||
activePage.Title = message.Account.Name;
|
||||
await Dispatcher.TryRunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
activePage.Title = message.Account.Name;
|
||||
});
|
||||
}
|
||||
|
||||
public void Receive(MergedInboxRenamed message)
|
||||
|
||||
@@ -38,7 +38,8 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
|
||||
protected IWinoLogger LogInitializer { get; }
|
||||
protected IApplicationConfiguration AppConfiguration { get; }
|
||||
protected IWinoServerConnectionManager<AppServiceConnection> AppServiceConnectionManager { get; }
|
||||
protected IThemeService ThemeService { get; }
|
||||
public IThemeService ThemeService { get; }
|
||||
public IUnderlyingThemeService UnderlyingThemeService { get; }
|
||||
protected IDatabaseService DatabaseService { get; }
|
||||
protected ITranslationService TranslationService { get; }
|
||||
|
||||
@@ -62,6 +63,7 @@ public abstract class WinoApplication : Application, IRecipient<LanguageChanged>
|
||||
ThemeService = Services.GetService<IThemeService>();
|
||||
DatabaseService = Services.GetService<IDatabaseService>();
|
||||
TranslationService = Services.GetService<ITranslationService>();
|
||||
UnderlyingThemeService = Services.GetService<IUnderlyingThemeService>();
|
||||
|
||||
// Make sure the paths are setup on app start.
|
||||
AppConfiguration.ApplicationDataFolderPath = ApplicationData.Current.LocalFolder.Path;
|
||||
|
||||
Reference in New Issue
Block a user