The only unread cues were a font-weight bump and a grey-to-white shift
on the sender name, which barely render on some device fonts and are
nearly invisible in the dark theme. Mirror the webmail's dedicated
indicator (email-list-item.tsx): an 8px circle in the theme's existing
unread color, vertically centered in the row's start gutter, shown in
both the mailbox list and the unified inbox.
Verified on a Pixel 7 API 34 emulator in dark theme: unread rows are
unambiguous at a glance, read rows unchanged.
PR #20 (c5e5092) fixed#11 on Android by moving the editor page to
android/app/src/main/assets/editor.html, but the real bug was never
'webview scripting broken in release builds': the template literal in
buildEditorHtml cooked the insertLink scheme-regex escapes into an
invalid regex, and that SyntaxError killed the whole inline script.
The PR's buildEditorScript (injectedJavaScript) still contains the
cooked regex, so its theme/init injection dies on Android and the
editor stays completely dead on iOS, whose page no longer has any
inline script.
Resolve by keeping the lib-based editor from the local fix (valid,
escape-free inline script for both platforms, regression-tested in
src/lib/__tests__/editor-html.test.ts, verified on a Pixel 7 API 34
release build) and dropping the now-unused editor.html asset. All
other upstream fixes are kept.
The template literal in buildEditorHtml cooked the backslash escapes in
the insertLink scheme regex (\/ and \? became bare / and ?), so the page
received /^(https?:|mailto:|tel:|sms:|/|?|#)/i — an invalid regex. The
resulting SyntaxError killed the entire inline editor script: no change
messages ever reached RN, bodyHtml stayed empty, canSend never enabled
without an attachment, and mails sent with one had empty bodies.
Regressed in 29b06a3.
Rewrite the scheme check without backslash escapes and move the page
builder into src/lib/editor-html.ts so a unit test can assert the emitted
script parses and stays backslash-free.
Verified on a Pixel 7 API 34 emulator (release build): typing now posts
change messages and the plain-text body extraction sees the content.
Coalesces concurrent OAuth token refreshes using a Promise-based lock map keyed by the refresh token. This prevents the app from firing duplicate refresh requests with the same expired refresh token, which causes replay revocations on OIDC providers (e.g. Authelia/Hydra) enforcing strict rotation.
Also optimizes persistRefreshedTokens and ensureFreshCredentials to prevent redundant SecureStore/disk writes when concurrent operations complete.
Fixes#14