2021-01-21 14:51:52 +00:00
import prettyMilliseconds from 'pretty-ms' ;
2021-02-19 23:06:56 +00:00
const { AppSubUrl , csrf , NotificationSettings , EnableTimetracking } = window . config ;
2021-01-21 14:51:52 +00:00
let updateTimeInterval = null ; // holds setInterval id when active
export async function initStopwatch ( ) {
2021-02-19 23:06:56 +00:00
if ( ! EnableTimetracking ) {
return ;
}
2021-01-21 14:51:52 +00:00
2021-02-19 23:06:56 +00:00
const stopwatchEl = $ ( '.active-stopwatch-trigger' ) ;
2021-04-05 10:45:01 -06:00
if ( ! stopwatchEl . length ) {
return ;
}
2021-01-21 14:51:52 +00:00
stopwatchEl . removeAttr ( 'href' ) ; // intended for noscript mode only
stopwatchEl . popup ( {
position : 'bottom right' ,
hoverable : true ,
} ) ;
// form handlers
$ ( 'form > button' , stopwatchEl ) . on ( 'click' , function ( ) {
$ ( this ) . parent ( ) . trigger ( 'submit' ) ;
} ) ;
2021-02-19 10:05:35 +00:00
if ( NotificationSettings . EventSourceUpdateTime > 0 && ! ! window . EventSource && window . SharedWorker ) {
// Try to connect to the event source via the shared worker first
const worker = new SharedWorker ( ` ${ _ _webpack _public _path _ _ } js/eventsource.sharedworker.js ` , 'notification-worker' ) ;
worker . addEventListener ( 'error' , ( event ) => {
console . error ( event ) ;
} ) ;
worker . port . onmessageerror = ( ) => {
console . error ( 'Unable to deserialize message' ) ;
} ;
worker . port . postMessage ( {
type : 'start' ,
url : ` ${ window . location . origin } ${ AppSubUrl } /user/events ` ,
} ) ;
worker . port . addEventListener ( 'message' , ( event ) => {
if ( ! event . data || ! event . data . type ) {
console . error ( event ) ;
return ;
}
if ( event . data . type === 'stopwatches' ) {
updateStopwatchData ( JSON . parse ( event . data . data ) ) ;
} else if ( event . data . type === 'error' ) {
console . error ( event . data ) ;
} else if ( event . data . type === 'logout' ) {
if ( event . data !== 'here' ) {
return ;
}
worker . port . postMessage ( {
type : 'close' ,
} ) ;
worker . port . close ( ) ;
window . location . href = AppSubUrl ;
2021-04-04 22:37:50 +01:00
} else if ( event . data . type === 'close' ) {
worker . port . postMessage ( {
type : 'close' ,
} ) ;
worker . port . close ( ) ;
2021-02-19 10:05:35 +00:00
}
} ) ;
worker . port . addEventListener ( 'error' , ( e ) => {
console . error ( e ) ;
} ) ;
worker . port . start ( ) ;
window . addEventListener ( 'beforeunload' , ( ) => {
worker . port . postMessage ( {
type : 'close' ,
} ) ;
worker . port . close ( ) ;
} ) ;
return ;
}
if ( NotificationSettings . MinTimeout <= 0 ) {
2021-01-21 14:51:52 +00:00
return ;
}
const fn = ( timeout ) => {
setTimeout ( async ( ) => {
await updateStopwatchWithCallback ( fn , timeout ) ;
} , timeout ) ;
} ;
fn ( NotificationSettings . MinTimeout ) ;
const currSeconds = $ ( '.stopwatch-time' ) . data ( 'seconds' ) ;
if ( currSeconds ) {
updateTimeInterval = updateStopwatchTime ( currSeconds ) ;
}
}
async function updateStopwatchWithCallback ( callback , timeout ) {
const isSet = await updateStopwatch ( ) ;
if ( ! isSet ) {
timeout = NotificationSettings . MinTimeout ;
} else if ( timeout < NotificationSettings . MaxTimeout ) {
timeout += NotificationSettings . TimeoutStep ;
}
callback ( timeout ) ;
}
async function updateStopwatch ( ) {
const data = await $ . ajax ( {
type : 'GET' ,
url : ` ${ AppSubUrl } /api/v1/user/stopwatches ` ,
headers : { 'X-Csrf-Token' : csrf } ,
} ) ;
if ( updateTimeInterval ) {
clearInterval ( updateTimeInterval ) ;
updateTimeInterval = null ;
}
2021-02-19 10:05:35 +00:00
return updateStopwatchData ( data ) ;
}
async function updateStopwatchData ( data ) {
2021-01-21 14:51:52 +00:00
const watch = data [ 0 ] ;
const btnEl = $ ( '.active-stopwatch-trigger' ) ;
if ( ! watch ) {
btnEl . addClass ( 'hidden' ) ;
} else {
const { repo _owner _name , repo _name , issue _index , seconds } = watch ;
const issueUrl = ` ${ AppSubUrl } / ${ repo _owner _name } / ${ repo _name } /issues/ ${ issue _index } ` ;
$ ( '.stopwatch-link' ) . attr ( 'href' , issueUrl ) ;
$ ( '.stopwatch-commit' ) . attr ( 'action' , ` ${ issueUrl } /times/stopwatch/toggle ` ) ;
$ ( '.stopwatch-cancel' ) . attr ( 'action' , ` ${ issueUrl } /times/stopwatch/cancel ` ) ;
$ ( '.stopwatch-issue' ) . text ( ` ${ repo _owner _name } / ${ repo _name } # ${ issue _index } ` ) ;
$ ( '.stopwatch-time' ) . text ( prettyMilliseconds ( seconds * 1000 ) ) ;
updateStopwatchTime ( seconds ) ;
btnEl . removeClass ( 'hidden' ) ;
}
return ! ! data . length ;
}
async function updateStopwatchTime ( seconds ) {
const secs = parseInt ( seconds ) ;
if ( ! Number . isFinite ( secs ) ) return ;
const start = Date . now ( ) ;
updateTimeInterval = setInterval ( ( ) => {
const delta = Date . now ( ) - start ;
const dur = prettyMilliseconds ( secs * 1000 + delta , { compact : true } ) ;
$ ( '.stopwatch-time' ) . text ( dur ) ;
} , 1000 ) ;
}