fix(reader): propagate SEEN flag off the message-open critical path #170

Merged
JMR-dev merged 6 commits from fix-148-async-seen-flag into main 2026-07-03 01:20:36 +00:00
6 Commits
Author SHA1 Message Date
Jason Ross ecbc052389 Merge main into fix-148-async-seen-flag 2026-07-02 20:08:15 -05:00
Jason Ross 47b7efade7 Merge main into fix-148-async-seen-flag 2026-07-02 19:44:29 -05:00
Jason Ross 565a4ebfa8 Merge main into fix-148-async-seen-flag 2026-07-02 19:33:17 -05:00
Jason Ross e2ab1b8953 Merge main into fix-148-async-seen-flag 2026-07-02 19:21:10 -05:00
Jason Ross 7201ff3eaa Merge branch 'main' into fix-148-async-seen-flag 2026-07-02 19:16:12 -05:00
JMR-devandClaude Opus 4.8 89c9f688a1 fix(reader): propagate SEEN flag off the message-open critical path
openMessage() was running a live imapClient.setFlag(SEEN) IMAP round trip
(connection + STORE) before returning whenever a message's body was already
cached but unread — purely to mark it read on the server. That network call
sat on the reader's critical path even though nothing needed for rendering
(body/attachments) required it, making "open an already-downloaded message"
feel slow (#148).

The local isRead flag is now set immediately (optimistic, local-only) and
openMessage returns without awaiting the SEEN push. The push itself runs on
a new application-lifetime backgroundScope (same CoroutineScope(SupervisorJob()
+ Dispatchers.IO) pattern already used by LibreMailApplication.appScope and
IdleService.scope), with a bounded retry (3 attempts, short backoff) since
today's folder sync deliberately never overwrites local read/star flags with
server state (see MessageDao.updateHeaderContent) and therefore would not
otherwise re-drive a push that never reached the server.

Closes #148

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 16:58:56 -05:00