Skip to content

Commit 0280733

Browse files
committed
update
- update clock every minute - enable/disable clock in setting - adjust ui update behavior in setting
1 parent 7cc1d11 commit 0280733

File tree

3 files changed

+84
-60
lines changed

3 files changed

+84
-60
lines changed

apps/jwalk/app.js

Lines changed: 70 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,32 @@
1+
// === Utility Functions ===
2+
function formatTime(seconds) {
3+
let mins = Math.floor(seconds / 60);
4+
let secs = (seconds % 60).toString().padStart(2, '0');
5+
return `${mins}:${secs}`;
6+
}
7+
8+
function getTimeStr() {
9+
let d = new Date();
10+
return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
11+
}
12+
13+
function updateCachedLeftTime() {
14+
cachedLeftTime = "Left: " + formatTime(state.remainingTotal);
15+
}
16+
17+
// === Constants ===
118
const FILE = "jwalk.json";
219
const DEFAULTS = {
320
totalDuration: 30,
421
intervalDuration: 3,
522
startMode: 0,
6-
modeBuzzerDuration: 1000,
7-
finishBuzzerDuration: 1500,
23+
modeBuzzerDuration: 1000,
24+
finishBuzzerDuration: 1500,
25+
showClock: true,
26+
updateWhileLocked: false
827
};
928

29+
// === Settings and State ===
1030
let settings = require("Storage").readJSON(FILE, 1) || DEFAULTS;
1131

