From 67027eb74b392380e588e00a1e801394bd6514bd Mon Sep 17 00:00:00 2001 From: Kevin Zhang Date: Tue, 17 Aug 2021 00:50:36 +0800 Subject: [PATCH] Allow JsonRPCPlugin.cs to have setting control --- Flow.Launcher.Core/Plugin/JsonPRCModel.cs | 2 +- Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs | 130 ++++++++++++++++++++- Flow.Launcher.Core/Plugin/PythonPlugin.cs | 7 +- 3 files changed, 128 insertions(+), 11 deletions(-) diff --git a/Flow.Launcher.Core/Plugin/JsonPRCModel.cs b/Flow.Launcher.Core/Plugin/JsonPRCModel.cs index 5232e46da..3dcefc094 100644 --- a/Flow.Launcher.Core/Plugin/JsonPRCModel.cs +++ b/Flow.Launcher.Core/Plugin/JsonPRCModel.cs @@ -45,7 +45,7 @@ namespace Flow.Launcher.Core.Plugin public string DebugMessage { get; set; } } - + public class JsonRPCRequestModel { public string Method { get; set; } diff --git a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs index 65977219d..d1bfaee21 100644 --- a/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs +++ b/Flow.Launcher.Core/Plugin/JsonRPCPlugin.cs @@ -1,4 +1,6 @@ -using Flow.Launcher.Core.Resource; +using Accessibility; +using Flow.Launcher.Core.Resource; +using Flow.Launcher.Infrastructure; using System; using System.Collections.Generic; using System.Diagnostics; @@ -8,12 +10,22 @@ using System.Reflection; using System.Text.Json; using System.Threading; using System.Threading.Tasks; -using System.Windows.Forms; using Flow.Launcher.Infrastructure.Logger; +using Flow.Launcher.Infrastructure.UserSettings; using Flow.Launcher.Plugin; using ICSharpCode.SharpZipLib.Zip; using JetBrains.Annotations; using Microsoft.IO; +using System.Text.Json.Serialization; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Forms; +using CheckBox = System.Windows.Controls.CheckBox; +using Control = System.Windows.Controls.Control; +using Label = System.Windows.Controls.Label; +using Orientation = System.Windows.Controls.Orientation; +using TextBox = System.Windows.Controls.TextBox; +using UserControl = System.Windows.Controls.UserControl; namespace Flow.Launcher.Core.Plugin { @@ -21,7 +33,7 @@ namespace Flow.Launcher.Core.Plugin /// Represent the plugin that using JsonPRC /// every JsonRPC plugin should has its own plugin instance /// - internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu + internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu, ISettingProvider, ISavable { protected PluginInitContext context; public const string JsonRPC = "JsonRPC"; @@ -35,6 +47,8 @@ namespace Flow.Launcher.Core.Plugin private static readonly RecyclableMemoryStreamManager BufferManager = new(); + private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, context.CurrentPluginMetadata.Name, "Setting.json"); + public List LoadContextMenus(Result selectedResult) { var request = new JsonRPCRequestModel @@ -58,6 +72,7 @@ namespace Flow.Launcher.Core.Plugin new JsonObjectConverter() } }; + private Dictionary Settings { get; set; } private async Task> DeserializedResultAsync(Stream output) { @@ -292,10 +307,115 @@ namespace Flow.Launcher.Core.Plugin return await DeserializedResultAsync(output); } - public virtual Task InitAsync(PluginInitContext context) + public async Task InitSettingAsync() + { + if (File.Exists(SettingPath)) + Settings = await JsonSerializer.DeserializeAsync>(File.OpenRead(SettingPath), options); + + var request = new JsonRPCRequestModel() + { + Method = "get_setting_template" + }; + await using var result = await RequestAsync(request); + if (result.Length == 0) + return; + var settingsTemplate = await JsonSerializer.DeserializeAsync>(result, options) ?? + new(); + + Settings ??= new(); + + foreach (var (key, element) in settingsTemplate) + { + if (!Settings.ContainsKey(key)) + { + Settings[key] = element.ValueKind switch + { + JsonValueKind.True or JsonValueKind.False => element.GetBoolean(), + JsonValueKind.String or JsonValueKind.Number => element.GetString(), + JsonValueKind.Null => throw new ArgumentNullException(), + _ => throw new ArgumentOutOfRangeException() + }; + } + } + } + + public virtual async Task InitAsync(PluginInitContext context) { this.context = context; - return Task.CompletedTask; + await InitSettingAsync(); + } + private static Thickness settingControlMargin = new(10); + public Control CreateSettingPanel() + { + if (Settings == null) + return new(); + var settingWindow = new UserControl(); + var mainPanel = new StackPanel + { + Margin = settingControlMargin, + Orientation = Orientation.Vertical + }; + settingWindow.Content = mainPanel; + foreach (var (key, value) in Settings) + { + var panel = new StackPanel + { + Orientation = Orientation.Horizontal, + Margin = settingControlMargin + }; + var name = new Label + { + Content = key, + VerticalAlignment = VerticalAlignment.Center + }; + UIElement content = null; + switch (value) + { + case int i: + case double d: + throw new TypeAccessException(); + case string s: + var textBox = new TextBox + { + Text = s, + Margin = settingControlMargin, + VerticalAlignment = VerticalAlignment.Center + }; + textBox.TextChanged += (_, _) => + { + Settings[key] = textBox.Text; + }; + content = textBox; + break; + case bool b: + var checkBox = new CheckBox + { + IsChecked = b, + Margin = settingControlMargin, + VerticalAlignment = VerticalAlignment.Center + }; + checkBox.Click += (_, _) => + { + Settings[key] = checkBox.IsChecked; + }; + content = checkBox; + break; + default: + throw new ArgumentOutOfRangeException(); + } + panel.Children.Add(name); + panel.Children.Add(content); + mainPanel.Children.Add(panel); + } + return settingWindow; + } + public void Save() + { + if (Settings != null) + { + Helper.ValidateDirectory(Path.Combine(DataLocation.PluginSettingsDirectory, context.CurrentPluginMetadata.Name)); + File.WriteAllText(SettingPath, JsonSerializer.Serialize(Settings)); + } } } } \ No newline at end of file diff --git a/Flow.Launcher.Core/Plugin/PythonPlugin.cs b/Flow.Launcher.Core/Plugin/PythonPlugin.cs index 5711ed6aa..968c0ab23 100644 --- a/Flow.Launcher.Core/Plugin/PythonPlugin.cs +++ b/Flow.Launcher.Core/Plugin/PythonPlugin.cs @@ -46,15 +46,12 @@ namespace Flow.Launcher.Core.Plugin // TODO: Async Action return Execute(_startInfo); } - public override Task InitAsync(PluginInitContext context) + public override async Task InitAsync(PluginInitContext context) { - this.context = context; _startInfo.ArgumentList.Add(context.CurrentPluginMetadata.ExecuteFilePath); _startInfo.ArgumentList.Add(""); - + await base.InitAsync(context); _startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory; - - return Task.CompletedTask; } } } \ No newline at end of file