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/updateToastWindowOptions.test.ts b/electron/updateToastWindowOptions.test.ts deleted file mode 100644 index 64934a84..00000000 --- a/electron/updateToastWindowOptions.test.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { describe, expect, it } from "vitest"; -import { getUpdateToastWindowAppearance } from "./updateToastWindowOptions"; - -describe("update toast window appearance", () => { - it("uses native transparency on macOS", () => { - expect(getUpdateToastWindowAppearance("darwin")).toEqual({ - transparent: true, - backgroundColor: "#00000000", - }); - }); - - it.each(["win32", "linux"] as const)("uses a visible opaque fallback on %s", (platform) => { - expect(getUpdateToastWindowAppearance(platform)).toEqual({ - transparent: false, - backgroundColor: "#101418", - }); - }); -}); diff --git a/electron/updateToastWindowOptions.ts b/electron/updateToastWindowOptions.ts deleted file mode 100644 index b2253f20..00000000 --- a/electron/updateToastWindowOptions.ts +++ /dev/null @@ -1,8 +0,0 @@ -export function getUpdateToastWindowAppearance(platform: NodeJS.Platform) { - const transparent = platform === "darwin"; - - return { - transparent, - backgroundColor: transparent ? "#00000000" : "#101418", - }; -} diff --git a/electron/updater.ts b/electron/updater.ts index 8fb24177..206900f5 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); } @@ -644,6 +648,28 @@ async function showDownloadedUpdateDialog( } } +export function previewNativeUpdateDialog(getMainWindow: () => BrowserWindow | null) { + return showDownloadedUpdateDialog(getMainWindow, DEV_UPDATE_PREVIEW_VERSION, { + isPreview: true, + }); +} + +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 +771,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 +835,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); + } } }); diff --git a/electron/windows.ts b/electron/windows.ts index 7579beaf..47e90b8f 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -12,7 +12,6 @@ import { } from "./hudOverlayBounds"; import { getHudOverlayTaskbarOptions } from "./hudOverlayWindowOptions"; import { getPackagedRendererBaseUrl } from "./rendererServer"; -import { getUpdateToastWindowAppearance } from "./updateToastWindowOptions"; const electronWindowsDir = path.dirname(fileURLToPath(import.meta.url)); const nodeRequire = createRequire(import.meta.url); @@ -690,7 +689,6 @@ export function setHudOverlayRecordingActive(recording: boolean): void { export function createUpdateToastWindow(): BrowserWindow { const initialBounds = getUpdateToastBounds(); - const appearance = getUpdateToastWindowAppearance(process.platform); const win = new BrowserWindow({ width: initialBounds.width, @@ -698,14 +696,14 @@ export function createUpdateToastWindow(): BrowserWindow { x: initialBounds.x, y: initialBounds.y, frame: false, - transparent: appearance.transparent, + transparent: true, resizable: false, alwaysOnTop: true, skipTaskbar: true, hasShadow: false, show: false, focusable: true, - backgroundColor: appearance.backgroundColor, + backgroundColor: "#00000000", webPreferences: { preload: path.join(electronWindowsDir, "preload.mjs"), nodeIntegration: false,