diff --git a/src/LipUI/BuiltInPlugins/DefaultLipProxySetter/DefaultLipProxySetter.cs b/src/LipUI/BuiltInPlugins/DefaultLipProxySetter/DefaultLipProxySetter.cs index 41d40b4..bc20139 100644 --- a/src/LipUI/BuiltInPlugins/DefaultLipProxySetter/DefaultLipProxySetter.cs +++ b/src/LipUI/BuiltInPlugins/DefaultLipProxySetter/DefaultLipProxySetter.cs @@ -1,5 +1,4 @@ -using LipUI.Models; -using LipUI.Models.Lip; +using LipUI.Models.Lip; using LipUI.Models.Plugin; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; @@ -7,7 +6,7 @@ namespace LipUI.BuiltInPlugins.DefaultLipProxySetter; [LipUIModule] -internal class DefaultLipProxySetter : ILipuiPlugin +internal class DefaultLipProxySetter : IPlugin { private static class Strings { @@ -29,15 +28,26 @@ private static class Strings private static class DefaultProxies { - public const string Github = "github.bibk.top"; + public const string Github = "mirror.ghproxy.com"; } - void ILipuiPlugin.OnEnable(LipuiServices services) + void IPlugin.OnInitlalize(LipuiServices services) { - //todo (plugin config) - if (services.LipuiConfig.GeneralSettings.GithubProxy is DefaultProxies.Github) + var config = services.GetPluginConfig(this); + + var selfDisabled = config["SelfDisabled"]; + if (selfDisabled.IsNull) + config["SelfDisabled"] = false; + } + + void IPlugin.OnEnable(LipuiServices services) + { + var config = services.GetPluginConfig(this); + if (config["SelfDisabled"].As()) return; + config["SelfDisabled"] = true; + if (System.Globalization.CultureInfo.CurrentCulture.Name.ToLower() is "zh-cn") { services.DispatcherQueue.TryEnqueue(async () => @@ -97,7 +107,7 @@ void ILipuiPlugin.OnEnable(LipuiServices services) await services.ShowInfoBarAsync( severity: InfoBarSeverity.Warning, message: Strings.InfoBarMessage, - interval: TimeSpan.FromSeconds(10), + interval: TimeSpan.FromSeconds(30), barContent: stackPanel, cancellationToken: cts.Token); }); diff --git a/src/LipUI/BuiltInPlugins/LipuiTips/LipuiTips.cs b/src/LipUI/BuiltInPlugins/LipuiTips/LipuiTips.cs new file mode 100644 index 0000000..83dd4e4 --- /dev/null +++ b/src/LipUI/BuiltInPlugins/LipuiTips/LipuiTips.cs @@ -0,0 +1,5 @@ +namespace LipUI.BuiltInPlugins.LipuiTips; + +internal class LipuiTips +{ +} \ No newline at end of file diff --git a/src/LipUI/MainWindow/MainWindow.xaml.cs b/src/LipUI/MainWindow/MainWindow.xaml.cs index 3e0d38a..2f7f192 100644 --- a/src/LipUI/MainWindow/MainWindow.xaml.cs +++ b/src/LipUI/MainWindow/MainWindow.xaml.cs @@ -87,9 +87,9 @@ private void RootBorder_DragOver(object sender, DragEventArgs e) e.DragUIOverride.IsGlyphVisible = false; } - private async void RootBorder_Loaded(object sender, RoutedEventArgs e) + private void RootBorder_Loaded(object sender, RoutedEventArgs e) { - await PluginSystem.LoadAsync(); + Task.Run(PluginSystem.LoadAsync); var timer = DispatcherQueue.CreateTimer(); timer.Interval = TimeSpan.FromSeconds(60); diff --git a/src/LipUI/MainWindow/MainWindowNavigationView.cs b/src/LipUI/MainWindow/MainWindowNavigationView.cs index 479b9ee..3ed0806 100644 --- a/src/LipUI/MainWindow/MainWindowNavigationView.cs +++ b/src/LipUI/MainWindow/MainWindowNavigationView.cs @@ -95,7 +95,7 @@ private async void NavView_ItemInvoked(NavigationView sender, NavigationViewItem if (args.InvokedItemContainer.Tag is null) return; - if (args.InvokedItemContainer.Tag is ILipuiPluginUI plugin) + if (args.InvokedItemContainer.Tag is IUIPlugin plugin) { try { diff --git a/src/LipUI/MainWindow/MainWindowPluginsHandler.cs b/src/LipUI/MainWindow/MainWindowPluginsHandler.cs index 4e08396..975a45b 100644 --- a/src/LipUI/MainWindow/MainWindowPluginsHandler.cs +++ b/src/LipUI/MainWindow/MainWindowPluginsHandler.cs @@ -12,12 +12,12 @@ public static void InitEventHandlers() PluginSystem.PluginDisabled += PluginSystem_PluginDisabled; } - private static readonly HashSet enabledModules = []; - private static void PluginSystem_PluginEnabled(ILipuiPlugin obj) + private static readonly HashSet enabledModules = []; + private static void PluginSystem_PluginEnabled(IPlugin obj) { lock (enabledModules) { - if (obj is ILipuiPluginUI uiPlugin) + if (obj is IUIPlugin uiPlugin) { enabledModules.Add(uiPlugin); enabled?.Invoke(uiPlugin); @@ -25,11 +25,11 @@ private static void PluginSystem_PluginEnabled(ILipuiPlugin obj) } } - private static void PluginSystem_PluginDisabled(ILipuiPlugin obj) + private static void PluginSystem_PluginDisabled(IPlugin obj) { lock (enabledModules) { - if (obj is ILipuiPluginUI uiPlugin) + if (obj is IUIPlugin uiPlugin) { enabledModules.Remove(uiPlugin); disabled?.Invoke(uiPlugin); @@ -37,15 +37,15 @@ private static void PluginSystem_PluginDisabled(ILipuiPlugin obj) } } - private static Action? enabled; - private static Action? disabled; + private static Action? enabled; + private static Action? disabled; private readonly object _lock = new(); private uint navViewBarEnabledPluginsCount; - private readonly Dictionary views = []; + private readonly Dictionary views = []; - private void PluginEnabled(ILipuiPluginUI plugin) + private void PluginEnabled(IUIPlugin plugin) { DispatcherQueue.TryEnqueue(async () => { @@ -86,7 +86,7 @@ private void PluginEnabled(ILipuiPluginUI plugin) }); } - private void PluginDisabled(ILipuiPluginUI plugin) + private void PluginDisabled(IUIPlugin plugin) { DispatcherQueue.TryEnqueue(async () => { diff --git a/src/LipUI/Models/Config.cs b/src/LipUI/Models/Config.cs index e0e91fc..85894c1 100644 --- a/src/LipUI/Models/Config.cs +++ b/src/LipUI/Models/Config.cs @@ -20,6 +20,8 @@ internal static class DefaultSettings public const string DataDirectory = ".lipui"; + public const string ConfigsDirectory = DataDirectory + "/configs"; + public const string LipRepoOwner = "lippkg"; public const string LipRepoName = "lip"; @@ -207,7 +209,7 @@ public void ResetPersonalizationSettings() PersonalizationSettings.ResetColors = true; } - private static readonly JsonSerializerOptions options = new() + internal static readonly JsonSerializerOptions options = new() { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping diff --git a/src/LipUI/Models/InternalServices.cs b/src/LipUI/Models/InternalServices.cs index 71d3cb8..4d2e44e 100644 --- a/src/LipUI/Models/InternalServices.cs +++ b/src/LipUI/Models/InternalServices.cs @@ -122,4 +122,11 @@ public static void ShowInfoBar( internal static void OnWindowClosed() => WindowClosed?.Invoke(); public static ApplicationTheme ApplicationTheme { get; internal set; } + + public static HttpClient HttpClient { get; } = new HttpClient( + new HttpClientHandler() { ClientCertificateOptions = ClientCertificateOption.Automatic }) + { + Timeout = TimeSpan.FromSeconds(5), + DefaultRequestHeaders = { ExpectContinue = false } + }; } diff --git a/src/LipUI/Models/Main.cs b/src/LipUI/Models/Main.cs index 074d0fc..13746e3 100644 --- a/src/LipUI/Models/Main.cs +++ b/src/LipUI/Models/Main.cs @@ -111,6 +111,9 @@ private static void InitializeConfig() private static bool saveRequesting = false; private static void ConfigPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) + => ConfigChanged(); + + internal static void ConfigChanged() { configChanged = true; configEditCount++; @@ -121,6 +124,8 @@ private static void ConfigPropertyChanged(object? sender, System.ComponentModel. internal static void SaveConfig() { + Task.Run(Plugin.PluginConfigManager.Save); + if (saving) { saveRequesting = true; diff --git a/src/LipUI/Models/Plugin/ConfigCollection.cs b/src/LipUI/Models/Plugin/ConfigCollection.cs new file mode 100644 index 0000000..27539af --- /dev/null +++ b/src/LipUI/Models/Plugin/ConfigCollection.cs @@ -0,0 +1,154 @@ +using System.Collections; +using System.Collections.Specialized; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace LipUI.Models.Plugin; + +public struct ConfigItem +{ + [JsonPropertyName("value")] + public string Value { get; set; } + + [JsonIgnore] + public readonly bool IsNull => Value is "null"; + + public readonly T As(IFormatProvider? formatProvider = null) + where T : IParsable + => T.Parse(Value, formatProvider); + + public static implicit operator ConfigItem(string value) => new() { Value = value }; + + public static implicit operator ConfigItem(int value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(double value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(bool value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(Guid value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(DateTime value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(TimeSpan value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(Version value) => new() { Value = value.ToString() }; + + public static implicit operator ConfigItem(Uri value) => new() { Value = value.ToString() }; + + public static implicit operator string(ConfigItem item) => item.Value; + + public static ConfigItem Create(T value) + where T : IParsable + => new() { Value = value.ToString() ?? "null" }; + + public override readonly string ToString() => Value; +} + +public class ConfigCollection + : IDictionary + , INotifyCollectionChanged +{ + private readonly Dictionary items; + internal bool Changed { get; set; } = false; + + internal ConfigCollection() + { + items = []; + CollectionChanged += ConfigCollection_CollectionChanged; + } + + internal ConfigCollection(string json) + { + items = JsonSerializer.Deserialize>(json) ?? throw new ArgumentNullException(nameof(json)); + CollectionChanged += ConfigCollection_CollectionChanged; + } + + public ConfigItem this[string key] + { + get + { + if (items.TryGetValue(key, out var value)) + return value; + + var item = new ConfigItem() { Value = "null" }; + items.Add(key, item); + return item; + } + set + { + items[key] = value; + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset)); + } + } + + public ICollection Keys => items.Keys; + + public ICollection Values => items.Values; + + public int Count => items.Count; + + public bool IsReadOnly => ((ICollection>)items).IsReadOnly; + + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + private void ConfigCollection_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + Changed = true; + Main.ConfigChanged(); + } + + public void Add(string key, ConfigItem value) + { + items.Add(key, value); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset)); + } + + public void Add(KeyValuePair item) + { + ((ICollection>)items).Add(item); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset)); + } + + public void Clear() + { + ((ICollection>)items).Clear(); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset)); + } + + public bool Contains(KeyValuePair item) + => ((ICollection>)items).Contains(item); + + public bool ContainsKey(string key) + => items.ContainsKey(key); + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + => ((ICollection>)items).CopyTo(array, arrayIndex); + + public IEnumerator> GetEnumerator() + => items.GetEnumerator(); + + public bool Remove(string key) + { + var ret = ((IDictionary)items).Remove(key); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Remove)); + return ret; + } + + public bool Remove(KeyValuePair item) + { + var ret = ((ICollection>)items).Remove(item); + CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Remove)); + return ret; + } + + public bool TryGetValue(string key, [MaybeNullWhen(false)] out ConfigItem value) + => items.TryGetValue(key, out value); + + IEnumerator IEnumerable.GetEnumerator() + => items.GetEnumerator(); + + internal string Serialize() => JsonSerializer.Serialize(items, Config.options); + + internal static ConfigCollection Deserialize([StringSyntax("Json")] string json) => new(json); +} diff --git a/src/LipUI/Models/Plugin/ILipuiPluginModule.cs b/src/LipUI/Models/Plugin/IHomePageModule.cs similarity index 87% rename from src/LipUI/Models/Plugin/ILipuiPluginModule.cs rename to src/LipUI/Models/Plugin/IHomePageModule.cs index 4488b27..5ba7903 100644 --- a/src/LipUI/Models/Plugin/ILipuiPluginModule.cs +++ b/src/LipUI/Models/Plugin/IHomePageModule.cs @@ -4,7 +4,7 @@ namespace LipUI.Models.Plugin; -public interface ILipuiPluginModule : ILipuiPlugin +public interface IHomePageModule : IPlugin { public Type PageType { get; } diff --git a/src/LipUI/Models/Plugin/ILipuiPlugin.cs b/src/LipUI/Models/Plugin/IPlugin.cs similarity index 83% rename from src/LipUI/Models/Plugin/ILipuiPlugin.cs rename to src/LipUI/Models/Plugin/IPlugin.cs index 141415c..a69781c 100644 --- a/src/LipUI/Models/Plugin/ILipuiPlugin.cs +++ b/src/LipUI/Models/Plugin/IPlugin.cs @@ -5,7 +5,7 @@ public sealed class LipUIModuleAttribute : Attribute { } -public interface ILipuiPlugin +public interface IPlugin { public string PluginName { get; } @@ -13,7 +13,7 @@ public interface ILipuiPlugin public Guid Guid { get; } - public void OnInitlalize(LipuiRuntimeInfo info) { } + public void OnInitlalize(LipuiServices services) { } public void OnEnable(LipuiServices services) { } diff --git a/src/LipUI/Models/Plugin/ILipuiPluginUI.cs b/src/LipUI/Models/Plugin/IUIPlugin.cs similarity index 85% rename from src/LipUI/Models/Plugin/ILipuiPluginUI.cs rename to src/LipUI/Models/Plugin/IUIPlugin.cs index 8889502..5f6d422 100644 --- a/src/LipUI/Models/Plugin/ILipuiPluginUI.cs +++ b/src/LipUI/Models/Plugin/IUIPlugin.cs @@ -2,7 +2,7 @@ namespace LipUI.Models.Plugin; -public interface ILipuiPluginUI : ILipuiPlugin +public interface IUIPlugin : IPlugin { public IconElement NavigatonBarIcon { get; } diff --git a/src/LipUI/Models/Plugin/LipuiServices.cs b/src/LipUI/Models/Plugin/LipuiServices.cs index ad21d2b..e0d1cc2 100644 --- a/src/LipUI/Models/Plugin/LipuiServices.cs +++ b/src/LipUI/Models/Plugin/LipuiServices.cs @@ -63,11 +63,20 @@ public void ShowInfoBar( CancellationToken cancellationToken = default) => InternalServices.ShowInfoBar(ex, containsStacktrace, severity, interval, barContent, completed, cancellationToken); - public string GetPluginKey(ILipuiPlugin plugin) => PluginSystem.GetPluginKey(plugin); + public string GetPluginKey(IPlugin plugin) => PluginSystem.GetPluginKey(plugin); + + public ConfigCollection GetPluginConfig(IPlugin plugin) + => PluginConfigManager.GetOrCreatePluginConfig(plugin); public string? CurrentServerDirectory => Main.Config.SelectedServer?.WorkingDirectory; public Config LipuiConfig => Main.Config; public DispatcherQueue DispatcherQueue => InternalServices.MainWindow!.DispatcherQueue; + + public LipuiRuntimeInfo LipuiInfo => new() + { + Theme = Main.Config.PersonalizationSettings.ColorTheme, + ApplicationWindow = InternalServices.MainWindow ?? throw new NullReferenceException() + }; } diff --git a/src/LipUI/Models/Plugin/PluginConfigManager.cs b/src/LipUI/Models/Plugin/PluginConfigManager.cs new file mode 100644 index 0000000..f9793b4 --- /dev/null +++ b/src/LipUI/Models/Plugin/PluginConfigManager.cs @@ -0,0 +1,122 @@ +using System.Diagnostics.CodeAnalysis; +using System.Text.RegularExpressions; +using PluginKey = System.String; + +namespace LipUI.Models.Plugin; + +internal record struct PluginConfigFileInfo(string AssemblyName, string Name, Guid Guid); + +internal static partial class PluginConfigManager +{ + private static readonly Dictionary pluginConfigs = []; + + [GeneratedRegex(@"(?.+?)\+(?.+)\+(?[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12})$")] + private static partial Regex PluginConfigInfoRegex(); + + private static bool TryParse(string str, [NotNullWhen(true)] out PluginConfigFileInfo info) + { + info = default; + + var match = PluginConfigInfoRegex().Match(str); + if (match.Success is false) + return false; + + info = new(match.Groups["assembly_name"].Value, match.Groups["name"].Value, Guid.Parse(match.Groups["guid"].Value)); + return true; + } + + public static void Load() + { + lock (pluginConfigs) + { + var dir = new DirectoryInfo(DefaultSettings.ConfigsDirectory); + if (dir.Exists is false) + dir.Create(); + + foreach (var file in dir.EnumerateFiles()) + { + var key = Path.GetFileNameWithoutExtension(file.Name); + + if (TryParse(key, out var info) is false) + continue; + + pluginConfigs.Add(key, (info, ConfigCollection.Deserialize(File.ReadAllText(file.FullName)))); + } + } + } + + public static void Save(PluginKey key, ConfigCollection config) + { + lock (config) + { + if (config.Changed is false) + return; + + var path = Path.Combine(DefaultSettings.ConfigsDirectory, $"{key}.json"); + if (File.Exists(path)) + File.Delete(path); + File.WriteAllText(path, config.Serialize()); + + config.Changed = false; + } + } + + public static void Save() + { + lock (pluginConfigs) + { + foreach (var (key, (_, config)) in pluginConfigs) + Save(key, config); + } + } + + public static ConfigCollection? InitPluginConfig(PluginKey key) + { + if (TryParse(key, out var info) is false) + return null; + + lock (pluginConfigs) + { + if (pluginConfigs.ContainsKey(key)) + return null; + + var ret = new ConfigCollection(); + + pluginConfigs.Add(key, (info, ret)); + + return ret; + } + } + + public static ConfigCollection? InitPluginConfig(IPlugin plugin) + => InitPluginConfig(PluginSystem.GetPluginKey(plugin)); + + public static bool TryGetPluginConfig(PluginKey key, [NotNullWhen(true)] out ConfigCollection? config) + { + config = null; + + if (TryParse(key, out var _) && pluginConfigs.TryGetValue(key, out var temp) is true) + { + config = temp.Config; + return true; + } + + return false; + } + + public static bool TryGetPluginConfig(IPlugin plugin, [NotNullWhen(true)] out ConfigCollection? config) + => TryGetPluginConfig(PluginSystem.GetPluginKey(plugin), out config); + + public static ConfigCollection GetOrCreatePluginConfig(PluginKey key) + { + if (TryGetPluginConfig(key, out var config)) + return config; + + return InitPluginConfig(key) ?? throw new NullReferenceException(); + } + + public static ConfigCollection GetOrCreatePluginConfig(IPlugin plugin) + => GetOrCreatePluginConfig(PluginSystem.GetPluginKey(plugin)); + + public static bool Contains(IPlugin plugin) => pluginConfigs.ContainsKey(PluginSystem.GetPluginKey(plugin)); +} diff --git a/src/LipUI/Models/Plugin/PluginSystem.cs b/src/LipUI/Models/Plugin/PluginSystem.cs index bc6084c..770f81c 100644 --- a/src/LipUI/Models/Plugin/PluginSystem.cs +++ b/src/LipUI/Models/Plugin/PluginSystem.cs @@ -1,7 +1,7 @@ using LipUI.Pages.Home.Modules; using System.Reflection; using System.Runtime.Loader; -using guid_string = System.String; +using GuidString = System.String; namespace LipUI.Models.Plugin; @@ -9,19 +9,20 @@ internal static class PluginSystem { static PluginSystem() { + PluginConfigManager.Load(); ModulesPage.InitEventHandlers(); MainWindow.InitEventHandlers(); } - public static IEnumerable? Plugins { get; private set; } + public static IEnumerable? Plugins { get; private set; } - public static IEnumerable? UIPlugins { get; private set; } + public static IEnumerable? UIPlugins { get; private set; } - public static IEnumerable? Modules { get; private set; } + public static IEnumerable? Modules { get; private set; } - private static readonly HashSet enabledPlugins = []; + private static readonly HashSet enabledPlugins = []; - private static readonly Dictionary guidWithPlugins = []; + private static readonly Dictionary guidWithPlugins = []; /// @@ -48,11 +49,9 @@ public static async ValueTask LoadAsync() private static async ValueTask?> GetPluginTypes() { var dir = Path.Combine(Main.WorkingDirectory, DefaultSettings.PluginsDir); + if (Directory.Exists(dir) is false) - { Directory.CreateDirectory(dir); - return null; - } List pluginTypes = []; var ctx = AssemblyLoadContext.GetLoadContext(Assembly.GetExecutingAssembly())!; @@ -60,7 +59,7 @@ public static async ValueTask LoadAsync() var dirInfo = new DirectoryInfo(dir); var types = from type in Assembly.GetExecutingAssembly().GetTypes() - where type.IsAssignableTo(typeof(ILipuiPlugin)) && type.GetCustomAttribute() is not null + where type.IsAssignableTo(typeof(IPlugin)) && type.GetCustomAttribute() is not null select type; pluginTypes.AddRange(types); @@ -84,7 +83,7 @@ where type.IsAssignableTo(typeof(ILipuiPlugin)) && type.GetCustomAttribute() is not null + where type.IsAssignableTo(typeof(IPlugin)) && type.GetCustomAttribute() is not null select type; return types; } @@ -95,11 +94,11 @@ where type.IsAssignableTo(typeof(ILipuiPlugin)) && type.GetCustomAttribute, IEnumerable, IEnumerable)> CreateInstances(IEnumerable types) + private static async ValueTask<(IEnumerable, IEnumerable, IEnumerable)> CreateInstances(IEnumerable types) { - List instances = new(types.Count()); - List uiInstances = []; - List modules = []; + List instances = new(types.Count()); + List uiInstances = []; + List modules = []; foreach (var type in types) { @@ -107,7 +106,7 @@ where type.IsAssignableTo(typeof(ILipuiPlugin)) && type.GetCustomAttribute plugins) + private static async ValueTask InitializePlugins(IEnumerable plugins) { - var info = new LipuiRuntimeInfo() - { - Theme = Main.Config.PersonalizationSettings.ColorTheme, - ApplicationWindow = InternalServices.MainWindow ?? throw new NullReferenceException() - }; foreach (var plugin in plugins) { try { - await Task.Run(() => plugin.OnInitlalize(info)); + await Task.Run(() => plugin.OnInitlalize(LipuiServices.Default)); } catch (Exception ex) { @@ -154,10 +148,10 @@ private static async ValueTask InitializePlugins(IEnumerable plugi } } - public static string GetPluginKey(ILipuiPlugin plugin) + public static string GetPluginKey(IPlugin plugin) => $"{plugin.GetType().Assembly.GetName().Name}+{plugin.PluginName}+{plugin.Guid}"; - private static async ValueTask EnablePlugins(IEnumerable plugins) + private static async ValueTask EnablePlugins(IEnumerable plugins) { var enableInfo = Main.Config.PluginEanbleInfo; List<(string, bool)> temp = new(8); @@ -191,7 +185,7 @@ private static async ValueTask EnablePlugins(IEnumerable plugins) Main.Config.AddPluginEnableInfo(key, val); } - public static void EnablePlugin(ILipuiPlugin plugin) + public static void EnablePlugin(IPlugin plugin) { try { @@ -211,7 +205,7 @@ public static void EnablePlugin(ILipuiPlugin plugin) } } - public static void DisablePlugin(ILipuiPlugin plugin) + public static void DisablePlugin(IPlugin plugin) { try { @@ -231,9 +225,9 @@ public static void DisablePlugin(ILipuiPlugin plugin) } } - public static bool IsPluginEnabled(ILipuiPlugin plugin) + public static bool IsPluginEnabled(IPlugin plugin) => enabledPlugins.Contains(plugin); - public static event Action? PluginEnabled; - public static event Action? PluginDisabled; + public static event Action? PluginEnabled; + public static event Action? PluginDisabled; } diff --git a/src/LipUI/Pages/Home/Modules/BdsPropertiesEditorPage.xaml.cs b/src/LipUI/Pages/Home/Modules/BdsPropertiesEditorPage.xaml.cs index 8192820..0f8ad00 100644 --- a/src/LipUI/Pages/Home/Modules/BdsPropertiesEditorPage.xaml.cs +++ b/src/LipUI/Pages/Home/Modules/BdsPropertiesEditorPage.xaml.cs @@ -16,7 +16,7 @@ namespace LipUI.Pages.Home.Modules; [LipUIModule] -internal class BdsPropertiesEditorPage_Module : ILipuiPluginModule +internal class BdsPropertiesEditorPage_Module : IHomePageModule { public string PluginName => "modules$title$propertiesEditor".GetLocalized(); diff --git a/src/LipUI/Pages/Home/Modules/ModuleIcon.xaml.cs b/src/LipUI/Pages/Home/Modules/ModuleIcon.xaml.cs index 59d7b38..db7d31f 100644 --- a/src/LipUI/Pages/Home/Modules/ModuleIcon.xaml.cs +++ b/src/LipUI/Pages/Home/Modules/ModuleIcon.xaml.cs @@ -12,11 +12,11 @@ namespace LipUI.Pages.Home.Modules; public sealed partial class ModuleIcon : UserControl { - internal static Dictionary Modules { get; private set; } = new(); + internal static Dictionary Modules { get; private set; } = new(); public Type? PageType { get; private set; } - public ModuleIcon(ILipuiPluginModule module) + public ModuleIcon(IHomePageModule module) { InitializeComponent(); diff --git a/src/LipUI/Pages/Home/Modules/ModulesPage.xaml.cs b/src/LipUI/Pages/Home/Modules/ModulesPage.xaml.cs index 9161a50..c511f19 100644 --- a/src/LipUI/Pages/Home/Modules/ModulesPage.xaml.cs +++ b/src/LipUI/Pages/Home/Modules/ModulesPage.xaml.cs @@ -10,7 +10,7 @@ namespace LipUI.Pages.Home.Modules; -internal class ModulesPage_Module : ILipuiPluginModule +internal class ModulesPage_Module : IHomePageModule { public FrameworkElement IconContent => new Viewbox(); @@ -37,21 +37,21 @@ public static void InitEventHandlers() PluginSystem.PluginDisabled += PluginSystem_PluginDisabled; } - private static readonly HashSet enabledModules = new(); - private static void PluginSystem_PluginEnabled(ILipuiPlugin obj) + private static readonly HashSet enabledModules = new(); + private static void PluginSystem_PluginEnabled(IPlugin obj) { lock (enabledModules) { - if (obj is ILipuiPluginModule module) + if (obj is IHomePageModule module) enabledModules.Add(module); } } - private static void PluginSystem_PluginDisabled(ILipuiPlugin obj) + private static void PluginSystem_PluginDisabled(IPlugin obj) { lock (enabledModules) { - if (obj is ILipuiPluginModule module) + if (obj is IHomePageModule module) enabledModules.Remove(module); } } diff --git a/src/LipUI/Pages/Index/IndexPage.xaml.cs b/src/LipUI/Pages/Index/IndexPage.xaml.cs index 1712e73..3b16186 100644 --- a/src/LipUI/Pages/Index/IndexPage.xaml.cs +++ b/src/LipUI/Pages/Index/IndexPage.xaml.cs @@ -65,7 +65,7 @@ private static async ValueTask RequestLipIndexAsync(string lipApiUrl) { static void ThrowException(string api) => throw new NullReferenceException($"Failed to get index : {api}"); - using var client = new HttpClient(); + using var client = InternalServices.HttpClient; //foreach all lip index pages diff --git a/src/LipUI/Pages/LipExecutionPanel/LipInstallerView.xaml.cs b/src/LipUI/Pages/LipExecutionPanel/LipInstallerView.xaml.cs index 9b00f2b..c98cc8a 100644 --- a/src/LipUI/Pages/LipExecutionPanel/LipInstallerView.xaml.cs +++ b/src/LipUI/Pages/LipExecutionPanel/LipInstallerView.xaml.cs @@ -34,7 +34,7 @@ private record InstallerInfo(string AssetUrl, string Tag, string PublishedTime, private static async ValueTask RequestLipInstallerInfo() { - using var client = new HttpClient(); + var client = InternalServices.HttpClient; // Fetch latest release from GitHub API client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json"); @@ -80,23 +80,18 @@ void InternalServices_WindowClosed() try { - using var client = new HttpClient(new HttpClientHandler() { ClientCertificateOptions = ClientCertificateOption.Automatic }) - { - Timeout = TimeSpan.FromSeconds(5), - DefaultRequestHeaders = { ExpectContinue = false } - }; + var client = InternalServices.HttpClient; HttpResponseMessage response; - try - { - response = await client.GetAsync(info.AssetUrl, HttpCompletionOption.ResponseHeadersRead); - } - catch (Exception ex) - { - await InternalServices.ShowInfoBarAsync(ex, severity: InfoBarSeverity.Warning); - response = await client.GetAsync($"{Main.Config.GeneralSettings.GithubProxy}/{info.AssetUrl}"); - } + string url; + var proxy = Main.Config.GeneralSettings.GithubProxy; + if (string.IsNullOrWhiteSpace(proxy)) + url = info.AssetUrl; + else + url = $"{(proxy.StartsWith("https://") ? "" : $"https://")}{proxy}/{info.AssetUrl}"; + + response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead); var input = await response.Content.ReadAsStreamAsync(); diff --git a/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml b/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml index 82f5a11..cbf5011 100644 --- a/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml +++ b/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml @@ -12,7 +12,8 @@ Padding="12,4,12,4"> + x:Name="PluginsListView" + CharacterSpacing="4"/> diff --git a/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml.cs b/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml.cs index 3a624d8..bae72db 100644 --- a/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml.cs +++ b/src/LipUI/Pages/ModuleManager/LipuiPluginsView.xaml.cs @@ -16,9 +16,9 @@ public sealed partial class LipuiPluginsView : UserControl private readonly Brush TextFillColorPrimaryBrush = (Brush)Application.Current.Resources["TextFillColorPrimaryBrush"]; private readonly Brush TextFillColorSecondaryBrush = (Brush)Application.Current.Resources["TextFillColorSecondaryBrush"]; - private readonly IEnumerable plugins; + private readonly IEnumerable plugins; - public LipuiPluginsView(IEnumerable plugins) + public LipuiPluginsView(IEnumerable plugins) { InitializeComponent(); @@ -28,7 +28,7 @@ public LipuiPluginsView(IEnumerable plugins) public async ValueTask InitializeUIAsync() { - Dictionary> assemblyAndPlugins = new(); + Dictionary> assemblyAndPlugins = []; foreach (var plugin in plugins) { @@ -36,7 +36,7 @@ public async ValueTask InitializeUIAsync() { var assembly = plugin.GetType().Assembly; if (assemblyAndPlugins.TryGetValue(assembly, out var list) is false) - assemblyAndPlugins[assembly] = list = new(); + assemblyAndPlugins[assembly] = list = []; list.Add(plugin); } @@ -118,28 +118,29 @@ public async ValueTask InitializeUIAsync() var grid = new Grid() { + Margin = new(4), RowSpacing = 2, ColumnSpacing = 2, RowDefinitions = - { - new() { Height = new(1, GridUnitType.Star) }, - new() { Height = new(1, GridUnitType.Star) } - }, + { + new() { Height = new(1, GridUnitType.Star) }, + new() { Height = new(1, GridUnitType.Star) } + }, ColumnDefinitions = - { - new() { Width = new(1, GridUnitType.Star) }, - new() { Width = new(1, GridUnitType.Star) }, - new() { Width = new(4, GridUnitType.Star) }, - new() { Width = new(2, GridUnitType.Star) }, - }, + { + new() { Width = new(1, GridUnitType.Star) }, + new() { Width = new(1, GridUnitType.Star) }, + new() { Width = new(4, GridUnitType.Star) }, + new() { Width = new(2, GridUnitType.Star) }, + }, Children = - { - pluginNameTextBlock, - assemblyNameTextBlock, - assemblyPathTextBlock, - guidTextBlock, - swich - } + { + pluginNameTextBlock, + assemblyNameTextBlock, + assemblyPathTextBlock, + guidTextBlock, + swich + } }; PluginsListView.Items.Add(grid); }