The chunked buffer was the right structure for this workload, but the
implementation let the edited chunk grow without bound (the type comment
even admitted 'not rebalanced'): sustained typing at one spot made that
chunk grow monotonically, so each subsequent insert copied the whole
grown chunk -- quadratic total copy work for sustained typing.
Insert now splits any chunk that grows past 2x the target size in half,
and the empty-buffer path chunks a large first paste directly instead of
creating one oversized chunk. The per-edit copy cost is now bounded by
O(chunkSize) by construction. The split cut is an arbitrary byte offset
(like SetContent boundaries): chunk edges may fall inside multi-byte
sequences, which is fine because readers reassemble whole line-aligned
windows from chunk bytes.
Shrunken/empty chunks from deletes are left in place: chunk count never
grows with deletes, all readers walk actual lengths, and removal would be
pure churn with no reader-side benefit.
No behavior change visible to readers (Content/FullContent/LineIndex all
walk actual chunk lengths); covered by three new tests: sustained-typing
chunk-size invariant + content, large paste into empty buffer, and
content integrity across newly created split boundaries. Full suite green
under -race.
- Viewport: swallow the opening tap/scroll (justOpenedAt window) and
re-clamp ScrollOffset to [0,MaxScroll] in EditorLayout so a short file
never opens past its content (blank viewport).
- Chunked buffer: replace the fixed i*chunkSize slot model (which drifted
after length-changing edits and could re-read stale disk for shifted
tail chunks) with an ordered chunk slice + prefix-sum byte offsets.
In-range files now load fully on open (SetContent), so there is no lazy
load and no stale-disk re-read. Edits splice only the affected chunk(s).
- Size guard: files > MaxEditableFileSize (50 MB) show a 'too large to
edit' notice instead of loading; the browser still lists them. Edit
handlers (KeyDown/ReplaceRange) are no-ops for too-large files.
- Tests: rewrite chunked_buffer_test.go for prefix-sum correctness (insert/
delete across chunk boundaries, rune->byte after edit); fix the large-file
e2e expectation to the shift-correct ground truth.