Merge pull request #2728 from bobrippling/drained-fixes

`drained`: align clock and permit boot exceptions
master
Gordon Williams 2023-05-11 09:23:00 +01:00 committed by GitHub
commit 7b3dfee1db
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 199 additions and 97 deletions

View File

@ -1 +1,4 @@
0.01: New app! 0.01: New app!
0.02: Allow boot exceptions, e.g. to load DST
0.03: Permit exceptions to load in low-power mode, e.g. daylight saving time.
Also avoid polluting global scope.

View File

@ -35,14 +35,16 @@ var draw = function () {
var dateStr = require("locale").date(date, 0).toUpperCase() + var dateStr = require("locale").date(date, 0).toUpperCase() +
"\n" + "\n" +
require("locale").dow(date, 0).toUpperCase(); require("locale").dow(date, 0).toUpperCase();
var x2 = x + 6;
var y2 = y + 66;
g.reset() g.reset()
.clearRect(Bangle.appRect) .clearRect(Bangle.appRect)
.setFont("Vector", 55) .setFont("Vector", 55)
.setFontAlign(0, 0) .setFontAlign(0, 0)
.drawString(timeStr, x, y) .drawString(timeStr, x, y)
.setFont("Vector", 24) .setFont("Vector", 24)
.drawString(dateStr, x, y + 56) .drawString(dateStr, x2, y2)
.drawString("".concat(E.getBattery(), "%"), x, y + 104); .drawString("".concat(E.getBattery(), "%"), x2, y2 + 48);
if (nextDraw) if (nextDraw)
clearTimeout(nextDraw); clearTimeout(nextDraw);
nextDraw = setTimeout(function () { nextDraw = setTimeout(function () {
@ -75,9 +77,9 @@ var reload = function () {
}; };
reload(); reload();
Bangle.emit("drained", E.getBattery()); Bangle.emit("drained", E.getBattery());
var _a = require("Storage").readJSON("".concat(app, ".setting.json"), true) || {}, _b = _a.disableBoot, disableBoot = _b === void 0 ? false : _b, _c = _a.restore, restore = _c === void 0 ? 20 : _c; var _a = require("Storage").readJSON("".concat(app, ".setting.json"), true) || {}, _b = _a.keepStartup, keepStartup = _b === void 0 ? true : _b, _c = _a.restore, restore = _c === void 0 ? 20 : _c, _d = _a.exceptions, exceptions = _d === void 0 ? ["widdst.0"] : _d;
function drainedRestore() { function drainedRestore() {
if (disableBoot) { if (!keepStartup) {
try { try {
eval(require('Storage').read('bootupdate.js')); eval(require('Storage').read('bootupdate.js'));
} }
@ -87,16 +89,28 @@ function drainedRestore() {
} }
load(); load();
} }
if (disableBoot) { var checkCharge = function () {
var checkCharge_1 = function () {
if (E.getBattery() < restore) if (E.getBattery() < restore)
return; return;
drainedRestore(); drainedRestore();
}; };
if (Bangle.isCharging()) if (Bangle.isCharging())
checkCharge_1(); checkCharge();
Bangle.on("charging", function (charging) { Bangle.on("charging", function (charging) {
if (charging) if (charging)
checkCharge_1(); checkCharge();
}); });
if (!keepStartup) {
var storage = require("Storage");
for (var _i = 0, exceptions_1 = exceptions; _i < exceptions_1.length; _i++) {
var boot = exceptions_1[_i];
try {
var js = storage.read("".concat(boot, ".boot.js"));
if (js)
eval(js);
}
catch (e) {
console.log("error loading boot exception \"".concat(boot, "\": ").concat(e));
}
}
} }

View File

@ -52,6 +52,8 @@ const draw = () => {
const dateStr = require("locale").date(date, 0).toUpperCase() + const dateStr = require("locale").date(date, 0).toUpperCase() +
"\n" + "\n" +
require("locale").dow(date, 0).toUpperCase(); require("locale").dow(date, 0).toUpperCase();
const x2 = x + 6;
const y2 = y + 66;
g.reset() g.reset()
.clearRect(Bangle.appRect) .clearRect(Bangle.appRect)
@ -59,8 +61,8 @@ const draw = () => {
.setFontAlign(0, 0) .setFontAlign(0, 0)
.drawString(timeStr, x, y) .drawString(timeStr, x, y)
.setFont("Vector", 24) .setFont("Vector", 24)
.drawString(dateStr, x, y + 56) .drawString(dateStr, x2, y2)
.drawString(`${E.getBattery()}%`, x, y + 104); .drawString(`${E.getBattery()}%`, x2, y2 + 48);
if(nextDraw) clearTimeout(nextDraw); if(nextDraw) clearTimeout(nextDraw);
nextDraw = setTimeout(() => { nextDraw = setTimeout(() => {
@ -97,12 +99,12 @@ reload();
Bangle.emit("drained", E.getBattery()); Bangle.emit("drained", E.getBattery());
// restore normal boot on charge // restore normal boot on charge
const { disableBoot = false, restore = 20 }: DrainedSettings const { keepStartup = true, restore = 20, exceptions = ["widdst.0"] }: DrainedSettings
= require("Storage").readJSON(`${app}.setting.json`, true) || {}; = require("Storage").readJSON(`${app}.setting.json`, true) || {};
// re-enable normal boot code when we're above a threshold: // re-enable normal boot code when we're above a threshold:
function drainedRestore() { // "public", to allow users to call function drainedRestore() { // "public", to allow users to call
if(disableBoot){ if(!keepStartup){
try{ try{
eval(require('Storage').read('bootupdate.js')); eval(require('Storage').read('bootupdate.js'));
}catch(e){ }catch(e){
@ -112,7 +114,6 @@ function drainedRestore() { // "public", to allow users to call
load(); // necessary after updating boot.0 load(); // necessary after updating boot.0
} }
if(disableBoot){
const checkCharge = () => { const checkCharge = () => {
if(E.getBattery() < restore) return; if(E.getBattery() < restore) return;
drainedRestore(); drainedRestore();
@ -124,4 +125,15 @@ if(disableBoot){
Bangle.on("charging", charging => { Bangle.on("charging", charging => {
if(charging) checkCharge(); if(charging) checkCharge();
}); });
if(!keepStartup){
const storage = require("Storage");
for(const boot of exceptions){
try{
const js = storage.read(`${boot}.boot.js`);
if(js) eval(js);
}catch(e){
console.log(`error loading boot exception "${boot}": ${e}`);
}
}
} }

View File

@ -1,13 +1,13 @@
{ (function () {
var _a = require("Storage").readJSON("drained.setting.json", true) || {}, _b = _a.battery, threshold_1 = _b === void 0 ? 5 : _b, _c = _a.interval, interval = _c === void 0 ? 10 : _c, _d = _a.disableBoot, disableBoot_1 = _d === void 0 ? false : _d; var _a = require("Storage").readJSON("drained.setting.json", true) || {}, _b = _a.battery, threshold = _b === void 0 ? 5 : _b, _c = _a.interval, interval = _c === void 0 ? 10 : _c, _d = _a.keepStartup, keepStartup = _d === void 0 ? true : _d;
drainedInterval = setInterval(function () { drainedInterval = setInterval(function () {
if (Bangle.isCharging()) if (Bangle.isCharging())
return; return;
if (E.getBattery() > threshold_1) if (E.getBattery() > threshold)
return; return;
var app = "drained.app.js"; var app = "drained.app.js";
if (disableBoot_1) if (!keepStartup)
require("Storage").write(".boot0", "if(typeof __FILE__ === \"undefined\" || __FILE__ !== \"".concat(app, "\") setTimeout(load, 100, \"").concat(app, "\");")); require("Storage").write(".boot0", "if(typeof __FILE__ === \"undefined\" || __FILE__ !== \"".concat(app, "\") setTimeout(load, 100, \"").concat(app, "\");"));
load(app); load(app);
}, interval * 60 * 1000); }, interval * 60 * 1000);
} })();

View File

@ -1,5 +1,5 @@
{ (() => {
const { battery: threshold = 5, interval = 10, disableBoot = false }: DrainedSettings const { battery: threshold = 5, interval = 10, keepStartup = true }: DrainedSettings
= require("Storage").readJSON(`drained.setting.json`, true) || {}; = require("Storage").readJSON(`drained.setting.json`, true) || {};
drainedInterval = setInterval(() => { drainedInterval = setInterval(() => {
@ -10,7 +10,7 @@ drainedInterval = setInterval(() => {
const app = "drained.app.js"; const app = "drained.app.js";
if(disableBoot) if(!keepStartup)
require("Storage").write( require("Storage").write(
".boot0", ".boot0",
`if(typeof __FILE__ === "undefined" || __FILE__ !== "${app}") setTimeout(load, 100, "${app}");` `if(typeof __FILE__ === "undefined" || __FILE__ !== "${app}") setTimeout(load, 100, "${app}");`
@ -18,4 +18,4 @@ drainedInterval = setInterval(() => {
load(app); load(app);
}, interval * 60 * 1000); }, interval * 60 * 1000);
} })()

View File

@ -1,7 +1,7 @@
{ {
"id": "drained", "id": "drained",
"name": "Drained", "name": "Drained",
"version": "0.01", "version": "0.03",
"description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals",
"readme": "README.md", "readme": "README.md",
"icon": "icon.png", "icon": "icon.png",
@ -14,5 +14,8 @@
{"name":"drained.app.js","url":"app.js"}, {"name":"drained.app.js","url":"app.js"},
{"name":"drained.settings.js","url":"settings.js"}, {"name":"drained.settings.js","url":"settings.js"},
{"name":"drained.img","url":"app-icon.js","evaluate":true} {"name":"drained.img","url":"app-icon.js","evaluate":true}
],
"data": [
{"name":"drained.setting.json"}
] ]
} }

View File

@ -1,26 +1,19 @@
(function (back) { (function (back) {
var _a, _b, _c, _d; var _a, _b, _c, _d, _e;
var SETTINGS_FILE = "drained.setting.json"; var SETTINGS_FILE = "drained.setting.json";
var storage = require("Storage"); var storage = require("Storage");
var settings = storage.readJSON(SETTINGS_FILE, true) || {}; var settings = storage.readJSON(SETTINGS_FILE, true) || {};
(_a = settings.battery) !== null && _a !== void 0 ? _a : (settings.battery = 5); (_a = settings.battery) !== null && _a !== void 0 ? _a : (settings.battery = 5);
(_b = settings.restore) !== null && _b !== void 0 ? _b : (settings.restore = 20); (_b = settings.restore) !== null && _b !== void 0 ? _b : (settings.restore = 20);
(_c = settings.interval) !== null && _c !== void 0 ? _c : (settings.interval = 10); (_c = settings.interval) !== null && _c !== void 0 ? _c : (settings.interval = 10);
(_d = settings.disableBoot) !== null && _d !== void 0 ? _d : (settings.disableBoot = false); (_d = settings.keepStartup) !== null && _d !== void 0 ? _d : (settings.keepStartup = true);
(_e = settings.exceptions) !== null && _e !== void 0 ? _e : (settings.exceptions = ["widdst.0"]);
var save = function () { var save = function () {
storage.writeJSON(SETTINGS_FILE, settings); storage.writeJSON(SETTINGS_FILE, settings);
}; };
E.showMenu({ var menu = {
"": { "title": "Drained" }, "": { "title": "Drained" },
"< Back": back, "< Back": back,
"Keep startup code": {
value: settings.disableBoot,
format: function () { return settings.disableBoot ? "No" : "Yes"; },
onchange: function () {
settings.disableBoot = !settings.disableBoot;
save();
},
},
"Trigger at batt%": { "Trigger at batt%": {
value: settings.battery, value: settings.battery,
min: 0, min: 0,
@ -54,5 +47,44 @@
save(); save();
}, },
}, },
"Keep startup code": {
value: settings.keepStartup,
onchange: function (b) {
settings.keepStartup = b;
save();
updateAndRedraw();
},
},
};
var updateAndRedraw = function () {
setTimeout(function () { E.showMenu(menu); }, 10);
if (settings.keepStartup) {
delete menu["Startup exceptions"];
return;
}
menu["Startup exceptions"] = function () { return E.showMenu(bootExceptions); };
var bootExceptions = {
"": { "title": "Startup exceptions" },
"< Back": function () { return E.showMenu(menu); },
};
storage.list(/\.boot\.js/)
.map(function (name) { return name.replace(".boot.js", ""); })
.forEach(function (name) {
bootExceptions[name] = {
value: settings.exceptions.indexOf(name) >= 0,
onchange: function (b) {
if (b) {
settings.exceptions.push(name);
}
else {
var i = settings.exceptions.indexOf(name);
if (i >= 0)
settings.exceptions.splice(i, 1);
}
save();
},
};
}); });
};
updateAndRedraw();
}); });

View File

@ -2,7 +2,8 @@ type DrainedSettings = {
battery?: number, battery?: number,
restore?: number, restore?: number,
interval?: number, interval?: number,
disableBoot?: ShortBoolean, keepStartup?: ShortBoolean,
exceptions?: string[],
}; };
(back => { (back => {
@ -13,23 +14,16 @@ type DrainedSettings = {
settings.battery ??= 5; settings.battery ??= 5;
settings.restore ??= 20; settings.restore ??= 20;
settings.interval ??= 10; settings.interval ??= 10;
settings.disableBoot ??= false; settings.keepStartup ??= true;
settings.exceptions ??= ["widdst.0"]; // daylight savings
const save = () => { const save = () => {
storage.writeJSON(SETTINGS_FILE, settings) storage.writeJSON(SETTINGS_FILE, settings)
}; };
E.showMenu({ const menu: Menu = {
"": { "title": "Drained" }, "": { "title": "Drained" },
"< Back": back, "< Back": back,
"Keep startup code": {
value: settings.disableBoot,
format: () => settings.disableBoot ? "No" : "Yes",
onchange: () => {
settings.disableBoot = !settings.disableBoot;
save();
},
},
"Trigger at batt%": { "Trigger at batt%": {
value: settings.battery, value: settings.battery,
min: 0, min: 0,
@ -63,5 +57,48 @@ type DrainedSettings = {
save(); save();
}, },
}, },
"Keep startup code": {
value: settings.keepStartup as boolean,
onchange: (b: boolean) => {
settings.keepStartup = b;
save();
updateAndRedraw();
},
},
};
const updateAndRedraw = () => {
// will change the menu, queue redraw:
setTimeout(() => { E.showMenu(menu) }, 10);
if (settings.keepStartup) {
delete menu["Startup exceptions"];
return;
}
menu["Startup exceptions"] = () => E.showMenu(bootExceptions);
const bootExceptions: Menu = {
"": { "title" : "Startup exceptions" },
"< Back": () => E.showMenu(menu),
};
storage.list(/\.boot\.js/)
.map(name => name.replace(".boot.js", ""))
.forEach((name: string) => {
bootExceptions[name] = {
value: settings.exceptions!.indexOf(name) >= 0,
onchange: (b: boolean) => {
if (b) {
settings.exceptions!.push(name);
} else {
const i = settings.exceptions!.indexOf(name);
if (i >= 0) settings.exceptions!.splice(i, 1);
}
save();
},
};
}); });
};
updateAndRedraw();
}) satisfies SettingsFunc }) satisfies SettingsFunc

View File

@ -1,2 +1,3 @@
0.01: New App! 0.01: New App!
0.02: Trim old entries from the popcon app cache 0.02: Trim old entries from the popcon app cache
0.03: Avoid polluting global scope

View File

@ -1,18 +1,18 @@
{ (function () {
var oldRead_1 = require("Storage").readJSON; var oldRead = require("Storage").readJSON;
var oneMonth_1 = 1000 * 86400 * 28; var oneMonth = 1000 * 86400 * 28;
var monthAgo_1 = Date.now() - oneMonth_1; var monthAgo = Date.now() - oneMonth;
var cache_1; var cache;
var ensureCache_1 = function () { var ensureCache = function () {
if (!cache_1) { if (!cache) {
cache_1 = oldRead_1("popcon.cache.json", true); cache = oldRead("popcon.cache.json", true);
if (!cache_1) if (!cache)
cache_1 = {}; cache = {};
} }
return cache_1; return cache;
}; };
var trimCache_1 = function (cache) { var trimCache = function (cache) {
var threeMonthsBack = Date.now() - oneMonth_1 * 3; var threeMonthsBack = Date.now() - oneMonth * 3;
var del = []; var del = [];
for (var k in cache) for (var k in cache)
if (cache[k].last < threeMonthsBack) if (cache[k].last < threeMonthsBack)
@ -22,21 +22,21 @@
delete cache[k]; delete cache[k];
} }
}; };
var saveCache_1 = function (cache, orderChanged) { var saveCache = function (cache, orderChanged) {
trimCache_1(cache); trimCache(cache);
require("Storage").writeJSON("popcon.cache.json", cache); require("Storage").writeJSON("popcon.cache.json", cache);
if (orderChanged) { if (orderChanged) {
var info = oldRead_1("popcon.info", true); var info = oldRead("popcon.info", true);
info.cacheBuster = !info.cacheBuster; info.cacheBuster = !info.cacheBuster;
require("Storage").writeJSON("popcon.info", info); require("Storage").writeJSON("popcon.info", info);
} }
}; };
var sortCache_1 = function () { var sortCache = function () {
var ents = Object.values(cache_1); var ents = Object.values(cache);
ents.sort(function (a, b) { ents.sort(function (a, b) {
var n; var n;
var am = (a.last > monthAgo_1); var am = (a.last > monthAgo);
var bm = (b.last > monthAgo_1); var bm = (b.last > monthAgo);
n = bm - am; n = bm - am;
if (n) if (n)
return n; return n;
@ -64,31 +64,31 @@
}; };
require("Storage").readJSON = (function (fname, skipExceptions) { require("Storage").readJSON = (function (fname, skipExceptions) {
var _a; var _a;
var j = oldRead_1(fname, skipExceptions); var j = oldRead(fname, skipExceptions);
if (/\.info$/.test(fname)) { if (/\.info$/.test(fname)) {
var cache_2 = ensureCache_1(); var cache_1 = ensureCache();
var so = void 0; var so = void 0;
if (j.src && (so = (_a = cache_2[j.src]) === null || _a === void 0 ? void 0 : _a.sortorder) != null) if (j.src && (so = (_a = cache_1[j.src]) === null || _a === void 0 ? void 0 : _a.sortorder) != null)
j.sortorder = so; j.sortorder = so;
else else
j.sortorder = 99; j.sortorder = 99;
} }
return j; return j;
}); });
var oldLoad_1 = load; var oldLoad = load;
global.load = function (src) { global.load = function (src) {
if (src) { if (src) {
var cache_3 = ensureCache_1(); var cache_2 = ensureCache();
var ent = cache_3[src] || (cache_3[src] = { var ent = cache_2[src] || (cache_2[src] = {
pop: 0, pop: 0,
last: 0, last: 0,
sortorder: -10, sortorder: -10,
}); });
ent.pop++; ent.pop++;
ent.last = Date.now(); ent.last = Date.now();
var orderChanged = sortCache_1(); var orderChanged = sortCache();
saveCache_1(cache_3, orderChanged); saveCache(cache_2, orderChanged);
} }
return oldLoad_1(src); return oldLoad(src);
}; };
} })();

View File

@ -1,4 +1,4 @@
{ (() => {
type Timestamp = number; type Timestamp = number;
type Cache = { type Cache = {
[key: string]: { [key: string]: {
@ -113,4 +113,4 @@ global.load = (src: string) => {
return oldLoad(src); return oldLoad(src);
}; };
} })()

View File

@ -2,7 +2,7 @@
"id": "popconlaunch", "id": "popconlaunch",
"name": "Popcon Launcher", "name": "Popcon Launcher",
"shortName": "Popcon", "shortName": "Popcon",
"version": "0.02", "version": "0.03",
"description": "Launcher modification - your launchers will display your favourite (popular) apps first. Overrides `readJSON`, may slow down your watch", "description": "Launcher modification - your launchers will display your favourite (popular) apps first. Overrides `readJSON`, may slow down your watch",
"readme": "README.md", "readme": "README.md",
"icon": "app.png", "icon": "app.png",