From 04d58e37201028def7004ccefd2f01620c6597fd Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 20 May 2024 12:41:20 +0200 Subject: [PATCH 01/19] messagesoverlay - Adapt to new setLCDOverlay --- apps/messagesoverlay/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 9cfba7652..9119999bd 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -55,7 +55,7 @@ const show = function(){ if (ovr.getBPP() == 1) { img.palette = new Uint16Array([g.theme.fg,g.theme.bg]); } - Bangle.setLCDOverlay(img, ovrx, ovry); + Bangle.setLCDOverlay(img, ovrx, ovry, {id:"messagesoverlay", remove:cleanup}); }; const manageEvent = function(event) { @@ -618,7 +618,7 @@ const cleanup = function(){ } restoreHandlers(); - Bangle.setLCDOverlay(); + Bangle.setLCDOverlay(undefined, {id: "messagesoverlay"}); ovr = undefined; }; From 76fd49dad7b908bbeb7da1a76bc7bfb33b055c68 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 20 May 2024 12:49:04 +0200 Subject: [PATCH 02/19] widget_utils - Adapt to new setLCDOverlay --- modules/widget_utils.js | 79 +++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 70fdedb40..867cb2cff 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -1,3 +1,5 @@ +exports.overlayRemoved = false; +exports.offset = 0; exports.hide = function() { exports.cleanup(); if (!global.WIDGETS) return; @@ -26,22 +28,13 @@ exports.show = function() { } }; -/// Remove any intervals/handlers/etc that we might have added. Does NOT re-show widgets that were hidden -exports.cleanup = function() { +/// Remove anthing not needed if the overlay was removed +exports.cleanupOverlay = function() { + exports.overlayRemoved = true; + exports.offset = -24; + Bangle.setLCDOverlay(undefined, {id: "widget_utils"}); delete exports.autohide; delete Bangle.appRect; - if (exports.origSetLCDOverlay){ - Bangle.setLCDOverlay = exports.origSetLCDOverlay; - } - delete exports.origSetLCDOverlay; - if (exports.cleanUpOverlay){ - Bangle.setLCDOverlay(); - } - delete exports.cleanUpOverlay; - if (exports.swipeHandler) { - Bangle.removeListener("swipe", exports.swipeHandler); - delete exports.swipeHandler; - } if (exports.animInterval) { clearInterval(exports.animInterval); delete exports.animInterval; @@ -50,6 +43,17 @@ exports.cleanup = function() { clearTimeout(exports.hideTimeout); delete exports.hideTimeout; } +}; + +/// Remove any intervals/handlers/etc that we might have added. Does NOT re-show widgets that were hidden +exports.cleanup = function() { + exports.cleanupOverlay(); + delete exports.overlayRemoved; + delete exports.offset; + if (exports.swipeHandler) { + Bangle.removeListener("swipe", exports.swipeHandler); + delete exports.swipeHandler; + } if (exports.origDraw) { Bangle.drawWidgets = exports.origDraw; delete exports.origDraw; @@ -74,14 +78,6 @@ exports.swipeOn = function(autohide) { /* TODO: maybe when widgets are offscreen we don't even store them in an offscreen buffer? */ - if (!exports.origSetLCDOverlay) { - exports.origSetLCDOverlay = Bangle.setLCDOverlay; - Bangle.setLCDOverlay = function(){ - require("widget_utils").origSetLCDOverlay.apply(Bangle, arguments); - require("widget_utils").cleanUpOverlay = false; - }; - } - // force app rect to be fullscreen Bangle.appRect = { x: 0, y: 0, w: g.getWidth(), h: g.getHeight(), x2: g.getWidth()-1, y2: g.getHeight()-1 }; // setup offscreen graphics for widgets @@ -93,16 +89,22 @@ exports.swipeOn = function(autohide) { }; og.reset().clearRect(0,0,og.getWidth(),23).fillRect(0,24,og.getWidth(),25); let _g = g; - let offset = -24; // where on the screen are we? -24=hidden, 0=full visible + exports.offset = -24; // where on the screen are we? -24=hidden, 0=full visible function queueDraw() { - Bangle.appRect.y = offset+24; - Bangle.appRect.h = 1 + Bangle.appRect.y2 - Bangle.appRect.y; - if (offset>-24) { - Bangle.setLCDOverlay(og, 0, offset); - exports.cleanUpOverlay = true; - } else { - Bangle.setLCDOverlay(); + if (!exports.overlayRemoved) { + Bangle.appRect.y = exports.offset+24; + Bangle.appRect.h = 1 + Bangle.appRect.y2 - Bangle.appRect.y; + if (exports.offset>-24) { + Bangle.setLCDOverlay(og, 0, exports.offset, { + id:"widget_utils", + remove:()=>{ + require("widget_utils").cleanupOverlay(); + } + }); + } else { + Bangle.setLCDOverlay(undefined, {id: "widget_utils"}); + } } } @@ -112,7 +114,7 @@ exports.swipeOn = function(autohide) { g=og; this._draw(this); g=_g; - if (offset>-24) queueDraw(); + if (exports.offset>-24) queueDraw(); }; w._area = w.area; if (w.area.startsWith("b")) @@ -129,14 +131,14 @@ exports.swipeOn = function(autohide) { function anim(dir, callback) { if (exports.animInterval) clearInterval(exports.animInterval); exports.animInterval = setInterval(function() { - offset += dir; + exports.offset += dir; let stop = false; - if (dir>0 && offset>=0) { // fully down + if (dir>0 && exports.offset>=0) { // fully down stop = true; - offset = 0; - } else if (dir<0 && offset<-23) { // fully up + exports.offset = 0; + } else if (dir<0 && exports.offset<-23) { // fully up stop = true; - offset = -24; + exports.offset = -24; } if (stop) { clearInterval(exports.animInterval); @@ -158,8 +160,9 @@ exports.swipeOn = function(autohide) { anim(-4); }, exports.autohide); }; - if (ud>0 && offset<0) anim(4, cb); - if (ud<0 && offset>-24) anim(-4); + exports.overlayRemoved = false; + if (ud>0 && exports.offset<0) anim(4, cb); + if (ud<0 && exports.offset>-24) anim(-4); }; Bangle.on("swipe", exports.swipeHandler); Bangle.drawWidgets(); From 2a6b428344668c992cb26399442881eec91c888d Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 20 May 2024 14:29:07 +0200 Subject: [PATCH 03/19] widget_utils - Remove exports.overlayRemoved --- modules/widget_utils.js | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 867cb2cff..15b99f5bb 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -1,4 +1,3 @@ -exports.overlayRemoved = false; exports.offset = 0; exports.hide = function() { exports.cleanup(); @@ -28,9 +27,8 @@ exports.show = function() { } }; -/// Remove anthing not needed if the overlay was removed +/// Remove anything not needed if the overlay was removed exports.cleanupOverlay = function() { - exports.overlayRemoved = true; exports.offset = -24; Bangle.setLCDOverlay(undefined, {id: "widget_utils"}); delete exports.autohide; @@ -48,7 +46,6 @@ exports.cleanupOverlay = function() { /// Remove any intervals/handlers/etc that we might have added. Does NOT re-show widgets that were hidden exports.cleanup = function() { exports.cleanupOverlay(); - delete exports.overlayRemoved; delete exports.offset; if (exports.swipeHandler) { Bangle.removeListener("swipe", exports.swipeHandler); @@ -92,11 +89,12 @@ exports.swipeOn = function(autohide) { exports.offset = -24; // where on the screen are we? -24=hidden, 0=full visible function queueDraw() { - if (!exports.overlayRemoved) { - Bangle.appRect.y = exports.offset+24; + const o = exports.offset; + if (o>-24) { + Bangle.appRect.y = o+24; Bangle.appRect.h = 1 + Bangle.appRect.y2 - Bangle.appRect.y; - if (exports.offset>-24) { - Bangle.setLCDOverlay(og, 0, exports.offset, { + if (o>-24) { + Bangle.setLCDOverlay(og, 0, o, { id:"widget_utils", remove:()=>{ require("widget_utils").cleanupOverlay(); @@ -114,7 +112,7 @@ exports.swipeOn = function(autohide) { g=og; this._draw(this); g=_g; - if (exports.offset>-24) queueDraw(); + if (o>-24) queueDraw(); }; w._area = w.area; if (w.area.startsWith("b")) @@ -160,7 +158,6 @@ exports.swipeOn = function(autohide) { anim(-4); }, exports.autohide); }; - exports.overlayRemoved = false; if (ud>0 && exports.offset<0) anim(4, cb); if (ud<0 && exports.offset>-24) anim(-4); }; From 1c3babc3c4e80ea055fcbabe06531652a7d87b97 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 20 May 2024 17:14:58 +0200 Subject: [PATCH 04/19] widget_utils - Fix offset reference --- modules/widget_utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 15b99f5bb..4e2acd296 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -112,7 +112,7 @@ exports.swipeOn = function(autohide) { g=og; this._draw(this); g=_g; - if (o>-24) queueDraw(); + if (exports.offset>-24) queueDraw(); }; w._area = w.area; if (w.area.startsWith("b")) From bfde7083727d582371029c880b3cc2d4f43ee483 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 20 May 2024 17:20:53 +0200 Subject: [PATCH 05/19] messagesoverlay - Update changelog --- apps/messagesoverlay/ChangeLog | 1 + apps/messagesoverlay/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messagesoverlay/ChangeLog b/apps/messagesoverlay/ChangeLog index fcabb290c..094694c0d 100644 --- a/apps/messagesoverlay/ChangeLog +++ b/apps/messagesoverlay/ChangeLog @@ -14,3 +14,4 @@ 0.09: Fix scrolling to last line for long text 0.10: Track Listeners added with prependListener Handle changed internal callback variable name for watches introduced in 2v21.104 +0.11: Update for new setLCDOverlay remove handler \ No newline at end of file diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index 631eb6168..26095eb33 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -1,7 +1,7 @@ { "id": "messagesoverlay", "name": "Messages Overlay", - "version": "0.10", + "version": "0.11", "description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)", "icon": "app.png", "type": "bootloader", From 19bf4b4cdf6a07bd175d04e1e96519123cbd014b Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Fri, 24 May 2024 23:04:44 +0200 Subject: [PATCH 06/19] supaclockpro wip --- apps/supaclockpro/app.js | 200 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 apps/supaclockpro/app.js diff --git a/apps/supaclockpro/app.js b/apps/supaclockpro/app.js new file mode 100644 index 000000000..074425cef --- /dev/null +++ b/apps/supaclockpro/app.js @@ -0,0 +1,200 @@ +{ // 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; + +Graphics.prototype.setFontPlayfairDisplay = function() { + // https://www.espruino.com/Font+Converter + // + // 60pt, 2bpp, Numeric + // Actual height 62 (67 - 6) + return this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 46, + atob("ExouGyYjJiEoISgoFQ=="), + 70|65536 + ); +} + +Graphics.prototype.setFontPlayfairDisplaySm = function() { + // Actual height 18 (17 - 0) + // + // 18pt, 1bpp, ASCII capitals + return this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('ABU/weP/3j/E4BAMIgEH4EB8EAkEAjwICgGADYcQgFEgEX4EeoEBBANHgE9gEEBAYABjl8h+Gg/woM+iFP4n///En1Bw/wvH4CgIXBgfggP4glDg0QoUH+cA/MAgO+gGf4HEiHBwlAn8Ah5NCgeAgPwh3+g/j4MQuFEzkc+cHmXA7+wg/8gO3g9hwP44Fv8ETEARbCPoMfPoIIDgf8gf/4P//nwh9gBgUEAQPwg8f//D//An6gBgEUJ4SoBgP+gF/wAqBgfwgFIZAqaBEwMBAwKjB/4IGCIStDJ4ISBEgIADmEAhhXBAwLcBBAYhCAAcBBoNwXgYWDfwPAQgIgBDI0AW4Mf8EPQwOHgGAoEgiEMhiPBOAUPEoZbCoEfSAKhCMoZEDCQPA4Eg+EMvkD+75B4EcKAtAhEQgUIoODmFA/1wn/8h8+WgIpDb4M4gEWgEJwEMuEH/+D/7EBJwLQCR4Mg8kInMGh1Dgef4Hn8F4/EAjB/Ej/Aj/4h//gfh4OQiFGhkh/8In7uB4EOYAOAGQPwnH+h1/gewgDWBZILiDgfPwP7+F/gkT8MEvlB//wvv8ghtBAAMPFwPwgf+kHBxEgkkMj6qBwF/4EPNYYAB8PAnFwhzyERgIIBjrgBQgLDDAQIeBlEAicAglAgUQgGCgFgwAFBAAkSCIOAgK3BpAILGA1AwEIkECVgNEGoUCSwUAGIYgBLQLqB8WAnGBh0xwZxBgKjBeIMAjzSBsEQgkIgGEn0in/Iz/yo0IyMOkl/5Mf+FHIAMCgZIBv5PFgfAgcQg2Ah0gg/ogP/gE//gECj6aBH4MMDYMEgDXCv/8j//gkQoICBdIIIBg/v4HzOAN4G4X+HwPAn/4CIUB4KABoAdBgIsBS4Mgvl8KYosBGoUH/4aIoPAuAsBh/+gI1BSYIABCIIaCLIZWDoM/EYUcg8HQwI6DDRsfKYNAGAMHcgLaBh/wHwMD/+B+HwsBQDhFBWYNA/kIn0H5/AgQ1LVQZNBQAdBI44LBAAYUBR4gRBDoQAChKHBv//z//4//8IdEdJdAg5wB8ETFgMP4JsBoEcHwbOLFIQRCoEAuEAdIQ1EvhZB4EH/kAv/gAgU8gEcgE4AIJrNHwsBgfggF+YoPAgP4gE/VoLFBNYYbBcAMfa4nB4FwFgLXCKAOAmF4ngRDEoOAgaaEPpMCTYOEiFgg/4gJoBnyjBeoQjCj/6FgOHw/hwE4WwI+B4kAvPAn1//eP/3h/84j6JBa5tBBYND8BHC9/A/PwjAcBYoUAuPwn0Mj/BKANBj0QofEiH/gYLB8akBkBWBg+AgOAcYIyBgbFEHwKYFeIb+D//gv/4KAUB4CACBwQCBwP/4FAgEYGoaYBv/Ai/+AgUD+EAnEAuEE8AkCDQJsBg72BCoXwJwKxB4MB8Fw4EfwEH/hHCp4vCDYMBhxZCHwLpEsEMj0Hg/DoP9iFffoP4DgMBk/wuF8jEPMQJrCsBHFRgKPBgZHDh/wrgRCDQIACvEcjEfgi8Bj/wr/kj/hg/goPgmFgVYcAE4IAEJAIlCHwMGAgNwCQLGBNQL7CgTHCAAiCBAAQA='))), + 32, + atob("BAUHCwsNEQQGBgkKBQkFBwwHCgkKCQoJCgoFBQsLCwkQDAwNDgwLDQ8HBw0LEQ0PDA8NCwwMDBINCwsGBwY="), + 18|65536 + ); +} + +const supaClockImg = { + width : 95, height : 13, bpp : 1, + buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), + palette: new Uint16Array([0, g.toColor("#fff")]), +} +const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; + +const interpolatePos = function(pos1, pos2, factor, easing) { + if (easing !== undefined) { + factor = Math.pow(factor, easing); + } + return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} +} + +let drawSplashScreen = function (t, total) { + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + const startPos = {x: -200, y: R.h/2}; + const endPos = {x: 100, y: R.h/2}; + const lastPos = interpolatePos(startPos, endPos, (t-1)/total) + const pos = interpolatePos(startPos, endPos, t/total) + + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, t*18); + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - t*18); + + g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+5); + g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); + +} + +let splashScreen = function () { + g.clearRect(R.x,R.y, R.x2, R.y2); + return new Promise((resolve, reject) => { + let t = 0; + function tick() { + drawSplashScreen(t, 10); + t += 1; + if (t < 20) { + setTimeout(tick, 100); + } else { + resolve(); + } + } + tick(); + }) +} + +// Actually draw the watch face +let draw = function() { + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + g.clearRect(R.x,R.y, R.x2, R.y2 - 60); + var date = new Date(); + let minutes = date.getMinutes(); + minutes = (minutes < 10 ? '0' : '') + minutes; + + g.setColor(g.theme.fg) + // Time + const yt = R.y + 92 - 20 - 30 + 6 + 10; + const xt = R.w/2; + let hours = date.getHours()+''; + + g.setFontAlign(1, 0).setFontPlayfairDisplay().drawString(hours, xt - 8, yt); + g.setFontAlign(0, 0).setFontPlayfairDisplay().drawString(':', xt, yt); + g.setFontAlign(-1, 0).setFontPlayfairDisplay().drawString(minutes, xt + 8, yt); + + g.drawImage(supaClockImg, R.x2 - supaClockImg.width - 2, R.y + 2); + // Day of week + + let dateStr = require("locale").dow(date).toUpperCase() + '\n' + require("locale").month(date, 2).toUpperCase() + ' ' + date.getDate(); + g.setFont('6x8').setFontAlign(-1, 0).drawString(dateStr, R.x2 - supaClockImg.width - 2, R.y + 42 - 30 + 8); + + g.drawLine(0, upperCI, R.x2, upperCI); + + // queue next draw + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +}; + +let clockInfoDraw = (itm, info, options) => { + g.reset().setFontPlayfairDisplaySm().setColor(g.theme.fg).setBgColor(g.theme.bg); + if (options.focus) g.setBgColor("#FF0"); + g.clearRect({x:options.x,y:options.y,w:options.w,h:options.h}); + + if (info.img) { + g.drawImage(info.img, options.x+1,options.y+2); + } + var text = info.text.toString().toUpperCase(); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + g.setFontAlign(-1,-1).drawString(text, options.x+24+3, options.y+6); +}; + +let clockInfoDrawR = (itm, info, options) => { + g.reset().setFontPlayfairDisplaySm().setColor(g.theme.fg).setBgColor(g.theme.bg); + if (options.focus) g.setBgColor("#FF0"); + g.clearRect({x:options.x,y:options.y,w:options.w,h:options.h}); + + if (info.img) { + g.drawImage(info.img, options.x + options.w-1-24,options.y+2); + } + var text = info.text.toString().toUpperCase(); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); +}; + +// 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; + // remove info menu + clockInfoMenu.remove(); + delete clockInfoMenu; + clockInfoMenu2.remove(); + delete clockInfoMenu2; + clockInfoMenu3.remove(); + delete clockInfoMenu3; + clockInfoMenu4.remove(); + delete clockInfoMenu4; + // reset theme + g.setTheme(oldTheme); + }}); +// Load widgets +Bangle.loadWidgets(); + +(() => { + function draw() { + g.reset(); // reset the graphics context to defaults (color/font/etc) + // add your code + g.drawString("XABCDEF", 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 + }; +})() + +// Work out sizes +let R = Bangle.appRect; +let midX = R.x+R.w/2; +let upperCI = R.y2-28-28; +let lowerCI = R.y2-28; + +// Clear the screen once, at startup +let oldTheme = g.theme; +g.clearRect(R.x, R.y, R.x2, R.y2); + +splashScreen().then(() => { + g.clearRect(R.x, 0, R.x2, R.y2); + draw(); + Bangle.drawWidgets(); + // Allocate and draw clockinfos + g.drawString('Loading Clock Info Modules...', R.x + 10, upperCI); + setTimeout(() => { + // delay loading of clock info, so that the clock face appears quicker + g.clearRect(R.x, upperCI, R.x2, upperCI+10); // clear loading text + let clockInfoItems = require("clock_info").load(); + let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); + let clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); + let clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); + let clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + }, 1); +}); + +} From b93539da9ec47b3c0fcecfd928470afc81b9618e Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 19 Nov 2023 20:43:01 +0100 Subject: [PATCH 07/19] sixths: reduce wakeups to 60s when inactive --- apps/sixths/sixths.app.js | 65 ++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/apps/sixths/sixths.app.js b/apps/sixths/sixths.app.js index 098600072..6bfad2fc3 100644 --- a/apps/sixths/sixths.app.js +++ b/apps/sixths/sixths.app.js @@ -30,7 +30,7 @@ var gps_dist = 0; var mark_heading = -1; // Is the human present? -var is_active = false, last_active = getTime(); +var is_active = false, last_active = getTime(), last_unlocked = getTime(); var is_level = false; // For altitude handling. @@ -61,8 +61,15 @@ function toMorse(x) { } return r; } +function doBuzz(s) { + if (buzz == "") { + buzz = s; + buzzTask(); + } else + buzz += s; +} function aload(s) { - buzz += toMorse(' E'); + doBuzz(toMorse(' E')); load(s); } function gpsRestart() { @@ -102,7 +109,7 @@ function fmtTimeDiff(d) { function gpsHandleFix(fix) { if (!prev_fix) { show("GPS acquired", 10); - buzz += " ."; + doBuzz(" ."); prev_fix = fix; } if (0) { @@ -201,7 +208,7 @@ function markHandle() { } function entryDone() { show(":" + in_str); - buzz += " ."; + doBuzz(" ."); switch (mode) { case 1: logstamp(">" + in_str); break; case 2: cur_mark.name = in_str; break; @@ -232,7 +239,7 @@ function inputHandler(s) { s += 'E'; else s = s+(bat/5); - buzz += toMorse(s); + doBuzz(toMorse(s)); show("Bat "+bat+"%", 60); break; case 'F': gpsOff(); show("GPS off", 3); break; @@ -253,10 +260,10 @@ function inputHandler(s) { d = new Date(); s += d.getHours() % 10; s += add0(d.getMinutes()); - buzz += toMorse(s); + doBuzz(toMorse(s)); break; case 'R': aload("run.app.js"); break; - case 'Y': buzz += " ."; Bangle.resetCompass(); break; + case 'Y': doBuzz(buzz); Bangle.resetCompass(); break; } } const morseDict = { @@ -375,7 +382,7 @@ function hourly() { print("hourly"); s = ' T'; if (is_active) - buzz += toMorse(s); + doBuzz(toMorse(s)); logstamp(""); } function show(msg, timeout) { @@ -387,7 +394,7 @@ function fivemin() { bat = E.getBattery(); if (bat < 25) { if (is_active) - buzz += toMorse(s); + doBuzz(toMorse(s)); show("Bat "+bat+"%", 60); } try { @@ -614,17 +621,17 @@ function accelTask() { en = !Bangle.isLocked(); if (en && acc.z < -0.95) { msg = "Level"; - buzz = ".-.."; + doBuzz(".-.."); tm = 3000; } if (en && acc.x < -0.80) { msg = "Down"; - buzz = "-.."; + doBuzz("-.."); tm = 3000; } if (en && acc.x > 0.95) { msg = "Up"; - buzz = "..-"; + doBuzz("..-"); tm = 3000; } @@ -646,8 +653,7 @@ function buzzTask() { } else if (now == "/") { setTimeout(buzzTask, 6*dot); } else print("Unknown character -- ", now, buzz); - } else - setTimeout(buzzTask, 1000); + } } function aliveTask() { function cmp(s) { @@ -666,23 +672,30 @@ function aliveTask() { setTimeout(aliveTask, 60000); } - -var drawTimeout; +function lockHandler(locked) { + if (!locked) { + last_Unlocked = getTime(); + draw(); + } +} function queueDraw() { - if (drawTimeout) clearTimeout(drawTimeout); - if (0) // FIXME + if (getTime() - last_unlocked > 5*60) next = 60000; else next = 1000; - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, next - (Date.now() % next)); - + setTimeout(draw, (Date.now() % next)); } function start() { + g.reset(); + Bangle.setUI({ + mode : "clock" + }); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + Bangle.on("drag", touchHandler); + Bangle.on("lock", lockHandler); if (0) Bangle.on("accel", accelHandler); if (1) { @@ -705,12 +718,6 @@ function start() { } } -g.reset(); -Bangle.setUI({ - mode : "clock" -}); -Bangle.loadWidgets(); -Bangle.drawWidgets(); let logfile = require("Storage").open("sixths.egt", "a"); if (0) { From b7f127a2e14ea4b20afaf075cf85c80d7c6af2e6 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 19 Nov 2023 20:49:54 +0100 Subject: [PATCH 08/19] sixths: Powering up sensors all the time may not be neccessary --- apps/sixths/sixths.app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sixths/sixths.app.js b/apps/sixths/sixths.app.js index 6bfad2fc3..ef87168d0 100644 --- a/apps/sixths/sixths.app.js +++ b/apps/sixths/sixths.app.js @@ -13,7 +13,7 @@ var buzz = "", /* Set this to transmit morse via vibrations */ inm = "", l = "", /* For incoming morse handling */ in_str = "", note = "(NOTEHERE)", - debug = "v930", debug2 = "(otherdb)", debug3 = "(short)"; + debug = "v1119", debug2 = "(otherdb)", debug3 = "(short)"; var mode = 0, mode_time = 0; // 0 .. normal, 1 .. note, 2.. mark name var disp_mode = 0; // 0 .. normal, 1 .. small time @@ -482,7 +482,7 @@ function drawBackground() { g.setColor(0.5, 0.5, 1); drawDot(h, 0.7, 10); } - } + } if (prev_fix && prev_fix.fix) { g.setColor(0.5, 1, 0.5); drawDot(prev_fix.course, 0.5, 6); @@ -698,7 +698,7 @@ function start() { Bangle.on("lock", lockHandler); if (0) Bangle.on("accel", accelHandler); - if (1) { + if (0) { Bangle.setCompassPower(1, "sixths"); Bangle.setBarometerPower(1, "sixths"); } From 9f5c13aa364810f5b085a2f375132ca3573e3308 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 19 Nov 2023 21:30:17 +0100 Subject: [PATCH 09/19] sixths: add blinking dot, rework altitude adjustment to use system. --- apps/sixths/sixths.app.js | 42 ++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/apps/sixths/sixths.app.js b/apps/sixths/sixths.app.js index ef87168d0..10debc20e 100644 --- a/apps/sixths/sixths.app.js +++ b/apps/sixths/sixths.app.js @@ -30,13 +30,13 @@ var gps_dist = 0; var mark_heading = -1; // Is the human present? -var is_active = false, last_active = getTime(), last_unlocked = getTime(); +var is_active = false, last_active = getTime() - 14*60, last_unlocked = getTime(); +var draw_dot = false; var is_level = false; // For altitude handling. var cur_altitude = 0; -var cur_temperature = 0, alt_adjust = 0; -var alt_adjust_mode = ""; +var cur_temperature = 0; // Marks var cur_mark = null; @@ -117,9 +117,6 @@ function gpsHandleFix(fix) { alt_adjust = cur_altitude - (fix.alt + geoid_to_sea_level); alt_adjust_mode = "g"; } - if (1) { - debug = ""+fix.alt+"m "+alt_adjust; - } if (1) { let now1 = Date(); let now2 = fix.time; @@ -498,7 +495,18 @@ function drawTime(now) { else g.setFont('Vector', 26); g.setFontAlign(1, 1); - g.drawString(now.getHours() + ":" + add0(now.getMinutes()), W, 90); + draw_dot = !draw_dot; + let dot = ":"; + if (!draw_dot) + dot = "."; + g.drawString(now.getHours() + dot + add0(now.getMinutes()), W, 90); +} +function adjPressure(a) { + o = Bangle.getOptions(); + print(o); + o.seaLevelPressure = o.seaLevelPressure * m + a; + Bangle.setOptions(o); + avr = []; } function draw() { if (disp_mode == 2) { @@ -539,11 +547,21 @@ function draw() { g.drawString(msg, 10, 145); if (getTime() - last_active > 15*60) { - alt_adjust = cur_altitude - rest_altitude; - alt_adjust_mode = "h"; - msg = "H)" + fmtAlt(alt_adjust); + let alt_adjust = cur_altitude - rest_altitude; + let abs = Math.abs(alt_adjust); + print("adj", alt_adjust); + o = Bangle.getOptions(); + if (abs > 10 && abs < 150) { + let a = 0.01; + // FIXME: draw is called often compared to alt reading + if (cur_altitude > rest_altitude) + a = -a; + o.seaLevelPressure = o.seaLevelPressure + a; + Bangle.setOptions(o); + } + msg = o.seaLevelPressure.toFixed(1) + "hPa"; } else { - msg = alt_adjust_mode+")"+fmtAlt(cur_altitude - alt_adjust); + msg = fmtAlt(cur_altitude); } msg = msg + " " + cur_temperature.toFixed(1)+icon_c; if (cur_mark) { @@ -674,7 +692,7 @@ function aliveTask() { } function lockHandler(locked) { if (!locked) { - last_Unlocked = getTime(); + last_unlocked = getTime(); draw(); } } From 7c2d24823a40225970c4e802106524ab48ceef73 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 27 May 2024 21:59:14 +0200 Subject: [PATCH 10/19] sixths: fix drawing timeouts, dot now blinks as expected. --- apps/sixths/sixths.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sixths/sixths.app.js b/apps/sixths/sixths.app.js index 10debc20e..bfd523395 100644 --- a/apps/sixths/sixths.app.js +++ b/apps/sixths/sixths.app.js @@ -702,7 +702,7 @@ function queueDraw() { next = 60000; else next = 1000; - setTimeout(draw, (Date.now() % next)); + setTimeout(draw, next - (Date.now() % next)); } function start() { g.reset(); From bca8593185e936dee180f273fc5606ab095910bc Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 28 May 2024 13:17:51 +0200 Subject: [PATCH 11/19] sixths: Mark this as v0.04 --- apps/sixths/ChangeLog | 3 ++- apps/sixths/metadata.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/sixths/ChangeLog b/apps/sixths/ChangeLog index c70e1531a..08c4b83b0 100644 --- a/apps/sixths/ChangeLog +++ b/apps/sixths/ChangeLog @@ -1,3 +1,4 @@ 0.01: attempt to import 0.02: better GPS support, adding altitude and temperature support -0.03: Minor code improvements +0.03: minor code improvements +0.04: make height auto-calibration useful and slow ticks to save power diff --git a/apps/sixths/metadata.json b/apps/sixths/metadata.json index ee80be84d..91492fe1c 100644 --- a/apps/sixths/metadata.json +++ b/apps/sixths/metadata.json @@ -1,6 +1,6 @@ { "id": "sixths", "name": "Sixth sense", - "version": "0.03", + "version": "0.04", "description": "Clock for outdoor use with GPS support", "icon": "app.png", "readme": "README.md", From e20d2bb3eb64bfb83b4f0694a5057e5667025f12 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 30 May 2024 22:17:00 +0100 Subject: [PATCH 12/19] package.json: add `fix` script --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index b09e7780b..619a4c482 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "lint-apps": "node bin/sync-lint-exemptions.mjs && eslint ./apps", "lint-modules": "eslint ./modules", "test": "node bin/sanitycheck.js && npm run lint-apps && npm run lint-modules", + "fix": "eslint --fix ./apps ./modules", "update-local-apps": "./bin/create_apps_json.sh apps.local.json", "local": "npm-watch & npx http-server -a localhost -c-1", "start": "npx http-server -c-1" From 43e752851bb62cd566eab9994a158207598e03ca Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 30 May 2024 22:18:29 +0100 Subject: [PATCH 13/19] sixths: fix some lint warnings --- apps/sixths/sixths.app.js | 94 ++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 46 deletions(-) diff --git a/apps/sixths/sixths.app.js b/apps/sixths/sixths.app.js index bfd523395..00c83153f 100644 --- a/apps/sixths/sixths.app.js +++ b/apps/sixths/sixths.app.js @@ -1,4 +1,5 @@ // Sixth sense +/* eslint-disable no-unused-vars */ // Options you'll want to edit const rest_altitude = 354; @@ -7,8 +8,8 @@ const geoid_to_sea_level = 0; // Maybe BangleJS2 already compensates? const W = g.getWidth(); const H = g.getHeight(); -var cx = 100; cy = 105; sc = 70; -temp = 0; alt = 0; bpm = 0; +var cx = 100, cy = 105, sc = 70, +temp = 0, alt = 0, bpm = 0; var buzz = "", /* Set this to transmit morse via vibrations */ inm = "", l = "", /* For incoming morse handling */ in_str = "", @@ -43,16 +44,16 @@ var cur_mark = null; // Icons -icon_alt = "\0\x08\x1a\1\x00\x00\x00\x20\x30\x78\x7C\xFE\xFF\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; -icon_m = "\0\x08\x1a\1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; -icon_km = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; -icon_kph = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\xFF\x00\xC3\xC3\xFF\xC3\xC3"; -icon_c = "\0\x08\x1a\1\x00\x00\x60\x90\x90\x60\x00\x7F\xFF\xC0\xC0\xC0\xC0\xC0\xFF\x7F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; +var icon_alt = "\0\x08\x1a\1\x00\x00\x00\x20\x30\x78\x7C\xFE\xFF\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; +var icon_m = "\0\x08\x1a\1\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; +var icon_km = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\x00\x00\x00\x00\x00\x00\x00"; +var icon_kph = "\0\x08\x1a\1\xC3\xC6\xCC\xD8\xF0\xD8\xCC\xC6\xC3\x00\xC3\xE7\xFF\xDB\xC3\xC3\xC3\xC3\x00\xFF\x00\xC3\xC3\xFF\xC3\xC3"; +var icon_c = "\0\x08\x1a\1\x00\x00\x60\x90\x90\x60\x00\x7F\xFF\xC0\xC0\xC0\xC0\xC0\xFF\x7F\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"; function toMorse(x) { - r = ""; + var r = ""; for (var i = 0; i < x.length; i++) { - c = x[i]; + var c = x[i]; if (c == " ") { r += " "; continue; @@ -120,12 +121,12 @@ function gpsHandleFix(fix) { if (1) { let now1 = Date(); let now2 = fix.time; - n1 = now1.getMinutes() * 60 + now1.getSeconds(); - n2 = now2.getMinutes() * 60 + now2.getSeconds(); + var n1 = now1.getMinutes() * 60 + now1.getSeconds(); + var n2 = now2.getMinutes() * 60 + now2.getSeconds(); debug2 = "te "+(n2-n1)+"s"; } loggps(fix); - d = calcDistance(fix, prev_fix); + var d = calcDistance(fix, prev_fix); if (d > 30) { prev_fix = fix; gps_dist += d/1000; @@ -134,7 +135,7 @@ function gpsHandleFix(fix) { function gpsHandle() { let msg = ""; if (!last_restart) { - d = (getTime()-last_pause); + var d = (getTime()-last_pause); if (last_fix) msg = "PL"+ fmtTimeDiff(getTime()-last_fix); else @@ -145,12 +146,12 @@ function gpsHandle() { gpsRestart(); } } else { - fix = Bangle.getGPSFix(); + var fix = Bangle.getGPSFix(); if (fix && fix.fix && fix.lat) { gpsHandleFix(fix); msg = fix.speed.toFixed(1) + icon_kph; print("GPS FIX", msg); - + if (!last_fstart) last_fstart = getTime(); last_fix = getTime(); @@ -166,10 +167,10 @@ function gpsHandle() { } } - d = (getTime()-last_restart); - d2 = (getTime()-last_fstart); + var d = (getTime()-last_restart); + var d2 = (getTime()-last_fstart); print("gps on, restarted ", d, gps_needed, d2, fix.lat); - if (getTime() > gps_speed_limit && + if (getTime() > gps_speed_limit && (d > gps_needed || (last_fstart && d2 > 10))) { gpsPause(); gps_needed = gps_needed * 1.5; @@ -191,7 +192,7 @@ function markNew() { } function markHandle() { let m = cur_mark; - msg = m.name + ">" + fmtTimeDiff(getTime()- m.time); + var msg = m.name + ">" + fmtTimeDiff(getTime()- m.time); if (m.fix && m.fix.fix) { let s = fmtDist(calcDistance(m.fix, prev_fix)/1000) + icon_km; msg += " " + s; @@ -231,7 +232,7 @@ function inputHandler(s) { switch(s) { case 'B': s = ' B'; - bat = E.getBattery(); + var bat = E.getBattery(); if (bat > 45) s += 'E'; else @@ -242,7 +243,7 @@ function inputHandler(s) { case 'F': gpsOff(); show("GPS off", 3); break; case 'G': gpsOn(); gps_limit = getTime() + 60*60*4; show("GPS on", 3); break; case 'I': - disp_mode += 1; + disp_mode += 1; if (disp_mode == 2) { disp_mode = 0; } @@ -254,7 +255,7 @@ function inputHandler(s) { case 'S': gpsOn(); gps_limit = getTime() + 60*30; gps_speed_limit = gps_limit; show("GPS on", 3); break; case 'T': s = ' T'; - d = new Date(); + var d = new Date(); s += d.getHours() % 10; s += add0(d.getMinutes()); doBuzz(toMorse(s)); @@ -356,7 +357,7 @@ function touchHandler(d) { if (x > W/2 && y > H/2 && l != "-d") { inm = inm + "-"; l = "-d"; - } + } //print(inm, "drag:", d); } @@ -377,7 +378,7 @@ function loggps(fix) { } function hourly() { print("hourly"); - s = ' T'; + var s = ' T'; if (is_active) doBuzz(toMorse(s)); logstamp(""); @@ -387,8 +388,8 @@ function show(msg, timeout) { } function fivemin() { print("fivemin"); - s = ' B'; - bat = E.getBattery(); + var s = ' B'; + var bat = E.getBattery(); if (bat < 25) { if (is_active) doBuzz(toMorse(s)); @@ -401,7 +402,7 @@ function fivemin() { } catch (e) { print("Altimeter error", e); } - + } function every(now) { if ((mode > 0) && (getTime() - mode_time > 10)) { @@ -469,7 +470,7 @@ function drawDot(h, d, s) { g.fillCircle(x,y, 10); } function drawBackground() { - acc = Bangle.getAccel(); + var acc = Bangle.getAccel(); is_level = (acc.z < -0.95); if (is_level) { let obj = Bangle.getCompass(); @@ -479,7 +480,7 @@ function drawBackground() { g.setColor(0.5, 0.5, 1); drawDot(h, 0.7, 10); } - } + } if (prev_fix && prev_fix.fix) { g.setColor(0.5, 1, 0.5); drawDot(prev_fix.course, 0.5, 6); @@ -490,10 +491,10 @@ function drawBackground() { } } function drawTime(now) { - if (disp_mode == 0) + if (disp_mode == 0) g.setFont('Vector', 60); else - g.setFont('Vector', 26); + g.setFont('Vector', 26); g.setFontAlign(1, 1); draw_dot = !draw_dot; let dot = ":"; @@ -502,11 +503,11 @@ function drawTime(now) { g.drawString(now.getHours() + dot + add0(now.getMinutes()), W, 90); } function adjPressure(a) { - o = Bangle.getOptions(); + var o = Bangle.getOptions(); print(o); o.seaLevelPressure = o.seaLevelPressure * m + a; Bangle.setOptions(o); - avr = []; + var avr = []; } function draw() { if (disp_mode == 2) { @@ -545,12 +546,12 @@ function draw() { + fmtSteps(Bangle.getHealthStatus("day").steps), 10, 115); g.drawString(msg, 10, 145); - + if (getTime() - last_active > 15*60) { let alt_adjust = cur_altitude - rest_altitude; let abs = Math.abs(alt_adjust); print("adj", alt_adjust); - o = Bangle.getOptions(); + var o = Bangle.getOptions(); if (abs > 10 && abs < 150) { let a = 0.01; // FIXME: draw is called often compared to alt reading @@ -568,13 +569,13 @@ function draw() { msg = markHandle(); } g.drawString(msg, 10, 175); - + if (disp_mode == 1) { g.drawString(debug, 10, 45); g.drawString(debug2, 10, 65); g.drawString(debug3, 10, 85); } - + queueDraw(); } function draw_all() { @@ -587,16 +588,16 @@ function draw_all() { let now = new Date(); g.drawString(now.getHours() + ":" + add0(now.getMinutes()) + ":" + add0(now.getSeconds()), 10, 40); - acc = Bangle.getAccel(); + var acc = Bangle.getAccel(); let ax = 0 + acc.x, ay = 0.75 + acc.y, az = 0.75 + acc.y; let diff = ax * ax + ay * ay + az * az; diff = diff * 3; if (diff > 1) diff = 1; - co = Bangle.getCompass(); - step = Bangle.getStepCount(); - bat = E.getBattery(); + var co = Bangle.getCompass(); + var step = Bangle.getStepCount(); + var bat = E.getBattery(); Bangle.getPressure().then((x) => { alt = x.altitude; temp = x.temperature; }, print); @@ -634,9 +635,10 @@ function draw_all() { queueDraw(); } function accelTask() { - tm = 100; - acc = Bangle.getAccel(); - en = !Bangle.isLocked(); + var tm = 100; + var acc = Bangle.getAccel(); + var en = !Bangle.isLocked(); + var msg; if (en && acc.z < -0.95) { msg = "Level"; doBuzz(".-.."); @@ -657,9 +659,9 @@ function accelTask() { } function buzzTask() { if (buzz != "") { - now = buzz[0]; + var now = buzz[0]; buzz = buzz.substring(1); - dot = 100; + var dot = 100; if (now == " ") { setTimeout(buzzTask, 300); } else if (now == ".") { From 5ddecd2ceffb26549d4062a3d74be40f63a149ec Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 30 May 2024 22:18:49 +0100 Subject: [PATCH 14/19] lint_exemptions: remove contacts entry --- apps/lint_exemptions.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js index f0928b678..669865ae2 100644 --- a/apps/lint_exemptions.js +++ b/apps/lint_exemptions.js @@ -1161,12 +1161,6 @@ module.exports = { "no-undef" ] }, - "apps/contacts/contacts.app.js": { - "hash": "f105adae91ef5bb79266bd20b8f1f5aaebe9863853c714d1f2b22c97d9ff7773", - "rules": [ - "no-undef" - ] - }, "apps/calendar/settings.js": { "hash": "9f05366b91d0293ed965d8de019bfd044f96683542b86ebabaa3c8d3cc3ad3a7", "rules": [ From c222676501e51c5021588934d5cec65028a1d06b Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Thu, 30 May 2024 22:20:49 +0100 Subject: [PATCH 15/19] lint_exemptions: update for sixths --- apps/lint_exemptions.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js index 669865ae2..d3c628503 100644 --- a/apps/lint_exemptions.js +++ b/apps/lint_exemptions.js @@ -197,9 +197,8 @@ module.exports = { ] }, "apps/sixths/sixths.app.js": { - "hash": "b4572a529b31a5edcbd6ca5843b91c54abcbf75b2a28e90bd33751f7d6a3ebcd", + "hash": "2a4676828bdf78df052df402de34e6f1abd1c847ebe0d193fc789cd6e9dd0e5c", "rules": [ - "no-unused-vars", "no-undef" ] }, From be770a02dc39e7217bfc0813c9ca9df116046cce Mon Sep 17 00:00:00 2001 From: Tom Wallroth Date: Thu, 30 May 2024 15:13:42 +0200 Subject: [PATCH 16/19] Initial version done! --- apps/supaclk/ChangeLog | 1 + apps/supaclk/README.md | 25 ++++ apps/supaclk/app-icon.js | 1 + apps/{supaclockpro => supaclk}/app.js | 169 +++++++++++++------------- apps/supaclk/app.png | Bin 0 -> 3964 bytes apps/supaclk/metadata.json | 16 +++ apps/supaclk/screenshot.png | Bin 0 -> 3964 bytes apps/supaclk/screenshot2.png | Bin 0 -> 4206 bytes 8 files changed, 125 insertions(+), 87 deletions(-) create mode 100644 apps/supaclk/ChangeLog create mode 100644 apps/supaclk/README.md create mode 100644 apps/supaclk/app-icon.js rename apps/{supaclockpro => supaclk}/app.js (78%) create mode 100644 apps/supaclk/app.png create mode 100644 apps/supaclk/metadata.json create mode 100644 apps/supaclk/screenshot.png create mode 100644 apps/supaclk/screenshot2.png diff --git a/apps/supaclk/ChangeLog b/apps/supaclk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/supaclk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/supaclk/README.md b/apps/supaclk/README.md new file mode 100644 index 000000000..fc8f1a096 --- /dev/null +++ b/apps/supaclk/README.md @@ -0,0 +1,25 @@ +# SUPACLOCK Pro ULTRA + +A nice clock, with four ClockInfo areas at the bottom. Tap them and swipe up/down and left/right to toggle between different information. + + - Supports Light and Dark Themes. + - It has a useless splash-screen for increased ULTRAness + - Lazy Loading of Clock-Info, shows clock-face faster + - Uses locale module to display of day and month + + +Based on [LCD Clock Plus](https://banglejs.com/apps/?id=lcdclockplus) + +## Screenshots + +Light theme + +![light](screenshot.png) + +Dark theme + +![dark](screenshot2.png) + +## Credits + +Written by devsnd diff --git a/apps/supaclk/app-icon.js b/apps/supaclk/app-icon.js new file mode 100644 index 000000000..77598357b --- /dev/null +++ b/apps/supaclk/app-icon.js @@ -0,0 +1 @@ +atob("MDAB/////////////////////////////////gX2D8H//f328z3//f32+v3//AX2+v3///X2BgH///bm/v3/+A8e/v3//////////hf4/C+/+ffnM+5/+/ff1+3/+/ff1+H/+/ff1+7/+ffvt+9//BAweC+//////////4B//////AAf////+P+P////8+fH////48/H////45/H////8R/F////8x+A/////j8A/8H//j4APwD//AAYDjD//EA5HHD/+EByOHDf+EDkOGCf8OfkAAA/8P/4AAB/4P/8AAD/4f/8HAP/+///////////////55OAADx/55OTBxh/55OTD5k/55PTQDM/55PzxnAf4BAzzyOf8DAT7yff////////") diff --git a/apps/supaclockpro/app.js b/apps/supaclk/app.js similarity index 78% rename from apps/supaclockpro/app.js rename to apps/supaclk/app.js index 074425cef..c6731849f 100644 --- a/apps/supaclockpro/app.js +++ b/apps/supaclk/app.js @@ -2,6 +2,59 @@ // we also define functions using 'let fn = function() {..}' for the same reason. function decls are global let drawTimeout; +const supaClockImg = { + width : 95, height : 13, bpp : 1, + buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), + palette: new Uint16Array(g.theme.dark ? [g.toColor("#fff"), 0] : [0, g.toColor("#fff")]), +} +// todo +// const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; + +const interpolatePos = function(pos1, pos2, factor, easing) { + if (easing !== undefined) { + factor = Math.pow(factor, easing); + } + return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} +} + +let drawSplashScreen = function (frame, total) { + const R = Bangle.appRect; + g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); + const startPos = {x: -200, y: R.h/2}; + const endPos = {x: R.x2 - supaClockImg.width*2 + 30, y: R.h/2}; + const pos = interpolatePos(startPos, endPos, frame/total, 0.1) + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, frame*18); + g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - frame*18); + g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+25); + var date = new Date(); + let minutes = date.getMinutes(); + minutes = (minutes < 10 ? '0' : '') + minutes; + let hours = date.getHours()+''; + g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); + g.setColor(0).setFont('6x8:2').setFontAlign(0, 1).drawString(hours + ':' + minutes, R.x2/2, pos.y + supaClockImg.height + 25) +} + +// for fast startup-feeling, draw the splash screen once directly once +drawSplashScreen(0, 20); + +let splashScreen = function () { + g.clearRect(R.x,R.y, R.x2, R.y2); + return new Promise((resolve, reject) => { + let frame = 0; + function tick() { + drawSplashScreen(frame, 20); + frame += 1; + if (frame < 20) { + setTimeout(tick, 50); + } else { + resolve(); + } + } + tick(); + }) +} + + Graphics.prototype.setFontPlayfairDisplay = function() { // https://www.espruino.com/Font+Converter // @@ -27,52 +80,6 @@ Graphics.prototype.setFontPlayfairDisplaySm = function() { ); } -const supaClockImg = { - width : 95, height : 13, bpp : 1, - buffer : atob("wL7B+Dhf4/C+4P//f328z0+/OZ9zPv/+/vt9fr99/X7e3f/8Bfb6/X77+vw9e///6+wMAv339fu+4DD/25v79Pv32/e4HNvAePf37BAweC+3+7f////////////P4B////////////////////////////7UEYf///////////2qrW////////////tdxh////////////iLtaA="), - palette: new Uint16Array([0, g.toColor("#fff")]), -} -const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; - -const interpolatePos = function(pos1, pos2, factor, easing) { - if (easing !== undefined) { - factor = Math.pow(factor, easing); - } - return {x: (pos1.x*(1-factor) + pos2.x*factor)/2, y: (pos1.y*(1-factor) + pos2.y*factor)/2} -} - -let drawSplashScreen = function (t, total) { - g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); - const startPos = {x: -200, y: R.h/2}; - const endPos = {x: 100, y: R.h/2}; - const lastPos = interpolatePos(startPos, endPos, (t-1)/total) - const pos = interpolatePos(startPos, endPos, t/total) - - g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('ULTRA', 100, t*18); - g.setFontAlign(0, 1).setColor('#888').setFont("4x6:3").drawString('PRO', 40, R.x2 - t*18); - - g.clearRect(0, pos.y-5, R.x2, pos.y + supaClockImg.height+5); - g.drawImage(supaClockImg, pos.x, pos.y, {scale: 2}); - -} - -let splashScreen = function () { - g.clearRect(R.x,R.y, R.x2, R.y2); - return new Promise((resolve, reject) => { - let t = 0; - function tick() { - drawSplashScreen(t, 10); - t += 1; - if (t < 20) { - setTimeout(tick, 100); - } else { - resolve(); - } - } - tick(); - }) -} - // Actually draw the watch face let draw = function() { g.reset().setColor(g.theme.fg).setBgColor(g.theme.bg); @@ -84,22 +91,17 @@ let draw = function() { g.setColor(g.theme.fg) // Time const yt = R.y + 92 - 20 - 30 + 6 + 10; - const xt = R.w/2; + const xt = R.w/2 - 5; let hours = date.getHours()+''; - g.setFontAlign(1, 0).setFontPlayfairDisplay().drawString(hours, xt - 8, yt); g.setFontAlign(0, 0).setFontPlayfairDisplay().drawString(':', xt, yt); g.setFontAlign(-1, 0).setFontPlayfairDisplay().drawString(minutes, xt + 8, yt); - + // logo g.drawImage(supaClockImg, R.x2 - supaClockImg.width - 2, R.y + 2); - // Day of week - + // dow + date let dateStr = require("locale").dow(date).toUpperCase() + '\n' + require("locale").month(date, 2).toUpperCase() + ' ' + date.getDate(); g.setFont('6x8').setFontAlign(-1, 0).drawString(dateStr, R.x2 - supaClockImg.width - 2, R.y + 42 - 30 + 8); - g.drawLine(0, upperCI, R.x2, upperCI); - - // queue next draw if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; @@ -133,67 +135,60 @@ let clockInfoDrawR = (itm, info, options) => { g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); }; + +let clockInfoItems; +let clockInfoMenu1; +let clockInfoMenu2; +let clockInfoMenu3; +let clockInfoMenu4; + // Show launcher when middle button pressed Bangle.setUI({ mode : "clock", - remove : function() { - // Called to unload all of the clock app + remove : function() { // for fastloading, clear the app memory if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; - // remove info menu - clockInfoMenu.remove(); - delete clockInfoMenu; + delete Graphics.prototype.setFontPlayfairDisplay + delete Graphics.prototype.setFontPlayfairDisplaySm + delete clockInfoItems; + clockInfoMenu1.remove(); + delete clockInfoMenu1; clockInfoMenu2.remove(); delete clockInfoMenu2; clockInfoMenu3.remove(); delete clockInfoMenu3; clockInfoMenu4.remove(); delete clockInfoMenu4; - // reset theme - g.setTheme(oldTheme); }}); -// Load widgets + Bangle.loadWidgets(); -(() => { - function draw() { - g.reset(); // reset the graphics context to defaults (color/font/etc) - // add your code - g.drawString("XABCDEF", 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 - }; -})() - -// Work out sizes let R = Bangle.appRect; let midX = R.x+R.w/2; let upperCI = R.y2-28-28; let lowerCI = R.y2-28; -// Clear the screen once, at startup -let oldTheme = g.theme; g.clearRect(R.x, R.y, R.x2, R.y2); - splashScreen().then(() => { g.clearRect(R.x, 0, R.x2, R.y2); draw(); Bangle.drawWidgets(); // Allocate and draw clockinfos - g.drawString('Loading Clock Info Modules...', R.x + 10, upperCI); + g.setFontAlign(1, 1).setFont('6x8').drawString('Loading Clock Info Modules...', R.x + 10, upperCI); setTimeout(() => { // delay loading of clock info, so that the clock face appears quicker g.clearRect(R.x, upperCI, R.x2, upperCI+10); // clear loading text - let clockInfoItems = require("clock_info").load(); - let clockInfoMenu = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); - let clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); - let clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); - let clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + try { + clockInfoItems = require("clock_info").load(); + clockInfoMenu1 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDraw}); + clockInfoMenu2 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:upperCI, w:midX-2, h:28, draw : clockInfoDrawR}); + clockInfoMenu3 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:R.x+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDraw}); + clockInfoMenu4 = require("clock_info").addInteractive(clockInfoItems, { app:"lcdclock", x:midX+1, y:lowerCI, w:midX-2, h:28, draw : clockInfoDrawR}); + } catch(err) { + if ((err + '').includes('Module "clock_info" not found' )) { + g.setFont('6x8').drawString('Please install\nclockinfo module!', R.x + 10, upperCI); + } + } }, 1); }); diff --git a/apps/supaclk/app.png b/apps/supaclk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..54f2047a58f4193aebeae3d8a83842d088ccb2d9 GIT binary patch literal 3964 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 WMWWKyoVMox00000J~ literal 0 HcmV?d00001 diff --git a/apps/supaclk/metadata.json b/apps/supaclk/metadata.json new file mode 100644 index 000000000..016182545 --- /dev/null +++ b/apps/supaclk/metadata.json @@ -0,0 +1,16 @@ +{ "id": "supaclk", + "name": "SUPACLOCK Pro ULTRA", + "version": "0.01", + "description": "SUPACLOCK Pro ULTRA, with four ClockInfo areas at the bottom. Tap them and swipe up/down and left/right to toggle between different information.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"},{"url":"screenshot2.png"}], + "type": "clock", + "tags": "clock,clkinfo,clockinfo", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "dependencies" : { "clock_info":"module" }, + "storage": [ + {"name":"supaclk.app.js","url":"app.js"}, + {"name":"supaclk.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/supaclk/screenshot.png b/apps/supaclk/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..54f2047a58f4193aebeae3d8a83842d088ccb2d9 GIT binary patch literal 3964 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 WMWWKyoVMox00000J~ literal 0 HcmV?d00001 diff --git a/apps/supaclk/screenshot2.png b/apps/supaclk/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..46d04a1661dc2d931a1d36801d052064a89858a2 GIT binary patch literal 4206 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 Ef>;jwKmY&$ literal 0 HcmV?d00001 From 249a119e12c06c5019173e70ef625be3ee51ce22 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 1 Jun 2024 13:41:35 +0200 Subject: [PATCH 17/19] supaclk: misc suggested fixes and changes - clear screen including widgets before drawing splash screen. - change from a font that's not defined to one that is. - make it so the splash screen can be cut short to load the launcher. --- apps/supaclk/app.js | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/apps/supaclk/app.js b/apps/supaclk/app.js index c6731849f..b9ac0ba5b 100644 --- a/apps/supaclk/app.js +++ b/apps/supaclk/app.js @@ -1,5 +1,6 @@ { // 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 + // we also define functions using 'let fn = function() {..}' for the same reason. function decls are globalj +let removeHasNotRun = true; let drawTimeout; const supaClockImg = { @@ -35,6 +36,7 @@ let drawSplashScreen = function (frame, total) { } // for fast startup-feeling, draw the splash screen once directly once +g.clear() drawSplashScreen(0, 20); let splashScreen = function () { @@ -42,9 +44,11 @@ let splashScreen = function () { return new Promise((resolve, reject) => { let frame = 0; function tick() { - drawSplashScreen(frame, 20); + if (removeHasNotRun) drawSplashScreen(frame, 20); frame += 1; - if (frame < 20) { + if (!removeHasNotRun) { + reject(); + } else if (frame < 20) { setTimeout(tick, 50); } else { resolve(); @@ -118,7 +122,7 @@ let clockInfoDraw = (itm, info, options) => { g.drawImage(info.img, options.x+1,options.y+2); } var text = info.text.toString().toUpperCase(); - if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("4x6:2"); g.setFontAlign(-1,-1).drawString(text, options.x+24+3, options.y+6); }; @@ -131,7 +135,7 @@ let clockInfoDrawR = (itm, info, options) => { g.drawImage(info.img, options.x + options.w-1-24,options.y+2); } var text = info.text.toString().toUpperCase(); - if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("8x12"); + if (g.setFontPlayfairDisplaySm().stringWidth(text)+24-2>options.w) g.setFont("4x6:2"); g.setFontAlign(1,-1).drawString(text, options.x+options.w-24-3, options.y+6); }; @@ -146,18 +150,19 @@ let clockInfoMenu4; Bangle.setUI({ mode : "clock", remove : function() { // for fastloading, clear the app memory + removeHasNotRun = false; if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; delete Graphics.prototype.setFontPlayfairDisplay delete Graphics.prototype.setFontPlayfairDisplaySm delete clockInfoItems; - clockInfoMenu1.remove(); + clockInfoMenu1&&clockInfoMenu1.remove(); delete clockInfoMenu1; - clockInfoMenu2.remove(); + clockInfoMenu2&&clockInfoMenu2.remove(); delete clockInfoMenu2; - clockInfoMenu3.remove(); + clockInfoMenu3&&clockInfoMenu3.remove(); delete clockInfoMenu3; - clockInfoMenu4.remove(); + clockInfoMenu4&&clockInfoMenu4.remove(); delete clockInfoMenu4; }}); @@ -190,6 +195,6 @@ splashScreen().then(() => { } } }, 1); -}); +},() => {}); } From 82a5ab5724116f903d4b4d28703f204d21876c99 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 1 Jun 2024 15:12:01 +0200 Subject: [PATCH 18/19] supaclk: remove unnecessary delete in remove funct since they are initiatied with let inside the outer curly braces they should be cleared automatically like all other let-ibles. --- apps/supaclk/app.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/apps/supaclk/app.js b/apps/supaclk/app.js index b9ac0ba5b..f0bf32ae5 100644 --- a/apps/supaclk/app.js +++ b/apps/supaclk/app.js @@ -155,15 +155,10 @@ Bangle.setUI({ drawTimeout = undefined; delete Graphics.prototype.setFontPlayfairDisplay delete Graphics.prototype.setFontPlayfairDisplaySm - delete clockInfoItems; clockInfoMenu1&&clockInfoMenu1.remove(); - delete clockInfoMenu1; clockInfoMenu2&&clockInfoMenu2.remove(); - delete clockInfoMenu2; clockInfoMenu3&&clockInfoMenu3.remove(); - delete clockInfoMenu3; clockInfoMenu4&&clockInfoMenu4.remove(); - delete clockInfoMenu4; }}); Bangle.loadWidgets(); From 93461e6c2ddd740bdb54a082e55f2e2d8ec4719c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 3 Jun 2024 14:17:12 +0100 Subject: [PATCH 19/19] bump recommended version --- loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader.js b/loader.js index 81e3433d4..a8d6d10eb 100644 --- a/loader.js +++ b/loader.js @@ -16,7 +16,7 @@ if (window.location.host=="banglejs.com") { 'This is not the official Bangle.js App Loader - you can try the Official Version here.'; } -var RECOMMENDED_VERSION = "2v21"; +var RECOMMENDED_VERSION = "2v22"; // could check http://www.espruino.com/json/BANGLEJS.json for this // We're only interested in Bangles