1232
let state = {
@@ -20,28 +40,14 @@ let state = {
2040
forceDraw: false,
2141
};
2242

23-
let drawTimerInterval;
2443
let cachedLeftTime = "";
44+
let lastMinuteStr = getTimeStr();
45+
let drawTimerInterval;
2546

26-
function formatTime(seconds) {
27-
let mins = Math.floor(seconds / 60);
28-
let secs = (seconds % 60).toString().padStart(2, '0');
29-
return `${mins}:${secs}`;
30-
}
31-
32-
function updateCachedLeftTime() {
33-
cachedLeftTime = "Left: " + formatTime(state.remainingTotal);
34-
}
35-
36-
function getTimeStr() {
37-
let d = new Date();
38-
return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
39-
}
40-
47+
// === UI Rendering ===
4148
function drawUI() {
4249
let y = Bangle.appRect.y + 8;
4350
g.reset().setBgColor(g.theme.bg).clearRect(Bangle.appRect);
44-
4551
g.setColor(g.theme.fg);
4652

4753
let displayInterval = state.paused
@@ -76,17 +82,46 @@ function drawUI() {
7682
g.drawString(state.currentMode, g.getWidth() / 2, y + 15);
7783
g.drawString(cachedLeftTime, g.getWidth() / 2, cy + 15);
7884

79-
g.setFontAlign(1, 0);
80-
g.drawString(getTimeStr(), g.getWidth() - 4, y);
85+
if (settings.showClock) {
86+
g.setFontAlign(1, 0);
87+
g.drawString(lastMinuteStr, g.getWidth() - 4, y);
88+
}
8189
g.flip();
8290
}
8391

92+
// === Workout Logic ===
8493
function toggleMode() {
8594
state.currentMode = state.currentMode === "Relax" ? "Intense" : "Relax";
8695
Bangle.buzz(settings.modeBuzzerDuration);
8796
state.forceDraw = true;
8897
}
8998

99+
function startNextInterval() {
100+
if (state.remainingTotal <= 0) {
101+
finishWorkout();
102+
return;
103+
}
104+
105+
state.remainingInterval = Math.min(state.intervalDuration, state.remainingTotal);
106+
state.remainingTotal -= state.remainingInterval;
107+
updateCachedLeftTime();
108+
state.intervalEnd = Date.now() + state.remainingInterval * 1000;
109+
state.forceDraw = true;
110+
}
111+
112+
function togglePause() {
113+
if (state.finished) return;
114+
115+
if (!state.paused) {
116+
state.remainingInterval = Math.max(0, Math.floor((state.intervalEnd - Date.now()) / 1000));
117+
state.paused = true;
118+
} else {
119+
state.intervalEnd = Date.now() + state.remainingInterval * 1000;
120+
state.paused = false;
121+
}
122+
drawUI();
123+
}
124+
90125
function finishWorkout() {
91126
clearInterval(drawTimerInterval);
92127
Bangle.buzz(settings.finishBuzzerDuration);
@@ -110,58 +145,34 @@ function finishWorkout() {
110145
}, 500);
111146
}
112147

113-
114-
function startNextInterval() {
115-
if (state.remainingTotal <= 0) {
116-
finishWorkout();
117-
return;
118-
}
119-
120-
state.remainingInterval = Math.min(state.intervalDuration, state.remainingTotal);
121-
state.remainingTotal -= state.remainingInterval;
122-
updateCachedLeftTime();
123-
state.intervalEnd = Date.now() + state.remainingInterval * 1000;
124-
125-
state.forceDraw = true;
126-
}
127-
148+
// === Timer Tick ===
128149
function tick() {
129150
if (state.finished) return;
130151

131-
if (!state.paused) {
132-
if ((state.intervalEnd - Date.now()) / 1000 <= 0) {
133-
toggleMode();
134-
startNextInterval();
135-
return;
136-
}
152+
const currentMinuteStr = getTimeStr();
153+
if (currentMinuteStr !== lastMinuteStr) {
154+
lastMinuteStr = currentMinuteStr;
155+
state.forceDraw = true;
137156
}
138157

139-
if (!Bangle.isLocked() || state.forceDraw) {
140-
drawUI();
141-
state.forceDraw = false;
158+
if (!state.paused && (state.intervalEnd - Date.now()) / 1000 <= 0) {
159+
toggleMode();
160+
startNextInterval();
161+
return;
142162
}
143-
}
144-
145163

146-
function togglePause() {
147-
if (state.finished) return;
148-
149-
if (!state.paused) {
150-
state.remainingInterval = Math.max(0, Math.floor((state.intervalEnd - Date.now()) / 1000));
151-
state.paused = true;
152-
} else {
153-
state.intervalEnd = Date.now() + state.remainingInterval * 1000;
154-
state.paused = false;
164+
if (state.forceDraw || settings.updateWhileLocked || !Bangle.isLocked()) {
165+
drawUI();
166+
state.forceDraw = false;
155167
}
156-
drawUI();
157168
}
158169

159-
// Setup
170+
// === Initialization ===
160171
Bangle.on("touch", togglePause);
161172
Bangle.loadWidgets();
162173
Bangle.drawWidgets();
163174

164175
updateCachedLeftTime();
165176
startNextInterval();
166177
drawUI();
167-
drawTimerInterval = setInterval(tick, 1000);
178+
drawTimerInterval = setInterval(tick, 1000);

apps/jwalk/metadata.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"name": "Japanese Walking",
44
"shortName": "J-Walk",
55
"icon": "app.png",
6-
"version": "0.01",
6+
"version": "0.01.1",
77
"description": "Alternating walk timer: 3 min Relax / 3 min Intense for a set time. Tap to pause/resume. Start mode, interval and total time configurable via Settings.",
88
"tags": "walk,timer,fitness",
99
"supports": ["BANGLEJS","BANGLEJS2"],

apps/jwalk/settings.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
startMode: 0,
77
modeBuzzerDuration: 1000,
88
finishBuzzerDuration: 1500,
9+
showClock: true,
10+
updateWhileLocked: false
911
};
1012

1113
let settings = require("Storage").readJSON(FILE, 1) || DEFAULTS;
@@ -34,6 +36,17 @@
3436
format: v => v ? "Intense" : "Relax",
3537
onchange: v => { settings.startMode = v; saveSettings(); }
3638
},
39+
'Show Clock': {
40+
value: settings.showClock,
41+
format: v => v ? "Yes" : "No",
42+
onchange: v => { settings.showClock = v; saveSettings(); }
43+
},
44+
'While Locked:': 'Lower power use',
45+
'Update UI While Locked': {
46+
value: settings.updateWhileLocked,
47+
format: v => v ? "Always" : "Mode Changes",
48+
onchange: v => { settings.updateWhileLocked = v; saveSettings(); }
49+
},
3750
'Mode Buzz (ms)': {
3851
value: settings.modeBuzzerDuration,
3952
min: 0, max: 2000, step: 50,

0 commit comments

Comments
 (0)