From 242a53b6082867a35763c4c3a2970f0b8870c9be Mon Sep 17 00:00:00 2001 From: Wolfgang Schoenberger <221313372+wolfiesch@users.noreply.github.com> Date: Fri, 17 Jul 2026 21:44:09 -0700 Subject: [PATCH 1/6] feat: add conflict-safe file editing --- apps/web/src/features/panes/FilesPane.tsx | 114 ++++++++- apps/web/src/features/panes/fixtures.ts | 23 +- .../web/src/features/panes/inspector-store.ts | 225 +++++++++++++++++- apps/web/src/features/panes/live-inspector.ts | 74 +++++- apps/web/src/features/panes/model.ts | 2 + apps/web/test/panes-files.test.ts | 135 ++++++++++- apps/web/test/panes-live.test.ts | 81 ++++++- 7 files changed, 619 insertions(+), 35 deletions(-) diff --git a/apps/web/src/features/panes/FilesPane.tsx b/apps/web/src/features/panes/FilesPane.tsx index 6bed1f63..19589c3a 100644 --- a/apps/web/src/features/panes/FilesPane.tsx +++ b/apps/web/src/features/panes/FilesPane.tsx @@ -1,13 +1,13 @@ // Files pane: lazy workspace tree with search over loaded folders and a // preview surface that stays honest about what it can show — code, images, // binaries, read failures, and offline hosts each get their own state. -import { Badge, cn, Skeleton } from "@t4-code/ui"; +import { Badge, Button, cn, Skeleton } from "@t4-code/ui"; import { ChevronRight, FileText, Folder, ImageIcon, WifiOff } from "lucide-react"; import { useEffect, useMemo } from "react"; import { FamilyEmpty } from "./FamilyEmpty.tsx"; import { PaneHeading } from "./PaneHeading.tsx"; -import { useInspector, type InspectorStoreApi } from "./inspector-store.ts"; +import { useInspector, type FileDraft, type InspectorStoreApi } from "./inspector-store.ts"; import type { FilePreview, FileTreeNode } from "./model.ts"; function formatBytes(bytes: number): string { @@ -203,11 +203,62 @@ function PreviewBody({ preview }: { readonly preview: FilePreview }) { } } +function EditorBody({ + api, + draft, + saveEnabled, +}: { + readonly api: InspectorStoreApi; + readonly draft: FileDraft; + readonly saveEnabled: boolean; +}) { + const saving = draft.status === "saving"; + return ( +
+