@bobfrankston/rmfmail 1.2.69 → 1.2.71
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/bin/build-bundles.mjs +42 -0
- package/client/app.bundle.js +18 -8
- package/client/app.bundle.js.map +2 -2
- package/client/app.js +14 -9
- package/client/app.js.map +1 -1
- package/client/app.ts +15 -10
- package/client/components/message-list.js +13 -3
- package/client/components/message-list.js.map +1 -1
- package/client/components/message-list.ts +13 -3
- package/client/compose/compose.html +1 -1
- package/client/index.html +2 -5
- package/package.json +1 -1
package/bin/build-bundles.mjs
CHANGED
|
@@ -18,11 +18,52 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as esbuild from "esbuild";
|
|
20
20
|
import path from "node:path";
|
|
21
|
+
import fs from "node:fs";
|
|
22
|
+
import crypto from "node:crypto";
|
|
21
23
|
import { fileURLToPath } from "node:url";
|
|
22
24
|
|
|
23
25
|
const root = path.resolve(fileURLToPath(import.meta.url), "..", "..");
|
|
24
26
|
const watch = process.argv.includes("--watch");
|
|
25
27
|
|
|
28
|
+
/** Cache-bust the bundle references in the HTML entry points with a content
|
|
29
|
+
* hash. The msger custom protocol serves bundles with no cache headers, so
|
|
30
|
+
* WebView2 caches `app.bundle.js` and keeps serving the OLD bundle across
|
|
31
|
+
* daemon relaunches — every client-side fix silently failed to reach the user
|
|
32
|
+
* until the cache happened to evict (Bob 2026-06-26: flag/Ctrl+A fixes "still
|
|
33
|
+
* happening" while the daemon was already on the new version). Stamping a
|
|
34
|
+
* per-build `?v=<hash>` makes the URL change whenever the bundle changes, so
|
|
35
|
+
* the WebView is forced to fetch the new one. */
|
|
36
|
+
function shortHash(file) {
|
|
37
|
+
try { return crypto.createHash("sha1").update(fs.readFileSync(file)).digest("hex").slice(0, 10); }
|
|
38
|
+
catch { return String(Date.now()); }
|
|
39
|
+
}
|
|
40
|
+
function stampHtml(htmlFile, refs) {
|
|
41
|
+
let html;
|
|
42
|
+
try { html = fs.readFileSync(htmlFile, "utf8"); } catch { return; }
|
|
43
|
+
let changed = false;
|
|
44
|
+
for (const { name, file } of refs) {
|
|
45
|
+
const v = shortHash(file);
|
|
46
|
+
// Match the bundle name + optional existing ?v=… up to the closing
|
|
47
|
+
// quote, so re-runs replace the prior hash instead of stacking.
|
|
48
|
+
const re = new RegExp(`(${name.replace(/[.\\/]/g, m => "\\" + m)})(\\?v=[a-z0-9]+)?(")`, "g");
|
|
49
|
+
const next = html.replace(re, `$1?v=${v}$3`);
|
|
50
|
+
if (next !== html) { html = next; changed = true; }
|
|
51
|
+
}
|
|
52
|
+
if (changed) {
|
|
53
|
+
fs.writeFileSync(htmlFile, html);
|
|
54
|
+
console.log(` stamped ${path.relative(root, htmlFile)}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function stampAll() {
|
|
58
|
+
stampHtml(path.join(root, "client", "index.html"), [
|
|
59
|
+
{ name: "./app.bundle.js", file: path.join(root, "client", "app.bundle.js") },
|
|
60
|
+
{ name: "./android-bootstrap.bundle.js", file: path.join(root, "client", "android-bootstrap.bundle.js") },
|
|
61
|
+
]);
|
|
62
|
+
stampHtml(path.join(root, "client", "compose", "compose.html"), [
|
|
63
|
+
{ name: "compose.bundle.js", file: path.join(root, "client", "compose", "compose.bundle.js") },
|
|
64
|
+
]);
|
|
65
|
+
}
|
|
66
|
+
|
|
26
67
|
// Each entry has its own external list because the Android bootstrap bundle
|
|
27
68
|
// needs to INCLUDE @bobfrankston/mailx-store-web (entire purpose of the
|
|
28
69
|
// bundle), while app.bundle.js externalizes it so the desktop build doesn't
|
|
@@ -132,6 +173,7 @@ async function buildAll() {
|
|
|
132
173
|
}
|
|
133
174
|
const failed = results.filter(r => !r.ok).length;
|
|
134
175
|
if (failed) process.exit(1);
|
|
176
|
+
stampAll();
|
|
135
177
|
console.log(`build-bundles: done in ${Date.now() - t0} ms`);
|
|
136
178
|
}
|
|
137
179
|
|
package/client/app.bundle.js
CHANGED
|
@@ -2749,6 +2749,7 @@ var init_folder_picker = __esm({
|
|
|
2749
2749
|
var message_list_exports = {};
|
|
2750
2750
|
__export(message_list_exports, {
|
|
2751
2751
|
clearSearchMode: () => clearSearchMode,
|
|
2752
|
+
exitMultiSelect: () => exitMultiSelect,
|
|
2752
2753
|
getCurrentFocused: () => getCurrentFocused,
|
|
2753
2754
|
getSelectedMessages: () => getSelectedMessages,
|
|
2754
2755
|
initMessageList: () => initMessageList,
|
|
@@ -3891,7 +3892,7 @@ function escapeHtml2(s) {
|
|
|
3891
3892
|
div.textContent = s;
|
|
3892
3893
|
return div.innerHTML;
|
|
3893
3894
|
}
|
|
3894
|
-
var onMessageSelect, currentAccountId2, currentFolderId, currentSpecialUse, lastClickedRow, currentPage, totalMessages, loading, unifiedMode, searchMode, liveFilterText, currentSearchQuery, wasUnifiedBeforeSearch, showToInsteadOfFrom, touchWasScroll, currentSort, currentSortDir, loadGen, listCache, CACHE_KEY_UNIFIED, positionMemory, POSITION_STORAGE_KEY, focusedRow, rowByKey, prioritySenders, priorityDomains, timeFmt, dateFmt, dateFmtSameYear, MessageRow;
|
|
3895
|
+
var onMessageSelect, currentAccountId2, currentFolderId, currentSpecialUse, lastClickedRow, currentPage, totalMessages, loading, unifiedMode, searchMode, liveFilterText, currentSearchQuery, wasUnifiedBeforeSearch, showToInsteadOfFrom, touchWasScroll, lastPointerWasTouch, currentSort, currentSortDir, loadGen, listCache, CACHE_KEY_UNIFIED, positionMemory, POSITION_STORAGE_KEY, focusedRow, rowByKey, prioritySenders, priorityDomains, timeFmt, dateFmt, dateFmtSameYear, MessageRow;
|
|
3895
3896
|
var init_message_list = __esm({
|
|
3896
3897
|
"client/components/message-list.js"() {
|
|
3897
3898
|
"use strict";
|
|
@@ -3911,6 +3912,12 @@ var init_message_list = __esm({
|
|
|
3911
3912
|
wasUnifiedBeforeSearch = false;
|
|
3912
3913
|
showToInsteadOfFrom = false;
|
|
3913
3914
|
touchWasScroll = false;
|
|
3915
|
+
lastPointerWasTouch = false;
|
|
3916
|
+
if (typeof document !== "undefined") {
|
|
3917
|
+
document.addEventListener("pointerdown", (e) => {
|
|
3918
|
+
lastPointerWasTouch = e.pointerType === "touch";
|
|
3919
|
+
}, true);
|
|
3920
|
+
}
|
|
3914
3921
|
currentSort = "date";
|
|
3915
3922
|
currentSortDir = "desc";
|
|
3916
3923
|
loadGen = 0;
|
|
@@ -4239,8 +4246,7 @@ var init_message_list = __esm({
|
|
|
4239
4246
|
return;
|
|
4240
4247
|
}
|
|
4241
4248
|
if (body?.classList.contains("multi-select-on")) {
|
|
4242
|
-
|
|
4243
|
-
if (!isTouch && !e.ctrlKey && !e.metaKey) {
|
|
4249
|
+
if (!lastPointerWasTouch && !e.ctrlKey && !e.metaKey) {
|
|
4244
4250
|
exitMultiSelect();
|
|
4245
4251
|
focusRow(this);
|
|
4246
4252
|
lastClickedRow = this.el;
|
|
@@ -8798,11 +8804,6 @@ document.getElementById("btn-spam-report")?.addEventListener("click", async () =
|
|
|
8798
8804
|
}
|
|
8799
8805
|
});
|
|
8800
8806
|
document.getElementById("btn-compose")?.addEventListener("click", () => openCompose("new"));
|
|
8801
|
-
document.getElementById("btn-selection")?.addEventListener("click", (e) => {
|
|
8802
|
-
e.stopPropagation();
|
|
8803
|
-
const r = e.currentTarget.getBoundingClientRect();
|
|
8804
|
-
void showSelectionMenu(r.left, r.bottom + 2);
|
|
8805
|
-
});
|
|
8806
8807
|
document.getElementById("btn-mark-unread")?.addEventListener("click", () => {
|
|
8807
8808
|
const sel = getCurrentFocused();
|
|
8808
8809
|
if (!sel) return;
|
|
@@ -9930,6 +9931,15 @@ document.addEventListener("keydown", (e) => {
|
|
|
9930
9931
|
e.preventDefault();
|
|
9931
9932
|
applyFontSize(next);
|
|
9932
9933
|
}
|
|
9934
|
+
if (e.key === "Escape" && document.getElementById("ml-body")?.classList.contains("multi-select-on")) {
|
|
9935
|
+
const t = e.target;
|
|
9936
|
+
const tag = t?.tagName;
|
|
9937
|
+
if (tag !== "INPUT" && tag !== "TEXTAREA" && tag !== "SELECT" && !t?.isContentEditable) {
|
|
9938
|
+
e.preventDefault();
|
|
9939
|
+
exitMultiSelect();
|
|
9940
|
+
return;
|
|
9941
|
+
}
|
|
9942
|
+
}
|
|
9933
9943
|
if (e.ctrlKey && e.key === "a") {
|
|
9934
9944
|
const t = e.target;
|
|
9935
9945
|
const tag = t?.tagName;
|