2022-08-07 21:32:16 +00:00
|
|
|
var calendar = [];
|
|
|
|
var current = [];
|
|
|
|
var next = [];
|
|
|
|
|
|
|
|
function updateCalendar() {
|
|
|
|
calendar = require("Storage").readJSON("android.calendar.json",true)||[];
|
|
|
|
calendar = calendar.filter(e => isActive(e) || getTime() <= e.timestamp);
|
|
|
|
calendar.sort((a,b) => a.timestamp - b.timestamp);
|
|
|
|
|
|
|
|
current = calendar.filter(isActive);
|
|
|
|
next = calendar.filter(e=>!isActive(e));
|
|
|
|
}
|
|
|
|
|
|
|
|
function isActive(event) {
|
|
|
|
var timeActive = getTime() - event.timestamp;
|
|
|
|
return timeActive >= 0 && timeActive <= event.durationInSeconds;
|
|
|
|
}
|
|
|
|
function zp(str) {
|
|
|
|
return ("0"+str).substr(-2);
|
|
|
|
}
|
|
|
|
|
2022-08-30 09:01:01 +00:00
|
|
|
function drawEventHeader(event, y) {
|
2022-11-29 22:14:51 +00:00
|
|
|
var x = 0;
|
2022-08-07 21:32:16 +00:00
|
|
|
var time = isActive(event) ? new Date() : new Date(event.timestamp * 1000);
|
2022-11-29 22:14:51 +00:00
|
|
|
|
|
|
|
//Don't need to know what time the event is at if its all day
|
|
|
|
if (isActive(event) || !event.allDay) {
|
|
|
|
g.setFont("Vector", 24);
|
|
|
|
var timeStr = zp(time.getHours()) + ":" + zp(time.getMinutes());
|
|
|
|
g.drawString(timeStr, 0, y);
|
|
|
|
y += 3;
|
|
|
|
x = 13*timeStr.length+5;
|
|
|
|
}
|
2022-08-07 21:32:16 +00:00
|
|
|
|
2022-08-30 09:01:01 +00:00
|
|
|
g.setFont("12x20", 1);
|
2022-11-29 22:14:51 +00:00
|
|
|
|
2022-08-07 21:32:16 +00:00
|
|
|
if (isActive(event)) {
|
2022-11-29 22:14:51 +00:00
|
|
|
g.drawString(zp(time.getDate())+". " + require("locale").month(time,1),x,y);
|
2022-08-07 21:32:16 +00:00
|
|
|
} else {
|
|
|
|
var offset = 0-time.getTimezoneOffset()/1440;
|
|
|
|
var days = Math.floor((time.getTime()/1000)/86400+offset)-Math.floor(getTime()/86400+offset);
|
2022-11-29 22:14:51 +00:00
|
|
|
if(days > 0 || event.allDay) {
|
2022-08-07 21:32:16 +00:00
|
|
|
var daysStr = days===1?/*LANG*/"tomorrow":/*LANG*/"in "+days+/*LANG*/" days";
|
2022-11-29 22:14:51 +00:00
|
|
|
g.drawString(daysStr,x,y);
|
2022-08-07 21:32:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-29 22:14:51 +00:00
|
|
|
y += 21;
|
2022-08-30 09:01:01 +00:00
|
|
|
return y;
|
|
|
|
}
|
2022-08-07 21:32:16 +00:00
|
|
|
|
2022-08-30 09:01:01 +00:00
|
|
|
function drawEventBody(event, y) {
|
2022-08-07 21:32:16 +00:00
|
|
|
g.setFont("12x20", 1);
|
2022-11-29 22:14:51 +00:00
|
|
|
var lines = g.wrapString(event.title, g.getWidth()-15);
|
|
|
|
var yStart = y;
|
2022-08-30 09:01:01 +00:00
|
|
|
if (lines.length > 2) {
|
|
|
|
lines = lines.slice(0,2);
|
2022-12-10 11:40:39 +00:00
|
|
|
lines[1] += "...";
|
2022-08-30 09:01:01 +00:00
|
|
|
}
|
2022-11-29 22:14:51 +00:00
|
|
|
g.drawString(lines.join('\n'),10,y);
|
2022-08-30 09:01:01 +00:00
|
|
|
y+=20 * lines.length;
|
|
|
|
if(event.location) {
|
2022-11-29 22:14:51 +00:00
|
|
|
g.drawImage(atob("DBSBAA8D/H/nDuB+B+B+B3Dn/j/B+A8A8AYAYAYAAAAAAA=="),10,y);
|
2022-12-10 11:40:39 +00:00
|
|
|
var loclines = g.wrapString(event.location, g.getWidth()-30);
|
|
|
|
if(loclines.length>1) loclines[0] += "...";
|
|
|
|
g.drawString(loclines[0],25,y);
|
2022-08-30 09:01:01 +00:00
|
|
|
y+=20;
|
|
|
|
}
|
2022-11-29 22:14:51 +00:00
|
|
|
if (event.color) {
|
|
|
|
var oldColor = g.getColor();
|
|
|
|
g.setColor("#"+(0x1000000+Number(event.color)).toString(16).padStart(6,"0"));
|
|
|
|
g.fillRect(0,yStart,5,y-3);
|
|
|
|
g.setColor(oldColor);
|
|
|
|
}
|
2022-08-30 09:01:01 +00:00
|
|
|
y+=5;
|
|
|
|
return y;
|
|
|
|
}
|
2022-08-07 21:32:16 +00:00
|
|
|
|
2022-08-30 09:01:01 +00:00
|
|
|
function drawEvent(event, y) {
|
|
|
|
y = drawEventHeader(event, y);
|
|
|
|
y = drawEventBody(event, y);
|
2022-08-07 21:32:16 +00:00
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
var curEventHeight = 0;
|
|
|
|
|
|
|
|
function drawCurrentEvents(y) {
|
2022-11-29 22:14:51 +00:00
|
|
|
g.setColor(g.theme.dark ? "#0ff" : "#00f");
|
|
|
|
g.clearRect(0,y,g.getWidth()-5,y+curEventHeight);
|
2022-08-07 21:32:16 +00:00
|
|
|
curEventHeight = y;
|
|
|
|
|
|
|
|
if(current.length === 0) {
|
|
|
|
y = drawEvent({timestamp: getTime(), durationInSeconds: 100}, y);
|
|
|
|
} else {
|
2022-11-29 22:14:51 +00:00
|
|
|
y = drawEventHeader(current[0],y);
|
2022-08-07 21:32:16 +00:00
|
|
|
for (var e of current) {
|
2022-11-29 22:14:51 +00:00
|
|
|
y = drawEventBody(e,y);
|
2022-08-07 21:32:16 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-29 22:14:51 +00:00
|
|
|
curEventHeight = y-curEventHeight;
|
2022-08-07 21:32:16 +00:00
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
function drawFutureEvents(y) {
|
2022-08-30 09:01:01 +00:00
|
|
|
g.setColor(g.theme.fg);
|
2022-08-07 21:32:16 +00:00
|
|
|
for (var e of next) {
|
|
|
|
y = drawEvent(e, y);
|
|
|
|
if(y>g.getHeight())break;
|
|
|
|
}
|
|
|
|
return y;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fullRedraw() {
|
2022-11-29 22:14:51 +00:00
|
|
|
g.clearRect(0,24,g.getWidth()-5,g.getHeight());
|
2022-08-07 21:32:16 +00:00
|
|
|
updateCalendar();
|
|
|
|
var y = 30;
|
|
|
|
y = drawCurrentEvents(y);
|
|
|
|
drawFutureEvents(y);
|
|
|
|
}
|
|
|
|
|
2023-10-30 18:41:30 +00:00
|
|
|
function buzzForEvents() {
|
|
|
|
let nextEvent = next[0]; if (!nextEvent) return;
|
2023-12-13 20:30:52 +00:00
|
|
|
// No buzz for all day events or events before 7am
|
|
|
|
// TODO: make this configurable
|
|
|
|
if (nextEvent.allDay || (new Date(nextEvent.timestamp * 1000)).getHours() < 7) return;
|
2023-10-30 18:41:30 +00:00
|
|
|
let minToEvent = Math.round((nextEvent.timestamp - getTime()) / 60.0);
|
|
|
|
switch (minToEvent) {
|
2023-12-13 20:30:52 +00:00
|
|
|
case 30: require("buzz").pattern(":"); break;
|
2023-10-30 18:41:30 +00:00
|
|
|
case 15: require("buzz").pattern(", ,"); break;
|
|
|
|
case 1: require("buzz").pattern(": : :"); break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-07 21:32:16 +00:00
|
|
|
function redraw() {
|
|
|
|
g.reset();
|
|
|
|
if (current.find(e=>!isActive(e)) || next.find(isActive)) {
|
|
|
|
fullRedraw();
|
|
|
|
} else {
|
|
|
|
drawCurrentEvents(30);
|
|
|
|
}
|
2023-10-30 18:41:30 +00:00
|
|
|
buzzForEvents();
|
2022-08-07 21:32:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g.clear();
|
|
|
|
fullRedraw();
|
2023-10-30 18:41:30 +00:00
|
|
|
buzzForEvents();
|
2024-03-04 20:34:50 +00:00
|
|
|
/*var minuteInterval =*/ setInterval(redraw, 60 * 1000);
|
2022-08-07 21:32:16 +00:00
|
|
|
|
2022-09-06 17:32:51 +00:00
|
|
|
Bangle.setUI("clock");
|
2022-08-07 21:32:16 +00:00
|
|
|
Bangle.loadWidgets();
|
|
|
|
Bangle.drawWidgets();
|