@bobfrankston/rmfmail 1.0.665 → 1.0.666

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/client/index.html CHANGED
@@ -648,9 +648,16 @@
648
648
  } else {
649
649
  window.__btick && window.__btick("desktop bootstrap (mailxapi pre-injected)");
650
650
  }
651
- window.__btick && window.__btick("app.js import begin");
652
- await import("./app.js");
653
- window.__btick && window.__btick("app.js loaded");
651
+ window.__btick && window.__btick("app.bundle.js import begin");
652
+ // app.bundle.js collapses the client's ~17-file import graph
653
+ // into one fetch — msger's custom protocol pays a multi-second
654
+ // IPC roundtrip per request, so the cascade was the dominant
655
+ // cold-start cost (~43 s on 2026-05-11 measurements). The
656
+ // bundle is regenerated by `npm run build` via
657
+ // bin/build-bundles.mjs; dynamic `await import()` of optional
658
+ // adapters (rmf-tiny, android-bootstrap) stays external.
659
+ await import("./app.bundle.js");
660
+ window.__btick && window.__btick("app.bundle.js loaded");
654
661
  } catch (e) {
655
662
  const msg = "BOOTSTRAP FAILED: " + (e.message || e) + "\n" + (e.stack || "");
656
663
  const el = document.getElementById("startup-status");
@@ -885,5 +892,48 @@
885
892
  <div id="startup-status">Starting…</div>
886
893
  </div>
887
894
  </div>
895
+
896
+ <!-- Boot-snapshot hydration. The bundled app saves the rendered folder
897
+ tree, message list, and viewer state into localStorage on a 30 s
898
+ tick and on beforeunload. This inline script (synchronous, runs at
899
+ body-end before any module imports) restores those DOM regions
900
+ instantly so the user sees their inbox / preview right away while
901
+ the bundle is still being fetched + parsed. The live render later
902
+ overwrites in place — no flicker because the snapshot DOM matches
903
+ the post-bundle structure.
904
+
905
+ Best-effort: missing snapshot, parse failure, stale data ≥ 7 days,
906
+ or any DOM mutation error → quietly skip and show the regular
907
+ "Starting…" overlay. -->
908
+ <script>
909
+ (function hydrateFromBootSnapshot() {
910
+ try {
911
+ var raw = localStorage.getItem("mailx-boot-snapshot");
912
+ if (!raw) return;
913
+ var snap = JSON.parse(raw);
914
+ if (!snap || !snap.savedAt) return;
915
+ var ageMs = Date.now() - snap.savedAt;
916
+ if (ageMs < 0 || ageMs > 7 * 24 * 60 * 60 * 1000) return;
917
+ var hydrated = false;
918
+ var setIfHas = function (id, html) {
919
+ if (!html) return;
920
+ var el = document.getElementById(id);
921
+ if (el) { el.innerHTML = html; hydrated = true; }
922
+ };
923
+ setIfHas("folder-tree", snap.folderTree);
924
+ setIfHas("ml-body", snap.messageList);
925
+ setIfHas("ml-folder-title", snap.folderTitle);
926
+ if (hydrated) {
927
+ // Drop the spinner overlay — we have content. The
928
+ // bundle's first render will overwrite this DOM in
929
+ // place (typically a flicker-free no-op since the
930
+ // snapshot was captured from the same render path).
931
+ var overlay = document.getElementById("startup-overlay");
932
+ if (overlay) overlay.style.display = "none";
933
+ window.__btick && window.__btick("boot-snapshot hydrated (age " + Math.round(ageMs / 1000) + "s)");
934
+ }
935
+ } catch (e) { /* hydration is best-effort */ }
936
+ })();
937
+ </script>
888
938
  </body>
889
939
  </html>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/rmfmail",
3
- "version": "1.0.665",
3
+ "version": "1.0.666",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -23,7 +23,7 @@
23
23
  "client"
24
24
  ],
25
25
  "scripts": {
26
- "build": "npm run build --workspaces --if-present && tsc -p bin && node bin/build-icon-ico.js && node bin/build-rmfmailto-exe.js && node bin/build-rmf-tiny.js && node bin/build-tinymce.js",
26
+ "build": "npm run build --workspaces --if-present && tsc -p bin && node bin/build-icon-ico.js && node bin/build-rmfmailto-exe.js && node bin/build-rmf-tiny.js && node bin/build-tinymce.js && node bin/build-bundles.mjs",
27
27
  "watch": "tsc -w",
28
28
  "start": "node --watch packages/mailx-server/index.js",
29
29
  "start:prod": "node packages/mailx-server/index.js",
@@ -61,6 +61,7 @@
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/mailparser": "^3.4.6",
64
+ "esbuild": "^0.28.0",
64
65
  "jsdom": "^29.1.1"
65
66
  },
66
67
  "keywords": [