From 24d35eca2cf4e676832362803a378e453871e2db Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 18:54:29 +0800 Subject: [PATCH 001/101] Update stopwatch.js --- apps/swatch/stopwatch.js | 67 ++++++++++++++++++++++++++++------------ 1 file changed, 47 insertions(+), 20 deletions(-) diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 6f8ad9e34..478c22619 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -1,8 +1,11 @@ +var tTotal = Date.now(); var tStart = Date.now(); var tCurrent = Date.now(); var started = false; -var timeY = 60; +var timeY = 45; var hsXPos = 0; +var TtimeY = 75; +var ThsXPos = 0; var lapTimes = []; var displayInterval; @@ -12,6 +15,7 @@ function timeToText(t) { var hs = Math.floor(t/10)%100; return mins+":"+("0"+secs).substr(-2)+"."+("0"+hs).substr(-2); } + function updateLabels() { g.reset(1); g.clearRect(0,23,g.getWidth()-1,g.getHeight()-24); @@ -24,35 +28,53 @@ function updateLabels() { g.setFontAlign(-1,-1); for (var i in lapTimes) { if (i<16) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 30 + i*8);} + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 40 + i*8);} else if (i<32) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 30 + (i-16)*8);} + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-16)*8);} } drawsecs(); } + function drawsecs() { var t = tCurrent-tStart; - g.reset(1); - g.setFont("Vector",48); - g.setFontAlign(0,0); + var Tt = tCurrent-tTotal; var secs = Math.floor(t/1000)%60; var mins = Math.floor(t/60000); var txt = mins+":"+("0"+secs).substr(-2); + var Tsecs = Math.floor(Tt/1000)%60; + var Tmins = Math.floor(Tt/60000); + var Ttxt = Tmins+":"+("0"+Tsecs).substr(-2); var x = 100; - g.clearRect(0,timeY-26,200,timeY+26); - g.drawString(txt,x,timeY); + var Tx = 125; + g.reset(1); + g.setFont("Vector",38); + g.setFontAlign(0,0); + g.clearRect(0,timeY-21,200,timeY+21); + g.drawString(Ttxt,x,timeY); hsXPos = 5+x+g.stringWidth(txt)/2; + g.setFont("6x8",2); + g.clearRect(0,TtimeY-7,200,TtimeY+7); + g.drawString(txt,Tx,TtimeY); + ThsXPos = 5+Tx+g.stringWidth(Ttxt)/2; drawms(); } + function drawms() { var t = tCurrent-tStart; var hs = Math.floor(t/10)%100; + var Tt = tCurrent-tTotal; + var Ths = Math.floor(Tt/10)%100; g.setFontAlign(-1,0); g.setFont("6x8",2); g.clearRect(hsXPos,timeY,220,timeY+20); - g.drawString("."+("0"+hs).substr(-2),hsXPos,timeY+10); + g.drawString("."+("0"+Ths).substr(-2),hsXPos-5,timeY+14); + g.setFont("6x8",1); + g.clearRect(ThsXPos,TtimeY,220,TtimeY+5); + g.drawString("."+("0"+hs).substr(-2),ThsXPos-5,TtimeY+3); } + function getLapTimesArray() { + lapTimes.push(tCurrent-tTotal); return lapTimes.map(timeToText).reverse(); } @@ -61,7 +83,8 @@ setWatch(function() { // Start/stop Bangle.beep(); if (started) tStart = Date.now()+tStart-tCurrent; - tCurrent = Date.now(); + tTotal = Date.now()+tTotal-tCurrent; + tCurrent = Date.now(); if (displayInterval) { clearInterval(displayInterval); displayInterval = undefined; @@ -69,37 +92,41 @@ setWatch(function() { // Start/stop updateLabels(); if (started) displayInterval = setInterval(function() { - var last = tCurrent; - if (started) tCurrent = Date.now(); - if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) - drawsecs(); - else - drawms(); + var last = tCurrent; + if (started) tCurrent = Date.now(); + if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) + drawsecs(); + else + drawms(); }, 20); }, BTN2, {repeat:true}); + setWatch(function() { // Lap Bangle.beep(); if (started) { tCurrent = Date.now(); lapTimes.unshift(tCurrent-tStart); } - tStart = tCurrent; if (!started) { // save var timenow= Date(); var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json"; // this maxes out the 28 char maximum + lapTimes.unshift(tCurrent-tStart); require("Storage").writeJSON(filename, getLapTimesArray()); + tStart = tCurrent = tTotal = Date.now(); + lapTimes = []; E.showMessage("Laps Saved","Stopwatch"); setTimeout(updateLabels, 1000); } else { + tStart = tCurrent; updateLabels(); } }, BTN1, {repeat:true}); setWatch(function() { // Reset if (!started) { - Bangle.beep(); - tStart = tCurrent = Date.now(); - lapTimes = []; + Bangle.beep(); + tStart = tCurrent = tTotal = Date.now(); + lapTimes = []; } updateLabels(); }, BTN3, {repeat:true}); From 9a03c9bcce110c428d7334a11b01e4b48019ce81 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 18:57:52 +0800 Subject: [PATCH 002/101] Update ChangeLog --- apps/swatch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/swatch/ChangeLog b/apps/swatch/ChangeLog index 3246eeced..9a037fa41 100644 --- a/apps/swatch/ChangeLog +++ b/apps/swatch/ChangeLog @@ -5,3 +5,4 @@ Fixed bug from 0.01 where BN1 (reset) could clear the lap log when timer is running 0.04: Changed save file filename, add interface.html to allow laps to be loaded 0.05: Added widgets +0.06: Added total running time, moved lap time to smaller display, total run time now appends as first entry in array, saving now saves last lap as well From 5d588d6d696d00133e28269e4d125595faa8d89e Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:11:54 +0800 Subject: [PATCH 003/101] Update interface.html --- apps/swatch/interface.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 928c5fe39..bfa7f8193 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date}
+
${lap.date} Elapsed Time: ${lap.d.1}
${lap.d.length} Laps
@@ -32,7 +32,7 @@ function getLapTimes() { - ${ lap.d.map((d,n)=>`${n+1}${d}`).join("\n") } + ${ lap.d.map((d+1,n)=>`${n+1}${d+1}`).join("\n") }
From 70e9c23c54f5898a83cdf1abb61b17e5304fa66d Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:17:03 +0800 Subject: [PATCH 004/101] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index bfa7f8193..735f643a8 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date} Elapsed Time: ${lap.d.1}
+
${lap.date} Elapsed Time: ${lap[1]}
${lap.d.length} Laps
From 02aaf2dd166ba350019c3eb44eba757ba835dfef Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:22:07 +0800 Subject: [PATCH 005/101] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 735f643a8..53f0dd503 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -20,7 +20,7 @@ function getLapTimes() { html += `
-
${lap.date} Elapsed Time: ${lap[1]}
+
${lap.date}
${lap.d.length} Laps
From 0f20176280e15875b8c9c3ef06619b887c3c28c3 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:22:51 +0800 Subject: [PATCH 006/101] Update interface.html --- apps/swatch/interface.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 53f0dd503..928c5fe39 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -32,7 +32,7 @@ function getLapTimes() { - ${ lap.d.map((d+1,n)=>`${n+1}${d+1}`).join("\n") } + ${ lap.d.map((d,n)=>`${n+1}${d}`).join("\n") }
From 32e811b2312ab99bf7ba1bcf466621c0d0a30bc2 Mon Sep 17 00:00:00 2001 From: Red-The-Hunter <62763030+Red-The-Hunter@users.noreply.github.com> Date: Wed, 15 Apr 2020 19:32:17 +0800 Subject: [PATCH 008/101] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0643ad6de..5fae8f482 100644 --- a/apps.json +++ b/apps.json @@ -399,7 +399,7 @@ { "id": "swatch", "name": "Stopwatch", "icon": "stopwatch.png", - "version":"0.05", + "version":"0.06", "interface": "interface.html", "description": "Simple stopwatch with Lap Time logging to a JSON file", "tags": "health", From b8226cce8fbfaa0a86c5f13a288a6d920be74bd1 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Wed, 15 Apr 2020 14:00:01 +0200 Subject: [PATCH 009/101] Added DANE Signed-off-by: OmegaRogue --- apps.json | 22 +++++ apps/dane/ChangeLog | 4 + apps/dane/add_to_apps.json | 22 +++++ apps/dane/app-icon.js | 1 + apps/dane/app.js | 163 +++++++++++++++++++++++++++++++++++++ apps/dane/app.png | Bin 0 -> 15535 bytes site.webmanifest | 4 +- 7 files changed, 214 insertions(+), 2 deletions(-) create mode 100644 apps/dane/ChangeLog create mode 100644 apps/dane/add_to_apps.json create mode 100644 apps/dane/app-icon.js create mode 100644 apps/dane/app.js create mode 100644 apps/dane/app.png diff --git a/apps.json b/apps.json index 0643ad6de..91d2d249b 100644 --- a/apps.json +++ b/apps.json @@ -1241,5 +1241,27 @@ {"name":"calculator.app.js","url":"app.js"}, {"name":"calculator.img","url":"calculator-icon.js","evaluate":true} ] + }, + { + "id": "dane", + "name": "Digital Assistant, not EDITH", + "shortName": "DANE", + "icon": "app.png", + "version": "0.06", + "description": "A detailed description of my great app", + "tags": "clock", + "type": "clock", + "allow_emulator": true, + "storage": [ + { + "name": "dane.app.js", + "url": "app.js" + }, + { + "name": "dane.img", + "url": "app-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/dane/ChangeLog b/apps/dane/ChangeLog new file mode 100644 index 000000000..607d0adf5 --- /dev/null +++ b/apps/dane/ChangeLog @@ -0,0 +1,4 @@ +0.01: New App! +0.04: Added Icon to watchface +0.05: bugfix +0.06: moved and resized icon \ No newline at end of file diff --git a/apps/dane/add_to_apps.json b/apps/dane/add_to_apps.json new file mode 100644 index 000000000..6efb3ec85 --- /dev/null +++ b/apps/dane/add_to_apps.json @@ -0,0 +1,22 @@ +{ + "id": "dane", + "name": "Digital Assistant, not EDITH", + "shortName": "DANE", + "icon": "app.png", + "version": "0.06", + "description": "A detailed description of my great app", + "tags": "clock", + "type": "clock", + "allow_emulator": true, + "storage": [ + { + "name": "dane.app.js", + "url": "app.js" + }, + { + "name": "dane.img", + "url": "app-icon.js", + "evaluate": true + } + ] +} \ No newline at end of file diff --git a/apps/dane/app-icon.js b/apps/dane/app-icon.js new file mode 100644 index 000000000..4deb12640 --- /dev/null +++ b/apps/dane/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("l8wxH+AH4A/AH4A/AFUvl8Cu4AEgUCBQIrfFQMRAAe/Aw4xbDYIlBiUS7AjCAAY5BBYMSiJkBGC4sCicTiRQJHoUSCAIwBF6sv30SikUiRMMMIISD7AvTl/YiYtPF40TF6R4BicVFqAWDF4MViaPRIwQWTF4O/IwiKRCoMRUiZHEDJ5cXJAxeOOQuQhQuShWQJIe/JJkviIuC74tTFwORRqKLD+3cmVLpsLFZtNAANKhXeDYKNOu4uEmdlDwVNBoNlsoDDmoKBhYQChcyFycVFwOTFwJcBpomBhYjCmouBAwYMCmZdBa4d3FyonBKoIoCAwIECLooucEIIjCRIYuFms1Lqq7CFwS7DLQQsDhYrBHIZdHXZkCdQpQDXoIQDFwIDBeoQQCpYuSl8RFwMT70KCRYAIhUSFwMTiMvFxm/CQUSFyp5Did3Fxi8DOBwuLDSEv7ETfoRCNDI13DIMT34ZPIYSgOaxJ3SIgZeTC7COBdgMCC58vOoakWiQvQFoQTBFqgvEiURF5gRDOKIdIDwMRiO/axMCBoMRLQItXF4Z9B7F3BxF37BZBAAQnRIYobDMAKqIl5aDAA5zJFwaCBAA6PBFxQQEAAYKBFxjSCU4IECA4YuJCAoAEFx0UikTAAIEBAwQuKCIoADFxsCI5RdiUAoAEVgIVJABRDHAH4A/AH4A/ADAA=")) \ No newline at end of file diff --git a/apps/dane/app.js b/apps/dane/app.js new file mode 100644 index 000000000..dc6262c58 --- /dev/null +++ b/apps/dane/app.js @@ -0,0 +1,163 @@ +const font = "6x8"; +const timeFontSize = 4; +const dateFontSize = 3; +const smallFontSize = 2; +const yOffset = 23; +const xyCenter = g.getWidth()/2; +const cornerSize = 14; +const cornerOffset = 3; +const borderWidth = 1; +const yposTime = 27+yOffset; +const yposDate = 65+yOffset; + +const mainColor = "#26dafd"; +const mainColorDark = "#029dbb"; +const mainColorLight = "#8bebfe"; + +const secondaryColor = "#df9527"; +const secondaryColorDark = "#8b5c15"; +const secondaryColorLight = "#ecc180"; + +const success = "#00ff00"; +const successDark = "#000900"; +const successLight = "#060f06"; + +const alert = "#ff0000"; +const alertDark = "#090000"; +const alertLight = "#0f0606"; + +var img = { + width : 120, height : 120, bpp : 8, + transparent : 254, + buffer : require("heatshrink").decompress(atob("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")) +} + + +function drawTopLeftCorner(x,y) { + g.setColor(mainColor); + var x1 = x-cornerOffset; + var y1 = y-cornerOffset; + g.fillRect(x1,y1,x1+cornerSize,y1+cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x+cornerSize-cornerOffset,y+cornerSize-cornerOffset); +} +function drawTopRightCorner(x,y) { + g.setColor(mainColor); + var x1 = x+cornerOffset; + var y1 = y-cornerOffset; + g.fillRect(x1,y1,x1-cornerSize,y1+cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x-cornerSize-cornerOffset,y+cornerSize-cornerOffset); +} +function drawBottomLeftCorner(x,y) { + g.setColor(mainColor); + var x1 = x-cornerOffset; + var y1 = y+cornerOffset; + g.fillRect(x1,y1,x1+cornerSize,y1-cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x+cornerSize-cornerOffset,y-cornerSize+cornerOffset); +} +function drawBottomRightCorner(x,y) { + g.setColor(mainColor); + var x1 = x+cornerOffset; + var y1 = y+cornerOffset; + g.fillRect(x1,y1,x1-cornerSize,y1-cornerSize); + g.setColor("#000000"); + g.fillRect(x,y,x-cornerSize+cornerOffset,y-cornerSize+cornerOffset); +} + +function drawFrame(x1,y1,x2,y2) { + drawTopLeftCorner(x1,y1); + drawTopRightCorner(x2,y1); + drawBottomLeftCorner(x1,y2); + drawBottomRightCorner(x2,y2); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} +function drawTopFrame(x1,y1,x2,y2) { + + drawBottomLeftCorner(x1,y2); + drawBottomRightCorner(x2,y2); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} +function drawBottomFrame(x1,y1,x2,y2) { + drawTopLeftCorner(x1,y1); + drawTopRightCorner(x2,y1); + g.setColor(mainColorDark); + g.drawRect(x1,y1,x2,y2); + g.setColor("#000000"); + g.fillRect(x1+borderWidth,y1+borderWidth,x2-borderWidth,y2-borderWidth); +} + +function getUTCTime(d) { + return d.toUTCString().split(' ')[4].split(':').map(function(d){return Number(d);}); +} + + + + + +function drawTimeText() { + g.setFontAlign(0, 0); + var d = new Date(); + var da = d.toString().split(" "); + var dutc = getUTCTime(d); + + var time = da[4].split(":"); + var hours = time[0], + minutes = time[1], + seconds = time[2]; + g.setColor(mainColor); + g.setFont(font, timeFontSize); + g.drawString(`${hours}:${minutes}:${seconds}`, xyCenter, yposTime, true); + g.setFont(font, smallFontSize); +} +function drawDateText() { + g.setFontAlign(0, 0); + var d = new Date(); + g.setFont(font, dateFontSize); + g.drawString(`${d.getDate()}.${d.getMonth()+1}.${d.getFullYear()}`, xyCenter, yposDate, true); +} + + + +function drawClock() { + // main frame + drawFrame(3,10+yOffset,g.getWidth()-3,g.getHeight()-3); + // time frame + drawTopFrame(20,10+yOffset,220,46+yOffset); + // date frame + drawTopFrame(28,46+yOffset,212,46+yOffset+35); + + // texts + drawTimeText(); + drawDateText(); + g.drawImage(img,g.getWidth()/2-(img.width/2),g.getHeight()/2); +} +function updateClock() { + drawTimeText(); + drawDateText(); +} + + +Bangle.on('lcdPower', function(on) { + if (on) drawClock(); +}); +g.clear(); + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + + +drawClock(); + + +setWatch(Bangle.showLauncher, BTN2, {repeat:false,edge:"falling"}); + +// refesh every 100 milliseconds +setInterval(updateClock, 100); diff --git a/apps/dane/app.png b/apps/dane/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ee4f8403a82262e37b2750c9d7b245668e6cc46e GIT binary patch literal 15535 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 literal 0 HcmV?d00001 diff --git a/site.webmanifest b/site.webmanifest index 0d1fb4679..0565f159c 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -17,6 +17,6 @@ "theme_color": "#5755d9", "background_color": "#5755d9", "display": "standalone", - "start_url": "https://banglejs.com/apps/", - "scope": "https://banglejs.com/apps/" + "start_url": "https://omegavoid.codes/BangleApps", + "scope": "https://omegavoid.codes/BangleApps" } From 0ef33e12dce47fe91106b7b03b5bc7880dc68c33 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:21:27 +0200 Subject: [PATCH 010/101] Distance calc and display --- apps/activepedom/ChangeLog | 3 +- apps/activepedom/README.md | 23 +++++++++++--- apps/activepedom/settings.js | 33 +++++++++++++++++++- apps/activepedom/widget.js | 58 +++++++++++++++++++++++++----------- 4 files changed, 93 insertions(+), 24 deletions(-) diff --git a/apps/activepedom/ChangeLog b/apps/activepedom/ChangeLog index 4c21f3ace..fb0bc78e5 100644 --- a/apps/activepedom/ChangeLog +++ b/apps/activepedom/ChangeLog @@ -1 +1,2 @@ -0.01: New Widget! +0.01: New Widget! +0.02: Distance calculation and display \ No newline at end of file diff --git a/apps/activepedom/README.md b/apps/activepedom/README.md index 8a10727cd..055a91f56 100644 --- a/apps/activepedom/README.md +++ b/apps/activepedom/README.md @@ -1,4 +1,4 @@ -# Improved pedometer +# Active Pedometer Pedometer that filters out arm movement and displays a step goal progress. I changed the step counting algorithm completely. @@ -19,8 +19,9 @@ When you reach the step threshold, the steps needed to reach the threshold are c ## Features * Two line display +* Can display distance (in km) or steps in each line * Large number for good readability -* Small number with the exact steps counted +* Small number with the exact steps counted or more exact distance * Large number is displayed in green when status is 'active' * Progress bar for step goal * Counts steps only if they are reached in a certain time @@ -29,9 +30,23 @@ When you reach the step threshold, the steps needed to reach the threshold are c * Steps are saved to a file and read-in at start (to not lose step progress) * Settings can be changed in Settings - App/widget settings - Active Pedometer -## Development version +## Settings -* https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/pedometer +* Max time (ms): Maximum time between two steps in milliseconds, steps will not be counted if exceeded. Standard: 1100 +* Min time (ms): Minimum time between two steps in milliseconds, steps will not be counted if fallen below. Standard: 240 +* Step threshold: How many steps are needed to reach 'active' mode. If you do not reach the threshold in the 'Active Reset' time, the steps are not counted. Standard: 30 +* Act.Res. (ms): Active Reset. After how many miliseconds will the 'active mode' reset. You have to reach the step threshold in this time, otherwise the steps are not counted. Standard: 30000 +* Step sens.: Step Sensitivity. How sensitive should the sted detection be? This changes sensitivity in step detection in the firmware. Standard in firmware: 80 +* Step goal: This is your daily step goal. Standard: 10000 +* Step length: Length of one step in cm. Standard: 75 +* Line One: What to display in line one, steps or distance. Standard: steps +* Line Two: What to display in line two, steps or distance. Standard: distance + +## Releases + +* Offifical app loader: https://github.com/espruino/BangleApps/tree/master/apps/activepedom (https://banglejs.com/apps) +* Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/activepedom (https://purple-tentacle.github.io/BangleApps/#widget) +* Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/pedometer ## Requests diff --git a/apps/activepedom/settings.js b/apps/activepedom/settings.js index 43764a164..94ae435d2 100644 --- a/apps/activepedom/settings.js +++ b/apps/activepedom/settings.js @@ -4,6 +4,7 @@ */ (function(back) { const SETTINGS_FILE = 'activepedom.settings.json'; + const LINES = ['Steps', 'Distance']; // initialize with default settings... let s = { @@ -13,6 +14,9 @@ 'intervalResetActive' : 30000, 'stepSensitivity' : 80, 'stepGoal' : 10000, + 'stepLength' : 75, + 'lineOne': LINES[0], + 'lineTwo': LINES[1], }; // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -27,7 +31,7 @@ return function (value) { s[key] = value; storage.write(SETTINGS_FILE, s); - WIDGETS["activepedom"].draw(); + //WIDGETS["activepedom"].draw(); }; } @@ -76,6 +80,33 @@ step: 1000, onchange: save('stepGoal'), }, + 'Step length (cm)': { + value: s.stepLength, + min: 1, + max: 150, + step: 1, + onchange: save('stepLength'), + }, + 'Line One': { + format: () => s.lineOne, + onchange: function () { + // cycles through options + const oldIndex = LINES.indexOf(s.lineOne) + const newIndex = (oldIndex + 1) % LINES.length + s.lineOne = LINES[newIndex] + save('lineOne')(s.lineOne) + }, + }, + 'Line Two': { + format: () => s.lineTwo, + onchange: function () { + // cycles through options + const oldIndex = LINES.indexOf(s.lineTwo) + const newIndex = (oldIndex + 1) % LINES.length + s.lineTwo = LINES[newIndex] + save('lineTwo')(s.lineTwo) + }, + }, }; E.showMenu(menu); }); \ No newline at end of file diff --git a/apps/activepedom/widget.js b/apps/activepedom/widget.js index 0c8b2438d..d569716ec 100644 --- a/apps/activepedom/widget.js +++ b/apps/activepedom/widget.js @@ -8,22 +8,16 @@ var active = 0; //x steps in y seconds achieved var stepGoalPercent = 0; //percentage of step goal var stepGoalBarLength = 0; //length og progress bar - var lastUpdate = new Date(); - var width = 45; + var lastUpdate = new Date(); //used to reset counted steps on new day + var width = 45; //width of widget - var stepsTooShort = 0; + //used for statistics and debugging + var stepsTooShort = 0; var stepsTooLong = 0; var stepsOutsideTime = 0; - //define default settings - const DEFAULTS = { - 'cMaxTime' : 1100, - 'cMinTime' : 240, - 'stepThreshold' : 30, - 'intervalResetActive' : 30000, - 'stepSensitivity' : 80, - 'stepGoal' : 10000, - }; + var distance = 0; //distance travelled + const SETTINGS_FILE = 'activepedom.settings.json'; const PEDOMFILE = "activepedom.steps.json"; @@ -32,10 +26,21 @@ function loadSettings() { settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; } + //return setting function setting(key) { - if (!settings) { loadSettings(); } - return (key in settings) ? settings[key] : DEFAULTS[key]; + //define default settings + const DEFAULTS = { + 'cMaxTime' : 1100, + 'cMinTime' : 240, + 'stepThreshold' : 30, + 'intervalResetActive' : 30000, + 'stepSensitivity' : 80, + 'stepGoal' : 10000, + 'stepLength' : 75, + }; + if (!settings) { loadSettings(); } + return (key in settings) ? settings[key] : DEFAULTS[key]; } function setStepSensitivity(s) { @@ -46,7 +51,7 @@ } //format number to make them shorter - function kFormatter(num) { + function kFormatterSteps(num) { if (num <= 999) return num; //smaller 1.000, return 600 as 600 if (num >= 1000 && num < 10000) { //between 1.000 and 10.000 num = Math.floor(num/100)*100; @@ -99,11 +104,12 @@ else { stepsOutsideTime++; } + settings = 0; //reset settings to save memory } function draw() { var height = 23; //width is deined globally - var stepsDisplayLarge = kFormatter(stepsCounted); + distance = (stepsCounted * setting('stepLength')) / 100 /1000 //distance in km //Check if same day let date = new Date(); @@ -121,10 +127,21 @@ if (active == 1) g.setColor(0x07E0); //green else g.setColor(0xFFFF); //white g.setFont("6x8", 2); - g.drawString(stepsDisplayLarge,this.x+1,this.y); //first line, big number + + if (setting('lineOne') == 'Steps') { + g.drawString(kFormatterSteps(stepsCounted),this.x+1,this.y); //first line, big number, steps + } + if (setting('lineOne') == 'Distance') { + g.drawString(distance.toFixed(2),this.x+1,this.y); //first line, big number, distance + } g.setFont("6x8", 1); g.setColor(0xFFFF); //white - g.drawString(stepsCounted,this.x+1,this.y+14); //second line, small number + if (setting('lineTwo') == 'Steps') { + g.drawString(stepsCounted,this.x+1,this.y+14); //second line, small number, steps + } + if (setting('lineTwo') == 'Distance') { + g.drawString(distance.toFixed(3) + "km",this.x+1,this.y+14); //second line, small number, distance + } //draw step goal bar stepGoalPercent = (stepsCounted / setting('stepGoal')) * 100; @@ -136,6 +153,8 @@ g.fillRect(this.x, this.y+height, this.x+1, this.y+height-1); //draw start of bar g.fillRect(this.x+width, this.y+height, this.x+width-1, this.y+height-1); //draw end of bar g.fillRect(this.x, this.y+height, this.x+stepGoalBarLength, this.y+height); // draw progress bar + + settings = 0; //reset settings to save memory } //This event is called just before the device shuts down for commands such as reset(), load(), save(), E.reboot() or Bangle.off() @@ -164,6 +183,7 @@ //Read data from file and set variables let pedomData = require("Storage").readJSON(PEDOMFILE,1); + if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stepsCounted = pedomData.stepsToday|0; @@ -172,6 +192,8 @@ stepsOutsideTime = pedomData.stepsOutsideTime; } + pedomdata = 0; //reset pedomdata to save memory + setStepSensitivity(setting('stepSensitivity')); //set step sensitivity (80 is standard, 400 is muss less sensitive) //Add widget From 505730cd50cb9ab08b2100bd6064399c907be3a3 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:23:38 +0200 Subject: [PATCH 011/101] active pedometer: added readme --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 3dbccb9b1..ec211f060 100644 --- a/apps.json +++ b/apps.json @@ -1116,6 +1116,7 @@ "description": "Pedometer that filters out arm movement and displays a step goal progress.", "tags": "outdoors,widget", "type":"widget", + "readme": "README.md", "storage": [ {"name":"activepedom.wid.js","url":"widget.js"}, {"name":"activepedom.settings.js","url":"settings.js"}, From d74eb43fb6477e5958dee98c623cb43dc3213e3d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 08:27:13 +0200 Subject: [PATCH 012/101] active pedometer: version 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ec211f060..ab8af0f37 100644 --- a/apps.json +++ b/apps.json @@ -1112,7 +1112,7 @@ "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Pedometer that filters out arm movement and displays a step goal progress.", "tags": "outdoors,widget", "type":"widget", From 078a3e6d5f31363a7ab7042859870f02cf3a1126 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 08:16:27 +0100 Subject: [PATCH 013/101] change default temperature for israel as per #248 --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index ebf28e53d..508c92015 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -220,7 +220,7 @@ var locales = { int_curr_symbol: "ILS", speed: "kmh", distance: { 0: "m", 1: "km" }, - temperature: "°F", + temperature: "°C", ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, datePattern: { 0: "%A, %B %d, %Y", "1": "%d/%m/%Y" }, // Sunday, 1 March 2020 // 01/03/2020 From 944693eaf966fe4b54cbfeaef5148f5b1efc444d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:06:44 +0200 Subject: [PATCH 014/101] Chronowid initial --- apps/chronowid/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/chronowid/ChangeLog diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog new file mode 100644 index 000000000..a6f342f01 --- /dev/null +++ b/apps/chronowid/ChangeLog @@ -0,0 +1 @@ +0.01: New widget and app! From 1a935951b03efdeca39d61da79302ff83c73ea18 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:07:39 +0200 Subject: [PATCH 015/101] Chronowid initial --- apps/chronowid/README.md | 35 ++++++++++++++ apps/chronowid/app-icon.js | 1 + apps/chronowid/app.js | 91 ++++++++++++++++++++++++++++++++++++ apps/chronowid/app.png | Bin 0 -> 1060 bytes apps/chronowid/widget.js | 93 +++++++++++++++++++++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 apps/chronowid/README.md create mode 100644 apps/chronowid/app-icon.js create mode 100644 apps/chronowid/app.js create mode 100644 apps/chronowid/app.png create mode 100644 apps/chronowid/widget.js diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md new file mode 100644 index 000000000..b6325d94f --- /dev/null +++ b/apps/chronowid/README.md @@ -0,0 +1,35 @@ +# Chronometer Widget + +Chronometer (timer) that runs as a widget. +The advantage is, that you can still see your normal watchface and other widgets when the timer is running. +The widget is always active, but only shown when the timer is on. +Hours, minutes, seconds and timer status can be set with an app. + +## Screenshots + +TBD + +## Features + +* Using other apps does not interrupt the timer, no need to keep the widget open (BUT: there will be no buzz when the time is up, for that the widget has to be loaded) +* Target time is saved to a file and timer picks up again when widget is loaded again. + +## Settings + +There are no settings section in the settings app, timer can be set using an app. + +* Hours: Set the hours for the timer +* Minutes: Set the minutes for the timer +* Seconds: Set the seconds for the timer +* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app. The widget is always there, but only visible when timer is on. + + +## Releases + +* Offifical app loader: Not yet published. +* Forked app loader: Not yet published. +* Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid + +## Requests + +If you have any feature requests, please contact me on the Espruino forum: http://forum.espruino.com/profiles/155005/ \ No newline at end of file diff --git a/apps/chronowid/app-icon.js b/apps/chronowid/app-icon.js new file mode 100644 index 000000000..db2010218 --- /dev/null +++ b/apps/chronowid/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIFCn/8BYYFRABcD4AFFgIFCh/wgeAAoP//8HCYMDAoPD8EAg4FB8PwgEf+EP/H4HQOAgP8uEAvwfBv0ggBFCn4CB/EBwEfgEB+AFBh+AgfgAoI1BIoQJB4AHBAoXgg4uBAIIFCCYQFGh5rDJQJUBK4IFCNYIFVDoopDGoJiBHYYFKVYRZBWIYDBA4IFBNIQzBG4IbBToKkBAQKVFUIYICVoQUCXIQmCYoIsCaITqDAoLvDNYUAA=")) \ No newline at end of file diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js new file mode 100644 index 000000000..cb99268af --- /dev/null +++ b/apps/chronowid/app.js @@ -0,0 +1,91 @@ +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +const storage = require('Storage'); +const boolFormat = v => v ? "On" : "Off"; +let settingsChronowid; + +function updateSettings() { + var now = new Date(); + const goal = new Date(now.getFullYear(), now.getMonth(), now.getDate(), + now.getHours() + settingsChronowid.hours, now.getMinutes() + settingsChronowid.minutes, now.getSeconds() + settingsChronowid.seconds); + settingsChronowid.goal = goal.getTime(); + storage.writeJSON('chronowid.json', settingsChronowid); +} + +function resetSettings() { + settingsChronowid = { + hours : 0, + minutes : 0, + seconds : 0, + started : false, + counter : 0, + goal : 0, + }; + updateSettings(); +} + +settingsChronowid = storage.readJSON('chronowid.json',1); +if (!settingsChronowid.started) resetSettings(); + +E.on('kill', () => { + print("-KILL-"); + updateSettings(); +}); + +function showMenu() { + const timerMenu = { + '': { + 'title': 'Set timer', + 'predraw': function() { + timerMenu.hours.value = settingsChronowid.hours; + timerMenu.minutes.value = settingsChronowid.minutes; + timerMenu.seconds.value = settingsChronowid.seconds; + timerMenu.started.value = settingsChronowid.started; + } + }, + 'Hours': { + value: settingsChronowid.hours, + min: 0, + max: 24, + step: 1, + onchange: v => { + settingsChronowid.hours = v; + updateSettings(); + } + }, + 'Minutes': { + value: settingsChronowid.minutes, + min: 0, + max: 59, + step: 1, + onchange: v => { + settingsChronowid.minutes = v; + updateSettings(); + } + }, + 'Seconds': { + value: settingsChronowid.seconds, + min: 0, + max: 59, + step: 1, + onchange: v => { + settingsChronowid.seconds = v; + updateSettings(); + } + }, + 'Timer on': { + value: settingsChronowid.started, + format: boolFormat, + onchange: v => { + settingsChronowid.started = v; + updateSettings(); + } + }, + }; + timerMenu['-Exit-'] = ()=>{load();}; + return E.showMenu(timerMenu); +} + +showMenu(); \ No newline at end of file diff --git a/apps/chronowid/app.png b/apps/chronowid/app.png new file mode 100644 index 0000000000000000000000000000000000000000..5ac7a480c5d4533c9851ba6264b74aae48035eb0 GIT binary patch literal 1060 zcmV+<1l#+GP)*2?CL* z=jdIsdaVqLAjyY*ycLl}Syc2;L97)RfoN7x+ost=DzrV^$!5>oot--~TQ7d$;EsFG z_k7Qtx%ZxXXA1}qX~XsfVFXm;x<_9I=$uURJ1ZseBV6R)F#Xg92 zC;;k!X6tX2rp*iB9q=U=45ym<6tfq%{NOz;R#zF~ zJ#TM22egDKJPw=zW_$>jHUpdnVmAI3OLSh6Xa!Os2$%L1*ptsBqQH3<0V&k;dH^*J zV!%>h8S0MJS>N^N=zw!Tp-U3u_?VrR0C%$lOrU0pB8}e`%Or|`Hefgl=b%lbJ&8}K z0d9mSa7Pnl3h2bW9NBGIHbj6fi%XY;{Z5Sg5f5-dL;ez|^x%8cvRtS_-ANgz&(_A* zqSmeY`$fNzK2BYIbgjB!6`wIzK6`b8=ix@{cYKKzS;Nui}lHqvFZQ(WIb6|yu`hkz&m1I8mjlf19JVWAIYSZF1nYXRZFlZI3veZ?Zx{Zz- z8U)9%7bjUM#@w4ba1E#UKX%2CD=z$#UYuryQ`9i1TdC|xfDJ{$-!T?-V<2r9M8a*K z9dr-w(56e^hqzvD804PIcY}spvhJGp;v`o<(?MK={xM1d>kPT%AWp~zx;ro;uD2Qn z9RX@lgZaBNBK9n5lVt>Xh&6?IE#n8Z zsI|x*yVnoVDxC9q0(E+jFT`XVq)WAoT2$kM2z58s3?hyzbG@mhlt>&`<*F<;=^ zP>ZwY)2MUOz$gT6YsjZjrw2i1rwDKu=QE!MZt?eMF)&KeCy_?gPVK0L$193a^SqoY z?cz&A(mszu+>h5Mfy=-_)QTBL?Ioht=LYM$0h}wWd~8DNc^%r&ZyAGHk`M;0SHw|0 z71k@JUh*@uTUMOHnq3)qg@)Rd!MF@c(8CV;o7*RA(a euUUTu4g4F8cKpwc4bA8P0000 { + const storage = require('Storage'); + settingsChronowid = storage.readJSON("chronowid.json",1)||{}; //read settingsChronowid from file + var height = 23; + var width = 58; + var interval = 0; //used for the 1 second interval timer + var now = new Date(); + + var time = 0; + var diff = settingsChronowid.goal - now; + + //Convert ms to time + function getTime(t) { + var milliseconds = parseInt((t % 1000) / 100), + seconds = Math.floor((t / 1000) % 60), + minutes = Math.floor((t / (1000 * 60)) % 60), + hours = Math.floor((t / (1000 * 60 * 60)) % 24); + + hours = (hours < 10) ? "0" + hours : hours; + minutes = (minutes < 10) ? "0" + minutes : minutes; + seconds = (seconds < 10) ? "0" + seconds : seconds; + + return hours + ":" + minutes + ":" + seconds; + } + + function printDebug() { + print ("Nowtime: " + getTime(now)); + print ("Now: " + now); + print ("Goaltime: " + getTime(settingsChronowid.goal)); + print ("Goal: " + settingsChronowid.goal); + print("Difftime: " + getTime(diff)); + print("Diff: " + diff); + print ("Started: " + settingsChronowid.started); + print ("----"); + } + + //counts down, calculates and displays + function countDown() { + //printDebug(); + now = new Date(); + diff = settingsChronowid.goal - now; //calculate difference + WIDGETS["chronowid"].draw(); + //time is up + if (settingsChronowid.started && diff <= 0) { + Bangle.buzz(1500); + //write timer off to file + settingsChronowid.started = false; + storage.writeJSON('chronowid.json', settingsChronowid); + clearInterval(interval); //stop interval + //printDebug(); + } + } + + // draw your widget + function draw() { + if (!settingsChronowid.started) { + width = 0; + return; //do not draw anything if timer is not started + } + g.reset(); + if (diff >= 0) { + if (diff < 600000) { //less than 1 hour left + width = 58; + g.clearRect(this.x,this.y,this.x+width,this.y+height); + g.setFont("6x8", 2); + g.drawString(getTime(diff).substring(3), this.x+1, this.y+5); //remove hour part 00:00:00 -> 00:00 + } + if (diff >= 600000) { //one hour or more left + width = 48; + g.clearRect(this.x,this.y,this.x+width,this.y+height); + g.setFont("6x8", 1); + g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 + } + } + else { + width = 58; + g.clearRect(this.x,this.y,this.x+width,this.y+height); + g.setFont("6x8", 2); + g.drawString("END", this.x+15, this.y+5); + } + } + + if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second + + // add the widget + WIDGETS["chronowid"]={area:"bl",width:width,draw:draw,reload:function() { + reload(); + Bangle.drawWidgets(); // relayout all widgets + }}; + + //printDebug(); + countDown(); +})(); \ No newline at end of file From 6fc326bb49ae2e004c6c210e84f68c3c76906764 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:10:57 +0200 Subject: [PATCH 016/101] Chronowid initial --- apps.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ab8af0f37..0d6cdd214 100644 --- a/apps.json +++ b/apps.json @@ -1108,7 +1108,7 @@ {"name":"openstmap.img","url":"app-icon.js","evaluate":true} ] }, - { "id": "activepedom", + { "id": "activepedom", "name": "Active Pedometer", "shortName":"Active Pedometer", "icon": "app.png", @@ -1123,6 +1123,21 @@ {"name":"activepedom.img","url":"app-icon.js","evaluate":true} ] }, + { "id": "chronowidget", + "name": "Chrono Widget", + "shortName":"Chrono Widget", + "icon": "app.png", + "version":"0.01", + "description": "Chronometer (timer) which runs as widget.", + "tags": "tools,widget", + "type":"widget", + "readme": "README.md", + "storage": [ + {"name":"chronowidget.wid.js","url":"widget.js"}, + {"name":"chronowidget.app.js","url":"app.js"}, + {"name":"chronowidget.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "tabata", "name": "Tabata", "shortName": "Tabata - Control High-Intensity Interval Training", From e2657a62a592ab6e4b3018bfb8f8216d0ff3412b Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:13:23 +0200 Subject: [PATCH 017/101] chronowid typo --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 0d6cdd214..591ddad28 100644 --- a/apps.json +++ b/apps.json @@ -1123,7 +1123,7 @@ {"name":"activepedom.img","url":"app-icon.js","evaluate":true} ] }, - { "id": "chronowidget", + { "id": "chronowid", "name": "Chrono Widget", "shortName":"Chrono Widget", "icon": "app.png", @@ -1133,9 +1133,9 @@ "type":"widget", "readme": "README.md", "storage": [ - {"name":"chronowidget.wid.js","url":"widget.js"}, - {"name":"chronowidget.app.js","url":"app.js"}, - {"name":"chronowidget.img","url":"app-icon.js","evaluate":true} + {"name":"chronowid.wid.js","url":"widget.js"}, + {"name":"chronowid.app.js","url":"app.js"}, + {"name":"chronowid.img","url":"app-icon.js","evaluate":true} ] }, { "id": "tabata", From e0a3b9ae3e15274d77d1a4af5ad7c8c90b737316 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 09:16:37 +0100 Subject: [PATCH 018/101] Launchers: Only store relevant app data (saves RAM when many apps) --- apps.json | 4 ++-- apps/launch/ChangeLog | 2 ++ apps/launch/app.js | 2 +- apps/toucher/ChangeLog | 3 ++- apps/toucher/app.js | 8 ++++---- 5 files changed, 11 insertions(+), 8 deletions(-) create mode 100644 apps/launch/ChangeLog diff --git a/apps.json b/apps.json index d3dd95b26..167df46f6 100644 --- a/apps.json +++ b/apps.json @@ -41,7 +41,7 @@ "name": "Default Launcher", "shortName":"Launcher", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "This is needed by Bangle.js to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", "tags": "tool,system,launcher", "type":"launch", @@ -1050,7 +1050,7 @@ "name": "Touch Launcher", "shortName":"Menu", "icon": "app.png", - "version":"0.05", + "version":"0.06", "description": "Touch enable left to right launcher.", "tags": "tool,system,launcher", "type":"launch", diff --git a/apps/launch/ChangeLog b/apps/launch/ChangeLog new file mode 100644 index 000000000..9e4a1eaf3 --- /dev/null +++ b/apps/launch/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Only store relevant app data (saves RAM when many apps) diff --git a/apps/launch/app.js b/apps/launch/app.js index 682122f82..a256b6909 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -1,5 +1,5 @@ var s = require("Storage"); -var apps = s.list(/\.info$/).map(app=>s.readJSON(app,1)||{name:"DEAD: "+app.substr(1)}).filter(app=>app.type=="app" || app.type=="clock" || !app.type); +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" || !app.type)); apps.sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first diff --git a/apps/toucher/ChangeLog b/apps/toucher/ChangeLog index a2a709ee3..0c97d9e13 100644 --- a/apps/toucher/ChangeLog +++ b/apps/toucher/ChangeLog @@ -2,4 +2,5 @@ 0.02: Add swipe support and doucle tap to run application 0.03: Close launcher when lcd turn off 0.04: Complete rewrite to add animation and loop ( issue #210 ) -0.05: Improve perf \ No newline at end of file +0.05: Improve perf +0.06: Only store relevant app data (saves RAM when many apps) diff --git a/apps/toucher/app.js b/apps/toucher/app.js index b67e5b26c..cf7d5333b 100644 --- a/apps/toucher/app.js +++ b/apps/toucher/app.js @@ -5,8 +5,8 @@ g.flip(); const Storage = require("Storage"); function getApps(){ - return Storage.list(/\.info$/).filter(app => app.endsWith('.info')).map(app => Storage.readJSON(app,1) || { name: "DEAD: "+app.substr(1) }) - .filter(app=>app.type=="app" || app.type=="clock" || !app.type) + return Storage.list(/\.info$/).map(app=>{var a=Storage.readJSON(app,1);return a&&{name:a.name,type:a.type,icon:a.icon,sortorder:a.sortorder,src:a.src,version:a.version}}) + .filter(app=>app && (app.type=="app" || app.type=="clock" || !app.type)) .sort((a,b)=>{ var n=(0|a.sortorder)-(0|b.sortorder); if (n) return n; // do sortorder first @@ -19,7 +19,7 @@ function getApps(){ const HEIGHT = g.getHeight(); const WIDTH = g.getWidth(); const HALF = WIDTH/2; -const ANIMATION_FRAME = 4; +const ANIMATION_FRAME = 4; const ANIMATION_STEP = HALF / ANIMATION_FRAME; function getPosition(index){ @@ -192,4 +192,4 @@ Bangle.on('swipe', dir => { // close launcher when lcd is off Bangle.on('lcdPower', on => { if(!on) return load(); -}); \ No newline at end of file +}); From 8c2decfa7b1d8a2d059129622207bbe810645d6a Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:17:14 +0200 Subject: [PATCH 019/101] readme update --- apps/chronowid/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md index b6325d94f..f31c24c7b 100644 --- a/apps/chronowid/README.md +++ b/apps/chronowid/README.md @@ -27,7 +27,7 @@ There are no settings section in the settings app, timer can be set using an app ## Releases * Offifical app loader: Not yet published. -* Forked app loader: Not yet published. +* Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/chronowid (https://purple-tentacle.github.io/BangleApps/index.html#) * Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid ## Requests From 9704522813daaf13354e63f79ba0f655546161b4 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:26:32 +0200 Subject: [PATCH 020/101] removed type widget --- apps.json | 1 - 1 file changed, 1 deletion(-) diff --git a/apps.json b/apps.json index 591ddad28..0a894353b 100644 --- a/apps.json +++ b/apps.json @@ -1130,7 +1130,6 @@ "version":"0.01", "description": "Chronometer (timer) which runs as widget.", "tags": "tools,widget", - "type":"widget", "readme": "README.md", "storage": [ {"name":"chronowid.wid.js","url":"widget.js"}, From 8c6b78ebe19b29e7513d708a8f9bfe34d1f51cdf Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Thu, 16 Apr 2020 10:32:41 +0200 Subject: [PATCH 021/101] Bugfix json creation --- apps/chronowid/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js index cb99268af..48401a7bb 100644 --- a/apps/chronowid/app.js +++ b/apps/chronowid/app.js @@ -27,7 +27,7 @@ function resetSettings() { } settingsChronowid = storage.readJSON('chronowid.json',1); -if (!settingsChronowid.started) resetSettings(); +if (!settingsChronowid) resetSettings(); E.on('kill', () => { print("-KILL-"); @@ -88,4 +88,4 @@ function showMenu() { return E.showMenu(timerMenu); } -showMenu(); \ No newline at end of file +showMenu(); From 304e23f53ed8715d640b797e94b7d2c041f9c990 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:23:19 +0200 Subject: [PATCH 022/101] Fix home button and add min/max for chart --- apps/batchart/app.js | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/apps/batchart/app.js b/apps/batchart/app.js index deb406d8b..2d0d8e585 100644 --- a/apps/batchart/app.js +++ b/apps/batchart/app.js @@ -65,9 +65,7 @@ function loadData() { // Top up to MaxValueCount from previous days as required let previousDay = decrementDay(startingDay); - while (dataLines.length < MaxValueCount - && previousDay !== startingDay) { - + while (dataLines.length < MaxValueCount && previousDay !== startingDay) { let topUpLogFileName = "bclog" + previousDay; let remainingLines = MaxValueCount - dataLines.length; let topUpLines = loadLinesFromFile(remainingLines, topUpLogFileName); @@ -126,6 +124,12 @@ function renderData(dataArray) { const batteryIndex = 1; const temperatureIndex = 2; const switchabelsIndex = 3; + + const minTemperature = 20; + const maxTemparature = 40; + + const belowMinIndicatorValue = minTemperature - 1; + const aboveMaxIndicatorValue = maxTemparature + 1; var allConsumers = switchableConsumers.none | switchableConsumers.lcd | switchableConsumers.compass | switchableConsumers.bluetooth | switchableConsumers.gps | switchableConsumers.hrm; @@ -140,8 +144,19 @@ function renderData(dataArray) { // Temperature g.setColor(0.4, 0.4, 1); - let scaledTemp = Math.floor(((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000)/20) + ((((parseFloat(dataInfo[temperatureIndex]) * 100) - 2000) % 100)/25); + + let datapointTemp = parseFloat(dataInfo[temperatureIndex]); + if (datapointTemp < minTemperature) { + datapointTemp = belowMinIndicatorValue; + } + if (datapointTemp > maxTemparature) { + datapointTemp = aboveMaxIndicatorValue; + } + + // Scale down the range of 20 - 40°C to a 100px y-axis, where 1px = .25° + let scaledTemp = Math.floor(((datapointTemp * 100) - 2000) / 20) + ((((datapointTemp * 100) - 2000) % 100) / 25); + g.setPixel(GraphXZero + i, GraphYZero - scaledTemp); // LCD state @@ -213,8 +228,6 @@ function switchOffApp(){ // special function to handle display switch on Bangle.on('lcdPower', (on) => { if (on) { - // call your app function here - // If you clear the screen, do Bangle.drawWidgets(); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); @@ -222,12 +235,11 @@ Bangle.on('lcdPower', (on) => { } }); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); +setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -// call your app function here renderHomeIcon(); From 24eb0f33fef2431bb589d59f95c342005b08a03a Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:24:17 +0200 Subject: [PATCH 023/101] Minor changes based on JSLint hints --- apps/batchart/widget.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/batchart/widget.js b/apps/batchart/widget.js index 53f8b3549..1b8ce79ba 100644 --- a/apps/batchart/widget.js +++ b/apps/batchart/widget.js @@ -12,8 +12,8 @@ var batChartFile; // file for battery percentage recording const recordingInterval10Min = 60 * 10 * 1000; - const recordingInterval1Min = 60*1000; //For testing - const recordingInterval10S = 10*1000; //For testing + const recordingInterval1Min = 60 * 1000; //For testing + const recordingInterval10S = 10 * 1000; //For testing var recordingInterval = null; var compassEventReceived = false; @@ -26,15 +26,15 @@ let y = this.y; g.setColor(0, 1, 0); - g.fillPoly([x+5, y, x+5, y+4, x+1, y+4, x+1, y+20, x+18, y+20, x+18, y+4, x+13, y+4, x+13, y], true); + g.fillPoly([x + 5, y, x + 5, y + 4, x + 1, y + 4, x + 1, y + 20, x + 18, y + 20, x + 18, y + 4, x + 13, y + 4, x + 13, y], true); - g.setColor(0,0,0); - g.drawPoly([x+5, y+6, x+8, y+12, x+13, y+12, x+16, y+18], false); + g.setColor(0, 0, 0); + g.drawPoly([x + 5, y + 6, x + 8, y + 12, x + 13, y + 12, x + 16, y + 18], false); g.reset(); } - function onMag(){ + function onMag() { compassEventReceived = true; // Stop handling events when no longer necessarry Bangle.removeListener("mag", onMag); @@ -51,6 +51,7 @@ } function getEnabledConsumersValue() { + // Wait for an event from each of the devices to see if they are switched on var enabledConsumers = switchableConsumers.none; Bangle.on('mag', onMag); @@ -58,13 +59,12 @@ Bangle.on('HRM', onHrm); // Wait two seconds, that should be enough for each of the events to get raised once - setTimeout(() => { + setTimeout(() => { Bangle.removeAllListeners(); }, 2000); if (Bangle.isLCDOn()) enabledConsumers = enabledConsumers | switchableConsumers.lcd; - // Already added in the hope they will be available soon to get more details if (compassEventReceived) enabledConsumers = enabledConsumers | switchableConsumers.compass; if (gpsEventReceived) @@ -90,8 +90,7 @@ const logFileName = "bclog" + currentWriteDay; // Change log target on day change - if (!isNaN(previousWriteDay) - && previousWriteDay != currentWriteDay) { + if (!isNaN(previousWriteDay) && previousWriteDay != currentWriteDay) { //Remove a log file containing data from a week ago Storage.open(logFileName, "r").erase(); Storage.open(previousWriteLogName, "w").write(parseInt(currentWriteDay)); @@ -111,7 +110,7 @@ } function reload() { - WIDGETS["batchart"].width = 24; + WIDGETS.batchart.width = 24; recordingInterval = setInterval(logBatteryData, recordingInterval10Min); @@ -119,11 +118,12 @@ } // add the widget - WIDGETS["batchart"]={area:"tl",width:24,draw:draw,reload:function() { - reload(); - Bangle.drawWidgets(); // relayout all widgets - }}; + WIDGETS.batchart = { + area: "tl", width: 24, draw: draw, reload: function () { + reload(); + Bangle.drawWidgets(); + } + }; - // load settings, set correct widget width reload(); -})() \ No newline at end of file +})(); \ No newline at end of file From bb42044aa92f25f5375112194488c82ce76f0a37 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 10:25:13 +0100 Subject: [PATCH 024/101] Show elapsed time, and tweak stopwatch so lap times don't overlap the bottom widget area --- apps/swatch/interface.html | 3 ++- apps/swatch/stopwatch.js | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/apps/swatch/interface.html b/apps/swatch/interface.html index 928c5fe39..45391fb6e 100644 --- a/apps/swatch/interface.html +++ b/apps/swatch/interface.html @@ -17,11 +17,12 @@ function getLapTimes() {
\n`; lapData.forEach((lap,lapIndex) => { lap.date = lap.n.substr(7,16).replace("_"," "); + lap.elapsed = lap.d.shift(); // remove first item html += `
${lap.date}
-
${lap.d.length} Laps
+
${lap.d.length} Laps, total time ${lap.elapsed}
diff --git a/apps/swatch/stopwatch.js b/apps/swatch/stopwatch.js index 478c22619..659f0606d 100644 --- a/apps/swatch/stopwatch.js +++ b/apps/swatch/stopwatch.js @@ -27,10 +27,10 @@ function updateLabels() { g.setFont("6x8",1); g.setFontAlign(-1,-1); for (var i in lapTimes) { - if (i<16) + if (i<15) {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),35,timeY + 40 + i*8);} - else if (i<32) - {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-16)*8);} + else if (i<30) + {g.drawString(lapTimes.length-i+": "+timeToText(lapTimes[i]),125,timeY + 40 + (i-15)*8);} } drawsecs(); } @@ -92,12 +92,12 @@ setWatch(function() { // Start/stop updateLabels(); if (started) displayInterval = setInterval(function() { - var last = tCurrent; - if (started) tCurrent = Date.now(); - if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) - drawsecs(); - else - drawms(); + var last = tCurrent; + if (started) tCurrent = Date.now(); + if (Math.floor(last/1000)!=Math.floor(tCurrent/1000)) + drawsecs(); + else + drawms(); }, 20); }, BTN2, {repeat:true}); @@ -108,10 +108,10 @@ setWatch(function() { // Lap lapTimes.unshift(tCurrent-tStart); } if (!started) { // save - var timenow= Date(); var filename = "swatch-"+(new Date()).toISOString().substr(0,16).replace("T","_")+".json"; + if (tCurrent!=tStart) + lapTimes.unshift(tCurrent-tStart); // this maxes out the 28 char maximum - lapTimes.unshift(tCurrent-tStart); require("Storage").writeJSON(filename, getLapTimesArray()); tStart = tCurrent = tTotal = Date.now(); lapTimes = []; From de2dc3a2cc23010af7d1cdb454048401ece9cf33 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 11:26:57 +0200 Subject: [PATCH 025/101] Add readme and increment version --- apps.json | 3 +- apps/batchart/ChangeLog | 3 +- apps/batchart/README.md | 67 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 apps/batchart/README.md diff --git a/apps.json b/apps.json index 7449a233b..7985c6776 100644 --- a/apps.json +++ b/apps.json @@ -1178,7 +1178,8 @@ "name": "Battery Chart", "shortName":"Battery Chart", "icon": "app.png", - "version":"0.07", + "version":"0.08", + "readme": "README.md", "description": "A widget and an app for recording and visualizing battery percentage over time.", "tags": "app,widget,battery,time,record,chart,tool", "storage": [ diff --git a/apps/batchart/ChangeLog b/apps/batchart/ChangeLog index ba9e4e847..439d877be 100644 --- a/apps/batchart/ChangeLog +++ b/apps/batchart/ChangeLog @@ -4,4 +4,5 @@ 0.04: chart in the app is now active. 0.05: Display temperature and LCD state in chart 0.06: Fixes widget events and charting of component states -0.07: Improve logging and charting of component states and add widget icon \ No newline at end of file +0.07: Improve logging and charting of component states and add widget icon +0.08: Fix for Home button in the app and README added. \ No newline at end of file diff --git a/apps/batchart/README.md b/apps/batchart/README.md new file mode 100644 index 000000000..0ce2c646d --- /dev/null +++ b/apps/batchart/README.md @@ -0,0 +1,67 @@ +# Summary + +Battery Chart contains a widget that records the battery usage as well as information that might influence this usage. + +The app that comes with provides a graph that accumulates this information in a single screen. + +## How the widget works + +The widget records data in a fixed interval of ten minutes. + +When this timespan has passed, it saves the following information to a file called `bclogx` where `x` is + +the current day retrieved by `new Date().getDay()`: + +- Battery percentage +- Temperature (of the die) +- LCD state +- Compass state +- HRM state +- GPS state + +After seven days the logging rolls over and the previous data is overwritten. + +To properly handle the roll-over, the day of the previous logging operation is stored in `bcprvday`. + +The value is changed with the first recording operation of the new day. + +## How the App works + +### Events + +The app charts the last 144 (6/h * 24h) datapoints that have been recorded. + +If for the current day the 144 events have not been reached the list is padded with + +events from the previous `bclog` file(s). + +### Graph + +The graph then contains the battery percentage (left y-axis) and the temperature (right y-axis). + +In case the recorded temperature is outside the limits of the graph, the value is set to a minimum of 19 or a maximum of 41 and thus should be clearly visible outside of the graph's boundaries for the y-axis. + +The states of the various SoC devices are depicted below the graph. If at the time of recording the device was enabled a marker in the respective color is set, if not the pixels for this point in time stay black. + +If a device was not enabled during the 144 selected events, the name is not displayed. + +## File schema + +You can download the `bclog` files for your own analysis. They are `CSV` files without header rows and contain + +``` +timestamp,batteryPercentage,temperatureInDegreeC,deviceStates +``` + +with the `deviceStates` resembling a flag set consisting of + +``` +const switchableConsumers = { + none: 0, + lcd: 1, + compass: 2, + bluetooth: 4, + gps: 8, + hrm: 16 +}; +``` From a4ec9965ba5dae7768b20f25aadec9e6459411b4 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 10:31:59 +0100 Subject: [PATCH 026/101] Make widget play well with other Gadgetbridge widgets/apps --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + apps/gbridge/widget.js | 2 ++ 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e6fb7aaac..447d45154 100644 --- a/apps.json +++ b/apps.json @@ -93,7 +93,7 @@ { "id": "gbridge", "name": "Gadgetbridge", "icon": "app.png", - "version":"0.09", + "version":"0.10", "description": "The default notification handler for Gadgetbridge notifications from Android", "tags": "tool,system,android,widget", "type":"widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index 53f8a1b4c..f23a4eb6d 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -8,3 +8,4 @@ 0.07: Move configuration to settings menu 0.08: Don't turn on LCD at start of every song 0.09: Update Bluetooth connection state automatically +0.10: Make widget play well with other Gadgetbridge widgets/apps diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 03c622443..a87b9d1ec 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -145,6 +145,7 @@ } } + var _GB = global.GB; global.GB = (event) => { switch (event.t) { case "notify": @@ -160,6 +161,7 @@ handleCallEvent(event); break; } + if(_GB)setTimeout(_GB,0,event); }; // Touch control From eb4ac302ccd3464bd3d97b6f18b5fa635fcbe436 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 16 Apr 2020 11:33:36 +0100 Subject: [PATCH 027/101] Reduce memory usage further when running app settings page --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 447d45154..0adf7de0b 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.15", + "version":"0.16", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3d82be9c0..3acfb5fb0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -17,3 +17,4 @@ Move LCD Brightness menu into more general LCD menu 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) +0.16: Reduce memory usage further when running app settings page diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 9e343a68e..d0d88ce20 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -417,7 +417,7 @@ function showAppSettingsMenu() { '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.info$/) - .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?a:undefined}) + .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?{sortorder:a.sortorder,name:a.name,settings:a.settings}:undefined}) .filter(app => app) // filter out any undefined apps .sort((a, b) => a.sortorder - b.sortorder) if (apps.length === 0) { From 92c24e2cfc5f5d5f1b391b61a57674641c20becd Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Thu, 16 Apr 2020 12:35:43 +0200 Subject: [PATCH 028/101] Fix URLs in Webmanifest Signed-off-by: OmegaRogue --- site.webmanifest | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/site.webmanifest b/site.webmanifest index 0565f159c..0d1fb4679 100644 --- a/site.webmanifest +++ b/site.webmanifest @@ -17,6 +17,6 @@ "theme_color": "#5755d9", "background_color": "#5755d9", "display": "standalone", - "start_url": "https://omegavoid.codes/BangleApps", - "scope": "https://omegavoid.codes/BangleApps" + "start_url": "https://banglejs.com/apps/", + "scope": "https://banglejs.com/apps/" } From b02af77e514aa4bbcb41a8ab2039bb81762a1b03 Mon Sep 17 00:00:00 2001 From: OmegaRogue Date: Thu, 16 Apr 2020 12:48:35 +0200 Subject: [PATCH 029/101] Add Description, Remove add_to_apps.json Add Description Remove add_to_apps.json Signed-off-by: OmegaRogue --- apps.json | 4 ++-- apps/dane/ChangeLog | 3 ++- apps/dane/add_to_apps.json | 22 ---------------------- 3 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 apps/dane/add_to_apps.json diff --git a/apps.json b/apps.json index 91d2d249b..c29bf8018 100644 --- a/apps.json +++ b/apps.json @@ -1247,8 +1247,8 @@ "name": "Digital Assistant, not EDITH", "shortName": "DANE", "icon": "app.png", - "version": "0.06", - "description": "A detailed description of my great app", + "version": "0.07", + "description": "A Watchface inspired by Tony Stark's EDITH", "tags": "clock", "type": "clock", "allow_emulator": true, diff --git a/apps/dane/ChangeLog b/apps/dane/ChangeLog index 607d0adf5..419109ec1 100644 --- a/apps/dane/ChangeLog +++ b/apps/dane/ChangeLog @@ -1,4 +1,5 @@ 0.01: New App! 0.04: Added Icon to watchface 0.05: bugfix -0.06: moved and resized icon \ No newline at end of file +0.06: moved and resized icon +0.07: Added Description \ No newline at end of file diff --git a/apps/dane/add_to_apps.json b/apps/dane/add_to_apps.json deleted file mode 100644 index 6efb3ec85..000000000 --- a/apps/dane/add_to_apps.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "id": "dane", - "name": "Digital Assistant, not EDITH", - "shortName": "DANE", - "icon": "app.png", - "version": "0.06", - "description": "A detailed description of my great app", - "tags": "clock", - "type": "clock", - "allow_emulator": true, - "storage": [ - { - "name": "dane.app.js", - "url": "app.js" - }, - { - "name": "dane.img", - "url": "app-icon.js", - "evaluate": true - } - ] -} \ No newline at end of file From 217d19815456966c0fd268e31153d6bf8ac57e63 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 12 Apr 2020 00:26:08 +0200 Subject: [PATCH 030/101] Add a "data" section to apps.json, with data files to clean on uninstall These are added to `appid.info` as "dataFiles" or "storageFiles", and can contain wildcards. --- README.md | 25 ++++++++++++++++++++----- bin/sanitycheck.js | 33 +++++++++++++++++++++++++++++++++ js/appinfo.js | 13 +++++++++++++ js/comms.js | 24 +++++++++++++++++++++--- js/index.js | 13 +++++++++++++ js/utils.js | 12 ++++++++++++ 6 files changed, 112 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ca874ad2f..7a96ad335 100644 --- a/README.md +++ b/README.md @@ -202,6 +202,13 @@ and which gives information about the app for the Launcher. "files:"file1,file2,file3", // added by BangleApps loader on upload - lists all files // that belong to the app so it can be deleted + "dataFiles":"appid.data.json,appid.data?.json" + // added by BangleApps loader on upload - lists files that + // the app might write, so they can be deleted on uninstall + // typically these files are not uploaded, but created by the app + // these can include '*' or '?' wildcards + "storageFiles":" + // same as "dataFiles", except the app handles these as storageFile } ``` @@ -240,16 +247,27 @@ and which gives information about the app for the Launcher. "evaluate":true // if supplied, data isn't quoted into a String before upload // (eg it's evaluated as JS) }, + ] + "data": [ // list of files the app writes to + {"name":"appid.data.json", // filename used in storage + "storageFile":true // if supplied, file is treated as storageFile + }, + {"wildcard":"appid.data.*" // wildcard of filenames used in storage + }, // this is mutually exclusive with using "name" + ], "sortorder" : 0, // optional - choose where in the list this goes. // this should only really be used to put system // stuff at the top - ] } ``` * name, icon and description present the app in the app loader. * tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher` or empty. * storage is used to identify the app files and how to handle them +* data is used to clean up files when the app is uninstalled + (If the app has settings but no data section, it is assumed settings are + stored in `appid.settings.json`, so there is no need to add a data section + containing only that file) ### `apps.json`: `custom` element @@ -351,19 +369,16 @@ Example `settings.js` E.showMenu(appMenu) }) ``` -In this example the app needs to add both `app.settings.js` and -`app.settings.json` to `apps.json`: +In this example the app needs to add `app.settings.js` to `apps.json`: ```json { "id": "app", ... "storage": [ ... {"name":"app.settings.js","url":"settings.js"}, - {"name":"app.settings.json","content":"{}"} ] }, ``` -That way removing the app also cleans up `app.settings.json`. ## Coding hints diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 62b111ae0..fdf15a26b 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -74,6 +74,8 @@ apps.forEach((app,appIdx) => { var fileNames = []; app.storage.forEach((file) => { if (!file.name) ERROR(`App ${app.id} has a file with no name`); + if (file.name.includes('?') || file.name.includes('*')) + ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); if (fileNames.includes(file.name)) ERROR(`App ${app.id} file ${file.name} is a duplicate`); fileNames.push(file.name); @@ -115,6 +117,37 @@ apps.forEach((app,appIdx) => { if (!STORAGE_KEYS.includes(key)) ERROR(`App ${app.id}'s ${file.name} has unknown key ${key}`); } }); + let dataNames = []; + (app.data||[]).forEach((data)=>{ + if (!data.name && !data.wildcard) ERROR(`App ${app.id} has a data file with no name`); + if (dataNames.includes(data.name||data.wildcard)) + ERROR(`App ${app.id} data file ${data.name||data.wildcard} is a duplicate`); + dataNames.push(data.name||data.wildcard) + if ('name' in data && 'wildcard' in data) + ERROR(`App ${app.id} data file ${data.name} has both name and wildcard`); + if (data.name) { + if (data.name.includes('?') || data.name.includes('*')) + ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); + } + if (data.wildcard) { + if (!data.wildcard.includes('?') && !data.wildcard.includes('*')) + ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not actually contains wildcard`); + if (data.wildcard.replace(/\?|\*/g,'') === '') + ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not contain regular characters`); + else if (data.wildcard.replace(/\?|\*/g,'').length < 3) + WARN(`App ${app.id} data file wildcard ${data.wildcard} is very broad`); + else if (!data.wildcard.includes(app.id)) + WARN(`App ${app.id} data file wildcard ${data.wildcard} does not include app ID`); + } + if ('storageFile' in data && typeof data.storageFile !== 'boolean') + ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); + for (const key in data) { + if (!['name','wildcard','storageFile'].includes(key)) + ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); + } + }); + if (fileNames.includes(app.id+".settings.js") && dataNames.length===1 && dataNames[0] === app.id+'.settings.json') + WARN(`App ${app.id} has settings, so does not need to declare data file ${app.id+'.settings.json'}`) //console.log(fileNames); if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`); if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`); diff --git a/js/appinfo.js b/js/appinfo.js index f4ab498b1..04c5da893 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,6 +69,19 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); + let dataFileList = [], storageFileList = []; + if ('data' in app) { + // add "data" files to appropriate list + app.data.forEach(d=>{ + if (d.storageFile) storageFileList.push(d.name||d.wildcard) + else dataFileList.push(d.name||d.wildcard) + }) + } else if (json.settings) { + // settings but no data files: assume app uses .settings.json file + dataFileList.push(app.id + '.settings.json') + } + if (dataFileList.length) json.dataFiles = dataFileList.join(","); + if (storageFileList.length) json.storageFiles = storageFileList.join(","); fileContents.push({ name : appJSONName, content : JSON.stringify(json) diff --git a/js/comms.js b/js/comms.js index 1f840ada7..1e8250305 100644 --- a/js/comms.js +++ b/js/comms.js @@ -94,10 +94,28 @@ getInstalledApps : () => { }); }, removeApp : app => { // expects an appid.info structure (i.e. with `files`) - if (app.files === '') return Promise.resolve(); // nothing to erase + if (!app.files && !app.dataFiles && !app.storageFiles) return Promise.resolve(); // nothing to erase Progress.show({title:`Removing ${app.name}`,sticky:true}); - var cmds = app.files.split(',').map(file=>{ - return `\x10require("Storage").erase(${toJS(file)});\n`; + let cmds = '\x10const s=require("Storage");\n'; + // remove App files (regular files, exact names only) + cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); + // remove Data files (regular files, can use wildcards) + cmds += (app.dataFiles||[]).split(',').map(file => { + const isGlob = (file.includes('*') || file.includes('?')) + if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; + const regex = new RegExp(globToRegex(file)) + return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; + }).join(""); + // remove Storage files (storageFiles, can use wildcards) + cmds += (app.storageFiles||[]).split(',').map(file => { + const isGlob = (file.includes('*') || file.includes('?')) + if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; + // storageFiles have a chunk number appended to their real name + const regex = globToRegex(file+'\u0001') + // open() doesn't want the chunk number though + let cmd = `\x10s.list(${regex}).forEach(f=>s.open(f.substring(0,f.length-1),'r').erase());\n` + // using a literal \u0001 char fails (not sure why), so escape it + return cmd.replace('\u0001', '\\x01') }).join(""); console.log("removeApp", cmds); return Comms.reset().then(new Promise((resolve,reject) => { diff --git a/js/index.js b/js/index.js index ef9bcb4f1..c48920315 100644 --- a/js/index.js +++ b/js/index.js @@ -349,6 +349,19 @@ function updateApp(app) { .filter(f => f !== app.id + '.info') .filter(f => !app.storage.some(s => s.name === f)) .join(','); + let dataFiles = (remove.dataFiles||'').split(','), + storageFiles = (remove.storageFiles||'').split(',') + if ('data' in app) { + // keep declared (in new version) data files + dataFiles = dataFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) + storageFiles = storageFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) + } + else if (remove.settings || app.settings) { + // app with settings but no data files declared: keep .settings.json + dataFiles = dataFiles.filter(f => f !== (app.id + '.settings.json')) + } + if (dataFiles.length) remove.dataFiles = dataFiles.join(','); + if (storageFiles.length) remove.storageFiles = storageFiles.join(',') return Comms.removeApp(remove); }).then(()=>{ showToast(`Updating ${app.name}...`); diff --git a/js/utils.js b/js/utils.js index d8c1b8063..50d319338 100644 --- a/js/utils.js +++ b/js/utils.js @@ -8,6 +8,18 @@ function escapeHtml(text) { }; return text.replace(/[&<>"']/g, function(m) { return map[m]; }); } +// simple glob to regex conversion, only supports "*" and "?" wildcards +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} function htmlToArray(collection) { return [].slice.call(collection); } From 9e0fd91339dc48acd38c4c0687000f199ddb5c23 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 15 Apr 2020 21:30:44 +0200 Subject: [PATCH 031/101] Data files: save all data files as a single string Separate regular and storage files by a semicolon --- README.md | 4 +--- bin/sanitycheck.js | 5 +++-- js/appinfo.js | 39 ++++++++++++++++++++++++++++++++------- js/comms.js | 14 ++++++++------ js/index.js | 18 ++++++++---------- 5 files changed, 52 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 7a96ad335..a04ee95b2 100644 --- a/README.md +++ b/README.md @@ -202,13 +202,11 @@ and which gives information about the app for the Launcher. "files:"file1,file2,file3", // added by BangleApps loader on upload - lists all files // that belong to the app so it can be deleted - "dataFiles":"appid.data.json,appid.data?.json" + "data":"appid.data.json,appid.data?.json;appidStorageFile,appidStorageFile*" // added by BangleApps loader on upload - lists files that // the app might write, so they can be deleted on uninstall // typically these files are not uploaded, but created by the app // these can include '*' or '?' wildcards - "storageFiles":" - // same as "dataFiles", except the app handles these as storageFile } ``` diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index fdf15a26b..197ebf57e 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -39,9 +39,10 @@ try{ const APP_KEYS = [ 'id', 'name', 'shortName', 'version', 'icon', 'description', 'tags', 'type', - 'sortorder', 'readme', 'custom', 'interface', 'storage', 'allow_emulator', + 'sortorder', 'readme', 'custom', 'interface', 'storage', 'data', 'allow_emulator', ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate']; +const DATA_KEYS = ['name', 'wildcard', 'storageFile']; apps.forEach((app,appIdx) => { if (!app.id) ERROR(`App ${appIdx} has no id`); @@ -142,7 +143,7 @@ apps.forEach((app,appIdx) => { if ('storageFile' in data && typeof data.storageFile !== 'boolean') ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); for (const key in data) { - if (!['name','wildcard','storageFile'].includes(key)) + if (!DATA_KEYS.includes(key)) ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); } }); diff --git a/js/appinfo.js b/js/appinfo.js index 04c5da893..413098bc4 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,26 +69,51 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); - let dataFileList = [], storageFileList = []; + let data = {dataFiles: [], storageFiles: []}; if ('data' in app) { // add "data" files to appropriate list app.data.forEach(d=>{ - if (d.storageFile) storageFileList.push(d.name||d.wildcard) - else dataFileList.push(d.name||d.wildcard) + if (d.storageFile) data.storageFiles.push(d.name||d.wildcard) + else data.dataFiles.push(d.name||d.wildcard) }) } else if (json.settings) { // settings but no data files: assume app uses .settings.json file - dataFileList.push(app.id + '.settings.json') + data.dataFiles.push(app.id + '.settings.json') } - if (dataFileList.length) json.dataFiles = dataFileList.join(","); - if (storageFileList.length) json.storageFiles = storageFileList.join(","); + const dataString = AppInfo.makeDataString(data) + if (dataString) json.data = dataString fileContents.push({ name : appJSONName, content : JSON.stringify(json) }); resolve(fileContents); }); - } + }, + // (.info).data holds filenames of data: both regular and storageFiles + // These are stored as: (note comma vs semicolons) + // "fil1,file2", "file1,file2;storageFileA,storageFileB" or ";storageFileA" + /** + * Convert appid.info "data" to object with file names/patterns + * Passing in undefined works + * @param data "data" as stored in appid.info + * @returns {{storageFiles:[], dataFiles:[]}} + */ + parseDataString(data) { + data = data || ''; + let [files = [], storage = []] = data.split(';').map(d => d.split(',')) + return {dataFiles: files, storageFiles: storage} + }, + /** + * Convert object with file names/patterns to appid.info "data" string + * Passing in an incomplete object will not work + * @param data {{storageFiles:[], dataFiles:[]}} + * @returns {string} "data" to store in appid.info + */ + makeDataString(data) { + if (!data.dataFiles.length && !data.storageFiles.length) { return '' } + if (!data.storageFiles.length) { return data.dataFiles.join(',') } + return [data.dataFiles.join(','),data.storageFiles.join(',')].join(';') + }, }; if ("undefined"!=typeof module) diff --git a/js/comms.js b/js/comms.js index 1e8250305..736a2b7c7 100644 --- a/js/comms.js +++ b/js/comms.js @@ -94,20 +94,22 @@ getInstalledApps : () => { }); }, removeApp : app => { // expects an appid.info structure (i.e. with `files`) - if (!app.files && !app.dataFiles && !app.storageFiles) return Promise.resolve(); // nothing to erase + if (!app.files && !app.data) return Promise.resolve(); // nothing to erase Progress.show({title:`Removing ${app.name}`,sticky:true}); let cmds = '\x10const s=require("Storage");\n'; - // remove App files (regular files, exact names only) + // remove App files: regular files, exact names only cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); - // remove Data files (regular files, can use wildcards) - cmds += (app.dataFiles||[]).split(',').map(file => { + // remove app Data: (dataFiles and storageFiles) + const data = AppInfo.parseDataString(app.data) + // regular files, can use wildcards + cmds += data.dataFiles.map(file => { const isGlob = (file.includes('*') || file.includes('?')) if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; const regex = new RegExp(globToRegex(file)) return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; }).join(""); - // remove Storage files (storageFiles, can use wildcards) - cmds += (app.storageFiles||[]).split(',').map(file => { + // storageFiles, can use wildcards + cmds += data.storageFiles.map(file => { const isGlob = (file.includes('*') || file.includes('?')) if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; // storageFiles have a chunk number appended to their real name diff --git a/js/index.js b/js/index.js index c48920315..41a43730e 100644 --- a/js/index.js +++ b/js/index.js @@ -349,19 +349,17 @@ function updateApp(app) { .filter(f => f !== app.id + '.info') .filter(f => !app.storage.some(s => s.name === f)) .join(','); - let dataFiles = (remove.dataFiles||'').split(','), - storageFiles = (remove.storageFiles||'').split(',') + let data = AppInfo.parseDataString(remove.data) if ('data' in app) { - // keep declared (in new version) data files - dataFiles = dataFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) - storageFiles = storageFiles.filter(f => app.data.some(d => (d.name||d.wildcard) === f)) - } - else if (remove.settings || app.settings) { + // only remove data files which are no longer declared in new app version + const removeData = (f) => !app.data.some(d => (d.name || d.wildcard)===f) + data.dataFiles = data.dataFiles.filter(removeData) + data.storageFiles = data.storageFiles.filter(removeData) + } else if (remove.settings || app.settings) { // app with settings but no data files declared: keep .settings.json - dataFiles = dataFiles.filter(f => f !== (app.id + '.settings.json')) + data.dataFiles = data.dataFiles.filter(f => f!==(app.id+'.settings.json')) } - if (dataFiles.length) remove.dataFiles = dataFiles.join(','); - if (storageFiles.length) remove.storageFiles = storageFiles.join(',') + remove.data = AppInfo.makeDataString(data) return Comms.removeApp(remove); }).then(()=>{ showToast(`Updating ${app.name}...`); From 3e5cfcdc12cdaadbf5f761ea2883905ca8ad4583 Mon Sep 17 00:00:00 2001 From: msdeibel Date: Thu, 16 Apr 2020 14:32:42 +0200 Subject: [PATCH 032/101] Fixed home button and added readme for WOHRM --- apps.json | 1 + apps/wohrm/ChangeLog | 1 + apps/wohrm/README.md | 29 +++++++++++++++++++++++++++++ apps/wohrm/app.js | 7 ++----- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 apps/wohrm/README.md diff --git a/apps.json b/apps.json index 899eed03e..459ecb3ab 100644 --- a/apps.json +++ b/apps.json @@ -891,6 +891,7 @@ "name": "Workout HRM", "icon": "app.png", "version":"0.06", + "readme": "README.md", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index f5c64dbee..53c451bcd 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -4,3 +4,4 @@ 0.04: Only buzz on high confidence (>85%) 0.05: Improved buzz timing and rendering 0.06: Removed debug outputs, fixed rendering for upper limit, improved rendering for +/- icons, changelog version order fixed +0.07: Home button fixed and README added \ No newline at end of file diff --git a/apps/wohrm/README.md b/apps/wohrm/README.md new file mode 100644 index 000000000..ad9e82525 --- /dev/null +++ b/apps/wohrm/README.md @@ -0,0 +1,29 @@ +# Summary +Workout heart rate monitor that buzzes when your heart rate hits the limits. + +This app is for the [Bangle.js watch](https://banglejs.com/). While active it monitors your heart rate +and will notify you with a buzz whenever your heart rate falls below or jumps above the set limits. + +# How it works +[Try it out](https://www.espruino.com/ide/emulator.html?codeurl=https://raw.githubusercontent.com/msdeibel/BangleApps/master/apps/wohrm/app.js&upload) using the [online Espruino emulator](https://www.espruino.com/ide/emulator.html). + +## Setting the limits +For setting the lower limit press button 4 (left part of the watch's touch screen). +Then adjust the value with the buttons 1 (top) and 3 (bottom) of the watch. + +For setting the upper limit act accordingly after pressing button 5 (the right part of the watch's screen). + +## Reading Reliability +As per the specs of the watch the HR monitor is not 100% reliable all the time. +That's why the WOHRM displays a confidence value for each reading of the current heart rate. + +To the left and right of the "Current" value two colored bars indicate the confidence in +the received value: For 85% and above the bars are green, between 84% and 50% the bars are yellow +and below 50% they turn red. + +## Closing the app +Pressing button 2 (middle) will switch off the HRM of the watch and return you to the launcher. + +# HRM usage +The HRM is switched on when the app is started. It stays switch on while the app is running, even +when the watch screen goes to stand-by. diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 7e0af4219..b3ce8acc8 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -287,13 +287,11 @@ function resetHighlightTimeout() { setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); } -// Show launcher when middle button pressed function switchOffApp(){ Bangle.setHRMPower(0); Bangle.showLauncher(); } -// special function to handle display switch on Bangle.on('lcdPower', (on) => { g.clear(); if (on) { @@ -312,19 +310,18 @@ Bangle.setHRMPower(1); Bangle.on('HRM', onHrm); setWatch(incrementLimit, BTN1, {edge:"rising", debounce:50, repeat:true}); -setWatch(switchOffApp, BTN2, {edge:"rising", debounce:50, repeat:true}); setWatch(decrementLimit, BTN3, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToLower, BTN4, {edge:"rising", debounce:50, repeat:true}); setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); +setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -//drawTrainingHeartRate(); renderHomeIcon(); renderLowerLimitBackground(); renderUpperLimitBackground(); -// refesh every sec setInterval(drawTrainingHeartRate, 1000); From 9f0adf190019b5dd0bcef5f713c34dabd8ca1c3d Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Thu, 16 Apr 2020 17:06:25 +0200 Subject: [PATCH 033/101] Data files: remove settings magic, some more sanitychecks --- README.md | 13 +++++---- bin/sanitycheck.js | 69 ++++++++++++++++++++++++++++++++++++++++------ js/appinfo.js | 9 ++---- js/comms.js | 7 ++--- js/index.js | 3 -- 5 files changed, 73 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index a04ee95b2..a45647daf 100644 --- a/README.md +++ b/README.md @@ -263,9 +263,6 @@ and which gives information about the app for the Launcher. * tags is used for grouping apps in the library, separate multiple entries by comma. Known tags are `tool`, `system`, `clock`, `game`, `sound`, `gps`, `widget`, `launcher` or empty. * storage is used to identify the app files and how to handle them * data is used to clean up files when the app is uninstalled - (If the app has settings but no data section, it is assumed settings are - stored in `appid.settings.json`, so there is no need to add a data section - containing only that file) ### `apps.json`: `custom` element @@ -351,10 +348,10 @@ Example `settings.js` ```js // make sure to enclose the function in parentheses (function(back) { - let settings = require('Storage').readJSON('app.settings.json',1)||{}; + let settings = require('Storage').readJSON('app.json',1)||{}; function save(key, value) { settings[key] = value; - require('Storage').write('app.settings.json',settings); + require('Storage').write('app.json',settings); } const appMenu = { '': {'title': 'App Settings'}, @@ -367,13 +364,17 @@ Example `settings.js` E.showMenu(appMenu) }) ``` -In this example the app needs to add `app.settings.js` to `apps.json`: +In this example the app needs to add `app.settings.js` to `storage` in `apps.json`. +It should also add `app.json` to `data`, to make sure it is cleaned up when the app is uninstalled. ```json { "id": "app", ... "storage": [ ... {"name":"app.settings.js","url":"settings.js"}, + ], + "data": [ + {"name":"app.json"} ] }, ``` diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 197ebf57e..51230f6fa 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -43,7 +43,22 @@ const APP_KEYS = [ ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate']; const DATA_KEYS = ['name', 'wildcard', 'storageFile']; +const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} +const isGlob = f => /[?*]/.test(f) +// All storage+data files in all apps: {app:,[file: | data:]} +let allFiles = []; apps.forEach((app,appIdx) => { if (!app.id) ERROR(`App ${appIdx} has no id`); //console.log(`Checking ${app.id}...`); @@ -75,11 +90,13 @@ apps.forEach((app,appIdx) => { var fileNames = []; app.storage.forEach((file) => { if (!file.name) ERROR(`App ${app.id} has a file with no name`); - if (file.name.includes('?') || file.name.includes('*')) - ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); + if (isGlob(file.name)) ERROR(`App ${app.id} storage file ${file.name} contains wildcards`); + let char = file.name.match(FORBIDDEN_FILE_NAME_CHARS) + if (char) ERROR(`App ${app.id} storage file ${file.name} contains invalid character "${char[0]}"`) if (fileNames.includes(file.name)) ERROR(`App ${app.id} file ${file.name} is a duplicate`); fileNames.push(file.name); + allFiles.push({app: app.id, file: file.name}); if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`); if (!file.url && !file.content && !app.custom) ERROR(`App ${app.id} file ${file.name} has no contents`); var fileContents = ""; @@ -124,14 +141,13 @@ apps.forEach((app,appIdx) => { if (dataNames.includes(data.name||data.wildcard)) ERROR(`App ${app.id} data file ${data.name||data.wildcard} is a duplicate`); dataNames.push(data.name||data.wildcard) + allFiles.push({app: app.id, data: (data.name||data.wildcard)}); if ('name' in data && 'wildcard' in data) ERROR(`App ${app.id} data file ${data.name} has both name and wildcard`); - if (data.name) { - if (data.name.includes('?') || data.name.includes('*')) - ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); - } + if (isGlob(data.name)) + ERROR(`App ${app.id} data file name ${data.name} contains wildcards`); if (data.wildcard) { - if (!data.wildcard.includes('?') && !data.wildcard.includes('*')) + if (!isGlob(data.wildcard)) ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not actually contains wildcard`); if (data.wildcard.replace(/\?|\*/g,'') === '') ERROR(`App ${app.id} data file wildcard ${data.wildcard} does not contain regular characters`); @@ -140,6 +156,8 @@ apps.forEach((app,appIdx) => { else if (!data.wildcard.includes(app.id)) WARN(`App ${app.id} data file wildcard ${data.wildcard} does not include app ID`); } + let char = (data.name||data.wildcard).match(FORBIDDEN_FILE_NAME_CHARS) + if (char) ERROR(`App ${app.id} data file ${data.name||data.wildcard} contains invalid character "${char[0]}"`) if ('storageFile' in data && typeof data.storageFile !== 'boolean') ERROR(`App ${app.id} data file ${data.name||data.wildcard} has non-boolean value for "storageFile"`); for (const key in data) { @@ -147,8 +165,24 @@ apps.forEach((app,appIdx) => { ERROR(`App ${app.id} data file ${data.name||data.wildcard} has unknown property "${key}"`); } }); - if (fileNames.includes(app.id+".settings.js") && dataNames.length===1 && dataNames[0] === app.id+'.settings.json') - WARN(`App ${app.id} has settings, so does not need to declare data file ${app.id+'.settings.json'}`) + // prefer "appid.json" over "appid.settings.json" (TODO: change to ERROR once all apps comply?) + if (dataNames.includes(app.id+".settings.json") && !dataNames.includes(app.id+".json")) + WARN(`App ${app.id} uses data file ${app.id+'.settings.json'} instead of ${app.id+'.json'}`) + // settings files should be listed under data, not storage (TODO: change to ERROR once all apps comply?) + if (fileNames.includes(app.id+".settings.json")) + WARN(`App ${app.id} uses storage file ${app.id+'.settings.json'} instead of data file`) + if (fileNames.includes(app.id+".json")) + WARN(`App ${app.id} uses storage file ${app.id+'.json'} instead of data file`) + // warn if storage file matches data file of same app + dataNames.forEach(dataName=>{ + const glob = globToRegex(dataName) + fileNames.forEach(fileName=>{ + if (glob.test(fileName)) { + if (isGlob(dataName)) WARN(`App ${app.id} storage file ${fileName} matches data wildcard ${dataName}`) + else WARN(`App ${app.id} storage file ${fileName} is also listed in data`) + } + }) + }) //console.log(fileNames); if (isApp && !fileNames.includes(app.id+".app.js")) ERROR(`App ${app.id} has no entrypoint`); if (isApp && !fileNames.includes(app.id+".img")) ERROR(`App ${app.id} has no JS icon`); @@ -157,3 +191,20 @@ apps.forEach((app,appIdx) => { if (!APP_KEYS.includes(key)) ERROR(`App ${app.id} has unknown key ${key}`); } }); +// Do not allow files from different apps to collide +let fileA +while(fileA=allFiles.pop()) { + const nameA = (fileA.file||fileA.data), + globA = globToRegex(nameA), + typeA = fileA.file?'storage':'data' + allFiles.forEach(fileB => { + const nameB = (fileB.file||fileB.data), + globB = globToRegex(nameB), + typeB = fileB.file?'storage':'data' + if (globA.test(nameB)||globB.test(nameA)) { + if (isGlob(nameA)||isGlob(nameB)) + ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`) + else ERROR(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) + } + }) +} diff --git a/js/appinfo.js b/js/appinfo.js index 413098bc4..56b6ff2f8 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -69,19 +69,16 @@ var AppInfo = { var fileList = fileContents.map(storageFile=>storageFile.name); fileList.unshift(appJSONName); // do we want this? makes life easier! json.files = fileList.join(","); - let data = {dataFiles: [], storageFiles: []}; if ('data' in app) { + let data = {dataFiles: [], storageFiles: []}; // add "data" files to appropriate list app.data.forEach(d=>{ if (d.storageFile) data.storageFiles.push(d.name||d.wildcard) else data.dataFiles.push(d.name||d.wildcard) }) - } else if (json.settings) { - // settings but no data files: assume app uses .settings.json file - data.dataFiles.push(app.id + '.settings.json') + const dataString = AppInfo.makeDataString(data) + if (dataString) json.data = dataString } - const dataString = AppInfo.makeDataString(data) - if (dataString) json.data = dataString fileContents.push({ name : appJSONName, content : JSON.stringify(json) diff --git a/js/comms.js b/js/comms.js index 736a2b7c7..b825a06ad 100644 --- a/js/comms.js +++ b/js/comms.js @@ -101,17 +101,16 @@ removeApp : app => { // expects an appid.info structure (i.e. with `files`) cmds += app.files.split(',').map(file => `\x10s.erase(${toJS(file)});\n`).join(""); // remove app Data: (dataFiles and storageFiles) const data = AppInfo.parseDataString(app.data) + const isGlob = f => /[?*]/.test(f) // regular files, can use wildcards cmds += data.dataFiles.map(file => { - const isGlob = (file.includes('*') || file.includes('?')) - if (!isGlob) return `\x10s.erase(${toJS(file)});\n`; + if (!isGlob(file)) return `\x10s.erase(${toJS(file)});\n`; const regex = new RegExp(globToRegex(file)) return `\x10s.list(${regex}).forEach(f=>s.erase(f));\n`; }).join(""); // storageFiles, can use wildcards cmds += data.storageFiles.map(file => { - const isGlob = (file.includes('*') || file.includes('?')) - if (!isGlob) return `\x10s.open(${toJS(file)},'r').erase();\n`; + if (!isGlob(file)) return `\x10s.open(${toJS(file)},'r').erase();\n`; // storageFiles have a chunk number appended to their real name const regex = globToRegex(file+'\u0001') // open() doesn't want the chunk number though diff --git a/js/index.js b/js/index.js index 41a43730e..483dc09c7 100644 --- a/js/index.js +++ b/js/index.js @@ -355,9 +355,6 @@ function updateApp(app) { const removeData = (f) => !app.data.some(d => (d.name || d.wildcard)===f) data.dataFiles = data.dataFiles.filter(removeData) data.storageFiles = data.storageFiles.filter(removeData) - } else if (remove.settings || app.settings) { - // app with settings but no data files declared: keep .settings.json - data.dataFiles = data.dataFiles.filter(f => f!==(app.id+'.settings.json')) } remove.data = AppInfo.makeDataString(data) return Comms.removeApp(remove); From 372f5123f4fe611284d0f6f5fc5a09d30a585ae8 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 15:55:41 +0200 Subject: [PATCH 034/101] chronowid 0.02 --- apps/chronowid/ChangeLog | 3 ++- apps/chronowid/README.md | 9 ++++++--- apps/chronowid/app.js | 11 +++++++++-- apps/chronowid/widget.js | 18 +++++++++--------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/apps/chronowid/ChangeLog b/apps/chronowid/ChangeLog index a6f342f01..263145407 100644 --- a/apps/chronowid/ChangeLog +++ b/apps/chronowid/ChangeLog @@ -1 +1,2 @@ -0.01: New widget and app! +0.01: New widget and app! +0.02: Setting to reset values, timer buzzes at 00:00 and not later (see readme) \ No newline at end of file diff --git a/apps/chronowid/README.md b/apps/chronowid/README.md index f31c24c7b..f422dd956 100644 --- a/apps/chronowid/README.md +++ b/apps/chronowid/README.md @@ -5,6 +5,8 @@ The advantage is, that you can still see your normal watchface and other widgets The widget is always active, but only shown when the timer is on. Hours, minutes, seconds and timer status can be set with an app. +Depending on when you start the timer, it may alert up to 0,999 seconds early. This is because it checks only for full seconds. When there is less than one seconds left, it buzzes. This cannot be avoided without checking more than every second, which I would like to avoid. + ## Screenshots TBD @@ -18,18 +20,19 @@ TBD There are no settings section in the settings app, timer can be set using an app. +* Reset values: Reset hours, minutes, seconds to 0; set timer on to false; write to settings file * Hours: Set the hours for the timer * Minutes: Set the minutes for the timer * Seconds: Set the seconds for the timer -* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app. The widget is always there, but only visible when timer is on. +* Timer on: Starts the timer and displays the widget when set to 'On'. You have to leave the app to load the widget which starts the timer. The widget is always there, but only visible when timer is on. ## Releases -* Offifical app loader: Not yet published. +* Offifical app loader: https://github.com/espruino/BangleApps/tree/master/apps/chronowid (https://banglejs.com/apps/) * Forked app loader: https://github.com/Purple-Tentacle/BangleApps/tree/master/apps/chronowid (https://purple-tentacle.github.io/BangleApps/index.html#) * Development: https://github.com/Purple-Tentacle/BangleAppsDev/tree/master/apps/chronowid ## Requests -If you have any feature requests, please contact me on the Espruino forum: http://forum.espruino.com/profiles/155005/ \ No newline at end of file +If you have any feature requests, please write here: http://forum.espruino.com/conversations/345972/ \ No newline at end of file diff --git a/apps/chronowid/app.js b/apps/chronowid/app.js index 48401a7bb..dd9531233 100644 --- a/apps/chronowid/app.js +++ b/apps/chronowid/app.js @@ -30,7 +30,6 @@ settingsChronowid = storage.readJSON('chronowid.json',1); if (!settingsChronowid) resetSettings(); E.on('kill', () => { - print("-KILL-"); updateSettings(); }); @@ -45,6 +44,14 @@ function showMenu() { timerMenu.started.value = settingsChronowid.started; } }, + 'Reset values': function() { + settingsChronowid.hours = 0; + settingsChronowid.minutes = 0; + settingsChronowid.seconds = 0; + settingsChronowid.started = false; + updateSettings(); + showMenu(); + }, 'Hours': { value: settingsChronowid.hours, min: 0, @@ -88,4 +95,4 @@ function showMenu() { return E.showMenu(timerMenu); } -showMenu(); +showMenu(); \ No newline at end of file diff --git a/apps/chronowid/widget.js b/apps/chronowid/widget.js index 708bc6345..557104d92 100644 --- a/apps/chronowid/widget.js +++ b/apps/chronowid/widget.js @@ -36,19 +36,18 @@ //counts down, calculates and displays function countDown() { - //printDebug(); now = new Date(); diff = settingsChronowid.goal - now; //calculate difference WIDGETS["chronowid"].draw(); //time is up - if (settingsChronowid.started && diff <= 0) { + if (settingsChronowid.started && diff < 1000) { Bangle.buzz(1500); //write timer off to file settingsChronowid.started = false; storage.writeJSON('chronowid.json', settingsChronowid); clearInterval(interval); //stop interval - //printDebug(); } + //printDebug(); } // draw your widget @@ -72,12 +71,13 @@ g.drawString(getTime(diff), this.x+1, this.y+((height/2)-4)); //display hour 00:00:00 } } - else { - width = 58; - g.clearRect(this.x,this.y,this.x+width,this.y+height); - g.setFont("6x8", 2); - g.drawString("END", this.x+15, this.y+5); - } + // not needed anymoe, because we check if diff < 1000 now, so 00:00 is displayed. + // else { + // width = 58; + // g.clearRect(this.x,this.y,this.x+width,this.y+height); + // g.setFont("6x8", 2); + // g.drawString("END", this.x+15, this.y+5); + // } } if (settingsChronowid.started) interval = setInterval(countDown, 1000); //start countdown each second From dcb2a6c2d9b4f327796a3aaec53a43e33e4d715d Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 15:56:55 +0200 Subject: [PATCH 035/101] chronowid 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 447d45154..e2b20cca4 100644 --- a/apps.json +++ b/apps.json @@ -1142,7 +1142,7 @@ "name": "Chrono Widget", "shortName":"Chrono Widget", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Chronometer (timer) which runs as widget.", "tags": "tools,widget", "readme": "README.md", From 9a664ecae4b9b64a7f9e773ff43adbd62c0ab3fa Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:38:33 +0200 Subject: [PATCH 036/101] Compass: 0.02 --- apps/compass/ChangeLog | 2 ++ apps/compass/compass.js | 77 +++++++++++++++++++++++------------------ 2 files changed, 45 insertions(+), 34 deletions(-) create mode 100644 apps/compass/ChangeLog diff --git a/apps/compass/ChangeLog b/apps/compass/ChangeLog new file mode 100644 index 000000000..efd778c72 --- /dev/null +++ b/apps/compass/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Show text if uncalibrated \ No newline at end of file diff --git a/apps/compass/compass.js b/apps/compass/compass.js index 10895e3cd..a014d79ff 100644 --- a/apps/compass/compass.js +++ b/apps/compass/compass.js @@ -1,34 +1,43 @@ -g.clear(); -g.setColor(0,0.5,1); -g.fillCircle(120,130,80,80); -g.setColor(0,0,0); -g.fillCircle(120,130,70,70); - -function arrow(r,c) { - r=r*Math.PI/180; - var p = Math.PI/2; - g.setColor(c); - g.fillPoly([ - 120+60*Math.sin(r), 130-60*Math.cos(r), - 120+10*Math.sin(r+p), 130-10*Math.cos(r+p), - 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p), - ]); -} - -var oldHeading = 0; -Bangle.on('mag', function(m) { - if (!Bangle.isLCDOn()) return; - g.setFont("6x8",3); - g.setColor(0); - g.fillRect(70,0,170,24); - g.setColor(0xffff); - g.setFontAlign(0,0); - g.drawString(isNaN(m.heading)?"---":Math.round(m.heading),120,12); - g.setColor(0,0,0); - arrow(oldHeading,0); - arrow(oldHeading+180,0); - arrow(m.heading,0xF800); - arrow(m.heading+180,0x001F); - oldHeading = m.heading; -}); -Bangle.setCompassPower(1); +g.clear(); +g.setColor(0,0.5,1); +g.fillCircle(120,130,80,80); +g.setColor(0,0,0); +g.fillCircle(120,130,70,70); + +function arrow(r,c) { + r=r*Math.PI/180; + var p = Math.PI/2; + g.setColor(c); + g.fillPoly([ + 120+60*Math.sin(r), 130-60*Math.cos(r), + 120+10*Math.sin(r+p), 130-10*Math.cos(r+p), + 120+10*Math.sin(r+-p), 130-10*Math.cos(r-p), + ]); +} + +var oldHeading = 0; +Bangle.on('mag', function(m) { + if (!Bangle.isLCDOn()) return; + g.setFont("6x8",3); + g.setColor(0); + g.fillRect(0,0,230,40); + g.setColor(0xffff); + if (isNaN(m.heading)) { + g.setFontAlign(-1,-1); + g.setFont("6x8",2); + g.drawString("Uncalibrated",50,12); + g.drawString("turn 360° around",25,26); + } + else { + g.setFontAlign(0,0); + g.setFont("6x8",3); + g.drawString(Math.round(m.heading),120,12); + } + g.setColor(0,0,0); + arrow(oldHeading,0); + arrow(oldHeading+180,0); + arrow(m.heading,0xF800); + arrow(m.heading+180,0x001F); + oldHeading = m.heading; +}); +Bangle.setCompassPower(1); From 1017090cbe5fc6fb42101a0544fdd6e8ada983d0 Mon Sep 17 00:00:00 2001 From: Purple-Tentacle <59914607+Purple-Tentacle@users.noreply.github.com> Date: Fri, 17 Apr 2020 16:40:25 +0200 Subject: [PATCH 037/101] compass 0.02 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e2b20cca4..d7bd6a7a1 100644 --- a/apps.json +++ b/apps.json @@ -235,7 +235,7 @@ { "id": "compass", "name": "Compass", "icon": "compass.png", - "version":"0.01", + "version":"0.02", "description": "Simple compass that points North", "tags": "tool,outdoors", "storage": [ From 1fff62e48da25d2455294643ac66321033088c76 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 16:55:35 +0200 Subject: [PATCH 038/101] init hid camera app --- apps/hidcam/ChangeLog | 1 + apps/hidcam/add_to_apps.json | 13 +++++++++++++ apps/hidcam/app-icon.js | 1 + apps/hidcam/app.js | 12 ++++++++++++ apps/hidcam/app.png | Bin 0 -> 1620 bytes 5 files changed, 27 insertions(+) create mode 100644 apps/hidcam/ChangeLog create mode 100644 apps/hidcam/add_to_apps.json create mode 100644 apps/hidcam/app-icon.js create mode 100644 apps/hidcam/app.js create mode 100644 apps/hidcam/app.png diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/hidcam/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/hidcam/add_to_apps.json b/apps/hidcam/add_to_apps.json new file mode 100644 index 000000000..ca75a7bd8 --- /dev/null +++ b/apps/hidcam/add_to_apps.json @@ -0,0 +1,13 @@ +// Create an entry in apps.json as follows: +{ "id": "7chname", + "name": "My app's human readable name", + "shortName":"Short Name", + "icon": "app.png", + "version":"0.01", + "description": "A detailed description of my great app", + "tags": "", + "storage": [ + {"name":"7chname.app.js","url":"app.js"}, + {"name":"7chname.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/hidcam/app-icon.js b/apps/hidcam/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/hidcam/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js new file mode 100644 index 000000000..af367779a --- /dev/null +++ b/apps/hidcam/app.js @@ -0,0 +1,12 @@ +// place your const, vars, functions or classes here + +// special function to handle display switch on +Bangle.on('lcdPower', (on) => { + if (on) { + // call your app function here + // If you clear the screen, do Bangle.drawWidgets(); + } +}); + +g.clear(); +// call your app function here diff --git a/apps/hidcam/app.png b/apps/hidcam/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 Date: Fri, 17 Apr 2020 18:56:38 +0200 Subject: [PATCH 039/101] app code and config --- apps/hidcam/ChangeLog | 2 +- apps/hidcam/add_to_apps.json | 13 ------------- apps/hidcam/app-icon.js | 2 +- apps/hidcam/app.js | 12 ------------ apps/hidcam/app.png | Bin 1620 -> 1425 bytes apps/hidcam/hidcam.app.js | 28 ++++++++++++++++++++++++++++ apps/hidcam/hidcam.app.json | 13 +++++++++++++ 7 files changed, 43 insertions(+), 27 deletions(-) delete mode 100644 apps/hidcam/add_to_apps.json delete mode 100644 apps/hidcam/app.js create mode 100644 apps/hidcam/hidcam.app.js create mode 100644 apps/hidcam/hidcam.app.json diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog index 5560f00bc..665c0df6e 100644 --- a/apps/hidcam/ChangeLog +++ b/apps/hidcam/ChangeLog @@ -1 +1 @@ -0.01: New App! +0.01: Init diff --git a/apps/hidcam/add_to_apps.json b/apps/hidcam/add_to_apps.json deleted file mode 100644 index ca75a7bd8..000000000 --- a/apps/hidcam/add_to_apps.json +++ /dev/null @@ -1,13 +0,0 @@ -// Create an entry in apps.json as follows: -{ "id": "7chname", - "name": "My app's human readable name", - "shortName":"Short Name", - "icon": "app.png", - "version":"0.01", - "description": "A detailed description of my great app", - "tags": "", - "storage": [ - {"name":"7chname.app.js","url":"app.js"}, - {"name":"7chname.img","url":"app-icon.js","evaluate":true} - ] -} diff --git a/apps/hidcam/app-icon.js b/apps/hidcam/app-icon.js index 49232b838..aa9d5e194 100644 --- a/apps/hidcam/app-icon.js +++ b/apps/hidcam/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) +E.toArrayBuffer(atob("MDCEAzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMxERERERETMzMzMzMzMzMzMzMzMzMzMzMRERERERERMzMzMzMzMzMzMzMzMzMzMzMREREREREREzMzMzMzMzMzMzMzMAAAAzEREREREREREzMzMzMzMzMzMzMzMAAAAxERERERERERETMzMzMzMzMzMzMxERERERERERERERERERERERETMzMzMzMRERERERERERERERERERERERERMzMzMzEREREREREREAAAAAEREREREREREzMzMzEREREREREQAAAAAAABERESIiIREzMzMzEREREREREAAAAAAAAAERESIiIREzMzMzEREREREQAAAKqqqgAAABESIiIREzMzMzEREREREQAAqqqqqqoAABESIiIREzMzMzEREREREAAKqqqqqqqgAAEREREREzMzMzERERERAACqqqqqqqqqAAAREREREzMzMzERERERAAqqqiIiIqqqoAAREREREzMzMzqqqqqgAAqqoiIiIiKqoAAKqqqqozMzMzqqqqqgAKqqIiIiIiKqqgAKqqqqozMzMzqqqqqgAKqqIiqqqiKqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAKqqqqqqqqqqqgAKqqqqozMzMzqqqqqgAAqqqqqqqqqqoAAKqqqqozMzMzqqqqqqAAqqqqqqqqqqoACqqqqqozMzMzqqqqqqAACqqqqqqqqqAACqqqqqozMzMzqqqqqqoAAKqqqqqqqgAAqqqqqqozMzMzqqqqqqoAAAqqqqqqoAAAqqqqqqozMzMzqqqqqqqgAAAKqqqgAAAKqqqqqqozMzMzqqqqqqqqAAAAAAAAAACqqqqqqqozMzMzqqqqqqqqqgAAAAAAAKqqqqqqqqozMzMzqqqqqqqqqqoAAAAAqqqqqqqqqqozMzMzOqqqqqqqqqqqqqqqqqqqqqqqqqMzMzMzM6qqqqqqqqqqqqqqqqqqqqqqqjMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMzMw==")) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js deleted file mode 100644 index af367779a..000000000 --- a/apps/hidcam/app.js +++ /dev/null @@ -1,12 +0,0 @@ -// place your const, vars, functions or classes here - -// special function to handle display switch on -Bangle.on('lcdPower', (on) => { - if (on) { - // call your app function here - // If you clear the screen, do Bangle.drawWidgets(); - } -}); - -g.clear(); -// call your app function here diff --git a/apps/hidcam/app.png b/apps/hidcam/app.png index 582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0..3f631a0d8c2c9a2f82ad03564f6e503e97ec3b74 100644 GIT binary patch delta 1389 zcmV-z1(N#I43P_vHGc(0Nkl2XW^HHNnRPdH7YVh3 zAi4-C0tqZh0&gNIp^K!1F0{>?F8ZK?L=!~R#889`D}{vAtGp@*QYh5@80TYmE$3rD zXXnhv+r_N&?d+VhW?jr54xID6@AEwW|9PMDejI3`i6)w8Vt*MB_an&A!4sV_lRgYQ z(U60bA)%^oee%v5e=Ilm@&!mKhW3ATK_WL9^bF=wV%=wZcFZg%y|Nrf4_+Hu9Ce*+^R zc(KwX1zV6(7k9~?h!Hyfbl2<$#^#4n_>Pe{25aG9oee=sBAVos>< zeZK4Uo0W}K0(Kub;#YIxcL|;c!>=(2h$%VihL7Ie9x1h3sya$#pG2A>uj?sd(I~Ss z(fP@7oD9euxgs&*b+QBp??8vTYo};@fk(eQ-ni7;;|S=S+iZ& zQ%oh|M8YB59uK{}eKm#b*!n`1?bz81c@c`J;#MU9gEb$E-r?5R7`a@wF$XD$N25$9 z;`H^e#@*T3crrpoc}d^j=`$FZd*5QTQ}=G&k&it!R5#a z5~;sHN+RJ9nx^6DT=C!p=z5AY=&?+XoiY$ z0cl;&&o+yA*7s@|d7*&A4IY2~>ga(^KeTm$wPd}uTO2&!yS?xnk48!Bx?urTB{Y8O zp}Gz;soP|d`93RsYw&MaTMTA}HgEpTmqCEmlE3B>kete!eU3qVk*5icj{q=sO~q-e zpMSp+hDSipOcn0eKC-^7&AFmTK9h#|DVU2xY93ges2m+&u@!v=RuyBUGRAk-hCkwT zHd(mu>FzIU%Vt2;Ai4OKOP92ymMNh=r@|E=O@~DvjMJ4404)_dY^MYJZcj2U)uHs1y5MFf2e3*24Yl+_d3@l_-s& zD%LtZ@4?5YgGDLMg^}9mAF27tr*+VQKx5Z z7#3i+xVd`{3XYEuniw^l^e(~^VJCsEUR|D=s!a{d|_>g7N8ZA(iCfm4ELF z&rVwxsxW@gF|`+JYw@Fq{E9U_6X*QpQ!J#COL!HrkVtXhxX+mFkcUw@=#W~T_>4sc`SYWX)K1a5mj_QiwG0~G+^w0W_p zHez$bVew zFhhQ-(okyzE&*GOL{)@^c6%>Q%}X*JXCa*+BNxbK^Lrar)vzjd>=rk6t!Bg2Yy*Jc zVx_5CfXEIZ)s29G-vxQ7iiXqX#cA`JBUl$AmdnVYN^4aKef`VU8(5UbfNwBZPX7|7 v5qz7=%BN2Lwq^LgCeuU{O*GNO{|o;Bs>Z}7R{Rfy00000NkvXXu0mjfd2ysS delta 1586 zcmV-22F>}A3)BpdHGc*PNklVsi@IIDWLJF z<-tS+MbQVNMvWngMiMVMF($}~PbV60iJqKGq6sl-z#5IgNDvG@D81m_8L(pU0#u>& zLWh~o%w9f}(&^0JyL+a!If?wA_PXuwzxMtv>-#=9jnnvZLw~00MXDHdHZ-F~E6@xy zAk0IFoNQ?rJ?=L3M zHi1NI%W6w_1%Iftvl|hOhaVrR!sN{2xw@hkSSKyk8akT z^^R7(Pu73-SLjz9%wK^oEKM9^v2d+uZBzb_ElWR@^923y?MQ5Sh3y}H359v|8R9g6# zr~d$slVYvzX{^gvI{yK&9t6Sw)^Fo(=6P9=8U6ZW2$40`DO|&}2{l-??t>KM^xP{PQp9J>sMDt1wG0P7(^*|FxpxgxUNu=e>XY@94oX zm34@@sD<7z%UMsx_zdi4z8GAI!3iDJ{-uogg{9 zcYkp~PAMU^CCrIu%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FSn>E+sATQ)Q)70!M+WViTAl9FdlI^_bw) zg$_FC{~s`6^Y4_v-WecL8bso`qEiB0GeD&@Sajx!_6dmf;f#FXiqAg!jge#)(`PVmVSj|$`UsHZGo<5&Mq0i(4E(oP@&iXk=-U1(Bgrgt{}SSg8|!FVQpN1*ApW3%X$qBd z0$g%sHPPlXP=%gv2Ryu4{+&-ACfn41x}XBX7bma&a6)1z%_mzAlTKO8TYoT%Ma!#@ zNsf>EkEEDA*ST6fiC+AnsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6y zeLWqoYkSl4pzFQ(_Vp&ItO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmi zn45#=3l9BmL6Bp<*MZejrhnxPZJd$0O%`^i+?+grDp}Z_q9=X}=<|3S6D2}Xo}(vz z>ty7i#49G<-Lx9fe*rb6#JivumHVB}LG4gdXO*R~xABLfz>ADt4^0(GkQeZWqQ#Jh z>AK{zSO Date: Fri, 17 Apr 2020 19:00:45 +0200 Subject: [PATCH 040/101] adding the extra comma as mentioned on bangle js documentation --- apps/hidcam/hidcam.app.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/hidcam/hidcam.app.json b/apps/hidcam/hidcam.app.json index df35404e4..ad3ea89fe 100644 --- a/apps/hidcam/hidcam.app.json +++ b/apps/hidcam/hidcam.app.json @@ -1,4 +1,4 @@ -// Create an entry in apps.json as follows: +}, { "id": "hidcam", "name": "HID camera shutter", "shortName":"HID cam", @@ -11,3 +11,4 @@ {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ], } +] From 15535b0f19c232425c01311e1f1b5c33da50d78f Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 19:06:09 +0200 Subject: [PATCH 041/101] move json info to the good place --- apps.json | 14 +++++++++++++- apps/hidcam/hidcam.app.json | 14 -------------- 2 files changed, 13 insertions(+), 15 deletions(-) delete mode 100644 apps/hidcam/hidcam.app.json diff --git a/apps.json b/apps.json index effa14aa4..d57f218be 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,17 @@ "evaluate": true } ] - } + }, +{ "id": "hidcam", + "name": "HID camera shutter", + "shortName":"HID cam", + "icon": "app.png", + "version":"0.01", + "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", + "tags": "tools", + "storage": [ + {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.img","url":"app-icon.js","evaluate":true} + ], +} ] diff --git a/apps/hidcam/hidcam.app.json b/apps/hidcam/hidcam.app.json deleted file mode 100644 index ad3ea89fe..000000000 --- a/apps/hidcam/hidcam.app.json +++ /dev/null @@ -1,14 +0,0 @@ -}, -{ "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", - "icon": "app.png", - "version":"0.01", - "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", - "tags": "tools", - "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, - {"name":"hidcam.img","url":"app-icon.js","evaluate":true} - ], -} -] From 1dc2e3805d0cbbde633669b88c9f36465931ab69 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 17 Apr 2020 19:12:17 +0200 Subject: [PATCH 042/101] json format --- apps.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index d57f218be..d89fe95b0 100644 --- a/apps.json +++ b/apps.json @@ -1294,16 +1294,16 @@ } ] }, -{ "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", - "icon": "app.png", - "version":"0.01", - "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", - "tags": "tools", - "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, - {"name":"hidcam.img","url":"app-icon.js","evaluate":true} - ], + { "id": "hidcam", + "name": "HID camera shutter", + "shortName":"HID cam", + "icon": "app.png", + "version":"0.01", + "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", + "tags": "tools", + "storage": [ + {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.img","url":"app-icon.js","evaluate":true} + ] } ] From c7f2a18caaff5a472db6f7f3765cd4234f936da1 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:08:07 +0200 Subject: [PATCH 043/101] Remove "settings" from appid.info --- apps.json | 2 +- apps/setting/ChangeLog | 1 + apps/setting/settings.js | 22 ++++++++++++++-------- js/appinfo.js | 2 -- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..4b8b4a6b3 100644 --- a/apps.json +++ b/apps.json @@ -120,7 +120,7 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.16", + "version":"0.17", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3acfb5fb0..81ac1fa81 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -18,3 +18,4 @@ 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) 0.16: Reduce memory usage further when running app settings page +0.17: Remove need for "settings" in appid.info diff --git a/apps/setting/settings.js b/apps/setting/settings.js index d0d88ce20..97ce464ad 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -416,10 +416,19 @@ function showAppSettingsMenu() { '': { 'title': 'App Settings' }, '< Back': ()=>showMainMenu(), } - const apps = storage.list(/\.info$/) - .map(app => {var a=storage.readJSON(app, 1);return (a&&a.settings)?{sortorder:a.sortorder,name:a.name,settings:a.settings}:undefined}) - .filter(app => app) // filter out any undefined apps - .sort((a, b) => a.sortorder - b.sortorder) + const apps = storage.list(/\.settings\.js$/) + .map(s => s.substr(0, s.length-12)) + .map(id => { + const a=storage.readJSON(id+'.info',1); + return {id:id,name:a.name,sortorder:a.sortorder}; + }) + .sort((a, b) => { + const n = (0|a.sortorder)-(0|b.sortorder); + if (n) return n; // do sortorder first + if (a.nameb.name) return 1; + return 0; + }) if (apps.length === 0) { appmenu['No app has settings'] = () => { }; } @@ -433,10 +442,7 @@ function showAppSettings(app) { E.showMessage(`${app.name}:\n${msg}!\n\nBTN1 to go back`); setWatch(showAppSettingsMenu, BTN1, { repeat: false }); } - let appSettings = storage.read(app.settings); - if (!appSettings) { - return showError('Missing settings'); - } + let appSettings = storage.read(app.id+'.settings.js'); try { appSettings = eval(appSettings); } catch (e) { diff --git a/js/appinfo.js b/js/appinfo.js index 56b6ff2f8..9fff7c92a 100644 --- a/js/appinfo.js +++ b/js/appinfo.js @@ -60,8 +60,6 @@ var AppInfo = { if (app.type && app.type!="app") json.type = app.type; if (fileContents.find(f=>f.name==app.id+".app.js")) json.src = app.id+".app.js"; - if (fileContents.find(f=>f.name==app.id+".settings.js")) - json.settings = app.id+".settings.js"; if (fileContents.find(f=>f.name==app.id+".img")) json.icon = app.id+".img"; if (app.sortorder) json.sortorder = app.sortorder; From 43b0d8897e7a50556b93a58eff19d068d2f43544 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:25:56 +0200 Subject: [PATCH 044/101] widbatpc: Save settings in data file --- apps.json | 8 +++++--- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 2 +- apps/widbatpc/widget.js | 2 +- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..315120cc7 100644 --- a/apps.json +++ b/apps.json @@ -342,14 +342,16 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.09", + "version":"0.10", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", "storage": [ {"name":"widbatpc.wid.js","url":"widget.js"}, - {"name":"widbatpc.settings.js","url":"settings.js"}, - {"name":"widbatpc.settings.json","content": "{}"} + {"name":"widbatpc.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"widbatpc.json"} ] }, { "id": "widbt", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 129707320..138c1adc8 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -6,3 +6,4 @@ 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery 0.09: Fix regression stopping correct widget updates +0.10: Don't overwrite existing settings on app update diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js index 5c0bdbcae..88988cf22 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/settings.js @@ -3,7 +3,7 @@ * @param {function} back Use back() to return to settings menu */ (function(back) { - const SETTINGS_FILE = 'widbatpc.settings.json' + const SETTINGS_FILE = 'widbatpc.json' const COLORS = ['By Level', 'Green', 'Monochrome'] // initialize with default settings... diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index aca690ce0..189ca215f 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -11,7 +11,7 @@ const COLORS = { 'ok': 0xFD20, // "Orange" 'low':0xF800, // "Red" } -const SETTINGS_FILE = 'widbatpc.settings.json' +const SETTINGS_FILE = 'widbatpc.json' let settings function loadSettings() { From b691f783aa7cb956c0644658907a93e27ce836c9 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:29:56 +0200 Subject: [PATCH 045/101] welcome: Save settings in data file fwelcom --- apps.json | 6 ++++-- apps/welcome/ChangeLog | 1 + apps/welcome/boot.js | 4 ++-- apps/welcome/settings-default.json | 3 --- apps/welcome/settings.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 apps/welcome/settings-default.json diff --git a/apps.json b/apps.json index 315120cc7..a8b29b685 100644 --- a/apps.json +++ b/apps.json @@ -78,7 +78,7 @@ { "id": "welcome", "name": "Welcome", "icon": "app.png", - "version":"0.07", + "version":"0.08", "description": "Appears at first boot and explains how to use Bangle.js", "tags": "start,welcome", "allow_emulator":true, @@ -86,8 +86,10 @@ {"name":"welcome.boot.js","url":"boot.js"}, {"name":"welcome.app.js","url":"app.js"}, {"name":"welcome.settings.js","url":"settings.js"}, - {"name":"welcome.settings.json","url":"settings-default.json","evaluate":true}, {"name":"welcome.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"welcome.json"} ] }, { "id": "gbridge", diff --git a/apps/welcome/ChangeLog b/apps/welcome/ChangeLog index b8786af6a..a377fc81e 100644 --- a/apps/welcome/ChangeLog +++ b/apps/welcome/ChangeLog @@ -7,3 +7,4 @@ 0.07: Run again when updated Don't run again when settings app is updated (or absent) Add "Run Now" option to settings +0.08: Don't overwrite existing settings on app update diff --git a/apps/welcome/boot.js b/apps/welcome/boot.js index bc5afcc66..f6ba6d2d6 100644 --- a/apps/welcome/boot.js +++ b/apps/welcome/boot.js @@ -1,11 +1,11 @@ (function() { - let s = require('Storage').readJSON('welcome.settings.json', 1) + let s = require('Storage').readJSON('welcome.json', 1) || require('Storage').readJSON('setting.json', 1) || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('welcome.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('welcome.settings.json', {welcomed: "yes"}) + require('Storage').write('welcome.json', {welcomed: "yes"}) load('welcome.app.js') }) } diff --git a/apps/welcome/settings-default.json b/apps/welcome/settings-default.json deleted file mode 100644 index d250efff5..000000000 --- a/apps/welcome/settings-default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "welcomed": false -} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index b11921646..e873c2785 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,13 +1,13 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('welcome.settings.json', 1) + let settings = require('Storage').readJSON('welcome.sjson', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' }, 'Run on Next Boot': { value: !settings.welcomed, format: v => v ? 'OK' : 'No', - onchange: v => require('Storage').write('welcome.settings.json', {welcomed: !v}), + onchange: v => require('Storage').write('welcome.json', {welcomed: !v}), }, 'Run Now': () => load('welcome.app.js'), '< Back': back, From b047f14d4ada97c510edc7a773a3e1f08982bc5d Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:35:59 +0200 Subject: [PATCH 046/101] setting: Save settings in data file --- apps.json | 6 ++++-- apps/setting/ChangeLog | 1 + apps/setting/settings-default.json | 25 ------------------------- 3 files changed, 5 insertions(+), 27 deletions(-) delete mode 100644 apps/setting/settings-default.json diff --git a/apps.json b/apps.json index a8b29b685..4d5493e49 100644 --- a/apps.json +++ b/apps.json @@ -122,15 +122,17 @@ { "id": "setting", "name": "Settings", "icon": "settings.png", - "version":"0.16", + "version":"0.17", "description": "A menu for setting up Bangle.js", "tags": "tool,system", "storage": [ {"name":"setting.app.js","url":"settings.js"}, {"name":"setting.boot.js","url":"boot.js"}, - {"name":"setting.json","url":"settings-default.json","evaluate":true}, {"name":"setting.img","url":"settings-icon.js","evaluate":true} ], + "data": [ + {"name":"setting.json"} + ], "sortorder" : -2 }, { "id": "alarm", diff --git a/apps/setting/ChangeLog b/apps/setting/ChangeLog index 3acfb5fb0..773b510f0 100644 --- a/apps/setting/ChangeLog +++ b/apps/setting/ChangeLog @@ -18,3 +18,4 @@ 0.14: Reduce memory usage when running app settings page 0.15: Reduce memory usage when running default clock chooser (#294) 0.16: Reduce memory usage further when running app settings page +0.17: Don't overwrite existing settings on app update diff --git a/apps/setting/settings-default.json b/apps/setting/settings-default.json deleted file mode 100644 index c61fd6109..000000000 --- a/apps/setting/settings-default.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - ble: true, // Bluetooth enabled by default - blerepl: true, // Is REPL on Bluetooth - can Espruino IDE be used? - log: false, // Do log messages appear on screen? - timeout: 10, // Default LCD timeout in seconds - vibrate: true, // Vibration enabled by default. App must support - beep: "vib", // Beep enabled by default. App must support - timezone: 0, // Set the timezone for the device - HID : false, // BLE HID mode, off by default - clock: null, // a string for the default clock's name - "12hour" : false, // 12 or 24 hour clock? - // welcomed : undefined/true (whether welcome app should show) - brightness: 1, // LCD brightness from 0 to 1 - options: { - wakeOnBTN1: true, - wakeOnBTN2: true, - wakeOnBTN3: true, - wakeOnFaceUp: false, - wakeOnTouch: false, - wakeOnTwist: true, - twistThreshold: 819.2, - twistMaxY: -800, - twistTimeout: 1000 - } -} From 9358b4b5995e2efa6a49a1ca7865a0484f0c2c3f Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:39:27 +0200 Subject: [PATCH 047/101] alarm: Save settings in data file --- apps.json | 6 ++++-- apps/alarm/ChangeLog | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 4d5493e49..30fb669d2 100644 --- a/apps.json +++ b/apps.json @@ -139,16 +139,18 @@ "name": "Default Alarm", "shortName":"Alarms", "icon": "app.png", - "version":"0.06", + "version":"0.07", "description": "Set and respond to alarms", "tags": "tool,alarm,widget", "storage": [ {"name":"alarm.app.js","url":"app.js"}, {"name":"alarm.boot.js","url":"boot.js"}, {"name":"alarm.js","url":"alarm.js"}, - {"name":"alarm.json","content":"[]"}, {"name":"alarm.img","url":"app-icon.js","evaluate":true}, {"name":"alarm.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"alarm.json"} ] }, { "id": "wclock", diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 2ff60e658..ca92a0d97 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -4,3 +4,4 @@ 0.04: Tweaks for variable size widget system 0.05: Add alarm.boot.js and move code from the bootloader 0.06: Change 'New Alarm' to 'Save', allow Deletion of Alarms +0.07: Don't overwrite existing settings on app update From e4c0574ab77ad2b8064e3c50dd1e900f5a2fe7fb Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:45:48 +0200 Subject: [PATCH 048/101] heart: Save settings in data file, add recording files to data --- apps.json | 7 +++++-- apps/heart/ChangeLog | 3 ++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 30fb669d2..6509458bf 100644 --- a/apps.json +++ b/apps.json @@ -300,15 +300,18 @@ { "id": "heart", "name": "Heart Rate Recorder", "icon": "app.png", - "version":"0.01", + "version":"0.02", "interface": "interface.html", "description": "Application that allows you to record your heart rate. Can run in background", "tags": "tool,health,widget", "storage": [ {"name":"heart.app.js","url":"app.js"}, - {"name":"heart.json","url":"app-settings.json","evaluate":true}, {"name":"heart.img","url":"app-icon.js","evaluate":true}, {"name":"heart.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"heart.json"}, + {"wildcard":".heart?","storageFile": true} ] }, { "id": "slevel", diff --git a/apps/heart/ChangeLog b/apps/heart/ChangeLog index 4c4db83bc..70134af27 100644 --- a/apps/heart/ChangeLog +++ b/apps/heart/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! - +0.02: Don't overwrite existing settings on app update + Clean up recordings on app removal From db35edede6527b4613ed147298be6497def457ee Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:49:57 +0200 Subject: [PATCH 049/101] ncstart: Save settings in data file --- apps.json | 6 ++++-- apps/ncstart/ChangeLog | 1 + apps/ncstart/boot.js | 4 ++-- apps/ncstart/settings-default.json | 3 --- apps/ncstart/settings.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) delete mode 100644 apps/ncstart/settings-default.json diff --git a/apps.json b/apps.json index 6509458bf..c3544abee 100644 --- a/apps.json +++ b/apps.json @@ -528,20 +528,22 @@ "id": "ncstart", "name": "NCEU Startup", "icon": "start.png", - "version":"0.04", + "version":"0.05", "description": "NodeConfEU 2019 'First Start' Sequence", "tags": "start,welcome", "storage": [ {"name":"ncstart.app.js","url":"start.js"}, {"name":"ncstart.boot.js","url":"boot.js"}, {"name":"ncstart.settings.js","url":"settings.js"}, - {"name":"ncstart.settings.json","url":"settings-default.json","evaluate":true}, {"name":"ncstart.img","url":"start-icon.js","evaluate":true}, {"name":"nc-bangle.img","url":"start-bangle.js","evaluate":true}, {"name":"nc-nceu.img","url":"start-nceu.js","evaluate":true}, {"name":"nc-nfr.img","url":"start-nfr.js","evaluate":true}, {"name":"nc-nodew.img","url":"start-nodew.js","evaluate":true}, {"name":"nc-tf.img","url":"start-tf.js","evaluate":true} + ], + "data": [ + {"name":"ncstart.json"} ] }, { "id": "ncfrun", diff --git a/apps/ncstart/ChangeLog b/apps/ncstart/ChangeLog index f4418827e..522633f7b 100644 --- a/apps/ncstart/ChangeLog +++ b/apps/ncstart/ChangeLog @@ -5,3 +5,4 @@ 0.04: Run again when updated Don't run again when settings app is updated (or absent) Add "Run Now" option to settings +0.05: Don't overwrite existing settings on app update diff --git a/apps/ncstart/boot.js b/apps/ncstart/boot.js index e3f514f5b..094033094 100644 --- a/apps/ncstart/boot.js +++ b/apps/ncstart/boot.js @@ -1,11 +1,11 @@ (function() { - let s = require('Storage').readJSON('ncstart.settings.json', 1) + let s = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {welcomed: true} // do NOT run if global settings are also absent if (!s.welcomed && require('Storage').read('ncstart.app.js')) { setTimeout(() => { s.welcomed = true - require('Storage').write('ncstart.settings.json', s) + require('Storage').write('ncstart.json', s) load('ncstart.app.js') }) } diff --git a/apps/ncstart/settings-default.json b/apps/ncstart/settings-default.json deleted file mode 100644 index d250efff5..000000000 --- a/apps/ncstart/settings-default.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "welcomed": false -} diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 2b24095cf..6780264a7 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,13 +1,13 @@ // The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('ncstart.settings.json', 1) + let settings = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'NCEU Startup' }, 'Run on Next Boot': { value: !settings.welcomed, format: v => v ? 'OK' : 'No', - onchange: v => require('Storage').write('ncstart.settings.json', {welcomed: !v}), + onchange: v => require('Storage').write('ncstart.json', {welcomed: !v}), }, 'Run Now': () => load('ncstart.app.js'), '< Back': back, From 595de45e348799bb38d0728dd8a82aecc5c09287 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:52:42 +0200 Subject: [PATCH 050/101] numerals: Save settings in data file --- apps.json | 8 +++++--- apps/numerals/ChangeLog | 3 ++- apps/numerals/numerals-default.json | 5 ----- 3 files changed, 7 insertions(+), 9 deletions(-) delete mode 100644 apps/numerals/numerals-default.json diff --git a/apps.json b/apps.json index c3544abee..18fad4cfe 100644 --- a/apps.json +++ b/apps.json @@ -1235,7 +1235,7 @@ "name": "Numerals Clock", "shortName": "Numerals Clock", "icon": "numerals.png", - "version":"0.03", + "version":"0.04", "description": "A simple big numerals clock", "tags": "numerals,clock", "type":"clock", @@ -1243,8 +1243,10 @@ "storage": [ {"name":"numerals.app.js","url":"numerals.app.js"}, {"name":"numerals.img","url":"numerals-icon.js","evaluate":true}, - {"name":"numerals.settings.js","url":"numerals.settings.js"}, - {"name":"numerals.json","url":"numerals-default.json","evaluate":true} + {"name":"numerals.settings.js","url":"numerals.settings.js"} + ], + "data":[ + {"name":"numerals.json"} ] }, { "id": "bledetect", diff --git a/apps/numerals/ChangeLog b/apps/numerals/ChangeLog index ec465a83f..927c4ff5f 100644 --- a/apps/numerals/ChangeLog +++ b/apps/numerals/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Use BTN2 for settings menu like other clocks -0.03: maximize numerals, make menu button configurable, change icon to mac palette, add default settings file, respect 12hour setting \ No newline at end of file +0.03: maximize numerals, make menu button configurable, change icon to mac palette, add default settings file, respect 12hour setting +0.04: Don't overwrite existing settings on app update diff --git a/apps/numerals/numerals-default.json b/apps/numerals/numerals-default.json deleted file mode 100644 index aa6a25047..000000000 --- a/apps/numerals/numerals-default.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - color:0, - drawMode:"fill", - menuButton:22 -} \ No newline at end of file From a8d1ef3e53b35732bb8871956d1b2d1d13875d5e Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 21:42:29 +0200 Subject: [PATCH 051/101] gpsrec: Save settings in data file, add track files to data --- apps.json | 7 +++++-- apps/gpsrec/ChangeLog | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 18fad4cfe..a18029abc 100644 --- a/apps.json +++ b/apps.json @@ -286,15 +286,18 @@ { "id": "gpsrec", "name": "GPS Recorder", "icon": "app.png", - "version":"0.07", + "version":"0.08", "interface": "interface.html", "description": "Application that allows you to record a GPS track. Can run in background", "tags": "tool,outdoors,gps,widget", "storage": [ {"name":"gpsrec.app.js","url":"app.js"}, - {"name":"gpsrec.json","url":"app-settings.json","evaluate":true}, {"name":"gpsrec.img","url":"app-icon.js","evaluate":true}, {"name":"gpsrec.wid.js","url":"widget.js"} + ], + "data": [ + {"name":"gpsrec.json"}, + {"wildcard":".gpsrc?","storageFile": true} ] }, { "id": "heart", diff --git a/apps/gpsrec/ChangeLog b/apps/gpsrec/ChangeLog index 8f1c575a1..17678bf3a 100644 --- a/apps/gpsrec/ChangeLog +++ b/apps/gpsrec/ChangeLog @@ -5,3 +5,5 @@ 0.05: Tweaks for variable size widget system 0.06: Ensure widget update itself (fix #118) and change to using icons 0.07: Added @jeffmer's awesome track viewer +0.08: Don't overwrite existing settings on app update + Clean up recorded tracks on app removal From e615b49cd027976ca9bceb869d18cab3e30d9d7f Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 17 Apr 2020 22:17:36 +0200 Subject: [PATCH 052/101] wohrm: fix `apps.json` version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0c97b9e57..7499b352c 100644 --- a/apps.json +++ b/apps.json @@ -890,7 +890,7 @@ { "id": "wohrm", "name": "Workout HRM", "icon": "app.png", - "version":"0.06", + "version":"0.07", "readme": "README.md", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "tags": "hrm,workout", From 2278947b3d4b7a2ff0cea136bfa16d7bbb0a9497 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sat, 18 Apr 2020 00:51:22 +0200 Subject: [PATCH 053/101] App Manager: Add support for data files --- apps.json | 2 +- apps/files/ChangeLog | 1 + apps/files/files.js | 94 +++++++++++++++++++++++++++++++++----------- 3 files changed, 74 insertions(+), 23 deletions(-) diff --git a/apps.json b/apps.json index 0c97b9e57..bac885598 100644 --- a/apps.json +++ b/apps.json @@ -319,7 +319,7 @@ { "id": "files", "name": "App Manager", "icon": "files.png", - "version":"0.02", + "version":"0.03", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "tags": "tool,system,files", "storage": [ diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog index 8b7be7640..1140000fe 100644 --- a/apps/files/ChangeLog +++ b/apps/files/ChangeLog @@ -1 +1,2 @@ 0.02: Fix deletion of apps - now use files list in app.info (fix #262) +0.03: Add support for data files diff --git a/apps/files/files.js b/apps/files/files.js index 4775d35d0..ef0481f0c 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -30,29 +30,80 @@ function showMainMenu() { return E.showMenu(mainmenu); } -function eraseApp(app) { - E.showMessage('Erasing\n' + app.name + '...'); +function isGlob(f) {return /[?*]/.test(f)} +function globToRegex(pattern) { + const ESCAPE = '.*+-?^${}()|[]\\'; + const regex = pattern.replace(/./g, c => { + switch (c) { + case '?': return '.'; + case '*': return '.*'; + default: return ESCAPE.includes(c) ? ('\\' + c) : c; + } + }); + return new RegExp('^'+regex+'$'); +} + +function eraseFiles(app) { app.files.split(",").forEach(f=>storage.erase(f)); } +function eraseData(app) { + if(!app.data) return; + const d=app.data.split(';'), + files=d[0].split(','), + sFiles=(d[1]||'').split(','); + let erase = f=>storage.erase(f); + files.forEach(f=>{ + if (!isGlob(f)) erase(f); + else storage.list(globToRegex(f)).forEach(erase); + }) + erase = sf=>storage.open(sf,'r').erase(); + sFiles.forEach(sf=>{ + if (!isGlob(sf)) erase(sf); + else storage.list(globToRegex(sf+'\u0001')) + .forEach(fs=>erase(fs.substring(0,fs.length-1))); + }) +} +function eraseApp(app, files,data) { + E.showMessage('Erasing\n' + app.name + '...'); + if (files) eraseFiles(app) + if (data) eraseData(app) +} +function eraseOne(app, files,data){ + E.showPrompt('Erase\n'+app.name+'?').then((v) => { + if (v) { + Bangle.buzz(100, 1); + eraseApp(app, files,data) + showApps(); + } else { + showAppMenu(app) + } + }) +} +function eraseAll(apps, files,data) { + E.showPrompt('Erase all?').then((v) => { + if (v) { + Bangle.buzz(100, 1); + for(var n = 0; n m = showApps(), - 'Erase': () => { - E.showPrompt('Erase\n' + app.name + '?').then((v) => { - if (v) { - Bangle.buzz(100, 1); - eraseApp(app); - m = showApps(); - } else { - m = showAppMenu(app) - } - }); - } - }; + } + if (app.data) { + appmenu['Erase Completely'] = () => eraseOne(app, true, true) + appmenu['Erase App,Keep Data'] = () => eraseOne(app,true, false) + appmenu['Only Erase Data'] = () => eraseOne(app,false, true) + } else { + appmenu['Erase'] = () => eraseOne(app,true, false) + } return E.showMenu(appmenu); } @@ -78,13 +129,12 @@ function showApps() { return menu; }, appsmenu); appsmenu['Erase All'] = () => { - E.showPrompt('Erase all?').then((v) => { - if (v) { - Bangle.buzz(100, 1); - for (var n = 0; n < list.length; n++) - eraseApp(list[n]); - } - m = showApps(); + E.showMenu({ + '': {'title': 'Erase All'}, + 'Erase Everything': () => eraseAll(list, true, true), + 'Erase Apps,Keep Data': () => eraseAll(list, true, false), + 'Only Erase Data': () => eraseAll(list, false, true), + '< Back': () => showApps(), }); }; } else { From c0f9c8b3e28b56680037a74f1666f0bac59c3cd9 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:38:12 +0100 Subject: [PATCH 054/101] Store GPS coords, for use on next start if user desires --- apps.json | 2 +- apps/astrocalc/ChangeLog | 2 ++ apps/astrocalc/astrocalc-app.js | 51 +++++++++++++++++++++++++++++---- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/apps.json b/apps.json index bbe0bbfcd..60b47dbd8 100644 --- a/apps.json +++ b/apps.json @@ -1018,7 +1018,7 @@ { "id": "astrocalc", "name": "Astrocalc", "icon": "astrocalc.png", - "version":"0.01", + "version":"0.02", "description": "Calculates interesting information on the sun and moon cycles for the current day based on your location.", "tags": "app,sun,moon,cycles,tool,outdoors", "allow_emulator":true, diff --git a/apps/astrocalc/ChangeLog b/apps/astrocalc/ChangeLog index 0c8adeb61..188fc287b 100644 --- a/apps/astrocalc/ChangeLog +++ b/apps/astrocalc/ChangeLog @@ -1 +1,3 @@ 0.01: Create astrocalc app +0.02: Store last GPS lock, can be used instead of waiting for new GPS on +start. diff --git a/apps/astrocalc/astrocalc-app.js b/apps/astrocalc/astrocalc-app.js index 318147b13..0b0c63658 100644 --- a/apps/astrocalc/astrocalc-app.js +++ b/apps/astrocalc/astrocalc-app.js @@ -1,8 +1,18 @@ /** + * BangleJS ASTROCALC + * * Inspired by: https://www.timeanddate.com + * + * Original Author: Paul Cockrell https://github.com/paulcockrell + * Created: April 2020 + * + * Calculate the Sun and Moon positions based on watch GPS and display graphically */ const SunCalc = require("suncalc.js"); +const storage = require("Storage"); +const LAST_GPS_FILE = "astrocalc.gps.json"; +let lastGPS = (storage.readJSON(LAST_GPS_FILE, 1) || null); function drawMoon(phase, x, y) { const moonImgFiles = [ @@ -296,22 +306,50 @@ function indexPageMenu(gps) { return E.showMenu(menu); } +function getCenterStringX(str) { + return (g.getWidth() - g.stringWidth(str)) / 2; +} + /** * GPS wait page, shows GPS locating animation until it gets a lock, then moves to the Sun page */ function drawGPSWaitPage() { - const img = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AW43GF1wwsFwYwqFwowoFw4wmFxIwdE5YAPF/4vM5nN6YAE5vMF8YtHGIgvhFpQxKF7AuOGA4vXFyAwGF63MFyIABF6xeWMC4UDLwvNGpAJG5gwSdhIIDRBLyWCIgcJHAgJJDoouQF4vMQoICBBJoeGFx6GGACIfHL6YvaX6gvZeCIdFc4gAFXogvGFxgwFDwovQCAguOGAnMMBxeG5guTGAggGGAwNKFySREcA3N5vM5gDBdpQvXEY4AKXqovGGCKbFF7AwPZQwvZGJgtGF7vGdQItG5gSIF7gASF/44WEzgwRF0wwHF1AwFF1QwDF1gvwAH4A/AFAA==")) - + const img = require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AW43GF1wwsFwYwqFwowoFw4wmFxIwdE5YAPF/4vM5nN6YAE5vMF8YtHGIgvhFpQxKF7AuOGA4vXFyAwGF63MFyIABF6xeWMC4UDLwvNGpAJG5gwSdhIIDRBLyWCIgcJHAgJJDoouQF4vMQoICBBJoeGFx6GGACIfHL6YvaX6gvZeCIdFc4gAFXogvGFxgwFDwovQCAguOGAnMMBxeG5guTGAggGGAwNKFySREcA3N5vM5gDBdpQvXEY4AKXqovGGCKbFF7AwPZQwvZGJgtGF7vGdQItG5gSIF7gASF/44WEzgwRF0wwHF1AwFF1QwDF1gvwAH4A/AFAA==")); + const str1 = "Astrocalc v0.02"; + const str2 = "Locating GPS"; + const str3 = "Please wait..."; + g.clear(); g.drawImage(img, 100, 50); g.setFont("6x8", 1); - g.drawString("Astrocalc v0.01", 80, 105); - g.drawString("Locating GPS", 85, 140); - g.drawString("Please wait...", 80, 155); + g.drawString(str1, getCenterStringX(str1), 105); + g.drawString(str2, getCenterStringX(str2), 140); + g.drawString(str3, getCenterStringX(str3), 155); + + if (lastGPS) { + lastGPS = JSON.parse(lastGPS); + lastGPS.time = new Date(); + + const str4 = "Press Button 3 to use last GPS"; + g.setColor("#d32e29"); + g.fillRect(0, 190, g.getWidth(), 215); + g.setColor("#ffffff"); + g.drawString(str4, getCenterStringX(str4), 200); + + setWatch(() => { + clearWatch(); + Bangle.setGPSPower(0); + lastGPS.time = new Date(); + m = indexPageMenu(lastGPS); + }, BTN3, {repeat: false}); + } + g.flip(); const DEBUG = false; if (DEBUG) { + clearWatch(); + const gps = { "lat": 56.45783133333, "lon": -3.02188583333, @@ -330,7 +368,10 @@ function drawGPSWaitPage() { Bangle.on('GPS', (gps) => { if (gps.fix === 0) return; + clearWatch(); + if (isNaN(gps.course)) gps.course = 0; + require("Storage").writeJSON(LAST_GPS_FILE, JSON.stringify(gps)); Bangle.setGPSPower(0); Bangle.buzz(); Bangle.setLCDPower(true); From 173969839e0a80e96b2d55065dc82382ce536cc7 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:39:32 +0100 Subject: [PATCH 055/101] Fix Changelog --- apps/astrocalc/ChangeLog | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/astrocalc/ChangeLog b/apps/astrocalc/ChangeLog index 188fc287b..60ef5da0a 100644 --- a/apps/astrocalc/ChangeLog +++ b/apps/astrocalc/ChangeLog @@ -1,3 +1,2 @@ 0.01: Create astrocalc app -0.02: Store last GPS lock, can be used instead of waiting for new GPS on -start. +0.02: Store last GPS lock, can be used instead of waiting for new GPS on start From e052a6e65fdaad4c14c99798ea7dd316cadf7345 Mon Sep 17 00:00:00 2001 From: Paul Cockrell Date: Sat, 18 Apr 2020 00:41:15 +0100 Subject: [PATCH 056/101] Remove repeated assignment of date to gps object --- apps/astrocalc/astrocalc-app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/astrocalc/astrocalc-app.js b/apps/astrocalc/astrocalc-app.js index 0b0c63658..6b848abda 100644 --- a/apps/astrocalc/astrocalc-app.js +++ b/apps/astrocalc/astrocalc-app.js @@ -339,7 +339,6 @@ function drawGPSWaitPage() { setWatch(() => { clearWatch(); Bangle.setGPSPower(0); - lastGPS.time = new Date(); m = indexPageMenu(lastGPS); }, BTN3, {repeat: false}); } From bf4a3e0321abc7007a1fc1acede9616ff4a9cd49 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 09:01:15 +0200 Subject: [PATCH 057/101] Added rclock app --- apps.json | 12 +++ apps/rclock/ChangeLog | 1 + apps/rclock/app-icon.js | 1 + apps/rclock/app.png | Bin 0 -> 1620 bytes apps/rclock/rclock.app.js | 163 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 177 insertions(+) create mode 100644 apps/rclock/ChangeLog create mode 100644 apps/rclock/app-icon.js create mode 100644 apps/rclock/app.png create mode 100644 apps/rclock/rclock.app.js diff --git a/apps.json b/apps.json index bbe0bbfcd..ac7181bb4 100644 --- a/apps.json +++ b/apps.json @@ -1291,6 +1291,18 @@ "name": "dane.img", "url": "app-icon.js", "evaluate": true + }, + { "id": "rclock", + "name": "Round clock with seconds, minutes and date", + "shortName":"Round Clock", + "icon": "app.png", + "version":"0.01", + "description": "Designed round clock with ticks for minutes and seconds", + "tags": "", + "storage": [ + {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.img","url":"app-icon.js","evaluate":true} + ] } ] } diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/rclock/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/rclock/app-icon.js b/apps/rclock/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/rclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/rclock/app.png b/apps/rclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 Date: Sat, 18 Apr 2020 11:17:50 +0200 Subject: [PATCH 058/101] Fix error in app.json --- apps.json | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps.json b/apps.json index ac7181bb4..89fd1a0a3 100644 --- a/apps.json +++ b/apps.json @@ -1291,19 +1291,18 @@ "name": "dane.img", "url": "app-icon.js", "evaluate": true - }, - { "id": "rclock", - "name": "Round clock with seconds, minutes and date", - "shortName":"Round Clock", - "icon": "app.png", - "version":"0.01", - "description": "Designed round clock with ticks for minutes and seconds", - "tags": "", - "storage": [ - {"name":"rclock.app.js","url":"app.js"}, - {"name":"rclock.img","url":"app-icon.js","evaluate":true} - ] } ] - } + }, + { "id": "rclock", + "name": "Round clock with seconds, minutes and date", + "shortName":"Round Clock", + "icon": "app.png", + "version":"0.01", + "description": "Designed round clock with ticks for minutes and seconds", + "tags": "", + "storage": [ + {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.img","url":"app-icon.js","evaluate":true} + ] ] From 8f562d817782203bdf250c7d60803b9ac3102b40 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:21:14 +0200 Subject: [PATCH 059/101] Fix error in app.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 89fd1a0a3..d7e857066 100644 --- a/apps.json +++ b/apps.json @@ -1305,4 +1305,5 @@ {"name":"rclock.app.js","url":"app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} ] + } ] From 06705a6e5d0a3de5db7131c6a56684a917b6a710 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:28:08 +0200 Subject: [PATCH 060/101] Fixes --- apps.json | 6 ++++-- apps/rclock/ChangeLog | 2 +- apps/rclock/rclock.app.js | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index d7e857066..dc768218b 100644 --- a/apps.json +++ b/apps.json @@ -1294,13 +1294,15 @@ } ] }, - { "id": "rclock", + { + "id": "rclock", "name": "Round clock with seconds, minutes and date", "shortName":"Round Clock", "icon": "app.png", "version":"0.01", "description": "Designed round clock with ticks for minutes and seconds", - "tags": "", + "tags": "clock", + "type": "clock", "storage": [ {"name":"rclock.app.js","url":"app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} diff --git a/apps/rclock/ChangeLog b/apps/rclock/ChangeLog index 5560f00bc..a8f708a0a 100644 --- a/apps/rclock/ChangeLog +++ b/apps/rclock/ChangeLog @@ -1 +1 @@ -0.01: New App! +0.01: First published version of app diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 27fbda772..c681e0588 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -104,6 +104,7 @@ } first = false; } + // Reset seconds if (seconds == 59) { g.setColor('#000000'); From 7216b188672dfe4f5141c3a0470c38128f089cae Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:48:22 +0200 Subject: [PATCH 061/101] Fix error in reference to files --- apps.json | 2 +- package.json | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index dc768218b..bf771882a 100644 --- a/apps.json +++ b/apps.json @@ -1304,7 +1304,7 @@ "tags": "clock", "type": "clock", "storage": [ - {"name":"rclock.app.js","url":"app.js"}, + {"name":"rclock.app.js","url":"rclock.app.js"}, {"name":"rclock.img","url":"app-icon.js","evaluate":true} ] } diff --git a/package.json b/package.json index 400385139..24793d86a 100644 --- a/package.json +++ b/package.json @@ -9,5 +9,8 @@ "scripts": { "test": "node bin/sanitycheck.js", "start": "npx http-server" + }, + "dependencies": { + "acorn": "^7.1.1" } } From a1f1da0341f4a8985e4f5baafcbdf1b1a1469f6a Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:52:30 +0200 Subject: [PATCH 062/101] Updated grey colors --- apps/rclock/rclock.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index c681e0588..405da7052 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#777777', - colorsec: '#444444', + colormin: '#999999', + colorsec: '#777777', width: 10, middle: screen.middle, center: screen.center, From afeff2c5761ed15d7164b1b3e338b7113ddee2b3 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 11:55:40 +0200 Subject: [PATCH 063/101] Updated grey colors --- apps/rclock/rclock.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 405da7052..25ca757cd 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#999999', - colorsec: '#777777', + colormin: '#bbbbbb', + colorsec: '#999999', width: 10, middle: screen.middle, center: screen.center, From 0a7a9e0b97652f96738c1a39e4bb6132c2aa9424 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:02:01 +0200 Subject: [PATCH 064/101] Align fonts --- apps/rclock/rclock.app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/rclock/rclock.app.js b/apps/rclock/rclock.app.js index 25ca757cd..bd8395116 100644 --- a/apps/rclock/rclock.app.js +++ b/apps/rclock/rclock.app.js @@ -20,7 +20,7 @@ font: 'Vector', size: 60, middle: screen.middle - 30, - center: screen.center + 5 , + center: screen.center, }, date: { color: '#f0af00', @@ -31,8 +31,8 @@ center: screen.center, }, circle: { - colormin: '#bbbbbb', - colorsec: '#999999', + colormin: '#eeeeee', + colorsec: '#bbbbbb', width: 10, middle: screen.middle, center: screen.center, @@ -149,6 +149,7 @@ // clean app screen g.clear(); + g.setFontAlign( 0, 0, 0); Bangle.loadWidgets(); Bangle.drawWidgets(); From 6d1e87a765de9a48dee5939d66aeff0a97f3760b Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:39:13 +0200 Subject: [PATCH 065/101] Added icons --- .DS_Store | Bin 0 -> 6148 bytes apps/.DS_Store | Bin 0 -> 6148 bytes apps/rclock/.DS_Store | Bin 0 -> 6148 bytes apps/rclock/app-icon.js | 2 +- apps/rclock/app.png | Bin 1620 -> 0 bytes apps/rclock/appp.png | Bin 0 -> 10357 bytes 6 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 .DS_Store create mode 100644 apps/.DS_Store create mode 100644 apps/rclock/.DS_Store delete mode 100644 apps/rclock/app.png create mode 100644 apps/rclock/appp.png diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..e9892b6bcf444f36764922b8e4fcf88ecca916a8 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4I%_5-~#-K2??Z%JxAx+@j_rm6?#VYi=A4u-_X<| zqMPSsEi#Bm4>y&Sg~k+lCr5eUH(oE}`EJ);>!>lNF#jv{Xd}rZGKew5pFG zR`+&jitBP{sao4bWBAbcXSFE?rnOx(A%SUjVITn#Xb8+}KG^xcgMXX3Z5S>vG!N$@uSMUZw^aNf&RBRL$6#K0_mq+u>r%+ZqEtEGfdC6p6LSC`6 zBO*G#>}Dbp5gEY^}dS)lX)N&paQ?HfPEhd+^{CLf&S^h;4J`ffUq0p-b(H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T01gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 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 TkibuO00000NkvXXu0mjfp7a2c literal 0 HcmV?d00001 From cdba3a32c22bc330ba64fd3ba7088349b49ad78f Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 12:42:03 +0200 Subject: [PATCH 066/101] FIx name error --- apps/rclock/{appp.png => app.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/rclock/{appp.png => app.png} (100%) diff --git a/apps/rclock/appp.png b/apps/rclock/app.png similarity index 100% rename from apps/rclock/appp.png rename to apps/rclock/app.png From 2f834a585632acdd4f0ea5fc78effcb86a4e0fb2 Mon Sep 17 00:00:00 2001 From: Fredrik Lautrup Date: Sat, 18 Apr 2020 13:00:59 +0200 Subject: [PATCH 067/101] Changes to permissions on file --- apps/rclock/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/rclock/.DS_Store diff --git a/apps/rclock/.DS_Store b/apps/rclock/.DS_Store deleted file mode 100644 index 5008ddfcf53c02e82d7eee2e57c38e5672ef89f6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 Date: Sat, 18 Apr 2020 13:08:23 +0200 Subject: [PATCH 068/101] Delete .DS_Store --- apps/.DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/.DS_Store diff --git a/apps/.DS_Store b/apps/.DS_Store deleted file mode 100644 index f1e36c314ed1b52c7092fec1d7f2c0441196819d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeHKI|>3Z5S>vG!N$@uSMUZw^aNf&RBRL$6#K0_mq+u>r%+ZqEtEGfdC6p6LSC`6 zBO*G#>}Dbp5gEY^}dS)lX)N&paQ?HfPEhd+^{CLf&S^h;4J`ffUq0p-b( Date: Sat, 18 Apr 2020 13:09:31 +0200 Subject: [PATCH 069/101] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index e9892b6bcf444f36764922b8e4fcf88ecca916a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4I%_5-~#-K2??Z%JxAx+@j_rm6?#VYi=A4u-_X<| zqMPSsEi#Bm4>y&Sg~k+lCr5eUH(oE}`EJ);>!>lNF#jv{Xd}rZGKew5pFG zR`+&jitBP{sao4bWBAbcXSFE?rnOx(A%SUjVITn#Xb8+}KG^xcgMXX Date: Sat, 18 Apr 2020 15:34:35 +0200 Subject: [PATCH 070/101] shorter JS file name --- apps.json | 6 +++--- apps/hidcam/{hidcam.app.js => app.js} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename apps/hidcam/{hidcam.app.js => app.js} (100%) diff --git a/apps.json b/apps.json index 1e6b5e945..0546d6f65 100644 --- a/apps.json +++ b/apps.json @@ -1295,14 +1295,14 @@ ] }, { "id": "hidcam", - "name": "HID camera shutter", - "shortName":"HID cam", + "name": "Camera shutter", + "shortName":"Cam shutter", "icon": "app.png", "version":"0.01", "description": "Enable HID, connect to your phone, start your camera and trigger the shot on your Bangle", "tags": "tools", "storage": [ - {"name":"hidcam.app.js","url":"hidcam.app.js"}, + {"name":"hidcam.app.js","url":"app.js"}, {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ] } diff --git a/apps/hidcam/hidcam.app.js b/apps/hidcam/app.js similarity index 100% rename from apps/hidcam/hidcam.app.js rename to apps/hidcam/app.js From 37e26d6139782852411b61328006860a38034c47 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:38:32 +0100 Subject: [PATCH 071/101] Create ChangeLog --- apps/gpsnav/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/gpsnav/ChangeLog diff --git a/apps/gpsnav/ChangeLog b/apps/gpsnav/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/gpsnav/ChangeLog @@ -0,0 +1 @@ +0.01: New App! From ed51586dd0afdf9dd2df5c315e031c41ed62b162 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:39:36 +0100 Subject: [PATCH 072/101] Add files via upload --- apps/gpsnav/README.md | 66 ++++++++++ apps/gpsnav/app-icon.js | 1 + apps/gpsnav/app.js | 224 ++++++++++++++++++++++++++++++++ apps/gpsnav/first_screen.jpg | Bin 0 -> 65452 bytes apps/gpsnav/gpsnav.jpg | Bin 0 -> 47970 bytes apps/gpsnav/icon.png | Bin 0 -> 1887 bytes apps/gpsnav/marked_screen.jpg | Bin 0 -> 65895 bytes apps/gpsnav/select_screen.jpg | Bin 0 -> 64877 bytes apps/gpsnav/waypoint_screen.jpg | Bin 0 -> 67409 bytes apps/gpsnav/waypoints.json | 23 ++++ 10 files changed, 314 insertions(+) create mode 100644 apps/gpsnav/README.md create mode 100644 apps/gpsnav/app-icon.js create mode 100644 apps/gpsnav/app.js create mode 100644 apps/gpsnav/first_screen.jpg create mode 100644 apps/gpsnav/gpsnav.jpg create mode 100644 apps/gpsnav/icon.png create mode 100644 apps/gpsnav/marked_screen.jpg create mode 100644 apps/gpsnav/select_screen.jpg create mode 100644 apps/gpsnav/waypoint_screen.jpg create mode 100644 apps/gpsnav/waypoints.json diff --git a/apps/gpsnav/README.md b/apps/gpsnav/README.md new file mode 100644 index 000000000..80c6c1d00 --- /dev/null +++ b/apps/gpsnav/README.md @@ -0,0 +1,66 @@ +## gpsnav - navigate to waypoints + +The app is aimed at small boat navigation although it can also be used to mark the location of your car, bicycle etc and then get directions back to it. Please note that it would be foolish in the extreme to rely on this as your only boat navigation aid! + +The app displays direction of travel (course), speed, direction to waypoint (bearing) and distance to waypoint. The screen shot below is before the app has got a GPS fix. + +![](first_screen.jpg) + +The large digits are the course and speed. The top of the display is a linear compass which displays the direction of travel when a fix is received and you are moving. The blue text is the name of the current waypoint. NONE means that there is no waypoint set and so bearing and distance will remain at 0. To select a waypoint, press BTN2 (middle) and wait for the blue text to turn white. Then use BTN1 and BTN3 to select a waypoint. The waypoint choice is fixed by pressing BTN2 again. In the screen shot below a waypoint giving the location of Stone Henge has been selected. + +![](waypoint_screen.jpg) + +The display shows that Stone Henge is 108.75Km from the location where I made the screenshot and the direction is 255 degrees - approximately west. The display shows that I am currently moving approximately north - albeit slowly!. The position of the blue circle indicates that I need to turn left to get on course to Stone Henge. When the circle and red triangle line up you are on course and course will equal bearing. + +### Marking Waypoints + +The app lets you mark your current location as follows. There are vacant slots in the waypoint file which can be allocated a location. In the distributed waypoint file these are labelled WP0 to WP4. Select one of these - WP2 is shown below. + +![](select_screen.jpg) + +Bearing and distance are both zero as WP1 has currently no GPS location associated with it. To mark the location, press BTN2. + +![](marked_screen.jpg) + +The app indicates that WP2 is now marked by adding the prefix @ to it's name. The distance should be small as shown in the screen shot as you have just marked your current location. + +### Waypoint JSON file + +When the app is loaded from the app loader, a file named waypoints.json is loaded along with the javascript etc. The file has the following contents: + +~~~ +[ + { + "mark":0, + "name":"NONE" + }, + { + "mark":1, + "name":"No10", + "lat":51.5032, + "lon":-0.1269 + }, + { + "mark":1, + "name":"Stone", + "lat":51.1788, + "lon":-1.8260 + }, + { "name":"WP0" }, + { "name":"WP1" }, + { "name":"WP2" }, + { "name":"WP3" }, + { "name":"WP4" } +] +~~~ + +The file contains the initial NONE waypoint which is useful if you just want to display course and speed. The next two entries are waypoints to No 10 Downing Street and to Stone Henge - obtained from Google Maps. The last five entries are entries which can be *marked*. + +You add and delete entries using the Web IDE to load and then save the file from and to watch storage. The app itself does not limit the number of entries although it does load the entire file into RAM which will obviously limit this. + +I plan to release an accompanying watch app to edit waypoint files in the near future and a way to download your own waypoint file using the app loader. + + + + + diff --git a/apps/gpsnav/app-icon.js b/apps/gpsnav/app-icon.js new file mode 100644 index 000000000..890981d5a --- /dev/null +++ b/apps/gpsnav/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AFmACysDC9+IC6szC/8AgUgLwYXBPAgLDAA8kC5MyC5cyogXHmYiDURMkDAMzC4JgBmcyoAXMGANCC4YDBkgXMHwVEC4hQDC5kyF4kjJ4QAMOgMjC4eCohGNMARbCC4ODkilLAAQSBCYJ3EmYVLhAWCCgQaCAAUwCpowCFwYADIRAYHC4wZFRQIAGnAhJXgwAFxAYHwC9JFwiQCFhIZISAQwDX5sCoQTCDYUjUpAAFglElAXDmS9JAAtEoUyC4ckkbvMC4QQBC4YeBC5sEB4IXEkgfBJBkEH4QXCCYMkoQXMHwcIC4ZQCUpYMDC4oiBC5YEDC40AkCRNAAIXBCJ4X2URgAJhAXvCyoA/ACoA=")) \ No newline at end of file diff --git a/apps/gpsnav/app.js b/apps/gpsnav/app.js new file mode 100644 index 000000000..2a480410c --- /dev/null +++ b/apps/gpsnav/app.js @@ -0,0 +1,224 @@ +const Yoff = 40; +var pal2color = new Uint16Array([0x0000,0xffff,0x07ff,0xC618],0,2); +var buf = Graphics.createArrayBuffer(240,50,2,{msb:true}); + +function flip(b,y) { + g.drawImage({width:240,height:50,bpp:2,buffer:b.buffer, palette:pal2color},0,y); + b.clear(); +} + +var brg=0; +var wpindex=0; +const labels = ["N","NE","E","SE","S","SW","W","NW"]; + +function drawCompass(course) { + buf.setColor(1); + buf.setFont("Vector",16); + var start = course-90; + if (start<0) start+=360; + buf.fillRect(28,45,212,49); + var xpos = 30; + var frag = 15 - start%15; + if (frag<15) xpos+=frag; else frag = 0; + for (var i=frag;i<=180-frag;i+=15){ + var res = start + i; + if (res%90==0) { + buf.drawString(labels[Math.floor(res/45)%8],xpos-8,0); + buf.fillRect(xpos-2,25,xpos+2,45); + } else if (res%45==0) { + buf.drawString(labels[Math.floor(res/45)%8],xpos-12,0); + buf.fillRect(xpos-2,30,xpos+2,45); + } else if (res%15==0) { + buf.fillRect(xpos,35,xpos+1,45); + } + xpos+=15; + } + if (wpindex!=0) { + var bpos = brg - course; + if (bpos>180) bpos -=360; + if (bpos<-180) bpos +=360; + bpos+=120; + if (bpos<30) bpos = 14; + if (bpos>210) bpos = 226; + buf.setColor(2); + buf.fillCircle(bpos,40,8); + } + flip(buf,Yoff); +} + +//displayed heading +var heading = 0; +function newHeading(m,h){ + var s = Math.abs(m - h); + var delta = 1; + if (s<2) return h; + if (m > h){ + if (s >= 180) { delta = -1; s = 360 - s;} + } else if (m <= h){ + if (s < 180) delta = -1; + else s = 360 -s; + } + delta = delta * (1 + Math.round(s/15)); + heading+=delta; + if (heading<0) heading += 360; + if (heading>360) heading -= 360; + return heading; +} + +var course =0; +var speed = 0; +var satellites = 0; +var wp; +var dist=0; + +function radians(a) { + return a*Math.PI/180; +} + +function degrees(a) { + var d = a*180/Math.PI; + return (d+360)%360; +} + +function bearing(a,b){ + var delta = radians(b.lon-a.lon); + var alat = radians(a.lat); + var blat = radians(b.lat); + var y = Math.sin(delta) * Math.cos(blat); + var x = Math.cos(alat)*Math.sin(blat) - + Math.sin(alat)*Math.cos(blat)*Math.cos(delta); + return Math.round(degrees(Math.atan2(y, x))); +} + +function distance(a,b){ + var x = radians(a.lon-b.lon) * Math.cos(radians((a.lat+b.lat)/2)); + var y = radians(b.lat-a.lat); + return Math.round(Math.sqrt(x*x + y*y) * 6371000); +} + +var selected = false; + +function drawN(){ + buf.setColor(1); + buf.setFont("6x8",2); + buf.drawString("o",100,0); + buf.setFont("6x8",1); + buf.drawString("kph",220,40); + buf.setFont("Vector",40); + var cs = course.toString(); + cs = course<10?"00"+cs : course<100 ?"0"+cs : cs; + buf.drawString(cs,10,0); + var txt = (speed<10) ? speed.toFixed(1) : Math.round(speed); + buf.drawString(txt,140,4); + flip(buf,Yoff+70); + buf.setColor(1); + buf.setFont("Vector",20); + var bs = brg.toString(); + bs = brg<10?"00"+bs : brg<100 ?"0"+bs : bs; + buf.setColor(3); + buf.drawString("Brg: ",0,0); + buf.drawString("Dist: ",0,30); + buf.setColor(selected?1:2); + buf.drawString(wp.name,140,0); + buf.setColor(1); + buf.drawString(bs,60,0); + if (dist<1000) + buf.drawString(dist.toString()+"m",60,30); + else + buf.drawString((dist/1000).toFixed(2)+"Km",60,30); + flip(buf,Yoff+130); + g.setFont("6x8",1); + g.setColor(0,0,0); + g.fillRect(10,230,60,239); + g.setColor(1,1,1); + g.drawString("Sats " + satellites.toString(),10,230); +} + +var savedfix; + +function onGPS(fix) { + savedfix = fix; + if (fix!==undefined){ + course = isNaN(fix.course) ? course : Math.round(fix.course); + speed = isNaN(fix.speed) ? speed : fix.speed; + satellites = fix.satellites; + } + if (Bangle.isLCDOn()) { + if (fix!==undefined && fix.fix==1){ + dist = distance(fix,wp); + if (isNaN(dist)) dist = 0; + brg = bearing(fix,wp); + if (isNaN(brg)) brg = 0; + } + drawN(); + } +} + +var intervalRef; + +function clearTimers() { + if(intervalRef) {clearInterval(intervalRef);} +} + +function startTimers() { + intervalRefSec = setInterval(function() { + newHeading(course,heading); + if (course!=heading) drawCompass(heading); + },200); +} + +Bangle.on('lcdPower',function(on) { + if (on) { + g.clear(); + Bangle.drawWidgets(); + startTimers(); + drawAll(); + }else { + clearTimers(); + } +}); + +function drawAll(){ + g.setColor(1,0.5,0.5); + g.fillPoly([120,Yoff+50,110,Yoff+70,130,Yoff+70]); + g.setColor(1,1,1); + drawN(); + drawCompass(heading); +} + +var waypoints = require("Storage").readJSON("waypoints.json")||[{name:"NONE"}]; +wp=waypoints[0]; + +function nextwp(inc){ + if (!selected) return; + wpindex+=inc; + if (wpindex>=waypoints.length) wpindex=0; + if (wpindex<0) wpindex = waypoints.length-1; + wp = waypoints[wpindex]; + drawN(); +} + +function doselect(){ + if (selected && waypoints[wpindex].mark===undefined && savedfix.fix) { + waypoints[wpindex] ={mark:1, name:"@"+wp.name, lat:savedfix.lat, lon:savedfix.lon}; + wp = waypoints[wpindex]; + require("Storage").writeJSON("waypoints.json", waypoints); + } + selected=!selected; + drawN(); +} + +g.clear(); +Bangle.setLCDBrightness(1); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +// load widgets can turn off GPS +Bangle.setGPSPower(1); +drawAll(); +startTimers(); +Bangle.on('GPS', onGPS); +// Toggle selected +setWatch(nextwp.bind(null,-1), BTN1, {repeat:true,edge:"falling"}); +setWatch(doselect, BTN2, {repeat:true,edge:"falling"}); +setWatch(nextwp.bind(null,1), BTN3, {repeat:true,edge:"falling"}); + diff --git a/apps/gpsnav/first_screen.jpg b/apps/gpsnav/first_screen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..34fbe1b506bf3b8951abadeac5589b11b202dc0f GIT binary patch literal 65452 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 AZvX%Q literal 0 HcmV?d00001 diff --git a/apps/gpsnav/gpsnav.jpg b/apps/gpsnav/gpsnav.jpg new file mode 100644 index 0000000000000000000000000000000000000000..975fe39032cb28fc755874e231842684fe3a73bb GIT binary patch literal 47970 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

M#X#R-X}cOVGl^%PqF>L!1JtcqDhm zdBLy7-w$}lTh?JWa<;=1OtJt-8<=p!bq5@A#ct`J5PU^rWj>h(=MU5zGo3k0<4I@1|hjEoZ}o0)p&eV&{}D% ze$Y}-{3M4VqwZH8g!Zq=tIrkqgG$nL>wPxxUrBur%^M7PMF=5%2yFDgti3nlFN!tY zay<)CMz^@O-x|7P`E18I1F81p;8jP&JQwn_8F*WmEpEQ^_3AH)I#srlJkZ@qaLI;M z;|MnuVh6bOtyuhNr_B|!OMFU9>>fg+DTFLHj)3H2K9%_!rg)RYFi9-`0B>bgY%nZ- zY-b>Y$G<&2>!G&zgRf}13l_dIWz1-tgStVSpYJX|D%L(AU^?8wei!B)8bANk{zvpl zPOE(bUI4`4amU^7^{qCzl5J{I+!Y`UdK_l4{3rhaAFzHkqMz~^pZ(?jV!Y;h1*jB@ zv0_<_WEa6FuOhW=blXdb=1CXstAIyd7b3G_{{WD(f4F~{u7^$k0FSGWqyGTt6|BJ3 z(HqOs;kIGEIY|r~oZxX>b^A$YZ!N8}6knL|eGe7a=^ydqYyR_pBV2y5)?fEu`O=7^ zvCi7uNp&P^HzI83wmy}a@fSeTMU+~CCfNcmNWjn6zw1{t-}TnNjb8YR{{SFJ{{Y-y z=T|L-J&z@`fg`pBayOhG%9_!xcCjoEud&5gw*LT+RQ~{b`c!TA$K(G1p-~l~o7oVU zm*v~WH)9^(=bE8~Wnw_V86&aAc=}eE?f(D+ti}6{{^_i)E`>QQAu)zwl1c0ADX+(kAb+hN@Gs_Tam(Q~Srs7+qn)9-=bn`7)s7oje6<|ppL4q(%85VJ z5BCT2rPROU)(^-307I#eLvl@ss*Ixr@ssrb0QFUgAPX2Fj|6_ap4Ah5$bS#yYUJPQ zht+C?_b`O>?0FT+pOo=|)YAErm6An~l!shn9B_TA75@NG{{Te(bs+x$Qz!fD{HnVd zK-aTRHX}TQmKYrO`MaLAy8D*SA(DTLGF;^s`lT1@in5~>X-hyN&KrQd6I5gK_1Y60HbPv z0LBkE$4d2EJ9w;gg}Ai=T6Sc90pkPISD0FV?8*GA)rb6mZT|r4tA8O{)7aW8L(+ax zWd*vZ92~Iw#3{mpeFbLQ*us28HkeC!M;-aW86!TKtt0-b52OD8=v583{Ekxn6aN4~ ztt3&dY~Zx=C4gb2kz;e*sa*b@tBuli8{H;(ZR}(ylOLFN`MUmOS9y2$Er09bKlB>& zX#W7?_wgUria!usmg4T?Qqm`B*oH=83i}*)$o(s^ourS#7B=d~W3+pRuI^26w*LU~ z2fF&V{)Ju5*Zhk5cl*(QDzyFMDQ?d1>{iLH+S;o8rqj$myNMm^GSf_tUAfe)Z{(22 z6YUBQ1P@$;Tdn^9BQ>Y}c(4A1DyN430OTX9f7eE>B-tx-nA5CaeKPXPkcbNmaB>O! z>k3(3Ee7Tx$WCKsNVHQ8(5de{EDC-SZ;@BTj1 O{<@#%S|_lrq5s*41p!O| literal 0 HcmV?d00001 diff --git a/apps/gpsnav/icon.png b/apps/gpsnav/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f899683d1d7e98b906c52bb0a5913de6f4dd2534 GIT binary patch literal 1887 zcmV-l2cY`(ry)@ zWg;nB2-><0R?!l+PBTp>?PycSfGwlYQ9@gxDi^5^Y!XysZ9`Hv!b-Z9ktKmZOG1;1 zCXVAvocMaqw;z!+C)oJ-up{jU&#!a&-tT!Hzu)Ekj)D8QkN;mB`Dd_r^P7X;l9Pjx zvvYyRCa<4=UQP~$oSjq9a;Gm;A}5Dz8F=jyHG+^e4tG$u`R$Hae0FUrS0IWbM zCMNh7<>Hae0420MdhPLrpOlM776XTGP!)j3qxZL6fv%nM{B=n=IV+3j}L&T$&Cy2NL|Z1ywhXg^}xUB_|UUE>&v^4ZV4e*T$c z6s_+xJvRAy_unUgh*(*o4OCWE^79H7A57O|{v>Vin)i>jHE|~6KF0_i~U{%gVDj4ZUBY__!88|{>mj)A_OwZjAb6Qdc%y{TwQc@h&! z_AV;2ps;i~JT9kU=(Fn$2X<{AJXZVS1^@t0HzkU7Pw+bc;M}REg{}66dO;Ab0H_$~ z>%r$;m!Z$i{Uyh7LP~m4H2?su_Qt;gcp^#+01RPZ$jiH`*m{Uig{nB(cK^w~>A0LM zrN6G|9E>5Rr_ zrRtEp6F*V8y`O--<>0kA<1I#mx*DJO7bK0#$>3@ar!=X60a&UV13EVc}j)QO~NW$2w~pc zy+YAJ2%$&;q71A*(XZC>?6a=%@Qz_u@F8Cy!rrZYtk9@|c;e&88KIQEM+t3FWUJoa zy_f_g8+f{YxG*62cX=iwPu+F~^MesSrEEn7??2ghM^;2)54iURXPNN16( z*pQV149!2raYX)NE{fm3@PqC# zpWmV`Tm{wFSE4hp039*nftdyX;9~D6h8-R(%bvvQ%r9Y5j33)jvF$mj8YJ(;$6l^k z=N!3h5qx8qymA)$tAB>W;Yk{|LVXM0^}L1htZT?&$3ZB5_}f*u?mbo3u)QLNX!JZPI3Z z#IRGeF$W^TgZ@T}mXr+~t=;p2*Ewp85l;cM2n?}2R$0B%pi^B+6ieB(mOZb&v1Vam zNttQxysNP$2=Ms(EsfSx^`v|ra65)yi4osQ1ZuNxt^PFnUZ2Sx2e3Y_0g%%Gu;Z2e z7Xg@${$kJ5KG)chfxeyx0HCmR`94bNs#Ge{l$OyWw&xG3)EPf3u#|QZ2rpSHx3|S> z_aN6B9-oXTfEml^V9mqIh4I9_{!-0Om(#J|IA^Y|pk&#W4bN1c601q{5aKvasnzM% z6+X1I(ppiqI+1t)n4?o&oBfP{oKE!1KDY1H`r6~o`UoGk4c)l<^Y-?3(IZ2&0W+Xn zxW-y$t*B~Amg1~*_MO?!C>72m8{bdZxSvkZ{buANgnzX+}uL(%f;Ug8Y8OUJO z2bigCnGch+vvTpsie>w*yAO2+&dbRm>%Wvnjq(BkK9rL~Rs&h->}!;uUrvtuxQ~0p Ze*jRY!kx=d0W$yq002ovPDHLkV1iy}i`f7G literal 0 HcmV?d00001 diff --git a/apps/gpsnav/marked_screen.jpg b/apps/gpsnav/marked_screen.jpg new file mode 100644 index 0000000000000000000000000000000000000000..accd3b15fe5fa0996c51ada2f75ddd416dd17394 GIT binary patch literal 65895 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%0D85DN}Kju4Ys-^?RDWah8DK1Yt!XB1!a-x5(? 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

SKQuyodtT#X^!9_vAdcfo!M@gV% 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

2$hmvlvTQ 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 literal 0 HcmV?d00001 diff --git a/apps/gpsnav/waypoints.json b/apps/gpsnav/waypoints.json new file mode 100644 index 000000000..143316b19 --- /dev/null +++ b/apps/gpsnav/waypoints.json @@ -0,0 +1,23 @@ +[ + { + "mark":0, + "name":"NONE" + }, + { + "mark":1, + "name":"No10", + "lat":51.5032, + "lon":-0.1269 + }, + { + "mark":1, + "name":"Stone", + "lat":51.1788, + "lon":-1.8260 + }, + { "name":"WP0" }, + { "name":"WP1" }, + { "name":"WP2" }, + { "name":"WP3" }, + { "name":"WP4" } +] \ No newline at end of file From 73366a600cdf52d0f108f2aacd7542ee502bb583 Mon Sep 17 00:00:00 2001 From: jeffmer Date: Sat, 18 Apr 2020 14:44:00 +0100 Subject: [PATCH 073/101] Update apps.json --- apps.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps.json b/apps.json index 0c97b9e57..0b7001a5e 100644 --- a/apps.json +++ b/apps.json @@ -291,6 +291,18 @@ {"name":"gpsrec.wid.js","url":"widget.js"} ] }, + { "id": "gpsnav", + "name": "GPS Navigation", + "icon": "icon.png", + "version":"0.01", + "description": "Displays GPS Course and Speed, + Directions to waypoint and waypoint recording", + "tags": "tool,outdoors,gps", + "storage": [ + {"name":"gpsnav.app.js","url":"app.js"}, + {"name":"waypoints.json","url":"waypoints.json","evaluate":false}, + {"name":"gpsnav.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "heart", "name": "Heart Rate Recorder", "icon": "app.png", From 696afd7f6bae48410d27df696298b239b31c1f3f Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:08:33 +0200 Subject: [PATCH 074/101] ble hid control is removed from require and is now hard written in app --- apps/hidcam/app.js | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 6a4150673..f529deff2 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -1,16 +1,46 @@ -var controls = require("ble_hid_controls"); var storage = require('Storage'); const settings = storage.readJSON('setting.json',1) || { HID: false }; +// hidcontrol module selective and manual import : +report = new Uint8Array([ + 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) + 0x09, 0x01, // USAGE (Consumer Control) + 0xa1, 0x01, // COLLECTION (Application) + // -------------------- common global items + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit + // -------------------- misc bits + 0x95, 0x05, // REPORT_COUNT (5) + 0x09, 0xb5, // USAGE (Scan Next Track) + 0x09, 0xb6, // USAGE (Scan Previous Track) + 0x09, 0xb7, // USAGE (Stop) + 0x09, 0xcd, // USAGE (Play/Pause) + 0x09, 0xe2, // USAGE (Mute) + 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs + // -------------------- volume up/down bits + 0x95, 0x02, // REPORT_COUNT (2) + 0x09, 0xe9, // USAGE (Volume Up) + 0x09, 0xea, // USAGE (Volume Down) + 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs + // -------------------- padding bit + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Cnst,Ary,Abs) + 0xc0 // END_COLLECTION +]); +function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } +volumeUp = function(cb) { p(0x20,cb) }; +//end of manual selective import + g.clear(); E.showMessage('BTN2 to trigger','camTrigger'); Bangle.loadWidgets(); Bangle.drawWidgets(); if (settings.HID) { - NRF.setServices(undefined, { hid : controls.report }); - shotTrigger = function() {controls.volumeUp();}; + NRF.setServices(undefined, { hid : report }); + shotTrigger = function() {volumeUp();}; } else { E.showMessage('HID disabled'); setTimeout(load, 1000); From 41d206cdbe03461808b54f71149f6598b7ac0a24 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:24:33 +0200 Subject: [PATCH 075/101] typos in code and no more useless timeout --- apps/hidcam/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index f529deff2..9117d94f5 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -33,6 +33,8 @@ function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }) volumeUp = function(cb) { p(0x20,cb) }; //end of manual selective import +NRF.setServices(undefined, { hid : report }); + g.clear(); E.showMessage('BTN2 to trigger','camTrigger'); Bangle.loadWidgets(); @@ -50,7 +52,6 @@ setWatch(function(e){ E.showMessage('capture'); Bangle.beep(); shotTrigger(); - set.Timeout(load,1000); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From fc6d6aa4bbe1fdfefade4a0e85ab96460d1feda2 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:41:43 +0200 Subject: [PATCH 076/101] hid code correction --- apps/hidcam/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 9117d94f5..e114863cc 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -30,7 +30,7 @@ report = new Uint8Array([ 0xc0 // END_COLLECTION ]); function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } -volumeUp = function(cb) { p(0x20,cb) }; +volumeUp = function(cb) { p(0x80,cb) }; //end of manual selective import NRF.setServices(undefined, { hid : report }); From b58069fba13b50bba26dadf667dc55616d64bdc2 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 16:52:30 +0200 Subject: [PATCH 077/101] massive rewrite with really heavy inspiration from music control app --- apps/hidcam/app.js | 89 +++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 48 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index e114863cc..57d4a6f05 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -2,58 +2,51 @@ var storage = require('Storage'); const settings = storage.readJSON('setting.json',1) || { HID: false }; -// hidcontrol module selective and manual import : -report = new Uint8Array([ - 0x05, 0x0c, // USAGE_PAGE (Consumer Devices) - 0x09, 0x01, // USAGE (Consumer Control) - 0xa1, 0x01, // COLLECTION (Application) - // -------------------- common global items - 0x15, 0x00, // LOGICAL_MINIMUM (0) - 0x25, 0x01, // LOGICAL_MAXIMUM (1) - 0x75, 0x01, // REPORT_SIZE (1) - each field occupies 1 bit - // -------------------- misc bits - 0x95, 0x05, // REPORT_COUNT (5) - 0x09, 0xb5, // USAGE (Scan Next Track) - 0x09, 0xb6, // USAGE (Scan Previous Track) - 0x09, 0xb7, // USAGE (Stop) - 0x09, 0xcd, // USAGE (Play/Pause) - 0x09, 0xe2, // USAGE (Mute) - 0x81, 0x06, // INPUT (Data,Var,Rel) - relative inputs - // -------------------- volume up/down bits - 0x95, 0x02, // REPORT_COUNT (2) - 0x09, 0xe9, // USAGE (Volume Up) - 0x09, 0xea, // USAGE (Volume Down) - 0x81, 0x02, // INPUT (Data,Var,Abs) - absolute inputs - // -------------------- padding bit - 0x95, 0x01, // REPORT_COUNT (1) - 0x81, 0x01, // INPUT (Cnst,Ary,Abs) - 0xc0 // END_COLLECTION -]); -function p(c,cb) { NRF.sendHIDReport(c, function() { NRF.sendHIDReport(0, cb) }); } -volumeUp = function(cb) { p(0x80,cb) }; -//end of manual selective import - -NRF.setServices(undefined, { hid : report }); - -g.clear(); -E.showMessage('BTN2 to trigger','camTrigger'); -Bangle.loadWidgets(); -Bangle.drawWidgets(); +var sendHid, camShot, profile; if (settings.HID) { - NRF.setServices(undefined, { hid : report }); - shotTrigger = function() {volumeUp();}; + profile = 'camShutter'; + sendHid = function (code, cb) { + try { + NRF.sendHIDReport([1,code], () => { + NRF.sendHIDReport([1,0], () => { + if (cb) cb(); + }); + }); + } catch(e) { + print(e); + } + }; + camShot = function (cb) { sendHid(0x80, cb); }; } else { E.showMessage('HID disabled'); setTimeout(load, 1000); } - -setWatch(function(e){ - E.showMessage('capture'); - Bangle.beep(); - shotTrigger(); +function drawApp() { g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - E.showMessage('BTN2 to trigger','camTrigger'); -},BTN2,{ repeat:true, edge:'falling' }); + g.setFont("6x8",2); + g.setFontAlign(0,0); + g.drawString(profile, 120, 120); + const d = g.getWidth() - 18; + + function c(a) { + return { + width: 8, + height: a.length, + bpp: 1, + buffer: (new Uint8Array(a)).buffer + }; + } + + g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); +} + +if (camShot) { + setWatch(function(e) { + E.showMessage('camShot !'); + setTimeout(drawApp, 1000); + camShot(() => {}); + }, BTN2, { edge:"falling",repeat:true,debounce:50}); + + drawApp(); +} From 58e826accc018bbc638721f822b105959a19df52 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:01:01 +0200 Subject: [PATCH 078/101] adding widgets --- apps/hidcam/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 57d4a6f05..c3c672d4c 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -24,6 +24,8 @@ if (settings.HID) { } function drawApp() { g.clear(); + Bangle.loadWidgets() + Bangle.drawWidgets() g.setFont("6x8",2); g.setFontAlign(0,0); g.drawString(profile, 120, 120); From 63526c49e227a423eea5eaab25226c029d3e37b9 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:08:01 +0200 Subject: [PATCH 079/101] using app icon instead of text --- apps/hidcam/app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index c3c672d4c..6e599959c 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -26,9 +26,10 @@ function drawApp() { g.clear(); Bangle.loadWidgets() Bangle.drawWidgets() - g.setFont("6x8",2); - g.setFontAlign(0,0); - g.drawString(profile, 120, 120); +// g.setFont("6x8",2); +// g.setFontAlign(0,0); +// g.drawString(profile, 120, 120); + g.drawImage(storage.read("hidcam.img"),120,120) const d = g.getWidth() - 18; function c(a) { From aa168c3d5c5dce983dc4f3a52a24bd5e1d435868 Mon Sep 17 00:00:00 2001 From: fredericrous Date: Sat, 18 Apr 2020 16:30:05 +0100 Subject: [PATCH 080/101] Fix App Calculator issues MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Javascript rounded float issues - Reset after equals wasn't done properly - Introduce unit tests 🤗 --- apps.json | 4 +- apps/calculator/ChangeLog | 1 + apps/calculator/app.js | 146 +++++++++++++------- apps/calculator/tests.html | 273 +++++++++++++++++++++++++++++++++++++ 4 files changed, 369 insertions(+), 55 deletions(-) create mode 100644 apps/calculator/tests.html diff --git a/apps.json b/apps.json index 0c97b9e57..9bd4ee6fb 100644 --- a/apps.json +++ b/apps.json @@ -1264,8 +1264,8 @@ "name": "Calculator", "shortName":"Calculator", "icon": "calculator.png", - "version":"0.01", - "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus. Push button1 and 3 to navigate up/down, tap right or left to navigate the sides, push button 2 to select.", + "version":"0.02", + "description": "Basic calculator reminiscent of MacOs's one. Handy for small calculus.", "tags": "app,tool", "storage": [ {"name":"calculator.app.js","url":"app.js"}, diff --git a/apps/calculator/ChangeLog b/apps/calculator/ChangeLog index 5560f00bc..3b9b23270 100644 --- a/apps/calculator/ChangeLog +++ b/apps/calculator/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: fix precision rounding issue + no reset when equals pressed diff --git a/apps/calculator/app.js b/apps/calculator/app.js index 91dd7c49d..ad26d2d22 100644 --- a/apps/calculator/app.js +++ b/apps/calculator/app.js @@ -144,19 +144,57 @@ function drawKey(name, k, selected) { g.drawString(k.val || name, k.xy[0] + RIGHT_MARGIN + rMargin, k.xy[1] + BOTTOM_MARGIN + bMargin); } +function getIntWithPrecision(x) { + var xStr = x.toString(); + var xRadix = xStr.indexOf('.'); + var xPrecision = xRadix === -1 ? 0 : xStr.length - xRadix - 1; + return { + num: Number(xStr.replace('.', '')), + p: xPrecision + }; +} + +function multiply(x, y) { + var xNum = getIntWithPrecision(x); + var yNum = getIntWithPrecision(y); + return xNum.num * yNum.num / Math.pow(10, xNum.p + yNum.p); +} + +function divide(x, y) { + var xNum = getIntWithPrecision(x); + var yNum = getIntWithPrecision(y); + return xNum.num / yNum.num / Math.pow(10, xNum.p - yNum.p); +} + +function sum(x, y) { + let xNum = getIntWithPrecision(x); + let yNum = getIntWithPrecision(y); + + let diffPrecision = Math.abs(xNum.p - yNum.p); + if (diffPrecision > 0) { + if (xNum.p > yNum.p) { + yNum.num = yNum.num * Math.pow(10, diffPrecision); + } else { + xNum.num = xNum.num * Math.pow(10, diffPrecision); + } + } + return (xNum.num + yNum.num) / Math.pow(10, Math.max(xNum.p, yNum.p)); +} + +function subtract(x, y) { + return sum(x, -y); +} + function doMath(x, y, operator) { - // might not be a number due to display of dot "." algo - x = Number(x); - y = Number(y); switch (operator) { case '/': - return x / y; + return divide(x, y); case '*': - return x * y; + return multiply(x, y); case '+': - return x + y; + return sum(x, y); case '-': - return x - y; + return subtract(x, y); } } @@ -204,7 +242,7 @@ function displayOutput(num) { } len = (num + '').length; - if (numNumeric < 0) { + if (numNumeric < 0 || (numNumeric === 0 && 1/numNumeric === -Infinity)) { // minus is not available in font 7x11Numeric7Seg, we use Vector g.setFont('Vector', 20); g.drawString('-', 220 - (len * 15), 10); @@ -214,18 +252,33 @@ function displayOutput(num) { } g.drawString(num, 220 - (len * 15) + minusMarge, 10); } - +var wasPressedEquals = false; +var hasPressedNumber = false; function calculatorLogic(x) { - if (hasPressedEquals) { - currNumber = results; + if (wasPressedEquals && hasPressedNumber !== false) { prevNumber = null; - operator = null; - results = null; - isDecimal = null; - displayOutput(currNumber); - hasPressedEquals = false; + currNumber = hasPressedNumber; + wasPressedEquals = false; + hasPressedNumber = false; + return; } - if (prevNumber != null && currNumber != null && operator != null) { + if (hasPressedEquals) { + if (hasPressedNumber) { + prevNumber = null; + hasPressedNumber = false; + operator = null; + } else { + currNumber = null; + prevNumber = results; + } + hasPressedEquals = false; + wasPressedEquals = true; + } + + if (currNumber == null && operator != null && '/*-+'.indexOf(x) !== -1) { + operator = x; + displayOutput(prevNumber); + } else if (prevNumber != null && currNumber != null && operator != null) { // we execute the calculus only when there was a previous number entered before and an operator results = doMath(prevNumber, currNumber, operator); operator = x; @@ -255,8 +308,10 @@ function buttonPress(val) { operator = null; } else { keys.R.val = 'AC'; - drawKey('R', keys.R); + drawKey('R', keys.R, true); } + wasPressedEquals = false; + hasPressedNumber = false; displayOutput(0); break; case '%': @@ -265,11 +320,12 @@ function buttonPress(val) { } else if (currNumber != null) { displayOutput(currNumber /= 100); } + hasPressedNumber = false; break; case 'N': if (results != null) { displayOutput(results *= -1); - } else if (currNumber != null) { + } else { displayOutput(currNumber *= -1); } break; @@ -278,6 +334,7 @@ function buttonPress(val) { case '-': case '+': calculatorLogic(val); + hasPressedNumber = false; break; case '.': keys.R.val = 'C'; @@ -290,18 +347,24 @@ function buttonPress(val) { results = doMath(prevNumber, currNumber, operator); prevNumber = results; displayOutput(results); - hasPressedEquals = true; + hasPressedEquals = 1; } + hasPressedNumber = false; break; default: keys.R.val = 'C'; drawKey('R', keys.R); + const is0Negative = (currNumber === 0 && 1/currNumber === -Infinity); if (isDecimal) { - currNumber = currNumber == null ? 0 + '.' + val : currNumber + '.' + val; + currNumber = currNumber == null || hasPressedEquals === 1 ? 0 + '.' + val : currNumber + '.' + val; isDecimal = false; } else { - currNumber = currNumber == null ? val : currNumber + val; + currNumber = currNumber == null || hasPressedEquals === 1 ? val : (is0Negative ? '-' + val : currNumber + val); } + if (hasPressedEquals === 1) { + hasPressedEquals = 2; + } + hasPressedNumber = currNumber; displayOutput(currNumber); break; } @@ -315,38 +378,15 @@ for (var k in keys) { g.setFont('7x11Numeric7Seg', 2.8); g.drawString('0', 205, 10); - -setWatch(function() { - drawKey(selected, keys[selected]); - // key 0 is 2 keys wide, go up to 1 if it was previously selected - if (selected == '0' && prevSelected === '1') { - prevSelected = selected; - selected = '1'; - } else { - prevSelected = selected; - selected = keys[selected].trbl[0]; - } - drawKey(selected, keys[selected], true); -}, BTN1, {repeat: true, debounce: 100}); - -setWatch(function() { +function moveDirection(d) { drawKey(selected, keys[selected]); prevSelected = selected; - selected = keys[selected].trbl[2]; + selected = (d === 0 && selected == '0' && prevSelected === '1') ? '1' : keys[selected].trbl[d]; drawKey(selected, keys[selected], true); -}, BTN3, {repeat: true, debounce: 100}); +} -Bangle.on('touch', function(direction) { - drawKey(selected, keys[selected]); - prevSelected = selected; - if (direction == 1) { - selected = keys[selected].trbl[3]; - } else if (direction == 2) { - selected = keys[selected].trbl[1]; - } - drawKey(selected, keys[selected], true); -}); - -setWatch(function() { - buttonPress(selected); -}, BTN2, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(0), BTN1, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(2), BTN3, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(3), BTN4, {repeat: true, debounce: 100}); +setWatch(_ => moveDirection(1), BTN5, {repeat: true, debounce: 100}); +setWatch(_ => buttonPress(selected), BTN2, {repeat: true, debounce: 100}); diff --git a/apps/calculator/tests.html b/apps/calculator/tests.html new file mode 100644 index 000000000..1cbfdf617 --- /dev/null +++ b/apps/calculator/tests.html @@ -0,0 +1,273 @@ + + + + + + Calculator tests + + + + + + +
+ + + + + + + From 20f7c80462ce905288a987eda8455d9016771041 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:30:28 +0200 Subject: [PATCH 081/101] graphical adjustments --- apps/hidcam/app.js | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/hidcam/app.js b/apps/hidcam/app.js index 6e599959c..89b8ac4a1 100644 --- a/apps/hidcam/app.js +++ b/apps/hidcam/app.js @@ -24,12 +24,10 @@ if (settings.HID) { } function drawApp() { g.clear(); - Bangle.loadWidgets() - Bangle.drawWidgets() -// g.setFont("6x8",2); -// g.setFontAlign(0,0); -// g.drawString(profile, 120, 120); - g.drawImage(storage.read("hidcam.img"),120,120) + Bangle.loadWidgets(); + Bangle.drawWidgets(); + g.fillCircle(122,127,60); + g.drawImage(storage.read("hidcam.img"),100,105); const d = g.getWidth() - 18; function c(a) { @@ -40,8 +38,7 @@ function drawApp() { buffer: (new Uint8Array(a)).buffer }; } - - g.drawImage(c([0,8,12,14,255,14,12,8]),d,116); + g.fillRect(180,130, 240, 124); } if (camShot) { From d545a7a87d8a73270f90263e337a232339355360 Mon Sep 17 00:00:00 2001 From: paul Date: Sat, 18 Apr 2020 17:36:47 +0200 Subject: [PATCH 082/101] changelog update --- apps/hidcam/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/hidcam/ChangeLog b/apps/hidcam/ChangeLog index 665c0df6e..73b3268b7 100644 --- a/apps/hidcam/ChangeLog +++ b/apps/hidcam/ChangeLog @@ -1 +1 @@ -0.01: Init +0.01: Core functionnality From 406deafadd762bd45c427362a40a210c61fb8bbf Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 21:22:04 +0300 Subject: [PATCH 083/101] BlackJack game --- apps/blackjack/ChangeLog | 1 + apps/blackjack/blackjack.app.js | 191 ++++++++++++++++++++++++++++++++ apps/blackjack/blackjack.img | Bin 0 -> 706 bytes apps/blackjack/blackjack.info | 1 + 4 files changed, 193 insertions(+) create mode 100644 apps/blackjack/ChangeLog create mode 100644 apps/blackjack/blackjack.app.js create mode 100644 apps/blackjack/blackjack.img create mode 100644 apps/blackjack/blackjack.info diff --git a/apps/blackjack/ChangeLog b/apps/blackjack/ChangeLog new file mode 100644 index 000000000..c941d90e5 --- /dev/null +++ b/apps/blackjack/ChangeLog @@ -0,0 +1 @@ +0.01: New game! BTN4- Hit card, BTN5- Stand \ No newline at end of file diff --git a/apps/blackjack/blackjack.app.js b/apps/blackjack/blackjack.app.js new file mode 100644 index 000000000..dc5d35494 --- /dev/null +++ b/apps/blackjack/blackjack.app.js @@ -0,0 +1,191 @@ +const Clubs = { width : 48, height : 48, bpp : 1, + buffer : require("heatshrink").decompress(atob("ACcP+AFDn/8Aod//wFD///AgUBAoOAApsDAoPAAr4vLI4pTEgP8L4M/wEH/5rB//gh//x/x//wj//9/3//4n4iBAAIZBAol/Aof+Apv5z4FP+OPAo41BAoX8I4Pj45HBAoPD4YFBLIOD4JZBRAMD4CKC/AFBj59Cg/gQYYFXAB4=")) +}; + +const Spades = { width : 48, height : 48, bpp : 1, + buffer : require("heatshrink").decompress(atob("ABsBwAFDgfAAocH8AFDh/wAocf/AFDn/8Aod//wFD///FwYFBGAUDAoIwCg4FBGAUPAoIwCj4FBGAU/AoIwCv4FBGAQEBGAQuCGAQuCGAQFLHQQ8CAupHLL4prB+fPTgU/8fHVwbLLApbXFbpYFLdIoADA==")) +}; + +const Hearts = { width : 48, height : 48, bpp : 4, + buffer : require("heatshrink").decompress(atob("ADlVqtQBQ8FBYIKIrnMAAINGqoKC4okGCwYAB4AKDhgKE4oWKAAILDBQwYEBYwwDFwojFgoLHEgQ6H5hhCBZAkCBRAjLEgI6IC4YLIC5Y7BBZXBjgjVABYX/C8CnKABbXLABTvMC8sMC6fAC4KQURwIABRypgULwRgULwRIUCwhIRIwiRSRoZITCwx5POoowRCxAwNFxIwNCxQwLFxYwLCxgwJFxowJCxwwHFx4wHCyAwFFyIwFCyQwDFycAgoXBqAXTgFc4oWUJAJGUJARGVAEo")) + }; + +const Diamonds = { width : 48, height : 48, bpp : 4, + buffer : require("heatshrink").decompress(atob("AHUFC60M4AXV5nFIyvM5hGVC4JIUCwJIUIwRIUIwRIUCwZISIwgABqBGUJCQWFPKBGGJCFcC455OCw4wOOox5QIxB5NOpBIOFxZ5LCxYwKOpQwMIxh5KOxipLL6xgNR5QwMX5TvXPJZ1JJBpGLPJR1LJBZGNPJIWOJA5GOPJB1NJBIWQPIpGRJApGRPIoWSJAa8PJA5GTJAYWUJAJGVAAJGVAHo=")) + }; + + +var deck = []; +var player = {Hand:[]}; +var computer = {Hand:[]}; + +function createDeck() { + var suits = ["Spades", "Hearts", "Diamonds", "Clubs"]; + var values = ["2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A"]; + + var dck = []; + for (var i = 0 ; i < values.length; i++) { + for(var x = 0; x < suits.length; x++) { + dck.push({ Value: values[i], Suit: suits[x] }); + } + } + return dck; +} + +function shuffle(a) { + var j, x, i; + for (i = a.length - 1; i > 0; i--) { + j = Math.floor(Math.random() * (i + 1)); + x = a[i]; + a[i] = a[j]; + a[j] = x; + } + return a; +} + +function EndGameMessdage(msg){ + g.drawString(msg, 155, 200); + setTimeout(function(){ + startGame(); + }, 2500); + +} + +function hitMe() { + player.Hand.push(deck.pop()); + renderOnScreen(1); + var playerWeight = calcWeight(player.Hand, 0); + + if(playerWeight == 21) + EndGameMessdage('WINNER'); + else if(playerWeight > 21) + EndGameMessdage('LOOSER'); +} + +function calcWeight(hand, hideCard) { + + if(hideCard === 1) { + if (hand[0].Value == "J" || hand[0].Value == "Q" || hand[0].Value == "K") + return "10 +"; + else if (hand[0].Value == "A") + return "11 +"; + else + return parseInt(hand[0].Value) +" +"; + } + else { + var weight = 0; + for(i=0; i 21 || bangleWeight < playerWeight) + EndGameMessdage('WINNER'); + else if(bangleWeight > playerWeight) + EndGameMessdage('LOOSER'); +} + +function renderOnScreen(HideCard) { + const fontName = "6x8"; + + g.clear(); // clear screen + g.reset(); // default draw styles + g.setFont(fontName, 1); + + g.drawString('RST', 220, 35); + g.drawString('Hit', 60, 230); + g.drawString('Stand', 165, 230); + + g.setFont(fontName, 3); + for(i=0; i9WgH5ul2)7_0>|Km^WM! ktsjd-R^R}YcOcfVu~7y4Cx08IkIR{#J2 literal 0 HcmV?d00001 diff --git a/apps/blackjack/blackjack.info b/apps/blackjack/blackjack.info new file mode 100644 index 000000000..b30333f2e --- /dev/null +++ b/apps/blackjack/blackjack.info @@ -0,0 +1 @@ +{"id":"blackjack","name":"Black Jack","src":"blackjack.app.js","icon":"blackjack.img","version":"0.1","files":"blackjack.info,blackjack.app.js,blackjack.img"} \ No newline at end of file From 58d640a2e2dc08e79423ce984f9c1c0156e23a80 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:11:50 +0300 Subject: [PATCH 084/101] added blackjack game to apps.json --- apps.json | 12 ++++++++++++ apps/blackjack/blackjack.png | Bin 0 -> 646 bytes 2 files changed, 12 insertions(+) create mode 100644 apps/blackjack/blackjack.png diff --git a/apps.json b/apps.json index 0c97b9e57..0a6281c37 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,17 @@ "evaluate": true } ] + }, + { "id": "blackjack", + "name": "Black Jack game", + "shortName":"BlackJack game", + "icon": "blackjack.png", + "version":"0.01", + "description": "Simplle implementation of card game Black Jack", + "tags": "", + "storage": [ + {"name":"blackjack.app.js","url":"blackjack.app.js"}, + {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} + ] } ] diff --git a/apps/blackjack/blackjack.png b/apps/blackjack/blackjack.png new file mode 100644 index 0000000000000000000000000000000000000000..53715b5e44226d70a129a36fc2f663e4e6157f0e GIT binary patch literal 646 zcmV;10(t$3P)Px#1ZP1_K>z@;j|==^1poj5Fi=cXMF0Q*78VvLC@3~IHc3fIR8&-GXlQnJc87+Amh{@>F7O#lD@32;bRa{vGi!vFvd!vV){sAK>D0pCeP zK~y-)rIWu;6hRcnzXx|W!-?iPS{f2UNu$=DlaT_>83S%9tk^I!6*|as>t=o1 zrJvG>k!LXqxx|Z4A74gs{_PI%Akg(TfJI{Cugo!h<(+25uNnN{ERuBfM1wo3)LJn|XA$T-T{l3VA%^j=gFO901_m@WD5=}vb6`NG zp~0hQy+xe_M*_^V$jA-SJqspuhUDwPhYMI>u2sI{R&{~_ zO#|9M{X0KJ$pE7kvV(yxZ{BVjVAMjiQUAui9s?Oa?~ Date: Sat, 18 Apr 2020 22:20:09 +0300 Subject: [PATCH 085/101] adde icon for game --- apps/blackjack/blackjack-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js new file mode 100644 index 000000000..5c184fe4a --- /dev/null +++ b/apps/blackjack/blackjack-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("ABsD4AECn//2AEBg/4gEQAoMIAQIFFjACHBYoFIh+AgEMGQXwAokfAoMP8EHwPghk//AXBmEMnl8n+AjEMvl8/4FCvE9AoMQAoM894XBgkYvgdCgkAAocGgF4AoNgAoPwAongAocB4AFDgeAAoPAg0HL4QFBhwFEjkGh+BwEGnEOAoUCv/+Apd//a3BAorBDAohLBgf+AocB/gFDgFMAogCCUoUH8AFDDASxDn/AYYQrB/DMCAAN/zAFDg7LBAAYlBAAoA==")) \ No newline at end of file From 98795281a190d9dd5ba9e6ff2217ba919d9f331e Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:20:57 +0300 Subject: [PATCH 086/101] fix typo in description --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 0a6281c37..3b7ac0def 100644 --- a/apps.json +++ b/apps.json @@ -1299,7 +1299,7 @@ "shortName":"BlackJack game", "icon": "blackjack.png", "version":"0.01", - "description": "Simplle implementation of card game Black Jack", + "description": "Simple implementation of card game Black Jack", "tags": "", "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, From 34e3748ee6ee01eddbf09e47b08ecc1c7dbc5303 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:27:58 +0300 Subject: [PATCH 087/101] add game tag and change icon --- apps.json | 5 +++-- apps/blackjack/blackjack-icon.js | 1 - 2 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps.json b/apps.json index 3b7ac0def..a62fa9ece 100644 --- a/apps.json +++ b/apps.json @@ -1300,10 +1300,11 @@ "icon": "blackjack.png", "version":"0.01", "description": "Simple implementation of card game Black Jack", - "tags": "", + "tags": "game", + "allow_emulator":true, "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, - {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} + {"name":"blackjack.img","url":"blackjack.img"} ] } ] diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js deleted file mode 100644 index 5c184fe4a..000000000 --- a/apps/blackjack/blackjack-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("ABsD4AECn//2AEBg/4gEQAoMIAQIFFjACHBYoFIh+AgEMGQXwAokfAoMP8EHwPghk//AXBmEMnl8n+AjEMvl8/4FCvE9AoMQAoM894XBgkYvgdCgkAAocGgF4AoNgAoPwAongAocB4AFDgeAAoPAg0HL4QFBhwFEjkGh+BwEGnEOAoUCv/+Apd//a3BAorBDAohLBgf+AocB/gFDgFMAogCCUoUH8AFDDASxDn/AYYQrB/DMCAAN/zAFDg7LBAAYlBAAoA==")) \ No newline at end of file From aee60d97c0476dd7fd694a78e73e85d45ce4badf Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:43:29 +0300 Subject: [PATCH 088/101] Fix icon --- apps.json | 4 ++-- apps/blackjack/blackjack-icon.js | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 apps/blackjack/blackjack-icon.js diff --git a/apps.json b/apps.json index a62fa9ece..6e221c778 100644 --- a/apps.json +++ b/apps.json @@ -1296,7 +1296,7 @@ }, { "id": "blackjack", "name": "Black Jack game", - "shortName":"BlackJack game", + "shortName":"Black Jack game", "icon": "blackjack.png", "version":"0.01", "description": "Simple implementation of card game Black Jack", @@ -1304,7 +1304,7 @@ "allow_emulator":true, "storage": [ {"name":"blackjack.app.js","url":"blackjack.app.js"}, - {"name":"blackjack.img","url":"blackjack.img"} + {"name":"blackjack.img","url":"blackjack-icon.js","evaluate":true} ] } ] diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js new file mode 100644 index 000000000..f0976a5be --- /dev/null +++ b/apps/blackjack/blackjack-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgIQNgfAAgU/+UQAgMHmEAAoUIAQIFFjACHBYoFIgeAAocA+EAhgFCg4FBg/ggeB8EMj/4h+AmEMnl4j+AjEMvF8v4FDnv3wEQhk4nnnC4MEjE8g4FCgF4Ao8gAoNwAoNgg0A8AFDgPAAoZXBAoPAgxQBAocOAokcBoOAwEGnEOg+BwECv/+AosPAol//MAAoP8v/7RgLBDAokCAoO8AoJRBgHMAolMAogCCNIJLBcQKrCgP8WIk7wC9Dgf4ZgQABu4FEYIIFDRYIFEAAI")) \ No newline at end of file From 0c03bce926a8cac1282001c885dfa9d28eafde33 Mon Sep 17 00:00:00 2001 From: Ignas Bukys Date: Sat, 18 Apr 2020 22:45:33 +0300 Subject: [PATCH 089/101] icon brightness --- apps/blackjack/blackjack-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/blackjack/blackjack-icon.js b/apps/blackjack/blackjack-icon.js index f0976a5be..cb4d00cdd 100644 --- a/apps/blackjack/blackjack-icon.js +++ b/apps/blackjack/blackjack-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwgIQNgfAAgU/+UQAgMHmEAAoUIAQIFFjACHBYoFIgeAAocA+EAhgFCg4FBg/ggeB8EMj/4h+AmEMnl4j+AjEMvF8v4FDnv3wEQhk4nnnC4MEjE8g4FCgF4Ao8gAoNwAoNgg0A8AFDgPAAoZXBAoPAgxQBAocOAokcBoOAwEGnEOg+BwECv/+AosPAol//MAAoP8v/7RgLBDAokCAoO8AoJRBgHMAolMAogCCNIJLBcQKrCgP8WIk7wC9Dgf4ZgQABu4FEYIIFDRYIFEAAI")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwgIQNgfAAgU///wAgMH/4dBAoMMAQMQAQMIAQMYAQ4RCApcPwAFDgIwBAoQ4BAoMP8EHwfghk//AXBuEMv38n+AjEMvl8/4FDvoFBmEMvF994FBg04vgdBAoMAAot4AoNgAoPwAoZFBAongAoPggyIBAoPAg0HwAFDh4BBAoUeh0PwOAg08AocDv/+Ao3DAod//a3BAorBDAohRBgf+AocBAokApgCBhzSCWIkHVYgYCWIngYwQrB/gFDgF//AFDD4QAD8AFEAAIA=")) \ No newline at end of file From 79f18015ef8ae54f9ff24eb1573fb2acb6f9bb8a Mon Sep 17 00:00:00 2001 From: fredericrous Date: Sat, 18 Apr 2020 22:05:36 +0100 Subject: [PATCH 090/101] Add Calculator App Readme --- apps/calculator/README.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 apps/calculator/README.md diff --git a/apps/calculator/README.md b/apps/calculator/README.md new file mode 100644 index 000000000..78848908a --- /dev/null +++ b/apps/calculator/README.md @@ -0,0 +1,23 @@ +# Calculator + +Basic calculator reminiscent of MacOs's one. Handy for small calculus. + + + +## Features + +- add / substract / divide / multiply +- handles floats +- basic memory button + +## Controls + +- UP: BTN1 +- DOWN: BTN3 +- LEFT: BTN4 +- RIGHT: BTN5 +- SELECT: BTN2 + +## Creator + + From 0df1fb19e3d45f92ed5e490c11a59017df9d27eb Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 13:55:20 +0200 Subject: [PATCH 091/101] initial commit adding metronome app --- apps.json | 20 +++++++ apps/metronome/README.md | 10 ++++ apps/metronome/metronome-icon.js | 1 + apps/metronome/metronome.info | 1 + apps/metronome/metronome.js | 93 ++++++++++++++++++++++++++++++ apps/metronome/metronome_icon.png | Bin 0 -> 7575 bytes 6 files changed, 125 insertions(+) create mode 100644 apps/metronome/README.md create mode 100644 apps/metronome/metronome-icon.js create mode 100644 apps/metronome/metronome.info create mode 100644 apps/metronome/metronome.js create mode 100644 apps/metronome/metronome_icon.png diff --git a/apps.json b/apps.json index 0c97b9e57..590a85e38 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,25 @@ "evaluate": true } ] + }, + { + "id": "Metronome", + "name": "Metronome", + "icon": "metronome_icon.png", + "version": "0.03", + "description": "Makes the watch blinking and vibrating with a given rate", + "tags": "tool", + "allow_emulator": true, + "storage": [ + { + "name": "metronome.app.js", + "url": "metronome.js" + }, + { + "name": "metronome.img", + "url": "metronome-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/metronome/README.md b/apps/metronome/README.md new file mode 100644 index 000000000..19d489327 --- /dev/null +++ b/apps/metronome/README.md @@ -0,0 +1,10 @@ +# Metronome + +This metronome makes your watch blink and vibrate with a given rate. + +## Usage + +* Tap the screen at least three times. The app calculates the mean rate of your tapping. This rate is displayed in bmp while the text blinks and the watch softly vibrates with every beat. +* Use `BTN1` to increase the bmp value by one. +* Use `BTN3` to decrease the bmp value by one. +* You can change the bpm value any time by tapping the screen or using `BTN1` and `BTN3`. diff --git a/apps/metronome/metronome-icon.js b/apps/metronome/metronome-icon.js new file mode 100644 index 000000000..8b45f233b --- /dev/null +++ b/apps/metronome/metronome-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwxH+ABt4AB4fOFyFOABtUGDotOAAYvcp4ARqovbq0rACAvbqwABF98yGCAvdGAcHgAAEF8tWmIuGGA6QaF4lWFw4vgFwovPmIvuYDIvd0ejF59cF6qQFFwIvnMAguSqxfaFyQvYvOi0QuTF64uCAAQuRXwIvUqouEF6guFF5+cAAiOZF6iOaF5sxv+iF6xfRmVWFwWjv8rp4tSL6YvBqwuDMgQvnFwovURwIvQRggAELygvPgwuIF8ouEBwIvnFwwwXF54uBvwuFq0yF6buCF5guClQuFGAgvfFwcAF49WmIvRFwQvKFwkAmQvHYQMxF7l+FwgvKGAIvalQuGF5dWFx1VABVUvF4p0qAAdPCZNPF51OAD4vOKQIACF/4waF9wuEqgv/F/gwMF97vvAAUqADYtQAAMAADYuRGDgmLA=")) diff --git a/apps/metronome/metronome.info b/apps/metronome/metronome.info new file mode 100644 index 000000000..74dcbd2c7 --- /dev/null +++ b/apps/metronome/metronome.info @@ -0,0 +1 @@ +{"id":"metronome","name":"Metronome","src":"metronome.app.js", "icon": "metronome_icon.png", "sortorder":-2,"version":"0.03","files":"metronome.info,metronome.app.js, metronome_icon.png"} diff --git a/apps/metronome/metronome.js b/apps/metronome/metronome.js new file mode 100644 index 000000000..acd4b70b8 --- /dev/null +++ b/apps/metronome/metronome.js @@ -0,0 +1,93 @@ +var tStart = Date.now(); +var cindex=0; // index to iterate through colous +var bpm=60; // ininital bpm value +var time_diffs = [1000, 1000, 1000]; //array to calculate mean bpm +var tindex=0; //index to iterate through time_diffs + +Bangle.setLCDTimeout(undefined); //do not deaktivate display while running this app + +function changecolor() { + const maxColors = 2; + const colors = { + 0: { value: 0xFFFF, name: "White" }, + 1: { value: 0x000F, name: "Navy" }, + // 2: { value: 0x03E0, name: "DarkGreen" }, + // 3: { value: 0x03EF, name: "DarkCyan" }, + // 4: { value: 0x7800, name: "Maroon" }, + // 5: { value: 0x780F, name: "Purple" }, + // 6: { value: 0x7BE0, name: "Olive" }, + // 7: { value: 0xC618, name: "LightGray" }, + // 8: { value: 0x7BEF, name: "DarkGrey" }, + // 9: { value: 0x001F, name: "Blue" }, + // 10: { value: 0x07E0, name: "Green" }, + // 11: { value: 0x07FF, name: "Cyan" }, + // 12: { value: 0xF800, name: "Red" }, + // 13: { value: 0xF81F, name: "Magenta" }, + // 14: { value: 0xFFE0, name: "Yellow" }, + // 15: { value: 0xFFFF, name: "White" }, + // 16: { value: 0xFD20, name: "Orange" }, + // 17: { value: 0xAFE5, name: "GreenYellow" }, + // 18: { value: 0xF81F, name: "Pink" }, + }; + g.setColor(colors[cindex].value); + if (cindex == maxColors-1) { + cindex = 0; + } + else { + cindex += 1; + } + return cindex; +} + +function updateScreen() { + g.clear(); + changecolor(); + Bangle.buzz(50, 0.75); + g.setFont("Vector",48); + g.drawString(Math.floor(bpm)+"bpm", -1, 70); +} + +Bangle.on('touch', function(button) { +// setting bpm by tapping the screen. Uses the mean time difference between several tappings. + if (tindex < time_diffs.length) { + if (Date.now()-tStart < 5000) { + time_diffs[tindex] = Date.now()-tStart; + } + } else { + tindex=0; + time_diffs[tindex] = Date.now()-tStart; + } + tindex += 1; + mean_time = 0.0; + for(count = 0; count < time_diffs.length; count++) { + mean_time += time_diffs[count]; + } + time_diff = mean_time/count; + + tStart = Date.now(); + clearInterval(time_diff); + g.clear(); + g.setFont("Vector",48); + bpm = (60 * 1000/(time_diff)); + g.drawString(Math.floor(bpm)+"bpm", -1, 70); + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); + return bpm; +}); + +// enable bpm finetuning via buttons. +setWatch(() => { + bpm += 1; + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); +}, BTN1, {repeat:true}); + +setWatch(() => { + if (bpm > 1) { + bpm -= 1; + clearInterval(interval); + interval = setInterval(updateScreen, 60000 / bpm); + } +}, BTN3, {repeat:true}); + +interval = setInterval(updateScreen, 60000 / bpm); diff --git a/apps/metronome/metronome_icon.png b/apps/metronome/metronome_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..4dac7117f9e91221b0cfec54538e339c81df1939 GIT binary patch literal 7575 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 literal 0 HcmV?d00001 From 28dc51c377cb8b1c692df97f5f0bbc741b16ed7d Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 14:03:11 +0200 Subject: [PATCH 092/101] correct app path --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 590a85e38..83c0ba88f 100644 --- a/apps.json +++ b/apps.json @@ -1295,7 +1295,7 @@ ] }, { - "id": "Metronome", + "id": "metronome", "name": "Metronome", "icon": "metronome_icon.png", "version": "0.03", From 0bdf476ea6fe78aafaaf5318d92ac7f0fe8b5b60 Mon Sep 17 00:00:00 2001 From: Michael Bengfort Date: Sun, 19 Apr 2020 14:13:26 +0200 Subject: [PATCH 093/101] remove metronome.info --- apps/metronome/metronome.info | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/metronome/metronome.info diff --git a/apps/metronome/metronome.info b/apps/metronome/metronome.info deleted file mode 100644 index 74dcbd2c7..000000000 --- a/apps/metronome/metronome.info +++ /dev/null @@ -1 +0,0 @@ -{"id":"metronome","name":"Metronome","src":"metronome.app.js", "icon": "metronome_icon.png", "sortorder":-2,"version":"0.03","files":"metronome.info,metronome.app.js, metronome_icon.png"} From 1596b0246b9693bdf7fd26a04417e49aa61dfb9d Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sun, 19 Apr 2020 16:18:13 +0200 Subject: [PATCH 094/101] Add setting to hide widget when battery is over 20%. --- apps/widbatpc/{settings.js => widbatpc.settings.js} | 12 +++++++++--- apps/widbatpc/widbatpc.settings.json | 1 + apps/widbatpc/{widget.js => widbatpc.wid.js} | 13 ++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) rename apps/widbatpc/{settings.js => widbatpc.settings.js} (88%) create mode 100644 apps/widbatpc/widbatpc.settings.json rename apps/widbatpc/{widget.js => widbatpc.wid.js} (95%) diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/widbatpc.settings.js similarity index 88% rename from apps/widbatpc/settings.js rename to apps/widbatpc/widbatpc.settings.js index 5c0bdbcae..9f39b5d07 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/widbatpc.settings.js @@ -11,6 +11,7 @@ 'color': COLORS[0], 'percentage': true, 'charger': true, + 'hideifmorethan20pct': false, } // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings @@ -51,8 +52,13 @@ const newIndex = (oldIndex + 1) % COLORS.length s.color = COLORS[newIndex] save('color')(s.color) - }, - }, - } + } + }, + 'Hide when \> 20\%': { + value: s.hideifmorethan20pct, + format: onOffFormat, + onchange: save('hideifmorethan20pct'), + }, + } E.showMenu(menu) }) diff --git a/apps/widbatpc/widbatpc.settings.json b/apps/widbatpc/widbatpc.settings.json new file mode 100644 index 000000000..7a22adfc0 --- /dev/null +++ b/apps/widbatpc/widbatpc.settings.json @@ -0,0 +1 @@ +{"color":"By Level","percentage":true,"charger":true,"hideifmorethan20pct":false} diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widbatpc.wid.js similarity index 95% rename from apps/widbatpc/widget.js rename to apps/widbatpc/widbatpc.wid.js index aca690ce0..959ec211f 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widbatpc.wid.js @@ -3,6 +3,7 @@ const DEFAULTS = { 'color': 'By Level', 'percentage': true, 'charger': true, + 'hideifmorethan20pct': false, } const COLORS = { 'white': -1, @@ -53,8 +54,16 @@ function setWidth() { } } function draw() { + var s = 39; var x = this.x, y = this.y; + const l = E.getBattery(), + c = levelColor(l); + const xl = x+4+l*(s-12)/100 + + if(!Bangle.isCharging() && setting('hideifmorethan20pct') && l > 20){ + return;} + if (Bangle.isCharging() && setting('charger')) { g.setColor(chargerColor()).drawImage(atob( "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y); @@ -64,9 +73,7 @@ function draw() { g.fillRect(x,y+2,x+s-4,y+21); g.clearRect(x+2,y+4,x+s-6,y+19); g.fillRect(x+s-3,y+10,x+s,y+14); - const l = E.getBattery(), - c = levelColor(l); - const xl = x+4+l*(s-12)/100 + g.setColor(c).fillRect(x+4,y+6,xl,y+17); g.setColor(-1); if (!setting('percentage')) { From d2270eaae6565a322895e25afb3c638a26c2b186 Mon Sep 17 00:00:00 2001 From: Frederic R Date: Sun, 19 Apr 2020 16:48:33 +0100 Subject: [PATCH 095/101] Update App Calculator's Readme. Larger image --- apps/calculator/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/calculator/README.md b/apps/calculator/README.md index 78848908a..b25d355bf 100644 --- a/apps/calculator/README.md +++ b/apps/calculator/README.md @@ -2,7 +2,7 @@ Basic calculator reminiscent of MacOs's one. Handy for small calculus. - + ## Features From 4d52de224ceddc49aabc107bf246374da8393106 Mon Sep 17 00:00:00 2001 From: Stefano Baldan Date: Sun, 19 Apr 2020 18:03:14 +0200 Subject: [PATCH 096/101] Added app for running --- apps.json | 21 +++ apps/banglerun/ChangeLog | 1 + apps/banglerun/app-icon.js | 1 + apps/banglerun/app.js | 314 +++++++++++++++++++++++++++++++++++ apps/banglerun/banglerun.png | Bin 0 -> 10456 bytes 5 files changed, 337 insertions(+) create mode 100755 apps/banglerun/ChangeLog create mode 100644 apps/banglerun/app-icon.js create mode 100644 apps/banglerun/app.js create mode 100644 apps/banglerun/banglerun.png diff --git a/apps.json b/apps.json index 0c97b9e57..143b02bd3 100644 --- a/apps.json +++ b/apps.json @@ -1293,5 +1293,26 @@ "evaluate": true } ] + }, + { + "id": "banglerun", + "name": "BangleRun", + "shortName": "BangleRun", + "icon": "banglerun.png", + "version": "0.01", + "description": "An app for running sessions.", + "tags": "run,running,fitness,outdoors", + "allow_emulator": false, + "storage": [ + { + "name": "banglerun.app.js", + "url": "app.js" + }, + { + "name": "banglerun.img", + "url": "app-icon.js", + "evaluate": true + } + ] } ] diff --git a/apps/banglerun/ChangeLog b/apps/banglerun/ChangeLog new file mode 100755 index 000000000..7b83706bf --- /dev/null +++ b/apps/banglerun/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/banglerun/app-icon.js b/apps/banglerun/app-icon.js new file mode 100644 index 000000000..0ccbedab4 --- /dev/null +++ b/apps/banglerun/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwMB/4ACx4ED/0DApP8AqAXB84GDg/DAgXj/+DCAUABgIFB4EAv4FCwEAj0PAoJPBgwFEgEfDgMOAoM/AoMegFAAoP8jkA8F/AoM8gP4DgP4nBvD/F4KQfwuAFE+A/CAoPgAofx8A/CKYRwELIIFDLII6BAoZSBLIYeC/0BwAFDgfAGAQFBHgf8g4BBIIUH/wFBSYMPAoXwAog/Bj4FEv4FDDQQCBQoQFCZYYFi/6KE/+P/4A=")) diff --git a/apps/banglerun/app.js b/apps/banglerun/app.js new file mode 100644 index 000000000..fc21e3627 --- /dev/null +++ b/apps/banglerun/app.js @@ -0,0 +1,314 @@ +/** Global constants */ +const DEG_TO_RAD = Math.PI / 180; +const EARTH_RADIUS = 6371008.8; + +/** Utilities for handling vectors */ +class Vector { + static magnitude(a) { + let sum = 0; + for (const key of Object.keys(a)) { + sum += a[key] * a[key]; + } + return Math.sqrt(sum); + } + + static add(a, b) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] + b[key]; + } + return result; + } + + static sub(a, b) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] - b[key]; + } + return result; + } + + static multiplyScalar(a, x) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] * x; + } + return result; + } + + static divideScalar(a, x) { + const result = {}; + for (const key of Object.keys(a)) { + result[key] = a[key] / x; + } + return result; + } +} + +/** Interquartile range filter, to detect outliers */ +class IqrFilter { + constructor(size, threshold) { + const q = Math.floor(size / 4); + this._buffer = []; + this._size = 4 * q + 2; + this._i1 = q; + this._i3 = 3 * q + 1; + this._threshold = threshold; + } + + isReady() { + return this._buffer.length === this._size; + } + + isOutlier(point) { + let result = true; + if (this._buffer.length === this._size) { + result = false; + for (const key of Object.keys(point)) { + const data = this._buffer.map(item => item[key]); + data.sort((a, b) => (a - b) / Math.abs(a - b)); + const q1 = data[this._i1]; + const q3 = data[this._i3]; + const iqr = q3 - q1; + const lower = q1 - this._threshold * iqr; + const upper = q3 + this._threshold * iqr; + if (point[key] < lower || point[key] > upper) { + result = true; + break; + } + } + } + this._buffer.push(point); + this._buffer = this._buffer.slice(-this._size); + return result; + } +} + +/** Process GPS data */ +class Gps { + constructor() { + this._lastCall = Date.now(); + this._lastValid = 0; + this._coords = null; + this._filter = new IqrFilter(10, 1.5); + this._shift = { x: 0, y: 0, z: 0 }; + } + + isReady() { + return this._filter.isReady(); + } + + getDistance(gps) { + const time = Date.now(); + const interval = (time - this._lastCall) / 1000; + this._lastCall = time; + + if (!gps.fix) { + return { t: interval, d: 0 }; + } + + const p = gps.lat * DEG_TO_RAD; + const q = gps.lon * DEG_TO_RAD; + const coords = { + x: EARTH_RADIUS * Math.sin(p) * Math.cos(q), + y: EARTH_RADIUS * Math.sin(p) * Math.sin(q), + z: EARTH_RADIUS * Math.cos(p), + }; + + if (!this._coords) { + this._coords = coords; + this._lastValid = time; + return { t: interval, d: 0 }; + } + + const ds = Vector.sub(coords, this._coords); + const dt = (time - this._lastValid) / 1000; + const v = Vector.divideScalar(ds, dt); + + if (this._filter.isOutlier(v)) { + return { t: interval, d: 0 }; + } + + this._shift = Vector.add(this._shift, ds); + const length = Vector.magnitude(this._shift); + const remainder = length % 10; + const distance = length - remainder; + + this._coords = coords; + this._lastValid = time; + if (distance > 0) { + this._shift = Vector.multiplyScalar(this._shift, remainder / length); + } + + return { t: interval, d: distance }; + } +} + +/** Process step counter data */ +class Step { + constructor(size) { + this._buffer = []; + this._size = size; + } + + getCadence() { + this._buffer.push(Date.now() / 1000); + this._buffer = this._buffer.slice(-this._size); + const interval = this._buffer[this._buffer.length - 1] - this._buffer[0]; + return interval ? Math.round(60 * (this._buffer.length - 1) / interval) : 0; + } +} + +const gps = new Gps(); +const step = new Step(10); + +let totDist = 0; +let totTime = 0; +let totSteps = 0; + +let speed = 0; +let cadence = 0; +let heartRate = 0; + +let gpsReady = false; +let hrmReady = false; +let running = false; + +function formatClock(date) { + return ('0' + date.getHours()).substr(-2) + ':' + ('0' + date.getMinutes()).substr(-2); +} + +function formatDistance(m) { + return ('0' + (m / 1000).toFixed(2) + ' km').substr(-7); +} + +function formatTime(s) { + const hrs = Math.floor(s / 3600); + const min = Math.floor(s / 60); + const sec = Math.floor(s % 60); + return (hrs ? hrs + ':' : '') + ('0' + min).substr(-2) + `:` + ('0' + sec).substr(-2); +} + +function formatSpeed(kmh) { + if (kmh <= 0.6) { + return `__'__"`; + } + const skm = 3600 / kmh; + const min = Math.floor(skm / 60); + const sec = Math.floor(skm % 60); + return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; +} + +function drawBackground() { + g.setColor(running ? 0x00E0 : 0x0000); + g.fillRect(0, 30, 240, 240); + + g.setColor(0xFFFF); + g.setFontAlign(0, -1, 0); + g.setFont('6x8', 2); + + g.drawString('DISTANCE', 120, 50); + g.drawString('TIME', 60, 100); + g.drawString('PACE', 180, 100); + g.drawString('STEPS', 60, 150); + g.drawString('STP/m', 180, 150); + g.drawString('SPEED', 40, 200); + g.drawString('HEART', 120, 200); + g.drawString('CADENCE', 200, 200); +} + +function draw() { + const totSpeed = totTime ? 3.6 * totDist / totTime : 0; + const totCadence = totTime ? Math.round(60 * totSteps / totTime) : 0; + + g.setColor(running ? 0x00E0 : 0x0000); + g.fillRect(0, 30, 240, 50); + g.fillRect(0, 70, 240, 100); + g.fillRect(0, 120, 240, 150); + g.fillRect(0, 170, 240, 200); + g.fillRect(0, 220, 240, 240); + + g.setFont('6x8', 2); + + g.setFontAlign(-1, -1, 0); + g.setColor(gpsReady ? 0x07E0 : 0xF800); + g.drawString(' GPS', 6, 30); + + g.setFontAlign(1, -1, 0); + g.setColor(0xFFFF); + g.drawString(formatClock(new Date()), 234, 30); + + g.setFontAlign(0, -1, 0); + g.setFontVector(20); + g.drawString(formatDistance(totDist), 120, 70); + g.drawString(formatTime(totTime), 60, 120); + g.drawString(formatSpeed(totSpeed), 180, 120); + g.drawString(totSteps, 60, 170); + g.drawString(totCadence, 180, 170); + + g.setFont('6x8', 2); + g.drawString(formatSpeed(speed), 40, 220); + + g.setColor(hrmReady ? 0x07E0 : 0xF800); + g.drawString(heartRate, 120, 220); + + g.setColor(0xFFFF); + g.drawString(cadence, 200, 220); +} + +function handleGps(coords) { + const step = gps.getDistance(coords); + gpsReady = coords.fix > 0 && gps.isReady(); + speed = isFinite(gps.speed) ? gps.speed : 0; + if (running) { + totDist += step.d; + totTime += step.t; + } +} + +function handleHrm(hrm) { + hrmReady = hrm.confidence > 50; + heartRate = hrm.bpm; +} + +function handleStep() { + cadence = step.getCadence(); + if (running) { + totSteps += 1; + } +} + +function start() { + running = true; + drawBackground(); + draw(); +} + +function stop() { + if (!running) { + totDist = 0; + totTime = 0; + totSteps = 0; + } + running = false; + drawBackground(); + draw(); +} + +Bangle.on('GPS', handleGps); +Bangle.on('HRM', handleHrm); +Bangle.on('step', handleStep); + +Bangle.setGPSPower(1); +Bangle.setHRMPower(1); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +drawBackground(); +draw(); + +setInterval(draw, 500); + +setWatch(start, BTN1, { repeat: true }); +setWatch(stop, BTN3, { repeat: true }); diff --git a/apps/banglerun/banglerun.png b/apps/banglerun/banglerun.png new file mode 100644 index 0000000000000000000000000000000000000000..bf2cd8af3ef5f9711d18df1656a03a98283bcc67 GIT binary patch literal 10456 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 O0000 Date: Mon, 20 Apr 2020 09:27:57 +0200 Subject: [PATCH 097/101] Removed href="#" that scrolls page on top --- js/index.js | 2 +- js/utils.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/js/index.js b/js/index.js index ef9bcb4f1..d8c7a4473 100644 --- a/js/index.js +++ b/js/index.js @@ -207,7 +207,7 @@ function refreshLibrary() { var version = getVersionInfo(app, appInstalled); var versionInfo = version.text; if (versionInfo) versionInfo = " ("+versionInfo+")"; - var readme = `Read more...`; + var readme = `Read more...`; var favourite = favourites.find(e => e == app.id); return `
diff --git a/js/utils.js b/js/utils.js index 4913c7129..406e3a0a1 100644 --- a/js/utils.js +++ b/js/utils.js @@ -49,7 +49,7 @@ function getVersionInfo(appListing, appInstalled) { var versionText = ""; var canUpdate = false; function clicky(v) { - return `${v}`; + return `${v}`; } if (!appInstalled) { From 9cc58597cd5d0934f34da6a935b2187cb1b3df36 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 09:21:27 +0100 Subject: [PATCH 098/101] merge with new namings --- apps/widbatpc/{widbatpc.settings.js => settings.js} | 0 apps/widbatpc/{widbatpc.wid.js => widget.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename apps/widbatpc/{widbatpc.settings.js => settings.js} (100%) rename apps/widbatpc/{widbatpc.wid.js => widget.js} (100%) diff --git a/apps/widbatpc/widbatpc.settings.js b/apps/widbatpc/settings.js similarity index 100% rename from apps/widbatpc/widbatpc.settings.js rename to apps/widbatpc/settings.js diff --git a/apps/widbatpc/widbatpc.wid.js b/apps/widbatpc/widget.js similarity index 100% rename from apps/widbatpc/widbatpc.wid.js rename to apps/widbatpc/widget.js From 20bb1aed8456dcfc6028d77400970e45ebf6c2db Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 10:06:23 +0100 Subject: [PATCH 099/101] Add 'hide if charge greater than' Move 'DEFAULTS' to try and reduce memory usage a little --- apps.json | 4 +-- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/settings.js | 23 +++++++------ apps/widbatpc/widbatpc.settings.json | 1 - apps/widbatpc/widget.js | 50 +++++++++++++++++----------- 5 files changed, 46 insertions(+), 33 deletions(-) delete mode 100644 apps/widbatpc/widbatpc.settings.json diff --git a/apps.json b/apps.json index fe3d5f3eb..5b024eb97 100644 --- a/apps.json +++ b/apps.json @@ -354,7 +354,7 @@ "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", "icon": "widget.png", - "version":"0.09", + "version":"0.10", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "tags": "widget,battery", "type":"widget", @@ -1372,7 +1372,7 @@ {"name":"hidcam.img","url":"app-icon.js","evaluate":true} ] }, - { + { "id": "rclock", "name": "Round clock with seconds, minutes and date", "shortName":"Round Clock", diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 129707320..4c5f16a04 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -6,3 +6,4 @@ 0.07: Add settings: percentage/color/charger icon 0.08: Draw percentage as inverted on monochrome battery 0.09: Fix regression stopping correct widget updates +0.10: Add 'hide if charge greater than' diff --git a/apps/widbatpc/settings.js b/apps/widbatpc/settings.js index 9f39b5d07..bfed48f09 100644 --- a/apps/widbatpc/settings.js +++ b/apps/widbatpc/settings.js @@ -11,22 +11,22 @@ 'color': COLORS[0], 'percentage': true, 'charger': true, - 'hideifmorethan20pct': false, + 'hideifmorethan': 100, } // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings const storage = require('Storage') const saved = storage.readJSON(SETTINGS_FILE, 1) || {} for (const key in saved) { - s[key] = saved[key] + s[key] = saved[key]; } // creates a function to safe a specific setting, e.g. save('color')(1) function save(key) { return function (value) { - s[key] = value - storage.write(SETTINGS_FILE, s) - WIDGETS["batpc"].reload() + s[key] = value; + storage.write(SETTINGS_FILE, s); + WIDGETS["batpc"].reload(); } } @@ -54,11 +54,14 @@ save('color')(s.color) } }, - 'Hide when \> 20\%': { - value: s.hideifmorethan20pct, - format: onOffFormat, - onchange: save('hideifmorethan20pct'), + 'Hide if >': { + value: s.hideifmorethan||100, + min: 10, + max : 100, + step: 10, + format: x => x+"%", + onchange: save('hideifmorethan'), }, - } + } E.showMenu(menu) }) diff --git a/apps/widbatpc/widbatpc.settings.json b/apps/widbatpc/widbatpc.settings.json deleted file mode 100644 index 7a22adfc0..000000000 --- a/apps/widbatpc/widbatpc.settings.json +++ /dev/null @@ -1 +0,0 @@ -{"color":"By Level","percentage":true,"charger":true,"hideifmorethan20pct":false} diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 959ec211f..fe6f8550c 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,10 +1,4 @@ (function(){ -const DEFAULTS = { - 'color': 'By Level', - 'percentage': true, - 'charger': true, - 'hideifmorethan20pct': false, -} const COLORS = { 'white': -1, 'charging': 0x07E0, // "Green" @@ -17,10 +11,19 @@ const SETTINGS_FILE = 'widbatpc.settings.json' let settings function loadSettings() { settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} + const DEFAULTS = { + 'color': 'By Level', + 'percentage': true, + 'charger': true, + 'hideifmorethan': 100, + }; + Object.keys(DEFAULTS).forEach(k=>{ + if (settings[k]===undefined) settings[k]=DEFAULTS[k] + }); } function setting(key) { if (!settings) { loadSettings() } - return (key in settings) ? settings[key] : DEFAULTS[key] + return settings[key]; } const levelColor = (l) => { @@ -46,24 +49,27 @@ const levelColor = (l) => { const chargerColor = () => { return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging } - +// sets width, returns true if it changed function setWidth() { - WIDGETS["batpc"].width = 40; - if (Bangle.isCharging() && setting('charger')) { - WIDGETS["batpc"].width += 16; - } + var w = 40; + if (Bangle.isCharging() && setting('charger')) + w += 16; + if (E.getBattery() > setting('hideifmorethan')) + w = 0; + var changed = WIDGETS["batpc"].width != w; + WIDGETS["batpc"].width = w; + return changed; } function draw() { - + // if hidden, don't draw + if (!WIDGETS["batpc"].width) return; + // else... var s = 39; var x = this.x, y = this.y; const l = E.getBattery(), c = levelColor(l); const xl = x+4+l*(s-12)/100 - if(!Bangle.isCharging() && setting('hideifmorethan20pct') && l > 20){ - return;} - if (Bangle.isCharging() && setting('charger')) { g.setColor(chargerColor()).drawImage(atob( "DhgBHOBzgc4HOP////////////////////3/4HgB4AeAHgB4AeAHgB4AeAHg"),x,y); @@ -104,20 +110,24 @@ function reload() { g.clear(); Bangle.drawWidgets(); } +// update widget - redraw just widget, or all widgets if size changed +function update() { + if (setWidth()) Bangle.drawWidgets(); + else WIDGETS["batpc"].draw(); +} Bangle.on('charging',function(charging) { if(charging) Bangle.buzz(); - setWidth(); - Bangle.drawWidgets(); // relayout widgets + update(); g.flip(); }); var batteryInterval; Bangle.on('lcdPower', function(on) { if (on) { - WIDGETS["batpc"].draw(); + update(); // refresh once a minute if LCD on if (!batteryInterval) - batteryInterval = setInterval(()=>WIDGETS["batpc"].draw(), 60000); + batteryInterval = setInterval(update, 60000); } else { if (batteryInterval) { clearInterval(batteryInterval); From 5fe7f48477818c1bb31b7650e9d93f45d594f7e0 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Apr 2020 10:07:55 +0100 Subject: [PATCH 100/101] Add 'update all' button (fix #237) --- index.html | 1 + js/index.js | 42 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 39 insertions(+), 4 deletions(-) diff --git a/index.html b/index.html index f016ffb49..3c8b440e4 100644 --- a/index.html +++ b/index.html @@ -113,6 +113,7 @@
+
diff --git a/js/index.js b/js/index.js index 2b1fb1cfc..51b1d71c3 100644 --- a/js/index.js +++ b/js/index.js @@ -218,7 +218,7 @@ function refreshLibrary() {

${escapeHtml(app.description)}${app.readme?`
${readme}`:""}

See the code on GitHub
-
+
@@ -401,10 +401,18 @@ function showLoadingIndicator(id) { panelbody.innerHTML = '
'; } +function getAppsToUpdate() { + var appsToUpdate = []; + appsInstalled.forEach(appInstalled => { + var app = appNameToApp(appInstalled.id); + if (app.version != appInstalled.version) + appsToUpdate.push(app); + }); + return appsToUpdate; +} + function refreshMyApps() { var panelbody = document.querySelector("#myappscontainer .panel-body"); - var tab = document.querySelector("#tab-myappscontainer a"); - tab.setAttribute("data-badge", appsInstalled.length); panelbody.innerHTML = appsInstalled.map(appInstalled => { var app = appNameToApp(appInstalled.id); var version = getVersionInfo(app, appInstalled); @@ -436,6 +444,17 @@ return `
if (icon.classList.contains("icon-download")) handleAppInterface(app); }); }); + var appsToUpdate = getAppsToUpdate(); + var tab = document.querySelector("#tab-myappscontainer a"); + var updateApps = document.querySelector("#myappscontainer .updateapps"); + if (appsToUpdate.length) { + updateApps.innerHTML = `Update ${appsToUpdate.length} apps`; + updateApps.classList.remove("hidden"); + tab.setAttribute("data-badge", `${appsInstalled.length} ⬆${appsToUpdate.length}`); + } else { + updateApps.classList.add("hidden"); + tab.setAttribute("data-badge", appsInstalled.length); + } } let haveInstalledApps = false; @@ -471,6 +490,22 @@ htmlToArray(document.querySelectorAll(".btn.refresh")).map(button => button.addE showToast("Getting app list failed, "+err,"error"); }); })); +htmlToArray(document.querySelectorAll(".btn.updateapps")).map(button => button.addEventListener("click", () => { + var appsToUpdate = getAppsToUpdate(); + var count = appsToUpdate.length; + function updater() { + if (!appsToUpdate.length) return; + var app = appsToUpdate.pop(); + return updateApp(app).then(function() { + return updater(); + }); + } + updater().then(err => { + showToast(`Updated ${count} apps`,"success"); + }).catch(err => { + showToast("Update failed, "+err,"error"); + }); +})); connectMyDeviceBtn.addEventListener("click", () => { if (connectMyDeviceBtn.classList.contains('is-connected')) { Comms.disconnectDevice(); @@ -621,4 +656,3 @@ document.getElementById("installfavourite").addEventListener("click",event=>{ showToast("App Install failed, "+err,"error"); }); }); - From 0f8247e7e49f3b976e96dea0626a3369ea2a9456 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Mon, 20 Apr 2020 11:52:19 +0200 Subject: [PATCH 101/101] Data file fixes for settings/welcome/ncstart settings: never delete settings file welcome: fix typo, remove outdated comment ncstart: remove outdated comment --- apps.json | 3 --- apps/ncstart/settings.js | 1 - apps/welcome/settings.js | 3 +-- 3 files changed, 1 insertion(+), 6 deletions(-) diff --git a/apps.json b/apps.json index a18029abc..32a7e7dff 100644 --- a/apps.json +++ b/apps.json @@ -130,9 +130,6 @@ {"name":"setting.boot.js","url":"boot.js"}, {"name":"setting.img","url":"settings-icon.js","evaluate":true} ], - "data": [ - {"name":"setting.json"} - ], "sortorder" : -2 }, { "id": "alarm", diff --git a/apps/ncstart/settings.js b/apps/ncstart/settings.js index 6780264a7..560fad8ba 100644 --- a/apps/ncstart/settings.js +++ b/apps/ncstart/settings.js @@ -1,4 +1,3 @@ -// The welcome app is special, and gets to use global settings (function(back) { let settings = require('Storage').readJSON('ncstart.json', 1) || require('Storage').readJSON('setting.json', 1) || {} diff --git a/apps/welcome/settings.js b/apps/welcome/settings.js index e873c2785..20c2e9b13 100644 --- a/apps/welcome/settings.js +++ b/apps/welcome/settings.js @@ -1,6 +1,5 @@ -// The welcome app is special, and gets to use global settings (function(back) { - let settings = require('Storage').readJSON('welcome.sjson', 1) + let settings = require('Storage').readJSON('welcome.json', 1) || require('Storage').readJSON('setting.json', 1) || {} E.showMenu({ '': { 'title': 'Welcome App' },