Better handle install and re-install lifecycle. Also display all the juicy bits about the plugin

This commit is contained in:
tutman96 2025-01-06 18:56:29 +00:00
parent 2e24916331
commit 16064aa876
6 changed files with 70 additions and 27 deletions

View File

@ -19,7 +19,7 @@ type PluginInstall struct {
ExtractedVersions map[string]string `json:"extracted_versions"`
manifest *PluginManifest
runningVersion *string
runningVersion string
processManager *ProcessManager
rpcServer *PluginRpcServer
}
@ -84,10 +84,7 @@ func (p *PluginInstall) ReconcileSubprocess() error {
return fmt.Errorf("failed to get plugin manifest: %v", err)
}
versionRunning := ""
if p.runningVersion != nil {
versionRunning = *p.runningVersion
}
versionRunning := p.runningVersion
versionShouldBeRunning := p.Version
if !p.Enabled {
@ -105,7 +102,7 @@ func (p *PluginInstall) ReconcileSubprocess() error {
log.Printf("Stopping plugin %s running version %s", manifest.Name, versionRunning)
p.processManager.Disable()
p.processManager = nil
p.runningVersion = nil
p.runningVersion = ""
err = p.rpcServer.Stop()
if err != nil {
return fmt.Errorf("failed to stop rpc server: %v", err)
@ -146,7 +143,11 @@ func (p *PluginInstall) ReconcileSubprocess() error {
})
p.processManager.StartMonitor()
p.processManager.Enable()
p.runningVersion = &p.Version
p.runningVersion = p.Version
// Clear out manifest so the new version gets pulled next time
p.manifest = nil
log.Printf("Started plugin %s version %s", manifest.Name, p.Version)
return nil
}
@ -155,7 +156,7 @@ func (p *PluginInstall) Shutdown() {
if p.processManager != nil {
p.processManager.Disable()
p.processManager = nil
p.runningVersion = nil
p.runningVersion = ""
}
if p.rpcServer != nil {

View File

@ -120,7 +120,6 @@ func RpcPluginExtract(filename string) (*PluginManifest, error) {
}
func RpcPluginInstall(name string, version string) error {
// TODO: find the plugin version in the plugins.json file
pluginInstall, ok := pluginDatabase.Plugins[name]
if !ok {
return fmt.Errorf("plugin not found: %s", name)
@ -136,8 +135,6 @@ func RpcPluginInstall(name string, version string) error {
return fmt.Errorf("plugin version not found: %s", version)
}
// TODO: If there is a running plugin with the same name, stop it and start the new version
pluginInstall.Version = version
pluginInstall.Enabled = true
pluginDatabase.Plugins[name] = pluginInstall
@ -151,7 +148,7 @@ func RpcPluginInstall(name string, version string) error {
return fmt.Errorf("failed to start plugin %s: %v", name, err)
}
// TODO: Determine if the old version should be removed
// TODO: Determine if the old extract should be removed
return nil
}

View File

@ -1,4 +1,4 @@
import { PluginStatus } from "@/hooks/stores";
import { PluginStatus, usePluginStore } from "@/hooks/stores";
import Modal from "@components/Modal";
import AutoHeight from "@components/AutoHeight";
import Card, { GridCard } from "@components/Card";
@ -33,6 +33,8 @@ function Dialog({ plugin, setOpen }: { plugin: PluginStatus | null, setOpen: (op
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const {setIsPluginUploadModalOpen} = usePluginStore();
useEffect(() => {
setLoading(false);
}, [plugin])
@ -73,6 +75,11 @@ function Dialog({ plugin, setOpen }: { plugin: PluginStatus | null, setOpen: (op
});
}, [send, plugin, setOpen])
const uploadPlugin = useCallback(() => {
setOpen(false);
setIsPluginUploadModalOpen(true);
}, [setIsPluginUploadModalOpen, setOpen])
return (
<AutoHeight>
<div className="mx-auto max-w-4xl px-4 transition-all duration-300 ease-in-out">
@ -118,6 +125,30 @@ function Dialog({ plugin, setOpen }: { plugin: PluginStatus | null, setOpen: (op
</div>
</div>
<div className="grid grid-cols-[auto,1fr] gap-x-4 text-sm text-black dark:text-white">
<span className="font-semibold">
Name
</span>
<span>{plugin?.name}</span>
<span className="font-semibold">
Active Version
</span>
<span>{plugin?.version}</span>
<span className="font-semibold">
Description
</span>
<span>{plugin?.description}</span>
<span className="font-semibold">
Homepage
</span>
<a href={plugin?.homepage} target="_blank" rel="noopener noreferrer" className="text-blue-600 hover:text-blue-800 dark:text-blue-500 dark:hover:text-blue-400">
{plugin?.homepage}
</a>
</div>
<div className="h-[1px] w-full bg-slate-800/10 dark:bg-slate-300/20" />
<div
@ -129,15 +160,15 @@ function Dialog({ plugin, setOpen }: { plugin: PluginStatus | null, setOpen: (op
{error && <p className="text-red-500 dark:text-red-400">{error}</p>}
{plugin?.message && (
<>
<p className="text-sm text-gray-500 dark:text-gray-400">
Plugin message:
</p>
<Card className={cx(
"text-gray-500 dark:text-gray-400 p-4 border",
plugin.status === "error" && "border-red-200 bg-red-50 text-red-800 dark:text-red-400",
)}>
{plugin.message}
</Card>
<p className="text-sm text-gray-500 dark:text-gray-400">
Plugin message:
</p>
<Card className={cx(
"text-gray-500 dark:text-gray-400 p-4 border",
plugin.status === "error" && "border-red-200 bg-red-50 text-red-800 dark:text-red-400",
)}>
{plugin.message}
</Card>
</>
)}
<p className="text-sm text-gray-500 dark:text-gray-400 py-10">
@ -154,6 +185,13 @@ function Dialog({ plugin, setOpen }: { plugin: PluginStatus | null, setOpen: (op
}}
>
<div className="flex items-center w-full space-x-2">
<Button
size="MD"
theme="primary"
text="Upload New Version"
disabled={loading}
onClick={uploadPlugin}
/>
<Button
size="MD"
theme="blank"

View File

@ -67,7 +67,7 @@ export default function PluginList() {
theme="light"
text="Settings"
onClick={() => {
setConfiguringPlugin(plugin);
setConfiguringPlugin(plugin.name);
setPluginConfigureModalOpen(true);
}}
/>
@ -85,7 +85,7 @@ export default function PluginList() {
updatePlugins();
}
}}
plugin={plugins.find(p => p.name == configuringPlugin?.name) ?? null}
plugin={plugins.find(p => p.name == configuringPlugin) ?? null}
/>
<div className="flex items-center gap-x-2">

View File

@ -45,6 +45,8 @@ function Dialog({ setOpen }: { setOpen: (open: boolean) => void }) {
setPluginUploadFilename,
pluginUploadManifest,
setPluginUploadManifest,
setConfiguringPlugin,
setPluginConfigureModalOpen,
} = usePluginStore();
const [send] = useJsonRpc();
const [extractError, setExtractError] = useState<string | null>(null);
@ -112,7 +114,12 @@ function Dialog({ setOpen }: { setOpen: (open: boolean) => void }) {
onInstall={() => {
setOpen(false)
setPluginUploadFilename(null)
// TODO: Open plugin settings dialog
if (pluginUploadManifest) {
setConfiguringPlugin(pluginUploadManifest.name)
setPluginConfigureModalOpen(true)
}
setPluginUploadManifest(null)
setPluginUploadModalView("upload")
}}
onBack={() => {
setPluginUploadModalView("upload")

View File

@ -562,8 +562,8 @@ interface PluginState {
pluginConfigureModalOpen: boolean;
setPluginConfigureModalOpen: (isOpen: boolean) => void;
configuringPlugin: PluginStatus | null;
setConfiguringPlugin: (plugin: PluginStatus | null) => void;
configuringPlugin: string | null;
setConfiguringPlugin: (pluginName: string | null) => void;
}
export const usePluginStore = create<PluginState>(set => ({