From 79a8f8be470050a84c6b1c6a1eb78d1dea6740fe Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:04:49 +0100 Subject: [PATCH 01/13] promenu: E.showMenu() acts as Bangle.setUI() (i.e. reset) --- apps/promenu/bootb2.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index ab5444113..9ed29affc 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -13,7 +13,12 @@ const prosettings = (require("Storage").readJSON("promenu.settings.json", true) prosettings.naturalScroll ??= false; prosettings.wrapAround ??= true; -E.showMenu = (items?: Menu): MenuInstance => { +E.showMenu = ((items?: Menu): MenuInstance | void => { + if(items == null){ + g.clearRect(Bangle.appRect); + return Bangle.setUI(); + } + const RectRnd = (x1: number, y1: number, x2: number, y2: number, r: number) => { const pp = []; pp.push(...g.quadraticBezier([x2 - r, y1, x2, y1, x2, y1 + r])); @@ -269,4 +274,4 @@ E.showMenu = (items?: Menu): MenuInstance => { } as SetUIArg<"updown">, cb); return l; -}; +}) as typeof E.showMenu; From 7b5a7afb066500c380886f982851748b7d9729a4 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:05:19 +0100 Subject: [PATCH 02/13] promenu: typecheck `back()` --- apps/promenu/bootb2.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index 9ed29affc..55c45445c 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -259,7 +259,7 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { Bangle.setUI({ mode: "updown", - back, + back: back as () => void, remove: () => { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); From febeda3375a9de6d569d8e0e7ddcd2b26df4e223 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:06:02 +0100 Subject: [PATCH 03/13] promenu: pull out touch handler --- apps/promenu/bootb2.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index 55c45445c..9794a4f9e 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -257,6 +257,13 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { else l.select(evt); }; + const touchcb = ((_button, xy) => { + // since we've specified options.touch, + // we need to pass through all taps since the default + // touchHandler isn't installed in setUI + cb(void 0, xy); + }) satisfies TouchCallback; + Bangle.setUI({ mode: "updown", back: back as () => void, @@ -265,12 +272,7 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { Bangle.removeListener("swipe", onSwipe); options.remove?.(); }, - touch: ((_button, xy) => { - // since we've specified options.touch, - // we need to pass through all taps since the default - // touchHandler isn't installed in setUI - cb(void 0, xy); - }) satisfies TouchCallback, + touch: touchcb, } as SetUIArg<"updown">, cb); return l; From 25af19d98b207aa04bf88e513f16209b333316ae Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:07:11 +0100 Subject: [PATCH 04/13] promenu: pull out setUI() options --- apps/promenu/bootb2.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index 9794a4f9e..196db3404 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -264,7 +264,7 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { cb(void 0, xy); }) satisfies TouchCallback; - Bangle.setUI({ + const uiopts = { mode: "updown", back: back as () => void, remove: () => { @@ -273,7 +273,9 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { options.remove?.(); }, touch: touchcb, - } as SetUIArg<"updown">, cb); + } as SetUIArg<"updown">; + + Bangle.setUI(uiopts, cb); return l; }) as typeof E.showMenu; From 5ae472358e961f58c6175f1e9a6095aac19301a1 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:08:18 +0100 Subject: [PATCH 05/13] promenu: workaround 2v2[67] bug - use separate touch handler See: - 8b2e5a5 - https://github.com/orgs/espruino/discussions/7697#discussioncomment-13782299 - https://github.com/espruino/Espruino/issues/2648#issuecomment-3095831472 --- apps/promenu/bootb2.ts | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index 196db3404..46fe112fc 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -270,12 +270,26 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { remove: () => { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); + if(is2v26_27) + Bangle.removeListener("touch", touchcb); options.remove?.(); }, - touch: touchcb, - } as SetUIArg<"updown">; + } satisfies SetUIArg<"updown">; + + const is2v26_27 = process.env.VERSION === "2v26" || process.env.VERSION === "2v27"; + if (!is2v26_27) { + // no need for workaround + (uiopts as any).touch = touchcb; + } Bangle.setUI(uiopts, cb); + if(is2v26_27){ + // work around: + // - https://github.com/espruino/Espruino/issues/2648 + // - https://github.com/orgs/espruino/discussions/7697#discussioncomment-13782299 + Bangle.on("touch", touchcb); + } + return l; }) as typeof E.showMenu; From 372dfed735f26b0ad0229f661b2c1f26e22d5662 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:10:19 +0100 Subject: [PATCH 06/13] promenu: generate js --- apps/promenu/bootb2.js | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js index 368bc623b..504f2d51b 100644 --- a/apps/promenu/bootb2.js +++ b/apps/promenu/bootb2.js @@ -2,7 +2,11 @@ var _a, _b; var prosettings = (require("Storage").readJSON("promenu.settings.json", true) || {}); (_a = prosettings.naturalScroll) !== null && _a !== void 0 ? _a : (prosettings.naturalScroll = false); (_b = prosettings.wrapAround) !== null && _b !== void 0 ? _b : (prosettings.wrapAround = true); -E.showMenu = function (items) { +E.showMenu = (function (items) { + if (items == null) { + g.clearRect(Bangle.appRect); + return Bangle.setUI(); + } var RectRnd = function (x1, y1, x2, y2, r) { var pp = []; pp.push.apply(pp, g.quadraticBezier([x2 - r, y1, x2, y1, x2, y1 + r])); @@ -204,7 +208,10 @@ E.showMenu = function (items) { else l.select(evt); }; - Bangle.setUI({ + var touchcb = (function (_button, xy) { + cb(void 0, xy); + }); + var uiopts = { mode: "updown", back: back, remove: function () { @@ -212,11 +219,18 @@ E.showMenu = function (items) { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); + if (is2v26_27) + Bangle.removeListener("touch", touchcb); (_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options); }, - touch: (function (_button, xy) { - cb(void 0, xy); - }), - }, cb); + }; + var is2v26_27 = process.env.VERSION === "2v26" || process.env.VERSION === "2v27"; + if (!is2v26_27) { + uiopts.touch = touchcb; + } + Bangle.setUI(uiopts, cb); + if (is2v26_27) { + Bangle.on("touch", touchcb); + } return l; -}; +}); From 65b9dbd3885e8174da9802bd7227d914e9e70455 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:11:14 +0100 Subject: [PATCH 07/13] promenu: bump version --- apps/promenu/ChangeLog | 1 + apps/promenu/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 6cf4b09b8..174ff7e22 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -16,3 +16,4 @@ 0.12: Fix bug where settings would behave as if all were set to false 0.13: Update to new touch-event handling 0.14: Fix bug in handling changes to `Bangle.appRect` +0.15: Workaround bug in 2v26/2v27 firmware diff --git a/apps/promenu/metadata.json b/apps/promenu/metadata.json index cd7e66e99..cfbd1ebd8 100644 --- a/apps/promenu/metadata.json +++ b/apps/promenu/metadata.json @@ -1,7 +1,7 @@ { "id": "promenu", "name": "Pro Menu", - "version": "0.14", + "version": "0.15", "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "bootloader", From c0545cf2c2c83f96707c4350a0867c82ec07c7fc Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:33:47 +0100 Subject: [PATCH 08/13] promenu: remove redundant setColor --- apps/promenu/bootb2.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index 46fe112fc..dd92a9deb 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -172,7 +172,6 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { }, 300, name, v, item, idx, x, iy); } - g.setColor(g.theme.fg); iy += fontHeight; idx++; } From 2c51bc80e56aad4b3a5e8f5bcab5fec5094e7879 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Wed, 23 Jul 2025 20:54:14 +0100 Subject: [PATCH 09/13] promenu: fix double-render from having two callbacks with "updown" --- apps/promenu/bootb2.js | 11 ++++++----- apps/promenu/bootb2.ts | 20 ++++++++++++++------ 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js index 504f2d51b..f458e426f 100644 --- a/apps/promenu/bootb2.js +++ b/apps/promenu/bootb2.js @@ -126,7 +126,6 @@ E.showMenu = (function (items) { nameScroll_1 = 0; }, 300, name, v, item, idx, x, iy); } - g.setColor(g.theme.fg); iy += fontHeight; idx++; }; @@ -219,17 +218,19 @@ E.showMenu = (function (items) { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); - if (is2v26_27) + if (setUITouch) Bangle.removeListener("touch", touchcb); (_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options); }, }; - var is2v26_27 = process.env.VERSION === "2v26" || process.env.VERSION === "2v27"; - if (!is2v26_27) { + var setUITouch = process.env.VERSION >= "2v26"; + if (!setUITouch) { uiopts.touch = touchcb; } Bangle.setUI(uiopts, cb); - if (is2v26_27) { + if (setUITouch) { + Bangle.removeListener("touch", Bangle.touchHandler); + delete Bangle.touchHandler; Bangle.on("touch", touchcb); } return l; diff --git a/apps/promenu/bootb2.ts b/apps/promenu/bootb2.ts index dd92a9deb..0306128f1 100644 --- a/apps/promenu/bootb2.ts +++ b/apps/promenu/bootb2.ts @@ -269,24 +269,32 @@ E.showMenu = ((items?: Menu): MenuInstance | void => { remove: () => { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); - if(is2v26_27) + if(setUITouch) Bangle.removeListener("touch", touchcb); options.remove?.(); }, } satisfies SetUIArg<"updown">; - const is2v26_27 = process.env.VERSION === "2v26" || process.env.VERSION === "2v27"; - if (!is2v26_27) { - // no need for workaround + // does setUI install its own touch handler? + const setUITouch = process.env.VERSION >= "2v26"; + if (!setUITouch) { + // old firmware, we can use its touch handler - no need for workaround (uiopts as any).touch = touchcb; } Bangle.setUI(uiopts, cb); - if(is2v26_27){ - // work around: + if(setUITouch){ + // new firmware, remove setUI's touch handler and use just our own to + // avoid `cb` drawing the menu (as part of setUI's touch handler) + // followed by us drawing the menu (as part of our touch handler) + // + // work around details: // - https://github.com/espruino/Espruino/issues/2648 // - https://github.com/orgs/espruino/discussions/7697#discussioncomment-13782299 + Bangle.removeListener("touch", (Bangle as any).touchHandler); + delete (Bangle as any).touchHandler; + Bangle.on("touch", touchcb); } From 8dc9e5686268788085a799e95d4026415e97e9ed Mon Sep 17 00:00:00 2001 From: RKBoss6 <178680496+RKBoss6@users.noreply.github.com> Date: Wed, 23 Jul 2025 18:00:54 -0400 Subject: [PATCH 10/13] Update ChangeLog --- apps/setting/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index dafaef48c..1a7681595 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -88,4 +88,4 @@ of 'Select Clock' 0.77: Save altitude calibration when user exits via reset 0.78: Fix menu scroll restore on BangleJS1 0.79: Ensure that tapping on pressure/altitude doesn't cause a menu to display temporarily -0.80: Add option to set LCD brightness to 0, default brightness is now 0 as well. +0.80: Add option to set LCD brightness to 0, keep default brightness at 1. From 5204bd469037df77bcdf13260008dd690b143693 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 27 Jul 2025 09:37:33 +0200 Subject: [PATCH 11/13] elite: Add elite clock. --- apps/eliteclock/ChangeLog | 1 + apps/eliteclock/README.md | 5 ++ apps/eliteclock/eliteclock.app.js | 86 +++++++++++++++++++++++++++++++ apps/eliteclock/metadata.json | 14 +++++ 4 files changed, 106 insertions(+) create mode 100644 apps/eliteclock/ChangeLog create mode 100644 apps/eliteclock/README.md create mode 100644 apps/eliteclock/eliteclock.app.js create mode 100644 apps/eliteclock/metadata.json diff --git a/apps/eliteclock/ChangeLog b/apps/eliteclock/ChangeLog new file mode 100644 index 000000000..52f6f5685 --- /dev/null +++ b/apps/eliteclock/ChangeLog @@ -0,0 +1 @@ +0.01: initial import diff --git a/apps/eliteclock/README.md b/apps/eliteclock/README.md new file mode 100644 index 000000000..0b32015e6 --- /dev/null +++ b/apps/eliteclock/README.md @@ -0,0 +1,5 @@ +# Elite clock ![](app.png) + +Simple binary clock for leet haxorz. + +Written by: [Pavel Machek](https://github.com/pavelmachek) diff --git a/apps/eliteclock/eliteclock.app.js b/apps/eliteclock/eliteclock.app.js new file mode 100644 index 000000000..daf9fb567 --- /dev/null +++ b/apps/eliteclock/eliteclock.app.js @@ -0,0 +1,86 @@ +// Bangle.js 2 - Binary Leet ClockZ +/* + +bangle.js2: create binary 'leet clock' where the time is shown as text +"leet clockz" with binary 0 being normal character and binary one +being leet translation. Be careful to only update time on minute +boundaries. + +So yeah — 1337 c10ckZ = certified leetspeak 😎 + +ChatGPT said: +Alright, here’s a hardcore hacker variant of elite clock in full-on aggressive leetspeak: + +£|173 ¢|_0¢| + binMask[i] === '1' ? (LEET[ch] || ch) : ch + ).join(""); +} + +function draw() { + g.reset().clear(); + const now = new Date(); + const bin = getBinaryFromTime(now); + const txt = getDisplayText(bin); + + const w = 0; + g.setFont("Vector", 47).setFontAlign(0,0); + + g.drawString(txt, (g.getWidth() - w) / 2, (g.getHeight() - 0) / 2); +} + +function scheduleNextDraw() { + const now = new Date(); + const msToNextMin = 60000 - (now.getSeconds() * 1000 + now.getMilliseconds()); + setTimeout(() => { + draw(); + scheduleNextDraw(); + }, msToNextMin); +} + +// Init +draw(); +scheduleNextDraw(); +//Bangle.loadWidgets(); +//Bangle.drawWidgets(); diff --git a/apps/eliteclock/metadata.json b/apps/eliteclock/metadata.json new file mode 100644 index 000000000..91f9c0013 --- /dev/null +++ b/apps/eliteclock/metadata.json @@ -0,0 +1,14 @@ +{ "id": "eliteclock", + "name": "Elite clock", + "version": "0.01", + "description": "Simple binary clock for leet haxorz", + "icon": "app.png", + "readme": "README.md", + "supports" : ["BANGLEJS2"], + "type": "clock", + "tags": "clock", + "storage": [ + {"name":"eliteclock.app.js","url":"eliteclock.app.js"}, + {"name":"eliteclock.img","url":"app-icon.js","evaluate":true} + ] +} From 1f6844d90208fd44ee5b514af222cd5ebe970e1b Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 27 Jul 2025 10:11:45 +0200 Subject: [PATCH 12/13] elite: Add an icon --- apps/iconbits/README.md | 3 +-- apps/iconbits/icon.png | Bin 0 -> 9859 bytes 2 files changed, 1 insertion(+), 2 deletions(-) create mode 100644 apps/iconbits/icon.png diff --git a/apps/iconbits/README.md b/apps/iconbits/README.md index 90bc0f5a3..f63ac788f 100644 --- a/apps/iconbits/README.md +++ b/apps/iconbits/README.md @@ -16,5 +16,4 @@ It is also possible to load existing icon into editor, using "load_icon("");" command. At the end of iconbits.app.js file there are more utility functions. - - +Create 48x48 icon in gimp. \ No newline at end of file diff --git a/apps/iconbits/icon.png b/apps/iconbits/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..10c6e078c18ca074212e5f188ff9edafd074d090 GIT binary patch literal 9859 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 V^}S71kd&(ceH|0+hnh~2{{@k3c}f5P literal 0 HcmV?d00001 From 2e95f12321c6c7e30f40b4b9c8f57b5e75cec9ef Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 27 Jul 2025 10:22:49 +0200 Subject: [PATCH 13/13] elite: add an icon --- apps/eliteclock/app-icon.js | 1 + apps/eliteclock/app.png | Bin 0 -> 9859 bytes 2 files changed, 1 insertion(+) create mode 100644 apps/eliteclock/app-icon.js create mode 100644 apps/eliteclock/app.png diff --git a/apps/eliteclock/app-icon.js b/apps/eliteclock/app-icon.js new file mode 100644 index 000000000..bc7850c4f --- /dev/null +++ b/apps/eliteclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIspiEPgEeAoU/4F/wGAiEAsEA4AFImAHBAolj/gRD4YFEC4UPwEfgAFC4EfF5IpHAp4dC4EQv/A/+AHYJlDnjY/AH4AJ")) diff --git a/apps/eliteclock/app.png b/apps/eliteclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..10c6e078c18ca074212e5f188ff9edafd074d090 GIT binary patch literal 9859 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 V^}S71kd&(ceH|0+hnh~2{{@k3c}f5P literal 0 HcmV?d00001