@bobfrankston/rmfmail 1.2.274 → 1.2.277
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 +31 -0
- package/bin/build-tinymce.js +27 -0
- package/client/android-bootstrap.bundle.js +169 -0
- package/client/android-bootstrap.bundle.js.map +2 -2
- package/client/app.bundle.js +231 -23
- package/client/app.bundle.js.map +4 -4
- package/client/app.js +81 -1
- package/client/app.js.map +1 -1
- package/client/app.ts +75 -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/compose/compose.bundle.js +90 -2
- package/client/compose/compose.bundle.js.map +4 -4
- package/client/compose/compose.js +26 -1
- package/client/compose/compose.js.map +1 -1
- package/client/compose/compose.ts +22 -1
- package/client/compose/editor.js +12 -1
- package/client/compose/editor.js.map +1 -1
- package/client/compose/editor.ts +17 -2
- package/client/index.html +1 -0
- package/client/lib/rmf-tiny.js +3 -0
- package/client/lib/tinymce/langs/ar-SA.js +440 -0
- package/client/lib/tinymce/langs/ar.js +441 -0
- package/client/lib/tinymce/langs/az.js +440 -0
- package/client/lib/tinymce/langs/be.js +440 -0
- package/client/lib/tinymce/langs/bg-BG.js +440 -0
- package/client/lib/tinymce/langs/bn-BD.js +440 -0
- package/client/lib/tinymce/langs/bs.js +440 -0
- package/client/lib/tinymce/langs/ca.js +440 -0
- package/client/lib/tinymce/langs/cs.js +440 -0
- package/client/lib/tinymce/langs/cy.js +440 -0
- package/client/lib/tinymce/langs/da.js +440 -0
- package/client/lib/tinymce/langs/de.js +440 -0
- package/client/lib/tinymce/langs/el.js +440 -0
- package/client/lib/tinymce/langs/eo.js +440 -0
- package/client/lib/tinymce/langs/es-MX.js +440 -0
- package/client/lib/tinymce/langs/es.js +440 -0
- package/client/lib/tinymce/langs/et.js +440 -0
- package/client/lib/tinymce/langs/eu.js +440 -0
- package/client/lib/tinymce/langs/fa.js +441 -0
- package/client/lib/tinymce/langs/fi.js +440 -0
- package/client/lib/tinymce/langs/fr-FR.js +440 -0
- package/client/lib/tinymce/langs/gl.js +440 -0
- package/client/lib/tinymce/langs/he-IL.js +440 -0
- package/client/lib/tinymce/langs/hr.js +440 -0
- package/client/lib/tinymce/langs/hu-HU.js +440 -0
- package/client/lib/tinymce/langs/hy.js +440 -0
- package/client/lib/tinymce/langs/id.js +440 -0
- package/client/lib/tinymce/langs/index.json +63 -0
- package/client/lib/tinymce/langs/is-IS.js +440 -0
- package/client/lib/tinymce/langs/it.js +440 -0
- package/client/lib/tinymce/langs/ja.js +440 -0
- package/client/lib/tinymce/langs/ka-GE.js +440 -0
- package/client/lib/tinymce/langs/kab.js +440 -0
- package/client/lib/tinymce/langs/kk.js +440 -0
- package/client/lib/tinymce/langs/ko-KR.js +440 -0
- package/client/lib/tinymce/langs/lt.js +440 -0
- package/client/lib/tinymce/langs/lv.js +440 -0
- package/client/lib/tinymce/langs/nb-NO.js +440 -0
- package/client/lib/tinymce/langs/ne.js +440 -0
- package/client/lib/tinymce/langs/nl-BE.js +440 -0
- package/client/lib/tinymce/langs/nl.js +440 -0
- package/client/lib/tinymce/langs/oc.js +440 -0
- package/client/lib/tinymce/langs/pl.js +440 -0
- package/client/lib/tinymce/langs/pt-BR.js +440 -0
- package/client/lib/tinymce/langs/pt-PT.js +440 -0
- package/client/lib/tinymce/langs/ro.js +440 -0
- package/client/lib/tinymce/langs/ru.js +440 -0
- package/client/lib/tinymce/langs/sk.js +440 -0
- package/client/lib/tinymce/langs/sl-SI.js +440 -0
- package/client/lib/tinymce/langs/sr.js +440 -0
- package/client/lib/tinymce/langs/sv-SE.js +440 -0
- package/client/lib/tinymce/langs/ta.js +440 -0
- package/client/lib/tinymce/langs/tg.js +440 -0
- package/client/lib/tinymce/langs/th-TH.js +440 -0
- package/client/lib/tinymce/langs/tr.js +440 -0
- package/client/lib/tinymce/langs/ug.js +440 -0
- package/client/lib/tinymce/langs/uk.js +440 -0
- package/client/lib/tinymce/langs/vi.js +440 -0
- package/client/lib/tinymce/langs/zh-CN.js +440 -0
- package/client/lib/tinymce/langs/zh-HK.js +440 -0
- package/client/lib/tinymce/langs/zh-MO.js +440 -0
- package/client/lib/tinymce/langs/zh-TW.js +440 -0
- package/client/lib/tinymce-langs.js +96 -0
- package/client/lib/tinymce-langs.js.map +1 -0
- package/client/lib/tinymce-langs.ts +99 -0
- package/client/package.json +1 -1
- package/client/styles/components.css +48 -0
- package/docs/editor.md +29 -3
- package/docs/preferences.md +2 -1
- package/npmchanges.md +29 -0
- package/package.json +18 -15
- 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-48352}/.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>
|
|
@@ -7839,6 +7937,67 @@ whatever it finds.</p>
|
|
|
7839
7937
|
}
|
|
7840
7938
|
});
|
|
7841
7939
|
|
|
7940
|
+
// client/lib/tinymce-langs.js
|
|
7941
|
+
var tinymce_langs_exports = {};
|
|
7942
|
+
__export(tinymce_langs_exports, {
|
|
7943
|
+
LANGUAGE_AUTO: () => LANGUAGE_AUTO,
|
|
7944
|
+
LANGUAGE_ENGLISH: () => LANGUAGE_ENGLISH,
|
|
7945
|
+
availableLanguages: () => availableLanguages,
|
|
7946
|
+
langManifestUrl: () => langManifestUrl,
|
|
7947
|
+
languageLabel: () => languageLabel,
|
|
7948
|
+
resolveLanguage: () => resolveLanguage
|
|
7949
|
+
});
|
|
7950
|
+
function langManifestUrl(tinymceScriptUrl) {
|
|
7951
|
+
return new URL("langs/index.json", new URL(tinymceScriptUrl, location.href)).href;
|
|
7952
|
+
}
|
|
7953
|
+
async function availableLanguages(tinymceScriptUrl) {
|
|
7954
|
+
try {
|
|
7955
|
+
const r = await fetch(langManifestUrl(tinymceScriptUrl));
|
|
7956
|
+
if (!r.ok)
|
|
7957
|
+
return [];
|
|
7958
|
+
const list = await r.json();
|
|
7959
|
+
return Array.isArray(list) ? list.filter((x) => typeof x === "string") : [];
|
|
7960
|
+
} catch {
|
|
7961
|
+
return [];
|
|
7962
|
+
}
|
|
7963
|
+
}
|
|
7964
|
+
function resolveLanguage(setting, available, preferred = navigator.languages || [navigator.language]) {
|
|
7965
|
+
const byLower = new Map(available.map((code) => [code.toLowerCase(), code]));
|
|
7966
|
+
if (setting && setting !== LANGUAGE_AUTO) {
|
|
7967
|
+
if (setting === LANGUAGE_ENGLISH)
|
|
7968
|
+
return LANGUAGE_ENGLISH;
|
|
7969
|
+
return byLower.get(setting.toLowerCase()) || LANGUAGE_ENGLISH;
|
|
7970
|
+
}
|
|
7971
|
+
for (const tag of preferred) {
|
|
7972
|
+
if (!tag)
|
|
7973
|
+
continue;
|
|
7974
|
+
const lower = tag.toLowerCase();
|
|
7975
|
+
const base = lower.split("-")[0];
|
|
7976
|
+
if (base === LANGUAGE_ENGLISH)
|
|
7977
|
+
return LANGUAGE_ENGLISH;
|
|
7978
|
+
const hit = byLower.get(lower) || byLower.get(base) || available.find((code) => code.toLowerCase().split("-")[0] === base);
|
|
7979
|
+
if (hit)
|
|
7980
|
+
return hit;
|
|
7981
|
+
}
|
|
7982
|
+
return LANGUAGE_ENGLISH;
|
|
7983
|
+
}
|
|
7984
|
+
function languageLabel(code) {
|
|
7985
|
+
try {
|
|
7986
|
+
const names = new Intl.DisplayNames(navigator.languages || void 0, { type: "language" });
|
|
7987
|
+
return names.of(code) || code;
|
|
7988
|
+
} catch {
|
|
7989
|
+
return code;
|
|
7990
|
+
}
|
|
7991
|
+
}
|
|
7992
|
+
var LANGUAGE_AUTO, LANGUAGE_ENGLISH;
|
|
7993
|
+
var init_tinymce_langs = __esm({
|
|
7994
|
+
"client/lib/tinymce-langs.js"() {
|
|
7995
|
+
"use strict";
|
|
7996
|
+
LANGUAGE_AUTO = "auto";
|
|
7997
|
+
LANGUAGE_ENGLISH = "en";
|
|
7998
|
+
}
|
|
7999
|
+
});
|
|
8000
|
+
|
|
7842
8001
|
// client/components/folder-tree.js
|
|
7843
8002
|
init_api_client();
|
|
7844
8003
|
init_context_menu();
|
|
@@ -9261,6 +9420,7 @@ window.__btick && window.__btick("app.ts module body executing");
|
|
|
9261
9420
|
var baseTitle = APP_NAME;
|
|
9262
9421
|
var lastSeenCount = 0;
|
|
9263
9422
|
var badgeCount = 0;
|
|
9423
|
+
var lastOverlayCount = -1;
|
|
9264
9424
|
function updateBadge(count) {
|
|
9265
9425
|
badgeCount = count;
|
|
9266
9426
|
document.title = count > 0 ? `(${count}) ${baseTitle}` : baseTitle;
|
|
@@ -9297,7 +9457,8 @@ function updateBadge(count) {
|
|
|
9297
9457
|
link.href = dataUrl;
|
|
9298
9458
|
try {
|
|
9299
9459
|
const hostApi = window.mailxapi;
|
|
9300
|
-
if (hostApi?.setTaskbarOverlay) {
|
|
9460
|
+
if (hostApi?.setTaskbarOverlay && count !== lastOverlayCount) {
|
|
9461
|
+
lastOverlayCount = count;
|
|
9301
9462
|
if (count > 0) {
|
|
9302
9463
|
const bc = document.createElement("canvas");
|
|
9303
9464
|
bc.width = 32;
|
|
@@ -13006,11 +13167,11 @@ function offsetToLineCol(src, pos) {
|
|
|
13006
13167
|
return { pos, line, col };
|
|
13007
13168
|
}
|
|
13008
13169
|
function renderMarkdown(md) {
|
|
13009
|
-
const
|
|
13170
|
+
const esc2 = (s) => s.replace(/[&<>"']/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[c]);
|
|
13010
13171
|
const blocks = [];
|
|
13011
13172
|
let src = md.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, _lang, code) => {
|
|
13012
13173
|
const i = blocks.length;
|
|
13013
|
-
blocks.push(`<pre class="mailx-help-code"><code>${
|
|
13174
|
+
blocks.push(`<pre class="mailx-help-code"><code>${esc2(code)}</code></pre>`);
|
|
13014
13175
|
return `\0BLOCK${i}\0`;
|
|
13015
13176
|
});
|
|
13016
13177
|
const lines = src.split(/\r?\n/);
|
|
@@ -13030,7 +13191,7 @@ function renderMarkdown(md) {
|
|
|
13030
13191
|
}
|
|
13031
13192
|
};
|
|
13032
13193
|
function inline(s) {
|
|
13033
|
-
s =
|
|
13194
|
+
s = esc2(s);
|
|
13034
13195
|
s = s.replace(/`([^`]+)`/g, (_m, c) => `<code>${c}</code>`);
|
|
13035
13196
|
s = s.replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>");
|
|
13036
13197
|
s = s.replace(/(^|[^*])\*([^*\n]+)\*/g, "$1<em>$2</em>");
|
|
@@ -13375,6 +13536,53 @@ document.getElementById("opt-compose-font-size")?.addEventListener("change", (e)
|
|
|
13375
13536
|
}).catch(() => {
|
|
13376
13537
|
});
|
|
13377
13538
|
});
|
|
13539
|
+
var optEditorLanguage = document.getElementById("opt-editor-language");
|
|
13540
|
+
if (optEditorLanguage) {
|
|
13541
|
+
(async () => {
|
|
13542
|
+
const scriptUrl = localStorage.getItem("mailx-tinymce-cdn") || "lib/tinymce/tinymce.min.js";
|
|
13543
|
+
const { availableLanguages: availableLanguages2, resolveLanguage: resolveLanguage2, languageLabel: languageLabel2, LANGUAGE_AUTO: LANGUAGE_AUTO2, LANGUAGE_ENGLISH: LANGUAGE_ENGLISH2 } = await Promise.resolve().then(() => (init_tinymce_langs(), tinymce_langs_exports));
|
|
13544
|
+
const available = await availableLanguages2(scriptUrl);
|
|
13545
|
+
const autoPick = resolveLanguage2(LANGUAGE_AUTO2, available);
|
|
13546
|
+
const add = (value, text) => {
|
|
13547
|
+
const o = document.createElement("option");
|
|
13548
|
+
o.value = value;
|
|
13549
|
+
o.textContent = text;
|
|
13550
|
+
optEditorLanguage.appendChild(o);
|
|
13551
|
+
};
|
|
13552
|
+
add(LANGUAGE_AUTO2, `Auto \u2014 ${languageLabel2(autoPick)}`);
|
|
13553
|
+
add(LANGUAGE_ENGLISH2, languageLabel2(LANGUAGE_ENGLISH2));
|
|
13554
|
+
for (const code of [...available].sort((a, b) => languageLabel2(a).localeCompare(languageLabel2(b)))) {
|
|
13555
|
+
add(code, `${languageLabel2(code)} (${code})`);
|
|
13556
|
+
}
|
|
13557
|
+
if (!available.length) {
|
|
13558
|
+
optEditorLanguage.disabled = true;
|
|
13559
|
+
optEditorLanguage.title = "No language packs found next to tinymce.min.js \u2014 English only";
|
|
13560
|
+
}
|
|
13561
|
+
let current = LANGUAGE_AUTO2;
|
|
13562
|
+
try {
|
|
13563
|
+
current = localStorage.getItem("mailx-editor-language") || LANGUAGE_AUTO2;
|
|
13564
|
+
} catch {
|
|
13565
|
+
}
|
|
13566
|
+
try {
|
|
13567
|
+
const settings = await getSettings();
|
|
13568
|
+
if (typeof settings?.ui?.editorLanguage === "string" && settings.ui.editorLanguage) current = settings.ui.editorLanguage;
|
|
13569
|
+
} catch {
|
|
13570
|
+
}
|
|
13571
|
+
optEditorLanguage.value = current;
|
|
13572
|
+
if (!optEditorLanguage.value) optEditorLanguage.value = LANGUAGE_AUTO2;
|
|
13573
|
+
})().catch((e) => console.error("[settings] editor-language menu failed:", e?.message || e));
|
|
13574
|
+
optEditorLanguage.addEventListener("change", () => {
|
|
13575
|
+
const value = optEditorLanguage.value;
|
|
13576
|
+
try {
|
|
13577
|
+
localStorage.setItem("mailx-editor-language", value);
|
|
13578
|
+
} catch {
|
|
13579
|
+
}
|
|
13580
|
+
getSettings().then((settings) => {
|
|
13581
|
+
settings.ui = { ...settings.ui, editorLanguage: value };
|
|
13582
|
+
saveSettings(settings);
|
|
13583
|
+
}).catch((e) => console.error("[settings] editor language save failed:", e?.message || e));
|
|
13584
|
+
});
|
|
13585
|
+
}
|
|
13378
13586
|
function saveEditorSetting(editor) {
|
|
13379
13587
|
try {
|
|
13380
13588
|
localStorage.setItem("mailx-editor-type", editor);
|