mirror of https://github.com/espruino/BangleApps
248 lines
6.0 KiB
JavaScript
248 lines
6.0 KiB
JavaScript
/**
|
|
* Mystic Dock for Bangle.js
|
|
*
|
|
* + Original Author: Eric Wooodward https://itsericwoodward.com/
|
|
* + see README.md for details
|
|
*/
|
|
|
|
/* jshint esversion: 6 */
|
|
|
|
const timeFontSize = 6;
|
|
const dataFontSize = 2;
|
|
const font = "6x8";
|
|
|
|
const xyCenter = g.getWidth() / 2;
|
|
|
|
const ypos = [
|
|
45, // Time
|
|
105, // Date
|
|
145, // Symbol
|
|
210 // Info
|
|
];
|
|
|
|
const settings = require('Storage').readJSON('mysticdock.json', 1) ||
|
|
require('Storage').readJSON('mysticclock.json', 1) || {};
|
|
const colors = ['white', 'blue', 'green', 'purple', 'red', 'teal', 'other'];
|
|
const color = settings.color ? colors[settings.color] : 0;
|
|
|
|
const yposMax = 190;
|
|
const yposMin = 60;
|
|
let y = yposMax;
|
|
|
|
let lastButtonPressTime;
|
|
let wasInActiveMode = false;
|
|
|
|
|
|
const infoData = {
|
|
'*GMT_MODE': {
|
|
calc: () => (new Date()).toString().split(" ")[5],
|
|
},
|
|
BATT_MODE: {
|
|
calc: () => `BATT: ${E.getBattery()}%`,
|
|
},
|
|
ID_MODE: {
|
|
calc: () => {
|
|
const val = NRF.getAddress().split(":");
|
|
return `ID: ${val[4]}${val[5]}`;
|
|
},
|
|
},
|
|
MEM_MODE: {
|
|
calc: () => {
|
|
const val = process.memory();
|
|
return `MEM: ${Math.round(val.usage * 100 / val.total)}%`;
|
|
},
|
|
},
|
|
VER_MODE: {
|
|
calc: () => `FW: ${process.env.VERSION}`,
|
|
},
|
|
};
|
|
const infoList = Object.keys(infoData).sort();
|
|
let infoMode = infoList[0];
|
|
|
|
|
|
function setColor() {
|
|
const colorCommands = {
|
|
white: () => g.setColor(1, 1, 1),
|
|
blue: () => g.setColor(0, 0, 1),
|
|
green: () => g.setColor(0, 1, 0),
|
|
purple: () => g.setColor(1, 0, 1),
|
|
red: () => g.setColor(1, 0, 0),
|
|
teal: () => g.setColor(0, 1, 1),
|
|
other: () => g.setColor(1, 1, 0)
|
|
};
|
|
|
|
// default if value unknown
|
|
if (!color || !colorCommands[color]) return colorCommands.white();
|
|
return colorCommands[color]();
|
|
}
|
|
|
|
|
|
function drawInfo() {
|
|
if (infoData[infoMode] && infoData[infoMode].calc) {
|
|
// clear info
|
|
g.setColor(0, 0, 0);
|
|
g.fillRect(0, ypos[3] - 8, 239, ypos[3] + 25);
|
|
|
|
// draw info
|
|
g.setFont(font, dataFontSize);
|
|
setColor();
|
|
g.drawString((infoData[infoMode].calc()), xyCenter, ypos[3], true);
|
|
}
|
|
}
|
|
|
|
function drawImage() {
|
|
setColor();
|
|
g.drawPoly([xyCenter - 100, ypos[2], xyCenter + 100, ypos[2], xyCenter, ypos[2] + 30], true);
|
|
}
|
|
|
|
function drawClock() {
|
|
|
|
// default draw styles
|
|
g.reset();
|
|
|
|
// get date
|
|
const d = new Date();
|
|
const dLocal = d.toString().split(" ");
|
|
|
|
const minutes = (`0${d.getMinutes()}`).substr(-2);
|
|
const seconds = (`0${d.getSeconds()}`).substr(-2);
|
|
|
|
const useLocale = !settings.useLocale;
|
|
|
|
let hours = (`0${d.getHours()}`).substr(-2);
|
|
let meridian = "";
|
|
|
|
if (d.getSeconds() % 10 === 0) {
|
|
y = Math.floor(Math.random() * (yposMax - yposMin)) + yposMin;
|
|
}
|
|
|
|
// drawSting centered
|
|
g.setFontAlign(0, 0);
|
|
|
|
// setup color
|
|
setColor();
|
|
|
|
if (settings.use12Hour) {
|
|
hours = parseInt(hours, 10);
|
|
meridian = 'AM';
|
|
if (hours === 0) {
|
|
hours = 12;
|
|
}
|
|
else if (hours >= 12) {
|
|
meridian = 'PM';
|
|
if (hours > 12) hours -= 12;
|
|
}
|
|
hours = (' ' + hours).substr(-2);
|
|
}
|
|
|
|
g.setFont(font, timeFontSize);
|
|
|
|
if (lastButtonPressTime && ((d.getTime() - lastButtonPressTime) / 1000) < 5) {
|
|
|
|
// clear screen when switching modes
|
|
if (!wasInActiveMode) {
|
|
g.clear();
|
|
wasInActiveMode = true;
|
|
}
|
|
|
|
// draw clock in center w/ seconds
|
|
// show date (locale'd, based on settings)
|
|
// show info line below it
|
|
g.drawString(`${hours}${(d.getSeconds() % 2) ? ' ' : ':'}${minutes}`, xyCenter - 15, ypos[0], true);
|
|
g.setFont(font, dataFontSize);
|
|
|
|
if (settings.use12Hour) {
|
|
g.drawString(seconds, xyCenter + 97, ypos[0] - 10, true);
|
|
g.drawString(meridian, xyCenter + 97, ypos[0] + 10, true);
|
|
}
|
|
else {
|
|
g.drawString(seconds, xyCenter + 97, ypos[0] + 10, true);
|
|
}
|
|
|
|
// draw DoW, name of month, date, year
|
|
g.setFont(font, dataFontSize);
|
|
g.drawString([
|
|
useLocale ? require('locale').dow(d, 1) : dLocal[0],
|
|
useLocale ? require('locale').month(d, 1) : dLocal[1],
|
|
d.getDate(),
|
|
d.getFullYear()
|
|
].join(' '), xyCenter, ypos[1], true);
|
|
|
|
drawInfo();
|
|
drawImage();
|
|
}
|
|
else if (d.getSeconds() % 10 === 8) {
|
|
g.clear();
|
|
wasInActiveMode = false;
|
|
}
|
|
else if (d.getSeconds() % 10 !== 9) {
|
|
// clear screen when switching modes
|
|
if (wasInActiveMode) {
|
|
g.clear();
|
|
wasInActiveMode = false;
|
|
}
|
|
g.drawString(`${hours}${(d.getSeconds() % 2) ? ' ' : ':'}${minutes}`, xyCenter - (settings.use12Hour ? 15 : 0), y, true);
|
|
g.setFont(font, dataFontSize);
|
|
if (settings.use12Hour) {
|
|
g.drawString(meridian, xyCenter + 97, y + 10, true);
|
|
}
|
|
g.drawString(`BATT: ${E.getBattery() === 100 ? '100' : ('0' + E.getBattery()).substr(-2)}%`, xyCenter, y + 35, true);
|
|
}
|
|
|
|
g.flip();
|
|
}
|
|
|
|
|
|
function nextInfo() {
|
|
lastButtonPressTime = Date.now();
|
|
let idx = infoList.indexOf(infoMode);
|
|
|
|
if (idx > -1) {
|
|
if (idx === infoList.length - 1) infoMode = infoList[0];
|
|
else infoMode = infoList[idx + 1];
|
|
}
|
|
}
|
|
|
|
|
|
function prevInfo() {
|
|
lastButtonPressTime = Date.now();
|
|
let idx = infoList.indexOf(infoMode);
|
|
|
|
if (idx > -1) {
|
|
if (idx === 0) infoMode = infoList[infoList.length - 1];
|
|
else infoMode = infoList[idx - 1];
|
|
}
|
|
}
|
|
|
|
|
|
if (Bangle.getAccel().x < -0.7) {
|
|
g.setRotation(3); // assume watch in charge cradle
|
|
}
|
|
|
|
g.clear();
|
|
|
|
setInterval(drawClock, 1000);
|
|
drawClock();
|
|
|
|
if (Bangle.isCharging()) {
|
|
Bangle.on("charging", isCharging => {
|
|
const reloadOnUplug = !settings.reloadOnUplug;
|
|
|
|
if (!isCharging && reloadOnUplug) load();
|
|
});
|
|
}
|
|
|
|
// show launcher when middle button pressed
|
|
setWatch(Bangle.showLauncher, BTN2, { repeat: false, edge: "falling" });
|
|
|
|
// change to "active mode" and rotate through info when the buttons are pressed
|
|
setWatch(() => {
|
|
nextInfo();
|
|
drawClock();
|
|
}, BTN3, { repeat: true });
|
|
|
|
setWatch(() => {
|
|
prevInfo();
|
|
drawClock();
|
|
}, BTN1, { repeat: true });
|