1
1
/*
2
- * Entry point for the watch app
2
+ * Terminology:
3
+ * 1 Session is made up for 4 Sets
4
+ * 1 Set is made up of 2 Sprints
5
+ * Each Sprint is either a Flow Sprint of a Break Sprint
3
6
*/
4
7
import document from "document" ;
5
8
import * as messaging from "messaging" ;
@@ -11,33 +14,35 @@ clock.granularity = "minutes";
11
14
import { preferences } from "user-settings" ;
12
15
import { vibration } from "haptics" ;
13
16
import { style , stopStyle } from "./style.js"
17
+ import { format } from "path" ;
14
18
15
19
//grab screen elements
16
20
const time = document . getElementById ( "time" ) ;
17
21
const progressArc = document . getElementById ( "progressArc" ) ;
18
- const countdown = document . getElementById ( "countdown" ) ;
19
- const sprintCounter = document . getElementById ( "sprintCounter " ) ;
20
- const currentIntervalText = document . getElementById ( "currentIntervalText " ) ;
22
+ const countdownText = document . getElementById ( "countdown" ) ;
23
+ const setCounter = document . getElementById ( "setCounter " ) ;
24
+ const currentSprintText = document . getElementById ( "currentSprintText " ) ;
21
25
const playPauseButton = document . getElementById ( "playPauseButton" ) ;
22
26
const playPauseIcon = playPauseButton . getElementById ( "combo-button-icon" ) ;
23
27
const playPauseIconPressed = playPauseButton . getElementById ( "combo-button-icon-press" ) ;
24
28
const restartSkipButton = document . getElementById ( "restartSkipButton" ) ;
25
29
const restartSkipIcon = restartSkipButton . getElementById ( "combo-button-icon" ) ;
26
30
27
-
28
31
//Default these incase they haven't setup custom times on mobile app
29
- const totalFlowInSeconds = 1500 ;
32
+ const totalFlowInSeconds = 5 ; // 1500;
30
33
const totalShortBreakInSeconds = 10 ; //300;
31
34
const totalLongBreakInSeconds = 15 ; //900;
32
- const totalSprints = 4 ;
35
+ const totalSets = 4 ;
33
36
const flowText = "Flow" ;
34
37
const breakText = "Break" ;
35
38
36
- let counting = false ;
37
- let countdownSeconds = totalFlowInSeconds ;
39
+ let paused = true ;
38
40
let flow = true ; //used to toggle between flow intervals and breaks
39
- let currentIntervalTime ;
40
- let currentSprint = 1 ;
41
+ let currentSprintTotalTime ;
42
+ let currentSet = 1 ;
43
+ let deadlineInSeconds ;
44
+ let timeLeft = totalFlowInSeconds ;
45
+ var countdown ;
41
46
42
47
//setup clock
43
48
clock . ontick = ( evt ) => {
@@ -52,31 +57,27 @@ clock.ontick = (evt) => {
52
57
}
53
58
54
59
setupWithUserSettings ( ) ;
55
- style ( display ) ;
56
- //clock.tick does not run in background so use setInterval instead
57
- setInterval ( ( ) => progress ( ) , 1000 )
60
+ style ( ) ;
61
+ progress ( ) ;
62
+
58
63
playPauseButton . onactivate = ( evt ) => {
59
- counting ? pause ( ) : play ( ) ;
64
+ paused ? play ( ) : pause ( ) ;
60
65
}
61
-
62
66
restartSkipButton . onactivate = ( evt ) => {
63
- counting ? restart ( ) : skip ( ) ;
67
+ paused ? skip ( ) : restart ( ) ;
64
68
}
65
-
66
69
display . onchange = ( ) => { // optimize battery life
67
70
display . on ? style ( ) : stopStyle ( ) ;
68
71
}
69
-
70
72
messaging . peerSocket . onmessage = ( evt ) => {
71
73
//persist
72
74
writeToFile ( evt . data , "flowSettings.txt" ) ;
73
75
setupWithUserSettings ( ) ;
74
76
}
75
-
76
77
me . onunload = ( ) => {
77
78
//save data on exit
78
79
let text = flow ? flowText : breakText ;
79
- writeToFile ( { closeTime : Date . now ( ) , timeLeft : countdownSeconds , text : text , state : currentIntervalTime , flow : flow , sprint : currentSprint , counting : counting } , "saveState.txt" ) ;
80
+ writeToFile ( { deadlineInSeconds : deadlineInSeconds , timeLeft : timeLeft , state : currentSprintTotalTime , flow : flow , set : currentSet , paused : paused } , "saveState.txt" ) ;
80
81
}
81
82
82
83
@@ -92,26 +93,27 @@ function writeToFile(data, fileName){
92
93
93
94
function secondsToAngle ( seconds ) {
94
95
//degree per second * elapsedseconds
95
- return ( 360 / currentIntervalTime ) * seconds ;
96
+ return ( 360 / currentSprintTotalTime ) * seconds ;
96
97
}
97
98
98
99
function progress ( ) {
99
- if ( counting ) {
100
- if ( ! isSprintOver ( countdownSeconds ) ) {
101
- countdownSeconds -- ;
102
- }
100
+ if ( ! isSprintOver ( deadlineInSeconds ) ) {
101
+ let t = calculateRemainingTimeInSeconds ( deadlineInSeconds ) ;
103
102
if ( display . on ) {
103
+ formatCountdown ( t ) ;
104
104
//calculate and update angle
105
- progressArc . sweepAngle = secondsToAngle ( currentIntervalTime - countdownSeconds ) ;
105
+ progressArc . sweepAngle = secondsToAngle ( currentSprintTotalTime - t ) ;
106
106
}
107
107
}
108
- if ( display . on ) {
109
- formatCountdown ( countdownSeconds ) ;
110
- }
111
108
}
112
109
113
- function isSprintOver ( seconds ) {
114
- if ( seconds === 0 ) {
110
+ function calculateRemainingTimeInSeconds ( deadlineInSeconds ) {
111
+ let t = deadlineInSeconds - ( Date . now ( ) / 1000 ) ;
112
+ return t ;
113
+ }
114
+
115
+ function isSprintOver ( deadlineInSeconds ) {
116
+ if ( Date . now ( ) / 1000 >= deadlineInSeconds ) {
115
117
pause ( ) ;
116
118
nextSprint ( ) ;
117
119
return true ;
@@ -124,25 +126,69 @@ function nextSprint(){
124
126
flow = ! flow ;
125
127
126
128
if ( flow ) {
127
- currentSprint < totalSprints ? currentSprint ++ : currentSprint = 1 ;
128
- setupNextInterval ( totalFlowInSeconds , totalFlowInSeconds , flowText , 0 , currentSprint ) ;
129
+ currentSet < totalSets ? currentSet ++ : currentSet = 1 ;
130
+ setupSprint ( totalFlowInSeconds , totalFlowInSeconds , flowText , 0 , ( Date . now ( ) / 1000 ) + totalFlowInSeconds ) ;
129
131
130
132
}
131
133
else {
132
- if ( currentSprint < totalSprints ) {
133
- setupNextInterval ( totalShortBreakInSeconds , totalShortBreakInSeconds , breakText , 0 , currentSprint ) ;
134
+ if ( currentSet < totalSets ) {
135
+ setupSprint ( totalShortBreakInSeconds , totalShortBreakInSeconds , breakText , 0 , ( Date . now ( ) / 1000 ) + totalShortBreakInSeconds ) ;
134
136
}
135
137
else {
136
- setupNextInterval ( totalLongBreakInSeconds , totalLongBreakInSeconds , breakText , 0 , currentSprint ) ;
138
+ setupSprint ( totalLongBreakInSeconds , totalLongBreakInSeconds , breakText , 0 , ( Date . now ( ) / 1000 ) + totalLongBreakInSeconds ) ;
137
139
}
138
140
}
139
141
140
142
vibration . start ( "nudge" ) ;
141
143
}
142
144
145
+ function setupSprint ( sprintTotalTime , left , text , angleLeft , deadline ) {
146
+ progressArc . sweepAngle = angleLeft ;
147
+ currentSprintText . text = text ;
148
+
149
+ currentSprintTotalTime = sprintTotalTime ;
150
+ timeLeft = left ;
151
+ deadlineInSeconds = deadline ;
152
+
153
+ formatCountdown ( timeLeft ) ;
154
+ setCounter . text = `${ currentSet } of ${ totalSets } ` ;
155
+ }
156
+
157
+ function play ( ) {
158
+ paused = false ;
159
+ deadlineInSeconds = ( Date . now ( ) / 1000 ) + timeLeft ;
160
+ timeLeft = 0 ;
161
+ playPauseIcon . image = "pause.png" ;
162
+ playPauseIconPressed . image = "pause_press.png" ;
163
+ restartSkipIcon . image = "reset.png" ;
164
+ //clock.tick does not run in background so use setInterval instead
165
+ countdown = setInterval ( ( ) => progress ( ) , 1000 ) ;
166
+ }
167
+
168
+ function pause ( ) {
169
+ paused = true ;
170
+ //stop the clock
171
+ clearInterval ( countdown ) ;
172
+ timeLeft = calculateRemainingTimeInSeconds ( deadlineInSeconds ) ;
173
+ playPauseIcon . image = "play.png" ;
174
+ playPauseIconPressed . image = "play_press.png" ;
175
+ restartSkipIcon . image = "skip.png" ;
176
+ }
177
+
178
+ function skip ( ) {
179
+ pause ( ) ;
180
+ timeLeft = 0 ;
181
+ nextSprint ( ) ;
182
+ }
183
+
184
+ function restart ( ) {
185
+ pause ( ) ;
186
+ setupSprint ( currentSprintTotalTime , currentSprintTotalTime , flow ? flowText : breakText , 0 , ( Date . now ( ) / 1000 ) + currentSprintTotalTime ) ;
187
+ }
188
+
143
189
function setupWithUserSettings ( ) {
144
190
let settings ;
145
- try {
191
+ try { //read settings about time intervals
146
192
settings = fs . readFileSync ( "flowSettings.txt" , "cbor" ) ;
147
193
}
148
194
catch ( err ) {
@@ -155,67 +201,35 @@ function setupWithUserSettings(){
155
201
totalLongBreakInSeconds = settings . longBreakTime == 0 ? totalLongBreakInSeconds : parseInt ( settings . longBreakTime ) * 60 ;
156
202
157
203
//pick up where the user ended
158
- try {
159
- //{closeTime: Date.now(), timeLeft: countdownSeconds, text: text, state: currentIntervalTime, sprint: currentSprint, counting: counting}
160
- let saveState = fs . readFileSync ( "saveState.txt" , "cbor" ) ;
161
- //secondsLeft when app closed - seconds passed since exit
162
- let secondsLeft = saveState . timeLeft - ( ( Date . now ( ) - parseInt ( saveState . closeTime ) ) / 1000 ) ;
163
- secondsLeft <= 0 ? 0 : Math . ceil ( secondsLeft ) ;
164
- countdownSeconds = secondsLeft ;
165
- flow = saveState . flow ;
166
- currentIntervalTime = saveState . state ;
167
- currentSprint = saveState . sprint ;
168
- if ( secondsLeft <= 0 ) {
169
- pause ( ) ;
170
- nextSprint ( ) ;
171
- }
172
- else {
173
- saveState . counting ? play ( ) : pause ( ) ;
174
- setupNextInterval ( currentIntervalTime , countdownSeconds , saveState . text , secondsToAngle ( currentIntervalTime - countdownSeconds ) , currentSprint ) ;
175
- }
204
+ try { //read settings about past states
205
+ restorePreviousSession ( fs . readFileSync ( "saveState.txt" , "cbor" ) ) ;
176
206
}
177
207
catch ( err ) {
178
208
console . log ( err ) ;
179
- setupNextInterval ( totalFlowInSeconds , totalFlowInSeconds , flowText , 0 , currentSprint ) ;
209
+ setupSprint ( totalFlowInSeconds , totalFlowInSeconds , flowText , 0 , ( Date . now ( ) / 1000 ) + totalFlowInSeconds ) ;
180
210
}
181
211
}
182
212
183
- function setupNextInterval ( nextIntervalSeconds , secondsLeft , text , angleLeft , currentSprint ) {
184
- //change the arc back to 0
185
- progressArc . sweepAngle = angleLeft ;
186
- //update interval text
187
- currentIntervalText . text = text ;
188
- //set the correct seconds for progress
189
- currentIntervalTime = nextIntervalSeconds ;
190
- countdownSeconds = secondsLeft ;
191
- currentIntervalText . text = text ;
192
- sprintCounter . text = `${ currentSprint } of ${ totalSprints } ` ;
193
- }
213
+ function restorePreviousSession ( saveState ) {
214
+ timeLeft = calculateRemainingTimeInSeconds ( saveState . deadlineInSeconds ) ;
194
215
195
- function play ( ) {
196
- counting = true ;
197
- playPauseIcon . image = "pause.png" ;
198
- playPauseIconPressed . image = "pause_press.png" ;
199
-
200
- restartSkipIcon . image = "reset.png" ;
201
- }
216
+ //set state variables
217
+ deadlineInSeconds = saveState . deadlineInSeconds ;
202
218
203
- function pause ( ) {
204
- counting = false ;
205
- playPauseIcon . image = "play.png" ;
206
- playPauseIconPressed . image = "play_press.png" ;
207
-
208
- restartSkipIcon . image = "skip.png" ;
209
- }
210
219
211
- function skip ( ) {
212
- counting = false ;
213
- nextSprint ( ) ;
214
- }
215
-
216
- function restart ( ) {
217
- pause ( ) ;
218
- setupNextInterval ( currentIntervalTime , currentIntervalTime , flow ? flowText : breakText , 0 , currentSprint ) ;
220
+ flow = saveState . flow ;
221
+ currentSprintTotalTime = saveState . state ;
222
+ currentSet = saveState . set ;
223
+
224
+ let text = flow ? flowText : breakText ;
225
+ deadlineInSeconds = saveState . paused ? ( Date . now ( ) / 1000 ) + saveState . timeLeft : saveState . deadlineInSeconds ;
226
+ saveState . paused ? pause ( ) : play ( ) ;
227
+ if ( deadlineInSeconds >= ( Date . now ( ) / 1000 ) || saveState . paused ) {
228
+ setupSprint ( currentSprintTotalTime , timeLeft , text , secondsToAngle ( currentSprintTotalTime - deadlineInSeconds ) , deadlineInSeconds ) ;
229
+ }
230
+ else { //finished sprint while our of app, so move to the next
231
+ skip ( ) ;
232
+ }
219
233
}
220
234
221
235
function formatCountdown ( seconds ) {
@@ -230,5 +244,5 @@ function formatCountdown(seconds){
230
244
formattedSeconds = formattedSeconds < 10 ? "0" + formattedSeconds : formattedSeconds ;
231
245
232
246
//update countdown text
233
- countdown . text = `${ formattedHours } :${ formattedMinutes } :${ formattedSeconds } ` ;
234
- }
247
+ countdownText . text = `${ formattedHours } :${ formattedMinutes } :${ formattedSeconds } ` ;
248
+ }
0 commit comments