Allow JsonRPCPlugin.cs to have setting control

This commit is contained in:
Kevin Zhang 2021-08-17 00:50:36 +08:00
parent 8ae13a5473
commit 67027eb74b
3 changed files with 128 additions and 11 deletions

View file

@ -1,4 +1,6 @@
using Flow.Launcher.Core.Resource; using Accessibility;
using Flow.Launcher.Core.Resource;
using Flow.Launcher.Infrastructure;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -8,12 +10,22 @@ using System.Reflection;
using System.Text.Json; using System.Text.Json;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms;
using Flow.Launcher.Infrastructure.Logger; using Flow.Launcher.Infrastructure.Logger;
using Flow.Launcher.Infrastructure.UserSettings;
using Flow.Launcher.Plugin; using Flow.Launcher.Plugin;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using JetBrains.Annotations; using JetBrains.Annotations;
using Microsoft.IO; 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 namespace Flow.Launcher.Core.Plugin
{ {
@ -21,7 +33,7 @@ namespace Flow.Launcher.Core.Plugin
/// Represent the plugin that using JsonPRC /// Represent the plugin that using JsonPRC
/// every JsonRPC plugin should has its own plugin instance /// every JsonRPC plugin should has its own plugin instance
/// </summary> /// </summary>
internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu internal abstract class JsonRPCPlugin : IAsyncPlugin, IContextMenu, ISettingProvider, ISavable
{ {
protected PluginInitContext context; protected PluginInitContext context;
public const string JsonRPC = "JsonRPC"; public const string JsonRPC = "JsonRPC";
@ -35,6 +47,8 @@ namespace Flow.Launcher.Core.Plugin
private static readonly RecyclableMemoryStreamManager BufferManager = new(); private static readonly RecyclableMemoryStreamManager BufferManager = new();
private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, context.CurrentPluginMetadata.Name, "Setting.json");
public List<Result> LoadContextMenus(Result selectedResult) public List<Result> LoadContextMenus(Result selectedResult)
{ {
var request = new JsonRPCRequestModel var request = new JsonRPCRequestModel
@ -58,6 +72,7 @@ namespace Flow.Launcher.Core.Plugin
new JsonObjectConverter() new JsonObjectConverter()
} }
}; };
private Dictionary<string, object> Settings { get; set; }
private async Task<List<Result>> DeserializedResultAsync(Stream output) private async Task<List<Result>> DeserializedResultAsync(Stream output)
{ {
@ -292,10 +307,115 @@ namespace Flow.Launcher.Core.Plugin
return await DeserializedResultAsync(output); return await DeserializedResultAsync(output);
} }
public virtual Task InitAsync(PluginInitContext context) public async Task InitSettingAsync()
{
if (File.Exists(SettingPath))
Settings = await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(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<Dictionary<string, JsonElement>>(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; 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));
}
} }
} }
} }

View file

@ -46,15 +46,12 @@ namespace Flow.Launcher.Core.Plugin
// TODO: Async Action // TODO: Async Action
return Execute(_startInfo); 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(context.CurrentPluginMetadata.ExecuteFilePath);
_startInfo.ArgumentList.Add(""); _startInfo.ArgumentList.Add("");
await base.InitAsync(context);
_startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory; _startInfo.WorkingDirectory = context.CurrentPluginMetadata.PluginDirectory;
return Task.CompletedTask;
} }
} }
} }