From 779b16b67177cf8096f304113773acae8d6d38d0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 1 Nov 2022 14:21:27 +0000 Subject: [PATCH 1/4] Fix for issue where launcher would fast-load back to clock even if the clock didn't have widgets --- apps/boot/ChangeLog | 1 + apps/boot/bootloader.js | 8 +++++++- apps/launch/app.js | 4 ++-- apps/setting/ChangeLog | 2 +- apps/setting/metadata.json | 2 +- apps/setting/settings.js | 18 ++++++++---------- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 05b7050c4..3bd1fc9fd 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -57,3 +57,4 @@ Remove support for 2v11 and earlier firmware 0.51: Remove patches for 2v10 firmware (BEEPSET and setUI) Add patch to ensure that compass heading is corrected + Ensure clock is only fast-loaded if it doesn't contain widgets diff --git a/apps/boot/bootloader.js b/apps/boot/bootloader.js index 1e0d22645..6e6466f48 100644 --- a/apps/boot/bootloader.js +++ b/apps/boot/bootloader.js @@ -1,5 +1,10 @@ // This runs after a 'fresh' boot var s = require("Storage").readJSON("setting.json",1)||{}; +/* If were being called from JS code in order to load the clock quickly (eg from a launcher) +and the clock in question doesn't have widgets, force a normal 'load' as this will then +reset everything and remove the widgets. */ +if (global.__FILE__ && !s.clockHasWidgets) {load();throw "Clock has no widgets, can't fast load";} +// Otherwise continue to try and load the clock var _clkApp = require("Storage").read(s.clock); if (!_clkApp) { _clkApp = require("Storage").list(/\.info$/) @@ -13,7 +18,8 @@ if (!_clkApp) { .sort((a, b) => a.sortorder - b.sortorder)[0]; if (_clkApp){ s.clock = _clkApp.src; - _clkApp = require("Storage").read(_clkApp.src); + _clkApp = require("Storage").read(_clkApp.src); + s.clockHasWidgets = _clkApp.includes("Bangle.loadWidgets"); require("Storage").writeJSON("setting.json", s); } } diff --git a/apps/launch/app.js b/apps/launch/app.js index 05f5bef43..3b33e530a 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -66,7 +66,7 @@ E.showScroller({ }); g.flip(); // force a render before widgets have finished drawing -function returnToClock() { +let returnToClock = function() { // unload everything manually // ... or we could just call `load();` but it will be slower Bangle.setUI(); // remove scroller's handling @@ -85,7 +85,7 @@ if (process.env.HWVERSION==2) { // 10s of inactivity goes back to clock Bangle.setLocked(false); // unlock initially let lockTimeout; -function lockHandler(locked) { +let lockHandler = function(locked) { if (lockTimeout) clearTimeout(lockTimeout); lockTimeout = undefined; if (locked) diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 25adad359..cd97e1dda 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -57,4 +57,4 @@ 0.50: Add Bangle.js 2 touchscreen calibration - for 2v16 or 2v15 cutting edge builds 0.51: Add setting for configuring a launcher 0.52: Add option for left-handed users - +0.53: Ensure that when clock is set, clockHasWidgets is set correctly too diff --git a/apps/setting/metadata.json b/apps/setting/metadata.json index 3a3094a4e..47d0a309f 100644 --- a/apps/setting/metadata.json +++ b/apps/setting/metadata.json @@ -1,7 +1,7 @@ { "id": "setting", "name": "Settings", - "version": "0.52", + "version": "0.53", "description": "A menu for setting up Bangle.js", "icon": "settings.png", "tags": "tool,system", diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 5d3bd3705..d7bb060ea 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -39,6 +39,7 @@ function resetSettings() { timezone: 0, // Set the timezone for the device HID: false, // BLE HID mode, off by default clock: null, // a string for the default clock's name + // clockHasWidgets: false, // Does the clock in 'clock' contain the string 'Bangle.loadWidgets' "12hour" : false, // 12 or 24 hour clock? firstDayOfWeek: 0, // 0 -> Sunday (default), 1 -> Monday brightness: 1, // LCD brightness from 0 to 1 @@ -674,11 +675,10 @@ function showClockMenu() { label = "* " + label; } clockMenu[label] = () => { - if (settings.clock !== app.src) { - settings.clock = app.src; - updateSettings(); - showMainMenu(); - } + settings.clock = app.src; + settings.clockHasWidgets = require("Storage").read(app.src).includes("Bangle.loadWidgets"); + updateSettings(); + showMainMenu(); }; }); if (clockApps.length === 0) { @@ -703,11 +703,9 @@ function showLauncherMenu() { label = "* " + label; } launcherMenu[label] = () => { - if (settings.launcher !== app.src) { - settings.launcher = app.src; - updateSettings(); - showMainMenu(); - } + settings.launcher = app.src; + updateSettings(); + showMainMenu(); }; }); if (launcherApps.length === 0) { From de55589e1f6ef47b710a29fa53853db26bc7ddf9 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Tue, 1 Nov 2022 16:15:47 +0100 Subject: [PATCH 2/4] iconlaunch - Remove no longer needed fastload option --- apps/iconlaunch/ChangeLog | 1 + apps/iconlaunch/README.md | 4 ---- apps/iconlaunch/app.js | 34 +++++++++++++++------------------- apps/iconlaunch/metadata.json | 2 +- apps/iconlaunch/settings.js | 7 +------ 5 files changed, 18 insertions(+), 30 deletions(-) diff --git a/apps/iconlaunch/ChangeLog b/apps/iconlaunch/ChangeLog index b47cd6590..eca18b06c 100644 --- a/apps/iconlaunch/ChangeLog +++ b/apps/iconlaunch/ChangeLog @@ -7,3 +7,4 @@ 0.07: Read app icons on demand Add swipe-to-exit 0.08: Only use fast loading for switching to clock to prevent problems in full screen apps +0.09: Remove fast load option since clocks containing Bangle.loadWidgets are now always normally loaded diff --git a/apps/iconlaunch/README.md b/apps/iconlaunch/README.md index 1bee0b8d0..0d36fdeb4 100644 --- a/apps/iconlaunch/README.md +++ b/apps/iconlaunch/README.md @@ -10,7 +10,3 @@ This launcher shows 9 apps per screen, making it much faster to navigate versus ## Technical note The app uses `E.showScroller`'s code in the app but not the function itself because `E.showScroller` doesn't report the position of a press to the select function. - -### Fastload option - -Fastload clears up the memory used by the launcher and directly evals the code of the clock to load. diff --git a/apps/iconlaunch/app.js b/apps/iconlaunch/app.js index 6bd9cf7ac..8d2f1ec4c 100644 --- a/apps/iconlaunch/app.js +++ b/apps/iconlaunch/app.js @@ -1,6 +1,6 @@ { const s = require("Storage"); - const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,swipeExit:false,oneClickExit:false,fastload:false }; + const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,swipeExit:false,oneClickExit:false}; if (!settings.fullscreen) { Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -180,24 +180,20 @@ }; const returnToClock = function() { - if (settings.fastload == true){ - Bangle.setUI(); - delete launchCache; - delete launchHash; - delete drawItemAuto; - delete drawText; - delete selectItem; - delete onDrag; - delete drawItems; - delete drawItem; - delete returnToClock; - delete idxToY; - delete YtoIdx; - delete settings; - setTimeout(eval, 0, s.read(".bootcde")); - } else { - load(); - } + Bangle.setUI(); + delete launchCache; + delete launchHash; + delete drawItemAuto; + delete drawText; + delete selectItem; + delete onDrag; + delete drawItems; + delete drawItem; + delete returnToClock; + delete idxToY; + delete YtoIdx; + delete settings; + setTimeout(eval, 0, s.read(".bootcde")); }; diff --git a/apps/iconlaunch/metadata.json b/apps/iconlaunch/metadata.json index c2335579f..e310ede4d 100644 --- a/apps/iconlaunch/metadata.json +++ b/apps/iconlaunch/metadata.json @@ -2,7 +2,7 @@ "id": "iconlaunch", "name": "Icon Launcher", "shortName" : "Icon launcher", - "version": "0.08", + "version": "0.09", "icon": "app.png", "description": "A launcher inspired by smartphones, with an icon-only scrollable menu.", "tags": "tool,system,launcher", diff --git a/apps/iconlaunch/settings.js b/apps/iconlaunch/settings.js index 02b65784f..49a49f700 100644 --- a/apps/iconlaunch/settings.js +++ b/apps/iconlaunch/settings.js @@ -5,8 +5,7 @@ fullscreen: false, direct: false, oneClickExit: false, - swipeExit: false, - fastload: false + swipeExit: false }, require("Storage").readJSON("launch.json", true) || {}); let fonts = g.getFonts(); @@ -36,10 +35,6 @@ /*LANG*/"Swipe exit": { value: settings.swipeExit == true, onchange: m => { save("swipeExit", m) } - }, - /*LANG*/"Fastload": { - value: settings.fastload == true, - onchange: (m) => { save("fastload", m) } } }; E.showMenu(appMenu); From 2fe7dc2c854ef454633e89cc80345f8a1e616c68 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 1 Nov 2022 16:11:51 +0000 Subject: [PATCH 3/4] Added 'slope clock' --- apps/slopeclock/ChangeLog | 1 + apps/slopeclock/app-icon.js | 1 + apps/slopeclock/app.js | 117 +++++++++++++++++++++++++++++++++ apps/slopeclock/app.png | Bin 0 -> 13455 bytes apps/slopeclock/metadata.json | 14 ++++ apps/slopeclock/screenshot.png | Bin 0 -> 3202 bytes 6 files changed, 133 insertions(+) create mode 100644 apps/slopeclock/ChangeLog create mode 100644 apps/slopeclock/app-icon.js create mode 100644 apps/slopeclock/app.js create mode 100644 apps/slopeclock/app.png create mode 100644 apps/slopeclock/metadata.json create mode 100644 apps/slopeclock/screenshot.png diff --git a/apps/slopeclock/ChangeLog b/apps/slopeclock/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/slopeclock/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/slopeclock/app-icon.js b/apps/slopeclock/app-icon.js new file mode 100644 index 000000000..528758a7a --- /dev/null +++ b/apps/slopeclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AAMfBIWSyhL/ACkD1cAlWq1WABYk6BYnABQcO1QLa3//FwgLEHIoABlQLO3WsBZHqHYwLGEooLF0ALHnW/BZMDDII8DmoLDAAILDmtVBZHV+oLEmEA1Ws6vAgNVh5EB+Eq/2lq4cCqqPBIYMqytVoALCioLD6tVBYMDqALEr4KBqotBqkAgsP/9VvkMhoLBhoLCKwQrCIoQLCBQITBM4QPB+ALBFYYLBhpHDBY0BIoILFuEPBYNcBY1XP4fAmgLENIYDBI4JGCNIlXqp3CCof/F4UPIIILEI4wtEIQVwAYIzCO4oLCSgIXFqpfCIwjTBCQXAEQgA/AAoA=")) diff --git a/apps/slopeclock/app.js b/apps/slopeclock/app.js new file mode 100644 index 000000000..621a61376 --- /dev/null +++ b/apps/slopeclock/app.js @@ -0,0 +1,117 @@ +Graphics.prototype.setFontPaytoneOne = function(scale) { + // Actual height 81 (91 - 11) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 46, + atob("ITZOMzs7SDxHNUdGIQ=="), + 113+(scale<<8)+(1<<16) + ); + return this; +}; + +{ // must be inside our own scope here so that when we are unloaded everything disappears + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global +let drawTimeout; + +let g2 = Graphics.createArrayBuffer(g.getWidth(),90,1,{msb:true}); +let g2img = { + width:g2.getWidth(), height:g2.getHeight(), bpp:1, + buffer:g2.buffer, transparent:0 +}; +const slope = 20; +const offsy = 20; // offset of numbers from middle +const fontBorder = 4; // offset from left/right +const slopeBorder = 10, slopeBorderUpper = 4; // fudge-factor to move minutes down from slope +let R,x,y; // middle of the clock face +let dateStr = ""; +let bgColors = g.theme.dark ? ["#ff0","#0ff","#f0f"] : ["#f00","#0f0","#00f"]; +let bgColor = bgColors[(Math.random()*bgColors.length)|0]; + + +// Draw the hour, and the minute into an offscreen buffer +let draw = function() { + R = Bangle.appRect; + x = R.w / 2; + y = R.y + R.h / 2 - 12; // 12 = room for date + var date = new Date(); + var hourStr = date.getHours(); + var minStr = date.getMinutes().toString().padStart(2,0); + dateStr = require("locale").dow(date, 1).toUpperCase()+ " "+ + require("locale").date(date, 0).toUpperCase(); + + // Draw hour + g.reset().clearRect(R); // clear whole background (w/o widgets) + g.setFontAlign(-1, 0).setFont("PaytoneOne"); + g.drawString(hourStr, fontBorder, y-offsy); + // add slope in background color + g.setColor(g.theme.bg).fillPoly([0,y+slope-slopeBorderUpper, R.w,y-slope-slopeBorderUpper, + R.w,y-slope, 0,y+slope]); + // Draw minute to offscreen buffer + g2.setColor(0).fillRect(0,0,g2.getWidth(),g2.getHeight()).setFontAlign(1, 0).setFont("PaytoneOne"); + g2.setColor(1).drawString(minStr, g2.getWidth()-fontBorder, g2.getHeight()/2); + g2.setColor(0).fillPoly([0,0, g2.getWidth(),0, 0,slope*2]); + // start the animation *in* + animate(true); + + // queue next draw + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + animate(false, function() { + draw(); + }); + }, 60000 - (Date.now() % 60000)); +}; + +let isAnimIn = true; +let animInterval; +// Draw *just* the minute image +let drawMinute = function() { + var yo = slopeBorder + offsy + y - 2*slope*minuteX/R.w; + // draw over the slanty bit + g.setColor(bgColor).fillPoly([0,y+slope, R.w,y-slope, R.w,R.h+R.y, 0,R.h+R.y]); + // draw the minutes + g.setColor(g.theme.bg).drawImage(g2img, x+minuteX-(g2.getWidth()/2), yo-(g2.getHeight()/2)); +}; +let animate = function(isIn, callback) { + if (animInterval) clearInterval(animInterval); + isAnimIn = isIn; + minuteX = isAnimIn ? -g2.getWidth() : 0; + drawMinute(); + animInterval = setInterval(function() { + minuteX += 8; + let stop = false; + if (isAnimIn && minuteX>=0) { + minuteX=0; + stop = true; + } else if (!isAnimIn && minuteX>=R.w) + stop = true; + drawMinute(); + if (stop) { + clearInterval(animInterval); + animInterval=undefined; + if (callback) callback(); + if (isAnimIn) { + // draw the date + g.setColor(g.theme.bg).setFontAlign(0, 0).setFont("6x15").drawString(dateStr, R.x + R.w/2, R.y+R.h-9);} + } + }, 20); +}; + + +// Show launcher when middle button pressed +Bangle.setUI({ + mode : "clock", + remove : function() { + // Called to unload all of the clock app + if (animInterval) clearInterval(animInterval); + animInterval = undefined; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + delete Graphics.prototype.setFontPaytoneOne; + }}); +// Load widgets +Bangle.loadWidgets(); +draw(); +setTimeout(Bangle.drawWidgets,0); +} diff --git a/apps/slopeclock/app.png b/apps/slopeclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..d72b8faf954e814f6c6b0d103c901d5a98eefa2f GIT binary patch literal 13455 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 VGet6r)SnqZML|=(TGl+^{{Zz@lIs8f literal 0 HcmV?d00001 diff --git a/apps/slopeclock/metadata.json b/apps/slopeclock/metadata.json new file mode 100644 index 000000000..d880a0cf6 --- /dev/null +++ b/apps/slopeclock/metadata.json @@ -0,0 +1,14 @@ +{ "id": "slopeclock", + "name": "Slope Clock", + "version":"0.01", + "description": "A clock where hours and minutes are divided by a sloping line. When the minute changes, the numbers slide off the screen", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "storage": [ + {"name":"slopeclock.app.js","url":"app.js"}, + {"name":"slopeclock.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/slopeclock/screenshot.png b/apps/slopeclock/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..4a59f5c4a07a6192415d701889f5743fb13cd7c2 GIT binary patch literal 3202 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 literal 0 HcmV?d00001 From a989ae30880f1485dd4fe85ac7f4e9e91ee7b454 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 2 Nov 2022 08:23:32 +0000 Subject: [PATCH 4/4] 0.52: Ensure heading patch for pre-2v15.68 firmware applies to getCompass --- apps/boot/ChangeLog | 3 ++- apps/boot/bootupdate.js | 3 ++- apps/boot/metadata.json | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 3bd1fc9fd..7b95d8686 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -56,5 +56,6 @@ 0.50: Allow setting of screen rotation Remove support for 2v11 and earlier firmware 0.51: Remove patches for 2v10 firmware (BEEPSET and setUI) - Add patch to ensure that compass heading is corrected + Add patch to ensure that compass heading is corrected on pre-2v15.68 firmware Ensure clock is only fast-loaded if it doesn't contain widgets +0.52: Ensure heading patch for pre-2v15.68 firmware applies to getCompass diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index d6fc3011c..e9a24f5f5 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -79,7 +79,8 @@ if (s.rotate) boot+=`g.setRotation(${s.rotate&3},${s.rotate>>2});\n` // screen r // ================================================== FIXING OLDER FIRMWARES // 2v15.68 and before had compass heading inverted. if (process.version.replace("v","")<215.68) - boot += `Bangle.on('mag',e=>{if(!isNaN(e.heading)) e.heading=360-e.heading;});`; + boot += `Bangle.on('mag',e=>{if(!isNaN(e.heading))e.heading=360-e.heading;}); +Bangle.getCompass=(c=>(()=>{e=c();if(!isNaN(e.heading))e.heading=360-e.heading;return e;}))(Bangle.getCompass);`; // ================================================== BOOT.JS // Append *.boot.js files diff --git a/apps/boot/metadata.json b/apps/boot/metadata.json index f94d25150..339f8503e 100644 --- a/apps/boot/metadata.json +++ b/apps/boot/metadata.json @@ -1,7 +1,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.51", + "version": "0.52", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader",