@bobfrankston/rmfmail 1.2.115 → 1.2.117
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.
- package/TODO.md +1217 -1217
- package/bin/mailx.js +41 -0
- package/bin/mailx.js.map +1 -1
- package/bin/mailx.ts +34 -0
- package/bin/popout-server.js +98 -0
- package/bin/popout-server.js.map +1 -1
- package/bin/popout-server.ts +97 -0
- package/client/app.bundle.js +19 -0
- package/client/app.bundle.js.map +2 -2
- package/client/compose/compose.bundle.js +118 -8
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/compose/compose.html +1 -0
- package/client/compose/compose.js +130 -16
- package/client/compose/compose.js.map +1 -1
- package/client/compose/compose.ts +122 -17
- package/client/lib/api-client.js +21 -0
- package/client/lib/api-client.js.map +1 -1
- package/client/lib/api-client.ts +22 -0
- package/client/lib/mailxapi.js +31 -4
- package/client/lib/popout-bridge.js +55 -0
- package/client/lib/popout-bridge.js.map +1 -0
- package/client/lib/popout-bridge.ts +48 -0
- package/package.json +1 -1
- package/packages/mailx-service/index.d.ts +36 -0
- package/packages/mailx-service/index.d.ts.map +1 -1
- package/packages/mailx-service/index.js +46 -0
- package/packages/mailx-service/index.js.map +1 -1
- package/packages/mailx-service/index.ts +56 -0
- package/packages/mailx-service/jsonrpc.js +6 -0
- package/packages/mailx-service/jsonrpc.js.map +1 -1
- package/packages/mailx-service/jsonrpc.ts +6 -0
|
@@ -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 {
|
|
@@ -4124,6 +4148,17 @@ function getFromAccountId() {
|
|
|
4124
4148
|
function getFromAddress() {
|
|
4125
4149
|
return fromInput.value.trim();
|
|
4126
4150
|
}
|
|
4151
|
+
function smartTab(current) {
|
|
4152
|
+
const fields = [toInput, ccInput, bccInput, subjectInput];
|
|
4153
|
+
const currentIdx = fields.indexOf(current);
|
|
4154
|
+
for (let i = currentIdx + 1; i < fields.length; i++) {
|
|
4155
|
+
if (!fields[i].value.trim() && fields[i].offsetParent !== null) {
|
|
4156
|
+
fields[i].focus();
|
|
4157
|
+
return;
|
|
4158
|
+
}
|
|
4159
|
+
}
|
|
4160
|
+
editor.focus();
|
|
4161
|
+
}
|
|
4127
4162
|
function showAutocompleteContextMenu(e, row) {
|
|
4128
4163
|
showContextMenu(e.clientX, e.clientY, [
|
|
4129
4164
|
{
|
|
@@ -4370,6 +4405,14 @@ function setupAutocomplete(input) {
|
|
|
4370
4405
|
setupAutocomplete(toInput);
|
|
4371
4406
|
setupAutocomplete(ccInput);
|
|
4372
4407
|
setupAutocomplete(bccInput);
|
|
4408
|
+
for (const field of [toInput, ccInput, bccInput, subjectInput]) {
|
|
4409
|
+
field.addEventListener("keydown", (e) => {
|
|
4410
|
+
const ke = e;
|
|
4411
|
+
if (ke.key !== "Tab" || ke.shiftKey || ke.ctrlKey || ke.altKey || ke.defaultPrevented) return;
|
|
4412
|
+
ke.preventDefault();
|
|
4413
|
+
smartTab(field);
|
|
4414
|
+
});
|
|
4415
|
+
}
|
|
4373
4416
|
function splitRecipients(s) {
|
|
4374
4417
|
const raw = [];
|
|
4375
4418
|
let cur = "", inQuote = false;
|
|
@@ -4478,17 +4521,26 @@ function expandGroups(raw) {
|
|
|
4478
4521
|
}
|
|
4479
4522
|
function applyInit(init) {
|
|
4480
4523
|
populateFromOptions(init.accounts, init.accountId);
|
|
4481
|
-
if (init.
|
|
4524
|
+
if (init.fromRaw) {
|
|
4525
|
+
fromInput.value = init.fromRaw;
|
|
4526
|
+
} else if (init.fromAddress) {
|
|
4482
4527
|
const account = init.accounts.find((a) => a.id === init.accountId);
|
|
4483
4528
|
const displayName = account?.name || "";
|
|
4484
4529
|
fromInput.value = displayName ? `${displayName} <${init.fromAddress}>` : init.fromAddress;
|
|
4485
4530
|
}
|
|
4486
4531
|
toInput.value = formatAddrs(init.to);
|
|
4487
4532
|
ccInput.value = formatAddrs(init.cc);
|
|
4533
|
+
bccInput.value = formatAddrs(init.bcc || []);
|
|
4488
4534
|
subjectInput.value = init.subject;
|
|
4489
4535
|
autoGrowAddrInput(toInput);
|
|
4490
4536
|
autoGrowAddrInput(ccInput);
|
|
4491
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
|
+
}
|
|
4492
4544
|
if (ccInput.value.trim()) {
|
|
4493
4545
|
const ccRowEl = document.getElementById("compose-cc-row");
|
|
4494
4546
|
const ccBtn = document.getElementById("btn-toggle-cc");
|
|
@@ -4728,19 +4780,33 @@ function waitForParentInit(maxMs) {
|
|
|
4728
4780
|
}
|
|
4729
4781
|
(async () => {
|
|
4730
4782
|
_ctick("init IIFE start");
|
|
4731
|
-
let parentInit =
|
|
4732
|
-
if (
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
|
|
4736
|
-
|
|
4783
|
+
let parentInit = null;
|
|
4784
|
+
if (popoutInitId) {
|
|
4785
|
+
try {
|
|
4786
|
+
parentInit = (await consumePopoutComposeInit(popoutInitId))?.init || null;
|
|
4787
|
+
} catch (e) {
|
|
4788
|
+
console.error("Failed to fetch popout compose init:", e);
|
|
4789
|
+
}
|
|
4790
|
+
_ctick(`popout init ${parentInit ? "received" : "MISSING"}`);
|
|
4791
|
+
try {
|
|
4792
|
+
document.title = parentInit?.subject ? `Compose: ${parentInit.subject}` : "Compose";
|
|
4793
|
+
} catch {
|
|
4794
|
+
}
|
|
4795
|
+
} else {
|
|
4796
|
+
parentInit = pullInitFromParent();
|
|
4797
|
+
if (!parentInit && !sessionStorage.getItem("composeInit") && !_postedInit) {
|
|
4798
|
+
_ctick("waiting for parent init");
|
|
4799
|
+
await waitForParentInit(1500);
|
|
4800
|
+
_ctick(`parent init received (msgEvents=${_msgEventCount})`);
|
|
4801
|
+
if (!_postedInit) parentInit = pullInitFromParent();
|
|
4802
|
+
}
|
|
4737
4803
|
}
|
|
4738
4804
|
const stored = sessionStorage.getItem("composeInit");
|
|
4739
4805
|
const initRaw = parentInit || _postedInit || (stored ? JSON.parse(stored) : null);
|
|
4740
4806
|
if (initRaw) {
|
|
4741
4807
|
sessionStorage.removeItem("composeInit");
|
|
4742
4808
|
const init = initRaw;
|
|
4743
|
-
const src = parentInit ? "parent-stash" : _postedInit ? "postMessage" : "sessionStorage";
|
|
4809
|
+
const src = parentInit ? popoutInitId ? "popout" : "parent-stash" : _postedInit ? "postMessage" : "sessionStorage";
|
|
4744
4810
|
_ctick(`init parsed (mode=${init.mode}, bodyHtml=${init.bodyHtml?.length || 0} bytes, src=${src})`);
|
|
4745
4811
|
if (init.accounts && init.accounts.length > 0) {
|
|
4746
4812
|
applyInit(init);
|
|
@@ -5025,6 +5091,50 @@ document.getElementById("btn-discard")?.addEventListener("click", async () => {
|
|
|
5025
5091
|
}
|
|
5026
5092
|
closeCompose();
|
|
5027
5093
|
});
|
|
5094
|
+
var composePopoutBtn = document.getElementById("btn-compose-popout");
|
|
5095
|
+
if (composePopoutBtn && popoutInitId) composePopoutBtn.style.display = "none";
|
|
5096
|
+
composePopoutBtn?.addEventListener("click", async () => {
|
|
5097
|
+
if (!draftId) draftId = `mailx-draft-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
5098
|
+
const init = {
|
|
5099
|
+
// "draft" mode so applyInit does NOT re-append the signature — the
|
|
5100
|
+
// body already carries whatever the user has (sig included).
|
|
5101
|
+
mode: "draft",
|
|
5102
|
+
accountId: getFromAccountId(),
|
|
5103
|
+
to: parseAddrs(toInput.value),
|
|
5104
|
+
cc: parseAddrs(ccInput.value),
|
|
5105
|
+
bcc: parseAddrs(bccInput.value),
|
|
5106
|
+
subject: subjectInput.value,
|
|
5107
|
+
bodyHtml: editor.getHtml(),
|
|
5108
|
+
inReplyTo: replyInReplyTo,
|
|
5109
|
+
references: replyReferences,
|
|
5110
|
+
accounts: knownAccounts,
|
|
5111
|
+
fromRaw: getFromAddress(),
|
|
5112
|
+
attachments: attachments.map((a) => ({ filename: a.filename, mimeType: a.mimeType, dataBase64: a.dataBase64 })),
|
|
5113
|
+
draftUid: draftUid ?? void 0,
|
|
5114
|
+
draftId: draftId ?? void 0
|
|
5115
|
+
};
|
|
5116
|
+
composePopoutBtn.disabled = true;
|
|
5117
|
+
try {
|
|
5118
|
+
const r = await popoutCompose(init);
|
|
5119
|
+
if (r?.ok) {
|
|
5120
|
+
if (draftDebounceTimer) {
|
|
5121
|
+
clearTimeout(draftDebounceTimer);
|
|
5122
|
+
draftDebounceTimer = null;
|
|
5123
|
+
}
|
|
5124
|
+
if (draftTimer) {
|
|
5125
|
+
clearInterval(draftTimer);
|
|
5126
|
+
draftTimer = null;
|
|
5127
|
+
}
|
|
5128
|
+
closeCompose();
|
|
5129
|
+
} else {
|
|
5130
|
+
showDraftStatus(`Popout failed: ${r?.reason || "unknown"}`, true);
|
|
5131
|
+
composePopoutBtn.disabled = false;
|
|
5132
|
+
}
|
|
5133
|
+
} catch (e) {
|
|
5134
|
+
showDraftStatus(`Popout failed: ${e?.message || e}`, true);
|
|
5135
|
+
composePopoutBtn.disabled = false;
|
|
5136
|
+
}
|
|
5137
|
+
});
|
|
5028
5138
|
var ccRow = document.getElementById("compose-cc-row");
|
|
5029
5139
|
var bccRow = document.getElementById("compose-bcc-row");
|
|
5030
5140
|
var toggleCcBtn = document.getElementById("btn-toggle-cc");
|