@bobfrankston/rmfmail 1.2.226 → 1.2.227

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.
@@ -1795,6 +1795,18 @@ function confirmDeleteAttachments(msg, accountId, uid, ids, question) {
1795
1795
  backdrop.append(panel);
1796
1796
  document.body.append(backdrop);
1797
1797
  }
1798
+ function markRenderStart(accountId, uid) {
1799
+ try {
1800
+ sessionStorage.setItem(RENDER_MARK_KEY, JSON.stringify({ key: renderKey(accountId, uid), at: Date.now() }));
1801
+ } catch {
1802
+ }
1803
+ }
1804
+ function markRenderDone() {
1805
+ try {
1806
+ sessionStorage.removeItem(RENDER_MARK_KEY);
1807
+ } catch {
1808
+ }
1809
+ }
1798
1810
  async function showMessage(accountId, uid, folderId, specialUse, isRetry = false, envelope) {
1799
1811
  const gen = ++showMessageGeneration;
1800
1812
  if (!isRetry)
@@ -1850,11 +1862,28 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
1850
1862
  headerEl.hidden = true;
1851
1863
  }
1852
1864
  attEl.hidden = true;
1865
+ if (poisonedMessages.has(renderKey(accountId, uid)) && !isRetry) {
1866
+ const emlHint = envelope?.emlPath || "";
1867
+ bodyEl.innerHTML = `<div class="mv-system-message mv-system-error">
1868
+ <div class="mv-system-tag">mailx</div>
1869
+ <div class="mv-system-title">Render failed for this message</div>
1870
+ <div class="mv-system-body">The display engine stopped while drawing this message last time, so it hasn't been drawn again automatically.
1871
+ Usually this means an unusually large body.${emlHint ? `<br><code style="user-select:all;font-size:0.9em">${escapeHtml2(emlHint)}</code>` : ""}
1872
+ <br><br><button type="button" id="mv-render-anyway" class="mailx-modal-btn">Try anyway</button></div>
1873
+ </div>`;
1874
+ document.getElementById("mv-render-anyway")?.addEventListener("click", () => {
1875
+ poisonedMessages.delete(renderKey(accountId, uid));
1876
+ void showMessage(accountId, uid, folderId, specialUse, true, envelope);
1877
+ });
1878
+ attEl.hidden = true;
1879
+ return;
1880
+ }
1853
1881
  try {
1854
1882
  if (cachedMsg)
1855
1883
  _ptick("parsedCache HIT \u2014 sync render");
1856
1884
  else
1857
1885
  _ptick("parsedCache MISS \u2014 IPC begin");
1886
+ markRenderStart(accountId, uid);
1858
1887
  const msg = cachedMsg ? cachedMsg : await getMessage(accountId, uid, false, folderId);
1859
1888
  if (!cachedMsg)
1860
1889
  _ptick(`IPC done (cached=${msg.cached !== false}, ${msg.bodyHtml?.length || 0} bytes html)`);
@@ -2387,6 +2416,19 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
2387
2416
  const pre = document.createElement("pre");
2388
2417
  pre.style.cssText = "padding: 1rem; white-space: pre-wrap; word-break: break-word; font-family: system-ui, sans-serif; font-size: 17.5px; line-height: 1.5; color: #1a1a2e; background: #fff; margin: 0; height: 100%; overflow: auto;";
2389
2418
  pre.innerHTML = linkifyText(msg.bodyText);
2419
+ const trunc = msg.bodyTruncated;
2420
+ if (trunc) {
2421
+ const mb = (n) => `${(n / 1048576).toFixed(1)} MB`;
2422
+ const note = document.createElement("div");
2423
+ note.className = "mv-system-message mv-system-error";
2424
+ note.style.cssText = "margin: 0 0 12px 0;";
2425
+ note.innerHTML = `<div class="mv-system-tag">mailx</div>
2426
+ <div class="mv-system-title">Showing the first ${mb(trunc.sentBytes)} of a ${mb(trunc.totalBytes)} message</div>
2427
+ <div class="mv-system-body">This body is too large to render in the app window${trunc.hadHtml ? " (its HTML part was dropped \u2014 a partial HTML document renders as garbage)" : ""}.
2428
+ The complete message is on disk:<br>
2429
+ <code style="user-select:all;font-size:0.9em">${escapeHtml2(trunc.emlPath || "(path unavailable)")}</code></div>`;
2430
+ bodyEl.appendChild(note);
2431
+ }
2390
2432
  bodyEl.appendChild(pre);
2391
2433
  } else {
2392
2434
  const fetchErr = recentFetchErrors.get(`${accountId}:${uid}`);
@@ -2408,6 +2450,7 @@ async function showMessage(accountId, uid, folderId, specialUse, isRetry = false
2408
2450
  </div>`;
2409
2451
  }
2410
2452
  }
2453
+ markRenderDone();
2411
2454
  attEl.innerHTML = "";
2412
2455
  attEl.hidden = true;
2413
2456
  if (msg.attachments?.length) {
@@ -3275,7 +3318,7 @@ function spawnDesktopPopout(msg, accountId) {
3275
3318
  function escapeHtmlLocal(s) {
3276
3319
  return (s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
3277
3320
  }
3278
- var currentMessage, currentAccountId, dragOutUrls, showMessageGeneration, retryCount, lastEnvelope, PARSED_CACHE_LIMIT, parsedCache, sessionAllowedRemote, recentFetchErrors, ZOOM_KEY, ZOOM_MIN, ZOOM_MAX, ZOOM_STEP, previewZoom;
3321
+ var currentMessage, currentAccountId, dragOutUrls, showMessageGeneration, retryCount, lastEnvelope, PARSED_CACHE_LIMIT, parsedCache, sessionAllowedRemote, recentFetchErrors, ZOOM_KEY, ZOOM_MIN, ZOOM_MAX, ZOOM_STEP, previewZoom, RENDER_MARK_KEY, RENDER_MARK_MAX_AGE_MS, poisonedMessages, renderKey;
3279
3322
  var init_message_viewer = __esm({
3280
3323
  "client/components/message-viewer.js"() {
3281
3324
  "use strict";
@@ -3324,6 +3367,24 @@ var init_message_viewer = __esm({
3324
3367
  clearViewer();
3325
3368
  }
3326
3369
  });
3370
+ RENDER_MARK_KEY = "mailx-rendering";
3371
+ RENDER_MARK_MAX_AGE_MS = 6e4;
3372
+ poisonedMessages = /* @__PURE__ */ new Set();
3373
+ renderKey = (a, u) => `${a}:${u}`;
3374
+ (() => {
3375
+ try {
3376
+ const raw = sessionStorage.getItem(RENDER_MARK_KEY);
3377
+ if (!raw)
3378
+ return;
3379
+ sessionStorage.removeItem(RENDER_MARK_KEY);
3380
+ const mark = JSON.parse(raw);
3381
+ if (!mark?.key || Date.now() - (mark.at || 0) > RENDER_MARK_MAX_AGE_MS)
3382
+ return;
3383
+ poisonedMessages.add(mark.key);
3384
+ console.error(`[viewer] previous render of ${mark.key} did not complete \u2014 the WebView probably died on it; not auto-rendering again`);
3385
+ } catch {
3386
+ }
3387
+ })();
3327
3388
  subscribeStore("*", (ev) => {
3328
3389
  if (ev.kind !== "bodyFetchError")
3329
3390
  return;