@bobfrankston/mailx 1.0.192 → 1.0.193

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.
@@ -1 +1 @@
1
- {"height":1344,"width":2151,"x":500,"y":36}
1
+ {"height":1344,"width":2151,"x":400,"y":28}
@@ -44,8 +44,10 @@ export function showContextMenu(x, y, items) {
44
44
  menu.style.top = `${y - rect.height}px`;
45
45
  activeMenu = menu;
46
46
  }
47
- // Close on click outside or Escape
47
+ // Close on any interaction outside the menu
48
48
  document.addEventListener("click", closeContextMenu);
49
49
  document.addEventListener("keydown", (e) => { if (e.key === "Escape")
50
50
  closeContextMenu(); });
51
+ document.addEventListener("scroll", closeContextMenu, true);
52
+ document.addEventListener("contextmenu", () => { });
51
53
  //# sourceMappingURL=context-menu.js.map
@@ -3,6 +3,7 @@
3
3
  * Subscribes to message-state: clears when selected becomes null.
4
4
  */
5
5
  import { getMessage, updateFlags, allowRemoteContent, getAttachment } from "../lib/api-client.js";
6
+ import { showContextMenu } from "./context-menu.js";
6
7
  import * as state from "../lib/message-state.js";
7
8
  /** Currently displayed message (for reply/forward) */
8
9
  let currentMessage = null;
@@ -58,7 +59,7 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
58
59
  const bodyEl = document.getElementById("mv-body");
59
60
  const attEl = document.getElementById("mv-attachments");
60
61
  bodyEl.innerHTML = `<div class="mv-empty">Fetching message body...</div>`;
61
- // Don't hide the header — keep previous header visible until new one loads
62
+ headerEl.hidden = true;
62
63
  attEl.hidden = true;
63
64
  try {
64
65
  const msg = await getMessage(accountId, uid, false, folderId);
@@ -74,12 +75,34 @@ export async function showMessage(accountId, uid, folderId, specialUse, isRetry
74
75
  }
75
76
  // Header
76
77
  headerEl.hidden = false;
77
- headerEl.querySelector(".mv-from").textContent = formatAddr(msg.from);
78
- headerEl.querySelector(".mv-to").textContent = `To: ${msg.to.map(formatAddr).join(", ")}`;
78
+ const fromEl = headerEl.querySelector(".mv-from");
79
+ const toEl = headerEl.querySelector(".mv-to");
80
+ fromEl.textContent = formatAddr(msg.from);
81
+ toEl.textContent = `To: ${msg.to.map(formatAddr).join(", ")}`;
79
82
  if (msg.cc?.length) {
80
- headerEl.querySelector(".mv-to").textContent += ` Cc: ${msg.cc.map(formatAddr).join(", ")}`;
83
+ toEl.textContent += ` Cc: ${msg.cc.map(formatAddr).join(", ")}`;
81
84
  }
82
85
  headerEl.querySelector(".mv-subject").textContent = msg.subject;
86
+ // Right-click on email addresses in header
87
+ const allAddresses = [msg.from, ...(msg.to || []), ...(msg.cc || [])].filter((a) => a?.address);
88
+ for (const el of [fromEl, toEl]) {
89
+ el.addEventListener("contextmenu", (e) => {
90
+ e.preventDefault();
91
+ const me = e;
92
+ const items = [];
93
+ for (const addr of (el === fromEl ? [msg.from] : [...(msg.to || []), ...(msg.cc || [])])) {
94
+ if (!addr?.address)
95
+ continue;
96
+ const display = addr.name ? `${addr.name} <${addr.address}>` : addr.address;
97
+ items.push({ label: `Copy: ${display}`, action: () => navigator.clipboard.writeText(addr.address) });
98
+ }
99
+ items.push({ label: "", action: () => { }, separator: true });
100
+ items.push({ label: "Reply", action: () => document.dispatchEvent(new CustomEvent("mailx-compose", { detail: { mode: "reply" } })) });
101
+ items.push({ label: "Reply All", action: () => document.dispatchEvent(new CustomEvent("mailx-compose", { detail: { mode: "replyAll" } })) });
102
+ items.push({ label: "Forward", action: () => document.dispatchEvent(new CustomEvent("mailx-compose", { detail: { mode: "forward" } })) });
103
+ showContextMenu(me.clientX, me.clientY, items);
104
+ });
105
+ }
83
106
  headerEl.querySelector(".mv-date").textContent = new Date(msg.date).toLocaleString(undefined, { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", hour12: false });
84
107
  // Unsubscribe button (upper right of header)
85
108
  const unsubBtn = document.getElementById("mv-unsubscribe");
@@ -155,7 +155,7 @@ body {
155
155
  }
156
156
  }
157
157
 
158
- /* Hide hamburger and back on wide screens */
159
- @media (min-width: 769px) {
158
+ /* Hide hamburger and back on wide screens (folder panel always visible) */
159
+ @media (min-width: 1101px) {
160
160
  #btn-menu, #btn-back { display: none !important; }
161
161
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/mailx",
3
- "version": "1.0.192",
3
+ "version": "1.0.193",
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.243",
27
+ "@bobfrankston/msger": "^0.1.244",
28
28
  "@capacitor/android": "^8.3.0",
29
29
  "@capacitor/cli": "^8.3.0",
30
30
  "@capacitor/core": "^8.3.0",