setting-utils

This commit is contained in:
frostime 2023-09-16 18:03:59 +08:00
parent deb065668f
commit cdb5085f35
3 changed files with 255 additions and 22 deletions

View file

@ -18,6 +18,8 @@ import "@/index.scss";
import HelloExample from "@/hello.svelte"; import HelloExample from "@/hello.svelte";
import SettingPannel from "@/libs/setting-panel.svelte"; import SettingPannel from "@/libs/setting-panel.svelte";
import { SettingUtils } from "./libs/setting-utils";
const STORAGE_NAME = "menu-config"; const STORAGE_NAME = "menu-config";
const TAB_TYPE = "custom_tab"; const TAB_TYPE = "custom_tab";
const DOCK_TYPE = "dock_tab"; const DOCK_TYPE = "dock_tab";
@ -27,6 +29,7 @@ export default class PluginSample extends Plugin {
private customTab: () => IModel; private customTab: () => IModel;
private isMobile: boolean; private isMobile: boolean;
private blockIconEventBindThis = this.blockIconEvent.bind(this); private blockIconEventBindThis = this.blockIconEvent.bind(this);
private settingUtils: SettingUtils;
async onload() { async onload() {
this.data[STORAGE_NAME] = { readonlyText: "Readonly" }; this.data[STORAGE_NAME] = { readonlyText: "Readonly" };
@ -158,32 +161,66 @@ export default class PluginSample extends Plugin {
} }
}); });
const textareaElement = document.createElement("textarea"); this.settingUtils = new SettingUtils(this, STORAGE_NAME);
this.setting = new Setting({ this.settingUtils.addItem({
confirmCallback: () => { key: "Input",
this.saveData(STORAGE_NAME, { readonlyText: textareaElement.value }); value: "",
type: "textinput",
title: "Readonly text",
description: "Input description",
});
this.settingUtils.addItem({
key: "InputArea",
value: "",
type: "textarea",
title: "Readonly text",
description: "Input description",
});
this.settingUtils.addItem({
key: "Select",
value: 1,
type: "select",
title: "Readonly text",
description: "Select description",
select: {
options: [
{
val: 1,
text: "Option 1"
},
{
val: 2,
text: "Option 2"
}
]
} }
}); });
this.setting.addItem({ this.settingUtils.addItem({
title: "Readonly text", key: "Slider",
createActionElement: () => { value: 50,
textareaElement.className = "b3-text-field fn__block"; type: "slider",
textareaElement.placeholder = "Readonly text in the menu"; title: "Slider text",
textareaElement.value = this.data[STORAGE_NAME].readonlyText; description: "Slider description",
return textareaElement; slider: {
}, min: 0,
max: 100,
step: 1,
}
}); });
const btnaElement = document.createElement("button"); this.settingUtils.addItem({
btnaElement.className = "b3-button b3-button--outline fn__flex-center fn__size200"; key: "Btn",
btnaElement.textContent = "Open"; value: "",
btnaElement.addEventListener("click", () => { type: "button",
window.open("https://github.com/siyuan-note/plugin-sample-vite-svelte"); title: "Button",
}); description: "Button description",
this.setting.addItem({ button: {
title: "Open plugin url", label: "Button",
description: "Open plugin url in browser", callback: () => {
actionElement: btnaElement, showMessage("Button clicked");
}
}
}); });
this.settingUtils.load();
this.protyleSlash = [{ this.protyleSlash = [{
filter: ["insert emoji 😊", "插入表情 😊", "crbqwx"], filter: ["insert emoji 😊", "插入表情 😊", "crbqwx"],

20
src/libs/index.d.ts vendored Normal file
View file

@ -0,0 +1,20 @@
type TSettingItemType = "checkbox" | "select" | "textinput" | "textarea" | "slider" | "button";
interface ISettingItem {
key: string;
value: any;
type: TSettingItemType;
title: string;
description?: string;
slider?: {
min: number;
max: number;
step: number;
};
select?: {
options: {val: any; text: string}[];
};
button?: {
label: string;
callback: () => void;
}
}

176
src/libs/setting-utils.ts Normal file
View file

@ -0,0 +1,176 @@
import { Plugin, Setting } from 'siyuan';
export class SettingUtils {
plugin: Plugin;
name: string;
file: string;
settings: Map<string, ISettingItem> = new Map();
elements: Map<string, HTMLElement> = new Map();
constructor(plugin: Plugin, name?: string, width?: string, height?: string) {
this.name = name ?? 'settings';
this.plugin = plugin;
this.file = this.name.endsWith('.json') ? this.name : `${this.name}.json`;
this.plugin.setting = new Setting({
width: width,
height: height,
confirmCallback: () => {
for (let key of this.settings.keys()) {
this.updateValue(key);
}
let data = this.dump();
this.plugin.data[this.name] = data;
this.save();
}
});
}
async load() {
let data = await this.plugin.loadData(this.file);
if (data) {
for (let [key, item] of this.settings) {
item.value = data?.[key] ?? item.value;
}
}
}
async save() {
let data = this.dump();
await this.plugin.saveData(this.file, this.dump());
return data;
}
/**
* Get setting item value
* @param key key name
* @returns setting item value
*/
get(key: string) {
return this.settings.get(key)?.value;
}
/**
* JSON
* @returns object
*/
dump(): Object {
let data: any = {};
for (let [key, item] of this.settings) {
if (item.type === 'button') continue;
data[key] = item.value;
}
return data;
}
addItem(item: ISettingItem) {
this.settings.set(item.key, item);
let itemElement: HTMLElement;
switch (item.type) {
case 'checkbox':
let element: HTMLInputElement = document.createElement('input');
element.type = 'checkbox';
element.checked = item.value;
element.className = "b3-switch fn__flex-center";
itemElement = element;
break;
case 'select':
let selectElement: HTMLSelectElement = document.createElement('select');
selectElement.className = "b3-select fn__flex-center fn__size200";
for (let option of item.select?.options ?? []) {
let optionElement = document.createElement('option');
optionElement.value = option.val;
optionElement.text = option.text;
selectElement.appendChild(optionElement);
}
selectElement.value = item.value;
itemElement = selectElement;
break;
case 'slider':
let sliderElement: HTMLInputElement = document.createElement('input');
sliderElement.type = 'range';
sliderElement.className = 'b3-slider fn__size200';
sliderElement.ariaLabel = item.value;
sliderElement.min = item.slider?.min.toString() ?? '0';
sliderElement.max = item.slider?.max.toString() ?? '100';
sliderElement.step = item.slider?.step.toString() ?? '1';
sliderElement.value = item.value;
itemElement = sliderElement;
break;
case 'textinput':
let textInputElement: HTMLInputElement = document.createElement('input');
textInputElement.className = 'b3-text-field fn__flex-center fn__size200';
textInputElement.value = item.value;
itemElement = textInputElement;
break;
case 'textarea':
let textareaElement: HTMLTextAreaElement = document.createElement('textarea');
textareaElement.className = "b3-text-field fn__block";
textareaElement.value = item.value;
itemElement = textareaElement;
break;
case 'button':
let buttonElement: HTMLButtonElement = document.createElement('button');
buttonElement.className = "b3-button b3-button--outline fn__flex-center fn__size200";
buttonElement.innerText = item.button?.label ?? 'Button';
buttonElement.onclick = item.button?.callback ?? (() => {});
itemElement = buttonElement;
break;
}
this.elements.set(item.key, itemElement);
this.plugin.setting.addItem({
title: item.title,
description: item?.description,
createActionElement: () => {
let element = this.getElement(item.key);
return element;
}
})
}
private getElement(key: string) {
let item = this.settings.get(key);
let element = this.elements.get(key) as any;
switch (item.type) {
case 'checkbox':
element.checked = item.value;
break;
case 'select':
element.value = item.value;
break;
case 'slider':
element.value = item.value;
break;
case 'textinput':
element.value = item.value;
break;
case 'textarea':
element.value = item.value;
break;
}
return element;
}
private updateValue(key: string) {
let item = this.settings.get(key);
let element = this.elements.get(key) as any;
switch (item.type) {
case 'checkbox':
item.value = element.checked;
break;
case 'select':
item.value = element.value;
break;
case 'slider':
item.value = element.value;
break;
case 'textinput':
item.value = element.value;
break;
case 'textarea':
item.value = element.value;
break;
}
}
}