mirror of https://github.com/espruino/BangleApps
244 lines
7.0 KiB
JavaScript
244 lines
7.0 KiB
JavaScript
/*
|
|
* Burn: Calories Counter for Bangle.js (Espruino). Based on the original Counter app.
|
|
* Features:
|
|
* - Persistent counter: saved to a file.
|
|
* - Daily reset: counter resets each day.
|
|
* - Adjustable increment value.
|
|
*
|
|
* Bangle.js 1 Controls:
|
|
* - BTN1: Increase (or tap right)
|
|
* - BTN3: Decrease (or tap left)
|
|
* - Press BTN2: Change increment
|
|
*
|
|
* Bangle.js 2 Controls:
|
|
* - Swipe up: Increase
|
|
* - Swipe down: Decrease
|
|
* - Press BTN: Change increment
|
|
*/
|
|
|
|
// File variable to handle file operations
|
|
let file;
|
|
|
|
// Check if the hardware version is Bangle.js 2
|
|
const BANGLEJS2 = process.env.HWVERSION == 2;
|
|
|
|
// Importing the Storage module for file operations
|
|
const Storage = require("Storage");
|
|
|
|
// File path for the counter data
|
|
const PATH = "kcal.txt";
|
|
|
|
// Function to get the current date as a string
|
|
function dayString() {
|
|
const date = new Date();
|
|
// Month is 0-indexed, so we add 1 to get the correct month number
|
|
return `${date.getMonth() + 1}-${date.getDate()}-${date.getFullYear()}`;
|
|
}
|
|
|
|
// Counter object to keep track of the count and the date
|
|
let counter = { count: 0, date: dayString() };
|
|
|
|
// Function to read the counter from the file
|
|
function readCounterFromFile() {
|
|
try {
|
|
// Open the file in read mode
|
|
file = Storage.open(PATH, "r");
|
|
let line = file.readLine();
|
|
|
|
// If the file has content, parse it and update the counter
|
|
if (line) {
|
|
let splitLine = line.trim().split(",");
|
|
counter = { count: parseInt(splitLine[0]), date: splitLine[1] };
|
|
}
|
|
} catch (err) {
|
|
// If the file does not exist, the counter will remain 0
|
|
}
|
|
}
|
|
|
|
// Function to write the counter to the file
|
|
function writeCounterToFile() {
|
|
// Open the file in write mode
|
|
file = Storage.open(PATH, "w");
|
|
// Write the counter and date to the file
|
|
file.write(counter.count.toString() + "," + counter.date + "\n");
|
|
}
|
|
|
|
// Function to reset the counter
|
|
function resetCounter() {
|
|
// Reset the counter to 0 and update the date
|
|
counter = { count: 0, date: dayString() };
|
|
}
|
|
|
|
// Function to update the counter value
|
|
function updateCounterValue(value) {
|
|
// Update the counter with the new value, ensuring it's not less than 0
|
|
counter = { count: Math.max(0, value), date: dayString() };
|
|
}
|
|
|
|
// Function to update the counter
|
|
function updateCounter(value) {
|
|
// If the date has changed, reset the counter
|
|
if (counter.date != dayString()) {
|
|
resetCounter();
|
|
} else {
|
|
// Otherwise, update the counter value
|
|
updateCounterValue(value);
|
|
}
|
|
|
|
// Write the updated counter to the file
|
|
writeCounterToFile();
|
|
// Update the screen with the new counter value
|
|
updateScreen();
|
|
}
|
|
|
|
// Function to set a watch on a button to update the counter when pressed
|
|
function counterButtonWatch(button, increment) {
|
|
setWatch(
|
|
() => {
|
|
// If the button is for incrementing, or the counter is greater than 0, update the counter
|
|
if (increment || counter.count > 0) {
|
|
updateCounter(
|
|
counter.count + (increment ? getInterval() : -getInterval())
|
|
);
|
|
// Update the screen with the new counter value
|
|
updateScreen();
|
|
}
|
|
},
|
|
button,
|
|
{ repeat: true }
|
|
);
|
|
}
|
|
|
|
// Function to create interval functions
|
|
const createIntervalFunctions = function () {
|
|
// Array of intervals
|
|
const intervals = [50, 100, 200, 10];
|
|
// Current location in the intervals array
|
|
let location = 0;
|
|
|
|
// Function to get the current interval
|
|
const getInterval = function () {
|
|
return intervals[location];
|
|
};
|
|
|
|
// Function to rotate the increment
|
|
const rotateIncrement = function () {
|
|
// Update the location to the next index in the intervals array, wrapping around if necessary
|
|
location = (location + 1) % intervals.length;
|
|
// Update the screen with the new increment
|
|
updateScreen();
|
|
};
|
|
|
|
// Return the getInterval and rotateIncrement functions
|
|
return { getInterval, rotateIncrement };
|
|
};
|
|
|
|
// Create the interval functions
|
|
const intervalFunctions = createIntervalFunctions();
|
|
const getInterval = intervalFunctions.getInterval;
|
|
const rotateIncrement = intervalFunctions.rotateIncrement;
|
|
|
|
// Function to update the screen
|
|
function updateScreen() {
|
|
// Clear the screen area for the counter
|
|
g.clearRect(0, 50, 250, BANGLEJS2 ? 130 : 150)
|
|
.setBgColor(g.theme.bg)
|
|
.setColor(g.theme.fg)
|
|
.setFont("Vector", 40)
|
|
.setFontAlign(0, 0)
|
|
// Draw the counter value
|
|
.drawString(Math.floor(counter.count), g.getWidth() / 2, 100)
|
|
.setFont("6x8")
|
|
// Clear the screen area for the increment
|
|
.clearRect(g.getWidth() / 2 - 50, 140, g.getWidth() / 2 + 50, 160)
|
|
// Draw the increment value
|
|
.drawString("Increment: " + getInterval(), g.getWidth() / 2, 150);
|
|
|
|
// If the hardware version is Bangle.js 1, draw the increment and decrement buttons
|
|
if (!BANGLEJS2) {
|
|
g.drawString("-", 45, 100).drawString("+", 185, 100);
|
|
}
|
|
}
|
|
|
|
// If the hardware version is Bangle.js 2, set up the drag handling and button watch
|
|
|
|
let drag;
|
|
|
|
if (BANGLEJS2) {
|
|
// Set up drag handling
|
|
Bangle.on("drag", (e) => {
|
|
// If this is the start of a drag, record the initial coordinates
|
|
if (!drag) {
|
|
drag = { x: e.x, y: e.y };
|
|
return;
|
|
}
|
|
|
|
// If the button is still being pressed, ignore this event
|
|
if (e.b) return;
|
|
|
|
// Calculate the change in x and y from the start of the drag
|
|
const dx = e.x - drag.x;
|
|
const dy = e.y - drag.y;
|
|
// Reset the drag start coordinates
|
|
drag = null;
|
|
|
|
// Determine if the drag is primarily horizontal or vertical
|
|
const isHorizontalDrag = Math.abs(dx) > Math.abs(dy) + 10;
|
|
const isVerticalDrag = Math.abs(dy) > Math.abs(dx) + 10;
|
|
|
|
// If the drag is primarily horizontal, ignore it
|
|
if (isHorizontalDrag) {
|
|
return;
|
|
}
|
|
|
|
// If the drag is primarily vertical, update the counter
|
|
if (isVerticalDrag) {
|
|
// If the drag is downwards and the counter is greater than 0, decrease the counter
|
|
if (dy > 0 && counter.count > 0) {
|
|
updateCounter(counter.count - getInterval());
|
|
} else if (dy < 0) {
|
|
// If the drag is upwards, increase the counter
|
|
updateCounter(counter.count + getInterval());
|
|
}
|
|
// Update the screen with the new counter value
|
|
updateScreen();
|
|
}
|
|
});
|
|
|
|
// Set a watch on the button to rotate the increment when pressed
|
|
setWatch(rotateIncrement, BTN1, { repeat: true });
|
|
} else {
|
|
// If the hardware version is Bangle.js 1, set up the button watches
|
|
|
|
// Set watch on button to increase the counter
|
|
counterButtonWatch(BTN1, true);
|
|
counterButtonWatch(BTN5, true); // screen tap
|
|
// Set watch on button to decrease the counter
|
|
counterButtonWatch(BTN3, false);
|
|
counterButtonWatch(BTN4, false); // screen tap
|
|
|
|
// Set a watch on button to rotate the increment when pressed
|
|
setWatch(
|
|
() => {
|
|
rotateIncrement();
|
|
},
|
|
BTN2,
|
|
{ repeat: true }
|
|
);
|
|
}
|
|
|
|
// clear the screen
|
|
g.clear();
|
|
|
|
// Set the background and foreground colors
|
|
g.setBgColor(g.theme.bg).setColor(g.theme.fg);
|
|
|
|
// Load and draw the widgets
|
|
Bangle.loadWidgets();
|
|
Bangle.drawWidgets();
|
|
|
|
// Read the counter from the file
|
|
readCounterFromFile();
|
|
// Update the screen with the counter value
|
|
updateScreen();
|