mirror of https://github.com/espruino/BangleApps
Merge branch 'release/timer' of https://github.com/fbedussi/BangleApps into fbedussi-release/timer
commit
5b788fbc96
21
apps.json
21
apps.json
|
@ -1568,5 +1568,26 @@
|
|||
{"name":"switch-on.img","url":"switch-on.js","evaluate":true},
|
||||
{"name":"switch-off.img","url":"switch-off.js","evaluate":true}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "timer",
|
||||
"name": "Timer",
|
||||
"icon": "app.png",
|
||||
"version": "0.01",
|
||||
"description": "Simple timer, useful when playing board games or cooking",
|
||||
"tags": "timer",
|
||||
"readme": "README.md",
|
||||
"allow_emulator": true,
|
||||
"storage": [
|
||||
{
|
||||
"name": "timer.app.js",
|
||||
"url": "app.js"
|
||||
},
|
||||
{
|
||||
"name": "timer.img",
|
||||
"url": "app-icon.js",
|
||||
"evaluate": true
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
0.01: Initial version
|
|
@ -0,0 +1,16 @@
|
|||
# Timer
|
||||
|
||||
Simple timer, useful when playing board games or cooking
|
||||
|
||||
## Features
|
||||
|
||||
- When the time is up the timer can be reset to starting time, this is useful e.g. for playing board games
|
||||
- When the countdown is running the timer cannot be adjusted, this prevents accidental time variations
|
||||
- When the time is up the starting time is shown, as a reminder of the time elapsed
|
||||
|
||||
## How to use it
|
||||
|
||||
- Tap on minutes to increase them one by one
|
||||
- Tap on seconds to increase them one by one
|
||||
- Press BTN3 to reset time to 0
|
||||
- Press BTN1 to start the timer or reset to the original time
|
|
@ -0,0 +1,5 @@
|
|||
require("heatshrink").decompress(
|
||||
atob(
|
||||
"mEwxH+AH4A/AEsxAAQso1eyrgvDrmrw4skAAQuDAAIHBrYABFsQvMGLYtGAAOAFweA2WrF4gwYFxAwEFwIvBwowFsIub64AB6wJF6wJB1mGMTFbrmsEYoADHAwAC1dhGCoTCmJhBEYoAM2RiFF6VbleBF6QABGAguSw2sgAwnCAdhXYIwBqwvT2WFDwYvP1YZCwMAlYwT1ZgORogZEqwwB1iRhBoYmGlcAYiZgOBgWFDIzCBAALESYIYvMw4ZHGCuHF5aOKeYgABYiCQMBYeyDZLzBAAQwO2QvPDhbzCeqAvbGAQQBlYvqeYIvteYMreJ7vaACbvQJxwAP1YvLGAeHF7uHFxYvDwovdwovPSDusRxgvEwwvbwwvNGAmrds4vGsOyFy+ysIvPSLqNPGDwuT/xyEwySS2QuEF6BgEYYL0Q1ZIEFyIwGMQIxM1ZcFFyYwHreFw+rSwmy1eHwoSGFygxJABwtXeo4upMSQtdGZorjAH4A/AF4A=="
|
||||
)
|
||||
)
|
|
@ -0,0 +1,151 @@
|
|||
let counter = 0;
|
||||
let setValue = 0;
|
||||
let counterInterval;
|
||||
let state;
|
||||
|
||||
const DEBOUNCE = 50;
|
||||
|
||||
function buzzAndBeep() {
|
||||
return Bangle.buzz(1000, 1)
|
||||
.then(() => Bangle.beep(200, 3000))
|
||||
.then(() => setTimeout(buzzAndBeep, 5000));
|
||||
}
|
||||
|
||||
function outOfTime() {
|
||||
g.clearRect(0, 0, 220, 70);
|
||||
g.setFontAlign(0, 0);
|
||||
g.setFont("6x8", 3);
|
||||
g.drawString("Time UP!", 120, 50);
|
||||
counter = setValue;
|
||||
buzzAndBeep();
|
||||
setInterval(() => {
|
||||
g.clearRect(0, 70, 220, 160);
|
||||
setTimeout(draw, 200);
|
||||
}, 400);
|
||||
state = "stopped";
|
||||
}
|
||||
|
||||
function draw() {
|
||||
const minutes = Math.floor(counter / 60);
|
||||
const seconds = Math.floor(counter % 60);
|
||||
const seconds2Digits = seconds < 10 ? `0${seconds}` : seconds.toString();
|
||||
g.clearRect(0, 70, 220, 160);
|
||||
g.setFontAlign(0, 0);
|
||||
g.setFont("6x8", 7);
|
||||
g.drawString(
|
||||
`${minutes < 10 ? "0" : ""}${minutes}:${seconds2Digits}`,
|
||||
120,
|
||||
120
|
||||
);
|
||||
}
|
||||
|
||||
function countDown() {
|
||||
if (counter <= 0) {
|
||||
if (counterInterval) {
|
||||
clearInterval(counterInterval);
|
||||
counterInterval = undefined;
|
||||
}
|
||||
outOfTime();
|
||||
return;
|
||||
}
|
||||
|
||||
counter--;
|
||||
draw();
|
||||
}
|
||||
|
||||
function clearIntervals() {
|
||||
clearInterval();
|
||||
counterInterval = undefined;
|
||||
}
|
||||
|
||||
function set(delta) {
|
||||
if (state === "started") return;
|
||||
counter += delta;
|
||||
if (state === "unset") {
|
||||
state = "set";
|
||||
}
|
||||
draw();
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
setValue = counter;
|
||||
countDown();
|
||||
counterInterval = setInterval(countDown, 1000);
|
||||
}
|
||||
|
||||
// unset -> set -> started -> -> stopped -> set
|
||||
const stateMap = {
|
||||
set: () => {
|
||||
state = "started";
|
||||
startTimer();
|
||||
},
|
||||
started: () => {
|
||||
reset(setValue);
|
||||
},
|
||||
stopped: () => {
|
||||
reset(setValue);
|
||||
}
|
||||
};
|
||||
|
||||
function changeState() {
|
||||
if (stateMap[state]) stateMap[state]();
|
||||
}
|
||||
|
||||
function drawLabels() {
|
||||
g.clear();
|
||||
g.setFontAlign(-1, 0);
|
||||
g.setFont("6x8", 7);
|
||||
g.drawString(`+ +`, 35, 180);
|
||||
g.setFontAlign(0, 0, 3);
|
||||
g.setFont("6x8", 1);
|
||||
g.drawString(`reset (re)start`, 230, 120);
|
||||
}
|
||||
|
||||
function reset(value) {
|
||||
clearIntervals();
|
||||
counter = value;
|
||||
setValue = value;
|
||||
drawLabels();
|
||||
draw();
|
||||
state = value === 0 ? "unset" : "set";
|
||||
}
|
||||
|
||||
function addWatch() {
|
||||
clearWatch();
|
||||
setWatch(changeState, BTN1, {
|
||||
debounce: DEBOUNCE,
|
||||
repeat: true,
|
||||
edge: "falling"
|
||||
});
|
||||
setWatch(
|
||||
() => {
|
||||
reset(0);
|
||||
},
|
||||
BTN3,
|
||||
{
|
||||
debounce: DEBOUNCE,
|
||||
repeat: true,
|
||||
edge: "falling"
|
||||
}
|
||||
);
|
||||
setWatch(
|
||||
() => {
|
||||
set(60);
|
||||
},
|
||||
BTN4,
|
||||
{
|
||||
debounce: DEBOUNCE,
|
||||
repeat: true,
|
||||
edge: "falling"
|
||||
}
|
||||
);
|
||||
setWatch(() => set(1), BTN5, {
|
||||
debounce: DEBOUNCE,
|
||||
repeat: true,
|
||||
edge: "falling"
|
||||
});
|
||||
}
|
||||
|
||||
reset(0);
|
||||
addWatch();
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
Loading…
Reference in New Issue