import { useMemo, useState } from "react"; import { Link, Navigate, useNavigate, useSearchParams } from "react-router-dom"; import { LuCopy, LuPencil, LuPlay, LuPlus, LuSearch, LuTrash2 } from "react-icons/lu"; import { errorMessage } from "../api/client.js"; import { useDeleteScript, useForkScript, useInstallPlugin, useScripts, } from "../api/hooks.js"; import { ScriptIcon } from "../components/ScriptIcon.jsx"; import { TagBadge } from "../components/TagBadge.jsx"; import { scriptTags } from "../lib/script.js"; import { useNotifications } from "../notifications.jsx"; export function ScriptsPage() { const [params] = useSearchParams(); const navigate = useNavigate(); const editName = params.get("edit"); const { data: scripts = [], isLoading } = useScripts(); const [confirmDelete, setConfirmDelete] = useState(null); const [query, setQuery] = useState(""); const [forkFor, setForkFor] = useState(null); const [forkId, setForkId] = useState(""); const del = useDeleteScript(); const fork = useForkScript(); const install = useInstallPlugin(); const { notify } = useNotifications(); const visible = useMemo(() => { const term = query.trim().toLowerCase(); if (!term) return scripts; return scripts.filter((s) => { const name = typeof s === "string" ? s : s.name ?? ""; const description = typeof s === "string" ? "" : s.meta?.description ?? ""; const tags = typeof s === "string" ? [] : scriptTags(s.meta); const kind = typeof s === "string" ? "" : s.kind ?? ""; return ( name.toLowerCase().includes(term) || description.toLowerCase().includes(term) || kind.toLowerCase().includes(term) || tags.some((t) => t.toLowerCase().includes(term)) ); }); }, [scripts, query]); if (editName) { return ; } return (

Scripts

Add plugin
{install.isError ? (

{errorMessage(install.error)}

) : null} {isLoading ? ( ) : scripts.length === 0 ? (

No scripts yet.

) : visible.length === 0 ? (

No scripts match “{query.trim()}”.

) : (
{visible.map((s) => { const name = typeof s === "string" ? s : s.name; const description = typeof s === "string" ? "" : s.meta?.description; const metaError = typeof s === "string" ? null : s.metaError; const hasIcon = typeof s === "string" ? undefined : s.hasIcon; const tags = typeof s === "string" ? [] : scriptTags(s.meta); const kind = typeof s === "string" ? "core" : s.kind ?? "core"; const isCore = kind === "core"; return (

{name}

{kind}

{metaError ? ( {metaError} ) : ( description || "—" )}

{tags.length ? (
{tags.map((tag) => ( setQuery(tag)} /> ))}
) : null}
{isCore ? ( ) : ( )} {!isCore ? ( ) : null}
); })}
)} {forkFor ? (

Fork {forkFor}

Creates plugin/<id> from this core script.

setForkId(e.target.value)} /> {fork.isError ? (

{errorMessage(fork.error)}

) : null}
) : null} {confirmDelete ? (

Delete {confirmDelete}?

This uninstalls the plugin.

{del.isError ? (

{errorMessage(del.error)}

) : null}
) : null}
); }