import { useEffect, useState } from "react"; import { open } from "@tauri-apps/plugin-dialog"; import type { Project, ProjectPath } from "../../../../lib/types"; import Button from "../../../ui/Button"; import Field, { ConfigGroup, inputClass, monoInputClass } from "../../../ui/Field"; interface Props { project: Project; save: (patch: Partial) => Promise; disabled: boolean; } export default function WorkspaceSection({ project, save, disabled }: Props) { const [name, setName] = useState(project.name); const [paths, setPaths] = useState(project.paths ?? []); useEffect(() => { setName(project.name); setPaths(project.paths ?? []); }, [project]); /** * Save only when every row is fully filled in. * * Both inputs save on blur, so tabbing from the host path to the mount name * fires a save with the name still empty. `update_project` now validates — * a half-filled row is refused — so the unconditional save turned an ordinary * keystroke into an error toast. A blank row is *not* incomplete: the * "+ Add folder" button adds one deliberately, and it is dropped on save. */ const saveIfComplete = () => { const filled = paths.filter((p) => p.host_path.trim() || p.mount_name.trim()); const halfFilled = filled.some((p) => !p.host_path.trim() || !p.mount_name.trim()); if (halfFilled) return; return save({ paths }); }; return ( {(id) => ( setName(e.target.value)} onBlur={() => { const trimmed = name.trim(); if (!trimmed) { setName(project.name); return; } if (trimmed !== project.name) save({ name: trimmed }); }} onKeyDown={(e) => { if (e.key === "Enter") (e.target as HTMLInputElement).blur(); if (e.key === "Escape") setName(project.name); }} className={inputClass} /> )}
Folders

Each host folder is mounted at /workspace/<name>{" "} inside the container.

{paths.map((pp, i) => (
{ const updated = [...paths]; updated[i] = { ...updated[i], host_path: e.target.value }; setPaths(updated); }} onBlur={() => saveIfComplete()} placeholder="/path/to/folder" disabled={disabled} className={`flex-1 min-w-0 ${inputClass}`} />
/workspace/ { const updated = [...paths]; updated[i] = { ...updated[i], mount_name: e.target.value }; setPaths(updated); }} onBlur={() => saveIfComplete()} placeholder="name" disabled={disabled} className={`w-40 ${monoInputClass}`} /> {paths.length > 1 && ( )}
))}
); }