Part of the high-latency work. Measured behind a proxy adding 125 ms each way (250 ms per round trip).
Opening a conversation: two round trips → one.
A thread the list already knows sends Thread/get and the missing bodies in the same tick, so both go in one request.
A thread it doesn't know chains Email/get off Thread/get with a back-reference. When the thread is longer than one Email/get may carry, the members are then fetched in parts.
Measured: the body arrived 257 ms after the press. Before this change it took two sequential requests.
Loading before the click.
A conversation starts loading when the pointer rests on its row for 80 ms, or as soon as a press starts.
Once a conversation is open, the one below it loads in idle time. Moving on with j then fetched no bodies, and the view drew immediately.
Loads of the same thread share one request, and an open that finds a finished prefetch sends nothing more.
Drafts are skipped, since they open in the composer.
The open conversation's bodies were already protected from eviction, so hovering over many rows can't drop them.
Folder switching.
The last 12 plain folder views are kept: up to 200 ids and the total for each.
Going back to one shows that list in the first frame while the query runs. Messages that have since moved out are dropped. Searches and new folders still start empty.
Measured: 29 rows in the first frame, where a skeleton used to show for a round trip.
Cleared on account switch.
Tests. 1,360 pass, with 7 new cases:
one-request open, for both a known and an unknown thread;
fallback for a thread that is too long for one request;
Part of the high-latency work. Measured behind a proxy adding 125 ms each way (250 ms per round trip).
**Opening a conversation: two round trips → one.**
- A thread the list already knows sends `Thread/get` and the missing bodies in the same tick, so both go in one request.
- A thread it doesn't know chains `Email/get` off `Thread/get` with a back-reference. When the thread is longer than one `Email/get` may carry, the members are then fetched in parts.
- Measured: the body arrived 257 ms after the press. Before this change it took two sequential requests.
**Loading before the click.**
- A conversation starts loading when the pointer rests on its row for 80 ms, or as soon as a press starts.
- Once a conversation is open, the one below it loads in idle time. Moving on with `j` then fetched no bodies, and the view drew immediately.
- Loads of the same thread share one request, and an open that finds a finished prefetch sends nothing more.
- Drafts are skipped, since they open in the composer.
- The open conversation's bodies were already protected from eviction, so hovering over many rows can't drop them.
**Folder switching.**
- The last 12 plain folder views are kept: up to 200 ids and the total for each.
- Going back to one shows that list in the first frame while the query runs. Messages that have since moved out are dropped. Searches and new folders still start empty.
- Measured: 29 rows in the first frame, where a skeleton used to show for a round trip.
- Cleared on account switch.
**Tests.** 1,360 pass, with 7 new cases:
- one-request open, for both a known and an unknown thread;
- fallback for a thread that is too long for one request;
- prefetch sharing, skip and dedupe;
- snapshot restore and pruning;
- search and new folders starting empty.
No new UI strings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
**Merged** 2026-09-16 as coffey-labs/ihasmail@786976312fc1
<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.
Part of the high-latency work. Measured behind a proxy adding 125 ms each way (250 ms per round trip).
Opening a conversation: two round trips → one.
Thread/getand the missing bodies in the same tick, so both go in one request.Email/getoffThread/getwith a back-reference. When the thread is longer than oneEmail/getmay carry, the members are then fetched in parts.Loading before the click.
jthen fetched no bodies, and the view drew immediately.Folder switching.
Tests. 1,360 pass, with 7 new cases:
No new UI strings.
🤖 Generated with Claude Code
Merged 2026-09-16 as coffey-labs/ihasmail@786976312f
Rebuilt from: git history, session transcript.