Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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?
Expand Down
9 changes: 7 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@ function initUpdater(opts: ReturnType<typeof validateInput>) {
*
* @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.',
Expand All @@ -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;

Expand All @@ -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);
});
};
}
Expand Down
15 changes: 15 additions & 0 deletions test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand Down
Loading