392 lines
10 KiB
JavaScript
392 lines
10 KiB
JavaScript
{ // 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 apiKey = require("Storage").readJSON("apikey.json", null);
|
|
if (!apiKey) {
|
|
require("Storage").writeJSON("apikey.json", "NEEDTOSET");
|
|
}
|
|
|
|
|
|
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("Vector", 60).drawString(timeStr, x, y); // Used to be Anton, +20
|
|
|
|
var utc_sec = getTime();
|
|
var utc = utc_sec % 86400;
|
|
var utcHour = Math.floor(utc / 3600);
|
|
var utcMinute = Math.floor((utc % 3600) / 60);
|
|
var utcStr = utcHour.toString().padStart(2, '0') + ":" + utcMinute.toString().padStart(2, '0');
|
|
g.setFontAlign(0, 0).setFont("Vector", 36).drawString(utcStr, x-25, y+43);
|
|
|
|
var tz_offset = date.toString().indexOf("GMT");
|
|
var tz = date.toString().substring(tz_offset+3, tz_offset+6);
|
|
g.setFontAlign(0, 0).setFont("Vector", 24).drawString(tz, x+60, y+43);
|
|
|
|
// 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+76);
|
|
|
|
//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 headers = {"Authorization": "Bearer " + apiKey};
|
|
const options = {timeout:3000, method: "post", body: direction, headers: headers};
|
|
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 headers = {"Authorization": "Bearer " + apiKey};
|
|
const options = {timeout:3000, method: "post", body: gridNum, headers: headers};
|
|
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 headers = {"Authorization": "Bearer " + apiKey};
|
|
const options = {timeout:3000, method: "post", body: prevNum, headers: headers};
|
|
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 (menuCommand == "commands,util,pull menu,") {
|
|
console.log("Pulling new menu...");
|
|
menu = null;
|
|
require("Storage").writeJSON("menu.json", menu);
|
|
}
|
|
|
|
if (Bangle.http){
|
|
const headers = {"Authorization": "Bearer " + apiKey};
|
|
const options = {timeout:3000, method: "post", body: menuCommand, headers: headers};
|
|
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 = key;
|
|
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);
|
|
}
|