mirror of
https://github.com/Flow-Launcher/Flow.Launcher.git
synced 2026-03-11 08:54:32 +00:00
Completely rewrite resource load / update / remove
1. part of #468 2. fix #1245, bug introduced in 7e1c77beddf2c978fa1440e799fec4eb9554739d
This commit is contained in:
parent
17e5bb8d53
commit
d0c426a7f9
10 changed files with 157 additions and 203 deletions
|
|
@ -15,7 +15,6 @@ namespace Wox.Plugin.Sys
|
|||
{
|
||||
public class Main : IPlugin, ISettingProvider, IPluginI18n
|
||||
{
|
||||
List<Result> availableResults = new List<Result>();
|
||||
private PluginInitContext context;
|
||||
|
||||
#region DllImport
|
||||
|
|
@ -47,21 +46,23 @@ namespace Wox.Plugin.Sys
|
|||
|
||||
public Control CreateSettingPanel()
|
||||
{
|
||||
return new SysSettings(availableResults);
|
||||
var results = Commands();
|
||||
return new SysSettings(results);
|
||||
}
|
||||
|
||||
public List<Result> Query(Query query)
|
||||
{
|
||||
List<Result> results = new List<Result>();
|
||||
foreach (Result availableResult in availableResults)
|
||||
var commands = Commands();
|
||||
var results = new List<Result>();
|
||||
foreach (var c in commands)
|
||||
{
|
||||
var titleScore = StringMatcher.Score(availableResult.Title, query.Search);
|
||||
var subTitleScore = StringMatcher.Score(availableResult.SubTitle, query.Search);
|
||||
var titleScore = StringMatcher.Score(c.Title, query.Search);
|
||||
var subTitleScore = StringMatcher.Score(c.SubTitle, query.Search);
|
||||
var score = Math.Max(titleScore, subTitleScore);
|
||||
if (score > 0)
|
||||
{
|
||||
availableResult.Score = score;
|
||||
results.Add(availableResult);
|
||||
c.Score = score;
|
||||
results.Add(c);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
|
|
@ -70,12 +71,12 @@ namespace Wox.Plugin.Sys
|
|||
public void Init(PluginInitContext context)
|
||||
{
|
||||
this.context = context;
|
||||
LoadCommands();
|
||||
}
|
||||
|
||||
private void LoadCommands()
|
||||
private List<Result> Commands()
|
||||
{
|
||||
availableResults.AddRange(new[]
|
||||
var results = new List<Result>();
|
||||
results.AddRange(new[]
|
||||
{
|
||||
new Result
|
||||
{
|
||||
|
|
@ -126,7 +127,7 @@ namespace Wox.Plugin.Sys
|
|||
LockWorkStation();
|
||||
return true;
|
||||
}
|
||||
},
|
||||
},
|
||||
new Result
|
||||
{
|
||||
Title = "Sleep",
|
||||
|
|
@ -188,6 +189,7 @@ namespace Wox.Plugin.Sys
|
|||
}
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
|
||||
public string GetTranslatedPluginTitle()
|
||||
|
|
|
|||
|
|
@ -87,9 +87,6 @@ namespace Wox.Core.Plugin
|
|||
}
|
||||
public static void InitializePlugins(IPublicAPI api)
|
||||
{
|
||||
//load plugin i18n languages
|
||||
ResourceMerger.UpdatePluginLanguages();
|
||||
|
||||
API = api;
|
||||
Parallel.ForEach(AllPlugins, pair =>
|
||||
{
|
||||
|
|
@ -103,7 +100,6 @@ namespace Wox.Core.Plugin
|
|||
});
|
||||
pair.Metadata.InitTime += milliseconds;
|
||||
Log.Info($"|PluginManager.InitializePlugins|Total init cost for <{pair.Metadata.Name}> is <{pair.Metadata.InitTime}ms>");
|
||||
InternationalizationManager.Instance.UpdatePluginMetadataTranslations(pair);
|
||||
});
|
||||
|
||||
_contextMenuPlugins = GetPluginsForInterface<IContextMenu>();
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using JetBrains.Annotations;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Exception;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
|
@ -10,13 +14,34 @@ using Wox.Plugin;
|
|||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public class Internationalization : Resource
|
||||
public class Internationalization
|
||||
{
|
||||
public Settings Settings { get; set; }
|
||||
private const string DirectoryName = "Languages";
|
||||
private string DirectoryPath => Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
private readonly List<string> _languageDirectories = new List<string>();
|
||||
private readonly List<ResourceDictionary> _oldResources = new List<ResourceDictionary>();
|
||||
|
||||
public Internationalization()
|
||||
{
|
||||
DirectoryName = "Languages";
|
||||
var woxThemeDirectory = Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
_languageDirectories.Add(woxThemeDirectory);
|
||||
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
|
||||
var dir = Path.GetDirectoryName(location);
|
||||
if (dir != null)
|
||||
{
|
||||
var pluginThemeDirectory = Path.Combine(dir, DirectoryName);
|
||||
_languageDirectories.Add(pluginThemeDirectory);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|ResourceMerger.UpdatePluginLanguages|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
|
||||
}
|
||||
}
|
||||
|
||||
MakesureDirectoriesExist();
|
||||
}
|
||||
|
||||
|
|
@ -37,6 +62,7 @@ namespace Wox.Core.Resource
|
|||
|
||||
public void ChangeLanguage(string languageCode)
|
||||
{
|
||||
languageCode = languageCode.NonNull();
|
||||
Language language = GetLanguageByLanguageCode(languageCode);
|
||||
ChangeLanguage(language);
|
||||
}
|
||||
|
|
@ -58,42 +84,37 @@ namespace Wox.Core.Resource
|
|||
|
||||
public void ChangeLanguage(Language language)
|
||||
{
|
||||
if (language != null)
|
||||
language = language.NonNull();
|
||||
|
||||
var files = _languageDirectories.Select(LanguageFile).Where(f => !string.IsNullOrEmpty(f)).ToArray();
|
||||
|
||||
if (files.Length > 0)
|
||||
{
|
||||
string path = GetLanguagePath(language);
|
||||
if (!string.IsNullOrEmpty(path))
|
||||
Settings.Language = language.LanguageCode;
|
||||
|
||||
var dicts = Application.Current.Resources.MergedDictionaries;
|
||||
foreach (var r in _oldResources)
|
||||
{
|
||||
Settings.Language = language.LanguageCode;
|
||||
ResourceMerger.UpdateResource(this);
|
||||
dicts.Remove(r);
|
||||
}
|
||||
else
|
||||
foreach (var f in files)
|
||||
{
|
||||
Log.Error($"|Internationalization.ChangeLanguage|Language path can't be found <{path}>");
|
||||
path = GetLanguagePath(AvailableLanguages.English);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
var r = new ResourceDictionary
|
||||
{
|
||||
Log.Error($"|Internationalization.ChangeLanguage|Default english language path can't be found <{path}>");
|
||||
}
|
||||
Source = new Uri(f, UriKind.Absolute)
|
||||
};
|
||||
dicts.Add(r);
|
||||
_oldResources.Add(r);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
Log.Error("|Internationalization.ChangeLanguage|Language can't be null");
|
||||
UpdatePluginMetadataTranslations(plugin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override ResourceDictionary GetResourceDictionary()
|
||||
{
|
||||
var uri = GetLanguageFile(DirectoryPath);
|
||||
var dictionary = new ResourceDictionary
|
||||
{
|
||||
Source = new Uri(uri, UriKind.Absolute)
|
||||
};
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
public List<Language> LoadAvailableLanguages()
|
||||
{
|
||||
return AvailableLanguages.GetAvailableLanguages();
|
||||
|
|
@ -112,14 +133,7 @@ namespace Wox.Core.Resource
|
|||
}
|
||||
}
|
||||
|
||||
private string GetLanguagePath(string languageCode)
|
||||
{
|
||||
Language language = GetLanguageByLanguageCode(languageCode);
|
||||
return GetLanguagePath(language);
|
||||
}
|
||||
|
||||
|
||||
internal void UpdatePluginMetadataTranslations(PluginPair pluginPair)
|
||||
private void UpdatePluginMetadataTranslations(PluginPair pluginPair)
|
||||
{
|
||||
var pluginI18n = pluginPair.Plugin as IPluginI18n;
|
||||
if (pluginI18n == null) return;
|
||||
|
|
@ -134,38 +148,34 @@ namespace Wox.Core.Resource
|
|||
}
|
||||
}
|
||||
|
||||
private string GetLanguagePath(Language language)
|
||||
public string LanguageFile(string folder)
|
||||
{
|
||||
string path = Path.Combine(DirectoryPath, language.LanguageCode + ".xaml");
|
||||
if (File.Exists(path))
|
||||
if (Directory.Exists(folder))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
|
||||
public string GetLanguageFile(string folder)
|
||||
{
|
||||
if (!Directory.Exists(folder)) return string.Empty;
|
||||
|
||||
string path = Path.Combine(folder, Settings.Language + ".xaml");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return path;
|
||||
string path = Path.Combine(folder, Settings.Language + ".xaml");
|
||||
if (File.Exists(path))
|
||||
{
|
||||
return path;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|Internationalization.LanguageFile|Language path can't be found <{path}>");
|
||||
string english = Path.Combine(folder, "en.xaml");
|
||||
if (File.Exists(english))
|
||||
{
|
||||
return english;
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|Internationalization.LanguageFile|Default English Language path can't be found <{path}>");
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
string english = Path.Combine(folder, "en.xaml");
|
||||
if (File.Exists(english))
|
||||
{
|
||||
return english;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +0,0 @@
|
|||
using System.IO;
|
||||
using System.Windows;
|
||||
using Wox.Infrastructure;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public abstract class Resource
|
||||
{
|
||||
public string DirectoryName { get; protected set; }
|
||||
|
||||
protected string DirectoryPath => Path.Combine(Infrastructure.Constant.ProgramDirectory, DirectoryName);
|
||||
|
||||
public abstract ResourceDictionary GetResourceDictionary();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Windows;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Plugin;
|
||||
using Wox.Infrastructure.Exception;
|
||||
using Wox.Infrastructure.Logger;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public static class ResourceMerger
|
||||
{
|
||||
static ResourceMerger()
|
||||
{
|
||||
// remove all dictionaries defined in xaml e.g.g App.xaml
|
||||
Application.Current.Resources.MergedDictionaries.Clear();
|
||||
}
|
||||
private static void RemoveResource(string directoryName)
|
||||
{
|
||||
var dictionaries = Application.Current.Resources.MergedDictionaries;
|
||||
var invalids = dictionaries.Where(dict =>
|
||||
{
|
||||
var dir = Path.GetDirectoryName(dict.Source.AbsolutePath).NonNull();
|
||||
var invalid = dir.Contains(directoryName);
|
||||
return invalid;
|
||||
}).ToList();
|
||||
foreach (var i in invalids)
|
||||
{
|
||||
dictionaries.Remove(i);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateResource<T>(T t) where T : Core.Resource.Resource
|
||||
{
|
||||
RemoveResource(t.DirectoryName);
|
||||
Application.Current.Resources.MergedDictionaries.Add(t.GetResourceDictionary());
|
||||
}
|
||||
|
||||
internal static void UpdatePluginLanguages()
|
||||
{
|
||||
RemoveResource(Infrastructure.Constant.Plugins);
|
||||
foreach (var plugin in PluginManager.GetPluginsForInterface<IPluginI18n>())
|
||||
{
|
||||
var location = Assembly.GetAssembly(plugin.Plugin.GetType()).Location;
|
||||
var directoryName = Path.GetDirectoryName(location);
|
||||
if (directoryName != null)
|
||||
{
|
||||
var internationalization = InternationalizationManager.Instance;
|
||||
var folder = Path.Combine(directoryName, internationalization.DirectoryName);
|
||||
|
||||
var file = internationalization.GetLanguageFile(folder);
|
||||
if (!string.IsNullOrEmpty(file))
|
||||
{
|
||||
var resource = new ResourceDictionary
|
||||
{
|
||||
Source = new Uri(file, UriKind.Absolute)
|
||||
};
|
||||
Application.Current.Resources.MergedDictionaries.Add(resource);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error($"|ResourceMerger.UpdatePluginLanguages|Can't find plugin path <{location}> for <{plugin.Metadata.Name}>");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -7,15 +7,18 @@ using System.Windows;
|
|||
using System.Windows.Controls;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
||||
namespace Wox.Core.Resource
|
||||
{
|
||||
public class Theme : Resource
|
||||
public class Theme
|
||||
{
|
||||
private static List<string> themeDirectories = new List<string>();
|
||||
public Settings Settings { get; set; }
|
||||
protected string DirectoryPath => Path.Combine(Constant.ProgramDirectory, DirectoryName);
|
||||
public string DirectoryName { get; protected set; }
|
||||
|
||||
public Theme()
|
||||
{
|
||||
|
|
@ -42,40 +45,47 @@ namespace Wox.Core.Resource
|
|||
}
|
||||
}
|
||||
|
||||
public void ChangeTheme(string themeName)
|
||||
public void ChangeTheme(string theme)
|
||||
{
|
||||
string themePath = GetThemePath(themeName);
|
||||
if (string.IsNullOrEmpty(themePath))
|
||||
{
|
||||
themePath = GetThemePath("Dark");
|
||||
if (string.IsNullOrEmpty(themePath))
|
||||
{
|
||||
throw new Exception("Change theme failed");
|
||||
}
|
||||
}
|
||||
const string dark = "Dark";
|
||||
bool valid;
|
||||
|
||||
Settings.Theme = themeName;
|
||||
ResourceMerger.UpdateResource(this);
|
||||
|
||||
// Exception of FindResource can't be cathed if global exception handle is set
|
||||
if (Environment.OSVersion.Version >= new Version(6, 2))
|
||||
string path = GetThemePath(theme);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
|
||||
bool blur;
|
||||
if (resource is bool)
|
||||
Log.Error($"|Theme.ChangeTheme|Theme path can't be found <{path}>, use default dark theme");
|
||||
path = GetThemePath(dark);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
blur = (bool)resource;
|
||||
valid = false;
|
||||
Log.Error($"|Theme.ChangeTheme|Default theme path can't be found <{path}>");
|
||||
}
|
||||
else
|
||||
{
|
||||
blur = false;
|
||||
valid = true;
|
||||
theme = dark;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
valid = true;
|
||||
}
|
||||
|
||||
if (valid)
|
||||
{
|
||||
Settings.Theme = theme;
|
||||
|
||||
var dicts = Application.Current.Resources.MergedDictionaries;
|
||||
// OnStartup, there is nothing to remove
|
||||
var oldResource = dicts.FirstOrDefault(d => d.Source.AbsolutePath == path) ?? new ResourceDictionary();
|
||||
dicts.Remove(oldResource);
|
||||
var newResource = GetResourceDictionary();
|
||||
dicts.Add(newResource);
|
||||
|
||||
SetBlurForWindow(Application.Current.MainWindow, blur);
|
||||
}
|
||||
}
|
||||
|
||||
public override ResourceDictionary GetResourceDictionary()
|
||||
public ResourceDictionary GetResourceDictionary()
|
||||
{
|
||||
var uri = GetThemePath(Settings.Theme);
|
||||
var dict = new ResourceDictionary
|
||||
|
|
@ -176,17 +186,31 @@ namespace Wox.Core.Resource
|
|||
/// <summary>
|
||||
/// Sets the blur for a window via SetWindowCompositionAttribute
|
||||
/// </summary>
|
||||
/// <param name="w">window to blur</param>
|
||||
/// <param name="blur">true/false - on or off correspondingly</param>
|
||||
private void SetBlurForWindow(Window w, bool blur)
|
||||
public void SetBlurForWindow()
|
||||
{
|
||||
if (blur)
|
||||
|
||||
// Exception of FindResource can't be cathed if global exception handle is set
|
||||
if (Environment.OSVersion.Version >= new Version(6, 2))
|
||||
{
|
||||
SetWindowAccent(w, AccentState.ACCENT_ENABLE_BLURBEHIND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowAccent(w, AccentState.ACCENT_DISABLED);
|
||||
var resource = Application.Current.TryFindResource("ThemeBlurEnabled");
|
||||
bool blur;
|
||||
if (resource is bool)
|
||||
{
|
||||
blur = (bool)resource;
|
||||
}
|
||||
else
|
||||
{
|
||||
blur = false;
|
||||
}
|
||||
|
||||
if (blur)
|
||||
{
|
||||
SetWindowAccent(Application.Current.MainWindow, AccentState.ACCENT_ENABLE_BLURBEHIND);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetWindowAccent(Application.Current.MainWindow, AccentState.ACCENT_DISABLED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -115,8 +115,6 @@
|
|||
<Compile Include="Resource\InternationalizationManager.cs" />
|
||||
<Compile Include="Resource\Language.cs" />
|
||||
<Compile Include="Resource\ThemeManager.cs" />
|
||||
<Compile Include="Resource\Resource.cs" />
|
||||
<Compile Include="Resource\ResourceMerger.cs" />
|
||||
<Compile Include="Plugin\PluginInstaller.cs" />
|
||||
<Compile Include="Plugin\JsonRPCPlugin.cs" />
|
||||
<Compile Include="Plugin\JsonPRCModel.cs" />
|
||||
|
|
|
|||
|
|
@ -4,8 +4,10 @@ using System.Timers;
|
|||
using System.Windows;
|
||||
using Wox.Core;
|
||||
using Wox.Core.Plugin;
|
||||
using Wox.Core.Resource;
|
||||
using Wox.Helper;
|
||||
using Wox.Infrastructure;
|
||||
using Wox.Infrastructure.Http;
|
||||
using Wox.Infrastructure.Image;
|
||||
using Wox.Infrastructure.Logger;
|
||||
using Wox.Infrastructure.UserSettings;
|
||||
|
|
@ -58,6 +60,18 @@ namespace Wox
|
|||
Current.MainWindow = window;
|
||||
Current.MainWindow.Title = Constant.Wox;
|
||||
|
||||
// happlebao todo temp fix for instance code logic
|
||||
// remove all dictionaries defined in xaml e.g.g App.xaml
|
||||
Current.Resources.MergedDictionaries.Clear();
|
||||
// load plugin before change language, because plugin language also needs be changed
|
||||
InternationalizationManager.Instance.Settings = _settings;
|
||||
InternationalizationManager.Instance.ChangeLanguage(_settings.Language);
|
||||
// main windows needs initialized before theme change because of blur settigns
|
||||
ThemeManager.Instance.Settings = _settings;
|
||||
ThemeManager.Instance.ChangeTheme(_settings.Theme);
|
||||
|
||||
Http.Proxy = _settings.Proxy;
|
||||
|
||||
RegisterExitEvents();
|
||||
|
||||
AutoStartup();
|
||||
|
|
@ -68,6 +82,7 @@ namespace Wox
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
private void AutoStartup()
|
||||
{
|
||||
if (_settings.StartWoxOnSystemStartup)
|
||||
|
|
|
|||
|
|
@ -60,8 +60,9 @@ namespace Wox
|
|||
|
||||
private void OnLoaded(object sender, RoutedEventArgs _)
|
||||
{
|
||||
// todo is there a way to set blur only once?
|
||||
ThemeManager.Instance.SetBlurForWindow();
|
||||
WindowsInteropHelper.DisableControlBox(this);
|
||||
ThemeManager.Instance.ChangeTheme(_settings.Theme);
|
||||
InitProgressbarAnimation();
|
||||
|
||||
_viewModel.PropertyChanged += (o, e) =>
|
||||
|
|
|
|||
|
|
@ -33,11 +33,7 @@ namespace Wox.ViewModel
|
|||
}
|
||||
};
|
||||
|
||||
// happlebao todo temp fix for instance code logic
|
||||
InternationalizationManager.Instance.Settings = Settings;
|
||||
InternationalizationManager.Instance.ChangeLanguage(Settings.Language);
|
||||
ThemeManager.Instance.Settings = Settings;
|
||||
Http.Proxy = Settings.Proxy;
|
||||
|
||||
}
|
||||
|
||||
public Settings Settings { get; set; }
|
||||
|
|
|
|||
Loading…
Reference in a new issue