Skip to content
This repository has been archived by the owner on Jan 26, 2025. It is now read-only.

Commit

Permalink
feat: plugin config system & fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
Pd233 committed Feb 29, 2024
1 parent 0cbc8bc commit 5bf5ecb
Show file tree
Hide file tree
Showing 22 changed files with 411 additions and 106 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
using LipUI.Models;
using LipUI.Models.Lip;
using LipUI.Models.Lip;
using LipUI.Models.Plugin;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace LipUI.BuiltInPlugins.DefaultLipProxySetter;

[LipUIModule]
internal class DefaultLipProxySetter : ILipuiPlugin
internal class DefaultLipProxySetter : IPlugin
{
private static class Strings
{
Expand All @@ -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<bool>())
return;

config["SelfDisabled"] = true;

if (System.Globalization.CultureInfo.CurrentCulture.Name.ToLower() is "zh-cn")
{
services.DispatcherQueue.TryEnqueue(async () =>
Expand Down Expand Up @@ -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);
});
Expand Down
5 changes: 5 additions & 0 deletions src/LipUI/BuiltInPlugins/LipuiTips/LipuiTips.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
namespace LipUI.BuiltInPlugins.LipuiTips;

internal class LipuiTips
{
}
4 changes: 2 additions & 2 deletions src/LipUI/MainWindow/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/LipUI/MainWindow/MainWindowNavigationView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
20 changes: 10 additions & 10 deletions src/LipUI/MainWindow/MainWindowPluginsHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,40 +12,40 @@ public static void InitEventHandlers()
PluginSystem.PluginDisabled += PluginSystem_PluginDisabled;
}

private static readonly HashSet<ILipuiPluginUI> enabledModules = [];
private static void PluginSystem_PluginEnabled(ILipuiPlugin obj)
private static readonly HashSet<IUIPlugin> 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);
}
}
}

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);
}
}
}

private static Action<ILipuiPluginUI>? enabled;
private static Action<ILipuiPluginUI>? disabled;
private static Action<IUIPlugin>? enabled;
private static Action<IUIPlugin>? disabled;

private readonly object _lock = new();
private uint navViewBarEnabledPluginsCount;

private readonly Dictionary<ILipuiPluginUI, NavigationViewItemBase> views = [];
private readonly Dictionary<IUIPlugin, NavigationViewItemBase> views = [];

private void PluginEnabled(ILipuiPluginUI plugin)
private void PluginEnabled(IUIPlugin plugin)
{
DispatcherQueue.TryEnqueue(async () =>
{
Expand Down Expand Up @@ -86,7 +86,7 @@ private void PluginEnabled(ILipuiPluginUI plugin)
});
}

private void PluginDisabled(ILipuiPluginUI plugin)
private void PluginDisabled(IUIPlugin plugin)
{
DispatcherQueue.TryEnqueue(async () =>
{
Expand Down
4 changes: 3 additions & 1 deletion src/LipUI/Models/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions src/LipUI/Models/InternalServices.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
};
}
5 changes: 5 additions & 0 deletions src/LipUI/Models/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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++;
Expand All @@ -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;
Expand Down
154 changes: 154 additions & 0 deletions src/LipUI/Models/Plugin/ConfigCollection.cs
Original file line number Diff line number Diff line change
@@ -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<T>(IFormatProvider? formatProvider = null)
where T : IParsable<T>
=> 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>(T value)
where T : IParsable<T>
=> new() { Value = value.ToString() ?? "null" };

public override readonly string ToString() => Value;
}

public class ConfigCollection
: IDictionary<string, ConfigItem>
, INotifyCollectionChanged
{
private readonly Dictionary<string, ConfigItem> items;
internal bool Changed { get; set; } = false;

internal ConfigCollection()
{
items = [];
CollectionChanged += ConfigCollection_CollectionChanged;
}

internal ConfigCollection(string json)
{
items = JsonSerializer.Deserialize<Dictionary<string, ConfigItem>>(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<string> Keys => items.Keys;

public ICollection<ConfigItem> Values => items.Values;

public int Count => items.Count;

public bool IsReadOnly => ((ICollection<KeyValuePair<string, ConfigItem>>)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<string, ConfigItem> item)
{
((ICollection<KeyValuePair<string, ConfigItem>>)items).Add(item);
CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset));
}

public void Clear()
{
((ICollection<KeyValuePair<string, ConfigItem>>)items).Clear();
CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Reset));
}

public bool Contains(KeyValuePair<string, ConfigItem> item)
=> ((ICollection<KeyValuePair<string, ConfigItem>>)items).Contains(item);

public bool ContainsKey(string key)
=> items.ContainsKey(key);

public void CopyTo(KeyValuePair<string, ConfigItem>[] array, int arrayIndex)
=> ((ICollection<KeyValuePair<string, ConfigItem>>)items).CopyTo(array, arrayIndex);

public IEnumerator<KeyValuePair<string, ConfigItem>> GetEnumerator()
=> items.GetEnumerator();

public bool Remove(string key)
{
var ret = ((IDictionary<string, ConfigItem>)items).Remove(key);
CollectionChanged?.Invoke(this, new(NotifyCollectionChangedAction.Remove));
return ret;
}

public bool Remove(KeyValuePair<string, ConfigItem> item)
{
var ret = ((ICollection<KeyValuePair<string, ConfigItem>>)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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

namespace LipUI.Models.Plugin;

public interface ILipuiPluginModule : ILipuiPlugin
public interface IHomePageModule : IPlugin
{
public Type PageType { get; }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@ public sealed class LipUIModuleAttribute : Attribute
{
}

public interface ILipuiPlugin
public interface IPlugin
{
public string PluginName { get; }

public bool DefaultEnabled { get; }

public Guid Guid { get; }

public void OnInitlalize(LipuiRuntimeInfo info) { }
public void OnInitlalize(LipuiServices services) { }

public void OnEnable(LipuiServices services) { }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace LipUI.Models.Plugin;

public interface ILipuiPluginUI : ILipuiPlugin
public interface IUIPlugin : IPlugin
{
public IconElement NavigatonBarIcon { get; }

Expand Down
Loading

0 comments on commit 5bf5ecb

Please sign in to comment.