bangle/antonclk/antonclk.app.js

370 lines
16 KiB
JavaScript

// Clock with large digits using the "Anton" bold font
Graphics.prototype.setFontAnton = function(scale) {
// Actual height 69 (68 - 0)
g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78 + (scale << 8) + (1 << 16));
};
{ // must be inside our own scope here so that when we are unloaded everything disappears
// we also define functions using 'let fn = function() {..}' for the same reason. function decls are global
const STATE_IDLE = 0;
const STATE_GRID_OPEN_WAIT = 1;
const STATE_GRID_OPEN = 2;
const STATE_MENU_OPEN = 3;
let watchState = STATE_IDLE;
let myMessage = "";
let temperature = "";
let drawTimer = null;
let gridTimer = null;
let lockTimer = null;
let swipeLockout = false;
let grid = require("Storage").readJSON("grid.json", true);
let prevNum = require("Storage").readJSON("prevNum.json", true) || -1;
let gridNum = -1;
let gridDir = -1;
let menu = require("Storage").readJSON("menu.json", true);
let subMenu = null;
let menuCommand = "";
let paintFace = function() {
if (watchState != STATE_IDLE) return;
var x = g.getWidth() / 2;
var y = g.getHeight() / 2;
g.reset().clearRect(Bangle.appRect); // clear whole background (w/o widgets)
var date = new Date();
var timeStr = require("locale").time(date, 1); // Hour and minute
g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y+20);
// Show date and day of week
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
var dateStr = date.getDate() + " " + days[date.getDay()] + " " + temperature;
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(dateStr, x, y+70);
//var wrapped = g.wrapString(myMessage, g.getWidth()-10).join("\n");
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(myMessage, x, y-45);
};
// Actually draw the watch face
let draw = function() {
if (Bangle.http){
Bangle.http("https://api.home.dns.t0.vc/bangle", {timeout:3000}).then(event => {
let result = JSON.parse(event.resp);
myMessage = result.context;
temperature = result.temperature;
if (watchState == STATE_IDLE) {
if (paintFace) paintFace();
}
}).catch((e)=>{
myMessage = "GET error";
if (paintFace) paintFace();
});
}
// queue next draw
if (drawTimer) clearTimeout(drawTimer);
drawTimer = setTimeout(function() {
drawTimer = undefined;
draw();
}, 60000 - (Date.now() % 60000));
};
let handleSwipe = function(dir1, dir2) {
var direction;
if (swipeLockout) return;
if (dir1 == 1) {
direction = "right";
} else if (dir1 == -1) {
direction = "left";
} else if (dir2 == 1) {
direction = "down";
} else if (dir2 == -1) {
direction = "up";
} else {
direction = "none";
}
if (Bangle.http){
const options = {timeout:3000, method: "post", body: direction};
Bangle.http("https://api.home.dns.t0.vc/bangle", options).then(event => {
myMessage = "Sent " + direction;
if (paintFace) paintFace();
}).catch((e)=>{
myMessage = "POST error";
if (paintFace) paintFace();
});
}
};
let drawGrid = function(touchX, touchY) {
let x = g.getWidth() / 2;
let y = g.getHeight() / 2;
let text = "";
let rank = "";
g.reset().clearRect(Bangle.appRect);
truncX = Math.floor(touchX/15);
truncY = Math.floor(touchY/15);
gridNum = -1;
gridDir = -1;
if (!grid) {
text = "Grid missing";
} else if (truncX < 2) {
text = "left";
gridDir = "left";
} else if (truncX > 10) {
text = "right";
gridDir = "right";
} else if (truncY < 2) {
text = "Repeat";
gridDir = "top";
} else if (truncY > 10) {
text = "Cancel";
gridDir = "bottom";
} else {
const gridX = truncX - 2;
const gridY = truncY - 2;
gridNum = gridY * 9 + gridX;
rank = "ABCDEFGHI"[gridY];
text = grid[gridNum] || gridNum;
}
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(text, x, y-45);
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(text, x, y+70);
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(rank, x-65, y+15);
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(rank, x+65, y+15);
};
let handleDrag = function(e) {
//console.log(e);
// { "x": 96, "y": 147, "b": 1, "dx": 0, "dy": 1 }
const touchX = e.x;
const touchY = e.y;
const pressed = Boolean(e.b);
if (watchState == STATE_IDLE && pressed) {
watchState = STATE_GRID_OPEN_WAIT;
gridTimer = setTimeout(function() {
watchState = STATE_GRID_OPEN;
drawGrid(touchX, touchY);
swipeLockout = true;
}, 500);
} else if (watchState == STATE_GRID_OPEN_WAIT && !pressed) {
watchState = STATE_IDLE;
if (gridTimer) clearTimeout(gridTimer);
} else if (watchState == STATE_GRID_OPEN && !pressed) {
watchState = STATE_IDLE;
if (lockTimer) clearTimeout(lockTimer);
lockTimer = setTimeout(function() {
swipeLockout = false;
}, 2000);
if (gridNum == 72) {
myMessage = "Refresh Grid";
require("Storage").writeJSON("grid.json", false);
grid = false;
gridNum = -1;
load();
} else if (gridNum >= 0 && grid[gridNum]) {
myMessage = grid[gridNum];
prevNum = gridNum;
require("Storage").writeJSON("prevNum.json", prevNum);
if (Bangle.http){
const options = {timeout:3000, method: "post", body: gridNum};
Bangle.http("https://api.home.dns.t0.vc/grid", options).then(event => {
myMessage = "ok";
if (paintFace) paintFace();
}).catch((e)=>{
myMessage = "POST error";
if (paintFace) paintFace();
});
}
gridNum = -1;
} else if (gridDir == "top") {
if (prevNum >= 0) {
myMessage = grid[prevNum];
if (Bangle.http){
const options = {timeout:3000, method: "post", body: prevNum};
Bangle.http("https://api.home.dns.t0.vc/grid", options).then(event => {
myMessage = "ok";
if (paintFace) paintFace();
}).catch((e)=>{
myMessage = "POST error";
if (paintFace) paintFace();
});
}
} else {
myMessage = "No repeat";
}
} else if (gridDir == "bottom") {
myMessage = "Cancelled";
Bangle.setLocked(true);
}
if (paintFace) paintFace();
} else if (watchState == STATE_GRID_OPEN && pressed) {
drawGrid(touchX, touchY);
}
};
let drawMenu = function(menu) {
const keys = Object.keys(menu);
g.reset().clearRect(Bangle.appRect);
g.drawLine(88, 0, 88, 175); // |
g.drawLine(0, 88, 175, 88); // --
const wrap = function(text) {
return g.wrapString(text, 80).join("\n");
};
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[0]), 50, 50); // 0
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[1]), 130, 50); // 1
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[2]), 50, 130); // 2
g.setFontAlign(0, 0).setFont("Vector", 26).drawString(wrap(keys[3]), 130, 130); // 3
};
let handleTouch = function(button, xy) {
console.log(button, xy);
const touchX = xy.x;
const touchY = xy.y;
const pressed = xy.type == 0;
// 0 1
// 2 3
let quad = -1;
if (touchY < 110) {
if (touchX < 110) {
quad = 0;
} else {
quad = 1;
}
} else {
if (touchX < 110) {
quad = 2;
} else {
quad = 3;
}
}
console.log("quad:", quad);
if (watchState == STATE_IDLE && pressed) {
watchState = STATE_MENU_OPEN;
subMenu = menu;
menuCommand = "";
}
const keys = Object.keys(subMenu);
const key = keys[quad];
subMenu = subMenu[key];
menuCommand += key + ",";
console.log("submenu:", subMenu);
if (subMenu) {
drawMenu(subMenu);
} else {
watchState = STATE_IDLE;
console.log("menuCommand:", menuCommand);
Bangle.drawWidgets();
Bangle.buzz(100, 0.2);
if (Bangle.http){
const options = {timeout:3000, method: "post", body: menuCommand};
Bangle.http("https://api.home.dns.t0.vc/menu", options).then(event => {
myMessage = "ok";
if (paintFace) paintFace();
}).catch((e)=>{
myMessage = "POST error";
if (paintFace) paintFace();
});
}
myMessage = "sent";
if (paintFace) paintFace();
}
};
let handleTwist = function() {
console.log("twisted");
if (watchState == STATE_MENU_OPEN) {
watchState = STATE_IDLE;
myMessage = "cancelled";
if (paintFace) paintFace();
Bangle.drawWidgets();
}
};
if (Bangle.http && (!grid || !menu)){
Bangle.http("https://api.home.dns.t0.vc/grid", {timeout:3000}).then(event => {
grid = JSON.parse(event.resp);
require("Storage").writeJSON("grid.json", grid);
//console.log(grid);
}).catch((e)=>{
myMessage = "Grid error";
if (paintFace) paintFace();
});
Bangle.http("https://api.home.dns.t0.vc/menu", {timeout:3000}).then(event => {
menu = JSON.parse(event.resp);
require("Storage").writeJSON("menu.json", menu);
//console.log(grid);
}).catch((e)=>{
myMessage = "Menu error";
if (paintFace) paintFace();
});
}
Bangle.on('swipe', handleSwipe);
Bangle.on('drag', handleDrag);
Bangle.on('touch', handleTouch);
Bangle.on('twist', handleTwist);
// Show launcher when middle button pressed
Bangle.setUI({
mode : "clock",
remove : function() {
// Called to unload all of the clock app
Bangle.removeListener('swipe', handleSwipe);
Bangle.removeListener('drag', handleDrag);
Bangle.removeListener('touch', handleTouch);
Bangle.removeListener('twist', handleTwist);
if (drawTimer) clearTimeout(drawTimer);
drawTimer = undefined;
if (gridTimer) clearTimeout(gridTimer);
gridTimer = undefined;
if (lockTimer) clearTimeout(lockTimer);
lockTimer = undefined;
delete Graphics.prototype.setFontAnton;
paintFace = undefined; // http request may resolve after font's been unloaded, so unset
}});
// Load widgets
Bangle.loadWidgets();
paintFace();
draw();
setTimeout(Bangle.drawWidgets,0);
}