@@ -2,7 +2,6 @@ import $ from 'jquery';
2
2
import prettyMilliseconds from 'pretty-ms' ;
3
3
4
4
const { appSubUrl, csrfToken, notificationSettings, enableTimeTracking} = window . config ;
5
- let updateTimeInterval = null ; // holds setInterval id when active
6
5
7
6
export function initStopwatch ( ) {
8
7
if ( ! enableTimeTracking ) {
@@ -26,28 +25,45 @@ export function initStopwatch() {
26
25
$ ( this ) . parent ( ) . trigger ( 'submit' ) ;
27
26
} ) ;
28
27
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 ) {
30
43
// Try to connect to the event source via the shared worker first
31
44
const worker = new SharedWorker ( `${ __webpack_public_path__ } js/eventsource.sharedworker.js` , 'notification-worker' ) ;
32
45
worker . addEventListener ( 'error' , ( event ) => {
33
- console . error ( event ) ;
46
+ console . error ( 'worker error' , event ) ;
34
47
} ) ;
35
48
worker . port . addEventListener ( 'messageerror' , ( ) => {
36
- console . error ( 'Unable to deserialize message' ) ;
49
+ console . error ( 'unable to deserialize message' ) ;
37
50
} ) ;
38
51
worker . port . postMessage ( {
39
52
type : 'start' ,
40
53
url : `${ window . location . origin } ${ appSubUrl } /user/events` ,
41
54
} ) ;
42
55
worker . port . addEventListener ( 'message' , ( event ) => {
43
56
if ( ! event . data || ! event . data . type ) {
44
- console . error ( event ) ;
57
+ console . error ( 'unknown worker message event' , event ) ;
45
58
return ;
46
59
}
47
60
if ( event . data . type === 'stopwatches' ) {
48
61
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 ) ;
49
65
} else if ( event . data . type === 'error' ) {
50
- console . error ( event . data ) ;
66
+ console . error ( 'worker port event error' , event . data ) ;
51
67
} else if ( event . data . type === 'logout' ) {
52
68
if ( event . data . data !== 'here' ) {
53
69
return ;
@@ -65,7 +81,7 @@ export function initStopwatch() {
65
81
}
66
82
} ) ;
67
83
worker . port . addEventListener ( 'error' , ( e ) => {
68
- console . error ( e ) ;
84
+ console . error ( 'worker port error' , e ) ;
69
85
} ) ;
70
86
worker . port . start ( ) ;
71
87
window . addEventListener ( 'beforeunload' , ( ) => {
@@ -78,22 +94,7 @@ export function initStopwatch() {
78
94
return ;
79
95
}
80
96
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 ) ;
97
98
}
98
99
99
100
async function updateStopwatchWithCallback ( callback , timeout ) {
@@ -114,23 +115,14 @@ async function updateStopwatch() {
114
115
url : `${ appSubUrl } /user/stopwatches` ,
115
116
headers : { 'X-Csrf-Token' : csrfToken } ,
116
117
} ) ;
117
-
118
- if ( updateTimeInterval ) {
119
- clearInterval ( updateTimeInterval ) ;
120
- updateTimeInterval = null ;
121
- }
122
-
123
118
return updateStopwatchData ( data ) ;
124
119
}
125
120
126
121
function updateStopwatchData ( data ) {
127
122
const watch = data [ 0 ] ;
128
123
const btnEl = $ ( '.active-stopwatch-trigger' ) ;
129
124
if ( ! watch ) {
130
- if ( updateTimeInterval ) {
131
- clearInterval ( updateTimeInterval ) ;
132
- updateTimeInterval = null ;
133
- }
125
+ clearStopwatchTimer ( ) ;
134
126
btnEl . addClass ( 'hidden' ) ;
135
127
} else {
136
128
const { repo_owner_name, repo_name, issue_index, seconds} = watch ;
@@ -139,22 +131,31 @@ function updateStopwatchData(data) {
139
131
$ ( '.stopwatch-commit' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/toggle` ) ;
140
132
$ ( '.stopwatch-cancel' ) . attr ( 'action' , `${ issueUrl } /times/stopwatch/cancel` ) ;
141
133
$ ( '.stopwatch-issue' ) . text ( `${ repo_owner_name } /${ repo_name } #${ issue_index } ` ) ;
142
- $ ( '.stopwatch-time' ) . text ( prettyMilliseconds ( seconds * 1000 ) ) ;
143
134
updateStopwatchTime ( seconds ) ;
144
135
btnEl . removeClass ( 'hidden' ) ;
145
136
}
146
-
147
137
return ! ! data . length ;
148
138
}
149
139
140
+ let updateTimeIntervalId = null ; // holds setInterval id when active
141
+ function clearStopwatchTimer ( ) {
142
+ if ( updateTimeIntervalId !== null ) {
143
+ clearInterval ( updateTimeIntervalId ) ;
144
+ updateTimeIntervalId = null ;
145
+ }
146
+ }
150
147
function updateStopwatchTime ( seconds ) {
151
148
const secs = parseInt ( seconds ) ;
152
149
if ( ! Number . isFinite ( secs ) ) return ;
153
150
151
+ clearStopwatchTimer ( ) ;
152
+ const $stopwatch = $ ( '.stopwatch-time' ) ;
154
153
const start = Date . now ( ) ;
155
- updateTimeInterval = setInterval ( ( ) => {
154
+ const updateUi = ( ) => {
156
155
const delta = Date . now ( ) - start ;
157
156
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 ) ;
160
161
}
0 commit comments