From 785ce647793568fd9d1ee038303a3e552235a801 Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Fri, 18 Mar 2022 18:35:44 -0400 Subject: [PATCH 01/94] Add disc golf score tracking app --- apps/discgolf/ChangeLog | 1 + apps/discgolf/README.md | 14 +++ apps/discgolf/app-icon.js | 1 + apps/discgolf/app.js | 171 +++++++++++++++++++++++++++++++ apps/discgolf/app.png | Bin 0 -> 10687 bytes apps/discgolf/metadata.json | 14 +++ apps/discgolf/summary_screen.png | Bin 0 -> 3025 bytes apps/discgolf/throw_screen.png | Bin 0 -> 2459 bytes 8 files changed, 201 insertions(+) create mode 100644 apps/discgolf/ChangeLog create mode 100644 apps/discgolf/README.md create mode 100644 apps/discgolf/app-icon.js create mode 100644 apps/discgolf/app.js create mode 100644 apps/discgolf/app.png create mode 100644 apps/discgolf/metadata.json create mode 100644 apps/discgolf/summary_screen.png create mode 100644 apps/discgolf/throw_screen.png diff --git a/apps/discgolf/ChangeLog b/apps/discgolf/ChangeLog new file mode 100644 index 000000000..220e1d1c2 --- /dev/null +++ b/apps/discgolf/ChangeLog @@ -0,0 +1 @@ +0.01: Initial version of disc golf app. Has throw and hole counter, along with summary screen. Uses buttons for holes & throws. \ No newline at end of file diff --git a/apps/discgolf/README.md b/apps/discgolf/README.md new file mode 100644 index 000000000..34a9dfe90 --- /dev/null +++ b/apps/discgolf/README.md @@ -0,0 +1,14 @@ +# Disc Golf + +Individual score tracking for disc golf on your wrist. + +![](throw_screen.png) +![](summary_screen.png) + +## Usage + +Press the side button once to increment throws. Double-tap the side button to increment holes. View your game summary with the button in the upper right of the screen. + +## Creator + +Made by [Noah Howard](https://github.com/nh-99) diff --git a/apps/discgolf/app-icon.js b/apps/discgolf/app-icon.js new file mode 100644 index 000000000..cfc07a2fa --- /dev/null +++ b/apps/discgolf/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+AH4A/ABFzudsAAImmABIppAAIQBFcYMBzwMDFbP+y5RJHYiHdLJYADG5AATzxaNFotszwuXFp5sFLq4tIVpANNF0D4FRqobFJ5peaFxKtJXgi9VzxdSLwwvUFyYvaFxIhKOYwvSFxoAEzyjJF7I/VFyzRjU5QICuYiNBxBJTQp7lFF7byQGQYwSOwovSOpJsFdpwvTao4voMQ4vQOQQwmX4oQCBAwwgCxAvWDIwvPGD4vIy4WJSSzcFMCCpGMC+eGChiUYJwjJPIRiTF5xULBxwvVEJgQQCIQOEF5X+zwfLSoY0HBYg9FF5a2QDSQvNWqJbBAQTaOMTY9PF6DFNAB4uRGLguUYygucfKwubGQgzLFsAAHFYV6Fc4A/AAw=")) \ No newline at end of file diff --git a/apps/discgolf/app.js b/apps/discgolf/app.js new file mode 100644 index 000000000..68bbd817d --- /dev/null +++ b/apps/discgolf/app.js @@ -0,0 +1,171 @@ +Bangle.loadWidgets(); + +// +// App imports +// +var Layout = require("Layout"); + +// +// App variables +// +var holeCount = 1; +var throwCount = 0; +var drawTimeout; +var currentScreen = 'throw'; +var redraw = true; +var update = true; +var holeSummary = { + "< Back" : () => { update = true; redraw = true; currentScreen = 'throw'; E.showMenu(); createThrowLayout(); }, + "Hole #1": { value: 0 }, + "Hole #2": { value: 0 }, + "Hole #3": { value: 0 }, + "Hole #4": { value: 0 }, + "Hole #5": { value: 0 }, + "Hole #6": { value: 0 }, + "Hole #7": { value: 0 }, + "Hole #8": { value: 0 }, + "Hole #9": { value: 0 }, + "Front": { value: 0 }, + "Hole #10": { value: 0 }, + "Hole #11": { value: 0 }, + "Hole #12": { value: 0 }, + "Hole #13": { value: 0 }, + "Hole #14": { value: 0 }, + "Hole #15": { value: 0 }, + "Hole #16": { value: 0 }, + "Hole #17": { value: 0 }, + "Hole #18": { value: 0 }, + "Back": { value: 0 }, +}; + +// Images +function getBackImage() { + return atob("FhYBAAAAEAAAwAAHAAA//wH//wf//g///BwB+DAB4EAHwAAPAAA8AADwAAPAAB4AAHgAB+AH/wA/+AD/wAH8AA=="); +} +function getMenuImage() { + return { + width : 20, height : 20, bpp : 1, + buffer : require("heatshrink").decompress(atob("AAk///D//8CBcDBwITB4AiVA")) + }; +} +function getBasketIcon() { + return { + width : 20, height : 20, bpp : 1, + buffer : require("heatshrink").decompress(atob("gFggF/8EH/0AiWAgtogEW0EDt0Am3ggfsgEf4EB/EA//4j//wEChEP/8AgwnDAgw")) + }; +} +function getFrisbeeIcon() { + return { + width : 20, height : 20, bpp : 1, + buffer : require("heatshrink").decompress(atob("AAf+gF/wE+uEPx0B+PAn0cgf/4F3/0G/1g9/7g1/7AJB4+f/k+v3B/Hcg4WBj/4E4ItC")) + }; +} + +var throwLayout; + +function createThrowLayout() { + throwLayout = new Layout( { + type:"v", c: [ + // Title & menu button + { + type:"h", fillx:1, valign:-1, bgCol:g.theme.bg2, col: g.theme.fg2, c: [ + {type:"img", src:getBasketIcon()}, + {type:"txt", pad:4, font:"15%", label:holeCount, id: "holeCount"}, + {type:"txt", pad:4, font:"15%", label: '', fillx:1}, + {type:"btn", src:getMenuImage(), halign:1, cb: l=>{ currentScreen = 'summary'; update = true; redraw = true; }} + ] + }, + // Throw count + { + type:"h", filly:1, c: [ + {type:"img", pad:4, src:getFrisbeeIcon() }, + {type:"txt", fillx:1, font:"6x8:2", label:"Throws: "+throwCount, id:"throwCount"} + ] + } + ] + }, {lazy:true}); +} + +function incrementHole() { + if (holeCount > 18) return; + resetThrow(); + holeCount += 1; + holeSummary["Hole #" + holeCount] = {value: 0}; +} +function incrementThrow() { + throwCount += 1; + holeSummary["Hole #" + holeCount] = {value: throwCount}; +} +function decrementThrow() { + throwCount -= 1; + holeSummary["Hole #" + holeCount] = {value: throwCount}; +} +function resetThrow() { + throwCount = 0; +} +function computeFrontScore() { + var scoreSum = 0; + for (var i = 1; i < 10; i++) { + scoreSum += holeSummary["Hole #" + i].value; + } + holeSummary.Front = {value: scoreSum}; +} +function computeBackScore() { + var scoreSum = 0; + for (var i = 1; i < 19; i++) { + scoreSum += holeSummary["Hole #" + i].value; + } + holeSummary.Back = {value: scoreSum}; +} + +// update the app state/variables +function updateApp() { + throwLayout.holeCount.label = holeCount; + throwLayout.throwCount.label = "Throws: " + throwCount; +} + +// update the screen +function draw() { + updateApp(); + if (redraw) { + throwLayout.forgetLazyState(); + redraw = false; + } + if (update) { + if (currentScreen == 'throw') { + throwLayout.render(); + } else if (currentScreen == 'summary') { + E.showMenu(holeSummary); + } + update = false; + } + // schedule a draw for the next 500ms + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 500 - (Date.now() % 500)); +} + +// +// button press events +// +setWatch((p) => { + if (p.time - p.lastTime < 0.2) { + decrementThrow(); + incrementHole(); + } else { + incrementThrow(); + } + computeFrontScore(); + computeBackScore(); + update = true; +}, BTN, {edge:"rising", debounce:50, repeat:true}); + +// +// main app function start +// +g.clear(); +Bangle.drawWidgets(); +createThrowLayout(); +draw(); \ No newline at end of file diff --git a/apps/discgolf/app.png b/apps/discgolf/app.png new file mode 100644 index 0000000000000000000000000000000000000000..6aba5e54816571474aae74f0db98b39a7db7933a GIT binary patch literal 10687 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 literal 0 HcmV?d00001 diff --git a/apps/discgolf/metadata.json b/apps/discgolf/metadata.json new file mode 100644 index 000000000..6d56f05e4 --- /dev/null +++ b/apps/discgolf/metadata.json @@ -0,0 +1,14 @@ +{ "id": "discgolf", + "name": "Disc Golf", + "shortName":"Disc Golf", + "version":"0.01", + "description": "A personal disc golf score tracker", + "icon": "app.png", + "tags": "", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"discgolf.app.js","url":"app.js"}, + {"name":"discgolf.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/discgolf/summary_screen.png b/apps/discgolf/summary_screen.png new file mode 100644 index 0000000000000000000000000000000000000000..480d36eddfa8646b874e96458520979ac2de4ad6 GIT binary patch literal 3025 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 literal 0 HcmV?d00001 From 123d4814696eafc50062b774a62b7fdc90b80518 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 12:22:04 -0500 Subject: [PATCH 02/94] Running setScan with active: true --- apps/bthrm/settings.js | 2 +- apps/health/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bthrm/settings.js b/apps/bthrm/settings.js index 4b564d670..9f409880a 100644 --- a/apps/bthrm/settings.js +++ b/apps/bthrm/settings.js @@ -127,7 +127,7 @@ }); }; } - }, { filters: [{services: [ "180d" ]}]}); + }, { active: true, filters: [{services: [ "180d" ]}]}); } diff --git a/apps/health/README.md b/apps/health/README.md index f44854e3e..e3a84068b 100644 --- a/apps/health/README.md +++ b/apps/health/README.md @@ -2,7 +2,7 @@ Logs health data to a file every 10 minutes, and provides an app to view it -**BETA - requires firmware 2v11** +**BETA - requires firmware 2v11 or later** ## Usage From d27deac8aadfa6f9393e31aa26c4c69bb4f39dd2 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 14:47:17 -0500 Subject: [PATCH 03/94] Adding 'active: true' to NRF.requestDevice call made when btname is set --- apps/bthrm/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 3a1f1cc4c..93e72b83b 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -370,7 +370,7 @@ filters = [{name: settings.btname}]; } log("Requesting device with filters", filters); - promise = NRF.requestDevice({ filters: filters }); + promise = NRF.requestDevice({ filters: filters, active: true }); if (settings.gracePeriodRequest){ log("Add " + settings.gracePeriodRequest + "ms grace period after request"); From d89db8f7d7f680c11aa73780c50483364972059b Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 15:55:14 -0500 Subject: [PATCH 04/94] Removing call to function that doesn't exist --- apps/bthrm/boot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 93e72b83b..227f78c1a 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -108,7 +108,7 @@ var sensorContact; if (flags & 2){ - sensorContact = (flags & 4) ? true : false; + sensorContact = !!(flags & 4); } var idx = 2 + (flags&1); @@ -297,7 +297,7 @@ }); } else if (newCharacteristic.read){ result = result.then(()=>{ - readData(newCharacteristic); + // readData(newCharacteristic); log("Reading data for " + newCharacteristic); return newCharacteristic.read().then((data)=>{ supportedCharacteristics[newCharacteristic.uuid].handler(data); From 75c4e5b54b54181c054bbb2a68603435f02761cf Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 16:48:15 -0500 Subject: [PATCH 05/94] bthrm fixes for reading characteristics generally and displaying location --- apps/bthrm/boot.js | 17 +++++++++-------- apps/bthrm/bthrm.js | 13 +++++++++++-- typescript/types/globals.d.ts | 6 +++--- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 227f78c1a..dd25634e5 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -168,14 +168,14 @@ //Body sensor location handler: function(data){ if (!lastReceivedData["0x180d"]) lastReceivedData["0x180d"] = {}; - if (!lastReceivedData["0x180d"]["0x2a38"]) lastReceivedData["0x180d"]["0x2a38"] = data.target.value; + lastReceivedData["0x180d"]["0x2a38"] = parseInt(data.buffer, 10); } }, "0x2a19": { //Battery handler: function (event){ - if (!lastReceivedData["0x180f"]) lastReceivedData["0x180f"] = {}; - if (!lastReceivedData["0x180f"]["0x2a19"]) lastReceivedData["0x180f"]["0x2a19"] = event.target.value.getUint8(0); + if (!lastReceivedData["0x180f"]) lastReceivedData["0x180f"] = { "0x2a19": null }; + lastReceivedData["0x180f"]["0x2a19"] = event.target.value.getUint8(0); } } @@ -295,12 +295,13 @@ } return startPromise; }); - } else if (newCharacteristic.read){ + } else if (newCharacteristic.readValue){ result = result.then(()=>{ - // readData(newCharacteristic); - log("Reading data for " + newCharacteristic); - return newCharacteristic.read().then((data)=>{ - supportedCharacteristics[newCharacteristic.uuid].handler(data); + log("Reading data for " + JSON.stringify(newCharacteristic)); + return newCharacteristic.readValue().then((data)=>{ + if (supportedCharacteristics[newCharacteristic.uuid] && supportedCharacteristics[newCharacteristic.uuid].handler) { + supportedCharacteristics[newCharacteristic.uuid].handler(data); + } }); }); } diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index cc533eedd..5ab3b0018 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -1,7 +1,16 @@ -var btm = g.getHeight()-1; var intervalInt; var intervalBt; +var BODY_LOCS = { + 0: 'Other', + 1: 'Chest', + 2: 'Wrist', + 3: 'Finger', + 4: 'Hand', + 5: 'Ear Lobe', + 6: 'Foot', +} + function clear(y){ g.reset(); g.clearRect(0,y,g.getWidth(),y+75); @@ -25,7 +34,7 @@ function draw(y, type, event) { if (event.battery) str += " Bat: " + (event.battery ? event.battery : ""); g.setFontVector(12).drawString(str,px,y+40); str= ""; - if (event.location) str += "Loc: " + event.location.toFixed(0) + "ms"; + if (event.location) str += "Loc: " + BODY_LOCS[event.location]; if (event.rr && event.rr.length > 0) str += " RR: " + event.rr.join(","); g.setFontVector(12).drawString(str,px,y+50); str= ""; diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 2ef52dcdf..442140e70 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -158,9 +158,9 @@ declare type Image = { }; declare type GraphicsApi = { - reset: () => void; + reset: () => GraphicsApi; flip: () => void; - setColor: (color: string) => void; // TODO we can most likely type color more usefully than this + setColor: (color: string) => GraphicsApi; // TODO we can most likely type color more usefully than this drawImage: ( image: string | Image | ArrayBuffer, xOffset: number, @@ -169,7 +169,7 @@ declare type GraphicsApi = { rotate?: number; scale?: number; } - ) => void; + ) => GraphicsApi; // TODO add more }; From d19a68e5117904689b9a35706fceeb64f3bd04fc Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 17:29:20 -0500 Subject: [PATCH 06/94] Fix how events and reads were handled differently --- apps/bthrm/boot.js | 55 +++++++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index dd25634e5..0a6af55b6 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -31,7 +31,7 @@ function addNotificationHandler(characteristic){ log("Setting notification handler: " + supportedCharacteristics[characteristic.uuid].handler); - characteristic.on('characteristicvaluechanged', supportedCharacteristics[characteristic.uuid].handler); + characteristic.on('characteristicvaluechanged', (ev) => supportedCharacteristics[characteristic.uuid].handler(ev.target.value)); } function writeCache(cache){ @@ -92,15 +92,14 @@ services: [ "180d" ] }]; - supportedServices = [ + var supportedServices = [ "0x180d", "0x180f" ]; var supportedCharacteristics = { "0x2a37": { //Heart rate measurement - handler: function (event){ - var dv = event.target.value; + handler: function (dv){ var flags = dv.getUint8(0); var bpm = (flags & 1) ? (dv.getUint16(1) / 100 /* ? */ ) : dv.getUint8(1); // 8 or 16 bit @@ -121,7 +120,7 @@ var interval; if (flags & 16) { interval = []; - maxIntervalBytes = (dv.byteLength - idx); + var maxIntervalBytes = (dv.byteLength - idx); log("Found " + (maxIntervalBytes / 2) + " rr data fields"); for(var i = 0 ; i < maxIntervalBytes / 2; i++){ interval[i] = dv.getUint16(idx,1); // in milliseconds @@ -140,14 +139,14 @@ } if (settings.replace){ - var newEvent = { + var repEvent = { bpm: bpm, confidence: (sensorContact || sensorContact === undefined)? 100 : 0, src: "bthrm" }; - log("Emitting HRM: ", newEvent); - Bangle.emit("HRM", newEvent); + log("Emitting HRM: ", repEvent); + Bangle.emit("HRM", repEvent); } var newEvent = { @@ -159,23 +158,23 @@ if (energyExpended) newEvent.energy = energyExpended; if (battery) newEvent.battery = battery; if (sensorContact) newEvent.contact = sensorContact; - + log("Emitting BTHRM: ", newEvent); Bangle.emit("BTHRM", newEvent); } }, "0x2a38": { //Body sensor location - handler: function(data){ + handler: function(dv){ if (!lastReceivedData["0x180d"]) lastReceivedData["0x180d"] = {}; - lastReceivedData["0x180d"]["0x2a38"] = parseInt(data.buffer, 10); + lastReceivedData["0x180d"]["0x2a38"] = parseInt(dv.buffer, 10); } }, "0x2a19": { //Battery - handler: function (event){ - if (!lastReceivedData["0x180f"]) lastReceivedData["0x180f"] = { "0x2a19": null }; - lastReceivedData["0x180f"]["0x2a19"] = event.target.value.getUint8(0); + handler: function (dv){ + if (!lastReceivedData["0x180f"]) lastReceivedData["0x180f"] = {}; + lastReceivedData["0x180f"]["0x2a19"] = dv.getUint8(0); } } @@ -282,6 +281,18 @@ function createCharacteristicPromise(newCharacteristic){ log("Create characteristic promise: ", newCharacteristic); var result = Promise.resolve(); + // For values that can be read, go ahead and read them, even if we might be notified in the future + // Allows for getting initial state of infrequently updating characteristics, like battery + if (newCharacteristic.readValue){ + result = result.then(()=>{ + log("Reading data for " + JSON.stringify(newCharacteristic)); + return newCharacteristic.readValue().then((data)=>{ + if (supportedCharacteristics[newCharacteristic.uuid] && supportedCharacteristics[newCharacteristic.uuid].handler) { + supportedCharacteristics[newCharacteristic.uuid].handler(data); + } + }); + }); + } if (newCharacteristic.properties.notify){ result = result.then(()=>{ log("Starting notifications for: ", newCharacteristic); @@ -295,15 +306,6 @@ } return startPromise; }); - } else if (newCharacteristic.readValue){ - result = result.then(()=>{ - log("Reading data for " + JSON.stringify(newCharacteristic)); - return newCharacteristic.readValue().then((data)=>{ - if (supportedCharacteristics[newCharacteristic.uuid] && supportedCharacteristics[newCharacteristic.uuid].handler) { - supportedCharacteristics[newCharacteristic.uuid].handler(data); - } - }); - }); } return result.then(()=>log("Handled characteristic: ", newCharacteristic)); } @@ -526,10 +528,9 @@ } }; } - - + var fallbackInterval; - + function switchInternalHrm(){ if (settings.allowFallback && !fallbackInterval){ log("Fallback to HRM enabled"); @@ -558,7 +559,7 @@ } switchInternalHrm(); } - + E.on("kill", ()=>{ if (gatt && gatt.connected){ log("Got killed, trying to disconnect"); From d9908ee6a2a77eab3b6371ade461a1ea449eec87 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 5 Apr 2022 09:53:52 -0500 Subject: [PATCH 07/94] Switch from setScan to findDevices --- apps/bthrm/boot.js | 8 +-- apps/bthrm/settings.js | 110 +++++++++++++---------------------------- 2 files changed, 38 insertions(+), 80 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 0a6af55b6..ad3c85591 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -24,7 +24,7 @@ function getCache(){ var cache = require('Storage').readJSON("bthrm.cache.json", true) || {}; - if (settings.btname && settings.btname == cache.name) return cache; + if (settings.btid && settings.btid == cache.id) return cache; clearCache(); return {}; } @@ -368,9 +368,9 @@ if (!device){ var filters = serviceFilters; - if (settings.btname){ - log("Configured device name", settings.btname); - filters = [{name: settings.btname}]; + if (settings.btid){ + log("Configured device id", settings.btid); + filters = [{id: settings.btid }]; } log("Requesting device with filters", filters); promise = NRF.requestDevice({ filters: filters, active: true }); diff --git a/apps/bthrm/settings.js b/apps/bthrm/settings.js index 9f409880a..b376d6a2d 100644 --- a/apps/bthrm/settings.js +++ b/apps/bthrm/settings.js @@ -5,14 +5,14 @@ require('Storage').writeJSON(FILE, s); readSettings(); } - + function readSettings(){ settings = Object.assign( require('Storage').readJSON("bthrm.default.json", true) || {}, require('Storage').readJSON(FILE, true) || {} ); } - + var FILE="bthrm.json"; var settings; readSettings(); @@ -61,12 +61,13 @@ } }; - if (settings.btname){ - var name = "Clear " + settings.btname; + if (settings.btname || settings.btid){ + var name = "Clear " + (settings.btname || settings.btid); mainmenu[name] = function() { - E.showPrompt("Clear current device name?").then((r)=>{ + E.showPrompt("Clear current device?").then((r)=>{ if (r) { writeSettings("btname",undefined); + writeSettings("btid",undefined); } E.showMenu(buildMainMenu()); }); @@ -78,9 +79,7 @@ mainmenu.Debug = function() { E.showMenu(submenu_debug); }; return mainmenu; } - - var submenu_debug = { '' : { title: "Debug"}, '< Back': function() { E.showMenu(buildMainMenu()); }, @@ -103,35 +102,39 @@ function createMenuFromScan(){ E.showMenu(); - E.showMessage("Scanning"); + E.showMessage("Scanning for 4 seconds"); var submenu_scan = { - '' : { title: "Scan"}, '< Back': function() { E.showMenu(buildMainMenu()); } }; - var packets=10; - var scanStart=Date.now(); - NRF.setScan(function(d) { - packets--; - if (packets<=0 || Date.now() - scanStart > 5000){ - NRF.setScan(); - E.showMenu(submenu_scan); - } else if (d.name){ - print("Found device", d); - submenu_scan[d.name] = function(){ - E.showPrompt("Set "+d.name+"?").then((r)=>{ - if (r) { - writeSettings("btname",d.name); - } - E.showMenu(buildMainMenu()); + NRF.findDevices(function(devices) { + submenu_scan[''] = { title: `Scan (${devices.length} found)`}; + if (devices.length === 0) { + E.showAlert("No devices found") + .then(() => E.showMenu(buildMainMenu())); + return; + } else { + devices.forEach((d) => { + print("Found device", d); + var shown = (d.name || d.id.substr(0, 17)); + submenu_scan[shown] = function () { + E.showPrompt("Set " + shown + "?").then((r) => { + if (r) { + writeSettings("btid", d.id); + // Store the name for displaying later. Will connect by ID + if (d.name) { + writeSettings("btname", d.name); + } + } + E.showMenu(buildMainMenu()); + }); + }; }); - }; } - }, { active: true, filters: [{services: [ "180d" ]}]}); + E.showMenu(submenu_scan); + }, { timeout: 4000, active: true, filters: [{services: [ "180d" ]}]}); } - - var submenu_custom = { '' : { title: "Custom mode"}, '< Back': function() { E.showMenu(buildMainMenu()); }, @@ -167,7 +170,7 @@ } }, }; - + var submenu_grace = { '' : { title: "Grace periods"}, '< Back': function() { E.showMenu(submenu_debug); }, @@ -212,51 +215,6 @@ } } }; - - var submenu = { - '' : { title: "Grace periods"}, - '< Back': function() { E.showMenu(buildMainMenu()); }, - 'Request': { - value: settings.gracePeriodRequest, - min: 0, - max: 3000, - step: 100, - format: v=>v+"ms", - onchange: v => { - writeSettings("gracePeriodRequest",v); - } - }, - 'Connect': { - value: settings.gracePeriodConnect, - min: 0, - max: 3000, - step: 100, - format: v=>v+"ms", - onchange: v => { - writeSettings("gracePeriodConnect",v); - } - }, - 'Notification': { - value: settings.gracePeriodNotification, - min: 0, - max: 3000, - step: 100, - format: v=>v+"ms", - onchange: v => { - writeSettings("gracePeriodNotification",v); - } - }, - 'Service': { - value: settings.gracePeriodService, - min: 0, - max: 3000, - step: 100, - format: v=>v+"ms", - onchange: v => { - writeSettings("gracePeriodService",v); - } - } - }; - + E.showMenu(buildMainMenu()); -}) +}); From 88a785df7f7d0e05023fbcd69b7ae71e85a6fb8b Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 5 Apr 2022 20:58:33 -0500 Subject: [PATCH 08/94] Update some types --- typescript/types/globals.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 442140e70..7af19700b 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -140,7 +140,7 @@ declare const require: ((module: 'heatshrink') => { declare const Bangle: { // functions - buzz: () => void; + buzz: (duration: number, intensity: number) => Promise; drawWidgets: () => void; isCharging: () => boolean; // events From 908a41d5237f2b6e30eca2c2bfd00954dd329051 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 5 Apr 2022 20:58:47 -0500 Subject: [PATCH 09/94] Try to bond --- apps/bthrm/boot.js | 79 ++++++++++++++++++++++++--------------------- apps/bthrm/bthrm.js | 6 ++-- 2 files changed, 46 insertions(+), 39 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index ad3c85591..8e18b3e34 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -3,7 +3,7 @@ require('Storage').readJSON("bthrm.default.json", true) || {}, require('Storage').readJSON("bthrm.json", true) || {} ); - + var log = function(text, param){ if (settings.debuglog){ var logline = new Date().toISOString() + " - " + text; @@ -13,9 +13,9 @@ print(logline); } }; - + log("Settings: ", settings); - + if (settings.enabled){ function clearCache(){ @@ -24,25 +24,24 @@ function getCache(){ var cache = require('Storage').readJSON("bthrm.cache.json", true) || {}; - if (settings.btid && settings.btid == cache.id) return cache; + if (settings.btid && settings.btid === cache.id) return cache; clearCache(); return {}; } - + function addNotificationHandler(characteristic){ log("Setting notification handler: " + supportedCharacteristics[characteristic.uuid].handler); characteristic.on('characteristicvaluechanged', (ev) => supportedCharacteristics[characteristic.uuid].handler(ev.target.value)); } - + function writeCache(cache){ var oldCache = getCache(); - if (oldCache != cache) { + if (oldCache !== cache) { log("Writing cache"); require('Storage').writeJSON("bthrm.cache.json", cache) } else { log("No changes, don't write cache"); } - } function characteristicsToCache(characteristics){ @@ -177,7 +176,6 @@ lastReceivedData["0x180f"]["0x2a19"] = dv.getUint8(0); } } - }; var device; @@ -185,7 +183,7 @@ var characteristics = []; var blockInit = false; var currentRetryTimeout; - var initialRetryTime = 40; + var initialRetryTime = 1000; var maxRetryTime = 60000; var retryTime = initialRetryTime; @@ -214,7 +212,6 @@ }; } - if (settings.replace){ var origIsHRMOn = Bangle.isHRMOn; @@ -309,14 +306,14 @@ } return result.then(()=>log("Handled characteristic: ", newCharacteristic)); } - + function attachCharacteristicPromise(promise, characteristic){ return promise.then(()=>{ log("Handling characteristic:", characteristic); return createCharacteristicPromise(characteristic); }); } - + function createCharacteristicsPromise(newCharacteristics){ log("Create characteristics promise: ", newCharacteristics); var result = Promise.resolve(); @@ -327,12 +324,12 @@ if (c.properties.notify){ addNotificationHandler(c); } - + result = attachCharacteristicPromise(result, c); } return result.then(()=>log("Handled characteristics")); } - + function createServicePromise(service){ log("Create service promise: ", service); var result = Promise.resolve(); @@ -342,11 +339,11 @@ }); return result.then(()=>log("Handled service" + service.uuid)); } - + function attachServicePromise(promise, service){ return promise.then(()=>createServicePromise(service)); } - + var reUseCounter = 0; function initBt() { @@ -363,9 +360,9 @@ gatt=undefined; reUseCounter = 0; } - + var promise; - + if (!device){ var filters = serviceFilters; if (settings.btid){ @@ -374,27 +371,26 @@ } log("Requesting device with filters", filters); promise = NRF.requestDevice({ filters: filters, active: true }); - + if (settings.gracePeriodRequest){ log("Add " + settings.gracePeriodRequest + "ms grace period after request"); } - + promise = promise.then((d)=>{ log("Got device: ", d); d.on('gattserverdisconnected', onDisconnect); device = d; }); - + promise = promise.then(()=>{ log("Wait after request"); return waitingPromise(settings.gracePeriodRequest); }); - } else { promise = Promise.resolve(); log("Reuse device: ", device); } - + promise = promise.then(()=>{ if (gatt){ log("Reuse GATT: ", gatt); @@ -402,7 +398,7 @@ log("GATT is new: ", gatt); characteristics = []; var cachedName = getCache().name; - if (device.name != cachedName){ + if (device.name !== cachedName){ log("Device name changed from " + cachedName + " to " + device.name + ", clearing cache"); clearCache(); } @@ -411,10 +407,10 @@ writeCache(newCache); gatt = device.gatt; } - + return Promise.resolve(gatt); }); - + promise = promise.then((gatt)=>{ if (!gatt.connected){ var connectPromise = gatt.connect(connectSettings); @@ -430,16 +426,28 @@ return Promise.resolve(); } }); - + + promise = promise.then(() => { + log(JSON.stringify(gatt.getSecurityStatus())); + if (gatt.getSecurityStatus()['bonded']) { + log("Already bonded"); + return Promise.resolve(); + } else { + log("Start bonding"); + return gatt.startBonding() + .then(() => console.log(gatt.getSecurityStatus())); + } + }); + promise = promise.then(()=>{ - if (!characteristics || characteristics.length == 0){ + if (!characteristics || characteristics.length === 0){ characteristics = characteristicsFromCache(); } }); promise = promise.then(()=>{ var characteristicsPromise = Promise.resolve(); - if (characteristics.length == 0){ + if (characteristics.length === 0){ characteristicsPromise = characteristicsPromise.then(()=>{ log("Getting services"); return gatt.getPrimaryServices(); @@ -462,17 +470,16 @@ } return result; }); - } else { for (var characteristic of characteristics){ characteristicsPromise = attachCharacteristicPromise(characteristicsPromise, characteristic, true); } } - + return characteristicsPromise; }); - promise = promise.then(()=>{ + return promise.then(()=>{ log("Connection established, waiting for notifications"); reUseCounter = 0; characteristicsToCache(characteristics); @@ -490,7 +497,7 @@ if (Bangle._PWR===undefined) Bangle._PWR={}; if (Bangle._PWR.BTHRM===undefined) Bangle._PWR.BTHRM=[]; if (isOn && !Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM.push(app); - if (!isOn && Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM = Bangle._PWR.BTHRM.filter(a=>a!=app); + if (!isOn && Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM = Bangle._PWR.BTHRM.filter(a=>a!==app); isOn = Bangle._PWR.BTHRM.length; // so now we know if we're really on if (isOn) { @@ -513,7 +520,7 @@ } } }; - + var origSetHRMPower = Bangle.setHRMPower; if (settings.startWithHrm){ @@ -563,7 +570,7 @@ E.on("kill", ()=>{ if (gatt && gatt.connected){ log("Got killed, trying to disconnect"); - var promise = gatt.disconnect().then(()=>log("Disconnected on kill")).catch((e)=>log("Error during disconnnect on kill", e)); + gatt.disconnect().then(()=>log("Disconnected on kill")).catch((e)=>log("Error during disconnnect on kill", e)); } }); } diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 5ab3b0018..dd9230386 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -24,13 +24,13 @@ function draw(y, type, event) { g.setFontAlign(0,0); g.setFontVector(40).drawString(str,px,y+20); str = "Event: " + type; - if (type == "HRM") { + if (type === "HRM") { str += " Confidence: " + event.confidence; g.setFontVector(12).drawString(str,px,y+40); str = " Source: " + (event.src ? event.src : "internal"); g.setFontVector(12).drawString(str,px,y+50); } - if (type == "BTHRM"){ + if (type === "BTHRM"){ if (event.battery) str += " Bat: " + (event.battery ? event.battery : ""); g.setFontVector(12).drawString(str,px,y+40); str= ""; @@ -54,7 +54,7 @@ function onBtHrm(e) { firstEventBt = false; } draw(100, "BTHRM", e); - if (e.bpm == 0){ + if (e.bpm === 0){ Bangle.buzz(100,0.2); } if (intervalBt){ From 31fd2344a8ffb7e9ec9bf97635a155e8f75bf429 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 5 Apr 2022 21:05:03 -0500 Subject: [PATCH 10/94] Fix for buzz type updated in previous commit --- typescript/types/globals.d.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/typescript/types/globals.d.ts b/typescript/types/globals.d.ts index 7af19700b..e82c3da3d 100644 --- a/typescript/types/globals.d.ts +++ b/typescript/types/globals.d.ts @@ -140,7 +140,7 @@ declare const require: ((module: 'heatshrink') => { declare const Bangle: { // functions - buzz: (duration: number, intensity: number) => Promise; + buzz: (duration?: number, intensity?: number) => Promise; drawWidgets: () => void; isCharging: () => boolean; // events From 9eb4d8eb73684eca9ee4d0eadc8aec94bf467d6c Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Thu, 7 Apr 2022 15:58:39 -0500 Subject: [PATCH 11/94] Remove bonding for now --- apps/bthrm/boot.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 8e18b3e34..f9de2ee5d 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -427,7 +427,7 @@ } }); - promise = promise.then(() => { +/* promise = promise.then(() => { log(JSON.stringify(gatt.getSecurityStatus())); if (gatt.getSecurityStatus()['bonded']) { log("Already bonded"); @@ -437,7 +437,7 @@ return gatt.startBonding() .then(() => console.log(gatt.getSecurityStatus())); } - }); + });*/ promise = promise.then(()=>{ if (!characteristics || characteristics.length === 0){ From 7eeeca52ca25b2c633aed8a99c7fa12701e6d69c Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Thu, 7 Apr 2022 22:04:47 -0500 Subject: [PATCH 12/94] Update README and follow linting instructions --- apps/bthrm/README.md | 13 ++-- apps/bthrm/boot.js | 124 ++++++++++++++++++--------------------- apps/bthrm/metadata.json | 2 +- 3 files changed, 66 insertions(+), 73 deletions(-) diff --git a/apps/bthrm/README.md b/apps/bthrm/README.md index 42ad619bd..8d5872670 100644 --- a/apps/bthrm/README.md +++ b/apps/bthrm/README.md @@ -2,7 +2,7 @@ When this app is installed it overrides Bangle.js's build in heart rate monitor with an external Bluetooth one. -HRM is requested it searches on Bluetooth for a heart rate monitor, connects, and sends data back using the `Bangle.on('HRM'` event as if it came from the on board monitor. +HRM is requested it searches on Bluetooth for a heart rate monitor, connects, and sends data back using the `Bangle.on('HRM')` event as if it came from the on board monitor. This means it's compatible with many Bangle.js apps including: @@ -16,19 +16,23 @@ as that requires live sensor data (rather than just BPM readings). Just install the app, then install an app that uses the heart rate monitor. -Once installed it'll automatically try and connect to the first bluetooth -heart rate monitor it finds. +Once installed you will have to go into this app's settings while your heart rate monitor + is available for bluetooth pairing and scan for devices. **To disable this and return to normal HRM, uninstall the app** ## Compatible Heart Rate Monitors This works with any heart rate monitor providing the standard Bluetooth -Heart Rate Service (`180D`) and characteristic (`2A37`). +Heart Rate Service (`180D`) and characteristic (`2A37`). It additionally supports +the location (`2A38`) characteristic and the Battery Service (`180F`), reporting +that information in the `BTHRM` event when they are available. So far it has been tested on: * CooSpo Bluetooth Heart Rate Monitor +* Polar H10 +* Polar OH1 * Wahoo TICKR X 2 ## Internals @@ -38,7 +42,6 @@ This replaces `Bangle.setHRMPower` with its own implementation. ## TODO * A widget to show connection state? -* Specify a specific device by address? ## Creator diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index f9de2ee5d..064f65eac 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -18,33 +18,33 @@ if (settings.enabled){ - function clearCache(){ + var clearCache = function() { return require('Storage').erase("bthrm.cache.json"); - } + }; - function getCache(){ + var getCache = function() { var cache = require('Storage').readJSON("bthrm.cache.json", true) || {}; if (settings.btid && settings.btid === cache.id) return cache; clearCache(); return {}; - } + }; - function addNotificationHandler(characteristic){ + var addNotificationHandler = function(characteristic) { log("Setting notification handler: " + supportedCharacteristics[characteristic.uuid].handler); characteristic.on('characteristicvaluechanged', (ev) => supportedCharacteristics[characteristic.uuid].handler(ev.target.value)); - } + }; - function writeCache(cache){ + var writeCache = function(cache) { var oldCache = getCache(); if (oldCache !== cache) { log("Writing cache"); - require('Storage').writeJSON("bthrm.cache.json", cache) + require('Storage').writeJSON("bthrm.cache.json", cache); } else { log("No changes, don't write cache"); } - } + }; - function characteristicsToCache(characteristics){ + var characteristicsToCache = function(characteristics) { log("Cache characteristics"); var cache = getCache(); if (!cache.characteristics) cache.characteristics = {}; @@ -59,9 +59,9 @@ }; } writeCache(cache); - } + }; - function characteristicsFromCache(){ + var characteristicsFromCache = function() { log("Read cached characteristics"); var cache = getCache(); if (!cache.characteristics) return []; @@ -80,19 +80,16 @@ restored.push(r); } return restored; - } + }; log("Start"); var lastReceivedData={ }; - var serviceFilters = [{ - services: [ "180d" ] - }]; - var supportedServices = [ - "0x180d", "0x180f" + "0x180d", // Heart Rate + "0x180f", // Battery ]; var supportedCharacteristics = { @@ -100,17 +97,17 @@ //Heart rate measurement handler: function (dv){ var flags = dv.getUint8(0); - + var bpm = (flags & 1) ? (dv.getUint16(1) / 100 /* ? */ ) : dv.getUint8(1); // 8 or 16 bit - + var sensorContact; - + if (flags & 2){ sensorContact = !!(flags & 4); } - + var idx = 2 + (flags&1); - + var energyExpended; if (flags & 8){ energyExpended = dv.getUint16(idx,1); @@ -123,7 +120,7 @@ log("Found " + (maxIntervalBytes / 2) + " rr data fields"); for(var i = 0 ; i < maxIntervalBytes / 2; i++){ interval[i] = dv.getUint16(idx,1); // in milliseconds - idx += 2 + idx += 2; } } @@ -143,7 +140,7 @@ confidence: (sensorContact || sensorContact === undefined)? 100 : 0, src: "bthrm" }; - + log("Emitting HRM: ", repEvent); Bangle.emit("HRM", repEvent); } @@ -151,7 +148,7 @@ var newEvent = { bpm: bpm }; - + if (location) newEvent.location = location; if (interval) newEvent.rr = interval; if (energyExpended) newEvent.energy = energyExpended; @@ -183,7 +180,7 @@ var characteristics = []; var blockInit = false; var currentRetryTimeout; - var initialRetryTime = 1000; + var initialRetryTime = 40; var maxRetryTime = 60000; var retryTime = initialRetryTime; @@ -192,7 +189,7 @@ maxInterval: 1500 }; - function waitingPromise(timeout) { + var waitingPromise = function(timeout) { return new Promise(function(resolve){ log("Start waiting for " + timeout); setTimeout(()=>{ @@ -200,7 +197,7 @@ resolve(); }, timeout); }); - } + }; if (settings.enabled){ Bangle.isBTHRMOn = function(){ @@ -225,15 +222,15 @@ }; } - function clearRetryTimeout(){ + var clearRetryTimeout = function() { if (currentRetryTimeout){ log("Clearing timeout " + currentRetryTimeout); clearTimeout(currentRetryTimeout); currentRetryTimeout = undefined; } - } + }; - function retry(){ + var retry = function() { log("Retry"); if (!currentRetryTimeout){ @@ -255,10 +252,10 @@ } else { log("Already in retry..."); } - } + }; var buzzing = false; - function onDisconnect(reason) { + var onDisconnect = function(reason) { log("Disconnect: " + reason); log("GATT: ", gatt); log("Characteristics: ", characteristics); @@ -273,9 +270,9 @@ if (Bangle.isBTHRMOn()){ retry(); } - } + }; - function createCharacteristicPromise(newCharacteristic){ + var createCharacteristicPromise = function(newCharacteristic) { log("Create characteristic promise: ", newCharacteristic); var result = Promise.resolve(); // For values that can be read, go ahead and read them, even if we might be notified in the future @@ -298,23 +295,23 @@ log("Add " + settings.gracePeriodNotification + "ms grace period after starting notifications"); startPromise = startPromise.then(()=>{ log("Wait after connect"); - waitingPromise(settings.gracePeriodNotification) + return waitingPromise(settings.gracePeriodNotification); }); } return startPromise; }); } return result.then(()=>log("Handled characteristic: ", newCharacteristic)); - } + }; - function attachCharacteristicPromise(promise, characteristic){ + var attachCharacteristicPromise = function(promise, characteristic) { return promise.then(()=>{ log("Handling characteristic:", characteristic); return createCharacteristicPromise(characteristic); }); - } + }; - function createCharacteristicsPromise(newCharacteristics){ + var createCharacteristicsPromise = function(newCharacteristics) { log("Create characteristics promise: ", newCharacteristics); var result = Promise.resolve(); for (var c of newCharacteristics){ @@ -328,9 +325,9 @@ result = attachCharacteristicPromise(result, c); } return result.then(()=>log("Handled characteristics")); - } + }; - function createServicePromise(service){ + var createServicePromise = function(service) { log("Create service promise: ", service); var result = Promise.resolve(); result = result.then(()=>{ @@ -338,15 +335,13 @@ return service.getCharacteristics().then((c)=>createCharacteristicsPromise(c)); }); return result.then(()=>log("Handled service" + service.uuid)); - } + }; - function attachServicePromise(promise, service){ + var attachServicePromise = function(promise, service) { return promise.then(()=>createServicePromise(service)); - } + }; - var reUseCounter = 0; - - function initBt() { + var initBt = function () { log("initBt with blockInit: " + blockInit); if (blockInit){ retry(); @@ -355,19 +350,15 @@ blockInit = true; - if (reUseCounter > 10){ - log("Reuse counter to high"); - gatt=undefined; - reUseCounter = 0; - } - var promise; + var filters; if (!device){ - var filters = serviceFilters; if (settings.btid){ log("Configured device id", settings.btid); - filters = [{id: settings.btid }]; + filters = [{ id: settings.btid }]; + } else { + return; } log("Requesting device with filters", filters); promise = NRF.requestDevice({ filters: filters, active: true }); @@ -397,13 +388,13 @@ } else { log("GATT is new: ", gatt); characteristics = []; - var cachedName = getCache().name; - if (device.name !== cachedName){ - log("Device name changed from " + cachedName + " to " + device.name + ", clearing cache"); + var cachedId = getCache().id; + if (device.id !== cachedId){ + log("Device ID changed from " + cachedId + " to " + device.id + ", clearing cache"); clearCache(); } var newCache = getCache(); - newCache.name = device.name; + newCache.id = device.id; writeCache(newCache); gatt = device.gatt; } @@ -465,7 +456,7 @@ log("Add " + settings.gracePeriodService + "ms grace period after services"); result = result.then(()=>{ log("Wait after services"); - return waitingPromise(settings.gracePeriodService) + return waitingPromise(settings.gracePeriodService); }); } return result; @@ -478,10 +469,9 @@ return characteristicsPromise; }); - + return promise.then(()=>{ log("Connection established, waiting for notifications"); - reUseCounter = 0; characteristicsToCache(characteristics); clearRetryTimeout(); }).catch((e) => { @@ -489,7 +479,7 @@ log("Error:", e); onDisconnect(e); }); - } + }; Bangle.setBTHRMPower = function(isOn, app) { // Do app power handling @@ -538,7 +528,7 @@ var fallbackInterval; - function switchInternalHrm(){ + var switchInternalHrm = function() { if (settings.allowFallback && !fallbackInterval){ log("Fallback to HRM enabled"); origSetHRMPower(1, "bthrm_fallback"); @@ -551,7 +541,7 @@ } }, settings.fallbackTimeout); } - } + }; if (settings.replace){ log("Replace HRM event"); diff --git a/apps/bthrm/metadata.json b/apps/bthrm/metadata.json index b35ebd6af..faff72d0f 100644 --- a/apps/bthrm/metadata.json +++ b/apps/bthrm/metadata.json @@ -6,7 +6,7 @@ "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", - "tags": "health,bluetooth", + "tags": "health,bluetooth,hrm", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ From ab11b7068115b6678d69e70c21b7787bba778ece Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 19 Apr 2022 16:54:27 -0500 Subject: [PATCH 13/94] Default custom values to the same as default mode so you can choose which pieces to change knowing the rest is the same --- apps/bthrm/default.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/bthrm/default.json b/apps/bthrm/default.json index 64e638b8a..fb284bcd2 100644 --- a/apps/bthrm/default.json +++ b/apps/bthrm/default.json @@ -7,10 +7,10 @@ "allowFallback": true, "warnDisconnect": false, "fallbackTimeout": 10, - "custom_replace": false, + "custom_replace": true, "custom_debuglog": false, - "custom_startWithHrm": false, - "custom_allowFallback": false, + "custom_startWithHrm": true, + "custom_allowFallback": true, "custom_warnDisconnect": false, "custom_fallbackTimeout": 10, "gracePeriodNotification": 0, From dbecd1ae6f009220f84b989d2bfc3666ebf27ca2 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 19 Apr 2022 16:54:50 -0500 Subject: [PATCH 14/94] Adding tag to find 'hrm' more easily --- apps/bthrm/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bthrm/metadata.json b/apps/bthrm/metadata.json index faff72d0f..85c19ab33 100644 --- a/apps/bthrm/metadata.json +++ b/apps/bthrm/metadata.json @@ -6,7 +6,7 @@ "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", - "tags": "health,bluetooth,hrm", + "tags": "health,bluetooth,hrm,bthrm", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ From 650d2bd288e47bbf95f94aef62949ad22aefdd32 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Tue, 19 Apr 2022 16:55:04 -0500 Subject: [PATCH 15/94] Scaled retryTime for clampedTime instead of itself --- apps/bthrm/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 064f65eac..e9e640563 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -245,7 +245,7 @@ initBt(); }, clampedTime); - retryTime = Math.pow(retryTime, 1.1); + retryTime = Math.pow(clampedTime, 1.1); if (retryTime > maxRetryTime){ retryTime = maxRetryTime; } From 437630574d49a1af4ba3a15565e0f37932d42b0e Mon Sep 17 00:00:00 2001 From: Marco H Date: Wed, 18 May 2022 20:12:53 +0200 Subject: [PATCH 16/94] Optimize settings --- apps/circlesclock/settings.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 0b9e94aca..3bfdb54c7 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -100,7 +100,7 @@ /*LANG*/'valid period': { value: settings.hrmValidity, min: 10, - max : 600, + max : 1800, step: 10, format: x => { return x + "s"; @@ -117,9 +117,9 @@ /*LANG*/'< Back': ()=>showMainMenu(), /*LANG*/'goal': { value: settings.stepGoal, - min: 2000, + min: 1000, max : 50000, - step: 2000, + step: 500, format: x => { return x; }, @@ -127,9 +127,9 @@ }, /*LANG*/'distance goal': { value: settings.stepDistanceGoal, - min: 2000, - max : 30000, - step: 1000, + min: 1000, + max : 50000, + step: 500, format: x => { return x; }, From 5358fec9ba79833a0fd05bd592373be6262f3af8 Mon Sep 17 00:00:00 2001 From: Marco H Date: Wed, 18 May 2022 20:13:57 +0200 Subject: [PATCH 17/94] Allow configuration of update interval --- apps/circlesclock/ChangeLog | 1 + apps/circlesclock/app.js | 4 ++-- apps/circlesclock/default.json | 3 ++- apps/circlesclock/metadata.json | 2 +- apps/circlesclock/settings.js | 10 ++++++++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 46eddd32b..c3e7918e7 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -23,3 +23,4 @@ 0.11: New color option: foreground color Improve performance, reduce memory usage Small optical adjustments +0.12: Allow configuration of update interval diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index a6aa1a8b1..48e3a1a1a 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -848,8 +848,8 @@ Bangle.loadWidgets(); // schedule a draw for the next minute setTimeout(function() { - // draw every 60 seconds - setInterval(draw,60000); + // draw in interval + setInterval(draw, settings.updateInterval * 1000); }, 60000 - (Date.now() % 60000)); draw(); diff --git a/apps/circlesclock/default.json b/apps/circlesclock/default.json index cb6bfcff8..ea00dc347 100644 --- a/apps/circlesclock/default.json +++ b/apps/circlesclock/default.json @@ -21,5 +21,6 @@ "circle2colorizeIcon": true, "circle3colorizeIcon": true, "circle4colorizeIcon": false, - "hrmValidity": 60 + "hrmValidity": 60, + "updateInterval": 60 } diff --git a/apps/circlesclock/metadata.json b/apps/circlesclock/metadata.json index b16f14c06..c35d99334 100644 --- a/apps/circlesclock/metadata.json +++ b/apps/circlesclock/metadata.json @@ -1,7 +1,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.11", + "version":"0.12", "description": "A clock with three or four circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}, {"url":"screenshot-dark-4.png"}, {"url":"screenshot-light-4.png"}], diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 3bfdb54c7..fb23f8d5e 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -58,6 +58,16 @@ min: 0, max: 2, format: v => weatherData[v], onchange: x => save('weatherCircleData', weatherData[x]), + }, + /*LANG*/'update interval': { + value: settings.updateInterval, + min: 0, + max : 3600, + step: 30, + format: x => { + return x + 's'; + }, + onchange: x => save('updateInterval', x), } }; E.showMenu(menu); From 4dfd1b2bf0b01d14bafb0c10e43e5b3d31fc4d37 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Thu, 19 May 2022 23:43:59 +0200 Subject: [PATCH 18/94] - removed unused font - fix autoCycle --- apps/rebble/ChangeLog | 3 ++- apps/rebble/KdamThmor.ttf | Bin 0 -> 11884 bytes apps/rebble/metadata.json | 2 +- apps/rebble/rebble.app.js | 18 ++++++++++-------- 4 files changed, 13 insertions(+), 10 deletions(-) create mode 100644 apps/rebble/KdamThmor.ttf diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index 5dd28453e..aec12e247 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -4,4 +4,5 @@ 0.04: Fixed icon and png to 48x48 pixels 0.05: added charging icon 0.06: Add 12h support and autocycle control -0.07: added localization; removed deprecated code \ No newline at end of file +0.07: added localization, removed deprecated code +0.08: removed unused font, fix autocycle \ No newline at end of file diff --git a/apps/rebble/KdamThmor.ttf b/apps/rebble/KdamThmor.ttf new file mode 100644 index 0000000000000000000000000000000000000000..ca484ccbdbab0059c1cca27b39e01240b3773656 GIT binary patch literal 11884 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 literal 0 HcmV?d00001 diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index e1f18ea55..c373ee202 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,7 +2,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.07", + "version": "0.08", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index bdc7ed1a3..981773369 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -6,14 +6,15 @@ let settings; let location; let is12Hour; -Graphics.prototype.setFontLECO1976Regular22 = function(scale) { - // Actual height 22 (21 - 0) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/nA/+cD/5wP/nAAAAAAAAPwAA/gAD+AAPwAAAAAD+AAP4AA/gAAAAAAAAAAAAAcOAP//A//8D//wP//AHDgAcOAP//A//8D//wP//AHDgAAAAAAAAH/jgf+OB/44H/jj8OP/w4//Dj/8OPxw/4HD/gcP+Bw/4AAAAAAAP+AA/8AD/wQOHHA4c8D//wP/8A//gAD4AAfAAH/8A//wP//A84cDjhwIP/AA/8AB/wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8ABwAAAAAAAAD8AAP4AA/gAD8AAAAAAAAAAAEAAD+AB//A///v/D//gB/wABwAAAAAADgAA/wAf/4P8///wf/4AP8AAOAAAAAAAAAyAAHcAAPwAD/gAP/AA/8AA/AAH8AAMwAAAAAAAAAAAAADgAAOAAA4AAf8AD/wAP/AA/8AAOAAA4AADgAAAAAAAAAAD8AAfwAB/AAD8AAAAAAAADgAAOAAA4AADgAAOAAA4AADgAAAAAAAAAADgAAOAAA4AADgAAAAAAAAABwAB/AA/8A//gP/gA/wADwAAIAAAAAAD//wP//A//8D//wOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA4AcDgBwOAHA//8D//wP//A//8AABwAAHAAAcAAAAAAAA+f8D5/wPn/A+f8DhxwOHHA4ccDhxwP/HA/8cD/xwP/HAAAAAAAAOAHA4AcDhxwOHHA4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/wAP/AA/8AD/wAAHAAAcAABwAAHAA//8D//wP//A//8AAAAAAAA/98D/3wP/fA/98DhxwOHHA4ccDhxwOH/A4f8Dh/wOH/AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccDh/wOH/A4f8Dh/wAAAAAAAD4AAPgAA+AADgAAOAAA4AADgAAP//A//8D//wP//AAAAAAAAP//A//8D//wP//A4ccDhxwOHHA4ccD//wP//A//8D//wAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA//8D//wP//A//8AAAAAAAAOA4A4DgDgOAOA4AAAAAAAAOA/A4H8DgfwOA/AAAAAAAAB4AAPwAA/AAD8AAf4ABzgAPPAA8cAHh4AAAAAAAAAAAAHHAAccABxwAHHAAccABxwAHHAAccABxwAHHAAAAAAAAAOHAA4cADzwAPPAAf4AB/gAD8AAPwAAeAAB4AAAAAAAAA+AAD4AAPgAA+ecDh9wOH3A4fcDhwAP/AA/8AD/wAP/AAAAAAAAAP//4///j//+P//44ADjn/OOf845/zjnHOP8c4//zj//OP/84AAAAAAAP//A//8D//wP//A4cADhwAOHAA4cAD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA//8D//wP9/A/j8AAAAAAAA//8D//wP//A//8DgBwOAHA4AcDgBwOAHA4AcDgBwOAHAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA8A8D//wH/+AP/wAf+AAAAAAAAD//wP//A//8D//wOHHA4ccDhxwOHHA4ccDhxwOAHA4AcAAAAAAAA//8D//wP//A//8DhwAOHAA4cADhwAOHAA4cADgAAOAAAAAAD//wP//A//8D//wOAHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA//8D//wP//A//8ABwAAHAAAcAABwAP//A//8D//wP//AAAAAAAAP//A//8D//wP//AAAAAAAAOAHA4AcDgBwOAHA4AcDgBwOAHA//8D//wP//A//8AAAAAAAA//8D//wP//A//8AHwAA/AAP8AB/wAPn/A8f8DB/wIH/AAAAAAAAP//A//8D//wP//AAAcAABwAAHAAAcAABwAAHAAAAAAAAP//A//8D//wP//Af8AAP+AAH/AAD8AAHwAD/AB/wAf8AP+AA//8D//wP//AAAAAAAAP//A//8D//wP//AfwAAfwAAfwAAfwAAfwP//A//8D//wAAAAAAAAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//wP//A//8D//wAAAAAAAD//wP//A//8D//wOHAA4cADhwAOHAA/8AD/wAP/AA/8AAAAAP//A//8D//wP//A4AcDgBwOAHA4AcD//+P//4///j//+AAA4AADgAAAP//A//8D//wP//A4eADh+AOH8A4f4D/3wP/HA/8MD/wQAAAAAAAD/xwP/HA/8cD/xwOHHA4ccDhxwOHHA4f8Dh/wOH/A4f8AAAAAAAA4AADgAAOAAA//8D//wP//A//8DgAAOAAA4AADgAAAAAA//8D//wP//A//8AABwAAHAAAcAABwP//A//8D//wP//AAAADAAAPgAA/wAD/4AB/8AA/8AAfwAB/AA/8Af+AP/AA/wAD4AAMAAA4AAD+AAP/gA//8AH/wAB/AAf8Af/wP/4A/4AD/gAP/4AH/8AB/wAB/AB/8D//wP/gA/gADgAAIABA4AcDwDwPw/Afn4Af+AA/wAD/AA//AH5+A/D8DwDwOAHAgAEAAAAP/AA/8AD/wAP/AAAf8AB/wAH/AAf8D/wAP/AA/8AD/wAAAAAAAADh/wOH/A4f8Dh/wOHHA4ccDhxwOHHA/8cD/xwP/HA/8cAAAAAAAAf//9///3///f//9wAA3AADcAAMAAAOAAA/gAD/wAH/8AB/8AA/wAAPAAAEAAAAHAADcAANwAB3///f//9///wAA"), 32, atob("BwYLDg4UDwYJCQwMBgkGCQ4MDg4ODg4NDg4GBgwMDA4PDg4ODg4NDg4GDQ4MEg8ODQ8ODgwODhQODg4ICQg="), 22+(scale<<8)+(1<<16)); -} - Graphics.prototype.setFontKdamThmor = function(scale) { - // Actual height 72 (71 - 0) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAAAAAAAAAH+AAAAAAAAAAAAAP/AAAAAAAAAAAAAf/gAAAAAAAAAAAA//gAAAAAAAAAAAA//wAAAAAAAAAAAA//wAAAAAAAAAAAA//wAAAAAAAAAAAA//wAAAAAAAAAAAA//gAAAAAAAAAAAAf/gAAAAAAAAAAAAf/AAAAAAAAAAAAAP+AAAAAAAAAAAAAD8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAAAAAAAAAAAAAB/AAAAAAAAAAAAAP/AAAAAAAAAAAAA//AAAAAAAAAAAAH/+AAAAAAAAAAAAf/+AAAAAAAAAAAD//+AAAAAAAAAAAf//8AAAAAAAAAAB///4AAAAAAAAAAP///wAAAAAAAAAA////AAAAAAAAAAH///4AAAAAAAAAAf///gAAAAAAAAAD///8AAAAAAAAAAf///wAAAAAAAAAB///+AAAAAAAAAAP///4AAAAAAAAAA////AAAAAAAAAAH///4AAAAAAAAAAf///gAAAAAAAAAD///8AAAAAAAAAAP///wAAAAAAAAAB///+AAAAAAAAAAP///4AAAAAAAAAA////AAAAAAAAAAD///4AAAAAAAAAAP///gAAAAAAAAAAf//8AAAAAAAAAAA///wAAAAAAAAAAA//+AAAAAAAAAAAA//4AAAAAAAAAAAA//AAAAAAAAAAAAA/4AAAAAAAAAAAAA/gAAAAAAAAAAAAA8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//AAAAAAAAAAAP///+AAAAAAAAAD/////wAAAAAAAAP/////+AAAAAAAA///////gAAAAAAD///////4AAAAAAH///////8AAAAAAf///////+AAAAAA/////////gAAAAB/////////wAAAAB/////////wAAAAD/////////4AAAAH///AAA///8AAAAH//wAAAB//8AAAAP/+AAAAAP/+AAAAP/4AAAAAD/+AAAAf/gAAAAAA//AAAAf/AAAAAAAf/AAAAf+AAAAAAAP/AAAA/+AAAAAAAP/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/8AAAAAAAH/gAAA/+AAAAAAAP/gAAAf+AAAAAAAP/AAAAf/AAAAAAAf/AAAAf/gAAAAAA//AAAAP/4AAAAAD/+AAAAP/+AAAAAP/+AAAAH//gAAAA//8AAAAH///AAAf//8AAAAD/////////4AAAAD/////////wAAAAB/////////wAAAAA/////////gAAAAAf////////AAAAAAH///////8AAAAAAD///////4AAAAAAA///////gAAAAAAAP/////+AAAAAAAAD/////4AAAAAAAAAf////AAAAAAAAAAA///gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAADwAAAAAAAAAAAAAD4AAAAAAAAAAAAAH8AAAAAAAAAAAAAP+AAAAAAAAAAAAAf/AAAAAH/AAAAAA//AAAAAH/AAAAAB//AAAAAH/AAAAAB//AAAAAH/AAAAAD/+AAAAAH/AAAAAH/8AAAAAH/AAAAAP/4AAAAAH/AAAAAf/wAAAAAH/AAAAA//gAAAAAH/AAAAB//gAAAAAH/AAAAB//AAAAAAH/AAAAD/+AAAAAAH/AAAAH/8AAAAAAH/AAAAP//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/AAAAAAHgAAAAAD/AAAAAA/wAAAAAH/AAAAAD/wAAAAAP/AAAAAH/wAAAAAf/AAAAAP/wAAAAA//AAAAA//wAAAAB//AAAAB//wAAAAD//AAAAB//wAAAAH//AAAAD//wAAAAP//AAAAH//wAAAAf//AAAAH//gAAAA///AAAAP/+AAAAB///AAAAP/4AAAAD///AAAAf/gAAAAH///AAAAf/AAAAAP///AAAAf+AAAAAf///AAAAf+AAAAA//v/AAAA/8AAAAB//P/AAAA/8AAAAD/+P/AAAA/8AAAAH/8P/AAAA/8AAAAP/4P/AAAA/8AAAAf/wf/AAAA/8AAAA//gf/AAAA/8AAAD//Af/AAAA/8AAAH/+Af/AAAA/+AAAP/8Af/AAAA/+AAAf/4Af/AAAAf/AAB//wAf/AAAAf/gAD//gAf/AAAAf/wAf//AAf/AAAAf/+D//+AAf/AAAAP/////8AAf/AAAAP/////4AAf/AAAAH/////wAAf/AAAAH/////gAAf/AAAAD/////AAAf/AAAAB////8AAAf/AAAAA////4AAAf/AAAAAf///wAAAf/AAAAAP///AAAAf/AAAAAD//8AAAAf/AAAAAA//gAAAAP/AAAAAABwAAAAAH/AAAAAAAAAAAAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAAAAAAAAAAAfAAAAAAAAHgAAAA/wAAAAAAA/wAAAA/8AAAAAAD/wAAAB/+AAAAAAH/wAAAB//AAAAAAP/wAAAB//gAAAAA//wAAAB//wAAAAB//wAAAB//4AAAAB//wAAAB//8AAAAD//wAAAA//8AAAAH//wAAAAf/+AAAAH//gAAAAH/+AAAAP/+AAAAAB//AAAAP/4AAAAAA//AAAAf/gAAAAAAf/AAAAf/AAAAAAAf/AAAAf/AAAAAAAP/gAAAf+AAAAAAAP/gAAA/+AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAD/gAAH/gAAA/8AAH/wAAH/gAAA/8AAH/wAAP/gAAA/+AAH/wAAP/AAAAf/AAP/4AAf/AAAAf/AAf/4AA//AAAAf/wA//8AB//AAAAf/+H//+AD/+AAAAP//////4f/+AAAAP////v////8AAAAH////v////8AAAAH////H////4AAAAD////H////wAAAAB///+D////wAAAAA///8D////gAAAAAf//4B////AAAAAAP//wA///+AAAAAAD//AAf//4AAAAAAAf4AAH//gAAAAAAAAAAAB/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAAAAAAD/gAAAAAAAAAAAAP/wAAAAAAAAAAAAf/wAAAAAAAAAAAA//wAAAAAAAAAAAD//wAAAAAAAAAAAH//wAAAAAAAAAAAP//wAAAAAAAAAAA///wAAAAAAAAAAB///wAAAAAAAAAAD///wAAAAAAAAAAP///wAAAAAAAAAAf///wAAAAAAAAAA//9/wAAAAAAAAAD//x/wAAAAAAAAAH//h/wAAAAAAAAAP/+B/wAAAAAAAAA//8B/wAAAAAAAAB//4B/wAAAAAAAAD//gB/wAAAAAAAAP//AB/wAAAAAAAAf/+AB/wAAAAAAAA//4AB/wAAAAAAAD//wAB/wAAAAAAAH//AAB/wAAAAAAAP/+AAB/wAAAAAAA//8AAB/wAAAAAAB//wAAB/wAAAAAAD//gAAB/wAAAAAAP/+AAAB/wAAAAAAf/8AAAB/wAAAAAAf/5////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAf//////////AAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/wAAAAAAAAAAAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAAAAAAAAPgAAAAAAAAAAAAA/wAAAAAAAAD4AAB/4AAAAAAAD/4AAB/4AAAAAAD//4AAB/8AAAAAD///8AAB/8AAAAD////8AAB/+AAAAf////8AAA/+AAAAf////+AAA/+AAAAf////+AAAf/AAAAf////8AAAf/AAAAf////8AAAP/AAAAf////8AAAP/AAAAf//4/4AAAH/gAAAf/8A/4AAAH/gAAAf+AA/4AAAH/gAAAf+AA/4AAAH/gAAAf+AA/4AAAH/gAAAf+AA/4AAAH/gAAAf+AA/4AAAH/gAAAf+AB/4AAAH/gAAAf+AB/4AAAH/gAAAf+AA/8AAAP/gAAAf+AA/8AAAP/AAAAf+AA/8AAAP/AAAAf+AA/+AAAf/AAAAf+AA/+AAA//AAAAf+AA//AAB/+AAAAf+AAf/gAD/+AAAAf+AAf/4Af/8AAAAf+AAf/////8AAAAf+AAP/////4AAAAf+AAP/////wAAAAf+AAH/////wAAAAf+AAD/////gAAAAf+AAD/////AAAAAf+AAB////+AAAAAf8AAA////8AAAAAf4AAAP///wAAAAAfgAAAH///AAAAAAAAAAAA//8AAAAAAAAAAAAH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AAAAAAAAAAAB///AAAAAAAAAAAP///wAAAAAAAAAA////8AAAAAAAAAB////+AAAAAAAAAH/////AAAAAAAAAP/////gAAAAAAAA//////wAAAAAAAB//////4AAAAAAAH//////8AAAAAAAP//////8AAAAAAAf//+AP/+AAAAAAB///4AB/+AAAAAAD///wAA/+AAAAAAH///gAAf/AAAAAAf///AAAP/AAAAAA///+AAAP/AAAAAB///+AAAH/gAAAAH//3+AAAH/gAAAAP//v8AAAH/gAAAAf//P8AAAH/gAAAB//+P8AAAH/gAAAD//4f8AAAH/gAAAH//wf8AAAH/gAAAP//gf8AAAH/gAAAf//Af8AAAH/gAAAf/8Af+AAAH/gAAAf/4Af+AAAP/AAAAf/wAf+AAAP/AAAAf/gAf/AAAf/AAAAf/AAP/gAA//AAAAf8AAP/wAB/+AAAAf4AAP/4AD/+AAAAfwAAP//Af/8AAAAfgAAH/////8AAAAeAAAH/////4AAAAcAAAD/////4AAAAYAAAD/////wAAAAQAAAB/////gAAAAAAAAA/////AAAAAAAAAAf///+AAAAAAAAAAP///8AAAAAAAAAAD///wAAAAAAAAAAB///AAAAAAAAAAAAP/8AAAAAAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAAAAAAAAAf+AAAAAAAAAAAAAf+AAAAAAAAAAAAAf+AAAAAAAAAAAAAf+AAAAAAAAAAAAAf+AAAAAAAABAAAAf+AAAAAAAAHAAAAf+AAAAAAAAfAAAAf+AAAAAAAB/AAAAf+AAAAAAAH/AAAAf+AAAAAAAf/AAAAf+AAAAAAB//AAAAf+AAAAAAH//AAAAf+AAAAAAf//AAAAf+AAAAAB///AAAAf+AAAAAH///AAAAf+AAAAAf///AAAAf+AAAAB///+AAAAf+AAAAH///8AAAAf+AAAAf///wAAAAf+AAAA////AAAAAf+AAAD///8AAAAAf+AAAP///wAAAAAf+AAA////AAAAAAf+AAD///8AAAAAAf+AAP///wAAAAAAf+AA////AAAAAAAf+AD///8AAAAAAAf+AP///wAAAAAAAf+A////AAAAAAAAf+D///8AAAAAAAAf+P///wAAAAAAAAf+f//+AAAAAAAAAf////4AAAAAAAAAf////gAAAAAAAAAf///+AAAAAAAAAAf///4AAAAAAAAAAf///gAAAAAAAAAAf//+AAAAAAAAAAAf//4AAAAAAAAAAAf//gAAAAAAAAAAAf/+AAAAAAAAAAAAf/4AAAAAAAAAAAAf/gAAAAAAAAAAAAf+AAAAAAAAAAAAAfgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAAAAAAAAAAB//gAAAAAAADwAAH//4AAAAAAA//AAf//8AAAAAAD//wA////AAAAAAP//4B////gAAAAAf//+B////wAAAAA////D////wAAAAB////H////4AAAAD////n////8AAAAH/////////8AAAAH/////////+AAAAP//////wP/+AAAAP//////AB/+AAAAf/wD//8AA//AAAAf/AA//4AAf/AAAAf+AAf/4AAP/AAAAf8AAP/wAAH/AAAA/8AAH/wAAH/gAAA/4AAH/gAAH/gAAA/4AAH/gAAD/gAAA/4AAD/gAAD/gAAA/4AAD/gAAD/gAAA/4AAD/gAAD/gAAA/4AAD/gAAD/gAAA/4AAD/gAAD/gAAA/4AAH/gAAH/gAAA/8AAH/wAAH/gAAAf8AAP/wAAH/gAAAf+AAP/wAAP/AAAAf/AAf/4AAf/AAAAf/wB//8AAf/AAAAP/////+AB//AAAAP//////wH/+AAAAH/////////+AAAAH/////////8AAAAD////n////8AAAAB////H////4AAAAA////D////wAAAAAf//+B////wAAAAAP//8B////gAAAAAH//wA////AAAAAAB//AAf//8AAAAAAAH4AAH//4AAAAAAAAAAAB//gAAAAAAAAAAAAP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/8AAAAAAAAAAAAf//AAAAAAAAAAAB///wAAAAAAAAAAH///4AAAAAAAAAAP///+AAAAAAAAAAf////AAAAAAAAAA/////AAAADAAAAB/////gAAAHAAAAD/////wAAAPAAAAH/////wAAAfAAAAH/////4AAB/AAAAP//A//4AAD/AAAAP/4AH/8AAH/AAAAf/gAD/8AAP/AAAAf/AAB/8AA//AAAAf+AAA/8AB//AAAAf+AAA/8AD//AAAA/8AAAf8AH//AAAA/8AAAf8Af//AAAA/8AAAf8A//+AAAA/8AAAf8B//+AAAA/8AAAf8D//8AAAA/8AAAf8P//wAAAA/8AAAf8f//gAAAA/8AAAf4//+AAAAA/8AAAf5//8AAAAA/8AAAf3//4AAAAAf+AAA////gAAAAAf+AAB////AAAAAAf/AAB///8AAAAAAf/gAD///4AAAAAAP/4AP///gAAAAAAP//B////AAAAAAAH//////+AAAAAAAH//////4AAAAAAAD//////wAAAAAAAB//////AAAAAAAAA/////+AAAAAAAAAf////4AAAAAAAAAP////wAAAAAAAAAH////AAAAAAAAAAB///8AAAAAAAAAAAf//gAAAAAAAAAAAB/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAAD8AAAAAAAA/4AAAP+AAAAAAAB/8AAAf/AAAAAAAB/+AAAf/gAAAAAAD/+AAA//gAAAAAAD//AAA//wAAAAAAD//AAA//wAAAAAAD//AAA//wAAAAAAD//AAA//wAAAAAAD/+AAA//gAAAAAAB/+AAAf/gAAAAAAA/8AAAP/AAAAAAAAf4AAAH+AAAAAAAAHgAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"), 46, atob("FCM0NDQ0NDQ0NDQ0GA=="), 90+(scale<<8)+(1<<16)); + // Actual height 70 (69 - 0) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('AH4AMgfABZM/BZMB/4WJg/+BZMf/ALJ//gIpP/wAugLpUAvyBKsDC/ACKYJQIKYJgaYKv6YJh7HJeoP8VxLSJg//+D0JIhMf/7RIf4JPJv//LX5a6CwLvJn5aJLYIKJgY4IADn/KpKvBAAKvIAARiGBQanGOwILJBQgLFFogvGIgZHGWAIAEdwg5FNYreBAAjvDeoIAFYQcfBYy3DEQRKEKQQiCAoRiCIogoDCIJGDEQLlEIwZoBCwYLCHQQoBQwgGEj7aFGoKuDKwYSFE4LZFv41Ch6dEIITICn5FEDwQuDeAwuEBQgeEB4b8EFwbADNIZdaHQoSBFwUfNIoGEv5GFXYpGEIoJBCZgjZGHQILDCwIpDj//GgQoBMggcBAApkDBQwiDDoQAEEQY0BERJGBERBGCERC8BBYrYFBQj8FLwrBGBQbkFEYoKFBYgtFL4jLFZ4gKJAH4AciALKRA73DbIgAFj/ABZLOGEQjDEj40En6tEv4oDgLPEAoLRFCIcHDgouJDgP4FxAiFFwt//xXEFwcDEQouEj4iEFwv/EQguEEQJ6EFwgiBS4guE/5uEFwiiBAAyiDBQwdDCw4uCIoIAGFwSLBF34unAAy7EAAy7EAAzqEAArqEF34ukAH4AGgfgNJWAAod8Cwn+SQn4RggFEv4oE/4FDg//FAYFFn4oEAoidBFAYFFh//YIYFBFwd//7BDAoIuCgf/YIYFBFwcfFAgFFDgIoDDgIFCEQpcBFwZFFn4uEAoJcEFwYFBLgouDQoo/BAwcf/hcEFwgiELgPfFwQRBEQYVBFwcPDYYzB+YSDn55DKwOPFwgbCKwP8CQYuBXIouEKIZcBIIgbF/BBEDYZcB4ASFDYI5BCgIuEHQSzCFwo6CeYQuEv4nBOYIPBFwa7Ddoa7FJoLtCFwhNBAAQfBFwiTBAAXAT4oKDCYSfFAAQ9BFwg6BAAQHBFwhDCLgQuFIwY5BFwhGDDwT9FOQI5CFwpSDDoYuDBYQWCFwoLCAgQuFCIsHFwgAFh4uEAH4AWjgLKvwGFj6LDP4sBcgjhCCwaGDn4LEgKjDAgKXEh61Dg7LEdQIuDj7AEZgIpDfYPACIgdCFwLjDdIQRCFwIoDEQJdEFAgiBJgYoEEQoLCAoRFFBYRjCFAIWDQII0Dv6SFv40CRYg1DHQRXBBQg1BFISpDBwQSEEQTQDj4SCDYJKBh42Cv4uCh4TCn4aBIIIuDCYIHBDQIeBFwYPBg4aCe4YPDfAYuHv4uNLo6bBLpJ4EFwYTBEQIHBCQYbBHQIqBEwIGCXYl/IQTwDD4P+CwIfBFILCCBAQACwACBEQQQBAArlDn4LGcoY3BGAIlEHQYAB+YiGMQIAB54DCOgRGD/0fEQpGD+A+CEQZ6BLYhFEKQX8HwYKDBYXgHwQ5DBYQpBBYQ5DHYRWDUQQAGgK5DADsBBZUfb4IAIOYoAETgJcFAAbLBBRBoBUQg5FRYxQDRYJGIZQQ5KFxDtCFxDpCFw7dIfAouICwQuHHIP+FxBQB8YuHf4UPFw6KCn4uGKAWAFw6KB/glBHJHAFw5QCQQIuGRQLzBFww5CKgRQH/A9BFwxQCFw45BCYQuGKAI5BFwwGBKAIuHRQRVCFwhQDFw6KBKAIuHfwQAEGAYKGGgbQCAAowCFwIAGF34ugAAjqHTojqFfQrqFcYoWJF0f+CxMH8ALJAEkCBZU8BRMB/CCKOw0DA4V/OwqhBA4IDBwAKFVoTlBBQytCn6xDBQX/IQQDDAgIACSwIRBTQQWDGwUHHQYzBAAK5CHQk/Fwo6EFwppBNoQuGgIPDFwYeCOoguC34eCh74DEASMCCQI+CDYQCBCQYuDDYMPFwQ6BFwYbBn4uCg4uE8ASBFwUfFwqIBCQV/FwsfLpAbBPgZdFFwpdGFwhdHDwQPELoYeCHwYbD/46CAYaMEBwLqFFwRGCv5RDFYUfBYIWBGQQuDv7iDMIQuCNIIADCwQuCfIgiDFwT5DEQYuDHQIiFVAc/EQyJDIwYiDc4RGDNAYuBCAJGDRYQHBCAQLDCwcPCAR+BHIgAEBYQKHEYQtDAH4Ak/gKJZALMBRhLGDAAjSGWYgLCEY7qDBYwtCXhBEBewzpF/5fGj4LDdYwKD//gKBBeHKAZGGHIX+gJGGKAQfBHQoSBCYQEB+A5GA4InBHQiJEQgKKGOIUPHQg5CFQU/HQaKDVgR1ERQQeCIwK8DBQPvDwUHFwZQB/0/DwUfFwaKB+IeDv4PCHIWHFw45B/geDFwjBCDwYPDEQKsCLoxFB+CIDCQIPCP4OAj6MCj4uEBAN/FQV/SAS0CFwIqBXYioCA4ZYBVwYbBHoIaCQAY+CHoPACwKADGwa+CEQcPFQIfBAARVCgE+dgiGCBYRVCHQLiFganEEQsIZQgiFAAZFGAAZGDNAYADcQSLDAAhSCVwYLHHI4LCCxC5FAH4AIJhRYBXgQAGh5vJgE/VI4uDSRAuJoAuJg4uKvguJg/wFxN/OAQuGaoIuJv/8FxAWBFxN/T4YuFCwIuJCwIuICwQuICwIuICwQGDFwgWCEQQuECwQpDFwk/BQIdDFwYPBCwguECwwuDCw4uDCw4uCCw4uDCw4uCCxAuCCxAuBCwYKEFwQWCRIYuD8YWIEAO/CxEPCoQWGLQYWHFwIWJJ4YWHFwYKGFwYWHFwYKHFwQWIFwQKHFwQWIFwQKIFwIWJdQQuJ8ALJAH8f/BuK/gIFv6RDBYqlBwEBSIIjFA4OAWgSSEA4WAv4LGA4TXC//Ab4v+j4LCwBYDAwP8DQTNEAwXzAYTCDFQfvAYRSDFQYADIwYqDAAZGCEQYAB8A6ENARHCDoI6DAgKKCD4N/HQQIB8ACBCYQGBAYMHE4IxBIQIPBHQU/DYIOBA4ISCDYQHBh4iCh7ICD4IaEAYJpCB4d/GwQuEGwasBDwYPBA4MHFw4HCj4uHA4QuULqyUDRgxCCRhC0Cn46CEwYbB+DhCYQa7DAAQyBcoIaBdQoLBawYrCAApRCHQILGKIT/C//7Eoh1DAAPvAYRRCIwkfEQpGD/AyDBQSBBCQQiGKQX+HwYiDKQXwGQRFDBYYyDNAYLCAwILCBQg+FHIgAEC4IKIQwKtCAH4AWnwKJPoKrEOAi3GaY4WJ/6KHW4ShIfwTbFAAMDCwX8A4UYHIrQE8AiFeYcHHwQiDKQZ6DEQZSCgYmDEQZGCj4uCEQQZBCYRtDNAPAg46Cg5hDv5aBBYI6Bn4aCRYInBDQIpCFwQTBGwQaBGQIuCn59Cn4uBSAgbDHoYuCE4JlCEwJjBCQUPEQUH/hjCFwaUCj/wHIKzDSgd/4AWBQAhhDcYTpDFwg5BUYYuE8Y5ELoufHIhdFaoguBYYbJESgjWDGgQHCH4IiDBQZZBCIIiCKAa7CIwIWCKAbPC8AWCKAZpCCgRQFIQhQGHQQADKAhOEKApGDAARQEIwZQHIwpQFBYpQFKQgWHPwYWHBYQWIEYREGL4YKJAH4AegIEDsCxGPIfgCwr/Dn6nFh6jCgKcGn/wEQQbDXgYqCn/4BQkDDwYPDFzV/JoUfB4RdOgI1DnjG/ACoA='))), + 46, + atob("GBo2NjY2NjY2NjY2Gg=="), + 94+(scale<<8)+(1<<16) + ); + return this; } var boot_img = require("heatshrink").decompress(atob("oFAwkEogA/AH4A/AH4A/AH4A/AE8AAAoeXoAfeDQUBmcyD7A+Dh///8QD649CiAfaHwUvD4sEHy0DDYIfEICg+Cn4fHICY+DD4nxcgojOHwgfEIAYfRCIQaDD4ZAFD5r7DH4//kAfRCIZ/GAAnwD5p9DX44fTHgYSBf4ofVDAQEBl4fFUAgfOXoQzBgIfFBAIfPP4RAEAoYAB+cRiK/SG4h/WIBAfXIA7CBAAswD55AHn6fUIBMCD65AHl4gCmcziAfQQJqfQQJpiDgk0IDXxQLRAEECaBM+QgRYRYgUIA0CD4ggSQJiDCiAKBICszAAswD55AHABKBVD7BAFABIqBD5pAFABPxD55AOD6BADiIAJQAyxLABwf/gaAPAH4A/AH4ARA==")); @@ -27,6 +28,7 @@ var sunSet = "00:00"; function log_debug(o) { //console.log(o); + } // requires the myLocation app @@ -282,7 +284,7 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - if (!settings.autoCycle) { + if (settings.autoCycle) { nextSidebar(); } draw(); From ef996391c656ff64ba261d865f4cb4545b0c48b7 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Fri, 20 May 2022 00:03:36 +0200 Subject: [PATCH 19/94] imported suncalc and trimmed --- apps/rebble/ChangeLog | 3 +- apps/rebble/metadata.json | 5 +- apps/rebble/rebble.app.js | 2 +- apps/rebble/suncalc.js | 143 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+), 4 deletions(-) create mode 100644 apps/rebble/suncalc.js diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index aec12e247..0f18538be 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -5,4 +5,5 @@ 0.05: added charging icon 0.06: Add 12h support and autocycle control 0.07: added localization, removed deprecated code -0.08: removed unused font, fix autocycle \ No newline at end of file +0.08: removed unused font, fix autocycle +0.09: imported suncalc and trimmed diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index c373ee202..b56d3a4cb 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,7 +2,7 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.08", + "version": "0.09", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", @@ -14,6 +14,7 @@ "storage": [ {"name":"rebble.app.js","url":"rebble.app.js"}, {"name":"rebble.settings.js","url":"rebble.settings.js"}, - {"name":"rebble.img","url":"rebble.icon.js","evaluate":true} + {"name":"rebble.img","url":"rebble.icon.js","evaluate":true}, + {"name":"suncalc","url":"suncalc.js"} ] } diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index 981773369..c34d20e1d 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -1,4 +1,4 @@ -var SunCalc = require("https://raw.githubusercontent.com/mourner/suncalc/master/suncalc.js"); +var SunCalc = require("suncalc"); const SETTINGS_FILE = "rebble.json"; const LOCATION_FILE = "mylocation.json"; const GLOBAL_SETTINGS = "setting.json"; diff --git a/apps/rebble/suncalc.js b/apps/rebble/suncalc.js new file mode 100644 index 000000000..d86f039c5 --- /dev/null +++ b/apps/rebble/suncalc.js @@ -0,0 +1,143 @@ +/* + (c) 2011-2015, Vladimir Agafonkin + SunCalc is a JavaScript library for calculating sun/moon position and light phases. + https://github.com/mourner/suncalc + + edit for banglejs +*/ + +(function () { 'use strict'; + +// shortcuts for easier to read formulas + +var PI = Math.PI, + sin = Math.sin, + cos = Math.cos, + tan = Math.tan, + asin = Math.asin, + atan = Math.atan2, + acos = Math.acos, + rad = PI / 180; + +// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas + + +// date/time constants and conversions + +var dayMs = 1000 * 60 * 60 * 24, + J1970 = 2440588, + J2000 = 2451545; + +function toJulian(date) { return date.valueOf() / dayMs - 0.5 + J1970; } +function fromJulian(j) { return new Date((j + 0.5 - J1970) * dayMs); } +function toDays(date) { return toJulian(date) - J2000; } + + +// general calculations for position + +var e = rad * 23.4397; // obliquity of the Earth + +function declination(l, b) { return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); } + + +// general sun calculations + +function solarMeanAnomaly(d) { return rad * (357.5291 + 0.98560028 * d); } + +function eclipticLongitude(M) { + + var C = rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)), // equation of center + P = rad * 102.9372; // perihelion of the Earth + + return M + C + P + PI; +} + +var SunCalc = {}; + + +// sun times configuration (angle, morning name, evening name) + +var times = SunCalc.times = [ + [-0.833, 'sunrise', 'sunset' ], + [ -0.3, 'sunriseEnd', 'sunsetStart' ], + [ -6, 'dawn', 'dusk' ], + [ -12, 'nauticalDawn', 'nauticalDusk'], + [ -18, 'nightEnd', 'night' ], + [ 6, 'goldenHourEnd', 'goldenHour' ] +]; + + + +// calculations for sun times + +var J0 = 0.0009; + +function julianCycle(d, lw) { return Math.round(d - J0 - lw / (2 * PI)); } + +function approxTransit(Ht, lw, n) { return J0 + (Ht + lw) / (2 * PI) + n; } +function solarTransitJ(ds, M, L) { return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); } + +function hourAngle(h, phi, d) { return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); } +function observerAngle(height) { return -2.076 * Math.sqrt(height) / 60; } + +// returns set time for the given sun altitude +function getSetJ(h, lw, phi, dec, n, M, L) { + + var w = hourAngle(h, phi, dec), + a = approxTransit(w, lw, n); + return solarTransitJ(a, M, L); +} + + +// calculates sun times for a given date, latitude/longitude, and, optionally, +// the observer height (in meters) relative to the horizon + +SunCalc.getTimes = function (date, lat, lng, height) { + + height = height || 0; + + var lw = rad * -lng, + phi = rad * lat, + + dh = observerAngle(height), + + d = toDays(date), + n = julianCycle(d, lw), + ds = approxTransit(0, lw, n), + + M = solarMeanAnomaly(ds), + L = eclipticLongitude(M), + dec = declination(L, 0), + + Jnoon = solarTransitJ(ds, M, L), + + i, len, time, h0, Jset, Jrise; + + + var result = { + solarNoon: fromJulian(Jnoon), + nadir: fromJulian(Jnoon - 0.5) + }; + + for (i = 0, len = times.length; i < len; i += 1) { + time = times[i]; + h0 = (time[0] + dh) * rad; + + Jset = getSetJ(h0, lw, phi, dec, n, M, L); + Jrise = Jnoon - (Jset - Jnoon); + + result[time[1]] = fromJulian(Jrise); + result[time[2]] = fromJulian(Jset); + } + + return result; +}; + + +// export as Node module / AMD module / browser variable +if (typeof exports === 'object' && typeof module !== 'undefined') module.exports = SunCalc; +else if (typeof define === 'function' && define.amd) define(SunCalc); +else window.SunCalc = SunCalc; + + +}()); \ No newline at end of file From 07b53c5893048917ef2bb9a0d05e35e8259b88b9 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Fri, 20 May 2022 00:17:55 +0200 Subject: [PATCH 20/94] removed pedometer dependency --- apps/rebble/ChangeLog | 3 +-- apps/rebble/metadata.json | 4 ++-- apps/rebble/rebble.app.js | 13 ++----------- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index 0f18538be..10720242b 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -5,5 +5,4 @@ 0.05: added charging icon 0.06: Add 12h support and autocycle control 0.07: added localization, removed deprecated code -0.08: removed unused font, fix autocycle -0.09: imported suncalc and trimmed +0.08: removed unused font, fix autocycle, imported suncalc and trimmed, removed pedometer dependency diff --git a/apps/rebble/metadata.json b/apps/rebble/metadata.json index b56d3a4cb..e28c67784 100644 --- a/apps/rebble/metadata.json +++ b/apps/rebble/metadata.json @@ -2,11 +2,11 @@ "id": "rebble", "name": "Rebble Clock", "shortName": "Rebble", - "version": "0.09", + "version": "0.08", "description": "A Pebble style clock, with configurable background, three sidebars including steps, day, date, sunrise, sunset, long live the rebellion", "readme": "README.md", "icon": "rebble.png", - "dependencies": {"mylocation":"app", "widpedom":"app"}, + "dependencies": {"mylocation":"app"}, "screenshots": [{"url":"screenshot_rebble.png"}], "type": "clock", "tags": "clock", diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index c34d20e1d..4fec172f0 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -238,20 +238,11 @@ function drawBattery(x,y,wi,hi) { } -function getSteps() { - if (WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); - } - return '????'; -} - // format steps so they fit in the place function formatSteps() { - var s = getSteps(); + var s = Bangle.getHealthStatus("day").steps; - if ( s == '????') { - return s; - } else if (s < 1000) { + if (s < 1000) { return s + ''; } else if (s < 10000) { return '' + (s/1000).toFixed(1) + 'K'; From d760fcdf9304529c6a5059c8077f99741624c75e Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Fri, 20 May 2022 01:26:11 +0200 Subject: [PATCH 21/94] "tap to Cycle" setting --- apps/rebble/ChangeLog | 2 +- apps/rebble/rebble.app.js | 38 ++++++++++++--- apps/rebble/rebble.settings.js | 86 ++++++++++++++++++++++++++-------- 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/apps/rebble/ChangeLog b/apps/rebble/ChangeLog index 10720242b..4b415c1c5 100644 --- a/apps/rebble/ChangeLog +++ b/apps/rebble/ChangeLog @@ -5,4 +5,4 @@ 0.05: added charging icon 0.06: Add 12h support and autocycle control 0.07: added localization, removed deprecated code -0.08: removed unused font, fix autocycle, imported suncalc and trimmed, removed pedometer dependency +0.08: removed unused font, fix autocycle, imported suncalc and trimmed, removed pedometer dependency, "tap to cycle" setting diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index 4fec172f0..2dc57524a 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -37,7 +37,16 @@ function loadLocation() { } function loadSettings() { - settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'autoCycle': true}; + settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'autoCycle': true,'sideTap':'on'}; + + let settings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true,'sideTap':'on'}; + let tmp = require('Storage').readJSON(SETTINGS_FILE, 1) || settings; + for (const key in tmp) { + settings[key] = tmp[key] + } + + if(settings.sideTap!='on') + sideBar=parseInt(settings.sideTap)-1; //tab to show is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false; } @@ -251,20 +260,19 @@ function formatSteps() { } function nextSidebar() { + if (++sideBar > 2) sideBar = 0; log_debug("next: " + sideBar); + } function prevSidebar() { + if (--sideBar < 0) sideBar = 2; log_debug("prev: " + sideBar); + } -Bangle.setUI("clockupdown", btn=> { - if (btn<0) prevSidebar(); - if (btn>0) nextSidebar(); - draw(); -}); // timeout used to update every minute @@ -294,6 +302,24 @@ Bangle.loadWidgets(); for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} loadSettings(); loadLocation(); + + + +if(settings.autoCycle || settings.sideTap=='on') +{ + Bangle.setUI("clockupdown", btn=> { + if (btn<0) prevSidebar(); + if (btn>0) nextSidebar(); + draw(); + }); +} +else{ + Bangle.setUI("clock"); +} + + + + draw(); // queues the next draw for a minutes time Bangle.on('charging', function(charging) { //redraw the sidebar ( with the battery ) diff --git a/apps/rebble/rebble.settings.js b/apps/rebble/rebble.settings.js index 91142d72d..4c0d57363 100644 --- a/apps/rebble/rebble.settings.js +++ b/apps/rebble/rebble.settings.js @@ -2,12 +2,13 @@ const SETTINGS_FILE = "rebble.json"; // initialize with default settings... - let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true} + let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true, 'sideTap':'on'}; // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings const storage = require('Storage') let settings = storage.readJSON(SETTINGS_FILE, 1) || localSettings; + const saved = settings || {} for (const key in saved) { localSettings[key] = saved[key] @@ -21,26 +22,71 @@ var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; var bg_code = ['#0f0','#ff0','#0ff','#f0f','#f00','#00f']; - E.showMenu({ - '': { 'title': 'Rebble Clock' }, - '< Back': back, - 'Colour': { - value: 0 | color_options.indexOf(localSettings.color), - min: 0, max: 5, - format: v => color_options[v], - onchange: v => { - localSettings.color = color_options[v]; - localSettings.bg = bg_code[v]; - save(); + function showMenu() + { + const menu={ + '': { 'title': 'Rebble Clock' }, + '< Back': back, + 'Colour': { + value: 0 | color_options.indexOf(localSettings.color), + min: 0, max: 5, + format: v => color_options[v], + onchange: v => { + localSettings.color = color_options[v]; + localSettings.bg = bg_code[v]; + save(); + }, }, - }, - 'Auto Cycle': { - value: "autoCycle" in localSettings ? localSettings.autoCycle : true, - format: () => (localSettings.autoCycle ? 'Yes' : 'No'), - onchange: () => { - localSettings.autoCycle = !localSettings.autoCycle; - save(); + 'Auto Cycle': { + value: localSettings.autoCycle, + onchange: (v) => { + localSettings.autoCycle = v; + save(); + showMenu(); + } } + }; + + if( !localSettings.autoCycle) + { + menu['Tap to Cycle']={ + value: localSettings.sideTap, + onchange: () => setTimeout(showTapMenu, 100, changedValue => { + localSettings.sideTap=changedValue; + save(); + setTimeout(showMenu, 10); + }) + }; } - }); + E.showMenu(menu); + } + + function showTapMenu(changeCallback) + { + var current = localSettings.sideTap; + const menu = { + "": { "title": /*LANG*/"Tap to Cycle" }, + "< Back": () => changeCallback(current), + "on": { // No days set: the alarm will fire once + value: current == 'on', + onchange: () => changeCallback('on') + }, + "1": { + value: current == '1', + onchange: () => changeCallback('1') + }, + "2": { + value: current == '2', + onchange: () => changeCallback('2') + }, + "3": { + value: current == '3', + onchange: () => changeCallback('3') + }, + }; + + E.showMenu(menu); + } + + showMenu(); }) From 3e275a51ae3bfef65a1a7a66de7a639d6ee539df Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Fri, 20 May 2022 01:42:18 +0200 Subject: [PATCH 22/94] - sideTap setting converted into number - sideTap setting menu is radiobutton --- apps/rebble/rebble.app.js | 8 +++--- apps/rebble/rebble.settings.js | 45 ++++++++++++---------------------- 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/apps/rebble/rebble.app.js b/apps/rebble/rebble.app.js index 2dc57524a..8ba61f818 100644 --- a/apps/rebble/rebble.app.js +++ b/apps/rebble/rebble.app.js @@ -37,15 +37,15 @@ function loadLocation() { } function loadSettings() { - settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'bg': '#0f0', 'color': 'Green', 'autoCycle': true,'sideTap':'on'}; + settings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true,'sideTap':0}; + //sideTap 0 = on | 1 = sidebar1... - let settings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true,'sideTap':'on'}; let tmp = require('Storage').readJSON(SETTINGS_FILE, 1) || settings; for (const key in tmp) { settings[key] = tmp[key] } - if(settings.sideTap!='on') + if(settings.sideTap!=0) sideBar=parseInt(settings.sideTap)-1; //tab to show is12Hour = (require("Storage").readJSON(GLOBAL_SETTINGS, 1) || {})["12hour"] || false; } @@ -305,7 +305,7 @@ loadLocation(); -if(settings.autoCycle || settings.sideTap=='on') +if(settings.autoCycle || settings.sideTap==0) { Bangle.setUI("clockupdown", btn=> { if (btn<0) prevSidebar(); diff --git a/apps/rebble/rebble.settings.js b/apps/rebble/rebble.settings.js index 4c0d57363..37b7be3a1 100644 --- a/apps/rebble/rebble.settings.js +++ b/apps/rebble/rebble.settings.js @@ -2,7 +2,8 @@ const SETTINGS_FILE = "rebble.json"; // initialize with default settings... - let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true, 'sideTap':'on'}; + let localSettings = {'bg': '#0f0', 'color': 'Green', 'autoCycle': true, 'sideTap':0}; + //sideTap 0 = on| 1= sideBar1 | 2 = ... // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -49,44 +50,28 @@ if( !localSettings.autoCycle) { - menu['Tap to Cycle']={ + menu['Tap to Cycle']= { value: localSettings.sideTap, - onchange: () => setTimeout(showTapMenu, 100, changedValue => { - localSettings.sideTap=changedValue; + min: 0, + max: 3, + step: 1, + format: v => NumberToSideTap(v), + onchange: v => { + localSettings.sideTap=v save(); setTimeout(showMenu, 10); - }) + } }; } E.showMenu(menu); } - function showTapMenu(changeCallback) + function NumberToSideTap(Number) { - var current = localSettings.sideTap; - const menu = { - "": { "title": /*LANG*/"Tap to Cycle" }, - "< Back": () => changeCallback(current), - "on": { // No days set: the alarm will fire once - value: current == 'on', - onchange: () => changeCallback('on') - }, - "1": { - value: current == '1', - onchange: () => changeCallback('1') - }, - "2": { - value: current == '2', - onchange: () => changeCallback('2') - }, - "3": { - value: current == '3', - onchange: () => changeCallback('3') - }, - }; - - E.showMenu(menu); + if(Number==0) + return 'on'; + return Number+""; } showMenu(); -}) +}) \ No newline at end of file From 542d9f6fec381e33a49c1540b0ebda029e464891 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 20 May 2022 13:13:54 +0200 Subject: [PATCH 23/94] Version 0.09: Larger font size if colon is hidden to improve readability further. --- apps/bwclk/ChangeLog | 3 ++- apps/bwclk/app.js | 32 +++++++++++++++++++++----------- apps/bwclk/metadata.json | 2 +- apps/bwclk/screenshot.png | Bin 2908 -> 2725 bytes apps/bwclk/screenshot_2.png | Bin 3225 -> 3043 bytes apps/bwclk/screenshot_3.png | Bin 3508 -> 3133 bytes 6 files changed, 24 insertions(+), 13 deletions(-) diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index ecf441925..ecd0c355f 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -5,4 +5,5 @@ 0.05: Included icons for information. 0.06: Design and usability improvements. 0.07: Improved positioning. -0.08: Select the color of widgets correctly. Additional settings to hide colon. \ No newline at end of file +0.08: Select the color of widgets correctly. Additional settings to hide colon. +0.09: Larger font size if colon is hidden to improve readability further. \ No newline at end of file diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index c22ec050f..5bfec4097 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -44,6 +44,16 @@ Graphics.prototype.setLargeFont = function(scale) { return this; }; +Graphics.prototype.setXLargeFont = function(scale) { + // Actual height 53 (55 - 3) + this.setFontCustom( + E.toString(require('heatshrink').decompress(atob('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'))), + 46, + atob("FR4uHyopKyksJSssGA=="), + 70+(scale<<8)+(1<<16) + ); +}; + Graphics.prototype.setMediumFont = function(scale) { // Actual height 41 (42 - 2) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAAAB/AAAAAAAP/AAAAAAD//AAAAAA///AAAAAP///AAAAB///8AAAAf///AAAAH///wAAAB///+AAAAH///gAAAAH//4AAAAAH/+AAAAAAH/wAAAAAAH8AAAAAAAHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAH////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gAAH+AAD+AAAD/AAH8AAAB/AAH4AAAA/gAH4AAAAfgAH4AAAAfgAPwAAAAfgAPwAAAAfgAPwAAAAfgAHwAAAAfgAH4AAAAfgAH4AAAA/gAH8AAAA/AAD+AAAD/AAD/gAAH/AAB/////+AAB/////8AAA/////4AAAf////wAAAH////gAAAB///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAAAAfwAAAAAAA/gAAAAAAA/AAAAAAAB/AAAAAAAD+AAAAAAAD8AAAAAAAH8AAAAAAAH//////AAH//////AAH//////AAH//////AAH//////AAH//////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAA/AAAP4AAB/AAAf4AAD/AAA/4AAD/AAB/4AAH/AAD/4AAP/AAH/AAAf/AAH8AAA//AAH4AAB//AAP4AAD//AAPwAAH+/AAPwAAP8/AAPwAAf4/AAPwAA/4/AAPwAA/w/AAPwAB/g/AAPwAD/A/AAP4AH+A/AAH8AP8A/AAH/A/4A/AAD///wA/AAD///gA/AAB///AA/AAA//+AA/AAAP/8AA/AAAD/wAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAH4AAAHwAAH4AAAH4AAH4AAAH8AAH4AAAP+AAH4AAAH+AAH4A4AB/AAH4A+AA/AAH4B/AA/gAH4D/AAfgAH4H+AAfgAH4P+AAfgAH4f+AAfgAH4/+AAfgAH5/+AAfgAH5//AAfgAH7+/AA/gAH/8/gB/AAH/4f4H/AAH/wf//+AAH/gP//8AAH/AH//8AAH+AD//wAAH8AB//gAAD4AAf+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAD/AAAAAAAP/AAAAAAB//AAAAAAH//AAAAAAf//AAAAAB///AAAAAH///AAAAAf/8/AAAAB//w/AAAAH/+A/AAAA//4A/AAAD//gA/AAAH/+AA/AAAH/4AA/AAAH/gAA/AAAH+AAA/AAAHwAAA/AAAHAAf///AAEAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAf///AAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAP/AHgAAH///AP4AAH///gP8AAH///gP8AAH///gP+AAH///gD/AAH/A/AB/AAH4A/AA/gAH4A+AAfgAH4B+AAfgAH4B+AAfgAH4B8AAfgAH4B8AAfgAH4B+AAfgAH4B+AAfgAH4B+AA/gAH4B/AA/AAH4A/gD/AAH4A/4H+AAH4Af//+AAH4AP//8AAH4AP//4AAHwAD//wAAAAAB//AAAAAAAf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAAAD////AAAAP////wAAAf////4AAA/////8AAB/////+AAD/gP4H+AAD/AfgD/AAH8A/AB/AAH8A/AA/gAH4B+AAfgAH4B+AAfgAPwB8AAfgAPwB8AAfgAPwB+AAfgAPwB+AAfgAH4B+AAfgAH4B/AA/gAH8B/AB/AAH+A/wD/AAD+A/8P+AAB8Af//+AAB4AP//8AAAwAH//4AAAAAD//gAAAAAA//AAAAAAAP4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAAAAPwAAAAHAAPwAAAA/AAPwAAAD/AAPwAAAf/AAPwAAB//AAPwAAP//AAPwAA//8AAPwAH//wAAPwAf/+AAAPwB//4AAAPwP//AAAAPw//8AAAAP3//gAAAAP//+AAAAAP//wAAAAAP//AAAAAAP/4AAAAAAP/gAAAAAAP+AAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AAAAH+A//gAAAf/h//4AAA//z//8AAB/////+AAD/////+AAD///+H/AAH+H/4B/AAH8B/wA/gAH4A/gAfgAH4A/gAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAPwA/AAfgAH4A/gAfgAH4A/gAfgAH8B/wA/gAH/H/4B/AAD///+H/AAD/////+AAB/////+AAA//z//8AAAf/h//4AAAH+A//gAAAAAAH+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAD/8AAAAAAP/+AAAAAAf//AAcAAA///gA8AAB///wB+AAD/x/4B/AAD+AP4B/AAH8AH8A/gAH4AH8A/gAH4AD8AfgAP4AD8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAPwAB8AfgAH4AD8AfgAH4AD4A/gAH8AH4B/AAD+APwD/AAD/g/wP+AAB/////+AAA/////8AAAf////4AAAP////wAAAH////AAAAA///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAD8APwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DxcjFyAfISAiHCAiEg=="), 54+(scale<<8)+(1<<16)); @@ -304,17 +314,13 @@ function drawTime(){ g.setColor(g.theme.bg); g.setFontAlign(0,0); - var timeStr; - if(settings.hideColon){ - var hours = date.getHours(); - hours -= hours >=12 ? 12 : 0; - var minutes = date.getMinutes(); - minutes = minutes < 10 ? String("0") + minutes : minutes; - timeStr = String(hours) + minutes; - } else { - timeStr = locale.time(date,1); - } + var hours = String(date.getHours()); + var minutes = date.getMinutes(); + minutes = minutes < 10 ? String("0") + minutes : minutes; + var colon = settings.hideColon ? "" : ":"; + var timeStr = hours + colon + minutes; + // Set y coordinates correctly y += parseInt((H - y)/2) + 5; var infoEntry = getInfoEntry(); @@ -324,7 +330,11 @@ function drawTime(){ // Show large or small time depending on info entry if(infoStr == null){ - g.setLargeFont(); + if(settings.hideColon){ + g.setXLargeFont(); + } else { + g.setLargeFont(); + } } else { y -= 15; g.setMediumFont(); diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index 60634e26c..eba1449a6 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.08", + "version": "0.09", "description": "BW Clock.", "readme": "README.md", "icon": "app.png", diff --git a/apps/bwclk/screenshot.png b/apps/bwclk/screenshot.png index 302117ea9634f90ff61126e8ed98a035acc7f7ad..55091342296e3d342175e44c5f1b199b3e89e748 100644 GIT binary patch literal 2725 zcmd6pSv1>=7RLYiOIwMl5o%Vmwy3#E(Go+=9Sv2Hqlk#sP)dYK(3vA>drFaBl&eKj z1P9d!RUHg5i-WYKE|E5J#C*6tulM0TpKq=GeQWLC+g|(OyLZOhRSK>Q2LM3I?X=Um zpGp6F#P|MmTGK50XF#r>b9Dr2`&1VI03Ph-iO@kTu?%g+-iPAU+0=6Zj zM3n&f&Z5r?nzCGjb-&aZ`U8<`=y*XDsY^`;x*0Wd z3_d5m2VOSY7exL4+Z5o8jcW>&p6ehh?Fn)!1daL_^Va(0aRm%iSo9J(`hLf z>#Sut{kc8+X%^t&ok1mb5R>1Qr#^eIsQp4ZE|X$tkGk*a7nVEXtX=$p z##PMgTuMU?MRQCOPf_;^K#|nmjOlJZog=Z}N^xp+;qu3G?Qa8F7Nr4KAn)R`htIq8 z@c%3PORBw_s+3(BQDG7)kGcv-r1#^N_h0#kQ=*3r7v*%J)uJGDh3P3h0b0D5e}h2M=1xg*?z37yGp*C$fGqO3%JfkH zuYLs4|3mL2T(_kUl*YA3(hJ<$cJ=429Je*Zn@>GhyZ+Tn5U9^MiwMdILaZ|&v zEJY;q&45KTnII-k=HasEFV)EOY~p~N%tS1SJyT&0$IRMUg4UpZT{xU6 z+jjQ+8m)ftqj7fQQe`UO$T~h6fk^>BNaSMEiEF+DOQED8`6VH!96{LEElQT^%9Hl0 zIiZ#aM34thm5-G1-{#3D_tIg81rMcuOqzaKAkQs#XeJf@JUYZA@7+`55_2=Se%&>3 zrgA-{f;y^^@3Z(;_~sjR%ORO!5y>5>c5c7-tAmzT%*Xb;Yai#K<6k(PmI#4;F^+)^ zg3_C!?O@#2n-o0A-!U4I#>^i2#nc*(mcuMa<^WkYCv9tn?4vHFJgUXPVl29H1?`aS zQL9a{eev#EJhPdu)7%|v>Fgv4&Ega6@aGAaC|a9?-w)&HK+0GK77R{x&=>v7s54)G zhU3kx*Yu^-r{`511QkJne6#*Rj#!pwvHYlp2G(IK9)+tgxFj}0sLr?0wz}Zkj?#C{1bEn0JE6r@9m@!`h{!n$BHILu9KoQ7sEL22*@@0M7vke zW^_f39D?f`JBIxEOaBW}+uu~Zc@%QrXbylJmB*emg*FF&doG9Mo{L>YqDWg|Xm`_p zB#1r2j80ou+IX;VXQ*t4)KF2GD;KfiiW^v3SY}N|!Izhm+k5y81c`w?Me zQ{?jZm!fXYd?Gc5bapvnD8jA==fh*Sm#((HL{?3d>c^#Z>3ih3PMMGxrR)ku0-|$z z^jRul?R{ZOVgjS^hVTz5`bERY7mRj!lLlk_UrjtSMr3^0Dk3(c7~c%6iaSe*mVO~i z@;{y<9%xHzzjkt_d2aWHum}hi7D4C-p5Su|d5F})WFcRJb}BhJC46~1TQcX2&rqFi zzd?Bkc12gTveh8v+5c}F^)%X;yPakWni?Q3*j-KPZGal@$zl&+>624WVIJixZ26e5c=#@y*B9j$viELL*@6LgbASk_HRJO zNex9<&@8$DpaIbmB;B%_AuHss;&-v|)1 zFUweH`) zH1+Sr4eo-QA_P}~^qih3=08~9nfqB;0dfp1+7s=oVbDSR{+4&;aq#4uTNH3jc{hG0 z6sm<&G9_UDBMfySb=>J%qIJo0AN9SM={KUgaSSbY|M*lg^GQ358f%5k(7}C3GSb;& z8zR(dF$6p~wt}72dUNK)x3&(|gzN6g11j$I-syW64wv4ZyWPBKC_xXU>&5W#N8_WR za?wD; z7Dy$R^*uvw+`8H6<(qcMiM_vUtF)!5h?!T#*85j@nP55iE`zEpQUD(ye0Zc}`!zF{QV{rT25;hmVb(BB|U7 scCdleQbMjsL7QXO<;#)(U?4F5z|VXl&k4Nvvv&e+&fZS7j+pfS0`p=8UjP6A literal 2908 zcmdUx`#aN*7r+_A+?$ZX%I%XvmRx6wVJ=A&Ys2i*({IIxyfPj>}owe(J zulsL`iR{ZSBkWjFQ?qf1}BZ&`pfC48v}Ssp(Yzru>l+CyT6uR zl7@OcTAPGwKfO+8sR1xOdcl3tIw!jEY3Uk`EQ<-{Ck5W8Z~Zf;j@hT5F!M*wICqm8VQC6NNKq2vluz%1f3f8>^woEoEaasZM20n0 zrZMEpRkrz#_x@HsmYe2#%_`zbZAjU&A)LEJ{8&-PG1N*s*AptqJ@7{hi@13fQ4;$cGq;^Gx;VmypY%U@DX$L*Te@jIgEt)gqXQ0l33vy zKkpQG8`V2;>Xx=X^zY|#8B+miThSI1O*t!<`Au2ut4Cu@A&C)eQ~oR%Xe&tFFeA&0 z%A2Z*nJxG$o1KjZ%7b#UJbXnhCJs>0V&DH7P%`(`d10?w+`ixo31*0rLJhS~N+z&; z-l9$^tlz%+qtP0@5G2ZuS^+QfjGbb-@_v>m1o&?%Cq)gdGllV=sTf>g5&u6E07FmX zt=lr43)Vkz)?yxN|~uvrQQ5hr84#kNs+;P4lgEVG<~d~xjfU*U#y2u`@~$_^bm?RU$-jO>A`UVD^8vUL<%Q3a`d4}=2tOP+ucEI{# zVUis)4SU<;S-!ijm2QazI_~U-Qq1UV-gS@CO4V7iff=d7l`?aBH)lRjRODIwEkV>x zsmwl`h4NJgf-@_N<{x=md+?&0q0RJ4OnZZh?6^u!pU?b*bM``wLPAG77SKm$hh=lJ zD$++-Lf!>*KB9*^1{%0-Q$m=Xg4J|G;dfa$b4~b5<>=B-VC&u3d2`*?4muYr3%E0muLH|oF#a(K zr0>$Hmksf@Cs+Q?GE1w0;sW z+M(8jb-};en9G%M%m+wB^bJ^-(G&TuY$lE877?pjrUokg5@*}igeC+9ixMG|mOHkl zxf0aKR%lE9W^ZJTRxMdpQSo_OB4pCZbEisJLtnl!npY5LFX4xiY$I<)Hf63|`=sv-1L=OaQ$!uJ`C!0&xydvM2nJm1bR%5Oy ztZ^OU4qjH{{rGv8ggHHTK+s4KGNAQ5wq~E44Amsc<~6ev#ZIMScnLZJ>UXXysbw zcAi+p59ybH7nvw=Wy97As(*;8HiM?Jm~A)da(^@(1$6W-3&zeTOkKO0FpuM16f~Hr z--w_0rpagnd0=&cJd-d;ZfsSoosM&el1t8feV|V-wnhd8_~|If_db`(o(Z^RtmWtv zRKrch(cE7coiaGdX5dhugiI9MLk(VIqXt*=`{qAc{Z4-IT8~c;VdJ&#^{2(-seTKk z5H}^niB+uAw{GK6k}x&c$0*tjg^jsgRaN~(Y>-rG(I_6A5%KbcPr3SFP5Zgr-OupR z#cXQRE4^BEJ;0z@ch=Gh^xMtk#G&|d>lsJR@C<3(=!E{vn^pWy)p16+%j=Ou#x^6) z--~Tg1k+4_suL>&C~LV7>SIKm$!>kNakdL_%;opT0An8{$6N{<9voG}h*K3QQLX{` z4LO(C#1YD6E|d@*&@~K0Tr-z7TpM*SpAJUU2@iSV7rdEYy*)!fe$n1REZ!2?&mTKY zo1Q&$Xt>h@rorouCP0+O6zWGBg+$9_o=(za<`8w@!FYdeVsG!OjfUy#jeFz>mc>0t zmH=w5>2R3=kM=F*J1T=7?2nNvYK`>0iY%9j0#26M6T14G{}FQIobZQ^{lUxsc}}hc z`arl3d=m#d4#J@F=|yzsB@~V$z0Vc4pC#ErCc#diQi=Nkil#Wnry{2i{a;0g4lV(=Jc8o4Yduvoma?S_%(A=X=iAjl5L}K$8O-xOwx!YE5J)^ z|9AvhrG?K^<~zWY)oY6z@6uK-_zzGG$%ks(XRyfo2U~(-td6waPYxI9Orf7#pQ;C8 zx-s}i^Z6E6I*8Odi)9;$xB6Hj>BBUTp}M{N;m z2-;kqQUDnU#FyQ$^Q2Xj-|)lw1a8e6oy|Zgc6=~7SfM1ny6?&K3d(u4qre{k1}D9*wW+G(`TJJ1=M)s8&VeFLPV{Slps~={ fCv*SHtGhCRq~6N$(MJ>e@3Mfs%>`?!6(QwcQNChv diff --git a/apps/bwclk/screenshot_2.png b/apps/bwclk/screenshot_2.png index 9614131ece8acad8d25590f149185d720e817b9a..ccbc9aae1626f4b024081c9c8f30bbaf45d89213 100644 GIT binary patch literal 3043 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 CkEnzI literal 3225 zcmb_fX*AT28vf0g8DkqW2~9|vtc@kf8jW=>>PVq&0c9pb`z!3tZD;*HMQZTrd!s=l-A0ZD94 z;2qAn7fmrztY({htaNRAu=gwGz$zj`j%^6KI%+)LD+eG_$VyufXln}R%?6%E*qtGO zuFg6L3$Tw~DtMA!sURLDO(!!yaif`b8OiSi+?3hAa3s5QpohuDK80v)ZM~}XWp_=V^8e&J`B`Gtq%p~k@r@-bUWGMN%o%A5>lzeIs#SpsGpk>oRfwo0vG!47UXzZ zB$lHLvo@Tt@iw7RKFSm4gA2>Iek>@K%{km2= zP0nR*Xi(>QbrRWD4=B&tTzRHjnS?omv4oYO&C#8q&+@?@n(QK+Jux;`e<;hWd@Z+& zK`(fb#iis3e`hX76>j}nfo0v4N-juTtTG3qfYuX+y?$b5Jp;gpdqtLiCLFohEQyOg z`chbEHLQ5R0hN|o6D-=WtDi^Iq}@)@-`4xFIf-$ze3zgvA(r}D;a27V7J>lR+Gm{= zBWj&ErRYHFaREi}dBm>oV3YKugO%3h7VSD>BKl*v+7abB!pVE($0dw3Yc+G%LV>i= z8(e|A#v3~87C^|W3FIm01#w+)7?qt$`0r*87m5bkG?E+9_R zF`D0RzjQ2sKTx%^6jHI{$uucS2Gj*+jY0VgJ?Kg~q5W2T2#0@`=fw=IF;!dtsF6ZTsr zU$BjI8lD4>f3v#sqwJXqdS-68GwQ;vupesNlD>+8am{A98jDEUY#`RB}a;lS;fI3ebVGUL|8O&aqir6N=(+Tj z#K`|g`#s$B`cziNy_3f0HdY82<~v3;pr%=PBz823jR2=Ur?hoMOj?86yMe5kh;u+v zq%i9SOG1Cq`lxcJ`MrrZstA@Qw9FcR#O3{4t*k5Z`CZdFLT*b0S;;$p-{e=)H)^Da%xMJO z9?uP06X;?92`;oZFbIQ8=3xDQQLZ`SJkzHHq;3^JVLQFmt4~!RGq2N$o_b(1epkmtfO+3Hlq~gsrJ(~o(TwsA0=NQ+YKrvIv29CQH`&>%!>a8G zAi$J8kEGX_&Gs~U1!qtcIB1)%5|H?~p$FeL8^iVl#OzCbgnD7m#KuP=El&v%Oe#T^cLbm zuB$tatZvGE}y$5I8b2!r{ z@_vVVGKMmrs`0~I{LC{}(V%2ti>~SWFOIpRm8qQE76$)5GrwWLTl5Nt_zajC4nDS9 zw$I$F;dv#SUT|i4AnWPf7He^pv;m^N|NG*SiYbVwO`u<13oU7s2pmm$s+JUc?ECQmE?T_^F5iAXQ5=V^9-Hi5ZJcj(G_AnpjDx_9SH)xT8-!BwgG{BQ%1#MJT#CU zjvXxlAVz5~olW4#z`klF8EXhMLC&z5$}I|~ZF)JS2yZ;Ee{djXy|FpqU3H<&XM!R=uWz2N^|?`#N8G6b6VQQ64!7 zQMICO^6HKl^bk6$_rsKkHsvj4jkrFyc~q1;D{z)TY_W5HGDYPe&h_#-mR-k`qzs6~w@c{i1xEZ%9v zA??0oYnm9L6<(E%hQDP63N8)pxa(XHIH_K1_l@o&&fvd$%Y;tjoFz zJ3r{$DK5yqQz1?>a8+o=G$IL~9|czAyr&C&VdZPL$80J@Bw%}WKaC%n%II1Bcm?>1 zstRi$o#(AWGxff7Vwdm!J_5Z2y52`3l^}S#e@9@_E NObpEpD)ihU{{vEc?Faw> diff --git a/apps/bwclk/screenshot_3.png b/apps/bwclk/screenshot_3.png index 148f005e63c27d44f43a6dd8afab217f566a7eec..5bf7083f0c1b9c9a10e7f86848dc1eb2adf3a682 100644 GIT binary patch literal 3133 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 PfwM6&x^7sDc76IkHAHgo From 53a1bf8c7d689906073f726970e539ca97dc0f31 Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 08:52:31 -0500 Subject: [PATCH 24/94] Fixed the readme with better words --- apps/pokeclk/README.md | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/apps/pokeclk/README.md b/apps/pokeclk/README.md index 6a76623c9..1903b1646 100644 --- a/apps/pokeclk/README.md +++ b/apps/pokeclk/README.md @@ -1,7 +1,17 @@ -# About this Watchface +# Poketch Clock -Based on the electronic device from the Pokemon game. +A clock based on the Poketch electronic device found in Sinnoh -# Features +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Features Has a dark mode + +## Requests + +Please file any issues here: [https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug](https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug) + +## Creator + +Eleanor Tayam From 9237616514048504f8ecec52e60ae40b24237c14 Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 10:47:44 -0500 Subject: [PATCH 25/94] compressed the color image --- apps/pokeclk/app.js | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/apps/pokeclk/app.js b/apps/pokeclk/app.js index 8c1a00556..17a487bc0 100644 --- a/apps/pokeclk/app.js +++ b/apps/pokeclk/app.js @@ -8,9 +8,10 @@ const font = "Vector:12"; const locale = require("locale"); var img = { - width : 176, height : 176, bpp : 8, - transparent : 254, - buffer : E.toArrayBuffer(atob("/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXAAAAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcAAAAXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcAAAAXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwAAABcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NAAAAAABcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXAAAAAAADQ1cXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQBcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwADQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXAANDQ0NDQ1cXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ1cXFxcXFxcXFxcXA0NDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDVxcXFxcXFxcXFxcDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ1cXAAADQ0NDQ0NDQ0NXFwAAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDVxcAAANDQ0NDQ0NDQ1cXAAAXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NAAAAAA0NDQ0NDQ0NDQAAAABcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0AAAAADQ0NDQ0NDQ0NAAAAAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQAAAAAAAA0NDQ0NDQ0NDQAADQ0NDQ0NAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXA0NDQ0NAAAAAAAADQ0NDQ0NDQ0NAAANDQ0NDQ0AXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFwNDQ0NDQ0AAAAAAAANDQ0NDQAAAAAAAAAADQ0NDQBcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDVxcXFxcXFxcXA0NDQ0NDQAAAAAAAA0NDQ0NAAAAAAAAAAANDQ0NAFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcDQ0NDQ0NAAAAAAAADQ0NDQ0NDQ0NDQ0NDQ0NDQ0AXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFwNDQ0NDQ0AAAAAAAANDQ0NDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDVxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ1cXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NDQ0NDQ0NDQ0NDVxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcDQ0NDQ0NXFxcDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ1cXFwNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDVxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFwNDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXA0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ==")) + width : 176, height : 149, bpp : 4, + transparent : -1, + palette : new Uint16Array([25804,806,0,21514]), + buffer : require("heatshrink").decompress((atob("iIA/AH4A/AH4AGgAA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4ATgUiIP5IVK/5IVgMSkRX/K5MiiJXJiMSJ/5YJiJX/K7BYHKwJjKAH5MKK/5YWBAZX/K65M/LB4AHJf5XWJX5X/K98RiBM/K/5WtK/5XQgEiKokCkBN/K/5XmkRXEiUiK/5WOK5EjJf75BBZJUBKoshAYRX/K/77aiMQBYYHCK4kSAoRYBK/5X/K9IAFK/5XXiJX/K45QIK35XcK3pXHLASu/LipXPKX5X/AChHKK54A/AH4AUXKgaPAHhXQiBN/AH4A/AH4A/AAY"))) }; var night= { @@ -18,6 +19,7 @@ var night= { transparent : 2, buffer : (atob("ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERABEREREREREAEREREREREREREREREREREREREREREREREREREREREREREREQABERERERHwABEREREREREREREREREREREREREREREREREREREREREREREREQ/xERERER/wERERERERERERERERERERERERERERERERERERERERERERERERH//xERERH//xERERERERERERERERERERERERERERERERERERERERERERERERH//xEREf/xERERERERERERERERERERERERERERERERERERERERERERERERERH///////ERERERERERERERERERERERERERERERERERERERERERERERERERER////////8RERERERERERERERERERERERERERERERERERERERERERERERERH/////////ERERERERERERERERERERERERERERERERERERERERERERERERER////D///DxERERERERERERERERERERERERERERERERERERERERERERERERH////w///w8RERERERERERERERERERERERERERERERERERERERER//ERERER//AA///w/w8REREREREREREREREREREREREREREREREREREREREf////EREf/wAP/wAA8PERERERERERERERERERERERERERERERERERERERERH////xERH/8AD/////DxERERERERERERERERERERERERERERERERERERERER////8REf//////////ERERERERERERERERERERERERERERERERERERERERERERH/8R/////////xERERERERERERERERERERERERERERERERERERERER////////Ef////////////////////////////////////////////////////////////////////////////////////////////////////////////8RERERH////////////xERERERERERERERERERERERERERERERERERERERERERERERH///////////EREREREREREREREREREREREREREREREREREREREREf/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w==")) }; + var time= "10:20"; function time() { //numbers @@ -31,16 +33,14 @@ function time() { //numbers const damo = d.getDate(); var dayMonth = mo+"-"+damo; - - + // time require("Font4x5").add(Graphics); isDark(); g.setFontAlign(0,0); //g.setFont("6x8:4x5"); g.setFont("4x5",7); - g.drawString(time, width/2, height/2); - + g.drawString(time, width/2, height/2); // date require("Font4x5").add(Graphics); g.setFontAlign(1,1); @@ -64,19 +64,15 @@ function draw() { //poketch background g.drawImage(night, 0, 25, {scale:2}); //poketch is life } else { - g.drawImage(img, 0, 0); //poketch is life - } - + g.drawImage(img, 0, 25); //poketch is life + } time(); } //program start -// Clear the screen once, at startup g.clear(); -// draw immediately at first draw(); -var secondInterval = setInterval(draw, 1000); -// Stop updates when LCD is off, restart when on +var secondInterval = setInterval(draw, 1000); // Stop updates when LCD is off, restart when on Bangle.on('lcdPower',on=>{ if (secondInterval) clearInterval(secondInterval); secondInterval = undefined; From 09d3e40e1a74e8426c8fb836712f550f24f2c1b9 Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 10:48:49 -0500 Subject: [PATCH 26/94] Add files via upload --- apps/pokeclk/screenshot (1).png | Bin 0 -> 2354 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/pokeclk/screenshot (1).png diff --git a/apps/pokeclk/screenshot (1).png b/apps/pokeclk/screenshot (1).png new file mode 100644 index 0000000000000000000000000000000000000000..1e17a632b5325553e83aecf6bdcfd339b9512d48 GIT binary patch literal 2354 zcma)8dpHwp8)w!`TH7e3mmH=Pjkofq$YBg~m_yDsM#*6xn@_w%nE04P?_Q0HMiMeC zhs`03luL?>9CC<-@`kmM*lWhOzJIwx}N90uIG0>_kI2D`*%OrO?AWCL-woh zmywZyU>s~cq?Yw_gF(`>p0gMzHL|fD_9&UU!C$`0$beTdw$`2rf&7x`_yuDyn!mUA z*IUQf`>&thwsJ`8SgL4@bV89o^fb`wIMaN#5DGo?gPW6f+wNdvs(D%(92Ei8;*ETI znE=cMIVQ=-79KqIT9va@Q8TfozuITp1QSK=Bo{t;&0HvB@5XKrfW2cm% zCkwPo4xW#t$eS3OkUt+j1h651aTjjk>A%vn3>CDD=M|M1isn^6pVXJa)BrZTH%C?* za{mAZV`M1spdt~DXANTwIz1UI?Maz269+Qw4&-q{bKM|2f>XfgoZPUE#!?k)8q^_KPh z`zcbmuDBaHpoW3bfiShTOzO}+&Hu8|CVxH<@AujvorOr_W*a#tBZZ})r=YqQ=_rDf z?Eg^hW2z@y5QUZWx~Fz@ai$hNVjuJkCzMZNBscmvV~opSLzm965B!@RT~jOGW_Hbu zIX&$qk;6lb>8XB2qj?!t0$DT5(xi zmzCbDOt*pU~FZ%G9u9$hXI z9pHc9Qy%2bR8yX;J{X4`Vm0*Ci5|Ywi9>T!jAt4qtRZ9u zC!C21j;d68S06^3T(Bm9S5vm%nk9PmFQN$%ZUT(|*|{m~1IAWdKXxUKf2%02m}bHn zyD-iR__JqfP#PLvpTOqpnO)02G5P+w20%Q@bs3B{&D>n>3vgC~hvhGQHk!C8bt{&2 zC%I!D-@o+es_XkWX*H7aWE~!pl*&Rv)!P(hrI{gF=c@=@_x>ZTrHG~)CDR*6K5l<( z8wiOypV?#|3Ic9wlj+jH{ZmNK7hw|T;zdu=^H9akxRmjDT31$}G}kQ^Ak9;#c9SPNQ`l*lB4Q;){+F_M8y(1#;E;My(lr+!mzMEbwX*)*(&se36pSS6N zf<0JG6OFeU$1Dus&AYU3q-M^FMI?cN&#u!_D<$YvH}TK zz5npDF5nCcu;j3)dUGdviayp_*OS|K<>R-?{I z@I@^FRnnGm`&+PMO?Z>B5!%BrK>iexugLiq69dc{LyQ&~8PoiY<6lXvUZSvbI<~Cnj!ZKag-cbKIf{!C>;4* z~%Y51;t5N3LwQc<2W@*`>l1HBsH9@%eh z(63EKt+Opmn{(D3oN3wl+a!s^6E6Krn3I{MAgps|^`fz;yXMR2W_j(M%56AcNr$}B zKswy-?oy-SGo3#cSgp|x11ULTHRAA2SWH1}Jc@_XiGVCuiJ!dl+HKz2nyQR+g%sC-=)C}n<-$ISvXU>lv}PJgiG{1JEziqR>ancl?^)co z+^oB;JNqa#%6~0y+VF6;6k%I}6|Y8_xxJ&!LM~`uMW$NwmVs?;5+7Z%;Gv;Zs$H}6 zK_xU@H?8qY5;f*A*!*_J0H1AWmO3L;>h7>ggnP&x)AVgUJi4qcC?MnJx(CZ0#IH=WE% zTAqpwj#7epS4(#2F9Ic-Q|P2Q1XxeFcP50vHKMUWc%6E7*LY0pkWay>R6Au+l?q!) zc^#B~0l5miT^stT2O{PN`Xo z8T8RI*0JDZ?;%*84>!k?vn0nf)Knq^pa1s7TzF=cq~fZt8vo-sJYi!py?z(^YTEnz zuIk#Zqyu9w#@PyV$b$Q~q5)2G=r6^UMla0; literal 0 HcmV?d00001 From 83ba058b39b65c9ce49dd1395de29a95de06ab35 Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 10:55:17 -0500 Subject: [PATCH 27/94] fixed words --- apps/pokeclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/pokeclk/README.md b/apps/pokeclk/README.md index 1903b1646..a7b3ea6b1 100644 --- a/apps/pokeclk/README.md +++ b/apps/pokeclk/README.md @@ -2,7 +2,7 @@ A clock based on the Poketch electronic device found in Sinnoh -Add screen shots (if possible) to the app folder and link then into this file with ![](.png) +![](https://user-images.githubusercontent.com/44651387/157491789-1b608c11-8af2-4519-a90f-41b8a58a9a14.png) ## Features @@ -10,7 +10,7 @@ Has a dark mode ## Requests -Please file any issues here: [https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug](https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug) +If you have any issues or would like to suggest a feature, click here to send a message -> [here](https://github.com/elykittytee/BangleApps/issues/new?title=Poketch%20Clock%20Bug). ## Creator From e483b09d3c48c289ce711f57aa4f09b186121c1a Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 11:11:38 -0500 Subject: [PATCH 28/94] Update ChangeLog --- apps/pokeclk/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pokeclk/ChangeLog b/apps/pokeclk/ChangeLog index 09ae62ed3..8e506ce50 100644 --- a/apps/pokeclk/ChangeLog +++ b/apps/pokeclk/ChangeLog @@ -1 +1,2 @@ 0.01: New face :) +0.02: Color image compressed From d22e254eb99ac6530f91517f45211db9fea253e3 Mon Sep 17 00:00:00 2001 From: eleanor <44651387+elykittytee@users.noreply.github.com> Date: Fri, 20 May 2022 11:11:52 -0500 Subject: [PATCH 29/94] Update metadata.json --- apps/pokeclk/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pokeclk/metadata.json b/apps/pokeclk/metadata.json index b7fca3273..433077efe 100644 --- a/apps/pokeclk/metadata.json +++ b/apps/pokeclk/metadata.json @@ -2,7 +2,7 @@ "id": "pokeclk", "name": "Poketch Clock", "shortName":"Poketch Clock", - "version": "0.01", + "version": "0.02", "description": "A clock based on the Poketch electronic device found in Sinnoh", "icon": "app.png", "type": "clock", From 531cf4b5f98ceafa043a08be2b40607df866bcc6 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 18:17:48 +0200 Subject: [PATCH 30/94] [Scheduler] Improve readability of some filters The common conditions are now in the same order --- apps/sched/boot.js | 12 ++++++------ apps/sched/lib.js | 21 ++++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/sched/boot.js b/apps/sched/boot.js index 06dc4f308..3020f4945 100644 --- a/apps/sched/boot.js +++ b/apps/sched/boot.js @@ -8,12 +8,12 @@ var time = new Date(); var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000); var d = time.getDate(); - var active = alarms.filter( - a=>a.on && // enabled - a.last!=d && // not already fired today - a.t+60000>currentTime && // is not in the past by >1 minute - (a.dow>>time.getDay())&1 && // is allowed on this day of the week - (!a.date || a.date==time.toISOString().substr(0,10)) // is allowed on this date + var active = alarms.filter(a => + a.on // enabled + && (a.last != d) // not already fired today + && (a.t + 60000 > currentTime) // is not in the past by >1 minute + && (a.dow >> time.getDay() & 1) // is allowed on this day of the week + && (!a.date || a.date == time.toISOString().substr(0, 10)) // is allowed on this date ); if (active.length) { active = active.sort((a,b)=>a.t-b.t); // sort by time diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 063402e3d..dbc8660b9 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -11,16 +11,19 @@ exports.getAlarm = function(id) { return exports.getAlarms().find(a=>a.id==id); }; // Given a list of alarms from getAlarms, return a list of active alarms for the given time (or current time if time not specified) -exports.getActiveAlarms = function(alarms, time) { +exports.getActiveAlarms = function (alarms, time) { if (!time) time = new Date(); - var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000) - +10000;// get current time - 10s in future to ensure we alarm if we've started the app a tad early - return alarms.filter(a=>a.on - &&(a.t> (time).getDay() & 1) - .sort((a,b)=>a.t-b.t); + // get current time 10s in future to ensure we alarm if we've started the app a tad early + var currentTime = (time.getHours() * 3600000) + (time.getMinutes() * 60000) + (time.getSeconds() * 1000) + 10000; + return alarms + .filter(a => + a.on // enabled + && (a.last != time.getDate()) // not already fired today + && (a.t < currentTime) + && (a.dow >> time.getDay() & 1) // is allowed on this day of the week + && (!a.date || a.date == time.toISOString().substr(0, 10)) // is allowed on this date + ) + .sort((a, b) => a.t - b.t); } // Set an alarm object based on ID. Leave 'alarm' undefined to remove it exports.setAlarm = function(id, alarm) { From c7f8322e3a52a5cccddd95d37f64b340e953cd1b Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 18:19:34 +0200 Subject: [PATCH 31/94] [Scheduler] Fix default dow --- apps/sched/ChangeLog | 3 ++- apps/sched/lib.js | 2 +- apps/sched/metadata.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 9c2f68348..e003248a3 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -6,6 +6,7 @@ 0.06: Refactor some methods to library 0.07: Update settings Correct `decodeTime(t)` to return a more likely expected time -0.08: add day of week check to getActiveAlarms() +0.08: Add day of week check to getActiveAlarms() 0.09: Move some functions to new time_utils module 0.10: Default to sched.js if custom js not found +0.11: Fix default dow diff --git a/apps/sched/lib.js b/apps/sched/lib.js index dbc8660b9..315e4e387 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -69,7 +69,7 @@ exports.newDefaultAlarm = function () { on: true, rp: settings.defaultRepeat, as: settings.defaultAutoSnooze, - dow: settings.defaultRepeat ? 0b1111111 : 0b0000000, + dow: 0b1111111, last: 0, vibrate: settings.defaultAlarmPattern, }; diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index c3fc7ca8a..76341a7ad 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.10", + "version": "0.11", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", From fbc5e9643942c648e0208c0272bb311cac0dd22b Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 18:21:32 +0200 Subject: [PATCH 32/94] [Alarms & Timers] Fix bug with alarms not firing when configured to fire only once --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 42 ++++++++++++++++++++++------------------ apps/alarm/metadata.json | 2 +- 3 files changed, 25 insertions(+), 20 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index b952b1dcd..3d75e1209 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -27,3 +27,4 @@ 0.25: Fix redrawing selected Alarm/Timer entry inside edit submenu 0.26: Add support for Monday as first day of the week (#1780) 0.27: New UI! +0.28: Fix bug with alarms not firing when configured to fire only once diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 0cf1f3d6f..46efe37bf 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -50,7 +50,7 @@ function showMainMenu() { alarms.forEach((e, index) => { var label = e.timer ? require("time_utils").formatDuration(e.timer) - : require("time_utils").formatTime(e.t) + (e.dow > 0 ? (" " + decodeDOW(e)) : ""); + : require("time_utils").formatTime(e.t) + (e.rp ? ` ${decodeDOW(e)}` : ""); menu[label] = { value: e.on ? (e.timer ? iconTimerOn : iconAlarmOn) : (e.timer ? iconTimerOff : iconAlarmOff), onchange: () => setTimeout(e.timer ? showEditTimerMenu : showEditAlarmMenu, 10, e, index) @@ -111,8 +111,8 @@ function showEditAlarmMenu(selectedAlarm, alarmIndex) { }, /*LANG*/"Repeat": { value: decodeDOW(alarm), - onchange: () => setTimeout(showEditRepeatMenu, 100, alarm.dow, dow => { - alarm.rp = dow > 0; + onchange: () => setTimeout(showEditRepeatMenu, 100, alarm.rp, alarm.dow, (repeat, dow) => { + alarm.rp = repeat; alarm.dow = dow; alarm.t = require("time_utils").encodeTime(time); setTimeout(showEditAlarmMenu, 10, alarm, alarmIndex); @@ -178,42 +178,46 @@ function decodeDOW(alarm) { : "Once" } -function showEditRepeatMenu(dow, dowChangeCallback) { +function showEditRepeatMenu(repeat, dow, dowChangeCallback) { + var originalRepeat = repeat; var originalDow = dow; - var isCustom = dow > 0 && dow != WORKDAYS && dow != WEEKEND && dow != EVERY_DAY; + var isCustom = repeat && dow != WORKDAYS && dow != WEEKEND && dow != EVERY_DAY; const menu = { "": { "title": /*LANG*/"Repeat Alarm" }, - "< Back": () => dowChangeCallback(dow), - /*LANG*/"Once": { // No days set: the alarm will fire once - value: dow == 0, - onchange: () => dowChangeCallback(0) + "< Back": () => dowChangeCallback(repeat, dow), + /*LANG*/"Once": { + // The alarm will fire once. Internally it will be saved + // as "fire every days" BUT the repeat flag is false so + // we avoid messing up with the scheduler. + value: !repeat, + onchange: () => dowChangeCallback(false, EVERY_DAY) }, /*LANG*/"Workdays": { - value: dow == WORKDAYS, - onchange: () => dowChangeCallback(WORKDAYS) + value: repeat && dow == WORKDAYS, + onchange: () => dowChangeCallback(true, WORKDAYS) }, /*LANG*/"Weekends": { - value: dow == WEEKEND, - onchange: () => dowChangeCallback(WEEKEND) + value: repeat && dow == WEEKEND, + onchange: () => dowChangeCallback(true, WEEKEND) }, /*LANG*/"Every Day": { - value: dow == EVERY_DAY, - onchange: () => dowChangeCallback(EVERY_DAY) + value: repeat && dow == EVERY_DAY, + onchange: () => dowChangeCallback(true, EVERY_DAY) }, /*LANG*/"Custom": { value: isCustom ? decodeDOW({ rp: true, dow: dow }) : false, - onchange: () => setTimeout(showCustomDaysMenu, 10, isCustom ? dow : EVERY_DAY, dowChangeCallback, originalDow) + onchange: () => setTimeout(showCustomDaysMenu, 10, isCustom ? dow : EVERY_DAY, dowChangeCallback, originalRepeat, originalDow) } }; E.showMenu(menu); } -function showCustomDaysMenu(dow, dowChangeCallback, originalDow) { +function showCustomDaysMenu(dow, dowChangeCallback, originalRepeat, originalDow) { const menu = { "": { "title": /*LANG*/"Custom Days" }, - "< Back": () => dowChangeCallback(dow), + "< Back": () => dowChangeCallback(true, dow), }; require("date_utils").dows(firstDayOfWeek).forEach((day, i) => { @@ -223,7 +227,7 @@ function showCustomDaysMenu(dow, dowChangeCallback, originalDow) { }; }); - menu[/*LANG*/"Cancel"] = () => setTimeout(showEditRepeatMenu, 10, originalDow, dowChangeCallback) + menu[/*LANG*/"Cancel"] = () => setTimeout(showEditRepeatMenu, 10, originalRepeat, originalDow, dowChangeCallback) E.showMenu(menu); } diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index b9ce55756..b38ab1ef1 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.27", + "version": "0.28", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From f1170b3e341578cc91688cbbc4b8cbda9b235a1c Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 22:08:59 +0200 Subject: [PATCH 33/94] [Alarms & Timer] Fix label --- apps/alarm/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 46efe37bf..4ff739cbc 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -320,7 +320,7 @@ function enableAll(on) { buttons: { /*LANG*/"Ok": true } }).then(() => showAdvancedMenu()); } else { - E.showPrompt(/*LANG*/"Are you sure?", { title: on ? "/*LANG*/Enable All" : /*LANG*/"Disable All" }).then((confirm) => { + E.showPrompt(/*LANG*/"Are you sure?", { title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All" }).then((confirm) => { if (confirm) { alarms.forEach(alarm => alarm.on = on); saveAndReload(); From de567965809056aaf87904b43a6c26f71d4e9f63 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 22:26:36 +0200 Subject: [PATCH 34/94] [Alarms & Timers] Fix repeat when user unchecks ALL the days --- apps/alarm/app.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 4ff739cbc..1b1801f66 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -217,7 +217,12 @@ function showEditRepeatMenu(repeat, dow, dowChangeCallback) { function showCustomDaysMenu(dow, dowChangeCallback, originalRepeat, originalDow) { const menu = { "": { "title": /*LANG*/"Custom Days" }, - "< Back": () => dowChangeCallback(true, dow), + "< Back": () => { + // If the user unchecks all the days then we assume repeat = once + // and we force the dow to every day. + var repeat = dow > 0; + dowChangeCallback(repeat, repeat ? dow : EVERY_DAY) + } }; require("date_utils").dows(firstDayOfWeek).forEach((day, i) => { From f432e10b35c682b23d4fb89aef03c97c8f43d049 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 22:41:26 +0200 Subject: [PATCH 35/94] [Alarms & Timers] Replace showPrompt with showAlert --- apps/alarm/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 1b1801f66..8e2e2b0a6 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -320,10 +320,10 @@ function showAdvancedMenu() { function enableAll(on) { if (alarms.filter(e => e.on == !on).length == 0) { - E.showPrompt(on ? /*LANG*/"Nothing to Enable" : /*LANG*/"Nothing to Disable", { - title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All", - buttons: { /*LANG*/"Ok": true } - }).then(() => showAdvancedMenu()); + E.showAlert( + on ? /*LANG*/"Nothing to Enable" : /*LANG*/"Nothing to Disable", + on ? /*LANG*/"Enable All" : /*LANG*/"Disable All" + ).then(() => showAdvancedMenu()); } else { E.showPrompt(/*LANG*/"Are you sure?", { title: on ? /*LANG*/"Enable All" : /*LANG*/"Disable All" }).then((confirm) => { if (confirm) { @@ -339,7 +339,7 @@ function enableAll(on) { function deleteAll() { if (alarms.length == 0) { - E.showPrompt(/*LANG*/"Nothing to delete", { title: /*LANG*/"Delete All", buttons: { /*LANG*/"Ok": true } }).then(() => showAdvancedMenu()); + E.showAlert(/*LANG*/"Nothing to delete", /*LANG*/"Delete All").then(() => showAdvancedMenu()); } else { E.showPrompt(/*LANG*/"Are you sure?", { title: /*LANG*/"Delete All" From d082e23de1bfb97a3ea7c35559e53d9a2235e19a Mon Sep 17 00:00:00 2001 From: Lutz Date: Sat, 21 May 2022 14:02:38 +0200 Subject: [PATCH 36/94] added tags to the metadata this app is actually a clock... tell the world about it --- apps/bowserWF/metadata.json | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/bowserWF/metadata.json b/apps/bowserWF/metadata.json index 22df2dea4..a0bdfb8e9 100644 --- a/apps/bowserWF/metadata.json +++ b/apps/bowserWF/metadata.json @@ -1,14 +1,18 @@ -{ "id": "bowserWF", +{ + "id": "bowserWF", "name": "Bowser Watchface", "shortName":"Bowser Watchface", - "version":"0.01", + "version":"0.02", "description": "Let bowser show you the time", "icon": "app.png", - "tags": "", - "supports" : ["BANGLEJS2"], + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, "readme": "README.md", "storage": [ {"name":"bowserWF.app.js","url":"app.js"}, {"name":"bowserWF.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"bowserWF.json"}] } From 89edc64922ce90711668514dbaa2648474ea471f Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:50:00 +0200 Subject: [PATCH 37/94] [Nifty-A Clock] Call setUI before loading widgets --- apps/ffcniftya/app.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 5da1ec48e..ffa43fec3 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -103,9 +103,6 @@ Bangle.on('lcdPower', (on) => { } }); -// Load widgets +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); - -// Show launcher when middle button pressed -Bangle.setUI("clock"); \ No newline at end of file From b6e9474bf42e92f503470e1fe09232cca50f45e7 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:51:01 +0200 Subject: [PATCH 38/94] [Nifty-A Clock] Improve settings page --- apps/ffcniftya/app.js | 34 ++++++++++++++++------------------ apps/ffcniftya/settings.js | 26 +++++++++----------------- 2 files changed, 25 insertions(+), 35 deletions(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index ffa43fec3..87ed449e7 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,6 +1,6 @@ const locale = require("locale"); -const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; -const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeekNum: true}; +const is12Hour = Object.assign({ "12hour": false }, require("Storage").readJSON("setting.json", true))["12hour"]; +const showWeekNum = Object.assign({ showWeekNum: true }, require('Storage').readJSON("ffcniftya.json", true))["showWeekNum"]; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -17,16 +17,17 @@ const center = { y: Math.round(((viewport.height - widget) / 2) + widget), } -function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 - var tdt = new Date(date.valueOf()); - var dayn = (date.getDay() + 6) % 7; - tdt.setDate(tdt.getDate() - dayn + 3); - var firstThursday = tdt.valueOf(); - tdt.setMonth(0, 1); - if (tdt.getDay() !== 4) { - tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); - } - return 1 + Math.ceil((firstThursday - tdt) / 604800000); +// copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 +function ISO8601_week_no(date) { + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); } function d02(value) { @@ -59,7 +60,7 @@ function draw() { g.drawString(year, centerDatesScaleX, center.y - 62 * scale); g.drawString(month, centerDatesScaleX, center.y - 44 * scale); g.drawString(day, centerDatesScaleX, center.y - 26 * scale); - if (CFG.showWeekNum) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); + if (showWeekNum) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } @@ -79,7 +80,6 @@ function clearTickTimer() { function queueNextTick() { clearTickTimer(); tickTimer = setTimeout(tick, 60000 - (Date.now() % 60000)); - // tickTimer = setTimeout(tick, 3000); } function tick() { @@ -91,15 +91,13 @@ function tick() { // Clear the screen once, at startup g.clear(); -// Start ticking tick(); -// Stop updates when LCD is off, restart when on Bangle.on('lcdPower', (on) => { if (on) { - tick(); // Start ticking + tick(); } else { - clearTickTimer(); // stop ticking + clearTickTimer(); } }); diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index 46e4ef5aa..aec1d680a 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -1,23 +1,15 @@ -(function(back) { - var FILE = "ffcniftya.json"; - // Load settings - var cfg = require('Storage').readJSON(FILE, 1) || { showWeekNum: true }; +(function (back) { + const settings = Object.assign({ showWeekNum: true }, require("Storage").readJSON("ffcniftya.json", true)); - function writeSettings() { - require('Storage').writeJSON(FILE, cfg); - } - - // Show the menu E.showMenu({ - "" : { "title" : "Nifty-A Clock" }, - "< Back" : () => back(), - 'week number?': { - value: cfg.showWeekNum, - format: v => v?"On":"Off", + "": { "title": "Nifty-A Clock" }, + "< Back": () => back(), + /*LANG*/"Show Week Number": { + value: settings.showWeekNum, onchange: v => { - cfg.showWeekNum = v; - writeSettings(); + settings.showWeekNum = v; + require("Storage").writeJSON("ffcniftya.json", settings); } } }); -}) \ No newline at end of file +}) From 3b6db907e7716904af4c4d61ca6d78083f0ffc52 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sun, 22 May 2022 11:21:39 +0200 Subject: [PATCH 39/94] [Nifty-A Clock] Remove unnecessary function call --- apps/ffcniftya/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 87ed449e7..4000a1578 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -60,7 +60,7 @@ function draw() { g.drawString(year, centerDatesScaleX, center.y - 62 * scale); g.drawString(month, centerDatesScaleX, center.y - 44 * scale); g.drawString(day, centerDatesScaleX, center.y - 26 * scale); - if (showWeekNum) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); + if (showWeekNum) g.drawString(weekNum, centerDatesScaleX, center.y + 15 * scale); g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } From ac161c103e02b2fa4829b160e7c5bd0abcc3ec8d Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:51:27 +0200 Subject: [PATCH 40/94] [Nifty-A Clock] Update metadata & changelog --- apps/ffcniftya/ChangeLog | 4 +++- apps/ffcniftya/README.md | 7 +++---- apps/ffcniftya/metadata.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index 420c553f5..cb520193b 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1,2 +1,4 @@ 0.01: New Clock Nifty A -0.02: Shows the current week number (ISO8601), can be disabled via settings "" +0.02: Shows the current week number (ISO8601), can be disabled via settings +0.03: Call setUI before loading widgets + Improve settings page diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 86f1f5c2d..80005fd3c 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,13 +1,12 @@ # Nifty-A Clock -Colors are black/white - photos have non correct camera color "blue" +Colors are black/white - photos have non correct camera color "blue". -## This is the clock +This is the clock: ![](screenshot_nifty.png) -## The week number (ISO8601) can be turned of in settings -(default is **"On"**) +The week number (ISO8601) can be turned off in settings (default is `On`) ![](screenshot_settings_nifty.png) diff --git a/apps/ffcniftya/metadata.json b/apps/ffcniftya/metadata.json index ce91cc225..91b426cd0 100644 --- a/apps/ffcniftya/metadata.json +++ b/apps/ffcniftya/metadata.json @@ -1,7 +1,7 @@ { "id": "ffcniftya", "name": "Nifty-A Clock", - "version": "0.02", + "version": "0.03", "description": "A nifty clock with time and date", "icon": "app.png", "screenshots": [{"url":"screenshot_nifty.png"}], From e481c0daa29f131d4dc1b4bf180562b0d12c2a32 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:29:39 +0200 Subject: [PATCH 41/94] [Nifty-B Clock] Call setUI before loading widgets --- apps/ffcniftyb/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/ffcniftyb/app.js b/apps/ffcniftyb/app.js index 75d217ab4..71fbece9e 100644 --- a/apps/ffcniftyb/app.js +++ b/apps/ffcniftyb/app.js @@ -112,7 +112,6 @@ Bangle.on('lcdPower', (on) => { } }); +Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); - -Bangle.setUI("clock"); From 58f9461dacaada0c848358957e2c912456601ff0 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:32:57 +0200 Subject: [PATCH 42/94] [Nifty-B Clock] Fix bug with black being unselectable --- apps/ffcniftyb/app.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/apps/ffcniftyb/app.js b/apps/ffcniftyb/app.js index 71fbece9e..65c74dbd7 100644 --- a/apps/ffcniftyb/app.js +++ b/apps/ffcniftyb/app.js @@ -1,9 +1,5 @@ -const locale = require("locale"); -const storage = require('Storage'); - -const is12Hour = (storage.readJSON("setting.json", 1) || {})["12hour"]; -const color = (storage.readJSON("ffcniftyb.json", 1) || {})["color"] || 63488 /* red */; - +const is12Hour = Object.assign({ "12hour": false }, require("Storage").readJSON("setting.json", true))["12hour"]; +const color = Object.assign({ color: 63488 }, require("Storage").readJSON("ffcniftyb.json", true)).color; // Default to RED /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -19,7 +15,7 @@ const center = { }; function d02(value) { - return ('0' + value).substr(-2); + return ("0" + value).substr(-2); } function renderEllipse(g) { @@ -35,8 +31,8 @@ function renderText(g) { const month = d02(now.getMonth() + 1); const year = now.getFullYear(); - const month2 = locale.month(now, 3); - const day2 = locale.dow(now, 3); + const month2 = require("locale").month(now, 3); + const day2 = require("locale").dow(now, 3); g.setFontAlign(1, 0).setFont("Vector", 90 * scale); g.drawString(hour, center.x + 32 * scale, center.y - 31 * scale); @@ -96,7 +92,6 @@ function startTick(run) { stopTick(); run(); ticker = setTimeout(() => startTick(run), 60000 - (Date.now() % 60000)); - // ticker = setTimeout(() => startTick(run), 3000); } /* Init **********************************************/ @@ -104,7 +99,7 @@ function startTick(run) { g.clear(); startTick(draw); -Bangle.on('lcdPower', (on) => { +Bangle.on("lcdPower", (on) => { if (on) { startTick(draw); } else { From adf7c7536593968002c76ee0948082f069db5644 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:34:44 +0200 Subject: [PATCH 43/94] [Nifty-B Clock] Improve settings page --- apps/ffcniftyb/settings.js | 62 ++++++++++++++------------------------ 1 file changed, 22 insertions(+), 40 deletions(-) diff --git a/apps/ffcniftyb/settings.js b/apps/ffcniftyb/settings.js index 00abf80b5..da350edd8 100644 --- a/apps/ffcniftyb/settings.js +++ b/apps/ffcniftyb/settings.js @@ -1,49 +1,31 @@ (function (back) { - const storage = require('Storage'); - const SETTINGS_FILE = "ffcniftyb.json"; + const settings = Object.assign({ color: 63488 }, require("Storage").readJSON("ffcniftyb.json", true)); const colors = { - 65535: 'White', - 63488: 'Red', - 65504: 'Yellow', - 2047: 'Cyan', - 2016: 'Green', - 31: 'Blue', - 0: 'Black', + 65535: /*LANG*/"White", + 63488: /*LANG*/"Red", + 65504: /*LANG*/"Yellow", + 2047: /*LANG*/"Cyan", + 2016: /*LANG*/"Green", + 31: /*LANG*/"Blue", + 0: /*LANG*/"Black" } - function load(settings) { - return Object.assign(settings, storage.readJSON(SETTINGS_FILE, 1) || {}); - } + const menu = {}; + menu[""] = { title: "Nifty-B Clock" }; + menu["< Back"] = back; - function save(settings) { - storage.write(SETTINGS_FILE, settings) - } - - const settings = load({ - color: 63488 /* red */, + Object.keys(colors).forEach(color => { + var label = colors[color]; + menu[label] = { + value: settings.color == color, + onchange: () => { + settings.color = color; + require("Storage").write("ffcniftyb.json", settings); + setTimeout(load, 10); + } + }; }); - const saveColor = (color) => () => { - settings.color = color; - save(settings); - back(); - }; - - function showMenu(items, opt) { - items[''] = opt || {}; - items['< Back'] = back; - E.showMenu(items); - } - - showMenu( - Object.keys(colors).reduce((menu, color) => { - menu[colors[color]] = saveColor(color); - return menu; - }, {}), - { - title: 'Color', - selected: Object.keys(colors).indexOf(settings.color) - } - ); + E.showMenu(menu); }); From 1a00f7d9e2f1160c6fb316fc3887776be4757e23 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 15:35:56 +0200 Subject: [PATCH 44/94] [Nifty-B Clock] Update metadata & changelog --- apps/ffcniftyb/ChangeLog | 5 ++++- apps/ffcniftyb/README.md | 5 +---- apps/ffcniftyb/metadata.json | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/ffcniftyb/ChangeLog b/apps/ffcniftyb/ChangeLog index dedd31452..9fc7e3c5c 100644 --- a/apps/ffcniftyb/ChangeLog +++ b/apps/ffcniftyb/ChangeLog @@ -1,2 +1,5 @@ 0.01: New Clock Nifty B -0.02: Added configuration \ No newline at end of file +0.02: Added configuration +0.03: Call setUI before loading widgets + Fix bug with black being unselectable + Improve settings page diff --git a/apps/ffcniftyb/README.md b/apps/ffcniftyb/README.md index e04243a0b..072f71cce 100644 --- a/apps/ffcniftyb/README.md +++ b/apps/ffcniftyb/README.md @@ -1,9 +1,6 @@ # Nifty Series B Clock - Display Time and Date -- Color Configuration - -## +- Colour Configuration ![](screenshot.png) - diff --git a/apps/ffcniftyb/metadata.json b/apps/ffcniftyb/metadata.json index 73f93ed36..3d26c27ea 100644 --- a/apps/ffcniftyb/metadata.json +++ b/apps/ffcniftyb/metadata.json @@ -1,8 +1,8 @@ { "id": "ffcniftyb", "name": "Nifty-B Clock", - "version": "0.02", - "description": "A nifty clock (series B) with time, date and color configuration", + "version": "0.03", + "description": "A nifty clock (series B) with time, date and colour configuration", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", From 5b98fdad52eaf3a4ea662ee99c490df21102e997 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 21 May 2022 16:17:26 +0200 Subject: [PATCH 45/94] [lang] Update Italian translations with strings used by Nifty clocks --- lang/it_IT.json | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lang/it_IT.json b/lang/it_IT.json index 4bc36ee48..310af8580 100644 --- a/lang/it_IT.json +++ b/lang/it_IT.json @@ -192,7 +192,15 @@ "Notifications": "Notifiche", "Scheduler": "Schedulatore", "Stop": "Stop", - "Min Font": "Dimensione minima del font" + "Min Font": "Dimensione minima del font", + "White": "Bianco", + "Red": "Rosso", + "Yellow": "Giallo", + "Cyan": "Ciano", + "Green": "Verde", + "Blue": "Blu", + "Black": "Nero", + "Show Week Number": "Mostra numero settimana" }, "//2": "App-specific overrides", "alarm": { From 365b3859b35a2afd2a4e790efe78d3d541912c6b Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 22 May 2022 19:59:17 +0200 Subject: [PATCH 46/94] ClockFace: set Bangle.CLOCK=1 before loading widgets --- modules/ClockFace.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ClockFace.js b/modules/ClockFace.js index 25e2430bf..9939ae4fa 100644 --- a/modules/ClockFace.js +++ b/modules/ClockFace.js @@ -66,6 +66,7 @@ ClockFace.prototype.tick = function() { }; ClockFace.prototype.start = function() { + Bangle.CLOCK = 1; Bangle.loadWidgets(); if (this.init) this.init.apply(this); if (this._upDown) Bangle.setUI("clockupdown", d=>this._upDown.apply(this,[d])); From b6366761fc23af86dc689e9924764504ea68f8af Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 16:13:52 +1200 Subject: [PATCH 47/94] Update app.js --- apps/speedalt2/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/speedalt2/app.js b/apps/speedalt2/app.js index ed16131a4..4cdf71913 100644 --- a/apps/speedalt2/app.js +++ b/apps/speedalt2/app.js @@ -5,8 +5,9 @@ Mike Bennett mike[at]kereru.com 1.14 : Add VMG screen 1.34 : Add bluetooth data stream for Droidscript 1.43 : Keep GPS in SuperE mode while using Droiscript screen mirroring +1.50 : Add cfg.wptSfx one char suffix to append to waypoints.json filename. Protects speedalt2 waypoints from other apps that use the same file name for waypoints. */ -var v = '1.49'; +var v = '1.50'; var vDroid = '1.50'; // Required DroidScript program version /*kalmanjs, Wouter Bulten, MIT, https://github.com/wouterbulten/kalmanjs */ @@ -209,7 +210,7 @@ function nxtWp(){ } function loadWp() { - var w = require("Storage").readJSON('waypoints.json')||[{name:"NONE"}]; + var w = require("Storage").readJSON('waypoints'+cfg.wptSfx+'.json')||[{name:"NONE"}]; if (cfg.wp>=w.length) cfg.wp=0; if (cfg.wp<0) cfg.wp = w.length-1; savSettings(); @@ -718,6 +719,7 @@ cfg.primSpd = cfg.primSpd||0; // 1 = Spd in primary, 0 = Spd in secondary cfg.spdFilt = cfg.spdFilt==undefined?true:cfg.spdFilt; cfg.altFilt = cfg.altFilt==undefined?true:cfg.altFilt; cfg.touch = cfg.touch==undefined?true:cfg.touch; +cfg.wptSfx = cfg.wptSfx==undefined?'':cfg.wptSfx; if ( cfg.spdFilt ) var spdFilter = new KalmanFilter({R: 0.1 , Q: 1 }); if ( cfg.altFilt ) var altFilter = new KalmanFilter({R: 0.01, Q: 2 }); From 864fa672aba173fd7082fe9f1c8e3e2f1f5a13cb Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 16:17:40 +1200 Subject: [PATCH 48/94] Update ChangeLog --- apps/speedalt2/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/speedalt2/ChangeLog b/apps/speedalt2/ChangeLog index 73e9bfc40..fe20dcf3d 100644 --- a/apps/speedalt2/ChangeLog +++ b/apps/speedalt2/ChangeLog @@ -13,3 +13,4 @@ 1.14: Add VMG and coordinates screens 1.43: Adds mirroring of the watch face to an Android device. See README.md 1.49: Droidscript mirroring prog automatically uses last connection address. Auto connects when run. +1.50: Add configuration item Waypoints Suffix. A one character suffix to append to the waypoints.json file. A number of other apps also use this file name. Using the file name suffix allows the speedalt2 waypoints to be retained if one of these other apps is installed for a different use. From 1ac9864bae22ec6aa82fe8a1ba9496e5aa55e766 Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 16:35:04 +1200 Subject: [PATCH 49/94] Update settings.js --- apps/speedalt2/settings.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/apps/speedalt2/settings.js b/apps/speedalt2/settings.js index babb03061..1bdb58f9d 100644 --- a/apps/speedalt2/settings.js +++ b/apps/speedalt2/settings.js @@ -30,6 +30,11 @@ writeSettings(); } + function setSfx(s) { + settings.wptSfx = s; + writeSettings(); + } + const appMenu = { '': {'title': 'GPS Adv Sprt II'}, @@ -38,6 +43,7 @@ 'Units' : function() { E.showMenu(unitsMenu); }, 'Colours' : function() { E.showMenu(colMenu); }, 'Kalman Filter' : function() { E.showMenu(kalMenu); }, + 'Wpt File Suffix' : function() { E.showMenu(sfxMenu); }, 'Touch' : { value : settings.touch, format : v => v?"On":"Off", @@ -69,6 +75,15 @@ 'Inverted' : function() { setColour(3); } }; + const sfxMenu = { + '': {'title': 'Wpt File Suffix'}, + '< Back': function() { E.showMenu(appMenu); }, + 'Default' : function() { setSfx(''); }, + '1' : function() { setSfx('1'); }, + '2' : function() { setSfx('2'); }, + '3' : function() { setSfx('3'); } + }; + const kalMenu = { '': {'title': 'Kalman Filter'}, '< Back': function() { E.showMenu(appMenu); }, From 445b21fc076c3272d2cef95c7672ae5c86fd24d5 Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 16:36:11 +1200 Subject: [PATCH 50/94] Update metadata.json --- apps/speedalt2/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/speedalt2/metadata.json b/apps/speedalt2/metadata.json index 4ace46854..801d65fb0 100644 --- a/apps/speedalt2/metadata.json +++ b/apps/speedalt2/metadata.json @@ -2,7 +2,7 @@ "id": "speedalt2", "name": "GPS Adventure Sports II", "shortName":"GPS Adv Sport II", - "version":"1.49", + "version":"1.50", "description": "GPS speed, altitude and distance to waypoint display. Designed for easy viewing and use during outdoor activities such as para-gliding, hang-gliding, sailing, cycling etc.", "icon": "app.png", "type": "app", From 824705203842e6f93297164ba0852900e7468880 Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 16:53:56 +1200 Subject: [PATCH 51/94] Update ChangeLog --- apps/speedalt2/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/speedalt2/ChangeLog b/apps/speedalt2/ChangeLog index fe20dcf3d..9e2abb4ef 100644 --- a/apps/speedalt2/ChangeLog +++ b/apps/speedalt2/ChangeLog @@ -13,4 +13,4 @@ 1.14: Add VMG and coordinates screens 1.43: Adds mirroring of the watch face to an Android device. See README.md 1.49: Droidscript mirroring prog automatically uses last connection address. Auto connects when run. -1.50: Add configuration item Waypoints Suffix. A one character suffix to append to the waypoints.json file. A number of other apps also use this file name. Using the file name suffix allows the speedalt2 waypoints to be retained if one of these other apps is installed for a different use. +1.50: Add configuration item Wpt File Suffix. A one character suffix to append to the waypoints.json file. A number of other apps also use this file name. Using the file name suffix allows the speedalt2 waypoints to be retained if one of these other apps is installed for a different use. From fa77e25b103432830bad03d469dd870e113896f3 Mon Sep 17 00:00:00 2001 From: nujw Date: Mon, 23 May 2022 17:00:01 +1200 Subject: [PATCH 52/94] Update README.md --- apps/speedalt2/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/speedalt2/README.md b/apps/speedalt2/README.md index e1c6b0a5a..76532bc40 100644 --- a/apps/speedalt2/README.md +++ b/apps/speedalt2/README.md @@ -80,6 +80,8 @@ The [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app in the App Sample waypoints.json (My sailing waypoints) +**Note** : The waypoints.json file is used by a number of different gps apps. The setting 'Wpt File Suffix' allows one of waypoints1.json, waypoints2.json or waypoints3.json to be used instead. This allows the other apps to be used with a different set of waypoints without losing the speedalt2 waypoint set. +
 [
   {

From c6f45f06a0a0b5b8fcdb9749e3005814347fd1e3 Mon Sep 17 00:00:00 2001
From: nujw 
Date: Mon, 23 May 2022 17:02:25 +1200
Subject: [PATCH 53/94] Update README.md

---
 apps/speedalt2/README.md | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/apps/speedalt2/README.md b/apps/speedalt2/README.md
index 76532bc40..c124e0c00 100644
--- a/apps/speedalt2/README.md
+++ b/apps/speedalt2/README.md
@@ -78,9 +78,11 @@ Waypoints are used in Distance and VMG modes. Create a file waypoints.json and w
 
 The [GPS Navigation](https://banglejs.com/apps/#gps%20navigation) app in the App Loader has a really nice waypoints file editor. (Must be connected to your Bangle.JS and then click on the Download icon.)
 
-Sample waypoints.json (My sailing waypoints)
+By default the waypoints file is called waypoints.json
 
 **Note** : The waypoints.json file is used by a number of different gps apps. The setting 'Wpt File Suffix' allows one of waypoints1.json, waypoints2.json or waypoints3.json to be used instead. This allows the other apps to be used with a different set of waypoints without losing the speedalt2 waypoint set. 
+ 
+Sample waypoints.json (My sailing waypoints)
 
 
 [

From 778432e94563045fd79a613501c8aded2acea13e Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 10:25:31 +0100
Subject: [PATCH 54/94] comment

---
 modules/ClockFace.js | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/modules/ClockFace.js b/modules/ClockFace.js
index 9939ae4fa..d6c3a2e66 100644
--- a/modules/ClockFace.js
+++ b/modules/ClockFace.js
@@ -66,7 +66,10 @@ ClockFace.prototype.tick = function() {
 };
 
 ClockFace.prototype.start = function() {
-  Bangle.CLOCK = 1;
+  /* Some widgets want to know if we're in a clock or not (like chrono, widget clock, etc). Normally
+  .CLOCK is set by Bangle.setUI('clock') but we want to load widgets so we can check appRect and *then*
+  call setUI. see #1864 */
+  Bangle.CLOCK = 1; 
   Bangle.loadWidgets();
   if (this.init) this.init.apply(this);
   if (this._upDown) Bangle.setUI("clockupdown", d=>this._upDown.apply(this,[d]));
@@ -104,4 +107,4 @@ ClockFace.prototype.redraw = function() {
   this.tick();
 };
 
-exports = ClockFace;
\ No newline at end of file
+exports = ClockFace;

From d3a0128bc8b9836f20c16663c1700bbd087eb1da Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 10:34:18 +0100
Subject: [PATCH 55/94] Revert "Update boot.js"

The old code was fine, and this broke it

This reverts commit 2351340a73a354e377c504edec3c960d176137ae.
---
 apps/sched/boot.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/apps/sched/boot.js b/apps/sched/boot.js
index 3020f4945..98bb0ff7d 100644
--- a/apps/sched/boot.js
+++ b/apps/sched/boot.js
@@ -24,7 +24,7 @@
     will then clearInterval() to get rid of this call so it can proceed
     normally.
     If active[0].js is defined, just run that code as-is and not alarm.js */
-    Bangle.SCHED = setTimeout(require("Storage").read(active[0].js)!==undefined ? active[0].js : 'load("sched.js")',t);
+    Bangle.SCHED = setTimeout(active[0].js||'load("sched.js")',t);
   } else { // check for new alarms at midnight (so day of week works)
     Bangle.SCHED = setTimeout('eval(require("Storage").read("sched.boot.js"))', 86400000 - (Date.now()%86400000));
   }

From 1b290a69822d1605c051e9f261d37d2a1b9c1738 Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 11:16:40 +0100
Subject: [PATCH 56/94] settings 0.45: Add calibrate battery option

---
 apps/setting/ChangeLog     |  1 +
 apps/setting/README.md     |  3 ++-
 apps/setting/metadata.json |  2 +-
 apps/setting/settings.js   | 12 ++++++++++++
 4 files changed, 16 insertions(+), 2 deletions(-)

diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog
index bfd32a130..6d3bbb468 100644
--- a/apps/setting/ChangeLog
+++ b/apps/setting/ChangeLog
@@ -48,3 +48,4 @@
 0.43: Add some Bangle 1 colours to theme customizer
 0.44: Add "Start Week On X" option (#1780)
       UI improvements to Locale and Date & Time menu
+0.45: Add calibrate battery option
diff --git a/apps/setting/README.md b/apps/setting/README.md
index 451b48c06..657b96f71 100644
--- a/apps/setting/README.md
+++ b/apps/setting/README.md
@@ -13,7 +13,6 @@ This is Bangle.js's settings menu
 * **LCD** Configure settings about the screen. How long it stays on, how bright it is, and when it turns on - see below.
 * **Theme** Adjust the colour scheme
 * **Utils** Utilities - including resetting settings (see below)
-* **Turn Off** Turn Bangle.js off
 
 ## BLE - Bluetooth Settings
 
@@ -61,5 +60,7 @@ The exact effects depend on the app.  In general the watch will not wake up by i
 * **Compact Storage** Removes deleted/old files from Storage - this will speed up your Bangle.js
 * **Rewrite Settings** Should not normally be required, but if `.boot0` has been deleted/corrupted (and so no settings are being loaded) this will fix it.
 * **Flatten Battery** Turns on all devices and draws as much power as possible, attempting to flatten the Bangle.js battery. This can still take 5+ hours.  
+* **Calibrate Battery** If you're finding your battery percentage meter isn't accurate, leave your Bangle.js on charge for at least 3 hours, and then choose this menu option. It will measure the battery voltage when full and will allow Bangle.js to report a more accurate battery percentage.
 * **Reset Settings** Reset the settings (as set in this app) to defaults. Does not reset settings for other apps.
 * **Factory Reset** (not available on Bangle.js 1) - wipe **everything** and return to a factory state
+* **Turn Off** Turn Bangle.js off
diff --git a/apps/setting/metadata.json b/apps/setting/metadata.json
index 85dddf9db..c5c368fae 100644
--- a/apps/setting/metadata.json
+++ b/apps/setting/metadata.json
@@ -1,7 +1,7 @@
 {
   "id": "setting",
   "name": "Settings",
-  "version": "0.44",
+  "version": "0.45",
   "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 9b5bdae68..5c14e914d 100644
--- a/apps/setting/settings.js
+++ b/apps/setting/settings.js
@@ -546,6 +546,18 @@ function showUtilMenu() {
         var i=1000;while (i--);
       }, 1);
     },
+    /*LANG*/'Calibrate Battery': () => {
+      E.showPrompt(/*LANG*/"Is the battery fully charged?",{title:/*LANG*/"Calibrate"}).then(ok => {
+        if (ok) {
+          var s=require("Storage").readJSON("setting.json");
+          s.batFullVoltage = (analogRead(D3)+analogRead(D3)+analogRead(D3)+analogRead(D3))/4;
+          require("Storage").writeJSON("setting.json",s);
+          E.showAlert(/*LANG*/"Calibrated!").then(() => load("settings.app.js"));
+        } else {
+          E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("settings.app.js"));
+        }
+      });
+    },
     /*LANG*/'Reset Settings': () => {
       E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => {
         if (v) {

From 43a3d70571d35896a24fb1364e9fb0f066391807 Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 11:53:25 +0100
Subject: [PATCH 57/94] run 0.14: Fix Bangle.js 1 issue where after the
 'overwrite track' menu, the start/stop button stopped working Add 'setUI' to
 Layout

---
 apps/run/ChangeLog     |   1 +
 apps/run/app.js        |   1 +
 apps/run/metadata.json |   2 +-
 modules/Layout.js      | 114 +++++++++++++++++++++--------------------
 4 files changed, 61 insertions(+), 57 deletions(-)

diff --git a/apps/run/ChangeLog b/apps/run/ChangeLog
index de070dbd8..95945be78 100644
--- a/apps/run/ChangeLog
+++ b/apps/run/ChangeLog
@@ -12,3 +12,4 @@
 0.11: Notifications fixes
 0.12: Fix for recorder not stopping at end of run. Bug introduced in 0.11
 0.13: Revert #1578 (stop duplicate entries) as with 2v12 menus it causes other boxes to be wiped (fix #1643)
+0.14: Fix Bangle.js 1 issue where after the 'overwrite track' menu, the start/stop button stopped working
diff --git a/apps/run/app.js b/apps/run/app.js
index 19dcd7e88..4038b8c1a 100644
--- a/apps/run/app.js
+++ b/apps/run/app.js
@@ -55,6 +55,7 @@ function onStartStop() {
       prepPromises.push(
         WIDGETS["recorder"].setRecording(true).then(() => {
           isMenuDisplayed = false;
+          layout.setUI(); // grab our input handling again
           layout.forgetLazyState();
           layout.render();
         })
diff --git a/apps/run/metadata.json b/apps/run/metadata.json
index afa52b2f7..933576a5d 100644
--- a/apps/run/metadata.json
+++ b/apps/run/metadata.json
@@ -1,6 +1,6 @@
 { "id": "run",
   "name": "Run",
-  "version":"0.13",
+  "version":"0.14",
   "description": "Displays distance, time, steps, cadence, pace and more for runners.",
   "icon": "app.png",
   "tags": "run,running,fitness,outdoors,gps",
diff --git a/modules/Layout.js b/modules/Layout.js
index 019d63815..43419a397 100644
--- a/modules/Layout.js
+++ b/modules/Layout.js
@@ -65,6 +65,8 @@ Other functions:
 * `layout.debug(obj)` - draw outlines for objects on screen
 * `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render)
 * `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render
+* `layout.setUI()` - (called when module initialised) This sets up input (buttons, touch, etc) with Bangle._setUI
+                     This can be useful if you called E.showMenu/showPrompt/etc and those grabbed input away from layour
 */
 
 
@@ -73,11 +75,10 @@ function Layout(layout, options) {
   // Do we have >1 physical buttons?
   this.physBtns = (process.env.HWVERSION==2) ? 1 : 3;
 
-  options = options || {};
-  this.lazy = options.lazy || false;
+  this.options = options || {};
+  this.lazy = this.options.lazy || false;
 
-  var btnList, uiSet;
-  Bangle.setUI(); // remove all existing input handlers
+  var btnList;
   if (process.env.HWVERSION!=2) {
     // no touchscreen, find any buttons in 'layout'
     btnList = [];
@@ -91,48 +92,19 @@ function Layout(layout, options) {
       this.physBtns = 0;
       this.buttons = btnList;
       this.selectedButton = -1;
-      Bangle.setUI({mode:"updown", back:options.back}, dir=>{
-        var s = this.selectedButton, l=this.buttons.length;
-        if (dir===undefined && this.buttons[s])
-          return this.buttons[s].cb();
-        if (this.buttons[s]) {
-          delete this.buttons[s].selected;
-          this.render(this.buttons[s]);
-        }
-        s = (s+l+dir) % l;
-        if (this.buttons[s]) {
-          this.buttons[s].selected = 1;
-          this.render(this.buttons[s]);
-        }
-        this.selectedButton = s;
-      });
-      uiSet = true;
     }
   }
-  if (options.back && !uiSet) Bangle.setUI({mode: "custom", back: options.back});
 
-  if (options.btns) {
-    var buttons = options.btns;
+  if (this.options.btns) {
+    var buttons = this.options.btns;
     this.b = buttons;
     if (this.physBtns >= buttons.length) {
-      // Handler for button watch events
-      function pressHandler(btn,e) {
-        if (e.time-e.lastTime > 0.75 && this.b[btn].cbl)
-          this.b[btn].cbl(e);
-        else
-          if (this.b[btn].cb) this.b[btn].cb(e);
-      }
       // enough physical buttons
       let btnHeight = Math.floor(Bangle.appRect.h / this.physBtns);
-      if (Bangle.btnWatches) Bangle.btnWatches.forEach(clearWatch);
-      Bangle.btnWatches = [];
       if (this.physBtns > 2 && buttons.length==1)
         buttons.unshift({label:""}); // pad so if we have a button in the middle
       while (this.physBtns > buttons.length)
         buttons.push({label:""});
-      if (buttons[0]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,0), BTN1, {repeat:true,edge:-1}));
-      if (buttons[1]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,1), BTN2, {repeat:true,edge:-1}));
-      if (buttons[2]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,2), BTN3, {repeat:true,edge:-1}));
       this._l.width = g.getWidth()-8; // text width
       this._l = {type:"h", filly:1, c: [
         this._l,
@@ -149,19 +121,8 @@ function Layout(layout, options) {
       if (btnList) btnList.push.apply(btnList, this._l.c[1].c);
     }
   }
-  if (process.env.HWVERSION==2) {
-
-    // Handler for touch events
-    function touchHandler(l,e) {
-      if (l.cb && e.x>=l.x && e.y>=l.y && e.x<=l.x+l.w && e.y<=l.y+l.h) {
-        if (e.type==2 && l.cbl) l.cbl(e); else if (l.cb) l.cb(e);
-      }
-      if (l.c) l.c.forEach(n => touchHandler(n,e));
-    }
-    Bangle.touchHandler = (_,e)=>touchHandler(this._l,e);
-    Bangle.on('touch',Bangle.touchHandler);
-  }
-
+  // Link in all buttons/touchscreen/etc
+  this.setUI();
   // recurse over layout doing some fixing up if needed
   var ll = this;
   function recurser(l) {
@@ -175,16 +136,57 @@ function Layout(layout, options) {
   this.updateNeeded = true;
 }
 
-Layout.prototype.remove = function (l) {
-  if (Bangle.btnWatches) {
-    Bangle.btnWatches.forEach(clearWatch);
-    delete Bangle.btnWatches;
+Layout.prototype.setUI = function() {
+  Bangle.setUI(); // remove all existing input handlers
+
+  var uiSet;
+  if (this.buttons) {
+    // multiple buttons so we'll jus use back/next/select
+    Bangle.setUI({mode:"updown", back:this.options.back}, dir=>{
+      var s = this.selectedButton, l=this.buttons.length;
+      if (dir===undefined && this.buttons[s])
+        return this.buttons[s].cb();
+      if (this.buttons[s]) {
+        delete this.buttons[s].selected;
+        this.render(this.buttons[s]);
+      }
+      s = (s+l+dir) % l;
+      if (this.buttons[s]) {
+        this.buttons[s].selected = 1;
+        this.render(this.buttons[s]);
+      }
+      this.selectedButton = s;
+    });
+    uiSet = true;
   }
-  if (Bangle.touchHandler) {
-    Bangle.removeListener("touch",Bangle.touchHandler);
-    delete Bangle.touchHandler;
+  if (this.options.back && !uiSet) Bangle.setUI({mode: "custom", back: this.options.back});
+  // physical buttons -> actual applications
+  if (this.b) {
+    // Handler for button watch events
+    function pressHandler(btn,e) {
+      if (e.time-e.lastTime > 0.75 && this.b[btn].cbl)
+        this.b[btn].cbl(e);
+      else
+        if (this.b[btn].cb) this.b[btn].cb(e);
+    }
+    if (Bangle.btnWatches) Bangle.btnWatches.forEach(clearWatch);
+    Bangle.btnWatches = [];
+    if (this.b[0]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,0), BTN1, {repeat:true,edge:-1}));
+    if (this.b[1]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,1), BTN2, {repeat:true,edge:-1}));
+    if (this.b[2]) Bangle.btnWatches.push(setWatch(pressHandler.bind(this,2), BTN3, {repeat:true,edge:-1}));
   }
-};
+  // Handle touch events on new Bangle.js
+  if (process.env.HWVERSION==2) {
+    function touchHandler(l,e) {
+      if (l.cb && e.x>=l.x && e.y>=l.y && e.x<=l.x+l.w && e.y<=l.y+l.h) {
+        if (e.type==2 && l.cbl) l.cbl(e); else if (l.cb) l.cb(e);
+      }
+      if (l.c) l.c.forEach(n => touchHandler(n,e));
+    }
+    Bangle.touchHandler = (_,e)=>touchHandler(this._l,e);
+    Bangle.on('touch',Bangle.touchHandler);
+  }
+}
 
 function prepareLazyRender(l, rectsToClear, drawList, rects, parentBg) {
   var bgCol = l.bgCol == null ? parentBg : g.toColor(l.bgCol);

From acae22049a78590fe36f21bf2c133ca2ee010bce Mon Sep 17 00:00:00 2001
From: Noah Howard <3317164+nh-99@users.noreply.github.com>
Date: Mon, 23 May 2022 09:06:48 -0400
Subject: [PATCH 58/94] Use locale for time, add date to watchface

---
 apps/mandelbrotclock/mandelbrotclock.js | 12 +++++++-----
 1 file changed, 7 insertions(+), 5 deletions(-)

diff --git a/apps/mandelbrotclock/mandelbrotclock.js b/apps/mandelbrotclock/mandelbrotclock.js
index 94636056e..d46dae782 100644
--- a/apps/mandelbrotclock/mandelbrotclock.js
+++ b/apps/mandelbrotclock/mandelbrotclock.js
@@ -1,4 +1,5 @@
 // MIT License - James Milner 2021
+const locale = require('locale');
 
 const mandelbrotBmp = {
   width: 176,
@@ -15,16 +16,17 @@ const mandelbrotBmp = {
 function draw() {
   g.drawImage(mandelbrotBmp);
   // work out how to display the current time
-  const d = new Date();
-  const h = d.getHours(),
-    m = d.getMinutes();
-  const time = h + ":" + ("0" + m).substr(-2);
+  var date = new Date();
+  var timeStr = locale.time(date,1);
+  var dateStr = locale.dow(date, true).toUpperCase() + ' ' + date.getDate();
 
   // Reset the state of the graphics library
   g.reset();
   g.setColor(1, 1, 1);
   g.setFont("Vector", 30);
-  g.drawString(time, 70, 68, false);
+  g.drawString(timeStr, 70, 58, false);
+  g.setFont("Vector", 20);
+  g.drawString(dateStr, 70, 88, false);
 }
 
 g.clear();

From e1fc5c0996bda7a4940fb0458655374e69b255c4 Mon Sep 17 00:00:00 2001
From: Noah Howard <3317164+nh-99@users.noreply.github.com>
Date: Mon, 23 May 2022 09:15:04 -0400
Subject: [PATCH 59/94] Make screen updates more efficient

---
 apps/mandelbrotclock/mandelbrotclock.js | 29 ++++++++++++++++++++++++-
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/apps/mandelbrotclock/mandelbrotclock.js b/apps/mandelbrotclock/mandelbrotclock.js
index d46dae782..ffc50e9bd 100644
--- a/apps/mandelbrotclock/mandelbrotclock.js
+++ b/apps/mandelbrotclock/mandelbrotclock.js
@@ -13,6 +13,18 @@ const mandelbrotBmp = {
   ),
 };
 
+// timeout used to update every minute
+var drawTimeout;
+
+// schedule a draw for the next minute
+function queueDraw() {
+  if (drawTimeout) clearTimeout(drawTimeout);
+  drawTimeout = setTimeout(function() {
+    drawTimeout = undefined;
+    draw();
+  }, 60000 - (Date.now() % 60000));
+}
+
 function draw() {
   g.drawImage(mandelbrotBmp);
   // work out how to display the current time
@@ -27,10 +39,25 @@ function draw() {
   g.drawString(timeStr, 70, 58, false);
   g.setFont("Vector", 20);
   g.drawString(dateStr, 70, 88, false);
+  
+  queueDraw();
 }
 
+// Clear the screen once, at startup
 g.clear();
 
 // draw immediately at first
 draw();
-var secondInterval = setInterval(draw, 1000);
+
+// Stop updates when LCD is off, restart when on
+Bangle.on('lcdPower',on=>{
+  if (on) {
+    draw(); // draw immediately, queue redraw
+  } else { // stop draw timer
+    if (drawTimeout) clearTimeout(drawTimeout);
+    drawTimeout = undefined;
+  }
+});
+
+// Show launcher when middle button pressed
+Bangle.setUI("clock");

From 1abe720645aa33ac0f87e979f13fd56aa9a6ba4a Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 15:20:32 +0100
Subject: [PATCH 60/94] Allow spaces to be typed in search terms

---
 core | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core b/core
index 147892754..404e98183 160000
--- a/core
+++ b/core
@@ -1 +1 @@
-Subproject commit 147892754eaf50c8581ebfb4d8651b9ec24aa44e
+Subproject commit 404e981834f2e8df9c505a8fab12ae12fe3bd562

From 54920af066c1c7bbed836f4b3852a388501994ef Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 16:54:00 +0100
Subject: [PATCH 61/94] android webview teaks

---
 android.html | 352 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 352 insertions(+)
 create mode 100644 android.html

diff --git a/android.html b/android.html
new file mode 100644
index 000000000..93999008f
--- /dev/null
+++ b/android.html
@@ -0,0 +1,352 @@
+
+
+  
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    
+    Bangle.js App Loader
+  
+  
+
+
+    
+
+    
+ +
+ + + + +
+
+ +
+ + +
+
+
+ + +
+
+
+
+
+ + + + + +
+ + +
+ + + + + + + + + + + + + + + + + From fd9569ffa9a12346d83844cc1f25341c906970c2 Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Mon, 23 May 2022 15:50:49 -0400 Subject: [PATCH 62/94] Add R2D2 clock --- apps/r2d2clk/ChangeLog | 1 + apps/r2d2clk/README.md | 7 ++++ apps/r2d2clk/app-icon.js | 1 + apps/r2d2clk/app.js | 67 +++++++++++++++++++++++++++++++++++++ apps/r2d2clk/app.png | Bin 0 -> 3143 bytes apps/r2d2clk/metadata.json | 14 ++++++++ 6 files changed, 90 insertions(+) create mode 100644 apps/r2d2clk/ChangeLog create mode 100644 apps/r2d2clk/README.md create mode 100644 apps/r2d2clk/app-icon.js create mode 100644 apps/r2d2clk/app.js create mode 100644 apps/r2d2clk/app.png create mode 100644 apps/r2d2clk/metadata.json diff --git a/apps/r2d2clk/ChangeLog b/apps/r2d2clk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/r2d2clk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/r2d2clk/README.md b/apps/r2d2clk/README.md new file mode 100644 index 000000000..24730a0bf --- /dev/null +++ b/apps/r2d2clk/README.md @@ -0,0 +1,7 @@ +# R2D2 Clock + +A clock with R2D2's shiny metal face on it. :) + +## Creator + +Made by [Noah Howard](https://github.com/nh-99) diff --git a/apps/r2d2clk/app-icon.js b/apps/r2d2clk/app-icon.js new file mode 100644 index 000000000..17ef6b709 --- /dev/null +++ b/apps/r2d2clk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("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")) \ No newline at end of file diff --git a/apps/r2d2clk/app.js b/apps/r2d2clk/app.js new file mode 100644 index 000000000..a7ead76f1 --- /dev/null +++ b/apps/r2d2clk/app.js @@ -0,0 +1,67 @@ +Graphics.prototype.setFontUndo = function(scale) { + // Actual height 19 (20 - 2) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqKAqooCqigKqKAAAACgAAKAAAoAACgAAAAAAAAACgAAKAAAoAACgAAAAAAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAAAAAKgoAqCgKqKAqooKiioqKKiooqKiioKKqAoqoCgqAKCoAAAACoCgKgKAiCoCIKgKioAqKgACoAAKgACoAAKgACoqAKioCoIgKgiAoCoCgKgAAAAKqgAqqAKqqAqqoKiioqKKiooqKiioKAKAoAoCgCgKAKAAAACgAAKAAAoAACgAAAAAAKqgAqqAKqqAqqoCgCgKAKAAAACgCgKAKAqqoCqqgCqoAKqgAAAACigAKKAAqoACqgAqoACqgAKqAAqoAAqoACqgAKKAAooAAAAAAoAACgAAKAAAoAAqqACqoAKqgAqqAAKAAAoAACgAAKAAAAAAACoAAKgAAqAACoAAAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAAAAACgAAKAAAoAACgAAAAAAoAACgAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAKAAAoAAAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoAAAAKCqAoKoCiqgKKqAoooCiigKKKAoooCqigKqKAKgoAqCgAAAAoAoCgCgKAKAoAoCiigKKKAoooCiigKqqAqqoAqqACqoAAAACqAAKoAAqoACqgAAKAAAoAACgAAKAAqqoCqqgKqqAqqoAAAAKoKAqgoCqigKqKAoooCiigKKKAoooCiqgKKqAoKgCgqAAAAAKqgAqqAKqqAqqoCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKAAAoAACgAAKAAAqqoCqqgCqqAKqoAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCqqgKqqAKqgAqqAAAAAKgAAqAAKqAAqoACigAKKAAooACigAKqqAqqoAqqgCqqAAAACgCgKAKAoAoCgCgAAAAoAqCgCoKAKgoAqAAAAAKAAAoAAKoAAqgAKqgAqqAKgqAqCoCgCgKAKAAAAAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAAAAKAKAoAoCoKgKgqAKqgAqqAAqgACqAACgAAKAAAAACgAAKAAAoAACgAAKKKAoooCiigKKKAqoACqgACoAAKgAAAAACqqAKqoCqqgKqqAoAACgAAKCoAoKgCiqgKKqAoooCiigKqqAqqoAqqACqoAAAAAqqgCqqAqqoCqqgKKAAooACigAKKAAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAoooCiigKKKAoooCqqgKqqAKCgAoKAAAAAKqgAqqAKqqAqqoCgCgKAKAoAoCgCgKAKAoAoCgCgKAKAAAACqqgKqqAqqoCqqgKAKAoAoCoKgKgqAKqgAqqAAqgACqAAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCgCgKAKAoAoCgCgAAAAKqoAqqgKqqAqqoCigAKKAAooACigAKAAAoAACgAAKAAAAAAAqqACqoAqqoCqqgKAKAoAoCiigKKKAoqoCiqgKKqAoqoAAAAKqqAqqoCqqgKqqAAoAACgAAKAAAoACqqgKqqAqqoCqqgAAAAoAoCgCgKAKAoAoCqqgKqqAqqoCqqgKAKAoAoCgCgKAKAAAAAAKAAAoAACoAAKgAAKAAAoAACgAAKAqqoCqqgKqoAqqgAAAAKqqAqqoCqqgKqqACqAAKoACqoAKqgCoKgKgqAoAoCgCgAAAAqqgCqqAKqqAqqoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAKgAAqAAKqqAqqoCqqgKqqAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAqqoCqqgKqqAqqoAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoCigAKKAAooACigAKqAAqoAAqAACoAAAAAAqqACqoAqqoCqqgKAKAoAoCgKgKAqAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAooACigAKKgAoqACqqgKqqAKioAqKgAAAAKgoAqCgKqKAqooCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKqqAqqoCqqgKqqAoAACgAAKAAAoAAAAAAKqoAqqgCqqgKqqAAAoAACgAAKAAAoCqqgKqqAqqgCqqAAAAAqqACqoAKqoAqqgAAKgAAqAACoAAKgKqoAqqgCqoAKqgAAAACqqgKqqAqqoCqqgACoAAKgACoAAKgAAKgAAqAKqqAqqoCqqgKqqAAAACoKgKgqAqqoCqqgAqgACqAAKoAAqgAqqoCqqgKgqAqCoAAAAKoAAqgACqgAKqAAAqoACqgAKqAAqoCqgAKqAAqgACqAAAAAAoCoCgKgKCqAoKoCiqgKKqAqooCqigKoKAqgoCoCgKgKAAAACqqgKqqAqqoCqqgKAKAoAoAAAAKAAAoAACoAAKgAAKgAAqAAAqAACoAACoAAKgAAKgAAqAAAqAACoAACgAAKAAAACgCgKAKAqqoCqqgKqqAqqoAAA"), 32, atob("DQULDw0RDQUHBw0NBQ0FEQ0FDQ0NDQ0NDQ0FBQsNCw0RDQ0NDQ0NDQ0NDQ0NDw0NDQ0NDQ0NDQ8NDQ0HEQc="), 22+(scale<<8)+(1<<16)); + return this; +}; + +var IMAGEWIDTH = 117; +var IMAGEHEIGHT = 60; +var r2d2 = require("heatshrink").decompress(atob("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")); + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function draw() { + //reset().clearRect(0,24,g.getWidth(),g.getHeight()-IMAGEHEIGHT); + // draw r2d2 + g.drawImage(r2d2, (g.getWidth()/2)-(IMAGEWIDTH/2), g.getHeight()-IMAGEHEIGHT); + + var x = g.getWidth()/2; + var y = g.getHeight()/2 - 30; + g.reset(); + // work out locale-friendly date/time + var date = new Date(); + var timeStr = require("locale").time(date,1).trim(); + var dateStr = require("locale").date(date).toUpperCase(); + + + // draw time + g.setFontAlign(0,0).setFont("Undo:3"); + g.clearRect(0,y-30,g.getWidth(),y+30); // clear the background + g.drawString(timeStr,x,y); + // draw date + y += 40; + g.setFontAlign(0,0).setFont("Undo"); + g.clearRect(0,y-10,g.getWidth(),y+20); // clear the background + g.drawString(dateStr,x,y); + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/r2d2clk/app.png b/apps/r2d2clk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..94502501d69c4d629548302d7d8b3fa7b5126452 GIT binary patch literal 3143 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 literal 0 HcmV?d00001 diff --git a/apps/r2d2clk/metadata.json b/apps/r2d2clk/metadata.json new file mode 100644 index 000000000..3d521e1e6 --- /dev/null +++ b/apps/r2d2clk/metadata.json @@ -0,0 +1,14 @@ +{ "id": "r2d2clk", + "name": "R2D2 Clock", + "shortName":"R2D2 Clock", + "version":"0.01", + "description": "A clock with R2D2's shiny metal face on it. :)", + "icon": "app.png", + "tags": "", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"r2d2clk.app.js","url":"app.js"}, + {"name":"r2d2clk.img","url":"app-icon.js","evaluate":true} + ] +} From 9973435b69f744bbdc420d02f20cd9f96f12b97e Mon Sep 17 00:00:00 2001 From: nujw Date: Tue, 24 May 2022 09:37:47 +1200 Subject: [PATCH 63/94] Update metadata.json --- apps/speedalt2/metadata.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/speedalt2/metadata.json b/apps/speedalt2/metadata.json index 801d65fb0..0de0b28bb 100644 --- a/apps/speedalt2/metadata.json +++ b/apps/speedalt2/metadata.json @@ -15,5 +15,10 @@ {"name":"speedalt2.img","url":"app-icon.js","evaluate":true}, {"name":"speedalt2.settings.js","url":"settings.js"} ], - "data": [{"name":"speedalt2.json"}] + "data": [ + {"name":"speedalt2.json"}, + {"name":"waypoints1.json"}, + {"name":"waypoints2.json"}, + {"name":"waypoints3.json"} + ] } From a7c9c124eac162a76aa58dd3e58b6005c4d59403 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Mon, 23 May 2022 17:05:34 -0700 Subject: [PATCH 64/94] Update ChangeLog --- apps/multitimer/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/multitimer/ChangeLog b/apps/multitimer/ChangeLog index 624f1b0fb..9b60f403a 100644 --- a/apps/multitimer/ChangeLog +++ b/apps/multitimer/ChangeLog @@ -1 +1,2 @@ -0.01: Initial version \ No newline at end of file +0.01: Initial version +0.02: Update for time_utils module From 5330784b3fc0bef3d04b1b3e6b09bf91de148f42 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Mon, 23 May 2022 17:05:59 -0700 Subject: [PATCH 65/94] Update alarm.js --- apps/multitimer/alarm.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/alarm.js b/apps/multitimer/alarm.js index fc0195455..97cbaa5fa 100644 --- a/apps/multitimer/alarm.js +++ b/apps/multitimer/alarm.js @@ -73,7 +73,7 @@ function showAlarm(alarm) { const settings = require("sched").getSettings(); let msg = ""; - msg += require("sched").formatTime(alarm.timer); + if (alarm.timer) msg += require("time_utils").formatTime(alarm.timer); if (alarm.msg) { msg += "\n"+alarm.msg; } @@ -86,7 +86,7 @@ function showAlarm(alarm) { if (alarm.data.hm && alarm.data.hm == true) { //hard mode extends auto-snooze time - buzzCount = buzzCount * 2; + buzzCount = buzzCount * 3; startHM(); } From 5854217f1ccc166dcf2f64fe1f6ca40117a41a53 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Mon, 23 May 2022 17:06:31 -0700 Subject: [PATCH 66/94] Update app.js --- apps/multitimer/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/app.js b/apps/multitimer/app.js index becaf6169..e5d77d860 100644 --- a/apps/multitimer/app.js +++ b/apps/multitimer/app.js @@ -258,7 +258,7 @@ function editTimer(idx, a) { a.last = 0; a.data.ot = a.timer; a.appid = "multitimer"; - a.js = "load('multitimer.alarm.js')"; + a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; if (idx < 0) alarms.push(a); else alarms[timerIdx[idx]] = a; require("sched").setAlarms(alarms); @@ -585,7 +585,7 @@ function editAlarm(idx, a) { var menu = { "": { "title": "Alarm" }, "< Back": () => { - if (a.data.hm == true) a.js = "load('multitimer.alarm.js')"; + if (a.data.hm == true) a.js = "(require('Storage').read('multitimer.alarm.js') !== undefined) ? load('multitimer.alarm.js') : load('sched.js')"; if (a.data.hm == false && a.js) delete a.js; if (idx >= 0) alarms[alarmIdx[idx]] = a; else alarms.push(a); From b56eff48c6e57e1f84b0675fba2ce59c14949244 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Mon, 23 May 2022 17:06:55 -0700 Subject: [PATCH 67/94] Update metadata.json --- apps/multitimer/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/multitimer/metadata.json b/apps/multitimer/metadata.json index 6e53e2c8c..abb958b90 100644 --- a/apps/multitimer/metadata.json +++ b/apps/multitimer/metadata.json @@ -1,7 +1,7 @@ { "id": "multitimer", "name": "Multi Timer", - "version": "0.01", + "version": "0.02", "description": "Set timers and chronographs (stopwatches) and watch them count down in real time. Pause, create, edit, and delete timers and chronos, and add custom labels/messages. Also sets alarms.", "icon": "app.png", "screenshots": [ @@ -19,4 +19,4 @@ ], "data": [{"name":"multitimer.json"}], "dependencies": {"scheduler":"type"} -} \ No newline at end of file +} From 3bdcc55c9b40dfcc28125dfc033e7fd3c8ca970a Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 24 May 2022 10:18:26 +1000 Subject: [PATCH 68/94] iconlaunch: Release app --- apps/iconlaunch/ChangeLog | 1 + apps/iconlaunch/README.md | 12 ++ apps/iconlaunch/app.js | 201 ++++++++++++++++++++++++++++++++ apps/iconlaunch/app.png | Bin 0 -> 888 bytes apps/iconlaunch/metadata.json | 18 +++ apps/iconlaunch/screenshot1.png | Bin 0 -> 4689 bytes apps/iconlaunch/screenshot2.png | Bin 0 -> 4752 bytes apps/iconlaunch/settings.js | 28 +++++ 8 files changed, 260 insertions(+) create mode 100644 apps/iconlaunch/ChangeLog create mode 100644 apps/iconlaunch/README.md create mode 100644 apps/iconlaunch/app.js create mode 100644 apps/iconlaunch/app.png create mode 100644 apps/iconlaunch/metadata.json create mode 100644 apps/iconlaunch/screenshot1.png create mode 100644 apps/iconlaunch/screenshot2.png create mode 100644 apps/iconlaunch/settings.js diff --git a/apps/iconlaunch/ChangeLog b/apps/iconlaunch/ChangeLog new file mode 100644 index 000000000..af7f83942 --- /dev/null +++ b/apps/iconlaunch/ChangeLog @@ -0,0 +1 @@ +0.01: Initial release diff --git a/apps/iconlaunch/README.md b/apps/iconlaunch/README.md new file mode 100644 index 000000000..0d36fdeb4 --- /dev/null +++ b/apps/iconlaunch/README.md @@ -0,0 +1,12 @@ +# Icon launcher + +A launcher inspired by smartphones, with an icon-only scrollable menu. + +This launcher shows 9 apps per screen, making it much faster to navigate versus the default launcher. + +![A screenshot](screenshot1.png) +![Another screenshot](screenshot2.png) + +## 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. diff --git a/apps/iconlaunch/app.js b/apps/iconlaunch/app.js new file mode 100644 index 000000000..5dec33284 --- /dev/null +++ b/apps/iconlaunch/app.js @@ -0,0 +1,201 @@ +const s = require("Storage"); +const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false }; + +if (!settings.fullscreen) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} + +var apps = s + .list(/\.info$/) + .map((app) => { + var a = s.readJSON(app, 1); + return ( + a && { + name: a.name, + type: a.type, + icon: a.icon, + sortorder: a.sortorder, + src: a.src, + } + ); + }) + .filter( + (app) => + app && + (app.type == "app" || + (app.type == "clock" && settings.showClocks) || + !app.type) + ); +apps.sort((a, b) => { + var n = (0 | a.sortorder) - (0 | b.sortorder); + if (n) return n; // do sortorder first + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; +}); +apps.forEach((app) => { + if (app.icon) app.icon = s.read(app.icon); // should just be a link to a memory area +}); + +let scroll = 0; +let selectedItem = -1; +const R = Bangle.appRect; + +const iconSize = 48; + +const appsN = Math.floor(R.w / iconSize); +const whitespace = (R.w - appsN * iconSize) / (appsN + 1); + +const itemSize = iconSize + whitespace; + +function drawItem(itemI, r) { + g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1); + let x = 0; + for (let i = itemI * appsN; i < appsN * (itemI + 1); i++) { + if (!apps[i]) break; + x += whitespace; + if (!apps[i].icon) { + g.setFontAlign(0,0,0).setFont("12x20:2").drawString("?", x + r.x+iconSize/2, r.y + iconSize/2); + } else { + g.drawImage(apps[i].icon, x + r.x, r.y); + } + if (selectedItem == i) { + g.drawRect( + x + r.x - 1, + r.y - 1, + x + r.x + iconSize + 1, + r.y + iconSize + 1 + ); + } + x += iconSize; + } + drawText(itemI); +} + +function drawItemAuto(i) { + var y = idxToY(i); + g.reset().setClipRect(R.x, y, R.x2, y + itemSize); + drawItem(i, { + x: R.x, + y: y, + w: R.w, + h: itemSize + }); + g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1); +} + +let lastIsDown = false; + +function drawText(i) { + const selectedApp = apps[selectedItem]; + const idy = (selectedItem - (selectedItem % 3)) / 3; + if (!selectedApp || i != idy) return; + const appY = idxToY(idy) + iconSize / 2; + g.setFontAlign(0, 0, 0); + g.setFont("12x20"); + const rect = g.stringMetrics(selectedApp.name); + g.clearRect( + R.w / 2 - rect.width / 2, + appY - rect.height / 2, + R.w / 2 + rect.width / 2, + appY + rect.height / 2 + ); + g.drawString(selectedApp.name, R.w / 2, appY); +} + +function selectItem(id, e) { + const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1); + const appId = id * appsN + iconN; + if (appId == selectedItem && apps[appId]) { + const app = apps[appId]; + if (!app.src || s.read(app.src) === undefined) { + E.showMessage( /*LANG*/ "App Source\nNot found"); + } else { + load(app.src); + } + } + selectedItem = appId; + drawItems(); +} + +function idxToY(i) { + return i * itemSize + R.y - (scroll & ~1); +} + +function YtoIdx(y) { + return Math.floor((y + (scroll & ~1) - R.y) / itemSize); +} + +function drawItems() { + g.reset().clearRect(R.x, R.y, R.x2, R.y2); + g.setClipRect(R.x, R.y, R.x2, R.y2); + var a = YtoIdx(R.y); + var b = Math.min(YtoIdx(R.y2), 99); + for (var i = a; i <= b; i++) + drawItem(i, { + x: R.x, + y: idxToY(i), + w: R.w, + h: itemSize, + }); + g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1); +} + +drawItems(); +g.flip(); + +const itemsN = Math.ceil(apps.length / appsN); + +Bangle.setUI({ + mode: "custom", + drag: (e) => { + let dy = e.dy; + if (scroll + R.h - dy > itemsN * itemSize) { + dy = scroll + R.h - itemsN * itemSize; + } + if (scroll - dy < 0) { + dy = scroll; + } + scroll -= dy; + scroll = E.clip(scroll, 0, itemSize * (itemsN - 1)); + g.setClipRect(R.x, R.y, R.x2, R.y2); + g.scroll(0, dy); + if (dy < 0) { + g.setClipRect(R.x, R.y2 - (1 - dy), R.x2, R.y2); + let i = YtoIdx(R.y2 - (1 - dy)); + let y = idxToY(i); + while (y < R.y2) { + drawItem(i, { + x: R.x, + y: y, + w: R.w, + h: itemSize, + }); + i++; + y += itemSize; + } + } else { + // d>0 + g.setClipRect(R.x, R.y, R.x2, R.y + dy); + let i = YtoIdx(R.y + dy); + let y = idxToY(i); + while (y > R.y - itemSize) { + drawItem(i, { + x: R.x, + y: y, + w: R.w, + h: itemSize, + }); + y -= itemSize; + i--; + } + } + g.setClipRect(0, 0, g.getWidth() - 1, g.getHeight() - 1); + }, + touch: (_, e) => { + if (e.y < R.y - 4) return; + var i = YtoIdx(e.y); + selectItem(i, e); + }, +}); diff --git a/apps/iconlaunch/app.png b/apps/iconlaunch/app.png new file mode 100644 index 0000000000000000000000000000000000000000..6f498aa20f592305a7a0788fa67a46d7a12f0d6f GIT binary patch literal 888 zcmV-;1Bd*HP) zZzpt+A8*GQfBgk^aKE|P3BZfO@zVI9=EjxRI)G(s9l)}69YCKf$tdF%u8TlFTBCke-#!7@j;O-i{ff1$hzaIOB^;s0|EpzsVSg@_VQCFuaIpPWXA7 zxdX~crl=m$SH}S48P>t$SS`&ip_=->YU=xkhld?W zmHhenxx2rx_qK!5>i)vz=L$dIS>M-GegEj_sFftiKvKiZDtR*-Z*6V0Pft%vJbUk2 z1S5BU;AZ@dHkTiM!9Df|k|Y@bp=0s@O-bQsG@9)XY>evr12^L*<^F)(qP}m1`hLD_ zy!dXnJLxa%z3q^C_80bF-=80lv{UouoqWFLJ^5hm2UbGs0G6#s6TpM|0ZDP1rg!rb zvME2{S>M-GeZSl7F3d}c&d$!t{e}HEi;r(X#J7+4>jySBH*0xGF%X4eILA+Hw8>1B zdwf$w(s1~Jn)<$K>ic8aPQ~$Umsj2sTs+7eEsye{J=jkd15E9S~5)l O0000oY_o zvKvpt$QEKIWy$*W`2)V^^TX$!bMHO(ywADko_p@OulKo$7UssB5K#yK0N^yaZGb-Y z)&HaHtf#iBX%TzsSOU?;`T+75vDMSyOrXAr75k|~vb!Vz0K5k#26|SZ*p0lz>|*%2 zxYoIof`9tKhGzn5CGVFq)GR~nCz%oFc;C*ENTequonQQdd+CCEoVb%kieXU*#~CWV zi`1wKI4p}-5|se3fvUmBM+dvV4-O7)MRkEiFP+12ChwJAlnou*MqRG~?*+ym7xQW9 z(2&c2?OF%j_|%TBXc^9*KU>2~CGk4M_~#GXeE!E`!KCx+(a=J$GGL@Q*iYxAa#dqI zqLGBU4pA<;ZH)%uNHHPY0P{0?Xq!KlhyZREqxqv-ki%52h@USGFQ{Y=+A&Fsg`;X@9f+{Ee(d>ePk%G z#jTbHIeh-i;v>tHe%HVTr@ZJNTVaZOva|kc<5PLRdMoPlRyz&(#;;3T>Fsc6ySj1! zP7{**?k>Mrn+A;_-4_34a^`HAy5H)0sYhER-6jeRv+oT?v6rk;jtHO`6dgo2$kk2s zWRiOjQO-INL>MCj{`;-EGFXV*)-?T4q+r=4j-2(pYS~)l4HYfz(+PtNNI1dSzyjN@ zgUI>v$BpDxc(p-d1oIitG`^X{;F8;hWOx`$J(1GBlQG$<$VM!nzU8w#efE5o&E{|V zdPML|e@f==TOf^4m&~8l;Vqvcrd|EGkMY+ZY_z^9uTE14bHM+ynA&des+?c9QYhq+ zHSxRQ*;B8`PzD#jQz^e8%1QmuE#rDaF;R9qbasTG8lsEmTApv@sjdLvgd@!Z+KgXagxis{T{a|Q- z`M*m5{&jpMT_JkBtB%I7>K7Me zgr(au7bjPD0Pdmj$FMFgKdv(k_k5V3r#IgyL5VYZl8;M76^SJ7na5IIJKg@!-ir!C z=H){<;wZPMR~>Oc(+ZnUw<;G($S?#*ku}c4>IP-rP+x;O51R8b&)e0#pT$*pjRgI& zjMXTulIP63e|hI1*1;{-j!R91p=~8&^jgVbzrIe+&qJqS?G8jkjl@G$hnaa$?6r~3 zgWCq;t4Jut}YC-Tmg zy#EN$v{OpT>jKJlOTl1()cPF>GDjS(zsb-{08o^f6vSL#d07g<8QULltm$WjTHOQD zQJE>>4p(>ptwaRm{3ARdlu%M6E_Aw@6kT8F8{1s~h(B6=+uH+VseW!(G>j5t#~It* zSo5#Z1^j$4DH}up1ONXiB`SJ}wDdFEjuU$ac0z3x=ZBB$`|YAn#Mv1uXI4*G$TVB;N!lr$W+vI15A?Pw*+i4+~8v#+=!)E`N#14zWIRb z8r`BeL}Rh}oiW1T;5t|J?)knAKZT>5NTC3K7d7&m{&3)qC0a@XEby7=uGbYFTzK z+dh;hQeiG3!NY$hf@b@t =J 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 literal 0 HcmV?d00001 diff --git a/apps/iconlaunch/screenshot2.png b/apps/iconlaunch/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..b17efa78b87d432dac7a0c80be616cb7a1e74452 GIT binary patch literal 4752 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 S?|(lh!05W^wJJUQgZ}~Ti1d*F literal 0 HcmV?d00001 diff --git a/apps/iconlaunch/settings.js b/apps/iconlaunch/settings.js new file mode 100644 index 000000000..9fbc7ae6a --- /dev/null +++ b/apps/iconlaunch/settings.js @@ -0,0 +1,28 @@ +// make sure to enclose the function in parentheses +(function(back) { + let settings = Object.assign({ + showClocks: true, + fullscreen: false + }, require("Storage").readJSON("launch.json", true) || {}); + + let fonts = g.getFonts(); + function save(key, value) { + settings[key] = value; + require("Storage").write("launch.json",settings); + } + const appMenu = { + "": { "title": /*LANG*/"Launcher" }, + /*LANG*/"< Back": back, + /*LANG*/"Show Clocks": { + value: settings.showClocks == true, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: (m) => { save("showClocks", m) } + }, + /*LANG*/"Fullscreen": { + value: settings.fullscreen == true, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: (m) => { save("fullscreen", m) } + } + }; + E.showMenu(appMenu); +}); From 28eb907f57d7c4a44ba2bc00faf101f01a727725 Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Mon, 23 May 2022 20:39:54 -0400 Subject: [PATCH 69/94] Add properly sized icon --- apps/r2d2clk/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/r2d2clk/app-icon.js b/apps/r2d2clk/app-icon.js index 17ef6b709..246df9376 100644 --- a/apps/r2d2clk/app-icon.js +++ b/apps/r2d2clk/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("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")) \ No newline at end of file +require("heatshrink").decompress(atob("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")) \ No newline at end of file From 6c28d94b76e0758157b837174dae2179b8a823bb Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Mon, 23 May 2022 22:00:38 -0400 Subject: [PATCH 70/94] Add new metadata --- apps/r2d2clk/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/r2d2clk/metadata.json b/apps/r2d2clk/metadata.json index 3d521e1e6..f2cde76f4 100644 --- a/apps/r2d2clk/metadata.json +++ b/apps/r2d2clk/metadata.json @@ -4,7 +4,8 @@ "version":"0.01", "description": "A clock with R2D2's shiny metal face on it. :)", "icon": "app.png", - "tags": "", + "type": "clock", + "tags": "clock", "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ From 2ef59c470fdd35c0559a2b648a5b0d050af27c70 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Tue, 24 May 2022 10:18:03 +0200 Subject: [PATCH 71/94] implemented "direct launch" and "one click exit" settings --- apps/iconlaunch/ChangeLog | 1 + apps/iconlaunch/app.js | 10 +++++++++- apps/iconlaunch/metadata.json | 2 +- apps/iconlaunch/settings.js | 10 ++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) diff --git a/apps/iconlaunch/ChangeLog b/apps/iconlaunch/ChangeLog index af7f83942..4a72a9f28 100644 --- a/apps/iconlaunch/ChangeLog +++ b/apps/iconlaunch/ChangeLog @@ -1 +1,2 @@ 0.01: Initial release +0.02: implemented "direct launch" and "one click exit" settings \ No newline at end of file diff --git a/apps/iconlaunch/app.js b/apps/iconlaunch/app.js index 5dec33284..4eeaff589 100644 --- a/apps/iconlaunch/app.js +++ b/apps/iconlaunch/app.js @@ -1,5 +1,8 @@ const s = require("Storage"); -const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false }; +const settings = s.readJSON("launch.json", true) || { showClocks: true, fullscreen: false,direct:false,oneClickExit:false }; + +if( settings.oneClickExit) + setWatch(_=> load(), BTN1); if (!settings.fullscreen) { Bangle.loadWidgets(); @@ -107,6 +110,11 @@ function drawText(i) { function selectItem(id, e) { const iconN = E.clip(Math.floor((e.x - R.x) / itemSize), 0, appsN - 1); const appId = id * appsN + iconN; + if( settings.direct && apps[appId]) + { + load(apps[appId].src); + return; + } if (appId == selectedItem && apps[appId]) { const app = apps[appId]; if (!app.src || s.read(app.src) === undefined) { diff --git a/apps/iconlaunch/metadata.json b/apps/iconlaunch/metadata.json index 1dddb66b4..01e447672 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.01", + "version": "0.02", "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 9fbc7ae6a..e9667047c 100644 --- a/apps/iconlaunch/settings.js +++ b/apps/iconlaunch/settings.js @@ -22,6 +22,16 @@ value: settings.fullscreen == true, format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", onchange: (m) => { save("fullscreen", m) } + }, + /*LANG*/"Direct launch": { + value: settings.direct == true, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: (m) => { save("direct", m) } + }, + /*LANG*/"One click exit": { + value: settings.oneClickExit == true, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: (m) => { save("oneClickExit", m) } } }; E.showMenu(appMenu); From 9ef9137bc060757c491117d08a9effe26337029f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 24 May 2022 09:50:10 +0100 Subject: [PATCH 72/94] update after https://github.com/espruino/BangleApps/pull/1868 since we use waypoints.json too --- apps/speedalt2/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/speedalt2/metadata.json b/apps/speedalt2/metadata.json index 0de0b28bb..2a111af28 100644 --- a/apps/speedalt2/metadata.json +++ b/apps/speedalt2/metadata.json @@ -17,6 +17,7 @@ ], "data": [ {"name":"speedalt2.json"}, + {"name":"waypoints.json"}, {"name":"waypoints1.json"}, {"name":"waypoints2.json"}, {"name":"waypoints3.json"} From 4ded6c844ac4e8ecbbf4ee1a5d85b57ddc1e0baa Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 24 May 2022 22:54:16 +1000 Subject: [PATCH 73/94] iconlaunch: Change icon to one by icons8 This doesn't bump the version, as it doesn't change anything on the watch, just the website --- apps/iconlaunch/app.png | Bin 888 -> 1395 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/iconlaunch/app.png b/apps/iconlaunch/app.png index 6f498aa20f592305a7a0788fa67a46d7a12f0d6f..1c8068c50d528badf72b8b3355668c55feb377f7 100644 GIT binary patch delta 1376 zcmV-m1)uu(2J;G#B!32COGiWi{{a60|De66lK=n(C`m*?RA_nwDFa5?mTXX^@)+0xcR-V}wvKQR9P2jRsMOf|@9=zR&^@QZ>4T#At%m zN?WufUMK}&W7{mD*0xZMQp{M zA^zQ9w5A!h23Q#s09iXu+KRh+pi%%7zCU6s&i~x>7|xQNV7pMHFp3mTs_#o>U7UZy zOI_JHTXWbGkXH-KK8Ly66LwYPFbx%ZIa0ZsG&z*8|JLFjGMyS*OS)}Qa@gvfQw4H5 zo^a0kNIZaJcZO`ruLza~)R z8%JhlB`j%&C2cUX0>E-7-ur103mdE1e`XN?#FQLYz)-7-78pM&vJ+_z5!*N$P z8QA*{*hC`YQ}{1nLbBcU*(zI!e(%N>0jYPfQ6#(r0>NU}Dh%LUe+vea|Bxk%sDn-B z4kZ*Yf7S{fU9uAZO%L<)K%0F=d9{#J4TD}w6A0K!zhEI?ZOINi1)F0C7w42y?S7fl z{(oaM`|6Vya2H*ysg+n>P=z9=Q|ekxV4#t}KqIBDH7IgAo`OvYIj73SnhNOfdkJen zq+u@^-P_6N-i{bS^}XvtU*Q?m24!@C|*3xAPs-!BXvFEd@kzVW6E)&g{GS zY=u<2SV%&Efk9V)%WV_0gDDq#FJVGLPj!uRvhFvEq)Llvaww_tAWXi-8HFqylz$gi zvo!BvM1nF5Bq1Q0))Ez^qL^%r6C&ix^49ang6G-1xQ?Q1Pr?|>ER@O`=N9)XEOtG_ z`QN^|*;bUZoX3~GPKUqA)cu<7Kq_mTvT#u9T8$(m7S66@Z15wl^&etc-Ugg|<0FtTfqgp7O6T2le0JCMp6r)H?M_kM_b z&RTk|{y^E>7jObUUjBljY!9b;KejIb#@%84ihU?@*mUKixSbkjv#)_>Us(gCuGN&y zT@OHK|5qIE+HXZM@f`?hPM&UiHS&BHYn)MZ^?yxR8zZP*=hE+I6ZTK)5~tD~8W>y{ iJe9KfrZ9zj9sdBN)1W#sewIi80000A?Ru!uXiB+ox*s*S;K1kISuh3nqJ^=^>Wn0)pks|R1yn=&};t2b)u-n*4 zJkGRL6RMn@e?HG#d*nOkUiiZzpt+A8*GQfBgk^aKE|P3BZfO@zVI9=EjxR zI)G(s9l)}69e+TdEXgdY80Zy_@5ZO}ktZKyd@&Ob$&$<>ijba_&KRCNCEku1q6K*o z={VzyOQ;PDalgqJi1K@<^)S4MXioTfo4EtZNv5bC(pSd-DbM$ z_0XDGLWbK92)7?F+d2!iE;9m_VZU6Ukt$KH#ih}Iu(E?Pl^A1<@FmKhPxRbWP|(r0b}9^@@3=6Py9f1 zMMpkidU>haE|k{Q3F0yT7pawu92@{=((w3P0dk-`7-q z|LEwbl_bePQp3zDc{3YtZEdwrPftrcd+%BVBY$^);AZ@dHkTiM!9Df|k|Y@bp=0s@ zO-bQsG@9)XY>evr12^L*<^F)(qP}m1`hLD_y!dXnJLxa%z3q^C_80bF-=80lv{Uou zoqWFLJ^5hm2UbGs0G6#s6TpM|0ZDP1rg!rbvME2{S>M-GeZSl7F3d}c&d$!t{e}HE zi&~FwLBzL@_v;5XH#ci}Nih(GVK~Q6Y_!Qtm3w?sMAC5hftvchYU=xWhMmi&Y1+HE rxNz_1_g^1eC#f09dVKx#xctCBF?nJquv#)r00000NkvXXu0mjfF}Jb| From c3468fc0e91c4454d2e932deeeb5ce9dba7c8cf2 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 24 May 2022 16:28:22 +0100 Subject: [PATCH 74/94] bthrm 0.09: Misc Fixes and improvements (https://github.com/espruino/BangleApps/pull/1655) --- apps/bthrm/ChangeLog | 1 + apps/bthrm/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 41eec666a..7ca8319b6 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -21,3 +21,4 @@ Adds some preset modes and a custom one Restructure the settings menu 0.08: Allow scanning for devices in settings +0.09: Misc Fixes and improvements (https://github.com/espruino/BangleApps/pull/1655) diff --git a/apps/bthrm/metadata.json b/apps/bthrm/metadata.json index 85c19ab33..39c1ff8bb 100644 --- a/apps/bthrm/metadata.json +++ b/apps/bthrm/metadata.json @@ -2,7 +2,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.08", + "version": "0.09", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", From 4f512a15f4c23ade6788fd57628317dba178c97d Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Tue, 24 May 2022 12:02:37 -0400 Subject: [PATCH 75/94] Remove new apps from master branch --- apps/discgolf/ChangeLog | 1 - apps/discgolf/README.md | 14 --- apps/discgolf/app-icon.js | 1 - apps/discgolf/app.js | 171 ------------------------------- apps/discgolf/app.png | Bin 10687 -> 0 bytes apps/discgolf/metadata.json | 14 --- apps/discgolf/summary_screen.png | Bin 3025 -> 0 bytes apps/discgolf/throw_screen.png | Bin 2459 -> 0 bytes apps/r2d2clk/ChangeLog | 1 - apps/r2d2clk/README.md | 7 -- apps/r2d2clk/app-icon.js | 1 - apps/r2d2clk/app.js | 67 ------------ apps/r2d2clk/app.png | Bin 3143 -> 0 bytes apps/r2d2clk/metadata.json | 15 --- 14 files changed, 292 deletions(-) delete mode 100644 apps/discgolf/ChangeLog delete mode 100644 apps/discgolf/README.md delete mode 100644 apps/discgolf/app-icon.js delete mode 100644 apps/discgolf/app.js delete mode 100644 apps/discgolf/app.png delete mode 100644 apps/discgolf/metadata.json delete mode 100644 apps/discgolf/summary_screen.png delete mode 100644 apps/discgolf/throw_screen.png delete mode 100644 apps/r2d2clk/ChangeLog delete mode 100644 apps/r2d2clk/README.md delete mode 100644 apps/r2d2clk/app-icon.js delete mode 100644 apps/r2d2clk/app.js delete mode 100644 apps/r2d2clk/app.png delete mode 100644 apps/r2d2clk/metadata.json diff --git a/apps/discgolf/ChangeLog b/apps/discgolf/ChangeLog deleted file mode 100644 index 220e1d1c2..000000000 --- a/apps/discgolf/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -0.01: Initial version of disc golf app. Has throw and hole counter, along with summary screen. Uses buttons for holes & throws. \ No newline at end of file diff --git a/apps/discgolf/README.md b/apps/discgolf/README.md deleted file mode 100644 index 34a9dfe90..000000000 --- a/apps/discgolf/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# Disc Golf - -Individual score tracking for disc golf on your wrist. - -![](throw_screen.png) -![](summary_screen.png) - -## Usage - -Press the side button once to increment throws. Double-tap the side button to increment holes. View your game summary with the button in the upper right of the screen. - -## Creator - -Made by [Noah Howard](https://github.com/nh-99) diff --git a/apps/discgolf/app-icon.js b/apps/discgolf/app-icon.js deleted file mode 100644 index cfc07a2fa..000000000 --- a/apps/discgolf/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEwxH+AH4A/ABFzudsAAImmABIppAAIQBFcYMBzwMDFbP+y5RJHYiHdLJYADG5AATzxaNFotszwuXFp5sFLq4tIVpANNF0D4FRqobFJ5peaFxKtJXgi9VzxdSLwwvUFyYvaFxIhKOYwvSFxoAEzyjJF7I/VFyzRjU5QICuYiNBxBJTQp7lFF7byQGQYwSOwovSOpJsFdpwvTao4voMQ4vQOQQwmX4oQCBAwwgCxAvWDIwvPGD4vIy4WJSSzcFMCCpGMC+eGChiUYJwjJPIRiTF5xULBxwvVEJgQQCIQOEF5X+zwfLSoY0HBYg9FF5a2QDSQvNWqJbBAQTaOMTY9PF6DFNAB4uRGLguUYygucfKwubGQgzLFsAAHFYV6Fc4A/AAw=")) \ No newline at end of file diff --git a/apps/discgolf/app.js b/apps/discgolf/app.js deleted file mode 100644 index 68bbd817d..000000000 --- a/apps/discgolf/app.js +++ /dev/null @@ -1,171 +0,0 @@ -Bangle.loadWidgets(); - -// -// App imports -// -var Layout = require("Layout"); - -// -// App variables -// -var holeCount = 1; -var throwCount = 0; -var drawTimeout; -var currentScreen = 'throw'; -var redraw = true; -var update = true; -var holeSummary = { - "< Back" : () => { update = true; redraw = true; currentScreen = 'throw'; E.showMenu(); createThrowLayout(); }, - "Hole #1": { value: 0 }, - "Hole #2": { value: 0 }, - "Hole #3": { value: 0 }, - "Hole #4": { value: 0 }, - "Hole #5": { value: 0 }, - "Hole #6": { value: 0 }, - "Hole #7": { value: 0 }, - "Hole #8": { value: 0 }, - "Hole #9": { value: 0 }, - "Front": { value: 0 }, - "Hole #10": { value: 0 }, - "Hole #11": { value: 0 }, - "Hole #12": { value: 0 }, - "Hole #13": { value: 0 }, - "Hole #14": { value: 0 }, - "Hole #15": { value: 0 }, - "Hole #16": { value: 0 }, - "Hole #17": { value: 0 }, - "Hole #18": { value: 0 }, - "Back": { value: 0 }, -}; - -// Images -function getBackImage() { - return atob("FhYBAAAAEAAAwAAHAAA//wH//wf//g///BwB+DAB4EAHwAAPAAA8AADwAAPAAB4AAHgAB+AH/wA/+AD/wAH8AA=="); -} -function getMenuImage() { - return { - width : 20, height : 20, bpp : 1, - buffer : require("heatshrink").decompress(atob("AAk///D//8CBcDBwITB4AiVA")) - }; -} -function getBasketIcon() { - return { - width : 20, height : 20, bpp : 1, - buffer : require("heatshrink").decompress(atob("gFggF/8EH/0AiWAgtogEW0EDt0Am3ggfsgEf4EB/EA//4j//wEChEP/8AgwnDAgw")) - }; -} -function getFrisbeeIcon() { - return { - width : 20, height : 20, bpp : 1, - buffer : require("heatshrink").decompress(atob("AAf+gF/wE+uEPx0B+PAn0cgf/4F3/0G/1g9/7g1/7AJB4+f/k+v3B/Hcg4WBj/4E4ItC")) - }; -} - -var throwLayout; - -function createThrowLayout() { - throwLayout = new Layout( { - type:"v", c: [ - // Title & menu button - { - type:"h", fillx:1, valign:-1, bgCol:g.theme.bg2, col: g.theme.fg2, c: [ - {type:"img", src:getBasketIcon()}, - {type:"txt", pad:4, font:"15%", label:holeCount, id: "holeCount"}, - {type:"txt", pad:4, font:"15%", label: '', fillx:1}, - {type:"btn", src:getMenuImage(), halign:1, cb: l=>{ currentScreen = 'summary'; update = true; redraw = true; }} - ] - }, - // Throw count - { - type:"h", filly:1, c: [ - {type:"img", pad:4, src:getFrisbeeIcon() }, - {type:"txt", fillx:1, font:"6x8:2", label:"Throws: "+throwCount, id:"throwCount"} - ] - } - ] - }, {lazy:true}); -} - -function incrementHole() { - if (holeCount > 18) return; - resetThrow(); - holeCount += 1; - holeSummary["Hole #" + holeCount] = {value: 0}; -} -function incrementThrow() { - throwCount += 1; - holeSummary["Hole #" + holeCount] = {value: throwCount}; -} -function decrementThrow() { - throwCount -= 1; - holeSummary["Hole #" + holeCount] = {value: throwCount}; -} -function resetThrow() { - throwCount = 0; -} -function computeFrontScore() { - var scoreSum = 0; - for (var i = 1; i < 10; i++) { - scoreSum += holeSummary["Hole #" + i].value; - } - holeSummary.Front = {value: scoreSum}; -} -function computeBackScore() { - var scoreSum = 0; - for (var i = 1; i < 19; i++) { - scoreSum += holeSummary["Hole #" + i].value; - } - holeSummary.Back = {value: scoreSum}; -} - -// update the app state/variables -function updateApp() { - throwLayout.holeCount.label = holeCount; - throwLayout.throwCount.label = "Throws: " + throwCount; -} - -// update the screen -function draw() { - updateApp(); - if (redraw) { - throwLayout.forgetLazyState(); - redraw = false; - } - if (update) { - if (currentScreen == 'throw') { - throwLayout.render(); - } else if (currentScreen == 'summary') { - E.showMenu(holeSummary); - } - update = false; - } - // schedule a draw for the next 500ms - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, 500 - (Date.now() % 500)); -} - -// -// button press events -// -setWatch((p) => { - if (p.time - p.lastTime < 0.2) { - decrementThrow(); - incrementHole(); - } else { - incrementThrow(); - } - computeFrontScore(); - computeBackScore(); - update = true; -}, BTN, {edge:"rising", debounce:50, repeat:true}); - -// -// main app function start -// -g.clear(); -Bangle.drawWidgets(); -createThrowLayout(); -draw(); \ No newline at end of file diff --git a/apps/discgolf/app.png b/apps/discgolf/app.png deleted file mode 100644 index 6aba5e54816571474aae74f0db98b39a7db7933a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10687 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 diff --git a/apps/discgolf/metadata.json b/apps/discgolf/metadata.json deleted file mode 100644 index 6d56f05e4..000000000 --- a/apps/discgolf/metadata.json +++ /dev/null @@ -1,14 +0,0 @@ -{ "id": "discgolf", - "name": "Disc Golf", - "shortName":"Disc Golf", - "version":"0.01", - "description": "A personal disc golf score tracker", - "icon": "app.png", - "tags": "", - "supports" : ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"discgolf.app.js","url":"app.js"}, - {"name":"discgolf.img","url":"app-icon.js","evaluate":true} - ] -} diff --git a/apps/discgolf/summary_screen.png b/apps/discgolf/summary_screen.png deleted file mode 100644 index 480d36eddfa8646b874e96458520979ac2de4ad6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3025 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 diff --git a/apps/r2d2clk/ChangeLog b/apps/r2d2clk/ChangeLog deleted file mode 100644 index 5560f00bc..000000000 --- a/apps/r2d2clk/ChangeLog +++ /dev/null @@ -1 +0,0 @@ -0.01: New App! diff --git a/apps/r2d2clk/README.md b/apps/r2d2clk/README.md deleted file mode 100644 index 24730a0bf..000000000 --- a/apps/r2d2clk/README.md +++ /dev/null @@ -1,7 +0,0 @@ -# R2D2 Clock - -A clock with R2D2's shiny metal face on it. :) - -## Creator - -Made by [Noah Howard](https://github.com/nh-99) diff --git a/apps/r2d2clk/app-icon.js b/apps/r2d2clk/app-icon.js deleted file mode 100644 index 246df9376..000000000 --- a/apps/r2d2clk/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("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")) \ No newline at end of file diff --git a/apps/r2d2clk/app.js b/apps/r2d2clk/app.js deleted file mode 100644 index a7ead76f1..000000000 --- a/apps/r2d2clk/app.js +++ /dev/null @@ -1,67 +0,0 @@ -Graphics.prototype.setFontUndo = function(scale) { - // Actual height 19 (20 - 2) - this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqKAqooCqigKqKAAAACgAAKAAAoAACgAAAAAAAAACgAAKAAAoAACgAAAAAAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAAAAAKgoAqCgKqKAqooKiioqKKiooqKiioKKqAoqoCgqAKCoAAAACoCgKgKAiCoCIKgKioAqKgACoAAKgACoAAKgACoqAKioCoIgKgiAoCoCgKgAAAAKqgAqqAKqqAqqoKiioqKKiooqKiioKAKAoAoCgCgKAKAAAACgAAKAAAoAACgAAAAAAKqgAqqAKqqAqqoCgCgKAKAAAACgCgKAKAqqoCqqgCqoAKqgAAAACigAKKAAqoACqgAqoACqgAKqAAqoAAqoACqgAKKAAooAAAAAAoAACgAAKAAAoAAqqACqoAKqgAqqAAKAAAoAACgAAKAAAAAAACoAAKgAAqAACoAAAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAAAAACgAAKAAAoAACgAAAAAAoAACgAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAKAAAoAAAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoAAAAKCqAoKoCiqgKKqAoooCiigKKKAoooCqigKqKAKgoAqCgAAAAoAoCgCgKAKAoAoCiigKKKAoooCiigKqqAqqoAqqACqoAAAACqAAKoAAqoACqgAAKAAAoAACgAAKAAqqoCqqgKqqAqqoAAAAKoKAqgoCqigKqKAoooCiigKKKAoooCiqgKKqAoKgCgqAAAAAKqgAqqAKqqAqqoCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKAAAoAACgAAKAAAqqoCqqgCqqAKqoAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCqqgKqqAKqgAqqAAAAAKgAAqAAKqAAqoACigAKKAAooACigAKqqAqqoAqqgCqqAAAACgCgKAKAoAoCgCgAAAAoAqCgCoKAKgoAqAAAAAKAAAoAAKoAAqgAKqgAqqAKgqAqCoCgCgKAKAAAAAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAAAAKAKAoAoCoKgKgqAKqgAqqAAqgACqAACgAAKAAAAACgAAKAAAoAACgAAKKKAoooCiigKKKAqoACqgACoAAKgAAAAACqqAKqoCqqgKqqAoAACgAAKCoAoKgCiqgKKqAoooCiigKqqAqqoAqqACqoAAAAAqqgCqqAqqoCqqgKKAAooACigAKKAAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAoooCiigKKKAoooCqqgKqqAKCgAoKAAAAAKqgAqqAKqqAqqoCgCgKAKAoAoCgCgKAKAoAoCgCgKAKAAAACqqgKqqAqqoCqqgKAKAoAoCoKgKgqAKqgAqqAAqgACqAAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCgCgKAKAoAoCgCgAAAAKqoAqqgKqqAqqoCigAKKAAooACigAKAAAoAACgAAKAAAAAAAqqACqoAqqoCqqgKAKAoAoCiigKKKAoqoCiqgKKqAoqoAAAAKqqAqqoCqqgKqqAAoAACgAAKAAAoACqqgKqqAqqoCqqgAAAAoAoCgCgKAKAoAoCqqgKqqAqqoCqqgKAKAoAoCgCgKAKAAAAAAKAAAoAACoAAKgAAKAAAoAACgAAKAqqoCqqgKqoAqqgAAAAKqqAqqoCqqgKqqACqAAKoACqoAKqgCoKgKgqAoAoCgCgAAAAqqgCqqAKqqAqqoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAKgAAqAAKqqAqqoCqqgKqqAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAqqoCqqgKqqAqqoAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoCigAKKAAooACigAKqAAqoAAqAACoAAAAAAqqACqoAqqoCqqgKAKAoAoCgKgKAqAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAooACigAKKgAoqACqqgKqqAKioAqKgAAAAKgoAqCgKqKAqooCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKqqAqqoCqqgKqqAoAACgAAKAAAoAAAAAAKqoAqqgCqqgKqqAAAoAACgAAKAAAoCqqgKqqAqqgCqqAAAAAqqACqoAKqoAqqgAAKgAAqAACoAAKgKqoAqqgCqoAKqgAAAACqqgKqqAqqoCqqgACoAAKgACoAAKgAAKgAAqAKqqAqqoCqqgKqqAAAACoKgKgqAqqoCqqgAqgACqAAKoAAqgAqqoCqqgKgqAqCoAAAAKoAAqgACqgAKqAAAqoACqgAKqAAqoCqgAKqAAqgACqAAAAAAoCoCgKgKCqAoKoCiqgKKqAqooCqigKoKAqgoCoCgKgKAAAACqqgKqqAqqoCqqgKAKAoAoAAAAKAAAoAACoAAKgAAKgAAqAAAqAACoAACoAAKgAAKgAAqAAAqAACoAACgAAKAAAACgCgKAKAqqoCqqgKqqAqqoAAA"), 32, atob("DQULDw0RDQUHBw0NBQ0FEQ0FDQ0NDQ0NDQ0FBQsNCw0RDQ0NDQ0NDQ0NDQ0NDw0NDQ0NDQ0NDQ8NDQ0HEQc="), 22+(scale<<8)+(1<<16)); - return this; -}; - -var IMAGEWIDTH = 117; -var IMAGEHEIGHT = 60; -var r2d2 = require("heatshrink").decompress(atob("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")); - -// timeout used to update every minute -var drawTimeout; - -// schedule a draw for the next minute -function queueDraw() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, 60000 - (Date.now() % 60000)); -} - -function draw() { - //reset().clearRect(0,24,g.getWidth(),g.getHeight()-IMAGEHEIGHT); - // draw r2d2 - g.drawImage(r2d2, (g.getWidth()/2)-(IMAGEWIDTH/2), g.getHeight()-IMAGEHEIGHT); - - var x = g.getWidth()/2; - var y = g.getHeight()/2 - 30; - g.reset(); - // work out locale-friendly date/time - var date = new Date(); - var timeStr = require("locale").time(date,1).trim(); - var dateStr = require("locale").date(date).toUpperCase(); - - - // draw time - g.setFontAlign(0,0).setFont("Undo:3"); - g.clearRect(0,y-30,g.getWidth(),y+30); // clear the background - g.drawString(timeStr,x,y); - // draw date - y += 40; - g.setFontAlign(0,0).setFont("Undo"); - g.clearRect(0,y-10,g.getWidth(),y+20); // clear the background - g.drawString(dateStr,x,y); - // queue draw in one minute - queueDraw(); -} - -// Clear the screen once, at startup -g.clear(); -// draw immediately at first, queue update -draw(); -// Stop updates when LCD is off, restart when on -Bangle.on('lcdPower',on=>{ - if (on) { - draw(); // draw immediately, queue redraw - } else { // stop draw timer - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } -}); -// Show launcher when middle button pressed -Bangle.setUI("clock"); -// Load widgets -Bangle.loadWidgets(); -Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/r2d2clk/app.png b/apps/r2d2clk/app.png deleted file mode 100644 index 94502501d69c4d629548302d7d8b3fa7b5126452..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3143 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 diff --git a/apps/r2d2clk/metadata.json b/apps/r2d2clk/metadata.json deleted file mode 100644 index f2cde76f4..000000000 --- a/apps/r2d2clk/metadata.json +++ /dev/null @@ -1,15 +0,0 @@ -{ "id": "r2d2clk", - "name": "R2D2 Clock", - "shortName":"R2D2 Clock", - "version":"0.01", - "description": "A clock with R2D2's shiny metal face on it. :)", - "icon": "app.png", - "type": "clock", - "tags": "clock", - "supports" : ["BANGLEJS2"], - "readme": "README.md", - "storage": [ - {"name":"r2d2clk.app.js","url":"app.js"}, - {"name":"r2d2clk.img","url":"app-icon.js","evaluate":true} - ] -} From f5b85299a3bc17b2ebf38d2cba94b11e6e2370ef Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Tue, 24 May 2022 12:04:19 -0400 Subject: [PATCH 76/94] Revert patches to mandelbrot clock --- apps/mandelbrotclock/mandelbrotclock.js | 41 ++++--------------------- 1 file changed, 6 insertions(+), 35 deletions(-) diff --git a/apps/mandelbrotclock/mandelbrotclock.js b/apps/mandelbrotclock/mandelbrotclock.js index ffc50e9bd..94636056e 100644 --- a/apps/mandelbrotclock/mandelbrotclock.js +++ b/apps/mandelbrotclock/mandelbrotclock.js @@ -1,5 +1,4 @@ // MIT License - James Milner 2021 -const locale = require('locale'); const mandelbrotBmp = { width: 176, @@ -13,51 +12,23 @@ const mandelbrotBmp = { ), }; -// timeout used to update every minute -var drawTimeout; - -// schedule a draw for the next minute -function queueDraw() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, 60000 - (Date.now() % 60000)); -} - function draw() { g.drawImage(mandelbrotBmp); // work out how to display the current time - var date = new Date(); - var timeStr = locale.time(date,1); - var dateStr = locale.dow(date, true).toUpperCase() + ' ' + date.getDate(); + const d = new Date(); + const h = d.getHours(), + m = d.getMinutes(); + const time = h + ":" + ("0" + m).substr(-2); // Reset the state of the graphics library g.reset(); g.setColor(1, 1, 1); g.setFont("Vector", 30); - g.drawString(timeStr, 70, 58, false); - g.setFont("Vector", 20); - g.drawString(dateStr, 70, 88, false); - - queueDraw(); + g.drawString(time, 70, 68, false); } -// Clear the screen once, at startup g.clear(); // draw immediately at first draw(); - -// Stop updates when LCD is off, restart when on -Bangle.on('lcdPower',on=>{ - if (on) { - draw(); // draw immediately, queue redraw - } else { // stop draw timer - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } -}); - -// Show launcher when middle button pressed -Bangle.setUI("clock"); +var secondInterval = setInterval(draw, 1000); From c64882a82feee1bdb4836d8e9a46170cd2fa31df Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Tue, 24 May 2022 12:09:25 -0400 Subject: [PATCH 77/94] Add r2d2 clock --- apps/r2d2clk/ChangeLog | 1 + apps/r2d2clk/README.md | 11 ++++++ apps/r2d2clk/app-icon.js | 1 + apps/r2d2clk/app.js | 67 ++++++++++++++++++++++++++++++++++++ apps/r2d2clk/app.png | Bin 0 -> 3143 bytes apps/r2d2clk/metadata.json | 15 ++++++++ apps/r2d2clk/screenshot.png | Bin 0 -> 2885 bytes 7 files changed, 95 insertions(+) create mode 100644 apps/r2d2clk/ChangeLog create mode 100644 apps/r2d2clk/README.md create mode 100644 apps/r2d2clk/app-icon.js create mode 100644 apps/r2d2clk/app.js create mode 100644 apps/r2d2clk/app.png create mode 100644 apps/r2d2clk/metadata.json create mode 100644 apps/r2d2clk/screenshot.png diff --git a/apps/r2d2clk/ChangeLog b/apps/r2d2clk/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/r2d2clk/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/r2d2clk/README.md b/apps/r2d2clk/README.md new file mode 100644 index 000000000..cd98b9170 --- /dev/null +++ b/apps/r2d2clk/README.md @@ -0,0 +1,11 @@ +# R2D2 Clock + +A clock with R2D2's shiny metal face on it. :) + +![](screenshot.png) + +## Creator + +Made by [Noah Howard](https://github.com/nh-99) + +Based on [Interlaced Clock](https://github.com/espruino/BangleApps/tree/master/apps/intclock) \ No newline at end of file diff --git a/apps/r2d2clk/app-icon.js b/apps/r2d2clk/app-icon.js new file mode 100644 index 000000000..246df9376 --- /dev/null +++ b/apps/r2d2clk/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("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")) \ No newline at end of file diff --git a/apps/r2d2clk/app.js b/apps/r2d2clk/app.js new file mode 100644 index 000000000..a7ead76f1 --- /dev/null +++ b/apps/r2d2clk/app.js @@ -0,0 +1,67 @@ +Graphics.prototype.setFontUndo = function(scale) { + // Actual height 19 (20 - 2) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKqKAqooCqigKqKAAAACgAAKAAAoAACgAAAAAAAAACgAAKAAAoAACgAAAAAAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAKqqAqqoCqqgKqqAKCgAoKAAAAAKgoAqCgKqKAqooKiioqKKiooqKiioKKqAoqoCgqAKCoAAAACoCgKgKAiCoCIKgKioAqKgACoAAKgACoAAKgACoqAKioCoIgKgiAoCoCgKgAAAAKqgAqqAKqqAqqoKiioqKKiooqKiioKAKAoAoCgCgKAKAAAACgAAKAAAoAACgAAAAAAKqgAqqAKqqAqqoCgCgKAKAAAACgCgKAKAqqoCqqgCqoAKqgAAAACigAKKAAqoACqgAqoACqgAKqAAqoAAqoACqgAKKAAooAAAAAAoAACgAAKAAAoAAqqACqoAKqgAqqAAKAAAoAACgAAKAAAAAAACoAAKgAAqAACoAAAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAAAAACgAAKAAAoAACgAAAAAAoAACgAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAqAACoAAKAAAoAAAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoAAAAKCqAoKoCiqgKKqAoooCiigKKKAoooCqigKqKAKgoAqCgAAAAoAoCgCgKAKAoAoCiigKKKAoooCiigKqqAqqoAqqACqoAAAACqAAKoAAqoACqgAAKAAAoAACgAAKAAqqoCqqgKqqAqqoAAAAKoKAqgoCqigKqKAoooCiigKKKAoooCiqgKKqAoKgCgqAAAAAKqgAqqAKqqAqqoCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKAAAoAACgAAKAAAqqoCqqgCqqAKqoAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCqqgKqqAKqgAqqAAAAAKgAAqAAKqAAqoACigAKKAAooACigAKqqAqqoAqqgCqqAAAACgCgKAKAoAoCgCgAAAAoAqCgCoKAKgoAqAAAAAKAAAoAAKoAAqgAKqgAqqAKgqAqCoCgCgKAKAAAAAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAoKACgoAKCgAAAAKAKAoAoCoKgKgqAKqgAqqAAqgACqAACgAAKAAAAACgAAKAAAoAACgAAKKKAoooCiigKKKAqoACqgACoAAKgAAAAACqqAKqoCqqgKqqAoAACgAAKCoAoKgCiqgKKqAoooCiigKqqAqqoAqqACqoAAAAAqqgCqqAqqoCqqgKKAAooACigAKKAAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAoooCiigKKKAoooCqqgKqqAKCgAoKAAAAAKqgAqqAKqqAqqoCgCgKAKAoAoCgCgKAKAoAoCgCgKAKAAAACqqgKqqAqqoCqqgKAKAoAoCoKgKgqAKqgAqqAAqgACqAAAAACqoAKqgCqqgKqqAoooCiigKKKAoooCgCgKAKAoAoCgCgAAAAKqoAqqgKqqAqqoCigAKKAAooACigAKAAAoAACgAAKAAAAAAAqqACqoAqqoCqqgKAKAoAoCiigKKKAoqoCiqgKKqAoqoAAAAKqqAqqoCqqgKqqAAoAACgAAKAAAoACqqgKqqAqqoCqqgAAAAoAoCgCgKAKAoAoCqqgKqqAqqoCqqgKAKAoAoCgCgKAKAAAAAAKAAAoAACoAAKgAAKAAAoAACgAAKAqqoCqqgKqoAqqgAAAAKqqAqqoCqqgKqqACqAAKoACqoAKqgCoKgKgqAoAoCgCgAAAAqqgCqqAKqqAqqoAACgAAKAAAoAACgAAKAAAoAACgAAKAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAKgAAqAAKqqAqqoCqqgKqqAAAACqqgKqqAqqoCqqgCoAAKgAAKgAAqAAqqoCqqgKqqAqqoAAAACqoAKqgCqqgKqqAoAoCgCgKAKAoAoCqqgKqqAKqgAqqAAAAAqqoCqqgKqqAqqoCigAKKAAooACigAKqAAqoAAqAACoAAAAAAqqACqoAqqoCqqgKAKAoAoCgKgKAqAqqoCqqgCqqAKqoAAAAKqqAqqoCqqgKqqAooACigAKKgAoqACqqgKqqAKioAqKgAAAAKgoAqCgKqKAqooCiigKKKAoooCiigKKqAoqoCgqAKCoAAAACgAAKAAAoAACgAAKqqAqqoCqqgKqqAoAACgAAKAAAoAAAAAAKqoAqqgCqqgKqqAAAoAACgAAKAAAoCqqgKqqAqqgCqqAAAAAqqACqoAKqoAqqgAAKgAAqAACoAAKgKqoAqqgCqoAKqgAAAACqqgKqqAqqoCqqgACoAAKgACoAAKgAAKgAAqAKqqAqqoCqqgKqqAAAACoKgKgqAqqoCqqgAqgACqAAKoAAqgAqqoCqqgKgqAqCoAAAAKoAAqgACqgAKqAAAqoACqgAKqAAqoCqgAKqAAqgACqAAAAAAoCoCgKgKCqAoKoCiqgKKqAqooCqigKoKAqgoCoCgKgKAAAACqqgKqqAqqoCqqgKAKAoAoAAAAKAAAoAACoAAKgAAKgAAqAAAqAACoAACoAAKgAAKgAAqAAAqAACoAACgAAKAAAACgCgKAKAqqoCqqgKqqAqqoAAA"), 32, atob("DQULDw0RDQUHBw0NBQ0FEQ0FDQ0NDQ0NDQ0FBQsNCw0RDQ0NDQ0NDQ0NDQ0NDw0NDQ0NDQ0NDQ8NDQ0HEQc="), 22+(scale<<8)+(1<<16)); + return this; +}; + +var IMAGEWIDTH = 117; +var IMAGEHEIGHT = 60; +var r2d2 = require("heatshrink").decompress(atob("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")); + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +function draw() { + //reset().clearRect(0,24,g.getWidth(),g.getHeight()-IMAGEHEIGHT); + // draw r2d2 + g.drawImage(r2d2, (g.getWidth()/2)-(IMAGEWIDTH/2), g.getHeight()-IMAGEHEIGHT); + + var x = g.getWidth()/2; + var y = g.getHeight()/2 - 30; + g.reset(); + // work out locale-friendly date/time + var date = new Date(); + var timeStr = require("locale").time(date,1).trim(); + var dateStr = require("locale").date(date).toUpperCase(); + + + // draw time + g.setFontAlign(0,0).setFont("Undo:3"); + g.clearRect(0,y-30,g.getWidth(),y+30); // clear the background + g.drawString(timeStr,x,y); + // draw date + y += 40; + g.setFontAlign(0,0).setFont("Undo"); + g.clearRect(0,y-10,g.getWidth(),y+20); // clear the background + g.drawString(dateStr,x,y); + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/r2d2clk/app.png b/apps/r2d2clk/app.png new file mode 100644 index 0000000000000000000000000000000000000000..94502501d69c4d629548302d7d8b3fa7b5126452 GIT binary patch literal 3143 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 literal 0 HcmV?d00001 diff --git a/apps/r2d2clk/metadata.json b/apps/r2d2clk/metadata.json new file mode 100644 index 000000000..f2cde76f4 --- /dev/null +++ b/apps/r2d2clk/metadata.json @@ -0,0 +1,15 @@ +{ "id": "r2d2clk", + "name": "R2D2 Clock", + "shortName":"R2D2 Clock", + "version":"0.01", + "description": "A clock with R2D2's shiny metal face on it. :)", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"r2d2clk.app.js","url":"app.js"}, + {"name":"r2d2clk.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/r2d2clk/screenshot.png b/apps/r2d2clk/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..f0b3ca84f82f68f44b89a9c46a66fbe09adf0422 GIT binary patch literal 2885 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 literal 0 HcmV?d00001 From 43b07419b92a8ce1ee4759fac15f5b3f1fc2bf1a Mon Sep 17 00:00:00 2001 From: Gabriele Monaco Date: Wed, 25 May 2022 08:59:24 +0200 Subject: [PATCH 78/94] messages 0.38: using Telegram icon on Telegram FOSS --- apps/messages/app.js | 1 + apps/messages/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index aac59e246..ee9afc041 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -112,6 +112,7 @@ function getMessageImage(msg) { if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); + if (s=="telegram foss") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index ab9b03273..fd09fdfe4 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.37", + "version": "0.38", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From 8e4063004c86e06249d9c215ffc1d56d078defb2 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 May 2022 08:24:20 +0100 Subject: [PATCH 79/94] changelog and duplicate fix --- apps/messages/ChangeLog | 2 +- apps/messages/app.js | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index d6ad393d6..53157f0d8 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -50,4 +50,4 @@ 0.35: Reset graphics colors before rendering a message (possibly fix #1752) 0.36: Ensure a new message plus an almost immediate deletion of that message doesn't load the messages app (fix #1362) 0.37: Now use the setUI 'back' icon in the top left rather than specific buttons/menu items - +0.38: Add telegram foss handling diff --git a/apps/messages/app.js b/apps/messages/app.js index ee9afc041..93c8ebf3e 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -111,8 +111,7 @@ function getMessageImage(msg) { if (s=="sms message") return getNotificationImage(); if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); - if (s=="telegram") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); - if (s=="telegram foss") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); + if (s=="telegram" || s=="telegram foss") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); From cb890e6fc586e5efc5a26f1019c7384482d4ff12 Mon Sep 17 00:00:00 2001 From: Lubomir Date: Tue, 24 May 2022 22:08:43 +1000 Subject: [PATCH 80/94] android: Fix SMS bug --- apps/android/ChangeLog | 1 + apps/android/boot.js | 13 ++++++++++++- apps/android/metadata.json | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 55f456795..f13ccd95c 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -8,3 +8,4 @@ 0.07: Include charging state in battery updates to phone 0.08: Handling of alarms 0.09: Alarm vibration, repeat, and auto-snooze now handled by sched +0.10: Fix SMS bug diff --git a/apps/android/boot.js b/apps/android/boot.js index fb2101aa4..efd7e7e46 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -3,6 +3,7 @@ Bluetooth.println(""); Bluetooth.println(JSON.stringify(message)); } + var lastMsg; var settings = require("Storage").readJSON("android.settings.json",1)||{}; //default alarm settings @@ -18,7 +19,17 @@ /* TODO: Call handling, fitness */ var HANDLERS = { // {t:"notify",id:int, src,title,subject,body,sender,tel:string} add - "notify" : function() { Object.assign(event,{t:"add",positive:true, negative:true});require("messages").pushMessage(event); }, + "notify" : function() { + Object.assign(event,{t:"add",positive:true, negative:true}); + // Detect a weird GadgetBridge bug and fix it + // For some reason SMS messages send two GB notifications, with different sets of info + if (lastMsg && event.body == lastMsg.body && lastMsg.src == undefined && event.src == "Messages") { + // Mutate the other message + event.id = lastMsg.id; + } + lastMsg = event; + require("messages").pushMessage(event); + }, // {t:"notify~",id:int, title:string} // modified "notify~" : function() { event.t="modify";require("messages").pushMessage(event); }, // {t:"notify-",id:int} // remove diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 4051a344b..bf37b8407 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.09", + "version": "0.10", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", From 68edab1a18ef817bfd47f3531c5c51adf0b1b4e9 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 May 2022 09:58:02 +0100 Subject: [PATCH 81/94] Move getMessageImage/getMessageImageCol to the library as per https://github.com/espruino/BangleApps/pull/1872 No version bump as no functionality changes --- apps/messages/app.js | 95 +++----------------------------------------- apps/messages/lib.js | 81 +++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 90 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 93c8ebf3e..63154c4b4 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -67,99 +67,14 @@ function saveMessages() { require("Storage").writeJSON("messages.json",MESSAGES) } -function getNotificationImage() { - return atob("HBKBAD///8H///iP//8cf//j4//8f5//j/x/8//j/H//H4//4PB//EYj/44HH/Hw+P4//8fH//44///xH///g////A=="); -} -function getFBIcon() { - return atob("GBiBAAAAAAAAAAAYAAD/AAP/wAf/4A/48A/g8B/g+B/j+B/n+D/n/D8A/B8A+B+B+B/n+A/n8A/n8Afn4APnwADnAAAAAAAAAAAAAA=="); -} function getPosImage() { return atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA=="); } function getNegImage() { return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="); } -/* -* icons should be 24x24px with 1bpp colors and 'Transparency to Color' -* http://www.espruino.com/Image+Converter -*/ -function getMessageImage(msg) { - if (msg.img) return atob(msg.img); - var s = (msg.src||"").toLowerCase(); - if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA="); - if (s=="bibel") return atob("GBgBAAAAA//wD//4D//4H//4H/f4H/f4H+P4H4D4H4D4H/f4H/f4H/f4H/f4H/f4H//4H//4H//4GAAAEAAAEAAACAAAB//4AAAA"); - if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); - if (s=="corona-warn") return atob("GBgBAAAAABwAAP+AAf/gA//wB/PwD/PgDzvAHzuAP8EAP8AAPAAAPMAAP8AAH8AAHzsADzuAB/PAB/PgA//wAP/gAH+AAAwAAAAA"); - if (s=="discord") return atob("GBgBAAAAAAAAAAAAAIEABwDgDP8wH//4H//4P//8P//8P//8Pjx8fhh+fzz+f//+f//+e//ePH48HwD4AgBAAAAAAAAAAAAAAAAA"); - if (s=="facebook") return getFBIcon(); - if (s=="gmail") return getNotificationImage(); - if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); - if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); - if (s=="home assistant") return atob("FhaBAAAAAADAAAeAAD8AAf4AD/3AfP8D7fwft/D/P8ec572zbzbNsOEhw+AfD8D8P4fw/z/D/P8P8/w/z/AAAAA="); - if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); - if (s=="kalender") return atob("GBgBBgBgBQCgff++RQCiRgBiQAACf//+QAACQAACR//iRJkiRIEiR//iRNsiRIEiRJkiR//iRIEiRIEiR//iQAACQAACf//+AAAA"); - if (s=="lieferando") return atob("GBgBABgAAH5wAP9wAf/4A//4B//4D//4H//4P/88fV8+fV4//V4//Vw/HVw4HVw4HBg4HBg4HBg4HDg4Hjw4Hj84Hj44Hj44Hj44"); - if (s=="mail") return getNotificationImage(); - if (s=="messenger") return getFBIcon(); - if (s=="nina") return atob("GBgBAAAABAAQCAAICAAIEAAEEgAkJAgSJBwSKRxKSj4pUn8lVP+VVP+VUgAlSgApKQBKJAASJAASEgAkEAAECAAICAAIBAAQAAAA"); - if (s=="outlook mail") return atob("HBwBAAAAAAAAAAAIAAAfwAAP/gAB/+AAP/5/A//v/D/+/8P/7/g+Pv8Dye/gPd74w5znHDnOB8Oc4Pw8nv/Dwe/8Pj7/w//v/D/+/8P/7/gf/gAA/+AAAfwAAACAAAAAAAAAAAA="); - if (s=="phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA="); - if (s=="post & dhl") return atob("GBgBAPgAE/5wMwZ8NgN8NgP4NgP4HgP4HgPwDwfgD//AB/+AAf8AAAAABs7AHcdgG4MwAAAAGESAFESAEkSAEnyAEkSAFESAGETw"); - if (s=="signal") return atob("GBgBAAAAAGwAAQGAAhggCP8QE//AB//oJ//kL//wD//0D//wT//wD//wL//0J//kB//oA//ICf8ABfxgBYBAADoABMAABAAAAAAA"); - if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); - if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); - if (s=="sms message") return getNotificationImage(); - if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); - if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); - if (s=="telegram" || s=="telegram foss") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); - if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); - if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); - if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); - if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); - if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); - if (s=="wordfeud") return atob("GBgCWqqqqqqlf//////9v//////+v/////++v/////++v8///Lu+v8///L++v8///P/+v8v//P/+v9v//P/+v+fx/P/+v+Pk+P/+v/PN+f/+v/POuv/+v/Ofdv/+v/NvM//+v/I/Y//+v/k/k//+v/i/w//+v/7/6//+v//////+v//////+f//////9Wqqqqqql"); - if (s=="youtube") return atob("GBgBAAAAAAAAAAAAAAAAAf8AH//4P//4P//8P//8P5/8P4/8f4P8f4P8P4/8P5/8P//8P//8P//4H//4Af8AAAAAAAAAAAAAAAAA"); - if (msg.id=="music") return atob("FhaBAH//+/////////////h/+AH/4Af/gB/+H3/7/f/v9/+/3/7+f/vB/w8H+Dwf4PD/x/////////////3//+A="); - return getNotificationImage(); -} -function getMessageImageCol(msg,def) { - return { - // generic colors, using B2-safe colors - "alarm": "#fff", - "mail": "#ff0", - "music": "#f0f", - "phone": "#0f0", - "sms message": "#0ff", - // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) - // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) - "bibel": "#54342c", - "discord": "#738adb", - "facebook": "#4267b2", - "gmail": "#ea4335", - "google home": "#fbbc05", - "hangouts": "#1ba261", - "home assistant": "#fff", // ha-blue is #41bdf5, but that's the background - "instagram": "#dd2a7b", - "liferando": "#ee5c00", - "messenger": "#0078ff", - "nina": "#e57004", - "outlook mail": "#0072c6", - "post & dhl": "#f2c101", - "signal": "#00f", - "skype": "#00aff0", - "slack": "#e51670", - "snapchat": "#ff0", - "teams": "#464eb8", - "telegram": "#0088cc", - "threema": "#000", - "to do": "#3999e5", - "twitch": "#6441A4", - "twitter": "#1da1f2", - "whatsapp": "#4fce5d", - "wordfeud": "#e7d3c7", - "youtube": "#f00", - }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); -} + + function showMapMessage(msg) { active = "map"; @@ -411,7 +326,7 @@ function showMessage(msgid) { {type:"txt", font:fontSmall, label:msg.src||/*LANG*/"Message", bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2, halign:1 }, title?{type:"txt", font:titleFont, label:title, bgCol:g.theme.bg2, col: g.theme.fg2, fillx:1, pad:2 }:{}, ]}, - { type:"btn", src:getMessageImage(msg), col:getMessageImageCol(msg), pad: 3, cb:()=>{ + { type:"btn", src:require("messages").getMessageImage(msg), col:require("messages").getMessageImageCol(msg), pad: 3, cb:()=>{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, @@ -467,14 +382,14 @@ function checkMessages(options) { g.clearRect(r.x,r.y,r.x+r.w, r.y+r.h); if (!msg) return; var x = r.x+2, title = msg.title, body = msg.body; - var img = getMessageImage(msg); + var img = require("messages").getMessageImage(msg); if (msg.id=="music") { title = msg.artist || /*LANG*/"Music"; body = msg.track; } if (img) { var fg = g.getColor(); - g.setColor(getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering + g.setColor(require("messages").getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering .setColor(fg); // only color the icon x += 50; } diff --git a/apps/messages/lib.js b/apps/messages/lib.js index c39c8886c..3f801e101 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -104,3 +104,84 @@ exports.clearAll = function(event) { if (global.WIDGETS && WIDGETS.messages) WIDGETS.messages.hide(); } + +exports.getMessageImage = function(msg) { + /* + * icons should be 24x24px with 1bpp colors and 'Transparency to Color' + * http://www.espruino.com/Image+Converter + */ + if (msg.img) return atob(msg.img); + var s = (msg.src||"").toLowerCase(); + if (s=="alarm" || s =="alarmclockreceiver") return atob("GBjBAP////8AAAAAAAACAEAHAOAefng5/5wTgcgHAOAOGHAMGDAYGBgYGBgYGBgYGBgYDhgYBxgMATAOAHAHAOADgcAB/4AAfgAAAAAAAAA="); + if (s=="bibel") return atob("GBgBAAAAA//wD//4D//4H//4H/f4H/f4H+P4H4D4H4D4H/f4H/f4H/f4H/f4H/f4H//4H//4H//4GAAAEAAAEAAACAAAB//4AAAA"); + if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); + if (s=="corona-warn") return atob("GBgBAAAAABwAAP+AAf/gA//wB/PwD/PgDzvAHzuAP8EAP8AAPAAAPMAAP8AAH8AAHzsADzuAB/PAB/PgA//wAP/gAH+AAAwAAAAA"); + if (s=="discord") return atob("GBgBAAAAAAAAAAAAAIEABwDgDP8wH//4H//4P//8P//8P//8Pjx8fhh+fzz+f//+f//+e//ePH48HwD4AgBAAAAAAAAAAAAAAAAA"); + if (s=="facebook" || s=="messenger") return atob("GBiBAAAAAAAAAAAYAAD/AAP/wAf/4A/48A/g8B/g+B/j+B/n+D/n/D8A/B8A+B+B+B/n+A/n8A/n8Afn4APnwADnAAAAAAAAAAAAAA=="); + if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); + if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); + if (s=="home assistant") return atob("FhaBAAAAAADAAAeAAD8AAf4AD/3AfP8D7fwft/D/P8ec572zbzbNsOEhw+AfD8D8P4fw/z/D/P8P8/w/z/AAAAA="); + if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); + if (s=="kalender") return atob("GBgBBgBgBQCgff++RQCiRgBiQAACf//+QAACQAACR//iRJkiRIEiR//iRNsiRIEiRJkiR//iRIEiRIEiR//iQAACQAACf//+AAAA"); + if (s=="lieferando") return atob("GBgBABgAAH5wAP9wAf/4A//4B//4D//4H//4P/88fV8+fV4//V4//Vw/HVw4HVw4HBg4HBg4HBg4HDg4Hjw4Hj84Hj44Hj44Hj44"); + if (s=="nina") return atob("GBgBAAAABAAQCAAICAAIEAAEEgAkJAgSJBwSKRxKSj4pUn8lVP+VVP+VUgAlSgApKQBKJAASJAASEgAkEAAECAAICAAIBAAQAAAA"); + if (s=="outlook mail") return atob("HBwBAAAAAAAAAAAIAAAfwAAP/gAB/+AAP/5/A//v/D/+/8P/7/g+Pv8Dye/gPd74w5znHDnOB8Oc4Pw8nv/Dwe/8Pj7/w//v/D/+/8P/7/gf/gAA/+AAAfwAAACAAAAAAAAAAAA="); + if (s=="phone") return atob("FxeBABgAAPgAAfAAB/AAD+AAH+AAP8AAP4AAfgAA/AAA+AAA+AAA+AAB+AAB+AAB+OAB//AB//gB//gA//AA/8AAf4AAPAA="); + if (s=="post & dhl") return atob("GBgBAPgAE/5wMwZ8NgN8NgP4NgP4HgP4HgPwDwfgD//AB/+AAf8AAAAABs7AHcdgG4MwAAAAGESAFESAEkSAEnyAEkSAFESAGETw"); + if (s=="signal") return atob("GBgBAAAAAGwAAQGAAhggCP8QE//AB//oJ//kL//wD//0D//wT//wD//wL//0J//kB//oA//ICf8ABfxgBYBAADoABMAABAAAAAAA"); + if (s=="skype") return atob("GhoBB8AAB//AA//+Af//wH//+D///w/8D+P8Afz/DD8/j4/H4fP5/A/+f4B/n/gP5//B+fj8fj4/H8+DB/PwA/x/A/8P///B///gP//4B//8AD/+AAA+AA=="); + if (s=="slack") return atob("GBiBAAAAAAAAAABAAAHvAAHvAADvAAAPAB/PMB/veD/veB/mcAAAABzH8B3v+B3v+B3n8AHgAAHuAAHvAAHvAADGAAAAAAAAAAAAAA=="); + if (s=="snapchat") return atob("GBgBAAAAAAAAAH4AAf+AAf+AA//AA//AA//AA//AA//AH//4D//wB//gA//AB//gD//wH//4f//+P//8D//wAf+AAH4AAAAAAAAA"); + if (s=="teams") return atob("GBgBAAAAAAAAAAQAAB4AAD8IAA8cP/M+f/scf/gIeDgAfvvefvvffvvffvvffvvff/vff/veP/PeAA/cAH/AAD+AAD8AAAQAAAAA"); + if (s=="telegram" || s=="telegram foss") return atob("GBiBAAAAAAAAAAAAAAAAAwAAHwAA/wAD/wAf3gD/Pgf+fh/4/v/z/P/H/D8P/Acf/AM//AF/+AF/+AH/+ADz+ADh+ADAcAAAMAAAAA=="); + if (s=="threema") return atob("GBjB/4Yx//8AAAAAAAAAAAAAfgAB/4AD/8AH/+AH/+AP//AP2/APw/APw/AHw+AH/+AH/8AH/4AH/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); + if (s=="to do") return atob("GBgBAAAAAAAAAAAwAAB4AAD8AAH+AAP/DAf/Hg//Px/+f7/8///4///wf//gP//AH/+AD/8AB/4AA/wAAfgAAPAAAGAAAAAAAAAA"); + if (s=="twitch") return atob("GBgBH//+P//+P//+eAAGeAAGeAAGeDGGeDOGeDOGeDOGeDOGeDOGeDOGeAAOeAAOeAAcf4/4f5/wf7/gf//Af/+AA/AAA+AAAcAA"); + if (s=="twitter") return atob("GhYBAABgAAB+JgA/8cAf/ngH/5+B/8P8f+D///h///4f//+D///g///wD//8B//+AP//gD//wAP/8AB/+AB/+AH//AAf/AAAYAAA"); + if (s=="whatsapp") return atob("GBiBAAB+AAP/wAf/4A//8B//+D///H9//n5//nw//vw///x///5///4///8e//+EP3/APn/wPn/+/j///H//+H//8H//4H//wMB+AA=="); + if (s=="wordfeud") return atob("GBgCWqqqqqqlf//////9v//////+v/////++v/////++v8///Lu+v8///L++v8///P/+v8v//P/+v9v//P/+v+fx/P/+v+Pk+P/+v/PN+f/+v/POuv/+v/Ofdv/+v/NvM//+v/I/Y//+v/k/k//+v/i/w//+v/7/6//+v//////+v//////+f//////9Wqqqqqql"); + if (s=="youtube") return atob("GBgBAAAAAAAAAAAAAAAAAf8AH//4P//4P//8P//8P5/8P4/8f4P8f4P8P4/8P5/8P//8P//8P//4H//4Af8AAAAAAAAAAAAAAAAA"); + if (msg.id=="music") return atob("FhaBAH//+/////////////h/+AH/4Af/gB/+H3/7/f/v9/+/3/7+f/vB/w8H+Dwf4PD/x/////////////3//+A="); + // if (s=="sms message" || s=="mail" || s=="gmail") // .. default icon (below) + return atob("HBKBAD///8H///iP//8cf//j4//8f5//j/x/8//j/H//H4//4PB//EYj/44HH/Hw+P4//8fH//44///xH///g////A=="); +}; + +exports.getMessageImageCol = function(msg,def) { + return { + // generic colors, using B2-safe colors + "alarm": "#fff", + "mail": "#ff0", + "music": "#f0f", + "phone": "#0f0", + "sms message": "#0ff", + // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) + // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) + "bibel": "#54342c", + "discord": "#738adb", + "facebook": "#4267b2", + "gmail": "#ea4335", + "google home": "#fbbc05", + "hangouts": "#1ba261", + "home assistant": "#fff", // ha-blue is #41bdf5, but that's the background + "instagram": "#dd2a7b", + "liferando": "#ee5c00", + "messenger": "#0078ff", + "nina": "#e57004", + "outlook mail": "#0072c6", + "post & dhl": "#f2c101", + "signal": "#00f", + "skype": "#00aff0", + "slack": "#e51670", + "snapchat": "#ff0", + "teams": "#464eb8", + "telegram": "#0088cc", + "telegram foss": "#0088cc", + "threema": "#000", + "to do": "#3999e5", + "twitch": "#6441A4", + "twitter": "#1da1f2", + "whatsapp": "#4fce5d", + "wordfeud": "#e7d3c7", + "youtube": "#f00", + }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); +}; From a6d92c11151b4e0127bdc9fcccea7fa13098ba05 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 May 2022 10:00:27 +0100 Subject: [PATCH 82/94] inline tick/cross images to save some space --- apps/messages/app.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index 63154c4b4..745f7d208 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -67,15 +67,6 @@ function saveMessages() { require("Storage").writeJSON("messages.json",MESSAGES) } -function getPosImage() { - return atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA=="); -} -function getNegImage() { - return atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="); -} - - - function showMapMessage(msg) { active = "map"; var m; @@ -302,7 +293,7 @@ function showMessage(msgid) { var buttons = [ ]; if (msg.positive) { - buttons.push({type:"btn", src:getPosImage(), cb:()=>{ + buttons.push({type:"btn", src:atob("GRSBAAAAAYAAAcAAAeAAAfAAAfAAAfAAAfAAAfAAAfBgAfA4AfAeAfAPgfAD4fAA+fAAP/AAD/AAA/AAAPAAADAAAA=="), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now Bangle.messageResponse(msg,true); @@ -311,7 +302,7 @@ function showMessage(msgid) { } if (msg.negative) { if (buttons.length) buttons.push({width:32}); // nasty hack... - buttons.push({type:"btn", src:getNegImage(), cb:()=>{ + buttons.push({type:"btn", src:atob("FhaBADAAMeAB78AP/4B/fwP4/h/B/P4D//AH/4AP/AAf4AB/gAP/AB/+AP/8B/P4P4fx/A/v4B//AD94AHjAAMA="), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now Bangle.messageResponse(msg,false); From f0e262757109e83bb3b6bf77e4aba3c2658fd067 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Tue, 24 May 2022 22:25:44 +0200 Subject: [PATCH 83/94] Move Layout docs to a separate file --- modules/Layout.js | 70 +--------------------------------------- modules/Layout.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 69 deletions(-) create mode 100644 modules/Layout.md diff --git a/modules/Layout.js b/modules/Layout.js index 43419a397..19cfabe11 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -1,74 +1,6 @@ /* Copyright (c) 2022 Bangle.js contributors. See the file LICENSE for copying permission. */ -/* -Take a look at README.md for hints on developing with this library. -Usage: -``` -var Layout = require("Layout"); -var layout = new Layout( layoutObject, options ) -layout.render(optionalObject); -``` -For example: -``` -var Layout = require("Layout"); -var layout = new Layout( { - type:"v", c: [ - {type:"txt", font:"20%", label:"12:00" }, - {type:"txt", font:"6x8", label:"The Date" } - ] -}); -g.clear(); -layout.render(); -``` -layoutObject has: -* A `type` field of: - * `undefined` - blank, can be used for padding - * `"txt"` - a text label, with value `label`. 'font' is required - * `"btn"` - a button, with value `label` and callback `cb` - optional `src` specifies an image (like img) in which case label is ignored - Default font is `6x8`, scale 2. This can be overridden with the `font` or `scale` fields. - * `"img"` - an image where `src` is an image, or a function which is called to return an image to draw. - * `"custom"` - a custom block where `render(layoutObj)` is called to render - * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` - * `"v"` - Vertical layout, `c` is an array of more `layoutObject` -* A `id` field. If specified the object is added with this name to the - returned `layout` object, so can be referenced as `layout.foo` -* A `font` field, eg `6x8` or `30%` to use a percentage of screen height. Set scale with :, e.g. `6x8:2`. -* A `scale` field, eg `2` to set scale of an image -* A `r` field to set rotation of text or images (0: 0°, 1: 90°, 2: 180°, 3: 270°). -* A `wrap` field to enable line wrapping. Requires some combination of `width`/`height` - and `fillx`/`filly` to be set. Not compatible with text rotation. -* A `col` field, eg `#f00` for red -* A `bgCol` field for background color (will automatically fill on render) -* A `halign` field to set horizontal alignment WITHIN a `v` container. `-1`=left, `1`=right, `0`=center -* A `valign` field to set vertical alignment WITHIN a `h` container. `-1`=top, `1`=bottom, `0`=center -* A `pad` integer field to set pixels padding -* A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space -* A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space -* `width` and `height` fields to optionally specify minimum size -options is an object containing: -* `lazy` - a boolean specifying whether to enable automatic lazy rendering -* `btns` - array of objects containing: - * `label` - the text on the button - * `cb` - a callback function - * `cbl` - a callback function for long presses -* `back` - a callback function, passed as `back` into Bangle.setUI (which usually adds an icon in the top left) - -If automatic lazy rendering is enabled, calls to `layout.render()` will attempt to automatically -determine what objects have changed or moved, clear their previous locations, and re-render just those objects. -Once `layout.update()` is called, the following fields are added -to each object: -* `x` and `y` for the top left position -* `w` and `h` for the width and height -* `_w` and `_h` for the **minimum** width and height -Other functions: -* `layout.update()` - update positions of everything if contents have changed -* `layout.debug(obj)` - draw outlines for objects on screen -* `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render) -* `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render -* `layout.setUI()` - (called when module initialised) This sets up input (buttons, touch, etc) with Bangle._setUI - This can be useful if you called E.showMenu/showPrompt/etc and those grabbed input away from layour -*/ +// See Layout.md for documentation function Layout(layout, options) { this._l = this.l = layout; diff --git a/modules/Layout.md b/modules/Layout.md new file mode 100644 index 000000000..7a4177957 --- /dev/null +++ b/modules/Layout.md @@ -0,0 +1,81 @@ +Bangle.js Layout Library +======================== + +> Take a look at README.md for hints on developing with this library. + +Usage +----- + +```JS +var Layout = require("Layout"); +var layout = new Layout(layoutObject, options) + +layout.render(optionalObject); +``` + +For example: + +```JS +var Layout = require("Layout"); +var layout = new Layout({ + type:"v", + c: [ + { type: "txt", font: "20%", label: "12:00" }, + { type: "txt", font: "6x8", label: "The Date" } + ] +}); + +g.clear(); + +layout.render(); +``` + +`layoutObject` has: + +- A `type` field of: + - `undefined` - blank, can be used for padding + - `"txt"` - a text label, with value `label`. `font` is required + - `"btn"` - a button, with value `label` and callback `cb`. Optional `src` specifies an image (like img) in which case label is ignored. Default font is `6x8`, scale 2. This can be overridden with the `font` or `scale` fields. + - `"img"` - an image where `src` is an image, or a function which is called to return an image to draw + - `"custom"` - a custom block where `render(layoutObj)` is called to render + - `"h"` - Horizontal layout, `c` is an array of more `layoutObject` + - `"v"` - Vertical layout, `c` is an array of more `layoutObject` +- A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo` +- A `font` field, eg `6x8` or `30%` to use a percentage of screen height. Set scale with :, e.g. `6x8:2`. +- A `scale` field, eg `2` to set scale of an image +- A `r` field to set rotation of text or images (0: 0°, 1: 90°, 2: 180°, 3: 270°). +- A `wrap` field to enable line wrapping. Requires some combination of `width`/`height` and `fillx`/`filly` to be set. Not compatible with text rotation. +- A `col` field, eg `#f00` for red +- A `bgCol` field for background color (will automatically fill on render) +- A `halign` field to set horizontal alignment WITHIN a `v` container. `-1`=left, `1`=right, `0`=center +- A `valign` field to set vertical alignment WITHIN a `h` container. `-1`=top, `1`=bottom, `0`=center +- A `pad` integer field to set pixels padding +- A `fillx` int to choose if the object should fill available space in x. 0=no, 1=yes, 2=2x more space +- A `filly` int to choose if the object should fill available space in y. 0=no, 1=yes, 2=2x more space +- `width` and `height` fields to optionally specify minimum size options is an object containing: +- `lazy` - a boolean specifying whether to enable automatic lazy rendering +- `btns` - array of objects containing: + - `label` - the text on the button + - `cb` - a callback function + - `cbl` - a callback function for long presses +- `back` - a callback function, passed as `back` into Bangle.setUI (which usually adds an icon in the top left) + +If automatic lazy rendering is enabled, calls to `layout.render()` will attempt to automatically determine what objects have changed or moved, clear their previous locations, and re-render just those objects. + +Once `layout.update()` is called, the following fields are added to each object: + +- `x` and `y` for the top left position +- `w` and `h` for the width and height +- `_w` and `_h` for the **minimum** width and height + +Other functions: + +- `layout.update()` - update positions of everything if contents have changed +- `layout.debug(obj)` - draw outlines for objects on screen +- `layout.clear(obj)` - clear the given object (you can also just specify `bgCol` to clear before each render) +- `layout.forgetLazyState()` - if lazy rendering is enabled, makes the next call to `render()` perform a full re-render + +Links +----- + +- [Official tutorial](https://www.espruino.com/Bangle.js+Layout) From 4cbc80ddbb4e065e0aa7a5f1b4f28a54a9bcadb4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 25 May 2022 14:12:55 +0100 Subject: [PATCH 84/94] oops - disable battery calibration for Bangle.js 1 --- apps/setting/settings.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 5c14e914d..73cb4b497 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -545,8 +545,10 @@ function showUtilMenu() { setInterval(function() { var i=1000;while (i--); }, 1); - }, - /*LANG*/'Calibrate Battery': () => { + } + }; + if (BANGLEJS2) + menu[/*LANG*/'Calibrate Battery'] = () => { E.showPrompt(/*LANG*/"Is the battery fully charged?",{title:/*LANG*/"Calibrate"}).then(ok => { if (ok) { var s=require("Storage").readJSON("setting.json"); @@ -558,7 +560,7 @@ function showUtilMenu() { } }); }, - /*LANG*/'Reset Settings': () => { + menu[/*LANG*/'Reset Settings'] = () => { E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => { if (v) { E.showMessage('Resetting'); @@ -567,8 +569,8 @@ function showUtilMenu() { } else showUtilMenu(); }); }, - /*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() } - }; + menu[/*LANG*/'Turn Off'] = ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() } + if (Bangle.factoryReset) { menu[/*LANG*/'Factory Reset'] = ()=>{ E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset"}).then((v) => { From 280fd5e665249ea92256c30a36ed25d74bffaee6 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 25 May 2022 23:13:37 +0200 Subject: [PATCH 85/94] [Alarms & Timers] Fix dow handling for timers --- apps/alarm/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 8e2e2b0a6..fe0f67dbb 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -37,8 +37,8 @@ function handleFirstDayOfWeek(dow) { return dow; } -// Check the first day of week and update the dow field accordingly. -alarms.forEach(alarm => alarm.dow = handleFirstDayOfWeek(alarm.dow)); +// Check the first day of week and update the dow field accordingly (alarms only!) +alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow)); function showMainMenu() { const menu = { @@ -158,14 +158,14 @@ function saveAlarm(alarm, alarmIndex, time) { } function saveAndReload() { - // Before saving revert the dow to the standard format - alarms.forEach(a => a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek)); + // Before saving revert the dow to the standard format (alarms only!) + alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow)); require("sched").setAlarms(alarms); require("sched").reload(); // Fix after save - alarms.forEach(a => a.dow = handleFirstDayOfWeek(a.dow, firstDayOfWeek)); + alarms.filter(e => e.timer === undefined).forEach(a => a.dow = handleFirstDayOfWeek(a.dow)); } function decodeDOW(alarm) { From 2fd5ec8f37dd860db57da2e98d373b2f6ceedb3b Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 25 May 2022 23:20:00 +0200 Subject: [PATCH 86/94] [Alarms & Timers] Update metadata and changelog --- apps/alarm/ChangeLog | 1 + apps/alarm/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 3d75e1209..b00055334 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -28,3 +28,4 @@ 0.26: Add support for Monday as first day of the week (#1780) 0.27: New UI! 0.28: Fix bug with alarms not firing when configured to fire only once +0.29: Fix wrong 'dow' handling in new timer if first day of week is Monday diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index b38ab1ef1..cac837b5e 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.28", + "version": "0.29", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From 182743a0e3649a311cb0beaf485103bfd6798d4b Mon Sep 17 00:00:00 2001 From: Noah Howard <3317164+nh-99@users.noreply.github.com> Date: Wed, 25 May 2022 17:33:40 -0400 Subject: [PATCH 87/94] Add screenshot of R2D2 clock to metadata for app store --- apps/r2d2clk/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/r2d2clk/metadata.json b/apps/r2d2clk/metadata.json index f2cde76f4..249180ac8 100644 --- a/apps/r2d2clk/metadata.json +++ b/apps/r2d2clk/metadata.json @@ -4,6 +4,7 @@ "version":"0.01", "description": "A clock with R2D2's shiny metal face on it. :)", "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], "type": "clock", "tags": "clock", "supports" : ["BANGLEJS2"], From 211af92a41a5d167f9a42d5c73b4c3f09004234d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 26 May 2022 09:58:59 +0100 Subject: [PATCH 88/94] bangle.js 2 compat --- apps/rndmclk/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/rndmclk/metadata.json b/apps/rndmclk/metadata.json index e837c4bce..bb8e92f95 100644 --- a/apps/rndmclk/metadata.json +++ b/apps/rndmclk/metadata.json @@ -6,7 +6,7 @@ "icon": "rndmclk.png", "type": "widget", "tags": "widget,clock", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"rndmclk.wid.js","url":"widget.js"} From 6f202bc9254a96de7bccba21fe75ce75d00cf95b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 26 May 2022 09:59:11 +0100 Subject: [PATCH 89/94] fix locale errors after recent PRs --- apps/locale/locales.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index d1ac7687f..de56503fd 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -11,6 +11,8 @@ const speedUnits = { // how many kph per X? "kmh": 1, "kph": 1, "km/h": 1, + "kmt": 1, + "km/tim": 1, "mph": 1.60934, "kts": 1.852 }; From ed56c9142742eb3e7a132c730a4769a028396dde Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 26 May 2022 09:59:18 +0100 Subject: [PATCH 90/94] add relevant interface code to customize.js, and add checks to ensure the right file is used --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 404e98183..2054537a9 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 404e981834f2e8df9c505a8fab12ae12fe3bd562 +Subproject commit 2054537a9958f9812ae2cad908b6597ff01e449d From 6b8cf13f6c635efc1392c82c8a95f2927ba65e4f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 26 May 2022 10:07:04 +0100 Subject: [PATCH 91/94] 0.46: Fix regression after making 'calibrate battery' only for Bangle.js 2 --- apps/setting/ChangeLog | 1 + apps/setting/metadata.json | 2 +- apps/setting/settings.js | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 6d3bbb468..eca2b7938 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -49,3 +49,4 @@ 0.44: Add "Start Week On X" option (#1780) UI improvements to Locale and Date & Time menu 0.45: Add calibrate battery option +0.46: Fix regression after making 'calibrate battery' only for Bangle.js 2 diff --git a/apps/setting/metadata.json b/apps/setting/metadata.json index c5c368fae..183290a85 100644 --- a/apps/setting/metadata.json +++ b/apps/setting/metadata.json @@ -1,7 +1,7 @@ { "id": "setting", "name": "Settings", - "version": "0.45", + "version": "0.46", "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 73cb4b497..150251e7d 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -559,7 +559,7 @@ function showUtilMenu() { E.showAlert(/*LANG*/"Please charge Bangle.js for 3 hours and try again").then(() => load("settings.app.js")); } }); - }, + }; menu[/*LANG*/'Reset Settings'] = () => { E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => { if (v) { @@ -568,8 +568,8 @@ function showUtilMenu() { setTimeout(showMainMenu, 50); } else showUtilMenu(); }); - }, - menu[/*LANG*/'Turn Off'] = ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() } + }; + menu[/*LANG*/'Turn Off'] = ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() }; if (Bangle.factoryReset) { menu[/*LANG*/'Factory Reset'] = ()=>{ From 3a3a01136b018fc2a9ea2b0069d9442c228f9b1d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 26 May 2022 12:50:44 +0100 Subject: [PATCH 92/94] mylocation 0.07: Move mylocation app into 'Settings -> Apps' --- README.md | 1 + apps/mylocation/ChangeLog | 1 + apps/mylocation/README.md | 2 ++ apps/mylocation/icon.js | 1 - apps/mylocation/metadata.json | 7 +++--- apps/mylocation/{app.js => settings.js} | 30 ++++++++++++------------- bin/sanitycheck.js | 4 ++-- 7 files changed, 24 insertions(+), 22 deletions(-) delete mode 100644 apps/mylocation/icon.js rename apps/mylocation/{app.js => settings.js} (73%) diff --git a/README.md b/README.md index ee555cad2..b3da9f685 100644 --- a/README.md +++ b/README.md @@ -256,6 +256,7 @@ and which gives information about the app for the Launcher. // 'clock' - a clock - required for clocks to automatically start // 'widget' - a widget // 'bootloader' - an app that at startup (app.boot.js) but doesn't have a launcher entry for 'app.js' + // 'settings' - apps that appear in Settings->Apps (with appname.settings.js) but that have no 'app.js' // 'RAM' - code that runs and doesn't upload anything to storage // 'launch' - replacement 'Launcher' // 'textinput' - provides a 'textinput' library that allows text to be input on the Bangle diff --git a/apps/mylocation/ChangeLog b/apps/mylocation/ChangeLog index 1239554f0..c14e64ba9 100644 --- a/apps/mylocation/ChangeLog +++ b/apps/mylocation/ChangeLog @@ -4,3 +4,4 @@ 0.04: Fixed issue selecting Frankfurt not saved 0.05: Fixed issue with back option 0.06: renamed source files to match standard +0.07: Move mylocation app into 'Settings -> Apps' diff --git a/apps/mylocation/README.md b/apps/mylocation/README.md index fd597397a..a6a16ce83 100644 --- a/apps/mylocation/README.md +++ b/apps/mylocation/README.md @@ -2,6 +2,8 @@ *Sets and stores GPS lat and lon of your preferred city* +To access, go to `Settings -> Apps -> My Location` + * Select one of the preset Cities or setup through the GPS * Other Apps can read this information to do calculations based on location * When the City shows ??? it means the location has been set through the GPS diff --git a/apps/mylocation/icon.js b/apps/mylocation/icon.js deleted file mode 100644 index b79f5875f..000000000 --- a/apps/mylocation/icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEw4UA///gH4AYPO/QPDgNVqtADY/1BYNfBQ0PBQIAB+ALFmoLDrgLF6oLDq4KEgYKDBYPABYcNBYlVuAuIGAwuEAANUBYYKFHgg6Bq4ZCr4DBHgQLBvWq2te1WlBYZGBBYOr1Wq1qSDBYNqBIILDKgQLLgoLHqBqDBfJHLBZBrOgKPCBYiPCU4NaBYe1WYrABBQLCCfgYGCrwVBa4kAirvKNgIAErgLDKgIAEKQQ8EAAY6DBZhIDIww8GHQg8GHQgwGFwowEFwx5EOog8GHQ0AlWpBYNq1AKFWIILBAYOgBYbICytWAgQKCgTgDcwYXGAAgvGAAY8EEgYWGBgoVEA==")) diff --git a/apps/mylocation/metadata.json b/apps/mylocation/metadata.json index 16549b2ba..4ab9aa37e 100644 --- a/apps/mylocation/metadata.json +++ b/apps/mylocation/metadata.json @@ -2,16 +2,15 @@ "name": "My Location", "shortName":"My Location", "icon": "app.png", - "type": "app", + "type": "settings", "screenshots": [{"url":"screenshot_1.png"}], - "version":"0.06", + "version":"0.07", "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", "readme": "README.md", "tags": "tool,utility", "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ - {"name":"mylocation.app.js","url":"app.js"}, - {"name":"mylocation.img","url":"icon.js","evaluate": true } + {"name":"mylocation.settings.js","url":"settings.js"} ], "data": [ {"name":"mylocation.json"} diff --git a/apps/mylocation/app.js b/apps/mylocation/settings.js similarity index 73% rename from apps/mylocation/app.js rename to apps/mylocation/settings.js index fd5c9cc6d..7033500fa 100644 --- a/apps/mylocation/app.js +++ b/apps/mylocation/settings.js @@ -1,5 +1,4 @@ -Bangle.loadWidgets(); -Bangle.drawWidgets(); +(function(back) { const SETTINGS_FILE = "mylocation.json"; let settings; @@ -18,7 +17,7 @@ function loadSettings() { } } -function save() { +function saveSettings() { settings = s; require('Storage').write(SETTINGS_FILE, settings); } @@ -34,29 +33,29 @@ function setFromGPS() { //console.log("fix from GPS"); s = {'lat': gps.lat, 'lon': gps.lon, 'location': '???' }; Bangle.buzz(1500); // buzz on first position - Bangle.setGPSPower(0); - save(); + Bangle.setGPSPower(0, "mylocation"); + saveSettings(); Bangle.setUI("updown", ()=>{ load(); }); - E.showPrompt("Location has been saved from the GPS fix",{ - title:"Location Saved", - buttons : {"OK":1} + E.showPrompt(/*LANG*/"Location has been saved from the GPS fix",{ + title:/*LANG*/"Location Saved", + buttons : {/*LANG*/"OK":1} }).then(function(v) { load(); // load default clock }); }); - Bangle.setGPSPower(1); - E.showMessage("Waiting for GPS fix. Place watch in the open. Could take 10 minutes. Long press to abort", "GPS Running"); + Bangle.setGPSPower(1, "mylocation"); + E.showMessage(/*LANG*/"Waiting for GPS fix. Place watch in the open. Could take 10 minutes. Long press to abort", "GPS Running"); Bangle.setUI("updown", undefined); } function showMainMenu() { //console.log("showMainMenu"); const mainmenu = { - '': { 'title': 'My Location' }, - '< Back': ()=>{ load(); }, - 'City': { + '': { 'title': /*LANG*/'My Location' }, + '< Back': ()=>{ back(); }, + /*LANG*/'City': { value: 0 | locations.indexOf(s.location), min: 0, max: locations.length - 1, format: v => locations[v], @@ -65,14 +64,15 @@ function showMainMenu() { s.location = locations[v]; s.lat = lats[v]; s.lon = lons[v]; - save(); + saveSettings(); } } }, - 'Set From GPS': ()=>{ setFromGPS(); } + /*LANG*/'Set From GPS': ()=>{ setFromGPS(); } }; return E.showMenu(mainmenu); } loadSettings(); showMainMenu(); +}) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 850b793f4..81c0f75ac 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -65,7 +65,7 @@ const APP_KEYS = [ const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports']; const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate']; const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports' -const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale"]; // values allowed for "type" field +const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","textinput","scheduler","notify","locale","settings"]; // values allowed for "type" field const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ]; const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"]; @@ -140,7 +140,7 @@ apps.forEach((app,appIdx) => { ERROR(`App ${app.id} 'dependencies' must all be tagged 'type' or 'app' right now`); if (app.dependencies[dependency]=="type" && !METADATA_TYPES.includes(dependency)) ERROR(`App ${app.id} 'type' dependency must be one of `+METADATA_TYPES); - + }); } else ERROR(`App ${app.id} 'dependencies' must be an object`); From 95bf53e68d9bbe40f7879f743568e59d71b198be Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 26 May 2022 16:44:56 +0200 Subject: [PATCH 93/94] [TerminalClock] Add power related settings to control sensors --- apps/terminalclock/ChangeLog | 1 + apps/terminalclock/README.md | 5 +++ apps/terminalclock/app.js | 65 +++++++++++++++++++++++++------- apps/terminalclock/metadata.json | 2 +- apps/terminalclock/settings.js | 23 ++++++++++- 5 files changed, 81 insertions(+), 15 deletions(-) diff --git a/apps/terminalclock/ChangeLog b/apps/terminalclock/ChangeLog index b752c829d..ce31583e9 100644 --- a/apps/terminalclock/ChangeLog +++ b/apps/terminalclock/ChangeLog @@ -3,3 +3,4 @@ 0.03: Add Banglejs 1 compatibility 0.04: Fix settings bug 0.05: Add altitude display (only Bangle.js 2) +0.06: Add power related settings to control the HR and pressure(altitude) sensor from the watchface diff --git a/apps/terminalclock/README.md b/apps/terminalclock/README.md index c7452397d..93967e8a7 100644 --- a/apps/terminalclock/README.md +++ b/apps/terminalclock/README.md @@ -8,3 +8,8 @@ It can display : - hrm - motion - steps + + +"Power saving" setting control the HR and pressure (altitude) sensors. +If "Off" they will always be on. +If "On" the sensors will be turned on every "Power on interval" minutes for 45 secondes diff --git a/apps/terminalclock/app.js b/apps/terminalclock/app.js index 61861f745..833ed7694 100644 --- a/apps/terminalclock/app.js +++ b/apps/terminalclock/app.js @@ -3,15 +3,14 @@ var fontColor = g.theme.dark ? "#0f0" : "#000"; var heartRate = 0; var altitude = -9001; -// handling the differents versions of the Banglejs smartwatch +// handling the differents versions of the Banglejs smartwatch screen sizes if (process.env.HWVERSION == 1){ var paddingY = 3; var font6x8At4Size = 48; var font6x8At2Size = 27; var font6x8FirstTextSize = 6; var font6x8DefaultTextSize = 3; -} -else{ +} else{ var paddingY = 2; var font6x8At4Size = 32; var font6x8At2Size = 18; @@ -66,7 +65,7 @@ function drawDate(now, pos){ drawLine(locale_date, pos); } -function drawInput(now, pos){ +function drawInput(pos){ clearField(pos); drawLine(">", pos); } @@ -129,17 +128,55 @@ function draw(){ drawStepCount(curPos); curPos++; } - drawInput(now, curPos); + drawInput(curPos); } +function turnOnServices(){ + if(settings.showHRM){ + Bangle.setHRMPower(true, "terminalclock"); + } + if(settings.showAltitude && process.env.HWVERSION != 1){ + Bangle.setBarometerPower(true, "terminalclock"); + } + if(settings.powerSaving){ + setTimeout(function () { + turnOffServices(); + }, 45000); + } +} + +function turnOffServices(){ + if(settings.showHRM){ + Bangle.setHRMPower(false, "terminalclock"); + } + if(settings.showAltitude && process.env.HWVERSION != 1){ + Bangle.setBarometerPower(false, "terminalclock"); + } +} + +var unlockDrawIntervalID = -1; +Bangle.on('lock', function(on){ + if(!on){ // unclock + if(settings.powerSaving){ + turnOnServices(); + } + unlockDrawIntervalID = setInterval(draw, 1000); // every second + } + if(on && unlockDrawIntervalID != -1){ // lock + clearInterval(unlockDrawIntervalID); + } +}); + Bangle.on('HRM',function(hrmInfo) { + console.log('in hrm'); if(hrmInfo.confidence >= settings.HRMinConfidence) heartRate = hrmInfo.bpm; }); -var MEDIANLENGTH = 20; -var avr = [], median; +var MEDIANLENGTH = 20; // technical +var avr = [], median; // technical Bangle.on('pressure', function(e) { + console.log('in pressure'); while (avr.length>MEDIANLENGTH) avr.pop(); avr.unshift(e.altitude); median = avr.slice().sort(); @@ -161,18 +198,20 @@ var settings = Object.assign({ showActivity: true, showStepCount: true, showAltitude: process.env.HWVERSION != 1 ? true : false, + powerSaving: true, + PowerOnInterval: 15, }, require('Storage').readJSON("terminalclock.json", true) || {}); -if(settings.showAltitude && process.env.HWVERSION != 1){ - Bangle.setBarometerPower(true, "app"); +// turn the services before drawing anything +turnOnServices(); +if(settings.powerSaving){ + setInterval(turnOnServices, settings.PowerOnInterval*60000); // every PowerOnInterval min } - // Show launcher when middle button pressed Bangle.setUI("clock"); -// Load widgets +// Load and draw widgets Bangle.loadWidgets(); Bangle.drawWidgets(); // draw immediately at first draw(); - -var secondInterval = setInterval(draw, 10000); +setInterval(draw, 10000); // every 10 seconds diff --git a/apps/terminalclock/metadata.json b/apps/terminalclock/metadata.json index 7bc00bca4..9f76ed8f2 100644 --- a/apps/terminalclock/metadata.json +++ b/apps/terminalclock/metadata.json @@ -3,7 +3,7 @@ "name": "Terminal Clock", "shortName":"Terminal Clock", "description": "A terminal cli like clock displaying multiple sensor data", - "version":"0.05", + "version":"0.06", "icon": "app.png", "type": "clock", "tags": "clock", diff --git a/apps/terminalclock/settings.js b/apps/terminalclock/settings.js index 4b09aad6a..bd860b491 100644 --- a/apps/terminalclock/settings.js +++ b/apps/terminalclock/settings.js @@ -8,6 +8,8 @@ showHRM: true, showActivity: true, showStepCount: true, + powerSaving: true, + PowerOnInterval: 15, }, require('Storage').readJSON(FILE, true) || {}); function writeSettings() { @@ -65,10 +67,29 @@ settings.showStepCount = v; writeSettings(); } + }, + 'Power saving': { + value: settings.powerSaving, + format: v => v?"On":"Off", + onchange: v => { + settings.powerSaving = v; + writeSettings(); + } + }, + 'Power on interval': { + value: settings.PowerOnInterval, + min: 3, max: 60, + onchange: v => { + settings.PowerOnInterval = v; + writeSettings(); + }, + format: x => { + return x + " min"; + } } } if (process.env.HWVERSION == 1) { delete menu['Show Altitude'] } E.showMenu(menu); -}) +}) \ No newline at end of file From 76c40f94a259737f0dadbe6929d819147d4b84cc Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 26 May 2022 16:53:50 +0200 Subject: [PATCH 94/94] [TerminalClock] Remove logs --- apps/terminalclock/app.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/terminalclock/app.js b/apps/terminalclock/app.js index 833ed7694..7dc3bf1d1 100644 --- a/apps/terminalclock/app.js +++ b/apps/terminalclock/app.js @@ -168,7 +168,6 @@ Bangle.on('lock', function(on){ }); Bangle.on('HRM',function(hrmInfo) { - console.log('in hrm'); if(hrmInfo.confidence >= settings.HRMinConfidence) heartRate = hrmInfo.bpm; }); @@ -176,7 +175,6 @@ Bangle.on('HRM',function(hrmInfo) { var MEDIANLENGTH = 20; // technical var avr = [], median; // technical Bangle.on('pressure', function(e) { - console.log('in pressure'); while (avr.length>MEDIANLENGTH) avr.pop(); avr.unshift(e.altitude); median = avr.slice().sort();