Merge branch 'espruino:master' into modclk-updates
commit
0ea7ea5a8d
|
|
@ -0,0 +1 @@
|
||||||
|
0.01: initial import
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Elite clock 
|
||||||
|
|
||||||
|
Simple binary clock for leet haxorz.
|
||||||
|
|
||||||
|
Written by: [Pavel Machek](https://github.com/pavelmachek)
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
require("heatshrink").decompress(atob("mEwgIspiEPgEeAoU/4F/wGAiEAsEA4AFImAHBAolj/gRD4YFEC4UPwEfgAFC4EfF5IpHAp4dC4EQv/A/+AHYJlDnjY/AH4AJ"))
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
|
|
@ -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¢|<Z
|
||||||
|
|
||||||
|
Breakdown:
|
||||||
|
|
||||||
|
E → £ or 3
|
||||||
|
L → | or £
|
||||||
|
I → 1 or !
|
||||||
|
T → 7 or +
|
||||||
|
C → ¢ or (
|
||||||
|
O → 0
|
||||||
|
K → |< or X
|
||||||
|
|
||||||
|
Other extreme variants:
|
||||||
|
3|173 (|_0(<Z
|
||||||
|
€|!73 ©|0xX
|
||||||
|
3L1+3 (L0XXZ
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
const TEXT = "leet\nclockz";
|
||||||
|
const LEET = {
|
||||||
|
"l": "1",
|
||||||
|
"e": "3",
|
||||||
|
"t": "7",
|
||||||
|
" ": " ",
|
||||||
|
"c": "(",
|
||||||
|
"o": "0",
|
||||||
|
"k": "X",
|
||||||
|
"z": "2"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Convert hour (12h) and minute to binary mask
|
||||||
|
function getBinaryFromTime(d) {
|
||||||
|
let h = d.getHours() % 12;
|
||||||
|
if (h === 0) h = 12; // 12-hour format: 0 becomes 12
|
||||||
|
const m = d.getMinutes();
|
||||||
|
const bin = ((h << 7) | m).toString(2).padStart(11, '0');
|
||||||
|
return bin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map normal characters to leet if binary mask says so
|
||||||
|
function getDisplayText(binMask) {
|
||||||
|
return TEXT.split("").map((ch, i) =>
|
||||||
|
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();
|
||||||
|
|
@ -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}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -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
|
"load_icon("");" command. At the end of iconbits.app.js file there are
|
||||||
more utility functions.
|
more utility functions.
|
||||||
|
|
||||||
|
Create 48x48 icon in gimp.
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 9.6 KiB |
|
|
@ -16,3 +16,4 @@
|
||||||
0.12: Fix bug where settings would behave as if all were set to false
|
0.12: Fix bug where settings would behave as if all were set to false
|
||||||
0.13: Update to new touch-event handling
|
0.13: Update to new touch-event handling
|
||||||
0.14: Fix bug in handling changes to `Bangle.appRect`
|
0.14: Fix bug in handling changes to `Bangle.appRect`
|
||||||
|
0.15: Workaround bug in 2v26/2v27 firmware
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,11 @@ var _a, _b;
|
||||||
var prosettings = (require("Storage").readJSON("promenu.settings.json", true) || {});
|
var prosettings = (require("Storage").readJSON("promenu.settings.json", true) || {});
|
||||||
(_a = prosettings.naturalScroll) !== null && _a !== void 0 ? _a : (prosettings.naturalScroll = false);
|
(_a = prosettings.naturalScroll) !== null && _a !== void 0 ? _a : (prosettings.naturalScroll = false);
|
||||||
(_b = prosettings.wrapAround) !== null && _b !== void 0 ? _b : (prosettings.wrapAround = true);
|
(_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 RectRnd = function (x1, y1, x2, y2, r) {
|
||||||
var pp = [];
|
var pp = [];
|
||||||
pp.push.apply(pp, g.quadraticBezier([x2 - r, y1, x2, y1, x2, y1 + r]));
|
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;
|
nameScroll_1 = 0;
|
||||||
}, 300, name, v, item, idx, x, iy);
|
}, 300, name, v, item, idx, x, iy);
|
||||||
}
|
}
|
||||||
g.setColor(g.theme.fg);
|
|
||||||
iy += fontHeight;
|
iy += fontHeight;
|
||||||
idx++;
|
idx++;
|
||||||
};
|
};
|
||||||
|
|
@ -204,7 +207,10 @@ E.showMenu = function (items) {
|
||||||
else
|
else
|
||||||
l.select(evt);
|
l.select(evt);
|
||||||
};
|
};
|
||||||
Bangle.setUI({
|
var touchcb = (function (_button, xy) {
|
||||||
|
cb(void 0, xy);
|
||||||
|
});
|
||||||
|
var uiopts = {
|
||||||
mode: "updown",
|
mode: "updown",
|
||||||
back: back,
|
back: back,
|
||||||
remove: function () {
|
remove: function () {
|
||||||
|
|
@ -212,11 +218,20 @@ E.showMenu = function (items) {
|
||||||
if (nameScroller)
|
if (nameScroller)
|
||||||
clearInterval(nameScroller);
|
clearInterval(nameScroller);
|
||||||
Bangle.removeListener("swipe", onSwipe);
|
Bangle.removeListener("swipe", onSwipe);
|
||||||
|
if (setUITouch)
|
||||||
|
Bangle.removeListener("touch", touchcb);
|
||||||
(_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options);
|
(_a = options.remove) === null || _a === void 0 ? void 0 : _a.call(options);
|
||||||
},
|
},
|
||||||
touch: (function (_button, xy) {
|
|
||||||
cb(void 0, xy);
|
|
||||||
}),
|
|
||||||
}, cb);
|
|
||||||
return l;
|
|
||||||
};
|
};
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,12 @@ const prosettings = (require("Storage").readJSON("promenu.settings.json", true)
|
||||||
prosettings.naturalScroll ??= false;
|
prosettings.naturalScroll ??= false;
|
||||||
prosettings.wrapAround ??= true;
|
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 RectRnd = (x1: number, y1: number, x2: number, y2: number, r: number) => {
|
||||||
const pp = [];
|
const pp = [];
|
||||||
pp.push(...g.quadraticBezier([x2 - r, y1, x2, y1, x2, y1 + r]));
|
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);
|
}, 300, name, v, item, idx, x, iy);
|
||||||
}
|
}
|
||||||
|
|
||||||
g.setColor(g.theme.fg);
|
|
||||||
iy += fontHeight;
|
iy += fontHeight;
|
||||||
idx++;
|
idx++;
|
||||||
}
|
}
|
||||||
|
|
@ -252,21 +256,47 @@ E.showMenu = (items?: Menu): MenuInstance => {
|
||||||
else l.select(evt);
|
else l.select(evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
Bangle.setUI({
|
const touchcb = ((_button, xy) => {
|
||||||
mode: "updown",
|
|
||||||
back,
|
|
||||||
remove: () => {
|
|
||||||
if (nameScroller) clearInterval(nameScroller);
|
|
||||||
Bangle.removeListener("swipe", onSwipe);
|
|
||||||
options.remove?.();
|
|
||||||
},
|
|
||||||
touch: ((_button, xy) => {
|
|
||||||
// since we've specified options.touch,
|
// since we've specified options.touch,
|
||||||
// we need to pass through all taps since the default
|
// we need to pass through all taps since the default
|
||||||
// touchHandler isn't installed in setUI
|
// touchHandler isn't installed in setUI
|
||||||
cb(void 0, xy);
|
cb(void 0, xy);
|
||||||
}) satisfies TouchCallback,
|
}) satisfies TouchCallback;
|
||||||
} as SetUIArg<"updown">, cb);
|
|
||||||
|
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;
|
return l;
|
||||||
};
|
}) as typeof E.showMenu;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "promenu",
|
"id": "promenu",
|
||||||
"name": "Pro Menu",
|
"name": "Pro Menu",
|
||||||
"version": "0.14",
|
"version": "0.15",
|
||||||
"description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.",
|
"description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.",
|
||||||
"icon": "icon.png",
|
"icon": "icon.png",
|
||||||
"type": "bootloader",
|
"type": "bootloader",
|
||||||
|
|
|
||||||
|
|
@ -88,4 +88,4 @@ of 'Select Clock'
|
||||||
0.77: Save altitude calibration when user exits via reset
|
0.77: Save altitude calibration when user exits via reset
|
||||||
0.78: Fix menu scroll restore on BangleJS1
|
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.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.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue