@bobfrankston/rmfmail 1.2.121 → 1.2.123

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.js CHANGED
@@ -1329,6 +1329,7 @@ function showComposeOverlay(title = "Compose") {
1329
1329
  const SVG_ATTRS = `width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"`;
1330
1330
  const TRASH_SVG = `<svg ${SVG_ATTRS}><path d="M3 6h18"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>`;
1331
1331
  const POPOUT_SVG = `<svg ${SVG_ATTRS}><path d="M15 3h6v6"/><path d="M10 14 21 3"/><path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"/></svg>`;
1332
+ const MAXIMIZE_SVG = `<svg ${SVG_ATTRS}><rect x="4" y="4" width="16" height="16" rx="2"/><path d="M4 9h16"/></svg>`;
1332
1333
  const RESTORE_SVG = `<svg ${SVG_ATTRS}><path d="M21 9v-6h-6"/><path d="M3 15v6h6"/><path d="M21 3l-7 7"/><path d="M3 21l7-7"/></svg>`;
1333
1334
  const makeIconBtn = (svg, titleStr, hoverColor) => {
1334
1335
  const b = document.createElement("button");
@@ -1349,11 +1350,28 @@ function showComposeOverlay(title = "Compose") {
1349
1350
  catch { /* */ }
1350
1351
  });
1351
1352
  btnCluster.appendChild(discardBtn);
1352
- // Popout = toggle between the floating overlay and a host-window-filling
1353
- // layout. The compose iframe can't open in a real OS window (msger custom
1354
- // protocol doesn't propagate to child windows), so "popout" here means
1355
- // "fill the host window" second click restores the floating geometry.
1356
- const popoutBtn = makeIconBtn(POPOUT_SVG, "Maximize", "#000");
1353
+ // True popout hand the live compose off to its own OS window (native
1354
+ // msger window via the daemon; see compose.ts popoutHandoff). Lives in
1355
+ // the TITLE BAR with the other frame controls because it's about the
1356
+ // frame, not the content (Bob 2026-07-12). The iframe owns the state, so
1357
+ // this just pokes it with an event, same pattern as Discard/Close.
1358
+ // Hidden on small screens where the overlay is full-screen and a separate
1359
+ // OS window makes no sense (and Android has no popout host).
1360
+ if (!isSmall) {
1361
+ const osPopoutBtn = makeIconBtn(POPOUT_SVG, "Open in separate window", "#000");
1362
+ osPopoutBtn.addEventListener("click", () => {
1363
+ try {
1364
+ const win = frame.contentWindow;
1365
+ if (win)
1366
+ win.dispatchEvent(new Event("compose-popout"));
1367
+ }
1368
+ catch { /* */ }
1369
+ });
1370
+ btnCluster.appendChild(osPopoutBtn);
1371
+ }
1372
+ // Maximize = toggle between the floating overlay and a host-window-filling
1373
+ // layout — second click restores the floating geometry.
1374
+ const popoutBtn = makeIconBtn(MAXIMIZE_SVG, "Maximize", "#000");
1357
1375
  let maximized = false;
1358
1376
  let savedCss = "";
1359
1377
  popoutBtn.addEventListener("click", () => {
@@ -1366,7 +1384,7 @@ function showComposeOverlay(title = "Compose") {
1366
1384
  }
1367
1385
  else {
1368
1386
  wrapper.style.cssText = savedCss;
1369
- popoutBtn.innerHTML = POPOUT_SVG;
1387
+ popoutBtn.innerHTML = MAXIMIZE_SVG;
1370
1388
  popoutBtn.title = "Maximize";
1371
1389
  maximized = false;
1372
1390
  }