Files
marechai/Marechai.App/Services/ColorThemeService.cs

148 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Windows.Storage;
using Microsoft.UI.Xaml;
using Uno.Extensions.Toolkit;
namespace Marechai.App.Services;
public interface IColorThemeService
{
string CurrentColorTheme { get; }
IReadOnlyList<string> AvailableColorThemes { get; }
void ApplyColorTheme(string themeName);
void SetThemeService(IThemeService themeService);
void ReapplyCurrentTheme();
}
public class ColorThemeService : IColorThemeService
{
private const string COLOR_THEME_KEY = "ColorTheme";
private const string DEFAULT_THEME = "Default";
private IThemeService _themeService;
public ColorThemeService()
{
LoadSavedTheme();
}
public string CurrentColorTheme { get; private set; } = DEFAULT_THEME;
public IReadOnlyList<string> AvailableColorThemes => new List<string>
{
DEFAULT_THEME,
"Windows311"
};
public void SetThemeService(IThemeService themeService)
{
_themeService = themeService;
// Reapply the current theme now that we have the theme service
if(CurrentColorTheme != DEFAULT_THEME) ReapplyCurrentTheme();
}
public void ReapplyCurrentTheme()
{
// Force refresh of the current theme
ApplyColorTheme(CurrentColorTheme);
}
public void ApplyColorTheme(string themeName)
{
if(!AvailableColorThemes.Contains(themeName)) return;
CurrentColorTheme = themeName;
// Save preference
try
{
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
localSettings.Values[COLOR_THEME_KEY] = themeName;
}
catch
{
// Silently fail
}
// Apply the theme by rebuilding merged dictionaries
Application app = Application.Current;
if(app?.Resources == null) return;
// Store the existing merged dictionaries (except color overrides)
var existingDictionaries = app.Resources.MergedDictionaries
.Where(d => d.Source?.OriginalString?.Contains("ColorPaletteOverride") != true)
.ToList();
// Clear all merged dictionaries
app.Resources.MergedDictionaries.Clear();
// Re-add the existing dictionaries
foreach(ResourceDictionary dict in existingDictionaries) app.Resources.MergedDictionaries.Add(dict);
// Add the new color theme if not default
if(themeName != DEFAULT_THEME)
{
var newDictionary = new ResourceDictionary
{
Source = new Uri("ms-appx:///Styles/ColorPaletteOverride.xaml")
};
app.Resources.MergedDictionaries.Add(newDictionary);
}
// Force UI refresh by toggling the theme temporarily
ForceThemeRefresh();
}
private void LoadSavedTheme()
{
try
{
ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings;
if(localSettings.Values.ContainsKey(COLOR_THEME_KEY))
{
var savedTheme = localSettings.Values[COLOR_THEME_KEY] as string;
if(!string.IsNullOrEmpty(savedTheme) && AvailableColorThemes.Contains(savedTheme))
{
CurrentColorTheme = savedTheme;
ApplyColorTheme(CurrentColorTheme);
}
}
}
catch
{
// If loading fails, use default theme
}
}
private async void ForceThemeRefresh()
{
if(_themeService == null) return;
try
{
// Get current theme
AppTheme currentTheme = _themeService.Theme;
// Toggle to opposite theme briefly
AppTheme tempTheme = currentTheme == AppTheme.Light ? AppTheme.Dark : AppTheme.Light;
await _themeService.SetThemeAsync(tempTheme);
// Small delay to ensure the change is applied
await Task.Delay(50);
// Switch back to original theme
await _themeService.SetThemeAsync(currentTheme);
}
catch
{
// Silently fail
}
}
}