Some shell/ themes improvements

This commit is contained in:
Burak Kaan Köse
2025-09-29 19:09:48 +02:00
parent f6bf080c9e
commit 2bec513d2c
7 changed files with 84 additions and 85 deletions
@@ -6,7 +6,7 @@ using Wino.Core.Domain.Models.Reader;
namespace Wino.Core.Domain.Interfaces; namespace Wino.Core.Domain.Interfaces;
public interface IPreferencesService: INotifyPropertyChanged public interface IPreferencesService : INotifyPropertyChanged
{ {
/// <summary> /// <summary>
/// When any of the preferences are changed. /// When any of the preferences are changed.
@@ -6,6 +6,7 @@ namespace Wino.Core.WinUI.Interfaces;
public interface IWinoShellWindow public interface IWinoShellWindow
{ {
void HandleAppActivation(LaunchActivatedEventArgs args); void HandleAppActivation(LaunchActivatedEventArgs args);
Microsoft.UI.Xaml.Controls.TitleBar GetTitleBar(); TitleBar GetTitleBar();
Frame GetMainFrame(); Frame GetMainFrame();
FrameworkElement GetRootContent();
} }
+41 -50
View File
@@ -7,10 +7,9 @@ using System.Runtime.InteropServices.WindowsRuntime;
using System.Text.Json; using System.Text.Json;
using System.Threading.Tasks; using System.Threading.Tasks;
using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.Mvvm.Messaging;
using CommunityToolkit.WinUI;
using CommunityToolkit.WinUI.Helpers; using CommunityToolkit.WinUI.Helpers;
using Microsoft.UI;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup; using Microsoft.UI.Xaml.Markup;
using Microsoft.UI.Xaml.Media; using Microsoft.UI.Xaml.Media;
using Windows.Storage; using Windows.Storage;
@@ -23,6 +22,7 @@ using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.Personalization; using Wino.Core.Domain.Models.Personalization;
using Wino.Core.WinUI; using Wino.Core.WinUI;
using Wino.Core.WinUI.Extensions; using Wino.Core.WinUI.Extensions;
using Wino.Core.WinUI.Interfaces;
using Wino.Core.WinUI.Models.Personalization; using Wino.Core.WinUI.Models.Personalization;
using Wino.Core.WinUI.Services; using Wino.Core.WinUI.Services;
using Wino.Messaging.Client.Shell; using Wino.Messaging.Client.Shell;
@@ -44,8 +44,6 @@ public class ThemeService : IThemeService
private static string _snowflakeThemeId = "e143ddde-2e28-4846-9d98-dad63d6505f1"; private static string _snowflakeThemeId = "e143ddde-2e28-4846-9d98-dad63d6505f1";
private static string _gardenThemeId = "698e4466-f88c-4799-9c61-f0ea1308ed49"; private static string _gardenThemeId = "698e4466-f88c-4799-9c61-f0ea1308ed49";
private Frame mainApplicationFrame = null;
public event EventHandler<ApplicationElementTheme> ElementThemeChanged; public event EventHandler<ApplicationElementTheme> ElementThemeChanged;
public event EventHandler<string> AccentColorChanged; public event EventHandler<string> AccentColorChanged;
@@ -89,16 +87,15 @@ public class ThemeService : IThemeService
{ {
get get
{ {
if (mainApplicationFrame == null) return ApplicationElementTheme.Default; return GetShellRootContent().RequestedTheme.ToWinoElementTheme();
//if (mainApplicationFrame == null) return ApplicationElementTheme.Default;
return mainApplicationFrame.RequestedTheme.ToWinoElementTheme(); //return mainApplicationFrame.RequestedTheme.ToWinoElementTheme();
} }
set set
{ {
if (mainApplicationFrame == null) GetShellRootContent().RequestedTheme = value.ToWindowsElementTheme();
return; // mainApplicationFrame.RequestedTheme = value.ToWindowsElementTheme();
mainApplicationFrame.RequestedTheme = value.ToWindowsElementTheme();
_configurationService.Set(UnderlyingThemeService.SelectedAppThemeKey, value); _configurationService.Set(UnderlyingThemeService.SelectedAppThemeKey, value);
@@ -121,10 +118,13 @@ public class ThemeService : IThemeService
_configurationService.Set(CurrentApplicationThemeKey, value); _configurationService.Set(CurrentApplicationThemeKey, value);
_ = mainApplicationFrame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, async () => if (WinoApplication.MainWindow != null)
{ {
await ApplyCustomThemeAsync(false); WinoApplication.MainWindow.DispatcherQueue.TryEnqueue(async () =>
}); {
await ApplyCustomThemeAsync(false);
});
}
} }
} }
@@ -154,17 +154,14 @@ public class ThemeService : IThemeService
} }
} }
public FrameworkElement GetShellRootContent() => (WinoApplication.MainWindow as IWinoShellWindow)?.GetRootContent() ?? throw new Exception("No root content found");
private bool isInitialized = false;
public async Task InitializeAsync() public async Task InitializeAsync()
{ {
// Already initialized. There is no need. // Already initialized. There is no need.
if (mainApplicationFrame != null) if (isInitialized) return;
return;
// Save reference as this might be null when the user is in another app
mainApplicationFrame = WinoApplication.MainWindow.Content as Frame;
if (mainApplicationFrame == null) return;
RootTheme = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default); RootTheme = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default);
AccentColor = _configurationService.Get(AccentColorKey, string.Empty); AccentColor = _configurationService.Get(AccentColorKey, string.Empty);
@@ -177,56 +174,48 @@ public class ThemeService : IThemeService
// Registering to color changes, thus we notice when user changes theme system wide // Registering to color changes, thus we notice when user changes theme system wide
uiSettings.ColorValuesChanged -= UISettingsColorChanged; uiSettings.ColorValuesChanged -= UISettingsColorChanged;
uiSettings.ColorValuesChanged += UISettingsColorChanged; uiSettings.ColorValuesChanged += UISettingsColorChanged;
isInitialized = true;
} }
private void NotifyThemeUpdate() private void NotifyThemeUpdate()
{ {
if (mainApplicationFrame == null || mainApplicationFrame.Dispatcher == null) return; if (GetShellRootContent() is not UIElement rootContent) return;
_ = mainApplicationFrame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () => _ = rootContent.DispatcherQueue.EnqueueAsync(() =>
{ {
ElementThemeChanged?.Invoke(this, RootTheme); ElementThemeChanged?.Invoke(this, RootTheme);
WeakReferenceMessenger.Default.Send(new ApplicationThemeChanged(_underlyingThemeService.IsUnderlyingThemeDark())); WeakReferenceMessenger.Default.Send(new ApplicationThemeChanged(_underlyingThemeService.IsUnderlyingThemeDark()));
}); }, Microsoft.UI.Dispatching.DispatcherQueuePriority.High);
} }
private void UISettingsColorChanged(UISettings sender, object args) private void UISettingsColorChanged(UISettings sender, object args)
{ {
// Make sure we have a reference to our window so we dispatch a UI change // TODO: Buggy.
if (mainApplicationFrame != null) //GetShellRootContent().DispatcherQueue.TryEnqueue(() =>
{ //{
// Dispatch on UI thread so that we have a current appbar to access and change // UpdateSystemCaptionButtonColors();
//});
_ = mainApplicationFrame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, () =>
{
UpdateSystemCaptionButtonColors();
var accentColor = sender.GetColorValue(UIColorType.Accent);
//AccentColorChangedBySystem?.Invoke(this, accentColor.ToHex());
});
}
NotifyThemeUpdate(); NotifyThemeUpdate();
} }
public void UpdateSystemCaptionButtonColors() public void UpdateSystemCaptionButtonColors()
{ {
if (mainApplicationFrame == null) return; GetShellRootContent().DispatcherQueue.TryEnqueue(() =>
_ = mainApplicationFrame.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{ {
ApplicationViewTitleBar titleBar = ApplicationView.GetForCurrentView().TitleBar; Debug.WriteLine("TODO: Updating caption button colors");
if (titleBar == null) return; // var titleBar = (WinoApplication.MainWindow as IWinoShellWindow).GetTitleBar();
if (_underlyingThemeService.IsUnderlyingThemeDark()) //if (_underlyingThemeService.IsUnderlyingThemeDark())
{ //{
titleBar.ButtonForegroundColor = Colors.White; // titleBar.ButtonForegroundColor = Colors.White;
} //}
else //else
{ //{
titleBar.ButtonForegroundColor = Colors.Black; // titleBar.ButtonForegroundColor = Colors.Black;
} //}
}); });
} }
@@ -257,6 +246,8 @@ public class ThemeService : IThemeService
private void RefreshThemeResource() private void RefreshThemeResource()
{ {
var mainApplicationFrame = GetShellRootContent();
if (mainApplicationFrame == null) return; if (mainApplicationFrame == null) return;
if (mainApplicationFrame.RequestedTheme == ElementTheme.Dark) if (mainApplicationFrame.RequestedTheme == ElementTheme.Dark)
+1 -30
View File
@@ -356,22 +356,9 @@
<Grid <Grid
x:Name="RootGrid" x:Name="RootGrid"
Padding="0" Padding="0"
Background="{ThemeResource WinoApplicationBackgroundColor}"
ColumnSpacing="0" ColumnSpacing="0"
RowSpacing="0"> RowSpacing="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="48" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid
Grid.RowSpan="2"
Grid.ColumnSpan="2"
Background="{ThemeResource WinoApplicationBackgroundColor}"
IsHitTestVisible="False" />
<muxc:NavigationView <muxc:NavigationView
x:Name="navigationView" x:Name="navigationView"
@@ -452,21 +439,5 @@
</Grid> </Grid>
</muxc:NavigationView> </muxc:NavigationView>
<!--<coreControls:WinoAppTitleBar
x:Name="RealAppBar"
Grid.ColumnSpan="2"
BackButtonClicked="BackButtonClicked"
Canvas.ZIndex="150"
ConnectionStatus="{x:Bind ViewModel.ActiveConnectionStatus, Mode=OneWay}"
CoreWindowText="{x:Bind ViewModel.StatePersistenceService.CoreWindowTitle, Mode=OneWay}"
IsBackButtonVisible="{x:Bind ViewModel.StatePersistenceService.IsBackButtonVisible, Mode=OneWay}"
IsDragArea="True"
IsNavigationPaneOpen="{x:Bind navigationView.IsPaneOpen, Mode=TwoWay}"
IsReaderNarrowed="{x:Bind ViewModel.StatePersistenceService.IsReaderNarrowed, Mode=OneWay}"
NavigationViewDisplayMode="{x:Bind navigationView.DisplayMode, Mode=OneWay}"
OpenPaneLength="{x:Bind ViewModel.StatePersistenceService.OpenPaneLength, Mode=OneWay}"
ReadingPaneLength="{x:Bind ViewModel.StatePersistenceService.MailListPaneLength, Mode=OneWay}"
ReconnectCommand="{x:Bind ViewModel.ReconnectServerCommand}"
SystemReserved="180" />-->
</Grid> </Grid>
</abstract:AppShellAbstract> </abstract:AppShellAbstract>
+1 -1
View File
@@ -130,7 +130,7 @@ public sealed partial class AppShell : AppShellAbstract,
public async void Receive(AccountMenuItemExtended message) public async void Receive(AccountMenuItemExtended message)
{ {
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.High, async () => await DispatcherQueue.EnqueueAsync(async () =>
{ {
if (message.FolderId == default) return; if (message.FolderId == default) return;
+12 -2
View File
@@ -11,6 +11,7 @@
mc:Ignorable="d"> mc:Ignorable="d">
<winuiex:WindowEx.SystemBackdrop> <winuiex:WindowEx.SystemBackdrop>
<!-- TODO: Reach to ThemeService changes. -->
<MicaBackdrop /> <MicaBackdrop />
</winuiex:WindowEx.SystemBackdrop> </winuiex:WindowEx.SystemBackdrop>
@@ -20,8 +21,17 @@
<RowDefinition Height="*" /> <RowDefinition Height="*" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<TitleBar x:Name="ShellTitleBar" IsBackButtonVisible="True" /> <TitleBar
x:Name="ShellTitleBar"
Title="{x:Bind StatePersistanceService.CoreWindowTitle, Mode=OneWay}"
BackRequested="BackButtonClicked"
IsBackButtonVisible="{x:Bind StatePersistanceService.IsBackButtonVisible, Mode=OneWay}"
IsPaneToggleButtonVisible="True"
PaneToggleRequested="PaneButtonClicked" />
<Frame x:Name="MainShellFrame" Grid.Row="1" /> <Frame
x:Name="MainShellFrame"
Grid.Row="1"
Navigated="MainFrameNavigated" />
</Grid> </Grid>
</winuiex:WindowEx> </winuiex:WindowEx>
+26
View File
@@ -1,6 +1,12 @@
using System;
using CommunityToolkit.Mvvm.Messaging;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.UI.Xaml; using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls;
using Wino.Core.Domain.Interfaces;
using Wino.Core.WinUI;
using Wino.Core.WinUI.Interfaces; using Wino.Core.WinUI.Interfaces;
using Wino.Messaging.Client.Mails;
using Wino.Views; using Wino.Views;
using WinUIEx; using WinUIEx;
@@ -8,10 +14,15 @@ namespace Wino.Mail.WinUI;
public sealed partial class ShellWindow : WindowEx, IWinoShellWindow public sealed partial class ShellWindow : WindowEx, IWinoShellWindow
{ {
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 ShellWindow() public ShellWindow()
{ {
InitializeComponent(); InitializeComponent();
MinWidth = 420;
MinHeight = 420;
ConfigureTitleBar(); ConfigureTitleBar();
} }
@@ -30,4 +41,19 @@ public sealed partial class ShellWindow : WindowEx, IWinoShellWindow
public Microsoft.UI.Xaml.Controls.TitleBar GetTitleBar() => ShellTitleBar; public Microsoft.UI.Xaml.Controls.TitleBar GetTitleBar() => ShellTitleBar;
public Frame GetMainFrame() => MainShellFrame; public Frame GetMainFrame() => MainShellFrame;
public FrameworkElement GetRootContent() => Content as Grid ?? throw new Exception("RootContent is not a Grid or empty.");
private void BackButtonClicked(Microsoft.UI.Xaml.Controls.TitleBar sender, object args)
{
WeakReferenceMessenger.Default.Send(new ClearMailSelectionsRequested());
WeakReferenceMessenger.Default.Send(new DisposeRenderingFrameRequested());
}
private void MainFrameNavigated(object sender, Microsoft.UI.Xaml.Navigation.NavigationEventArgs e) => ShellTitleBar.Content = (e.Content as BasePage).ShellContent;
private void PaneButtonClicked(Microsoft.UI.Xaml.Controls.TitleBar sender, object args)
{
PreferencesService.IsNavigationPaneOpened = !PreferencesService.IsNavigationPaneOpened;
}
} }