@bobfrankston/rmfmail 1.0.492 → 1.0.493
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 +58 -47
- package/client/app.js.map +1 -1
- package/client/app.ts +55 -45
- package/client/components/message-viewer.js +145 -81
- package/client/components/message-viewer.js.map +1 -1
- package/client/components/message-viewer.ts +132 -85
- package/client/index.html +1 -1
- package/package.json +3 -3
- package/packages/mailx-settings/index.d.ts +1 -0
- package/packages/mailx-settings/index.d.ts.map +1 -1
- package/packages/mailx-settings/index.js +43 -2
- package/packages/mailx-settings/index.js.map +1 -1
- package/packages/mailx-settings/index.ts +50 -2
- package/packages/mailx-store/db.d.ts.map +1 -1
- package/packages/mailx-store/db.js +8 -0
- package/packages/mailx-store/db.js.map +1 -1
- package/packages/mailx-store/db.ts +6 -0
- package/packages/mailx-store-web/db.d.ts.map +1 -1
- package/packages/mailx-store-web/db.js +26 -0
- package/packages/mailx-store-web/db.js.map +1 -1
- package/packages/mailx-store-web/db.ts +20 -0
- package/packages/mailx-store-web/web-service.d.ts +4 -0
- package/packages/mailx-store-web/web-service.d.ts.map +1 -1
- package/packages/mailx-store-web/web-service.js +42 -0
- package/packages/mailx-store-web/web-service.js.map +1 -1
- package/packages/mailx-store-web/web-service.ts +42 -0
- package/packages/mailx-store-web/web-settings.d.ts +2 -0
- package/packages/mailx-store-web/web-settings.d.ts.map +1 -1
- package/packages/mailx-store-web/web-settings.js +34 -3
- package/packages/mailx-store-web/web-settings.js.map +1 -1
- package/packages/mailx-store-web/web-settings.ts +41 -3
package/client/app.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { initFolderTree, refreshFolderTree, updateFolderCounts, setFolderSynced, getFolderSynced, setOutboxTotal } from "./components/folder-tree.js";
|
|
6
6
|
import { initMessageList, loadMessages, loadUnifiedInbox, loadSearchResults, reloadCurrentFolder, clearSearchMode, getSelectedMessages, markBodiesCached, getCurrentFocused, releaseFocus, removeMessagesAndReconcile, setRowFlagged, scrollFocusedIntoView } from "./components/message-list.js";
|
|
7
|
-
import { showMessage, getCurrentMessage, initViewer, popOutCurrentMessage, toggleFullscreenPreview } from "./components/message-viewer.js";
|
|
7
|
+
import { showMessage, getCurrentMessage, initViewer, popOutCurrentMessage, toggleFullscreenPreview, showPreviewBodyMenu } from "./components/message-viewer.js";
|
|
8
8
|
import { connectWebSocket, onWsEvent, triggerSync, syncAccount, reauthenticate, getAccounts, getFolders, deleteMessages, undeleteMessage, restartServer, getSyncPending, getVersion, getSettings, saveSettings, getAutocompleteSettings, saveAutocompleteSettings, repairAccounts, updateFlags, markAsSpamMessages, logClientEvent, sendMessage as apiSendMessage } from "./lib/api-client.js";
|
|
9
9
|
import * as messageState from "./lib/message-state.js";
|
|
10
10
|
// ── New message badge (favicon + title) ──
|
|
@@ -516,6 +516,7 @@ document.getElementById("btn-sync")?.addEventListener("click", async () => {
|
|
|
516
516
|
const restartBtn = document.getElementById("btn-restart");
|
|
517
517
|
const restartDropdown = document.getElementById("restart-dropdown");
|
|
518
518
|
restartBtn?.addEventListener("click", () => {
|
|
519
|
+
restoreToolbarDropdown("restart-dropdown", "restart-menu");
|
|
519
520
|
if (restartDropdown)
|
|
520
521
|
restartDropdown.hidden = !restartDropdown.hidden;
|
|
521
522
|
});
|
|
@@ -1177,7 +1178,7 @@ document.getElementById("rail-tasks")?.addEventListener("click", async () => {
|
|
|
1177
1178
|
* content. We never put the dropdown back: the toolbar handler also
|
|
1178
1179
|
* works on a body-attached dropdown (it's just toggling .hidden), and
|
|
1179
1180
|
* re-parenting on every toggle would defeat any focus state inside. */
|
|
1180
|
-
function openMenuFromRail(dropdownId,
|
|
1181
|
+
function openMenuFromRail(dropdownId, _anchor) {
|
|
1181
1182
|
const dd = document.getElementById(dropdownId);
|
|
1182
1183
|
if (!dd)
|
|
1183
1184
|
return;
|
|
@@ -1194,54 +1195,39 @@ function openMenuFromRail(dropdownId, anchor) {
|
|
|
1194
1195
|
if (dd.parentElement?.classList.contains("tb-menu")) {
|
|
1195
1196
|
document.body.appendChild(dd);
|
|
1196
1197
|
}
|
|
1197
|
-
//
|
|
1198
|
-
//
|
|
1198
|
+
// Uniform behavior across desktop and Android: render rail-opened menus
|
|
1199
|
+
// as a centered modal with a dimmed backdrop. Anchor-based positioning
|
|
1200
|
+
// was inconsistent (worked on Android narrow but not Mac/desktop wide;
|
|
1201
|
+
// bottom-rail icons sit at the viewport floor and the menu spilled off
|
|
1202
|
+
// or landed under chrome). A centered card is always visible, always
|
|
1203
|
+
// dismissible by tapping the backdrop, and the same on every platform.
|
|
1199
1204
|
dd.style.cssText = "";
|
|
1200
1205
|
dd.style.position = "fixed";
|
|
1206
|
+
dd.style.top = "50%";
|
|
1207
|
+
dd.style.left = "50%";
|
|
1208
|
+
dd.style.transform = "translate(-50%, -50%)";
|
|
1209
|
+
dd.style.maxHeight = "85vh";
|
|
1210
|
+
dd.style.maxWidth = "92vw";
|
|
1211
|
+
dd.style.overflowY = "auto";
|
|
1212
|
+
dd.style.boxShadow = "0 8px 32px rgba(0,0,0,0.4)";
|
|
1201
1213
|
dd.style.zIndex = "10000";
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
else {
|
|
1220
|
-
// Wide tier: anchor to the right of the rail icon, growing whichever
|
|
1221
|
-
// way has more room. (Bottom-rail icons sit near the viewport floor —
|
|
1222
|
-
// anchoring `top: rect.top` makes the menu spill off the bottom.)
|
|
1223
|
-
const rect = anchor.getBoundingClientRect();
|
|
1224
|
-
const minWidth = 220;
|
|
1225
|
-
const left = Math.min(rect.right + 6, window.innerWidth - minWidth - 8);
|
|
1226
|
-
dd.style.left = `${Math.max(8, left)}px`;
|
|
1227
|
-
dd.hidden = false;
|
|
1228
|
-
const ddHeight = dd.getBoundingClientRect().height;
|
|
1229
|
-
const spaceBelow = window.innerHeight - rect.top - 8;
|
|
1230
|
-
const spaceAbove = rect.bottom - 8;
|
|
1231
|
-
if (ddHeight > spaceBelow && spaceAbove > spaceBelow) {
|
|
1232
|
-
dd.style.bottom = `${Math.max(8, window.innerHeight - rect.bottom)}px`;
|
|
1233
|
-
if (ddHeight > spaceAbove) {
|
|
1234
|
-
dd.style.maxHeight = `${spaceAbove}px`;
|
|
1235
|
-
dd.style.overflowY = "auto";
|
|
1236
|
-
}
|
|
1237
|
-
}
|
|
1238
|
-
else {
|
|
1239
|
-
dd.style.top = `${Math.max(8, rect.top)}px`;
|
|
1240
|
-
if (ddHeight > spaceBelow) {
|
|
1241
|
-
dd.style.maxHeight = `${spaceBelow}px`;
|
|
1242
|
-
dd.style.overflowY = "auto";
|
|
1243
|
-
}
|
|
1244
|
-
}
|
|
1214
|
+
dd.hidden = false;
|
|
1215
|
+
ensureRailMenuBackdrop();
|
|
1216
|
+
}
|
|
1217
|
+
/** Restore a body-parented rail-opened dropdown back to its toolbar parent
|
|
1218
|
+
* and clear inline positioning, so the toolbar button's plain
|
|
1219
|
+
* `dd.hidden = !dd.hidden` toggle renders the dropdown in its usual
|
|
1220
|
+
* position-absolute place. Without this, the toolbar dropdown opens at
|
|
1221
|
+
* the rail-modal's centered position (or somewhere else stale) the first
|
|
1222
|
+
* time a user mixes rail-open and toolbar-open in the same session. */
|
|
1223
|
+
function restoreToolbarDropdown(ddId, tbMenuId) {
|
|
1224
|
+
const dd = document.getElementById(ddId);
|
|
1225
|
+
const tb = document.getElementById(tbMenuId);
|
|
1226
|
+
if (!dd || !tb)
|
|
1227
|
+
return;
|
|
1228
|
+
if (dd.parentElement === document.body) {
|
|
1229
|
+
tb.appendChild(dd);
|
|
1230
|
+
dd.style.cssText = "";
|
|
1245
1231
|
}
|
|
1246
1232
|
}
|
|
1247
1233
|
/** Narrow-tier rail menus need a tap-anywhere-to-close backdrop because the
|
|
@@ -1570,6 +1556,26 @@ window.addEventListener("message", (e) => {
|
|
|
1570
1556
|
window.open(url, "_blank", "noopener,noreferrer");
|
|
1571
1557
|
}
|
|
1572
1558
|
}
|
|
1559
|
+
if (e.data?.type === "previewToggleFullscreen") {
|
|
1560
|
+
toggleFullscreenPreview();
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (e.data?.type === "previewContextMenu") {
|
|
1564
|
+
// Translate iframe-relative coords to viewport. Find the iframe whose
|
|
1565
|
+
// contentWindow matches the source so we map correctly even when
|
|
1566
|
+
// multiple iframes are present (compose iframe + viewer iframe).
|
|
1567
|
+
let iframeRect = null;
|
|
1568
|
+
for (const f of Array.from(document.querySelectorAll("iframe"))) {
|
|
1569
|
+
if (f.contentWindow === e.source) {
|
|
1570
|
+
iframeRect = f.getBoundingClientRect();
|
|
1571
|
+
break;
|
|
1572
|
+
}
|
|
1573
|
+
}
|
|
1574
|
+
const x = (iframeRect?.left || 0) + (e.data.x || 0);
|
|
1575
|
+
const y = (iframeRect?.top || 0) + (e.data.y || 0);
|
|
1576
|
+
showPreviewBodyMenu(x, y, String(e.data.selectedText || ""), e.source);
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1573
1579
|
if (e.data?.type === "linkContextMenu") {
|
|
1574
1580
|
// C29: right-click in body iframe → Open / Save / Copy URL menu.
|
|
1575
1581
|
// Iframe's clientX/Y is relative to the iframe; translate to viewport.
|
|
@@ -2380,6 +2386,10 @@ viewBtn?.addEventListener("click", (e) => {
|
|
|
2380
2386
|
const restartDd = document.getElementById("restart-dropdown");
|
|
2381
2387
|
if (restartDd)
|
|
2382
2388
|
restartDd.hidden = true;
|
|
2389
|
+
// If the dropdown was previously opened via the rail (re-parented to
|
|
2390
|
+
// body with inline modal styles), restore it to its toolbar parent so
|
|
2391
|
+
// it renders in the expected position-absolute location.
|
|
2392
|
+
restoreToolbarDropdown("view-dropdown", "view-menu");
|
|
2383
2393
|
if (viewDropdown)
|
|
2384
2394
|
viewDropdown.hidden = !viewDropdown.hidden;
|
|
2385
2395
|
});
|
|
@@ -3195,6 +3205,7 @@ settingsBtn?.addEventListener("click", (e) => {
|
|
|
3195
3205
|
const restartDd = document.getElementById("restart-dropdown");
|
|
3196
3206
|
if (restartDd)
|
|
3197
3207
|
restartDd.hidden = true;
|
|
3208
|
+
restoreToolbarDropdown("settings-dropdown", "settings-menu");
|
|
3198
3209
|
if (settingsDropdown)
|
|
3199
3210
|
settingsDropdown.hidden = !settingsDropdown.hidden;
|
|
3200
3211
|
});
|