@bobfrankston/rmfmail 1.2.68 → 1.2.70

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.
@@ -18,11 +18,52 @@
18
18
  */
19
19
  import * as esbuild from "esbuild";
20
20
  import path from "node:path";
21
+ import fs from "node:fs";
22
+ import crypto from "node:crypto";
21
23
  import { fileURLToPath } from "node:url";
22
24
 
23
25
  const root = path.resolve(fileURLToPath(import.meta.url), "..", "..");
24
26
  const watch = process.argv.includes("--watch");
25
27
 
28
+ /** Cache-bust the bundle references in the HTML entry points with a content
29
+ * hash. The msger custom protocol serves bundles with no cache headers, so
30
+ * WebView2 caches `app.bundle.js` and keeps serving the OLD bundle across
31
+ * daemon relaunches — every client-side fix silently failed to reach the user
32
+ * until the cache happened to evict (Bob 2026-06-26: flag/Ctrl+A fixes "still
33
+ * happening" while the daemon was already on the new version). Stamping a
34
+ * per-build `?v=<hash>` makes the URL change whenever the bundle changes, so
35
+ * the WebView is forced to fetch the new one. */
36
+ function shortHash(file) {
37
+ try { return crypto.createHash("sha1").update(fs.readFileSync(file)).digest("hex").slice(0, 10); }
38
+ catch { return String(Date.now()); }
39
+ }
40
+ function stampHtml(htmlFile, refs) {
41
+ let html;
42
+ try { html = fs.readFileSync(htmlFile, "utf8"); } catch { return; }
43
+ let changed = false;
44
+ for (const { name, file } of refs) {
45
+ const v = shortHash(file);
46
+ // Match the bundle name + optional existing ?v=… up to the closing
47
+ // quote, so re-runs replace the prior hash instead of stacking.
48
+ const re = new RegExp(`(${name.replace(/[.\\/]/g, m => "\\" + m)})(\\?v=[a-z0-9]+)?(")`, "g");
49
+ const next = html.replace(re, `$1?v=${v}$3`);
50
+ if (next !== html) { html = next; changed = true; }
51
+ }
52
+ if (changed) {
53
+ fs.writeFileSync(htmlFile, html);
54
+ console.log(` stamped ${path.relative(root, htmlFile)}`);
55
+ }
56
+ }
57
+ function stampAll() {
58
+ stampHtml(path.join(root, "client", "index.html"), [
59
+ { name: "./app.bundle.js", file: path.join(root, "client", "app.bundle.js") },
60
+ { name: "./android-bootstrap.bundle.js", file: path.join(root, "client", "android-bootstrap.bundle.js") },
61
+ ]);
62
+ stampHtml(path.join(root, "client", "compose", "compose.html"), [
63
+ { name: "compose.bundle.js", file: path.join(root, "client", "compose", "compose.bundle.js") },
64
+ ]);
65
+ }
66
+
26
67
  // Each entry has its own external list because the Android bootstrap bundle
27
68
  // needs to INCLUDE @bobfrankston/mailx-store-web (entire purpose of the
28
69
  // bundle), while app.bundle.js externalizes it so the desktop build doesn't
@@ -132,6 +173,7 @@ async function buildAll() {
132
173
  }
133
174
  const failed = results.filter(r => !r.ok).length;
134
175
  if (failed) process.exit(1);
176
+ stampAll();
135
177
  console.log(`build-bundles: done in ${Date.now() - t0} ms`);
136
178
  }
137
179
 
@@ -6240,7 +6240,12 @@ function initTabs(strip, apply) {
6240
6240
  if (raw) {
6241
6241
  const parsed = JSON.parse(raw);
6242
6242
  if (Array.isArray(parsed?.tabs) && parsed.tabs.length) {
6243
- tabs = parsed.tabs;
6243
+ tabs = parsed.tabs.map((t) => {
6244
+ if (t.view?.kind !== "search")
6245
+ return t;
6246
+ const v = t.view;
6247
+ return v.folderId ? { id: t.id, title: "Mail", view: { kind: "folder", accountId: v.accountId, folderId: v.folderId, specialUse: "" } } : { id: t.id, title: "All Inboxes", view: { kind: "unified" } };
6248
+ });
6244
6249
  activeId = parsed.activeId || tabs[0].id;
6245
6250
  for (const t of tabs) {
6246
6251
  const n = Number(String(t.id).replace(/^t/, ""));
@@ -11694,12 +11699,13 @@ function saveBootSnapshot() {
11694
11699
  const messageList2 = document.getElementById("ml-body");
11695
11700
  const folderTitle = document.getElementById("ml-folder-title");
11696
11701
  const ftHtml = folderTree2?.innerHTML?.trim() || "";
11697
- const mlHtml = messageList2?.innerHTML?.trim() || "";
11702
+ const searching = (searchInput?.value.trim() || "") !== "";
11703
+ const mlHtml = searching ? "" : messageList2?.innerHTML?.trim() || "";
11698
11704
  if (!ftHtml && !mlHtml) return;
11699
11705
  const snap = {
11700
11706
  folderTree: ftHtml,
11701
11707
  messageList: mlHtml,
11702
- folderTitle: folderTitle?.innerHTML?.trim() || "",
11708
+ folderTitle: searching ? "" : folderTitle?.innerHTML?.trim() || "",
11703
11709
  savedAt: Date.now()
11704
11710
  };
11705
11711
  localStorage.setItem("mailx-boot-snapshot", JSON.stringify(snap));