Skip to content

Commit 0d02978

Browse files
committed
feat: -persistent flag for win10/11 notifications keeps them on-screen until dismissed
1 parent 55327ba commit 0d02978

File tree

1 file changed

+50
-14
lines changed

1 file changed

+50
-14
lines changed

lib/utils.js

+50-14
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ const inArray = function (arr, val) {
2828
return arr.indexOf(val) !== -1;
2929
};
3030

31+
/*
32+
notifySend Flags
33+
*/
34+
3135
const notifySendFlags = {
3236
u: 'urgency',
3337
urgency: 'urgency',
@@ -81,6 +85,7 @@ module.exports.fileCommandJson = function (notifier, options, cb) {
8185
console.info('[notifier path]', notifier);
8286
console.info('[notifier options]', options.join(' '));
8387
}
88+
8489
return cp.execFile(notifier, options, function (error, stdout, stderr) {
8590
if (error) return cb(error, stdout);
8691
if (!stdout) return cb(error, {});
@@ -161,16 +166,19 @@ module.exports.mapToNotifySend = function (options) {
161166
if (options.timeout === false) {
162167
delete options.timeout;
163168
}
169+
164170
if (options.wait === true) {
165171
options['expire-time'] = 5; // 5 seconds default time (multipled below)
166172
}
173+
167174
for (const key in options) {
168175
if (key === 'message' || key === 'title') continue;
169176
if (options.hasOwnProperty(key) && notifySendFlags[key] !== key) {
170177
options[notifySendFlags[key]] = options[key];
171178
delete options[key];
172179
}
173180
}
181+
174182
if (typeof options['expire-time'] === 'undefined') {
175183
options['expire-time'] = 10 * 1000; // 10 sec timeout by default
176184
} else if (typeof options['expire-time'] === 'number') {
@@ -215,10 +223,19 @@ module.exports.mapToMac = function (options) {
215223
options.sound = 'Bottle';
216224
}
217225

226+
/*
227+
wait : Wait with callback, until user action is taken against notification,
228+
does not apply to Windows Toasters as they always wait or notify-send
229+
as it does not support the wait option
230+
231+
timeout : Takes precedence over wait if both are defined.
232+
*/
233+
218234
if (options.wait === true) {
219235
if (!options.timeout) {
220236
options.timeout = 5;
221237
}
238+
222239
delete options.wait;
223240
}
224241

@@ -325,20 +342,31 @@ function removeNewLines(str) {
325342
}
326343

327344
/*
328-
---- Options ----
329-
[-t] <title string> | Displayed on the first line of the toast.
330-
[-m] <message string> | Displayed on the remaining lines, wrapped.
331-
[-b] <button1;button2 string>| Displayed on the bottom line, can list multiple buttons separated by ";"
332-
[-tb] | Displayed a textbox on the bottom line, only if buttons are not presented.
333-
[-p] <image URI> | Display toast with an image, local files only.
334-
[-id] <id> | sets the id for a notification to be able to close it later.
335-
[-s] <sound URI> | Sets the sound of the notifications, for possible values see http://msdn.microsoft.com/en-us/library/windows/apps/hh761492.aspx.
336-
[-silent] | Don't play a sound file when showing the notifications.
337-
[-appID] <App.ID> | Don't create a shortcut but use the provided app id.
338-
[-pid] <pid> | Query the appid for the process <pid>, use -appID as fallback. (Only relevant for applications that might be packaged for the store)
339-
[-pipeName] <\.\pipe\pipeName\> | Provide a name pipe which is used for callbacks.
340-
[-application] <C:\foo.exe> | Provide a application that might be started if the pipe does not exist.
341-
-close <id> | Closes a currently displayed notification.
345+
Ntfy Toast / Toaster
346+
347+
Windows 10 & 11 use ntfy-toast library to send notifications:
348+
https://github.com/Aetherinox/ntfy-toast
349+
350+
ntfy-toast has a special parameter for ensuring that notifications stick and do dismiss
351+
unless the user physically dismisses them by using:
352+
-persistent
353+
354+
---- Options ----
355+
[-t] <title string> | Displayed on the first line of the toast.
356+
[-m] <message string> | Displayed on the remaining lines, wrapped.
357+
[-b] <button1;button2 string> | Displayed on the bottom line, can list multiple buttons separated by ";"
358+
[-tb] | Displayed a textbox on the bottom line, only if buttons are not presented.
359+
[-p] <image URI> | Display toast with an image, local files only.
360+
[-id] <id> | sets the id for a notification to be able to close it later.
361+
[-s] <sound URI> | Sets the sound of the notifications, for possible values see http://msdn.microsoft.com/en-us/library/windows/apps/hh761492.aspx.
362+
[-silent] | Don't play a sound file when showing the notifications.
363+
[-persistent] | Makes the notification stick until the user dismisses it.
364+
[-d] (short | long) | Set the duration default is "short" 7s, "long" is 25s.
365+
[-appID] <App.ID> | Don't create a shortcut but use the provided app id.
366+
[-pid] <pid> | Query the appid for the process <pid>, use -appID as fallback. (Only relevant for applications that might be packaged for the store)
367+
[-pipeName] <\.\pipe\pipeName\> | Provide a name pipe which is used for callbacks.
368+
[-application] <C:\foo.exe> | Provide a application that might be started if the pipe does not exist.
369+
-close <id> | Closes a currently displayed notification.
342370
*/
343371
const allowedToasterFlags = [
344372
't',
@@ -348,13 +376,16 @@ const allowedToasterFlags = [
348376
'p',
349377
'id',
350378
's',
379+
'd',
351380
'silent',
381+
'persistent',
352382
'appID',
353383
'pid',
354384
'pipeName',
355385
'close',
356386
'install'
357387
];
388+
358389
const toasterSoundPrefix = 'Notification.';
359390
const toasterDefaultSound = 'Notification.Default';
360391
module.exports.mapToWin8 = function (options) {
@@ -402,6 +433,11 @@ module.exports.mapToWin8 = function (options) {
402433
delete options.sound;
403434
}
404435

436+
if (options.wait === true) {
437+
options.persistent = true;
438+
delete options.wait;
439+
}
440+
405441
if (options.s === false) {
406442
options.silent = true;
407443
delete options.s;

0 commit comments

Comments
 (0)