@bobfrankston/rmfmail 1.0.502 → 1.0.503

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 (50) hide show
  1. package/client/app.js +82 -32
  2. package/client/app.js.map +1 -1
  3. package/client/app.ts +88 -32
  4. package/client/components/message-viewer.js +51 -21
  5. package/client/components/message-viewer.js.map +1 -1
  6. package/client/components/message-viewer.ts +38 -19
  7. package/client/compose/compose.css +14 -0
  8. package/client/compose/compose.html +4 -3
  9. package/client/compose/compose.js +288 -36
  10. package/client/compose/compose.js.map +1 -1
  11. package/client/compose/compose.ts +270 -40
  12. package/client/compose/editor-help.js +107 -0
  13. package/client/compose/editor-help.js.map +1 -0
  14. package/client/compose/editor-help.ts +106 -0
  15. package/client/compose/editor.js +43 -0
  16. package/client/compose/editor.js.map +1 -1
  17. package/client/compose/editor.ts +22 -0
  18. package/client/index.html +1 -4
  19. package/docs/editor.md +92 -0
  20. package/package.json +4 -2
  21. package/packages/mailx-service/html-to-docx.d.ts +1 -0
  22. package/packages/mailx-service/index.d.ts +10 -2
  23. package/packages/mailx-service/index.d.ts.map +1 -1
  24. package/packages/mailx-service/index.js +143 -21
  25. package/packages/mailx-service/index.js.map +1 -1
  26. package/packages/mailx-service/index.ts +114 -21
  27. package/packages/mailx-service/package.json +5 -3
  28. package/packages/mailx-settings/docs/accounts.md +41 -0
  29. package/packages/mailx-settings/docs/allowlist.md +27 -0
  30. package/packages/mailx-settings/docs/clients.md +24 -0
  31. package/packages/mailx-settings/docs/config.md +32 -0
  32. package/packages/mailx-settings/docs/contact-rules.md +40 -0
  33. package/packages/mailx-settings/docs/contacts.md +48 -0
  34. package/packages/mailx-settings/docs/editor.md +92 -0
  35. package/packages/mailx-settings/docs/preferences.md +43 -0
  36. package/packages/mailx-settings/index.d.ts +2 -2
  37. package/packages/mailx-settings/index.d.ts.map +1 -1
  38. package/packages/mailx-settings/index.js +7 -9
  39. package/packages/mailx-settings/index.js.map +1 -1
  40. package/packages/mailx-settings/index.ts +7 -9
  41. package/packages/mailx-types/groups.d.ts +38 -0
  42. package/packages/mailx-types/groups.d.ts.map +1 -0
  43. package/packages/mailx-types/groups.js +99 -0
  44. package/packages/mailx-types/groups.js.map +1 -0
  45. package/packages/mailx-types/groups.ts +112 -0
  46. package/packages/mailx-types/index.d.ts +2 -0
  47. package/packages/mailx-types/index.d.ts.map +1 -1
  48. package/packages/mailx-types/index.js +5 -0
  49. package/packages/mailx-types/index.js.map +1 -1
  50. package/packages/mailx-types/index.ts +9 -0
