@@ -2,7 +2,6 @@ import $ from 'jquery';
22import prettyMilliseconds from 'pretty-ms' ;
33
44const { appSubUrl, csrfToken, notificationSettings, enableTimeTracking} = window . config ;
5- let updateTimeInterval = null ; // holds setInterval id when active
65
76export function initStopwatch ( ) {
87 if ( ! enableTimeTracking ) {
@@ -26,28 +25,48 @@ export function initStopwatch() {
2625 $ ( this ) . parent ( ) . trigger ( 'submit' ) ;
2726 } ) ;
2827
29- if ( notificationSettings . EventSourceUpdateTime > 0 && ! ! window . EventSource && window . SharedWorker ) {
28+ // global stop watch (in the head_navbar), it should always work in any case either the EventSource or the TimerPoller is used.
29+ const currSeconds = $ ( '.stopwatch-time' ) . attr ( 'data-seconds' ) ;
30+ if ( currSeconds ) {
31+ updateStopwatchTime ( currSeconds ) ;
32+ }
33+
34+ let usingPeriodicPoller = false ;
35+ // poll the stopwatch status periodically
36+ const startPeriodicPoller = ( timeout ) => {
37+ if ( timeout <= 0 || ! Number . isFinite ( timeout ) ) return ;
38+ usingPeriodicPoller = true ;
39+ setTimeout ( async ( ) => {
40+ await updateStopwatchWithCallback ( startPeriodicPoller , timeout ) ;
41+ } , timeout ) ;
42+ } ;
43+
44+ // if the browser supports EventSource and SharedWorker, use it instead of the periodic poller
45+ if ( notificationSettings . EventSourceUpdateTime > 0 && window . EventSource && window . SharedWorker ) {
3046 // Try to connect to the event source via the shared worker first
3147 const worker = new SharedWorker ( `${ __webpack_public_path__ } js/eventsource.sharedworker.js` , 'notification-worker' ) ;
3248 worker . addEventListener ( 'error' , ( event ) => {
33- console . error ( event ) ;
49+ console . error ( 'worker error' , event ) ;
3450 } ) ;
3551 worker . port . addEventListener ( 'messageerror' , ( ) => {
36- console . error ( 'Unable to deserialize message' ) ;
52+ console . error ( 'unable to deserialize message' ) ;
3753 } ) ;
3854 worker . port . postMessage ( {
3955 type : 'start' ,
4056 url : `${ window . location . origin } ${ appSubUrl } /user/events` ,
4157 } ) ;
4258 worker . port . addEventListener ( 'message' , ( event ) => {
4359 if ( ! event . data || ! event . data . type ) {
44- console . error ( event ) ;
60+ console . error ( 'unknown worker message event' , event ) ;
4561 return ;
4662 }
4763 if ( event . data . type === 'stopwatches' ) {
4864 updateStopwatchData ( JSON . parse ( event . data . data ) ) ;
65+ } else if ( event . data . type === 'no-event-source' ) {
66+ console . error ( `browser doesn't support EventSource, falling back to periodic poller` ) ;
67+ if ( ! usingPeriodicPoller ) startPeriodicPoller ( notificationSettings . MinTimeout ) ;
4968 } else if ( event . data . type === 'error' ) {
50- console . error ( event . data ) ;
69+ console . error ( 'worker port event error' , event . data ) ;
5170 } else if ( event . data . type === 'logout' ) {
5271 if ( event . data . data !== 'here' ) {
5372 return ;
@@ -65,7 +84,7 @@ export function initStopwatch() {
6584 }
6685 } ) ;
6786 worker . port . addEventListener ( 'error' , ( e ) => {
68- console . error ( e ) ;
87+ console . error ( 'worker port error' , e ) ;
6988 } ) ;
7089 worker . port . start ( ) ;
7190 window . addEventListener ( 'beforeunload' , ( ) => {
@@ -78,22 +97,7 @@ export function initStopwatch() {
7897 return ;
7998 }
8099
81- if ( notificationSettings . MinTimeout <= 0 ) {
82- return ;
83- }
84-
85- const fn = ( timeout ) => {
86- setTimeout ( ( ) => {
87- const _promise = updateStopwatchWithCallback ( fn , timeout ) ;
88- } , timeout ) ;
89- } ;
90-
91- fn ( notificationSettings . MinTimeout ) ;
92-
93- const currSeconds = $ ( '.stopwatch-time' ) . data ( 'seconds' ) ;
94- if ( currSeconds ) {
95- updateTimeInterval = updateStopwatchTime ( currSeconds ) ;
96- }
100+ startPeriodicPoller ( notificationSettings . MinTimeout ) ;
97101}
98102
99103async function updateStopwatchWithCallback ( callback , timeout ) {
@@ -114,23 +118,14 @@ async function updateStopwatch() {
114118 url : `${ appSubUrl } /user/stopwatches` ,
115119 headers : { 'X-Csrf-Token' : csrfToken } ,
116120 } ) ;
117-
118- if ( updateTimeInterval ) {
119- clearInterval ( updateTimeInterval ) ;
120- updateTimeInterval = null ;
121- }
122-
123121 return updateStopwatchData ( data ) ;
124122}
125123
126124function updateStopwatchData ( data ) {
127125 const watch = data [ 0 ] ;
128126 const btnEl = $ ( '.active-stopwatch-trigger' ) ;
129127 if ( ! watch ) {
130- if ( updateTimeInterval ) {
131- clearInterval ( updateTimeInterval ) ;
132- updateTimeInterval = null ;
133- }
128+ clearStopwatchTimer ( ) ;
134129 btnEl . addClass ( 'hidden' ) ;
135130 } else {
136131 const { repo_owner_name, repo_name, issue_index, seconds} = watch ;
@@ -139,22 +134,32 @@ function updateStopwatchData(data) {
139134 $ ( '.stopwatch-commit' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/toggle` ) ;
140135 $ ( '.stopwatch-cancel' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/cancel` ) ;
141136 $ ( '.stopwatch-issue' ) . text ( `${ repo_owner_name } /${ repo_name } #${ issue_index } ` ) ;
142- $ ( '.stopwatch-time' ) . text ( prettyMilliseconds ( seconds * 1000 ) ) ;
143- updateTimeInterval = updateStopwatchTime ( seconds ) ;
137+ updateStopwatchTime ( seconds ) ;
144138 btnEl . removeClass ( 'hidden' ) ;
145139 }
146-
147140 return ! ! data . length ;
148141}
149142
143+ let updateTimeIntervalId = null ; // holds setInterval id when active
144+ function clearStopwatchTimer ( ) {
145+ if ( updateTimeIntervalId !== null ) {
146+ clearInterval ( updateTimeIntervalId ) ;
147+ updateTimeIntervalId = null ;
148+ }
149+ }
150150function updateStopwatchTime ( seconds ) {
151151 const secs = parseInt ( seconds ) ;
152- if ( ! Number . isFinite ( secs ) ) return null ;
153-
152+ if ( ! Number . isFinite ( secs ) ) {
153+ return ;
154+ }
155+ clearStopwatchTimer ( ) ;
156+ const $stopwatch = $ ( '.stopwatch-time' ) ;
154157 const start = Date . now ( ) ;
155- return setInterval ( ( ) => {
158+ const updateUi = ( ) => {
156159 const delta = Date . now ( ) - start ;
157160 const dur = prettyMilliseconds ( secs * 1000 + delta , { compact : true } ) ;
158- $ ( '.stopwatch-time' ) . text ( dur ) ;
159- } , 1000 ) ;
161+ $stopwatch . text ( dur ) ;
162+ } ;
163+ updateUi ( ) ;
164+ updateTimeIntervalId = setInterval ( updateUi , 1000 ) ;
160165}
0 commit comments