Use Yaml as configuration file

This commit is contained in:
Kevin Zhang 2021-10-30 13:46:57 -05:00
parent 67027eb74b
commit 054d1650e6
2 changed files with 164 additions and 51 deletions

View file

@ -0,0 +1,42 @@
using System.Collections.Generic;
namespace Flow.Launcher.Core.Plugin
{
public class JsonRpcConfigurationModel
{
public List<SettingField> Body { get; set; }
public void Deconstruct(out List<SettingField> Body)
{
Body = this.Body;
}
}
public class SettingField
{
public string Type { get; set; }
public FieldAttributes Attributes { get; set; }
public void Deconstruct(out string Type, out FieldAttributes attributes)
{
Type = this.Type;
attributes = this.Attributes;
}
}
public class FieldAttributes
{
public string Name { get; set; }
public string Label { get; set; }
public string Description { get; set; }
public bool Validation { get; set; }
public List<string> Options { get; set; }
public string DefaultValue { get; set; }
public void Deconstruct(out string Name, out string Label, out string Description, out bool Validation, out List<string> Options, out string DefaultValue)
{
Name = this.Name;
Label = this.Label;
Description = this.Description;
Validation = this.Validation;
Options = this.Options;
DefaultValue = this.DefaultValue;
}
}
}

View file

