@bobfrankston/rmfmail 1.2.116 → 1.2.118

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 (37) hide show
  1. package/TODO.md +1 -1
  2. package/bin/mailx.js +41 -0
  3. package/bin/mailx.js.map +1 -1
  4. package/bin/mailx.ts +34 -0
  5. package/bin/popout-server.js +98 -0
  6. package/bin/popout-server.js.map +1 -1
  7. package/bin/popout-server.ts +97 -0
  8. package/client/app.bundle.js +20 -0
  9. package/client/app.bundle.js.map +2 -2
  10. package/client/app.js +1 -0
  11. package/client/app.js.map +1 -1
  12. package/client/app.ts +1 -0
  13. package/client/compose/compose.bundle.js +100 -8
  14. package/client/compose/compose.bundle.js.map +2 -2
  15. package/client/compose/compose.html +1 -0
  16. package/client/compose/compose.js +115 -13
  17. package/client/compose/compose.js.map +1 -1
  18. package/client/compose/compose.ts +105 -12
  19. package/client/lib/api-client.js +21 -0
  20. package/client/lib/api-client.js.map +1 -1
  21. package/client/lib/api-client.ts +22 -0
  22. package/client/lib/mailxapi.js +31 -4
  23. package/client/lib/popout-bridge.js +55 -0
  24. package/client/lib/popout-bridge.js.map +1 -0
  25. package/client/lib/popout-bridge.ts +48 -0
  26. package/package.json +1 -1
  27. package/packages/mailx-service/index.d.ts +37 -1
  28. package/packages/mailx-service/index.d.ts.map +1 -1
  29. package/packages/mailx-service/index.js +50 -2
  30. package/packages/mailx-service/index.js.map +1 -1
  31. package/packages/mailx-service/index.ts +60 -2
  32. package/packages/mailx-service/jsonrpc.js +7 -1
  33. package/packages/mailx-service/jsonrpc.js.map +1 -1
  34. package/packages/mailx-service/jsonrpc.ts +7 -1
  35. package/packages/mailx-types/mailx-api.d.ts +1 -1
  36. package/packages/mailx-types/mailx-api.d.ts.map +1 -1
  37. package/packages/mailx-types/mailx-api.ts +3 -1
