diff --git a/Flow.Launcher.Core/Resource/Theme.cs b/Flow.Launcher.Core/Resource/Theme.cs index 4deea1f6648..cda125a39cb 100644 --- a/Flow.Launcher.Core/Resource/Theme.cs +++ b/Flow.Launcher.Core/Resource/Theme.cs @@ -12,7 +12,6 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using CommunityToolkit.Mvvm.DependencyInjection; using Flow.Launcher.Plugin; namespace Flow.Launcher.Core.Resource @@ -35,6 +34,8 @@ public class Theme private string DirectoryPath => Path.Combine(Constant.ProgramDirectory, Folder); private string UserDirectoryPath => Path.Combine(DataLocation.DataDirectory(), Folder); + public string CurrentTheme => _settings.Theme; + public bool BlurEnabled { get; set; } private double mainWindowWidth; diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj index dbc36ad424b..266c2417008 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj +++ b/Plugins/Flow.Launcher.Plugin.Sys/Flow.Launcher.Plugin.Sys.csproj @@ -39,6 +39,7 @@ + diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png b/Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png new file mode 100644 index 00000000000..704e9474eb2 Binary files /dev/null and b/Plugins/Flow.Launcher.Plugin.Sys/Images/theme_selector.png differ diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml index 91f32a844f8..2a266f8f651 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.Sys/Languages/en.xaml @@ -27,6 +27,7 @@ Flow Launcher Tips Flow Launcher UserData Folder Toggle Game Mode + Set the Flow Launcher Theme Shutdown Computer @@ -49,8 +50,9 @@ Visit Flow Launcher's documentation for more help and how to use tips Open the location where Flow Launcher's settings are stored Toggle Game Mode + Quickly change the Flow Launcher theme - + Success All Flow Launcher settings saved Reloaded all applicable plugin data diff --git a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs index 2331ee68c05..28747cc7cf1 100644 --- a/Plugins/Flow.Launcher.Plugin.Sys/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.Sys/Main.cs @@ -7,7 +7,6 @@ using Flow.Launcher.Infrastructure; using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.UserSettings; -using Flow.Launcher.Plugin.SharedCommands; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Security; @@ -20,6 +19,7 @@ namespace Flow.Launcher.Plugin.Sys public class Main : IPlugin, ISettingProvider, IPluginI18n { private PluginInitContext context; + private ThemeSelector themeSelector; private Dictionary KeywordTitleMappings = new Dictionary(); // SHTDN_REASON_MAJOR_OTHER indicates a generic shutdown reason that isn't categorized under hardware failure, software updates, or other predefined reasons. @@ -34,6 +34,11 @@ public Control CreateSettingPanel() public List Query(Query query) { + if(query.Search.StartsWith(ThemeSelector.Keyword)) + { + return themeSelector.Query(query); + } + var commands = Commands(); var results = new List(); foreach (var c in commands) @@ -82,6 +87,7 @@ private string GetDynamicTitle(Query query, Result result) public void Init(PluginInitContext context) { this.context = context; + themeSelector = new ThemeSelector(context); KeywordTitleMappings = new Dictionary{ {"Shutdown", "flowlauncher_plugin_sys_shutdown_computer_cmd"}, {"Restart", "flowlauncher_plugin_sys_restart_computer_cmd"}, @@ -102,7 +108,8 @@ public void Init(PluginInitContext context) {"Open Log Location", "flowlauncher_plugin_sys_open_log_location_cmd"}, {"Flow Launcher Tips", "flowlauncher_plugin_sys_open_docs_tips_cmd"}, {"Flow Launcher UserData Folder", "flowlauncher_plugin_sys_open_userdata_location_cmd"}, - {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"} + {"Toggle Game Mode", "flowlauncher_plugin_sys_toggle_game_mode_cmd"}, + {"Set Flow Launcher Theme", "flowlauncher_plugin_sys_theme_selector_cmd"} }; } @@ -451,6 +458,18 @@ private List Commands() context.API.ToggleGameMode(); return true; } + }, + new Result + { + Title = "Set Flow Launcher Theme", + SubTitle = context.API.GetTranslation("flowlauncher_plugin_sys_theme_selector"), + IcoPath = "Images\\app.png", + Glyph = new GlyphInfo (FontFamily:"/Resources/#Segoe Fluent Icons", Glyph:"\ue7fc"), + Action = c => + { + context.API.ChangeQuery($"{ThemeSelector.Keyword} "); + return false; + } } }); diff --git a/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs new file mode 100644 index 00000000000..38619cbbc2c --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.Sys/ThemeSelector.cs @@ -0,0 +1,115 @@ +using System.Collections.Generic; +using System.Linq; +using CommunityToolkit.Mvvm.DependencyInjection; +using Flow.Launcher.Core.Resource; +using Flow.Launcher.Infrastructure.UserSettings; + +namespace Flow.Launcher.Plugin.Sys +{ + public class ThemeSelector + { + public const string Keyword = "fltheme"; + + private readonly Settings _settings; + private readonly Theme _theme; + private readonly PluginInitContext _context; + + #region Theme Selection + + // Theme select codes simplified from SettingsPaneThemeViewModel.cs + + private Theme.ThemeData _selectedTheme; + private Theme.ThemeData SelectedTheme + { + get => _selectedTheme ??= Themes.Find(v => v.FileNameWithoutExtension == _theme.CurrentTheme); + set + { + _selectedTheme = value; + _theme.ChangeTheme(value.FileNameWithoutExtension); + + if (_theme.BlurEnabled && _settings.UseDropShadowEffect) + { + _theme.RemoveDropShadowEffectFromCurrentTheme(); + _settings.UseDropShadowEffect = false; + } + } + } + + private List Themes => _theme.LoadAvailableThemes(); + + #endregion + + public ThemeSelector(PluginInitContext context) + { + _context = context; + _theme = Ioc.Default.GetRequiredService(); + _settings = Ioc.Default.GetRequiredService(); + } + + public List Query(Query query) + { + var search = query.SecondToEndSearch; + if (string.IsNullOrWhiteSpace(search)) + { + return Themes.Select(CreateThemeResult) + .OrderBy(x => x.Title) + .ToList(); + } + + return Themes.Select(theme => (theme, matchResult: _context.API.FuzzySearch(search, theme.Name))) + .Where(x => x.matchResult.IsSearchPrecisionScoreMet()) + .Select(x => CreateThemeResult(x.theme, x.matchResult.Score, x.matchResult.MatchData)) + .OrderBy(x => x.Title) + .ToList(); + } + + private Result CreateThemeResult(Theme.ThemeData theme) => CreateThemeResult(theme, 0, null); + + private Result CreateThemeResult(Theme.ThemeData theme, int score, IList highlightData) + { + string themeName = theme.Name; + string title; + if (theme == SelectedTheme) + { + title = $"{theme.Name} ★"; + // Set current theme to the top + score = 2000; + } + else + { + title = theme.Name; + // Set them to 1000 so that they are higher than other non-theme records + score = 1000; + } + + string description = string.Empty; + if (theme.IsDark == true) + { + description += _context.API.GetTranslation("TypeIsDarkToolTip"); + } + + if (theme.HasBlur == true) + { + if (!string.IsNullOrEmpty(description)) + description += " "; + description += _context.API.GetTranslation("TypeHasBlurToolTip"); + } + + return new Result + { + Title = title, + TitleHighlightData = highlightData, + SubTitle = description, + IcoPath = "Images\\theme_selector.png", + Glyph = new GlyphInfo("/Resources/#Segoe Fluent Icons", "\ue790"), + Score = score, + Action = c => + { + SelectedTheme = theme; + _context.API.ReQuery(); + return false; + } + }; + } + } +}