From 123d4814696eafc50062b774a62b7fdc90b80518 Mon Sep 17 00:00:00 2001 From: Salim Blume Date: Mon, 4 Apr 2022 12:22:04 -0500 Subject: [PATCH 01/57] 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 02/57] 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 03/57] 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 04/57] 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 05/57] 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 06/57] 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 07/57] 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 08/57] 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 09/57] 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 10/57] 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 11/57] 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 12/57] 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 13/57] 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 14/57] 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 4dfd1b2bf0b01d14bafb0c10e43e5b3d31fc4d37 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Thu, 19 May 2022 23:43:59 +0200 Subject: [PATCH 15/57] - 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('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'))), + 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 16/57] 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 17/57] 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 18/57] "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 19/57] - 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 20/57] 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('AHM/8AIG/+AA4sD/wQGh/4EWQA/AC8YA40HNA0BRY8/RY0P/6LFgf//4iFA4IiFj4HBEQkHCAQiDHIIZGv4HCFQY5BDAo5CAAIpDDAfACA3wLYv//hsFKYxcCMgoiBOooiBQwwiBS40AHIgA/ACS/DLYjYCBAjQEBAYQDBAgHDUAbyDZQi3CegoHEVQQZFagUfW4Y0DaAgECaIJSEFYMPbIYNDv5ACGAIrBCgJ1EFYILCAAQWCj4zDGgILCegcDEQRNDHIIiCHgZ2BEQShFIqUDFYidCh5ODg4NCn40DAgd/AYR5BDILZEAAIMDAAYVCh7aHdYhKDbQg4Dv7rGBAihFCAwIDCAgA/AB3/eoa7GAAk/dgbVGDJrvCDK67DDIjaGdYpbCdYonCcQjjDEVUBEQ4A/AEMcAYV/NAUHcYUDawd/cYUPRYSmBBgaLBToP8BgYiBSgIiCj4iCg//EQSuDW4IMDVwYiCBgIiBBgrRDCATeBaIYqCv70DCgT4CEQMfIgQZBBoRnDv/3EQIvBDIffEQMHFwReBRYUfOgX/+IiDKIeHEQRRECwUHKwIuB8AiDIoJEBCwZFCv/4HIZaBIgPAEQS2CUYQiCD4SABEQcfOwIZBEQaHBO4RcEAAI/BEQQgBSIQiDTIRZBEQZuBVYQiDHoKWCEQQICFQIiDBAQeCEQQA/AANwA40BLIJ5BO4JWCBAUPAYR5En7RBUIQECN4SYCQQIiEh6CCEQk/BoQiBgYeCBoTrCAgT0CCgIfCFYQiBg4IBGgIiDj6rBg4rCBYLRDFYIiBbYIfBLgQiBIQYiD4JCCLgf/bQIWDBYV/EQV/BYXz/5FBgIiD5//IowZBD4M/NAX/BIPgDIJoC//5GgKUDn//4f/8KLE/wTBAAI8BEQPwj4HBVwYmBDgIZDN4QZCGYKJCHQP/JoSgCBATrCh5dBKITVDG4gICAAbvDAH5SCL4QADK4J5CCAiTCCAp1BCAqCDCAgiGCAIiFCAQiFeoIiFg6/FCAgiECAXnEQgQB/kfEQYQC4F/EQYQCgIiDfoIQBg4iDCAUAEQZUCcgIiDDIIQBEQhuBBoIiENoYiFDwQiECAQiFwEBPQQNCAQKDDEYMDDoMfRh4iGUwqvEESBiBaQ5oEbgr0FNAo+EEIwA+oAHGgJoFRAMHe4L0CAALNBBAT0BfwScDCAXweAL0DWgUPQYQiDwF/QYQiC/zTB+C0FBAL0CEQYIBGgMPCgIxBg4rCJIKsCh5IBBwTPCj4WBgYLBZ4V/MAIiBBQQrBEQYtCBYQiCO4QLFCwgiDIQIiGIoMHEQpFBn5FFD4JoENwRoGDgSUCAoKfBw//DgIiCT4auCFwN/T4RRET4TaCEQKoCDIQiCGgK/DAAQICdYQACHoIqCBAoQFEwIhFAH4AFQIROEj4IGXwIIGNwIACbgIhEBAiRCVwoqDTogHEW4QZFXgIZB/z9Cv49CF4MPBwI0Ca4LlB8ATCJoP4AoINDfQPAg7PBg4cBBwUfD4MfFYILCCwgOCf4QLEwEPCwILCgJaBn4WBBYQxCIQQiD+EDCYI5CBYRQBIo4fBMQIuBC4N/NAv8AoIcBSgU/FYIIBZIYrCW4hOCXIQZCgYUBv7jEh4uBZAscewZ8CgEgUYT0EEoQIBA4gICFQQIEHYQA+KQzdDAArdCAArpCEScHaIQiEvwiGe4QiFUwQiEbgIiFYIL0DEQTkBEQrJEEQc/cYYiCg4HBDIQiCfoRoEHQLaDEQQHBbQYiBCAT8Dn/BCAoXBJYP/OgZKC/6OEEARLCEQZLEEQZLEEQjKFEQI6EEQZLDEQbsGEQLjGYYYA/JIxzEg/AfgJSDAoPgfgiDC8COFAoPnaQj6CAAR+CW4TCFA4i6CDIqhCDIfwHoYHCYIN/GgKuBJ4JDBFYUf/C5CBYIZBv/Ag4ZBg4rBBYQTBAQIcBg4FBn5UBAQUfFwIfCEQeAgYfBAQUBFAKbCAQQiCGwIiE+A2BwBFNwE/AoM/EQJoIWwKCCh4cBFYKUERYV/W46uHFYIZGaJA0B/glBGYT0JIITiEMIJvCFQQAEHYQA/ABBlEOIhdGQAIRFSgQIBgQICn4IB8EAjiBCUYglCbQYeBEoQZCTwM/CYIZD/gEBUwIzBJ4UHYAU/EwIrBh4rCAoIXCn4rBCgUDAQN/FYMfBYIXBCYJnCBYXggf8HgQLCwEPEQQuBgJOECwILDCwgiLHIUHBYJFGD4IxBgYWCn4rBBwJoFDIYNBCgPADgKHBRYfDBQN/GAIrBToTLDVwYACDILiCWAb8DAAYzBYAjTCAAI9BAARNCBAoqCBAgQDFgbYCAH4AufgQACf4T8CAAT/CfgQACBwITCAAYOBCYQioh4iEAHQA=='))), + 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 zcmbW3X*iS%8^@n#3}!eJlL%3m?AooFgeFTp1Vx1gpQBulM005xu?QkyJ z%K2|2B(`V8tEo%d0tUO-S_9?pRptOdI?EnsDS7y?RpsLN+O6iAVm3DSB6hY$&&7JUc%rM;p!18?5sqM8yyH7 zv(R#+w?hL`vVyXa)+yv+r6CUx#=ZUHDHhZc^VGMb@Al^p4yNnr^9sPl1|y*>Qd3z@ zfUE3wf-9aU|Me;*IsckNLdIjM?ul{lvV-Z73&&MTupLEm7e)&4Y3QaKH6t`YWG|flNmUz^di40Z+`?b#Jzc1{iU7t90q{j2{c5D$w!8 z`aoU7vsexF8f&e79Q|wiCRrEhf4kzoPb$`9WhW`~UNthovRBO6gJEs3?l-2RA^f0{ zw~7OQrZM_oJy|XtOa~ML!eum?AHsi6lPUV>l0B=1fl_(|!b>6##?xw(Th3J6x>b^F zN^_`P@?6}I-4S=%iEA)h>eM}5?w;@cp+3eMlgmF#Q3~KTTDNTJ$+e$gdBCG_Edg4*cj9C3z3suARD+e<#)S@ zLu@76)7hWKs4!0;e7@l0tS~qB+6xs3BhZ9qHj}zs0LIR!TYIGGtAcf6^< zr|PeDHRfey>`U85+=5e?X9z+2u*Ow5cdrf&#)f=ZSHJ#%=S#}M+&fyT+)Bi}Poe~8 zDWMXIzl^gC=*csEh$%#73~v`*lfuqltf+FC!Ltv1tv0c=J9cmnD&asbSC*>v+N9=8 zN#`*RynOo4()Lb=acm6s&!wS`uIG6fY%wFdB-^cuoy8uuDAew}7>#2J z(q6lar41rEr(d=(5fo1!j|Jjxur##)F%Z!qNtDz1&M3JFU~G}`ZO)=+0N#fJC;dzA zebGDa?{O=2;0fGRdBTno27Lc!!w<47*zaxf%{~FX$e(m-At2^PW3}`@`dP)b;r9@V z8(|{P9ofjAed1Yt?g1D>zd5%M7+<{dF1FaY=igJnDIfwi*z*?_YU?95N`TZ|)n%yX z8RdmC)$cnTij_V(u{T&pqii)Ji!b}Z_zb04)Br*M>aYipMq(@~fk|%FxhJpwotSbT zV7S!8@H0f4Ua?2Bt#{2`Yd?w%YOl#57=jiB>7Vs7P=^?@pC82^cnY-6+XuF9C&|@D zrA4gx+O7$1c3N=^kWT(ieYaDvO!Fw#fO!><&B){FT|&R2I7CoUNRGP!Xi-t{TyJ9| zoDf+QNBrWvy@5SUtWbn`Rm|9)KTBtjed@gtLG{`D&L06SinCVY)S(qxgzG!_T4Bh5 z{sUl8xb7@3_y3pzQKGg(1e=C;;f6@NJNi>*9uKp(ihvuDVV{VI9unjAF#%^FkJqm( z*-c zH){Ki*S9El!xVD+D^G&bSUZ3@NsyQCxamJTr{*Ul3d_t&BA3G1 zCM<%pBsl+KXiDak>v9@bY&Wb)?~?}a3?JEGQODy>H!vf#pkr6IGKEhVxi9G7REUof zf3LL9f&vpWZcFgUZ&ouZ6vj)de#VLNN1HFo@H`WVD3ZSA@ErPLX!YB$6D3V7iJ*#F z%>6-!lO3Nur56ih&Cax@e$s?wHeTdc$ZveH;vDC~hmfMeA|DWYJY7|A02wsJ^E5P6 z2(neN4~a?#_%W3#``kcNGU1G1bLkxX^Q1+WL_nG9rsBCX$K~!8+AyBdQXJBjD^~Me zrA4WauPuko*H>sl4@`Er!Ax%wJiviJp6F2Us_Ghh>ZPEaL22ze>t7muVrTBxcEb09 z9QW`p8q!ezY|3R_pBrB7f$PVDrimlNzun4$XY78~@pigw>+(!bGplZ=+}e{l{U{by z;o|Au9w1Cx{`e8h7q`3aZzS7B?OMgS|Ky1*xf!B!qd%X3S(5cLUz@~?U)n;$8T>e!ViJtDuP+$N$GJ% zFQNP)53z-0;n1<52b|<1`zdAgmvl;eL1Jao`9(W=)xAXE0xYzd1w&Jp%|wxG^)sD6 z@{~R;2c%FZJLx7;+){OQRox^Ol+i>3Yy_#yhg^#ZF*BFNVK&0WHp7vP7VygkBKAF$ z%tyDX>gF7kGY!_WdxlT{^Xdt5Z;2-}&o`mtj|VNbV5Zrfm%KZ}wtx3>o27DiiJj2^ z{|yQKcd*t9tmxuCq{AWOXKa(*`yaUN>uYF+XX|pN%?ySO6SML|q}!CYm|W+PIe;D8 zbI=ilPkj_@o(N@ZMhLJUm5QFhG9mf82qzwVE%&;c!F|B}%Z8PaoFJM>tlS0jsuW80 zpQX!?ufKCa1idTY=Nha_uMae`jU1R*3`{kV2)R=C8#Er8&K2?@HE46e1xA85ybV0p z5Kil;+q;g1YjaT3lVC*C;13z`skggJjWZ!*%jf6uK)98{iTkn?&8QC@SaK-Chlu&? zxv+8+@HCN>QX&tE4c&aao?!k@E8!$Q6V1AD97=0pTjSPj@=d)ls_KuJk0#@%T7{EU zm)>Y|c1Y`fe>Ip6TYD_1rz~|(padpgH5oq^1~~(d4a+D_d>Ew7s|gONRcVc7CTMXfslsR)5RQCOG*U)fg8SkF9L`7S(L! zFRNo@+yR8=*g58Eu6c^H2`X6*Z4w_WOZ_Mv#vPJ7B`dq3*r9wdVgHrd#`*Pr#Jo68 zPWTV8s)coVsqO9*`dV~QZY5Efw2*OgT2t9i)cF&^x$dbL(2cj4za*9#+T`c`CycH7 zWFd_SG0lT(tNC5T=Y9_Kt@C}$_ZnZsCR?ofr-@&H?a)=pnw>qTvQa3_Qw^Zpig0vF z#y<0Z)ZpizB(Y}J&DTnR*ZzBaC%gXxrVT`MO<@ za*waHKAkRZKJp=`mh~ECl*v2_ZZ6M+ktG#Jp99;#bdY}ikQM}|7)O_{!Jh(k0JHun zASd|v+nWhF66^~sCVoZ_YV{3X@wrt1gAeJdrFWgD16}<&-C5g&TtN4-a0g*n_eh&i zJxh8P?B=?cI6~z0OKGeK07InOJ_pOILI2bIQ;c&uvIcipb!(g20sGSqxN>XK-Twe* 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 f1170b3e341578cc91688cbbc4b8cbda9b235a1c Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 20 May 2022 22:08:59 +0200 Subject: [PATCH 21/57] [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 22/57] [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 23/57] [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 24/57] 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 25/57] [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 26/57] [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 27/57] [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 28/57] [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 29/57] [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 30/57] [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 31/57] [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 32/57] [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 33/57] [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 34/57] 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 35/57] 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 36/57] 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 37/57] 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 38/57] 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 39/57] 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 40/57] 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 41/57] 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 42/57] 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 43/57] 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 44/57] 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 45/57] 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 1abe720645aa33ac0f87e979f13fd56aa9a6ba4a Mon Sep 17 00:00:00 2001
From: Gordon Williams 
Date: Mon, 23 May 2022 15:20:32 +0100
Subject: [PATCH 46/57] 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 47/57] 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 9973435b69f744bbdc420d02f20cd9f96f12b97e Mon Sep 17 00:00:00 2001 From: nujw Date: Tue, 24 May 2022 09:37:47 +1200 Subject: [PATCH 48/57] 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 49/57] 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 50/57] 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 51/57] 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 52/57] 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 53/57] 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 zcmZWNS5%V?tY3>oXpucCOA(o6>W?f1MP(FOEqm0;UNS_W45d|M$kHDRC|jUxD3(o? zPliBI0YN}nm8l>ylqKu(Kirplb23hnlbj?cFG;+)slf@jFdP7Y6Gn#DFh`R5AF;6> z@#=w9;VGQ(us*j>Sj+A3TdPbIPM-a*88V3NpT1MBdSQ2o{+3^o5N;qSRrw;S` z8c9gLSKP8gf5w|GIlYq3ZB@)PMh;&y>d> zCxb&x)Su}Dy&`TFLM+bjxR05oV)5s;kkvv*1tvm9jY+ro zF>FdzU@7Q`e*d;hY(?b4kP_SJmjD^Qieem69ZdCiST#8AV?0D@&dd<8fu=ALEL`Mkg&<3k8b(KgiPI%41sH08T z8oD@F)iBn=-+M=tX$8xWLi@NC4o7x=%=E=@7eUnnoXhObjY}d1_$D!S5y}|D#9cdL zFOu-b&2vgo&fGcv_|tPjk1jTU6&Rq#VpaXCeIH7(-VYXDM!~akB`-4{nRnxc zU&X?PT=XQ{V(yIRgV#6|f+&sy=zJzQAorK2g0@HgIVoSVJ4)W@=N|J;CaPqk@5 zAbdRBtNe46y`Zx-L6aEq_lbAJsL8kuKXTI6s7=fg77Y5qeI_hsYEx)&a84FW;%alSny|Hi-dgkS z4XziZ6mBVJ*s)rKm4m}y)NlEoOS@y5O zQAFRmO`@RfX&}VF`RP96fVsTau9|v2XejivsS<>9=dMcbJEHSUQU{KR5jv*+i*kXD+N(oH`Vs z>&9%C(T%sM_iWhqD6}b5AmG^E0GYgt@$;JU#@Pl$t|m>GgbfN!5N!!D85#fu2qCIZ zE$Fa0-|*@UW3J@vWb^g{rstVe8!=&bJzpuhj_OHAlyPL5_4s4qRW#lpRev2${-z1$ zrXUnQ6ta08zC9h}$y^pyN4>ft5$(%VT~XV7WRk5K*cuqv&PDVW{M7ECm+3rt?x$jl zXG;A3EuJp=HH9qY{;ohyt-cv8V$sQX(SIgl8IL%GJR&|?eod2z%xjCW@{$-w{*=ES z!YNtu^MN#i^qNvPM=r(KkcG~NW$Qyl%6q%KluEJqACYLcH(67Q0WS-n*e|U4>uu@x zGoA8Eknl*=G+p`=Go)!@OSn_n2gI}#!FI*w?Fegn&F#`Em3cD#bV~#85+ueW_VR-R z_GLu{iiR%vI{Dkxxy-UVT^Z|s={jfW+*g0{>zmubltdsdxL?{=pW(~}xQI#c#J9#1 zd2fU0m$E!{Kl`kNeU#vQwJvSplnCO`qJW3bZZww)0^&bQ72$I5{s3`yc2h*j*C3Lx zj(-sWmeca`BWVp$IbT$VPd$J=5ikAprz*5+vKviW4S&?oOMO{x1?7r zw)EAc6tmz9pe~HZZbBj5=@Ye?MI+zW|I&6h0{pb%nNtDEkFXqBE_Uenl)gIEm2Tf_ zKxBAVt)Biww^Q4L+LKvLW4h#BN614))+^RMsp~c`>&M<-4ZDT2Q`c&)MS)?*hu2Ph z?w1hSe1Z1SZboV->I}8T9ov$7wPhU0z8uWjO;BR|j54BZ?$*DfTUr-fx!5&ku&I@DZqUJWH%tYbi+$_btEoV<<&CHxh zY;-@B_Ywoo(%G`X8#cA9pF@SG(JD^jOCt}B;G0|Qw+mQdRTKRdVtRx?+hLK`8S#}X z@W}h$c7v6>!+3Y)j@FuY7^s=u8&}%PgjToS;(*+8I>aF;eS=@Je|rkP<^60VGZ+@t zqGS53P2_K=5*JN)NE{JcoXx^aFutvRXZ(a%p+59#%=b|R$f4lVQS%b|8N(MwVYnWp z3pe6}Z|B5 zeLPR#iQf|z*}`-$wxpTF0ZNHT(=Kc&^5(IkMl~tFYy%+Ct{(_21*0tYXV!Cnvze3p z?-G$spU09m?BXjvc1j_rEGR74hg@+YzqxU5Y_(v6^E`axg4ijhN{pJ!67^- z2g*PVr_k7)-N%<=1Oc1Ml7|^E4b*Mk?=$40ENFFpS3Y-;-0B+xr2O*9-+~d^T5e{z z6V$#JWX|bD$@RI%2Dqm!9+G*`;?_(2A2Q%ASZT$FbbCso$XS&xebUujo>Va|L6}CmhOIPTlq<0X+-jPcCpO-|L>rOWtY-&#{ zcTMk2PvmsQDFt&Ae7-5cH9ZvE^B^i7rwfYZS`BdsQt+4W9y1EA@4V0&|Cs(10vd#a zGN3->^=e$HTguoJxf#uq$|#@rF4L+I{KJmYj=QeL&BTmJe~?s znXa-fibnt3-vX2Z;?!0{7+N3+27+hoPq}G06j|9t$#!&p_*!(+ms@~k(r;B%ng?(J zuqy{0I%XR`Y=YaXeedqH)Rz@p6zY(8C<|i+s{CTvh_vO2bub^S+79*im4^B82nZ2P zYF1MC2_Fnbj@@VuFI3YSsj7c%-NwRfdmz8z)E>_}X>EpF^r-^b>DHk4GGQZMwetpm zok<&wq(j>WIFm`5uy?A99gP4yxbwSWz9v&^)YTf4oYykT5UsGtJk{pw%qU|23qd63~X39iRD_j*T{HB z;JvmP%xG^-IBHcJcw_&44<)BSY0UWKeNF&fG+g4Z)n1yZQ93xB8iN`W7BtK^H7$iG zBv~|R8kzZdMcGE&hdb)YoYXAt{`Ug)+zsoQ5x7ENnl;H-wkZ8OfFv!1=<6AV%C!tf z!yjj}*=qCC1y<`8d*!I}qNx05P)42Ea!OGZ@)I|76S2F7!EHy!SUdh3<#^NgO!6a5 z7$vW$HL{`Erp-AE2LvtOA!6}YskLUm(XYhkMw|E&wRM!ifLX`-e9QS4XVhmC6&HI+ z?=;!u#Vz%FKL{PK=7$@xX}orX8AB@)keNbSXp|eQ+!TACNDi=&vD^ zuOsr*xod31=h$ER_Z1z0nMsV7+DUfT8;YyRz$mmvD(BtwD6Xc`GO5@KZy8UkQa1GB zx6h*vrHWLpCPOnGB3bnKcIAas5bP2&k=3rYy-M`wN!HtzIW+jV?U}7Bo^Y zmP-19vVpSIS@nReU%9c-IcYyjCedbrn;o1)|171qUyb`j_sp@)qh6w&(Ao->Ps*Oi z{`me2WViy(8BbD8PdLwiOgTGpEZ+1AZ8YMnmI;O>pq$r-Y(rC-sTVO}ir04EUWqo3 zuhXwd_P2dK?JM}&;AJ5GJk+tQ>Q4_jmxVqtE|)!E^z2zdfRgFS{6SYm0E>RF7-!h= z?p0*Yrrn`JG?6W!CQ#<4R%(f7vUZTRscq`gXDDO&aq7DUUSrdIQ2oi%r=fp}I!y1o zX?XVLXqh%&C)J@9Eb!%|;$s@I0><8z3$vB_=SNc8#(2hg-&l{K$@O))FJ2eJMmc(X z1$aFD{WC=io88pK;qRZ@i;Ub^zSYHoPx#!Z75&M2O5^!g(Y!Zf0?AFyVc^05tIs0i zqBRz+9PX$)rD-aw#8^0OTgRB2Q&8$y{Vu~l+WuHpqBmCe*t1N*V$ktkPoOf<2Q3a5 zUtDWDCkcq(ss{+sWSO6mKu*7$>e(h36yH?&ayDA9zoNrLW3TrK#SWb_VXped!|wDa z&;Pv-IM0gTCIQ<6zY^Xa2j7APN7sk$*L$klfCiFK3xhHZT9jE&0moTV>MsL(o?D&F zDCp|uzl@=vwTS8L_$!P;K_r~|$2eK|jT;_wzKa@ehi3yrJFlN5M0{a4pP%k?C7S=h z$zG&Q`~s$|gml!b!}fUC&!fAqmgcf&FO=-E(33BmcK{h+So~AedCu#b9pA!k2gA0@ z-n?804n*h}#>eks6|};|75S1!1@M0&oa)6B83~pJz8a~#9&zc1m#16^9h-dXtBn#n z09|8oYQ66WH?^bI)O;u7o}V69sUQDI&75}kG}C^jT+%DEvwy!XOyQ<4Gs@uYyrLZR 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 2ef59c470fdd35c0559a2b648a5b0d050af27c70 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Tue, 24 May 2022 10:18:03 +0200 Subject: [PATCH 54/57] 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 55/57] 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 56/57] 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 57/57] 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",