@bobfrankston/rmfmail 1.1.213 → 1.1.214
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/lib/mailxapi.js
CHANGED
|
@@ -53,33 +53,67 @@
|
|
|
53
53
|
// turned a slow-but-fine search into "mailxapi timeout:
|
|
54
54
|
// searchMessages". Local search stays fast and well under any limit.
|
|
55
55
|
searchMessages: 120000,
|
|
56
|
-
// getVersion reads package.json — instant.
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
//
|
|
56
|
+
// getVersion reads package.json — instant. With the startup-race
|
|
57
|
+
// re-send above (it's in RESENDABLE) a dropped post is re-tried every
|
|
58
|
+
// 2s, so a 5s ceiling normally allows ~2 re-sends before giving up —
|
|
59
|
+
// enough to ride out the brief window before the Rust→daemon pipe is
|
|
60
|
+
// wired. Short ceiling so a genuinely wedged daemon surfaces fast
|
|
61
|
+
// rather than hanging the version display for 30s.
|
|
61
62
|
getVersion: 5000,
|
|
62
63
|
};
|
|
64
|
+
// Actions that are PURE READS and therefore safe to auto-re-send if the
|
|
65
|
+
// first post is lost. Why a post gets lost: at startup the WebView can
|
|
66
|
+
// call `window.ipc.postMessage` after `window.ipc` is injected but BEFORE
|
|
67
|
+
// the Rust host has wired its message handler to the daemon's stdin — the
|
|
68
|
+
// post is accepted by WebView2 and silently dropped downstream, so no
|
|
69
|
+
// response ever comes and the callback times out. That's the real cause of
|
|
70
|
+
// "getVersion got dropped" (Bob 2026-06-03) — a startup race in our own
|
|
71
|
+
// bridge, not a mysterious msger behavior. Re-sending a read is harmless
|
|
72
|
+
// (the daemon ignores a duplicate response — _msgapiServiceResolve no-ops
|
|
73
|
+
// when the callback is already gone). WRITES are NOT listed: re-sending a
|
|
74
|
+
// send/saveDraft/delete/move/flag could double-apply.
|
|
75
|
+
var RESENDABLE = {
|
|
76
|
+
getVersion: 1, getAccounts: 1, getFolders: 1, getUnifiedInbox: 1, getMessages: 1,
|
|
77
|
+
getSettings: 1, getAutocompleteSettings: 1, getDiagnostics: 1, getOutboxStatus: 1,
|
|
78
|
+
getSyncPending: 1, getCalendars: 1, getCalendarEvents: 1, getTasks: 1,
|
|
79
|
+
getPrimaryAccount: 1, getThreadMessages: 1, getPriorityLists: 1
|
|
80
|
+
};
|
|
81
|
+
var RESEND_INTERVAL_MS = 2000;
|
|
63
82
|
function callNode(action, params) {
|
|
64
83
|
var id = String(++_callbackId);
|
|
84
|
+
var msgStr = JSON.stringify(Object.assign({ _action: action, _cbid: id }, params || {}));
|
|
65
85
|
return new Promise(function(resolve, reject) {
|
|
66
|
-
|
|
86
|
+
function send() {
|
|
87
|
+
if (window.ipc && window.ipc.postMessage) {
|
|
88
|
+
// Trace BEFORE the call so a slow daemon-receive shows up as
|
|
89
|
+
// ipc-send + N s before the daemon logs `[ipc] ←`. Skip the
|
|
90
|
+
// trace event itself to avoid recursion.
|
|
91
|
+
if (action !== "logClientEvent") _traceIpcSend(action, id);
|
|
92
|
+
window.ipc.postMessage(msgStr);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
var entry = { resolve: resolve, reject: reject, timer: null, resend: null };
|
|
98
|
+
_callbacks[id] = entry;
|
|
99
|
+
entry.timer = setTimeout(function() {
|
|
67
100
|
delete _callbacks[id];
|
|
101
|
+
if (entry.resend) clearInterval(entry.resend);
|
|
68
102
|
reject(new Error("mailxapi timeout: " + action));
|
|
69
103
|
}, ACTION_TIMEOUT_MS[action] || 30000);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
//
|
|
74
|
-
|
|
75
|
-
// logs `[ipc] ←`. Skip tracing on the trace event itself so
|
|
76
|
-
// we don't recurse.
|
|
77
|
-
if (action !== "logClientEvent") _traceIpcSend(action, id);
|
|
78
|
-
window.ipc.postMessage(JSON.stringify(msg));
|
|
79
|
-
} else {
|
|
80
|
-
clearTimeout(timer);
|
|
104
|
+
var sent = send();
|
|
105
|
+
if (!sent && !RESENDABLE[action]) {
|
|
106
|
+
// Channel object not injected yet AND not safe to wait/re-send
|
|
107
|
+
// (a write) → fail now rather than risk it.
|
|
108
|
+
clearTimeout(entry.timer);
|
|
81
109
|
delete _callbacks[id];
|
|
82
110
|
reject(new Error("No IPC channel available"));
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// Re-send pure reads until a response lands or the ceiling fires —
|
|
114
|
+
// heals a startup-race drop (and a not-yet-injected window.ipc).
|
|
115
|
+
if (RESENDABLE[action]) {
|
|
116
|
+
entry.resend = setInterval(send, RESEND_INTERVAL_MS);
|
|
83
117
|
}
|
|
84
118
|
});
|
|
85
119
|
}
|
|
@@ -90,6 +124,7 @@
|
|
|
90
124
|
if (!cb) return;
|
|
91
125
|
delete _callbacks[id];
|
|
92
126
|
clearTimeout(cb.timer);
|
|
127
|
+
if (cb.resend) clearInterval(cb.resend);
|
|
93
128
|
cb.resolve(value);
|
|
94
129
|
};
|
|
95
130
|
|
|
@@ -99,6 +134,7 @@
|
|
|
99
134
|
if (!cb) return;
|
|
100
135
|
delete _callbacks[id];
|
|
101
136
|
clearTimeout(cb.timer);
|
|
137
|
+
if (cb.resend) clearInterval(cb.resend);
|
|
102
138
|
cb.reject(new Error(error));
|
|
103
139
|
};
|
|
104
140
|
|
package/package.json
CHANGED