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

163 lines
4.9 KiB
C#
Raw Normal View History

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,
2025-11-16 18:59:23 +00:00
"Windows311",
2025-11-16 19:11:21 +00:00
"MacOS9",
2025-11-16 19:18:19 +00:00
"DOS",
"Amiga"
};
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
2025-11-16 18:59:23 +00:00
.Where(d => d.Source?.OriginalString?.Contains("ColorPalette") != 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)
{
2025-11-16 18:59:23 +00:00
string themeFile = themeName switch
{
"Windows311" => "ms-appx:///Styles/Win311ColorPalette.xaml",
"MacOS9" => "ms-appx:///Styles/MacOS9ColorPalette.xaml",
2025-11-16 19:11:21 +00:00
"DOS" => "ms-appx:///Styles/DOSColorPalette.xaml",
2025-11-16 19:18:19 +00:00
"Amiga" => "ms-appx:///Styles/AmigaColorPalette.xaml",
2025-11-16 18:59:23 +00:00
_ => null
};
if(themeFile != null)
{
2025-11-16 18:59:23 +00:00
var newDictionary = new ResourceDictionary
{
Source = new Uri(themeFile)
};
2025-11-16 18:59:23 +00:00
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
}
}
}