From 7c410f0a45e892014966dd5b0dd716a0cab320cd Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Sat, 3 Feb 2024 00:29:32 +0100 Subject: [PATCH] support config wizard --- src/main/pkg_mng/commands/apply.js | 21 +-- src/main/pkg_mng/commands/install.js | 4 + src/renderer/src/App.jsx | 12 ++ .../src/components/InstallConfigAsk/index.jsx | 121 +++++++++++++++++ .../components/InstallConfigAsk/index.less | 32 +++++ .../components/PackageConfigItem/index.jsx | 110 +++++++++++++++ .../src/components/PackageItem/index.jsx | 2 + src/renderer/src/pages/pkg/index.jsx | 125 ++++-------------- 8 files changed, 318 insertions(+), 109 deletions(-) create mode 100644 src/renderer/src/components/InstallConfigAsk/index.jsx create mode 100644 src/renderer/src/components/InstallConfigAsk/index.less create mode 100644 src/renderer/src/components/PackageConfigItem/index.jsx diff --git a/src/main/pkg_mng/commands/apply.js b/src/main/pkg_mng/commands/apply.js index ae7fcb9..eeae96a 100644 --- a/src/main/pkg_mng/commands/apply.js +++ b/src/main/pkg_mng/commands/apply.js @@ -22,12 +22,6 @@ export default async function apply(pkg_id, changes) { console.log(`[${pkg_id}] apply() | Applying changes... >`, changes) - sendToRender(`pkg:update:status`, { - id: pkg_id, - status: "loading", - statusText: "Applying changes...", - }) - if (Array.isArray(changes.patches)) { if (!Array.isArray(pkg.applied_patches)) { pkg.applied_patches = [] @@ -70,6 +64,12 @@ export default async function apply(pkg_id, changes) { pkg.applied_patches = pkg.applied_patches.filter((p) => { return p !== patch.id }) + + sendToRender(`pkg:update:status`, { + id: pkg_id, + status: "done", + statusText: `Patch [${patch.id}] removed!`, + }) } for await (let patch of installPatches) { @@ -100,6 +100,12 @@ export default async function apply(pkg_id, changes) { // add to applied patches pkg.applied_patches.push(patch.id) + + sendToRender(`pkg:update:status`, { + id: pkg_id, + status: "done", + statusText: `Patch [${patch.id}] applied!`, + }) } } @@ -115,8 +121,6 @@ export default async function apply(pkg_id, changes) { } } - pkg.status = "installed" - await updateInstalledPackage(pkg) sendToRender(`new:notification`, { @@ -126,7 +130,6 @@ export default async function apply(pkg_id, changes) { sendToRender(`pkg:update:status`, { ...pkg, - status: "installed", statusText: "Changes applied!", }) diff --git a/src/main/pkg_mng/commands/install.js b/src/main/pkg_mng/commands/install.js index f66512e..e10c40f 100644 --- a/src/main/pkg_mng/commands/install.js +++ b/src/main/pkg_mng/commands/install.js @@ -98,6 +98,10 @@ export default async function install(manifest) { }) } + if (Array.isArray(pkg.install_ask_configs)) { + sendToRender("pkg:install:ask", pkg) + } + sendToRender(`pkg:update:status`, { id: pkg_id, status: "installed", diff --git a/src/renderer/src/App.jsx b/src/renderer/src/App.jsx index 0d77dab..6dc1e5d 100644 --- a/src/renderer/src/App.jsx +++ b/src/renderer/src/App.jsx @@ -7,6 +7,7 @@ import getRootCssVar from "utils/getRootCssVar" import ManifestInfo from "components/ManifestInfo" import PackageUpdateAvailable from "components/PackageUpdateAvailable" +import InstallConfigAsk from "components/InstallConfigAsk" import AppLayout from "layout" import AppModalDialog from "layout/components/ModalDialog" @@ -42,6 +43,14 @@ window.app = { } }) }, + pkgInstallWizard: (manifest) => { + app.modal.open(InstallConfigAsk, { + manifest: manifest, + close: () => { + app.modal.close() + } + }) + }, checkUpdates: () => { ipc.exec("updater:check") }, @@ -84,6 +93,9 @@ class App extends React.Component { "app:update_available": (event, data) => { this.onUpdateAvailable(data) }, + "pkg:install:ask": (event, data) => { + app.pkgInstallWizard(data) + }, "pkg:update_available": (event, data) => { app.pkgUpdateAvailable(data) }, diff --git a/src/renderer/src/components/InstallConfigAsk/index.jsx b/src/renderer/src/components/InstallConfigAsk/index.jsx new file mode 100644 index 0000000..24950b2 --- /dev/null +++ b/src/renderer/src/components/InstallConfigAsk/index.jsx @@ -0,0 +1,121 @@ +import React from "react" +import { Icons, Icon } from "components/Icons" + +import * as antd from "antd" + +import PKGConfigItem from "../PackageConfigItem" + +import "./index.less" + +const InstallConfigAsk = (props) => { + const { manifest } = props + + const [values, setValues] = React.useState({ + ...manifest.storaged_configs, + ...Object.keys(manifest.configs).reduce((prev, key) => { + prev[key] = manifest.configs[key].default + + return prev + }, {}) + }) + + const [currentStep, setCurrentStep] = React.useState(0) + + function handleChanges(key, value) { + setValues((prev) => { + return { + ...prev, + [key]: value + } + }) + } + + function handleNextStep() { + setCurrentStep(currentStep + 1) + } + + function handleFinish() { + console.log(`Finish config wizard, with values >`, values) + + if (typeof props.onFinish === "function") { + props.onFinish(values) + } + + if (typeof props.close === "function") { + props.close() + } + + if (typeof props.onClose === "function") { + props.onClose() + } + + ipc.exec("pkg:apply", manifest.id, { + configs: values + }) + + app.location.push("/") + } + + const stepsItems = React.useMemo(() => { + const steps = manifest.install_ask_configs.map((key, index) => { + return { + key: index, + title: manifest.configs[key].label + } + }) + + return [...steps, { + key: manifest.install_ask_configs.length, + title: "Finish" + }] + }, []) + + const stepsContent = React.useMemo(() => { + const steps = manifest.install_ask_configs.map((key, index) => { + const config = manifest.configs[key] + + return + }) + + return steps + }, []) + + return
+ { + setCurrentStep(currentStep) + }} + /> + +
+ {stepsContent[currentStep]} +
+ +
+ { + if (currentStep === stepsItems.length - 2) { + handleFinish() + } else { + handleNextStep() + } + }} + > + {currentStep === stepsItems.length - 2 ? "Finish" : "Next"} + +
+
+} + +export default InstallConfigAsk \ No newline at end of file diff --git a/src/renderer/src/components/InstallConfigAsk/index.less b/src/renderer/src/components/InstallConfigAsk/index.less new file mode 100644 index 0000000..d318ce2 --- /dev/null +++ b/src/renderer/src/components/InstallConfigAsk/index.less @@ -0,0 +1,32 @@ +.install_config_ask { + display: flex; + flex-direction: column; + + gap: 20px; + + h1 { + display: inline-flex; + flex-direction: row; + + gap: 6px; + + font-size: 1rem; + + svg { + font-size: 1.5rem; + } + } + + .ant-steps { + padding-right: 30px; + } + + .install_config_ask-content { + display: flex; + flex-direction: column; + + gap: 10px; + + padding: 0 15px; + } +} \ No newline at end of file diff --git a/src/renderer/src/components/PackageConfigItem/index.jsx b/src/renderer/src/components/PackageConfigItem/index.jsx new file mode 100644 index 0000000..8acbd5f --- /dev/null +++ b/src/renderer/src/components/PackageConfigItem/index.jsx @@ -0,0 +1,110 @@ +import React from "react" +import * as antd from "antd" +import { Icon } from "components/Icons" + +const PKGConfigsComponents = { + switch: antd.Switch, + button: antd.Button, + input: antd.Input, + slider: antd.Slider, +} + +const PKGConfigsComponentByTypes = { + string: "input", + action: "button", + bool: "switch", + number: "slider", +} + +const PKGConfigItem = (props) => { + const { config, storagedValue } = props + + const key = config.id + + const [localValue, setLocalValue] = React.useState(storagedValue ?? config.default) + + const ComponentType = config.ui_component ?? PKGConfigsComponentByTypes[config.type] ?? "input" + const ConfigComponent = PKGConfigsComponents[ComponentType] + + function handleOnChange(value) { + if (typeof value === "string" && config.string_trim === true) { + value = value.trim() + } + + setLocalValue(value) + + return props.onChange(key, value) + } + + if (ConfigComponent == null) { + return null + } + + const ComponentsProps = { + ...config.ui_component_props, + defaultValue: storagedValue ?? config.default, + value: localValue + } + + switch (ComponentType) { + case "input": { + ComponentsProps.onChange = (e) => { + handleOnChange(e.target.value) + } + break + } + + case "slider": { + ComponentsProps.onChange = (value) => { + handleOnChange(value) + } + break + } + + case "switch": { + ComponentsProps.onChange = (checked) => { + handleOnChange(checked) + } + break + } + + default: { + ComponentsProps.onChange = (value) => { + handleOnChange(value) + } + break; + } + } + + return
+
+ + { + config.icon && + } + { + config.label ?? key + } + + + { + config.description &&

+ {key} +

+ } +
+ +
+ { + React.createElement(ConfigComponent, ComponentsProps) + } +
+
+} + +export default PKGConfigItem \ No newline at end of file diff --git a/src/renderer/src/components/PackageItem/index.jsx b/src/renderer/src/components/PackageItem/index.jsx index d983537..772a2ac 100644 --- a/src/renderer/src/components/PackageItem/index.jsx +++ b/src/renderer/src/components/PackageItem/index.jsx @@ -170,10 +170,12 @@ const PackageItem = (props) => { { isInstalled && !manifest.executable && } type="primary" + disabled={isLoading} /> } diff --git a/src/renderer/src/pages/pkg/index.jsx b/src/renderer/src/pages/pkg/index.jsx index 2a8a2a7..47c1813 100644 --- a/src/renderer/src/pages/pkg/index.jsx +++ b/src/renderer/src/pages/pkg/index.jsx @@ -3,22 +3,10 @@ import * as antd from "antd" import { Icons, Icon } from "components/Icons" import { useParams } from "react-router-dom" +import PKGConfigItem from "components/PackageConfigItem" + import "./index.less" -const PKGConfigsComponents = { - switch: antd.Switch, - button: antd.Button, - input: antd.Input, - slider: antd.Slider, -} - -const PKGConfigsComponentByTypes = { - string: "input", - action: "button", - bool: "switch", - number: "slider", -} - const PKGConfigs = (props) => { const { defaultConfigs = {}, configs = {} } = props @@ -30,93 +18,15 @@ const PKGConfigs = (props) => { return Object.keys(defaultConfigs).map((key, index) => { const config = defaultConfigs[key] - const storagedValue = configs[key] - const [localValue, setLocalValue] = React.useState(storagedValue ?? config.default) + config.id = key - const ComponentType = config.ui_component ?? PKGConfigsComponentByTypes[config.type] ?? "input" - const ConfigComponent = PKGConfigsComponents[ComponentType] - - function handleOnChange(value) { - if (typeof value === "string" && config.string_trim === true) { - value = value.trim() - } - - setLocalValue(value) - - return props.onChange(key, value) - } - - if (ConfigComponent == null) { - return null - } - - const ComponentsProps = { - ...config.ui_component_props, - defaultValue: storagedValue ?? config.default, - value: localValue - } - - switch (ComponentType) { - case "input": { - ComponentsProps.onChange = (e) => { - handleOnChange(e.target.value) - } - break - } - - case "slider": { - ComponentsProps.onChange = (value) => { - handleOnChange(value) - } - break - } - - case "switch": { - ComponentsProps.onChange = (checked) => { - handleOnChange(checked) - } - break - } - - default: { - ComponentsProps.onChange = (value) => { - handleOnChange(value) - } - break; - } - } - - return
-
- - { - config.icon && - } - { - config.label ?? key - } - - - { - config.description &&

- {key} -

- } -
- -
- { - React.createElement(ConfigComponent, ComponentsProps) - } -
-
+ storagedValue={configs[key]} + config={config} + onChange={props.onChange} + /> }) } @@ -315,17 +225,32 @@ const PackageOptions = (props) => { onClick={handleReinstall} icon={} type="default" + size="small" > Reinstall - } type="default" + size="small" > Verify - + */} + + { + manifest.install_ask_configs && { + app.pkgInstallWizard(manifest) + }} + icon={} + type="default" + size="small" + > + Wizard + + }