feat(frontend): add usePluginInstallStream hook
This commit is contained in:
74
src/hooks/use-plugin-install-stream.ts
Normal file
74
src/hooks/use-plugin-install-stream.ts
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
import { useCallback, useRef, useState } from "react"
|
||||||
|
import { subscribe } from "@/lib/platform"
|
||||||
|
import type { PluginInstallEvent, PluginInstallEventKind } from "@/lib/types"
|
||||||
|
|
||||||
|
const PLUGIN_INSTALL_EVENT = "app://opencode-plugin-install"
|
||||||
|
|
||||||
|
export type PluginInstallStatus = "idle" | "running" | "success" | "failed"
|
||||||
|
|
||||||
|
interface PluginInstallStreamState {
|
||||||
|
status: PluginInstallStatus
|
||||||
|
logs: string[]
|
||||||
|
error: string | null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function usePluginInstallStream() {
|
||||||
|
const [state, setState] = useState<PluginInstallStreamState>({
|
||||||
|
status: "idle",
|
||||||
|
logs: [],
|
||||||
|
error: null,
|
||||||
|
})
|
||||||
|
const unsubRef = useRef<(() => void) | null>(null)
|
||||||
|
|
||||||
|
const start = useCallback(async (taskId: string) => {
|
||||||
|
setState({ status: "running", logs: [], error: null })
|
||||||
|
|
||||||
|
unsubRef.current?.()
|
||||||
|
|
||||||
|
const unsub = await subscribe<PluginInstallEvent>(
|
||||||
|
PLUGIN_INSTALL_EVENT,
|
||||||
|
(event) => {
|
||||||
|
if (event.task_id !== taskId) return
|
||||||
|
|
||||||
|
switch (event.kind as PluginInstallEventKind) {
|
||||||
|
case "started":
|
||||||
|
setState((prev) => ({ ...prev, status: "running" }))
|
||||||
|
break
|
||||||
|
case "log":
|
||||||
|
setState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
logs: [...prev.logs, event.payload],
|
||||||
|
}))
|
||||||
|
break
|
||||||
|
case "completed":
|
||||||
|
setState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
status: "success",
|
||||||
|
logs: [...prev.logs, event.payload],
|
||||||
|
}))
|
||||||
|
unsubRef.current?.()
|
||||||
|
break
|
||||||
|
case "failed":
|
||||||
|
setState((prev) => ({
|
||||||
|
...prev,
|
||||||
|
status: "failed",
|
||||||
|
error: event.payload,
|
||||||
|
logs: [...prev.logs, `ERROR: ${event.payload}`],
|
||||||
|
}))
|
||||||
|
unsubRef.current?.()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
unsubRef.current = unsub
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const reset = useCallback(() => {
|
||||||
|
unsubRef.current?.()
|
||||||
|
unsubRef.current = null
|
||||||
|
setState({ status: "idle", logs: [], error: null })
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return { ...state, start, reset }
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user