Skip to content

Commit 44c54ff

Browse files
committed
feat(updater): restore app menu with manual update checks
Add a default application menu including an Updates section with "Check for updates now" and user-facing status dialogs. Keep startup checks and temporarily increase background polling to every minute for faster update detection during testing. Made-with: Cursor
1 parent f709698 commit 44c54ff

1 file changed

Lines changed: 100 additions & 3 deletions

File tree

app/windows/build.cjs

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ const fs = require("fs");
55
const { pathToFileURL } = require("url");
66

77
const isDev = process.env.NODE_ENV === "development";
8+
const updaterMenuApi = {
9+
checkNow: null,
10+
};
811

912
function resolveNotificationIcon() {
1013
const candidates = [
@@ -41,6 +44,14 @@ function setupAutoUpdater() {
4144
if (isDev || !app.isPackaged) return;
4245
try {
4346
const { autoUpdater } = require("electron-updater");
47+
let manualCheckInProgress = false;
48+
49+
const showUpdateMessage = async (title, message) => {
50+
try {
51+
const win = BrowserWindow.getAllWindows()[0];
52+
await dialog.showMessageBox(win || null, { type: "info", title, message });
53+
} catch (_) {}
54+
};
4455
autoUpdater.logger = {
4556
info: (m) => log(`[updater] ${typeof m === "string" ? m : JSON.stringify(m)}`),
4657
warn: (m) => log(`[updater] ${typeof m === "string" ? m : JSON.stringify(m)}`),
@@ -123,6 +134,46 @@ function setupAutoUpdater() {
123134
});
124135
});
125136

137+
autoUpdater.on("checking-for-update", () => {
138+
if (manualCheckInProgress) {
139+
log("[updater] manual check started");
140+
}
141+
});
142+
143+
autoUpdater.on("update-available", (info) => {
144+
if (manualCheckInProgress) {
145+
manualCheckInProgress = false;
146+
void showUpdateMessage(
147+
"Update found",
148+
`Version ${info?.version || "new"} is available and downloading in background.`
149+
);
150+
}
151+
});
152+
153+
autoUpdater.on("update-not-available", () => {
154+
if (manualCheckInProgress) {
155+
manualCheckInProgress = false;
156+
void showUpdateMessage("No updates", "You are already on the latest version.");
157+
}
158+
});
159+
160+
autoUpdater.on("error", (err) => {
161+
if (manualCheckInProgress) {
162+
manualCheckInProgress = false;
163+
void showUpdateMessage("Update check failed", err?.message || String(err));
164+
}
165+
});
166+
167+
updaterMenuApi.checkNow = async () => {
168+
try {
169+
manualCheckInProgress = true;
170+
await autoUpdater.checkForUpdates();
171+
} catch (e) {
172+
manualCheckInProgress = false;
173+
await showUpdateMessage("Update check failed", e?.message || String(e));
174+
}
175+
};
176+
126177
app.on("before-quit", () => {
127178
if (installRequested) {
128179
log("[updater] before-quit for update install");
@@ -138,8 +189,8 @@ function setupAutoUpdater() {
138189
// 1) On startup (each app launch)
139190
markAndCheck();
140191

141-
// 2) While running: every 6 hours
142-
const periodicMs = 1 * 60 * 60 * 1000;
192+
// 2) While running: every 1 minute (temporary aggressive polling)
193+
const periodicMs = 1 * 60 * 1000;
143194
setInterval(markAndCheck, periodicMs);
144195

145196
// 3) When user brings the app back to foreground (throttled: at most once per 30 min)
@@ -154,6 +205,52 @@ function setupAutoUpdater() {
154205
}
155206
}
156207

208+
function setupAppMenu() {
209+
const template = [
210+
{
211+
label: "File",
212+
submenu: [{ role: "quit", label: "Exit" }],
213+
},
214+
{
215+
label: "Edit",
216+
submenu: [
217+
{ role: "undo" },
218+
{ role: "redo" },
219+
{ type: "separator" },
220+
{ role: "cut" },
221+
{ role: "copy" },
222+
{ role: "paste" },
223+
{ role: "selectAll" },
224+
],
225+
},
226+
{
227+
label: "View",
228+
submenu: [{ role: "reload" }, { role: "togglefullscreen" }],
229+
},
230+
{
231+
label: "Updates",
232+
submenu: [
233+
{
234+
label: "Check for updates now",
235+
click: () => {
236+
if (typeof updaterMenuApi.checkNow === "function") {
237+
void updaterMenuApi.checkNow();
238+
} else {
239+
void dialog.showMessageBox({
240+
type: "info",
241+
title: "Updates unavailable",
242+
message: "Updater is not available in development mode.",
243+
});
244+
}
245+
},
246+
},
247+
],
248+
},
249+
];
250+
const menu = Menu.buildFromTemplate(template);
251+
Menu.setApplicationMenu(menu);
252+
}
253+
157254
protocol.registerSchemesAsPrivileged([
158255
{ scheme: "app", privileges: { standard: true, supportFetchAPI: true } },
159256
]);
@@ -240,7 +337,7 @@ app.whenReady().then(() => {
240337
if (process.platform === "win32") {
241338
app.setAppUserModelId("com.sraibaby.app");
242339
}
243-
Menu.setApplicationMenu(null); // We can enable standart app menu by deteng this line
340+
setupAppMenu();
244341
if (!isDev) {
245342
const appPath = app.getAppPath();
246343
const distPath = path.join(appPath, "dist");

0 commit comments

Comments
 (0)