From 601250dd1675decae8214ff6a92f6c6577d910f1 Mon Sep 17 00:00:00 2001 From: Hi Flysoft Date: Mon, 17 Jul 2023 21:16:01 +0800 Subject: [PATCH] feat: add plugin settings page --- build.ts | 4 ++-- package.json | 12 +++++++---- publish/qqntim.json | 5 +++++ scripts/install.ps1 | 12 +++++++++++ scripts/install.sh | 11 ++++++++++ scripts/start.ps1 | 13 ++---------- scripts/start.sh | 9 -------- src/config.ts | 21 +++++++++++++++++++ src/main.ts | 3 +++ src/renderer.ts | 3 +++ src/settings.tsx | 51 +++++++++++++++++++++++++++++++++++++++++++++ src/utils/hooks.ts | 25 ++++++++++++++++++++++ yarn.lock | 2 ++ 13 files changed, 145 insertions(+), 26 deletions(-) create mode 100644 scripts/install.ps1 create mode 100755 scripts/install.sh create mode 100644 src/config.ts create mode 100644 src/settings.tsx create mode 100644 src/utils/hooks.ts diff --git a/build.ts b/build.ts index 7523624..7338783 100644 --- a/build.ts +++ b/build.ts @@ -18,9 +18,9 @@ async function buildPlugin() { minify: isProduction, treeShaking: isProduction, format: "cjs", - entryPoints: [`src${s}main.ts`, `src${s}renderer.ts`], + entryPoints: [`src${s}main.ts`, `src${s}renderer.ts`, `src${s}settings.tsx`], outdir: "dist", - external: ["electron", "react", "react/jsx-runtime", "react-dom", "react-dom/client", "qqntim/main", "qqntim/renderer"], + external: ["electron", "react", "react/jsx-runtime", "react-dom", "react-dom/client", "qqntim/main", "qqntim/renderer", "qqntim-settings", "qqntim-settings/components"], }); await fs.copy("publish", "dist"); } diff --git a/package.json b/package.json index 14ddcd8..37e897d 100644 --- a/package.json +++ b/package.json @@ -5,18 +5,22 @@ "packageManager": "yarn@3.6.1", "license": "MIT", "scripts": { - "dev": "NODE_ENV=development tsc & TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=development ts-node ./build.ts", - "build": "NODE_ENV=production tsc && TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=production ts-node ./build.ts", + "dev": "TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=development ts-node ./build.ts", + "build": "TS_NODE_FILES=1 TS_NODE_TRANSPILE_ONLY=1 NODE_ENV=production ts-node ./build.ts", + "install:win": "powershell -ExecutionPolicy Unrestricted -File ./scripts/install.ps1", + "install:linux": "chmod +x ./scripts/install.sh && ./scripts/install.sh", "start:win": "powershell -ExecutionPolicy Unrestricted -File ./scripts/start.ps1", "start:linux": "chmod +x ./scripts/start.sh && ./scripts/start.sh", - "lint": "rome check .", + "lint": "tsc && rome check .", "lint:apply": "rome check . --apply", "lint:apply-unsafe": "rome check . --apply-unsafe", "format": "rome format . --write" }, "devDependencies": { - "@flysoftbeta/qqntim-typings": "^2.0.1", + "@flysoftbeta/qqntim-typings": "^3.0.0", "@types/node": "^20.4.2", + "@types/react": "^18.2.15", + "@types/react-dom": "^18.2.7", "@yarnpkg/sdks": "^3.0.0-rc.48", "esbuild": "^0.18.12", "fs-extra": "^11.1.1", diff --git a/publish/qqntim.json b/publish/qqntim.json index 344986b..8f560fc 100644 --- a/publish/qqntim.json +++ b/publish/qqntim.json @@ -14,6 +14,11 @@ "type": "renderer", "stylesheet": "style.css", "script": "renderer.js" + }, + { + "type": "renderer", + "page": ["settings"], + "script": "settings.js" } ] } diff --git a/scripts/install.ps1 b/scripts/install.ps1 new file mode 100644 index 0000000..e7e417c --- /dev/null +++ b/scripts/install.ps1 @@ -0,0 +1,12 @@ +$ErrorActionPreference = "Stop" + +Set-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + "..") + +if ($null -eq $env:QQNTIM_HOME) { + $env:QQNTIM_HOME = "$UserProfile\.qqntim" +} + +$PluginId = (node --eval 'console.log(require("./publish/qqntim.json").id)') +$PluginDir = "$env:QQNTIM_HOME\plugins\$PluginId" + +Copy-Item ".\dist" $PluginDir -Recurse -Force diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 0000000..93e6f85 --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash + +cd "$( dirname "${BASH_SOURCE[0]}" )/.." + +[ ! $QQNTIM_HOME ] && export QQNTIM_HOME="$HOME/.local/share/QQNTim" + +plugin_id=$(node --eval 'console.log(require("./publish/qqntim.json").id)') +plugin_dir="$QQNTIM_HOME/plugins/$plugin_id" + +[ -d $plugin_dir ] && rm -rf "$plugin_dir" +cp -rf ./dist "$plugin_dir" diff --git a/scripts/start.ps1 b/scripts/start.ps1 index 47d9d1b..55e40a6 100644 --- a/scripts/start.ps1 +++ b/scripts/start.ps1 @@ -1,15 +1,6 @@ -$ErrorActionPreference = "Stop" +$ErrorActionPreference = "Stop" -Set-Location (Split-Path -Parent $MyInvocation.MyCommand.Definition) - -if ($null -eq $env:QQNTIM_HOME) { - $env:QQNTIM_HOME = "$UserProfile\.qqntim" -} - -$PluginId = (node --eval 'console.log(require("./publish/qqntim.json").id)') -$PluginDir = "$env:QQNTIM_HOME\plugins\$PluginId" - -Copy-Item ".\dist" $PluginDir -Recurse -Force +Set-Location ((Split-Path -Parent $MyInvocation.MyCommand.Definition) + "..") foreach ($RegistryPath in @("HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*", "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*")) { try { diff --git a/scripts/start.sh b/scripts/start.sh index 0bdec24..492ff20 100755 --- a/scripts/start.sh +++ b/scripts/start.sh @@ -2,13 +2,4 @@ cd "$( dirname "${BASH_SOURCE[0]}" )/.." -[ ! $QQNTIM_HOME ] && export QQNTIM_HOME="$HOME/.local/share/QQNTim" - -plugin_id=$(node --eval 'console.log(require("./publish/qqntim.json").id)') -plugin_dir="$QQNTIM_HOME/plugins/$plugin_id" - -[ -d $plugin_dir ] && rm -rf "$plugin_dir" -cp -rf ./dist "$plugin_dir" -echo "环境准备完毕。" - qq 2>&1 | sed -e '/NODE_TLS_REJECT_UNAUTHORIZED/d' -e '/Gtk-Message/d' -e '/to show where the warning was created/d' -e '/gbm_wrapper\.cc/d' -e '/node_bindings\.cc/d' -e '/UnhandledPromiseRejectionWarning/d' -e '/\[BuglyManager\.cpp\]/d' -e '/\[NativeCrashHandler\.cpp\]/d' -e '/\[BuglyService\.cpp\]/d' -e '/\[HotUpdater\]/d' -e '/ERROR:CONSOLE/d' diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..5c49c60 --- /dev/null +++ b/src/config.ts @@ -0,0 +1,21 @@ +export const id = "my-template-plugin" as const; + +export const defaults: PluginConfig = { + switchConfigItem: false, + anotherSwitchConfigItem: false, + inputConfigItem: "默认值", + dropdownConfigItem: "A", +}; +export function getPluginConfig(config: Config | undefined) { + return Object.assign({}, defaults, config?.[id] || {}); +} + +export interface PluginConfig { + switchConfigItem: boolean; + anotherSwitchConfigItem: boolean; + inputConfigItem: string; + dropdownConfigItem: "A" | "B" | "C"; +} +export type Config = { + [X in typeof id]?: Partial; +}; diff --git a/src/main.ts b/src/main.ts index 77fd743..5a1ec87 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,10 @@ +import { getPluginConfig } from "./config"; import * as qqntim from "qqntim/main"; export default class Entry implements QQNTim.Entry.Main { constructor() { + const config = getPluginConfig(qqntim.env.config.plugins.config); console.log("[Template] Hello world!", qqntim); + console.log("[Template] 当前插件配置:", config); } } diff --git a/src/renderer.ts b/src/renderer.ts index 2519c3f..9bfc233 100644 --- a/src/renderer.ts +++ b/src/renderer.ts @@ -1,7 +1,10 @@ +import { getPluginConfig } from "./config"; import * as qqntim from "qqntim/renderer"; export default class Entry implements QQNTim.Entry.Renderer { constructor() { + const config = getPluginConfig(qqntim.env.config.plugins.config); console.log("[Template] Hello world!", qqntim); + console.log("[Template] 当前插件配置:", config); } } diff --git a/src/settings.tsx b/src/settings.tsx new file mode 100644 index 0000000..53cdab9 --- /dev/null +++ b/src/settings.tsx @@ -0,0 +1,51 @@ +import { usePluginConfig } from "./utils/hooks"; +import { defineSettingsPanels } from "qqntim-settings"; +import { Dropdown, Input, SettingsBox, SettingsBoxItem, SettingsSection, Switch } from "qqntim-settings/components"; +import { env } from "qqntim/renderer"; +import { useMemo } from "react"; +import { getPluginConfig } from "./config"; + +export default class Entry implements QQNTim.Entry.Renderer { + constructor() { + // 如果不需要设置界面,将下一行注释掉即可;如果需要在设置项目旁边加一个小图标,请将 `undefined` 改为一段 HTML 代码(可以是 ``, `` 等等)。 + defineSettingsPanels(["模板插件设置", SettingsPanel, undefined]); + } +} + +function SettingsPanel({ config: _config, setConfig: _setConfig }: QQNTim.Settings.PanelProps) { + const [pluginConfig, setPluginConfig] = usePluginConfig(_config, _setConfig); + const currentPluginConfigString = useMemo(() => JSON.stringify(getPluginConfig(env.config.plugins.config)), []); + + return ( + <> + + + + + setPluginConfig("switchConfigItem", state)} /> + + {pluginConfig.switchConfigItem && ( + + setPluginConfig("anotherSwitchConfigItem", state)} /> + + )} + + setPluginConfig("dropdownConfigItem", state)} + width="150px" + /> + + + setPluginConfig("inputConfigItem", state)} /> + + + + + ); +} diff --git a/src/utils/hooks.ts b/src/utils/hooks.ts new file mode 100644 index 0000000..6a6dd2f --- /dev/null +++ b/src/utils/hooks.ts @@ -0,0 +1,25 @@ +import { Config, PluginConfig, getPluginConfig, id } from "../config"; +import { useEffect, useState } from "react"; + +export function usePluginConfig(config: Record, setConfig: React.Dispatch>>) { + const [pluginConfig, _setPluginConfig] = useState(getPluginConfig(config)); + + useEffect( + () => + setConfig((prev) => { + return { ...prev, [id]: pluginConfig }; + }), + [pluginConfig], + ); + + const setPluginConfig = function (key: T, value: PluginConfig[T]) { + _setPluginConfig((prev) => { + return { + ...prev, + [key]: value, + }; + }); + }; + + return [pluginConfig, setPluginConfig] as const; +} diff --git a/yarn.lock b/yarn.lock index 7672732..162bb12 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,6 +1283,8 @@ __metadata: dependencies: "@flysoftbeta/qqntim-typings": ^3.0.0 "@types/node": ^20.4.2 + "@types/react": ^18.2.15 + "@types/react-dom": ^18.2.7 "@yarnpkg/sdks": ^3.0.0-rc.48 esbuild: ^0.18.12 fs-extra: ^11.1.1