mirror of https://github.com/espruino/BangleApps
284 lines
5.9 KiB
JavaScript
284 lines
5.9 KiB
JavaScript
/************************************************
|
|
* Happy Clock
|
|
*/
|
|
|
|
|
|
const storage = require('Storage');
|
|
const widget_utils = require("widget_utils");
|
|
|
|
|
|
/************************************************
|
|
* Settings
|
|
*/
|
|
const SETTINGS_FILE = "happyclk.setting.json";
|
|
|
|
let settings = {
|
|
color: "Dark",
|
|
screen: "Dynamic"
|
|
};
|
|
|
|
let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings;
|
|
for (const key in saved_settings) {
|
|
settings[key] = saved_settings[key];
|
|
}
|
|
|
|
var color_map = {
|
|
"Dark":{
|
|
fg: "#fff",
|
|
bg: "#000",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Black":{
|
|
fg: "#fff",
|
|
bg: "#000",
|
|
eye: "#000",
|
|
eyePupils: "#fff"
|
|
},
|
|
"White":{
|
|
fg: "#000",
|
|
bg: "#fff",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Blue":{
|
|
fg: "#fff",
|
|
bg: "#00f",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Green":{
|
|
fg: "#000",
|
|
bg: "#0f0",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Red":{
|
|
fg: "#fff",
|
|
bg: "#f00",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Purple":{
|
|
fg: "#fff",
|
|
bg: "#f0f",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
},
|
|
"Yellow":{
|
|
fg: "#000",
|
|
bg: "#ff0",
|
|
eye: "#fff",
|
|
eyePupils: "#000"
|
|
}
|
|
};
|
|
var colors = color_map[settings.color];
|
|
|
|
/************************************************
|
|
* Globals
|
|
*/
|
|
var W = g.getWidth(),R=W/2;
|
|
var H = g.getHeight();
|
|
var drawTimeout;
|
|
|
|
|
|
/*
|
|
* HELPER
|
|
*/
|
|
|
|
let isFullscreen = function() {
|
|
var s = settings.screen.toLowerCase();
|
|
if(s == "dynamic"){
|
|
return Bangle.isLocked();
|
|
} else {
|
|
return s == "full";
|
|
}
|
|
};
|
|
|
|
|
|
// Based on the great multi clock from https://github.com/jeffmer/BangleApps/
|
|
Graphics.prototype.drawPupils = function(cx, cy, r1, dx, dy, angle) {
|
|
angle = angle % 360;
|
|
var theta=angle*Math.PI/180;
|
|
var x = parseInt(cx+r1*Math.sin(theta)*1.2);
|
|
var y = parseInt(cy-r1*Math.cos(theta)*1.2);
|
|
|
|
g.setColor(g.theme.fg);
|
|
g.fillCircle(cx, cy, 32);
|
|
|
|
g.setColor(colors.eye);
|
|
g.fillCircle(cx, cy, 27);
|
|
g.fillCircle(cx+dx, cy+dy, 28);
|
|
|
|
g.setColor(colors.eyePupils);
|
|
g.fillCircle(x, y, 8);
|
|
g.fillCircle(x+1, y, 8);
|
|
};
|
|
|
|
let quadraticCurve = function(t, p0x, p0y, p1x, p1y, p2x, p2y){
|
|
var t2 = t * t;
|
|
var oneMinT = 1 - t;
|
|
var oneMinT2 = oneMinT * oneMinT;
|
|
return {
|
|
x: p0x * oneMinT2 + 2 * p1x * t * oneMinT + p2x *t2,
|
|
y: p0y * oneMinT2 + 2 * p1y * t * oneMinT + p2y *t2
|
|
};
|
|
}
|
|
|
|
// Thanks to user stephaneAG from the Espruino forum!
|
|
// https://forum.espruino.com/conversations/330154/#comment14593349
|
|
let drawCurve = function(x1, y1, x2, y2, x3, y3){
|
|
var p0 = { x: x1, y: y1};
|
|
var p1 = { x: x2, y: y2};
|
|
var p2 = { x: x3, y: y3};
|
|
var time = 0;
|
|
var stepping = 0.1; // Stepping defines the speed.
|
|
|
|
for(var y = 0; y < 8; y++){
|
|
var pathPts = [];
|
|
for(time = 0; time <= 1; time+= stepping){
|
|
var pos = quadraticCurve(time, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y);
|
|
pathPts.push(pos.x, pos.y+y);
|
|
}
|
|
g.drawPoly(pathPts, false);
|
|
}
|
|
g.flip();
|
|
}
|
|
|
|
|
|
/*
|
|
* Draw the clock
|
|
*/
|
|
let drawEyes = function(){
|
|
// And now the analog time
|
|
var drawHour = g.drawPupils.bind(g,55,70,12,1,0);
|
|
var drawMinute = g.drawPupils.bind(g,125,70,12,0,1);
|
|
|
|
g.setFontAlign(0,0);
|
|
|
|
// Compute angles
|
|
var date = new Date();
|
|
var m = parseInt(date.getMinutes() * 360 / 60);
|
|
var h = date.getHours();
|
|
h = h > 12 ? h-12 : h;
|
|
h += date.getMinutes()/60.0;
|
|
h = parseInt(h*360/12);
|
|
|
|
// Draw minute and hour fg
|
|
g.setColor(g.theme.fg);
|
|
drawHour(h);
|
|
drawMinute(m);
|
|
}
|
|
|
|
|
|
let drawSmile = function(isLocked){
|
|
g.setColor(colors.fg);
|
|
var y = 120;
|
|
var o = parseInt(E.getBattery()*0.8);
|
|
|
|
// Draw smile
|
|
drawCurve(30, y, W/2+12, y+o, W-40, y);
|
|
|
|
// And the two "mouth lines"
|
|
var reachedSteps = Bangle.getHealthStatus("day").steps >= 10000;
|
|
for(var i=0; i < 6; i++){
|
|
if(isLocked) g.drawLine(25, y+6+i, 35, y-5+i);
|
|
if(reachedSteps) g.drawLine(W-35, y+5+i, W-45, y-5+i);
|
|
}
|
|
}
|
|
|
|
let drawEyeBrow = function(){
|
|
if(!isFullscreen()) return;
|
|
|
|
g.setColor(colors.fg);
|
|
var w = 6;
|
|
for(var i = 0; i < w; i++){
|
|
g.drawLine(25, 25+i, 70, 15+i%3);
|
|
g.drawLine(W-25, 28+i%3, W-68, 19+i);
|
|
}
|
|
}
|
|
|
|
|
|
let drawWidgets = function(isLocked){
|
|
if (isFullscreen()) {
|
|
widget_utils.hide();
|
|
} else {
|
|
if (isLocked) return;
|
|
Bangle.drawWidgets();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
let draw = function(){
|
|
// Queue draw in one minute
|
|
queueDraw();
|
|
|
|
var isLocked = Bangle.isLocked();
|
|
drawHelper(isLocked);
|
|
}
|
|
|
|
let drawHelper = function(isLocked){
|
|
g.setColor(g.theme.fg);
|
|
g.reset().clear();
|
|
|
|
drawEyes();
|
|
drawEyeBrow();
|
|
drawSmile(isLocked);
|
|
|
|
drawWidgets(isLocked);
|
|
}
|
|
|
|
|
|
/*
|
|
* Listeners
|
|
*/
|
|
Bangle.on('lcdPower',on=>{
|
|
if (on) {
|
|
draw();
|
|
} else { // stop draw timer
|
|
if (drawTimeout) clearTimeout(drawTimeout);
|
|
drawTimeout = undefined;
|
|
}
|
|
});
|
|
|
|
Bangle.on('lock', function(isLocked) {
|
|
if (drawTimeout) clearTimeout(drawTimeout);
|
|
drawTimeout = undefined;
|
|
|
|
if(!isLocked && settings.screen.toLowerCase() == "dynamic"){
|
|
// If we have to show the widgets again, we load it from our
|
|
// cache and not through Bangle.loadWidgets as its much faster!
|
|
widget_utils.show();
|
|
}
|
|
|
|
draw(isLocked);
|
|
});
|
|
|
|
|
|
/*
|
|
* Some helpers
|
|
*/
|
|
let queueDraw = function() {
|
|
if (drawTimeout) clearTimeout(drawTimeout);
|
|
drawTimeout = setTimeout(function() {
|
|
drawTimeout = undefined;
|
|
draw();
|
|
}, 60000 - (Date.now() % 60000));
|
|
}
|
|
|
|
|
|
/*
|
|
* Lets start widgets, listen for btn etc.
|
|
*/
|
|
// Show launcher when middle button pressed
|
|
Bangle.setUI("clock");
|
|
Bangle.loadWidgets();
|
|
|
|
// Clear the screen once, at startup and draw clock
|
|
g.setTheme({bg:colors.bg,fg:colors.fg,dark:false});
|
|
draw();
|
|
|
|
// After drawing the watch face, we can draw the widgets
|
|
// Bangle.drawWidgets();
|