@bobfrankston/rmfmail 1.2.172 → 1.2.175

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 (55) hide show
  1. package/TODO.md +4 -3
  2. package/bin/build-rmfshare-exe.js +79 -0
  3. package/bin/mailx.js +52 -1
  4. package/bin/mailx.js.map +1 -1
  5. package/bin/mailx.ts +51 -1
  6. package/bin/rmfshare-src/Program.cs +225 -0
  7. package/bin/rmfshare-src/rmfshare.csproj +36 -0
  8. package/bin/rmfshare.exe +0 -0
  9. package/bin/share-target.js +314 -0
  10. package/bin/share-target.js.map +1 -0
  11. package/bin/share-target.ts +331 -0
  12. package/client/app.bundle.js +120 -0
  13. package/client/app.bundle.js.map +3 -3
  14. package/client/app.js +69 -0
  15. package/client/app.js.map +1 -1
  16. package/client/app.ts +72 -0
  17. package/client/components/message-viewer.js +60 -0
  18. package/client/components/message-viewer.js.map +1 -1
  19. package/client/components/message-viewer.ts +60 -0
  20. package/client/compose/compose.bundle.js +11 -0
  21. package/client/compose/compose.bundle.js.map +2 -2
  22. package/client/lib/api-client.js +16 -0
  23. package/client/lib/api-client.js.map +1 -1
  24. package/client/lib/api-client.ts +21 -0
  25. package/client/lib/mailxapi.js +6 -0
  26. package/client/package.json +1 -1
  27. package/package.json +6 -6
  28. package/packages/mailx-imap/index.d.ts.map +1 -1
  29. package/packages/mailx-imap/index.js +22 -0
  30. package/packages/mailx-imap/index.js.map +1 -1
  31. package/packages/mailx-imap/index.ts +22 -0
  32. package/packages/mailx-imap/package-lock.json +2 -2
  33. package/packages/mailx-imap/package.json +1 -1
  34. package/packages/mailx-service/index.d.ts +45 -0
  35. package/packages/mailx-service/index.d.ts.map +1 -1
  36. package/packages/mailx-service/index.js +288 -0
  37. package/packages/mailx-service/index.js.map +1 -1
  38. package/packages/mailx-service/index.ts +274 -0
  39. package/packages/mailx-service/jsonrpc.js +4 -0
  40. package/packages/mailx-service/jsonrpc.js.map +1 -1
  41. package/packages/mailx-service/jsonrpc.ts +4 -0
  42. package/packages/mailx-service/package.json +1 -1
  43. package/packages/mailx-settings/package.json +1 -1
  44. package/packages/mailx-store/db.d.ts +3 -0
  45. package/packages/mailx-store/db.d.ts.map +1 -1
  46. package/packages/mailx-store/db.js +5 -0
  47. package/packages/mailx-store/db.js.map +1 -1
  48. package/packages/mailx-store/db.ts +8 -0
  49. package/packages/mailx-store/package.json +1 -1
  50. package/packages/mailx-store-web/package.json +1 -1
  51. package/packages/mailx-types/mailx-api.d.ts +11 -0
  52. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  53. package/packages/mailx-types/mailx-api.ts +7 -0
  54. package/packages/mailx-types/package.json +1 -1
  55. /package/packages/mailx-imap/{node_modules.npmglobalize-stash-74140 → node_modules.npmglobalize-stash-33656}/.package-lock.json +0 -0
@@ -453,6 +453,53 @@ subscribeStore("*", (ev: any) => {
453
453
  * preview snippet paint *immediately*, before the body fetch returns —
454
454
  * that's the "no Fetching… empty pane" guarantee. On retry, we reuse
455
455
  * the most recently provided envelope. */
456
+ /** Confirm-and-delete for received-message attachments. The service does the
457
+ * local strip synchronously (verified re-parse before any write) and queues
458
+ * the server-side replace; on success the viewer re-renders from the
459
+ * now-stripped local copy. Failures leave the message untouched and say so. */
460
+ function confirmDeleteAttachments(msg: any, accountId: string, uid: number, ids: number[] | "all", question: string): void {
461
+ const backdrop = document.createElement("div");
462
+ backdrop.className = "mailx-modal-backdrop";
463
+ backdrop.style.cssText = "position:fixed;inset:0;z-index:2100;background:rgba(0,0,0,0.4);display:flex;align-items:center;justify-content:center;";
464
+ const panel = document.createElement("div");
465
+ panel.style.cssText = "background:var(--color-bg,#fff);color:var(--color-text,#000);border-radius:8px;box-shadow:0 8px 32px rgba(0,0,0,0.3);width:min(440px,90vw);padding:16px;display:flex;flex-direction:column;gap:12px;";
466
+ const body = document.createElement("div");
467
+ body.style.cssText = "line-height:1.5;";
468
+ body.textContent = `${question} The attachment is removed from the local copy and from the server copy. The message text is kept. This cannot be undone.`;
469
+ const status = document.createElement("div");
470
+ status.style.cssText = "min-height:1.2em;font-size:0.9em;color:var(--color-text-muted);";
471
+ const row = document.createElement("div");
472
+ row.style.cssText = "display:flex;gap:8px;justify-content:flex-end;";
473
+ const cancel = document.createElement("button");
474
+ cancel.textContent = "Cancel";
475
+ cancel.style.cssText = "padding:6px 14px;";
476
+ cancel.addEventListener("click", () => backdrop.remove());
477
+ const del = document.createElement("button");
478
+ del.textContent = "Delete";
479
+ del.style.cssText = "padding:6px 14px;font-weight:600;background:#c0392b;color:#fff;border:none;border-radius:4px;cursor:pointer;";
480
+ del.addEventListener("click", async () => {
481
+ del.disabled = true;
482
+ cancel.disabled = true;
483
+ status.textContent = "Removing…";
484
+ try {
485
+ const { deleteAttachments } = await import("../lib/api-client.js");
486
+ const r = await deleteAttachments(accountId, uid, msg.folderId, ids);
487
+ backdrop.remove();
488
+ // Re-render from the stripped local copy (chips, paperclip, size).
489
+ void showMessage(accountId, uid, msg.folderId);
490
+ void r;
491
+ } catch (e: any) {
492
+ status.textContent = e?.message || "Delete failed — message unchanged.";
493
+ del.disabled = false;
494
+ cancel.disabled = false;
495
+ }
496
+ });
497
+ row.append(cancel, del);
498
+ panel.append(body, status, row);
499
+ backdrop.append(panel);
500
+ document.body.append(backdrop);
501
+ }
502
+
456
503
  export async function showMessage(accountId: string, uid: number, folderId?: number, specialUse?: string, isRetry = false, envelope?: ListMessage): Promise<void> {
457
504
  const gen = ++showMessageGeneration;
458
505
  if (!isRetry) retryCount = 0;
@@ -1491,6 +1538,19 @@ export async function showMessage(accountId: string, uid: number, folderId?: num
1491
1538
  if (msg.attachments.length > 1) {
1492
1539
  items.push({ label: `Save all (${msg.attachments.length})…`, action: () => { void saveAllAttachments(); } });
1493
1540
  }
1541
+ // Delete = real message surgery (local strip + server
1542
+ // replace via the sync queue) — confirmed, not instant.
1543
+ // Desktop-only today; Android's bridge lacks the method.
1544
+ if ((window as any).mailxapi?.platform !== "android") {
1545
+ items.push({ label: `Delete "${att.filename}"…`, separator: true, action: () => {
1546
+ confirmDeleteAttachments(msg, accountId, uid, [att.id], `Delete "${att.filename}" from this message?`);
1547
+ } });
1548
+ if (msg.attachments.length > 1) {
1549
+ items.push({ label: `Delete all (${msg.attachments.length})…`, action: () => {
1550
+ confirmDeleteAttachments(msg, accountId, uid, "all", `Delete all ${msg.attachments.length} attachments from this message?`);
1551
+ } });
1552
+ }
1553
+ }
1494
1554
  showContextMenu(e.clientX, e.clientY, items);
1495
1555
  });
1496
1556
  attEl.appendChild(chip);
@@ -1029,12 +1029,14 @@ __export(api_client_exports, {
1029
1029
  connectEvents: () => connectEvents,
1030
1030
  connectWebSocket: () => connectWebSocket,
1031
1031
  consumePendingMailto: () => consumePendingMailto,
1032
+ consumePendingShare: () => consumePendingShare,
1032
1033
  consumePopoutComposeInit: () => consumePopoutComposeInit,
1033
1034
  copyMessages: () => copyMessages,
1034
1035
  createCalendarEvent: () => createCalendarEvent,
1035
1036
  createFolder: () => createFolder,
1036
1037
  createTask: () => createTask,
1037
1038
  debugEvalResult: () => debugEvalResult,
1039
+ deleteAttachments: () => deleteAttachments,
1038
1040
  deleteCalendarEvent: () => deleteCalendarEvent,
1039
1041
  deleteContact: () => deleteContact,
1040
1042
  deleteDraft: () => deleteDraft,
@@ -1614,6 +1616,9 @@ function showReminderPopup(opts) {
1614
1616
  function consumePendingMailto() {
1615
1617
  return ipc().consumePendingMailto?.() ?? Promise.resolve(null);
1616
1618
  }
1619
+ function consumePendingShare() {
1620
+ return ipc().consumePendingShare?.() ?? Promise.resolve(null);
1621
+ }
1617
1622
  function aiTransform(req) {
1618
1623
  return ipc().aiTransform?.(req) ?? Promise.resolve({ text: "", reason: "AI not available in this host" });
1619
1624
  }
@@ -1630,6 +1635,12 @@ async function openAttachment(accountId, uid, attachmentId, folderId, filename)
1630
1635
  async function getMessageSource(accountId, uid, folderId) {
1631
1636
  return ipc().getMessageSource(accountId, uid, folderId);
1632
1637
  }
1638
+ async function deleteAttachments(accountId, uid, folderId, ids) {
1639
+ const fn = ipc().deleteAttachments;
1640
+ if (!fn)
1641
+ throw new Error("Attachment delete not available in this host");
1642
+ return fn(accountId, uid, folderId, ids);
1643
+ }
1633
1644
  async function grammarLint(blocks) {
1634
1645
  const fn = ipc().grammarLint;
1635
1646
  if (!fn)