@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.
- package/TODO.md +4 -3
- package/bin/build-rmfshare-exe.js +79 -0
- package/bin/mailx.js +52 -1
- package/bin/mailx.js.map +1 -1
- package/bin/mailx.ts +51 -1
- package/bin/rmfshare-src/Program.cs +225 -0
- package/bin/rmfshare-src/rmfshare.csproj +36 -0
- package/bin/rmfshare.exe +0 -0
- package/bin/share-target.js +314 -0
- package/bin/share-target.js.map +1 -0
- package/bin/share-target.ts +331 -0
- package/client/app.bundle.js +120 -0
- package/client/app.bundle.js.map +3 -3
- package/client/app.js +69 -0
- package/client/app.js.map +1 -1
- package/client/app.ts +72 -0
- package/client/components/message-viewer.js +60 -0
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +60 -0
- package/client/compose/compose.bundle.js +11 -0
- package/client/compose/compose.bundle.js.map +2 -2
- package/client/lib/api-client.js +16 -0
- package/client/lib/api-client.js.map +1 -1
- package/client/lib/api-client.ts +21 -0
- package/client/lib/mailxapi.js +6 -0
- package/client/package.json +1 -1
- package/package.json +6 -6
- package/packages/mailx-imap/index.d.ts.map +1 -1
- package/packages/mailx-imap/index.js +22 -0
- package/packages/mailx-imap/index.js.map +1 -1
- package/packages/mailx-imap/index.ts +22 -0
- package/packages/mailx-imap/package-lock.json +2 -2
- package/packages/mailx-imap/package.json +1 -1
- package/packages/mailx-service/index.d.ts +45 -0
- package/packages/mailx-service/index.d.ts.map +1 -1
- package/packages/mailx-service/index.js +288 -0
- package/packages/mailx-service/index.js.map +1 -1
- package/packages/mailx-service/index.ts +274 -0
- package/packages/mailx-service/jsonrpc.js +4 -0
- package/packages/mailx-service/jsonrpc.js.map +1 -1
- package/packages/mailx-service/jsonrpc.ts +4 -0
- package/packages/mailx-service/package.json +1 -1
- package/packages/mailx-settings/package.json +1 -1
- package/packages/mailx-store/db.d.ts +3 -0
- package/packages/mailx-store/db.d.ts.map +1 -1
- package/packages/mailx-store/db.js +5 -0
- package/packages/mailx-store/db.js.map +1 -1
- package/packages/mailx-store/db.ts +8 -0
- package/packages/mailx-store/package.json +1 -1
- package/packages/mailx-store-web/package.json +1 -1
- package/packages/mailx-types/mailx-api.d.ts +11 -0
- package/packages/mailx-types/mailx-api.d.ts.map +1 -1
- package/packages/mailx-types/mailx-api.ts +7 -0
- package/packages/mailx-types/package.json +1 -1
- /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)
|