@bobfrankston/rmfmail 1.1.139 → 1.1.140

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/app.ts CHANGED
@@ -937,13 +937,24 @@ async function openCompose(mode: ComposeMode, overrideMsg?: any, overrideAccount
937
937
  }
938
938
 
939
939
 
940
- // Store init data for compose window to pick up. sessionStorage is the
941
- // canonical handoff path same origin between parent and iframe; the
942
- // compose IIFE reads it after the editor finishes booting. We also
943
- // postMessage the iframe so it can short-circuit the listen-for-message
944
- // wait if it's already past editor init.
945
- sessionStorage.setItem("composeInit", JSON.stringify(init));
946
- try { frame?.contentWindow?.postMessage({ type: "compose-init-ready" }, "*"); } catch { /* */ }
940
+ // Store init data for compose window to pick up. Two parallel paths
941
+ // because sessionStorage propagation to a freshly-loading iframe has
942
+ // intermittently failed under WebView2's custom-protocol host (Bob
943
+ // 2026-05-24: reply-all opened with empty To/Subject; daemon log shows
944
+ // reply-init dump fired correctly but the iframe IIFE saw sessionStorage
945
+ // empty and timed out the wait). postMessage carries the FULL init
946
+ // payload so the iframe can populate even when storage doesn't bridge.
947
+ // sessionStorage remains as the fast-path for iframes that finish
948
+ // loading before postMessage fires.
949
+ const initJson = JSON.stringify(init);
950
+ try { sessionStorage.setItem("composeInit", initJson); }
951
+ catch (e: any) { console.error("[compose] sessionStorage.setItem failed:", e?.message || e); }
952
+ const post = (): void => {
953
+ try { frame?.contentWindow?.postMessage({ type: "compose-init", init }, "*"); } catch { /* */ }
954
+ };
955
+ post();
956
+ // Iframe may not be loaded yet — re-post on load so the listener exists.
957
+ try { frame?.addEventListener("load", post, { once: true }); } catch { /* */ }
947
958
  }
948
959
 
949
960
  function showComposeOverlay(title = "Compose"): HTMLIFrameElement {
@@ -4164,12 +4164,18 @@ function scheduleDraftSave() {
4164
4164
  });
4165
4165
  }, DRAFT_INPUT_DEBOUNCE_MS);
4166
4166
  }
4167
+ var _postedInit = null;
4167
4168
  var _parentInitReady = !!sessionStorage.getItem("composeInit");
4168
4169
  var _parentInitListeners = [];
4169
4170
  window.addEventListener("message", (e) => {
4170
- if (e.data?.type !== "compose-init-ready") return;
4171
- _parentInitReady = true;
4172
- for (const fn of _parentInitListeners.splice(0)) fn();
4171
+ if (e.data?.type === "compose-init-ready") {
4172
+ _parentInitReady = true;
4173
+ for (const fn of _parentInitListeners.splice(0)) fn();
4174
+ } else if (e.data?.type === "compose-init" && e.data.init) {
4175
+ _postedInit = e.data.init;
4176
+ _parentInitReady = true;
4177
+ for (const fn of _parentInitListeners.splice(0)) fn();
4178
+ }
4173
4179
  });
4174
4180
  function waitForParentInit(maxMs) {
4175
4181
  if (_parentInitReady) return Promise.resolve();
@@ -4186,16 +4192,17 @@ function waitForParentInit(maxMs) {
4186
4192
  }
4187
4193
  (async () => {
4188
4194
  _ctick("init IIFE start");
4189
- if (!sessionStorage.getItem("composeInit")) {
4195
+ if (!sessionStorage.getItem("composeInit") && !_postedInit) {
4190
4196
  _ctick("waiting for parent init");
4191
4197
  await waitForParentInit(1500);
4192
4198
  _ctick("parent init received");
4193
4199
  }
4194
4200
  const stored = sessionStorage.getItem("composeInit");
4195
- if (stored) {
4201
+ const initRaw = _postedInit || (stored ? JSON.parse(stored) : null);
4202
+ if (initRaw) {
4196
4203
  sessionStorage.removeItem("composeInit");
4197
- const init = JSON.parse(stored);
4198
- _ctick(`init parsed (mode=${init.mode}, bodyHtml=${init.bodyHtml?.length || 0} bytes)`);
4204
+ const init = initRaw;
4205
+ _ctick(`init parsed (mode=${init.mode}, bodyHtml=${init.bodyHtml?.length || 0} bytes, src=${_postedInit ? "postMessage" : "sessionStorage"})`);
4199
4206
  if (init.accounts && init.accounts.length > 0) {
4200
4207
  applyInit(init);
4201
4208
  _ctick("applyInit done \u2014 compose visible");