2017-11-28 20:47:41 +02:00
const notifier = require ( 'node-notifier' ) ;
2019-10-02 20:21:42 +02:00
const { bridge } = require ( 'electron' ) . remote . require ( './bridge' ) ;
2017-11-28 20:47:41 +02:00
2017-11-28 00:50:46 +02:00
class AlarmServiceDriverNode {
2017-11-28 20:47:41 +02:00
constructor ( options ) {
// Note: appName is required to get the notification to work. It must be the same as the appId defined in package.json
// https://github.com/mikaelbr/node-notifier/issues/144#issuecomment-319324058
this . appName _ = options . appName ;
2017-11-28 02:22:38 +02:00
this . notifications _ = { } ;
2019-10-02 20:21:42 +02:00
this . service _ = null ;
}
setService ( s ) {
this . service _ = s ;
}
logger ( ) {
return this . service _ . logger ( ) ;
2017-11-28 02:22:38 +02:00
}
hasPersistentNotifications ( ) {
return false ;
}
notificationIsSet ( id ) {
return id in this . notifications _ ;
}
2017-11-28 00:50:46 +02:00
async clearNotification ( id ) {
2017-11-28 02:22:38 +02:00
if ( ! this . notificationIsSet ( id ) ) return ;
clearTimeout ( this . notifications _ [ id ] . timeoutId ) ;
delete this . notifications _ [ id ] ;
2017-11-28 00:50:46 +02:00
}
2019-07-29 15:43:53 +02:00
2017-11-28 00:50:46 +02:00
async scheduleNotification ( notification ) {
2017-11-28 02:22:38 +02:00
const now = Date . now ( ) ;
const interval = notification . date . getTime ( ) - now ;
if ( interval < 0 ) return ;
2017-11-28 00:50:46 +02:00
2018-12-08 01:42:29 +02:00
if ( isNaN ( interval ) ) {
2019-09-19 23:51:18 +02:00
throw new Error ( ` Trying to create a notification from an invalid object: ${ JSON . stringify ( notification ) } ` ) ;
2018-12-08 01:42:29 +02:00
}
2019-10-02 20:21:42 +02:00
this . logger ( ) . info ( ` AlarmServiceDriverNode::scheduleNotification: Notification ${ notification . id } with interval: ${ interval } ms ` ) ;
if ( this . notifications _ [ notification . id ] ) clearTimeout ( this . notifications _ [ notification . id ] . timeoutId ) ;
let timeoutId = null ;
// Note: setTimeout will break for values larger than Number.MAX_VALUE - in which case the timer
// will fire immediately. So instead, if the interval is greater than a set max, reschedule after
// that max interval.
// https://stackoverflow.com/questions/3468607/why-does-settimeout-break-for-large-millisecond-delay-values/3468699
const maxInterval = 60 * 60 * 1000 ;
if ( interval >= maxInterval ) {
this . logger ( ) . info ( ` AlarmServiceDriverNode::scheduleNotification: Notification interval is greater than ${ maxInterval } ms - will reschedule in ${ maxInterval } ms ` ) ;
timeoutId = setTimeout ( ( ) => {
if ( ! this . notifications _ [ notification . id ] ) {
this . logger ( ) . info ( ` AlarmServiceDriverNode::scheduleNotification: Notification ${ notification . id } has been deleted - not rescheduling it ` ) ;
return ;
}
this . scheduleNotification ( this . notifications _ [ notification . id ] ) ;
} , maxInterval ) ;
} else {
timeoutId = setTimeout ( ( ) => {
const o = {
appID : this . appName _ ,
title : notification . title ,
icon : ` ${ bridge ( ) . electronApp ( ) . buildDir ( ) } /icons/512x512.png ` ,
} ;
if ( 'body' in notification ) o . message = notification . body ;
2019-12-18 12:22:01 +02:00
// Message is required on Windows 7 however we don't want to repeat the title so
// make it an empty string.
// https://github.com/laurent22/joplin/issues/2144
if ( ! o . message ) o . message = '-' ;
2019-10-02 20:21:42 +02:00
this . logger ( ) . info ( 'AlarmServiceDriverNode::scheduleNotification: Triggering notification:' , o ) ;
notifier . notify ( o , ( error , response ) => {
this . logger ( ) . info ( 'AlarmServiceDriverNode::scheduleNotification: node-notifier response:' , error , response ) ;
} ) ;
this . clearNotification ( notification . id ) ;
} , interval ) ;
}
2017-11-28 20:47:41 +02:00
this . notifications _ [ notification . id ] = Object . assign ( { } , notification ) ;
this . notifications _ [ notification . id ] . timeoutId = timeoutId ;
2017-11-28 00:50:46 +02:00
}
}
2019-07-29 15:43:53 +02:00
module . exports = AlarmServiceDriverNode ;