"use client"; import { useEffect, useMemo, useState } from "react"; import { Button } from "@kandev/ui/button"; import { Input } from "@kandev/ui/input"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@kandev/ui/select"; import type { EditorOption } from "@/lib/types/http"; type CustomKind = "custom_command" | "custom_remote_ssh" | "custom_hosted_url"; export type EditorFormState = { name: string; kind: CustomKind; command: string; host: string; user: string; url: string; scheme: string; enabled: boolean; }; const CUSTOM_KIND_OPTIONS: Array<{ value: CustomKind; label: string }> = [ { value: "custom_command", label: "Command" }, { value: "custom_remote_ssh", label: "VS Code Remote SSH" }, { value: "custom_hosted_url", label: "Hosted URL" }, ]; const PLACEHOLDER_HINT = "{cwd} {file} {rel} {line} {column}"; export function getCustomKindLabel(kind: string) { return CUSTOM_KIND_OPTIONS.find((option) => option.value === kind)?.label ?? "Custom"; } export function isCustomEditor(editor: EditorOption) { return editor.kind.startsWith("custom"); } function editorConfigValue(editor: EditorOption, key: string) { if (!editor.config || typeof editor.config !== "object") { return ""; } const value = (editor.config as Record)[key]; return typeof value === "string" ? value : ""; } export function getCustomEditorSummary(editor: EditorOption) { switch (editor.kind) { case "custom_command": { return editorConfigValue(editor, "command") || getCustomKindLabel(editor.kind); } case "custom_hosted_url": { return editorConfigValue(editor, "url") || getCustomKindLabel(editor.kind); } case "custom_remote_ssh": { const host = editorConfigValue(editor, "host"); const user = editorConfigValue(editor, "user"); if (host && user) return `${user}@${host}`; if (host) return host; return getCustomKindLabel(editor.kind); } default: return getCustomKindLabel(editor.kind); } } export function buildConfig(state: EditorFormState) { switch (state.kind) { case "custom_command": return { command: state.command }; case "custom_remote_ssh": return { host: state.host, user: state.user || undefined, scheme: state.scheme || undefined, }; case "custom_hosted_url": return { url: state.url }; default: return {}; } } export function defaultFormState(): EditorFormState { return { name: "", kind: "custom_command", command: "", host: "", user: "", url: "", scheme: "", enabled: true, }; } function resolveEditorName(state: EditorFormState) { const trimmed = state.name.trim(); if (trimmed) return trimmed; switch (state.kind) { case "custom_remote_ssh": return state.host.trim(); case "custom_hosted_url": return state.url.trim(); case "custom_command": default: return state.command.trim(); } } export function formStateFromEditor(editor: EditorOption): EditorFormState { return { name: editor.name, kind: (editor.kind as CustomKind) || "custom_command", command: editorConfigValue(editor, "command"), host: editorConfigValue(editor, "host"), user: editorConfigValue(editor, "user"), url: editorConfigValue(editor, "url"), scheme: editorConfigValue(editor, "scheme"), enabled: editor.enabled, }; } export function resolveAvailableEditors(editors: EditorOption[]) { return editors.filter((editor) => { if (!editor.enabled) return false; if (editor.kind === "built_in") return editor.installed; return true; }); } export function resolveDefaultEditorId(editors: EditorOption[], desiredId: string) { const available = resolveAvailableEditors(editors); if (desiredId && available.some((editor) => editor.id === desiredId)) { return desiredId; } if (!desiredId && available.length > 0) { return available[0].id; } return ""; } type EditorFormProps = { title: string; initialState: EditorFormState; onCancel: () => void; onSave: (state: EditorFormState) => void; submitLabel: string; isSaving: boolean; }; function EditorKindFields({ state, setField, }: { state: EditorFormState; setField: (key: K, value: EditorFormState[K]) => void; }) { if (state.kind === "custom_command") { return (
setField("command", event.target.value)} placeholder="code --goto {file}:{line}" />

Supports placeholders: {PLACEHOLDER_HINT}

); } if (state.kind === "custom_remote_ssh") { return (
setField("host", event.target.value)} placeholder="ssh-host.example.com" /> setField("user", event.target.value)} placeholder="optional username" /> setField("scheme", event.target.value)} placeholder="optional scheme (vscode, cursor)" />

Opens a VS Code Remote SSH URL using the scheme (example:{" "} vscode://vscode-remote/ssh-remote+user@host:/path/file:line).

); } if (state.kind === "custom_hosted_url") { return ( setField("url", event.target.value)} placeholder="https://code.example.com" /> ); } return null; } export function EditorForm({ title, initialState, onCancel, onSave, submitLabel, isSaving, }: EditorFormProps) { const [state, setState] = useState(initialState); useEffect(() => { setState(initialState); }, [initialState]); const setField = (key: K, value: EditorFormState[K]) => { setState((prev) => ({ ...prev, [key]: value })); }; const isValid = useMemo(() => { const resolvedName = resolveEditorName(state); if (!resolvedName) return false; if (state.kind === "custom_command") return Boolean(state.command.trim()); if (state.kind === "custom_remote_ssh") return Boolean(state.host.trim()); if (state.kind === "custom_hosted_url") return Boolean(state.url.trim()); return false; }, [state]); const handleSave = () => { const resolvedName = resolveEditorName(state); onSave(resolvedName === state.name ? state : { ...state, name: resolvedName }); }; return (
{title}
setField("name", event.target.value)} placeholder="Editor name" />
); }