@bobfrankston/mailx 1.0.295 → 1.0.296
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 +38 -0
- package/client/app.js +17 -0
- package/client/lib/mailxapi.js +3 -0
- package/package.json +1 -1
package/bin/mailx.js
CHANGED
|
@@ -868,6 +868,21 @@ async function main() {
|
|
|
868
868
|
return;
|
|
869
869
|
}
|
|
870
870
|
console.log(`[ipc] ← ${req._action} (${req._cbid})`);
|
|
871
|
+
// Auto-update action: run npm install then restart
|
|
872
|
+
if (req._action === "performUpdate") {
|
|
873
|
+
handle.send({ _cbid: req._cbid, ok: true, status: "updating" });
|
|
874
|
+
try {
|
|
875
|
+
const { execSync } = await import("child_process");
|
|
876
|
+
console.log(" [update] Installing latest version...");
|
|
877
|
+
execSync("npm install -g @bobfrankston/mailx", { encoding: "utf-8", timeout: 120_000, stdio: "inherit" });
|
|
878
|
+
console.log(" [update] Install complete — restarting");
|
|
879
|
+
}
|
|
880
|
+
catch (e) {
|
|
881
|
+
console.error(` [update] Install failed: ${e.message}`);
|
|
882
|
+
}
|
|
883
|
+
gracefulShutdown("Update complete — restarting");
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
871
886
|
try {
|
|
872
887
|
const response = await dispatch(svc, req);
|
|
873
888
|
console.log(`[ipc] → ${req._action} (${req._cbid}) ok`);
|
|
@@ -1045,6 +1060,29 @@ async function main() {
|
|
|
1045
1060
|
imapManager.startPeriodicSync(settings.sync.intervalMinutes);
|
|
1046
1061
|
imapManager.startOutboxWorker();
|
|
1047
1062
|
imapManager.watchConfigFiles();
|
|
1063
|
+
// Auto-update: periodically check npm for a newer version and push a
|
|
1064
|
+
// notification to the WebView so the user can update with one click.
|
|
1065
|
+
const UPDATE_CHECK_MS = 30 * 60_000; // 30 minutes
|
|
1066
|
+
async function checkForUpdate() {
|
|
1067
|
+
try {
|
|
1068
|
+
const { execSync } = await import("child_process");
|
|
1069
|
+
const latest = execSync("npm view @bobfrankston/mailx version", { encoding: "utf-8", timeout: 15_000 }).trim();
|
|
1070
|
+
const current = rootPkgVersion;
|
|
1071
|
+
if (latest && latest !== current) {
|
|
1072
|
+
console.log(` [update] New version available: ${current} → ${latest}`);
|
|
1073
|
+
handle.send({ _event: "updateAvailable", type: "updateAvailable", current, latest });
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
catch (e) {
|
|
1077
|
+
// Silent — network down, npm not reachable, etc.
|
|
1078
|
+
console.log(` [update] Check failed: ${e.message}`);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
// First check after 2 minutes (don't slow down startup), then every 30 min
|
|
1082
|
+
setTimeout(() => {
|
|
1083
|
+
checkForUpdate();
|
|
1084
|
+
setInterval(checkForUpdate, UPDATE_CHECK_MS);
|
|
1085
|
+
}, 120_000);
|
|
1048
1086
|
// Graceful shutdown — close IMAP connections, stop timers, close DB
|
|
1049
1087
|
let shuttingDown = false;
|
|
1050
1088
|
async function gracefulShutdown(reason) {
|
package/client/app.js
CHANGED
|
@@ -1044,6 +1044,23 @@ onWsEvent((event) => {
|
|
|
1044
1044
|
statusSync.textContent = `Synced ${new Date().toLocaleTimeString(undefined, { hour: "2-digit", minute: "2-digit", hour12: false })}`;
|
|
1045
1045
|
break;
|
|
1046
1046
|
}
|
|
1047
|
+
case "updateAvailable": {
|
|
1048
|
+
const banner = document.getElementById("alert-banner");
|
|
1049
|
+
const text = document.getElementById("alert-text");
|
|
1050
|
+
if (banner && text) {
|
|
1051
|
+
banner.hidden = false;
|
|
1052
|
+
banner.style.background = "oklch(0.45 0.12 250)";
|
|
1053
|
+
text.innerHTML = `mailx ${event.latest} available (you have ${event.current}) — <button id="btn-do-update" style="background:none;border:1px solid #fff;color:#fff;padding:0.15em 0.5em;border-radius:3px;cursor:pointer;margin-left:0.5em">Update now</button>`;
|
|
1054
|
+
document.getElementById("btn-do-update")?.addEventListener("click", () => {
|
|
1055
|
+
text.textContent = "Updating... mailx will restart when done";
|
|
1056
|
+
// performUpdate runs npm install then restarts the service
|
|
1057
|
+
const ipc = window.mailxapi || window.opener?.mailxapi;
|
|
1058
|
+
if (ipc?.performUpdate)
|
|
1059
|
+
ipc.performUpdate();
|
|
1060
|
+
});
|
|
1061
|
+
}
|
|
1062
|
+
break;
|
|
1063
|
+
}
|
|
1047
1064
|
case "syncActionFailed": {
|
|
1048
1065
|
// Surface sync failures (move/delete/flag not applied on server)
|
|
1049
1066
|
// so the user knows local-first actions haven't propagated yet.
|
package/client/lib/mailxapi.js
CHANGED
|
@@ -132,6 +132,9 @@
|
|
|
132
132
|
markAsSpamMessages: function(accountId, uids) {
|
|
133
133
|
return callNode("markAsSpamMessages", { accountId: accountId, uids: uids });
|
|
134
134
|
},
|
|
135
|
+
performUpdate: function() {
|
|
136
|
+
return callNode("performUpdate", {});
|
|
137
|
+
},
|
|
135
138
|
markFolderRead: function(accountId, folderId) {
|
|
136
139
|
return callNode("markFolderRead", { folderId: folderId });
|
|
137
140
|
},
|