feat(editor-v2): files-overlay reads/writes via window.__filesEditor

Routes 8 call sites through the cm6 controller alias:
- 5 reads (byte-count, save POST, dirty checks at 306, 481, 496, 511,
  528) → getEditorValue() helper, falling back to
  editorEls.contentBox.value if window.__filesEditor isn't mounted
  (no-JS / pre-mount path).
- 3 writes (clear, "Loading…" placeholder, fetched body content at
  362, 395, 402) → setEditorValue() helper with the same fallback.

The two helpers live inline next to editorEls so the rest of the
module's call sites stay close to existing style.

Known regressions (out of scope for v2, candidate follow-ups):
- Byte-count badge updates only on file-open / setContent calls, not
  live on every keystroke. Needs a controller.onChange(cb) hook.
- Ctrl+S inside cm6 doesn't trigger the modal Save. cm6 owns the
  keymap in its editing surface; users can still click the Save
  button. Adding a custom cm6 keymap entry would restore the
  shortcut.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
mwiegand 2026-05-17 02:08:42 +02:00
parent 59446bc105
commit 42bdc6ad98
No known key found for this signature in database

View file

@ -281,12 +281,29 @@
saveBtn: editorDialog.querySelector(".files-editor-save"),
};
// Bridge to the CodeMirror 6 controller, set up by static/js/editor.js
// on the .files-editor-content textarea. Falls back to the textarea
// directly if the bundle didn't load (no-JS fallback / file open
// before the controller has been mounted).
function getEditorValue() {
return (window.__filesEditor && window.__filesEditor.getValue)
? window.__filesEditor.getValue()
: editorEls.contentBox.value;
}
function setEditorValue(text) {
if (window.__filesEditor && window.__filesEditor.setContent) {
window.__filesEditor.setContent(text);
} else {
editorEls.contentBox.value = text;
}
}
function setEditorTitle(text) {
editorEls.title.textContent = text;
}
function updateByteCount() {
const bytes = new TextEncoder().encode(editorEls.contentBox.value).length;
const bytes = new TextEncoder().encode(getEditorValue()).length;
editorEls.byteCount.textContent = `UTF-8 · ${bytes} bytes`;
}
@ -342,7 +359,7 @@
setEditorTitle(`${folder ? folder + "/" : ""}…new file`);
editorEls.filename.value = "";
editorEls.filename.disabled = false;
editorEls.contentBox.value = "";
setEditorValue("");
editorEls.contentBox.disabled = false;
editorEls.renameHint.hidden = true;
editorEls.textPanel.hidden = false;
@ -375,14 +392,14 @@
editor.mode = "text";
editorEls.textPanel.hidden = false;
editorEls.binaryPanel.hidden = true;
editorEls.contentBox.value = "Loading…";
setEditorValue("Loading…");
editorEls.contentBox.disabled = true;
const r = await fetchJson(
`${baseUrl}/files/content?path=${encodeURIComponent(path)}`
);
if (r.ok && r.body) {
editorEls.contentBox.value = r.body.content;
setEditorValue(r.body.content);
editorEls.contentBox.disabled = false;
updateByteCount();
updateSaveEnabled();
@ -461,7 +478,7 @@
// Text-flavor create → /save with no new_path.
const r = await postJson(`${baseUrl}/files/save`, {
path: newRel,
content: editorEls.contentBox.value,
content: getEditorValue(),
});
if (r.ok) {
editorDialog.close();
@ -476,7 +493,7 @@
// For files, a plain /save overwrite is fine.
const r2 = await postJson(`${baseUrl}/files/save`, {
path: newRel,
content: editorEls.contentBox.value,
content: getEditorValue(),
});
if (r2.ok) {
editorDialog.close();
@ -491,7 +508,7 @@
const altered = withCollisionSuffix(newRel);
const r2 = await postJson(`${baseUrl}/files/save`, {
path: altered,
content: editorEls.contentBox.value,
content: getEditorValue(),
});
if (r2.ok) {
editorDialog.close();
@ -508,7 +525,7 @@
if (editor.mode === "text") {
const payload = {
path: editor.originalPath,
content: editorEls.contentBox.value,
content: getEditorValue(),
};
if (renaming) payload.new_path = newRel;
const r = await postJson(`${baseUrl}/files/save`, payload);