@ -19,7 +19,8 @@ using Microsoft.IO;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Forms; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using CheckBox = System.Windows.Controls.CheckBox; using CheckBox = System.Windows.Controls.CheckBox;
using Control = System.Windows.Controls.Control; using Control = System.Windows.Controls.Control;
using Label = System.Windows.Controls.Label; using Label = System.Windows.Controls.Label;
@ -47,6 +48,7 @@ namespace Flow.Launcher.Core.Plugin
private static readonly RecyclableMemoryStreamManager BufferManager = new(); private static readonly RecyclableMemoryStreamManager BufferManager = new();
private string SettingConfigurationPath => Path.Combine(context.CurrentPluginMetadata.PluginDirectory, "SettingConfiguration.yaml");
private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, context.CurrentPluginMetadata.Name, "Setting.json"); private string SettingPath => Path.Combine(DataLocation.PluginSettingsDirectory, context.CurrentPluginMetadata.Name, "Setting.json");
public List<Result> LoadContextMenus(Result selectedResult) public List<Result> LoadContextMenus(Result selectedResult)
@ -309,32 +311,22 @@ namespace Flow.Launcher.Core.Plugin
public async Task InitSettingAsync() public async Task InitSettingAsync()
{ {
if (!File.Exists(SettingConfigurationPath))
return;
if (File.Exists(SettingPath)) if (File.Exists(SettingPath))
Settings = await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(File.OpenRead(SettingPath), options); Settings = await JsonSerializer.DeserializeAsync<Dictionary<string, object>>(File.OpenRead(SettingPath), options);
var request = new JsonRPCRequestModel() var deserializer = new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance).Build();
{ _settingsTemplate = deserializer.Deserialize<JsonRpcConfigurationModel>(await File.ReadAllTextAsync(SettingConfigurationPath));
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(); Settings ??= new Dictionary<string, object>();
foreach (var (key, element) in settingsTemplate) foreach (var (type, attribute) in _settingsTemplate.Body)
{ {
if (!Settings.ContainsKey(key)) if (!Settings.ContainsKey(attribute.Name))
{ {
Settings[key] = element.ValueKind switch Settings[attribute.Name] = attribute.DefaultValue;
{
JsonValueKind.True or JsonValueKind.False => element.GetBoolean(),
JsonValueKind.String or JsonValueKind.Number => element.GetString(),
JsonValueKind.Null => throw new ArgumentNullException(),
_ => throw new ArgumentOutOfRangeException()
};
} }
} }
} }
@ -344,7 +336,8 @@ namespace Flow.Launcher.Core.Plugin
this.context = context; this.context = context;
await InitSettingAsync(); await InitSettingAsync();
} }
private static Thickness settingControlMargin = new(10); private static readonly Thickness settingControlMargin = new(10);
private JsonRpcConfigurationModel _settingsTemplate;
public Control CreateSettingPanel() public Control CreateSettingPanel()
{ {
if (Settings == null) if (Settings == null)
@ -352,61 +345,139 @@ namespace Flow.Launcher.Core.Plugin
var settingWindow = new UserControl(); var settingWindow = new UserControl();
var mainPanel = new StackPanel var mainPanel = new StackPanel
{ {
Margin = settingControlMargin, Margin = settingControlMargin, Orientation = Orientation.Vertical
Orientation = Orientation.Vertical
}; };
settingWindow.Content = mainPanel; settingWindow.Content = mainPanel;
foreach (var (key, value) in Settings)
foreach (var (type, attribute) in _settingsTemplate.Body)
{ {
var panel = new StackPanel var panel = new StackPanel
{ {
Orientation = Orientation.Horizontal, Orientation = Orientation.Horizontal,
Margin = settingControlMargin Margin = settingControlMargin
}; };
var name = new Label var name = new Label()
{ {
Content = key, Content = attribute.Label,
VerticalAlignment = VerticalAlignment.Center Margin = settingControlMargin
}; };
UIElement content = null;
switch (value) Control contentControl;
switch (type)
{ {
case int i: case "Input":
case double d:
throw new TypeAccessException();
case string s:
var textBox = new TextBox
{ {
Text = s, var textBox = new TextBox()
Margin = settingControlMargin, {
VerticalAlignment = VerticalAlignment.Center Width = 300, Text = Settings[attribute.Name] as string ?? string.Empty,
}; Margin = settingControlMargin
textBox.TextChanged += (_, _) => };
textBox.TextChanged += (_, _) =>
{
Settings[attribute.Name] = textBox.Text;
};
contentControl = textBox;
break;
}
case "textarea":
{ {
Settings[key] = textBox.Text; var textBox = new TextBox()
}; {
content = textBox; Width = 300,
break; Height = 100,
case bool b: Margin = settingControlMargin,
TextWrapping = TextWrapping.WrapWithOverflow,
Text = Settings[attribute.Name] as string ?? string.Empty
};
textBox.TextChanged += (sender, _) =>
{
Settings[attribute.Name] = ((TextBox)sender).Text;
};
contentControl = textBox;
break;
}
case "dropdown":
{
var comboBox = new ComboBox()
{
ItemsSource = attribute.Options, SelectedItem = Settings[attribute.Name],
Margin = settingControlMargin
};
comboBox.SelectionChanged += (sender, _) =>
{
Settings[attribute.Name] = (string)((ComboBox)sender).SelectedItem;
};
contentControl = comboBox;
break;
}
case "checkbox":
var checkBox = new CheckBox var checkBox = new CheckBox
{ {
IsChecked = b, IsChecked = Settings[attribute.Name] is bool isChecked ? isChecked : bool.Parse(attribute.DefaultValue),
Margin = settingControlMargin, Margin = settingControlMargin
VerticalAlignment = VerticalAlignment.Center
}; };
checkBox.Click += (_, _) => checkBox.Click += (_, _) =>
{ {
Settings[key] = checkBox.IsChecked; Settings[attribute.Name] = !((bool)Settings[attribute.Name]);
}; };
content = checkBox; contentControl = checkBox;
break; break;
default: default:
throw new ArgumentOutOfRangeException(); continue;
} }
panel.Children.Add(name); panel.Children.Add(name);
panel.Children.Add(content); panel.Children.Add(contentControl);
mainPanel.Children.Add(panel); mainPanel.Children.Add(panel);
} }
// 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();
// }
//
// }
return settingWindow; return settingWindow;
} }
public void Save() public void Save()