mirror of
https://github.com/bulwarkmail/native.git
synced 2026-11-04 00:06:53 +00:00
docs: inventory the native catch-up with webmail 1.19.1 and stalwart 1.0.1
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
# Native catch-up with webmail 1.19.1 and Stalwart 1.0.1 (2026-11)
|
||||
|
||||
Branch `catch-up-2026-11` from native main 7a42a15f (local main: 0.1.87 plus
|
||||
the unpushed 9d547b9d and 7a42a15f). Latest release 0.1.86. This file holds
|
||||
the inventory (Phase 0), the plan and decisions (Phase 1), then what landed
|
||||
and how it was tested.
|
||||
|
||||
Inventory sources, all checked against native main 7a42a15f and webmail main
|
||||
4887ed457:
|
||||
|
||||
- Webmail 1.19.0, 1.19.1 and the 237 commits since 2026-10-29:
|
||||
docs/parity/11-webmail-1.19.md (42 rows, 11 P2, 31 P3). 1.19.1 is the
|
||||
latest webmail release; the changelog has no Unreleased section.
|
||||
- Stalwart 1.0.1 (2026-10-28, the latest release): below.
|
||||
- Leftovers: the unticked rows of docs/parity/01-10, the "Open" and webmail
|
||||
bug lists of docs/native-sync-2026-10-29.md, the deferred items of
|
||||
docs/ux-audit-2026-10.md and docs/ios-test-2026-10.md, open issues and PRs:
|
||||
below.
|
||||
- Dependencies: below.
|
||||
|
||||
## Stalwart 1.0.1
|
||||
|
||||
v1.0.0...v1.0.1 is one squashed commit. Two release-note lines read the wrong
|
||||
way round: the "Fixed" JMAP lines describe the old bug. 1.0.0 answered a
|
||||
Mailbox, AddressBook, ContactCard or Identity create with only `{id}`; 1.0.1
|
||||
adds the server-set and defaulted properties the client left out (plus
|
||||
myRights, mayDelete, isDefault). Calendar adds description, color and
|
||||
timeZone as null and an empty shareWith when omitted; CalendarEvent adds
|
||||
isDraft, useDefaultAlerts, mayInviteSelf, mayInviteOthers and hideAttendees.
|
||||
Every native create caller reads only the id, re-reads, or merges the reply
|
||||
over what it sent (createMailbox src/api/email.ts:284, createAddressBook
|
||||
src/api/contacts.ts:352, createContact :263-275, createIdentity
|
||||
src/api/identity.ts:39-41, createEvent src/api/calendar.ts:1080, device sync
|
||||
src/device-sync/engine/item-sync.ts:1287-1312), except createCalendar.
|
||||
|
||||
Moving stw-rel to 1.0.1 surfaced two seed failures that looked like 1.0.1
|
||||
changes. Neither is: both behave the same on 1.0.0, and the app sends what
|
||||
both versions want.
|
||||
|
||||
- FileNode creates need `@type` (`File`/`Directory`/`SymLink`) and
|
||||
`mediaType` on the released 1.0.x; `nodeType` and `type` are refused. The
|
||||
app sends that shape whenever the account capability lists
|
||||
`supportedNodeTypes` (src/api/files.ts:67-72, :420-428, every create goes
|
||||
through createFileNodeIn :441-460). The seed script's fallback was written
|
||||
for the pre-release stw-v1 build, which still takes the old shape.
|
||||
- `/api/auth` answered 400 "JSON deserialization failed" to the seed's 0.16
|
||||
body: 1.0.x requires `query`. The app's body (src/lib/totp-login.ts:296-321)
|
||||
carries `query` and `consent: true`; probed on 1.0.1 it deserializes and
|
||||
gets as far as the client check.
|
||||
|
||||
Findings:
|
||||
|
||||
- [ ] **A new calendar lands in the store without its name and colour** — `P2` — `bug` (also on 1.0.0)
|
||||
- What Stalwart does: the Calendar/set create answer never echoes properties the client sent (crates/jmap/src/calendar/set.rs:1307-1367).
|
||||
- What RN does: createCalendar returns `created` alone (src/api/calendar.ts:1269) and the store inserts it (src/stores/calendar-store.ts:1415-1423), so the calendar shows nameless and colourless until the next fetch.
|
||||
- Fix hint: `{ ...props, ...created }`, as createEvent does. Live test in live-stalwart-calendar.
|
||||
|
||||
- [ ] **iOS Maestro OAuth flows have no step for the consent page** — `P2` — `test`
|
||||
- What Stalwart does: on 1.0.1 the consent page comes after Sign in, once per client grant ("Allow"/"Deny", login.html:462-463), for every client that isn't a Stalwart-installed Application, `bulwark-mobile` included.
|
||||
- What RN does: .maestro/subflows/stalwart-login-page.yaml types and taps Sign in, then inbox.yaml waits for the tab bar. The app doesn't depend on the order (oauth-native.ts never sends `prompt=consent`). The iOS e2e server (`vars.E2E_SERVER`) is the 0.16 server, so CI isn't affected today.
|
||||
- Fix hint: optional `runFlow when visible "Allow"` tap at the end of the subflow.
|
||||
|
||||
- [ ] **A `consentRequired` answer reads as a wrong password** — `P3` — `bug`
|
||||
- What Stalwart does: new answer `{type:'consentRequired', token}` and request `{type:'authConsent', token, query, consent}` in 1.0.1.
|
||||
- What RN does: readStalwartLoginResponse maps it to invalid credentials (src/lib/totp-login.ts:344-380). Not reachable while `consent: true` is sent. The webmail has the same gap (lib/auth/stalwart-login-request.ts).
|
||||
- Fix hint: answer it with `authConsent` and the same query, or a clear error.
|
||||
|
||||
- [ ] **The encrypt-on-upload copy no longer matches the server** — `P3` — `docs`
|
||||
- What Stalwart does: 1.0.1 stores JMAP `$draft` messages and the Sent copy unencrypted (crates/email/src/message/ingest.rs:608-611).
|
||||
- What RN does: no workaround for encrypted drafts; the comment at src/api/account-security.ts:249-254 says sent mail is encrypted too.
|
||||
- Fix hint: fix the comment; a live check in live-stalwart-compose that a draft and the Sent copy read back as text with encryption on.
|
||||
|
||||
No action: registry listings now return only the requested account (an admin
|
||||
login no longer sees other accounts' keys, src/api/account-security.ts:299-307);
|
||||
the iTIP PRIORITY fix (RSVP is a participationStatus patch); the
|
||||
FORGED_RCVD_TRAIL fix lowers spam scores the app shows; `denyLocation` left
|
||||
GET /api/auth/client (the app reads only `error`); telemetry, ACME, RocksDB,
|
||||
WebUI and installer changes.
|
||||
|
||||
## Leftovers
|
||||
|
||||
### Older parity files (01-10)
|
||||
|
||||
95 unticked rows: 77 still open, 3 done but unticked, 7 blocked, 8 not to
|
||||
do. About 15 of the 24 open rows in 01-09 duplicate a file 10 row. The four
|
||||
commits after file 10 close none.
|
||||
|
||||
- Done, to tick: templates sync on Stalwart 1.0 (04, fac318dc; 0.16 still
|
||||
needs settings sync), calendar strings (05, 84fef142), iOS push (08,
|
||||
f62849d1).
|
||||
- Not to do, reasons kept from the rows: identity visibility refresh (04),
|
||||
S/MIME send stub (04, see #58), component set on new calendars #760 (05),
|
||||
push without CalendarEvent types (05), legacy flat-name migration (07),
|
||||
stability banner (07), status bar theming (08), sharing before 0.16.6 (10,
|
||||
below the app's minimum).
|
||||
- Blocked on the webmail: hand-off password in the fragment, org policy,
|
||||
session limits, external sender chip, external recipient confirm, org
|
||||
signature and disclaimer (10), settings sync (08).
|
||||
- Priority changes: up to P2 the DuckDuckGo favicons (leak every sender
|
||||
domain and the device IP, on by default, src/lib/avatar-utils.ts:149,
|
||||
src/stores/settings-store.ts:312), the blockquote freeze, direction-override
|
||||
characters in attachment names, and no notification when the push lookup
|
||||
fails (#1041). Down to P3 the 09 offline-send row (same item as 04 and 10).
|
||||
- New: the move sheet still picks icons by folder name
|
||||
(src/components/MoveSheet.tsx:20-28), the #1235 bug 96c7c045 fixed in the
|
||||
sidebar. The recipient splitter row also covers pasting into the composer.
|
||||
|
||||
The policy route doesn't take a JMAP bearer token (app/api/admin/policy/route.ts:15,
|
||||
lib/auth/instance-details.ts:23). Without a session it still answers the
|
||||
global restrictions, feature gates, defaults and theme policy, and strips only
|
||||
organisation data, scopes, plugins and push relays (route.ts:19-37). If the
|
||||
app kept the webmail URL it gets at pairing or hand-off (src/lib/oauth.ts:292
|
||||
parses it, nothing stores it), the global locks need no webmail change.
|
||||
|
||||
### Report "Open" (2026-10-29)
|
||||
|
||||
- [ ] **iOS: reader CSP, composer nonce, `target=_blank` taps, #81 keyboard** — `P2` — `partial` — needs an iOS run (e2e-ios.yml in testing step 4)
|
||||
- [ ] **iOS push lapses after 7 days without opening the app** — `P2` — `bug` — the extension has no expiry handling (plugins/ios-push/NotificationService.swift), no BGTask; needs a device to verify
|
||||
- [ ] **Login switch from a deep link or notification keeps the old navigation stack** — `P2` — `bug` — App.tsx:118-122, :141-145, :181-186 switch and navigate on top; question 7
|
||||
- [ ] **Sieve editor loses typed text (#1162)** — `P3` — `bug` — src/components/filters/SieveEditorSheet.tsx:35-41 re-seeds on every content change
|
||||
- [ ] **No forward limit (#1155, #1208), no vacation length warning** — `P3` — `missing` — FilterRuleModal.tsx:443-459, VacationSettings.tsx:140-142
|
||||
- [ ] **Other-zone daily series keeps a wrong recurrenceId on the device's DST day** — `P3` — `bug` — src/lib/recurrence-expansion.ts:526-536 builds candidates from device-local fields
|
||||
- [ ] **New strings English-only** — `P3` — `partial` — 331 overlay keys missing in 25 locales, 86 in de; question 6
|
||||
- [ ] **Org policy, hand-off password** — blocked on the webmail (above)
|
||||
- [ ] **`C:\ns` junction and the native-sync worktree still exist** — chore — C:\ns points at C:\Users\info\worktrees\native-sync (e6e5e521, on main)
|
||||
|
||||
### Webmail bugs from the 2026-10-29 report
|
||||
|
||||
All 19 are fixed in the app. In the webmail, 17 are still open at current
|
||||
lines, one is fixed (invitation trust: failing DKIM beat dmarc=pass,
|
||||
e1b43c894, dropped) and one is fixed except alerts the settings rows don't
|
||||
show keep their old ids (lib/calendar-alerts.ts:206). The carried list with
|
||||
current lines is in "Webmail bugs" at the end of this file.
|
||||
|
||||
### UX audit deferred (docs/ux-audit-2026-10.md)
|
||||
|
||||
- [ ] **U-133 no way out of a hung "Signing in"** — `P2` — `missing` — src/screens/LoginScreen.tsx:218 swallows Back while busy, SigningInStep has no cancel; abortable sign-in, M
|
||||
- [ ] **U-069 recipient suggestions hidden in phone landscape** — `P2` — `missing` — needs a full-screen picker, M (feature)
|
||||
- [ ] **U-045 German Prev/Next read "Zurück"/"Weiter"** — `P3` — `bug` — override in locales/rn/de.json
|
||||
- [ ] **Plain-text mail dark background fixed at #0a0a0a** — `P3` — `partial` — src/lib/email-html.ts:963 ignores the theme
|
||||
- [ ] **U-017 system alert vs Dialog, U-136 empty all-day strip, U-124 language order** — product calls, kept deferred unless you say otherwise
|
||||
- U-016 scrim token: won't fix (no visible change). U-018 font scale resets navigation: React Native limitation. U-131: done (776447dd).
|
||||
|
||||
### iOS test deferred (docs/ios-test-2026-10.md)
|
||||
|
||||
- [ ] **Sign-in and features matrices empty; the last three release runs of e2e-ios failed** — `P2` — most failures miss seeded mail, so a reset and seed of stw-v016 comes first (testing step 4)
|
||||
- [ ] **ios-perf branch never merged** (d13769a9, measured -18% to first inbox) — not part of this run unless you want it
|
||||
- Blocked on a device or setup: real APNs path through the extension, QR scan with the camera, SSO pairing (needs an external IdP), discovery success (needs DNS records), iOS widgets (WidgetKit extension, L).
|
||||
- Done: the six app bugs from the test (on main), the webmail hand-off fix 310f910a6.
|
||||
|
||||
### GitHub (bulwarkmail/native)
|
||||
|
||||
- Fixed on main, unreleased (close after 0.1.87 ships): #80, #82, #83, #84, #86, #87, #89. #81 is fixed in code (01983a38), unchecked on iOS.
|
||||
- [ ] **#91 multi-select without long press** — `P3` — `missing` — EmailListScreen.tsx:190-218; tap on the avatar toggles selection
|
||||
- [ ] **#90 custom calendar colours** — `P3` — `missing` — CalendarEditSheet.tsx:222 offers the palette only
|
||||
- [ ] **#85 keep the shade open on Delete** — question 1
|
||||
- [ ] **#58 PGP / S/MIME** — `P3` — L, not in this run
|
||||
- [ ] **#3 TLS client certificates** — Android done in 0.1.83; iOS has none (L)
|
||||
- [ ] **PR #66 unified views for a single account** (lucletoffe) — conflicts, no review, the author's question unanswered
|
||||
|
||||
## Dependencies
|
||||
|
||||
Expo SDK 54 (expo 54.0.33, React Native 0.81.5, React 19.1.0). Newest stable
|
||||
is SDK 58 (React Native 0.88, React 19.3), four behind; SDK 54 still gets
|
||||
patch releases.
|
||||
|
||||
npm audit: 53 findings (2 critical, 17 high, 32 moderate, 2 low). Three chains
|
||||
ship in the app:
|
||||
|
||||
- postal-mime 3.0.0, high, reachable: quadratic CPU on RFC 2047 headers; the
|
||||
app parses .eml attachments and embedded messages with it
|
||||
(src/components/email/use-body-override.ts). Fixed in 4.0.8+; the webmail
|
||||
moved to postal-mime 4 on 2026-10-29 (4aea0976a). The local patch
|
||||
(Blob from typed arrays) has to be redone for 4.2.0.
|
||||
- query-string/decode-uri-component and nanoid via React Navigation, high,
|
||||
not reachable (no `linking` prop; default nanoid size). React Navigation
|
||||
native 7.5.1 drops them.
|
||||
|
||||
The rest (both criticals included: tar, shell-quote) sit in Expo CLI, Metro,
|
||||
the dev server or vitest and run only on dev machines and CI; a lockfile
|
||||
refresh within current ranges clears most.
|
||||
|
||||
Upgrades:
|
||||
|
||||
- On SDK 54 now: postal-mime 4.2.0 (redo the patch; fixes the advisory, risk:
|
||||
the RN Blob path, covered by src/lib/__tests__/postal-mime-rn.test.ts),
|
||||
@react-navigation native 7.5.1 with native-stack and bottom-tabs 7.21.0
|
||||
(drops two advisories, risk: navigation regressions, needs the emulator
|
||||
walk), zustand 5.0.16, jszip 3.10.2, vitest 4.1.12, the SDK 54 patch line
|
||||
(expo 54.0.38, expo-file-system 19.0.24, expo-image-picker 17.0.11,
|
||||
expo-localization 17.0.9), lockfile refresh.
|
||||
- With an SDK bump (its own project): SDK 58 means Gradle 9 and AGP 9 hand
|
||||
edits in android/, removing newArchEnabled/edgeToEdgeEnabled, Node 22 in
|
||||
six workflow lines, iOS 16.4 minimum, Expo's fetch replacing the global
|
||||
fetch (SDK 56), async File.write (StorageSettings.tsx:105,
|
||||
use-file-preview.ts:75), foreground notifications shown by default
|
||||
(calendar-notifications.ts), react-native-webview 14 (mail body and
|
||||
composer), react-native-android-widget 0.26 (the #52 patch can probably
|
||||
go). SDK 57 first keeps AGP 9 as its own step.
|
||||
- Skip: AsyncStorage 3, TypeScript 7, vitest 5.
|
||||
|
||||
## Test rig changes (VM 106)
|
||||
|
||||
- stw-rel moved from Stalwart 1.0.0 to 1.0.1 (servers.conf, backup
|
||||
servers.conf.bak-2026-10-31), reset and seeded with rel_setup.sh: 93 ok,
|
||||
0 failed.
|
||||
- seed.py (backup seed.py.bak-2026-10-31): FileNode creates retry in the
|
||||
draft-18 shape (`@type`, `mediaType`) when the server asks for `@type` or
|
||||
refuses `type`; the TOTP login registers a public client with the data
|
||||
scopes on 1.0 and sends `query` and `consent: true`. Checked: TOTP login
|
||||
works on stw-v016 and stw-rel, and stw-rel seeds cleanly.
|
||||
- stw-v016 is on 0.16.27, the newest 0.16. Not reset yet.
|
||||
|
||||
## Plan
|
||||
|
||||
Wave 1 runs four agents with disjoint files. Wave 2 takes the larger
|
||||
features and what depends on your answers. Dependency upgrades come last in
|
||||
their own worktree. Rows not listed under "Not in this run" are in a wave.
|
||||
|
||||
### Wave 1
|
||||
|
||||
**reader** (mail reading and the list; owns src/components/email/** except
|
||||
CalendarInvitationBanner and QuickReplyBox, EmailListScreen, EmailThreadScreen,
|
||||
SenderAvatar, MoveSheet, SidebarDrawer, TagSheet, src/lib/email-headers.ts,
|
||||
email-html.ts, attachment-display.ts, list-attachments.ts, avatar-utils.ts,
|
||||
src/stores/email-store.ts, src/api/email.ts list properties, tag-counts.ts)
|
||||
|
||||
- Security: forged From shows a shield, not the photo or favicon (11, P2);
|
||||
favicons off by default (10, P2 after re-rating); blockquote freeze (10,
|
||||
P2); direction-override characters in attachment names (10, P2); DKIM
|
||||
`header.i` (11, P3).
|
||||
- Mail: plain-text reading honours "Plain Text Only" plus a per-message
|
||||
switch (11, P2); body text size follows the app setting and font scale
|
||||
(11, P2); reduce motion and paused animated images in mail (11, P3); reply
|
||||
hidden on drafts and scheduled (11); report parts out of list chips (11);
|
||||
typed reader attachment icons (11); initials colour (11); search results
|
||||
into the open folder (11); MoveSheet icons by role (new); keyword undo
|
||||
(11); sort button (11); folder list selected state and unread label (11);
|
||||
#91 select by avatar tap; file 10 mail-list P3s (#1241, #1156, #1219,
|
||||
#1136, paperclip on inline-only, row growth, cold start folder, scroll
|
||||
position, folder deep link, "via" badge, quick reply off #1370); plain-text
|
||||
mail follows the theme's colours (UX audit).
|
||||
|
||||
**compose** (owns ComposeScreen, QuickReplyBox, src/components/compose/**,
|
||||
TemplateSheet, src/lib/compose-*.ts, editor-html.ts, reply-compose.ts,
|
||||
recipients.ts, placeholder-check.ts, identity/signature code)
|
||||
|
||||
- Quick reply runs the composer's checks (11); quoted history collapsed (11);
|
||||
new tag from the tag picker and Manage from the template picker (11); confirm
|
||||
before send (11, setting shared with reader's delete/archive confirms); alt
|
||||
text prompt (11); report parts not forwarded (11); file 10 composer P3s
|
||||
(signature swap on From change, plain-text part, composer prompts, schedule
|
||||
presets incl. "This morning"/"This afternoon" #1390, reply cursor, address
|
||||
autofill, recipient splitter, offline send message without the queue);
|
||||
04 group-account send row (verify against 31d8e4a4 first).
|
||||
|
||||
**calendar** (owns src/components/calendar/**, Calendar screens and stores,
|
||||
src/api/calendar.ts, src/lib/calendar-*.ts, recurrence-expansion.ts,
|
||||
CalendarInvitationBanner, contacts screens/stores/api, files screens/api,
|
||||
src/components/filters/**, src/lib/sieve/**, VacationSettings)
|
||||
|
||||
- createCalendar merge (Stalwart, P2, live test); cancellation removes the
|
||||
meeting (11, P2); event and task editors ask before discarding (11, P2);
|
||||
calendar grid labels (11, P2); shared calendar server colour (11); #90
|
||||
custom colours; DST recurrenceId; file 10 calendar P3s (save without
|
||||
invitations, task moves #1204, working hours, week all-day, light colours,
|
||||
birthday colour, duplicate/export/copy, date deep links); contacts P3s
|
||||
(category delete, list filters, deep links, autocomplete groups and recent
|
||||
recipients 06 P2); files P3s (copy folders, numbered names, next/previous,
|
||||
deep links); Sieve P3s (forward limit, vacation length, editor text loss,
|
||||
size value, undo after deleting rules).
|
||||
|
||||
**platform** (owns src/components/Input.tsx, ToastHost, UndoSnackbar,
|
||||
OfflineBanner, src/theme/**, SettingsScreen and src/components/settings/**
|
||||
except VacationSettings, LoginScreen and src/screens/login/**,
|
||||
src/lib/totp-login.ts, oauth*.ts, src/stores/auth-store.ts, App.tsx,
|
||||
src/lib/push-*.ts, src/i18n/**, locales/**)
|
||||
|
||||
- Accessibility page with phone presets and a wider text size (11, P2);
|
||||
field names (11, P2); announcements on iOS and the Undo bar (11, P2);
|
||||
contrast of muted text with a test (11, P2); toast duration (11); TOTP
|
||||
prompt tone (11); same-name accounts and port (11, question 9); density
|
||||
sample (11); identity editor discard (11); U-133 cancel sign-in (P2);
|
||||
consentRequired (Stalwart); encrypt-on-upload copy (Stalwart); file 10
|
||||
account P3s (IDN, IdP end session, refused token exchange message);
|
||||
push extras (#1041 fallback notification P2, Inbox-only, one ring, re-check
|
||||
on return); quota softLimit #1242; capability check #1239; screenshot
|
||||
protection; Thai and Estonian, locale sync, German "du" strings, U-045.
|
||||
|
||||
### Wave 2
|
||||
|
||||
- **cards**: booking, parcel and order cards with calendar add/update (11, P2).
|
||||
- **recovery**: recover deleted items #1319 and delegates (Stalwart 1.0).
|
||||
- **search**: search snippets and size filter (10).
|
||||
- Depending on your answers: nav reset (question 7), #85, MIG-02, the org
|
||||
policy with the kept webmail URL (and BIMI and help links behind it),
|
||||
translations, Stalwart live cases and the Maestro consent step (me).
|
||||
- **deps**: approved upgrades, own worktree and node_modules, last.
|
||||
|
||||
### Not in this run (reason)
|
||||
|
||||
- Blocked on the webmail: hand-off one-time code, bearer-token policy route
|
||||
(session limits, org signature and disclaimer, external mail settings),
|
||||
settings sync on 0.16.
|
||||
- Needs a device or setup this rig doesn't have: iOS push expiry in the
|
||||
extension, real APNs path, QR camera, SSO pairing, discovery success.
|
||||
- Large features, each its own project: iOS widgets, PGP/S/MIME #58, iOS
|
||||
client certificates #3, dark mode recolour, offline send queue, free/busy
|
||||
and CalendarEventNotification, Jalali and Saturday week start, composer
|
||||
extras (priority, mentions, DSN), tag nesting and visibility, global search
|
||||
and mail folder sharing, U-069 landscape recipient picker, reading fonts,
|
||||
colour-blind palette, plain language, the Involved sound (new channel ids).
|
||||
- Product calls kept as they are: U-017, U-124, U-136, U-018 (RN limitation).
|
||||
- PR #66 and the ios-perf branch: outside this branch.
|
||||
|
||||
## Webmail bugs (carried forward, not fixed in the webmail)
|
||||
|
||||
Inline images of drafts and sent mail on 1.0 only from `attachments`
|
||||
(components/email/email-viewer.tsx:2508; email-composer.tsx:953, :969, :1445,
|
||||
:2669, :2703). Save to Files on 0.16 stores the whole message
|
||||
(save-to-files-dialog.tsx:78-88). Blob/copy without the blob capability
|
||||
(lib/jmap/client.ts:10047). Reschedule after a lost answer can strand or
|
||||
double-send (client.ts:11686, :11706, :11721). Alerts the settings rows don't
|
||||
show keep their old ids (lib/calendar-alerts.ts:206). Sieve parser drops
|
||||
`elsif`/`else` and trailing comments (lib/sieve/parser.ts:251-263); generator
|
||||
falls back to `header :contains` (lib/sieve/generator.ts:105, :126). Vacation
|
||||
with a failed filter re-include only logs (stores/vacation-store.ts:206-210).
|
||||
Feed sync without END:VCALENDAR check or mass-deletion guard
|
||||
(stores/calendar-store.ts:1978). HELO SPF pass counts as aligned
|
||||
(lib/email-headers.ts:64). Files trash: purge without a fresh read
|
||||
(stores/file-store.ts:1947), restore with its folder lands at the root
|
||||
(:1914), no `.Trash` name check (lib/file-name-rules.ts:78). Push: no device
|
||||
client id check (lib/web-push.ts:788), cap path destroys first (:853),
|
||||
refused relay URL shown raw (components/settings/notification-settings.tsx:180).
|
||||
Probably: decoded CSS put back into STYLE (lib/email-sanitization.ts:613-740);
|
||||
Lite refresh follows redirects (lib/auth/lite-tokens.ts:536, also :376, :399,
|
||||
:467, :504). New in this pass: `consentRequired` reads as a wrong password
|
||||
(lib/auth/stalwart-login-request.ts).
|
||||
@@ -0,0 +1,251 @@
|
||||
# Webmail 1.19.0 and 1.19.1
|
||||
|
||||
## Summary
|
||||
The last pass (file 10) covered webmail 1.10.0 to 1.18.0 and the commits after the 1.18.0 release up to early 2026-10-29 (b0d1a97bb..4aea0976a). This file walks the changelog sections 1.19.0 (2026-10-29) and 1.19.1 (2026-10-31) and every webmail commit since (`git log --since=2026-10-29`, 237 commits; `4aea0976a..4887ed457` gives 238, the extra one is the plugin page fix #1358). There is no Unreleased section; 1.19.1 is the latest release. Checked against native main at 7a42a15f. Web paths are relative to the webmail root, native paths to this repo.
|
||||
|
||||
Many 1.19.0 entries were in "Unreleased" when file 10 was written and already have rows there (organisation policy, delegates, recover deleted items, shared tags and team templates, Files trash). They are not repeated; the unticked file 10 rows they touch are listed at the end.
|
||||
|
||||
Counts: 42 rows, P1 0, P2 11, P3 31.
|
||||
|
||||
What stands out:
|
||||
- A forged From still gets the real sender's favicon or contact photo. The webmail shows a warning shield in its place now.
|
||||
- The 1.19.1 booking, parcel and order cards are missing. The webmail's `lib/structured-mail` is plain TypeScript and takes the HTML parser as a parameter, so it can be ported.
|
||||
- The 1.19.0 accessibility work has little counterpart on the phone: form fields without names, toasts and Undo not read out on iOS, grey text at 2.56:1 in the light theme, a mail body fixed at 14 px, and a "Plain Text Only" switch that promises plain-text reading but doesn't change it.
|
||||
- Calendar: a cancellation mail can't remove the meeting, and the event and task editors throw typed changes away.
|
||||
|
||||
Classification: `bug` = fixed in the webmail, still live in the app; `missing`; `partial`. Not applicable on mobile and left out (same list as file 10): admin panel, plugins and marketplace, command palette, keyboard shortcuts and keyboard navigation, print, Bulwark Lite, CSP/third-party switch as a server feature, Mountain View, desktop-only layout (drag and drop, hover, multi-pane), server routes the app doesn't use, Docker, docs, demo mode and translation-only entries.
|
||||
|
||||
## Findings
|
||||
|
||||
### Reading mail
|
||||
|
||||
- [ ] **A forged From keeps the real sender's favicon and contact photo** — `P2` — `bug`
|
||||
- What WEB does: when the sender check fails or is unverified, the avatar shows a warning shield instead of a photo, logo or initials, in the reader, the conversation and the list (`components/ui/avatar.tsx:323`, `hooks/use-sender-warning.ts:13`, `components/email/email-viewer.tsx:721`). The list fetch asks for `header:Authentication-Results:all` (`lib/jmap/client.ts:461`). 605a3983b (#1439).
|
||||
- What RN does: MessageHeader works out the verdict (`src/components/email/MessageHeader.tsx:118`) but renders SenderAvatar with the claimed address (`:175`); the same in thread cards (`src/components/email/ThreadMessageCard.tsx:50`) and list rows (`src/screens/EmailListScreen.tsx:213`). SenderAvatar picks a contact photo or the domain favicon (`src/components/SenderAvatar.tsx:62-65`). List rows have no auth data (`src/api/email.ts:23-26`).
|
||||
- Fix hint: pass a sender warning from getSenderVerification into SenderAvatar and draw a shield; for list rows add `header:Authentication-Results:all` to the list properties.
|
||||
|
||||
- [ ] **No booking, parcel or order cards from schema.org markup** — `P2` — `missing`
|
||||
- What WEB does: reads JSON-LD/microdata booking markup and attached Wallet passes and shows a card above the message (flight, train, bus, hotel, rental car, event, restaurant, parcel tracking, order status) with copy buttons and links that show where they lead. Bookings go into a calendar the user picks with stable UIDs, so a later mail updates the event and a cancellation removes it. Gate: the receiving server verified the From domain, not a forward, not a personal mailbox provider, not turned off by the admin (`lib/structured-mail/index.ts:36`, `trust.ts:104`, `pkpass.ts`, `calendar.ts:147`, `components/email/structured-mail/use-booking-calendar.ts:115`, `lib/structured-mail-gate.ts:7`). a529e6e57..859d368a1.
|
||||
- What RN does: nothing; the only banners above the body are unsubscribe and invitation (`src/components/email/MessageContent.tsx:104`, `:112`).
|
||||
- Fix hint: port `lib/structured-mail/` with an RN-side HTML parser passed through `parseHtml` (`lib/structured-mail/index.ts:4-5`, `:21`) and build RN cards. The admin switch needs the org policy, so default on.
|
||||
|
||||
- [ ] **"Plain Text Only" says it also changes reading, but the reader ignores it** — `P2` — `bug`
|
||||
- What WEB does: reads HTML mail as plain text by default or per message (`lib/html-to-readable-text.ts:39`, `components/email/email-viewer.tsx`; 1e929b0a9).
|
||||
- What RN does: the switch reads "Compose and read in plain text only" (`src/components/settings/ReadingSettings.tsx:208-210`), but only the composer and the placeholder check read plainTextMode (`src/lib/compose-html.ts:175`, `src/lib/placeholder-check.ts:157`); EmailBodyView never does (`src/components/EmailBodyView.tsx:529-537`).
|
||||
- Fix hint: render the text part (or the HTML turned into text) when the setting is on, and add a per-message "Show as plain text".
|
||||
|
||||
- [ ] **Mail body ignores the app's text size and iOS Dynamic Type** — `P2` — `missing`
|
||||
- What WEB does: bodies follow the chosen text size, with a separate mail text size and a minimum font size (`lib/mail-reading.ts:32`, `:42`; c07ba1a37).
|
||||
- What RN does: the body is fixed at 14 px for HTML and plain text (`src/lib/email-html.ts:695`, `:979`); the app's text size scales only the app's own UI (`src/theme/dynamic.ts:48-69`). Android's WebView may follow the system font size (no textZoom set; unverified), iOS doesn't. Pinch zoom exists (`src/components/EmailBodyView.tsx:408`).
|
||||
- Fix hint: scale the body's base font size by the app setting and `PixelRatio.getFontScale()`.
|
||||
|
||||
- [ ] **Reading aids: paused animated images, reduce motion in mail, reader view, read aloud, reading width** — `P3` — `missing`
|
||||
- What WEB does: animations in mail stop with reduce motion (24a13cc1f), animated images pause behind a play button (bb7869798), plus reader view, read aloud, reading mask and width (caed2d313, af3019ea2, a982c3f23, 8cc0f8f25, dcc0d600f).
|
||||
- What RN does: none. The app reads reduce motion (`src/theme/dynamic.ts:92`) but doesn't pass it into mail.
|
||||
- Fix hint: pass reduce motion into the body CSS (animation off, GIFs paused) first; read aloud and reader view are left to the OS.
|
||||
|
||||
- [ ] **No BIMI sender logos or verified-mark check** — `P3` — `missing`
|
||||
- What WEB does: when DMARC passes for the exact From domain the avatar shows the domain's BIMI logo before the favicon, with a check mark when a VMC/CMC backs it; DNS and certificate checks run on the webmail server (`lib/email-headers.ts:175`, `components/ui/avatar.tsx:292`, `app/api/bimi/route.ts:49`). cf0eb03c4.
|
||||
- What RN does: contact photo, DuckDuckGo favicon, initials (`src/components/SenderAvatar.tsx:38`, `:62-65`; `src/lib/avatar-utils.ts:149`).
|
||||
- Fix hint: use the paired webmail's `/api/bimi` once the app keeps the webmail URL (same blocker as the org policy, file 10).
|
||||
|
||||
- [ ] **A DKIM pass reported only by `header.i` doesn't count (#1420)** — `P3` — `bug`
|
||||
- What WEB does: takes the signer domain from `header.i` when `header.d` is missing (`lib/email-headers.ts:282`, `:346`). f8f2e93cd.
|
||||
- What RN does: reads `header.d` only (`src/lib/email-headers.ts:397`); such mail shows as unverified and its invitations lose trust.
|
||||
- Fix hint: port identityDomain.
|
||||
|
||||
- [ ] **Reply and quick reply are offered on drafts and scheduled messages in a conversation** — `P3` — `bug`
|
||||
- What WEB does: hides Reply and Reply all on a conversation's drafts and scheduled messages (`components/email/email-viewer.tsx:881`). 8b29254a6 (#1404).
|
||||
- What RN does: every card is replyable (`src/screens/EmailThreadScreen.tsx:1212`, `src/components/email/ThreadMessageCard.tsx:68-85`); quick reply targets the last member, which can be the user's own draft (`src/screens/EmailThreadScreen.tsx:1124`).
|
||||
- Fix hint: `replyable={false}` for `$draft` and scheduled members; point quick reply at the newest message that is neither.
|
||||
|
||||
- [ ] **Bounce and receipt report parts show as list chips and go along on forward** — `P3` — `bug`
|
||||
- What WEB does: leaves `message/delivery-status`, `message/disposition-notification` and their `global-` forms out of list chips and forwards (`lib/attachment-visibility.ts:73`, `components/email/email-composer.tsx:985`). 8a09ba573.
|
||||
- What RN does: the reader hides them (`src/lib/attachment-display.ts:56`, `:130`), list chips and forwards don't (`src/lib/list-attachments.ts:21`, `src/lib/reply-compose.ts:14-19`); isReportPart misses the `global-` types.
|
||||
- Fix hint: filter isReportPart in both places and add the two global types.
|
||||
|
||||
- [ ] **Attachment icons in the reader aren't coloured by file type** — `P3` — `partial`
|
||||
- What WEB does: reader chips use the list's per-type icon and colour (`components/email/attachment-chips.tsx`). a78d03a18.
|
||||
- What RN does: list chips are typed (`src/components/email/ListAttachmentChips.tsx:96`), reader chips use a plain paperclip (`src/components/email/AttachmentChips.tsx:244`).
|
||||
- Fix hint: reuse attachmentKind in AttachmentChips.
|
||||
|
||||
- [ ] **Avatar initials are always white, even on light colours** — `P3` — `bug`
|
||||
- What WEB does: picks black or white initials by contrast (`components/ui/avatar.tsx:174-182`; 2e13accad).
|
||||
- What RN does: always `#ffffff` (`src/components/SenderAvatar.tsx:130-133`); several palette colours give 3.1 to 3.7:1 (`src/lib/avatar-utils.ts:19-20`, `:47-48`).
|
||||
- Fix hint: port initialsColor.
|
||||
|
||||
### Mail list and search
|
||||
|
||||
- [ ] **Search results can't be moved into the open folder (#1452)** — `P3` — `bug`
|
||||
- What WEB does: a search across folders keeps the open folder selected, and hits from other folders can move into it (`lib/move-targets.ts:71`). dafdda534.
|
||||
- What RN does: the move sheet greys out the current folder (`src/components/MoveSheet.tsx:110-115`) and the single-row pick returns on it (`src/screens/EmailListScreen.tsx:1904-1918`), even for rows from other folders.
|
||||
- Fix hint: in search mode mark a folder current only when the rows are already in it.
|
||||
|
||||
- [ ] **No Undo for read/unread, star and tag changes** — `P3` — `missing`
|
||||
- What WEB does: the toast offers Undo and puts back each message's previous keywords (`lib/email-action-toast.ts:86`). ee17c0dba.
|
||||
- What RN does: UndoEntry covers archive, delete, move and spam only (`src/stores/email-store.ts:322`).
|
||||
- Fix hint: a `keywords` undo kind with the original keywords per item.
|
||||
|
||||
- [ ] **No Sort menu in the list header** — `P3` — `partial`
|
||||
- What WEB does: Sort menu with the order presets in the list header (`components/email/mail-list-menus.tsx`). e3f1ccce7.
|
||||
- What RN does: the header only flips the direction (`src/screens/EmailListScreen.tsx:1193`); presets live in Settings > Layout (`src/components/settings/LayoutSettings.tsx:88-104`).
|
||||
- Fix hint: a sort button that opens the presets.
|
||||
|
||||
- [ ] **Tag counts don't use Keyword/get where the server counts keywords (#1399)** — `P3` — `missing`
|
||||
- What WEB does: one Keyword/get when the capability has `supportsCounts`, else two Email/query per tag (`lib/jmap/client.ts:2721`, `:2737`).
|
||||
- What RN does: always two queries per tag (`src/api/tag-counts.ts:22-40`).
|
||||
- Fix hint: same check and fallback. Stalwart doesn't advertise counts, so low value.
|
||||
|
||||
- [ ] **The folder list doesn't say which folder is open, and the unread count reads "Show unread"** — `P3` — `bug`
|
||||
- What WEB does: says which folder is open and how many are unread (7c282f1f4, 80a2a212a).
|
||||
- What RN does: folder rows have no selected state (`src/components/SidebarDrawer.tsx:170-180`); the count is a button labelled "Show unread" (`:126-133`).
|
||||
- Fix hint: `accessibilityState.selected` and a label like "Inbox, 3 unread".
|
||||
|
||||
### Composer and sending
|
||||
|
||||
- [ ] **Quick reply skips the placeholder, forgotten-attachment and confirm checks** — `P3` — `bug`
|
||||
- What WEB does: quick reply runs the composer's checks (`lib/outgoing/quick-reply.ts:34`). 534049952.
|
||||
- What RN does: the composer has them (`src/screens/ComposeScreen.tsx:2078`, `:2137`), QuickReplyBox sends straight away (`src/components/email/QuickReplyBox.tsx:78-140`).
|
||||
- Fix hint: run unfilledPlaceholdersInMessage and the attachment keyword check before send.
|
||||
|
||||
- [ ] **Quoted reply history isn't collapsed in the composer** — `P3` — `missing`
|
||||
- What WEB does: collapses the quote behind an ellipsis button (`components/email/reply-quote-collapse.ts:13`). 9e0089604 (#1405).
|
||||
- What RN does: seeds the full quote into the editor (`src/screens/ComposeScreen.tsx:562-615`).
|
||||
- Fix hint: hide the quoted block in the editor behind a toggle, keep it in the sent body.
|
||||
|
||||
- [ ] **Tag picker can't make a tag; template picker can't open the template manager** — `P3` — `missing`
|
||||
- What WEB does: "New tag" in the tag picker (`components/email/tag-picker.tsx:214`), "Manage" in the template picker (`components/templates/template-picker.tsx:227`). 19676a14f.
|
||||
- What RN does: tag sheets list existing tags only (`src/screens/EmailThreadScreen.tsx:1489`, `src/components/TagSheet.tsx`); the template sheet shows "No templates yet" with no way on (`src/components/TemplateSheet.tsx:148-150`).
|
||||
- Fix hint: a "New tag" row and a "Manage templates" link.
|
||||
|
||||
- [ ] **No optional confirm before sending, deleting or archiving** — `P3` — `missing`
|
||||
- What WEB does: `sendConfirmation`, `confirmDelete`, `confirmArchive` (`components/email/email-composer.tsx:501`, `lib/mail-removal-confirm.ts:24`, `lib/accessibility-settings.ts:93-94`). 4d91d9b29, 374ae9c8d.
|
||||
- What RN does: asks only before a permanent delete (`src/lib/delete-confirm.ts:27`).
|
||||
- Fix hint: three settings and an Alert in the send, delete and archive paths, swipes and quick reply included.
|
||||
|
||||
- [ ] **No alt-text prompt for images, no default compose font** — `P3` — `missing`
|
||||
- What WEB does: asks for alt text when an image goes in (`components/email/image-alt-dialog.tsx`; 53cb49d3c), starts new mail in a chosen font and size (1b24c1980), offers an accessible example template (420bf8f9a).
|
||||
- What RN does: alt is the file name (`src/screens/ComposeScreen.tsx:1857`, `src/lib/editor-html.ts:413-419`); the editor font is fixed (`src/lib/editor-html.ts:160`).
|
||||
- Fix hint: the alt prompt first.
|
||||
|
||||
### Accessibility
|
||||
|
||||
- [ ] **No Accessibility page or presets** — `P2` — `missing`
|
||||
- What WEB does: Settings > Accessibility with presets (screen reader, low vision, dyslexia, focus, motor, motion, hearing) and text size 87.5% to 200% (`components/settings/accessibility-settings.tsx`, `lib/accessibility-presets.ts:23`, `lib/accessibility-settings.ts:13-22`; 8008393e5, 0731d24f6).
|
||||
- What RN does: no page (`src/screens/SettingsScreen.tsx:150-174`); text size 0.92/1/1.12 (`src/theme/dynamic.ts:14-18`). Text follows the system font scale; reduce motion follows the system (`src/theme/dynamic.ts:88-120`).
|
||||
- Fix hint: a page that groups the existing switches, widens the text size range and takes the presets that make sense on a phone.
|
||||
|
||||
- [ ] **Form fields have no name for screen readers** — `P2` — `bug`
|
||||
- What WEB does: every field has a label tied to it (`components/ui/field.tsx:42`; ef13556a0, 0e2a05e0e, dcc21acd0, 4e2affe40, f73643bbb).
|
||||
- What RN does: the shared Input draws its label as separate Text (`src/components/Input.tsx:40-55`); the Security password and code fields have no label at all (`src/components/settings/AccountSecuritySettings.tsx:181`, `:191`, `:198`); contact fields rely on placeholders (`src/screens/ContactFormScreen.tsx:823-834`); the reminder field's only name is "30" (`src/components/calendar/EventModal.tsx:772`, `:817`).
|
||||
- Fix hint: Input passes its label as accessibilityLabel; every bare TextInput gets one.
|
||||
|
||||
- [ ] **Toasts and Undo are not read out on iOS; the Undo bar isn't read out anywhere** — `P2` — `bug`
|
||||
- What WEB does: live regions and announcements for toasts, loads, new mail, saved drafts and offline (`lib/announce.ts:124`, `components/ui/toast.tsx:471`; 36d13b76b, e2fc2c750, 23813be9b, d713d31af, 4c1f24947).
|
||||
- What RN does: no `announceForAccessibility` call in src; ToastHost and OfflineBanner use accessibilityLiveRegion, which only Android honours (`src/components/ToastHost.tsx:194`, `src/components/OfflineBanner.tsx:33`); the Undo bar has neither (`src/components/UndoSnackbar.tsx:129-160`).
|
||||
- Fix hint: announce through AccessibilityInfo on iOS, live region on the Undo bar.
|
||||
|
||||
- [ ] **Grey text is below 4.5:1 contrast** — `P2` — `bug`
|
||||
- What WEB does: every built-in theme at 4.5:1 or more, with a contrast test (`lib/builtin-themes.ts:16`, `lib/__tests__/theme-contrast.test.ts`; 9f6c7b99c).
|
||||
- What RN does: textMuted is `#94a3b8` on white in the light theme (2.56:1) and `#737373` in dark (4.18:1 on the background, 3.19:1 on surfaces) (`src/theme/tokens.ts:236`, `:140`); used in 456 places, also as placeholder colour.
|
||||
- Fix hint: adjust both, add a contrast test over tokens.ts and builtin-themes.ts.
|
||||
|
||||
- [ ] **The calendar grid reads poorly with a screen reader** — `P2` — `bug`
|
||||
- What WEB does: events sit inside their day cell and day cells have full date names (0026abba4, 19e0acde9).
|
||||
- What RN does: month day cells read only the number and the dots are silent (`src/components/calendar/MonthView.tsx:199-240`); event blocks have no role, label or date (`src/components/calendar/EventBlock.tsx:72-104`).
|
||||
- Fix hint: label day cells with date and event count; event blocks get a button role and a label with title, date and time.
|
||||
|
||||
- [ ] **No reading fonts, text spacing, more contrast or underlined links** — `P3` — `missing`
|
||||
- What WEB does: Atkinson Hyperlegible Next, Lexend, OpenDyslexic, spacing settings, more contrast, underlined links (`lib/accessibility-settings.ts:53-68`; 8008393e5, da215b8c0).
|
||||
- What RN does: none of these settings (`src/stores/settings-store.ts`).
|
||||
- Fix hint: the dyslexia font and line spacing first.
|
||||
|
||||
- [ ] **No colour-blind palette and no names next to colours** — `P3` — `missing`
|
||||
- What WEB does: a colour-blind-safe palette, a tag's letter in its dot, the calendar's name on events (cf4d02b49, d5d7d39ef, 396290003).
|
||||
- What RN does: colours only (`src/components/calendar/EventBlock.tsx:72-104`, `src/components/calendar/MonthView.tsx:233-240`).
|
||||
|
||||
- [ ] **Toast and Undo times are fixed and short** — `P3` — `missing`
|
||||
- What WEB does: one duration setting, 5 to 60 s or until closed (`lib/toast-duration.ts:7-15`; 8d2ebccf0, be5e2dbc5).
|
||||
- What RN does: 5 s, errors 10 s (`src/stores/toast-store.ts:44`), Undo 5 s (`src/components/UndoSnackbar.tsx:15`).
|
||||
- Fix hint: a duration setting and a longer default while a screen reader is on.
|
||||
|
||||
- [ ] **No plain language and no explanations for technical terms** — `P3` — `missing`
|
||||
- What WEB does: simpler English and German wording (`i18n/plain-language.ts`; bb739c744, 9861af6be, 5ffecf692) and term explanations (`components/ui/term.tsx`; 724c45d6e).
|
||||
- What RN does: none (`src/i18n/index.ts:79-140`).
|
||||
|
||||
- [ ] **Accessibility statement, help and sign-language links aren't shown** — `P3` — `missing`
|
||||
- What WEB does: shows the operator's links from the public `/api/config` (`app/api/config/route.ts:104`; 315e29270, 623c9e179).
|
||||
- What RN does: About has only the app's own links (`src/lib/about-links.ts:5-28`); the webmail URL isn't kept (`src/lib/oauth-native.ts:93-108`).
|
||||
- Fix hint: keep the paired webmail URL (also needed for the org policy) and read `/api/config`.
|
||||
|
||||
### Accounts and sign-in
|
||||
|
||||
- [ ] **The two-factor prompt shows as a red error (#1422)** — `P3` — `bug`
|
||||
- What WEB does: an info box with role status, no shake (`app/(main)/[locale]/login/page.tsx:1393`; 141190708).
|
||||
- What RN does: TotpRequiredError sets a notice (`src/screens/LoginScreen.tsx:389-391`) shown in the error tone (`src/screens/login/PasswordStep.tsx:151`, `src/screens/login/LoginNotice.tsx:15-24`).
|
||||
- Fix hint: `tone="info"` for the TOTP step.
|
||||
|
||||
- [ ] **Two accounts with the same name look alike in the switcher** — `P3` — `bug`
|
||||
- What WEB does: the address becomes the title when another account shares the name (`lib/account-utils.ts:159`; 3bb9f7df8).
|
||||
- What RN does: name as title, address below (`src/components/SidebarDrawer.tsx:884-891`, `src/components/settings/AccountSettings.tsx:186`). Report question 9 (port in the label) is the same area.
|
||||
- Fix hint: port accountRowText.
|
||||
|
||||
- [ ] **An expired session drops the open composer without saving** — `P3` — `partial`
|
||||
- What WEB does: open composers save their drafts before the session ends and the login page says if one couldn't be saved (`stores/auth-store.ts` saveDraftsBeforeExpiry; 842c369fa).
|
||||
- What RN does: on a dead refresh the account is evicted with no draft flush (`src/stores/auth-store.ts:1138-1153`, `:1170-1180`). Read from the code, not tried on a device.
|
||||
- Fix hint: flush the open composer's autosave before eviction.
|
||||
|
||||
### Settings
|
||||
|
||||
- [ ] **The density sample shows previews while "Show preview text" is off** — `P3` — `bug`
|
||||
- What WEB does: c166651d1 (`components/settings/appearance-settings.tsx:14-16`).
|
||||
- What RN does: showPreview comes from the density only (`src/components/settings/AppearanceSettings.tsx:11-15`, `:24-27`).
|
||||
|
||||
- [ ] **The identity editor closes without asking about unsaved changes** — `P3` — `bug`
|
||||
- What WEB does: identity, rule and Sieve editors ask (`components/settings/use-discard-changes.tsx`; 9d3ae2203).
|
||||
- What RN does: Close, Cancel and Back call closeEditor (`src/components/settings/IdentitySettings.tsx:122`, `:304`, `:311`, `:389`). FilterRuleModal already asks.
|
||||
|
||||
### Calendar
|
||||
|
||||
- [ ] **A cancellation mail can't remove the meeting from the calendar (#1425)** — `P2` — `missing`
|
||||
- What WEB does: offers "Remove from calendar" for a trusted cancellation from the organizer, for the series or one occurrence, and says when it's outdated (`components/email/calendar-invitation-banner.tsx:627-635`, `:831`, `:1229`, `lib/calendar-cancellation.ts:49`; 357b6af3c).
|
||||
- What RN does: only "This event was cancelled" (`src/components/email/CalendarInvitationBanner.tsx:201`, `:270-272`); it already looks up the server copy (`:122`).
|
||||
- Fix hint: port planCancellationRemoval behind the banner's trust check.
|
||||
|
||||
- [ ] **The event and task editors throw away typed changes on Close or Back** — `P2` — `bug`
|
||||
- What WEB does: asks before closing with unsaved changes (`components/calendar/event-modal.tsx:530-547`, `components/calendar/task-modal.tsx`; 13f9f27c4).
|
||||
- What RN does: close and Back call onClose (`src/components/calendar/EventModal.tsx:495`, `:500`); the task editor resets on the next open (`src/components/calendar/TasksSheet.tsx:135-146`, `:238-253`).
|
||||
- Fix hint: compare with the initial form and ask, as ContactFormScreen does (`src/screens/ContactFormScreen.tsx:639`).
|
||||
|
||||
- [ ] **A shared calendar's server colour is replaced by a random one (#1414)** — `P3` — `bug`
|
||||
- What WEB does: auto-colours only shared calendars with neither a server colour nor an override (`lib/shared-calendar-colors.ts:79`; 2dbe5d024).
|
||||
- What RN does: colours every shared calendar without an override (`src/screens/CalendarScreen.tsx:315-333`).
|
||||
- Fix hint: skip calendars with `cal.color`.
|
||||
|
||||
### Notifications
|
||||
|
||||
- [ ] **New mail can't play the Involved sound** — `P3` — `missing`
|
||||
- What WEB does: Involved by default (`stores/settings-store.ts:949`, `lib/notification-sound.ts:11`). 5eabdd890.
|
||||
- What RN does: the OS channel owns the sound (`src/stores/settings-store.ts:266-267`).
|
||||
- Fix hint: optional; needs a new Android channel id and a bundled iOS sound.
|
||||
|
||||
### i18n
|
||||
|
||||
- [ ] **No Thai or Estonian, and the vendored catalogs are stale** — `P3` — `missing`
|
||||
- What WEB does: 29 languages, Thai new in 1.19.0 (#1379, be52744a5; `i18n/routing.ts:15`).
|
||||
- What RN does: 27 (`src/i18n/index.ts:25-53`); `locales/et/common.json` is vendored but not registered; no `th`. German lacks 1283 of the webmail's keys (last sync 7c914183).
|
||||
- Fix hint: `node scripts/sync-locales.mjs`, register th and et, add overlays.
|
||||
|
||||
- [ ] **Some German phone strings still say "du"** — `P3` — `bug`
|
||||
- What WEB does: formal everywhere (7b720dd22).
|
||||
- What RN does: 12 overlay strings (`locales/rn/de.json`, e.g. settings.privacy.*, settings.backup.description); 18 more in the stale vendored catalog, which the sync fixes.
|
||||
- Fix hint: rewrite with "Sie".
|
||||
|
||||
## Already done in native
|
||||
Return to the list after archive/move/spam (#1458), shared mailbox identity (#1450), Bulwark Mobile client (#1459, 7a42a15f), security settings after a TOTP sign-in (#1432), unique default alert ids (#1435), keep-alive while push is live (#1401), vCard colons and 4.0 export (#1438 9d547b9d, #1407), chip moves between To/Cc/Bcc, placeholder warning, send waits for autosave (#1394), clearing filters keeps the folder (#1430), translated folder names in search (#1429), invitation passing DMARC (#1403), attachment download errors (#1426, #1428), partly failed bulk delete (#1384), .eml preview attachments (#1395), Files move/zip/delete undo, Contacts move and long-press menus, no Edit/Delete on read-only events, reduce motion. Details with file:line are in the inventory drafts summarised in docs/native-sync-2026-11.md.
|
||||
|
||||
## Unticked file 10 rows touched by 1.19
|
||||
Schedule presets (1.19.0 adds "This morning"/"This afternoon", #1390), undo after a cross-account move and in the unified inbox, search snippets and size filter, fixed-width tables (#1020), recover deleted items (#1319), delegates, external sender chip, external recipient confirm, org signature and disclaimer, org policy and session limits (the last five blocked on the policy route).
|
||||
|
||||
## Needs a decision
|
||||
- BIMI and the operator's help links need the app to keep the paired webmail's URL, the same thing the org policy needs.
|
||||
Reference in New Issue
Block a user