From 00220b9b812719437bf19237f952a620b4d35860 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 28 Jun 2026 04:34:05 +0000 Subject: [PATCH] feat: surface the dialog response from makeUserNotifier The function returned by makeUserNotifier now accepts an optional callback that receives the index of the button the user clicked (0 = restart, 1 = later), letting callers react when the user chooses "Later". Closes #194 Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Qoymwe8fe4vauwoGPtTzwq --- README.md | 23 +++++++++++++++++++++++ src/index.ts | 9 +++++++-- test/index.test.ts | 15 +++++++++++++++ 3 files changed, 45 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5d0b08b..afdeac4 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,29 @@ Additional Options: - `notifyUser` Boolean (optional) - Defaults to `true`. When enabled the user will be prompted to apply the update immediately after download. +### `makeUserNotifier(dialogProps)` + +Returns the default notifier callback used when `notifyUser` is `true`. The +returned function accepts an optional second argument, `callback(response)`, +which is invoked with the index of the dialog button the user clicked +(`0` = restart, `1` = later). This lets you react when the user chooses +"Later" — for example, to surface your own "restart now" UI: + +```js +const { makeUserNotifier, updateElectronApp } = require('update-electron-app') + +const notifier = makeUserNotifier() +updateElectronApp({ + onNotifyUser: (info) => { + notifier(info, (response) => { + if (response === 1) { + // user clicked "Later" + } + }) + }, +}) +``` + ## FAQ ### What kinds of assets do I need to build? diff --git a/src/index.ts b/src/index.ts index b06003b..7e97df0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -254,7 +254,9 @@ function initUpdater(opts: ReturnType) { * * @param dialogProps - Text to display in the dialog. */ -export function makeUserNotifier(dialogProps?: IUpdateDialogStrings): (info: IUpdateInfo) => void { +export function makeUserNotifier( + dialogProps?: IUpdateDialogStrings, +): (info: IUpdateInfo, callback?: (response: number) => void) => void { const defaultDialogMessages = { title: 'Application Update', detail: 'A new version has been downloaded. Restart the application to apply the updates.', @@ -264,7 +266,7 @@ export function makeUserNotifier(dialogProps?: IUpdateDialogStrings): (info: IUp const assignedDialog = Object.assign({}, defaultDialogMessages, dialogProps); - return (info: IUpdateInfo) => { + return (info: IUpdateInfo, callback?: (response: number) => void) => { const { releaseNotes, releaseName } = info; const { title, restartButtonText, laterButtonText, detail } = assignedDialog; @@ -280,6 +282,9 @@ export function makeUserNotifier(dialogProps?: IUpdateDialogStrings): (info: IUp if (response === 0) { autoUpdater.quitAndInstall(); } + // forward the clicked button index (0 = restart, 1 = later) so callers + // can react to the user choosing "Later" + callback?.(response); }); }; } diff --git a/test/index.test.ts b/test/index.test.ts index 7663419..4af3f31 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -142,6 +142,21 @@ describe('makeUserNotifier', () => { expect(autoUpdater.quitAndInstall).toHaveBeenCalledTimes(called); }); }); + + it.each([0, 1])('forwards the response index %i to the optional callback', async (response) => { + jest + .mocked(dialog.showMessageBox) + .mockResolvedValueOnce({ response, checkboxChecked: false }); + const callback = jest.fn(); + const notifier = makeUserNotifier(); + notifier(fakeUpdateInfo, callback); + + // the callback runs once the showMessageBox promise resolves; flush the + // microtask queue (timers are faked, so we can't rely on setImmediate) + await Promise.resolve(); + await Promise.resolve(); + expect(callback).toHaveBeenCalledWith(response); + }); }); it('can customize dialog properties', () => {