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/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 000000000..10c6e078c Binary files /dev/null and b/apps/eliteclock/app.png differ 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} + ] +} 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 000000000..10c6e078c Binary files /dev/null and b/apps/iconbits/icon.png differ 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/bootb2.js b/apps/promenu/bootb2.js index 368bc623b..f458e426f 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])); @@ -122,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++; }; @@ -204,7 +207,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 +218,20 @@ E.showMenu = function (items) { if (nameScroller) clearInterval(nameScroller); Bangle.removeListener("swipe", onSwipe); + if (setUITouch) + 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 setUITouch = process.env.VERSION >= "2v26"; + if (!setUITouch) { + uiopts.touch = touchcb; + } + Bangle.setUI(uiopts, cb); + 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 ab5444113..0306128f1 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])); @@ -167,7 +172,6 @@ E.showMenu = (items?: Menu): MenuInstance => { }, 300, name, v, item, idx, x, iy); } - g.setColor(g.theme.fg); iy += fontHeight; idx++; } @@ -252,21 +256,47 @@ E.showMenu = (items?: Menu): MenuInstance => { else l.select(evt); }; - Bangle.setUI({ - mode: "updown", - back, - remove: () => { - if (nameScroller) clearInterval(nameScroller); - Bangle.removeListener("swipe", onSwipe); - options.remove?.(); - }, - touch: ((_button, xy) => { + 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, - } as SetUIArg<"updown">, cb); + }) satisfies TouchCallback; + + const uiopts = { + mode: "updown", + back: back as () => void, + remove: () => { + if (nameScroller) clearInterval(nameScroller); + Bangle.removeListener("swipe", onSwipe); + if(setUITouch) + Bangle.removeListener("touch", touchcb); + options.remove?.(); + }, + } satisfies SetUIArg<"updown">; + + // 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(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); + } return l; -}; +}) as typeof E.showMenu; 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", 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.