2022-01-29 00:00:11 +03:00
import $ from 'jquery' ;
2020-04-24 06:57:38 +03:00
2022-08-23 15:58:04 +03:00
const { appSubUrl , csrfToken , notificationSettings , assetVersionEncoded } = window . config ;
2021-07-17 19:18:10 +03:00
let notificationSequenceNumber = 0 ;
2020-04-24 06:57:38 +03:00
export function initNotificationsTable ( ) {
2021-11-12 15:37:45 +03:00
$ ( '#notification_table .button' ) . on ( 'click' , function ( ) {
( async ( ) => {
const data = await updateNotification (
$ ( this ) . data ( 'url' ) ,
$ ( this ) . data ( 'status' ) ,
$ ( this ) . data ( 'page' ) ,
$ ( this ) . data ( 'q' ) ,
$ ( this ) . data ( 'notification-id' ) ,
) ;
2020-04-24 06:57:38 +03:00
2021-11-12 15:37:45 +03:00
if ( $ ( data ) . data ( 'sequence-number' ) === notificationSequenceNumber ) {
$ ( '#notification_div' ) . replaceWith ( data ) ;
initNotificationsTable ( ) ;
}
await updateNotificationCount ( ) ;
} ) ( ) ;
2020-04-24 06:57:38 +03:00
return false ;
} ) ;
}
2020-07-03 12:55:36 +03:00
async function receiveUpdateCount ( event ) {
try {
const data = JSON . parse ( event . data ) ;
2022-08-03 22:58:27 +03:00
for ( const count of document . querySelectorAll ( '.notification_count' ) ) {
count . classList . toggle ( 'hidden' , data . Count === 0 ) ;
count . textContent = ` ${ data . Count } ` ;
2020-07-03 12:55:36 +03:00
}
await updateNotificationTable ( ) ;
} catch ( error ) {
console . error ( error , event ) ;
}
}
2021-11-09 12:27:25 +03:00
export function initNotificationCount ( ) {
2020-05-08 00:49:00 +03:00
const notificationCount = $ ( '.notification_count' ) ;
if ( ! notificationCount . length ) {
2020-04-24 06:57:38 +03:00
return ;
}
2022-08-03 22:58:27 +03:00
let usingPeriodicPoller = false ;
const startPeriodicPoller = ( timeout , lastCount ) => {
if ( timeout <= 0 || ! Number . isFinite ( timeout ) ) return ;
usingPeriodicPoller = true ;
lastCount = lastCount ? ? notificationCount . text ( ) ;
setTimeout ( async ( ) => {
await updateNotificationCountWithCallback ( startPeriodicPoller , timeout , lastCount ) ;
} , timeout ) ;
} ;
if ( notificationSettings . EventSourceUpdateTime > 0 && window . EventSource && window . SharedWorker ) {
2020-07-03 12:55:36 +03:00
// Try to connect to the event source via the shared worker first
2022-08-23 15:58:04 +03:00
const worker = new SharedWorker ( ` ${ _ _webpack _public _path _ _ } js/eventsource.sharedworker.js?v= ${ assetVersionEncoded } ` , 'notification-worker' ) ;
2020-12-27 17:24:27 +03:00
worker . addEventListener ( 'error' , ( event ) => {
2022-08-03 22:58:27 +03:00
console . error ( 'worker error' , event ) ;
2020-12-27 17:24:27 +03:00
} ) ;
2021-08-17 08:32:48 +03:00
worker . port . addEventListener ( 'messageerror' , ( ) => {
2022-08-03 22:58:27 +03:00
console . error ( 'unable to deserialize message' ) ;
2021-08-17 08:32:48 +03:00
} ) ;
2020-12-27 17:24:27 +03:00
worker . port . postMessage ( {
type : 'start' ,
2021-10-21 10:37:43 +03:00
url : ` ${ window . location . origin } ${ appSubUrl } /user/events ` ,
2020-12-27 17:24:27 +03:00
} ) ;
worker . port . addEventListener ( 'message' , ( event ) => {
if ( ! event . data || ! event . data . type ) {
2022-08-03 22:58:27 +03:00
console . error ( 'unknown worker message event' , event ) ;
2020-12-27 17:24:27 +03:00
return ;
}
if ( event . data . type === 'notification-count' ) {
2021-11-09 12:27:25 +03:00
const _promise = receiveUpdateCount ( event . data ) ;
2022-08-03 22:58:27 +03:00
} else if ( event . data . type === 'no-event-source' ) {
// browser doesn't support EventSource, falling back to periodic poller
if ( ! usingPeriodicPoller ) startPeriodicPoller ( notificationSettings . MinTimeout ) ;
2020-12-27 17:24:27 +03:00
} else if ( event . data . type === 'error' ) {
2022-08-03 22:58:27 +03:00
console . error ( 'worker port event error' , event . data ) ;
2020-12-27 17:24:27 +03:00
} else if ( event . data . type === 'logout' ) {
2021-04-08 02:48:13 +03:00
if ( event . data . data !== 'here' ) {
2020-07-03 12:55:36 +03:00
return ;
}
worker . port . postMessage ( {
type : 'close' ,
} ) ;
worker . port . close ( ) ;
2021-10-21 10:37:43 +03:00
window . location . href = appSubUrl ;
2021-04-05 00:37:50 +03:00
} else if ( event . data . type === 'close' ) {
worker . port . postMessage ( {
type : 'close' ,
} ) ;
worker . port . close ( ) ;
2020-12-27 17:24:27 +03:00
}
} ) ;
worker . port . addEventListener ( 'error' , ( e ) => {
2022-08-03 22:58:27 +03:00
console . error ( 'worker port error' , e ) ;
2020-12-27 17:24:27 +03:00
} ) ;
worker . port . start ( ) ;
window . addEventListener ( 'beforeunload' , ( ) => {
worker . port . postMessage ( {
type : 'close' ,
2020-07-03 12:55:36 +03:00
} ) ;
2020-12-27 17:24:27 +03:00
worker . port . close ( ) ;
} ) ;
2020-04-24 06:57:38 +03:00
2020-12-27 17:24:27 +03:00
return ;
2020-04-24 06:57:38 +03:00
}
2020-05-08 00:49:00 +03:00
2022-08-03 22:58:27 +03:00
startPeriodicPoller ( notificationSettings . MinTimeout ) ;
2020-04-24 06:57:38 +03:00
}
async function updateNotificationCountWithCallback ( callback , timeout , lastCount ) {
const currentCount = $ ( '.notification_count' ) . text ( ) ;
if ( lastCount !== currentCount ) {
2021-10-21 10:37:43 +03:00
callback ( notificationSettings . MinTimeout , currentCount ) ;
2020-04-24 06:57:38 +03:00
return ;
}
const newCount = await updateNotificationCount ( ) ;
let needsUpdate = false ;
if ( lastCount !== newCount ) {
needsUpdate = true ;
2021-10-21 10:37:43 +03:00
timeout = notificationSettings . MinTimeout ;
} else if ( timeout < notificationSettings . MaxTimeout ) {
timeout += notificationSettings . TimeoutStep ;
2020-04-24 06:57:38 +03:00
}
callback ( timeout , newCount ) ;
2020-05-08 00:49:00 +03:00
if ( needsUpdate ) {
await updateNotificationTable ( ) ;
}
}
2020-04-24 06:57:38 +03:00
2020-05-08 00:49:00 +03:00
async function updateNotificationTable ( ) {
2020-04-24 06:57:38 +03:00
const notificationDiv = $ ( '#notification_div' ) ;
2020-05-08 00:49:00 +03:00
if ( notificationDiv . length > 0 ) {
2020-04-24 06:57:38 +03:00
const data = await $ . ajax ( {
type : 'GET' ,
2021-10-21 10:37:43 +03:00
url : ` ${ appSubUrl } /notifications? ${ notificationDiv . data ( 'params' ) } ` ,
2020-04-24 06:57:38 +03:00
data : {
'div-only' : true ,
2021-07-17 19:18:10 +03:00
'sequence-number' : ++ notificationSequenceNumber ,
2020-04-24 06:57:38 +03:00
}
} ) ;
2021-07-17 19:18:10 +03:00
if ( $ ( data ) . data ( 'sequence-number' ) === notificationSequenceNumber ) {
notificationDiv . replaceWith ( data ) ;
initNotificationsTable ( ) ;
}
2020-04-24 06:57:38 +03:00
}
}
async function updateNotificationCount ( ) {
const data = await $ . ajax ( {
type : 'GET' ,
2022-04-07 21:59:56 +03:00
url : ` ${ appSubUrl } /notifications/new ` ,
2020-04-24 06:57:38 +03:00
headers : {
2021-10-21 10:37:43 +03:00
'X-Csrf-Token' : csrfToken ,
2020-04-24 06:57:38 +03:00
} ,
} ) ;
const notificationCount = $ ( '.notification_count' ) ;
if ( data . new === 0 ) {
notificationCount . addClass ( 'hidden' ) ;
} else {
notificationCount . removeClass ( 'hidden' ) ;
}
notificationCount . text ( ` ${ data . new } ` ) ;
return ` ${ data . new } ` ;
}
async function updateNotification ( url , status , page , q , notificationID ) {
if ( status !== 'pinned' ) {
$ ( ` #notification_ ${ notificationID } ` ) . remove ( ) ;
}
return $ . ajax ( {
type : 'POST' ,
url ,
data : {
2021-10-21 10:37:43 +03:00
_csrf : csrfToken ,
2020-04-24 06:57:38 +03:00
notification _id : notificationID ,
status ,
page ,
q ,
noredirect : true ,
2021-07-17 19:18:10 +03:00
'sequence-number' : ++ notificationSequenceNumber ,
2020-04-24 06:57:38 +03:00
} ,
} ) ;
}