Couple aot fixes.
This commit is contained in:
@@ -124,12 +124,12 @@
|
||||
ItemsSource="{x:Bind ViewModel.DateNavigationHeaderItems}"
|
||||
SelectedIndex="{x:Bind ViewModel.SelectedDateNavigationHeaderIndex, Mode=OneWay}">
|
||||
<FlipView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate x:DataType="x:String">
|
||||
<TextBlock
|
||||
VerticalAlignment="Center"
|
||||
FontSize="18"
|
||||
Style="{StaticResource BodyTextBlockStyle}"
|
||||
Text="{Binding}" />
|
||||
Text="{x:Bind}" />
|
||||
</DataTemplate>
|
||||
</FlipView.ItemTemplate>
|
||||
</calendarControls:CustomCalendarFlipView>
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
|
||||
namespace Wino.Core.Domain.Interfaces;
|
||||
|
||||
public interface IThemeService : IInitializeAsync
|
||||
{
|
||||
event EventHandler<ApplicationElementTheme> ElementThemeChanged;
|
||||
event EventHandler<string> AccentColorChanged;
|
||||
|
||||
Task<List<AppThemeBase>> GetAvailableThemesAsync();
|
||||
Task<CustomThemeMetadata> CreateNewCustomThemeAsync(string themeName, string accentColor, byte[] wallpaperData);
|
||||
Task<List<CustomThemeMetadata>> GetCurrentCustomThemesAsync();
|
||||
List<string> GetAvailableAccountColors();
|
||||
Task ApplyCustomThemeAsync(bool isInitializing);
|
||||
|
||||
// Settings
|
||||
ApplicationElementTheme RootTheme { get; set; }
|
||||
Guid CurrentApplicationThemeId { get; set; }
|
||||
string AccentColor { get; set; }
|
||||
string GetSystemAccentColorHex();
|
||||
bool IsCustomTheme { get; }
|
||||
}
|
||||
@@ -6,6 +6,7 @@ using Serilog;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
|
||||
namespace Wino.Core.ViewModels;
|
||||
|
||||
@@ -47,19 +48,17 @@ public partial class AboutPageViewModel : CoreBaseViewModel
|
||||
PreferencesService = preferencesService;
|
||||
}
|
||||
|
||||
[RequiresDynamicCode("AOT")]
|
||||
[RequiresUnreferencedCode("AOT")]
|
||||
protected override void OnActivated()
|
||||
public override void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnActivated();
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
|
||||
PreferencesService.PreferenceChanged -= PreferencesChanged;
|
||||
PreferencesService.PreferenceChanged += PreferencesChanged;
|
||||
}
|
||||
|
||||
protected override void OnDeactivated()
|
||||
public override void OnNavigatedFrom(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnDeactivated();
|
||||
base.OnNavigatedFrom(mode, parameters);
|
||||
|
||||
PreferencesService.PreferenceChanged -= PreferencesChanged;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Entities.Mail;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models.Navigation;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
using Wino.Core.ViewModels.Data;
|
||||
|
||||
@@ -20,7 +21,6 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
public IPreferencesService PreferencesService { get; }
|
||||
|
||||
private readonly IDialogServiceBase _dialogService;
|
||||
private readonly IThemeService _themeService;
|
||||
private readonly INewThemeService _newThemeService;
|
||||
|
||||
private bool isPropChangeDisabled = false;
|
||||
@@ -147,12 +147,10 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
public AsyncRelayCommand CreateCustomThemeCommand { get; set; }
|
||||
public PersonalizationPageViewModel(IDialogServiceBase dialogService,
|
||||
IStatePersistanceService statePersistanceService,
|
||||
IThemeService themeService,
|
||||
INewThemeService newThemeService,
|
||||
IPreferencesService preferencesService)
|
||||
{
|
||||
_dialogService = dialogService;
|
||||
_themeService = themeService;
|
||||
_newThemeService = newThemeService;
|
||||
|
||||
StatePersistenceService = statePersistanceService;
|
||||
@@ -193,7 +191,7 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
|
||||
// Add system accent color as last item.
|
||||
|
||||
Colors.Add(new AppColorViewModel(_themeService.GetSystemAccentColorHex(), true));
|
||||
Colors.Add(new AppColorViewModel(_newThemeService.GetSystemAccentColorHex(), true));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -201,10 +199,10 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
/// </summary>
|
||||
private void SetInitialValues()
|
||||
{
|
||||
SelectedElementTheme = ElementThemes.Find(a => a.NativeTheme == _themeService.RootTheme);
|
||||
SelectedElementTheme = ElementThemes.Find(a => a.NativeTheme == _newThemeService.RootTheme);
|
||||
SelectedInfoDisplayMode = PreferencesService.MailItemDisplayMode;
|
||||
|
||||
var currentAccentColor = _themeService.AccentColor;
|
||||
var currentAccentColor = _newThemeService.AccentColor;
|
||||
|
||||
bool isWindowsColor = string.IsNullOrEmpty(currentAccentColor);
|
||||
|
||||
@@ -228,11 +226,9 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
SelectedBackdropType = AvailableBackdropTypes?.FirstOrDefault(x => x.BackdropType == targetBackdropType);
|
||||
}
|
||||
|
||||
[RequiresDynamicCode("AOT")]
|
||||
[RequiresUnreferencedCode("AOT")]
|
||||
protected override async void OnActivated()
|
||||
public override async void OnNavigatedTo(NavigationMode mode, object parameters)
|
||||
{
|
||||
base.OnActivated();
|
||||
base.OnNavigatedTo(mode, parameters);
|
||||
|
||||
await InitializeSettingsAsync();
|
||||
}
|
||||
@@ -241,7 +237,7 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
{
|
||||
Deactivate();
|
||||
|
||||
AppThemes = await _themeService.GetAvailableThemesAsync();
|
||||
AppThemes = await _newThemeService.GetAvailableThemesAsync();
|
||||
|
||||
OnPropertyChanged(nameof(AppThemes));
|
||||
|
||||
@@ -254,11 +250,11 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
PropertyChanged -= PersonalizationSettingsUpdated;
|
||||
PropertyChanged += PersonalizationSettingsUpdated;
|
||||
|
||||
_themeService.AccentColorChanged -= AccentColorChanged;
|
||||
_themeService.ElementThemeChanged -= ElementThemeChanged;
|
||||
_newThemeService.AccentColorChanged -= AccentColorChanged;
|
||||
_newThemeService.ElementThemeChanged -= ElementThemeChanged;
|
||||
|
||||
_themeService.AccentColorChanged += AccentColorChanged;
|
||||
_themeService.ElementThemeChanged += ElementThemeChanged;
|
||||
_newThemeService.AccentColorChanged += AccentColorChanged;
|
||||
_newThemeService.ElementThemeChanged += ElementThemeChanged;
|
||||
}
|
||||
|
||||
private void AccentColorChanged(object sender, string e)
|
||||
@@ -290,8 +286,8 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
{
|
||||
PropertyChanged -= PersonalizationSettingsUpdated;
|
||||
|
||||
_themeService.AccentColorChanged -= AccentColorChanged;
|
||||
_themeService.ElementThemeChanged -= ElementThemeChanged;
|
||||
_newThemeService.AccentColorChanged -= AccentColorChanged;
|
||||
_newThemeService.ElementThemeChanged -= ElementThemeChanged;
|
||||
|
||||
if (AppThemes != null)
|
||||
{
|
||||
@@ -307,7 +303,7 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
|
||||
if (e.PropertyName == nameof(SelectedElementTheme) && SelectedElementTheme != null)
|
||||
{
|
||||
_themeService.RootTheme = SelectedElementTheme.NativeTheme;
|
||||
_newThemeService.RootTheme = SelectedElementTheme.NativeTheme;
|
||||
}
|
||||
else if (e.PropertyName == nameof(SelectedAppTheme))
|
||||
{
|
||||
@@ -328,7 +324,7 @@ public partial class PersonalizationPageViewModel : CoreBaseViewModel
|
||||
if (e.PropertyName == nameof(SelectedInfoDisplayMode))
|
||||
PreferencesService.MailItemDisplayMode = SelectedInfoDisplayMode;
|
||||
else if (e.PropertyName == nameof(SelectedAppColor))
|
||||
_themeService.AccentColor = SelectedAppColor.Hex;
|
||||
_newThemeService.AccentColor = SelectedAppColor.Hex;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,8 +54,6 @@ public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
Debug.WriteLine($"Disposed {GetType().Name}");
|
||||
}
|
||||
|
||||
[RequiresDynamicCode("AOT")]
|
||||
[RequiresUnreferencedCode("AOT")]
|
||||
protected override void OnNavigatedTo(NavigationEventArgs e)
|
||||
{
|
||||
base.OnNavigatedTo(e);
|
||||
@@ -64,7 +62,7 @@ public abstract class BasePage<T> : BasePage where T : CoreBaseViewModel
|
||||
var parameter = e.Parameter;
|
||||
|
||||
WeakReferenceMessenger.Default.UnregisterAll(this);
|
||||
WeakReferenceMessenger.Default.RegisterAll(this);
|
||||
WeakReferenceMessenger.Default.Register<LanguageChanged>(this);
|
||||
|
||||
ViewModel.OnNavigatedTo(mode, parameter);
|
||||
}
|
||||
|
||||
@@ -1,508 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices.WindowsRuntime;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
using CommunityToolkit.Mvvm.Messaging;
|
||||
using CommunityToolkit.WinUI;
|
||||
using CommunityToolkit.WinUI.Helpers;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.UI.Xaml.Markup;
|
||||
using Microsoft.UI.Xaml.Media;
|
||||
using Windows.Storage;
|
||||
using Windows.UI.ViewManagement;
|
||||
using Wino.Core.Domain;
|
||||
using Wino.Core.Domain.Enums;
|
||||
using Wino.Core.Domain.Exceptions;
|
||||
using Wino.Core.Domain.Interfaces;
|
||||
using Wino.Core.Domain.Models;
|
||||
using Wino.Core.Domain.Models.Personalization;
|
||||
using Wino.Core.WinUI;
|
||||
using Wino.Core.WinUI.Extensions;
|
||||
using Wino.Core.WinUI.Interfaces;
|
||||
using Wino.Core.WinUI.Models.Personalization;
|
||||
using Wino.Core.WinUI.Services;
|
||||
using Wino.Messaging.Client.Shell;
|
||||
|
||||
namespace Wino.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Class providing functionality around switching and restoring theme settings
|
||||
/// </summary>
|
||||
public class ThemeService : IThemeService
|
||||
{
|
||||
public const string CustomThemeFolderName = "CustomThemes";
|
||||
|
||||
private static string _micaThemeId = "a160b1b0-2ab8-4e97-a803-f4050f036e25";
|
||||
private static string _acrylicThemeId = "fc08e58c-36fd-46e2-a562-26cf277f1467";
|
||||
private static string _cloudsThemeId = "3b621cc2-e270-4a76-8477-737917cccda0";
|
||||
private static string _forestThemeId = "8bc89b37-a7c5-4049-86e2-de1ae8858dbd";
|
||||
private static string _nightyThemeId = "5b65e04e-fd7e-4c2d-8221-068d3e02d23a";
|
||||
private static string _snowflakeThemeId = "e143ddde-2e28-4846-9d98-dad63d6505f1";
|
||||
private static string _gardenThemeId = "698e4466-f88c-4799-9c61-f0ea1308ed49";
|
||||
|
||||
public event EventHandler<ApplicationElementTheme> ElementThemeChanged;
|
||||
public event EventHandler<string> AccentColorChanged;
|
||||
|
||||
private const string AccentColorKey = nameof(AccentColorKey);
|
||||
private const string CurrentApplicationThemeKey = nameof(CurrentApplicationThemeKey);
|
||||
|
||||
// Custom theme
|
||||
public const string CustomThemeAccentColorKey = nameof(CustomThemeAccentColorKey);
|
||||
|
||||
// Keep reference so it does not get optimized/garbage collected
|
||||
private readonly UISettings uiSettings = new UISettings();
|
||||
|
||||
private readonly IConfigurationService _configurationService;
|
||||
private readonly IUnderlyingThemeService _underlyingThemeService;
|
||||
private readonly IApplicationResourceManager<ResourceDictionary> _applicationResourceManager;
|
||||
|
||||
private List<AppThemeBase> preDefinedThemes { get; set; } = new List<AppThemeBase>()
|
||||
{
|
||||
new SystemAppTheme("Mica", Guid.Parse(_micaThemeId)),
|
||||
new SystemAppTheme("Acrylic", Guid.Parse(_acrylicThemeId)),
|
||||
new PreDefinedAppTheme("Nighty", Guid.Parse(_nightyThemeId), "#e1b12c", ApplicationElementTheme.Dark),
|
||||
new PreDefinedAppTheme("Forest", Guid.Parse(_forestThemeId), "#16a085", ApplicationElementTheme.Dark),
|
||||
new PreDefinedAppTheme("Clouds", Guid.Parse(_cloudsThemeId), "#0984e3", ApplicationElementTheme.Light),
|
||||
new PreDefinedAppTheme("Snowflake", Guid.Parse(_snowflakeThemeId), "#4a69bd", ApplicationElementTheme.Light),
|
||||
new PreDefinedAppTheme("Garden", Guid.Parse(_gardenThemeId), "#05c46b", ApplicationElementTheme.Light),
|
||||
};
|
||||
|
||||
public ThemeService(IConfigurationService configurationService,
|
||||
IUnderlyingThemeService underlyingThemeService,
|
||||
IApplicationResourceManager<ResourceDictionary> applicationResourceManager)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_underlyingThemeService = underlyingThemeService;
|
||||
_applicationResourceManager = applicationResourceManager;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets (with LocalSettings persistence) the RequestedTheme of the root element.
|
||||
/// </summary>
|
||||
public ApplicationElementTheme RootTheme
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetShellRootContent().RequestedTheme.ToWinoElementTheme();
|
||||
//if (mainApplicationFrame == null) return ApplicationElementTheme.Default;
|
||||
|
||||
//return mainApplicationFrame.RequestedTheme.ToWinoElementTheme();
|
||||
}
|
||||
set
|
||||
{
|
||||
GetShellRootContent().RequestedTheme = value.ToWindowsElementTheme();
|
||||
// mainApplicationFrame.RequestedTheme = value.ToWindowsElementTheme();
|
||||
|
||||
_configurationService.Set(UnderlyingThemeService.SelectedAppThemeKey, value);
|
||||
|
||||
UpdateSystemCaptionButtonColors();
|
||||
|
||||
// PopupRoot usually needs to react to changes.
|
||||
NotifyThemeUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Guid currentApplicationThemeId;
|
||||
|
||||
public Guid CurrentApplicationThemeId
|
||||
{
|
||||
get { return currentApplicationThemeId; }
|
||||
set
|
||||
{
|
||||
currentApplicationThemeId = value;
|
||||
|
||||
_configurationService.Set(CurrentApplicationThemeKey, value);
|
||||
|
||||
if (WinoApplication.MainWindow != null)
|
||||
{
|
||||
WinoApplication.MainWindow.DispatcherQueue.TryEnqueue(async () =>
|
||||
{
|
||||
await ApplyCustomThemeAsync(false);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private string accentColor;
|
||||
|
||||
public string AccentColor
|
||||
{
|
||||
get { return accentColor; }
|
||||
set
|
||||
{
|
||||
accentColor = value;
|
||||
|
||||
UpdateAccentColor(value);
|
||||
|
||||
_configurationService.Set(AccentColorKey, value);
|
||||
AccentColorChanged?.Invoke(this, value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsCustomTheme
|
||||
{
|
||||
get
|
||||
{
|
||||
return currentApplicationThemeId != Guid.Parse(_micaThemeId) &&
|
||||
currentApplicationThemeId != Guid.Parse(_acrylicThemeId);
|
||||
}
|
||||
}
|
||||
|
||||
public FrameworkElement GetShellRootContent() => (WinoApplication.MainWindow as IWinoShellWindow)?.GetRootContent() ?? throw new Exception("No root content found");
|
||||
|
||||
private bool isInitialized = false;
|
||||
|
||||
public async Task InitializeAsync()
|
||||
{
|
||||
// Already initialized. There is no need.
|
||||
if (isInitialized) return;
|
||||
|
||||
RootTheme = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default);
|
||||
AccentColor = _configurationService.Get(AccentColorKey, string.Empty);
|
||||
|
||||
// Set the current theme id. Default to Mica.
|
||||
currentApplicationThemeId = _configurationService.Get(CurrentApplicationThemeKey, Guid.Parse(_micaThemeId));
|
||||
|
||||
await ApplyCustomThemeAsync(true);
|
||||
|
||||
// Registering to color changes, thus we notice when user changes theme system wide
|
||||
uiSettings.ColorValuesChanged -= UISettingsColorChanged;
|
||||
uiSettings.ColorValuesChanged += UISettingsColorChanged;
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
private void NotifyThemeUpdate()
|
||||
{
|
||||
if (GetShellRootContent() is not UIElement rootContent) return;
|
||||
|
||||
_ = rootContent.DispatcherQueue.EnqueueAsync(() =>
|
||||
{
|
||||
ElementThemeChanged?.Invoke(this, RootTheme);
|
||||
WeakReferenceMessenger.Default.Send(new ApplicationThemeChanged(_underlyingThemeService.IsUnderlyingThemeDark()));
|
||||
}, Microsoft.UI.Dispatching.DispatcherQueuePriority.High);
|
||||
}
|
||||
|
||||
private void UISettingsColorChanged(UISettings sender, object args)
|
||||
{
|
||||
// TODO: Buggy.
|
||||
//GetShellRootContent().DispatcherQueue.TryEnqueue(() =>
|
||||
//{
|
||||
// UpdateSystemCaptionButtonColors();
|
||||
//});
|
||||
|
||||
NotifyThemeUpdate();
|
||||
}
|
||||
|
||||
public void UpdateSystemCaptionButtonColors()
|
||||
{
|
||||
GetShellRootContent().DispatcherQueue.TryEnqueue(() =>
|
||||
{
|
||||
Debug.WriteLine("TODO: Updating caption button colors");
|
||||
|
||||
// var titleBar = (WinoApplication.MainWindow as IWinoShellWindow).GetTitleBar();
|
||||
|
||||
//if (_underlyingThemeService.IsUnderlyingThemeDark())
|
||||
//{
|
||||
// titleBar.ButtonForegroundColor = Colors.White;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// titleBar.ButtonForegroundColor = Colors.Black;
|
||||
//}
|
||||
});
|
||||
}
|
||||
|
||||
public void UpdateAccentColor(string hex)
|
||||
{
|
||||
// Change accent color if specified.
|
||||
if (!string.IsNullOrEmpty(hex))
|
||||
{
|
||||
var color = CommunityToolkit.WinUI.Helpers.ColorHelper.ToColor(hex);
|
||||
var brush = new SolidColorBrush(color);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemAccentColor"))
|
||||
_applicationResourceManager.ReplaceResource("SystemAccentColor", color);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("NavigationViewSelectionIndicatorForeground"))
|
||||
_applicationResourceManager.ReplaceResource("NavigationViewSelectionIndicatorForeground", brush);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemControlBackgroundAccentBrush"))
|
||||
_applicationResourceManager.ReplaceResource("SystemControlBackgroundAccentBrush", brush);
|
||||
|
||||
if (_applicationResourceManager.ContainsResourceKey("SystemColorControlAccentBrush"))
|
||||
_applicationResourceManager.ReplaceResource("SystemColorControlAccentBrush", brush);
|
||||
|
||||
|
||||
RefreshThemeResource();
|
||||
}
|
||||
}
|
||||
|
||||
private void RefreshThemeResource()
|
||||
{
|
||||
var mainApplicationFrame = GetShellRootContent();
|
||||
|
||||
if (mainApplicationFrame == null) return;
|
||||
|
||||
if (mainApplicationFrame.RequestedTheme == ElementTheme.Dark)
|
||||
{
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Light;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Dark;
|
||||
}
|
||||
else if (mainApplicationFrame.RequestedTheme == ElementTheme.Light)
|
||||
{
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Dark;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Light;
|
||||
}
|
||||
else
|
||||
{
|
||||
var isUnderlyingDark = _underlyingThemeService.IsUnderlyingThemeDark();
|
||||
|
||||
mainApplicationFrame.RequestedTheme = isUnderlyingDark ? ElementTheme.Light : ElementTheme.Dark;
|
||||
mainApplicationFrame.RequestedTheme = ElementTheme.Default;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task ApplyCustomThemeAsync(bool isInitializing)
|
||||
{
|
||||
AppThemeBase applyingTheme = null;
|
||||
|
||||
var controlThemeList = new List<AppThemeBase>(preDefinedThemes);
|
||||
|
||||
// Don't search for custom themes if applying theme is already in pre-defined templates.
|
||||
// This is important for startup performance because we won't be loading the custom themes on launch.
|
||||
|
||||
bool isApplyingPreDefinedTheme = preDefinedThemes.Exists(a => a.Id == currentApplicationThemeId);
|
||||
|
||||
if (isApplyingPreDefinedTheme)
|
||||
{
|
||||
applyingTheme = preDefinedThemes.Find(a => a.Id == currentApplicationThemeId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// User applied custom theme. Load custom themes and find it there.
|
||||
// Fallback to Mica if nothing found.
|
||||
|
||||
var customThemes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
controlThemeList.AddRange(customThemes.Select(a => new CustomAppTheme(a)));
|
||||
|
||||
applyingTheme = controlThemeList.Find(a => a.Id == currentApplicationThemeId) ?? preDefinedThemes.First(a => a.Id == Guid.Parse(_micaThemeId));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var existingThemeDictionary = _applicationResourceManager.GetLastResource();
|
||||
|
||||
if (existingThemeDictionary != null && existingThemeDictionary.TryGetValue("ThemeName", out object themeNameString))
|
||||
{
|
||||
var themeName = themeNameString.ToString();
|
||||
|
||||
// Applying different theme.
|
||||
if (themeName != applyingTheme.ThemeName)
|
||||
{
|
||||
var resourceDictionaryContent = await applyingTheme.GetThemeResourceDictionaryContentAsync();
|
||||
|
||||
var resourceDictionary = XamlReader.Load(resourceDictionaryContent) as ResourceDictionary;
|
||||
|
||||
// Custom themes require special attention for background image because
|
||||
// they share the same base theme resource dictionary.
|
||||
|
||||
if (applyingTheme is CustomAppTheme)
|
||||
{
|
||||
resourceDictionary["ThemeBackgroundImage"] = $"ms-appdata:///local/{CustomThemeFolderName}/{applyingTheme.Id}.jpg";
|
||||
}
|
||||
|
||||
_applicationResourceManager.RemoveResource(existingThemeDictionary);
|
||||
_applicationResourceManager.AddResource(resourceDictionary);
|
||||
|
||||
bool isSystemTheme = applyingTheme is SystemAppTheme || applyingTheme is CustomAppTheme;
|
||||
|
||||
if (isSystemTheme)
|
||||
{
|
||||
// For system themes, set the RootElement theme from saved values.
|
||||
// Potential bug: When we set it to system default, theme is not applied when system and
|
||||
// app element theme is different :)
|
||||
|
||||
var savedElement = _configurationService.Get(UnderlyingThemeService.SelectedAppThemeKey, ApplicationElementTheme.Default);
|
||||
RootTheme = savedElement;
|
||||
|
||||
// Quickly switch theme to apply theme resource changes.
|
||||
RefreshThemeResource();
|
||||
}
|
||||
else
|
||||
RootTheme = applyingTheme.ForceElementTheme;
|
||||
|
||||
// Theme has accent color. Override.
|
||||
if (!isInitializing)
|
||||
{
|
||||
AccentColor = applyingTheme.AccentColor;
|
||||
}
|
||||
}
|
||||
else
|
||||
UpdateSystemCaptionButtonColors();
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine($"Apply theme failed -> {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<AppThemeBase>> GetAvailableThemesAsync()
|
||||
{
|
||||
var availableThemes = new List<AppThemeBase>(preDefinedThemes);
|
||||
|
||||
var customThemes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
availableThemes.AddRange(customThemes.Select(a => new CustomAppTheme(a)));
|
||||
|
||||
return availableThemes;
|
||||
}
|
||||
|
||||
public async Task<CustomThemeMetadata> CreateNewCustomThemeAsync(string themeName, string accentColor, byte[] wallpaperData)
|
||||
{
|
||||
if (wallpaperData == null || wallpaperData.Length == 0)
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeMissingWallpaper);
|
||||
|
||||
if (string.IsNullOrEmpty(themeName))
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeMissingName);
|
||||
|
||||
var themes = await GetCurrentCustomThemesAsync();
|
||||
|
||||
if (themes.Exists(a => a.Name == themeName))
|
||||
throw new CustomThemeCreationFailedException(Translator.Exception_CustomThemeExists);
|
||||
|
||||
var newTheme = new CustomThemeMetadata()
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = themeName,
|
||||
AccentColorHex = accentColor
|
||||
};
|
||||
|
||||
// Save wallpaper.
|
||||
// Filename would be the same as metadata id, in jpg format.
|
||||
|
||||
var themeFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(CustomThemeFolderName, CreationCollisionOption.OpenIfExists);
|
||||
|
||||
var wallpaperFile = await themeFolder.CreateFileAsync($"{newTheme.Id}.jpg", CreationCollisionOption.ReplaceExisting);
|
||||
await FileIO.WriteBytesAsync(wallpaperFile, wallpaperData);
|
||||
|
||||
// Generate thumbnail for settings page.
|
||||
|
||||
var thumbnail = await wallpaperFile.GetThumbnailAsync(Windows.Storage.FileProperties.ThumbnailMode.PicturesView);
|
||||
var thumbnailFile = await themeFolder.CreateFileAsync($"{newTheme.Id}_preview.jpg", CreationCollisionOption.ReplaceExisting);
|
||||
|
||||
using (var readerStream = thumbnail.AsStreamForRead())
|
||||
{
|
||||
byte[] bytes = new byte[readerStream.Length];
|
||||
|
||||
await readerStream.ReadExactlyAsync(bytes);
|
||||
|
||||
var buffer = bytes.AsBuffer();
|
||||
|
||||
await FileIO.WriteBufferAsync(thumbnailFile, buffer);
|
||||
}
|
||||
|
||||
// Save metadata.
|
||||
var metadataFile = await themeFolder.CreateFileAsync($"{newTheme.Id}.json", CreationCollisionOption.ReplaceExisting);
|
||||
|
||||
var serialized = JsonSerializer.Serialize(newTheme, DomainModelsJsonContext.Default.CustomThemeMetadata);
|
||||
await FileIO.WriteTextAsync(metadataFile, serialized);
|
||||
|
||||
return newTheme;
|
||||
}
|
||||
|
||||
public async Task<List<CustomThemeMetadata>> GetCurrentCustomThemesAsync()
|
||||
{
|
||||
var results = new List<CustomThemeMetadata>();
|
||||
|
||||
var themeFolder = await ApplicationData.Current.LocalFolder.CreateFolderAsync(CustomThemeFolderName, CreationCollisionOption.OpenIfExists);
|
||||
|
||||
var allFiles = await themeFolder.GetFilesAsync();
|
||||
|
||||
var themeMetadatas = allFiles.Where(a => a.FileType == ".json");
|
||||
|
||||
foreach (var theme in themeMetadatas)
|
||||
{
|
||||
var metadata = await GetCustomMetadataAsync(theme).ConfigureAwait(false);
|
||||
|
||||
if (metadata == null) continue;
|
||||
|
||||
results.Add(metadata);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
private async Task<CustomThemeMetadata> GetCustomMetadataAsync(IStorageFile file)
|
||||
{
|
||||
var fileContent = await FileIO.ReadTextAsync(file);
|
||||
|
||||
return JsonSerializer.Deserialize(fileContent, DomainModelsJsonContext.Default.CustomThemeMetadata);
|
||||
}
|
||||
|
||||
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",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -27,7 +27,7 @@
|
||||
ItemClicked="BreadItemClicked"
|
||||
ItemsSource="{x:Bind PageHistory, Mode=OneWay}">
|
||||
<winuiControls:BreadcrumbBar.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
|
||||
<winuiControls:BreadcrumbBarItem Margin="0,0,8,0">
|
||||
<winuiControls:BreadcrumbBarItem.ContentTemplate>
|
||||
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
|
||||
@@ -35,7 +35,7 @@
|
||||
Margin="0,0,8,10"
|
||||
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightBySyncState(IsActive), Mode=OneWay}"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="{Binding Title, Mode=OneWay}" />
|
||||
Text="{x:Bind Title, Mode=OneWay}" />
|
||||
</DataTemplate>
|
||||
</winuiControls:BreadcrumbBarItem.ContentTemplate>
|
||||
</winuiControls:BreadcrumbBarItem>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
ItemClicked="BreadItemClicked"
|
||||
ItemsSource="{x:Bind PageHistory, Mode=OneWay}">
|
||||
<winuiControls:BreadcrumbBar.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
|
||||
<winuiControls:BreadcrumbBarItem Margin="0,0,8,0">
|
||||
<winuiControls:BreadcrumbBarItem.ContentTemplate>
|
||||
<DataTemplate x:DataType="viewModelData:BreadcrumbNavigationItemViewModel">
|
||||
@@ -35,7 +35,7 @@
|
||||
Margin="0,0,8,10"
|
||||
FontWeight="{x:Bind helpers:XamlHelpers.GetFontWeightBySyncState(IsActive), Mode=OneWay}"
|
||||
Style="{StaticResource TitleTextBlockStyle}"
|
||||
Text="{Binding Title}" />
|
||||
Text="{x:Bind Title}" />
|
||||
</DataTemplate>
|
||||
</winuiControls:BreadcrumbBarItem.ContentTemplate>
|
||||
</winuiControls:BreadcrumbBarItem>
|
||||
|
||||
Reference in New Issue
Block a user