package/client/app.js CHANGED
@@ -1276,14 +1276,10 @@ document.getElementById("rail-view")?.addEventListener("click", (e) => {
1276
1276
  document.getElementById("rail-help")?.addEventListener("click", () => {
1277
1277
  document.getElementById("btn-about")?.click();
1278
1278
  });
1279
- document.getElementById("rail-theme")?.addEventListener("click", () => {
1280
- // Rail theme icon cycles system dark light system. Settings menu
1281
- // exposes the same three as radio buttons for direct selection.
1282
- const root = document.documentElement;
1283
- const cur = root.getAttribute("data-theme") || "system";
1284
- const next = cur === "system" ? "dark" : cur === "dark" ? "light" : "system";
1285
- applyTheme(next);
1286
- });
1279
+ // rail-theme button removed 2026-05-04 — theme picker lives in the Settings
1280
+ // dropdown (collapsed into a single "Theme: <current> ▸" item with a popout).
1281
+ // Removing the dedicated rail icon was the user's call; keeping the radios in
1282
+ // Settings is enough since the picker is rare-use.
1287
1283
  function applyTheme(theme) {
1288
1284
  document.documentElement.setAttribute("data-theme", theme);
1289
1285
  try {
@@ -1637,7 +1633,7 @@ window.addEventListener("message", (e) => {
1637
1633
  }
1638
1634
  const x = (iframeRect?.left || 0) + (e.data.x || 0);
1639
1635
  const y = (iframeRect?.top || 0) + (e.data.y || 0);
1640
- showPreviewBodyMenu(x, y, String(e.data.selectedText || ""), e.source);
1636
+ showPreviewBodyMenu(x, y, String(e.data.selectedText || ""), e.source, String(e.data.linkUrl || "") || undefined, String(e.data.linkText || "") || undefined);
1641
1637
  return;
1642
1638
  }
1643
1639
  if (e.data?.type === "linkContextMenu") {
@@ -2384,33 +2380,72 @@ function openShortcutsDialog() {
2384
2380
  backdrop.className = "mailx-modal-backdrop mailx-shortcuts-modal";
2385
2381
  const panel = document.createElement("div");
2386
2382
  panel.className = "mailx-modal";
2387
- panel.style.maxWidth = "560px";
2383
+ panel.style.maxWidth = "640px";
2384
+ const tabs = [
2385
+ {
2386
+ id: "app", label: "Application",
2387
+ rows: [
2388
+ ["Compose", "Ctrl+N"],
2389
+ ["Reply", "Ctrl+R"],
2390
+ ["Reply all", "Ctrl+Shift+R"],
2391
+ ["Forward", "Ctrl+F"],
2392
+ ["Sync", "F5"],
2393
+ ["Delete selected", "Del or Ctrl+D"],
2394
+ ["Undo last delete/move", "Ctrl+Z"],
2395
+ ["Toggle read/unread", "R"],
2396
+ ["Toggle flag (★)", "(⚑ button in viewer)"],
2397
+ ["Select all visible", "Ctrl+A"],
2398
+ ["Navigate list", "↑ ↓ Home End PgUp PgDn"],
2399
+ ["Scroll-to-focused row", "Z"],
2400
+ ["Switch pane", "F6 / Shift+F6"],
2401
+ ["Find / search", "(focus the search box)"],
2402
+ ["Show this help", "?"],
2403
+ ["Close dialog", "Esc"],
2404
+ ],
2405
+ },
2406
+ {
2407
+ id: "compose", label: "Compose",
2408
+ rows: [
2409
+ ["Send", "Ctrl+Enter"],
2410
+ ["Insert / edit link", "Ctrl+K"],
2411
+ ["Remove link", "Ctrl+Shift+K"],
2412
+ ["Bold / italic / underline", "Ctrl+B / Ctrl+I / Ctrl+U"],
2413
+ ["Strikethrough", "Ctrl+Shift+X"],
2414
+ ["Ordered list", "Ctrl+Shift+7"],
2415
+ ["Bulleted list", "Ctrl+Shift+8"],
2416
+ ["Indent / outdent", "Ctrl+] / Ctrl+["],
2417
+ ["Clear formatting", "Ctrl+\\"],
2418
+ ["Color text", "Ctrl+Shift+C"],
2419
+ ["New line in To/Cc/Bcc", "(Enter inserts a comma)"],
2420
+ ["Editor reference", "(? button on compose toolbar — shows Quill/tiptap differences)"],
2421
+ ],
2422
+ },
2423
+ {
2424
+ id: "viewer", label: "Viewer",
2425
+ rows: [
2426
+ ["Toggle preview fullscreen", "double-click on body"],
2427
+ ["Exit fullscreen", "Esc / ✕ button / double-click"],
2428
+ ["Zoom in / out / reset", "Ctrl+= / Ctrl+- / Ctrl+0"],
2429
+ ["Right-click in body", "Copy / Search / Translate / Zoom"],
2430
+ ["Right-click a link", "Open / Save / Copy URL / Copy text"],
2431
+ ],
2432
+ },
2433
+ ];
2388
2434
  panel.innerHTML = `
2389
2435
  <div class="mailx-modal-title">
2390
2436
  <span class="mailx-modal-title-text">Keyboard shortcuts</span>
2391
2437
  <button type="button" class="mailx-modal-close" id="sc-x" title="Close (Esc)" aria-label="Close">&times;</button>
2392
2438
  </div>
2439
+ <div class="mailx-shortcuts-tabs" role="tablist" style="display:flex;gap:0;border-bottom:1px solid var(--color-border, #ddd);margin:0 -16px 12px -16px;padding:0 16px;">
2440
+ ${tabs.map((t, i) => `<button type="button" role="tab" class="mailx-shortcuts-tab" data-tab="${t.id}" aria-selected="${i === 0}" style="background:none;border:0;padding:8px 14px;cursor:pointer;font:inherit;border-bottom:2px solid ${i === 0 ? "var(--color-accent, #3b82f6)" : "transparent"};color:${i === 0 ? "var(--color-text)" : "var(--color-text-muted, #888)"};">${t.label}</button>`).join("")}
2441
+ </div>
2393
2442
  <div class="mailx-about">
2394
- <dl class="mailx-about-dl">
2395
- <dt>Compose</dt><dd>Ctrl+N</dd>
2396
- <dt>Reply</dt><dd>Ctrl+R</dd>
2397
- <dt>Reply all</dt><dd>Ctrl+Shift+R</dd>
2398
- <dt>Forward</dt><dd>Ctrl+F</dd>
2399
- <dt>Send (in compose)</dt><dd>Ctrl+Enter</dd>
2400
- <dt>Sync</dt><dd>F5</dd>
2401
- <dt>Delete selected</dt><dd>Del or Ctrl+D</dd>
2402
- <dt>Undo last delete/move</dt><dd>Ctrl+Z</dd>
2403
- <dt>Toggle read/unread</dt><dd>R</dd>
2404
- <dt>Toggle flag</dt><dd>(Flag button in viewer)</dd>
2405
- <dt>Select all visible</dt><dd>Ctrl+A</dd>
2406
- <dt>Navigate list</dt><dd>↑ ↓ Home End PgUp PgDn</dd>
2407
- <dt>Scroll-to-focused row</dt><dd>Z</dd>
2408
- <dt>Switch pane</dt><dd>F6 / Shift+F6</dd>
2409
- <dt>Find / search</dt><dd>(focus the search box)</dd>
2410
- <dt>Close dialog</dt><dd>Esc</dd>
2411
- <dt>Show this help</dt><dd>?</dd>
2412
- </dl>
2413
- <div class="mailx-about-foot">On Android most shortcuts need a Bluetooth/USB keyboard. Touch equivalents: tap a row to view, tap the rail icons for navigation/settings/theme/help, long-press a row for the context menu.</div>
2443
+ ${tabs.map((t, i) => `<div class="mailx-shortcuts-pane" data-pane="${t.id}" ${i === 0 ? "" : "hidden"}>
2444
+ <dl class="mailx-about-dl">
2445
+ ${t.rows.map(([k, v]) => `<dt>${k}</dt><dd>${v}</dd>`).join("")}
2446
+ </dl>
2447
+ </div>`).join("")}
2448
+ <div class="mailx-about-foot">On Android most shortcuts need a Bluetooth/USB keyboard. Touch equivalents: tap a row to view, tap the rail icons for navigation, long-press for context menu, double-tap the message body for fullscreen.</div>
2414
2449
  </div>
2415
2450
  <div class="mailx-modal-buttons">
2416
2451
  <span class="mailx-modal-spacer"></span>
@@ -2418,6 +2453,21 @@ function openShortcutsDialog() {
2418
2453
  </div>`;
2419
2454
  backdrop.appendChild(panel);
2420
2455
  document.body.appendChild(backdrop);
2456
+ // Wire tab clicks
2457
+ panel.querySelectorAll(".mailx-shortcuts-tab").forEach(tab => {
2458
+ tab.addEventListener("click", () => {
2459
+ const which = tab.dataset.tab;
2460
+ panel.querySelectorAll(".mailx-shortcuts-tab").forEach(t => {
2461
+ const sel = t.dataset.tab === which;
2462
+ t.setAttribute("aria-selected", String(sel));
2463
+ t.style.borderBottom = `2px solid ${sel ? "var(--color-accent, #3b82f6)" : "transparent"}`;
2464
+ t.style.color = sel ? "var(--color-text)" : "var(--color-text-muted, #888)";
2465
+ });
2466
+ panel.querySelectorAll(".mailx-shortcuts-pane").forEach(p => {
2467
+ p.hidden = p.dataset.pane !== which;
2468
+ });
2469
+ });
2470
+ });
2421
2471
  const close = () => { backdrop.remove(); document.removeEventListener("keydown", onKey, true); };
2422
2472
  const onKey = (e) => {
2423
2473
  if (e.key === "Escape") {
@@ -2427,8 +2477,8 @@ function openShortcutsDialog() {
2427
2477
  }
2428
2478
  };
2429
2479
  document.addEventListener("keydown", onKey, true);
2430
- panel.querySelector('[data-action="close"]').addEventListener("click", close);
2431
- panel.querySelector("#sc-x").addEventListener("click", close);
2480
+ const closeBtn = panel.querySelector("#sc-x");
2481
+ closeBtn?.addEventListener("click", close);
2432
2482
  backdrop.addEventListener("mousedown", (e) => { if (e.target === backdrop)
2433
2483
  close(); });
2434
2484
  }