BangleApps_old/apps/onewordclock/app.js

170 lines
3.9 KiB
JavaScript

{
// timeout used to update every minute
var drawTimeout;
require('Font4x5Numeric').add(Graphics);
// Load settings
const SETTINGS_FILE = "onewordclock.settings.json";
let settings = {
mode: "Named",
smallNumeralClock: true
};
let stored = require('Storage').readJSON(SETTINGS_FILE, 1) || {};
for (const key in stored) {
settings[key] = stored[key];
}
// https://www.espruino.com/Bangle.js+Locale
// schedule a draw for the next 3 minutes
const queueDraw = () => {
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = setTimeout(() => {
drawTimeout = undefined;
draw();
}, 180000 - (Date.now() % 180000));
};
const HOUR_WORDS = [
'Midnight',
'Early',
'Quiet',
'Still',
'Dawn',
'Earlybird',
'Sunrise',
'Morning',
'Bright',
'Active',
'Busy',
'Pre-noon',
'Noon',
'Post-noon',
'Afternoon',
'Siesta',
'Breezy',
'Evening',
'Twilight',
'Dinner',
'Cozy',
'Relax',
'Quietude',
'Night',
];
const HOURS = [
'Twelve',
'One',
'Two',
'Three',
'Four',
'Five',
'Six',
'Seven',
'Eight',
'Nine',
'Ten',
'Eleven',
'Twelve',
'Thirteen',
'Fourteen',
'Fifteen',
'Sixteen',
'Seventeen',
'Eighteen',
'Nineteen',
'Twenty',
'Twentyone',
'Twentytwo',
'Twentythree'
];
const wordFromHour = (h) => {
return settings.mode === "Named" ? HOUR_WORDS[h] : HOURS[h];
};
const wordsFromDayMonth = (day) => {
const DAY_WORD_ARRAY = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
return DAY_WORD_ARRAY[day];
};
const draw = () => {
var x = g.getWidth() / 2;
var y = g.getHeight() / 2;
g.reset();
var d = new Date();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
var day = d.getDay();
var timeStr = wordFromHour(h);
var dateStr = wordsFromDayMonth(day);
// draw time
g.setBgColor(g.theme.bg);
g.clear();
// Draw military time at the top only if smallNumeralClock is true
if (settings.smallNumeralClock) {
g.setColor(g.theme.bg2);
g.setFontAlign(0, 0).setFont('4x5Numeric', 2);
var militaryTime = ('0' + h).slice(-2) + ('0' + m).slice(-2);
g.drawString(militaryTime, x, 20);
}
g.setFontAlign(-1, 0).setFont('Vector', 36);
// Calculate exact progress through the hour (0 to 1)
var progress = (m + s / 60) / 60;
// Get total width of the word and starting position
var totalWidth = g.stringWidth(timeStr);
var startX = x - totalWidth / 2;
// Calculate the exact position where the color should change
var colorChangeX = startX + totalWidth * progress;
// First draw the entire text in the uncolored version
g.setColor(g.theme.fg2);
g.drawString(timeStr, startX, y);
// Then draw the colored portion
if (progress > 0) {
g.setClipRect(startX, 0, colorChangeX, g.getHeight());
g.setColor(g.theme.bg2);
g.drawString(timeStr, startX, y);
// Reset clip rect to full screen
g.setClipRect(0, 0, g.getWidth(), g.getHeight());
}
// draw date at bottom of screen
g.setColor(g.theme.fg2);
g.setFontAlign(0, 0).setFont('Vector', 20);
g.drawString(g.wrapString(dateStr, g.getWidth()).join('\n'), x, g.getHeight() - 30);
queueDraw();
};
// Clear the screen once/, at startup
g.clear();
// draw immediately at first, queue update
draw();
// Stop updates when LCD is off, restart when on
Bangle.on('lcdPower', (on) => {
if (on) {
draw(); // draw immediately, queue redraw
} else {
// stop draw timer
if (drawTimeout) clearTimeout(drawTimeout);
drawTimeout = undefined;
}
});
// Show launcher when middle button pressed
Bangle.setUI('clock');
// Load widgets
Bangle.loadWidgets();
Bangle.drawWidgets();
}