@@ -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,45 @@ 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 PeriodicPoller is used.
29+ const currSeconds = $ ( '.stopwatch-time' ) . attr ( 'data-seconds' ) ;
30+ if ( currSeconds ) {
31+ updateStopwatchTime ( currSeconds ) ;
32+ }
33+
34+ let usingPeriodicPoller = false ;
35+ const startPeriodicPoller = ( timeout ) => {
36+ if ( timeout <= 0 || ! Number . isFinite ( timeout ) ) return ;
37+ usingPeriodicPoller = true ;
38+ setTimeout ( ( ) => updateStopwatchWithCallback ( startPeriodicPoller , timeout ) , timeout ) ;
39+ } ;
40+
41+ // if the browser supports EventSource and SharedWorker, use it instead of the periodic poller
42+ if ( notificationSettings . EventSourceUpdateTime > 0 && window . EventSource && window . SharedWorker ) {
3043 // Try to connect to the event source via the shared worker first
3144 const worker = new SharedWorker ( `${ __webpack_public_path__ } js/eventsource.sharedworker.js` , 'notification-worker' ) ;
3245 worker . addEventListener ( 'error' , ( event ) => {
33- console . error ( event ) ;
46+ console . error ( 'worker error' , event ) ;
3447 } ) ;
3548 worker . port . addEventListener ( 'messageerror' , ( ) => {
36- console . error ( 'Unable to deserialize message' ) ;
49+ console . error ( 'unable to deserialize message' ) ;
3750 } ) ;
3851 worker . port . postMessage ( {
3952 type : 'start' ,
4053 url : `${ window . location . origin } ${ appSubUrl } /user/events` ,
4154 } ) ;
4255 worker . port . addEventListener ( 'message' , ( event ) => {
4356 if ( ! event . data || ! event . data . type ) {
44- console . error ( event ) ;
57+ console . error ( 'unknown worker message event' , event ) ;
4558 return ;
4659 }
4760 if ( event . data . type === 'stopwatches' ) {
4861 updateStopwatchData ( JSON . parse ( event . data . data ) ) ;
62+ } else if ( event . data . type === 'no-event-source' ) {
63+ // browser doesn't support EventSource, falling back to periodic poller
64+ if ( ! usingPeriodicPoller ) startPeriodicPoller ( notificationSettings . MinTimeout ) ;
4965 } else if ( event . data . type === 'error' ) {
50- console . error ( event . data ) ;
66+ console . error ( 'worker port event error' , event . data ) ;
5167 } else if ( event . data . type === 'logout' ) {
5268 if ( event . data . data !== 'here' ) {
5369 return ;
@@ -65,7 +81,7 @@ export function initStopwatch() {
6581 }
6682 } ) ;
6783 worker . port . addEventListener ( 'error' , ( e ) => {
68- console . error ( e ) ;
84+ console . error ( 'worker port error' , e ) ;
6985 } ) ;
7086 worker . port . start ( ) ;
7187 window . addEventListener ( 'beforeunload' , ( ) => {
@@ -78,22 +94,7 @@ export function initStopwatch() {
7894 return ;
7995 }
8096
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- }
97+ startPeriodicPoller ( notificationSettings . MinTimeout ) ;
9798}
9899
99100async function updateStopwatchWithCallback ( callback , timeout ) {
@@ -114,23 +115,14 @@ async function updateStopwatch() {
114115 url : `${ appSubUrl } /user/stopwatches` ,
115116 headers : { 'X-Csrf-Token' : csrfToken } ,
116117 } ) ;
117-
118- if ( updateTimeInterval ) {
119- clearInterval ( updateTimeInterval ) ;
120- updateTimeInterval = null ;
121- }
122-
123118 return updateStopwatchData ( data ) ;
124119}
125120
126121function updateStopwatchData ( data ) {
127122 const watch = data [ 0 ] ;
128123 const btnEl = $ ( '.active-stopwatch-trigger' ) ;
129124 if ( ! watch ) {
130- if ( updateTimeInterval ) {
131- clearInterval ( updateTimeInterval ) ;
132- updateTimeInterval = null ;
133- }
125+ clearStopwatchTimer ( ) ;
134126 btnEl . addClass ( 'hidden' ) ;
135127 } else {
136128 const { repo_owner_name, repo_name, issue_index, seconds} = watch ;
@@ -139,22 +131,31 @@ function updateStopwatchData(data) {
139131 $ ( '.stopwatch-commit' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/toggle` ) ;
140132 $ ( '.stopwatch-cancel' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/cancel` ) ;
141133 $ ( '.stopwatch-issue' ) . text ( `${ repo_owner_name } /${ repo_name } #${ issue_index } ` ) ;
142- $ ( '.stopwatch-time' ) . text ( prettyMilliseconds ( seconds * 1000 ) ) ;
143134 updateStopwatchTime ( seconds ) ;
144135 btnEl . removeClass ( 'hidden' ) ;
145136 }
146-
147137 return ! ! data . length ;
148138}
149139
140+ let updateTimeIntervalId = null ; // holds setInterval id when active
141+ function clearStopwatchTimer ( ) {
142+ if ( updateTimeIntervalId !== null ) {
143+ clearInterval ( updateTimeIntervalId ) ;
144+ updateTimeIntervalId = null ;
145+ }
146+ }
150147function updateStopwatchTime ( seconds ) {
151148 const secs = parseInt ( seconds ) ;
152149 if ( ! Number . isFinite ( secs ) ) return ;
153150
151+ clearStopwatchTimer ( ) ;
152+ const $stopwatch = $ ( '.stopwatch-time' ) ;
154153 const start = Date . now ( ) ;
155- updateTimeInterval = setInterval ( ( ) => {
154+ const updateUi = ( ) => {
156155 const delta = Date . now ( ) - start ;
157156 const dur = prettyMilliseconds ( secs * 1000 + delta , { compact : true } ) ;
158- $ ( '.stopwatch-time' ) . text ( dur ) ;
159- } , 1000 ) ;
157+ $stopwatch . text ( dur ) ;
158+ } ;
159+ updateUi ( ) ;
160+ updateTimeIntervalId = setInterval ( updateUi , 1000 ) ;
160161}
0 commit comments