BangleApps/apps/widalarmeta/widget.js

138 lines
4.4 KiB
JavaScript

(() => {
let config;
function loadSettings() {
config = Object.assign({
maxhours: 24,
drawBell: false,
padHours: true,
showSeconds: 0, // 0=never, 1=only when display is unlocked, 2=for less than a minute
font: 1, // 0=segment style font, 1=teletext font, 2=6x8:1x2
}, require("Storage").readJSON("widalarmeta.json",1) || {});
if (config.font == 0) {
require("Font5x9Numeric7Seg").add(Graphics);
} else if (config.font == 1) {
require("FontTeletext5x9Ascii").add(Graphics);
}
}
loadSettings();
function getNextAlarm(date) {
const alarms = require("sched")
.getAlarms()
// more precise filtering is done using getTimeToAlarm() below
.filter(alarm => alarm.on && alarm.hidden !== true);
WIDGETS["widalarmeta"].numActiveAlarms = alarms.length;
if (alarms.length > 0) {
const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY);
const eta = Math.min.apply(null, times);
if (eta !== Number.POSITIVE_INFINITY) {
const idx = times.indexOf(eta);
const alarm = alarms[idx];
delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory
return alarm;
}
}
} // getNextAlarm
function draw(_w, fromInterval) {
if (this.nextAlarm === undefined) {
let alarm = getNextAlarm();
if (alarm === undefined) {
// try again with next hour
const nextHour = new Date();
nextHour.setHours(nextHour.getHours()+1);
alarm = getNextAlarm(nextHour);
}
if (alarm !== undefined) {
this.nextAlarm = alarm;
}
}
const next = this.nextAlarm !== undefined ? require("sched").getTimeToAlarm(this.nextAlarm) : 0;
let calcWidth = 0;
let drawSeconds = false;
if (next > 0 && next <= config.maxhours*60*60*1000) {
const hours = Math.floor((next-1) / 3600000).toString();
const minutes = Math.floor(((next-1) % 3600000) / 60000).toString();
const seconds = Math.floor(((next-1) % 60000) / 1000).toString();
drawSeconds = (config.showSeconds & 0b01 && !Bangle.isLocked()) || (config.showSeconds & 0b10 && next <= 1000*60);
g.reset(); // reset the graphics context to defaults (color/font/etc)
g.setFontAlign(-1,0); // center font in y direction
g.clearRect(this.x, this.y, this.x+this.width-1, this.y+23);
var text = "";
if (config.padHours) {
text += hours.padStart(2, '0');
} else {
text += hours;
}
text += ":" + minutes.padStart(2, '0');
if (drawSeconds) {
text += ":" + seconds.padStart(2, '0');
}
if (config.font == 0) {
g.setFont("5x9Numeric7Seg:1x2");
} else if (config.font == 1) {
g.setFont("Teletext5x9Ascii:1x2");
} else {
// Default to this if no other font is set.
g.setFont("6x8:1x2");
}
g.drawString(text, this.x+1, this.y+12);
calcWidth = g.stringWidth(text) + 2; // One pixel on each side
this.bellVisible = false;
} else if (config.drawBell && this.numActiveAlarms > 0) {
calcWidth = 24;
// next alarm too far in future, draw only widalarm bell
if (this.bellVisible !== true || fromInterval !== true) {
g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y);
this.bellVisible = true;
}
}
if (this.width !== calcWidth) {
// width changed, re-layout
this.width = calcWidth;
Bangle.drawWidgets();
}
// redraw next hour when no alarm else full minute or second
const period = next === 0 ? 3600000 : (drawSeconds ? 1000 : 60000);
let timeout = next > 0 ? next % period : period - (Date.now() % period);
if (timeout === 0) {
timeout += period;
}
if (this.timeoutId !== undefined) {
clearTimeout(this.timeoutId);
}
this.timeoutId = setTimeout(()=>{
var w = WIDGETS["widalarmeta"];
w.timeoutId = undefined;
w.draw(w, true);
}, timeout);
} /* draw */
if (config.maxhours > 0) {
WIDGETS["widalarmeta"]={
area:"tl",
width: 0, // hide by default = assume no timer
draw:draw,
reload: function () {
this.nextAlarm = undefined;
loadSettings();
Bangle.drawWidgets();
},
};
Bangle.on("alarmReload", () => WIDGETS["widalarmeta"].reload());
}
})();