Some UI changes on settings.

This commit is contained in:
Burak Kaan Köse
2026-03-09 00:28:10 +01:00
parent 3e731967cd
commit 44be3eb4f7
17 changed files with 291 additions and 149 deletions
@@ -77,7 +77,7 @@ public static class CalendarRecurrenceSummaryFormatter
return string.Format(
culture,
Translator.GetTranslatedString("CalendarEventCompose_RecurringSummarySmart"),
Translator.CalendarEventCompose_RecurringSummarySmart,
cadenceSummary,
weekdaySummary,
timeSummary,
@@ -18,6 +18,11 @@ public interface IStatePersistanceService : INotifyPropertyChanged
/// </summary>
string CoreWindowTitle { get; set; }
/// <summary>
/// App mode title shown in the title bar.
/// </summary>
string AppModeTitle { get; set; }
/// <summary>
/// When only reader page is visible in small sized window.
/// </summary>
@@ -0,0 +1,74 @@
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Wino.Core.Domain.Misc;
public static class CalendarColorPalette
{
private static readonly string[] FlatUiColorPalette =
[
"#E53935", "#D81B60", "#8E24AA", "#5E35B1", "#3949AB", "#1E88E5", "#039BE5", "#00ACC1", "#00897B", "#43A047",
"#7CB342", "#C0CA33", "#FDD835", "#FFB300", "#FB8C00", "#F4511E", "#6D4C41", "#757575", "#546E7A", "#C62828",
"#AD1457", "#6A1B9A", "#4527A0", "#283593", "#1565C0", "#0277BD", "#00838F", "#00695C", "#2E7D32", "#558B2F",
"#9E9D24", "#F9A825", "#FF8F00", "#EF6C00", "#D84315", "#4E342E", "#616161", "#455A64", "#EF5350", "#EC407A",
"#AB47BC", "#7E57C2", "#5C6BC0", "#42A5F5", "#29B6F6", "#26C6DA", "#26A69A", "#66BB6A", "#9CCC65", "#D4E157",
"#FFEE58", "#FFCA28", "#FFA726", "#FF7043", "#8D6E63", "#BDBDBD", "#78909C", "#F06292", "#BA68C8", "#9575CD"
];
public static IReadOnlyList<string> GetColors() => FlatUiColorPalette;
public static string GetDistinctColor(IEnumerable<string> usedColors)
{
var used = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (usedColors != null)
{
foreach (var color in usedColors)
{
if (TryNormalizeHexColor(color, out var normalized))
{
used.Add(normalized);
}
}
}
foreach (var color in FlatUiColorPalette)
{
if (!used.Contains(color))
{
return color;
}
}
return FlatUiColorPalette[0];
}
private static bool TryNormalizeHexColor(string value, out string normalized)
{
normalized = null;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
var color = value.Trim();
if (color.StartsWith('#'))
{
color = color[1..];
}
if (color.Length != 6)
{
return false;
}
if (!int.TryParse(color, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _))
{
return false;
}
normalized = $"#{color.ToUpperInvariant()}";
return true;
}
}
@@ -150,6 +150,7 @@
"CalendarEventCompose_PickCalendarTitle": "Pick a calendar",
"CalendarEventCompose_Recurring": "Recurring",
"CalendarEventCompose_RecurringSummary": "Occurs every {0} {1}{2} {3} effective {4}{5}",
"CalendarEventCompose_RecurringSummarySmart": "Occurs {0}{1} {2} effective {3}{4}",
"CalendarEventCompose_RepeatEvery": "Repeat every",
"CalendarEventCompose_SelectCalendar": "Select calendar",
"CalendarEventCompose_SingleOccurrenceSummary": "Occurs on {0} {1}",
@@ -1,3 +1,5 @@
using System;
using System.Linq;
using FluentAssertions;
using Moq;
using Wino.Core.Domain;
@@ -5,6 +7,7 @@ using Wino.Core.Domain.Entities.Mail;
using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Misc;
using Wino.Core.Tests.Helpers;
using Wino.Services;
using Xunit;
@@ -49,6 +52,7 @@ public class AccountServiceTests : IAsyncLifetime
calendars.Should().HaveCount(1);
calendars[0].IsPrimary.Should().BeTrue();
calendars[0].Name.Should().Be(Translator.AccountDetailsPage_TabCalendar);
ColorHelpers.GetFlatColorPalette().Should().Contain(calendars[0].BackgroundColorHex);
}
[Fact]
@@ -72,6 +76,49 @@ public class AccountServiceTests : IAsyncLifetime
calendars.Should().BeEmpty();
}
[Fact]
public async Task CreateAccountAsync_ImapLocalOnly_AssignsDistinctCalendarColorsAcrossAccounts()
{
var firstAccountId = Guid.NewGuid();
var secondAccountId = Guid.NewGuid();
await _accountService.CreateAccountAsync(
CreateImapAccount(firstAccountId),
new CustomServerInformation
{
Id = Guid.NewGuid(),
AccountId = firstAccountId,
CalendarSupportMode = ImapCalendarSupportMode.LocalOnly
});
await _accountService.CreateAccountAsync(
CreateImapAccount(secondAccountId),
new CustomServerInformation
{
Id = Guid.NewGuid(),
AccountId = secondAccountId,
CalendarSupportMode = ImapCalendarSupportMode.LocalOnly
});
var calendars = await _databaseService.Connection.Table<Wino.Core.Domain.Entities.Calendar.AccountCalendar>()
.OrderBy(a => a.AccountId)
.ToListAsync();
calendars.Should().HaveCount(2);
calendars.Select(a => a.BackgroundColorHex).Should().OnlyHaveUniqueItems();
calendars.Should().OnlyContain(a => ColorHelpers.GetFlatColorPalette().Contains(a.BackgroundColorHex));
}
[Fact]
public void FlatCalendarPalette_ProvidesAtLeastFiftyDistinctColors()
{
ColorHelpers.GetFlatColorPalette()
.Distinct(StringComparer.OrdinalIgnoreCase)
.Count()
.Should()
.BeGreaterThanOrEqualTo(50);
}
private static MailAccount CreateImapAccount(Guid accountId)
{
return new MailAccount
@@ -15,8 +15,9 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
{
private readonly INativeAppService _nativeAppService;
private readonly IAccountService _accountService;
private readonly IStoreRatingService _storeRatingService;
public string WebsiteUrl => AppUrls.Website;
public string GitHubUrl => AppUrls.GitHub;
public string PaypalUrl => AppUrls.Paypal;
[ObservableProperty]
@@ -28,10 +29,13 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
[ObservableProperty]
public partial int AccountCount { get; set; }
public SettingOptionsPageViewModel(INativeAppService nativeAppService, IAccountService accountService)
public SettingOptionsPageViewModel(INativeAppService nativeAppService,
IAccountService accountService,
IStoreRatingService storeRatingService)
{
_nativeAppService = nativeAppService;
_accountService = accountService;
_storeRatingService = storeRatingService;
}
public override void OnNavigatedTo(NavigationMode mode, object parameters)
@@ -86,4 +90,19 @@ public partial class SettingOptionsPageViewModel : CoreBaseViewModel
Messenger.Send(new BreadcrumbNavigationRequested(pageTitle, pageType));
}
}
[RelayCommand]
private async Task NavigateExternalAsync(object target)
{
if (target is not string stringTarget || string.IsNullOrWhiteSpace(stringTarget))
return;
if (stringTarget == "Store")
{
await _storeRatingService.LaunchStorePageForReviewAsync();
return;
}
await _nativeAppService.LaunchUriAsync(new Uri(stringTarget));
}
}
+8 -79
View File
@@ -1,105 +1,34 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Globalization;
using System.Linq;
using Wino.Core.Domain.Misc;
namespace Wino.Core.Misc;
public static class ColorHelpers
{
private static readonly string[] FlatUiColorPalette =
[
"#B91C1C", "#C2410C", "#B45309", "#A16207", "#4D7C0F", "#15803D", "#047857", "#0F766E", "#0E7490", "#0369A1",
"#1D4ED8", "#4338CA", "#6D28D9", "#7E22CE", "#A21CAF", "#BE185D", "#E11D48", "#DC2626", "#EA580C", "#D97706",
"#CA8A04", "#65A30D", "#16A34A", "#059669", "#0D9488", "#0891B2", "#0284C7", "#2563EB", "#4F46E5", "#7C3AED",
"#9333EA", "#C026D3", "#DB2777", "#F43F5E", "#EF4444", "#F97316", "#F59E0B", "#EAB308", "#84CC16", "#22C55E",
"#10B981", "#14B8A6", "#06B6D4", "#0EA5E9", "#3B82F6", "#6366F1", "#8B5CF6", "#A855F7", "#D946EF", "#EC4899",
"#FB7185", "#F87171", "#FB923C", "#FBBF24", "#FACC15", "#A3E635", "#4ADE80", "#34D399", "#2DD4BF", "#22D3EE",
"#38BDF8", "#60A5FA", "#818CF8", "#A78BFA", "#C084FC", "#E879F9", "#F472B6", "#FDA4AF", "#FCA5A5", "#FDBA74",
"#FCD34D", "#FDE047", "#BEF264", "#86EFAC", "#6EE7B7", "#5EEAD4", "#67E8F9", "#7DD3FC", "#93C5FD", "#A5B4FC",
"#C4B5FD", "#D8B4FE", "#F0ABFC", "#F9A8D4", "#A16207", "#9A3412", "#7C2D12", "#6F1D1B", "#7F1D1D", "#881337",
"#831843", "#701A75", "#581C87", "#312E81", "#1E3A8A", "#1D4ED8", "#155E75", "#134E4A", "#14532D", "#3F6212",
"#365314", "#3F3F46", "#52525B", "#57534E", "#44403C", "#78716C", "#6B7280", "#4B5563", "#374151", "#1F2937",
"#A16207", "#B45309", "#C2410C", "#9F1239", "#BE123C", "#C026D3", "#7E22CE", "#6D28D9", "#4338CA", "#1D4ED8"
];
public static IReadOnlyList<string> GetFlatColorPalette() => FlatUiColorPalette;
public static IReadOnlyList<string> GetFlatColorPalette() => CalendarColorPalette.GetColors();
public static string GenerateFlatColorHex() => GetDistinctFlatColorHex(Array.Empty<string>());
public static string GetDistinctFlatColorHex(IEnumerable<string> usedColors)
{
var used = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (usedColors != null)
var palette = CalendarColorPalette.GetColors();
var distinctColor = CalendarColorPalette.GetDistinctColor(usedColors);
if (palette.Contains(distinctColor))
{
foreach (var color in usedColors)
{
if (TryNormalizeHexColor(color, out var normalized))
{
used.Add(normalized);
}
}
return distinctColor;
}
foreach (var color in FlatUiColorPalette)
{
if (!used.Contains(color))
{
return color;
}
}
var candidate = AdjustColor(palette[0], 1);
var attempt = 0;
while (attempt < 500)
{
var baseColor = FlatUiColorPalette[attempt % FlatUiColorPalette.Length];
var cycle = (attempt / FlatUiColorPalette.Length) + 1;
var candidate = AdjustColor(baseColor, cycle);
if (!used.Contains(candidate))
{
return candidate;
}
attempt++;
}
return "#5C7A8A";
}
public static string ToHexString(this Color c) => $"#{c.R:X2}{c.G:X2}{c.B:X2}";
public static string ToRgbString(this Color c) => $"RGB({c.R}, {c.G}, {c.B})";
private static bool TryNormalizeHexColor(string value, out string normalized)
{
normalized = null;
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
var color = value.Trim();
if (color.StartsWith('#'))
{
color = color[1..];
}
if (color.Length != 6)
{
return false;
}
if (!int.TryParse(color, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out _))
{
return false;
}
normalized = $"#{color.ToUpperInvariant()}";
return true;
}
private static string AdjustColor(string hexColor, int cycle)
{
var color = ColorTranslator.FromHtml(hexColor);
@@ -331,6 +331,7 @@ public sealed partial class ImagePreviewControl : PersonPicture
if (!IsActiveRefresh(refreshVersion, cancellationToken))
return;
DisplayName = string.Empty;
Initials = string.Empty;
ProfilePicture = bitmapImage;
}).ConfigureAwait(false);
@@ -188,7 +188,7 @@ public class NavigationService : NavigationServiceBase, INavigationService
// Update the application mode in state persistence service
_statePersistanceService.ApplicationMode = mode;
_statePersistanceService.CoreWindowTitle = mode == WinoApplicationMode.Calendar
_statePersistanceService.AppModeTitle = mode == WinoApplicationMode.Calendar
? "Wino Calendar"
: "Wino Mail";
@@ -13,6 +13,7 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
private const string OpenPaneLengthKey = nameof(OpenPaneLengthKey);
private const string MailListPaneLengthKey = nameof(MailListPaneLengthKey);
private const string AppModeTitleKey = nameof(AppModeTitle);
private readonly IConfigurationService _configurationService;
@@ -22,6 +23,7 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
_openPaneLength = _configurationService.Get(OpenPaneLengthKey, 320d);
_mailListPaneLength = _configurationService.Get(MailListPaneLengthKey, 420d);
_appModeTitle = _configurationService.Get(AppModeTitleKey, "Wino Mail");
_calendarDisplayType = EnsureValidCalendarDisplayType(_configurationService.Get(nameof(CalendarDisplayType), CalendarDisplayType.Week));
_dayDisplayCount = _configurationService.Get(nameof(DayDisplayCount), 1);
@@ -144,6 +146,21 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
}
}
private string _appModeTitle;
public string AppModeTitle
{
get => _appModeTitle;
set
{
if (SetProperty(ref _appModeTitle, value))
{
_configurationService.Set(AppModeTitleKey, value);
UpdateAppWindowTitle();
}
}
}
private double _openPaneLength;
public double OpenPaneLength
{
@@ -199,10 +216,15 @@ public class StatePersistenceService : ObservableObject, IStatePersistanceServic
}
private void UpdateAppCoreWindowTitle()
{
OnPropertyChanged(nameof(CoreWindowTitle));
}
private void UpdateAppWindowTitle()
{
if (WinoApplication.MainWindow != null)
{
WinoApplication.MainWindow.Title = CoreWindowTitle;
WinoApplication.MainWindow.Title = AppModeTitle;
}
}
+3 -2
View File
@@ -26,7 +26,7 @@
<Grid Grid.RowSpan="2" Background="{ThemeResource WinoApplicationBackgroundColor}" />
<TitleBar
x:Name="ShellTitleBar"
Title="{x:Bind StatePersistanceService.CoreWindowTitle, Mode=OneWay}"
Title="{x:Bind StatePersistanceService.AppModeTitle, Mode=OneWay}"
Margin="-2"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
@@ -34,7 +34,8 @@
Background="Transparent"
IsBackButtonVisible="{x:Bind StatePersistanceService.IsBackButtonVisible, Mode=OneWay}"
IsPaneToggleButtonVisible="True"
PaneToggleRequested="PaneButtonClicked">
PaneToggleRequested="PaneButtonClicked"
Subtitle="{x:Bind StatePersistanceService.CoreWindowTitle, Mode=OneWay}">
<TitleBar.RightHeader>
<StackPanel Orientation="Horizontal" Spacing="8">
<!-- Sync Status Button -->
+8 -1
View File
@@ -68,7 +68,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
ExitWinoCommand = new RelayCommand(ForceClose);
this.SetIcon("Assets/Wino_Icon.ico");
Title = "Wino Mail";
Title = StatePersistanceService.AppModeTitle;
SystemTrayIcon.ForceCreate();
}
@@ -122,6 +122,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
AppModeSegmentedControl.SelectedIndex = targetMode == WinoApplicationMode.Mail ? 0 : 1;
_isApplyingActivationMode = false;
StatePersistanceService.AppModeTitle = GetAppModeTitle(targetMode);
NavigationService.ChangeApplicationMode(targetMode);
}
@@ -317,6 +318,7 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
AppModeSegmentedControl.SelectedIndex = mode == WinoApplicationMode.Mail ? 0 : 1;
_isApplyingActivationMode = false;
StatePersistanceService.AppModeTitle = GetAppModeTitle(mode);
NavigationService.ChangeApplicationMode(mode);
RestoreFromTray();
}
@@ -371,4 +373,9 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow,
_currentMode = selectedMode;
NavigationService.ChangeApplicationMode(selectedMode);
}
private static string GetAppModeTitle(WinoApplicationMode mode)
=> mode == WinoApplicationMode.Calendar
? "Wino Calendar"
: "Wino Mail";
}
@@ -2,14 +2,14 @@
x:Class="Wino.Views.AccountDetailsPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:accounts="using:Wino.Core.Domain.Models.Accounts"
xmlns:abstract="using:Wino.Views.Abstract"
xmlns:accounts="using:Wino.Core.Domain.Models.Accounts"
xmlns:calendar="using:Wino.Core.Domain.Entities.Calendar"
xmlns:controls="using:CommunityToolkit.WinUI.Controls"
xmlns:controls1="using:Wino.Controls"
xmlns:coreControls="using:Wino.Mail.WinUI.Controls"
xmlns:data="using:Wino.Core.ViewModels.Data"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:data="using:Wino.Core.ViewModels.Data"
xmlns:domain="using:Wino.Core.Domain"
xmlns:folders="using:Wino.Core.Domain.Models.Folders"
xmlns:helpers="using:Wino.Helpers"
@@ -81,13 +81,9 @@
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<controls:SettingsExpander
Description="{x:Bind ViewModel.Address, Mode=OneWay}"
Header="{x:Bind ViewModel.AccountName, Mode=OneWay}">
<controls:SettingsExpander Description="{x:Bind ViewModel.Address, Mode=OneWay}" Header="{x:Bind ViewModel.AccountName, Mode=OneWay}">
<controls:SettingsExpander.HeaderIcon>
<BitmapIcon
ShowAsMonochrome="False"
UriSource="{x:Bind ViewModel.ProviderIconPath, Mode=OneWay}" />
<BitmapIcon ShowAsMonochrome="False" UriSource="{x:Bind ViewModel.ProviderIconPath, Mode=OneWay}" />
</controls:SettingsExpander.HeaderIcon>
<controls:SettingsExpander.Items>
<controls:SettingsCard Description="{x:Bind domain:Translator.AccountEditDialog_Message}" Header="{x:Bind domain:Translator.AccountDetailsPage_Title}">
@@ -132,6 +128,7 @@
<Button
Grid.Row="1"
Width="100"
HorizontalAlignment="Right"
Command="{x:Bind ViewModel.ResetColorCommand}"
Content="{x:Bind domain:Translator.Buttons_Reset}" />
@@ -310,6 +307,7 @@
<SymbolIcon Symbol="Save" />
</controls:SettingsCard.HeaderIcon>
<Button
Width="100"
HorizontalAlignment="Right"
Command="{x:Bind ViewModel.SaveChangesCommand}"
Content="{x:Bind domain:Translator.Buttons_Save}"
@@ -321,6 +319,7 @@
<SymbolIcon Symbol="Delete" />
</controls:SettingsCard.HeaderIcon>
<Button
Width="100"
Background="Red"
Command="{x:Bind ViewModel.DeleteAccountCommand}"
Content="{x:Bind domain:Translator.Buttons_Delete}" />
@@ -63,7 +63,9 @@
HorizontalContentAlignment="Left"
Style="{StaticResource DefaultButtonStyle}">
<Button.Flyout>
<Flyout Placement="BottomEdgeAlignedLeft">
<Flyout
x:Name="CalendarSelectionFlyout"
Placement="BottomEdgeAlignedLeft">
<ScrollViewer MaxHeight="360">
<ItemsControl ItemsSource="{x:Bind ViewModel.AvailableCalendarGroups, Mode=OneWay}">
<ItemsControl.ItemTemplate>
@@ -155,6 +155,7 @@ public sealed partial class CalendarEventComposePage : CalendarEventComposePageA
if (e.ClickedItem is AccountCalendarViewModel calendar)
{
ViewModel.SelectedCalendar = calendar;
CalendarSelectionFlyout.Hide();
}
}
+71 -22
View File
@@ -33,44 +33,93 @@
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image
Width="96"
Height="96"
VerticalAlignment="Center"
Source="ms-appx:///Assets/AppEntries/MailAssets/Square150x150Logo.scale-100.png"
Stretch="Uniform" />
<!-- App Info -->
<StackPanel
<Grid
Grid.Column="1"
Margin="20,0,0,0"
Margin="8,0,0,0"
VerticalAlignment="Center"
Spacing="4">
ColumnSpacing="12">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="12">
<Image
Width="56"
Height="56"
VerticalAlignment="Top"
Source="ms-appx:///Assets/AppEntries/MailAssets/Square150x150Logo.scale-100.png"
Stretch="Uniform" />
<StackPanel VerticalAlignment="Center">
<TextBlock
VerticalAlignment="Center"
Style="{StaticResource TitleTextBlockStyle}"
Text="Wino Mail" />
<TextBlock
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource BodyTextBlockStyle}"
Text="{x:Bind domain:Translator.SettingsOptions_HeroDescription}" />
<TextBlock
Margin="0,2,0,0"
VerticalAlignment="Top"
Foreground="{ThemeResource TextFillColorTertiaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind ViewModel.VersionText, Mode=OneWay}" />
</StackPanel>
</StackPanel>
<StackPanel
Margin="0,8,0,0"
Grid.RowSpan="2"
Grid.Column="2"
Margin="0,12,0,0"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="8">
<HyperlinkButton
Content="{x:Bind ViewModel.WebsiteUrl, Mode=OneWay}"
NavigateUri="{x:Bind ViewModel.WebsiteUrl, Mode=OneWay}" />
<HyperlinkButton
Content="{x:Bind domain:Translator.SettingsPaypal_Title}"
NavigateUri="{x:Bind ViewModel.PaypalUrl, Mode=OneWay}" />
Spacing="12">
<Button
Command="{x:Bind ViewModel.NavigateExternalCommand}"
CommandParameter="{x:Bind ViewModel.PaypalUrl, Mode=OneWay}"
Style="{StaticResource DefaultButtonStyle}"
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsPaypal_Title}">
<Viewbox Width="18" Height="18">
<Path
Data="M385.52,51.09C363.84,26.52,324.71,16,274.63,16H129.25a20.75,20.75,0,0,0-20.54,17.48l-60.55,382a12.43,12.43,0,0,0,10.39,14.22,12.58,12.58,0,0,0,1.94.15h89.76l22.54-142.29-.7,4.46a20.67,20.67,0,0,1,20.47-17.46h42.65c83.77,0,149.36-33.86,168.54-131.8.57-2.9,1.05-5.72,1.49-8.48h0C410.94,98.06,405.19,73.41,385.52,51.09Z"
Fill="{ThemeResource TextFillColorPrimaryBrush}"
Stretch="Uniform" />
</Viewbox>
</Button>
<Button
Grid.Column="1"
Command="{x:Bind ViewModel.NavigateExternalCommand}"
CommandParameter="{x:Bind ViewModel.GitHubUrl, Mode=OneWay}"
Style="{StaticResource DefaultButtonStyle}"
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsAboutGithub_Title}">
<StackPanel HorizontalAlignment="Center" Spacing="6">
<Viewbox Width="18" Height="18">
<Path
Data="m 12.2135 0 c -6.7538 0 -12.2135 5.5 -12.2135 12.3042 c 0 5.439 3.4983 10.043 8.3513 11.6725 c 0.6067 0.1225 0.829 -0.2647 0.829 -0.5905 c 0 -0.2853 -0.02 -1.263 -0.02 -2.2817 c -3.3975 0.7335 -4.105 -1.4668 -4.105 -1.4668 c -0.546 -1.426 -1.355 -1.7925 -1.355 -1.7925 c -1.112 -0.7538 0.081 -0.7538 0.081 -0.7538 c 1.2335 0.0815 1.8807 1.263 1.8807 1.263 c 1.0918 1.874 2.851 1.3445 3.5587 1.0185 c 0.101 -0.7945 0.4247 -1.3445 0.7685 -1.65 c -2.7097 -0.2853 -5.5607 -1.3445 -5.5607 -6.0708 c 0 -1.3445 0.485 -2.4445 1.2535 -3.3 c -0.1212 -0.3055 -0.546 -1.5687 0.1215 -3.2595 c 0 0 1.0313 -0.326 3.3565 1.263 a 11.7425 11.7425 90 0 1 3.0535 -0.4075 c 1.0313 0 2.0825 0.1428 3.0533 0.4075 c 2.3255 -1.589 3.3567 -1.263 3.3567 -1.263 c 0.6675 1.6908 0.2425 2.954 0.1212 3.2595 c 0.7888 0.8555 1.2538 1.9555 1.2538 3.3 c 0 4.7263 -2.851 5.765 -5.581 6.0708 c 0.445 0.387 0.829 1.1202 0.829 2.2815 c 0 1.65 -0.02 2.9743 -0.02 3.3815 c 0 0.326 0.2225 0.7132 0.829 0.591 c 4.853 -1.63 8.3513 -6.2338 8.3513 -11.6728 c 0.02 -6.8043 -5.4598 -12.3043 -12.1933 -12.3043 z"
Fill="{ThemeResource TextFillColorPrimaryBrush}"
Stretch="Uniform" />
</Viewbox>
</StackPanel>
</Button>
<Button
Grid.Column="2"
Command="{x:Bind ViewModel.NavigateExternalCommand}"
CommandParameter="Store"
Style="{StaticResource AccentButtonStyle}"
ToolTipService.ToolTip="{x:Bind domain:Translator.SettingsStore_Title}">
<Viewbox Width="18" Height="18">
<Path
Data="F1 M 19.003906 3.251953 L 19.003906 15.947266 C 19.003906 16.357422 18.920898 16.748047 18.754883 17.119141 C 18.588867 17.490234 18.367512 17.814127 18.09082 18.09082 C 17.814127 18.367514 17.490234 18.588867 17.119141 18.754883 C 16.748047 18.920898 16.357422 19.003906 15.947266 19.003906 L 3.056641 19.003906 C 2.646484 19.003906 2.255859 18.920898 1.884766 18.754883 C 1.513672 18.588867 1.189779 18.367514 0.913086 18.09082 C 0.636393 17.814127 0.415039 17.490234 0.249023 17.119141 C 0.083008 16.748047 0 16.357422 0 15.947266 L 0 3.251953 C 0 3.076172 0.032552 2.913412 0.097656 2.763672 C 0.16276 2.613934 0.252279 2.482098 0.366211 2.368164 C 0.480143 2.254232 0.611979 2.164715 0.761719 2.099609 C 0.911458 2.034506 1.074219 2.001953 1.25 2.001953 L 4.003906 2.001953 L 4.003906 0.996094 C 4.003906 0.859375 4.029948 0.730795 4.082031 0.610352 C 4.134114 0.48991 4.205729 0.384115 4.296875 0.292969 C 4.388021 0.201824 4.493815 0.130209 4.614258 0.078125 C 4.7347 0.026043 4.863281 0 5 0 L 14.003906 0 C 14.140624 0 14.269205 0.026043 14.389648 0.078125 C 14.510091 0.130209 14.615885 0.201824 14.707031 0.292969 C 14.798177 0.384115 14.869791 0.48991 14.921875 0.610352 C 14.973957 0.730795 14.999999 0.859375 15 0.996094 L 15 2.001953 L 17.753906 2.001953 C 17.923176 2.001953 18.084309 2.034506 18.237305 2.099609 C 18.390299 2.164715 18.523762 2.254232 18.637695 2.368164 C 18.751627 2.482098 18.841145 2.615561 18.90625 2.768555 C 18.971354 2.921551 19.003906 3.082684 19.003906 3.251953 Z M 14.003906 0.996094 L 5 0.996094 L 5 2.001953 L 14.003906 2.001953 Z M 5 10 L 9.003906 10 L 9.003906 5.996094 L 5 5.996094 Z M 10 10 L 14.003906 10 L 14.003906 5.996094 L 10 5.996094 Z M 5 15 L 9.003906 15 L 9.003906 10.996094 L 5 10.996094 Z M 10 15 L 14.003906 15 L 14.003906 10.996094 L 10 10.996094 Z "
Fill="{ThemeResource AccentTextFillColorPrimaryBrush}"
Stretch="Uniform" />
</Viewbox>
</Button>
</StackPanel>
</Grid>
</Grid>
<!-- Account Management Card -->
<controls:SettingsCard
+7 -22
View File
@@ -12,6 +12,7 @@ using Wino.Core.Domain.Entities.Shared;
using Wino.Core.Domain.Enums;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models.Accounts;
using Wino.Core.Domain.Misc;
using Wino.Messaging.Client.Calendar;
using Wino.Messaging.Client.Accounts;
using Wino.Messaging.UI;
@@ -20,22 +21,6 @@ namespace Wino.Services;
public class AccountService : BaseDatabaseService, IAccountService
{
private static readonly string[] DefaultCalendarFlatColors =
[
"#B91C1C",
"#15803D",
"#0E7490",
"#1D4ED8",
"#7C3AED",
"#C026D3",
"#EC4899",
"#F97316",
"#EAB308",
"#22C55E",
"#06B6D4",
"#60A5FA"
];
public IAuthenticator ExternalAuthenticationAuthenticator { get; set; }
private readonly ISignatureService _signatureService;
@@ -657,20 +642,20 @@ public class AccountService : BaseDatabaseService, IAccountService
IsExtended = true,
RemoteCalendarId = string.Empty,
TimeZone = string.Empty,
BackgroundColorHex = GetDefaultCalendarFlatColor(accountId),
BackgroundColorHex = await GetNextDistinctCalendarColorAsync().ConfigureAwait(false),
TextColorHex = "#FFFFFF"
};
await Connection.InsertAsync(localCalendar, typeof(AccountCalendar)).ConfigureAwait(false);
}
private static string GetDefaultCalendarFlatColor(Guid accountId)
private async Task<string> GetNextDistinctCalendarColorAsync()
{
var bytes = accountId.ToByteArray();
var hash = BitConverter.ToUInt32(bytes, 0);
var index = (int)(hash % (uint)DefaultCalendarFlatColors.Length);
var usedColors = await Connection.Table<AccountCalendar>()
.ToListAsync()
.ConfigureAwait(false);
return DefaultCalendarFlatColors[index];
return CalendarColorPalette.GetDistinctColor(usedColors.Select(a => a.BackgroundColorHex));
}
public async Task UpdateAccountOrdersAsync(Dictionary<Guid, int> accountIdOrderPair)