From 16202c1843d313496a01c6ce3e2feff02a22439b Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 09:46:22 +0100 Subject: [PATCH 01/40] drained: always check charge, regardless of boot-disable --- apps/drained/app.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index 9fc2665ee..22e173b46 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -112,16 +112,14 @@ function drainedRestore() { // "public", to allow users to call load(); // necessary after updating boot.0 } -if(disableBoot){ - const checkCharge = () => { - if(E.getBattery() < restore) return; - drainedRestore(); - }; +const checkCharge = () => { + if(E.getBattery() < restore) return; + drainedRestore(); +}; - if (Bangle.isCharging()) - checkCharge(); +if (Bangle.isCharging()) + checkCharge(); - Bangle.on("charging", charging => { - if(charging) checkCharge(); - }); -} +Bangle.on("charging", charging => { + if(charging) checkCharge(); +}); From cbc69c9275a05c6d8e0bd36d21f1e0b114350044 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 09:58:47 +0100 Subject: [PATCH 02/40] drained: better clock alignment --- apps/drained/app.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index 22e173b46..9111a49b4 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -52,6 +52,8 @@ const draw = () => { const dateStr = require("locale").date(date, 0).toUpperCase() + "\n" + require("locale").dow(date, 0).toUpperCase(); + const x2 = x + 6; + const y2 = y + 66; g.reset() .clearRect(Bangle.appRect) @@ -59,8 +61,8 @@ const draw = () => { .setFontAlign(0, 0) .drawString(timeStr, x, y) .setFont("Vector", 24) - .drawString(dateStr, x, y + 56) - .drawString(`${E.getBattery()}%`, x, y + 104); + .drawString(dateStr, x2, y2) + .drawString(`${E.getBattery()}%`, x2, y2 + 48); if(nextDraw) clearTimeout(nextDraw); nextDraw = setTimeout(() => { From 00cf120a28e6f3c476631db2df09c51862b2b640 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:36:31 +0100 Subject: [PATCH 03/40] drained: s/disableBoot/keepStartup/ --- apps/drained/app.ts | 4 ++-- apps/drained/boot.ts | 4 ++-- apps/drained/settings.ts | 22 ++++++++++++---------- 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index 9111a49b4..14a8ad4bc 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -99,12 +99,12 @@ reload(); Bangle.emit("drained", E.getBattery()); // restore normal boot on charge -const { disableBoot = false, restore = 20 }: DrainedSettings +const { keepStartup = true, restore = 20 }: DrainedSettings = require("Storage").readJSON(`${app}.setting.json`, true) || {}; // re-enable normal boot code when we're above a threshold: function drainedRestore() { // "public", to allow users to call - if(disableBoot){ + if(!keepStartup){ try{ eval(require('Storage').read('bootupdate.js')); }catch(e){ diff --git a/apps/drained/boot.ts b/apps/drained/boot.ts index 4dc885c20..3675e06e6 100644 --- a/apps/drained/boot.ts +++ b/apps/drained/boot.ts @@ -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) || {}; drainedInterval = setInterval(() => { @@ -10,7 +10,7 @@ drainedInterval = setInterval(() => { const app = "drained.app.js"; - if(disableBoot) + if(!keepStartup) require("Storage").write( ".boot0", `if(typeof __FILE__ === "undefined" || __FILE__ !== "${app}") setTimeout(load, 100, "${app}");` diff --git a/apps/drained/settings.ts b/apps/drained/settings.ts index c79e6605c..01e4be653 100644 --- a/apps/drained/settings.ts +++ b/apps/drained/settings.ts @@ -2,7 +2,7 @@ type DrainedSettings = { battery?: number, restore?: number, interval?: number, - disableBoot?: ShortBoolean, + keepStartup?: ShortBoolean, }; (back => { @@ -13,23 +13,17 @@ type DrainedSettings = { settings.battery ??= 5; settings.restore ??= 20; settings.interval ??= 10; - settings.disableBoot ??= false; + settings.keepStartup ??= true; const save = () => { storage.writeJSON(SETTINGS_FILE, settings) }; + const formatBool = (b: boolean) => b ? "On" : "Off"; + E.showMenu({ "": { "title": "Drained" }, "< Back": back, - "Keep startup code": { - value: settings.disableBoot, - format: () => settings.disableBoot ? "No" : "Yes", - onchange: () => { - settings.disableBoot = !settings.disableBoot; - save(); - }, - }, "Trigger at batt%": { value: settings.battery, min: 0, @@ -63,5 +57,13 @@ type DrainedSettings = { save(); }, }, + "Keep startup code": { + value: settings.keepStartup as boolean, + format: formatBool, + onchange: (b: boolean) => { + settings.keepStartup = b; + save(); + }, + }, }); }) satisfies SettingsFunc From dfece3994c7c71d6447fc8af28526332e5a75c7d Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:37:03 +0100 Subject: [PATCH 04/40] drained: add settings into metadata --- apps/drained/metadata.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/drained/metadata.json b/apps/drained/metadata.json index 89a069b2f..a845c4ce8 100644 --- a/apps/drained/metadata.json +++ b/apps/drained/metadata.json @@ -14,5 +14,8 @@ {"name":"drained.app.js","url":"app.js"}, {"name":"drained.settings.js","url":"settings.js"}, {"name":"drained.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"drained.setting.json"} ] } From 4d676a9e46954149099221cd2b7fe5fa4de675bc Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:39:14 +0100 Subject: [PATCH 05/40] drained: infrastructure for boot exceptions --- apps/drained/app.ts | 2 +- apps/drained/settings.ts | 42 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index 14a8ad4bc..a079d36df 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -99,7 +99,7 @@ reload(); Bangle.emit("drained", E.getBattery()); // restore normal boot on charge -const { keepStartup = true, restore = 20 }: DrainedSettings +const { keepStartup = true, restore = 20, exceptions = ["widdst.0"] }: DrainedSettings = require("Storage").readJSON(`${app}.setting.json`, true) || {}; // re-enable normal boot code when we're above a threshold: diff --git a/apps/drained/settings.ts b/apps/drained/settings.ts index 01e4be653..d3ed528f9 100644 --- a/apps/drained/settings.ts +++ b/apps/drained/settings.ts @@ -3,6 +3,7 @@ type DrainedSettings = { restore?: number, interval?: number, keepStartup?: ShortBoolean, + exceptions?: string[], }; (back => { @@ -14,6 +15,7 @@ type DrainedSettings = { settings.restore ??= 20; settings.interval ??= 10; settings.keepStartup ??= true; + settings.exceptions ??= ["widdst.0"]; // daylight savings const save = () => { storage.writeJSON(SETTINGS_FILE, settings) @@ -21,7 +23,7 @@ type DrainedSettings = { const formatBool = (b: boolean) => b ? "On" : "Off"; - E.showMenu({ + const menu: Menu = { "": { "title": "Drained" }, "< Back": back, "Trigger at batt%": { @@ -63,7 +65,43 @@ type DrainedSettings = { onchange: (b: boolean) => { settings.keepStartup = b; save(); + updateMenu(); + E.showMenu(menu); }, }, - }); + }; + + const updateMenu = () => { + 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, + format: formatBool, + 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(); + }, + }; + }); + }; + + updateMenu(); + E.showMenu(menu); }) satisfies SettingsFunc From c9f4fd7cc725f8ce2caacb2ad08289e8a34eca06 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:41:51 +0100 Subject: [PATCH 06/40] drained: load boot exceptions (e.g. dst) --- apps/drained/app.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/drained/app.ts b/apps/drained/app.ts index a079d36df..3adfbec02 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -125,3 +125,15 @@ if (Bangle.isCharging()) Bangle.on("charging", charging => { 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}`); + } + } +} From a5253487f11a3cbf1dc35c47e2acd60dea95c1b9 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:43:10 +0100 Subject: [PATCH 07/40] drained: version bump for boot exceptions --- apps/drained/ChangeLog | 1 + apps/drained/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/drained/ChangeLog b/apps/drained/ChangeLog index 1a3bc1757..ec09a29bd 100644 --- a/apps/drained/ChangeLog +++ b/apps/drained/ChangeLog @@ -1 +1,2 @@ 0.01: New app! +0.02: Allow boot exceptions, e.g. to load DST diff --git a/apps/drained/metadata.json b/apps/drained/metadata.json index a845c4ce8..ef7bbeb23 100644 --- a/apps/drained/metadata.json +++ b/apps/drained/metadata.json @@ -1,7 +1,7 @@ { "id": "drained", "name": "Drained", - "version": "0.01", + "version": "0.02", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "readme": "README.md", "icon": "icon.png", From e489b26834dda62f9fc9fa1c2068e55ebdce88b6 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 7 May 2023 10:44:04 +0100 Subject: [PATCH 08/40] drained: regenerate JS --- apps/drained/app.js | 46 +++++++++++++++++++----------- apps/drained/boot.js | 4 +-- apps/drained/settings.js | 60 ++++++++++++++++++++++++++++++++-------- 3 files changed, 80 insertions(+), 30 deletions(-) diff --git a/apps/drained/app.js b/apps/drained/app.js index f9ae04605..e27fcb1d1 100644 --- a/apps/drained/app.js +++ b/apps/drained/app.js @@ -35,14 +35,16 @@ var draw = function () { var dateStr = require("locale").date(date, 0).toUpperCase() + "\n" + require("locale").dow(date, 0).toUpperCase(); + var x2 = x + 6; + var y2 = y + 66; g.reset() .clearRect(Bangle.appRect) .setFont("Vector", 55) .setFontAlign(0, 0) .drawString(timeStr, x, y) .setFont("Vector", 24) - .drawString(dateStr, x, y + 56) - .drawString("".concat(E.getBattery(), "%"), x, y + 104); + .drawString(dateStr, x2, y2) + .drawString("".concat(E.getBattery(), "%"), x2, y2 + 48); if (nextDraw) clearTimeout(nextDraw); nextDraw = setTimeout(function () { @@ -75,9 +77,9 @@ var reload = function () { }; reload(); 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() { - if (disableBoot) { + if (!keepStartup) { try { eval(require('Storage').read('bootupdate.js')); } @@ -87,16 +89,28 @@ function drainedRestore() { } load(); } -if (disableBoot) { - var checkCharge_1 = function () { - if (E.getBattery() < restore) - return; - drainedRestore(); - }; - if (Bangle.isCharging()) - checkCharge_1(); - Bangle.on("charging", function (charging) { - if (charging) - checkCharge_1(); - }); +var checkCharge = function () { + if (E.getBattery() < restore) + return; + drainedRestore(); +}; +if (Bangle.isCharging()) + checkCharge(); +Bangle.on("charging", function (charging) { + if (charging) + 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)); + } + } } diff --git a/apps/drained/boot.js b/apps/drained/boot.js index 97f405123..b71db0d92 100644 --- a/apps/drained/boot.js +++ b/apps/drained/boot.js @@ -1,12 +1,12 @@ { - 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_1 = _b === void 0 ? 5 : _b, _c = _a.interval, interval = _c === void 0 ? 10 : _c, _d = _a.keepStartup, keepStartup_1 = _d === void 0 ? true : _d; drainedInterval = setInterval(function () { if (Bangle.isCharging()) return; if (E.getBattery() > threshold_1) return; var app = "drained.app.js"; - if (disableBoot_1) + if (!keepStartup_1) require("Storage").write(".boot0", "if(typeof __FILE__ === \"undefined\" || __FILE__ !== \"".concat(app, "\") setTimeout(load, 100, \"").concat(app, "\");")); load(app); }, interval * 60 * 1000); diff --git a/apps/drained/settings.js b/apps/drained/settings.js index fe4ab9c4b..47131224c 100644 --- a/apps/drained/settings.js +++ b/apps/drained/settings.js @@ -1,26 +1,20 @@ (function (back) { - var _a, _b, _c, _d; + var _a, _b, _c, _d, _e; var SETTINGS_FILE = "drained.setting.json"; var storage = require("Storage"); var settings = storage.readJSON(SETTINGS_FILE, true) || {}; (_a = settings.battery) !== null && _a !== void 0 ? _a : (settings.battery = 5); (_b = settings.restore) !== null && _b !== void 0 ? _b : (settings.restore = 20); (_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 () { storage.writeJSON(SETTINGS_FILE, settings); }; - E.showMenu({ + var formatBool = function (b) { return b ? "On" : "Off"; }; + var menu = { "": { "title": "Drained" }, "< 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%": { value: settings.battery, min: 0, @@ -54,5 +48,47 @@ save(); }, }, - }); + "Keep startup code": { + value: settings.keepStartup, + format: formatBool, + onchange: function (b) { + settings.keepStartup = b; + save(); + updateMenu(); + E.showMenu(menu); + }, + }, + }; + var updateMenu = function () { + 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, + format: formatBool, + 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(); + }, + }; + }); + }; + updateMenu(); + E.showMenu(menu); }); From efe023c5cb348e21d98e0a254092ba8f36c346ce Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 8 May 2023 11:07:17 +0100 Subject: [PATCH 09/40] drained: use Bangle's bool formatter --- apps/drained/settings.ts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/apps/drained/settings.ts b/apps/drained/settings.ts index d3ed528f9..23d7ce18d 100644 --- a/apps/drained/settings.ts +++ b/apps/drained/settings.ts @@ -21,8 +21,6 @@ type DrainedSettings = { storage.writeJSON(SETTINGS_FILE, settings) }; - const formatBool = (b: boolean) => b ? "On" : "Off"; - const menu: Menu = { "": { "title": "Drained" }, "< Back": back, @@ -61,7 +59,6 @@ type DrainedSettings = { }, "Keep startup code": { value: settings.keepStartup as boolean, - format: formatBool, onchange: (b: boolean) => { settings.keepStartup = b; save(); @@ -88,7 +85,6 @@ type DrainedSettings = { .forEach((name: string) => { bootExceptions[name] = { value: settings.exceptions!.indexOf(name) >= 0, - format: formatBool, onchange: (b: boolean) => { if (b) { settings.exceptions!.push(name); From 96342a3c39d1921a562f3bb9bf31bb7e5c2c5396 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Wed, 10 May 2023 05:00:03 -0500 Subject: [PATCH 10/40] Update interface.html - shadowclk Add comments Reduce timeout to 50ms --- apps/shadowclk/interface.html | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/apps/shadowclk/interface.html b/apps/shadowclk/interface.html index fd29b7cee..94facbadd 100644 --- a/apps/shadowclk/interface.html +++ b/apps/shadowclk/interface.html @@ -82,7 +82,6 @@ #message-container { height: 40px; - /* adjust the height based on your desired fixed height */ margin-top: 20px; text-align: center; } @@ -106,6 +105,7 @@ - + \ No newline at end of file diff --git a/apps/shadowclk/screenshot-1.png b/apps/shadowclk/screenshot-1.png index 2d4933110df1d029b6835f0ef7e84e687d642368..2ebc7a65cfda14f4648b466c0250b49d333ac919 100644 GIT binary patch literal 3155 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 literal 3510 zcmc&%=|9vB_x^ro7-P!_DeKr}8*8@~47sz_O=VxkR0u;2BD+y4%32wWEG9O%ovL(b3!oKb*#JaN=f`7y*^29O)^akI zAf{x84p{HhqWy*Fu$sXvz$A3P7e_y2PRqobMSAZ9Hlj}xq7G0aUP&^lBwPrzps|VN zNWduAn}}#MhzN_&C&Xl0+_BsM`fq-~D3M|KM$CGLM_c=qfTv;qYW4g=cW5!fw6A;s zD^O+fvcezvh3PF*I`!l04}ra262KMRB?3tg5hIKwNNG~1GGjSbAu+RVf+63-TG@nu zx4PV{z!nmJFyMUDIY;GnXB@nX$Qf z#r~_>m#}%hJ1<5{4*ZbWtQRQ=C_%Eq|8L)_&?0**RIDxPAMF zZhzSITnG&)Ry|CDN;%|s5h}9ov5Pf?^w0!oZ`E?VFdW~}r=;cvLX>ok&h+b}2@4jV z;pu{9prgW$VFWbU!~yP307UM(yjvI0@i|BBDj`CaZvLcPF9Ohy8{AsOi(S=TxQ zH0Dw+q6Pr>$re3d5YX!iF&SuqMkU=`nGArr|5fR$CXj8b*Dp{tD#rXO;MAW6%cgek zRrb^`PMKXEf3>m2tQ(F7RQHALrKa^QZlcbOX#D5EUJKuLIxuE(p{aHky{jpzwS*<*2s?x+iP?ZZiP!QXT!-aJ=%MH0QZ{&h7X^grt`c z(5Q}Gda(Xbv}Vsc@CTvoG8bIt{W~r4Kghay*VL z&UkEech7KD(Bb#uL{yVLmu)JSr)y9xLpbw~6dy-QMQD696~=N6uVlE%Bj>vO0H>wW zugCO*=g&$N--aj^s(HdJ?~Fp~|5<8#@eQCal4F^-Ci#oLtIM zC@544nvaHSpa@!ltw2RSU5e8XF5LU9zX;y@|r52>UF ztG4I;J1)aXP7l3g`6a#2n83_WjyR4*c#SbQvU8(})BqF#S5@4bdM)BLIN9iL$gl#v z-dOM?*N6!|z`G#ld%J!>#9-IbcLcgv`|VGi{V!TE!QwO_M6n$u3r0}c(^PJtYPEN6 zXM}LdS63u?GxE!E3*V2a!sAu%Cqi!7Mcg{wMw#d{DO;feIGr+ASxJ~4BAgs+Sl!Ho zM%1DpQRK8Lla{EF6o-XN6Z!^FoOXFdPu}Vs7*r14${sqUpg2ir*>*zU%*i?DJLHy& zB@|Rw5NZJKmcg0*w}b^lG&4pu7b-=9Ukgn}_*EUb0BDFbDG@1OcaNhVr=x}K)*2-6 zbsY)w+6e55@7CHj9-IXmIF-9p zh&N^1MTF)qdrhqp^7w}*O6{%bM}vO1A;`?*_2xDXDcuUmoQ$qPADDOMio6#V8%=KD zA$Q+yA*ps!QRP$DLqwVTcSuh?RyzX6FXj)yb8ch!ho`2*u;$2tXKy8Lymyu=B4H=W z`@$j|BhQXTAJ=72Ttv;S@Bh`xo^^(cO)5deWN$Fb(c>Qv~IyVti?HGQX9_# zMxs%P&(s;G2;O!FZ|PrKIV>gGWU@~h@C$cXvM*t-)l2-nJ z-OKle-4~iQ!h#L2#%G!l6b*f)kgW4o!)mn;)00;1lk+`%k;)gW+uM{sj%5R>MLs=Y zf3zOb@|9v#MNS`Y_t_biPZ1N`lV2f%SXZJjFm3Q8#U>+m!Vf%LC@qcm-qm08XYYkw zT92g^?DVrX85Dq6{yP5dB-C-x^{Qp!4#g&s~PLX+e(~0Y@JK^$aS392l*0{*mB`{AuU!s{g+fuvA zxhL2%l$D?>tt(S`05trGdf3Zf7tB67ix%(u@JxvJDiZb5<)59KI`AXOr(u&q)E_)s z3LL#VIvOtSW#-D~p!@qF^;RV~Q{(XV;22@FrllvJ$w!uv%RZSJi%tESHYzFDm@@w7 zhcZy^Bkm$D;mEYKahrXDZDT(!uL_4sgp38(f5^{j?0laPpcXpY}v~J@A9hqlZ ztnb2Z!Gzueyx3_~*!ujYR@y`wgM27wr040sof}0eA>WPm)Bg^}oucXIMCOd1w_m<2 zjuq}woV@Y$=)oKUeXB;v8>`HE6hIqekmRm{2h$fN@96XtW+w?NuIr0vq-8F6c*Ywv zsbpS-Hp#lnV$FX&f0EXHA^qsji(F51RRVQ;vfMuW0+G6^qS|VV5^0KqgnHVkYE&=a zAk3Gj0Ipihw@h=tmOLNMR^&e=yH}_dKkn3IY zt_~L>tR7sLUpkB?RLJxFMvH-Yy+`AvBjyAf6(FdMhEY_0QkWbz+8Hk&z-*0;SqQ%D z{s`VwxseOF1U`vAeY8yyJdpb9LIyhQ$Pg3*O)}?It$*87oC>k`C(=*Vbu({-v{=?b zvqQI}R~Os%y<)wimPDaWbY=|DC>{VYyj#xHI6C*>S#IuJEOm%+?g08m=%9oJ!OykM z+Ikuj?@-b!waD@OB@}D;3$uqZWIYXd!CmK0de8As#(nr?#*-kpT*7qQf<{?fWo*!T zVlZ}5(rJ!A1L5f7s;2a>`yWHA-I2A=K4JFhkVUInA)=KPYM;-q_i2yKr=~7{KXDRg z{v-Uj6?9&Xd46< z4X3o)J|c%7pOQeRB2lP0R>Ih2Ce|KMs{ZmoFj{L)t*WCmjE*^d^gvYRuesQV6q2Imq zT2Fj!bot~i{miLC&j*GLs%sEs#{dPU03@h3wdji42{Yq!KOSNofbr`sL}jPpOm;Q6 zYEj}C-Ms4%&pOydkblQ&Y^O)JEqmw)|Z%v=)$sMC#M@X@Q~WU0ueDGdiKu+u(9)ww>VFYys=>@ zWh?sozD>i;%ga_;uTa;GPO3=a#p&V-qRz_ {1&Eb)7-gw?d&bpP>&_Eo{~EDYn%; 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 From 5126f9178d94af475b44217c40eacb8038cae3b5 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Wed, 10 May 2023 16:59:18 -0500 Subject: [PATCH 16/40] better icons --- apps/shadowclk/app-icon.js | 2 +- apps/shadowclk/app.png | Bin 13926 -> 3098 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/shadowclk/app-icon.js b/apps/shadowclk/app-icon.js index f77ccb81c..b11a518c0 100644 --- a/apps/shadowclk/app-icon.js +++ b/apps/shadowclk/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwxH+64Af1gAIB4uBwIIGFy+yAAoJBBgOt1o+DwIvdjwAEtBYBFwQvBLwUAF8sAGAODF4VWwIvetAAFL4zIJF6x/Bd5IvCAH4A/AH4A/AH4A/AA2sABAQLC5QvOkYAHjguGBYgmBC5FdF7tAF59WF5scAAQvKxALFF7KiDxAxDipeJF40VAAmBeaQjDmSeKF4pFBjlkdx4AEshMDEQJbBDwOsrsVNgSPKGCQbEUwIGCE4KSFF5VAF6LjDLwIvINoQvCjgADMCmso5eEAAOBAALyGG4QxBAARJDrpeWABC/EVJM5F54TCjheDF5haBAAKiEJQJeeH4jvErusTQQvQJwa3EWQYvMAAovOLwcOVg63EF5yqLAARyCLw4vLI4NrFolHhyqLEgU5isVmQKGoEcY4ldjkcEgeIoFkx9krtWFxo7NX4oHCB42BBI4A/AH4AcwNWwK/IWIILBWYesc4OBBYIEDcyQWBAQI0BEwQdCqwHBHwgtCHwwvTC4RJDEgQ3CB4IJFO4QLCNoYvOAAIDDlYJCAIYCCSYQSEAAbEWDAodXFyJ6CQQZaCAYQLGHzQgCVoIkEeATNEewYvZEoIgCLAbhCFgQ6GT1B0GF1oA/AH4AeA")) +require("heatshrink").decompress(atob("mEwxH+64Ae1mBAA+sBgOt1oPBqwJBF7lcsQAEw+HEwWtwetwIvBqwvcsUeAAlDLAOs1tZwfXlcrq0ANIQviFAOtl4viw9DAAlo1l7L4ODR4OIZISPcb4QAGBgOJL4IAg1gAHFUIA/AH4A/AH4A51lkAA+ICI2IBYWB1msxAAH1gvNjkjAA0VDAuICAcVwIGCjgADAoMyF7msoALEF4IWHkYvOioACGYgvFro7FF5JfO6+BqwACioYChwvDNwwvFhwAEqz0RWYcclbjBGIOzWwYvHBIJ6BrruNAAs5JgeBXQMcnOIwM5hxsCR5McwJeZAwMVPgWlL5CaFMCJeFXYR/BJodAF4iKBAARgDrouPcYZeCBANdmVWAoSWBF4fXwIADJIcyF59dLwo+IX4gLFwJKChyQOLwcVlYPOfgNkAAOIJQIvSLxwvGd4c5LwYvPDwlWBQmIAAIvMaoIEDF51kCQUHCQgoCW4aPGFYgzDVRReOF4QJCF4q6EFwcHVRQvDmUOh0rOIusisVY4YRBA4IkDrsVnNAisylYuNDwQACBQ+BQwIREAwgOCq160otOAH4A/ACdWldWVYK/GqwBBAoIKCBAQLDAIIOBFx+sF4QCDcgIJBAgMrlYCBHwIUDGAQPDF6QADGAQvDEQZiCOYQtCHYQDBF6AwBAARcBJIQHEBQaTCAoQACAgTDVFYYGDB5LycXIbdELQQJCAAKJCLoQ0YXIatBYYQGCgDPGAIKMXF4YdCAIZlCGohrEMgKUcACCQBF9oA/AH4Ad")) diff --git a/apps/shadowclk/app.png b/apps/shadowclk/app.png index b1aa5c0b7df023904b24ac4a8a2383e046943474..a8f7d05ac0ac872d894c3aaa3becf03656abc790 100644 GIT binary patch delta 3080 zcmV+j4EOWqY?>I58AJvE00374`G)`i00d`2O+f$vv5yP zfP?@5`Tzg`fam}Kbua(`>RI+y?e7jT@qQ9P4@E*yUVYybcNY5;vkYCZq}00(qQ zO+^Ri1qu~71N5_EQ~&@A2}wjjRA}Dqn14)^SGvbP@4Pe2%lu%NK@d@K&_WR}f?BoR z;M#7LsCZLb?$#C3+)cfWO>eT?%ce$qada2#U((P@x zvIY){{qr&ZW z6NyBy*=#6^!o9@h%a{4nnLnZE;*T4Q1X)|Kmg3@K04`hrlL_+jK-<#N!l_fIP!xr% ztSrjP%I+xv$5jVDgO8gJ-y}31nr0ISQZy;#b?1N4*4oPU?Zvp=;Bvvab1@Ryix)2v ziA1p5?KCzvQd(MyUa!Ar1T>O{@vL!PTk{%TyhuosHWifu3fO7d$*0wya`ECtyxw)3 zI|s{_fuexs=+UEm@x>Qhy?T|(%1Rs#$32a}gr`;1$?wG91PNIq^ZxtqbNu-4Sg`_{ zn_+*^B1lUEZ8#ieWMqWi-d@JW#)w9v_nd$cBWqa02qV+VRaCOchA5Pmm-F=gXXxsJ z@^a|zhRc^hTTxL#M@I)*t(GlYwvd^bc~2*=)oU4ie~_Jyov5lh(=KVL8meN^q7*VS zmy($Y@4gEe8L(mnNJ0p4&s{zRfk1$PfdPMn8h;uBfz4*aYPA9|G6FhXY!7_v1pZcN zzU>M8lfbtVK029DRMf(cVs2QJ8HwajS7o zAixuwH)Baoo>9l+^YOcu7W#xhbE}PMXo&sm*Atc`S_TJ^G;=J1Xp~%=jhw8k`2K&3 zmj^y;Z>Lz22(DTMvt&pBNtQ`_=N+o-b~Zow;Ech4^OwKyyxmT8>C#vfv|9M>Z#fbQ z5#F$YpDkL1Y&OpxWl19Ha0E-3I zt%H=5DJ*7sFA@y$>x&oZ+O}dhwT*#wv}ELtP#0*)!eyy}i7fkpZ)L*JuQvZ+h9t2vk(S&=7z4{pf+D z zY9$~<%!7l2Fgy$e1+g}xqcgplkO0NSkeUkJ-6XZOvEOXwM_ad&m6L8O+RNRc$RV$TBZ@z5HKgC6`-U36zxFCNLWm z1xiX{zc+2-<`YkFxW1mWo*sU>ZXMDbvODiYcBZL`+T7gO=DX$n``gI%LF!U;@2JzEv>C{R-J!W1ja^2c*o~s z{0{FwwQU=jSy{9+HX?U)5FH+dOP9#Lr98H@G`_cG3rW|mP47^WF#7#);>2y06C$R1 z#l?`G4w6J~VIh@&{xfUmh~B&i)U>tnNk+!)!RqVDX=|hG`R4)HY`62DM~=|Z*@-q3 zqF{>pjE;^H2n43}7X^R*ZS7jd+uIp+yJN~D1d=52Ze1Opm6XJCMphOd|KSgK-EJ&X zm2V*g#{7Pc_Vh5aYgeqm??-#&2tWDZ56N1!3V;-=m0$h*=ZIS}sF{*oolYkM0|V3g zRE5BnlEQP(JvT#A#mSR==5RoEHY6u=RinY-a8USl3DmT-a5jH4Gxi7rP+iS~0|Wf1 zynM=vkdU>rcO_&Qk(fBGOqL`*Y;NYn;2@fW1k^x)5=r98?b{iZBrq5zI>sLeFgh|q zJj_X8Y;-i{{RxHecu-E9;MwwWQsQ`I29lDdCq6(U1g*g!zu&MSX7~GPJa&w}V36Y$ z3oKbOzrOEApw)lrK#0maYr{jqypPW{&e{hhu+u8`~^`vXHl&)EWX`+or z6I;(yAxW|Gl_Y^ILsAm0Pe08;pAR)PHP!|o7(^Z%j2m5;Lq^p|gg*`qF|>Mhtl-8C z%%@ND%#VLe;vGw(;rewBrl#`3`t|&W)5-C--kQ^ELXv-2qbL~q`)?PT&8SP4PCt7! zG?4A}vNAh+;RKqmT;XIS5|cJng}2{kM`|it9)5TxSy@I{t)M831N~DcCPYkjCo8K& zRh5VH^4Qzbg2mxLnsT0!0DU-&@sm%m96H2L_U&VFdU{*}abq*=@t_<(j`i3v5P}q^ zlb`PWhJl>>YCvhOaB&2jGo*|A!yqbUKl>T7Ix?+vE$M5CUg+H?4myE%f*Ivno5A4I4LNx}|DCzn{AE z=jrV1r2Wz*l9H0xuweraY}!Qnk|lExo1nXf&F* zV=aG(!0_-eFTVI99UUFyC>D(eVQFRcF^73&CQ!P*}Qo(AAIlu`T6+_4GrOTyLsuQ zm&lsqLO(A8UauELQ7{^f7z_puA3jWTb2EQNqmlIVbc%|K$jQmUVzF@H!UgWT?>+56Bo;`f^)mQZN^l!1{ zySphUD4@T;A4!rZEiIjt+pkUFPW1KlaqZeQ{C+>Gs$#WT*|>2dvMdt{g=lJOV*UE{ zGxCM1s(8I#l9Q9^>gocx>+<+UB5)_pojb>wGiPu*o#f``l97=?V`C!^Jn(-2H8nK| zA;{0q$K`VI$Rm$XRaHesMh4+<7`xq0e}6wUH8t$owTtW5ucIgmCXRVgYe zS`dMGU+SmA=kqZ-I?CYSAXQaWsH%#?;b8gl<+xlfTrL-?s&eq)L57Bg*uH%`ZnvAR zt}c8&ABv)I_Uu{G)6;P{9GHJhCNvriNl8fyCa~Z{mYSN1+wI2Z^I@@Ac>M9lvD@tw z6%`Q-2FcIQXZ7mU6c!dzR8&M^VIek~jnvds5)%_yv0?>gvzf;pdkl?6Ltb7UyLa#A z)mL9-WR8nVJS=z#2_Xmug9ste>2zo`8p7c)2?+^=LLqcI-DL6+LJ)tAMkl{|y&hFn zQB@VaUQZ|#LY8I1;V`ei{yMvN@8ppnGBYhOH7zkPR5CF-Ff=+eF)J`I WIxsNmyN&Ar0000tMc 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�>Wq&0JuDIux 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 Date: Wed, 10 May 2023 23:23:28 +0100 Subject: [PATCH 17/40] drained: avoid polluting global scope --- apps/drained/boot.js | 10 +++++----- apps/drained/boot.ts | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/drained/boot.js b/apps/drained/boot.js index b71db0d92..48c1572bd 100644 --- a/apps/drained/boot.js +++ b/apps/drained/boot.js @@ -1,13 +1,13 @@ -{ - 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.keepStartup, keepStartup_1 = _d === void 0 ? true : _d; +(function () { + 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 () { if (Bangle.isCharging()) return; - if (E.getBattery() > threshold_1) + if (E.getBattery() > threshold) return; var app = "drained.app.js"; - if (!keepStartup_1) + if (!keepStartup) require("Storage").write(".boot0", "if(typeof __FILE__ === \"undefined\" || __FILE__ !== \"".concat(app, "\") setTimeout(load, 100, \"").concat(app, "\");")); load(app); }, interval * 60 * 1000); -} +})(); diff --git a/apps/drained/boot.ts b/apps/drained/boot.ts index 3675e06e6..1fcb0591b 100644 --- a/apps/drained/boot.ts +++ b/apps/drained/boot.ts @@ -1,4 +1,4 @@ -{ +(() => { const { battery: threshold = 5, interval = 10, keepStartup = true }: DrainedSettings = require("Storage").readJSON(`drained.setting.json`, true) || {}; @@ -18,4 +18,4 @@ drainedInterval = setInterval(() => { load(app); }, interval * 60 * 1000); -} +})() From b4d46d5779ee43f5701e62b20d13ac1f3daf58eb Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 10 May 2023 23:26:03 +0100 Subject: [PATCH 18/40] popconlaunch: avoid polluting global scope --- apps/popconlaunch/boot.js | 54 +++++++++++++++++++-------------------- apps/popconlaunch/boot.ts | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/apps/popconlaunch/boot.js b/apps/popconlaunch/boot.js index eb3f18e1b..e918fffcf 100644 --- a/apps/popconlaunch/boot.js +++ b/apps/popconlaunch/boot.js @@ -1,29 +1,29 @@ -{ - var oldRead_1 = require("Storage").readJSON; - var monthAgo_1 = Date.now() - 1000 * 86400 * 28; - var cache_1; - var ensureCache_1 = function () { - if (!cache_1) { - cache_1 = oldRead_1("popcon.cache.json", true); - if (!cache_1) - cache_1 = {}; +(function () { + var oldRead = require("Storage").readJSON; + var monthAgo = Date.now() - 1000 * 86400 * 28; + var cache; + var ensureCache = function () { + if (!cache) { + cache = oldRead("popcon.cache.json", true); + if (!cache) + cache = {}; } - return cache_1; + return cache; }; - var saveCache_1 = function (orderChanged) { - require("Storage").writeJSON("popcon.cache.json", cache_1); + var saveCache = function (orderChanged) { + require("Storage").writeJSON("popcon.cache.json", cache); if (orderChanged) { - var info = oldRead_1("popcon.info", true); + var info = oldRead("popcon.info", true); info.cacheBuster = !info.cacheBuster; require("Storage").writeJSON("popcon.info", info); } }; - var sortCache_1 = function () { - var ents = Object.values(cache_1); + var sortCache = function () { + var ents = Object.values(cache); ents.sort(function (a, b) { var n; - var am = (a.last > monthAgo_1); - var bm = (b.last > monthAgo_1); + var am = (a.last > monthAgo); + var bm = (b.last > monthAgo); n = bm - am; if (n) return n; @@ -51,31 +51,31 @@ }; require("Storage").readJSON = (function (fname, skipExceptions) { var _a; - var j = oldRead_1(fname, skipExceptions); + var j = oldRead(fname, skipExceptions); if (/\.info$/.test(fname)) { - var cache_2 = ensureCache_1(); + var cache_1 = ensureCache(); 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; else j.sortorder = 99; } return j; }); - var oldLoad_1 = load; + var oldLoad = load; global.load = function (src) { if (src) { - var cache_3 = ensureCache_1(); - var ent = cache_3[src] || (cache_3[src] = { + var cache_2 = ensureCache(); + var ent = cache_2[src] || (cache_2[src] = { pop: 0, last: 0, sortorder: -10, }); ent.pop++; ent.last = Date.now(); - var orderChanged = sortCache_1(); - saveCache_1(orderChanged); + var orderChanged = sortCache(); + saveCache(orderChanged); } - return oldLoad_1(src); + return oldLoad(src); }; -} +})(); diff --git a/apps/popconlaunch/boot.ts b/apps/popconlaunch/boot.ts index a7ac73518..2fa101927 100644 --- a/apps/popconlaunch/boot.ts +++ b/apps/popconlaunch/boot.ts @@ -1,4 +1,4 @@ -{ +(() => { type Timestamp = number; const oldRead = require("Storage").readJSON; @@ -99,4 +99,4 @@ global.load = (src: string) => { return oldLoad(src); }; -} +})() From 2d3f4375edf7f0f93799b1cfa6b3e817851ce68b Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 10 May 2023 23:37:08 +0100 Subject: [PATCH 19/40] version bumps --- apps/drained/ChangeLog | 2 ++ apps/drained/metadata.json | 2 +- apps/popconlaunch/ChangeLog | 1 + apps/popconlaunch/metadata.json | 2 +- 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/drained/ChangeLog b/apps/drained/ChangeLog index ec09a29bd..c7fd27981 100644 --- a/apps/drained/ChangeLog +++ b/apps/drained/ChangeLog @@ -1,2 +1,4 @@ 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. diff --git a/apps/drained/metadata.json b/apps/drained/metadata.json index ef7bbeb23..6dfdac78d 100644 --- a/apps/drained/metadata.json +++ b/apps/drained/metadata.json @@ -1,7 +1,7 @@ { "id": "drained", "name": "Drained", - "version": "0.02", + "version": "0.03", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "readme": "README.md", "icon": "icon.png", diff --git a/apps/popconlaunch/ChangeLog b/apps/popconlaunch/ChangeLog index 8a2124e33..c430b4412 100644 --- a/apps/popconlaunch/ChangeLog +++ b/apps/popconlaunch/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Trim old entries from the popcon app cache +0.03: Avoid polluting global scope diff --git a/apps/popconlaunch/metadata.json b/apps/popconlaunch/metadata.json index 1acab2b6c..be3bc6a92 100644 --- a/apps/popconlaunch/metadata.json +++ b/apps/popconlaunch/metadata.json @@ -2,7 +2,7 @@ "id": "popconlaunch", "name": "Popcon Launcher", "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", "readme": "README.md", "icon": "app.png", From fb3e036ebde09b5790c097091c74b77506c41337 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Wed, 10 May 2023 20:15:04 -0500 Subject: [PATCH 20/40] Delete icon.png --- apps/shadowclk/icon.png | Bin 446 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/shadowclk/icon.png diff --git a/apps/shadowclk/icon.png b/apps/shadowclk/icon.png deleted file mode 100644 index 447dffb511a6bb298302bfc47555d32ccbb63134..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 446 zcmeAS@N?(olHy`uVBq!ia0vp^^*~(B!3HE_b>dlp6icy_X9x!n)NrJ9FfcHddb&7< zRLpsM_af&Z2N4EGQR@xt+Cdv#0<|}>XLraxdA;z&Igt+>I_2_;({JmY-jw5U>+dhd zAF>}0AK@3a_xWQ$EaSF6Z;KdPzR`SQvI{&AuJ-+=7-H;6%r`t@{m;ceX_Wq`l zn;6n~EZeYgefj$7*RN=V-FbI>V`Ny}j30@Q+B@adkQmCh60wS7s)UF<6MJj_nCq)S v_zGhuG>;ayR?YbQGjZErJWj$X^@cebP0l+XkKo@vS% From f7c5051bfa494fea59c125abcc42f5b963b6efe3 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Wed, 10 May 2023 20:15:39 -0500 Subject: [PATCH 21/40] v0.03 update - new settings --- apps/shadowclk/ChangeLog | 1 + apps/shadowclk/README.md | 15 ++++++++--- apps/shadowclk/app.js | 52 +++++++++++++++++++++--------------- apps/shadowclk/metadata.json | 2 +- apps/shadowclk/settings.js | 27 ++++++++++++++++--- 5 files changed, 66 insertions(+), 31 deletions(-) diff --git a/apps/shadowclk/ChangeLog b/apps/shadowclk/ChangeLog index 5a654d5a1..7ba343b2f 100644 --- a/apps/shadowclk/ChangeLog +++ b/apps/shadowclk/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: New 'Settings Menu' to choose your favorite color and switch between light or dark themes +0.03: New 'Leading Zero' and 'Date Suffix' options in 'Settings Menu' diff --git a/apps/shadowclk/README.md b/apps/shadowclk/README.md index 8b8dd2302..9e78d8e03 100644 --- a/apps/shadowclk/README.md +++ b/apps/shadowclk/README.md @@ -12,14 +12,21 @@ Shadow Clock uses the "Londrina" font in a user selectable color and surrounds i ## Configuration -Anton Clock is configured by the standard settings mechanism of Bangle.js's operating system: +Shadow Clock is configured by the standard settings mechanism of Bangle.js's operating system: Open the `Settings` app, then the `Apps` submenu and below it the `Shadow Clock` menu. -You configure Shadow Clock by selecting a `Light` or `Dark` system wide theme and then selecting the `Color` of the clock numbers. +You can configure Shadow Clock by selecting a `Light` or `Dark` system wide theme, selecting the `Color` of the clock numbers, enabling or disabling the suffix, and enabling or disabling the leading zero. + +### Configuration Options + +* Theme: Choose between `Light` and `Dark` themes. +* Color: Choose the color of the clock numbers from the available options. +* Date Suffix: `Yes` will show "10th" and `No` will show "10". +* Lead Zero: `Yes` to show the leading zero in 24hr mode, `No` to hide. ## Compatibility -Shadow Clock should be fully compatible with with Bangle.js 1 and Bangle.js 2. However, it was built and tested with Bangle.js 2 +Shadow Clock should be fully compatible with with Bangle.js 1 and Bangle.js 2. However, it was built and tested with Bangle.js 2. ## Creator -[stweedo](https://github.com/stweedo) +[stweedo](https://github.com/stweedo) \ No newline at end of file diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index 20c2fe7d1..2678f555a 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -1,6 +1,6 @@ // Clock with large colored digits using the "Londrina" font and a slightly larger "Londrina Shadow" font on top -Graphics.prototype.setFontLondrinaSolid = function() { +Graphics.prototype.setFontLondrinaSolid = function () { // Actual height 59 (64 - 6) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('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'))), @@ -10,7 +10,7 @@ Graphics.prototype.setFontLondrinaSolid = function() { ); }; -Graphics.prototype.setFontLondrinaShadow = function() { +Graphics.prototype.setFontLondrinaShadow = function () { // Actual height 63 (67 - 5) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('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'))), @@ -20,7 +20,7 @@ Graphics.prototype.setFontLondrinaShadow = function() { ); }; -Graphics.prototype.setFontRighteous = function() { +Graphics.prototype.setFontRighteous = function () { // Actual height 16 (15 - 0) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('ABN//ABBv0QA4N4AIVwAogACoEC+EH+EP4EOAovACIcPsEfsF7vABBjfghPAjEAv0As0Yv14n/gg+Aj34vP4sPYgH4gFgEgMP8Ef+F7nABBjcwjEwIwZNFEYM//H//3wn3AgwLBwEC8EO/3+v/8E4IfDmMAn+A/8A/0AAYIHBncAGQMDAIUHgEf4ABBBIYAEjwBChgGBB4YBJAAU4AIS1BhAFBgP4h/wHoKPBXYIlDj/gn/wuF4uE4sEYAYLXBBYK9BSwLhDAIKODuP4uYBB3ABDv84n84jgSCEoNzAIIRFFoUc8DFBv/gAIN+A4IBCWoIBBj7XEFoIBDu4BCH4XwsPggPAdIItBf4N+nFOnEOnB/Bg4tBwAmBQINwOoP4u5rB4CNEsEdS4ILBLIMYAIIFBBIINBgFAhznCn/AuPIuHYRIN7N4TnBZQcHnABBgTLBXoOeAIMBdYUHgEPwAZBnvgnHgiFAD4cNwABLCIcwsAbBdILbBg+AeIJoCPIfYTIR7BgABBv8AnwTCgIZB8EHuEP7ABE4EOoEH4CzBCoLNBQ4N48FwAIjvCboYACBIIBDuapBAIQJDnypBQYKBBcIU4vFwnABHmEwFI4PFXoSBCHpoVBsEYCJGAAISZDJY14JZD7BmJhCE48DVIIBEBYYVJgE4AIYJC+F/MYQVHJIXAJISBCoEIFJoBEgDRBToRxCU4wJECYI/Jn8AWIMD8EBG4rjQUILTNuHgAId/EYPAj+AFZ0+vF+n/2FaBhD7ArBjiHBXIM4ue4AI34uLtBoCLDS5YBBHIRbBDIN4dJXgCYNggF+C4JvB/CjBgZLBCIOADwNAFIYJBc4jxJF4YXBoEIRYN8E4SHBToa/BBoIRBvgtBAIOAgfAIIJDCwAJBBoIRBsAnCToKJBGoW4vzEBnFgIIMA//+AIfgh3AgxhBRoJ1BcoMH+AxBLYUACIIVBAIIdDBYMYCAQdBAYMQQoUAgYBMAAUwDY0BHYUP/EOnEOjADBA4ILDWYR5BWoPwCYQBECYMDboQnIAIUPnEGmA3NcogjH/ADBh+4EYcMTIK3C//49kA5gbHnYBCn8P/8H/0P/iFDaoQTBgABDPYRBB/EgCIgFBkEPv/+v/8A4IhFgPggY9Ch14hiwBhARFHYZlCHYgHFNYJBDgYZCB45THXJjhCZoaBC/7fHCYYjBEp3/EIJjLJoIBBgcYh/YAIMMAIf4AIVwCIN/8D3DSoMMjABBh+Ah4/CgChBAIQ1DHYKRCCYUBQISFBh/Ah66CAoQjGEIgHFCIPAhEIOYV4TIaBDJZE7gE/AIMP/0P/hLChBlCGYQBCNYUAjEDRoOAv/8//+/n+8EOAIIfBBIIBBv/+4EGBoYJC/kHwAfBCoMHAIgrBAYMGgA='))), @@ -30,15 +30,16 @@ Graphics.prototype.setFontRighteous = function() { ); }; -let storage = require('Storage'); +// Load and set default settings +let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; +let settings = Object.assign({ + color: teletextColors[6], + theme: 'light', + enableSuffix: true, + enableLeadingZero: false, +}, require('Storage').readJSON("shadowclk.json", true) || {}); -var settings = Object.assign({ - // default values - color: "#0ff", - theme: "light", -}, storage.readJSON("shadowclk.json", true) || {}); - -(function() { +(function () { let drawTimeout; function draw() { @@ -46,8 +47,13 @@ var settings = Object.assign({ var y = g.getHeight() / 2; g.reset().clearRect(Bangle.appRect); var date = new Date(); - var hour = String(date.getHours()).padStart(2, '0'); - if (hour[0] === '0') hour = hour[1]; + var hour = date.getHours(); + hour = String(hour); + if (settings.enableLeadingZero) { + hour = hour.padStart(2, '0'); + } else if (hour[0] === '0') { + hour = hour[1]; + } var minutes = String(date.getMinutes()).padStart(2, '0'); var timeStr = hour + ':' + minutes; var color = settings.color; @@ -59,14 +65,16 @@ var settings = Object.assign({ var month = locale.month(date, 1).slice(0, 1).toUpperCase() + locale.month(date, 1).slice(1).toLowerCase(); var year = date.getFullYear(); var dayOfMonthStr = dayOfMonth.toString(); - if (dayOfMonth === 1 || dayOfMonth === 21 || dayOfMonth === 31) { - dayOfMonthStr += "st"; - } else if (dayOfMonth === 2 || dayOfMonth === 22) { - dayOfMonthStr += "nd"; - } else if (dayOfMonth === 3 || dayOfMonth === 23) { - dayOfMonthStr += "rd"; - } else { - dayOfMonthStr += "th"; + if (settings.enableSuffix) { + if (dayOfMonth === 1 || dayOfMonth === 21 || dayOfMonth === 31) { + dayOfMonthStr += "st"; + } else if (dayOfMonth === 2 || dayOfMonth === 22) { + dayOfMonthStr += "nd"; + } else if (dayOfMonth === 3 || dayOfMonth === 23) { + dayOfMonthStr += "rd"; + } else { + dayOfMonthStr += "th"; + } } var dayOfWeek = locale.dow(date, 0).slice(0, 1).toUpperCase() + locale.dow(date, 0).slice(1).toLowerCase(); var dateStr = month + " " + dayOfMonthStr + ", " + year + "\n" + dayOfWeek; @@ -81,7 +89,7 @@ var settings = Object.assign({ Bangle.setUI({ mode: "clock", - remove: function() { + remove: function () { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; delete Graphics.prototype.setFontLondrinaSolid; diff --git a/apps/shadowclk/metadata.json b/apps/shadowclk/metadata.json index e1debfb6d..4e47b9845 100644 --- a/apps/shadowclk/metadata.json +++ b/apps/shadowclk/metadata.json @@ -1,7 +1,7 @@ { "id": "shadowclk", "name": "Shadow Clock", - "version": "0.02", + "version": "0.03", "description": "A simple clock using the Londrina font in color with a shadowed outline. Based on the Anton Clock.", "icon": "app.png", "screenshots": [{ diff --git a/apps/shadowclk/settings.js b/apps/shadowclk/settings.js index fd16d92e2..93408657c 100644 --- a/apps/shadowclk/settings.js +++ b/apps/shadowclk/settings.js @@ -1,4 +1,4 @@ -(function(back) { +(function (back) { let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; let teletextColorNames = ["Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"]; @@ -6,8 +6,11 @@ let appSettings = Object.assign({ color: teletextColors[6], theme: 'light', + enableSuffix: true, + enableLeadingZero: false, }, require('Storage').readJSON("shadowclk.json", true) || {}); + // Save settings to storage function writeSettings() { require('Storage').writeJSON("shadowclk.json", appSettings); @@ -52,10 +55,10 @@ writeSettings(); delete g.reset; g._reset = g.reset; - g.reset = function(n) { + g.reset = function (n) { return g._reset().setColor(newTheme.fg).setBgColor(newTheme.bg); }; - g.clear = function(n) { + g.clear = function (n) { if (n) g.reset(); return g.clearRect(0, 0, g.getWidth(), g.getHeight()); }; @@ -96,9 +99,25 @@ writeSettings(); }, format: v => teletextColorNames[v] + }, + 'Date Suffix:': { + value: appSettings.enableSuffix, + format: v => v ? 'Yes' : 'No', + onchange: v => { + appSettings.enableSuffix = v; + writeSettings(); + } + }, + 'Lead Zero:': { + value: appSettings.enableLeadingZero, + format: v => v ? 'Yes' : 'No', + onchange: v => { + appSettings.enableLeadingZero = v; + writeSettings(); + } } }); } // Initially show the menu showMenu(); -}); +}); \ No newline at end of file From 1f35b08ee0f0c4f4b620a47b69cb7cd61eb14c48 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Thu, 11 May 2023 00:42:32 -0500 Subject: [PATCH 22/40] Update app.js Fixed bug in leading zero logic --- apps/shadowclk/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index 2678f555a..13c094202 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -51,8 +51,8 @@ let settings = Object.assign({ hour = String(hour); if (settings.enableLeadingZero) { hour = hour.padStart(2, '0'); - } else if (hour[0] === '0') { - hour = hour[1]; + } else if (hour === '00') { + hour = '0'; } var minutes = String(date.getMinutes()).padStart(2, '0'); var timeStr = hour + ':' + minutes; @@ -100,4 +100,4 @@ let settings = Object.assign({ Bangle.loadWidgets(); draw(); setTimeout(Bangle.drawWidgets, 0); -})(); \ No newline at end of file +})(); From c971a7cd0e4e613220bd6ab53af10eb7c8b92d3a Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Thu, 11 May 2023 02:32:27 -0500 Subject: [PATCH 23/40] fixes broken 12hr format --- apps/shadowclk/app.js | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index 13c094202..eea083dd8 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -47,16 +47,30 @@ let settings = Object.assign({ var y = g.getHeight() / 2; g.reset().clearRect(Bangle.appRect); var date = new Date(); + var appSettings = require("Storage").readJSON("shadowclk.json", 1) || {}; + var settings = require("Storage").readJSON("setting.json", 1) || {}; + var is12HourFormat = settings["12hour"]; var hour = date.getHours(); - hour = String(hour); - if (settings.enableLeadingZero) { - hour = hour.padStart(2, '0'); - } else if (hour === '00') { - hour = '0'; - } var minutes = String(date.getMinutes()).padStart(2, '0'); + + // Handle 12-hour format + if (is12HourFormat) { + hour = hour % 12 || 12; // Convert 0 to 12 for 12-hour format + } else { + // If the leading zero option is enabled and hour is less than 10, add leading zero + if (appSettings.enableLeadingZero && hour < 10) { + hour = '0' + hour; + } + } + var timeStr = hour + ':' + minutes; - var color = settings.color; + + // Handle midnight in 12-hour format specifically + if (is12HourFormat && hour === 0) { + timeStr = '12' + timeStr.substring(2); + } + + var color = appSettings.color; g.setFontAlign(0, 0).setFont("LondrinaSolid").setColor(color).drawString(timeStr, x - 1, y); g.reset().setFontAlign(0, 0).setFont("LondrinaShadow").drawString(timeStr, x - 1, y); @@ -100,4 +114,4 @@ let settings = Object.assign({ Bangle.loadWidgets(); draw(); setTimeout(Bangle.drawWidgets, 0); -})(); +})(); \ No newline at end of file From 123cd79a5da91f748596e75213a15f590af72a40 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Thu, 11 May 2023 03:36:06 -0500 Subject: [PATCH 24/40] Fixes broken suffix --- apps/shadowclk/app.js | 51 +++++++++++++++++++------------------------ 1 file changed, 22 insertions(+), 29 deletions(-) diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index eea083dd8..9ad50d877 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -1,6 +1,6 @@ // Clock with large colored digits using the "Londrina" font and a slightly larger "Londrina Shadow" font on top -Graphics.prototype.setFontLondrinaSolid = function () { +Graphics.prototype.setFontLondrinaSolid = function() { // Actual height 59 (64 - 6) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('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'))), @@ -10,7 +10,7 @@ Graphics.prototype.setFontLondrinaSolid = function () { ); }; -Graphics.prototype.setFontLondrinaShadow = function () { +Graphics.prototype.setFontLondrinaShadow = function() { // Actual height 63 (67 - 5) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('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'))), @@ -20,7 +20,7 @@ Graphics.prototype.setFontLondrinaShadow = function () { ); }; -Graphics.prototype.setFontRighteous = function () { +Graphics.prototype.setFontRighteous = function() { // Actual height 16 (15 - 0) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('ABN//ABBv0QA4N4AIVwAogACoEC+EH+EP4EOAovACIcPsEfsF7vABBjfghPAjEAv0As0Yv14n/gg+Aj34vP4sPYgH4gFgEgMP8Ef+F7nABBjcwjEwIwZNFEYM//H//3wn3AgwLBwEC8EO/3+v/8E4IfDmMAn+A/8A/0AAYIHBncAGQMDAIUHgEf4ABBBIYAEjwBChgGBB4YBJAAU4AIS1BhAFBgP4h/wHoKPBXYIlDj/gn/wuF4uE4sEYAYLXBBYK9BSwLhDAIKODuP4uYBB3ABDv84n84jgSCEoNzAIIRFFoUc8DFBv/gAIN+A4IBCWoIBBj7XEFoIBDu4BCH4XwsPggPAdIItBf4N+nFOnEOnB/Bg4tBwAmBQINwOoP4u5rB4CNEsEdS4ILBLIMYAIIFBBIINBgFAhznCn/AuPIuHYRIN7N4TnBZQcHnABBgTLBXoOeAIMBdYUHgEPwAZBnvgnHgiFAD4cNwABLCIcwsAbBdILbBg+AeIJoCPIfYTIR7BgABBv8AnwTCgIZB8EHuEP7ABE4EOoEH4CzBCoLNBQ4N48FwAIjvCboYACBIIBDuapBAIQJDnypBQYKBBcIU4vFwnABHmEwFI4PFXoSBCHpoVBsEYCJGAAISZDJY14JZD7BmJhCE48DVIIBEBYYVJgE4AIYJC+F/MYQVHJIXAJISBCoEIFJoBEgDRBToRxCU4wJECYI/Jn8AWIMD8EBG4rjQUILTNuHgAId/EYPAj+AFZ0+vF+n/2FaBhD7ArBjiHBXIM4ue4AI34uLtBoCLDS5YBBHIRbBDIN4dJXgCYNggF+C4JvB/CjBgZLBCIOADwNAFIYJBc4jxJF4YXBoEIRYN8E4SHBToa/BBoIRBvgtBAIOAgfAIIJDCwAJBBoIRBsAnCToKJBGoW4vzEBnFgIIMA//+AIfgh3AgxhBRoJ1BcoMH+AxBLYUACIIVBAIIdDBYMYCAQdBAYMQQoUAgYBMAAUwDY0BHYUP/EOnEOjADBA4ILDWYR5BWoPwCYQBECYMDboQnIAIUPnEGmA3NcogjH/ADBh+4EYcMTIK3C//49kA5gbHnYBCn8P/8H/0P/iFDaoQTBgABDPYRBB/EgCIgFBkEPv/+v/8A4IhFgPggY9Ch14hiwBhARFHYZlCHYgHFNYJBDgYZCB45THXJjhCZoaBC/7fHCYYjBEp3/EIJjLJoIBBgcYh/YAIMMAIf4AIVwCIN/8D3DSoMMjABBh+Ah4/CgChBAIQ1DHYKRCCYUBQISFBh/Ah66CAoQjGEIgHFCIPAhEIOYV4TIaBDJZE7gE/AIMP/0P/hLChBlCGYQBCNYUAjEDRoOAv/8//+/n+8EOAIIfBBIIBBv/+4EGBoYJC/kHwAfBCoMHAIgrBAYMGgA='))), @@ -30,16 +30,17 @@ Graphics.prototype.setFontRighteous = function () { ); }; -// Load and set default settings +// Load and set default appSettings let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; -let settings = Object.assign({ +let appSettings = Object.assign({ color: teletextColors[6], theme: 'light', enableSuffix: true, enableLeadingZero: false, }, require('Storage').readJSON("shadowclk.json", true) || {}); -(function () { +// Draw the time and date +(function() { let drawTimeout; function draw() { @@ -52,58 +53,50 @@ let settings = Object.assign({ var is12HourFormat = settings["12hour"]; var hour = date.getHours(); var minutes = String(date.getMinutes()).padStart(2, '0'); - // Handle 12-hour format if (is12HourFormat) { hour = hour % 12 || 12; // Convert 0 to 12 for 12-hour format - } else { - // If the leading zero option is enabled and hour is less than 10, add leading zero - if (appSettings.enableLeadingZero && hour < 10) { - hour = '0' + hour; - } + } else if (appSettings.enableLeadingZero) { + hour = hour.toString().padStart(2, '0'); } - var timeStr = hour + ':' + minutes; - // Handle midnight in 12-hour format specifically if (is12HourFormat && hour === 0) { timeStr = '12' + timeStr.substring(2); } - + // Print time in selected color and then the outline var color = appSettings.color; g.setFontAlign(0, 0).setFont("LondrinaSolid").setColor(color).drawString(timeStr, x - 1, y); g.reset().setFontAlign(0, 0).setFont("LondrinaShadow").drawString(timeStr, x - 1, y); - + // Get full date and handle formatting var locale = require("locale"); var dayOfMonth = date.getDate(); var month = locale.month(date, 1).slice(0, 1).toUpperCase() + locale.month(date, 1).slice(1).toLowerCase(); var year = date.getFullYear(); var dayOfMonthStr = dayOfMonth.toString(); - if (settings.enableSuffix) { + if (appSettings.enableSuffix) { + var suffix = ""; if (dayOfMonth === 1 || dayOfMonth === 21 || dayOfMonth === 31) { - dayOfMonthStr += "st"; + suffix = "st"; } else if (dayOfMonth === 2 || dayOfMonth === 22) { - dayOfMonthStr += "nd"; + suffix = "nd"; } else if (dayOfMonth === 3 || dayOfMonth === 23) { - dayOfMonthStr += "rd"; + suffix = "rd"; } else { - dayOfMonthStr += "th"; + suffix = "th"; } + dayOfMonthStr += suffix; } var dayOfWeek = locale.dow(date, 0).slice(0, 1).toUpperCase() + locale.dow(date, 0).slice(1).toLowerCase(); var dateStr = month + " " + dayOfMonthStr + ", " + year + "\n" + dayOfWeek; g.setFontAlign(0, 0).setFont("Righteous").drawString(dateStr, x, y + 56); - + // Time interval set to redraw every 60 seconds if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(() => { - drawTimeout = undefined; - draw(); - }, 60000 - (Date.now() % 60000)); + drawTimeout = setTimeout(draw, 60000 - (Date.now() % 60000)); } - Bangle.setUI({ mode: "clock", - remove: function () { + remove: function() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; delete Graphics.prototype.setFontLondrinaSolid; @@ -114,4 +107,4 @@ let settings = Object.assign({ Bangle.loadWidgets(); draw(); setTimeout(Bangle.drawWidgets, 0); -})(); \ No newline at end of file +})(); From 482af03edfc0ba964da064c566304dcd704df1c5 Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Thu, 11 May 2023 04:03:49 -0500 Subject: [PATCH 25/40] Fixes default settings not being used --- apps/shadowclk/app.js | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index 9ad50d877..31d62a87d 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -32,7 +32,7 @@ Graphics.prototype.setFontRighteous = function() { // Load and set default appSettings let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; -let appSettings = Object.assign({ +let defaultAppSettings = Object.assign({ color: teletextColors[6], theme: 'light', enableSuffix: true, @@ -48,7 +48,7 @@ let appSettings = Object.assign({ var y = g.getHeight() / 2; g.reset().clearRect(Bangle.appRect); var date = new Date(); - var appSettings = require("Storage").readJSON("shadowclk.json", 1) || {}; + var appSettings = require("Storage").readJSON("shadowclk.json", 1) || defaultAppSettings; var settings = require("Storage").readJSON("setting.json", 1) || {}; var is12HourFormat = settings["12hour"]; var hour = date.getHours(); @@ -56,8 +56,11 @@ let appSettings = Object.assign({ // Handle 12-hour format if (is12HourFormat) { hour = hour % 12 || 12; // Convert 0 to 12 for 12-hour format - } else if (appSettings.enableLeadingZero) { - hour = hour.toString().padStart(2, '0'); + } else { + // If the leading zero option is enabled and hour is less than 10, add leading zero + if (appSettings.enableLeadingZero && hour < 10) { + hour = '0' + hour; + } } var timeStr = hour + ':' + minutes; // Handle midnight in 12-hour format specifically @@ -68,7 +71,7 @@ let appSettings = Object.assign({ var color = appSettings.color; g.setFontAlign(0, 0).setFont("LondrinaSolid").setColor(color).drawString(timeStr, x - 1, y); g.reset().setFontAlign(0, 0).setFont("LondrinaShadow").drawString(timeStr, x - 1, y); - // Get full date and handle formatting + // Get full date and format it var locale = require("locale"); var dayOfMonth = date.getDate(); var month = locale.month(date, 1).slice(0, 1).toUpperCase() + locale.month(date, 1).slice(1).toLowerCase(); @@ -87,12 +90,16 @@ let appSettings = Object.assign({ } dayOfMonthStr += suffix; } + // Combine and print date string var dayOfWeek = locale.dow(date, 0).slice(0, 1).toUpperCase() + locale.dow(date, 0).slice(1).toLowerCase(); var dateStr = month + " " + dayOfMonthStr + ", " + year + "\n" + dayOfWeek; g.setFontAlign(0, 0).setFont("Righteous").drawString(dateStr, x, y + 56); // Time interval set to redraw every 60 seconds if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(draw, 60000 - (Date.now() % 60000)); + drawTimeout = setTimeout(() => { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); } Bangle.setUI({ mode: "clock", From 0e05d97056da8e77cfa45c1aa4541cd6929f08dd Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 May 2023 10:27:27 +0100 Subject: [PATCH 26/40] example update --- apps/_example_app/README.md | 5 ++++ apps/_example_clkinfo/ChangeLog | 1 + apps/_example_clkinfo/README.md | 27 ++++++++++++++++++ apps/_example_clkinfo/clkinfo.js | 16 +++++++++++ .../widget.png => _example_clkinfo/icon.png} | Bin apps/_example_clkinfo/metadata.json | 14 +++++++++ apps/_example_widget/README.md | 2 ++ apps/_example_widget/icon.png | Bin 0 -> 1620 bytes apps/_example_widget/metadata.json | 2 +- apps/_example_widget/widget.js | 16 +++++------ 10 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 apps/_example_clkinfo/ChangeLog create mode 100644 apps/_example_clkinfo/README.md create mode 100644 apps/_example_clkinfo/clkinfo.js rename apps/{_example_widget/widget.png => _example_clkinfo/icon.png} (100%) create mode 100644 apps/_example_clkinfo/metadata.json create mode 100644 apps/_example_widget/icon.png diff --git a/apps/_example_app/README.md b/apps/_example_app/README.md index dc139bc9a..eff3919c6 100644 --- a/apps/_example_app/README.md +++ b/apps/_example_app/README.md @@ -1,5 +1,10 @@ # App Name +More information on making apps: + +* http://www.espruino.com/Bangle.js+First+App +* http://www.espruino.com/Bangle.js+App+Loader + Describe the app... Add screen shots (if possible) to the app folder and link then into this file with ![](.png) diff --git a/apps/_example_clkinfo/ChangeLog b/apps/_example_clkinfo/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/_example_clkinfo/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/_example_clkinfo/README.md b/apps/_example_clkinfo/README.md new file mode 100644 index 000000000..3d5970e39 --- /dev/null +++ b/apps/_example_clkinfo/README.md @@ -0,0 +1,27 @@ +# Clock Info Name + +More info on making Clock Infos and what they are: http://www.espruino.com/Bangle.js+Clock+Info + +Describe the clock info... + +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Usage + +Describe how to use it + +## Features + +Name the function + +## Controls + +Name the buttons and what they are used for + +## Requests + +Name who should be contacted for support/update requests + +## Creator + +Your name diff --git a/apps/_example_clkinfo/clkinfo.js b/apps/_example_clkinfo/clkinfo.js new file mode 100644 index 000000000..b653709ce --- /dev/null +++ b/apps/_example_clkinfo/clkinfo.js @@ -0,0 +1,16 @@ +(function() { + return { + name: "Bangle", + // img: 24x24px image for this list of items. The default "Bangle" list has its own image so this is not needed + items: [ + { name : "Item1", + get : function() { return { text : "TextOfItem1", + // v : 10, min : 0, max : 100, - optional + img : atob("GBiBAAAAAAAAAAAYAAD/AAOBwAYAYAwAMAgAEBgAGBAACBCBCDHDjDCBDBAACBAACBhCGAh+EAwYMAYAYAOBwAD/AAAYAAAAAAAAAA==") }}, + show : function() {}, + hide : function() {}, + // run : function() {} optional (called when tapped) + } + ] + }; +}) // must not have a semi-colon! \ No newline at end of file diff --git a/apps/_example_widget/widget.png b/apps/_example_clkinfo/icon.png similarity index 100% rename from apps/_example_widget/widget.png rename to apps/_example_clkinfo/icon.png diff --git a/apps/_example_clkinfo/metadata.json b/apps/_example_clkinfo/metadata.json new file mode 100644 index 000000000..83b8184d8 --- /dev/null +++ b/apps/_example_clkinfo/metadata.json @@ -0,0 +1,14 @@ +{ "id": "7chname", + "name": "My clock info's human readable name", + "shortName":"Short Name", + "version":"0.01", + "description": "A detailed description of my clock info", + "icon": "icon.png", + "type": "clkinfo", + "tags": "clkinfo", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"7chname.clkinfo.js","url":"clkinfo.js"} + ] +} diff --git a/apps/_example_widget/README.md b/apps/_example_widget/README.md index a909e9e7e..c786d3be8 100644 --- a/apps/_example_widget/README.md +++ b/apps/_example_widget/README.md @@ -1,5 +1,7 @@ # Widget Name +More info on making Widgets and what they are: http://www.espruino.com/Bangle.js+Widgets + Describe the app... Add screen shots (if possible) to the app folder and link then into this file with ![](.png) diff --git a/apps/_example_widget/icon.png b/apps/_example_widget/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 { - function draw() { - g.reset(); // reset the graphics context to defaults (color/font/etc) - // add your code - g.drawString("X", this.x, this.y); - } - // add your widget WIDGETS["mywidget"]={ area:"tl", // tl (top left), tr (top right), bl (bottom left), br (bottom right), be aware that not all apps support widgets at the bottom of the screen width: 28, // how wide is the widget? You can change this and call Bangle.drawWidgets() to re-layout - draw:draw // called to draw the widget + draw:function() { + g.reset(); // reset the graphics context to defaults (color/font/etc) + // add your code + g.drawString("X", this.x, this.y); + } // called to draw the widget }; })() From ef1f4e406465c127910d18037152aad5dcab102b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 May 2023 10:28:33 +0100 Subject: [PATCH 27/40] add magnetometer clock info --- apps/clkinfomag/ChangeLog | 1 + apps/clkinfomag/clkinfo.js | 48 ++++++++++++++++++++++++++++++++++ apps/clkinfomag/icon.png | Bin 0 -> 1769 bytes apps/clkinfomag/metadata.json | 12 +++++++++ 4 files changed, 61 insertions(+) create mode 100644 apps/clkinfomag/ChangeLog create mode 100644 apps/clkinfomag/clkinfo.js create mode 100644 apps/clkinfomag/icon.png create mode 100644 apps/clkinfomag/metadata.json diff --git a/apps/clkinfomag/ChangeLog b/apps/clkinfomag/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/clkinfomag/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/clkinfomag/clkinfo.js b/apps/clkinfomag/clkinfo.js new file mode 100644 index 000000000..7a6062a2f --- /dev/null +++ b/apps/clkinfomag/clkinfo.js @@ -0,0 +1,48 @@ +(function() { + var heading, cnt; + function magHandler(m) { + var h = m.heading; + if (isNaN(heading) || isNaN(h)) + heading = h; + else { + // Average + if (Math.abs(heading-h)>180) { + if (h<180 && heading>180) h+=360; + if (h>180 && heading<180) h-=360; + } + heading = heading*0.8 + h*0.2; + if (heading<0) heading+=360; + if (heading>=360) heading-=360; + } + // only draw 1 in 2 to try and save some power! + if (!(1&cnt++)) ci.items[0].emit('redraw'); + } + var ci = { + name: "Bangle", + items: [ + { name : "Compass", + get : function() { + var g = Graphics.createArrayBuffer(24,24,1,{msb:true}); + if (isNaN(heading)) + g.drawLine(8,12,16,12); + else + g.fillPoly(g.transformVertices([0,-10,4,10,-4,10],{x:12,y:12,rotate:-heading/57})); + return { text : isNaN(heading)?"--":Math.round(heading), + v : 0|heading, min : 0, max : 360, + img : g.asImage("string") }}, + show : function() { + Bangle.setCompassPower(1,"clkinfomag"); + Bangle.on('mag',magHandler); + cnt=0; + heading = undefined; + }, + hide : function() { + Bangle.removeListener('mag', magHandler); + Bangle.setCompassPower(0,"clkinfomag"); + }, + run : function() { Bangle.resetCompass(); } + } + ] + }; + return ci; +}) // must not have a semi-colon! \ No newline at end of file diff --git a/apps/clkinfomag/icon.png b/apps/clkinfomag/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..aaa9c7027e0659ae8af3b962840dfe4b9893bec6 GIT binary patch literal 1769 zcmV4FBKm#SdD;zL=7k^ zAPF(ymH3Dx$iu`c5F`dmdCZh;flAu|EzrmAmIAGo*0wxaC`ijfw`{xZF0|e0?Ce}h z5VXgfyWM5y&hF0a1JtB9ImztIoqNA?=bZ06)?gSO!((_PKZ;=FnC<@8OuW3>$diL6 zj=7;C9V<^Ir?YLJ;!9Q+> zQ6^446lue>d>MW@Ex{G94@6PaB{(;?NrJTesAg4;d!__Do<=0_&zfb}a@-GIAv(~j zy}eYTJ?|4l$ZU{c!ge{5lUGhGg8P$JAd=bO$u)LppLmsDwI&X)j7Q3#w7u`OXwkN`u;K;`bfq!DF{}CfcyzI&A1&>mF z@(dNd^Dnx6@DlqaIMSaG#Ujs#FNAh_!gPx=g)=_q!dRcNKc-j^=h;pR8*0!%i*wXz+m=bk=M zWlETK=tG|lBQQ@1e;Ii`+9@`-UV_YmVz5*w)GK1zs6`}^VA0UictJVe3Y z{CZl{b+bQQIkRn#ot@<_Cwd!RWLYZ zR0urEz}^habr;+G3I)dU@=9$5I8q$`66Q8~C=mUD+gBDk_1$Ghp0=sV_f(ztcvlzz@Ft07xy3y4I_4 z_}KK~4?SN%kt#c{YH!rj+ehO<^My;4HW#k4K=J$q0Bb)D$Q$>B6zJNx3|bwR!R7X7 zuG@Y^WSPjT{RJ5Q?-kS_Yn#qe$1SX=rZgHf8gZKTg4;yg92J)@^ErwHeKDaQ*@~`PGMzXE{ofJDeLU z%@&g~p#+_{#qNQrA60}D2nw3hqLpRTvGLTAUiFefO@dCWpiwLXwKnSS7vYO<>r~+1 zTVR9lx0OPHttwg;@(egC`$DKa+FzhaD1z{+{Moi|0(vBl_ zr!@UxCu=^O?9$!M!_<|n#IOKoHz}=Xqu`f)R}XFN0qWC}PNSenWgjSy=nqKUlk?aj zpR6||Q_x`dAbb;7S1-(2`YY@!u_s*6bas1a#m4$WMm_7i@{Q4115X;_8Q2kEOG>1* z;3icyPUv*?CS6i`1p(TeouS{y96p#}R`rRt8sZ(JbEJpaq8_UxyW4liiuy|)AH0&Q z>P!d;_f4@^$t*@&AJ{!ebz8;m_QBK$Z50zwW*d?j*sEk0ePI`Ys*9;>Y#nn%Xr}~B zXPY7EQ3NARJSkxpM?1ytL97^|)mrQoMEJQ*QrY|v>)6uL;og)rcd_9b;q%gy!vZ{( zBCOzCthOdIR2i1ESyR^BRWx}SW?~~Y*07kr)H-}Llf)B7!E3ySiY~JH)e)9gnoY`1 zKGMKmCCg5!5F=0el6Kg*`ldYLFu)`aT)u%kkF;&L+XJH`rX6hVq!V}-rU!9H*gG=P zVFWgvuy2DoI~E>T* Date: Thu, 11 May 2023 12:38:27 +0100 Subject: [PATCH 28/40] clockinfo 0.03: Reported image for battery now reflects charge level --- apps/clock_info/ChangeLog | 1 + apps/clock_info/lib.js | 15 +++++++++++---- apps/clock_info/metadata.json | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/apps/clock_info/ChangeLog b/apps/clock_info/ChangeLog index 7d51e0da5..0081c49d4 100644 --- a/apps/clock_info/ChangeLog +++ b/apps/clock_info/ChangeLog @@ -1,2 +1,3 @@ 0.01: Moved from modules/clock_info.js 0.02: Fix settings page +0.03: Reported image for battery now reflects charge level \ No newline at end of file diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index 7251f1b00..e849be256 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -53,10 +53,17 @@ exports.load = function() { items: [ { name : "Battery", hasRange : true, - get : () => { let v = E.getBattery(); return { - text : v + "%", v : v, min:0, max:100, - img : atob(Bangle.isCharging() ? "GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA==" : "GBiBAAAAAAAAAAAAAAAAAAAAAD//+P///IAAAr//Ar//Ar//A7//A7//A7//A7//Ar//AoAAAv///D//+AAAAAAAAAAAAAAAAAAAAA==") - }}, + get : () => { let v = E.getBattery(); + var img; + if (!Bangle.isCharging()) { + var s=24,g = Graphics.createArrayBuffer(24,24,1,{msb:true}); + g.fillRect(0,6,s-3,18).clearRect(2,8,s-5,16).fillRect(s-2,10,s,15).fillRect(3,9,3+v*(s-9)/100,15); + img = g.asImage("string"); + } else img=atob("GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA=="); + return { + text : v + "%", v : v, min:0, max:100, img : img + } + }, show : function() { this.interval = setInterval(()=>this.emit('redraw'), 60000); Bangle.on("charging", batteryUpdateHandler); batteryUpdateHandler(); }, hide : function() { clearInterval(this.interval); delete this.interval; Bangle.removeListener("charging", batteryUpdateHandler); }, }, diff --git a/apps/clock_info/metadata.json b/apps/clock_info/metadata.json index 6cc3e1233..703cf9909 100644 --- a/apps/clock_info/metadata.json +++ b/apps/clock_info/metadata.json @@ -1,7 +1,7 @@ { "id": "clock_info", "name": "Clock Info Module", "shortName": "Clock Info", - "version":"0.02", + "version":"0.03", "description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)", "icon": "app.png", "type": "module", From 9b84ada7b27ac1411c482b0d25a5720b77b2bc4c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 May 2023 12:38:51 +0100 Subject: [PATCH 29/40] added pebble++ - pebble clock with clockinfo --- apps/pebblepp/ChangeLog | 1 + apps/pebblepp/app.js | 124 +++++++++++++++++++++++++++++++++++ apps/pebblepp/app.png | Bin 0 -> 1610 bytes apps/pebblepp/icon.js | 1 + apps/pebblepp/metadata.json | 18 +++++ apps/pebblepp/screenshot.png | Bin 0 -> 1260 bytes apps/pebblepp/settings.js | 50 ++++++++++++++ 7 files changed, 194 insertions(+) create mode 100644 apps/pebblepp/ChangeLog create mode 100644 apps/pebblepp/app.js create mode 100644 apps/pebblepp/app.png create mode 100644 apps/pebblepp/icon.js create mode 100644 apps/pebblepp/metadata.json create mode 100644 apps/pebblepp/screenshot.png create mode 100644 apps/pebblepp/settings.js diff --git a/apps/pebblepp/ChangeLog b/apps/pebblepp/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/pebblepp/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/pebblepp/app.js b/apps/pebblepp/app.js new file mode 100644 index 000000000..6b165aaf0 --- /dev/null +++ b/apps/pebblepp/app.js @@ -0,0 +1,124 @@ +Graphics.prototype.setFontLECO1976Regular42 = function(scale) { + // Actual height 42 (41 - 0) + return g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAAAAAA/AAAAAAAAH/AAAAAAAA//AAAAAAAP//AAAAAAB///AAAAAAP///AAAAAB////AAAAAf////AAAAD////4AAAAf////AAAAH////4AAAA////+AAAAA////wAAAAA///+AAAAAA///gAAAAAA//8AAAAAAA//gAAAAAAA/4AAAAAAAA/AAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAH/AAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA//h////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////gD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4AAAH/AAA/4B/gH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAA////wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA////x//AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/wB////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/4B////AAA/wB////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA//gAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA/4AAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA////wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA/4B/wH/AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAA///////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAP+AAH/AAAAH+AAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("ERkmHyYmJiYmJCYmEQ=="), 60+(scale<<8)+(1<<16)); +}; + +Graphics.prototype.setFontLECO1976Regular22 = function(scale) { + // Actual height 22 (21 - 0) + return g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/nA/+cD/5wP/nAAAAAAAAPwAA/gAD+AAPwAAAAAD+AAP4AA/gAAAAAAAAAAAAAcOAP//A//8D//wP//AHDgAcOAP//A//8D//wP//AHDgAAAAAAAAH/jgf+OB/44H/jj8OP/w4//Dj/8OPxw/4HD/gcP+Bw/4AAAAAAAP+AA/8AD/wQOHHA4c8D//wP/8A//gAD4AAfAAH/8A//wP//A84cDjhwIP/AA/8AB/wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8ABwAAAAAAAAD8AAP4AA/gAD8AAAAAAAAAAAEAAD+AB//A///v/D//gB/wABwAAAAAADgAA/wAf/4P8///wf/4AP8AAOAAAAAAAAAyAAHcAAPwAD/gAP/AA/8AA/AAH8AAMwAAAAAAAAAAAAADgAAOAAA4AAf8AD/wAP/AA/8AAOAAA4AADgAAAAAAAAAAD8AAfwAB/AAD8AAAAAAAADgAAOAAA4AADgAAOAAA4AADgAAAAAAAAAADgAAOAAA4AADgAAAAAAAAABwAB/AA/8A//gP/gA/wADwAAIAAAAAAD//wP//A//8D//wOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA4AcDgBwOAHA//8D//wP//A//8AABwAAHAAAcAAAAAAAA+f8D5/wPn/A+f8DhxwOHHA4ccDhxwP/HA/8cD/xwP/HAAAAAAAAOAHA4AcDhxwOHHA4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/wAP/AA/8AD/wAAHAAAcAABwAAHAA//8D//wP//A//8AAAAAAAA/98D/3wP/fA/98DhxwOHHA4ccDhxwOH/A4f8Dh/wOH/AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccDh/wOH/A4f8Dh/wAAAAAAAD4AAPgAA+AADgAAOAAA4AADgAAP//A//8D//wP//AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA//8D//wP//A//8AAAAAAAAOA4A4DgDgOAOA4AAAAAAAAOA/A4H8DgfwOA/AAAAAAAAB4AAPwAA/AAD8AAf4ABzgAPPAA8cAHh4AAAAAAAAAAAAHHAAccABxwAHHAAccABxwAHHAAccABxwAHHAAAAAAAAAOHAA4cADzwAPPAAf4AB/gAD8AAPwAAeAAB4AAAAAAAAA+AAD4AAPgAA+ecDh9wOH3A4fcDhwAP/AA/8AD/wAP/AAAAAAAAAP//4///j//+P//44ADjn/OOf845/zjnHOP8c4//zj//OP/84AAAAAAAP//A//8D//wP//A4cADhwAOHAA4cAD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA//8D//wP9/A/j8AAAAAAAA//8D//wP//A//8DgBwOAHA4AcDgBwOAHA4AcDgBwOAHAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA8A8D//wH/+AP/wAf+AAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4ccDhxwOAHA4AcAAAAAAAA//8D//wP//A//8DhwAOHAA4cADhwAOHAA4cADgAAOAAAAAAD//wP//A//8D//wOAHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA//8D//wP//A//8ABwAAHAAAcAABwAP//A//8D//wP//AAAAAAAAP//A//8D//wP//AAAAAAAAOAHA4AcDgBwOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA//8D//wP//A//8AHwAA/AAP8AB/wAPn/A8f8DB/wIH/AAAAAAAAP//A//8D//wP//AAAcAABwAAHAAAcAABwAAHAAAAAAAAP//A//8D//wP//Af8AAP+AAH/AAD8AAHwAD/AB/wAf8AP+AA//8D//wP//AAAAAAAAP//A//8D//wP//AfwAAfwAAfwAAfwAAfwP//A//8D//wAAAAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHAA4cADhwAOHAA/8AD/wAP/AA/8AAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//+P//4///j//+AAA4AADgAAAP//A//8D//wP//A4eADh+AOH8A4f4D/3wP/HA/8MD/wQAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA4AADgAAOAAA//8D//wP//A//8DgAAOAAA4AADgAAAAAA//8D//wP//A//8AABwAAHAAAcAABwP//A//8D//wP//AAAADAAAPgAA/wAD/4AB/8AA/8AAfwAB/AA/8Af+AP/AA/wAD4AAMAAA4AAD+AAP/gA//8AH/wAB/AAf8Af/wP/4A/4AD/gAP/4AH/8AB/wAB/AB/8D//wP/gA/gADgAAIABA4AcDwDwPw/Afn4Af+AA/wAD/AA//AH5+A/D8DwDwOAHAgAEAAAAP/AA/8AD/wAP/AAAf8AB/wAH/AAf8D/wAP/AA/8AD/wAAAAAAAADh/wOH/A4f8Dh/wOHHA4ccDhxwOHHA/8cD/xwP/HA/8cAAAAAAAAf//9///3///f//9wAA3AADcAAMAAAOAAA/gAD/wAH/8AB/8AA/wAAPAAAEAAAAHAADcAANwAB3///f//9///wAA"), 32, atob("BwYLDg4UDwYJCQwMBgkGCQ4MDg4ODg4NDg4GBgwMDA4PDg4ODg4NDg4GDQ4MEg8ODQ8ODgwODhQODg4ICQg="), 22+(scale<<8)+(1<<16)); +}; + +{ +const SETTINGS_FILE = "pebblepp.json"; +let settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'theme':'System', 'showlock':false}; +let theme; +let drawTimeout; + +const h = g.getHeight(); +const w = g.getWidth(); +const ha = 2*h/5 - 4; +const h2 = 3*h/5 - 10; +const h3 = 7*h/8; + +let draw = function() { + let locale = require("locale"); + let date = new Date(); + let time = locale.time(date, 1); + + g.reset(); + g.setBgColor(theme.bg).clearRect(0, h2, w, h3); + g.setFontLECO1976Regular42().setFontAlign(0, -1); + g.setColor(theme.fg); + g.drawString(time, w/2, h2 + 8); + + // queue next draw + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +}; + +let loadThemeColors = function() { + theme = {fg: g.theme.fg, bg: g.theme.bg, day: g.toColor(0,0,0)}; + if (settings.theme === "Dark") { + theme.fg = g.toColor(1,1,1); + theme.bg = g.toColor(0,0,0); + } else if (settings.theme === "Light") { + theme.fg = g.toColor(0,0,0); + theme.bg = g.toColor(1,1,1); + } + // day and steps + if (settings.color == 'Blue' || settings.color == 'Red') + theme.day = g.toColor(1,1,1); // white on blue or red best contrast +}; +loadThemeColors(); + +// Load the clock infos +let clockInfoItems = require("clock_info").load(); +let clockInfoDraw = (itm, info, options) => { + // itm: the item containing name/hasRange/etc + // info: data returned from itm.get() containing text/img/etc + // options: options passed into addInteractive + // Clear the background - if focussed, add a border + g.reset().setBgColor(theme.bg).setColor(theme.fg); + var b = 0; // border + if (options.focus) { // white border + b = 4; + g.clearRect(options.x, options.y, options.x+options.w-1, options.y+options.h-1); + } + g.setBgColor(settings.bg).clearRect(options.x+b, options.y+b, options.x+options.w-1-b, options.y+options.h-1-b); + // we're drawing center-aligned here + var midx = options.x+options.w/2; + if (info.img) { // draw the image + // TODO: we could replace certain images with our own ones here... + var y = options.y+8; + if (g.floodFill) { + /* img is (usually) a black and white transparent image. But we really would like the bits in + the middle of it to be white. So what we do is we draw a slightly bigger rectangle in white, + draw the image, and then flood-fill the rectangle back to the background color. floodFill + was only added in 2v18 so we have to check for it and fallback if not. */ + g.setBgColor(theme.bg).clearRect(midx-25,y,midx+23,y+47); + g.drawImage(info.img, midx-24,y,{scale:2}); + g.floodFill(midx-25,y,settings.bg); + } else { // fallback + g.drawImage(info.img, midx-24,y,{scale:2}); + } + } + g.setFontLECO1976Regular22().setFontAlign(0, 0); + g.drawString(info.text, midx,options.y+options.h-12); // draw the text +}; + +let clockInfoMenuA = require("clock_info").addInteractive(clockInfoItems, { + x : 0, y: 0, w: w/2, h:h/2, + draw : clockInfoDraw +}); +let clockInfoMenuB = require("clock_info").addInteractive(clockInfoItems, { + x : w/2, y: 0, w: w/2, h:h/2, + draw : clockInfoDraw +}); + +// Show launcher when middle button pressed +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + clockInfoMenuA.remove(); + clockInfoMenuB.remove(); + delete Graphics.prototype.setFontLECO1976Regular22; + delete Graphics.prototype.setFontLECO1976Regular42; + require("widget_utils").show(); // re-show widgets + }}); + +Bangle.loadWidgets(); +require("widget_utils").swipeOn(); // hide widgets, make them visible with a swipe +g.setBgColor(settings.bg).clear(); // start off with completely clear background +// contrast bar (top) +g.setColor(theme.fg).fillRect(0, h2 - 6, w, h2); +// contrast bar (bottom) +g.setColor(theme.fg).fillRect(0, h3, w, h3 + 6); + +draw(); +} diff --git a/apps/pebblepp/app.png b/apps/pebblepp/app.png new file mode 100644 index 0000000000000000000000000000000000000000..cfdf584a15b949bfadf62c8e4ca6a089645b354e GIT binary patch literal 1610 zcmV-Q2DSN#P)EX>4Tx04R}tkv&MmKp2MKrWQpj4t5Z6h)|s@h>AFB6^c+H)C#RSm|Xe?O&XFE z7e~Rh;NZ_<)xpJCR|i)?5c~mgb#YR3krKa43N2#19s$1J#dwx~-JhdZ%~=cxh{UtZFm2)u;^|G> z;Ji;9VMSRbJ|`YC>4LCuVzld|SV+-%+{ZuY`XzEHI{4H2e1h2iS6a%!=Q!00009a7bBm001r{001r{0eGc9b^rhX2XskI zMF-~v3kxJL0}!_W0000PbVXQnLvL+uWo~o;Lvm$dbY)~9cWHEJAV*0}P*;Ht7XSbR zG)Y83R9M69m|aL)XBfwS$CFsUW2g#d%P`VR)_vebGZ{rT5z(O{f*@>eUWia|OmB9z z4kv7sT?ktILXf$0F;ps3bXOCK3WB{8OQC6Xjg}E?f=btP$uwsd$DEz!!{js_gpr4H zanAGp-{<_#^FCjRfJ{nB2BZo7PYL~<#7lzk*Q+Jug83u}d7$l;5ZXUubN$EbH=o>O z^JNLm!V$OuxC776N6Rs;M{osZDE*++@AsdaoJc=QJc^Bvb^Qrn0k94p_z)(~!wb>t z&@)=3mKz`4aJgJ&v$?9O3UIsK*M7OS`1vBa33x?@ui+F9Arn4^XJCPGkiiOo2;YN{ zfQRZw>zz)g93f7pvwpNbQQz!@u6^(U@CEz|`eD4FvbB!#Lxq{pTG+$z^*gb9su!o z3F+pVCX}QYqUesn3qU4ZfTsZDgCG20gCjVC639!St^OV=eHXzC`B1Ev&^FwHx8WhY z1AhQu0UK0<54`XLdum}b4NzxHvgxl~`$2et(S;Q{F>mb7n0Pn*sIE0_T0l&dMd;_L)&7Z;@ z$biT27-rxJT!FWA6~>d$2W5Z&r=iX)Ll6WI;RJvS@zPY*%!XbttyZgwkR(Z+S(lcUqJD}NlOXuu;2`R%)oKj}gNlWJ3&QyL zxGc+4Q&S5I3z2&q4o81~zY=g-%<=K@^z^hK2%VjsCX=b6q9Tk_RD+X~lclAl>SKO> zzUsC!LV_SPHZ}t5>+4~g%gV|mNy^U7Rsdm`Kp@c9*9SB;HJMB%yWMWLzc8gn8U$)< zYs<^a^|TI+SS*&DoE%_xcURFI9v*6se`sh3P%w(myk4&g(1KOj+uIA%sQls++Su4= zZf=gXYBHI6dwX9PUbeTZtEo~ zf~ZJ`!=cTlfq{Y1(NX2zY&N^yZY5+De{61UhPgjcLRnc^#l^*mAVpEsB6D+dweeJ0 zS!pyHS65eUHk(2*PGQ{I+5!d#2j}PKi;9ZI#>N!D+S*!cYpb@;^z`)9)zvArP87w7 ziHVYulE}iS7*s{^Pc}*5j~)MBDvkVy@bJWdemA0dsXax-7Cpy8;xiaILkP5%Y`PS89@oxckAa4<4LP zx_a8mY6Uz^^9kb(7wm7{K0QmS`^;2c+|@!_!Y@7VG=^Ttfx{Qo8U zEDQ6TN^01BIP&6CMdoML`}b|P+<55Mqic6f6%g!5^!8j%jzRhRK-!&AZ&P;AKlk*{1pI|14Q= z-*>gjwVj9M;Dz>{skJkHzFT=jk=fDUjOCF|Q=h5&hhrkGYbzEC-!A)YD`0E>%<%HL zEgd(2DjJ|EtEo!6EPngZ7L*jnz`&4Tlv!-eq94rBGylGfQlJB MUHx3vIVCg!01OWfvj6}9 literal 0 HcmV?d00001 diff --git a/apps/pebblepp/settings.js b/apps/pebblepp/settings.js new file mode 100644 index 000000000..b84a477e1 --- /dev/null +++ b/apps/pebblepp/settings.js @@ -0,0 +1,50 @@ +(function(back) { + const SETTINGS_FILE = "pebblepp.json"; + + // TODO Only the color/theme indices should be written in the settings file so the labels can be translated + + // Initialize with default settings... + let s = {'bg': '#0f0', 'color': 'Green', 'theme':'System', 'showlock':false} + + // ...and overwrite them with any saved values + // This way saved values are preserved if a new version adds more settings + const storage = require('Storage'); + let settings = storage.readJSON(SETTINGS_FILE, 1) || s; + const saved = settings || {}; + for (const key in saved) { + s[key] = saved[key] + } + + function save() { + settings = s; + storage.write(SETTINGS_FILE, settings); + } + + var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; + var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; + var theme_options = ['System', 'Light', 'Dark']; + + E.showMenu({ + '': { 'title': 'Pebble++ Clock' }, + /*LANG*/'< Back': back, + /*LANG*/'Colour': { + value: 0 | color_options.indexOf(s.color), + min: 0, max: 5, + format: v => color_options[v], + onchange: v => { + s.color = color_options[v]; + s.bg = bg_code[v]; + save(); + } + }, + /*LANG*/'Theme': { + value: 0 | theme_options.indexOf(s.theme), + min: 0, max: theme_options.length - 1, + format: v => theme_options[v], + onchange: v => { + s.theme = theme_options[v]; + save(); + } + } + }); +}); From 19bd1da0febae198c9a8e73907c16df0adbed51d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 11 May 2023 12:46:20 +0100 Subject: [PATCH 30/40] minor tweak --- apps/pebblepp/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pebblepp/app.js b/apps/pebblepp/app.js index 6b165aaf0..d296cdc1a 100644 --- a/apps/pebblepp/app.js +++ b/apps/pebblepp/app.js @@ -78,7 +78,7 @@ let clockInfoDraw = (itm, info, options) => { the middle of it to be white. So what we do is we draw a slightly bigger rectangle in white, draw the image, and then flood-fill the rectangle back to the background color. floodFill was only added in 2v18 so we have to check for it and fallback if not. */ - g.setBgColor(theme.bg).clearRect(midx-25,y,midx+23,y+47); + g.setBgColor(theme.bg).clearRect(midx-25,y-1,midx+24,y+48); g.drawImage(info.img, midx-24,y,{scale:2}); g.floodFill(midx-25,y,settings.bg); } else { // fallback From f89de44dfa7e2e82f121f3c88b6e6aff55ec37bd Mon Sep 17 00:00:00 2001 From: stweedo <108593831+stweedo@users.noreply.github.com> Date: Thu, 11 May 2023 13:01:54 -0500 Subject: [PATCH 31/40] +settings for UI, less IO r/w, rm timeout from eval --- apps/shadowclk/app.js | 48 ++++----- apps/shadowclk/interface.html | 189 +++++++++++++++++++++++++--------- 2 files changed, 160 insertions(+), 77 deletions(-) diff --git a/apps/shadowclk/app.js b/apps/shadowclk/app.js index 31d62a87d..7ffdc4683 100644 --- a/apps/shadowclk/app.js +++ b/apps/shadowclk/app.js @@ -1,6 +1,6 @@ // Clock with large colored digits using the "Londrina" font and a slightly larger "Londrina Shadow" font on top -Graphics.prototype.setFontLondrinaSolid = function() { +Graphics.prototype.setFontLondrinaSolid = function () { // Actual height 59 (64 - 6) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('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'))), @@ -10,7 +10,7 @@ Graphics.prototype.setFontLondrinaSolid = function() { ); }; -Graphics.prototype.setFontLondrinaShadow = function() { +Graphics.prototype.setFontLondrinaShadow = function () { // Actual height 63 (67 - 5) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('ADX/8AJH4EQBI9AhwJHkEHBI8QgeABI0IgPABI0EgA8HgUAuAJGgMAnAyHwEcKBH+BI8f/4JHg//KA49CDxATInFgBI/wKA8D4BQHh8AUI88I4IJG/AfBHgsBSgKhGg4QCUIseAYShFGAJbCK4oDC/hXFGgQJEK4I0CBIgmDh5SBEw0/IoYmDgF/AgYmDgLIEvgwDbggmDj4wEXAd/OwkwAYX/RQkYHwT5FhgmCMIkAgwmHDQJNCXYxNBEwoABwAmGKAV/LgYADiJNFQQYmHV4wAa/4ABMwwGCv49FWI8AjgEDhyiGP4SGDWwbGFBIsIAYUQBIkCBJAoDBIooDHYgABnArFcooCCg/4AYToDbwP/BQIyCH4MDRoQHBYoLoDwE/SANwCwSXDvA8D4EDbwUESYdggITCFoKYCQQIJCFoRkDRwYtBHwJaBWweAgItBEQMHAgIRCEYIiBbYJaBAgJQBDAIKCJARSBYYiXFVYw3CS4QJGgYJFjxLDBJAyFBIbUFBIZ8CAAU+ewZXCBIpUDAAP+AgcPDAf8BIcBeAUPAYQACn/wdQPwBIjyDGwgUC/4wEKISPGAAMOR4yRCgwJHjEBR4r9DHIyXCZgwHCPQgACDYI8HBII8HHIMDHg1ABII8GkBvB8EPQgKYCOwMHA4YsChAaFFgUEBIraCgRhIgJ/IKASdFKAaxFKAbFFKAZGHKAxGCKA0A8BQI+BQIuACB//9QQIACRoU/BAn//gJBToQJGAFIzBAYMf/5kBAAM8f4V8gEYLwixBBYKhCPgUYgKUBUIQPDBIShCBIUHBIShCBIUDwIQCHgQJBB4IJCS4T1BB4IaCnAJEuAJCeQT/CuD2CKAToCnAXCKAToCjgJCKAUMAoN+kDyGgf/FYIVBeQYJB2EAbgJQBeQMD/A1BaQJQCwEB8CdB/xQDoAJBH4P5KAY4BBIV4wBQCEgMwJIN4oBQCCAMcBIUgKAkHFoM8DIJQDJoU8DIJQCU4UAjwZBKASdCBIIZBKAR/CgEPNQKhFBIJqBKAQiBVAWAKAY8CBIRQDDAKyC4BQDbwYJBKAcASgIJCKAkGBIXgKAgrCBIJQEbgI7BFwP//5XDAoIJBn//IYUBBIIgBg4JDABV/CQIXBBIngmADBz/wBASsBdoZFDBILtDXgYDBdoiyCBIKcCPoJ/CS4JwCegJ/CUIRjBRgIYCG4KcCXQS1CBIKcBRgKrDGoJQCDYKrCMQMOv/4DAI0BJYUPsEGIgI8CZwMP0EBww8DIIMPyEB8ZVDCwMPxBSBFAJVBgaxBwhDBG4JGBPAWCIYItBIwXAgfBIYItBKoVgFgOAgxvBUwQiB8AWBwYtBBIJVBmA5BEAJQFfYRQDEQIECDYQOBSQQAES4SuCAAd4UIYAELQSXBAAhaCUgQADjwCBZ4QJGQYIJEh4DCMQIJHGQsfAYTNCBIwoFv4EE/4ADDAgID/wJDgYJD+CJGABIgBBI6JBL4qnDSoQAEXYKVCAAbKCeAQJGagRREOAICCAAYQCCwQADEgY0BBI7wCbAkBKA0YGARQFmAzB4BQFEYMH8BQFsDaB6BQFIIMfxBQFAgMfghQEBwU/gUAu//CoQiBvxQBj/AIQKwCvgNCUYcgeYQaCKQUQTgpSChCmIIQK6HIQLYHIQLsHIQYADUYRQBWIxQCYo5QGj5QDgf/+EA///F4MHAgP//AJCKAMBBIX8PgP+EIQRCLwLoFNYREDAAuAvwJHUYIJHj5ECACpiBAAPwL4JCEAAMMKIL9DFgUHBwMMBIShCaAOAgYJCUITQBBwL1CUIfgBwMweQtwBwIoCeQc4WAQFBeQccBwMBIYJQDhwOCKIRQFGQZQFeQxQDeQjmB8E8EIJQDvBQBh48DIIIQBnAfBN4RBBFgIBBFoNwKAQsBAIItBegWAFgIBBFoJGCoBOBAIKBBIwUgFwYJBIwRQDmAJCIwJQDg/8OQRQECwQjCKAMefQiXBKAMPTIQWDKASZCZoRQD2AJDG4JQC5AJDG4RQB8wJGKANxGQZBCKAM4sAJFUISICgEfaASHBOgQJDKALGB/AFBn4JCv//CAJ1BAgIXC/6rB////wJCg//CIM/BIgADgP/FQQAWFIIABBIs/WAMDZQKlGBQJABAAS0ESwQJGgYJIgAeDBIsYAYSpDAAMGAYUgOIqlCmBWFFATeBAAgQCFYYACZwToBGQ7oBAAhbCBgKpBFwUBAYLyBS4KLDSQLyBh4JESYTyB8BhDnBTCg+AEIIHBIwVggeAEIN+gEOLoQ2BOoM/wEHMgY2B4E8oAZBgEMOYVAj0gKAQ4Bh6aBhyIBcYRSB8EQg4jBKAZBBhEDxEAvDJDhyGBMwJaCGAMHLQyhBgeBYwUeS4nAS4RkCNYJBBcIRLBGQdwZoRuCGQU4YYSSBEIccEIQJDgfABYIyBBIcAvhBBJ4MPH4UAj//CIUfCYbnBWwP/AYL3DL4U/C4IAITwICB/6lBAAQ8CJgJiCKwSrDPoTaCUIVAOYZ0BUIUgcQSQCDIUQcQSkCDIS1BHgQXBDISTBGwQRBDITQDXoYZBKAI2CAQRQGCwRQGCARQGHwRQFYQKxCKAhwDn5QEQgd/AQJQCFoUAWwRQCIIUB/wNCwEGIgUD/gJCoEDQYf4BIUggKhCg/wBIUQWgcPbAZQBAAUfLgRQCLAYJDKAJiFKAZiFKAYDCLAZQCC4RYDKARiGKAkHMQZQEh5iDKAkfMQZQELAhQEv5JDKAixCKAqxEOgn/JwpNC/5OFBw40Fj5ZBn4rFv0/gHwgJTEMQPgA4MYLYYjBjoCBgwJFgYCBdocDXItgBIoACFATUEAAIoCBIwoCFYYADKIQJGuDoEGQw/CAAcOAQMwA4YEBg4WDh6GCNAcMBIKEBawQ8BKYMHWwM8G4IvBNwMDwgJBkEAnBaCgPCgEciACBLofhEQMIIwYgBuIgBghGDJYMfAgPMIwbDDGQIJBEoJQBS4oJBgT/GL4KrGS4ahGvCXIMgMAL4IAEHwI8HjwCBHgYhCBITeDFwQJCH4a0BOYaQDvphBn4JCg4eB/geBv42D/EH/kf9/+BIc///4gf/BIgGB+AcBa4IADh57GABYaCGgKvE8BIBgTICGIQEBuCwBbQIJCSAeASYYJCQwNAAoQJDS4MggB7BagkYXQIoCUIcGhC8DBIcDggkEEIUA4QQEoAJCuICB8DyFjARBGQRBBAAMODALGCfgcHCIMOAoJBBIAWcOosPHwPHHgcGBIK/BuAMBHgIWBh+8gE4G4NwCwUHwQ5BG4M4MgUDwI5BG4JGCsEB4GAh43BIwRLB8HAg4RBg5qCBYIgBcALQCDAMcR4YjBKATkEKAS/DAAZQBcYIJFvCrFAAU8UIoACUIwACjwCBbIIAEh4CBgQJIHg0PAwQyFBIZvBAAcfBIRtFv4FD/6CCgP/DAn/AAX+BIcDBIf8JgoJCSoIAig5DCv/wBIbMBK4NgfwIACR4LGBkDyCMIUAnCxBOouAXgMIeQQACoEOXYRcEEgQrDAAQkCFYYACEgYrCAAQkDFYRQEMIMgbwaXC/DTB/5QEn6pBWAJQEh4FCWwwAFA'))), @@ -20,7 +20,7 @@ Graphics.prototype.setFontLondrinaShadow = function() { ); }; -Graphics.prototype.setFontRighteous = function() { +Graphics.prototype.setFontRighteous = function () { // Actual height 16 (15 - 0) return this.setFontCustom( E.toString(require('heatshrink').decompress(atob('ABN//ABBv0QA4N4AIVwAogACoEC+EH+EP4EOAovACIcPsEfsF7vABBjfghPAjEAv0As0Yv14n/gg+Aj34vP4sPYgH4gFgEgMP8Ef+F7nABBjcwjEwIwZNFEYM//H//3wn3AgwLBwEC8EO/3+v/8E4IfDmMAn+A/8A/0AAYIHBncAGQMDAIUHgEf4ABBBIYAEjwBChgGBB4YBJAAU4AIS1BhAFBgP4h/wHoKPBXYIlDj/gn/wuF4uE4sEYAYLXBBYK9BSwLhDAIKODuP4uYBB3ABDv84n84jgSCEoNzAIIRFFoUc8DFBv/gAIN+A4IBCWoIBBj7XEFoIBDu4BCH4XwsPggPAdIItBf4N+nFOnEOnB/Bg4tBwAmBQINwOoP4u5rB4CNEsEdS4ILBLIMYAIIFBBIINBgFAhznCn/AuPIuHYRIN7N4TnBZQcHnABBgTLBXoOeAIMBdYUHgEPwAZBnvgnHgiFAD4cNwABLCIcwsAbBdILbBg+AeIJoCPIfYTIR7BgABBv8AnwTCgIZB8EHuEP7ABE4EOoEH4CzBCoLNBQ4N48FwAIjvCboYACBIIBDuapBAIQJDnypBQYKBBcIU4vFwnABHmEwFI4PFXoSBCHpoVBsEYCJGAAISZDJY14JZD7BmJhCE48DVIIBEBYYVJgE4AIYJC+F/MYQVHJIXAJISBCoEIFJoBEgDRBToRxCU4wJECYI/Jn8AWIMD8EBG4rjQUILTNuHgAId/EYPAj+AFZ0+vF+n/2FaBhD7ArBjiHBXIM4ue4AI34uLtBoCLDS5YBBHIRbBDIN4dJXgCYNggF+C4JvB/CjBgZLBCIOADwNAFIYJBc4jxJF4YXBoEIRYN8E4SHBToa/BBoIRBvgtBAIOAgfAIIJDCwAJBBoIRBsAnCToKJBGoW4vzEBnFgIIMA//+AIfgh3AgxhBRoJ1BcoMH+AxBLYUACIIVBAIIdDBYMYCAQdBAYMQQoUAgYBMAAUwDY0BHYUP/EOnEOjADBA4ILDWYR5BWoPwCYQBECYMDboQnIAIUPnEGmA3NcogjH/ADBh+4EYcMTIK3C//49kA5gbHnYBCn8P/8H/0P/iFDaoQTBgABDPYRBB/EgCIgFBkEPv/+v/8A4IhFgPggY9Ch14hiwBhARFHYZlCHYgHFNYJBDgYZCB45THXJjhCZoaBC/7fHCYYjBEp3/EIJjLJoIBBgcYh/YAIMMAIf4AIVwCIN/8D3DSoMMjABBh+Ah4/CgChBAIQ1DHYKRCCYUBQISFBh/Ah66CAoQjGEIgHFCIPAhEIOYV4TIaBDJZE7gE/AIMP/0P/hLChBlCGYQBCNYUAjEDRoOAv/8//+/n+8EOAIIfBBIIBBv/+4EGBoYJC/kHwAfBCoMHAIgrBAYMGgA='))), @@ -30,17 +30,15 @@ Graphics.prototype.setFontRighteous = function() { ); }; -// Load and set default appSettings -let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; -let defaultAppSettings = Object.assign({ - color: teletextColors[6], - theme: 'light', - enableSuffix: true, - enableLeadingZero: false, -}, require('Storage').readJSON("shadowclk.json", true) || {}); +let appSettings = require("Storage").readJSON("shadowclk.json", 1) || {}; +let settings = require("Storage").readJSON("setting.json", 1) || {}; +let is12Hour = settings["12hour"] !== undefined ? settings["12hour"] : false; +let color = appSettings.color !== undefined ? appSettings.color : "#0ff"; +let enableLeadingZero = appSettings.enableLeadingZero !== undefined ? appSettings.enableLeadingZero : false; +let enableSuffix = appSettings.enableSuffix !== undefined ? appSettings.enableSuffix : true; // Draw the time and date -(function() { +(function () { let drawTimeout; function draw() { @@ -48,36 +46,35 @@ let defaultAppSettings = Object.assign({ var y = g.getHeight() / 2; g.reset().clearRect(Bangle.appRect); var date = new Date(); - var appSettings = require("Storage").readJSON("shadowclk.json", 1) || defaultAppSettings; - var settings = require("Storage").readJSON("setting.json", 1) || {}; - var is12HourFormat = settings["12hour"]; var hour = date.getHours(); var minutes = String(date.getMinutes()).padStart(2, '0'); + // Handle 12-hour format - if (is12HourFormat) { + if (is12Hour) { hour = hour % 12 || 12; // Convert 0 to 12 for 12-hour format } else { // If the leading zero option is enabled and hour is less than 10, add leading zero - if (appSettings.enableLeadingZero && hour < 10) { + if (enableLeadingZero && hour < 10) { hour = '0' + hour; } } + var timeStr = hour + ':' + minutes; + // Handle midnight in 12-hour format specifically - if (is12HourFormat && hour === 0) { + if (is12Hour && hour === 0) { timeStr = '12' + timeStr.substring(2); } - // Print time in selected color and then the outline - var color = appSettings.color; + g.setFontAlign(0, 0).setFont("LondrinaSolid").setColor(color).drawString(timeStr, x - 1, y); g.reset().setFontAlign(0, 0).setFont("LondrinaShadow").drawString(timeStr, x - 1, y); - // Get full date and format it + var locale = require("locale"); var dayOfMonth = date.getDate(); var month = locale.month(date, 1).slice(0, 1).toUpperCase() + locale.month(date, 1).slice(1).toLowerCase(); var year = date.getFullYear(); var dayOfMonthStr = dayOfMonth.toString(); - if (appSettings.enableSuffix) { + if (enableSuffix) { var suffix = ""; if (dayOfMonth === 1 || dayOfMonth === 21 || dayOfMonth === 31) { suffix = "st"; @@ -90,11 +87,10 @@ let defaultAppSettings = Object.assign({ } dayOfMonthStr += suffix; } - // Combine and print date string var dayOfWeek = locale.dow(date, 0).slice(0, 1).toUpperCase() + locale.dow(date, 0).slice(1).toLowerCase(); var dateStr = month + " " + dayOfMonthStr + ", " + year + "\n" + dayOfWeek; g.setFontAlign(0, 0).setFont("Righteous").drawString(dateStr, x, y + 56); - // Time interval set to redraw every 60 seconds + if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(() => { drawTimeout = undefined; @@ -103,7 +99,7 @@ let defaultAppSettings = Object.assign({ } Bangle.setUI({ mode: "clock", - remove: function() { + remove: function () { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; delete Graphics.prototype.setFontLondrinaSolid; @@ -114,4 +110,4 @@ let defaultAppSettings = Object.assign({ Bangle.loadWidgets(); draw(); setTimeout(Bangle.drawWidgets, 0); -})(); +})(); \ No newline at end of file diff --git a/apps/shadowclk/interface.html b/apps/shadowclk/interface.html index 9a65a4893..40d2fff57 100644 --- a/apps/shadowclk/interface.html +++ b/apps/shadowclk/interface.html @@ -6,7 +6,8 @@ - 3-Bit Color Picker + + Shadow Clock Customizer -
-

3-Bit Color Picker

+

Clock Customizer

- + + + +
@@ -104,6 +119,15 @@
-

Clock Customizer

+

Clock Customizer

- - - - +
+
+ + +
+
+ + +
+
- +
+ +
@@ -147,6 +186,7 @@ let leadingZeroButton = document.getElementById('toggle-leading-zero'); let hourFormatButton = document.getElementById('toggle-hour-format'); let suffixButton = document.getElementById('toggle-suffix'); + let bgButton = document.getElementById('toggle-bg'); // Function to update the button text based on the current state function updateButtonState() { @@ -155,17 +195,18 @@ } else { leadingZeroButton.textContent = leadingZero ? 'Leading Zero: ON' : 'Leading Zero: OFF'; } - - hourFormatButton.textContent = is12Hour ? '12 Hour' : '24 Hour'; - suffixButton.textContent = suffix ? 'Suffix: On' : 'Suffix: Off'; + hourFormatButton.textContent = is12Hour ? 'Time Mode: 12 Hour' : 'Time Mode: 24 Hour'; + suffixButton.textContent = suffix ? 'Suffix: ON' : 'Suffix: OFF'; + bgButton.textContent = isDarkBg ? 'Theme: Dark' : 'Theme: Light'; if (is12Hour) { - if (leadingZero) prevLeadingZeroState = true; - leadingZero = false; + prevLeadingZeroState = leadingZero; // Store the state before disabling leadingZeroButton.disabled = true; + leadingZeroButton.textContent = prevLeadingZeroState ? 'Leading Zero: ON' : 'Leading Zero: OFF'; } else { - leadingZero = prevLeadingZeroState; + leadingZero = prevLeadingZeroState; // Retrieve the stored state leadingZeroButton.disabled = false; + leadingZeroButton.textContent = leadingZero ? 'Leading Zero: ON' : 'Leading Zero: OFF'; } } @@ -178,18 +219,19 @@ } } - // Function to toggle between 12 and 24 hour format function toggleHourFormat() { is12Hour = !is12Hour; - updateButtonState(); + updateButtonState(); // This will also correctly update leadingZero drawText(selectedColor); } + // Toggle the background color between dark and light function toggleBackground() { isDarkBg = !isDarkBg; // Toggle the background state let previewBox = document.getElementById("preview-box"); previewBox.style.backgroundColor = isDarkBg ? "black" : "white"; + updateButtonState(); drawText(selectedColor); // Redraw the text with updated color } @@ -197,9 +239,10 @@ suffix = !suffix; document.getElementById("toggle-suffix").textContent = `Suffix: ${suffix ? 'On' : 'Off'}`; updateButtonState(); + drawText(selectedColor); } - function formatTime(date, leadingZero) { + function formatTime(date) { let hours = date.getHours(); let minutes = date.getMinutes(); // If 12 hour format is selected, adjust hours @@ -207,7 +250,7 @@ hours = hours % 12; hours = hours ? hours : 12; // the hour '0' should be '12' in 12h format } - let formattedHours = leadingZero && hours < 10 ? `0${hours}` : `${hours}`; + let formattedHours = (!is12Hour && leadingZero && hours < 10) ? `0${hours}` : `${hours}`; let formattedMinutes = minutes < 10 ? `0${minutes}` : `${minutes}`; return `${formattedHours}:${formattedMinutes}`; } @@ -246,7 +289,7 @@ ctx.fillStyle = color; // Get the current local system time - let currentTime = formatTime(new Date(), leadingZero); + let currentTime = formatTime(new Date()); // Measure the text width and calculate the horizontal position let timeWidth = ctx.measureText(currentTime).width; @@ -355,47 +398,33 @@ }); } - // Set default settings - function setDefaultSettings() { - selectedColor = "#0ff"; - isDarkBg = false; - leadingZero = false; - suffix = true; - } - function loadSettings(callback) { - // Set a timeout for loading the settings - const timeout = new Promise((_, reject) => - setTimeout(() => reject(new Error("Timeout occurred")), 1000) - ); - // Load settings from Bangle.js storage - const loadSettingsFromStorage = new Promise((resolve) => { - Puck.eval('[require("Storage").readJSON("shadowclk.json", true)]', (dataArray) => { - let data = dataArray ? dataArray[0] : null; - if (data) { - // Apply color, theme, enableLeadingZero and enableSuffix from JSON - let { color, theme, enableLeadingZero, enableSuffix } = data; - selectedColor = color; - isDarkBg = theme === "dark"; - // Use the JSON values if they exist, otherwise use the current values - leadingZero = enableLeadingZero !== undefined ? enableLeadingZero : leadingZero; - suffix = enableSuffix !== undefined ? enableSuffix : suffix; - updateButtonState(); - displayMessage("Previous settings loaded.", 3000); - } else { - setDefaultSettings(); - } - resolve(); - }); + Puck.eval('[require("Storage").readJSON("shadowclk.json", true)]', (dataArray) => { + let data = dataArray ? dataArray[0] : null; + if (data) { + // Apply color, theme, enableLeadingZero, enableSuffix and timeMode from JSON + let { color, theme, enableLeadingZero, enableSuffix, enable12Hour } = data; + selectedColor = color !== undefined ? color : selectedColor; + isDarkBg = theme !== undefined ? (theme === "dark") : isDarkBg; + // Use the JSON values if they exist, otherwise use the current values + leadingZero = enableLeadingZero !== undefined ? enableLeadingZero : leadingZero; + prevLeadingZeroState = leadingZero; // Store the current state + suffix = enableSuffix !== undefined ? enableSuffix : suffix; + is12Hour = enable12Hour !== undefined ? enable12Hour : is12Hour; // Update the time mode from the settings + displayMessage("Previous settings loaded.", 3000); + } else { + // If no JSON data, load defaults + selectedColor = selectedColor; + isDarkBg = isDarkBg; + leadingZero = leadingZero; + prevLeadingZeroState = leadingZero; + suffix = suffix; + is12Hour = is12Hour; + displayMessage("Defaults loaded.", 3000); + } + updateButtonState(); // Update button state regardless + callback(); }); - // Execute the callback after loading the settings, or use default values in case of a timeout or error - Promise.race([loadSettingsFromStorage, timeout]) - .then(() => callback()) - .catch((error) => { - console.error(error); - setDefaultSettings(); - callback(); - }); } // Update the time display every second @@ -432,7 +461,8 @@ color: selectedColor, theme: isDarkBg ? "dark" : "light", enableLeadingZero: leadingZero, - enableSuffix: suffix + enableSuffix: suffix, + enable12Hour: is12Hour }; // Write the updated settings back to shadowclk.json diff --git a/apps/shadowclk/settings.js b/apps/shadowclk/settings.js index 93408657c..384710318 100644 --- a/apps/shadowclk/settings.js +++ b/apps/shadowclk/settings.js @@ -1,6 +1,7 @@ -(function (back) { +(function(back) { let teletextColors = ["#000", "#f00", "#0f0", "#ff0", "#00f", "#f0f", "#0ff", "#fff"]; let teletextColorNames = ["Black", "Red", "Green", "Yellow", "Blue", "Magenta", "Cyan", "White"]; + let sysSettings = require('Storage').readJSON("setting.json", 1) || {}; // Load and set default settings let appSettings = Object.assign({ @@ -8,14 +9,9 @@ theme: 'light', enableSuffix: true, enableLeadingZero: false, + enable12Hour: '24hour' // default time mode }, require('Storage').readJSON("shadowclk.json", true) || {}); - - // Save settings to storage - function writeSettings() { - require('Storage').writeJSON("shadowclk.json", appSettings); - } - // Colors from 'Light BW' and 'Dark BW' themes function createThemeColors(mode) { let cl = x => g.setColor(x).getColor(); @@ -55,10 +51,10 @@ writeSettings(); delete g.reset; g._reset = g.reset; - g.reset = function (n) { + g.reset = function(n) { return g._reset().setColor(newTheme.fg).setBgColor(newTheme.bg); }; - g.clear = function (n) { + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0, 0, g.getWidth(), g.getHeight()); }; @@ -69,15 +65,36 @@ // Read the current system theme function getCurrentTheme() { - let s = require('Storage').readJSON("setting.json", 1) || {}; - if (!s.theme) { + if (!sysSettings.theme) { return appSettings.theme; // fallback to appSettings.theme (light or dark) } - return s.theme.dark ? 'dark' : 'light'; + return sysSettings.theme.dark ? 'dark' : 'light'; + } + + // Read the current time mode + function getCurrentTimeMode() { + if (!sysSettings['12hour']) { + return appSettings.enable12Hour; // fallback to appSettings.enable12Hour + } + return sysSettings['12hour'] ? '12hour' : '24hour'; + } + + // Save settings to storage + function writeSettings() { + appSettings.enable12Hour = appSettings.enable12Hour === '12hour' ? '12hour' : '24hour'; + require('Storage').writeJSON("shadowclk.json", appSettings); + } + + // Save time mode to system settings + function writeTimeModeSetting() { + sysSettings['12hour'] = appSettings.enable12Hour === '12hour'; + require('Storage').writeJSON("setting.json", sysSettings); } function showMenu() { appSettings.theme = getCurrentTheme(); + appSettings.enable12Hour = getCurrentTimeMode(); + E.showMenu({ "": { "title": "Shadow Clock" @@ -115,6 +132,15 @@ appSettings.enableLeadingZero = v; writeSettings(); } + }, + 'Time Mode:': { + value: (appSettings.enable12Hour === '12hour'), + format: v => v ? '12 Hr' : '24 Hr', + onchange: v => { + appSettings.enable12Hour = v ? '12hour' : '24hour'; + writeSettings(); + writeTimeModeSetting(); + } } }); }