diff --git a/electron/main.ts b/electron/main.ts index eb640251..3514c1eb 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -39,6 +39,7 @@ import { getUpdaterLogPath, getUpdateStatusSummary, installDownloadedUpdateNow, + previewNativeUpdateDialog, previewUpdateToast, setExperimentalUpdatesEnabled, setupAutoUpdates, @@ -592,6 +593,10 @@ function syncDockIcon() { } function sendUpdateToastToWindows(channel: "update-toast-state", payload: unknown) { + if (process.platform !== "darwin") { + return false; + } + if (!payload) { const existingWindow = getUpdateToastWindow(); if (existingWindow) { @@ -683,7 +688,12 @@ ipcMain.handle("set-experimental-updates-enabled", async (_event, enabled: unkno } }); -ipcMain.handle("preview-update-toast", () => { +ipcMain.handle("preview-update-toast", async () => { + if (process.platform !== "darwin") { + await previewNativeUpdateDialog(getUpdateDialogWindow); + return { success: true }; + } + return { success: previewUpdateToast(sendUpdateToastToWindows) }; }); @@ -1035,7 +1045,12 @@ app.whenReady().then(async () => { setupAutoUpdates(getUpdateDialogWindow, sendUpdateToastToWindows); if (IS_DEV && process.env.RECORDLY_DEV_PREVIEW_UPDATE === "1") { setTimeout(() => { - previewUpdateToast(sendUpdateToastToWindows); + if (process.platform === "darwin") { + previewUpdateToast(sendUpdateToastToWindows); + return; + } + + void previewNativeUpdateDialog(getUpdateDialogWindow); }, 750); } diff --git a/electron/updater.ts b/electron/updater.ts index 8fb24177..86c2d76d 100644 --- a/electron/updater.ts +++ b/electron/updater.ts @@ -173,6 +173,10 @@ function showMessageBox( getMainWindow: () => BrowserWindow | null, options: MessageBoxOptions, ): Promise { + if (process.platform !== "darwin") { + return dialog.showMessageBox(options); + } + const window = getDialogWindow(getMainWindow); return window ? dialog.showMessageBox(window, options) : dialog.showMessageBox(options); } @@ -576,12 +580,19 @@ async function showAvailableUpdateDialog( getMainWindow: () => BrowserWindow | null, version: string, sendToRenderer?: UpdateToastSender, + options?: { isPreview?: boolean; isExperimental?: boolean }, ) { + const isPreview = Boolean(options?.isPreview); + const isExperimental = options?.isExperimental ?? getExperimentalUpdatesEnabled(); const result = await showMessageBox(getMainWindow, { type: "info", - title: "Update Available", - message: `Recordly ${version} is available.`, - detail: "Install and restart now, or remind me later.", + title: isExperimental ? "Experimental Update Available" : "Update Available", + message: `Recordly ${version} is available${isExperimental ? " on the experimental channel" : ""}.`, + detail: isPreview + ? `${isExperimental ? EXPERIMENTAL_UPDATE_DESCRIPTION : "This is a development preview of the standard update flow."} No real update will be installed.` + : isExperimental + ? EXPERIMENTAL_UPDATE_DESCRIPTION + : "Install and restart now, or remind me later.", buttons: ["Install & Restart", "Later"], defaultId: 0, cancelId: 1, @@ -589,10 +600,24 @@ async function showAvailableUpdateDialog( }); if (result.response === 0) { + if (isPreview) { + await showMessageBox(getMainWindow, { + type: "info", + title: "Preview Only", + message: "No real update was installed.", + detail: "This was only a manual development preview of the update prompt.", + }); + return; + } + await downloadAvailableUpdate(sendToRenderer, { installAfterDownload: true }); return; } + if (isPreview) { + return; + } + deferUpdateReminder(getMainWindow, sendToRenderer, UPDATE_REMINDER_DELAY_MS); } @@ -644,6 +669,29 @@ async function showDownloadedUpdateDialog( } } +export function previewNativeUpdateDialog(getMainWindow: () => BrowserWindow | null) { + return showAvailableUpdateDialog(getMainWindow, DEV_UPDATE_PREVIEW_VERSION, undefined, { + isPreview: true, + isExperimental: DEV_UPDATE_PREVIEW_IS_EXPERIMENTAL, + }); +} + +async function showUpdateErrorDialog( + getMainWindow: () => BrowserWindow | null, + version: string, + error: unknown, +) { + await showMessageBox(getMainWindow, { + type: "error", + title: "Update Failed", + message: `Recordly ${version} could not be downloaded.`, + detail: String(error), + buttons: ["OK"], + defaultId: 0, + noLink: true, + }); +} + export async function checkForAppUpdates( getMainWindow: () => BrowserWindow | null, options?: { manual?: boolean }, @@ -745,10 +793,8 @@ export function setupAutoUpdates( return; } - if (manualCheckRequested) { - void showAvailableUpdateDialog(getMainWindow, info.version, sendToRenderer); - manualCheckRequested = false; - } + void showAvailableUpdateDialog(getMainWindow, info.version, sendToRenderer); + manualCheckRequested = false; }); autoUpdater.on("update-not-available", () => { @@ -811,10 +857,13 @@ export function setupAutoUpdates( downloadInProgress = false; downloadToastDismissed = false; installAfterDownloadRequested = false; - emitUpdateToastState( + const shownInRenderer = emitUpdateToastState( sendToRenderer, createUpdateErrorToastPayload(availableVersion, error), ); + if (!shownInRenderer) { + void showUpdateErrorDialog(getMainWindow, availableVersion, error); + } } });