@bobfrankston/rmfmail 1.2.274 → 1.2.276
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/.commitmsg +26 -0
- package/client/android-bootstrap.bundle.js +169 -0
- package/client/android-bootstrap.bundle.js.map +2 -2
- package/client/app.bundle.js +123 -23
- package/client/app.bundle.js.map +4 -4
- package/client/app.js +16 -1
- package/client/app.js.map +1 -1
- package/client/app.ts +16 -1
- package/client/components/invite-card.js +107 -0
- package/client/components/invite-card.js.map +1 -0
- package/client/components/invite-card.ts +119 -0
- package/client/components/message-viewer.js +42 -17
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +42 -16
- package/client/package.json +1 -1
- package/client/styles/components.css +48 -0
- package/package.json +8 -8
- package/packages/mailx-imap/package-lock.json +2 -2
- package/packages/mailx-imap/package.json +2 -2
- package/packages/mailx-settings/package.json +1 -1
- package/packages/mailx-store/package.json +1 -1
- package/packages/mailx-store/store.d.ts +5 -0
- package/packages/mailx-store/store.d.ts.map +1 -1
- package/packages/mailx-store/store.js +21 -0
- package/packages/mailx-store/store.js.map +1 -1
- package/packages/mailx-store/store.ts +27 -0
- package/packages/mailx-types/index.d.ts +56 -0
- package/packages/mailx-types/index.d.ts.map +1 -1
- package/packages/mailx-types/index.js +187 -0
- package/packages/mailx-types/index.js.map +1 -1
- package/packages/mailx-types/index.ts +192 -0
- package/packages/mailx-types/package.json +1 -1
- /package/packages/mailx-imap/{node_modules.npmglobalize-stash-31304 → node_modules.npmglobalize-stash-59216}/.package-lock.json +0 -0
package/client/app.bundle.js
CHANGED
|
@@ -1467,6 +1467,11 @@ function formatSender(addr) {
|
|
|
1467
1467
|
return { text: address, claimed: null };
|
|
1468
1468
|
return { text: `${name} <${address}>`, claimed: displayNameClaimsOtherAddress(name, address) };
|
|
1469
1469
|
}
|
|
1470
|
+
function inviteHasGoogleRsvp(bodyHtml) {
|
|
1471
|
+
if (!bodyHtml)
|
|
1472
|
+
return false;
|
|
1473
|
+
return /calendar\.google\.com\/calendar\/event\?action=RESPOND/i.test(bodyHtml);
|
|
1474
|
+
}
|
|
1470
1475
|
var _SEEN, _FLAGGED, _DRAFT, seenOf, flaggedOf, draftOf, setSeen, setFlagged;
|
|
1471
1476
|
var init_mailx_types = __esm({
|
|
1472
1477
|
"packages/mailx-types/index.js"() {
|
|
@@ -1488,6 +1493,100 @@ var init_mailx_types = __esm({
|
|
|
1488
1493
|
}
|
|
1489
1494
|
});
|
|
1490
1495
|
|
|
1496
|
+
// client/components/invite-card.js
|
|
1497
|
+
function formatWhen(inv) {
|
|
1498
|
+
if (!inv.start)
|
|
1499
|
+
return "";
|
|
1500
|
+
if (inv.allDay) {
|
|
1501
|
+
try {
|
|
1502
|
+
const d = /* @__PURE__ */ new Date(inv.start + "T00:00:00");
|
|
1503
|
+
return d.toLocaleDateString(void 0, { weekday: "long", year: "numeric", month: "long", day: "numeric" }) + " (all day)";
|
|
1504
|
+
} catch {
|
|
1505
|
+
return inv.start + " (all day)";
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
const instant = (() => {
|
|
1509
|
+
if (/Z$/.test(inv.start))
|
|
1510
|
+
return new Date(inv.start);
|
|
1511
|
+
if (!inv.tzid)
|
|
1512
|
+
return new Date(inv.start);
|
|
1513
|
+
try {
|
|
1514
|
+
const guess = /* @__PURE__ */ new Date(inv.start + "Z");
|
|
1515
|
+
const asZone = new Date(guess.toLocaleString("en-US", { timeZone: inv.tzid }));
|
|
1516
|
+
const asUtc = new Date(guess.toLocaleString("en-US", { timeZone: "UTC" }));
|
|
1517
|
+
return new Date(guess.getTime() + (asUtc.getTime() - asZone.getTime()));
|
|
1518
|
+
} catch {
|
|
1519
|
+
return new Date(inv.start);
|
|
1520
|
+
}
|
|
1521
|
+
})();
|
|
1522
|
+
if (isNaN(instant.getTime()))
|
|
1523
|
+
return inv.start;
|
|
1524
|
+
const localZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
1525
|
+
const opts = {
|
|
1526
|
+
weekday: "short",
|
|
1527
|
+
month: "short",
|
|
1528
|
+
day: "numeric",
|
|
1529
|
+
hour: "numeric",
|
|
1530
|
+
minute: "2-digit"
|
|
1531
|
+
};
|
|
1532
|
+
let out = instant.toLocaleString(void 0, opts);
|
|
1533
|
+
if (inv.end && !/Z$/.test(inv.end)) {
|
|
1534
|
+
try {
|
|
1535
|
+
const endInstant = new Date(instant.getTime() + ((/* @__PURE__ */ new Date(inv.end + "Z")).getTime() - (/* @__PURE__ */ new Date(inv.start + "Z")).getTime()));
|
|
1536
|
+
out += " \u2013 " + endInstant.toLocaleString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
1537
|
+
} catch {
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1540
|
+
if (inv.tzid && inv.tzid !== localZone) {
|
|
1541
|
+
out += ` (sent as ${inv.start.slice(11, 16)} ${inv.tzid})`;
|
|
1542
|
+
}
|
|
1543
|
+
return out;
|
|
1544
|
+
}
|
|
1545
|
+
function buildInviteCard(inv, bodyHtml) {
|
|
1546
|
+
if (!inv || !inv.summary && !inv.start)
|
|
1547
|
+
return null;
|
|
1548
|
+
const card = document.createElement("div");
|
|
1549
|
+
card.className = "mv-invite";
|
|
1550
|
+
if (inv.method === "CANCEL")
|
|
1551
|
+
card.classList.add("mv-invite-cancelled");
|
|
1552
|
+
const when = formatWhen(inv);
|
|
1553
|
+
const isMeetLink = /^https?:/;
|
|
1554
|
+
const googleHandles = inv.fromGoogle && inviteHasGoogleRsvp(bodyHtml);
|
|
1555
|
+
const rows = [];
|
|
1556
|
+
if (when)
|
|
1557
|
+
rows.push(`<div class="mv-invite-when">${esc(when)}</div>`);
|
|
1558
|
+
if (inv.location) {
|
|
1559
|
+
rows.push(isMeetLink ? `<div class="mv-invite-row"><span class="mv-invite-label">Where</span><a href="${esc(inv.location)}" target="_blank" rel="noopener noreferrer">${esc(inv.location)}</a></div>` : `<div class="mv-invite-row"><span class="mv-invite-label">Where</span>${esc(inv.location)}</div>`);
|
|
1560
|
+
}
|
|
1561
|
+
if (inv.organizer.email) {
|
|
1562
|
+
rows.push(`<div class="mv-invite-row"><span class="mv-invite-label">Organizer</span>${esc(inv.organizer.name)}${inv.organizer.name !== inv.organizer.email ? " <" + esc(inv.organizer.email) + ">" : ""}</div>`);
|
|
1563
|
+
}
|
|
1564
|
+
if (inv.attendees.length) {
|
|
1565
|
+
const who = inv.attendees.map((a) => `${esc(a.name || a.email)} <span class="mv-invite-partstat">(${esc(PARTSTAT_LABEL[a.status] || a.status.toLowerCase())})</span>`).join(", ");
|
|
1566
|
+
rows.push(`<div class="mv-invite-row"><span class="mv-invite-label">Guests</span>${who}</div>`);
|
|
1567
|
+
}
|
|
1568
|
+
if (inv.rrule)
|
|
1569
|
+
rows.push(`<div class="mv-invite-row"><span class="mv-invite-label">Repeats</span><code>${esc(inv.rrule)}</code></div>`);
|
|
1570
|
+
const badge = inv.method === "CANCEL" ? "Cancelled" : inv.method === "REPLY" ? "Reply" : inv.status === "TENTATIVE" ? "Tentative" : "Invitation";
|
|
1571
|
+
card.innerHTML = `<div class="mv-invite-head"><span class="mv-invite-badge">${esc(badge)}</span><span class="mv-invite-summary">${esc(inv.summary || "(no title)")}</span></div>` + rows.join("") + (googleHandles ? `<div class="mv-invite-note">Respond with the Yes / No / Maybe buttons in the message below \u2014 they go straight to Google Calendar.</div>` : "");
|
|
1572
|
+
return card;
|
|
1573
|
+
}
|
|
1574
|
+
var PARTSTAT_LABEL, esc;
|
|
1575
|
+
var init_invite_card = __esm({
|
|
1576
|
+
"client/components/invite-card.js"() {
|
|
1577
|
+
"use strict";
|
|
1578
|
+
init_mailx_types();
|
|
1579
|
+
PARTSTAT_LABEL = {
|
|
1580
|
+
"ACCEPTED": "accepted",
|
|
1581
|
+
"DECLINED": "declined",
|
|
1582
|
+
"TENTATIVE": "maybe",
|
|
1583
|
+
"NEEDS-ACTION": "no reply yet",
|
|
1584
|
+
"DELEGATED": "delegated"
|
|
1585
|
+
};
|
|
1586
|
+
esc = (s) => (s || "").replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
1587
|
+
}
|
|
1588
|
+
});
|
|
1589
|
+
|
|
1491
1590
|
// client/components/address-book.js
|
|
1492
1591
|
var address_book_exports = {};
|
|
1493
1592
|
__export(address_book_exports, {
|
|
@@ -2361,19 +2460,6 @@ function installPreviewControls(iframe) {
|
|
|
2361
2460
|
}
|
|
2362
2461
|
if (e.ctrlKey && !e.altKey && !e.metaKey && (e.key === "a" || e.key === "A"))
|
|
2363
2462
|
return;
|
|
2364
|
-
const synth = new KeyboardEvent("keydown", {
|
|
2365
|
-
key: e.key,
|
|
2366
|
-
code: e.code,
|
|
2367
|
-
ctrlKey: e.ctrlKey,
|
|
2368
|
-
shiftKey: e.shiftKey,
|
|
2369
|
-
altKey: e.altKey,
|
|
2370
|
-
metaKey: e.metaKey,
|
|
2371
|
-
bubbles: true,
|
|
2372
|
-
cancelable: true
|
|
2373
|
-
});
|
|
2374
|
-
const allowDefault = document.dispatchEvent(synth);
|
|
2375
|
-
if (!allowDefault)
|
|
2376
|
-
e.preventDefault();
|
|
2377
2463
|
});
|
|
2378
2464
|
doc.addEventListener("wheel", (e) => {
|
|
2379
2465
|
if (!e.ctrlKey)
|
|
@@ -2410,6 +2496,7 @@ function clearViewer() {
|
|
|
2410
2496
|
headerEl.hidden = true;
|
|
2411
2497
|
if (attEl)
|
|
2412
2498
|
attEl.hidden = true;
|
|
2499
|
+
document.getElementById("mv-invite")?.remove();
|
|
2413
2500
|
setTimeout(() => {
|
|
2414
2501
|
try {
|
|
2415
2502
|
const stillPlaceholder = !!document.querySelector("#mv-body .mv-empty");
|
|
@@ -2669,6 +2756,16 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
|
|
|
2669
2756
|
fromEl.textContent = formatAddr(msg.from);
|
|
2670
2757
|
setRecipientLine(toEl, msg.to, msg.cc, msg.deliveredTo);
|
|
2671
2758
|
headerEl.querySelector(".mv-subject").textContent = msg.subject;
|
|
2759
|
+
document.getElementById("mv-invite")?.remove();
|
|
2760
|
+
try {
|
|
2761
|
+
const card = buildInviteCard(msg.invite, String(msg.bodyHtml || ""));
|
|
2762
|
+
if (card) {
|
|
2763
|
+
card.id = "mv-invite";
|
|
2764
|
+
headerEl.insertAdjacentElement("afterend", card);
|
|
2765
|
+
}
|
|
2766
|
+
} catch (e) {
|
|
2767
|
+
console.warn("[viewer] invite card failed:", e?.message || e);
|
|
2768
|
+
}
|
|
2672
2769
|
document.dispatchEvent(new CustomEvent("mailx-message-shown", { detail: { accountId } }));
|
|
2673
2770
|
for (const el of [fromEl, toEl]) {
|
|
2674
2771
|
el.addEventListener("contextmenu", (e) => {
|
|
@@ -3980,11 +4077,11 @@ function buildPrintableDoc(m) {
|
|
|
3980
4077
|
if (!m)
|
|
3981
4078
|
return null;
|
|
3982
4079
|
const fmt = (a) => a?.name ? `${a.name} <${a.address || ""}>` : a?.address || "";
|
|
3983
|
-
const
|
|
3984
|
-
const row = (label, value) => value ? `<div><strong>${label}:</strong> ${
|
|
4080
|
+
const esc2 = escapeHtmlLocal;
|
|
4081
|
+
const row = (label, value) => value ? `<div><strong>${label}:</strong> ${esc2(value)}</div>` : "";
|
|
3985
4082
|
const headerHtml = `<div style="font-family:system-ui,Segoe UI,sans-serif;font-size:11pt;border-bottom:1px solid #999;padding-bottom:8px;margin-bottom:14px;line-height:1.5;">` + row("From", fmt(m.from || {})) + row("To", (m.to || []).map(fmt).join(", ")) + (m.cc?.length ? row("Cc", m.cc.map(fmt).join(", ")) : "") + row("Subject", m.subject || "") + row("Date", m.date ? new Date(m.date).toLocaleString() : "") + `</div>`;
|
|
3986
|
-
const bodyHtml = m.bodyHtml ? m.bodyHtml : `<pre style="white-space:pre-wrap;word-break:break-word;font-family:system-ui,sans-serif;">${
|
|
3987
|
-
return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>${
|
|
4083
|
+
const bodyHtml = m.bodyHtml ? m.bodyHtml : `<pre style="white-space:pre-wrap;word-break:break-word;font-family:system-ui,sans-serif;">${esc2(m.bodyText || "")}</pre>`;
|
|
4084
|
+
return `<!DOCTYPE html><html><head><meta charset="utf-8"><title>${esc2(m.subject || "Message")}</title><style>@media print{body{margin:0;}}body{margin:16px;}img{max-width:100%;}</style></head><body>${headerHtml}${bodyHtml}</body></html>`;
|
|
3988
4085
|
}
|
|
3989
4086
|
function printCurrentMessage() {
|
|
3990
4087
|
if (!currentMessage)
|
|
@@ -4197,6 +4294,7 @@ var init_message_viewer = __esm({
|
|
|
4197
4294
|
"use strict";
|
|
4198
4295
|
init_api_client();
|
|
4199
4296
|
init_approved_senders();
|
|
4297
|
+
init_invite_card();
|
|
4200
4298
|
init_context_menu();
|
|
4201
4299
|
init_message_state();
|
|
4202
4300
|
init_message_list();
|
|
@@ -7386,7 +7484,7 @@ async function collectDueAlarms(now) {
|
|
|
7386
7484
|
}
|
|
7387
7485
|
return items;
|
|
7388
7486
|
}
|
|
7389
|
-
function
|
|
7487
|
+
function formatWhen2(ms) {
|
|
7390
7488
|
if (!ms)
|
|
7391
7489
|
return "";
|
|
7392
7490
|
const d = new Date(ms);
|
|
@@ -7509,7 +7607,7 @@ async function firePopupForItem(item) {
|
|
|
7509
7607
|
.actions button.action[data-btn="Delete"]:hover { background: #800; }
|
|
7510
7608
|
</style></head><body>
|
|
7511
7609
|
<div class="title"><span class="icon">${icon}</span>${escapeHtml7(item.title)}</div>
|
|
7512
|
-
<div class="when">${escapeHtml7(
|
|
7610
|
+
<div class="when">${escapeHtml7(formatWhen2(item.whenMs))}</div>
|
|
7513
7611
|
<div class="kind">${kindLabel}</div>
|
|
7514
7612
|
<div class="row">
|
|
7515
7613
|
<span class="row-label">Snooze:</span>
|
|
@@ -9261,6 +9359,7 @@ window.__btick && window.__btick("app.ts module body executing");
|
|
|
9261
9359
|
var baseTitle = APP_NAME;
|
|
9262
9360
|
var lastSeenCount = 0;
|
|
9263
9361
|
var badgeCount = 0;
|
|
9362
|
+
var lastOverlayCount = -1;
|
|
9264
9363
|
function updateBadge(count) {
|
|
9265
9364
|
badgeCount = count;
|
|
9266
9365
|
document.title = count > 0 ? `(${count}) ${baseTitle}` : baseTitle;
|
|
@@ -9297,7 +9396,8 @@ function updateBadge(count) {
|
|
|
9297
9396
|
link.href = dataUrl;
|
|
9298
9397
|
try {
|
|
9299
9398
|
const hostApi = window.mailxapi;
|
|
9300
|
-
if (hostApi?.setTaskbarOverlay) {
|
|
9399
|
+
if (hostApi?.setTaskbarOverlay && count !== lastOverlayCount) {
|
|
9400
|
+
lastOverlayCount = count;
|
|
9301
9401
|
if (count > 0) {
|
|
9302
9402
|
const bc = document.createElement("canvas");
|
|
9303
9403
|
bc.width = 32;
|
|
@@ -13006,11 +13106,11 @@ function offsetToLineCol(src, pos) {
|
|
|
13006
13106
|
return { pos, line, col };
|
|
13007
13107
|
}
|
|
13008
13108
|
function renderMarkdown(md) {
|
|
13009
|
-
const
|
|
13109
|
+
const esc2 = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
13010
13110
|
const blocks = [];
|
|
13011
13111
|
let src = md.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
13012
13112
|
const i = blocks.length;
|
|
13013
|
-
blocks.push(`<pre class="mailx-help-code"><code>${
|
|
13113
|
+
blocks.push(`<pre class="mailx-help-code"><code>${esc2(code)}</code></pre>`);
|
|
13014
13114
|
return `\0BLOCK${i}\0`;
|
|
13015
13115
|
});
|
|
13016
13116
|
const lines = src.split(/\r?\n/);
|
|
@@ -13030,7 +13130,7 @@ function renderMarkdown(md) {
|
|
|
13030
13130
|
}
|
|
13031
13131
|
};
|
|
13032
13132
|
function inline(s) {
|
|
13033
|
-
s =
|
|
13133
|
+
s = esc2(s);
|
|
13034
13134
|
s = s.replace(/`([^`]+)`/g, (_m, c) => `<code>${c}</code>`);
|
|
13035
13135
|
s = s.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
|
|
13036
13136
|
s = s.replace(/(^|[^*])\*([^*\n]+)\*/g, "$1<em>$2</em>");
|