Merge pull request #676 from Shaylin/master

Added countdown timer application
pull/678/head
Gordon Williams 2021-02-22 09:07:50 +00:00 committed by GitHub
commit d3d0941258
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 258 additions and 0 deletions

View File

@ -2856,6 +2856,18 @@
{"name":"widhrt.wid.js","url":"widget.js"} {"name":"widhrt.wid.js","url":"widget.js"}
] ]
}, },
{ "id": "countdowntimer",
"name" : "Countdown Timer",
"icon": "countdowntimer.png",
"version": "0.01",
"description": "A simple countdown timer with a focus on usability",
"tags": "timer, tool",
"readme": "README.md",
"storage": [
{"name": "countdowntimer.app.js", "url": "countdowntimer.js"},
{"name": "countdowntimer.img", "url": "countdowntimer-icon.js", "evaluate": true}
]
},
{ "id": "helloworld", { "id": "helloworld",
"name": "hello,world!", "name": "hello,world!",
"shortName":"helloworld", "shortName":"helloworld",

View File

@ -0,0 +1 @@
0.01: Initial version

View File

@ -0,0 +1,12 @@
# countdown-timer
A basic bangle.js timer with a focus on usability.
* Start or Pause the timer with BTN1
* Reset the timer with BTN2
* Exit the application with BTN3
* Touch the right side of the screen to increase the time amount by 1 second
* Touch the left side of the scren to decrease the time amount by 1 second
* Touching and holding the screen will increase or decrease the time amount by 60 seconds at a time.
Icons made by [Freepik](https://www.freepik.com) from [Flaticon](https://www.flaticon.com/).

View File

@ -0,0 +1 @@
require("heatshrink").decompress(atob("mEwwgMJhvd7tEogkSC4lAC6xWUgUgNysiC6hGBL58BiMQLoYXDMJkRAAIWEC4gYJFwIABCwgXFDBAWCpoXLMYwuCigUD6czmUSmQYKC4QuD6f//8xiUzmckJJIuECwQXEDAgXGFwc/C4XykYXCmZIJCwVPCwQABCwczmgwHXYXUCwgXFGBAXC74XLGAQXELowXIVgYXF6QWF+Z3EJAhGFUganHJAoXFRooXLMAQXCLwwXHMAQXUMAQXCRwQWFC9HSiMvC40iCocxiKoEC4cTC4sRiLBDC5MiF4wXFmQXHL4/zkRHEO6H/OwwXFX5IXfd5HfC5s0C4/TC5skRwZ4LLxAXHMAxeIC4hIJLxYXEJAxGMJAgwFFw4XGGAZhD+UjLoxGEC4owDmMSIoouGJAgYBGIIXDCwYuGGAoABIQMiaIQuKDA/dCoguJJIwXHCxQYGCyIYFCyRjELZYA="))

View File

@ -0,0 +1,232 @@
const heatshrinkDecompress = require("heatshrink").decompress;
const playIcon = heatshrinkDecompress(atob("jEYwhC/gFwBZV3BhV3u4LLBhILCEpALCBhALDu9gBaojKHZZrVQZSbLAG4A="));
const pauseIcon = heatshrinkDecompress(atob("jEYwhC/xGIAYoL/Bf4LfAHA="));
const resetIcon = heatshrinkDecompress(atob("jEYwg30h3u93gAgIKHBgXuBYgIBoEEBoQWFAgQMCBYgrBE4giEBYYjGAgY+DBY4AHBZlABZQ7DLIpTFAo5ZJLYYDFTZKzLAGQA=="));
const closeIcon = heatshrinkDecompress(atob("jEYwhC/4AEDhgKEhnMAofMCIgGECAoHFCwwIDCw4YDCxAYCCxALMEZY7KKZZrKQZibKAHIA="));
const timerState = {
IDLE: 0,
RUNNING: 1
};
let currentState = timerState.IDLE;
let remainingSeconds = 0;
let countdownInterval = null;
let increasingInterval = null;
let decreasingInterval = null;
let isDecreasingRemainingSeconds = false;
let isIncreasingRemainingSeconds = false;
function main() {
g.clear();
g.setFont("Vector", 40);
g.setFontAlign(0, 0);
registerInputHandlers();
draw();
}
function registerInputHandlers() {
setWatch(onPrimaryButtonPressed, BTN1, { repeat: true });
setWatch(onResetButtonPressed, BTN2, { repeat: true });
setWatch(onExitButtonPressed, BTN3, { repeat: true });
setWatch(onDecreaseRemainingSecondsPressed, BTN4, { repeat: true, edge: "rising" });
setWatch(onIncreaseRemainingSecondsPressed, BTN5, { repeat: true, edge: "rising" });
setWatch(onDecreaseRemainingSecondsReleased, BTN4, { repeat: true, edge: "falling" });
setWatch(onIncreaseRemainingSecondsReleased, BTN5, { repeat: true, edge: "falling" });
}
function draw() {
g.clearRect(200, 0, 240, 240);
g.clearRect(0, 0, 240, 80);
drawRemainingSecondsPanel();
g.drawImage(resetIcon, 216, 108);
g.drawImage(closeIcon, 216, 188);
if (currentState == timerState.IDLE) {
g.drawImage(playIcon, 216, 28);
} else {
g.drawImage(pauseIcon, 216, 28);
}
g.flip();
}
function drawRemainingSecondsPanel() {
g.clearRect(0, 100, 200, 140);
g.drawString(formatRemainingSeconds(), 105, 120);
if (currentState == timerState.IDLE) {
drawSubtractRemainingSeconds();
drawIncreaseRemainingSeconds();
} else {
g.setColor(0.4, 0.4, 0.4);
drawSubtractRemainingSeconds();
drawIncreaseRemainingSeconds();
g.setColor(-1);
}
}
function drawSubtractRemainingSeconds() {
if (isDecreasingRemainingSeconds) {
drawFilledCircle(22, 117, 15);
}
g.drawString("-", 25, 120);
}
function drawIncreaseRemainingSeconds() {
if (isIncreasingRemainingSeconds) {
drawFilledCircle(182, 117, 15);
}
g.drawString("+", 185, 120);
}
function drawFilledCircle(x, y, radians) {
g.setColor(0.1, 0.37, 0.87);
g.fillCircle(x, y, radians);
g.setColor(-1);
}
function formatRemainingSeconds() {
const minutes = Math.floor(remainingSeconds / 60);
const minutesTens = Math.floor(minutes / 10);
const minutesUnits = minutes % 10;
const seconds = remainingSeconds % 60;
const secondsTens = Math.floor(seconds / 10);
const secondsUnits = seconds % 10;
return `${minutesTens}${minutesUnits}:${secondsTens}${secondsUnits}`;
}
function onPrimaryButtonPressed() {
if (isIncreasingRemainingSeconds || isDecreasingRemainingSeconds) return;
if (currentState == timerState.IDLE) {
if (remainingSeconds == 0) return;
currentState = timerState.RUNNING;
beginCountdown();
draw();
} else {
currentState = timerState.IDLE;
stopCountdown();
draw();
}
}
function beginCountdown() {
countdownInterval = setInterval(countdown, 1000);
}
function countdown() {
--remainingSeconds;
if (remainingSeconds <= 0) {
remainingSeconds = 0;
stopCountdown();
}
drawRemainingSecondsPanel();
if (remainingSeconds <= 0) {
drawStopMessage();
}
}
function drawStopMessage() {
draw();
Bangle.buzz(800);
g.setFont("Vector", 30);
g.setColor(1.0, 0.91, 0);
g.drawString("Time's Up!", 105, 40);
g.setColor(-1);
g.setFont("Vector", 40);
}
function stopCountdown() {
clearInterval(countdownInterval);
countdownInterval = null;
currentState = timerState.IDLE;
}
function onResetButtonPressed() {
currentState = timerState.IDLE;
remainingSeconds = 0;
draw();
}
function onExitButtonPressed() {
Bangle.showLauncher();
}
function onIncreaseRemainingSecondsPressed() {
if (currentState == timerState.RUNNING) return;
incremementRemainingSeconds();
increasingInterval = setInterval(() => {
remainingSeconds += 60;
if (remainingSeconds >= 5999) {
remainingSeconds = 5999;
}
drawRemainingSecondsPanel();
}, 250);
isIncreasingRemainingSeconds = true;
drawRemainingSecondsPanel();
}
function incremementRemainingSeconds() {
if (remainingSeconds >= 5999) return;
++remainingSeconds;
}
function onIncreaseRemainingSecondsReleased() {
if (currentState == timerState.RUNNING) return;
clearInterval(increasingInterval);
isIncreasingRemainingSeconds = false;
drawRemainingSecondsPanel();
}
function onDecreaseRemainingSecondsPressed() {
if (currentState == timerState.RUNNING) return;
decreaseRemainingSeconds();
decreasingInterval = setInterval(() => {
remainingSeconds -= 60;
if (remainingSeconds < 0) {
remainingSeconds = 0;
}
drawRemainingSecondsPanel();
}, 250);
isDecreasingRemainingSeconds = true;
drawRemainingSecondsPanel();
}
function decreaseRemainingSeconds() {
if (remainingSeconds <= 0) return;
--remainingSeconds;
}
function onDecreaseRemainingSecondsReleased() {
if (currentState == timerState.RUNNING) return;
clearInterval(decreasingInterval);
isDecreasingRemainingSeconds = false;
draw();
}
main();

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB