mirror of
https://github.com/Ark0N/Codeman.git
synced 2026-10-07 07:59:42 +02:00
feat(file-viewer): edit mode for text files (edit + save in the viewer)
Closes #212. The file-preview overlay can now edit workspace text files in place, phone-first: agent writes a file, you review it in the viewer, tweak two lines, save, tell the agent to continue. Backend (file-routes.ts, policy in src/config/file-editing.ts): - GET file-content?edit=1: read-for-edit that never truncates (a truncated buffer must never become an edit buffer), 512KB cap (413 over it), and returns the sha256 hash + detected EOL the client echoes back on save. - PUT /api/sessions/:id/file-content: edit-in-place only, with no O_CREAT anywhere in the handler. Confinement matches the read path (realpath + workspace boundary + ownership via findSessionOrFail), plus sensitive-path and attachment-guard blocklists, a .git subtree deny, and an extension allowlist (svg and env deliberately excluded). Optimistic concurrency via baseHash: mismatch is a 409 unless force. Writes are wx-temp + fchmod + fsync + rename, closing the validate-then-write TOCTOU window. - Corruption guards: NUL sniff + UTF-8 round-trip compare (refuses binary and latin-1), and server-side EOL re-application so a textarea's LF normalization cannot rewrite every line of a CRLF file. - Plain reads gain an additive editable flag the UI keys the button off. Frontend (panels-ui.js + overlay markup/styles): - Edit button on editable text previews; textarea editor with Save/Cancel, dirty indicator, discard-confirm on cancel/close, and a conflict dialog that offers overwrite (force) when the file changed on disk mid-edit. - Phone: full-bleed window sized by --app-height so the editor and Save bar track the OS keyboard; 16px editor font (iOS zoom guard); no autofocus. - zh-CN strings for the new chrome. Tests: pure policy unit tests plus a route suite that deliberately does NOT mock node:fs. It runs against a real temp workspace so symlink escapes, write-through of in-workspace symlinks, mode preservation, CRLF round-trip, 409/force, and the no-create property are exercised for real. Also verified end to end on an isolated beta instance: 39-check curl matrix, Playwright desktop flow (real clicks and typing, bytes asserted on disk, live conflict with an external rewrite), and a 393px phone profile. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -9430,6 +9430,84 @@ kbd {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* ---- File Viewer edit mode (issue #212) ---- */
|
||||
|
||||
.file-preview-body textarea.file-preview-editor {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0;
|
||||
padding: 0.75rem;
|
||||
border: none;
|
||||
outline: none;
|
||||
resize: none;
|
||||
background: var(--bg-dark);
|
||||
color: var(--text);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 0.8rem;
|
||||
line-height: 1.5;
|
||||
white-space: pre;
|
||||
overflow-wrap: normal;
|
||||
overflow: auto;
|
||||
tab-size: 4;
|
||||
}
|
||||
|
||||
.file-preview-editbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.4rem 0.75rem;
|
||||
border-top: 1px solid var(--border);
|
||||
background: var(--bg-input);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.file-preview-editbar[hidden] {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.file-preview-editbar-spacer {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.file-preview-dirty {
|
||||
font-size: 0.7rem;
|
||||
color: var(--warning, #e5c07b);
|
||||
}
|
||||
|
||||
.file-preview-dirty::before {
|
||||
content: '\25CF ';
|
||||
}
|
||||
|
||||
.file-preview-editbar-btn {
|
||||
padding: 0.3rem 0.9rem;
|
||||
font-size: 0.75rem;
|
||||
border-radius: 6px;
|
||||
border: 1px solid var(--control-border);
|
||||
background: var(--bg-input);
|
||||
color: var(--text);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.file-preview-editbar-btn:hover {
|
||||
background: var(--bg-hover, rgba(255, 255, 255, 0.08));
|
||||
}
|
||||
|
||||
.file-preview-editbar-btn--save {
|
||||
background: var(--accent);
|
||||
border-color: var(--accent);
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.file-preview-editbar-btn--save:hover {
|
||||
background: var(--accent-hover);
|
||||
}
|
||||
|
||||
.file-preview-editbar-btn--save:disabled {
|
||||
opacity: 0.45;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
/* ========== Log Viewer Windows (Floating) ========== */
|
||||
|
||||
.log-viewer-window {
|
||||
|
||||
Reference in New Issue
Block a user