BangleApps/apps/touchtimer/app.js

457 lines
10 KiB
JavaScript

var DEBUG = false;
var FILE = "touchtimer.data.json";
var main = () => {
var settings = readSettings();
var button1 = new Button({ x1: 1, y1: 35, x2: 58, y2: 70 }, 1);
var button2 = new Button({ x1: 60, y1: 35, x2: 116, y2: 70 }, 2);
var button3 = new Button({ x1: 118, y1: 35, x2: 174, y2: 70 }, 3);
var button4 = new Button({ x1: 1, y1: 72, x2: 58, y2: 105 }, 4);
var button5 = new Button({ x1: 60, y1: 72, x2: 116, y2: 105 }, 5);
var button6 = new Button({ x1: 118, y1: 72, x2: 174, y2: 105 }, 6);
var button7 = new Button({ x1: 1, y1: 107, x2: 58, y2: 140 }, 7);
var button8 = new Button({ x1: 60, y1: 107, x2: 116, y2: 140 }, 8);
var button9 = new Button({ x1: 118, y1: 107, x2: 174, y2: 140 }, 9);
var buttonOK = new Button({ x1: 1, y1: 142, x2: 58, y2: 174 }, "OK");
var button0 = new Button({ x1: 60, y1: 142, x2: 116, y2: 174 }, 0);
var buttonDelete = new Button({ x1: 118, y1: 142, x2: 174, y2: 174 }, "<-");
var timerNumberButtons = [
button1,
button2,
button3,
button4,
button5,
button6,
button7,
button8,
button9,
button0,
];
var timerInputButtons = [
button1,
button2,
button3,
button4,
button5,
button6,
button7,
button8,
button9,
buttonOK,
button0,
buttonDelete,
];
var buttonStartPause = new Button(
{ x1: 1, y1: 35, x2: 174, y2: 105 },
"START"
);
var buttonStop = new Button({ x1: 1, y1: 107, x2: 174, y2: 174 }, "STOP");
var timerRunningButtons = [buttonStartPause, buttonStop];
var timerEdit = new TimerEdit();
timerNumberButtons.forEach((numberButton) => {
numberButton.setOnClick((number) => {
log("number button clicked");
log(number);
timerEdit.appendNumber(number);
timerEdit.draw();
});
});
buttonDelete.setOnClick(() => {
log("delete button clicked");
timerEdit.removeNumber();
timerEdit.draw();
});
buttonOK.setOnClick(() => {
if (timerEdit.timeStr.length === 0) {
return;
}
g.clear();
timerEdit.draw();
timerInputButtons.forEach((button) => button.disable());
timerRunningButtons.forEach((button) => {
button.enable();
button.draw();
});
});
var timerIntervalId = undefined;
var buzzIntervalId = undefined;
var timerCountDown = undefined;
buttonStartPause.setOnClick(() => {
if (buttonStartPause.value === "PAUSE") {
if (timerCountDown) {
timerCountDown.pause();
}
buttonStartPause.value = "START";
buttonStartPause.draw();
if (timerIntervalId) {
clearInterval(timerIntervalId);
timerIntervalId = undefined;
}
if (buzzIntervalId) {
clearInterval(buzzIntervalId);
buzzIntervalId = undefined;
}
return;
}
if (buttonStartPause.value === "START") {
if (!timerCountDown) {
timerCountDown = new TimerCountDown(timerEdit.timeStr);
} else {
timerCountDown.unpause();
}
buttonStartPause.value = "PAUSE";
buttonStartPause.draw();
timerIntervalId = setInterval(() => {
timerCountDown.draw();
if (timerCountDown.isFinished()) {
buttonStartPause.value = "FINISHED!";
buttonStartPause.draw();
if (timerIntervalId) {
clearInterval(timerIntervalId);
timerIntervalId = undefined;
}
var buzzCount = 1;
Bangle.buzz(settings.buzzDuration * 1000, 1);
buzzIntervalId = setInterval(() => {
if (buzzCount >= settings.buzzCount) {
clearInterval(buzzIntervalId);
buzzIntervalId = undefined;
return;
} else {
Bangle.buzz(settings.buzzDuration * 1000, 1);
buzzCount++;
}
}, settings.buzzDuration * 1000 + settings.pauseBetween * 1000);
}
}, 1000);
return;
}
});
buttonStop.setOnClick(() => {
if (timerCountDown) {
timerCountDown = undefined;
}
if (timerIntervalId) {
clearInterval(timerIntervalId);
timerIntervalId = undefined;
}
if (buzzIntervalId) {
clearInterval(buzzIntervalId);
buzzIntervalId = undefined;
}
buttonStartPause.value = "START";
buttonStartPause.draw();
g.clear();
timerEdit.reset();
timerEdit.draw();
timerRunningButtons.forEach((button) => button.disable());
timerInputButtons.forEach((button) => {
button.enable();
button.draw();
});
});
// initalize
g.clear();
timerEdit.draw();
timerInputButtons.forEach((button) => {
button.enable();
button.draw();
});
};
// lib functions
var log = (message) => {
if (DEBUG) {
console.log(JSON.stringify(message));
}
};
var touchHandlers = [];
Bangle.on("touch", (_button, xy) => {
log("touch");
log(xy);
var x = Math.min(Math.max(xy.x, 1), 174);
var y = Math.min(Math.max(xy.y, 1), 174);
touchHandlers.forEach((touchHandler) => {
touchHandler(x, y);
});
});
var BUTTON_BORDER_WITH = 2;
class Button {
constructor(position, value) {
this.position = position;
this.value = value;
this.touchHandler = undefined;
this.highlightTimeoutId = undefined;
}
draw(highlight) {
g.setColor(g.theme.fg);
g.fillRect(
this.position.x1,
this.position.y1,
this.position.x2,
this.position.y2
);
if (highlight) {
g.setColor(g.theme.bgH);
} else {
g.setColor(g.theme.bg);
}
g.fillRect(
this.position.x1 + BUTTON_BORDER_WITH,
this.position.y1 + BUTTON_BORDER_WITH,
this.position.x2 - BUTTON_BORDER_WITH,
this.position.y2 - BUTTON_BORDER_WITH
);
g.setColor(g.theme.fg);
g.setFontAlign(0, 0);
g.setFont("Vector", 35);
g.drawString(
this.value,
this.position.x1 + (this.position.x2 - this.position.x1) / 2 + 2,
this.position.y1 + (this.position.y2 - this.position.y1) / 2 + 2
);
}
setOnClick(callback) {
this.touchHandler = (x, y) => {
if (
x >= this.position.x1 &&
x <= this.position.x2 &&
y >= this.position.y1 &&
y <= this.position.y2
) {
this.draw(true);
this.highlightTimeoutId = setTimeout(() => {
this.draw();
this.highlightTimeoutId = undefined;
}, 100);
setTimeout(() => callback(this.value), 25);
}
};
}
disable() {
log("disable button");
log(this.value);
var touchHandlerIndex = touchHandlers.indexOf(this.touchHandler);
if (touchHandlerIndex > -1) {
log("clearing touch handler");
touchHandlers.splice(touchHandlerIndex, 1);
}
if (this.highlightTimeoutId) {
log("clearing higlight timeout");
clearTimeout(this.highlightTimeoutId);
this.highlightTimeoutId = undefined;
}
}
enable() {
if (this.touchHandler) {
touchHandlers.push(this.touchHandler);
}
}
}
class TimerEdit {
constructor() {
this.timeStr = "";
}
appendNumber(number) {
if (number === 0 && this.timeStr.length === 0) {
return;
}
if (this.timeStr.length <= 6) {
this.timeStr = this.timeStr + number;
}
}
removeNumber() {
if (this.timeStr.length > 0) {
this.timeStr = this.timeStr.slice(0, -1);
}
}
reset() {
this.timeStr = "";
}
draw() {
log("drawing timer edit");
var timeStrPadded = this.timeStr.padStart(6, "0");
var timeStrDisplay =
"" +
timeStrPadded.slice(0, 2) +
"h " +
timeStrPadded.slice(2, 4) +
"m " +
timeStrPadded.slice(4, 6) +
"s";
log(timeStrPadded);
log(timeStrDisplay);
g.clearRect(0, 0, 176, 34);
g.setColor(g.theme.fg);
g.setFontAlign(-1, -1);
g.setFont("Vector:26x40");
g.drawString(timeStrDisplay, 2, 0);
}
}
class TimerCountDown {
constructor(timeStr) {
log("creating timer");
this.timeStr = timeStr;
log(this.timeStr);
this.start = Math.floor(Date.now() / 1000);
log(this.start);
this.pausedTime = undefined;
}
getAdjustedTime() {
var elapsedTime = Math.floor(Date.now() / 1000) - this.start;
var timeStrPadded = this.timeStr.padStart(6, "0");
var timeStrHours = parseInt(timeStrPadded.slice(0, 2), 10);
var timeStrMinutes = parseInt(timeStrPadded.slice(2, 4), 10);
var timeStrSeconds = parseInt(timeStrPadded.slice(4, 6), 10);
var hours = timeStrHours;
var minutes = timeStrMinutes;
var seconds = timeStrSeconds - elapsedTime;
if (seconds < 0) {
var neededMinutes = Math.ceil(Math.abs(seconds) / 60);
seconds = seconds + neededMinutes * 60;
minutes = minutes - neededMinutes;
if (minutes < 0) {
var neededHours = Math.ceil(Math.abs(minutes) / 60);
minutes = minutes + neededHours * 60;
hours = hours - neededHours;
}
}
if (hours < 0 || minutes < 0 || seconds < 0) {
hours = 0;
minutes = 0;
seconds = 0;
}
return { hours: hours, minutes: minutes, seconds: seconds };
}
pause() {
this.pausedTime = Math.floor(Date.now() / 1000);
}
unpause() {
if (this.pausedTime) {
this.start += Math.floor(Date.now() / 1000) - this.pausedTime;
}
this.pausedTime = undefined;
}
draw() {
log("drawing timer count down");
var adjustedTime = this.getAdjustedTime();
var hours = adjustedTime.hours;
var minutes = adjustedTime.minutes;
var seconds = adjustedTime.seconds;
var timeStrDisplay =
"" +
hours.toString().padStart(2, "0") +
"h " +
minutes.toString().padStart(2, "0") +
"m " +
seconds.toString().padStart(2, "0") +
"s";
log(timeStrDisplay);
g.clearRect(0, 0, 176, 34);
g.setColor(g.theme.fg);
g.setFontAlign(-1, -1);
g.setFont("Vector:26x40");
g.drawString(timeStrDisplay, 2, 0);
}
isFinished() {
var adjustedTime = this.getAdjustedTime();
var hours = adjustedTime.hours;
var minutes = adjustedTime.minutes;
var seconds = adjustedTime.seconds;
if (hours <= 0 && minutes <= 0 && seconds <= 0) {
return true;
} else {
return false;
}
}
}
var readSettings = () => {
log("reading settings");
var settings = require("Storage").readJSON(FILE, 1) || {
buzzCount: 3,
buzzDuration: 1,
pauseBetween: 1,
};
log(settings);
return settings;
};
// start main function
main();