package/client/app.ts CHANGED
@@ -5616,6 +5616,7 @@ document.addEventListener("mailx-popout-message", (async (e: any) => {
5616
5616
  accountId,
5617
5617
  to: msg.to || [],
5618
5618
  cc: msg.cc || [],
5619
+ bcc: msg.bcc || [],
5619
5620
  subject: msg.subject || subject || "",
5620
5621
  bodyHtml: msg.bodyHtml || "",
5621
5622
  inReplyTo: msg.inReplyTo || "",
@@ -1024,10 +1024,12 @@ __export(api_client_exports, {
1024
1024
  autocomplete: () => autocomplete,
1025
1025
  cancelQueuedOutgoing: () => cancelQueuedOutgoing,
1026
1026
  cancelServerSearch: () => cancelServerSearch,
1027
+ closeComposePopout: () => closeComposePopout,
1027
1028
  closeWordEdit: () => closeWordEdit,
1028
1029
  connectEvents: () => connectEvents,
1029
1030
  connectWebSocket: () => connectWebSocket,
1030
1031
  consumePendingMailto: () => consumePendingMailto,
1032
+ consumePopoutComposeInit: () => consumePopoutComposeInit,
1031
1033
  copyMessages: () => copyMessages,
1032
1034
  createCalendarEvent: () => createCalendarEvent,
1033
1035
  createFolder: () => createFolder,
@@ -1082,6 +1084,7 @@ __export(api_client_exports, {
1082
1084
  openInTextEditor: () => openInTextEditor,
1083
1085
  openInWord: () => openInWord,
1084
1086
  openLocalPath: () => openLocalPath,
1087
+ popoutCompose: () => popoutCompose,
1085
1088
  popoutWindow: () => popoutWindow,
1086
1089
  readConfigHelp: () => readConfigHelp,
1087
1090
  readJsoncFile: () => readJsoncFile,
@@ -1625,6 +1628,22 @@ async function popoutWindow(accountId, uid, folderId, subject) {
1625
1628
  return { ok: false, reason: "no popoutWindow bridge" };
1626
1629
  return fn(accountId, uid, folderId, subject);
1627
1630
  }
1631
+ async function popoutCompose(init) {
1632
+ const fn = ipc().popoutCompose;
1633
+ if (!fn)
1634
+ return { ok: false, reason: "no popoutCompose bridge" };
1635
+ return fn(init);
1636
+ }
1637
+ async function consumePopoutComposeInit(id) {
1638
+ const fn = ipc().consumePopoutComposeInit;
1639
+ if (!fn)
1640
+ return { init: null };
1641
+ return fn(id);
1642
+ }
1643
+ function closeComposePopout(id) {
1644
+ const fn = ipc().closeComposePopout;
1645
+ return fn ? fn(id) : Promise.resolve({ ok: false });
1646
+ }
1628
1647
  async function getDeviceAccounts() {
1629
1648
  return ipc().getDeviceAccounts?.() ?? [];
1630
1649
  }
@@ -3725,8 +3744,13 @@ function _ctick(label) {
3725
3744
  }
3726
3745
  }
3727
3746
  _ctick("module body executing");
3747
+ var popoutInitId = new URLSearchParams(location.search).get("pi") || "";
3728
3748
  function closeCompose() {
3729
3749
  logClientEvent("compose-close");
3750
+ if (popoutInitId) {
3751
+ void closeComposePopout(popoutInitId).catch(() => {
3752
+ });
3753
+ }
3730
3754
  try {
3731
3755
  parent.postMessage({ type: "mailx-compose-close" }, "*");
3732
3756
  } catch {
@@ -4497,17 +4521,26 @@ function expandGroups(raw) {
4497
4521
  }
4498
4522
  function applyInit(init) {
4499
4523
  populateFromOptions(init.accounts, init.accountId);
4500
- if (init.fromAddress) {
4524
+ if (init.fromRaw) {
4525
+ fromInput.value = init.fromRaw;
4526
+ } else if (init.fromAddress) {
4501
4527
  const account = init.accounts.find((a) => a.id === init.accountId);
4502
4528
  const displayName = account?.name || "";
4503
4529
  fromInput.value = displayName ? `${displayName} <${init.fromAddress}>` : init.fromAddress;
4504
4530
  }
4505
4531
  toInput.value = formatAddrs(init.to);
4506
4532
  ccInput.value = formatAddrs(init.cc);
4533
+ bccInput.value = formatAddrs(init.bcc || []);
4507
4534
  subjectInput.value = init.subject;
4508
4535
  autoGrowAddrInput(toInput);
4509
4536
  autoGrowAddrInput(ccInput);
4510
4537
  autoGrowAddrInput(bccInput);
4538
+ if (bccInput.value.trim()) {
4539
+ const bccRowEl = document.getElementById("compose-bcc-row");
4540
+ const bccBtn = document.getElementById("btn-toggle-bcc");
4541
+ if (bccRowEl) bccRowEl.hidden = false;
4542
+ if (bccBtn) bccBtn.classList.add("active");
4543
+ }
4511
4544
  if (ccInput.value.trim()) {
4512
4545
  const ccRowEl = document.getElementById("compose-cc-row");
4513
4546
  const ccBtn = document.getElementById("btn-toggle-cc");
@@ -4660,6 +4693,7 @@ async function saveDraft2() {
4660
4693
  bodyText: editor.getText(),
4661
4694
  to: toInput.value,
4662
4695
  cc: ccInput.value,
4696
+ bcc: bccInput.value,
4663
4697
  previousDraftUid: draftUid,
4664
4698
  draftId
4665
4699
  });
@@ -4747,19 +4781,33 @@ function waitForParentInit(maxMs) {
4747
4781
  }
4748
4782
  (async () => {
4749
4783
  _ctick("init IIFE start");
4750
- let parentInit = pullInitFromParent();
4751
- if (!parentInit && !sessionStorage.getItem("composeInit") && !_postedInit) {
4752
- _ctick("waiting for parent init");
4753
- await waitForParentInit(1500);
4754
- _ctick(`parent init received (msgEvents=${_msgEventCount})`);
4755
- if (!_postedInit) parentInit = pullInitFromParent();
4784
+ let parentInit = null;
4785
+ if (popoutInitId) {
4786
+ try {
4787
+ parentInit = (await consumePopoutComposeInit(popoutInitId))?.init || null;
4788
+ } catch (e) {
4789
+ console.error("Failed to fetch popout compose init:", e);
4790
+ }
4791
+ _ctick(`popout init ${parentInit ? "received" : "MISSING"}`);
4792
+ try {
4793
+ document.title = parentInit?.subject ? `Compose: ${parentInit.subject}` : "Compose";
4794
+ } catch {
4795
+ }
4796
+ } else {
4797
+ parentInit = pullInitFromParent();
4798
+ if (!parentInit && !sessionStorage.getItem("composeInit") && !_postedInit) {
4799
+ _ctick("waiting for parent init");
4800
+ await waitForParentInit(1500);
4801
+ _ctick(`parent init received (msgEvents=${_msgEventCount})`);
4802
+ if (!_postedInit) parentInit = pullInitFromParent();
4803
+ }
4756
4804
  }
4757
4805
  const stored = sessionStorage.getItem("composeInit");
4758
4806
  const initRaw = parentInit || _postedInit || (stored ? JSON.parse(stored) : null);
4759
4807
  if (initRaw) {
4760
4808
  sessionStorage.removeItem("composeInit");
4761
4809
  const init = initRaw;
4762
- const src = parentInit ? "parent-stash" : _postedInit ? "postMessage" : "sessionStorage";
4810
+ const src = parentInit ? popoutInitId ? "popout" : "parent-stash" : _postedInit ? "postMessage" : "sessionStorage";
4763
4811
  _ctick(`init parsed (mode=${init.mode}, bodyHtml=${init.bodyHtml?.length || 0} bytes, src=${src})`);
4764
4812
  if (init.accounts && init.accounts.length > 0) {
4765
4813
  applyInit(init);
@@ -5044,6 +5092,50 @@ document.getElementById("btn-discard")?.addEventListener("click", async () => {
5044
5092
  }
5045
5093
  closeCompose();
5046
5094
  });
5095
+ var composePopoutBtn = document.getElementById("btn-compose-popout");
5096
+ if (composePopoutBtn && popoutInitId) composePopoutBtn.style.display = "none";
5097
+ composePopoutBtn?.addEventListener("click", async () => {
5098
+ if (!draftId) draftId = `mailx-draft-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5099
+ const init = {
5100
+ // "draft" mode so applyInit does NOT re-append the signature — the
5101
+ // body already carries whatever the user has (sig included).
5102
+ mode: "draft",
5103
+ accountId: getFromAccountId(),
5104
+ to: parseAddrs(toInput.value),
5105
+ cc: parseAddrs(ccInput.value),
5106
+ bcc: parseAddrs(bccInput.value),
5107
+ subject: subjectInput.value,
5108
+ bodyHtml: editor.getHtml(),
5109
+ inReplyTo: replyInReplyTo,
5110
+ references: replyReferences,
5111
+ accounts: knownAccounts,
5112
+ fromRaw: getFromAddress(),
5113
+ attachments: attachments.map((a) => ({ filename: a.filename, mimeType: a.mimeType, dataBase64: a.dataBase64 })),
5114
+ draftUid: draftUid ?? void 0,
5115
+ draftId: draftId ?? void 0
5116
+ };
5117
+ composePopoutBtn.disabled = true;
5118
+ try {
5119
+ const r = await popoutCompose(init);
5120
+ if (r?.ok) {
5121
+ if (draftDebounceTimer) {
5122
+ clearTimeout(draftDebounceTimer);
5123
+ draftDebounceTimer = null;
5124
+ }
5125
+ if (draftTimer) {
5126
+ clearInterval(draftTimer);
5127
+ draftTimer = null;
5128
+ }
5129
+ closeCompose();
5130
+ } else {
5131
+ showDraftStatus(`Popout failed: ${r?.reason || "unknown"}`, true);
5132
+ composePopoutBtn.disabled = false;
5133
+ }
5134
+ } catch (e) {
5135
+ showDraftStatus(`Popout failed: ${e?.message || e}`, true);
5136
+ composePopoutBtn.disabled = false;
5137
+ }
5138
+ });
5047
5139
  var ccRow = document.getElementById("compose-cc-row");
5048
5140
  var bccRow = document.getElementById("compose-bcc-row");
5049
5141
  var toggleCcBtn = document.getElementById("btn-toggle-cc");