@bobfrankston/mailx 1.0.180 → 1.0.181
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/mailx.js +19 -1
- package/client/.msger-window.json +1 -1
- package/client/app.js +2 -14
- package/client/components/message-viewer.js +9 -2
- package/package.json +2 -2
package/bin/mailx.js
CHANGED
|
@@ -28,6 +28,20 @@ function hasFlag(name) { return args.includes(`-${name}`) || args.includes(`--${
|
|
|
28
28
|
const serverMode = hasFlag("server");
|
|
29
29
|
const noBrowser = hasFlag("no-browser");
|
|
30
30
|
const verbose = hasFlag("verbose");
|
|
31
|
+
const isDaemon = hasFlag("daemon"); // internal: re-spawned detached process
|
|
32
|
+
// Auto-detach: re-spawn as background process so terminal returns immediately
|
|
33
|
+
// Skip for: --verbose (want console), --server (needs terminal), --daemon (already detached),
|
|
34
|
+
// and any command flags (setup, kill, test, etc.)
|
|
35
|
+
if (!verbose && !serverMode && !isDaemon && !process.argv.slice(2).some(a => /^-/.test(a) && !["--no-browser"].includes(a))) {
|
|
36
|
+
const { spawn } = await import("node:child_process");
|
|
37
|
+
const child = spawn(process.execPath, [...process.argv.slice(1), "--daemon"], {
|
|
38
|
+
detached: true,
|
|
39
|
+
stdio: "ignore",
|
|
40
|
+
windowsHide: true,
|
|
41
|
+
});
|
|
42
|
+
child.unref();
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
31
45
|
const setupMode = hasFlag("setup");
|
|
32
46
|
const addMode = hasFlag("add");
|
|
33
47
|
const testMode = hasFlag("test");
|
|
@@ -35,7 +49,7 @@ const rebuildMode = hasFlag("rebuild");
|
|
|
35
49
|
const repairMode = hasFlag("repair");
|
|
36
50
|
const importMode = hasFlag("import");
|
|
37
51
|
// Validate arguments
|
|
38
|
-
const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "repair", "native-imap", "log", "import", "email", "mail"];
|
|
52
|
+
const knownFlags = ["server", "no-browser", "verbose", "external", "kill", "v", "version", "setup", "add", "test", "rebuild", "repair", "native-imap", "log", "import", "email", "mail", "daemon"];
|
|
39
53
|
for (const arg of args) {
|
|
40
54
|
const flag = arg.replace(/^--?/, "");
|
|
41
55
|
if (arg.startsWith("-") && !knownFlags.includes(flag)) {
|
|
@@ -665,6 +679,10 @@ async function main() {
|
|
|
665
679
|
// Pass server version to dispatch so getVersion returns it
|
|
666
680
|
const rootPkg = JSON.parse(fs.readFileSync(path.join(import.meta.dirname, "..", "package.json"), "utf-8"));
|
|
667
681
|
handle.onRequest(async (req) => {
|
|
682
|
+
if (!req._action) {
|
|
683
|
+
console.log(`[ipc] ← ignored (no _action): ${JSON.stringify(req).substring(0, 100)}`);
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
668
686
|
console.log(`[ipc] ← ${req._action} (${req._cbid})`);
|
|
669
687
|
try {
|
|
670
688
|
const response = await dispatch(svc, req);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"height":1047,"width":1844,"x":
|
|
1
|
+
{"height":1047,"width":1844,"x":339,"y":168}
|
package/client/app.js
CHANGED
|
@@ -565,22 +565,10 @@ onWsEvent((event) => {
|
|
|
565
565
|
break;
|
|
566
566
|
}
|
|
567
567
|
case "folderCountsChanged": {
|
|
568
|
-
//
|
|
568
|
+
// Update folder badges only — never reload the message list or touch the viewer.
|
|
569
|
+
// The list refreshes when the user clicks a folder or presses Sync.
|
|
569
570
|
updateFolderCounts();
|
|
570
571
|
updateNewMessageCount();
|
|
571
|
-
// Only reload message list if the synced account is the one we're viewing
|
|
572
|
-
// (or unified inbox which shows all accounts). Debounce to avoid rapid reloads
|
|
573
|
-
// during first sync which emits per-batch.
|
|
574
|
-
const syncedAccount = event.accountId;
|
|
575
|
-
const viewingThis = !currentAccountId || currentAccountId === syncedAccount;
|
|
576
|
-
if (viewingThis) {
|
|
577
|
-
if (reloadDebounceTimer)
|
|
578
|
-
clearTimeout(reloadDebounceTimer);
|
|
579
|
-
reloadDebounceTimer = setTimeout(() => {
|
|
580
|
-
reloadDebounceTimer = null;
|
|
581
|
-
reloadCurrentFolder();
|
|
582
|
-
}, 500);
|
|
583
|
-
}
|
|
584
572
|
// Sync finished — re-enable sync button
|
|
585
573
|
const syncBtn = document.getElementById("btn-sync");
|
|
586
574
|
if (syncBtn) {
|
|
@@ -17,16 +17,23 @@ export function getCurrentMessage() {
|
|
|
17
17
|
/** Initialize viewer — subscribe to state changes */
|
|
18
18
|
export function initViewer() {
|
|
19
19
|
state.subscribe((change) => {
|
|
20
|
-
if (change === "removed"
|
|
20
|
+
if (change === "removed") {
|
|
21
|
+
// Message was deleted/moved — show auto-selected next, or clear
|
|
21
22
|
const sel = state.getSelected();
|
|
22
23
|
if (!sel) {
|
|
23
24
|
clearViewer();
|
|
24
25
|
}
|
|
25
26
|
else if (sel.uid !== currentMessage?.uid || sel.accountId !== currentAccountId) {
|
|
26
|
-
// State auto-selected a new message after removal — show it
|
|
27
27
|
showMessage(sel.accountId, sel.uid, sel.folderId);
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
|
+
else if (change === "selected") {
|
|
31
|
+
// Explicit deselect (folder switch, clearViewer)
|
|
32
|
+
if (!state.getSelected()) {
|
|
33
|
+
clearViewer();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// "messages" change (sync reload) — don't touch the viewer
|
|
30
37
|
});
|
|
31
38
|
}
|
|
32
39
|
function clearViewer() {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bobfrankston/mailx",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.181",
|
|
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.
|
|
27
|
+
"@bobfrankston/msger": "^0.1.231",
|
|
28
28
|
"@capacitor/android": "^8.3.0",
|
|
29
29
|
"@capacitor/cli": "^8.3.0",
|
|
30
30
|
"@capacitor/core": "^8.3.0",
|