@bobfrankston/rmfmail 1.1.45 → 1.1.49

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/TODO.md +9 -0
  2. package/client/app.bundle.js +371 -80
  3. package/client/app.bundle.js.map +4 -4
  4. package/client/app.js +167 -32
  5. package/client/app.js.map +1 -1
  6. package/client/app.ts +153 -32
  7. package/client/components/calendar-sidebar.js +221 -88
  8. package/client/components/calendar-sidebar.js.map +1 -1
  9. package/client/components/calendar-sidebar.ts +224 -83
  10. package/client/compose/compose.bundle.js +14 -0
  11. package/client/compose/compose.bundle.js.map +2 -2
  12. package/client/compose/spellcheck.js +15 -0
  13. package/client/compose/spellcheck.js.map +1 -1
  14. package/client/compose/spellcheck.ts +14 -0
  15. package/client/help/search-help.js +75 -0
  16. package/client/help/search-help.js.map +1 -0
  17. package/client/help/search-help.ts +75 -0
  18. package/client/index.html +7 -7
  19. package/client/lib/api-client.js +5 -0
  20. package/client/lib/api-client.js.map +1 -1
  21. package/client/lib/api-client.ts +5 -0
  22. package/client/lib/mailxapi.js +1 -0
  23. package/client/styles/components.css +204 -6
  24. package/docs/search.md +5 -1
  25. package/package.json +1 -1
  26. package/packages/mailx-service/google-sync.d.ts +3 -0
  27. package/packages/mailx-service/google-sync.d.ts.map +1 -1
  28. package/packages/mailx-service/google-sync.js +1 -0
  29. package/packages/mailx-service/google-sync.js.map +1 -1
  30. package/packages/mailx-service/google-sync.ts +4 -0
  31. package/packages/mailx-service/index.d.ts +11 -0
  32. package/packages/mailx-service/index.d.ts.map +1 -1
  33. package/packages/mailx-service/index.js +99 -127
  34. package/packages/mailx-service/index.js.map +1 -1
  35. package/packages/mailx-service/index.ts +91 -122
  36. package/packages/mailx-service/jsonrpc.js +2 -0
  37. package/packages/mailx-service/jsonrpc.js.map +1 -1
  38. package/packages/mailx-service/jsonrpc.ts +2 -0
  39. package/packages/mailx-settings/index.d.ts.map +1 -1
  40. package/packages/mailx-settings/index.js +4 -1
  41. package/packages/mailx-settings/index.js.map +1 -1
  42. package/packages/mailx-settings/index.ts +4 -1
  43. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-28848 → node_modules.npmglobalize-stash-43988}/.package-lock.json +0 -0
package/TODO.md CHANGED
@@ -248,6 +248,15 @@ Small, self-contained items. Pick them up between higher-priority blocks without
248
248
  When exposing the calendar picker to users, ship a curated allowlist of vetted IDs rather than a free-form text input, OR show a warning when a user enters a non-`.official` / non-proper-noun ID. The naming asymmetry is on Google.
249
249
 
250
250
  Alternative source worth evaluating before generalizing: **Hebcal** (`https://www.hebcal.com/`) publishes a more rigorously curated Jewish-only feed (iCal + JSON API), and similar projects exist for other traditions. A `JsonHolidayProvider` interface that abstracts Google vs Hebcal vs ICS-by-URL behind a common shape would let users plug in whatever feed they trust.
