Goes through the 7 exhaustive-deps warnings individually:
Added the genuinely-missing dependency (safe, no extra churn):
- email-viewer useMemo: add effectiveEmailContent.hasStyleTag (used for
hasOwnLayout; changes in lockstep with .html, closing a latent staleness gap).
- pro-compose-tab-body handleSend: add refreshCurrentMailbox (stable zustand
selector) and drop the stale fetchEmails/selectedMailbox deps — which left
those two selectors entirely unused, so remove them too.
- use-mailbox-drop handleDrop: add sourceMailboxId (changes in lockstep with
draggedEmails, already a dep).
Suppressed with a justified comment where depending on the whole object would
regress behavior — these are intentional fine-grained deps:
- email-composer signature-swap effect (keyed to signature fields + prev*Ref
guards; whole signatureIdentity would re-splice the live editor).
- email-viewer auto-mark-as-read (whole email would reset the delay timer on
any unrelated field update).
- email-viewer effective-attachments memo (derives from email.attachments;
whole email would churn the list + its layout measurement).
- email-viewer auto-MDN effect (email already captured via id +
sendReadReceiptNow; autoMdnRef guards double-send).
tsc --noEmit clean; eslint now reports 0 problems.
Clicking an email address in the viewer already shows a contact detail
sidebar. An "Edit" button now appears there (for known contacts) that
navigates directly to the contact edit form via the existing URL-param
intent system (?contactId=…&view=edit), removing the need to open the
Contacts page manually and search for the contact.
Some emails (Outlook / templated HTML) set `html, body { height: 100% }` in
their own <style>. Combined with the viewer srcDoc's `overflow: hidden` and the
scrollHeight-based iframe auto-resize, the measured height collapses to the
iframe's initial size, so everything below the first screenful (often just the
header/logo) is clipped and the rest of the message is invisible.
Force `height: auto !important` on html/body in the rendered srcDoc so the
document grows to its real content height before scrollHeight is measured.
Bulwark had no read-receipt support (JMAP/Stalwart have no native MDN).
End-to-end, client-side, in three parts:
- Request (compose): a toolbar toggle (MailCheck, green when on) sets
Disposition-Notification-To on the outgoing message via the JMAP
"header:<name>:asText" create property. Threaded composer -> page ->
email-store -> client.sendEmail. Default from requestReadReceiptDefault.
- Detect (viewer): reads Disposition-Notification-To case-insensitively from
the parsed headers and shows a banner (green Send / red Ignore) in the
unified notification bar. Hidden in Sent/Drafts/Trash/Junk and once handled.
message/disposition-notification + message/delivery-status report parts are
filtered out of the attachment list.
- Respond (MDN): lib/mdn.ts builds an RFC 8098 multipart/report (text/plain +
message/disposition-notification, UTF-8/base64, localized subject + body).
client.sendReadReceipt uploads the blob, imports it into Sent via
Email/import, then submits with an explicit envelope. Both Send and Ignore
set the $MDNSent keyword (RFC 3503) so no client re-prompts. Behaviour
configurable: ask / always / never.
New: lib/mdn.ts, read-receipt-banner.tsx. Settings (requestReadReceiptDefault,
readReceiptResponse) + UI. All 17 locales.
The global rule
td, th { word-break: break-word; }
was breaking HTML-email tables one glyph per row whenever a column was
narrow, especially for Hebrew/Arabic/CJK headers and long English
strings. The non-standard `word-break: break-word` keyword behaves
like `break-all` in some engines, splitting words at arbitrary
character boundaries even when the word would fit if the column auto-
expanded.
`overflow-wrap: break-word` is already set on body/table, so the rule
only needs to add min-content relaxation for cells. `overflow-wrap:
anywhere` does exactly that without re-introducing break-all
behaviour.
Repro: any transactional Hebrew/RTL order-summary email — each header
(`מוצר`, `כמות`, `מחיר`) collapses to one glyph per row. After the fix
they render on a single line.
Closes#341.