From 85fdc4be5cfad91d53168023d4c9909272b5e3bb Mon Sep 17 00:00:00 2001 From: user Date: Mon, 9 Dec 2024 23:56:33 +0100 Subject: [PATCH 1/3] A Tea Timer application --- apps/ateatimer/ChangeLog | 1 + apps/ateatimer/app-icon.js | 1 + apps/ateatimer/app.js | 122 +++++++++++++++++++++++++++++++++++ apps/ateatimer/app.json | 1 + apps/ateatimer/app.png | Bin 0 -> 5053 bytes apps/ateatimer/metadata.json | 13 ++++ 6 files changed, 138 insertions(+) create mode 100644 apps/ateatimer/ChangeLog create mode 100644 apps/ateatimer/app-icon.js create mode 100644 apps/ateatimer/app.js create mode 100644 apps/ateatimer/app.json create mode 100644 apps/ateatimer/app.png create mode 100644 apps/ateatimer/metadata.json diff --git a/apps/ateatimer/ChangeLog b/apps/ateatimer/ChangeLog new file mode 100644 index 000000000..b0b91b94a --- /dev/null +++ b/apps/ateatimer/ChangeLog @@ -0,0 +1 @@ +0.01: First release \ No newline at end of file diff --git a/apps/ateatimer/app-icon.js b/apps/ateatimer/app-icon.js new file mode 100644 index 000000000..49ce16c2f --- /dev/null +++ b/apps/ateatimer/app-icon.js @@ -0,0 +1 @@ +atob("LjCI/hsbGxsbGxsbGxsbGxsbGwcHBwccHBwcHBwcHBwHBxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBwccHR0eHh4PDw8PDx4eHh0cBwcHGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBxwdHg8PDw8PDw8eHg8PDw8PDx4dHAcbGxsHGxsbGxsbGxsbGxsbGxsbGxsHHB0eDw8PHh0cGxoaGhoaGxwdHg8PDx4dHAcbGxsbGxsbGxsbGxsbGxsbGwcHHR4PDx4dGxkZGRkZGRkZGRkYGRkbHR4PDx4dBxsbGxsbGwcbGxsbGxsbGwccHQ8PHh0bGRkaGhsbGxoaGhoaGRkZGRkaHB4PDx0cBxsbGxsHGxsbGxsbGwccHg8PHhsZGRsHBxsbGhoaGhkZGRkZGRkZGRkaHg8PHhwHBwcbGxsbGxsbGwccHg8eHBkZGxwHGxoaGxoZBx4aGRsbGRkZGRkZGRkcHg8eHAcbGxsHGxsbGwccHg8eHBkaBxwHGxoZGx4bGR0dGRkdBxkZGRkZGRkZGQceHh4cBxsbBwcbGxscHg8PHBkaBwcbGhkZGRseGhkcHhkZHgcZGRkZGRkZGRkZBx4eHQcbBwcbGxsHHQ8PHBkaBwcaGRkZGRkZHR0ZGR0cGBseGRkZGRkZGRkZGRkcHh4dBwcHGxsHHA8PHRkaBxsaGRkZGRkZGQcdGRkdHBgbHhoZGRkZGRkZGRkZGh0eHhwHBxsbBx4PHhoZGxsaGRkZGRkZGRkcBxkaHBoZBxwZGRkZGRkZGRkZGRkaHR4dBwcbBx0PDxwZGwcaGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHhwbGwceDx4ZGhsbGhkZGhoaGxoaGhoaGhoaGhoaGhoaGhoaGRkZGRkZGRkaHR4dBwcdHg8HGRobGhkZGRsdHh4eHh4eHh4eHh4eHh4eHh4eHh0aGRkZGRkZGQceHhwHHQ8eGRkaGhkZGRodDw8PDw8PHg8PHBkeDx4eDw8PDw8PGxkZGRkZGRkaHh4cHB4PHBgaGhkZGRkaHQ8PDw8PHZQcDxr0HR4YGA8PDw8PDwcZGRkZGRkZGRweHRwPDxsZGhkZGRkZGh0PDw8PDx4HHg8a9B0PHBwPDw8PDw8dHAcaGRkZGRkbHh4dDx4aGRkZGRkZGRodDw8PBxwPDw8PGvQdDw8PHgcdDw8PDw8eHRsZGRkZGh4eHQ8dGRkZGRkZGRkaHQ8PHqwZHg8PDxr0HQ8PDx2rBw8PDx0dHg8eGhkZGRodHh4PHRkZGRkZGRkZGh0PDw8eHg8PDw8a3B0PDw8eHh4PDw8HGRodDxwZGRkaHR4eDxwZGRkZGRkZGRodDw8PDw8PDw8erNwaHh4eHh4eDw8PBxkZBx4dGRkZGRweHg8cGRkZGRkZGRkaHQ8PGxsPDw8PG5YY3KysrKwYGB0PDxsZGRseHhkZGRkcHh4eHBkZGRkZGRkZGh0PDxoaHg8PDxv0rNyVlZOrrKwcDx4bGRkdDx0ZGRkZHB4eHhwZGRkZGRkZGRkcDw8eHg8PDw8dGJMaHR4eHh4eDw8eBwcdHg8bGRkZGRweHR4cGRkZGRkZGRkZBx4PDx4eDw8PDx4dHg8PDw8eHg8PHh4eDx4cGRkZGRodHh0eHRkZGRkZGRkZGRoeDx4ZGh4PDw8PDw8PDw8drAcPHh4eHh0HGRkZGRkaHR4cHh4aGRkZGRkZGRkZHA8PHB0PDw8PDw8PDw8PHgcdDx0bGRkZGRkZGRkZGx4eHB4eGxkZGRkZGRkZGRoeDw8PHgceDw8PDw8dHQ8PDx4cGRkZGRkZGRkZGQceHgceHhwZGRkZGRkZGRkZGx4PDx2sHA8dGg8eGRkPDx4dGhgZGRkZGRkZGRkdHh0HHR4eGhkZGRkZGRkZGRkbHh4PHg8PG5MeDx4eDx4dGhkZGRkZGRkZGRkaHh4HBxweHhwZGRkZGRkZGRkZGRsdHh4PDx4cDw8PHh0HGRkZGRkZGRkZGRkZHA8eGgcHHR4dGhkZGRkZGRkZGRkZGhscHh4eHh4eHQcaGRkZGRkZGRkZGRkZGx4PHBkHBxweHhwaGRkZGhwdHR0dHR0dHR4eHh4eHh4dHR0dHR0dHRwZGRkZGh0PHhoYGxsHHR4eBxkZGRodDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8dGRkZGRweDxwYGRsbBwceHh0aGRkZGx4eHh4eHh4eHh4eHh4eHh4eHh4eHh4dGhkZGRseDx4ZGBkHBwcHHB4eHRoZGRkaBwcHBwcHBwcHBwcHBwcHBwcHBwcbGhkZGRoeHh4aGBkZBwcHGxscHh4dGhkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRodHh4bGBgZGQcHBwcbGxweHh0bGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRsdHh4HGBgZGRoHBwcHGxsbHB4eHRsZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHh4HGBgZGRoaBwcHBxsbGxsHHR4eHBoZGRkZGRkZGRkZGRkZGRkZGRkZGx0eHh0bGBgZGRoaGgcHBwcHGxsbGhsdHh4dHBsZGRkZGRkZGRkZGRkZGRobHB4eHh0aGBgZGRkaGhoHBwcHBwcHGxsaGgcdHh4dHQcbGhkZGRkZGRkaGxwdHh4eHRsZGBgZGRkaGhobGxsHGxsHBwcbGxoaGgcdHh4eHh0dHRwcHB0dHh4eHh4dGxkYGBgZGRkaGhobGxsbGxsbBwcHGxsbGhoZGRscHR0eHh4eHh4eHh4dHRwaGBgYGBkZGRoaGhobGxsbGxsbGwcHBwcbGxsaGhoZGRkaGwcHHBwcBxsaGRkYGBgYGRkZGhoaGhobGxsbGxsHBwcHBwcHBxsbGxsaGhoZGRkZGRgYGBgYGBgYGBkZGRkZGhoaGhsbGxsbGw==") \ No newline at end of file diff --git a/apps/ateatimer/app.js b/apps/ateatimer/app.js new file mode 100644 index 000000000..52af806a5 --- /dev/null +++ b/apps/ateatimer/app.js @@ -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(); + diff --git a/apps/ateatimer/app.json b/apps/ateatimer/app.json new file mode 100644 index 000000000..7304a3d42 --- /dev/null +++ b/apps/ateatimer/app.json @@ -0,0 +1 @@ +{ "duration": 240 } \ No newline at end of file diff --git a/apps/ateatimer/app.png b/apps/ateatimer/app.png new file mode 100644 index 0000000000000000000000000000000000000000..4c25f7d33b11a258ffef18af9b3419c9b80719d2 GIT binary patch literal 5053 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 Date: Fri, 13 Dec 2024 22:26:50 +0100 Subject: [PATCH 2/3] Refactored to use sched API --- apps/ateatimer/app.js | 85 +++++++++++++++++++++++------------- apps/ateatimer/metadata.json | 3 +- 2 files changed, 57 insertions(+), 31 deletions(-) diff --git a/apps/ateatimer/app.js b/apps/ateatimer/app.js index 52af806a5..6c2837c33 100644 --- a/apps/ateatimer/app.js +++ b/apps/ateatimer/app.js @@ -1,13 +1,12 @@ -// Tea Timer Application for Bangle.js 2 +// Tea Timer Application for Bangle.js 2 using sched library + 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"); @@ -51,42 +50,53 @@ function startTimer() { timerDuration = timeRemaining; saveDefaultDuration(); - timerInterval = setInterval(() => { - timeRemaining--; - drawTime(); + // Schedule a new timer using the sched library + require("sched").setAlarm("mytimer", { + msg: "Tea is ready!", + timer: timeRemaining * 1000, // Convert to milliseconds + vibrate: ".." // Default vibration pattern + }); - if (timeRemaining === 0 && !buzzInterval) { - // Start continuous vibration when timer reaches 0 - buzzInterval = setInterval(() => Bangle.buzz(500), 1000); - } - }, 1000); + // Ensure the scheduler updates + require("sched").reload(); + + // Start the secondary timer to update the display + setInterval(updateDisplay, 1000); } function resetTimer() { - if (timerInterval) { - clearInterval(timerInterval); - timerInterval = null; - } + // Cancel the existing timer + require("sched").setAlarm("mytimer", undefined); + require("sched").reload(); + 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 + timeRemaining += amount; + timeRemaining = Math.max(1, timeRemaining); // Ensure time doesn't go negative + print(timeRemaining); + if (timerRunning) { + // Update the existing timer with the new remaining time + let alarm = require("sched").getAlarm("mytimer"); + if (alarm) { + // Cancel the current alarm + require("sched").setAlarm("mytimer", undefined); + + // Set a new alarm with the updated time + require("sched").setAlarm("mytimer", { + msg: "Tea is ready!", + timer: timeRemaining * 1000, // Convert to milliseconds + vibrate: ".." // Default vibration pattern + }); + + // Reload the scheduler to apply changes + require("sched").reload(); + } } + drawTime(); } @@ -107,6 +117,22 @@ function handleTouch(x, y) { } } +// Function to update the display every second +function updateDisplay() { + if (timerRunning) { + let alarm = require("sched").getAlarm("mytimer"); + if (alarm) { + timeRemaining = Math.ceil(require("sched").getTimeToAlarm(alarm) / 1000); + } + drawTime(); + if (timeRemaining <= 0) { + timeRemaining = 0 + clearInterval(updateDisplay); + timerRunning = false; + } + } +} + // Handle physical button press for resetting timer setWatch(() => { resetTimer(); @@ -119,4 +145,3 @@ Bangle.on("touch", (zone, xy) => { // Draw the initial timer display drawTime(); - diff --git a/apps/ateatimer/metadata.json b/apps/ateatimer/metadata.json index 673419f0d..02c7fe338 100644 --- a/apps/ateatimer/metadata.json +++ b/apps/ateatimer/metadata.json @@ -9,5 +9,6 @@ "storage": [ {"name":"ateatimer.app.js","url":"app.js"}, {"name":"ateatimer.img","url":"app-icon.js","evaluate":true} - ] + ], + "dependencies": {"scheduler":"type"} } From 80173b98515926c8a69b59b836c8babd241f6ca7 Mon Sep 17 00:00:00 2001 From: vovcia Date: Sat, 14 Dec 2024 18:08:23 +0100 Subject: [PATCH 3/3] Change icon, rename internal timer, display running timer on app restart Start timer on button press Invert icon, update metadata Update ChangeLog --- apps/ateatimer/ChangeLog | 3 +- apps/ateatimer/app-icon.js | 2 +- apps/ateatimer/app.js | 59 +++++++++++++++++++++--------------- apps/ateatimer/metadata.json | 4 +-- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/apps/ateatimer/ChangeLog b/apps/ateatimer/ChangeLog index b0b91b94a..81da9fdce 100644 --- a/apps/ateatimer/ChangeLog +++ b/apps/ateatimer/ChangeLog @@ -1 +1,2 @@ -0.01: First release \ No newline at end of file +0.01: First release +0.02: Fix icon, utilize sched, show running timer on app relaunch \ No newline at end of file diff --git a/apps/ateatimer/app-icon.js b/apps/ateatimer/app-icon.js index 49ce16c2f..f80208ead 100644 --- a/apps/ateatimer/app-icon.js +++ b/apps/ateatimer/app-icon.js @@ -1 +1 @@ -atob("LjCI/hsbGxsbGxsbGxsbGxsbGwcHBwccHBwcHBwcHBwHBxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBwccHR0eHh4PDw8PDx4eHh0cBwcHGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsHBxwdHg8PDw8PDw8eHg8PDw8PDx4dHAcbGxsHGxsbGxsbGxsbGxsbGxsbGxsHHB0eDw8PHh0cGxoaGhoaGxwdHg8PDx4dHAcbGxsbGxsbGxsbGxsbGxsbGwcHHR4PDx4dGxkZGRkZGRkZGRkYGRkbHR4PDx4dBxsbGxsbGwcbGxsbGxsbGwccHQ8PHh0bGRkaGhsbGxoaGhoaGRkZGRkaHB4PDx0cBxsbGxsHGxsbGxsbGwccHg8PHhsZGRsHBxsbGhoaGhkZGRkZGRkZGRkaHg8PHhwHBwcbGxsbGxsbGwccHg8eHBkZGxwHGxoaGxoZBx4aGRsbGRkZGRkZGRkcHg8eHAcbGxsHGxsbGwccHg8eHBkaBxwHGxoZGx4bGR0dGRkdBxkZGRkZGRkZGQceHh4cBxsbBwcbGxscHg8PHBkaBwcbGhkZGRseGhkcHhkZHgcZGRkZGRkZGRkZBx4eHQcbBwcbGxsHHQ8PHBkaBwcaGRkZGRkZHR0ZGR0cGBseGRkZGRkZGRkZGRkcHh4dBwcHGxsHHA8PHRkaBxsaGRkZGRkZGQcdGRkdHBgbHhoZGRkZGRkZGRkZGh0eHhwHBxsbBx4PHhoZGxsaGRkZGRkZGRkcBxkaHBoZBxwZGRkZGRkZGRkZGRkaHR4dBwcbBx0PDxwZGwcaGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHhwbGwceDx4ZGhsbGhkZGhoaGxoaGhoaGhoaGhoaGhoaGhoaGRkZGRkZGRkaHR4dBwcdHg8HGRobGhkZGRsdHh4eHh4eHh4eHh4eHh4eHh4eHh0aGRkZGRkZGQceHhwHHQ8eGRkaGhkZGRodDw8PDw8PHg8PHBkeDx4eDw8PDw8PGxkZGRkZGRkaHh4cHB4PHBgaGhkZGRkaHQ8PDw8PHZQcDxr0HR4YGA8PDw8PDwcZGRkZGRkZGRweHRwPDxsZGhkZGRkZGh0PDw8PDx4HHg8a9B0PHBwPDw8PDw8dHAcaGRkZGRkbHh4dDx4aGRkZGRkZGRodDw8PBxwPDw8PGvQdDw8PHgcdDw8PDw8eHRsZGRkZGh4eHQ8dGRkZGRkZGRkaHQ8PHqwZHg8PDxr0HQ8PDx2rBw8PDx0dHg8eGhkZGRodHh4PHRkZGRkZGRkZGh0PDw8eHg8PDw8a3B0PDw8eHh4PDw8HGRodDxwZGRkaHR4eDxwZGRkZGRkZGRodDw8PDw8PDw8erNwaHh4eHh4eDw8PBxkZBx4dGRkZGRweHg8cGRkZGRkZGRkaHQ8PGxsPDw8PG5YY3KysrKwYGB0PDxsZGRseHhkZGRkcHh4eHBkZGRkZGRkZGh0PDxoaHg8PDxv0rNyVlZOrrKwcDx4bGRkdDx0ZGRkZHB4eHhwZGRkZGRkZGRkcDw8eHg8PDw8dGJMaHR4eHh4eDw8eBwcdHg8bGRkZGRweHR4cGRkZGRkZGRkZBx4PDx4eDw8PDx4dHg8PDw8eHg8PHh4eDx4cGRkZGRodHh0eHRkZGRkZGRkZGRoeDx4ZGh4PDw8PDw8PDw8drAcPHh4eHh0HGRkZGRkaHR4cHh4aGRkZGRkZGRkZHA8PHB0PDw8PDw8PDw8PHgcdDx0bGRkZGRkZGRkZGx4eHB4eGxkZGRkZGRkZGRoeDw8PHgceDw8PDw8dHQ8PDx4cGRkZGRkZGRkZGQceHgceHhwZGRkZGRkZGRkZGx4PDx2sHA8dGg8eGRkPDx4dGhgZGRkZGRkZGRkdHh0HHR4eGhkZGRkZGRkZGRkbHh4PHg8PG5MeDx4eDx4dGhkZGRkZGRkZGRkaHh4HBxweHhwZGRkZGRkZGRkZGRsdHh4PDx4cDw8PHh0HGRkZGRkZGRkZGRkZHA8eGgcHHR4dGhkZGRkZGRkZGRkZGhscHh4eHh4eHQcaGRkZGRkZGRkZGRkZGx4PHBkHBxweHhwaGRkZGhwdHR0dHR0dHR4eHh4eHh4dHR0dHR0dHRwZGRkZGh0PHhoYGxsHHR4eBxkZGRodDw8PDw8PDw8PDw8PDw8PDw8PDw8PDw8dGRkZGRweDxwYGRsbBwceHh0aGRkZGx4eHh4eHh4eHh4eHh4eHh4eHh4eHh4dGhkZGRseDx4ZGBkHBwcHHB4eHRoZGRkaBwcHBwcHBwcHBwcHBwcHBwcHBwcbGhkZGRoeHh4aGBkZBwcHGxscHh4dGhkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRodHh4bGBgZGQcHBwcbGxweHh0bGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGRsdHh4HGBgZGRoHBwcHGxsbHB4eHRsZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGQceHh4HGBgZGRoaBwcHBxsbGxsHHR4eHBoZGRkZGRkZGRkZGRkZGRkZGRkZGx0eHh0bGBgZGRoaGgcHBwcHGxsbGhsdHh4dHBsZGRkZGRkZGRkZGRkZGRobHB4eHh0aGBgZGRkaGhoHBwcHBwcHGxsaGgcdHh4dHQcbGhkZGRkZGRkaGxwdHh4eHRsZGBgZGRkaGhobGxsHGxsHBwcbGxoaGgcdHh4eHh0dHRwcHB0dHh4eHh4dGxkYGBgZGRkaGhobGxsbGxsbBwcHGxsbGhoZGRscHR0eHh4eHh4eHh4dHRwaGBgYGBkZGRoaGhobGxsbGxsbGwcHBwcbGxsaGhoZGRkaGwcHHBwcBxsaGRkYGBgYGRkZGhoaGhobGxsbGxsHBwcHBwcHBxsbGxsaGhoZGRkZGRgYGBgYGBgYGBkZGRkZGhoaGhsbGxsbGw==") \ No newline at end of file +require("heatshrink").decompress(atob("mEwgIKHgwFKo0gAofmsALEGR0H/+f//+gEP/4ACAoXAn4FDAQn8g0DAoX4g0BAoXx4E4AoXhAoN/8EP4AzBn/4h/IC4M//kPzgjBz/+h+MAoMfj0PNYUfh4FDh8HAo0wg/454RBmBDBAoRnBCIIjCAAMPF4IFDHYOIgEBj5HBzkAIIPAIIIFBn4hBLIU+AoPgwEQvwFBOIX8CgP5w0RAoSJC/AsB/0EJwIgB/+Aj/wAoN/VgPgQwQFBwBKCXAQWBAAfgAoocCAoQcCAAPAj7XEcYIABcYLIBAAJBBA==")) \ No newline at end of file diff --git a/apps/ateatimer/app.js b/apps/ateatimer/app.js index 6c2837c33..9322d4e46 100644 --- a/apps/ateatimer/app.js +++ b/apps/ateatimer/app.js @@ -44,14 +44,21 @@ function drawTime() { function startTimer() { if (timerRunning) return; + if (timeRemaining == 0) return; timerRunning = true; // Save the default duration on timer start timerDuration = timeRemaining; saveDefaultDuration(); + scheduleTimer(); + // Start the secondary timer to update the display + setInterval(updateDisplay, 1000); +} + +function scheduleTimer() { // Schedule a new timer using the sched library - require("sched").setAlarm("mytimer", { + require("sched").setAlarm("ateatimer", { msg: "Tea is ready!", timer: timeRemaining * 1000, // Convert to milliseconds vibrate: ".." // Default vibration pattern @@ -59,14 +66,11 @@ function startTimer() { // Ensure the scheduler updates require("sched").reload(); - - // Start the secondary timer to update the display - setInterval(updateDisplay, 1000); } function resetTimer() { // Cancel the existing timer - require("sched").setAlarm("mytimer", undefined); + require("sched").setAlarm("ateatimer", undefined); require("sched").reload(); timerRunning = false; @@ -75,25 +79,21 @@ function resetTimer() { } function adjustTime(amount) { + if (-amount > timeRemaining) { + // Return if result will be negative + return; + } timeRemaining += amount; - timeRemaining = Math.max(1, timeRemaining); // Ensure time doesn't go negative - print(timeRemaining); + timeRemaining = Math.max(0, timeRemaining); // Ensure time doesn't go negative if (timerRunning) { // Update the existing timer with the new remaining time - let alarm = require("sched").getAlarm("mytimer"); + let alarm = require("sched").getAlarm("ateatimer"); if (alarm) { // Cancel the current alarm - require("sched").setAlarm("mytimer", undefined); + require("sched").setAlarm("ateatimer", undefined); // Set a new alarm with the updated time - require("sched").setAlarm("mytimer", { - msg: "Tea is ready!", - timer: timeRemaining * 1000, // Convert to milliseconds - vibrate: ".." // Default vibration pattern - }); - - // Reload the scheduler to apply changes - require("sched").reload(); + scheduleTimer(); } } @@ -120,13 +120,11 @@ function handleTouch(x, y) { // Function to update the display every second function updateDisplay() { if (timerRunning) { - let alarm = require("sched").getAlarm("mytimer"); - if (alarm) { - timeRemaining = Math.ceil(require("sched").getTimeToAlarm(alarm) / 1000); - } + let alarm = require("sched").getAlarm("ateatimer"); + timeRemaining = Math.floor(require("sched").getTimeToAlarm(alarm) / 1000); drawTime(); if (timeRemaining <= 0) { - timeRemaining = 0 + timeRemaining = 0; clearInterval(updateDisplay); timerRunning = false; } @@ -135,7 +133,11 @@ function updateDisplay() { // Handle physical button press for resetting timer setWatch(() => { - resetTimer(); + if (timerRunning) { + resetTimer(); + } else { + startTimer(); + } }, BTN1, { repeat: true, edge: "falling" }); // Handle touch @@ -143,5 +145,12 @@ Bangle.on("touch", (zone, xy) => { handleTouch(xy.x, xy.y, false); }); -// Draw the initial timer display -drawTime(); +let isRunning = require("sched").getAlarm("ateatimer"); +if (isRunning) { + timerRunning = true; + // Start the timer to update the display + setInterval(updateDisplay, 1000); +} else { + // Draw the initial timer display + drawTime(); +} \ No newline at end of file diff --git a/apps/ateatimer/metadata.json b/apps/ateatimer/metadata.json index 02c7fe338..c4b8a1458 100644 --- a/apps/ateatimer/metadata.json +++ b/apps/ateatimer/metadata.json @@ -2,8 +2,8 @@ "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.", + "version":"0.02", + "description": "Simple app for setting timers for tea. Touch up and down to change time, and time or button to start counting. When timer is running, button will stop timer and reset counter to last used value.", "tags": "timer", "supports": ["BANGLEJS2"], "storage": [