import { toast } from "@unom/ui/toast"; import { Play, Power, PowerOff } from "lucide-react"; import type { FC } from "react"; import { type RuntimeStatus, useSetRuntime, useStoreRuntime, } from "@/api/store"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import { m } from "@/paraglide/messages"; // The plugin/script runner is the service every plugin actually executes inside. Installing a plugin // while it's switched off silently gets you nothing running, so Browse carries a banner and the // Installed tab carries the full switch. /** Small helper both surfaces share: fire the toggle, surface a failure as a toast. */ function useRunnerToggle() { const set = useSetRuntime(); const toggle = (enabled: boolean) => { set.mutate(enabled, { onError: () => toast.error(m.store_runner_failed()), }); }; return { toggle, isPending: set.isPending }; } /** * Browse-tab banner: the runner is installed but off, so nothing an operator installs here would * start. Renders nothing in every other state (including "not installed" — the Installed tab's card * explains that case properly). */ export const RunnerBanner: FC = () => { const runtime = useStoreRuntime(); const { toggle, isPending } = useRunnerToggle(); const s = runtime.data; if (!s?.installed || s.enabled) return null; return (

{m.store_runner_banner()}

); }; /** * Container: the runner switch at the top of the Installed tab. Like the library's source toggles * this is a secondary control — it stays out of the way until the query resolves rather than * stacking a second error banner on top of the installed list's own. */ export const RunnerCardSection: FC = () => { const runtime = useStoreRuntime(); const { toggle, isPending } = useRunnerToggle(); if (!runtime.data) return null; return ( ); }; /** The runner card: what the service is, whether it's up, and the one switch that changes it. */ export const RunnerCard: FC<{ status: RuntimeStatus; busy: boolean; onToggle: (enabled: boolean) => void; }> = ({ status, busy, onToggle }) => ( {m.store_runner_title()} {!status.installed ? ( {m.store_runner_state_missing()} ) : status.running ? ( {m.store_runner_state_running()} ) : status.enabled ? ( {m.store_runner_state_stopped()} ) : ( {m.store_runner_state_disabled()} )}

{status.installed ? m.store_runner_help() : m.store_runner_not_installed()}

{m.store_runner_unit()}
{status.unit}
{status.principal && (
{m.store_runner_principal()}
{status.principal}
)}
{status.detail && (

{status.detail}

)} {status.installed && ( )}
);