@bobfrankston/mailx 1.0.193 → 1.0.195

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.
Files changed (2) hide show
  1. package/client/app.js +38 -13
  2. package/package.json +2 -2
package/client/app.js CHANGED
@@ -346,33 +346,53 @@ async function openCompose(mode) {
346
346
  showComposeOverlay();
347
347
  }
348
348
  function showComposeOverlay() {
349
- // Wrapper div for iframe + close button
350
349
  const wrapper = document.createElement("div");
351
350
  wrapper.className = "compose-overlay";
352
- wrapper.style.cssText = "position:fixed;bottom:0;right:16px;width:min(900px,55vw);height:min(700px,70vh);z-index:1000;border-radius:8px 8px 0 0;box-shadow:0 -4px 24px rgba(0,0,0,0.3);display:flex;flex-direction:column;";
353
- // Close button
351
+ wrapper.style.cssText = "position:fixed;bottom:0;right:16px;width:min(900px,55vw);height:min(700px,70vh);z-index:1000;border-radius:8px 8px 0 0;box-shadow:0 -4px 24px rgba(0,0,0,0.3);display:flex;flex-direction:column;resize:both;overflow:hidden;";
352
+ // Title bar — drag to move, close button
353
+ const titleBar = document.createElement("div");
354
+ titleBar.style.cssText = "display:flex;align-items:center;justify-content:space-between;padding:4px 8px;background:#e8ecf0;border-radius:8px 8px 0 0;cursor:move;user-select:none;flex-shrink:0;";
355
+ titleBar.textContent = "Compose";
354
356
  const closeBtn = document.createElement("button");
355
357
  closeBtn.textContent = "✕";
356
- closeBtn.title = "Close compose";
357
- closeBtn.style.cssText = "position:absolute;top:4px;right:8px;z-index:1001;background:none;border:none;font-size:18px;cursor:pointer;color:#666;padding:2px 6px;border-radius:4px;";
358
+ closeBtn.title = "Save draft and close";
359
+ closeBtn.style.cssText = "background:none;border:none;font-size:16px;cursor:pointer;color:#666;padding:2px 6px;border-radius:4px;";
358
360
  closeBtn.addEventListener("mouseenter", () => closeBtn.style.color = "#c00");
359
361
  closeBtn.addEventListener("mouseleave", () => closeBtn.style.color = "#666");
360
362
  closeBtn.addEventListener("click", () => {
361
- // Trigger draft save in the iframe before closing
362
363
  try {
363
364
  const win = frame.contentWindow;
364
- if (win) {
365
- // Dispatch a custom event that compose.ts can listen to
365
+ if (win)
366
366
  win.dispatchEvent(new Event("compose-save-and-close"));
367
- }
368
367
  }
369
- catch { /* cross-origin */ }
370
- // Give the draft save a moment, then close
368
+ catch { /* */ }
371
369
  setTimeout(() => wrapper.remove(), 500);
372
370
  });
371
+ titleBar.appendChild(closeBtn);
372
+ // Drag to move
373
+ let dragX = 0, dragY = 0;
374
+ titleBar.addEventListener("mousedown", (e) => {
375
+ if (e.target === closeBtn)
376
+ return;
377
+ e.preventDefault();
378
+ dragX = e.clientX - wrapper.offsetLeft;
379
+ dragY = e.clientY - wrapper.offsetTop;
380
+ const onMove = (e) => {
381
+ wrapper.style.left = `${e.clientX - dragX}px`;
382
+ wrapper.style.top = `${e.clientY - dragY}px`;
383
+ wrapper.style.bottom = "auto";
384
+ wrapper.style.right = "auto";
385
+ };
386
+ const onUp = () => {
387
+ document.removeEventListener("mousemove", onMove);
388
+ document.removeEventListener("mouseup", onUp);
389
+ };
390
+ document.addEventListener("mousemove", onMove);
391
+ document.addEventListener("mouseup", onUp);
392
+ });
373
393
  const frame = document.createElement("iframe");
374
394
  frame.src = "compose/compose.html";
375
- frame.style.cssText = "flex:1;border:none;border-radius:8px 8px 0 0;background:#fff;width:100%;";
395
+ frame.style.cssText = "flex:1;border:none;background:#fff;width:100%;";
376
396
  // Close when compose calls window.close()
377
397
  frame.addEventListener("load", () => {
378
398
  try {
@@ -383,7 +403,12 @@ function showComposeOverlay() {
383
403
  }
384
404
  catch { /* cross-origin safety */ }
385
405
  });
386
- wrapper.appendChild(closeBtn);
406
+ // Bring to front on click
407
+ wrapper.addEventListener("mousedown", () => {
408
+ document.querySelectorAll(".compose-overlay").forEach(el => el.style.zIndex = "1000");
409
+ wrapper.style.zIndex = "1001";
410
+ });
411
+ wrapper.appendChild(titleBar);
387
412
  wrapper.appendChild(frame);
388
413
  document.body.appendChild(wrapper);
389
414
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.193",
3
+ "version": "1.0.195",
4
4
  "description": "Local-first email client with IMAP sync and standalone native app",
5
5
  "type": "module",
6
6
  "main": "bin/mailx.js",
@@ -24,7 +24,7 @@
24
24
  "@bobfrankston/iflow-node": "^0.1.2",
25
25
  "@bobfrankston/miscinfo": "^1.0.8",
26
26
  "@bobfrankston/oauthsupport": "^1.0.21",
27
- "@bobfrankston/msger": "^0.1.244",
27
+ "@bobfrankston/msger": "^0.1.246",
28
28
  "@capacitor/android": "^8.3.0",
29
29
  "@capacitor/cli": "^8.3.0",
30
30
  "@capacitor/core": "^8.3.0",