v2 of the viewer. Edit on text and Markdown, both in the preview dialog and on the row context menu — the menu entry opens straight into the editor.
Save is explicit. Every save mints a new blob, so autosave would burn quota and multiply the conflicts it cannot see.
Two people, one file
The case worth getting right. saveText re-reads the node and compares the blob the editor started from; if somebody else saved in the meantime it refuses, says so, and leaves the work in the box to copy out.
ifInState is the obvious tool and the wrong one here: it is the state of every FileNode in the account, so an unrelated upload in another folder would fail this save — and a warning that cries wolf is a warning people learn to click through. The node’s own blobId answers the actual question.
Where editing is not offered
Each of these would lose data:
truncated for display — saving would write the tail away
not UTF-8 (the replacement character gives it away) — saving would write mojibake over whatever encoding it really is
no mayModifyContent — a read-only share simply has no Edit
The first two open read-only with a line saying which. The row menu can only guess from the name, so opening via menu Edit may still land in the read-only view — that path is handled rather than assumed.
Mail attachments are untouched: they pass no onSave, because a message part is not a thing that can be written back.
Closing or cancelling with unsaved changes asks first (Escape and the backdrop included); Ctrl/Cmd+S saves.
Verified
Mock stack, visible Chrome tab, two tabs for the conflict:
result
hello.txt edit → Save
"Saved", list 29 B → 47 B, view shows the new text
rich.md edit → Ctrl+S
saved, returns to Rendered showing the new document, 350 B → 91 B
tab A dirty, tab B saves first, tab A saves
refused with "Somebody else saved this file while it was open…", tab A’s text still in the box, tab B’s save intact
close while dirty
"Close without saving?" — Cancel keeps the work
row menu on hello.txt
Preview, Edit, Download, … — opens in the editor
row menu on report.pdf
no Edit
typecheck clean, 596 web + 110 server tests, i18n:check clean, build clean.
v2 of the viewer. **Edit** on text and Markdown, both in the preview dialog and on the row context menu — the menu entry opens straight into the editor.
Save is explicit. Every save mints a new blob, so autosave would burn quota and multiply the conflicts it cannot see.
## Two people, one file
The case worth getting right. `saveText` re-reads the node and compares the blob the editor started from; if somebody else saved in the meantime it refuses, says so, and **leaves the work in the box** to copy out.
`ifInState` is the obvious tool and the wrong one here: it is the state of every FileNode in the account, so an unrelated upload in another folder would fail this save — and a warning that cries wolf is a warning people learn to click through. The node’s own blobId answers the actual question.
## Where editing is not offered
Each of these would lose data:
- **truncated for display** — saving would write the tail away
- **not UTF-8** (the replacement character gives it away) — saving would write mojibake over whatever encoding it really is
- **no `mayModifyContent`** — a read-only share simply has no Edit
The first two open read-only with a line saying which. The row menu can only guess from the name, so opening via menu Edit may still land in the read-only view — that path is handled rather than assumed.
Mail attachments are untouched: they pass no `onSave`, because a message part is not a thing that can be written back.
Closing or cancelling with unsaved changes asks first (Escape and the backdrop included); Ctrl/Cmd+S saves.
## Verified
Mock stack, visible Chrome tab, two tabs for the conflict:
| | result |
|---|---|
| `hello.txt` edit → Save | "Saved", list 29 B → 47 B, view shows the new text |
| `rich.md` edit → Ctrl+S | saved, returns to **Rendered** showing the new document, 350 B → 91 B |
| tab A dirty, tab B saves first, tab A saves | refused with "Somebody else saved this file while it was open…", tab A’s text still in the box, tab B’s save intact |
| close while dirty | "Close without saving?" — Cancel keeps the work |
| row menu on `hello.txt` | Preview, **Edit**, Download, … — opens in the editor |
| row menu on `report.pdf` | no Edit |
`typecheck` clean, 596 web + 110 server tests, `i18n:check` clean, build clean.
**Merged** 2026-09-01 as coffey-labs/ihasmail@b5ca0021ef0c
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
v2 of the viewer. Edit on text and Markdown, both in the preview dialog and on the row context menu — the menu entry opens straight into the editor.
Save is explicit. Every save mints a new blob, so autosave would burn quota and multiply the conflicts it cannot see.
Two people, one file
The case worth getting right.
saveTextre-reads the node and compares the blob the editor started from; if somebody else saved in the meantime it refuses, says so, and leaves the work in the box to copy out.ifInStateis the obvious tool and the wrong one here: it is the state of every FileNode in the account, so an unrelated upload in another folder would fail this save — and a warning that cries wolf is a warning people learn to click through. The node’s own blobId answers the actual question.Where editing is not offered
Each of these would lose data:
mayModifyContent— a read-only share simply has no EditThe first two open read-only with a line saying which. The row menu can only guess from the name, so opening via menu Edit may still land in the read-only view — that path is handled rather than assumed.
Mail attachments are untouched: they pass no
onSave, because a message part is not a thing that can be written back.Closing or cancelling with unsaved changes asks first (Escape and the backdrop included); Ctrl/Cmd+S saves.
Verified
Mock stack, visible Chrome tab, two tabs for the conflict:
hello.txtedit → Saverich.mdedit → Ctrl+Shello.txtreport.pdftypecheckclean, 596 web + 110 server tests,i18n:checkclean, build clean.Merged 2026-09-01 as coffey-labs/ihasmail@b5ca0021ef
Rebuilt from: git history, session transcript.