stopwatch touch: Fast Loading support

pull/2941/head
Erik Andresen 2023-07-28 06:59:17 +02:00
parent 4777d98c10
commit 51838fc133
3 changed files with 64 additions and 57 deletions

View File

@ -2,3 +2,4 @@
0.02: Adjust for touch events outside of screen g dimensions 0.02: Adjust for touch events outside of screen g dimensions
0.03: Do not register as watch, manually start clock on button 0.03: Do not register as watch, manually start clock on button
0.04: Keep running in background by saving state 0.04: Keep running in background by saving state
0.05: Fast Loading support

View File

@ -1,7 +1,7 @@
{ {
"id": "stopwatch", "id": "stopwatch",
"name": "Stopwatch Touch", "name": "Stopwatch Touch",
"version": "0.04", "version": "0.05",
"description": "A touch based stop watch for Bangle JS 2", "description": "A touch based stop watch for Bangle JS 2",
"icon": "stopwatch.png", "icon": "stopwatch.png",
"screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}], "screenshots": [{"url":"screenshot1.png"},{"url":"screenshot2.png"},{"url":"screenshot3.png"}],

View File

@ -1,3 +1,4 @@
{
const CONFIGFILE = "stopwatch.json"; const CONFIGFILE = "stopwatch.json";
const now = Date.now(); const now = Date.now();
@ -20,6 +21,7 @@ let timeY = 2*h/5;
let displayInterval; let displayInterval;
let redrawButtons = true; let redrawButtons = true;
const iconScale = g.getWidth() / 178; // scale up/down based on Bangle 2 size const iconScale = g.getWidth() / 178; // scale up/down based on Bangle 2 size
const origTheme = g.theme;
// 24 pixel images, scale to watch // 24 pixel images, scale to watch
// 1 bit optimal, image string, no E.toArrayBuffer() // 1 bit optimal, image string, no E.toArrayBuffer()
@ -27,19 +29,19 @@ const pause_img = atob("GBiBAf////////////////wYP/wYP/wYP/wYP/wYP/wYP/wYP/wYP/wY
const play_img = atob("GBjBAP//AAAAAAAAAAAIAAAOAAAPgAAP4AAP+AAP/AAP/wAP/8AP//AP//gP//gP//AP/8AP/wAP/AAP+AAP4AAPgAAOAAAIAAAAAAAAAAA="); const play_img = atob("GBjBAP//AAAAAAAAAAAIAAAOAAAPgAAP4AAP+AAP/AAP/wAP/8AP//AP//gP//gP//AP/8AP/wAP/AAP+AAP4AAPgAAOAAAIAAAAAAAAAAA=");
const reset_img = atob("GBiBAf////////////AAD+AAB+f/5+f/5+f/5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+f/5+f/5+f/5+AAB/AAD////////////w=="); const reset_img = atob("GBiBAf////////////AAD+AAB+f/5+f/5+f/5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+cA5+f/5+f/5+f/5+AAB/AAD////////////w==");
function saveState() { const saveState = function() {
config.state.total = tTotal; config.state.total = tTotal;
config.state.start = tStart; config.state.start = tStart;
config.state.current = tCurrent; config.state.current = tCurrent;
config.state.running = running; config.state.running = running;
require("Storage").writeJSON(CONFIGFILE, config); require("Storage").writeJSON(CONFIGFILE, config);
} };
function log_debug(o) { const log_debug = function(o) {
//console.log(o); //console.log(o);
} };
function timeToText(t) { const timeToText = function(t) {
let hrs = Math.floor(t/3600000); let hrs = Math.floor(t/3600000);
let mins = Math.floor(t/60000)%60; let mins = Math.floor(t/60000)%60;
let secs = Math.floor(t/1000)%60; let secs = Math.floor(t/1000)%60;
@ -53,9 +55,9 @@ function timeToText(t) {
//log_debug(text); //log_debug(text);
return text; return text;
} };
function drawButtons() { const drawButtons = function() {
log_debug("drawButtons()"); log_debug("drawButtons()");
if (!running && tCurrent == tTotal) { if (!running && tCurrent == tTotal) {
bigPlayPauseBtn.draw(); bigPlayPauseBtn.draw();
@ -67,9 +69,9 @@ function drawButtons() {
} }
redrawButtons = false; redrawButtons = false;
} };
function drawTime() { const drawTime = function() {
log_debug("drawTime()"); log_debug("drawTime()");
let Tt = tCurrent-tTotal; let Tt = tCurrent-tTotal;
let Ttxt = timeToText(Tt); let Ttxt = timeToText(Tt);
@ -80,32 +82,32 @@ function drawTime() {
g.clearRect(0, timeY - 21, w, timeY + 21); g.clearRect(0, timeY - 21, w, timeY + 21);
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
g.drawString(Ttxt, w/2, timeY); g.drawString(Ttxt, w/2, timeY);
} };
function draw() { const draw = function() {
let last = tCurrent; let last = tCurrent;
if (running) tCurrent = Date.now(); if (running) tCurrent = Date.now();
g.setColor(g.theme.fg); g.setColor(g.theme.fg);
if (redrawButtons) drawButtons(); if (redrawButtons) drawButtons();
drawTime(); drawTime();
} };
function startTimer() { const startTimer = function() {
log_debug("startTimer()"); log_debug("startTimer()");
draw(); draw();
displayInterval = setInterval(draw, 100); displayInterval = setInterval(draw, 100);
} };
function stopTimer() { const stopTimer = function() {
log_debug("stopTimer()"); log_debug("stopTimer()");
if (displayInterval) { if (displayInterval) {
clearInterval(displayInterval); clearInterval(displayInterval);
displayInterval = undefined; displayInterval = undefined;
} }
} };
// BTN stop start // BTN stop start
function stopStart() { const stopStart = function() {
log_debug("stopStart()"); log_debug("stopStart()");
if (running) if (running)
@ -127,9 +129,9 @@ function stopStart() {
draw(); draw();
} }
saveState(); saveState();
} };
function setButtonImages() { const setButtonImages = function() {
if (running) { if (running) {
bigPlayPauseBtn.setImage(pause_img); bigPlayPauseBtn.setImage(pause_img);
smallPlayPauseBtn.setImage(pause_img); smallPlayPauseBtn.setImage(pause_img);
@ -139,10 +141,10 @@ function setButtonImages() {
smallPlayPauseBtn.setImage(play_img); smallPlayPauseBtn.setImage(play_img);
resetBtn.setImage(reset_img); resetBtn.setImage(reset_img);
} }
} };
// lap or reset // lap or reset
function lapReset() { const lapReset = function() {
log_debug("lapReset()"); log_debug("lapReset()");
if (!running && tStart != tCurrent) { if (!running && tStart != tCurrent) {
redrawButtons = true; redrawButtons = true;
@ -152,10 +154,10 @@ function lapReset() {
draw(); draw();
} }
saveState(); saveState();
} };
// simple on screen button class // simple on screen button class
function BUTTON(name,x,y,w,h,c,f,i) { const BUTTON = function(name,x,y,w,h,c,f,i) {
this.name = name; this.name = name;
this.x = x; this.x = x;
this.y = y; this.y = y;
@ -164,11 +166,11 @@ function BUTTON(name,x,y,w,h,c,f,i) {
this.color = c; this.color = c;
this.callback = f; this.callback = f;
this.img = i; this.img = i;
} };
BUTTON.prototype.setImage = function(i) { BUTTON.prototype.setImage = function(i) {
this.img = i; this.img = i;
} };
// if pressed the callback // if pressed the callback
BUTTON.prototype.check = function(x,y) { BUTTON.prototype.check = function(x,y) {
@ -197,48 +199,52 @@ BUTTON.prototype.draw = function() {
}; };
var bigPlayPauseBtn = new BUTTON("big",0, 3*h/4 ,w, h/4, "#0ff", stopStart, play_img); const bigPlayPauseBtn = new BUTTON("big",0, 3*h/4 ,w, h/4, "#0ff", stopStart, play_img);
var smallPlayPauseBtn = new BUTTON("small",w/2, 3*h/4 ,w/2, h/4, "#0ff", stopStart, play_img); const smallPlayPauseBtn = new BUTTON("small",w/2, 3*h/4 ,w/2, h/4, "#0ff", stopStart, play_img);
var resetBtn = new BUTTON("rst",0, 3*h/4, w/2, h/4, "#ff0", lapReset, pause_img); const resetBtn = new BUTTON("rst",0, 3*h/4, w/2, h/4, "#ff0", lapReset, pause_img);
bigPlayPauseBtn.setImage(play_img); bigPlayPauseBtn.setImage(play_img);
smallPlayPauseBtn.setImage(play_img); smallPlayPauseBtn.setImage(play_img);
resetBtn.setImage(pause_img); resetBtn.setImage(pause_img);
Bangle.setUI({mode:"custom", btn:() => load(), touch: (button,xy) => {
let x = xy.x;
let y = xy.y;
Bangle.on('touch', function(button, xy) { // adjust for outside the dimension of the screen
var x = xy.x; // http://forum.espruino.com/conversations/371867/#comment16406025
var y = xy.y; if (y > h) y = h;
if (y < 0) y = 0;
if (x > w) x = w;
if (x < 0) x = 0;
// adjust for outside the dimension of the screen // not running, and reset
// http://forum.espruino.com/conversations/371867/#comment16406025 if (!running && tCurrent == tTotal && bigPlayPauseBtn.check(x, y)) return;
if (y > h) y = h;
if (y < 0) y = 0;
if (x > w) x = w;
if (x < 0) x = 0;
// not running, and reset // paused and hit play
if (!running && tCurrent == tTotal && bigPlayPauseBtn.check(x, y)) return; if (!running && tCurrent != tTotal && smallPlayPauseBtn.check(x, y)) return;
// paused and hit play // paused and press reset
if (!running && tCurrent != tTotal && smallPlayPauseBtn.check(x, y)) return; if (!running && tCurrent != tTotal && resetBtn.check(x, y)) return;
// paused and press reset // must be running
if (!running && tCurrent != tTotal && resetBtn.check(x, y)) return; if (running && bigPlayPauseBtn.check(x, y)) return;
}, remove: () => {
// must be running if (displayInterval) {
if (running && bigPlayPauseBtn.check(x, y)) return; clearInterval(displayInterval);
}); displayInterval = undefined;
}
Bangle.removeListener('lcdPower',onLCDPower);
g.setTheme(origTheme);
}});
// Stop updates when LCD is off, restart when on // Stop updates when LCD is off, restart when on
Bangle.on('lcdPower',on=>{ const onLCDPower = (on) => {
if (on) { if (on) {
draw(); // draw immediately, queue redraw draw(); // draw immediately, queue redraw
} else { // stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
} }
}); };
Bangle.on('lcdPower',onLCDPower);
// Clear the screen once, at startup // Clear the screen once, at startup
g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear();
@ -254,4 +260,4 @@ if (running) {
} else { } else {
draw(); draw();
} }
setWatch(() => load(), BTN, { repeat: false, edge: "falling" }); }