diff --git a/Flow.Launcher.Core/Plugin/PluginManager.cs b/Flow.Launcher.Core/Plugin/PluginManager.cs index fcb261f24..cc7fa2bc1 100644 --- a/Flow.Launcher.Core/Plugin/PluginManager.cs +++ b/Flow.Launcher.Core/Plugin/PluginManager.cs @@ -26,12 +26,6 @@ namespace Flow.Launcher.Core.Plugin { private static readonly string ClassName = nameof(PluginManager); - private static IEnumerable _contextMenuPlugins; - private static IEnumerable _homePlugins; - private static IEnumerable _resultUpdatePlugin; - private static IEnumerable _translationPlugins; - private static IEnumerable _hotkeyPlugins; - public static List AllPlugins { get; private set; } public static readonly HashSet GlobalPlugins = new(); public static readonly Dictionary NonGlobalPlugins = new(); @@ -43,8 +37,13 @@ namespace Flow.Launcher.Core.Plugin private static IPublicAPI API => api ??= Ioc.Default.GetRequiredService(); private static PluginsSettings Settings; - private static List _metadatas; - private static readonly List _modifiedPlugins = new(); + private static readonly ConcurrentBag ModifiedPlugins = new(); + + private static IEnumerable _contextMenuPlugins; + private static IEnumerable _homePlugins; + private static IEnumerable _resultUpdatePlugin; + private static IEnumerable _translationPlugins; + private static IEnumerable _hotkeyPlugins; private static readonly Dictionary> _pluginHotkeyInfo = new(); private static readonly Dictionary> _windowPluginHotkeys = new(); @@ -183,12 +182,13 @@ namespace Flow.Launcher.Core.Plugin /// public static void LoadPlugins(PluginsSettings settings) { - _metadatas = PluginConfig.Parse(Directories); + var metadatas = PluginConfig.Parse(Directories); Settings = settings; - Settings.UpdatePluginSettings(_metadatas); - AllPlugins = PluginsLoader.Plugins(_metadatas, Settings); + Settings.UpdatePluginSettings(metadatas); + AllPlugins = PluginsLoader.Plugins(metadatas, Settings); // Since dotnet plugins need to get assembly name first, we should update plugin directory after loading plugins - UpdatePluginDirectory(_metadatas); + UpdatePluginDirectory(metadatas); + // Initialize plugin enumerable after all plugins are initialized _contextMenuPlugins = GetPluginsForInterface(); _homePlugins = GetPluginsForInterface(); @@ -432,10 +432,20 @@ namespace Flow.Launcher.Core.Plugin return AllPlugins?.Where(p => p.Plugin is T) ?? Array.Empty(); } + public static IList GetResultUpdatePlugin() + { + return _resultUpdatePlugin.Where(p => !PluginModified(p.Metadata.ID)).ToList(); + } + + public static IList GetTranslationPlugins() + { + return _translationPlugins.Where(p => !PluginModified(p.Metadata.ID)).ToList(); + } + public static List GetContextMenusForPlugin(Result result) { var results = new List(); - var pluginPair = _contextMenuPlugins.FirstOrDefault(o => o.Metadata.ID == result.PluginID); + var pluginPair = _contextMenuPlugins.Where(p => !PluginModified(p.Metadata.ID)).FirstOrDefault(o => o.Metadata.ID == result.PluginID); if (pluginPair != null) { var plugin = (IContextMenu)pluginPair.Plugin; @@ -463,7 +473,7 @@ namespace Flow.Launcher.Core.Plugin public static bool IsHomePlugin(string id) { - return _homePlugins.Any(p => p.Metadata.ID == id); + return _homePlugins.Where(p => !PluginModified(p.Metadata.ID)).Any(p => p.Metadata.ID == id); } public static IList GetResultUpdatePlugin() @@ -695,14 +705,14 @@ namespace Flow.Launcher.Core.Plugin public static bool PluginModified(string id) { - return _modifiedPlugins.Contains(id); + return ModifiedPlugins.Contains(id); } public static async Task UpdatePluginAsync(PluginMetadata existingVersion, UserPlugin newVersion, string zipFilePath) { - InstallPlugin(newVersion, zipFilePath, checkModified:false); - await UninstallPluginAsync(existingVersion, removePluginFromSettings:false, removePluginSettings:false, checkModified: false); - _modifiedPlugins.Add(existingVersion.ID); + InstallPlugin(newVersion, zipFilePath, checkModified: false); + await UninstallPluginAsync(existingVersion, removePluginFromSettings: false, removePluginSettings: false, checkModified: false); + ModifiedPlugins.Add(existingVersion.ID); } public static void InstallPlugin(UserPlugin plugin, string zipFilePath) @@ -789,7 +799,7 @@ namespace Flow.Launcher.Core.Plugin if (checkModified) { - _modifiedPlugins.Add(plugin.ID); + ModifiedPlugins.Add(plugin.ID); } } @@ -851,6 +861,12 @@ namespace Flow.Launcher.Core.Plugin } Settings.RemovePluginSettings(plugin.ID); AllPlugins.RemoveAll(p => p.Metadata.ID == plugin.ID); + GlobalPlugins.RemoveWhere(p => p.Metadata.ID == plugin.ID); + var keysToRemove = NonGlobalPlugins.Where(p => p.Value.Metadata.ID == plugin.ID).Select(p => p.Key).ToList(); + foreach (var key in keysToRemove) + { + NonGlobalPlugins.Remove(key); + } } // Marked for deletion. Will be deleted on next start up @@ -858,7 +874,7 @@ namespace Flow.Launcher.Core.Plugin if (checkModified) { - _modifiedPlugins.Add(plugin.ID); + ModifiedPlugins.Add(plugin.ID); } } diff --git a/Flow.Launcher.Infrastructure/Win32Helper.cs b/Flow.Launcher.Infrastructure/Win32Helper.cs index 86e7b7c97..32ed31137 100644 --- a/Flow.Launcher.Infrastructure/Win32Helper.cs +++ b/Flow.Launcher.Infrastructure/Win32Helper.cs @@ -791,5 +791,41 @@ namespace Flow.Launcher.Infrastructure } #endregion + + #region Win32 Dark Mode + + /* + * Inspired by https://github.com/ysc3839/win32-darkmode + */ + + [DllImport("uxtheme.dll", EntryPoint = "#135", SetLastError = true)] + private static extern int SetPreferredAppMode(int appMode); + + public static void EnableWin32DarkMode(string colorScheme) + { + try + { + // Undocumented API from Windows 10 1809 + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && + Environment.OSVersion.Version.Build >= 17763) + { + var flag = colorScheme switch + { + Constant.Light => 3, // ForceLight + Constant.Dark => 2, // ForceDark + Constant.System => 1, // AllowDark + _ => 0 // Default + }; + _ = SetPreferredAppMode(flag); + } + + } + catch + { + // Ignore errors on unsupported OS + } + } + + #endregion } } diff --git a/Flow.Launcher/App.xaml.cs b/Flow.Launcher/App.xaml.cs index 5df1f88ae..e99f5e643 100644 --- a/Flow.Launcher/App.xaml.cs +++ b/Flow.Launcher/App.xaml.cs @@ -188,6 +188,9 @@ namespace Flow.Launcher Notification.Install(); + // Enable Win32 dark mode if the system is in dark mode before creating all windows + Win32Helper.EnableWin32DarkMode(_settings.ColorScheme); + Ioc.Default.GetRequiredService().PreStartCleanUpAfterPortabilityUpdate(); API.LogInfo(ClassName, "Begin Flow Launcher startup ----------------------------------------------------"); diff --git a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs index b62a35495..3bee2a2b6 100644 --- a/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs +++ b/Flow.Launcher/SettingPages/ViewModels/SettingsPaneThemeViewModel.cs @@ -136,6 +136,7 @@ public partial class SettingsPaneThemeViewModel : BaseModel }; Settings.ColorScheme = value; _ = _theme.RefreshFrameAsync(); + Win32Helper.EnableWin32DarkMode(value); } }