251
+ - **Q145 — From header: RFC 2047 encoded-word not decoded when it spans the whole `name <addr>`.** Bob 2026-05-16, `screenshots/Screenshot 2026-05-16 141730.png`, sample `.eml` at `~/.rmfmail/mailxstore/bobma/1f/1fc0be6eb64d43e88503afaa8e424009.eml`. The From renders raw as `=?utf-8?q?PayPal_Nouveaut=C3=A9s_=3CParts=40samisec=2Ecom=3E?=@exch-smtp-out-01.wtr.livemail.co.uk`. The sender packed the entire display-name-and-address — including the `<`, `@`, `.`, `>` as `=3C =40 =2E =3E` — into ONE encoded-word, then concatenated `@domain` with no whitespace. Decoded it is `PayPal Nouveautés <Parts@samisec.com>`. mailx fails to decode it: the encoded-word isn't whitespace-delimited and sits where an addr-spec is expected, so the address parser (envelope `tokenizeParenList` / header decode) skips RFC 2047 decoding. Technically malformed mail, but Thunderbird decodes it. Fix: run encoded-word decoding on From/To/Cc display strings before address splitting, and tolerate a `=?...?=` token adjacent to non-whitespace. The broken string also propagates into the remote-content "Always: …" allowlist suggestions.
252
+ - **Q143 — Dynamic per-calendar checkboxes + per-source icons (Google-selected calendars).** ✅ **Implemented v1.1.47** (pending runtime verify). Shipped: `getCalendars()` service method, dynamic checkbox list, blue-dot/🇺🇸/✡️/🎂/monogram icons, per-event source icons, `hiddenCalendars` display-filter, `HOLIDAY_SOURCES` + `showHolidays`/`showJewishHolidays` removed. **Deferred**: multi-source badge (one event from two calendars still shows one icon — last-write-wins on `calendarId`; needs `iCalUID` + a source-set). Bob 2026-05-16, design settled. **Drop the hardcoded model**: today `HOLIDAY_SOURCES` hardcodes two Google calendar IDs and the sidebar has two fixed checkboxes (`showHolidays` / `showJewishHolidays`). Replace with a fully dynamic scheme — Bob curates *which* calendars exist by selecting them in Google Calendar; mailx enumerates the `selected` calendars (`listCalendars().filter(c => c.selected)`, already done in `refreshCalendarEvents`) and the sidebar **generates one checkbox per selected calendar**, each with an icon. Per-mailx visibility persists per calendar ID (replaces the two boolean settings). Calendar-URL input / non-Google calendar kinds are **deferred** (future TODO) — for now only Google-selected calendars.
253
+ - **Icons**: known types get a themed glyph — US holidays 🇺🇸, Jewish holidays ✡️, Birthdays 🎂 (detect via calendar ID pattern / `eventType`). Every other named calendar gets a **monogram badge**: the calendar name's first letter in a colored circle, color taken from the Google calendar's color (e.g. "Frankston Family" → "F" in a colored circle). The checkbox row and each event row from that calendar show the icon.
254
+ - **Birthdays**: shown automatically with 🎂 — no special checkbox (it's just one of the generated per-calendar checkboxes). Bob has already moved low-priority birthdays to a Contacts label so they don't flood; the two-tier "care about / FYI" split is his to manage upstream in Google for now. `eventType` (`default`/`birthday`/`fromGmail`/…) is NOT currently captured by `calendarEventToLocal` — add it.
255
+ - **Multi-source dedup**: the same event can arrive via two selected calendars. Show the row **once**, carry a *set* of source calendar IDs, render all their icons. Dedup key = `iCalUID` (stable across calendars), not `providerId`. Needs a source-list on the row replacing the single `calendarId`; the upsert passes in `refreshCalendarEvents` union into it instead of last-write-wins.
256
+ - Schema: `event_type` + source-list — no migration, calendar cache rebuilds from Google. Touches `GCalEvent` type, `calendarEventToLocal`, `refreshCalendarEvents`, a new service call exposing the enumerated calendar list (id, name, color, type) to the client, `db` calendar schema, `calendar-sidebar.ts` (dynamic checkbox list + icon rendering). Removes `HOLIDAY_SOURCES`, `showHolidays`, `showJewishHolidays`.
257
+ - **Q144 — Overdue tasks pinned to the top of the calendar list.** ✅ **Implemented v1.1.47** (pending runtime verify) — overdue block prepended in `renderEvents`, done-checkbox marks the task completed in Google (non-destructive). Bob 2026-05-16, design settled. NOT full Google-Calendar parity (which interleaves every due-dated task onto its due date). Instead: **only overdue tasks** — past due date AND `status: needsAction` — pin to the **top of the calendar event list** as a persistent "behind on these" block. Each row carries a done control (checkbox / ✓) which **marks the task completed in Google** (`updateTask` with `completedMs` → `status: "completed"`) — NOT a delete. Completing it drops it off the calendar top (no longer overdue) while the task survives in Google's Completed section. Tasks that are undated or due in the future stay only in the existing Task section — they don't appear on the calendar. Implementation: `renderEvents` in `calendar-sidebar.ts` prepends an overdue-task block built from `getTasks()` filtered to `dueMs < startOfToday && !completedMs`; reuse the existing `updateTask(uuid, {completedMs})` path the task-list checkbox already uses. Depends on the Q143 sidebar rework. Note: the existing task-list **× button is a hard `tasks.delete`** (destructive, no confirm) — distinct from the checkbox's mark-done; flagged for Bob, possible separate fix.
258
+ - **Q142 — Editor help should be HTML compiled into the app, not `editor.md`.** 2026-05-16: search help was converted from a deployed `docs/search.md` (shown raw, then rendered) to HTML compiled into the client (`client/help/search-help.ts`, dynamically imported, rendered as styled HTML in the panel). Bob's principle: feature help is application content and must display as HTML — the `docs/*.md` files are only a stand-in for proper settings UI and should hold *config-file* help only. `editor.md` is the remaining feature-help `.md` still in the deploy whitelist (`mailx-settings/index.ts` `USER_DOC_WHITELIST`). Convert it the same way: author `client/help/editor-help.ts` (or wherever the compose window's help is surfaced), point the editor's help affordance at it, drop `editor.md` from the whitelist, remove the file. Also: `docs/search.md` is now orphaned (no longer whitelisted, no longer read) — delete it; the `readConfigHelp` "search" mapping in `mailx-service` can go too.
259
+ - **Q141 — Shavuot shows in calendar sidebar with the ✡ Jewish-holidays checkbox OFF — DIAGNOSED, not a bug; design decision needed.** Bob 2026-05-16 (screenshot `screenshots/Screenshot 2026-05-16 105854.png`). Root cause confirmed from `rmfmail-2026-05-16.log`: `[calendar] enumerated 4 calendars, 3 selected` → `[calendar] pulled 10 events from "Jewish Holidays"`. There are **two independent Jewish-holiday paths** and only one is the checkbox: (1) mailx's ✡ checkbox → `showJewishHolidays` → pulls the `en.judaism#holiday` holiday-source feed; the log shows it is OFF (no "pulled N Jewish holiday events" line — only "5 US-official holiday events"). (2) `refreshCalendarEvents` enumerates *every* calendar the user marked `selected` in Google Calendar itself (`listCalendars().filter(c => c.selected)`) and pulls each as regular events. The user has Google's **"Jewish Holidays"** calendar subscribed + selected in their own Google account, so mailx faithfully pulls its 10 events — Shavuot among them — as ordinary calendar rows. The ✡ checkbox has no bearing on path (2). So mailx is behaving correctly: it shows a calendar the user selected in Google. Bob's own read ("artifact of Google Calendar") was right. **Resolutions** (pick one — needs Bob): (a) zero-code — deselect "Jewish Holidays" in Google Calendar's web UI and it stops appearing in mailx; (b) feature — add per-Google-calendar visibility toggles in the sidebar so a `selected` Google calendar can be hidden in mailx without changing Google (Q140-adjacent — the sidebar would list each enumerated calendar with a checkbox; gate the `calendarsToFetch` loop on it); (c) leave as-is. No code change made — this is a design call, not a defect.
251
260
  - **Q139 — General app-message channel from daemon to msger popups.** Bob 2026-05-11: "when an exit handler kills the popups by sending them a message — and can there be a general app message?" Today reminder popups are one-shot `showMessageBoxEx` (we have the handle for cross-platform reap). For graceful close-via-message AND other patterns (theme changes, in-flight content updates), spawn popups in `service: true` mode and use the bidirectional pipe — daemon calls `handle.send({type: "close"})` and the popup's JS listens for `_msgapiServiceEvent` events and reacts (`window.close()`, refresh content, etc.). Reuses the same wire mailx's main WebView already uses. Adapter shape: `showServicePopup(opts)` in `mailx-host` returns a `ServiceHandle` + a `result: Promise`; popup HTML's `<script>` registers `window._msgapiServiceEvent = (msg) => { if (msg.type === "close") window.close(); /* future: themeChanged, eventUpdated, … */ }`. Then `gracefulShutdown` in `bin/mailx.ts` iterates open popup handles and sends `{type:"close"}` instead of relying on the OS reaping. Pre-req: confirm msger's service mode supports the `rawHtml` content shape we use for reminders (may need a small msger PR).
252
261
  - **Q138 (original entry) — Quoted-reply image sizes lost.** Bob 2026-05-10: in the reply quote of a marketing email (Qatar Airways), the App Store / Google Play / AppGallery button images render larger than in the original. Cause: `sanitizeQuotedBody` in `client/app.ts` strips `width` / `height` attributes (along with `align`, `valign`, `bgcolor`, `cellpadding`, `cellspacing`, `border`) to flatten marketing-email layout tables. Stripping those attrs from `<img>` is collateral damage — table-only attributes there, but they also size images. Fix: in the regex, scope the attr strip to non-img tags, OR leave width/height alone everywhere (the layout flattening doesn't actually need them on tables either — `<table>→<div>` rewrites are doing the heavy lifting). ~10 line change. Low priority — visual nit, not data loss.
253
262
  - **Q136 — Server / provider capability matrix (forward backlog).** Catalog of server-specific features mailx could exploit. Detection is dynamic everywhere — IMAP via `CAPABILITY` + RFC 2971 `ID`, non-IMAP via provider-type at account setup. Each row below is its own future work item; this entry is the index.