mirror of https://github.com/espruino/BangleApps
A Tea Timer application
parent
1ec19d47b1
commit
85fdc4be5c
|
@ -0,0 +1 @@
|
|||
0.01: First release
|
|
@ -0,0 +1 @@
|
|||
atob("LjCI/hsbGxsbGxsbGxsbGxsbGwcHBwccHBwcHBwcHBwHBxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBwccHR0eHh4PDw8PDx4eHh0cBwcHGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBxwdHg8PDw8PDw8eHg8PDw8PDx4dHAcbGxsHGxsbGxsbGxsbGxsbGxsbGxsHHB0eDw8PHh0cGxoaGhoaGxwdHg8PDx4dHAcbGxsbGxsbGxsbGxsbGxsbGwcHHR4PDx4dGxkZGRkZGRkZGRkYGRkbHR4PDx4dBxsbGxsbGwcbGxsbGxsbGwccHQ8PHh0bGRkaGhsbGxoaGhoaGRkZGRkaHB4PDx0cBxsbGxsHGxsbGxsbGwccHg8PHhsZGRsHBxsbGhoaGhkZGRkZGRkZGRkaHg8PHhwHBwcbGxsbGxsbGwccHg8eHBkZGxwHGxoaGxoZBx4aGRsbGRkZGRkZGRkcHg8eHAcbGxsHGxsbGwccHg8eHBkaBxwHGxoZGx4bGR0dGRkdBxkZGRkZGRkZGQceHh4cBxsbBwcbGxscHg8PHBkaBwcbGhkZGRseGhkcHhkZHgcZGRkZGRkZGRkZBx4eHQcbBwcbGxsHHQ8PHBkaBwcaGRkZGRkZHR0ZGR0cGBseGRkZGRkZGRkZGRkcHh4dBwcHGxsHHA8PHRkaBxsaGRkZGRkZGQcdGRkdHBgbHhoZGRkZGRkZGRkZGh0eHhwHBxsbBx4PHhoZGxsaGRkZGRkZGRkcBxkaHBoZBxwZGRkZGRkZGRkZGRkaHR4dBwcbBx0PDxwZGwcaGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHhwbGwceDx4ZGhsbGhkZGhoaGxoaGhoaGhoaGhoaGhoaGhoaGRkZGRkZGRkaHR4dBwcdHg8HGRobGhkZGRsdHh4eHh4eHh4eHh4eHh4eHh4eHh0aGRkZGRkZGQceHhwHHQ8eGRkaGhkZGRodDw8PDw8PHg8PHBkeDx4eDw8PDw8PGxkZGRkZGRkaHh4cHB4PHBgaGhkZGRkaHQ8PDw8PHZQcDxr0HR4YGA8PDw8PDwcZGRkZGRkZGRweHRwPDxsZGhkZGRkZGh0PDw8PDx4HHg8a9B0PHBwPDw8PDw8dHAcaGRkZGRkbHh4dDx4aGRkZGRkZGRodDw8PBxwPDw8PGvQdDw8PHgcdDw8PDw8eHRsZGRkZGh4eHQ8dGRkZGRkZGRkaHQ8PHqwZHg8PDxr0HQ8PDx2rBw8PDx0dHg8eGhkZGRodHh4PHRkZGRkZGRkZGh0PDw8eHg8PDw8a3B0PDw8eHh4PDw8HGRodDxwZGRkaHR4eDxwZGRkZGRkZGRodDw8PDw8PDw8erNwaHh4eHh4eDw8PBxkZBx4dGRkZGRweHg8cGRkZGRkZGRkaHQ8PGxsPDw8PG5YY3KysrKwYGB0PDxsZGRseHhkZGRkcHh4eHBkZGRkZGRkZGh0PDxoaHg8PDxv0rNyVlZOrrKwcDx4bGRkdDx0ZGRkZHB4eHhwZGRkZGRkZGRkcDw8eHg8PDw8dGJMaHR4eHh4eDw8eBwcdHg8bGRkZGRweHR4cGRkZGRkZGRkZBx4PDx4eDw8PDx4dHg8PDw8eHg8PHh4eDx4cGRkZGRodHh0eHRkZGRkZGRkZGRoeDx4ZGh4PDw8PDw8PDw8drAcPHh4eHh0HGRkZGRkaHR4cHh4aGRkZGRkZGRkZHA8PHB0PDw8PDw8PDw8PHgcdDx0bGRkZGRkZGRkZGx4eHB4eGxkZGRkZGRkZGRoeDw8PHgceDw8PDw8dHQ8PDx4cGRkZGRkZGRkZGQceHgceHhwZGRkZGRkZGRkZGx4PDx2sHA8dGg8eGRkPDx4dGhgZGRkZGRkZGRkdHh0HHR4eGhkZGRkZGRkZGRkbHh4PHg8PG5MeDx4eDx4dGhkZGRkZGRkZGRkaHh4HBxweHhwZGRkZGRkZGRkZGRsdHh4PDx4cDw8PHh0HGRkZGRkZGRkZGRkZHA8eGgcHHR4dGhkZGRkZGRkZGRkZGhscHh4eHh4eHQcaGRkZGRkZGRkZGRkZGx4PHBkHBxweHhwaGRkZGhwdHR0dHR0dHR4eHh4eHh4dHR0dHR0dHRwZGRkZGh0PHhoYGxsHHR4eBxkZGRodDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8dGRkZGRweDxwYGRsbBwceHh0aGRkZGx4eHh4eHh4eHh4eHh4eHh4eHh4eHh4dGhkZGRseDx4ZGBkHBwcHHB4eHRoZGRkaBwcHBwcHBwcHBwcHBwcHBwcHBwcbGhkZGRoeHh4aGBkZBwcHGxscHh4dGhkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRodHh4bGBgZGQcHBwcbGxweHh0bGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRsdHh4HGBgZGRoHBwcHGxsbHB4eHRsZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHh4HGBgZGRoaBwcHBxsbGxsHHR4eHBoZGRkZGRkZGRkZGRkZGRkZGRkZGx0eHh0bGBgZGRoaGgcHBwcHGxsbGhsdHh4dHBsZGRkZGRkZGRkZGRkZGRobHB4eHh0aGBgZGRkaGhoHBwcHBwcHGxsaGgcdHh4dHQcbGhkZGRkZGRkaGxwdHh4eHRsZGBgZGRkaGhobGxsHGxsHBwcbGxoaGgcdHh4eHh0dHRwcHB0dHh4eHh4dGxkYGBgZGRkaGhobGxsbGxsbBwcHGxsbGhoZGRscHR0eHh4eHh4eHh4dHRwaGBgYGBkZGRoaGhobGxsbGxsbGwcHBwcbGxsaGhoZGRkaGwcHHBwcBxsaGRkYGBgYGRkZGhoaGhobGxsbGxsHBwcHBwcHBxsbGxsaGhoZGRkZGRgYGBgYGBgYGBkZGRkZGhoaGhsbGxsbGw==")
|
|
@ -0,0 +1,122 @@
|
|||
// Tea Timer Application for Bangle.js 2
|
||||
let timerDuration = (() => {
|
||||
let file = require("Storage").open("ateatimer.data", "r");
|
||||
let data = file.read(4); // Assuming 4 bytes for storage
|
||||
return data ? parseInt(data, 10) : 4 * 60; // Default to 4 minutes
|
||||
})();
|
||||
let timeRemaining = timerDuration;
|
||||
let timerRunning = false;
|
||||
let buzzInterval = null; // Interval for buzzing when timer reaches 0
|
||||
let timerInterval = null; // Interval for timer countdown
|
||||
|
||||
function saveDefaultDuration() {
|
||||
let file = require("Storage").open("ateatimer.data", "w");
|
||||
file.write(timerDuration.toString());
|
||||
}
|
||||
|
||||
function drawTime() {
|
||||
g.clear();
|
||||
g.setFont("Vector", 40);
|
||||
g.setFontAlign(0, 0); // Center align
|
||||
|
||||
const minutes = Math.floor(Math.abs(timeRemaining) / 60);
|
||||
const seconds = Math.abs(timeRemaining) % 60;
|
||||
const sign = timeRemaining < 0 ? "-" : "";
|
||||
const timeStr = `${sign}${minutes}:${seconds.toString().padStart(2, '0')}`;
|
||||
|
||||
g.drawString(timeStr, g.getWidth() / 2, g.getHeight() / 2);
|
||||
|
||||
// Draw Increase button (triangle pointing up)
|
||||
g.fillPoly([
|
||||
g.getWidth() / 2, g.getHeight() / 2 - 80, // Top vertex
|
||||
g.getWidth() / 2 - 20, g.getHeight() / 2 - 60, // Bottom-left vertex
|
||||
g.getWidth() / 2 + 20, g.getHeight() / 2 - 60 // Bottom-right vertex
|
||||
]);
|
||||
|
||||
// Draw Decrease button (triangle pointing down)
|
||||
g.fillPoly([
|
||||
g.getWidth() / 2, g.getHeight() / 2 + 80, // Bottom vertex
|
||||
g.getWidth() / 2 - 20, g.getHeight() / 2 + 60, // Top-left vertex
|
||||
g.getWidth() / 2 + 20, g.getHeight() / 2 + 60 // Top-right vertex
|
||||
]);
|
||||
|
||||
g.flip();
|
||||
}
|
||||
|
||||
function startTimer() {
|
||||
if (timerRunning) return;
|
||||
timerRunning = true;
|
||||
|
||||
// Save the default duration on timer start
|
||||
timerDuration = timeRemaining;
|
||||
saveDefaultDuration();
|
||||
|
||||
timerInterval = setInterval(() => {
|
||||
timeRemaining--;
|
||||
drawTime();
|
||||
|
||||
if (timeRemaining === 0 && !buzzInterval) {
|
||||
// Start continuous vibration when timer reaches 0
|
||||
buzzInterval = setInterval(() => Bangle.buzz(500), 1000);
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
function resetTimer() {
|
||||
if (timerInterval) {
|
||||
clearInterval(timerInterval);
|
||||
timerInterval = null;
|
||||
}
|
||||
timerRunning = false;
|
||||
timeRemaining = timerDuration;
|
||||
stopBuzzing();
|
||||
drawTime();
|
||||
}
|
||||
|
||||
function stopBuzzing() {
|
||||
if (buzzInterval) {
|
||||
clearInterval(buzzInterval);
|
||||
buzzInterval = null;
|
||||
}
|
||||
}
|
||||
|
||||
function adjustTime(amount) {
|
||||
if (!timerRunning) {
|
||||
timeRemaining += amount;
|
||||
timeRemaining = Math.floor(timeRemaining / 60) * 60; // Round to full minutes
|
||||
} else {
|
||||
timeRemaining += amount; // Allow adjustments during running
|
||||
}
|
||||
drawTime();
|
||||
}
|
||||
|
||||
function handleTouch(x, y) {
|
||||
const centerY = g.getHeight() / 2;
|
||||
|
||||
if (y < centerY - 40) {
|
||||
// Increase button area
|
||||
adjustTime(60);
|
||||
} else if (y > centerY + 40) {
|
||||
// Decrease button area
|
||||
adjustTime(-60);
|
||||
} else {
|
||||
// Center area
|
||||
if (!timerRunning) {
|
||||
startTimer();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Handle physical button press for resetting timer
|
||||
setWatch(() => {
|
||||
resetTimer();
|
||||
}, BTN1, { repeat: true, edge: "falling" });
|
||||
|
||||
// Handle touch
|
||||
Bangle.on("touch", (zone, xy) => {
|
||||
handleTouch(xy.x, xy.y, false);
|
||||
});
|
||||
|
||||
// Draw the initial timer display
|
||||
drawTime();
|
||||
|
|
@ -0,0 +1 @@
|
|||
{ "duration": 240 }
|
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
|
@ -0,0 +1,13 @@
|
|||
{ "id": "ateatimer",
|
||||
"name": "A Tea Timer",
|
||||
"shortName":"A Tea Timer",
|
||||
"icon": "app.png",
|
||||
"version":"0.01",
|
||||
"description": "Simple app for setting countdown timers for tea. Press up and down to change time, and touch time to start counting. Button will stop countdown and reset counter to last used value.",
|
||||
"tags": "timer",
|
||||
"supports": ["BANGLEJS2"],
|
||||
"storage": [
|
||||
{"name":"ateatimer.app.js","url":"app.js"},
|
||||
{"name":"ateatimer.img","url":"app-icon.js","evaluate":true}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue