From 87f0ffcd96ee6c71432523b5d4ec3440fa757d96 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 00:08:04 +0100 Subject: [PATCH 001/202] widhwt: Ported to Bangle.js2 Tactically all that was needed was to state that it works with Bangle.js2. However the swipe gesture interfered with using the menu on Bangle.js2. So it has been deactivated and we recommend using Pattern Launcher instead. --- apps.json | 7 ++++--- apps/widhwt/ChangeLog | 1 + apps/widhwt/app.js | 11 +++++++++++ apps/widhwt/widget.js | 14 ++++++++++---- 4 files changed, 26 insertions(+), 7 deletions(-) create mode 100644 apps/widhwt/app.js diff --git a/apps.json b/apps.json index 8b4e86d52..f69889d50 100644 --- a/apps.json +++ b/apps.json @@ -1889,12 +1889,13 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.01", - "description": "Swipe your wrist over the watch face to start your personal Bangle.js hand wash timer for 35 sec. Start washing after the short buzz and stop after the long buzz.", + "version": "0.02-rc6", + "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", "tags": "widget,tool", - "supports": ["BANGLEJS"], + "allow_emulator": true, + "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"widhwt.wid.js","url":"widget.js"} ] diff --git a/apps/widhwt/ChangeLog b/apps/widhwt/ChangeLog index 4c21f3ace..76c4fcec9 100644 --- a/apps/widhwt/ChangeLog +++ b/apps/widhwt/ChangeLog @@ -1 +1,2 @@ 0.01: New Widget! +0.02: Ported to Bangle.js2 diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js new file mode 100644 index 000000000..68555d21d --- /dev/null +++ b/apps/widhwt/app.js @@ -0,0 +1,11 @@ +// Replace the "Loading..." box +// with our own message +g.clearRect(38, 68, 138, 108); +g.drawRect(38, 68, 138, 108); +g.setFontVector(13).drawString("Wash...", 60, 82); + +Bangle.buzz(); +setTimeout(() => { + Bangle.buzz(1E3, 1); + setTimeout(() => load(), 2E3); +}, 35E3); diff --git a/apps/widhwt/widget.js b/apps/widhwt/widget.js index d178a5b5d..5e1f95a41 100644 --- a/apps/widhwt/widget.js +++ b/apps/widhwt/widget.js @@ -6,9 +6,7 @@ g.reset().setColor(color).drawImage(require("heatshrink").decompress(atob("jEYwIKHgwCBhwCBh4CEggPCkACBmAXDBwVZ+EB+F4gEsjl8EgMP+EChk/gEMh+ehkA+YIBxwxBnF/4HggH/wEAj0AA==")), this.x + 1, 0); } - WIDGETS["widhwt"] = { area: "tr", width: 26, draw: draw }; - - Bangle.on('swipe', function() { + function startTimer() { color = 0x41f; Bangle.buzz(); Bangle.drawWidgets(); @@ -17,6 +15,14 @@ Bangle.buzz(1E3, 1); Bangle.drawWidgets(); }, 35E3); + } - }); + if (process.env.HWVERSION == 1) { + WIDGETS["widhwt"] = { + area: "tr", + width: 26, + draw: draw, + }; + Bangle.on('swipe', startTimer); + } })(); From d51c6679fe342ccb6058184b345ebc4e4816a98c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 14:57:19 +0100 Subject: [PATCH 002/202] Bumped hwt version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f69889d50..b4acc8f0c 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc6", + "version": "0.02-rc7", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", From c5536ee49a6508da2e7a1fac1298bdf9ed00ddba Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 17:37:04 +0100 Subject: [PATCH 003/202] hwt: Center "Wash ..." text properly --- apps.json | 2 +- apps/widhwt/app.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index b4acc8f0c..092584ecf 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc7", + "version": "0.02-rc8", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js index 68555d21d..2aaf7f08a 100644 --- a/apps/widhwt/app.js +++ b/apps/widhwt/app.js @@ -2,7 +2,9 @@ // with our own message g.clearRect(38, 68, 138, 108); g.drawRect(38, 68, 138, 108); -g.setFontVector(13).drawString("Wash...", 60, 82); +g.setFontVector(13).setFontAlign(0, 0, 0).drawString("Wash...", + g.getWidth()/2, + g.getHeight()/2); Bangle.buzz(); setTimeout(() => { From 51422c44c0fc89874b96fc893b3d06014de0f771 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 18:46:16 +0100 Subject: [PATCH 004/202] hwt: Reduce line lenght --- apps.json | 2 +- apps/widhwt/app.js | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 092584ecf..cb991dbed 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc8", + "version": "0.02-rc9", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", diff --git a/apps/widhwt/app.js b/apps/widhwt/app.js index 2aaf7f08a..f18e78643 100644 --- a/apps/widhwt/app.js +++ b/apps/widhwt/app.js @@ -2,9 +2,9 @@ // with our own message g.clearRect(38, 68, 138, 108); g.drawRect(38, 68, 138, 108); -g.setFontVector(13).setFontAlign(0, 0, 0).drawString("Wash...", - g.getWidth()/2, - g.getHeight()/2); +g.setFontVector(13); +g.setFontAlign(0, 0, 0); +g.drawString("Wash...", g.getWidth()/2, g.getHeight()/2); Bangle.buzz(); setTimeout(() => { From 505ed38753a1a6611b9f5da7f4aa32789f0f69a0 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sat, 18 Dec 2021 22:14:26 +0100 Subject: [PATCH 005/202] hwt: Add app.js to apps.json --- apps.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index cb991dbed..d572a9aad 100644 --- a/apps.json +++ b/apps.json @@ -1889,7 +1889,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc9", + "version": "0.02-rc10", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", @@ -1897,6 +1897,7 @@ "allow_emulator": true, "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ + {"name":"widhwt.app.js","url":"app.js"}, {"name":"widhwt.wid.js","url":"widget.js"} ] }, From 03a295a4ff40d9c664f155324d139ffb007e76eb Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:00:43 +0100 Subject: [PATCH 006/202] wohrm: prepare porting to Bangle.js2 --- apps.json | 4 ++-- apps/wohrm/README.md | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index e5e9f8f02..07c773725 100644 --- a/apps.json +++ b/apps.json @@ -1714,12 +1714,12 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.08", + "version": "0.09-rc1", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", "tags": "hrm,workout", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], diff --git a/apps/wohrm/README.md b/apps/wohrm/README.md index ad9e82525..87b1a65da 100644 --- a/apps/wohrm/README.md +++ b/apps/wohrm/README.md @@ -8,6 +8,9 @@ and will notify you with a buzz whenever your heart rate falls below or jumps ab [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 + +Use the settings menu to set the limits. On the Bangle.js1 these can in addition be set with the buttons: + 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. @@ -22,7 +25,7 @@ the received value: For 85% and above the bars are green, between 84% and 50% th 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. +Pressing middle button 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 From e91324c16bc9b10dde21e14468933a5500979d05 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 12:11:27 +0100 Subject: [PATCH 007/202] wohrm: Prevent crash on BangleJs2 --- apps/wohrm/app.js | 655 +++++++++++++++++++++++----------------------- 1 file changed, 328 insertions(+), 327 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index c9c060e99..01fcca63e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -1,327 +1,328 @@ -/* eslint-disable no-undef */ -const Setter = { - NONE: "none", - UPPER: 'upper', - LOWER: 'lower' -}; - -const shortBuzzTimeInMs = 80; -const longBuzzTimeInMs = 400; - -let upperLimit = 130; -let upperLimitChanged = true; - -let lowerLimit = 100; -let lowerLimitChanged = true; - -let limitSetter = Setter.NONE; - -let currentHeartRate = 0; -let hrConfidence = -1; -let hrChanged = true; -let confidenceChanged = true; - -let setterHighlightTimeout; - -function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); - - //Round top left corner - g.fillEllipse(115,40,135,70); - - //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); - - //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); - - //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); -} - -function drawTrainingHeartRate() { - //Only redraw if the display is on - if (Bangle.isLCDOn()) { - renderUpperLimit(); - - renderCurrentHeartRate(); - - renderLowerLimit(); - - renderConfidenceBars(); - } - - buzz(); -} - -function renderUpperLimit() { - if(!upperLimitChanged) { return; } - - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - - if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); - - upperLimitChanged = false; -} - -function renderCurrentHeartRate() { - if(!hrChanged) { return; } - - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); - - g.setColor(0,0,0); - g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); - - //Reset alignment to defaults - g.setFontAlign(-1, -1, 0); - - hrChanged = false; -} - -function renderLowerLimit() { - if(!lowerLimitChanged) { return; } - - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - - if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); - } else { - g.setColor(255,255,255); - } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); - - lowerLimitChanged = false; -} - -function renderConfidenceBars(){ - if(!confidenceChanged) { return; } - - if(hrConfidence >= 85){ - g.setColor(0, 255, 0); - } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); - } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); - } else { - g.setColor(255, 255, 255); - } - - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); - - confidenceChanged = false; -} - -function renderPlusMinusIcons() { - if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); - } else { - g.setColor(1, 1, 1); - } - - g.setFontVector(14); - - //+ for Btn1 - g.drawString("+", 222, 50); - - //- for Btn3 - g.drawString("-", 222,165); - - return; -} - -function renderHomeIcon() { - //Home for Btn2 - g.setColor(1, 1, 1); - g.drawLine(220, 118, 227, 110); - g.drawLine(227, 110, 234, 118); - - g.drawPoly([222,117,222,125,232,125,232,117], false); - g.drawRect(226,120,229,125); -} - -function buzz() { - // Do not buzz if not confident - if(hrConfidence < 85) { return; } - - if(currentHeartRate > upperLimit) - { - Bangle.buzz(shortBuzzTimeInMs); - setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); - } - - if(currentHeartRate < lowerLimit) - { - Bangle.buzz(longBuzzTimeInMs); - } -} - -function onHrm(hrm){ - if(currentHeartRate !== hrm.bpm){ - currentHeartRate = hrm.bpm; - hrChanged = true; - } - - if(hrConfidence !== hrm.confidence) { - hrConfidence = hrm.confidence; - confidenceChanged = true; - } -} - -function setLimitSetterToLower() { - resetHighlightTimeout(); - - limitSetter = Setter.LOWER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderUpperLimit(); - renderLowerLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToUpper() { - resetHighlightTimeout(); - - limitSetter = Setter.UPPER; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function setLimitSetterToNone() { - limitSetter = Setter.NONE; - - upperLimitChanged = true; - lowerLimitChanged = true; - - renderLowerLimit(); - renderUpperLimit(); - renderPlusMinusIcons(); -} - -function incrementLimit() { - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit++; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit++; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function decrementLimit(){ - resetHighlightTimeout(); - - if (limitSetter === Setter.UPPER) { - upperLimit--; - renderUpperLimit(); - upperLimitChanged = true; - } else if(limitSetter === Setter.LOWER) { - lowerLimit--; - renderLowerLimit(); - lowerLimitChanged = true; - } -} - -function resetHighlightTimeout() { - if (setterHighlightTimeout) { - clearTimeout(setterHighlightTimeout); - } - - setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); -} - -function switchOffApp(){ - Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); -} - -Bangle.on('lcdPower', (on) => { - g.clear(); - if (on) { - Bangle.drawWidgets(); - - renderHomeIcon(); - renderLowerLimitBackground(); - renderUpperLimitBackground(); - lowerLimitChanged = true; - upperLimitChanged = true; - drawTrainingHeartRate(); - } -}); - -Bangle.setHRMPower(1,"wohrm"); -Bangle.on('HRM', onHrm); - -setWatch(incrementLimit, BTN1, {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(); - -renderHomeIcon(); -renderLowerLimitBackground(); -renderUpperLimitBackground(); - -setInterval(drawTrainingHeartRate, 1000); +/* eslint-disable no-undef */ +const Setter = { + NONE: "none", + UPPER: 'upper', + LOWER: 'lower' +}; + +const shortBuzzTimeInMs = 80; +const longBuzzTimeInMs = 400; + +let upperLimit = 130; +let upperLimitChanged = true; + +let lowerLimit = 100; +let lowerLimitChanged = true; + +let limitSetter = Setter.NONE; + +let currentHeartRate = 0; +let hrConfidence = -1; +let hrChanged = true; +let confidenceChanged = true; + +let setterHighlightTimeout; + +function renderUpperLimitBackground() { + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + g.fillRect(180,70, 210, 200); + + //Round top left corner + g.fillEllipse(115,40,135,70); + + //Round top right corner + g.setColor(0,0,0); + g.fillRect(205,40, 210, 45); + g.setColor(1,0,0); + g.fillEllipse(190,40,210,50); + + //Round inner corner + g.fillRect(174,71, 179, 76); + g.setColor(0,0,0); + g.fillEllipse(160,71,179,82); + + //Round bottom + g.setColor(1,0,0); + g.fillEllipse(180,190, 210, 210); +} + +function renderLowerLimitBackground() { + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + g.fillRect(10, 50, 40, 180); + + //Rounded top + g.setColor(0,0,1); + g.fillEllipse(10,40, 40, 60); + + //Round bottom right corner + g.setColor(0,0,1); + g.fillEllipse(90,180,110,210); + + //Round inner corner + g.setColor(0,0,1); + g.fillRect(40,175,45,180); + g.setColor(0,0,0); + g.fillEllipse(41,170,60,179); + + //Round bottom left corner + g.setColor(0,0,0); + g.fillRect(10,205, 15, 210); + g.setColor(0,0,1); + g.fillEllipse(10,200,30,210); +} + +function drawTrainingHeartRate() { + //Only redraw if the display is on + if (Bangle.isLCDOn()) { + renderUpperLimit(); + + renderCurrentHeartRate(); + + renderLowerLimit(); + + renderConfidenceBars(); + } + + buzz(); +} + +function renderUpperLimit() { + if(!upperLimitChanged) { return; } + + g.setColor(1,0,0); + g.fillRect(125,40, 210, 70); + + if(limitSetter === Setter.UPPER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Upper: " + upperLimit, 125, 50); + + upperLimitChanged = false; +} + +function renderCurrentHeartRate() { + if(!hrChanged) { return; } + + g.setColor(255,255,255); + g.fillRect(55, 110, 165, 150); + + g.setColor(0,0,0); + g.setFontVector(24); + g.setFontAlign(1, -1, 0); + g.drawString(currentHeartRate, 130, 117); + + //Reset alignment to defaults + g.setFontAlign(-1, -1, 0); + + hrChanged = false; +} + +function renderLowerLimit() { + if(!lowerLimitChanged) { return; } + + g.setColor(0,0,1); + g.fillRect(10, 180, 100, 210); + + if(limitSetter === Setter.LOWER){ + g.setColor(255,255, 0); + } else { + g.setColor(255,255,255); + } + g.setFontVector(13); + g.drawString("Lower: " + lowerLimit, 20,190); + + lowerLimitChanged = false; +} + +function renderConfidenceBars(){ + if(!confidenceChanged) { return; } + + if(hrConfidence >= 85){ + g.setColor(0, 255, 0); + } else if (hrConfidence >= 50) { + g.setColor(255, 255, 0); + } else if(hrConfidence >= 0){ + g.setColor(255, 0, 0); + } else { + g.setColor(255, 255, 255); + } + + g.fillRect(45, 110, 55, 150); + g.fillRect(165, 110, 175, 150); + + confidenceChanged = false; +} + +function renderPlusMinusIcons() { + if (limitSetter === Setter.NONE) { + g.setColor(0, 0, 0); + } else { + g.setColor(1, 1, 1); + } + + g.setFontVector(14); + + //+ for Btn1 + g.drawString("+", 222, 50); + + //- for Btn3 + g.drawString("-", 222,165); + + return; +} + +function renderHomeIcon() { + //Home for Btn2 + g.setColor(1, 1, 1); + g.drawLine(220, 118, 227, 110); + g.drawLine(227, 110, 234, 118); + + g.drawPoly([222,117,222,125,232,125,232,117], false); + g.drawRect(226,120,229,125); +} + +function buzz() { + // Do not buzz if not confident + if(hrConfidence < 85) { return; } + + if(currentHeartRate > upperLimit) + { + Bangle.buzz(shortBuzzTimeInMs); + setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); + } + + if(currentHeartRate < lowerLimit) + { + Bangle.buzz(longBuzzTimeInMs); + } +} + +function onHrm(hrm){ + if(currentHeartRate !== hrm.bpm){ + currentHeartRate = hrm.bpm; + hrChanged = true; + } + + if(hrConfidence !== hrm.confidence) { + hrConfidence = hrm.confidence; + confidenceChanged = true; + } +} + +function setLimitSetterToLower() { + resetHighlightTimeout(); + + limitSetter = Setter.LOWER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderUpperLimit(); + renderLowerLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToUpper() { + resetHighlightTimeout(); + + limitSetter = Setter.UPPER; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function setLimitSetterToNone() { + limitSetter = Setter.NONE; + + upperLimitChanged = true; + lowerLimitChanged = true; + + renderLowerLimit(); + renderUpperLimit(); + renderPlusMinusIcons(); +} + +function incrementLimit() { + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit++; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit++; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function decrementLimit(){ + resetHighlightTimeout(); + + if (limitSetter === Setter.UPPER) { + upperLimit--; + renderUpperLimit(); + upperLimitChanged = true; + } else if(limitSetter === Setter.LOWER) { + lowerLimit--; + renderLowerLimit(); + lowerLimitChanged = true; + } +} + +function resetHighlightTimeout() { + if (setterHighlightTimeout) { + clearTimeout(setterHighlightTimeout); + } + + setterHighlightTimeout = setTimeout(setLimitSetterToNone, 2000); +} + +function switchOffApp(){ + Bangle.setHRMPower(0,"wohrm"); + Bangle.showLauncher(); +} + +Bangle.on('lcdPower', (on) => { + g.clear(); + if (on) { + Bangle.drawWidgets(); + + renderHomeIcon(); + renderLowerLimitBackground(); + renderUpperLimitBackground(); + lowerLimitChanged = true; + upperLimitChanged = true; + drawTrainingHeartRate(); + } +}); + +Bangle.setHRMPower(1,"wohrm"); +Bangle.on('HRM', onHrm); + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +renderLowerLimitBackground(); +renderUpperLimitBackground(); + +if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + setWatch(incrementLimit, BTN1, {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}); +} + +setInterval(drawTrainingHeartRate, 1000); From e98690a8533eefd23d23cd017b65c3b2def73aa1 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:10:08 +0100 Subject: [PATCH 008/202] wohrm: parameterized renderUpperLimitBackground() --- apps/wohrm/app.js | 44 +++++++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 01fcca63e..ba037fc7c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -24,27 +24,45 @@ let confidenceChanged = true; let setterHighlightTimeout; function renderUpperLimitBackground() { - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); - g.fillRect(180,70, 210, 200); + var minX=125; + var maxX=210; + var minY=40; + var maxY=210; + var rectWidth=30; + var cornerRoundness=5; + var bgColor = 0; + var fgColor = '#f00'; + g.setColor(fgColor); + + g.fillRect(minX,minY, maxX, minY+rectWidth); + g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); //Round top left corner - g.fillEllipse(115,40,135,70); + g.fillEllipse(minX-cornerRoundness*2, + minY, + minX+cornerRoundness*2, + minY+rectWidth); //Round top right corner - g.setColor(0,0,0); - g.fillRect(205,40, 210, 45); - g.setColor(1,0,0); - g.fillEllipse(190,40,210,50); + g.setColor(bgColor); + g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); + g.setColor(fgColor); + g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); //Round inner corner - g.fillRect(174,71, 179, 76); - g.setColor(0,0,0); - g.fillEllipse(160,71,179,82); + g.fillRect(maxX-rectWidth-cornerRoundness-1, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness-1); + g.setColor(bgColor); + g.fillEllipse(maxX-rectWidth-cornerRoundness*4, + minY+rectWidth+1, + maxX-rectWidth-1, + minY+rectWidth+cornerRoundness*3-1); //Round bottom - g.setColor(1,0,0); - g.fillEllipse(180,190, 210, 210); + g.setColor(fgColor); + g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); } function renderLowerLimitBackground() { From 8c4f37e991fc3ab17ea6c24b7d15d813dc343b53 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 14:30:12 +0100 Subject: [PATCH 009/202] wohrm: renderLshape() from renderUpperLimitBackground() --- apps/wohrm/app.js | 69 ++++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ba037fc7c..e73307773 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,46 +23,49 @@ let confidenceChanged = true; let setterHighlightTimeout; -function renderUpperLimitBackground() { - var minX=125; - var maxX=210; - var minY=40; - var maxY=210; - var rectWidth=30; - var cornerRoundness=5; - var bgColor = 0; - var fgColor = '#f00'; - g.setColor(fgColor); +const upperLshape = { + minX: 125, + maxX: 210, + minY: 40, + maxY: 210, + rectWidth: 30, + cornerRoundness: 5, + bgColor: 0, + fgColor: '#f00' +}; - g.fillRect(minX,minY, maxX, minY+rectWidth); - g.fillRect(maxX-rectWidth, minY+rectWidth, maxX, maxY-cornerRoundness*2); +function renderLshape(p) { + g.setColor(p.fgColor); + + g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); + g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); //Round top left corner - g.fillEllipse(minX-cornerRoundness*2, - minY, - minX+cornerRoundness*2, - minY+rectWidth); + g.fillEllipse(p.minX-p.cornerRoundness*2, + p.minY, + p.minX+p.cornerRoundness*2, + p.minY+p.rectWidth); //Round top right corner - g.setColor(bgColor); - g.fillRect(maxX-cornerRoundness,minY, maxX, minY+cornerRoundness); - g.setColor(fgColor); - g.fillEllipse(maxX-cornerRoundness*4,minY,maxX,minY+cornerRoundness*2); + g.setColor(p.bgColor); + g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); //Round inner corner - g.fillRect(maxX-rectWidth-cornerRoundness-1, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness-1); - g.setColor(bgColor); - g.fillEllipse(maxX-rectWidth-cornerRoundness*4, - minY+rectWidth+1, - maxX-rectWidth-1, - minY+rectWidth+cornerRoundness*3-1); + g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness-1); + g.setColor(p.bgColor); + g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, + p.minY+p.rectWidth+1, + p.maxX-p.rectWidth-1, + p.minY+p.rectWidth+p.cornerRoundness*3-1); //Round bottom - g.setColor(fgColor); - g.fillEllipse(maxX-rectWidth,maxY-cornerRoundness*4, maxX, maxY); + g.setColor(p.fgColor); + g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); } function renderLowerLimitBackground() { @@ -317,7 +320,7 @@ Bangle.on('lcdPower', (on) => { renderHomeIcon(); renderLowerLimitBackground(); - renderUpperLimitBackground(); + renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; drawTrainingHeartRate(); @@ -331,7 +334,7 @@ g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); renderLowerLimitBackground(); -renderUpperLimitBackground(); +renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From f4a7a4f77e78a24cb26490f100e29bdf75e02676 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:28:26 +0100 Subject: [PATCH 010/202] wohrt: removed renderLowerLimitBackground() --- apps/wohrm/app.js | 102 ++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 48 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index e73307773..638627e17 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -30,68 +30,74 @@ const upperLshape = { maxY: 210, rectWidth: 30, cornerRoundness: 5, + orientation: -1, bgColor: 0, fgColor: '#f00' }; +const lowerLshape = { + maxX: 10, + minX: 100, + minY: 210, + maxY: 40, + rectWidth: 30, + cornerRoundness: 5, + orientation: 1, + bgColor: 0, + fgColor: '#00f' +}; + +function fillEllipse(x, y, x2, y2) { + g.fillEllipse(Math.min(x, x2), + Math.min(y, y2), + Math.max(x, x2), + Math.max(y, y2)); +} + function renderLshape(p) { g.setColor(p.fgColor); - g.fillRect(p.minX,p.minY, p.maxX, p.minY+p.rectWidth); - g.fillRect(p.maxX-p.rectWidth, p.minY+p.rectWidth, p.maxX, p.maxY-p.cornerRoundness*2); + g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); + g.fillRect(p.maxX+p.orientation*p.rectWidth, + p.minY-p.orientation*p.rectWidth, + p.maxX, + p.maxY+p.orientation*p.cornerRoundness*2); - //Round top left corner - g.fillEllipse(p.minX-p.cornerRoundness*2, - p.minY, - p.minX+p.cornerRoundness*2, - p.minY+p.rectWidth); + //Round end of small line + fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, + p.minY, + p.minX-p.orientation*p.cornerRoundness*2, + p.minY-p.orientation*p.rectWidth); - //Round top right corner + //Round outer corner g.setColor(p.bgColor); - g.fillRect(p.maxX-p.cornerRoundness,p.minY, p.maxX, p.minY+p.cornerRoundness); + g.fillRect(p.maxX+p.orientation*p.cornerRoundness, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness); g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.cornerRoundness*4,p.minY,p.maxX,p.minY+p.cornerRoundness*2); + fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, + p.minY, + p.maxX, + p.minY-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX-p.rectWidth-p.cornerRoundness-1, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness-1); + g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(p.bgColor); - g.fillEllipse(p.maxX-p.rectWidth-p.cornerRoundness*4, - p.minY+p.rectWidth+1, - p.maxX-p.rectWidth-1, - p.minY+p.rectWidth+p.cornerRoundness*3-1); + fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.minY-p.orientation*(p.rectWidth+1), + p.maxX+p.orientation*(p.rectWidth+1), + p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); - //Round bottom + //Round end of long line g.setColor(p.fgColor); - g.fillEllipse(p.maxX-p.rectWidth,p.maxY-p.cornerRoundness*4, p.maxX, p.maxY); -} - -function renderLowerLimitBackground() { - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); - g.fillRect(10, 50, 40, 180); - - //Rounded top - g.setColor(0,0,1); - g.fillEllipse(10,40, 40, 60); - - //Round bottom right corner - g.setColor(0,0,1); - g.fillEllipse(90,180,110,210); - - //Round inner corner - g.setColor(0,0,1); - g.fillRect(40,175,45,180); - g.setColor(0,0,0); - g.fillEllipse(41,170,60,179); - - //Round bottom left corner - g.setColor(0,0,0); - g.fillRect(10,205, 15, 210); - g.setColor(0,0,1); - g.fillEllipse(10,200,30,210); + fillEllipse(p.maxX+p.orientation*p.rectWidth, + p.maxY+p.orientation*p.cornerRoundness*4, + p.maxX, + p.maxY); } function drawTrainingHeartRate() { @@ -319,7 +325,7 @@ Bangle.on('lcdPower', (on) => { Bangle.drawWidgets(); renderHomeIcon(); - renderLowerLimitBackground(); + renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; upperLimitChanged = true; @@ -333,7 +339,7 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLowerLimitBackground(); +renderLshape(lowerLshape); renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { From 3e0e590b86a3a2282fd22ca03c37232410a35d94 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:41:06 +0100 Subject: [PATCH 011/202] Add home buttom for Bangle.js2 --- apps/wohrm/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 638627e17..de3db14e2 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -350,6 +350,8 @@ if (typeof(BTN5) !== typeof(undefined)) { setWatch(setLimitSetterToUpper, BTN5, { edge: "rising", debounce: 50, repeat: true }); setWatch(switchOffApp, BTN2, {edge:"falling", debounce:50, repeat:true}); +} else { + setWatch(switchOffApp, BTN1, {edge:"falling", debounce:50, repeat:true}); } setInterval(drawTrainingHeartRate, 1000); From 616f1f784f8780adce5f586ecc51e54b0c8a1a2a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:46:56 +0100 Subject: [PATCH 012/202] wohrm: Don't draw home-icon on Banglejs2 --- apps/wohrm/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index de3db14e2..8e041fa98 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -320,11 +320,13 @@ function switchOffApp(){ } Bangle.on('lcdPower', (on) => { - g.clear(); if (on) { + g.clear(); Bangle.drawWidgets(); - renderHomeIcon(); + if (typeof(BTN5) !== typeof(undefined)) { + renderHomeIcon(); + } renderLshape(lowerLshape); renderLshape(upperLshape); lowerLimitChanged = true; From 9f33ded981cb117537350698292509eac4f4e24b Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 15:56:03 +0100 Subject: [PATCH 013/202] wohrm: Fixed rounding of outer corner --- apps/wohrm/app.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 8e041fa98..0681a3b33 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -118,8 +118,7 @@ function drawTrainingHeartRate() { function renderUpperLimit() { if(!upperLimitChanged) { return; } - g.setColor(1,0,0); - g.fillRect(125,40, 210, 70); + renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ g.setColor(255,255, 0); @@ -152,8 +151,7 @@ function renderCurrentHeartRate() { function renderLowerLimit() { if(!lowerLimitChanged) { return; } - g.setColor(0,0,1); - g.fillRect(10, 180, 100, 210); + renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ g.setColor(255,255, 0); @@ -341,8 +339,6 @@ Bangle.on('HRM', onHrm); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -renderLshape(lowerLshape); -renderLshape(upperLshape); if (typeof(BTN5) !== typeof(undefined)) { renderHomeIcon(); From 0d172f1db04b957f6b9520b61affde4f6952e92c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 16:23:56 +0100 Subject: [PATCH 014/202] wohrm: place Upper/Lower relative to "L" --- apps/wohrm/app.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 0681a3b33..f761c421e 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -125,8 +125,10 @@ function renderUpperLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Upper: " + upperLimit, 125, 50); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Upper: " + upperLimit, + upperLshape.minX, + upperLshape.minY+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -158,8 +160,10 @@ function renderLowerLimit() { } else { g.setColor(255,255,255); } - g.setFontVector(13); - g.drawString("Lower: " + lowerLimit, 20,190); + g.setFontVector(13).setFontAlign(-1, 0, 0); + g.drawString("Lower: " + lowerLimit, + lowerLshape.maxX + lowerLshape.rectWidth/2, + lowerLshape.minY - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From 09e7330ae0547eaa5270e2a175756167e04ccb2d Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:25:05 +0100 Subject: [PATCH 015/202] wohrm: parameterized centerBar --- apps/wohrm/app.js | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index f761c421e..ef4a3013d 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -47,6 +47,14 @@ const lowerLshape = { fgColor: '#00f' }; +const centerBar = { + minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, + maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + confidenceWidth: 10, + minX: 55, + maxX: 165 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -136,13 +144,16 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(255,255,255); - g.fillRect(55, 110, 165, 150); + g.setColor(1, 1, 1); + g.fillRect(centerBar.minX, centerBar.minY, + centerBar.maxX, centerBar.maxY); g.setColor(0,0,0); g.setFontVector(24); - g.setFontAlign(1, -1, 0); - g.drawString(currentHeartRate, 130, 117); + g.setFontAlign(1, 0, 0); + g.drawString(currentHeartRate, + upperLshape.minX+upperLshape.cornerRoundness, + (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults g.setFontAlign(-1, -1, 0); @@ -181,8 +192,8 @@ function renderConfidenceBars(){ g.setColor(255, 255, 255); } - g.fillRect(45, 110, 55, 150); - g.fillRect(165, 110, 175, 150); + g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); + g.fillRect(centerBar.maxX, centerBar.minY, centerBar.maxX+centerBar.confidenceWidth, centerBar.maxY); confidenceChanged = false; } From 0456843385231a1e817100386adf24026065204a Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:45:38 +0100 Subject: [PATCH 016/202] wohrm: Use theme colors --- apps/wohrm/app.js | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index ef4a3013d..63194f390 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -31,8 +31,7 @@ const upperLshape = { rectWidth: 30, cornerRoundness: 5, orientation: -1, - bgColor: 0, - fgColor: '#f00' + color: '#f00' }; const lowerLshape = { @@ -43,8 +42,7 @@ const lowerLshape = { rectWidth: 30, cornerRoundness: 5, orientation: 1, - bgColor: 0, - fgColor: '#00f' + color: '#00f' }; const centerBar = { @@ -63,7 +61,7 @@ function fillEllipse(x, y, x2, y2) { } function renderLshape(p) { - g.setColor(p.fgColor); + g.setColor(p.color); g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); g.fillRect(p.maxX+p.orientation*p.rectWidth, @@ -78,12 +76,12 @@ function renderLshape(p) { p.minY-p.orientation*p.rectWidth); //Round outer corner - g.setColor(p.bgColor); + g.setColor(g.theme.bg); g.fillRect(p.maxX+p.orientation*p.cornerRoundness, p.minY, p.maxX, p.minY-p.orientation*p.cornerRoundness); - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, p.minY, p.maxX, @@ -94,14 +92,14 @@ function renderLshape(p) { p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); - g.setColor(p.bgColor); + g.setColor(g.theme.bg); fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), p.minY-p.orientation*(p.rectWidth+1), p.maxX+p.orientation*(p.rectWidth+1), p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line - g.setColor(p.fgColor); + g.setColor(p.color); fillEllipse(p.maxX+p.orientation*p.rectWidth, p.maxY+p.orientation*p.cornerRoundness*4, p.maxX, @@ -129,9 +127,9 @@ function renderUpperLimit() { renderLshape(upperLshape); if(limitSetter === Setter.UPPER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, @@ -144,11 +142,11 @@ function renderUpperLimit() { function renderCurrentHeartRate() { if(!hrChanged) { return; } - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); g.fillRect(centerBar.minX, centerBar.minY, centerBar.maxX, centerBar.maxY); - g.setColor(0,0,0); + g.setColor(g.theme.bg); g.setFontVector(24); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, @@ -167,9 +165,9 @@ function renderLowerLimit() { renderLshape(lowerLshape); if(limitSetter === Setter.LOWER){ - g.setColor(255,255, 0); + g.setColor(1,1,0); } else { - g.setColor(255,255,255); + g.setColor(g.theme.fg); } g.setFontVector(13).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, @@ -183,13 +181,13 @@ function renderConfidenceBars(){ if(!confidenceChanged) { return; } if(hrConfidence >= 85){ - g.setColor(0, 255, 0); + g.setColor(0, 1, 0); } else if (hrConfidence >= 50) { - g.setColor(255, 255, 0); + g.setColor(1, 1, 0); } else if(hrConfidence >= 0){ - g.setColor(255, 0, 0); + g.setColor(1, 0, 0); } else { - g.setColor(255, 255, 255); + g.setColor(g.theme.fg); } g.fillRect(centerBar.minX-centerBar.confidenceWidth, centerBar.minY, centerBar.minX, centerBar.maxY); @@ -200,9 +198,9 @@ function renderConfidenceBars(){ function renderPlusMinusIcons() { if (limitSetter === Setter.NONE) { - g.setColor(0, 0, 0); + g.setColor(g.theme.bg); } else { - g.setColor(1, 1, 1); + g.setColor(g.theme.fg); } g.setFontVector(14); From b513772692f129ad676b8f1dac15ecdf1419ce8f Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:51:55 +0100 Subject: [PATCH 017/202] wohrm: parameterized font sizes --- apps/wohrm/app.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 63194f390..bb21b5d59 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -53,6 +53,11 @@ const centerBar = { maxX: 165 }; +const fontSizes = { + limits: 13, + heartRate: 24 +}; + function fillEllipse(x, y, x2, y2) { g.fillEllipse(Math.min(x, x2), Math.min(y, y2), @@ -131,7 +136,7 @@ function renderUpperLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -147,7 +152,7 @@ function renderCurrentHeartRate() { centerBar.maxX, centerBar.maxY); g.setColor(g.theme.bg); - g.setFontVector(24); + g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, upperLshape.minX+upperLshape.cornerRoundness, @@ -169,7 +174,7 @@ function renderLowerLimit() { } else { g.setColor(g.theme.fg); } - g.setFontVector(13).setFontAlign(-1, 0, 0); + g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); From d5e08477e1692a7867f0c715070e58f0b7fddffd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 17:59:57 +0100 Subject: [PATCH 018/202] wohrm: deduplicate --- apps/wohrm/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index bb21b5d59..6ebcdabc3 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -37,10 +37,10 @@ const upperLshape = { const lowerLshape = { maxX: 10, minX: 100, - minY: 210, - maxY: 40, - rectWidth: 30, - cornerRoundness: 5, + minY: upperLshape.maxY, + maxY: upperLshape.minY, + rectWidth: upperLshape.rectWidth, + cornerRoundness: upperLshape.cornerRoundness, orientation: 1, color: '#00f' }; From b120f7572f454426ab8bb912830e758f177134dd Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 19:32:19 +0100 Subject: [PATCH 019/202] wohrm: resize on Bangls.js2 --- apps/wohrm/app.js | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 6ebcdabc3..75d48c7ff 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -23,7 +23,8 @@ let confidenceChanged = true; let setterHighlightTimeout; -const upperLshape = { +const isB1 = process.env.HWVERSION==1; +const upperLshape = isB1 ? { minX: 125, maxX: 210, minY: 40, @@ -32,10 +33,19 @@ const upperLshape = { cornerRoundness: 5, orientation: -1, color: '#f00' +} : { + minX: Bangle.appRect.x2-100, + maxX: Bangle.appRect.x2, + minY: Bangle.appRect.y, + maxY: Bangle.appRect.y2, + rectWidth: 26, + cornerRoundness: 4, + orientation: -1, + color: '#f00' }; const lowerLshape = { - maxX: 10, + maxX: isB1 ? 10 : Bangle.appRect.x, minX: 100, minY: upperLshape.maxY, maxY: upperLshape.minY, @@ -48,14 +58,17 @@ const lowerLshape = { const centerBar = { minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, - confidenceWidth: 10, - minX: 55, - maxX: 165 + confidenceWidth: isB1 ? 10 : 8, + minX: isB1 ? 55 : upperLshape.rectWidth + 14, + maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 }; -const fontSizes = { - limits: 13, - heartRate: 24 +const fontSizes = isB1 ? { + limits: 13, + heartRate: 24 +} : { + limits: 12, + heartRate: 20 }; function fillEllipse(x, y, x2, y2) { @@ -155,7 +168,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - upperLshape.minX+upperLshape.cornerRoundness, + Math.max(upperLshape.minX+upperLshape.cornerRoundness, + lowerLshape.minX-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults From 3ae35376fcd3db363c33030b01d88e254a0781d5 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 20:45:11 +0100 Subject: [PATCH 020/202] wohrm: fixes after running on Bangle.js2 - set to dark theme as doesn't look good with white in the corners) - leave space for widgets --- apps.json | 2 +- apps/wohrm/app.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 07c773725..2acd3b981 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc1", + "version": "0.09-rc2", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 75d48c7ff..429b9f565 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -36,7 +36,7 @@ const upperLshape = isB1 ? { } : { minX: Bangle.appRect.x2-100, maxX: Bangle.appRect.x2, - minY: Bangle.appRect.y, + minY: 24, maxY: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, @@ -368,7 +368,7 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From 9e1dd8eda39fb1bc76b9c52e1851072158cb4982 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:01:47 +0100 Subject: [PATCH 021/202] wohrm: Fix bgcolor --- apps.json | 2 +- apps/wohrm/app.js | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 2acd3b981..ed616c952 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc2", + "version": "0.09-rc3", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 429b9f565..115849fa6 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -351,7 +351,6 @@ function switchOffApp(){ Bangle.on('lcdPower', (on) => { if (on) { - g.clear(); Bangle.drawWidgets(); if (typeof(BTN5) !== typeof(undefined)) { @@ -368,7 +367,9 @@ Bangle.on('lcdPower', (on) => { Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); -g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); +g.setTheme({bg:"#000",fg:"#fff",dark:true}); +g.reset() +g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); From 288a204b9d608d90bb33cf82ec005f8a980df01e Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:13:39 +0100 Subject: [PATCH 022/202] wohrm: Add ChangeLog entry --- apps/wohrm/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 084ca6ed5..156d32740 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -5,4 +5,5 @@ 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 -0.08: tag HRM power requests to allow this ot work alongside other widgets/apps (fix #799) +0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) +0.09: Ported to Bangle.js2 From 15df1205060eaf866fb3b2eb0c4db861a0d7bc90 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 21:29:16 +0100 Subject: [PATCH 023/202] wohrm: Home returns to clock, instead of menu --- apps.json | 2 +- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index ed616c952..4d98ce731 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc3", + "version": "0.09-rc4", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index 156d32740..b177c1902 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -7,3 +7,4 @@ 0.07: Home button fixed and README added 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 + Home returns to clock, instead of menu diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 115849fa6..646dab58f 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -346,7 +346,7 @@ function resetHighlightTimeout() { function switchOffApp(){ Bangle.setHRMPower(0,"wohrm"); - Bangle.showLauncher(); + load(); } Bangle.on('lcdPower', (on) => { From 0caa10b7052a639ba80d2f35d061b6026cef6bf7 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 19 Dec 2021 22:01:08 +0100 Subject: [PATCH 024/202] wohrm: Add settings --- apps.json | 3 ++- apps/wohrm/ChangeLog | 1 + apps/wohrm/app.js | 26 ++++++++++++++------------ apps/wohrm/settings.js | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 apps/wohrm/settings.js diff --git a/apps.json b/apps.json index 4d98ce731..1d4f98c1e 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc4", + "version": "0.09-rc7", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", @@ -1725,6 +1725,7 @@ "screenshots": [{"url":"bangle1-workout-HRM-screenshot.png"}], "storage": [ {"name":"wohrm.app.js","url":"app.js"}, + {"name":"wohrm.settings.js","url":"settings.js"}, {"name":"wohrm.img","url":"app-icon.js","evaluate":true} ] }, diff --git a/apps/wohrm/ChangeLog b/apps/wohrm/ChangeLog index b177c1902..2ca405365 100644 --- a/apps/wohrm/ChangeLog +++ b/apps/wohrm/ChangeLog @@ -8,3 +8,4 @@ 0.08: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.09: Ported to Bangle.js2 Home returns to clock, instead of menu + Add settings diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 646dab58f..26e7b7eae 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -4,14 +4,16 @@ const Setter = { UPPER: 'upper', LOWER: 'lower' }; +const SETTINGS_FILE = "wohrm.setting.json"; +var settings = require('Storage').readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 +}; const shortBuzzTimeInMs = 80; const longBuzzTimeInMs = 400; -let upperLimit = 130; let upperLimitChanged = true; - -let lowerLimit = 100; let lowerLimitChanged = true; let limitSetter = Setter.NONE; @@ -150,7 +152,7 @@ function renderUpperLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Upper: " + upperLimit, + g.drawString("Upper: " + settings.upperLimit, upperLshape.minX, upperLshape.minY+upperLshape.rectWidth/2); @@ -189,7 +191,7 @@ function renderLowerLimit() { g.setColor(g.theme.fg); } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); - g.drawString("Lower: " + lowerLimit, + g.drawString("Lower: " + settings.lowerLimit, lowerLshape.maxX + lowerLshape.rectWidth/2, lowerLshape.minY - lowerLshape.rectWidth/2); @@ -247,13 +249,13 @@ function buzz() { // Do not buzz if not confident if(hrConfidence < 85) { return; } - if(currentHeartRate > upperLimit) + if(currentHeartRate > settings.upperLimit) { Bangle.buzz(shortBuzzTimeInMs); setTimeout(() => { Bangle.buzz(shortBuzzTimeInMs); }, shortBuzzTimeInMs * 2); } - if(currentHeartRate < lowerLimit) + if(currentHeartRate < settings.lowerLimit) { Bangle.buzz(longBuzzTimeInMs); } @@ -312,11 +314,11 @@ function incrementLimit() { resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit++; + settings.upperLimit++; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit++; + settings.lowerLimit++; renderLowerLimit(); lowerLimitChanged = true; } @@ -326,11 +328,11 @@ function decrementLimit(){ resetHighlightTimeout(); if (limitSetter === Setter.UPPER) { - upperLimit--; + settings.upperLimit--; renderUpperLimit(); upperLimitChanged = true; } else if(limitSetter === Setter.LOWER) { - lowerLimit--; + settings.lowerLimit--; renderLowerLimit(); lowerLimitChanged = true; } @@ -368,7 +370,7 @@ Bangle.setHRMPower(1,"wohrm"); Bangle.on('HRM', onHrm); g.setTheme({bg:"#000",fg:"#fff",dark:true}); -g.reset() +g.reset(); g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); diff --git a/apps/wohrm/settings.js b/apps/wohrm/settings.js new file mode 100644 index 000000000..6d31688f4 --- /dev/null +++ b/apps/wohrm/settings.js @@ -0,0 +1,35 @@ +(function menu(back) { + const SETTINGS_FILE = "wohrm.setting.json"; + + // initialize with default settings... + const storage = require('Storage'); + var settings = storage.readJSON(SETTINGS_FILE, 1) || { + upperLimit: 130, + lowerLimit: 100 + }; + + function save() { + storage.write(SETTINGS_FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Workout HRM' }, + '< Back': back, + 'Upper limit': { + value: settings.upperLimit, + min: 100, max: 200, + onchange: v => { + settings.upperLimit = v; + save(); + } + }, + 'Lower limit': { + value: settings.lowerLimit, + min: 50, max: 150, + onchange: v => { + settings.lowerLimit = v; + save(); + } + } + }); +}) From 964fa27bfb9a5b1ef72a612d9b90e0891b21b9b0 Mon Sep 17 00:00:00 2001 From: The Dod Date: Tue, 21 Dec 2021 01:01:10 +0200 Subject: [PATCH 025/202] Add Four Twenty Clock app --- apps.json | 18 ++ apps/ftclock/ChangeLog | 1 + apps/ftclock/app-icon.js | 1 + apps/ftclock/app.js | 52 ++++ apps/ftclock/app.png | Bin 0 -> 6742 bytes apps/ftclock/fourTwenty.js | 45 +++ apps/ftclock/fourTwentyTz.js | 536 +++++++++++++++++++++++++++++++++ apps/ftclock/mkFourTwentyTz.py | 46 +++ apps/ftclock/screenshot.png | Bin 0 -> 17635 bytes 9 files changed, 699 insertions(+) create mode 100644 apps/ftclock/ChangeLog create mode 100644 apps/ftclock/app-icon.js create mode 100644 apps/ftclock/app.js create mode 100644 apps/ftclock/app.png create mode 100644 apps/ftclock/fourTwenty.js create mode 100644 apps/ftclock/fourTwentyTz.js create mode 100644 apps/ftclock/mkFourTwentyTz.py create mode 100644 apps/ftclock/screenshot.png diff --git a/apps.json b/apps.json index e5e9f8f02..3dc4c3577 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,23 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "ftclock", + "name": "Four Twenty Clock", + "version": "0.01", + "description": "A clock that tells when and where it's going to be 4:20 next", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"ftclock.app.js","url":"app.js"}, + {"name":"fourTwenty","url":"fourTwenty.js"}, + {"name":"fourTwentyTz","url":"fourTwentyTz.js"}, + {"name":"ftclock.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ftclock/ChangeLog b/apps/ftclock/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/ftclock/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/ftclock/app-icon.js b/apps/ftclock/app-icon.js new file mode 100644 index 000000000..297847e95 --- /dev/null +++ b/apps/ftclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwghC/AH4A/AH4A/AAMHu4ACuwHBs4HDsEGBIQLCsADBgwPDCAQGEuwXFBwI0GEAMHuAGCCoMHC4pMHEAIXEAgIGEBwI9BC4wSCC8IVCMAwIBs4XKUQJfITQgXCDwp8EHAqaECoLFEu4cDBIggBs6uFZozuGBAVmC4g+FMgZQEZQ5vGC4iRIC5IrDN4h5EC5J3BCoIKGgyaEC44VBC46yEDgoeDgxqLC5SCMAgoTFY47GFC4xFBdwwPBD4oWFAH4A/AH4A/AH4AjA==")) diff --git a/apps/ftclock/app.js b/apps/ftclock/app.js new file mode 100644 index 000000000..1aed8da54 --- /dev/null +++ b/apps/ftclock/app.js @@ -0,0 +1,52 @@ +let getNextFourTwenty = require("fourTwenty").getNextFourTwenty; +require("FontTeletext10x18Ascii").add(Graphics); +let leaf_img = "\x17\x18\x81\x00\x00\x10\x00\x00 \x00\x00@\x00\x01\xc0\x00\x03\x80\x00\x0f\x80\x00\x1f\x00\x00>\x00\x00|\x00\xc0\xf8\x19\xe1\xf0\xf1\xe3\xe3\xc3\xf7\xdf\x83\xff\xfe\x03\xff\xf8\x03\xff\xe0\x03\xff\x80\x03\xfe\x00\x7f\xff\xc0\xff\xff\xc0\x06\xe0\x00\x18\xc0\x00 \x80\x00\x00\x00"; + +// timeout used to update every minute +let drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + + +function draw() { + g.reset(); + g.setBgColor("#ffffff"); + let date = new Date(); + let timeStr = require("locale").time(date,1); + let next420 = getNextFourTwenty(); + g.clearRect(0,26,g.getWidth(),g.getHeight()); + g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2); + g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28); + g.setColor("#000000"); + g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii"); + g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60); + + // queue draw in one minute + queueDraw(); +} + +// Clear the screen once, at startup +g.clear(); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); +// draw immediately at first, queue update +draw(); +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); +// Show launcher when middle button pressed +Bangle.setUI("clock"); diff --git a/apps/ftclock/app.png b/apps/ftclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..0553837ca47ff2061105cd49c40a86d8f66d4b7b GIT binary patch literal 6742 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 && current_min<25) { + current_time -= current_min-20; // 5 minutes grace period + } + let offset = 16*60+20-current_time; + if (offset<0) { + offset += 24*60; + } + return offset; +} + +function makeFourTwentyText(minutes, places) { + //let plural = minutes==1? "": "s"; + //let msgprefix = minutes? `${minutes} minute${plural} to`: "It is now"; + let msgprefix = minutes? `${minutes}m to`: "It is now"; + let msgsuffix = places.length>1? ", and other fine places": ""; + let msgplace = places[Math.floor(Math.random()*places.length)]; + return `${msgprefix} 4:20 at ${msgplace}${msgsuffix}.`; +} + +function getNextFourTwenty() { + let offs = get420offset(); + for (let i=0; i2: # e.g. America/North_Dakota/New_Salem + country = parts[1] # e.g. North Dakota + else: # e.g. America/Denver + country = countries[r[1]] # e.g. United States + if country==city: # Avoid awkward searches like "Anguilla, Anguilla" + country = r[1] # Use code instead + zones[int(r[0])] = {"name":', '.join((city,country))} +now = int(time.time()) +for r in csv.reader(open("timezone.csv")): + code = int(r[0]) + if code not in zones: + continue + starttime = int(r[2] or "0") # Bugger. They're feeding us blanks for UTC now + offs = int(r[3]) + if offs < 0: + offs += 60*60*24 + d = zones[code] + if starttime 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 W_a_}>UQb*A0000 Date: Tue, 21 Dec 2021 01:34:30 +0200 Subject: [PATCH 026/202] ftclock README and better screenshots --- apps.json | 3 ++- apps/ftclock/README.md | 16 ++++++++++++++++ apps/ftclock/mkFourTwentyTz.py | 4 ++-- apps/ftclock/screenshot.png | Bin 17635 -> 15457 bytes apps/ftclock/screenshot1.png | Bin 0 -> 19973 bytes 5 files changed, 20 insertions(+), 3 deletions(-) create mode 100644 apps/ftclock/README.md create mode 100644 apps/ftclock/screenshot1.png diff --git a/apps.json b/apps.json index 3dc4c3577..6a9fc7309 100644 --- a/apps.json +++ b/apps.json @@ -5069,11 +5069,12 @@ "version": "0.01", "description": "A clock that tells when and where it's going to be 4:20 next", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}], "type": "clock", "tags": "clock", "supports": ["BANGLEJS","BANGLEJS2"], "allow_emulator": true, + "readme": "README.md", "storage": [ {"name":"ftclock.app.js","url":"app.js"}, {"name":"fourTwenty","url":"fourTwenty.js"}, diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md new file mode 100644 index 000000000..ed3b7b3bd --- /dev/null +++ b/apps/ftclock/README.md @@ -0,0 +1,16 @@ +# Four Twenty Clock + +A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_(cannabis_culture%29) next + +![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) + +## Note + +Once in a while, there'd be updates to the [timezone database](https://timezonedb.com/download) which +would require updating `fourTwentyTz.js`. I'll do my best to release a new version every time this happens, +but if you ever need to do this yourself, just run `python mkFourTwentyTz.py` (after downloading the timezone CSV files. +See comment at the top of the script). + +## Creator + +[Nimrod Kerrett](zzzen.com) diff --git a/apps/ftclock/mkFourTwentyTz.py b/apps/ftclock/mkFourTwentyTz.py index 4de17c3cf..713b68059 100644 --- a/apps/ftclock/mkFourTwentyTz.py +++ b/apps/ftclock/mkFourTwentyTz.py @@ -1,4 +1,4 @@ -# Generates tz.js[on] from time zone csv files +# Generates fourTwentyTz.js from time zone csv files # get latest files from https://timezonedb.com/download import csv,json,time,os,math countries = {} @@ -35,7 +35,7 @@ for k in zones: continue offsdict[d["offs"]] = offsdict.get(d["offs"],[])+[d["name"]] res = sorted([[k,sorted(offsdict[k])] for k in offsdict],key=lambda x:-x[0]) -js = open("tz.js","w") +js = open("fourTwentyTz.js","w") js.write("// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock\n") js.write("// (version: {0})\n".format(time.ctime(time.time()))) js.write("// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n") diff --git a/apps/ftclock/screenshot.png b/apps/ftclock/screenshot.png index e04f766463b05d0ff9826cbc8b8f10c1034d8307..9247e0e04a55b533955a24369e4d29d293f3b38d 100644 GIT binary patch literal 15457 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 X3LR-t-PP6E00000NkvXXu0mjf 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 W_a_}>UQb*A0000 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 ULn*~EGXMYp07*qoM6N<$f|JYjo&W#< literal 0 HcmV?d00001 From d80ebe08ede97b367932925bce540d8ed5a14d33 Mon Sep 17 00:00:00 2001 From: The Dod Date: Tue, 21 Dec 2021 10:56:37 +0200 Subject: [PATCH 027/202] README edit (gh markdown chokes on "(" in url) --- apps/ftclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md index ed3b7b3bd..665a7693d 100644 --- a/apps/ftclock/README.md +++ b/apps/ftclock/README.md @@ -1,6 +1,6 @@ # Four Twenty Clock -A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_(cannabis_culture%29) next +A clock that tells when and where it's going to be [4:20](https://en.wikipedia.org/wiki/420_%28cannabis_culture%29) next ![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) From 4f16d6ce35cfc3ea49075a5fa0c4d9cda9c67754 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Mon, 20 Dec 2021 11:08:08 +0100 Subject: [PATCH 028/202] wohrm: Refactor renderLshape() rename variables and document renderLshape() --- apps.json | 2 +- apps/wohrm/app.js | 110 +++++++++++++++++++++++++--------------------- 2 files changed, 61 insertions(+), 51 deletions(-) diff --git a/apps.json b/apps.json index 1d4f98c1e..7898ba786 100644 --- a/apps.json +++ b/apps.json @@ -1714,7 +1714,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc7", + "version": "0.09-rc10", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", diff --git a/apps/wohrm/app.js b/apps/wohrm/app.js index 26e7b7eae..ab579463c 100644 --- a/apps/wohrm/app.js +++ b/apps/wohrm/app.js @@ -27,30 +27,30 @@ let setterHighlightTimeout; const isB1 = process.env.HWVERSION==1; const upperLshape = isB1 ? { - minX: 125, - maxX: 210, - minY: 40, - maxY: 210, + right: 125, + left: 210, + bottom: 40, + top: 210, rectWidth: 30, cornerRoundness: 5, orientation: -1, color: '#f00' } : { - minX: Bangle.appRect.x2-100, - maxX: Bangle.appRect.x2, - minY: 24, - maxY: Bangle.appRect.y2, + right: Bangle.appRect.x2-100, + left: Bangle.appRect.x2, + bottom: 24, + top: Bangle.appRect.y2, rectWidth: 26, cornerRoundness: 4, - orientation: -1, + orientation: -1, // rotated 180° color: '#f00' }; const lowerLshape = { - maxX: isB1 ? 10 : Bangle.appRect.x, - minX: 100, - minY: upperLshape.maxY, - maxY: upperLshape.minY, + left: isB1 ? 10 : Bangle.appRect.x, + right: 100, + bottom: upperLshape.top, + top: upperLshape.bottom, rectWidth: upperLshape.rectWidth, cornerRoundness: upperLshape.cornerRoundness, orientation: 1, @@ -58,8 +58,8 @@ const lowerLshape = { }; const centerBar = { - minY: (upperLshape.minY + upperLshape.maxY - upperLshape.rectWidth)/2, - maxY: (upperLshape.minY + upperLshape.maxY + upperLshape.rectWidth)/2, + minY: (upperLshape.bottom + upperLshape.top - upperLshape.rectWidth)/2, + maxY: (upperLshape.bottom + upperLshape.top + upperLshape.rectWidth)/2, confidenceWidth: isB1 ? 10 : 8, minX: isB1 ? 55 : upperLshape.rectWidth + 14, maxX: isB1 ? 165 : Bangle.appRect.x2 - upperLshape.rectWidth - 14 @@ -80,50 +80,60 @@ function fillEllipse(x, y, x2, y2) { Math.max(y, y2)); } +/** + * @param p.left: the X coordinate of the left side of the L in its orientation + * @param p.right: the X coordinate of the right side of the L in its orientation + * @param p.top: the Y coordinate of the top side of the L in its orientation + * @param p.bottom: the Y coordinate of the bottom side of the L in its orientation + * @param p.strokeWidth: how thick we draw the letter. + * @param p.cornerRoundness: how much the corners should be rounded + * @param p.orientation: 1 == turned 0°; -1 == turned 180° + * @param p.color: the color to draw the shape + */ function renderLshape(p) { g.setColor(p.color); - g.fillRect(p.minX, p.minY, p.maxX, p.minY-p.orientation*p.rectWidth); - g.fillRect(p.maxX+p.orientation*p.rectWidth, - p.minY-p.orientation*p.rectWidth, - p.maxX, - p.maxY+p.orientation*p.cornerRoundness*2); + g.fillRect(p.right, p.bottom, p.left, p.bottom-p.orientation*p.rectWidth); + g.fillRect(p.left+p.orientation*p.rectWidth, + p.bottom-p.orientation*p.rectWidth, + p.left, + p.top+p.orientation*p.cornerRoundness*2); //Round end of small line - fillEllipse(p.minX+p.orientation*p.cornerRoundness*2, - p.minY, - p.minX-p.orientation*p.cornerRoundness*2, - p.minY-p.orientation*p.rectWidth); + fillEllipse(p.right+p.orientation*p.cornerRoundness*2, + p.bottom, + p.right-p.orientation*p.cornerRoundness*2, + p.bottom-p.orientation*p.rectWidth); //Round outer corner g.setColor(g.theme.bg); - g.fillRect(p.maxX+p.orientation*p.cornerRoundness, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness); + g.fillRect(p.left+p.orientation*p.cornerRoundness, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness); g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.cornerRoundness*4, - p.minY, - p.maxX, - p.minY-p.orientation*p.cornerRoundness*2); + fillEllipse(p.left+p.orientation*p.cornerRoundness*4, + p.bottom, + p.left, + p.bottom-p.orientation*p.cornerRoundness*2); //Round inner corner - g.fillRect(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness+1), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness-1)); + g.fillRect(p.left+p.orientation*(p.rectWidth+p.cornerRoundness+1), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness-1)); g.setColor(g.theme.bg); - fillEllipse(p.maxX+p.orientation*(p.rectWidth+p.cornerRoundness*4), - p.minY-p.orientation*(p.rectWidth+1), - p.maxX+p.orientation*(p.rectWidth+1), - p.minY-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); + fillEllipse(p.left+p.orientation*(p.rectWidth+p.cornerRoundness*4), + p.bottom-p.orientation*(p.rectWidth+1), + p.left+p.orientation*(p.rectWidth+1), + p.bottom-p.orientation*(p.rectWidth+p.cornerRoundness*3-1)); //Round end of long line g.setColor(p.color); - fillEllipse(p.maxX+p.orientation*p.rectWidth, - p.maxY+p.orientation*p.cornerRoundness*4, - p.maxX, - p.maxY); + fillEllipse(p.left+p.orientation*p.rectWidth, + p.top+p.orientation*p.cornerRoundness*4, + p.left, + p.top); } function drawTrainingHeartRate() { @@ -153,8 +163,8 @@ function renderUpperLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Upper: " + settings.upperLimit, - upperLshape.minX, - upperLshape.minY+upperLshape.rectWidth/2); + upperLshape.right, + upperLshape.bottom+upperLshape.rectWidth/2); upperLimitChanged = false; } @@ -170,8 +180,8 @@ function renderCurrentHeartRate() { g.setFontVector(fontSizes.heartRate); g.setFontAlign(1, 0, 0); g.drawString(currentHeartRate, - Math.max(upperLshape.minX+upperLshape.cornerRoundness, - lowerLshape.minX-lowerLshape.cornerRoundness), + Math.max(upperLshape.right+upperLshape.cornerRoundness, + lowerLshape.right-lowerLshape.cornerRoundness), (centerBar.minY+centerBar.maxY)/2); //Reset alignment to defaults @@ -192,8 +202,8 @@ function renderLowerLimit() { } g.setFontVector(fontSizes.limits).setFontAlign(-1, 0, 0); g.drawString("Lower: " + settings.lowerLimit, - lowerLshape.maxX + lowerLshape.rectWidth/2, - lowerLshape.minY - lowerLshape.rectWidth/2); + lowerLshape.left + lowerLshape.rectWidth/2, + lowerLshape.bottom - lowerLshape.rectWidth/2); lowerLimitChanged = false; } From ee3a1ced6283778950d3aa748537d76bbe780b86 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 17:38:24 +0100 Subject: [PATCH 029/202] create app.js create app.js --- mmind/app.js | 198 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 mmind/app.js diff --git a/mmind/app.js b/mmind/app.js new file mode 100644 index 000000000..e7def025d --- /dev/null +++ b/mmind/app.js @@ -0,0 +1,198 @@ +//MMind + +//set vars +const H = g.getWidth(); +const W = g.getHeight(); +var touch_actions = []; +var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; +var turn = 0; +var col_menu = false; +//pinsRow = 6; +//pinsThick = 10; +//pinsRow = 5; +//pinsThick = 10; +var pinsRow = 4; +var pinsThick = 10; +var play = [-1, -1, -1, -1]; + +var pinsCol = 5; +var playx = -1; +var sx = (W - 30 )/pinsRow; +var sy = (H - 20 )/7; +var touch_actions = []; +var secret = []; +var secret_no_dub = true; +var endgame = false; + +g.clear(); +g.setColor("#FFFFFF"); +g.fillRect(0, 0, H, W); +g.setFont("Vector12",45); + +function draw() { + touch_actions = []; + g.clear(); + g.setColor("#FFFFFF"); + g.fillRect(0, 0, H, W); + g.setColor("#000000"); + //draw scores + for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); + secret[i]= s; + } + } + +function score() { + bScore = 0; + wScore = 0; + for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && + e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { + // a action is hit, add acctions here, todo: start, stop, new, etc. + switch (touch_actions[i][1][0]) { + case 1: + //get pins col menu + col_menu = 1; + playx = touch_actions[i][1][1]; + break; + case 2: + //copy choice col to play + play[playx] = touch_actions[i][1][1]; + col_menu = 0; + break; + case 3: + //score play + var sc; + sc = score(); + game.push([play, sc]); + play = [-1,-1,-1,-1]; + turn+=1; + if (turn==6 || sc[0]==pinsRow) { + play = secret; + col_menu = 0; + endgame = true; + } + break; + case 4: + //new game + play = [-1,-1,-1,-1]; + game = []; + endgame=false; + break; + } + } + } + //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); + + draw(); + } +); + + +game = []; +get_secret(); +draw(); +//Bangle.loadWidgets(); +//Bangle.drawWidgets(); + + + + + From c8f914359e8acd92373763f2be76f2ecaa50ce9a Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 17:57:26 +0100 Subject: [PATCH 030/202] add icon file --- mmind/app.png | Bin 0 -> 1339 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 mmind/app.png diff --git a/mmind/app.png b/mmind/app.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2a27ae5c614707bb35d6400f75e54514db68f5 GIT binary patch literal 1339 zcmWksdsLDK6u&Bc8AzQnW~4PLALTKIS<=?yL>fMGil(EZsY6p+Ddraun#DXU*>}En zENaEf9LG?zAR~69ma$sSLu6rV_&jP4W=qXXQ&eJ~f82Y|@7{Co{oUWW^7yz2DtS2> z0H{%s;XER;=FHuV@EJV|^h9te;zjHPO`Fdf0+4bzyEy=jKT&2g=K;7D#m6S?ayp$u zLqn%dokCI6Xf*cq^+_a>&dyGo%_fyf&1SRRZZ{YV0|Nu448{)`#BooBC)npO zRY}$Av=)nnPL~6W5h(;wS5>KXTAh-rbb`|kc7>EO&SJ@$qpUk4LA|RVtM@ zI(h~`MIud3PWqPk(qy!ek&%!P5r6|ha2ZWj;#+e6{(Y;}%49M}M@Q@H>oE*Ny}T>{ zgM)*B5zWM9D1bo)Dhx1`&2A(}jE&KxGzv~(Fo=>8r{GeW)NC>-C=`NnCqS7%;BYvq z)zyd|0SAzbBut6v^#*tM8h{yBSF=cjD>0>!WORT-kLcCa>cGIj($Z3eLb1uylL?TM zo?cZ|g|HA{0*>Qat(Hm+0bq(m5+*QN2&{3UN4ybqGx+ z^DQY!PEMA|WCDSJ&1QRhdwZc?U;z{bgMpAm1sIl=mX@EN&qmqMNaPvBcnXfwq*9aF zL{U%(Ap~UtgF#kpgWoKv0<#Olbq|;()X=(BD@~W(?6bglT zd3jEo&55EHSCc~tT^0x<`9%N=AIzD{Uj=np#7`zfg>#Z3V}{TDd(Z!B8KWQtuad}i)RH=J% z@$RJI-Q9bg#g`Wqy-BZ&O2nQEL+|*t2~Y3;tajizK zG7#9eo=$~h(#z7qmjUjc0lW9Jv;W&zIPDR-vFM+J$J$bxW?fS<6M_@2Zut6r;2-v> zFW!DH!&nhXH^ot{!kC}er)M@jHSO{1Ij2dsD)RPr?TyRpl@vbUn)!)m(xT+TcJ<@w z^VfylrU%_eh0*PCeH!u^(Tx1#(CbU@!lLON1z+*HPVBHwltsRYzi^}@?9&?b)`m|V zg-Bd~T|fnI;mLzF=#SR7wH57j$f1p;yiYu&{kGrd4FbFvB(X zz$=dwjeogSv*yYR)y@>ocJJGTAI_J~EbQqm9++9Qa>+KywcO|VlV@vF8;*UPoo6dQ zkluVXB=zB2b^$eIa^(2>qg5M*-6EzN|E_CUniw1GI5C}6VDfSDCYov)9tUmLAEod9 zpn2W>QJ2@sFAF6 Date: Sun, 2 Jan 2022 18:03:21 +0100 Subject: [PATCH 031/202] Delete mmind directory --- mmind/app.js | 198 -------------------------------------------------- mmind/app.png | Bin 1339 -> 0 bytes 2 files changed, 198 deletions(-) delete mode 100644 mmind/app.js delete mode 100644 mmind/app.png diff --git a/mmind/app.js b/mmind/app.js deleted file mode 100644 index e7def025d..000000000 --- a/mmind/app.js +++ /dev/null @@ -1,198 +0,0 @@ -//MMind - -//set vars -const H = g.getWidth(); -const W = g.getHeight(); -var touch_actions = []; -var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; -var turn = 0; -var col_menu = false; -//pinsRow = 6; -//pinsThick = 10; -//pinsRow = 5; -//pinsThick = 10; -var pinsRow = 4; -var pinsThick = 10; -var play = [-1, -1, -1, -1]; - -var pinsCol = 5; -var playx = -1; -var sx = (W - 30 )/pinsRow; -var sy = (H - 20 )/7; -var touch_actions = []; -var secret = []; -var secret_no_dub = true; -var endgame = false; - -g.clear(); -g.setColor("#FFFFFF"); -g.fillRect(0, 0, H, W); -g.setFont("Vector12",45); - -function draw() { - touch_actions = []; - g.clear(); - g.setColor("#FFFFFF"); - g.fillRect(0, 0, H, W); - g.setColor("#000000"); - //draw scores - for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); - secret[i]= s; - } - } - -function score() { - bScore = 0; - wScore = 0; - for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && - e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { - // a action is hit, add acctions here, todo: start, stop, new, etc. - switch (touch_actions[i][1][0]) { - case 1: - //get pins col menu - col_menu = 1; - playx = touch_actions[i][1][1]; - break; - case 2: - //copy choice col to play - play[playx] = touch_actions[i][1][1]; - col_menu = 0; - break; - case 3: - //score play - var sc; - sc = score(); - game.push([play, sc]); - play = [-1,-1,-1,-1]; - turn+=1; - if (turn==6 || sc[0]==pinsRow) { - play = secret; - col_menu = 0; - endgame = true; - } - break; - case 4: - //new game - play = [-1,-1,-1,-1]; - game = []; - endgame=false; - break; - } - } - } - //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); - - draw(); - } -); - - -game = []; -get_secret(); -draw(); -//Bangle.loadWidgets(); -//Bangle.drawWidgets(); - - - - - diff --git a/mmind/app.png b/mmind/app.png deleted file mode 100644 index bb2a27ae5c614707bb35d6400f75e54514db68f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1339 zcmWksdsLDK6u&Bc8AzQnW~4PLALTKIS<=?yL>fMGil(EZsY6p+Ddraun#DXU*>}En zENaEf9LG?zAR~69ma$sSLu6rV_&jP4W=qXXQ&eJ~f82Y|@7{Co{oUWW^7yz2DtS2> z0H{%s;XER;=FHuV@EJV|^h9te;zjHPO`Fdf0+4bzyEy=jKT&2g=K;7D#m6S?ayp$u zLqn%dokCI6Xf*cq^+_a>&dyGo%_fyf&1SRRZZ{YV0|Nu448{)`#BooBC)npO zRY}$Av=)nnPL~6W5h(;wS5>KXTAh-rbb`|kc7>EO&SJ@$qpUk4LA|RVtM@ zI(h~`MIud3PWqPk(qy!ek&%!P5r6|ha2ZWj;#+e6{(Y;}%49M}M@Q@H>oE*Ny}T>{ zgM)*B5zWM9D1bo)Dhx1`&2A(}jE&KxGzv~(Fo=>8r{GeW)NC>-C=`NnCqS7%;BYvq z)zyd|0SAzbBut6v^#*tM8h{yBSF=cjD>0>!WORT-kLcCa>cGIj($Z3eLb1uylL?TM zo?cZ|g|HA{0*>Qat(Hm+0bq(m5+*QN2&{3UN4ybqGx+ z^DQY!PEMA|WCDSJ&1QRhdwZc?U;z{bgMpAm1sIl=mX@EN&qmqMNaPvBcnXfwq*9aF zL{U%(Ap~UtgF#kpgWoKv0<#Olbq|;()X=(BD@~W(?6bglT zd3jEo&55EHSCc~tT^0x<`9%N=AIzD{Uj=np#7`zfg>#Z3V}{TDd(Z!B8KWQtuad}i)RH=J% z@$RJI-Q9bg#g`Wqy-BZ&O2nQEL+|*t2~Y3;tajizK zG7#9eo=$~h(#z7qmjUjc0lW9Jv;W&zIPDR-vFM+J$J$bxW?fS<6M_@2Zut6r;2-v> zFW!DH!&nhXH^ot{!kC}er)M@jHSO{1Ij2dsD)RPr?TyRpl@vbUn)!)m(xT+TcJ<@w z^VfylrU%_eh0*PCeH!u^(Tx1#(CbU@!lLON1z+*HPVBHwltsRYzi^}@?9&?b)`m|V zg-Bd~T|fnI;mLzF=#SR7wH57j$f1p;yiYu&{kGrd4FbFvB(X zz$=dwjeogSv*yYR)y@>ocJJGTAI_J~EbQqm9++9Qa>+KywcO|VlV@vF8;*UPoo6dQ zkluVXB=zB2b^$eIa^(2>qg5M*-6EzN|E_CUniw1GI5C}6VDfSDCYov)9tUmLAEod9 zpn2W>QJ2@sFAF6 Date: Sun, 2 Jan 2022 18:04:12 +0100 Subject: [PATCH 032/202] Create app.js --- apps/mmind/app.js | 198 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 apps/mmind/app.js diff --git a/apps/mmind/app.js b/apps/mmind/app.js new file mode 100644 index 000000000..e7def025d --- /dev/null +++ b/apps/mmind/app.js @@ -0,0 +1,198 @@ +//MMind + +//set vars +const H = g.getWidth(); +const W = g.getHeight(); +var touch_actions = []; +var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; +var turn = 0; +var col_menu = false; +//pinsRow = 6; +//pinsThick = 10; +//pinsRow = 5; +//pinsThick = 10; +var pinsRow = 4; +var pinsThick = 10; +var play = [-1, -1, -1, -1]; + +var pinsCol = 5; +var playx = -1; +var sx = (W - 30 )/pinsRow; +var sy = (H - 20 )/7; +var touch_actions = []; +var secret = []; +var secret_no_dub = true; +var endgame = false; + +g.clear(); +g.setColor("#FFFFFF"); +g.fillRect(0, 0, H, W); +g.setFont("Vector12",45); + +function draw() { + touch_actions = []; + g.clear(); + g.setColor("#FFFFFF"); + g.fillRect(0, 0, H, W); + g.setColor("#000000"); + //draw scores + for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); + secret[i]= s; + } + } + +function score() { + bScore = 0; + wScore = 0; + for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && + e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { + // a action is hit, add acctions here, todo: start, stop, new, etc. + switch (touch_actions[i][1][0]) { + case 1: + //get pins col menu + col_menu = 1; + playx = touch_actions[i][1][1]; + break; + case 2: + //copy choice col to play + play[playx] = touch_actions[i][1][1]; + col_menu = 0; + break; + case 3: + //score play + var sc; + sc = score(); + game.push([play, sc]); + play = [-1,-1,-1,-1]; + turn+=1; + if (turn==6 || sc[0]==pinsRow) { + play = secret; + col_menu = 0; + endgame = true; + } + break; + case 4: + //new game + play = [-1,-1,-1,-1]; + game = []; + endgame=false; + break; + } + } + } + //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); + + draw(); + } +); + + +game = []; +get_secret(); +draw(); +//Bangle.loadWidgets(); +//Bangle.drawWidgets(); + + + + + From fd7264a31d97c02bfb64504881fc4cfd22809e2c Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 18:04:39 +0100 Subject: [PATCH 033/202] Add files via upload --- apps/mmind/app.png | Bin 0 -> 1339 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/mmind/app.png diff --git a/apps/mmind/app.png b/apps/mmind/app.png new file mode 100644 index 0000000000000000000000000000000000000000..bb2a27ae5c614707bb35d6400f75e54514db68f5 GIT binary patch literal 1339 zcmWksdsLDK6u&Bc8AzQnW~4PLALTKIS<=?yL>fMGil(EZsY6p+Ddraun#DXU*>}En zENaEf9LG?zAR~69ma$sSLu6rV_&jP4W=qXXQ&eJ~f82Y|@7{Co{oUWW^7yz2DtS2> z0H{%s;XER;=FHuV@EJV|^h9te;zjHPO`Fdf0+4bzyEy=jKT&2g=K;7D#m6S?ayp$u zLqn%dokCI6Xf*cq^+_a>&dyGo%_fyf&1SRRZZ{YV0|Nu448{)`#BooBC)npO zRY}$Av=)nnPL~6W5h(;wS5>KXTAh-rbb`|kc7>EO&SJ@$qpUk4LA|RVtM@ zI(h~`MIud3PWqPk(qy!ek&%!P5r6|ha2ZWj;#+e6{(Y;}%49M}M@Q@H>oE*Ny}T>{ zgM)*B5zWM9D1bo)Dhx1`&2A(}jE&KxGzv~(Fo=>8r{GeW)NC>-C=`NnCqS7%;BYvq z)zyd|0SAzbBut6v^#*tM8h{yBSF=cjD>0>!WORT-kLcCa>cGIj($Z3eLb1uylL?TM zo?cZ|g|HA{0*>Qat(Hm+0bq(m5+*QN2&{3UN4ybqGx+ z^DQY!PEMA|WCDSJ&1QRhdwZc?U;z{bgMpAm1sIl=mX@EN&qmqMNaPvBcnXfwq*9aF zL{U%(Ap~UtgF#kpgWoKv0<#Olbq|;()X=(BD@~W(?6bglT zd3jEo&55EHSCc~tT^0x<`9%N=AIzD{Uj=np#7`zfg>#Z3V}{TDd(Z!B8KWQtuad}i)RH=J% z@$RJI-Q9bg#g`Wqy-BZ&O2nQEL+|*t2~Y3;tajizK zG7#9eo=$~h(#z7qmjUjc0lW9Jv;W&zIPDR-vFM+J$J$bxW?fS<6M_@2Zut6r;2-v> zFW!DH!&nhXH^ot{!kC}er)M@jHSO{1Ij2dsD)RPr?TyRpl@vbUn)!)m(xT+TcJ<@w z^VfylrU%_eh0*PCeH!u^(Tx1#(CbU@!lLON1z+*HPVBHwltsRYzi^}@?9&?b)`m|V zg-Bd~T|fnI;mLzF=#SR7wH57j$f1p;yiYu&{kGrd4FbFvB(X zz$=dwjeogSv*yYR)y@>ocJJGTAI_J~EbQqm9++9Qa>+KywcO|VlV@vF8;*UPoo6dQ zkluVXB=zB2b^$eIa^(2>qg5M*-6EzN|E_CUniw1GI5C}6VDfSDCYov)9tUmLAEod9 zpn2W>QJ2@sFAF6 Date: Sun, 2 Jan 2022 18:09:55 +0100 Subject: [PATCH 034/202] Create app-icon.js --- apps/mmind/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mmind/app-icon.js diff --git a/apps/mmind/app-icon.js b/apps/mmind/app-icon.js new file mode 100644 index 000000000..9bcedc5f3 --- /dev/null +++ b/apps/mmind/app-icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("mEwgn/AF/ykYEMmUvAYPzAIX/rnMBIPzu93n4EB1OZBIW73U/+cQ/8Qn/05nM4f/+wXBt//+OZzOv//63e7j/zmI1Bn/1C4f3C4NzCQIXByf/nYXBDgPxKQM/+IvGv4XFF4QXF+ZfGAgQXBAgPyC4JpBC4QJBmEBQoUggQECmAEDBIR3BgURCgNnFQerEoXzp3kAgWIxBCBgMD+cC+JyD+JVD+nu91PBIIXBj/yj8h+MCOQSKCC4OzC4fj/84C4OPC4UiiQvEQogXCof//AvFgMBRQoXBAgVO9yPCL4cfiUziP/mMSQoUyiYECmguBAAMxkYDBkMf/4FCAH4A/AH4A/AH4A/AH4A/AH4Ap5gACAoM/BIXzAhgXE+MDBoXwh4EC+IEDBIYXE+UfBoXyl4ELI4pfXACPdAASrv")) From 3ba5066073c151800c01f7867232e15e435f3831 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 18:16:01 +0100 Subject: [PATCH 035/202] added mmind app --- apps.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e5e9f8f02..5bbde6af5 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,20 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] - } + }, + + { "id": "mmind", + "name": "Clasic Mind Game", + "shortName":"Master Mind", + "icon": "app.png", + "version":"0.01", + "description": "This is a classic mind game for bangles 2", + "tags": "masterminf, game", + "storage": [ + {"name":"timer.app.js","url":"app.js"}, + {"name":"mmind.img","url":"app-icon.js","evaluate":true} + ] +} +] + ] From 8a75baae96d0c913e93c6e091033d6449e8a81fc Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 18:17:15 +0100 Subject: [PATCH 036/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 5bbde6af5..09c171616 100644 --- a/apps.json +++ b/apps.json @@ -5065,7 +5065,7 @@ }, { "id": "mmind", - "name": "Clasic Mind Game", + "name": "Classic Mind Game", "shortName":"Master Mind", "icon": "app.png", "version":"0.01", From f6e71200c177f17968798cae63100b43cbb7f39a Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 18:18:23 +0100 Subject: [PATCH 037/202] Update apps.json --- apps.json | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 09c171616..74b5b49b5 100644 --- a/apps.json +++ b/apps.json @@ -5063,7 +5063,6 @@ {"name":"ltherm.img","url":"icon.js","evaluate":true} ] }, - { "id": "mmind", "name": "Classic Mind Game", "shortName":"Master Mind", @@ -5074,8 +5073,7 @@ "storage": [ {"name":"timer.app.js","url":"app.js"}, {"name":"mmind.img","url":"app-icon.js","evaluate":true} - ] -} -] - + ] + } ] + From f93c785d1959ac2e4a19e73dafed443bb2c6bab6 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sun, 2 Jan 2022 21:23:43 +0100 Subject: [PATCH 038/202] Update apps.json --- apps.json | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/apps.json b/apps.json index 74b5b49b5..28dcf6912 100644 --- a/apps.json +++ b/apps.json @@ -5063,17 +5063,19 @@ {"name":"ltherm.img","url":"icon.js","evaluate":true} ] }, - { "id": "mmind", - "name": "Classic Mind Game", - "shortName":"Master Mind", - "icon": "app.png", - "version":"0.01", - "description": "This is a classic mind game for bangles 2", - "tags": "masterminf, game", - "storage": [ - {"name":"timer.app.js","url":"app.js"}, - {"name":"mmind.img","url":"app-icon.js","evaluate":true} + { + "id": "mmind", + "name": "Classic Mind Game", + "shortName":"Master Mind", + "icon": "app.png", + "version":"0.01", + "description": "This is a classic mind game", + "type": "game", + "tags": "mastermind, game, bangle 2", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"mmind.app.js","url":"app.js"}, + {"name":"mmind.img","url":"app-icon.js","evaluate":true} ] } ] - From ac6140704d5afb068009a4bfbdf49218101a507e Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:13:07 +0100 Subject: [PATCH 039/202] Delete app.js --- apps/mmind/app.js | 198 ---------------------------------------------- 1 file changed, 198 deletions(-) delete mode 100644 apps/mmind/app.js diff --git a/apps/mmind/app.js b/apps/mmind/app.js deleted file mode 100644 index e7def025d..000000000 --- a/apps/mmind/app.js +++ /dev/null @@ -1,198 +0,0 @@ -//MMind - -//set vars -const H = g.getWidth(); -const W = g.getHeight(); -var touch_actions = []; -var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; -var turn = 0; -var col_menu = false; -//pinsRow = 6; -//pinsThick = 10; -//pinsRow = 5; -//pinsThick = 10; -var pinsRow = 4; -var pinsThick = 10; -var play = [-1, -1, -1, -1]; - -var pinsCol = 5; -var playx = -1; -var sx = (W - 30 )/pinsRow; -var sy = (H - 20 )/7; -var touch_actions = []; -var secret = []; -var secret_no_dub = true; -var endgame = false; - -g.clear(); -g.setColor("#FFFFFF"); -g.fillRect(0, 0, H, W); -g.setFont("Vector12",45); - -function draw() { - touch_actions = []; - g.clear(); - g.setColor("#FFFFFF"); - g.fillRect(0, 0, H, W); - g.setColor("#000000"); - //draw scores - for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); - secret[i]= s; - } - } - -function score() { - bScore = 0; - wScore = 0; - for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && - e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { - // a action is hit, add acctions here, todo: start, stop, new, etc. - switch (touch_actions[i][1][0]) { - case 1: - //get pins col menu - col_menu = 1; - playx = touch_actions[i][1][1]; - break; - case 2: - //copy choice col to play - play[playx] = touch_actions[i][1][1]; - col_menu = 0; - break; - case 3: - //score play - var sc; - sc = score(); - game.push([play, sc]); - play = [-1,-1,-1,-1]; - turn+=1; - if (turn==6 || sc[0]==pinsRow) { - play = secret; - col_menu = 0; - endgame = true; - } - break; - case 4: - //new game - play = [-1,-1,-1,-1]; - game = []; - endgame=false; - break; - } - } - } - //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); - - draw(); - } -); - - -game = []; -get_secret(); -draw(); -//Bangle.loadWidgets(); -//Bangle.drawWidgets(); - - - - - From 377099b81af2f457c8fa5d1ca87c737b95f4ca46 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:19:55 +0100 Subject: [PATCH 040/202] Delete app.png --- apps/mmind/app.png | Bin 1339 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/mmind/app.png diff --git a/apps/mmind/app.png b/apps/mmind/app.png deleted file mode 100644 index bb2a27ae5c614707bb35d6400f75e54514db68f5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1339 zcmWksdsLDK6u&Bc8AzQnW~4PLALTKIS<=?yL>fMGil(EZsY6p+Ddraun#DXU*>}En zENaEf9LG?zAR~69ma$sSLu6rV_&jP4W=qXXQ&eJ~f82Y|@7{Co{oUWW^7yz2DtS2> z0H{%s;XER;=FHuV@EJV|^h9te;zjHPO`Fdf0+4bzyEy=jKT&2g=K;7D#m6S?ayp$u zLqn%dokCI6Xf*cq^+_a>&dyGo%_fyf&1SRRZZ{YV0|Nu448{)`#BooBC)npO zRY}$Av=)nnPL~6W5h(;wS5>KXTAh-rbb`|kc7>EO&SJ@$qpUk4LA|RVtM@ zI(h~`MIud3PWqPk(qy!ek&%!P5r6|ha2ZWj;#+e6{(Y;}%49M}M@Q@H>oE*Ny}T>{ zgM)*B5zWM9D1bo)Dhx1`&2A(}jE&KxGzv~(Fo=>8r{GeW)NC>-C=`NnCqS7%;BYvq z)zyd|0SAzbBut6v^#*tM8h{yBSF=cjD>0>!WORT-kLcCa>cGIj($Z3eLb1uylL?TM zo?cZ|g|HA{0*>Qat(Hm+0bq(m5+*QN2&{3UN4ybqGx+ z^DQY!PEMA|WCDSJ&1QRhdwZc?U;z{bgMpAm1sIl=mX@EN&qmqMNaPvBcnXfwq*9aF zL{U%(Ap~UtgF#kpgWoKv0<#Olbq|;()X=(BD@~W(?6bglT zd3jEo&55EHSCc~tT^0x<`9%N=AIzD{Uj=np#7`zfg>#Z3V}{TDd(Z!B8KWQtuad}i)RH=J% z@$RJI-Q9bg#g`Wqy-BZ&O2nQEL+|*t2~Y3;tajizK zG7#9eo=$~h(#z7qmjUjc0lW9Jv;W&zIPDR-vFM+J$J$bxW?fS<6M_@2Zut6r;2-v> zFW!DH!&nhXH^ot{!kC}er)M@jHSO{1Ij2dsD)RPr?TyRpl@vbUn)!)m(xT+TcJ<@w z^VfylrU%_eh0*PCeH!u^(Tx1#(CbU@!lLON1z+*HPVBHwltsRYzi^}@?9&?b)`m|V zg-Bd~T|fnI;mLzF=#SR7wH57j$f1p;yiYu&{kGrd4FbFvB(X zz$=dwjeogSv*yYR)y@>ocJJGTAI_J~EbQqm9++9Qa>+KywcO|VlV@vF8;*UPoo6dQ zkluVXB=zB2b^$eIa^(2>qg5M*-6EzN|E_CUniw1GI5C}6VDfSDCYov)9tUmLAEod9 zpn2W>QJ2@sFAF6 Date: Mon, 3 Jan 2022 15:20:30 +0100 Subject: [PATCH 041/202] Add files via upload --- apps/mmind/mmind.app.js | 3395 +++++++++++++++++++++++++++++++++++++++ apps/mmind/mmind.png | Bin 0 -> 1546 bytes 2 files changed, 3395 insertions(+) create mode 100644 apps/mmind/mmind.app.js create mode 100644 apps/mmind/mmind.png diff --git a/apps/mmind/mmind.app.js b/apps/mmind/mmind.app.js new file mode 100644 index 000000000..52a566ca9 --- /dev/null +++ b/apps/mmind/mmind.app.js @@ -0,0 +1,3395 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + BangleApps/app.js at master · psbest/BangleApps + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
+ + + +
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + psbest  /   + BangleApps  /   + +
+ + + + Type # for issues and pull requests, > for commands, and ? for help + + + Type # for issues, pull requests, and projects, > for commands, and ? for help + + + Type # for issues, pull requests, and projects, / for files, and > for commands + + +
+ +
+
+ We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. +
+
+ + No results matched your search + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + Search for issues and pull requests + + # + + + + Search for issues, pull requests, discussions, and projects + + # + + + + Search for organizations, repositories, and users + + @ + + + + Search for projects + + ! + + + + Search for files + + / + + + + Activate command mode + + > + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Search your issues, pull requests, and discussions + + # author:@me + + + + Filter to pull requests + + # is:pr + + + + Filter to issues + + # is:issue + + + + Filter to discussions + + # is:discussion + + + + Filter to projects + + # is:project + + + + Filter to open issues, pull requests, and discussions + + # is:open + + + + + + + + + + + + + + + + +
+
+
+ +
+ + + + + + + + + + +
+ + + + +
+
+
+ + + + + + + + + + +
+ +
+ +
+

+ + + / + + BangleApps + + + Public +

+ + forked from espruino/BangleApps + + +
+ +
    + +
  • + +
    + + + + + + + Watch + + + 0 + + + +
    +
    +

    Notifications

    + +
    + +
    +
    + + + + + + + + +
    + + +
    + + + + + Get push notifications on iOS or Android. + +
    +
    +
    +
    + + +
    +
    +
    + + + +
  • + + +
  • + + +
  • + +
  • + +
    +
    + +
    +
    + +
    +
    + + + + + +
    + +
    +
    + + + + + + + +
    + +
    +
    +
    +
    +
    +
  • + + +
  • + + +
  • +
+ +
+ +
+
+ + + + +
+ + + +
+
+ + Open in github.dev + Open in a new github.dev tab + + + + + + + +
+ + + + + Permalink + + +
+ +
+
+ + + master + + + + +
+
+
+ Switch branches/tags + +
+ + + +
+ +
+ +
+ + +
+ +
+ + + + + + + + + + + + + + + + +
+ + +
+
+
+
+ +
+ +
+ + + + Go to file + + +
+ + + + +
+
+
+ + + + +
+ +
+
+
 
+
+ +
+
 
+ Cannot retrieve contributors at this time +
+
+ + + + + + + + + + + +
+ +
+ + +
+ + 198 lines (178 sloc) + + 4.59 KB +
+ +
+ + + + +
+ + + + + + + + + + + + + + + +
+ +
+
+ +
+
+ +
+ +
+
+ + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
//MMind
+
//set vars
const H = g.getWidth();
const W = g.getHeight();
var touch_actions = [];
var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"];
var turn = 0;
var col_menu = false;
//pinsRow = 6;
//pinsThick = 10;
//pinsRow = 5;
//pinsThick = 10;
var pinsRow = 4;
var pinsThick = 10;
var play = [-1, -1, -1, -1];
+
var pinsCol = 5;
var playx = -1;
var sx = (W - 30 )/pinsRow;
var sy = (H - 20 )/7;
var touch_actions = [];
var secret = [];
var secret_no_dub = true;
var endgame = false;
+
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setFont("Vector12",45);
+
function draw() {
touch_actions = [];
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setColor("#000000");
//draw scores
for (y=0;y<game.length;y+=1) {
pp = game[y][0];
ps = game[y][1];
g.setColor("#000000");
//g.fillRect(W-30,10, W-30, 15);
g.setColor("#000000");
g.setFont("Vector30",10);
g.drawString(ps[0],W-31,y*sy+8);
g.setColor("#000000");
g.drawString(ps[1],W-15,y*sy+8);
g.setColor("#000000");
for (x=0;x<pinsRow;x+=1) {
xx = sx*x + pinsThick + 5;
yy = sy*y+20;
xc = pp[x];
g.setColor(cols[xc]);
g.fillCircle(xx,yy , pinsThick );
g.setColor("#000000");
g.drawCircle(xx,yy,pinsThick+1);
g.drawCircle(xx,yy,pinsThick);
}
}
//draw play input
for (k=0; k<pinsRow; k+=1){
xx = sx*k + pinsThick + 5;
yy = sy*7;
touch_actions.push([[xx-pinsThick-5, yy-pinsThick-10, xx+pinsThick+5, yy+pinsThick+20],[1,k]]);
if (play[k] < 0) {
//col not choisen, draw small dot
g.setColor("#000000");
g.fillCircle(xx,yy , 3 );
} else {
g.setColor(cols[play[k]]);
g.fillCircle(xx,yy , pinsThick );
+
}
}
// draw action button
// score, men
if (!endgame) {
if (col_menu) {
draw_col_choice();
} else {
// check if all pins are set yet
if (Math.min.apply(null,play) < 0) {
g.setColor("#FF0000");
} else {
g.setColor("#00FF00");
touch_actions.push([[W-30, H-30,192, 190], [3,1]]);
}
g.fillRect(W-30, H-30, W-1, H-10);
}
} else {
g.setColor("#0000FF");
touch_actions.push([[W-30, H-30,192, 190], [4,1]]);
g.fillRect(W-30, H-30, W-1, H-10);
}
}
+
function get_secret() {
//secret=[];
for (i=0; i<pinsRow; i+=1) {
s = Math.round(Math.random()*pinsCol);
if (secret_no_dub)
while(secret.indexOf(s) >= 0) s = Math.round(Math.random()*pinsCol);
secret[i]= s;
}
}
+
function score() {
bScore = 0;
wScore = 0;
for (i=0; i<pinsRow; i+=1) {
if (secret[i] == play[i]) {
bScore +=1;
}
else {
for (s=0; s<pinsRow; s+=1) {
if (secret[i] == play[s]) {
wScore +=1;
break;
}
}
}
}
+
return([bScore, wScore]);
}
+
function draw_col_choice(){
var cc = g.getColor();
var boxw = 30;
var boxh = H/pinsRow-20;
for (i=0; i<=pinsCol; i+=1) {
g.setColor(cols[i]);
g.fillRect(W-boxw, i*boxh, W-1, i*boxh+boxh);
touch_actions.push([[150, i*boxh, 191, i*boxh+boxh], [2,i]]);
g.setColor(cc);
}
+
}
+
Bangle.on('touch', function(zone,e) {
//console.log(e.x, e.y);
// check touch actions array to see what to do
for(i=0; i<touch_actions.length; i+=1) {
if (e.x > touch_actions[i][0][0] && e.x < touch_actions[i][0][2] &&
e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) {
// a action is hit, add acctions here, todo: start, stop, new, etc.
switch (touch_actions[i][1][0]) {
case 1:
//get pins col menu
col_menu = 1;
playx = touch_actions[i][1][1];
break;
case 2:
//copy choice col to play
play[playx] = touch_actions[i][1][1];
col_menu = 0;
break;
case 3:
//score play
var sc;
sc = score();
game.push([play, sc]);
play = [-1,-1,-1,-1];
turn+=1;
if (turn==6 || sc[0]==pinsRow) {
play = secret;
col_menu = 0;
endgame = true;
}
break;
case 4:
//new game
play = [-1,-1,-1,-1];
game = [];
endgame=false;
break;
}
}
}
//console.log(touch_actions[i][1][0], touch_actions[i][1][1]);
draw();
}
);
+
+
game = [];
get_secret();
draw();
//Bangle.loadWidgets();
//Bangle.drawWidgets();
+
+
+
+
+
+ + + +
+ +
+ + + + +
+ + +
+ + +
+
+ + + + +
+ + + +
+
+ +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + diff --git a/apps/mmind/mmind.png b/apps/mmind/mmind.png new file mode 100644 index 0000000000000000000000000000000000000000..8afcc26974bc8eaa2239927b33b4d566e8df42ba GIT binary patch literal 1546 zcmV+l2KD)gP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D1)oVoK~z{r?U-F? z6Im3;PqV{V8ipugkQ7?8+6Es=Ed5|9Qi@bXs_cUgVqsSiDSZ$>=tC$=D3KD;4QZii z_aQWYinyuOH0vSU0pqX{J70#8yOkFCQYcjt?fT08+MKe z0zQWJBjn4MFIDcULX3dyl@}KmSrn((t?0hSQ0pGoMbj5EvIon-q-?~(8)kx$ZXCk?HItTvuF43->3XPinTZhcM)>?_U)RQ8q5r*v%9`hzx>~6b==u?AkS3Dn*NSbW|K2Ej$$og~L)XNMo6db+Di^>}58av8Zvv z9zTBE)YPn+3xsd96bp{B5q(eQe`XU?3NpP$cUGVk8K!~AFsMRQS5$t<@|qcY2^Mr9RAjmkDQ zqNak#pr$6PR#~z_qq12GR~drez<9-F!b;k?bLZIDSZizRsZ*!uV0Jvz#5F2Qt2Biq z%^H=_-YOD_LSMYioYbgHPH(BQmX;PQrhE79(S!mg1Lh$!*{`MZ~vWp^Wbk>AQBNxrmiDL4jeeZoa^iBmoHy_@#4j0uoc;GuF z*ksVWJ5$z`jU(h|e3?}YHTd58<_$IQO@7A?#ihskI>gwB-+&1%k)>AB%62y-B85p9 zody0O#F5{>s3e5%i{zP~Cyk9tS0J)Xrlz?6`%F*sF5jFqAvbZWeKL_#B*i*Xe$8jY z&R@8j)6t>o3dC;beihH3KcAVI;SI*t3DFu#;GrT3$uy*S1BvrbPEj+V=?n3qFr}fP z;o!l8yrBn8NW?>h0D?(f>~tSTMNw1K^et{GT)K3rv$K;obiw(1NnT>16ZD z`CGeWe{nbG!2=?Sn-flYdbt1lY`tV$Wig0dhwErKz|jF6N~$U%0ON|$0#LjgL-&Q? w=1pqU)j@l^;?iSo4*L4It;N`m`91*u1O9JFJ2Em3SpWb407*qoM6N<$g6%QmuK)l5 literal 0 HcmV?d00001 From ff363e10955cb4b82ecd53b10d697f30b8b4c39b Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:27:45 +0100 Subject: [PATCH 042/202] Update apps.json --- apps.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index 28dcf6912..6f435fb82 100644 --- a/apps.json +++ b/apps.json @@ -5067,15 +5067,15 @@ "id": "mmind", "name": "Classic Mind Game", "shortName":"Master Mind", - "icon": "app.png", + "icon": "mmind.png", "version":"0.01", "description": "This is a classic mind game", "type": "game", - "tags": "mastermind, game, bangle 2", + "tags": "master mind, game, classic", "supports": ["BANGLEJS2"], "storage": [ - {"name":"mmind.app.js","url":"app.js"}, - {"name":"mmind.img","url":"app-icon.js","evaluate":true} + {"name":"mmind.app.js","url":"mmind.app.js"}, + {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] } ] From 4e40afbc87ef1c616c80e49d6cf0220b63310341 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:44:09 +0100 Subject: [PATCH 043/202] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 6f435fb82..50b2f3752 100644 --- a/apps.json +++ b/apps.json @@ -5069,9 +5069,9 @@ "shortName":"Master Mind", "icon": "mmind.png", "version":"0.01", - "description": "This is a classic mind game", + "description": "This is the classic game for masterminds", "type": "game", - "tags": "master mind, game, classic", + "tags": "mastermind, game, classic", "supports": ["BANGLEJS2"], "storage": [ {"name":"mmind.app.js","url":"mmind.app.js"}, From a6e7011b0d74fbbeb6b96f4c20dd3f43b60e7248 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 15:58:29 +0100 Subject: [PATCH 044/202] create changelog --- apps/mmind/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mmind/ChangeLog diff --git a/apps/mmind/ChangeLog b/apps/mmind/ChangeLog new file mode 100644 index 000000000..939ac3b5d --- /dev/null +++ b/apps/mmind/ChangeLog @@ -0,0 +1 @@ +0.01: First release From d12c58a6c6f07b1c8b47ebda14eadaf690510815 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:07:29 +0100 Subject: [PATCH 045/202] Delete app-icon.js --- apps/mmind/app-icon.js | 1 - 1 file changed, 1 deletion(-) delete mode 100644 apps/mmind/app-icon.js diff --git a/apps/mmind/app-icon.js b/apps/mmind/app-icon.js deleted file mode 100644 index 9bcedc5f3..000000000 --- a/apps/mmind/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -E.toArrayBuffer(atob("mEwgn/AF/ykYEMmUvAYPzAIX/rnMBIPzu93n4EB1OZBIW73U/+cQ/8Qn/05nM4f/+wXBt//+OZzOv//63e7j/zmI1Bn/1C4f3C4NzCQIXByf/nYXBDgPxKQM/+IvGv4XFF4QXF+ZfGAgQXBAgPyC4JpBC4QJBmEBQoUggQECmAEDBIR3BgURCgNnFQerEoXzp3kAgWIxBCBgMD+cC+JyD+JVD+nu91PBIIXBj/yj8h+MCOQSKCC4OzC4fj/84C4OPC4UiiQvEQogXCof//AvFgMBRQoXBAgVO9yPCL4cfiUziP/mMSQoUyiYECmguBAAMxkYDBkMf/4FCAH4A/AH4A/AH4A/AH4A/AH4Ap5gACAoM/BIXzAhgXE+MDBoXwh4EC+IEDBIYXE+UfBoXyl4ELI4pfXACPdAASrv")) From b33d629065fc0a57bbe3787ea2a61c2f29b1d667 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:07:53 +0100 Subject: [PATCH 046/202] Add files via upload --- apps/mmind/mmind.icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mmind/mmind.icon.js diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js new file mode 100644 index 000000000..c6f72ca38 --- /dev/null +++ b/apps/mmind/mmind.icon.js @@ -0,0 +1 @@ +E.toArrayBuffer(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) \ No newline at end of file From 503b64e817b3c98a5dcea565888db4d0e26a99b3 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:10:50 +0100 Subject: [PATCH 047/202] Update mmind.icon.js --- apps/mmind/mmind.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js index c6f72ca38..976243b48 100644 --- a/apps/mmind/mmind.icon.js +++ b/apps/mmind/mmind.icon.js @@ -1 +1 @@ -E.toArrayBuffer(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) \ No newline at end of file +require("heatshrink").decompress(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) From d0583def6bcfb19282b827ae1deae61e84b9f5c7 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:16:27 +0100 Subject: [PATCH 048/202] Delete mmind.app.js --- apps/mmind/mmind.app.js | 3395 --------------------------------------- 1 file changed, 3395 deletions(-) delete mode 100644 apps/mmind/mmind.app.js diff --git a/apps/mmind/mmind.app.js b/apps/mmind/mmind.app.js deleted file mode 100644 index 52a566ca9..000000000 --- a/apps/mmind/mmind.app.js +++ /dev/null @@ -1,3395 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - BangleApps/app.js at master · psbest/BangleApps - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - -
- - - -
- - - - - - - - - -
- - - - - - - - - - - - - - - - - - - - - -
- -
- - - psbest  /   - BangleApps  /   - -
- - - - Type # for issues and pull requests, > for commands, and ? for help - - - Type # for issues, pull requests, and projects, > for commands, and ? for help - - - Type # for issues, pull requests, and projects, / for files, and > for commands - - -
- -
-
- We’ve encountered an error and some results aren't available at this time. Type a new search or try again later. -
-
- - No results matched your search - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - - - - Search for issues and pull requests - - # - - - - Search for issues, pull requests, discussions, and projects - - # - - - - Search for organizations, repositories, and users - - @ - - - - Search for projects - - ! - - - - Search for files - - / - - - - Activate command mode - - > - - - - Search your issues, pull requests, and discussions - - # author:@me - - - - Search your issues, pull requests, and discussions - - # author:@me - - - - Filter to pull requests - - # is:pr - - - - Filter to issues - - # is:issue - - - - Filter to discussions - - # is:discussion - - - - Filter to projects - - # is:project - - - - Filter to open issues, pull requests, and discussions - - # is:open - - - - - - - - - - - - - - - - -
-
-
- -
- - - - - - - - - - -
- - - - -
-
-
- - - - - - - - - - -
- -
- -
-

- - - / - - BangleApps - - - Public -

- - forked from espruino/BangleApps - - -
- -
    - -
  • - -
    - - - - - - - Watch - - - 0 - - - -
    -
    -

    Notifications

    - -
    - -
    -
    - - - - - - - - -
    - - -
    - - - - - Get push notifications on iOS or Android. - -
    -
    -
    -
    - - -
    -
    -
    - - - -
  • - - -
  • - - -
  • - -
  • - -
    -
    - -
    -
    - -
    -
    - - - - - -
    - -
    -
    - - - - - - - -
    - -
    -
    -
    -
    -
    -
  • - - -
  • - - -
  • -
- -
- -
-
- - - - -
- - - -
-
- - Open in github.dev - Open in a new github.dev tab - - - - - - - -
- - - - - Permalink - - -
- -
-
- - - master - - - - -
-
-
- Switch branches/tags - -
- - - -
- -
- -
- - -
- -
- - - - - - - - - - - - - - - - -
- - -
-
-
-
- -
- -
- - - - Go to file - - -
- - - - -
-
-
- - - - -
- -
-
-
 
-
- -
-
 
- Cannot retrieve contributors at this time -
-
- - - - - - - - - - - -
- -
- - -
- - 198 lines (178 sloc) - - 4.59 KB -
- -
- - - - -
- - - - - - - - - - - - - - - -
- -
-
- -
-
- -
- -
-
- - - -
- - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//MMind
-
//set vars
const H = g.getWidth();
const W = g.getHeight();
var touch_actions = [];
var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"];
var turn = 0;
var col_menu = false;
//pinsRow = 6;
//pinsThick = 10;
//pinsRow = 5;
//pinsThick = 10;
var pinsRow = 4;
var pinsThick = 10;
var play = [-1, -1, -1, -1];
-
var pinsCol = 5;
var playx = -1;
var sx = (W - 30 )/pinsRow;
var sy = (H - 20 )/7;
var touch_actions = [];
var secret = [];
var secret_no_dub = true;
var endgame = false;
-
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setFont("Vector12",45);
-
function draw() {
touch_actions = [];
g.clear();
g.setColor("#FFFFFF");
g.fillRect(0, 0, H, W);
g.setColor("#000000");
//draw scores
for (y=0;y<game.length;y+=1) {
pp = game[y][0];
ps = game[y][1];
g.setColor("#000000");
//g.fillRect(W-30,10, W-30, 15);
g.setColor("#000000");
g.setFont("Vector30",10);
g.drawString(ps[0],W-31,y*sy+8);
g.setColor("#000000");
g.drawString(ps[1],W-15,y*sy+8);
g.setColor("#000000");
for (x=0;x<pinsRow;x+=1) {
xx = sx*x + pinsThick + 5;
yy = sy*y+20;
xc = pp[x];
g.setColor(cols[xc]);
g.fillCircle(xx,yy , pinsThick );
g.setColor("#000000");
g.drawCircle(xx,yy,pinsThick+1);
g.drawCircle(xx,yy,pinsThick);
}
}
//draw play input
for (k=0; k<pinsRow; k+=1){
xx = sx*k + pinsThick + 5;
yy = sy*7;
touch_actions.push([[xx-pinsThick-5, yy-pinsThick-10, xx+pinsThick+5, yy+pinsThick+20],[1,k]]);
if (play[k] < 0) {
//col not choisen, draw small dot
g.setColor("#000000");
g.fillCircle(xx,yy , 3 );
} else {
g.setColor(cols[play[k]]);
g.fillCircle(xx,yy , pinsThick );
-
}
}
// draw action button
// score, men
if (!endgame) {
if (col_menu) {
draw_col_choice();
} else {
// check if all pins are set yet
if (Math.min.apply(null,play) < 0) {
g.setColor("#FF0000");
} else {
g.setColor("#00FF00");
touch_actions.push([[W-30, H-30,192, 190], [3,1]]);
}
g.fillRect(W-30, H-30, W-1, H-10);
}
} else {
g.setColor("#0000FF");
touch_actions.push([[W-30, H-30,192, 190], [4,1]]);
g.fillRect(W-30, H-30, W-1, H-10);
}
}
-
function get_secret() {
//secret=[];
for (i=0; i<pinsRow; i+=1) {
s = Math.round(Math.random()*pinsCol);
if (secret_no_dub)
while(secret.indexOf(s) >= 0) s = Math.round(Math.random()*pinsCol);
secret[i]= s;
}
}
-
function score() {
bScore = 0;
wScore = 0;
for (i=0; i<pinsRow; i+=1) {
if (secret[i] == play[i]) {
bScore +=1;
}
else {
for (s=0; s<pinsRow; s+=1) {
if (secret[i] == play[s]) {
wScore +=1;
break;
}
}
}
}
-
return([bScore, wScore]);
}
-
function draw_col_choice(){
var cc = g.getColor();
var boxw = 30;
var boxh = H/pinsRow-20;
for (i=0; i<=pinsCol; i+=1) {
g.setColor(cols[i]);
g.fillRect(W-boxw, i*boxh, W-1, i*boxh+boxh);
touch_actions.push([[150, i*boxh, 191, i*boxh+boxh], [2,i]]);
g.setColor(cc);
}
-
}
-
Bangle.on('touch', function(zone,e) {
//console.log(e.x, e.y);
// check touch actions array to see what to do
for(i=0; i<touch_actions.length; i+=1) {
if (e.x > touch_actions[i][0][0] && e.x < touch_actions[i][0][2] &&
e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) {
// a action is hit, add acctions here, todo: start, stop, new, etc.
switch (touch_actions[i][1][0]) {
case 1:
//get pins col menu
col_menu = 1;
playx = touch_actions[i][1][1];
break;
case 2:
//copy choice col to play
play[playx] = touch_actions[i][1][1];
col_menu = 0;
break;
case 3:
//score play
var sc;
sc = score();
game.push([play, sc]);
play = [-1,-1,-1,-1];
turn+=1;
if (turn==6 || sc[0]==pinsRow) {
play = secret;
col_menu = 0;
endgame = true;
}
break;
case 4:
//new game
play = [-1,-1,-1,-1];
game = [];
endgame=false;
break;
}
}
}
//console.log(touch_actions[i][1][0], touch_actions[i][1][1]);
draw();
}
);
-
-
game = [];
get_secret();
draw();
//Bangle.loadWidgets();
//Bangle.drawWidgets();
-
-
-
-
-
- - - -
- -
- - - - -
- - -
- - -
-
- - - - -
- - - -
-
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - From ade75a3e7ce323cad8f862213fe1d68ec20aafce Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:18:11 +0100 Subject: [PATCH 049/202] Add files via upload --- apps/mmind/mmind.app.js | 198 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 198 insertions(+) create mode 100644 apps/mmind/mmind.app.js diff --git a/apps/mmind/mmind.app.js b/apps/mmind/mmind.app.js new file mode 100644 index 000000000..e7def025d --- /dev/null +++ b/apps/mmind/mmind.app.js @@ -0,0 +1,198 @@ +//MMind + +//set vars +const H = g.getWidth(); +const W = g.getHeight(); +var touch_actions = []; +var cols = ["#FF0000","#00FF00","#0000FF", "#FF00FF", "#FFFF00", "#00FFFF", "#000000","#FFFFFF"]; +var turn = 0; +var col_menu = false; +//pinsRow = 6; +//pinsThick = 10; +//pinsRow = 5; +//pinsThick = 10; +var pinsRow = 4; +var pinsThick = 10; +var play = [-1, -1, -1, -1]; + +var pinsCol = 5; +var playx = -1; +var sx = (W - 30 )/pinsRow; +var sy = (H - 20 )/7; +var touch_actions = []; +var secret = []; +var secret_no_dub = true; +var endgame = false; + +g.clear(); +g.setColor("#FFFFFF"); +g.fillRect(0, 0, H, W); +g.setFont("Vector12",45); + +function draw() { + touch_actions = []; + g.clear(); + g.setColor("#FFFFFF"); + g.fillRect(0, 0, H, W); + g.setColor("#000000"); + //draw scores + for (y=0;y= 0) s = Math.round(Math.random()*pinsCol); + secret[i]= s; + } + } + +function score() { + bScore = 0; + wScore = 0; + for (i=0; i touch_actions[i][0][0] && e.x < touch_actions[i][0][2] && + e.y > touch_actions[i][0][1] && e.y < touch_actions[i][0][3]) { + // a action is hit, add acctions here, todo: start, stop, new, etc. + switch (touch_actions[i][1][0]) { + case 1: + //get pins col menu + col_menu = 1; + playx = touch_actions[i][1][1]; + break; + case 2: + //copy choice col to play + play[playx] = touch_actions[i][1][1]; + col_menu = 0; + break; + case 3: + //score play + var sc; + sc = score(); + game.push([play, sc]); + play = [-1,-1,-1,-1]; + turn+=1; + if (turn==6 || sc[0]==pinsRow) { + play = secret; + col_menu = 0; + endgame = true; + } + break; + case 4: + //new game + play = [-1,-1,-1,-1]; + game = []; + endgame=false; + break; + } + } + } + //console.log(touch_actions[i][1][0], touch_actions[i][1][1]); + + draw(); + } +); + + +game = []; +get_secret(); +draw(); +//Bangle.loadWidgets(); +//Bangle.drawWidgets(); + + + + + From 383d183fa8fa302b8ac1db20b5f1b80935978806 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:33:12 +0100 Subject: [PATCH 050/202] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 50b2f3752..b195a5ee3 100644 --- a/apps.json +++ b/apps.json @@ -5073,6 +5073,7 @@ "type": "game", "tags": "mastermind, game, classic", "supports": ["BANGLEJS2"], + "allow_emulator": true, "storage": [ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} From 1241dba5e4833d57b72d5fcdec13218213a7cc44 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Mon, 3 Jan 2022 17:51:01 +0100 Subject: [PATCH 051/202] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index b195a5ee3..eaab9e297 100644 --- a/apps.json +++ b/apps.json @@ -5072,6 +5072,7 @@ "description": "This is the classic game for masterminds", "type": "game", "tags": "mastermind, game, classic", + "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, "storage": [ From b4809c9cdd81b1f358697e10f9e8d805db10bfc9 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 21:32:54 +0100 Subject: [PATCH 052/202] Add files via upload --- apps/mmind/mmind.png | Bin 1546 -> 712 bytes apps/mmind/screenshot_mmind.png | Bin 0 -> 2577 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/mmind/screenshot_mmind.png diff --git a/apps/mmind/mmind.png b/apps/mmind/mmind.png index 8afcc26974bc8eaa2239927b33b4d566e8df42ba..14a3ef7c647be749a768209a9dfaea0a09ab960f 100644 GIT binary patch delta 674 zcmeC;Il-#f8Q|y6%O%Cdz`(%k>ERLtq&I*t3p0?6o%u6&qN0MLM1W6->;M1%fkJTn zp8+iJ|9^zugt-&##Os+XJzX3_GVZ;dh9r6B4J?RMuJ;D?~a9lms4|@hr&o{8I0!Jl|U;hi%dQ8^(G6 z_$;&7>u-B@EPwyI`M`|lk3VY6OO0zw?3nst!ViPfqA91Rrhv%aCll(qPrKVk6&yd{ zFLtMR!&ABYk~fOl&$sPpTlkP?&@;u zUFtV}pd@_ctY-3|SNc0^pFOQV$hxe=^!U$((^Y0ITX*KQMW4~*?U}QDia$ww+fl;5 zXZO$%B z(=)p5(zmpO50o%u)+fz~teY_ZWBoy}E05?rl6`A?;LjXy&kYuA%pZ0gxLVd4z!i62 sJ9ho<(AUSms(Eak$?h27=k=E%;69JIf)@8nU>alaboFyt=akR{0Iy3qcK`qY delta 1534 zcmVVGd00o~(L_t(oN9~whXcJi!$4|4vSQ>^XVUQGBv)Tq9N-X_g zDN>45MXKzB4`N|g5h;BTKj=d!ODK^N(G6*#Y4;&Q9}2dLEKyQQLHtPZ#g8bpq7Vz4 zpx8>bwN2aDWMl81JNKrUiPU-Ze_?(zOwK)L?w!NE=bvP52_Xc2BuxDChv6rW$AcdW z3kw4S19$J<-L`F;-EL>GP2%ym&*z(*oWzjTYUSQMb8~b3{r%(P;}|M0FX!Gou~_Wt z)vJ+6WY3;G+qZA$UVv;id;k7@bh2hN8Z9X)kt7Ll$r6b~kKO(+04`n_e<0}hqjQr- zj~-bEt&pK%DJX@)As$eeo}RYZt^uSlEQ+JU!=pT)5DtZdQjh@2KxWW7h(j^|)2B~s zYimnOOVM6kT|IvMxXor885zMQO{lxA?LQ?Oc8&-FK8E%qYRqm=njDYNw7Z(>< z6sfOw0esyIi=zMI$B!(8f46yMFMUG(bXU1?KnzVyO}%~l*6DPjy|lD+>((t?0hSQ0 zp;~i?t#+!LO}%Mko}Lq9$slYByaMp^o zI0$zUa{Kn}nwlES45zcZyZi9r!)S}5NDU05%IrOM$ji(hELPc|)vAaLf|3*t6|3yp zHCrl0i*|HW933q@6$ypIQZPtknT&O?pfc=bHk+}ial#%ye}3H5)UKqWI_M58iyRaHJhPp_;|nafrG^(%cMJN?zrY5UaS+YW-vRMmP z8G_%yc*SMHe@fc9bLZIDSZizRsZ*!uV0Jvz#5F2Qt2Biq%^H=_-YOD_LSMYioYbgH zPH(BQmX;PQrhE79(S!mg1Lh$!9T(^jDjq(3IN8^?kz6NIe(~bPu3fu&dwZWfdlm=;aQV8rx{SXcdKd}mVI-u7 zk&qrne?oc~3F%=Zq=%7^9!5fX7zycNB&3ItkRFBivR8QEJ0;j;(7ZcS)|HJT zR1;2mdbt1lY`tV$Wig0dhwErKz|jF6N~$U%0ON|$0#LjgL-&Q?=1pqU)j@l^;?iSo k4*L4It;N`m`91*u1O9JFJ2Em3SpWb407*qoM6N<$f?a&%7XSbN diff --git a/apps/mmind/screenshot_mmind.png b/apps/mmind/screenshot_mmind.png new file mode 100644 index 0000000000000000000000000000000000000000..5c886e7e82c0a3a78ed1344837f32e33ecd639eb GIT binary patch literal 2577 zcmeHJ`#Td18=f`iPi93)YNl+N>Ez6E$T2ldFO$PqCE*pr*hVq0_hp+y)X2GnksJ!m zhs{2(P?Qg`G-ggEVHsW&msfwl_sjS5`@?hJ*Kc5!Ft)_Nzs zh6Qu>o%dc^tzxUmkj;{-P+aRHnceBu;ARBP66hcO3Gu@PKvSC>1c5gOhn$ub()Q%) zCGvBN&oP_=4mTUgfOxB`SS#Q(zg*EsIlg^@dGrI(ZDwemf-guO2xh_zz73Q;t45!n zajRzQE$wvOLR;5h?7LGy#qyRd5-Z8u8d;9P=&KZE4Wk#uHEqvJ9Y-1q8zRx`LZeUy z^+NjbL#?E($9ybNAWesu8!Xw{V($&eHi1M^FS=(Tj*BI7Ql)D*I2iQwc_8Ovuhz_j z|AUS;>wr>dAiDRR(Eq`UiUUu&Yq-TY)7v%h7e$tgJWc=oWT4ujgK!!j+M?cr?|RTy z?NMF{KPh>EaJZyNVTareswpoXyh~aRi}?26>o>P*`AQU4kr%AaYf6zC$3~*oG=fch z65EkS(M6obqSTQqkR~TF2zJ-Dhh5liSl2ageNz8UZd)#= z$mDK8SvO)^8_BAMo)6r|bRC_1lzwl{`b=?k{hnfbGk%U$x)$ ztRsI2l#v?sM{~+JdF{Lt+Bi$wSX;58@-qa;*?4gv^hPp zY^~2SoQWLT>@;({B&}7N&uj3M5!_zQsN=E5B2Ey6cau$3E8@174RQ0G=zWd3YkpVy z8Q+yRLgE?uBFO5qisa5X>9B}cpj@b#u;Ctb0Z)K?_O$B5$LZ=)eaq+eA`D#sJc8=V zxt^Kd)%u>hGZUCJFtI4omGwJF`?`|Im((@p5=plvbs-SstOtn@xb6{6sA|*pYc8*T zd0041D<8+zr`w3B1snb#(f#%fclM1PCZF^J1dp1~k63)uxni);x$rfDxc(U>I6LnOlcyh`Z~SRxYm`5viE)1x1B`F=~GD$S10%0+T3YaSfVA! zxg5v%+7;B!ZE>krVymgi^B(Y76PT_fA1gr3bc8TO+IxZTcb+xDKHbGM_YL#k&zoS%KL*uPFkYpn{xDdC5; z7Wr`k(mMWxJ}QyB{Ji@_0-`B8&sH_8-`Xa~{7VWs17qO*XM&oa$I0079)2RBlFhxZzLp<#1v=KhJ6N{6O9RU4|MAIZ;B zsUCQ@dQogjA6wa!wZq9SWvzP%!1TD8A|(h^sF;=47M^AHC-gKj1sF7=4I?^=un?r) zlGZWLh&k}T5%qTXs!k=!Fa!x-oQEK<8l|T3Rq9Pr^x-PB)|=OG0fFnR=$|KuL?~~Q zT}`iju{Y`y3IYq+(iO4g^8 T#S9|s{&)Zv2aJ8KT|m;`rbCOu literal 0 HcmV?d00001 From 786b13925cf1a3097706ec11a5c10565431e8fa9 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:32:36 +0100 Subject: [PATCH 053/202] Add files via upload --- apps/mmind/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/mmind/README.md diff --git a/apps/mmind/README.md b/apps/mmind/README.md new file mode 100644 index 000000000..508a158dd --- /dev/null +++ b/apps/mmind/README.md @@ -0,0 +1,34 @@ +# Mastermind + +Play the classic mind game mastermind on your Bangles 2. + +![](screenshot_mmind.png) + + +## Game +The game will start when run. +Four colors pins are randomly choosen and kept secret. +You need to find the secret by scoring your choise within 6 turns. +The game makes use of touch features. + + +## Play +Select one of the dots, the color menu will show, select a colour for the pin. +If all pins are choosen with a color the red button will turn green. +Hit the green button and your play will be scored and listed from the top. +The first digit shows the number of pins with the correct color and in the right place. +The second digit gives the number of pins with the correct color but in the wrong place. +There are six turns to get the correct secret. +The blue button will start a new game. + + +## Requests + +This is the first version, things to add: +Add menu to change game options number of colors, 5 pins per row. +Add feature to drag screen up and down to see more scores + + +## Creator + +This game is created by Peter Slendebroek. \ No newline at end of file From 1fdf05958dbd13af0e65ff30d0c044208a8c737f Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:36:51 +0100 Subject: [PATCH 054/202] Update README.md --- apps/mmind/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index 508a158dd..e09b5b966 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -13,6 +13,7 @@ The game makes use of touch features. ## Play +The screen needs to be unlocked. Select one of the dots, the color menu will show, select a colour for the pin. If all pins are choosen with a color the red button will turn green. Hit the green button and your play will be scored and listed from the top. @@ -25,10 +26,11 @@ The blue button will start a new game. ## Requests This is the first version, things to add: -Add menu to change game options number of colors, 5 pins per row. -Add feature to drag screen up and down to see more scores - +... +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. +Add feature to drag screen up and down to see more scores. +Times and high score ## Creator -This game is created by Peter Slendebroek. \ No newline at end of file +This game is created by Peter Slendebroek. From ed9b7f2e6b148f10a8a2b7f07bd4c12ea8622b02 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 22:44:04 +0100 Subject: [PATCH 055/202] Update README.md --- apps/mmind/README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index e09b5b966..0623459f7 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -25,11 +25,10 @@ The blue button will start a new game. ## Requests -This is the first version, things to add: -... -Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. -Add feature to drag screen up and down to see more scores. -Times and high score +This is the first version, things to add are:/ +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row./ +Add feature to drag screen up and down to see more scores./ +Timer and high score./ ## Creator From 8931817a2b23ec5740346ab4c571de520153a189 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 23:00:36 +0100 Subject: [PATCH 056/202] Add files via upload --- apps/mmind/mmind.info | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 apps/mmind/mmind.info diff --git a/apps/mmind/mmind.info b/apps/mmind/mmind.info new file mode 100644 index 000000000..a6dccde65 --- /dev/null +++ b/apps/mmind/mmind.info @@ -0,0 +1,5 @@ +require("Storage").write("mmind.info",{ + "id":"mmind", + "name":"Master Mindr", + "src":"mmind.app.js" +}); \ No newline at end of file From cd71d7937d636d2b3ba77b62b6edec5ecda3f0d7 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Tue, 4 Jan 2022 23:02:47 +0100 Subject: [PATCH 057/202] Update mmind.info --- apps/mmind/mmind.info | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/apps/mmind/mmind.info b/apps/mmind/mmind.info index a6dccde65..2e79822b1 100644 --- a/apps/mmind/mmind.info +++ b/apps/mmind/mmind.info @@ -1,5 +1,17 @@ -require("Storage").write("mmind.info",{ - "id":"mmind", - "name":"Master Mindr", - "src":"mmind.app.js" -}); \ No newline at end of file + { + "id": "mmind", + "name": "Classic Mind Game", + "shortName":"Master Mind", + "icon": "mmind.png", + "version":"0.01", + "description": "This is the classic game for masterminds", + "type": "game", + "tags": "mastermind, game, classic", + "readme":"README.md", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"mmind.app.js","url":"mmind.app.js"}, + {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} + ] + } From 6bdbd310bcc354b8b18da040138bc9122817ca66 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 4 Jan 2022 16:41:05 -0800 Subject: [PATCH 058/202] fix light mode not selected color from -10 to -20 --- apps/promenu/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/boot.js b/apps/promenu/boot.js index 002734113..bd813a812 100644 --- a/apps/promenu/boot.js +++ b/apps/promenu/boot.js @@ -70,7 +70,7 @@ E.showMenu = function(items) { if(g.theme.dark){ fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+20); }else{ - fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-10); + fillRectRnd(x+2,iy+1,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); } g.setColor(hl ? g.theme.fgH : g.theme.fg); g.setFontAlign(-1,-1); From 71504a7414dc35d136ae1cd45b991289fab1ec9a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 12:16:14 +0100 Subject: [PATCH 059/202] Setting to toggle visibility of widgets Setting to set minimal heart rate --- apps/circlesclock/app.js | 45 +++++++++++++++++++++-------------- apps/circlesclock/settings.js | 18 ++++++++++++++ 2 files changed, 45 insertions(+), 18 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 026b47cc6..f123e0c2a 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -8,12 +8,13 @@ const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmA const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); let settings; - function loadSettings() { settings = require("Storage").readJSON("circlesclock.json", 1) || { + 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, - 'batteryWarn': 30 + 'batteryWarn': 30, + 'showWidgets': false }; // Load step goal from pedometer widget as fallback if (settings.stepGoal == undefined) { @@ -21,18 +22,21 @@ function loadSettings() { settings.stepGoal = d != undefined && d.settings != undefined ? d.settings.goal : 10000; } } +loadSettings(); +const showWidgets = settings.showWidgets || false; +let hrtValue; + +// layout values: const colorFg = g.theme.dark ? '#fff' : '#000'; const colorBg = g.theme.dark ? '#000' : '#fff'; const colorGrey = '#808080'; const colorRed = '#ff0000'; const colorGreen = '#00ff00'; - -let hrtValue; - -const h = g.getHeight(); +const widgetOffset = showWidgets ? 12 : 0; +const h = g.getHeight() - widgetOffset; const w = g.getWidth(); -const hOffset = 30; +const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); const h3 = Math.round(8 * h / 8 - hOffset); @@ -102,7 +106,7 @@ function drawHeartRate() { g.fillCircle(w2, h3, radiusOuter); if (hrtValue != undefined && hrtValue > 0) { - const minHR = 40; + const minHR = settings.minHR || 40; const percent = (hrtValue - minHR) / (settings.maxHR - minHR); drawGauge(w2, h3, percent, colorRed); } @@ -233,19 +237,24 @@ Bangle.on('charging', function(charging) { }); g.clear(); + + Bangle.loadWidgets(); -/* - * we are not drawing the widgets as we are taking over the whole screen - * so we will blank out the draw() functions of each widget and change the - * area to the top bar doesn't get cleared. - */ -if (typeof WIDGETS === "object") { - for (let wd of WIDGETS) { - wd.draw = () => {}; - wd.area = ""; +if (!showWidgets) { + /* + * we are not drawing the widgets as we are taking over the whole screen + * so we will blank out the draw() functions of each widget and change the + * area to the top bar doesn't get cleared. + */ + if (WIDGETS && typeof WIDGETS === "object") { + for (let wd of WIDGETS) { + wd.draw = () => {}; + wd.area = ""; + } } } -loadSettings(); + + setInterval(draw, 60000); draw(); Bangle.setUI("clock"); diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index ffda51538..15596ff18 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -8,6 +8,16 @@ } E.showMenu({ '': { 'title': 'circlesclock' }, + 'min heartrate': { + value: "minHR" in settings ? settings.minHR : 40, + min: 0, + max : 250, + step: 10, + format: x => { + return x; + }, + onchange: x => save('minHR', x), + }, 'max heartrate': { value: "maxHR" in settings ? settings.maxHR : 200, min: 20, @@ -38,6 +48,14 @@ }, onchange: x => save('batteryWarn', x), }, + 'show widgets': { + value: "showWidgets" in settings ? settings.showWidgets : false, + format: () => (settings.showWidgets ? 'Yes' : 'No'), + onchange: () => { + settings.showWidgets = !settings.showWidgets; + save('showWidgets', settings.showWidgets); + }, + }, '< Back': back, }); }); From c41bae14c9e6c5a0dc8d33163415a03787baa632 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 12:16:38 +0100 Subject: [PATCH 060/202] Update README --- apps/circlesclock/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 66d9afe08..df47c369b 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -8,13 +8,11 @@ It shows besides time, date and day of week the following information: * Battery (including charging and battery low) ## Screenshot - ![Screenshot](screenshot.png) ## TODO * Show weather information * Configure which information to show in each circle -* Configure visibility of widgets ## Creator Marco ([myxor](https://github.com/myxor)) From fea7c2dcf817fbb9e6fe402fae1d79bf8089cab2 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 5 Jan 2022 13:49:02 +0200 Subject: [PATCH 061/202] typo fix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 😖 --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 04cc12a37..b0ebce263 100644 --- a/apps.json +++ b/apps.json @@ -5139,6 +5139,7 @@ {"name":"fourTwenty","url":"fourTwenty.js"}, {"name":"fourTwentyTz","url":"fourTwentyTz.js"}, {"name":"ftclock.img","url":"app-icon.js","evaluate":true} + ] }, { "id": "slash", From 766d3cc1892874b5a8be3f611c3e4335da236c80 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 13:27:50 +0100 Subject: [PATCH 062/202] Make the types of the circles configurable --- apps/circlesclock/app.js | 163 ++++++++++++++++++++++++---------- apps/circlesclock/settings.js | 29 ++++++ 2 files changed, 144 insertions(+), 48 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index f123e0c2a..58055e96e 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -14,7 +14,10 @@ function loadSettings() { 'maxHR': 200, 'stepGoal': 10000, 'batteryWarn': 30, - 'showWidgets': false + 'showWidgets': false, + 'circle1': 'hr', + 'circle2': 'steps', + 'circle3': 'battery' }; // Load step goal from pedometer widget as fallback if (settings.stepGoal == undefined) { @@ -32,7 +35,9 @@ const colorFg = g.theme.dark ? '#fff' : '#000'; const colorBg = g.theme.dark ? '#000' : '#fff'; const colorGrey = '#808080'; const colorRed = '#ff0000'; -const colorGreen = '#00ff00'; +const colorGreen = '#008000'; +const colorBlue = '#0000ff'; +const colorYellow = '#ffff00'; const widgetOffset = showWidgets ? 12 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); @@ -63,82 +68,137 @@ function draw() { g.drawString(locale.date(new Date()), w / 10, h2); g.drawString(locale.dow(new Date()), w / 10, h2 + 22); - // Steps circle - drawSteps(); - - // Heart circle - drawHeartRate(); - - // Battery circle - drawBattery(); + drawCircle(1, "steps"); + drawCircle(2, "hr"); + drawCircle(3, "battery"); } +function drawCircle(index, defaultType) { + const type = settings['circle' + index] || defaultType; + const w = index == 1 ? w1: index == 2 ? w2 : w3; -function drawSteps() { + switch (type) { + case "steps": + drawSteps(w); + break; + case "stepsDist": + drawStepsDistance(w); + break; + case "hr": + drawHeartRate(w); + break; + case "battery": + drawBattery(w); + break; + } +} +function getCirclePosition(type, defaultPos) { + for (let i = 1; i <= 3; i++) { + const setting = settings['circle' + i]; + if (setting == type) return i; + } + return defaultPos; +} + +function isCircleEnabled(type) { + return getCirclePosition(type) != undefined; +} + +function drawSteps(w) { + if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); - const blue = '#0000ff'; g.setColor(colorGrey); - g.fillCircle(w1, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); const stepGoal = settings.stepGoal || 10000; if (stepGoal > 0) { let percent = steps / stepGoal; if (stepGoal < steps) percent = 1; - drawGauge(w1, h3, percent, blue); + drawGauge(w, h3, percent, colorBlue); } g.setColor(colorBg); - g.fillCircle(w1, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w1, h3, w1 - 15, h3 + radiusOuter + 5, w1 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(shortValue(steps), w1 + 2, h3); + g.drawString(shortValue(steps), w + 2, h3); - g.drawImage(shoesIcon, w1 - 6, h3 + radiusOuter - 6); + g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); } -function drawHeartRate() { +function drawStepsDistance(w) { + if (!w) w = getCirclePosition("steps", w1); + const steps = getSteps(); + const stepDistance = 0.8; // TODO make configurable + const stepsDistance = steps * stepDistance; + g.setColor(colorGrey); - g.fillCircle(w2, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); + + const stepDistanceGoal = settings.stepDistanceGoal || 5; + if (stepDistanceGoal > 0) { + let percent = stepsDistance / stepDistanceGoal; + if (stepDistanceGoal < stepsDistance) percent = 1; + drawGauge(w, h3, percent, colorGreen); + } + + g.setColor(colorBg); + g.fillCircle(w, h3, radiusInner); + + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + + g.setFont("Vector:12"); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(shortValue(stepsDistance), w + 2, h3); + + g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); +} + +function drawHeartRate(w) { + if (!w) w = getCirclePosition("hr", w2); + g.setColor(colorGrey); + g.fillCircle(w, h3, radiusOuter); if (hrtValue != undefined && hrtValue > 0) { const minHR = settings.minHR || 40; const percent = (hrtValue - minHR) / (settings.maxHR - minHR); - drawGauge(w2, h3, percent, colorRed); + drawGauge(w, h3, percent, colorRed); } g.setColor(colorBg); - g.fillCircle(w2, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w2, h3, w2 - 15, h3 + radiusOuter + 5, w2 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(hrtValue != undefined ? hrtValue : "-", w2, h3); + g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); - g.drawImage(heartIcon, w2 - 6, h3 + radiusOuter - 6); + g.drawImage(heartIcon, w - 6, h3 + radiusOuter - 6); } -function drawBattery() { +function drawBattery(w) { + if (!w) w = getCirclePosition("battery", w3); const battery = E.getBattery(); - const yellow = '#ffff00'; g.setColor(colorGrey); - g.fillCircle(w3, h3, radiusOuter); + g.fillCircle(w, h3, radiusOuter); if (battery > 0) { const percent = battery / 100; - drawGauge(w3, h3, percent, yellow); + drawGauge(w, h3, percent, colorYellow); } g.setColor(colorBg); - g.fillCircle(w3, h3, radiusInner); + g.fillCircle(w, h3, radiusInner); - g.fillPoly([w3, h3, w3 - 15, h3 + radiusOuter + 5, w3 + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); g.setFont("Vector:12"); g.setFontAlign(0, 0); @@ -156,9 +216,9 @@ function drawBattery() { } } g.setColor(color); - g.drawString(battery + '%', w3, h3); + g.drawString(battery + '%', w, h3); - g.drawImage(icon, w3 - 6, h3 + radiusOuter - 6); + g.drawImage(icon, w - 6, h3 + radiusOuter - 6); } function radians(a) { @@ -210,30 +270,37 @@ function getSteps() { Bangle.on('lock', function(isLocked) { if (!isLocked) { - Bangle.setHRMPower(1, "watch"); - if (hrtValue == undefined) { - hrtValue = '...'; - drawHeartRate(); + if (isCircleEnabled("hr")) { + Bangle.setHRMPower(1, "watch"); + if (hrtValue == undefined) { + hrtValue = '...'; + drawHeartRate(); + } } } else { - Bangle.setHRMPower(0, "watch"); + if (isCircleEnabled("hr")) { + Bangle.setHRMPower(0, "watch"); + } } - drawHeartRate(); - drawSteps(); + if (isCircleEnabled("hr")) drawHeartRate(); + if (isCircleEnabled("steps")) drawSteps(); + if (isCircleEnabled("stepsDistance")) drawStepsDistance(); }); Bangle.on('HRM', function(hrm) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} + if (isCircleEnabled("hr")) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} + } }); Bangle.on('charging', function(charging) { - drawBattery(); + if (isCircleEnabled("battery")) drawBattery(); }); g.clear(); diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 15596ff18..754fa0c69 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -6,6 +6,8 @@ settings[key] = value; storage.write(SETTINGS_FILE, settings); } + var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; + var namesCircleTypes = ["steps", "step distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, 'min heartrate': { @@ -56,6 +58,33 @@ save('showWidgets', settings.showWidgets); }, }, + 'Left circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle1 = valuesCircleTypes[v]; + save('circle1', settings.circle1); + } + }, + 'Middle circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle2)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle2 = valuesCircleTypes[v]; + save('circle2', settings.circle2); + } + }, + 'Right circle': { + value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle3)), + min: 0, max: 3, + format: v => namesCircleTypes[v], + onchange: v => { + settings.circle3 = valuesCircleTypes[v]; + save('circle3', settings.circle3); + } + }, '< Back': back, }); }); From ee252a3a97fc3880c7744ed79966e6f25bb6e8da Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:04:04 +0100 Subject: [PATCH 063/202] Fix position, default settings and add green step distance icon --- apps/circlesclock/app.js | 5 +++-- apps/circlesclock/settings.js | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 58055e96e..686de735b 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -2,6 +2,7 @@ const locale = require("locale"); const heatshrink = require("heatshrink"); const shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA=")); +const shoesIconGreen = heatshrink.decompress(atob("h0OwYJGhIEDgVIAgUEyQKDkmACgcggVACIeQAYMSgIRCgmApIbDiQUDAAkBkAFDGoYAD")); const heartIcon = heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM")); const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbBIUN23AAoYOCgEDFIgODABI")); const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); @@ -96,7 +97,7 @@ function drawCircle(index, defaultType) { function getCirclePosition(type, defaultPos) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i; + if (setting == type) return i == 1 ? w1: i == 2 ? w2 : w3; } return defaultPos; } @@ -157,7 +158,7 @@ function drawStepsDistance(w) { g.setColor(colorFg); g.drawString(shortValue(stepsDistance), w + 2, h3); - g.drawImage(shoesIcon, w - 6, h3 + radiusOuter - 6); + g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } function drawHeartRate(w) { diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 754fa0c69..3ddacd29c 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -7,7 +7,7 @@ storage.write(SETTINGS_FILE, settings); } var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; - var namesCircleTypes = ["steps", "step distance", "heart", "battery"]; + var namesCircleTypes = ["steps", "distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, 'min heartrate': { @@ -40,7 +40,7 @@ }, onchange: x => save('stepGoal', x), }, - 'battery warn lvl': { + 'battery warn': { value: "batteryWarn" in settings ? settings.batteryWarn : 30, min: 10, max : 100, @@ -58,7 +58,7 @@ save('showWidgets', settings.showWidgets); }, }, - 'Left circle': { + 'left': { value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], @@ -67,8 +67,8 @@ save('circle1', settings.circle1); } }, - 'Middle circle': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle2)), + 'middle': { + value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], onchange: v => { @@ -76,8 +76,8 @@ save('circle2', settings.circle2); } }, - 'Right circle': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle3)), + 'right': { + value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], onchange: v => { From 3538c6024fe36715a82d0d2018862cab2992f944 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:14:47 +0100 Subject: [PATCH 064/202] Configuration of stepDistanceGoal and stepLength --- apps/circlesclock/app.js | 6 ++++-- apps/circlesclock/settings.js | 40 +++++++++++++++++++++-------------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 686de735b..3099b02ea 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -14,6 +14,8 @@ function loadSettings() { 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, + 'stepDistanceGoal': 8000, + 'stepLength': 0.8, 'batteryWarn': 30, 'showWidgets': false, 'circle1': 'hr', @@ -135,13 +137,13 @@ function drawSteps(w) { function drawStepsDistance(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); - const stepDistance = 0.8; // TODO make configurable + const stepDistance = settings.stepLength || 0.8; const stepsDistance = steps * stepDistance; g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); - const stepDistanceGoal = settings.stepDistanceGoal || 5; + const stepDistanceGoal = settings.stepDistanceGoal || 8000; if (stepDistanceGoal > 0) { let percent = stepsDistance / stepDistanceGoal; if (stepDistanceGoal < stepsDistance) percent = 1; diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 3ddacd29c..dc75f54af 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -40,6 +40,26 @@ }, onchange: x => save('stepGoal', x), }, + 'step length': { + value: "stepLength" in settings ? settings.stepLength : 0.8, + min: 0.1, + max : 1.5, + step: 0.01, + format: x => { + return x; + }, + onchange: x => save('stepLength', x), + }, + 'step dist goal': { + value: "stepDistanceGoal" in settings ? settings.stepDistanceGoal : 8000, + min: 2000, + max : 30000, + step: 1000, + format: x => { + return x; + }, + onchange: x => save('stepDistanceGoal', x), + }, 'battery warn': { value: "batteryWarn" in settings ? settings.batteryWarn : 30, min: 10, @@ -53,37 +73,25 @@ 'show widgets': { value: "showWidgets" in settings ? settings.showWidgets : false, format: () => (settings.showWidgets ? 'Yes' : 'No'), - onchange: () => { - settings.showWidgets = !settings.showWidgets; - save('showWidgets', settings.showWidgets); - }, + onchange: x => save('showWidgets', x), }, 'left': { value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle1 = valuesCircleTypes[v]; - save('circle1', settings.circle1); - } + onchange: x => save('circle1', x), }, 'middle': { value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle2 = valuesCircleTypes[v]; - save('circle2', settings.circle2); - } + onchange: x => save('circle2', x), }, 'right': { value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: v => { - settings.circle3 = valuesCircleTypes[v]; - save('circle3', settings.circle3); - } + onchange: x => save('circle3', x), }, '< Back': back, }); From f174cb56fbd586f7e6a357a73129f9d5d6ab244d Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:14:56 +0100 Subject: [PATCH 065/202] Update README --- apps/circlesclock/README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index df47c369b..86c388440 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -2,17 +2,19 @@ A clock with circles for different data at the bottom in a probably familiar style -It shows besides time, date and day of week the following information: +By default the time, date and day of week is shown. + +It can show the following information (this can be configured): * Steps (requires [pedometer widget](https://banglejs.com/apps/#pedometer)) - * Heart rate (when screen is on and unlocked) - * Battery (including charging and battery low) + * Steps distance (depending on steps) + * Heart rate (automatically updates when screen is on and unlocked) + * Battery (including charging status and battery low warning) ## Screenshot ![Screenshot](screenshot.png) ## TODO * Show weather information -* Configure which information to show in each circle ## Creator Marco ([myxor](https://github.com/myxor)) From ad371e9678cb380ea064ed01cbe6b7df385b4d56 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:21:01 +0100 Subject: [PATCH 066/202] Update changelog and bump version --- apps.json | 2 +- apps/circlesclock/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index f116049dc..c6600ada0 100644 --- a/apps.json +++ b/apps.json @@ -5071,7 +5071,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.03", + "version":"0.04", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index c0aa4e2f8..f416929ac 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: New clock 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes +0.04: Make configurable what to show in each circle; add step distance circle; allow switching visibility of widgets From 3ba696ed0e29c6916726412d35895c48d74d8560 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 14:30:02 +0100 Subject: [PATCH 067/202] Fix settings --- apps/circlesclock/settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index dc75f54af..0c42319f5 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -79,19 +79,19 @@ value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle1', x), + onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle2', x), + onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), min: 0, max: 3, format: v => namesCircleTypes[v], - onchange: x => save('circle3', x), + onchange: x => save('circle3', valuesCircleTypes[x]), }, '< Back': back, }); From 639bc1962eee45c31b4cf0d50f5edf782ac94e1c Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 15:28:18 +0100 Subject: [PATCH 068/202] Allow widgets to detect this is a clock --- apps/circlesclock/app.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 3099b02ea..2d6c132bb 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -308,7 +308,7 @@ Bangle.on('charging', function(charging) { g.clear(); - +Bangle.setUI("clock"); Bangle.loadWidgets(); if (!showWidgets) { /* @@ -324,7 +324,5 @@ if (!showWidgets) { } } - -setInterval(draw, 60000); draw(); -Bangle.setUI("clock"); +setInterval(draw, 60000); From 801237b2cfad1caf17a0d4bb496527bd4a217e8a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 15:35:01 +0100 Subject: [PATCH 069/202] Let's only register HRM and battery events when respective circle is visible --- apps/circlesclock/app.js | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 2d6c132bb..e10d55f17 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -280,31 +280,32 @@ Bangle.on('lock', function(isLocked) { drawHeartRate(); } } + if (isCircleEnabled("steps")) drawSteps(); + if (isCircleEnabled("stepsDistance")) drawStepsDistance(); } else { if (isCircleEnabled("hr")) { Bangle.setHRMPower(0, "watch"); } } - if (isCircleEnabled("hr")) drawHeartRate(); - if (isCircleEnabled("steps")) drawSteps(); - if (isCircleEnabled("stepsDistance")) drawStepsDistance(); }); -Bangle.on('HRM', function(hrm) { - if (isCircleEnabled("hr")) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} - } -}); +if (isCircleEnabled("hr")) { + Bangle.on('HRM', function(hrm) { + //if(hrm.confidence > 90){ + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} + }); +} -Bangle.on('charging', function(charging) { - if (isCircleEnabled("battery")) drawBattery(); -}); +if (isCircleEnabled("battery")) { + Bangle.on('charging', function(charging) { + drawBattery(); + }); +} g.clear(); From 0b34ffefd58ee58f5d0437b5c4ff568a95eb778d Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 22 Dec 2021 21:18:55 +0100 Subject: [PATCH 070/202] Anton clock: Update with optional seconds and ISO-8601 date --- apps.json | 8 +- apps/antonclk/ChangeLog | 1 + apps/antonclk/app.js | 176 +++++++++++++++++++++++++++-------- apps/antonclk/app.png | Bin 759 -> 1989 bytes apps/antonclk/screenshot.png | Bin 696 -> 1617 bytes apps/antonclk/settings.js | 87 +++++++++++++++++ 6 files changed, 232 insertions(+), 40 deletions(-) create mode 100644 apps/antonclk/settings.js diff --git a/apps.json b/apps.json index 5cc311413..b0d74926b 100644 --- a/apps.json +++ b/apps.json @@ -4238,8 +4238,8 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.03", - "description": "A simple clock using the bold Anton font.", + "version": "0.04", + "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", @@ -4248,8 +4248,10 @@ "allow_emulator": true, "storage": [ {"name":"antonclk.app.js","url":"app.js"}, + {"name":"antonclk.settings.js","url":"settings.js"}, {"name":"antonclk.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name":"antonclk.json"}] }, { "id": "waveclk", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index f88276a90..668047d7a 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Load widgets after setUI so widclk knows when to hide 0.03: Clock now shows day of week under date. +0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 7912dfc0f..3b9c14c46 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,10 +1,51 @@ +// Clock with large digits using the "Anton" bold font + +var SETTINGSFILE="antonclk.json"; + Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78+(scale<<8)+(1<<16)); +}; + +// variables defined from settings +var secondsOnUnlock; +var secondsAlways; +var dateAsISO; +var longDate; +var weekDay; +var upperCase; + +// dynamic variables +var drawTimeout; +var queueMillis=1000; +var withSeconds=true; + +var isBangle1=(g.getWidth()==240); + +/* For development purposes +require('Storage').writeJSON(SETTINGSFILE, { + secondsOnUnlock: false, + secondsAlways: false, + dateAsISO: false, + longDate: true, + weekDay: true, + upperCase: true +}); +*/ + +function def(value,def) { + return (value!==undefined?value:def); } -// timeout used to update every minute -var drawTimeout; +function loadSettings() { + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; + secondsOnUnlock = def(settings.secondsOnUnlock,true); + secondsAlways = def(settings.secondsAlways,false); + dateAsISO = def(settings.dateAsISO,true); + longDate = def(settings.longDate,true); + weekDay = def(settings.weekDay,true); + upperCase = def(settings.upperCase,false); +} // schedule a draw for the next minute function queueDraw() { @@ -12,50 +53,111 @@ function queueDraw() { drawTimeout = setTimeout(function() { drawTimeout = undefined; draw(); - }, 60000 - (Date.now() % 60000)); + }, queueMillis - (Date.now() % queueMillis)); } - -function draw() { - var x = g.getWidth()/2; - var y = g.getHeight()/2; - g.reset(); - var date = new Date(); - var timeStr = require("locale").time(date,1); - var dateStr = require("locale").date(date).toUpperCase(); - var dowStr = require("locale").dow(date).toUpperCase(); - // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.clearRect(0,y-40,g.getWidth(),y+35); // clear the background - g.drawString(timeStr,x,y); - // draw date - y += 40; - g.setFontAlign(0,0).setFont("6x8",2); - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dateStr,x,y); - //draw day of week - y += 16; - g.clearRect(0,y-8,g.getWidth(),y+8); // clear the background - g.drawString(dowStr,x,y); - // queue draw in one minute - queueDraw(); -} - -// Clear the screen once, at startup -g.clear(); -// draw immediately at first, queue update -draw(); -// Stop updates when LCD is off, restart when on -Bangle.on('lcdPower',on=>{ - if (on) { +function updateState() { + if (Bangle.isLCDOn()) { + if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + withSeconds=true; + queueMillis=1000; + } else { + withSeconds=false; + queueMillis=60000; + } draw(); // draw immediately, queue redraw } else { // stop draw timer if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; } -}); +} + +function isoStr(date) { + return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); +} + +function doColor() { + return !isBangle1 && !Bangle.isLocked(); +} + +function draw() { + var x = g.getWidth()/2; + var y = g.getHeight()/2; + if (secondsOnUnlock || secondsAlways) + y-= 25; + g.reset(); + g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + var date = new Date(); + var timeStr = require("locale").time(date,1); + // draw time + g.setFontAlign(0,0).setFont("Anton"); + g.drawString(timeStr,x,y); + if (withSeconds) { + y+=77; + var secStr = ":"+("0" + date.getSeconds()).substr(-2); + g.setFontAlign(1,0).setFont("Anton"); + if (doColor()) + g.setColor(0,0,1); + g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); + y-=77; + y+=60; + x=g.getWidth()/4+(isBangle1?12:-4); + var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year=dateStr2.slice(-4); + md=dateStr2.slice(0,-4); + if (!md.endsWith(".")) + md=md.slice(0,-1); + yearfirst=false; + } + else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2=isoStr(date); + year=dateStr2.slice(0,4); + md=dateStr2.slice(5); + yearfirst=true; + } + g.setFontAlign(0,0).setFont("Vector",24); + if (doColor()) + g.setColor(1,0,0); + g.drawString(md,x,(yearfirst?y+28:y)); + g.drawString(year,x,(yearfirst?y:y+28)); + } + else { + y+=52; + var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + if (upperCase) + dateStr=dateStr.toUpperCase(); + g.setFontAlign(0,0).setFont("Vector",24); + g.drawString(dateStr,x,y); + if (weekDay) { + var dowStr = require("locale").dow(date); + if (upperCase) + dowStr=dowStr.toUpperCase(); + g.drawString(dowStr,x,y+28); + } + } + + // queue next draw + queueDraw(); +} + +// Init the settings of the app +loadSettings(); +// Clear the screen once, at startup +g.clear(); +// Set dynamic state and perform initial drawing +updateState(); +// Register hooks for LCD on/off event and screen lock on/off event +Bangle.on('lcdPower',on=>{ updateState(); }); +Bangle.on('lock',on=>{ updateState(); }); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); + +// end of file diff --git a/apps/antonclk/app.png b/apps/antonclk/app.png index d96f1775886e280f46652131b7e8c747fd28bf39..a38093c5f3b6f88dbc9b75017422dbe237d4407f 100644 GIT binary patch delta 1986 zcmV;z2R-=r1;r1L8Gix*007uvZqNV#2aHKXK~z}7?O0t*Q&$}S(aJ|1h>ls;g4h+@ zB+AGl)8UNHxGbA|xTyGG;sOsoEFnM;B+-{a7Q@E_V_6nMW&&<;@}SXB3>rlzVu;X< zRWXwk`@zScE!aY#?d`|e!>RXPZf_BAEI#a?lbioJ=XcKe-G6(||Kr>ULI_?bk>E9x z{|Wt1=v8G^xDKDsH!(3`G#X=LV-*U8TrOXDqLGmilgUK&#Kc6EN+kdc4-cEoX0}QQ z*}i?dOePafM8w2kFdRO7m=7x{DH$0V5e0j_-m_=V3Z|{9s&YD=eAwyJrv(^`#S%K3 z2qBxzmYSLx`hN`y3JT`t=0fr3&YhD;M7F-UxtYZ<46||L#$^(^di83!ed+D(C4@{& zOjs-yi^VcGH|KCTl9H16n23l7R(HGIbWWX4$8TSNkjR^LcXzY8Ua#-%?PaT@qoV@@ z0~H&dOV(ykrCQkT3X65OnG@Zi=UX7pnuAvM~@a65=02q*VnUpQc}{o zb?ew_S63H*UcpOeWMo7}M)E(H!{MOHjT<+pQd3j2Oe+(oFOl#G1p(}#J#>U2O z-@eU%9{^UX^}>Y<0168WUuvx{Ar!jtTeog?yWPRTtL6=FZEYMVBWjNgS_V&)sPS%G}B_$%Z5oY6qtTenW{1Nu^g`m} z<4>G8QB+jKf{jMwlP6E8URztc{8*NimDSVJLv{8QshCWryu3WB-@kuHJ4%z_z)>FVmDx>~KaTCMyOIXO8QA0HnT74;HACXwg7ckH-_vDjOOaLMP{&$oTm9qN2UoY*s3j zp$k-3SBvIDeSLkQ;GCQstJS(Np~a>jgpg;?o|ToA30{|B7!pRFK7CqOSGQ-+9vU&4 zo0~=15JIkBzg|&MQBhHG^5n^>si{yvL^#7CggBi}n!+lT%5dRAkoEfg{-~&^mwyJV zg`(%{c5_{|Li5heVRRH03*>SnCSvt!A;4yX)rzSpC=^gC5figulK+bG%P%A?jR3)- zRuhee>z$q^RaIOsK(=io_wFrts9#0e+U70BmOFQXfFFJk2WYhdLRKr$>4@J?2q6v! z`Qs1b^%6qJ>@4Z+CDg1@L7z6pDG^{(i2SkbpPdKwMlnD;pTVci*9=hFgSs zgt0MHSEIZfVy=i!h!F4{kf=Wi^-z~Cfu=;}wcszLg7?YD27=M7%NyqKl1-Cm`wryLQYX}5_n<$Y$t;Rd=@Cijlp`igT z7pA8X8;jgrI2<^029c4dtqtxYA+Xy~SqZxxem@;2l_EMiSR_mQl~P#=wHoig549R) zWtf>+0YAjI`L;Gf2&t&xTJ(C-(h}Cne*HDfRr)^@l?oqxz*T?xiGSU)*;zC{H zE;Kda=byp9j!jSF`|t7mIj3K~jM-Uw_S)K@(Lke_XY-4Z^XGBv7Lt>LRjn4!pHo7A z{t3Gs9uLjDk)4gKEL^_K4gLLhIGynM0N~CYeEB6*D%`pSU~mw5dC1L0ZZ0gAr4fpb z#+z^A-FJgkyB$6sHGlhEyD&AyUdQ2bp|us6nb7Oe-Hnew#wVYEy>UvVFc>g11H1h{ ziS|=dXl%rhBS=q&%Y_36AV}0d{S^-&q4nIc68v%6&MW2&W1#Sn>XQf;(x2J0BqTUEnC3*|HA1l zEy&D-(a5<(Lh$z69KdWwOblM!|B#xBHEXEZd%eW%CT=(JdO4k+urdq>AVk>96Q`5N z<>FSIpHBh-Vlss_`<9lKNk2L}#ngwjPIXiTSuzz@0DyR1QVY3BO*tgz-R4N2842(v2JWwjJb}a{Z?UMX|0QIbl USs20!PXGV_07*qoM6N<$g0gzc;Q#;t delta 746 zcmV#Upe&?7suvS{7$`q%$XUdCYatL*UM&qYkz00_3gdZkp%IXiY3DTK~M*l*UhrGbOTH@s=dXV zf09G{s><3KAL0N6xR{=cL_nHCF0Qe5xz8(%f`4q@m5r`n_Xa#UzVHyArFz-Gc zKm+!|0~`-toKmZ@`fYBHXFhRJxmIAUji{nSriljb1AkP<@icA%+OjwZJs^29h?!Ef z-TemQ2C)dzr(Mf2wV1+4Ie;xTq4hl^_`-nK0TfEH`ypDS7J#jPXdpM>j2NN40NJq# z{&FFNH{#+t0W5K}=m5aZI0(+a83M-^4*{K7!lef}MT5(z_;g8nFi@MU!y9& z0D~Ga2Y=`lS%av@1!#4Vgg00wzKaaIJ2L@bNR#tpBy|nIlrv8rGG@(^FsdRJ-QP{XzCF~qci@anb7w@o;375x%BD_RYP}fDMfEo&3+L6^SSGaoh~4+ z$TC{G#j66=9oYBrc}77;VUgTDWelk_cCxHK`(vE&O}8IO0(v{XR&*Uo8wB1qJ*#jG z=4;wIwv|`|g31@bP&0h$WpisvZdEEkr`;hEFPcka7#vXBt?hE5xty{J^%m!07*qoM6N<$f`mLmfdBvi diff --git a/apps/antonclk/screenshot.png b/apps/antonclk/screenshot.png index c66f8bdd85c6c2acef19f20ff86dab7b1d9c6a3f..e949b8a24a4eac5cbd8f8a01ffdd57b3660b939c 100644 GIT binary patch delta 1612 zcmV-S2DACN1AlTS_;6Lfh=O!<|dqR0_rLj7-Gw6Z=mpp~2Trq^-sN$JXdw$RVuL zh2YN@K!k`6Pvr(ctjI(h8vf-F??mA#V@N4cYlvqI5okD%_;DP$JZ&Vq6!#OKe-2k= zTnY^!SWV;*Zhz&*?VkZ+T^e4FIMl4veaLv{kHiaY8ZJ4eOESUYRxBF6&rgK#5Xh#u zh^d_lGqUH{I#wmxlgh#wCnl!sX>jup40b>oT>LaiC5grV6yh5Y9s#T=rCdP_t1Cx7#uck6xw7CA)cmrN5Z z87(9agn^YANE_|bKkF>#Mh8M)8{$o5Cc8FRku2BfXl|D&q@GEB?SUN zAVavl{C^WbAb>!j%1%GIf&mFAH!(qn65YGTfB^eSxzyv^$ znVJGY8u8OfjN&<1-1>p|YKvQ0+=BCwv6TPI8h=j}(Y+yF1hHNYWjJb$33G_!II4DC zYVYQgVzm5w4K066RQR$ zvwt8Zm9^v%t&H@Hld&C=2LdZkV~V_>mBE*gfqO6qLeCZ&EsxUX*dAgmD-(t+LdIBD z7TmHy4l#+9`?qdRmZG|C)Cpzfh8v!>R7ug!2o7TC+uL5DUQL!?a#=z*HhC~Vr)qVlOVN{y2 zklNJprC*XtHyUc&5!~YRr73`LqoJxb@eOZJ4FZHG4SH=h_X`lCj+~MJ0@MHk_kf20 zxI*nMw_H*_2e}ycP|(HMkbBF0z5e<%9(or`Sg5dpWvA=*b`#zXp8drkAN2RV*MCku z^?-Q(Z1XqWwZ5h7#X}uLbRL-FFuL~(NzMJ{(r4=OEpLZP?_ykel#uZ>096FuUR>L< z9||t3+g@&Qkg^lU5FH4;+Rvk^M14T$`Lb1ilwhc`^UHwg1x(z7M3`-OzIJGsn+dg$ z0S$xGhm%5v`^6g?a>x^Jt{i4z;qd9(eZbJ6z7d?iIaz8J!^HVTx zo9(q;$U}H#Q@rsIJ!F{GjVOA^kfNdF-(`s*Uc>^z>^110uXiK=kikpwc!)Y0WD%jD z2nvLwW4P@LN&@8&;lso_aeu7&T&yhCt);PFdrdySbO84-x`!%T%P5Hpwfi}H`fc7s zO1ffKWuQBZ&3>p&s?%ZLn2L9trF-BI>6BmP3pBu=Lt)VGrBgx%c0I{@_ z`211;5uG+;5CLLcC&7UsL7Dj3re&u9;mm}_0Zcuu0fZ+LF6V67o<%|j6U86bJI}4B z1!gJ* literal 696 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(e8Ax8b$#WJ+v7|ftIx;Y9?C1WI$O_~uBzpw; zGB8xBF)%c=FfjZA3N^f7U???UV0e|lz+g3lfkC`r&aOZkpaf5VPl)UP|Nj{nfCxnV zoVS%9$Y4zJc6VXuV3qX%a@b2eeO=j~a*A_n%Kez1upTJA($mE;B;xSfYk_%(6?oVZ znx=@`mzU45aNRCkV(xU;^}@Uf{u^iKUb%22k=ZHgn#betkjQJ(wHVdc3iO{Um?DvM z`p1?79g#H?tfriI+96!Z*U!BsRg8cA`*^+i+8-jC+ouPvJND@90YimZJatyS5s?c& zt+tgDzj5GhL5XDLnY<58YfnAMc=^fV))bq*ZM!#=oOaa8IaTDs-PyLkAzNAs4m9XOIF3zyu2a|McptHjh`Yyi=a@ZK4iEEpI(UHx3vIVCg!011y7eE back(), + "Seconds...": () => E.showMenu(secmenu), + "ISO8601 date": { + value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateAsISO = v; + writeSettings(); + } + }, + "Long date": { + value: (settings.longDate !== undefined ? settings.longDate : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.longDate = v; + writeSettings(); + } + }, + "Show Weekday": { + value: (settings.weekDay !== undefined ? settings.weekDay : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.weekDay = v; + writeSettings(); + } + }, + "Uppercase": { + value: (settings.upperCase !== undefined ? settings.upperCase : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.upperCase = v; + writeSettings(); + } + }, + }; + + // Submenu + var secmenu = { + "": { + "title": "Show seconds..." + }, + "< Back": () => E.showMenu(mainmenu), + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + if (v) + settings.secondsAlways = false; + writeSettings(); + } + }, + "Always": { + value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsAlways = v; + if (v) + settings.secondsOnUnlock = false; + writeSettings(); + } + } + }; + + // Actually display the menu + E.showMenu(mainmenu); + +}); + +// end of file From a245fa748d3bb4e8b06c0c298af9122262342914 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:23 +0100 Subject: [PATCH 071/202] Anton clock: Coloured seconds, date format config, small enhancements Result of the feedback on the first version. --- apps/antonclk/app.js | 157 +++++++++++++++++++++----------------- apps/antonclk/settings.js | 38 +++++---- 2 files changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 3b9c14c46..31ba696b7 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,6 +1,6 @@ // Clock with large digits using the "Anton" bold font -var SETTINGSFILE="antonclk.json"; +var SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) @@ -10,44 +10,56 @@ Graphics.prototype.setFontAnton = function(scale) { // variables defined from settings var secondsOnUnlock; var secondsAlways; +var secondsColoured; var dateAsISO; +var dateOnSecs; var longDate; var weekDay; var upperCase; // dynamic variables var drawTimeout; -var queueMillis=1000; -var withSeconds=true; +var queueMillis = 1000; +var secondsScreen = true; -var isBangle1=(g.getWidth()==240); +var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { secondsOnUnlock: false, secondsAlways: false, + secondsColoured: true, dateAsISO: false, + dateOnSecs: true, longDate: true, weekDay: true, - upperCase: true + upperCase: false, }); -*/ +/* */ -function def(value,def) { - return (value!==undefined?value:def); +/* OR (also for development purposes) +require('Storage').erase(SETTINGSFILE); +/* */ + +// Helper method for loading the settings +function def(value, def) { + return (value !== undefined ? value : def); } +// Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock,true); - secondsAlways = def(settings.secondsAlways,false); - dateAsISO = def(settings.dateAsISO,true); - longDate = def(settings.longDate,true); - weekDay = def(settings.weekDay,true); - upperCase = def(settings.upperCase,false); + secondsOnUnlock = def(settings.secondsOnUnlock, false); + secondsAlways = def(settings.secondsAlways, false); + secondsColoured = def(settings.secondsColoured, false); + dateAsISO = def(settings.dateAsISO, false); + dateOnSecs = def(settings.dateOnSecs, true); + longDate = def(settings.longDate, true); + weekDay = def(settings.weekDay, true); + upperCase = def(settings.upperCase, true); } -// schedule a draw for the next minute +// schedule a draw for the next second or minute function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { @@ -59,11 +71,11 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { - withSeconds=true; - queueMillis=1000; + secondsScreen = true; + queueMillis = 1000; } else { - withSeconds=false; - queueMillis=60000; + secondsScreen = false; + queueMillis = 60000; } draw(); // draw immediately, queue redraw } else { // stop draw timer @@ -73,71 +85,70 @@ function updateState() { } function isoStr(date) { - return date.getFullYear()+"-"+("0" + (date.getMonth()+1)).substr(-2)+"-"+("0" + date.getDate()).substr(-2); + return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } function doColor() { - return !isBangle1 && !Bangle.isLocked(); + return !isBangle1 && !Bangle.isLocked() && secondsColoured; } function draw() { - var x = g.getWidth()/2; - var y = g.getHeight()/2; - if (secondsOnUnlock || secondsAlways) - y-= 25; + var x = g.getWidth() / 2; + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); g.reset(); - g.clearRect(0,24,g.getWidth(),g.getHeight()); // clear whole background + g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background var date = new Date(); - var timeStr = require("locale").time(date,1); + var timeStr = require("locale").time(date, 1); // draw time - g.setFontAlign(0,0).setFont("Anton"); - g.drawString(timeStr,x,y); - if (withSeconds) { - y+=77; - var secStr = ":"+("0" + date.getSeconds()).substr(-2); - g.setFontAlign(1,0).setFont("Anton"); + g.setFontAlign(0, 0).setFont("Anton"); + g.drawString(timeStr, x, y); + if (secondsScreen) { + y += 76; + var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) - g.setColor(0,0,1); - g.drawString(secStr,g.getWidth()-(isBangle1?32:2),y); - y-=77; - y+=60; - x=g.getWidth()/4+(isBangle1?12:-4); - var dateStr2=(dateAsISO?isoStr(date):require("locale").date(date,1)); - var year; - var md; - var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { - year=dateStr2.slice(-4); - md=dateStr2.slice(0,-4); - if (!md.endsWith(".")) - md=md.slice(0,-1); - yearfirst=false; + g.setColor(0, 0, 1); + g.setFont("Anton"); + if (dateOnSecs) { + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); + y -= 16; + x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + var year; + var md; + var yearfirst; + if (dateStr2.match(/\d\d\d\d$/)) { + year = dateStr2.slice(-4); + md = dateStr2.slice(0, -4); + if (!md.endsWith(".")) + md = md.slice(0, -1); + yearfirst = false; + } else { + if (!dateStr2.match(/^\d\d\d\d/)) + dateStr2 = isoStr(date); + year = dateStr2.slice(0, 4); + md = dateStr2.slice(5); + yearfirst = true; + } + g.setFontAlign(0, 0).setFont("Vector", 24); + if (doColor()) + g.setColor(1, 0, 0); + g.drawString(md, x, (yearfirst ? y + 28 : y)); + g.drawString(year, x, (yearfirst ? y : y + 28)); + } else { + g.setFontAlign(0, 0).drawString(secStr, x, y); } - else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2=isoStr(date); - year=dateStr2.slice(0,4); - md=dateStr2.slice(5); - yearfirst=true; - } - g.setFontAlign(0,0).setFont("Vector",24); - if (doColor()) - g.setColor(1,0,0); - g.drawString(md,x,(yearfirst?y+28:y)); - g.drawString(year,x,(yearfirst?y:y+28)); - } - else { - y+=52; - var dateStr = (dateAsISO?isoStr(date):require("locale").date(date,(longDate?0:1))); + } else { // No seconds screen + y += 50; + var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) - dateStr=dateStr.toUpperCase(); - g.setFontAlign(0,0).setFont("Vector",24); - g.drawString(dateStr,x,y); + dateStr = dateStr.toUpperCase(); + g.setFontAlign(0, 0).setFont("Vector", 24); + g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) - dowStr=dowStr.toUpperCase(); - g.drawString(dowStr,x,y+28); + dowStr = dowStr.toUpperCase(); + g.drawString(dowStr, x, y + 26); } } @@ -152,8 +163,12 @@ g.clear(); // Set dynamic state and perform initial drawing updateState(); // Register hooks for LCD on/off event and screen lock on/off event -Bangle.on('lcdPower',on=>{ updateState(); }); -Bangle.on('lock',on=>{ updateState(); }); +Bangle.on('lcdPower', on => { + updateState(); +}); +Bangle.on('lock', on => { + updateState(); +}); // Show launcher when middle button pressed Bangle.setUI("clock"); // Load widgets diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 22cae41fb..2bcc1d7ce 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -4,7 +4,7 @@ var FILE = "antonclk.json"; // Load settings var settings = Object.assign({ - secondsOnUnlock: true, + secondsOnUnlock: false, }, require('Storage').readJSON(FILE, true) || {}); function writeSettings() { @@ -57,23 +57,35 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - if (v) - settings.secondsAlways = false; - writeSettings(); - } - }, "Always": { value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), format: v => v ? "On" : "Off", onchange: v => { settings.secondsAlways = v; - if (v) - settings.secondsOnUnlock = false; + writeSettings(); + } + }, + "If unlocked": { + value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsOnUnlock = v; + writeSettings(); + } + }, + "Coloured": { + value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.secondsColoured = v; + writeSettings(); + } + }, + "With date": { + value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.dateOnSecs = v; writeSettings(); } } From 322a3a0b5aed5a697347b966ebd7d1e8ccb1370b Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sat, 25 Dec 2021 21:55:30 +0100 Subject: [PATCH 072/202] Anton clock: README added --- apps.json | 1 + apps/antonclk/README.md | 66 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 apps/antonclk/README.md diff --git a/apps.json b/apps.json index b0d74926b..3411befc8 100644 --- a/apps.json +++ b/apps.json @@ -4240,6 +4240,7 @@ "name": "Anton Clock", "version": "0.04", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", + "readme":"README.md", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md new file mode 100644 index 000000000..40aa9d457 --- /dev/null +++ b/apps/antonclk/README.md @@ -0,0 +1,66 @@ +# Anton Clock - Large font digital watch with seconds and date + +Anton clock uses the "Anton" bold font to show the time in a clear, easily readable manner. On the Bangle.js 2, the time can be read easily even if the screen is locked and unlit. + +## Features + +The basic time representation only shows hours and minutes of the current time. However, Anton clock can show additional information: + +* Seconds can be shown, either always or only if the screen is unlocked. +* To help easy recognition, the seconds can be coloured in blue on the Bangle.js 2. +* Date can be shown in three different formats: + * ISO-8601: 2021-12-19 + * short local format: 19/12/2021, 19.12.2021 + * long local format (not together with seconds): DEC 19 2021 +* Weekday can be shown (not together with seconds) + +## Usage + +Install Anton clock through the Bangle.js app loader. +Configure it through the default Bangle.js configuration mechanism +(Settings app, "Apps" menu, "Anton clock" submenu). +If you like it, make it your default watch face +(Settings app, "System" menu, "Clock" submenu, select "Anton clock"). + +## Configuration + +Anton clock is configured by the standard settings mechanism of Bangle.js's operating system: +Open the "Settings" app, then the "Apps" submenu and below it the "Anton clock" menu. +You configure Anton clock through several "on/off" switches in two menus. + +### The main menu + +The main menu contains several settings covering Anton clock in general. + +* **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. +* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. +* **Long date** - Show the date in long format (usually with month in letters instead of number). +Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Show Weekday** - Weekday is shown in the time presentation without seconds. +Weekday name depends on the current locale. +If seconds are shown, the weekday is never shown as there is not enough space on the watch face. +* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. +This can improve readability. + +### The "Seconds" submenu + +The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. + +* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +If this is enabled, weekdays will never been shown. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **If unlocked** - Seconds are shown if the display is unlocked. +On a locked display, only hour, minutes, date and weekday are shown. +"Always" overrides this option. +_This option is highly recommended on the Bangle.js 2!_ +* **Coloured** - If enabled, seconds are shown in blue instead of black. +This make the visual orientation much easier on the watch face. +* **With date** - If enabled, the date is shown together with the seconds. +Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. +The date is coloured in red if the "Coloured" option is chosen. + +If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. + +## Compatibility + +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. From 7829af0ef29837e829d4c13ef9c63f89cfdbb82e Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Sun, 26 Dec 2021 19:42:04 +0100 Subject: [PATCH 073/202] Anton clock: Switch between vector and 6x8 font for date and day of week --- apps/antonclk/README.md | 3 ++ apps/antonclk/app.js | 60 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 8 ++++++ 3 files changed, 46 insertions(+), 25 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 40aa9d457..cb37d566b 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,6 +41,9 @@ Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. This can improve readability. +* **Vector font** - Use the built-in vector font for dates and weekday. +This can improve readability. +Otherwise, a scaled version of the built-in 6x8 pixels font is used. ### The "Seconds" submenu diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 31ba696b7..e772d679d 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -16,6 +16,7 @@ var dateOnSecs; var longDate; var weekDay; var upperCase; +var vectorFont; // dynamic variables var drawTimeout; @@ -34,6 +35,7 @@ require('Storage').writeJSON(SETTINGSFILE, { longDate: true, weekDay: true, upperCase: false, + vectorFont: false, }); /* */ @@ -57,6 +59,7 @@ function loadSettings() { longDate = def(settings.longDate, true); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); + vectorFont = def(settings.vectorFont, false); } // schedule a draw for the next second or minute @@ -92,63 +95,70 @@ function doColor() { return !isBangle1 && !Bangle.isLocked() && secondsColoured; } +// Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : 12); + var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); g.reset(); g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background - var date = new Date(); - var timeStr = require("locale").time(date, 1); - // draw time - g.setFontAlign(0, 0).setFont("Anton"); - g.drawString(timeStr, x, y); + var date = new Date(); // Actually the current date, this one is shown + var timeStr = require("locale").time(date, 1); // Hour and minute + g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { y += 76; var secStr = ":" + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); g.setFont("Anton"); - if (dateOnSecs) { - g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); - y -= 16; - x = g.getWidth() / 4 + (isBangle1 ? 12 : -4); + if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds + y -= (vectorFont ? 20 : 16); + x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; - if (dateStr2.match(/\d\d\d\d$/)) { + if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year year = dateStr2.slice(-4); md = dateStr2.slice(0, -4); - if (!md.endsWith(".")) + if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); yearfirst = false; - } else { - if (!dateStr2.match(/^\d\d\d\d/)) - dateStr2 = isoStr(date); + } else { // formatted date begins with year + if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... + dateStr2 = isoStr(date); // ...use ISO date format instead year = dateStr2.slice(0, 4); - md = dateStr2.slice(5); + md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); if (doColor()) g.setColor(1, 0, 0); - g.drawString(md, x, (yearfirst ? y + 28 : y)); - g.drawString(year, x, (yearfirst ? y : y + 28)); + g.drawString(md, x, (yearfirst ? y + (vectorFont ? 26 : 16) : y)); + g.drawString(year, x, (yearfirst ? y : y + (vectorFont ? 26 : 16))); } else { - g.setFontAlign(0, 0).drawString(secStr, x, y); + g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } - } else { // No seconds screen - y += 50; + } else { // No seconds screen: Show date and optionally day of week + y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); - g.setFontAlign(0, 0).setFont("Vector", 24); + g.setFontAlign(0, 0); + if (vectorFont) + g.setFont("Vector", 24); + else + g.setFont("6x8", 2); g.drawString(dateStr, x, y); if (weekDay) { var dowStr = require("locale").dow(date); if (upperCase) dowStr = dowStr.toUpperCase(); - g.drawString(dowStr, x, y + 26); + g.drawString(dowStr, x, y + (vectorFont ? 26 : 16)); } } @@ -175,4 +185,4 @@ Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); -// end of file +// end of file \ No newline at end of file diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 2bcc1d7ce..3af9df292 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -49,6 +49,14 @@ writeSettings(); } }, + "Vector font": { + value: (settings.vectorFont !== undefined ? settings.vectorFont : false), + format: v => v ? "On" : "Off", + onchange: v => { + settings.vectorFont = v; + writeSettings(); + } + }, }; // Submenu From d290578af10db777f2b3ff00e68059d3ab884809 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:49:36 -0800 Subject: [PATCH 074/202] Update apps.json --- apps.json | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 89c5f7b70..49397479a 100644 --- a/apps.json +++ b/apps.json @@ -5147,10 +5147,11 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"] "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ - {"name":"promenu.boot.js","url":"boot.js"}, + {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, + {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From 1adeef592b84dff615a1937ae01216f8d492786f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:51:42 -0800 Subject: [PATCH 075/202] Create bootb2.js --- apps/promenu/bootb2.js | 142 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 apps/promenu/bootb2.js diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js new file mode 100644 index 000000000..096745f34 --- /dev/null +++ b/apps/promenu/bootb2.js @@ -0,0 +1,142 @@ +E.showMenu = function(items) { + function RectRnd(x1,y1,x2,y2,r) { + pp = []; + pp.push.apply(pp,g.quadraticBezier([x2-r,y1, x2,y1,x2,y1+r])); + pp.push.apply(pp,g.quadraticBezier([x2,y2-r,x2,y2,x2-r,y2])); + pp.push.apply(pp,g.quadraticBezier([x1+r,y2,x1,y2,x1,y2-r])); + pp.push.apply(pp,g.quadraticBezier([x1,y1+r,x1,y1,x1+r,y1])); + return pp; + } + function fillRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.fillPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + function drawRectRnd(x1,y1,x2,y2,r,c) { + g.setColor(c); + g.drawPoly(RectRnd(x1,y1,x2,y2,r),1); + g.setColor(255,255,255); + } + g.reset().clearRect(Bangle.appRect); // clear if no menu supplied + Bangle.setLCDPower(1); // ensure screen is on + if (!items) { + Bangle.setUI(); + return; + } + var menuItems = Object.keys(items); + var options = items[""]; + if (options) menuItems.splice(menuItems.indexOf(""),1); + if (!(options instanceof Object)) options = {}; + options.fontHeight = options.fontHeight||25; + if (options.selected === undefined) + options.selected = 0; + var ar = Bangle.appRect; + var x = ar.x; + var x2 = ar.x2; + var y = ar.y; + var y2 = ar.y2 - 12; // padding at end for arrow + if (options.title) + y += 22; + var loc = require("locale"); + var l = { + lastIdx : 0, + draw : function(rowmin,rowmax) { + var rows = 0|Math.min((y2-y) / options.fontHeight,menuItems.length); + var idx = E.clip(options.selected-( rows>>1),0,menuItems.length-rows); + if (idx!=l.lastIdx) rowmin=undefined; // redraw all if we scrolled + l.lastIdx = idx; + var iy = y; + g.reset().setFontAlign(0,-1,0).setFont('12x20'); + if (options.predraw) options.predraw(g); + if (rowmin===undefined && options.title) + g.drawString(options.title,(x+x2)/2,y-21).drawLine(x,y-2,x2,y-2). + setColor(g.theme.fg).setBgColor(g.theme.bg); + iy += 4; + if (rowmin!==undefined) { + if (idxrowmax) { + rows = 1+rowmax-rowmin; + } + } + while (rows--) { + var name = menuItems[idx]; + var item = items[name]; + var hl = (idx==options.selected && !l.selectEdit); + if(g.theme.dark){ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg+40); + }else{ + fillRectRnd(x,iy,x2,iy+options.fontHeight-3,7,hl ? g.theme.bgH : g.theme.bg-20); + } + g.setColor(hl ? g.theme.fgH : g.theme.fg); + g.setFontAlign(-1,-1); + var v = item.value; + v = loc.translate(""+v); + if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if (item.format) v=item.format(v); + g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); + }else{ + if(loc.translate(name).length >= 15){ + g.drawString(loc.translate(name).substring(0, 15)+"...",x+3.7,iy+2.7); + }else{ + g.drawString(loc.translate(name),x+3.7,iy+2.7); + } + } + if ("object" == typeof item) { + var xo = x2; + var v = item.value; + if (item.format) v=item.format(v); + v = loc.translate(""+v); + if (l.selectEdit && idx==options.selected) { + xo -= 24 + 1; + g.setColor(g.theme.fgH).drawImage("\x0c\x05\x81\x00 \x07\x00\xF9\xF0\x0E\x00@",xo,iy+(options.fontHeight-10)/2,{scale:2}); + } + g.setFontAlign(1,-1); + g.drawString(v,xo-2,iy+1); + } + g.setColor(g.theme.fg); + iy += options.fontHeight; + idx++; + } + g.setFontAlign(-1,-1); + g.setColor((idxitem.max) item.value = item.wrap ? item.min : item.max; + if (item.onchange) item.onchange(item.value); + l.draw(options.selected,options.selected); + } else { + var lastSelected=options.selected; + options.selected = (dir+options.selected+menuItems.length)%menuItems.length; + l.draw(Math.min(lastSelected,options.selected), Math.max(lastSelected,options.selected)); + } + } + }; + l.draw(); + Bangle.setUI("updown",dir => { + if (dir) l.move(dir); + else l.select(); + }); + return l; +}; From 3cfc5a83458bcd01bf913c2edcdad2a481afb0a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:53:08 -0800 Subject: [PATCH 076/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 01bdaf84f..a7a1c85a1 100644 --- a/apps.json +++ b/apps.json @@ -5163,7 +5163,7 @@ "id": "promenu", "name": "Pro Menu", "version": "0.01", - "description": "Replace Bangle.js 1's built in menu function.", + "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", "tags": "system", From 485fb4a3c2bf9082be4dfb623d7f1a1042cef853 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 08:54:56 -0800 Subject: [PATCH 077/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a7a1c85a1..16beb366a 100644 --- a/apps.json +++ b/apps.json @@ -5167,7 +5167,7 @@ "icon": "icon.png", "type": "boot", "tags": "system", - "supports": ["BANGLEJS","BANGLEJS2"] + "supports": ["BANGLEJS","BANGLEJS2"], "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, From c87d1d16509ca3943db44bc1606c8757039fb3e5 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:28:32 +0100 Subject: [PATCH 078/202] Fix settings default values --- apps/circlesclock/settings.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 0c42319f5..95ebc17db 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -10,6 +10,7 @@ var namesCircleTypes = ["steps", "distance", "heart", "battery"]; E.showMenu({ '': { 'title': 'circlesclock' }, + '< Back': back, 'min heartrate': { value: "minHR" in settings ? settings.minHR : 40, min: 0, @@ -76,23 +77,22 @@ onchange: x => save('showWidgets', x), }, 'left': { - value: Math.max(0,0 | valuesCircleTypes.indexOf(settings.circle1)), + value: settings.circle1 ? valuesCircleTypes.indexOf(settings.circle1) : 0, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { - value: Math.max(0,2 | valuesCircleTypes.indexOf(settings.circle2)), + value: settings.circle2 ? valuesCircleTypes.indexOf(settings.circle2) : 2, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { - value: Math.max(0,3 | valuesCircleTypes.indexOf(settings.circle3)), + value: settings.circle3 ? valuesCircleTypes.indexOf(settings.circle3) : 3, min: 0, max: 3, format: v => namesCircleTypes[v], onchange: x => save('circle3', valuesCircleTypes[x]), - }, - '< Back': back, + } }); }); From 9a5937a3eb3535636e74f926d83dd41ebdd8c407 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:38:18 +0100 Subject: [PATCH 079/202] Improve widget visibility --- apps/circlesclock/app.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index e10d55f17..a256c93ce 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -41,7 +41,7 @@ const colorRed = '#ff0000'; const colorGreen = '#008000'; const colorBlue = '#0000ff'; const colorYellow = '#ffff00'; -const widgetOffset = showWidgets ? 12 : 0; +const widgetOffset = showWidgets ? 14 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); const hOffset = 30 - widgetOffset; @@ -55,9 +55,9 @@ const radiusOuter = 22; const radiusInner = 16; function draw() { - g.reset(); + g.clear(true); g.setColor(colorBg); - g.fillRect(0, 0, w, h); + g.fillRect(0, widgetOffset, w, h); // time g.setFont("Vector:50"); @@ -265,7 +265,7 @@ function shortValue(v) { } function getSteps() { - if (WIDGETS.wpedom !== undefined) { + if (WIDGETS && WIDGETS.wpedom !== undefined) { return WIDGETS.wpedom.getSteps(); } return 0; @@ -307,8 +307,6 @@ if (isCircleEnabled("battery")) { }); } -g.clear(); - Bangle.setUI("clock"); Bangle.loadWidgets(); if (!showWidgets) { From c15b700ef6fde7bdad924150d25504e51660e358 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 5 Jan 2022 19:50:07 +0100 Subject: [PATCH 080/202] Fix widget drawing --- apps/circlesclock/app.js | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index a256c93ce..fb4635424 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -56,6 +56,23 @@ const radiusInner = 16; function draw() { g.clear(true); + + if (!showWidgets) { + /* + * we are not drawing the widgets as we are taking over the whole screen + * so we will blank out the draw() functions of each widget and change the + * area to the top bar doesn't get cleared. + */ + if (WIDGETS && typeof WIDGETS === "object") { + for (let wd of WIDGETS) { + wd.draw = () => {}; + wd.area = ""; + } + } + } else { + Bangle.drawWidgets(); + } + g.setColor(colorBg); g.fillRect(0, widgetOffset, w, h); @@ -280,8 +297,7 @@ Bangle.on('lock', function(isLocked) { drawHeartRate(); } } - if (isCircleEnabled("steps")) drawSteps(); - if (isCircleEnabled("stepsDistance")) drawStepsDistance(); + draw(); } else { if (isCircleEnabled("hr")) { Bangle.setHRMPower(0, "watch"); @@ -309,19 +325,6 @@ if (isCircleEnabled("battery")) { Bangle.setUI("clock"); Bangle.loadWidgets(); -if (!showWidgets) { - /* - * we are not drawing the widgets as we are taking over the whole screen - * so we will blank out the draw() functions of each widget and change the - * area to the top bar doesn't get cleared. - */ - if (WIDGETS && typeof WIDGETS === "object") { - for (let wd of WIDGETS) { - wd.draw = () => {}; - wd.area = ""; - } - } -} draw(); setInterval(draw, 60000); From d36743032c878bd73fdda87cf0b22d5b8e002b10 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Wed, 5 Jan 2022 22:21:55 +0100 Subject: [PATCH 081/202] Anton clock: Smaller seconds, weekday with seconds, seconds without colon, cleaner configuration --- apps/antonclk/README.md | 42 ++++++++++++-------- apps/antonclk/app.js | 81 +++++++++++++++++++++++---------------- apps/antonclk/settings.js | 64 ++++++++++++++----------------- 3 files changed, 101 insertions(+), 86 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index cb37d566b..41d3e4559 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -11,8 +11,8 @@ The basic time representation only shows hours and minutes of the current time. * Date can be shown in three different formats: * ISO-8601: 2021-12-19 * short local format: 19/12/2021, 19.12.2021 - * long local format (not together with seconds): DEC 19 2021 -* Weekday can be shown (not together with seconds) + * long local format: DEC 19 2021 +* Weekday can be shown (on seconds screen only instead of year) ## Usage @@ -33,9 +33,10 @@ You configure Anton clock through several "on/off" switches in two menus. The main menu contains several settings covering Anton clock in general. * **Seconds...** - Opens the submenu for configuring the presentation of the current time's seconds. -* **ISO8601 date** - Show the date in ISO-8601 format, irrespective of the current locale. -* **Long date** - Show the date in long format (usually with month in letters instead of number). -Exact format depends on the current locale. _Only evaluated if ISO8601 date is not set._ +* **Date** - Format of the date representation. Possible values are + * **Long** - "Long" date format in the current locale. Usually with the month as name, not number. + * **Short** - "Short" date format in the current locale. Usually with the month as number. + * **ISO8601** - Show the date in ISO-8601 format (YYYY-MM-DD), irrespective of the current locale. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. @@ -49,21 +50,28 @@ Otherwise, a scaled version of the built-in 6x8 pixels font is used. The "Seconds" submenu configures how (and if) seconds are shown on the "Anton" watch face. -* **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. -If this is enabled, weekdays will never been shown. -_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ -* **If unlocked** - Seconds are shown if the display is unlocked. -On a locked display, only hour, minutes, date and weekday are shown. -"Always" overrides this option. +* **Show** - Configure when the seconds should be shown at all: + * **Never** - Seconds are never shown. +In this case, hour and minute are a bit more centered on the screen and the clock will always only update every minute. +This saves battery power. + * **Unlocked** - Seconds are shown if the display is unlocked. +On locked displays, only hour, minutes, date and optionally the weekday are shown. _This option is highly recommended on the Bangle.js 2!_ -* **Coloured** - If enabled, seconds are shown in blue instead of black. + * **Always** - Seconds are _always_ shown, irrespective of the display's unlock state. +_Enabling this option increases power consumption as the watch face will update once per second instead of once per minute._ +* **With ":"** - If enabled, a colon ":" is prepended to the seconds. +This resembles the usual time representation "hh:mm:ss", even though the seconds are printed on a separate line. +* **Color** - If enabled, seconds are shown in blue instead of black. +If the date is shown on the seconds screen, it is colored read instead of black. This make the visual orientation much easier on the watch face. -* **With date** - If enabled, the date is shown together with the seconds. -Depending on the "ISO8601 date" settings, ISO8601 or short local format is used. -The date is coloured in red if the "Coloured" option is chosen. +* **Date** - It is possible to show the date together with the seconds: + * **No** - Date is _not_ shown in the seconds screen. +In this case, the seconds are centered below hour and minute. + * **Year** - Date is shown with day, month, and year. If "Date" in the main settings is configured to _ISO8601_, this is used here, too. Otherwise, the short local format is used. + * **Weekday** - Date is shown with day, month, and weekday. -If neither "Always" nor "If unlocked" is selected, Anton clock does _never_ show seconds. +The date is coloured in red if the "Coloured" option is chosen. ## Compatibility -Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to the hardware features. +Anton clock makes use of core Bangle.js 2 features (coloured display, display lock state). It also runs on the Bangle.js 1 but these features are not available there due to hardware restrictions. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index e772d679d..1f3e49792 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -3,17 +3,21 @@ var SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { -// Actual height 69 (68 - 0) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78+(scale<<8)+(1<<16)); + // Actual height 69 (68 - 0) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAAAAAAAAAAA/gAAAAAAAAAAP/gAAAAAAAAAH//gAAAAAAAAB///gAAAAAAAAf///gAAAAAAAP////gAAAAAAD/////gAAAAAA//////gAAAAAP//////gAAAAH///////gAAAB////////gAAAf////////gAAP/////////gAD//////////AA//////////gAA/////////4AAA////////+AAAA////////gAAAA///////wAAAAA//////8AAAAAA//////AAAAAAA/////gAAAAAAA////4AAAAAAAA///+AAAAAAAAA///gAAAAAAAAA//wAAAAAAAAAA/8AAAAAAAAAAA/AAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////AAAAAB///////8AAAAH////////AAAAf////////wAAA/////////4AAB/////////8AAD/////////+AAH//////////AAP//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wA//8AAAAAB//4A//wAAAAAAf/4A//gAAAAAAP/4A//gAAAAAAP/4A//gAAAAAAP/4A//wAAAAAAf/4A///////////4Af//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH//////////AAD/////////+AAB/////////8AAA/////////4AAAP////////gAAAD///////+AAAAAf//////4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/gAAAAAAAAAAP/gAAAAAAAAAAf/gAAAAAAAAAAf/gAAAAAAAAAAf/AAAAAAAAAAA//AAAAAAAAAAA/+AAAAAAAAAAB/8AAAAAAAAAAD//////////gAH//////////gAP//////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAAB/gAAD//4AAAAf/gAAP//4AAAB//gAA///4AAAH//gAB///4AAAf//gAD///4AAA///gAH///4AAD///gAP///4AAH///gAP///4AAP///gAf///4AAf///gAf///4AB////gAf///4AD////gA////4AH////gA////4Af////gA////4A/////gA//wAAB/////gA//gAAH/////gA//gAAP/////gA//gAA///8//gA//gAD///w//gA//wA////g//gA////////A//gA///////8A//gA///////4A//gAf//////wA//gAf//////gA//gAf/////+AA//gAP/////8AA//gAP/////4AA//gAH/////gAA//gAD/////AAA//gAB////8AAA//gAA////wAAA//gAAP///AAAA//gAAD//8AAAA//gAAAP+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/+AAAAAD/wAAB//8AAAAP/wAAB///AAAA//wAAB///wAAB//wAAB///4AAD//wAAB///8AAH//wAAB///+AAP//wAAB///+AAP//wAAB////AAf//wAAB////AAf//wAAB////gAf//wAAB////gA///wAAB////gA///wAAB////gA///w//AAf//wA//4A//AAA//wA//gA//AAAf/wA//gB//gAAf/wA//gB//gAAf/wA//gD//wAA//wA//wH//8AB//wA///////////gA///////////gA///////////gA///////////gAf//////////AAf//////////AAP//////////AAP/////////+AAH/////////8AAH///+/////4AAD///+f////wAAA///8P////gAAAf//4H///+AAAAH//gB///wAAAAAP4AAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/wAAAAAAAAAA//wAAAAAAAAAP//wAAAAAAAAB///wAAAAAAAAf///wAAAAAAAH////wAAAAAAA/////wAAAAAAP/////wAAAAAB//////wAAAAAf//////wAAAAH///////wAAAA////////wAAAP////////wAAA///////H/wAAA//////wH/wAAA/////8AH/wAAA/////AAH/wAAA////gAAH/wAAA///4AAAH/wAAA//+AAAAH/wAAA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gA///////////gAAAAAAAAH/4AAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//8AAA/////+B///AAA/////+B///wAA/////+B///4AA/////+B///8AA/////+B///8AA/////+B///+AA/////+B////AA/////+B////AA/////+B////AA/////+B////gA/////+B////gA/////+B////gA/////+A////gA//gP/gAAB//wA//gf/AAAA//wA//gf/AAAAf/wA//g//AAAAf/wA//g//AAAA//wA//g//gAAA//wA//g//+AAP//wA//g////////gA//g////////gA//g////////gA//g////////gA//g////////AA//gf///////AA//gf//////+AA//gP//////+AA//gH//////8AA//gD//////4AA//gB//////wAA//gA//////AAAAAAAH////8AAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////gAAAAB///////+AAAAH////////gAAAf////////4AAB/////////8AAD/////////+AAH//////////AAH//////////gAP//////////gAP//////////gAf//////////wAf//////////wAf//////////wAf//////////wAf//////////4A//wAD/4AAf/4A//gAH/wAAP/4A//gAH/wAAP/4A//gAP/wAAP/4A//gAP/4AAf/4A//wAP/+AD//4A///wP//////4Af//4P//////wAf//4P//////wAf//4P//////wAf//4P//////wAP//4P//////gAP//4H//////gAH//4H//////AAH//4D/////+AAD//4D/////8AAB//4B/////4AAA//4A/////wAAAP/4AP////AAAAB/4AD///4AAAAAAAAAH/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAAAAA//gAAAAAAADgA//gAAAAAAP/gA//gAAAAAH//gA//gAAAAB///gA//gAAAAP///gA//gAAAD////gA//gAAAf////gA//gAAB/////gA//gAAP/////gA//gAB//////gA//gAH//////gA//gA///////gA//gD///////gA//gf///////gA//h////////gA//n////////gA//////////gAA/////////AAAA////////wAAAA///////4AAAAA///////AAAAAA//////4AAAAAA//////AAAAAAA/////4AAAAAAA/////AAAAAAAA////8AAAAAAAA////gAAAAAAAA///+AAAAAAAAA///4AAAAAAAAA///AAAAAAAAAA//4AAAAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//gB///wAAAAP//4H///+AAAA///8P////gAAB///+f////4AAD///+/////8AAH/////////+AAH//////////AAP//////////gAP//////////gAf//////////gAf//////////wAf//////////wAf//////////wA///////////wA//4D//wAB//4A//wB//gAA//4A//gA//gAAf/4A//gA//AAAf/4A//gA//gAAf/4A//wB//gAA//4A///P//8AH//4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////gAP//////////gAP//////////AAH//////////AAD/////////+AAD///+/////8AAB///8f////wAAAf//4P////AAAAH//wD///8AAAAA/+AAf//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAAAAAAAAB///+AA/+AAAAP////gA//wAAAf////wA//4AAB/////4A//8AAD/////8A//+AAD/////+A///AAH/////+A///AAP//////A///gAP//////A///gAf//////A///wAf//////A///wAf//////A///wAf//////A///wA///////AB//4A//4AD//AAP/4A//gAB//AAP/4A//gAA//AAP/4A//gAA/+AAP/4A//gAB/8AAP/4A//wAB/8AAf/4Af//////////wAf//////////wAf//////////wAf//////////wAf//////////wAP//////////gAP//////////gAH//////////AAH/////////+AAD/////////8AAB/////////4AAAf////////wAAAP////////AAAAB///////4AAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf/AAB/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAA//AAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("EiAnGicnJycnJycnEw=="), 78 + (scale << 8) + (1 << 16)); +}; + +Graphics.prototype.setFontAntonSmall = function(scale) { + // Actual height 53 (52 - 0) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAf8AAAAAAAAAAAAAAAAAAAAMAAAAAAAAD8AAAAAAAA/8AAAAAAAf/8AAAAAAH//8AAAAAB///8AAAAA////8AAAAP////8AAAD/////8AAB//////8AAf//////8AH///////4A///////+AA///////AAA//////wAAA/////8AAAA////+AAAAA////gAAAAA///4AAAAAA//8AAAAAAA//AAAAAAAA/wAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/////wAAA//////8AAB//////+AAH///////gAH///////gAP///////wAf///////4Af///////4A////////8A////////8A////////8A//AAAAD/8A/8AAAAA/8A/8AAAAA/8A/8AAAAA/8A/+AAAAB/8A////////8A////////8A////////8Af///////4Af///////4AP///////wAP///////wAH///////gAD///////AAA//////8AAAP/////wAAAAAAAAAAAAAAAAAAAAAAAfwAAAAAAAA/4AAAAAAAA/4AAAAAAAB/wAAAAAAAB/wAAAAAAAD/wAAAAAAAD/gAAAAAAAH///////8AP///////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/4AAAP8AA//4AAA/8AB//4AAH/8AH//4AAP/8AP//4AA//8AP//4AB//8Af//4AD//8Af//4AP//8A///4Af//8A///4A///8A///4D///8A//AAH///8A/8AAP///8A/8AA//+/8A/8AD//8/8A/+Af//w/8A//////g/8A/////+A/8A/////8A/8Af////4A/8Af////wA/8AP////AA/8AP///+AA/8AH///8AA/8AD///wAA/8AA///AAA/8AAP/4AAA/8AAAAAAAAAAAAAAAAAAAAAAH4AAf/gAAA/4AAf/8AAD/4AAf//AAH/4AAf//gAP/4AAf//wAP/4AAf//wAf/4AAf//4Af/4AAf//4A//4AAf//8A//4AAf//8A//4AAP//8A//A/8AB/8A/8A/8AA/8A/8B/8AA/8A/8B/8AA/8A/+D//AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////gAH//9////gAD//4///+AAB//wf//4AAAP/AH//gAAAAAAAAAAAAAAAAAAAAAAAAAAAH/wAAAAAAB//wAAAAAAP//wAAAAAD///wAAAAA////wAAAAH////wAAAB/////wAAAf/////wAAD//////wAA///////wAA/////h/wAA////wB/wAA///8AB/wAA///AAB/wAA//gAAB/wAA////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8A////////8AAAAAAB/wAAAAAAAB/wAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAP/4AA////4P/+AA////4P//AA////4P//gA////4P//wA////4P//wA////4P//4A////4P//4A////4P//8A////4P//8A////4P//8A/8H/AAB/8A/8H+AAA/8A/8P+AAA/8A/8P+AAA/8A/8P/gAD/8A/8P/////8A/8P/////8A/8P/////8A/8P/////4A/8H/////4A/8H/////wA/8D/////wA/8B/////gA/8A////+AA/8AP///4AAAAAB///AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAf/////8AAB///////AAH///////gAP///////wAP///////wAf///////4Af///////4A////////8A////////8A////////8A/+AH/AB/8A/8AP+AA/8A/4Af+AA/8A/8Af+AA/8A/8Af/gH/8A//4f////8A//4f////8A//4f////8Af/4f////4Af/4f////4AP/4P////wAP/4P////gAH/4H////AAD/4D///+AAB/4B///4AAAP4AP//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/8AAAAAAAA/8AAAAAAAA/8AAAAAB8A/8AAAAB/8A/8AAAAf/8A/8AAAH//8A/8AAA///8A/8AAH///8A/8AA////8A/8AD////8A/8Af////8A/8B/////8A/8P/////8A/8//////8A////////AA///////AAA//////gAAA/////4AAAA/////AAAAA////4AAAAA////AAAAAA///8AAAAAA///gAAAAAA//+AAAAAAA//wAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/gD//gAAA//4P//8AAD//8f///AAH//+////gAH///////wAP///////4AP///////8Af///////8Af///////+Af///////+A////////+A//B//AB/+A/+A/+AA/+A/8Af+AA/+A/+Af+AA/+A//A//AB/+A////////+Af///////+Af///////+Af///////8Af///////8AP///////4AH///////4AH//+////wAD//+////AAA//4P//+AAAP/gH//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH//gAfgAAA///8A/8AAB///+A//AAH////A//gAH////g//wAP////g//wAf////w//4Af////w//4A/////w//8A/////w//8A/////w//8A//gP/wA/8A/8AD/wA/8A/8AD/wAf8A/8AD/gA/8A/+AH/AB/8A////////8A////////8A////////8Af///////4Af///////4Af///////wAP///////wAH///////gAD//////+AAA//////4AAAP/////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAP+AA/4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DhgeFB4eHh4eHh4eDw=="), 60 + (scale << 8) + (1 << 16)); }; // variables defined from settings -var secondsOnUnlock; -var secondsAlways; +var secondsMode; var secondsColoured; -var dateAsISO; +var secondsWithColon; +var dateOnMain; var dateOnSecs; -var longDate; var weekDay; var upperCase; var vectorFont; @@ -27,15 +31,14 @@ var isBangle1 = (g.getWidth() == 240); /* For development purposes require('Storage').writeJSON(SETTINGSFILE, { - secondsOnUnlock: false, - secondsAlways: false, + secondsMode: "Always", // "Never", "Unlocked", "Always" secondsColoured: true, - dateAsISO: false, - dateOnSecs: true, - longDate: true, + secondsWithColon: true, + dateOnMain: "Long", // "Short", "Long", "ISO8601" + dateOnSecs: "Year", // "No", "Year", "Weekday", LEGACY: true/false weekDay: true, - upperCase: false, - vectorFont: false, + upperCase: true, + vectorFont: true, }); /* */ @@ -51,15 +54,20 @@ function def(value, def) { // Load settings function loadSettings() { var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; - secondsOnUnlock = def(settings.secondsOnUnlock, false); - secondsAlways = def(settings.secondsAlways, false); - secondsColoured = def(settings.secondsColoured, false); - dateAsISO = def(settings.dateAsISO, false); - dateOnSecs = def(settings.dateOnSecs, true); - longDate = def(settings.longDate, true); + secondsMode = def(settings.secondsMode, "Never"); + secondsColoured = def(settings.secondsColoured, true); + secondsWithColon = def(settings.secondsWithColon, true); + dateOnMain = def(settings.dateOnMain, "Long"); + dateOnSecs = def(settings.dateOnSecs, "Year"); weekDay = def(settings.weekDay, true); upperCase = def(settings.upperCase, true); vectorFont = def(settings.vectorFont, false); + + // Legacy + if (dateOnSecs === true) + dateOnSecs = "Year"; + if (dateOnSecs === false) + dateOnSecs = "No"; } // schedule a draw for the next second or minute @@ -73,7 +81,7 @@ function queueDraw() { function updateState() { if (Bangle.isLCDOn()) { - if ((secondsOnUnlock && !Bangle.isLocked()) || secondsAlways) { + if ((secondsMode === "Unlocked" && !Bangle.isLocked()) || secondsMode === "Always") { secondsScreen = true; queueMillis = 1000; } else { @@ -98,28 +106,33 @@ function doColor() { // Actually draw the watch face function draw() { var x = g.getWidth() / 2; - var y = g.getHeight() / 2 - (secondsOnUnlock || secondsAlways ? 24 : (vectorFont ? 12 : 0)); + var y = g.getHeight() / 2 - (secondsMode !== "Never" ? 24 : (vectorFont ? 12 : 0)); g.reset(); - g.clearRect(0, 24, g.getWidth(), g.getHeight()); // clear whole background + /* This is to mark the widget areas during development. + g.setColor("#888") + .fillRect(0, 0, g.getWidth(), 23) + .fillRect(0, g.getHeight() - 23, g.getWidth(), g.getHeight()).reset(); + /* */ + g.clearRect(0, 24, g.getWidth(), g.getHeight() - 24); // clear whole background (w/o widgets) var date = new Date(); // Actually the current date, this one is shown var timeStr = require("locale").time(date, 1); // Hour and minute g.setFontAlign(0, 0).setFont("Anton").drawString(timeStr, x, y); // draw time if (secondsScreen) { - y += 76; - var secStr = ":" + ("0" + date.getSeconds()).substr(-2); + y += 65; + var secStr = (secondsWithColon ? ":" : "") + ("0" + date.getSeconds()).substr(-2); if (doColor()) g.setColor(0, 0, 1); - g.setFont("Anton"); - if (dateOnSecs) { // A bit of a complex drawing with seconds on the right and date on the left + g.setFont("AntonSmall"); + if (dateOnSecs !== "No") { // A bit of a complex drawing with seconds on the right and date on the left g.setFontAlign(1, 0).drawString(secStr, g.getWidth() - (isBangle1 ? 32 : 2), y); // seconds - y -= (vectorFont ? 20 : 16); - x = g.getWidth() / 4 + (isBangle1 ? 12 : -6); - var dateStr2 = (dateAsISO ? isoStr(date) : require("locale").date(date, 1)); + y -= (vectorFont ? 15 : 13); + x = g.getWidth() / 4 + (isBangle1 ? 12 : 4) + (secondsWithColon ? 0 : g.stringWidth(":") / 2); + var dateStr2 = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, 1)); var year; var md; var yearfirst; if (dateStr2.match(/\d\d\d\d$/)) { // formatted date ends with year - year = dateStr2.slice(-4); + year = (dateOnSecs === "Year" ? dateStr2.slice(-4) : require("locale").dow(date, 1)); md = dateStr2.slice(0, -4); if (!md.endsWith(".")) // keep separator before the year only if it is a dot (31.12. but 31/12) md = md.slice(0, -1); @@ -127,10 +140,12 @@ function draw() { } else { // formatted date begins with year if (!dateStr2.match(/^\d\d\d\d/)) // if year position cannot be detected... dateStr2 = isoStr(date); // ...use ISO date format instead - year = dateStr2.slice(0, 4); + year = (dateOnSecs === "Year" ? dateStr2.slice(0, 4) : require("locale").dow(date, 1)); md = dateStr2.slice(5); // never keep separator directly after year yearfirst = true; } + if (dateOnSecs === "Weekday" && upperCase) + year = year.toUpperCase(); g.setFontAlign(0, 0); if (vectorFont) g.setFont("Vector", 24); @@ -144,8 +159,8 @@ function draw() { g.setFontAlign(0, 0).drawString(secStr, x, y); // Just the seconds centered } } else { // No seconds screen: Show date and optionally day of week - y += (vectorFont ? 50 : (secondsOnUnlock || secondsAlways) ? 52 : 40); - var dateStr = (dateAsISO ? isoStr(date) : require("locale").date(date, (longDate ? 0 : 1))); + y += (vectorFont ? 50 : (secondsMode !== "Never") ? 52 : 40); + var dateStr = (dateOnMain === "ISO8601" ? isoStr(date) : require("locale").date(date, (dateOnMain === "Long" ? 0 : 1))); if (upperCase) dateStr = dateStr.toUpperCase(); g.setFontAlign(0, 0); diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 3af9df292..08fde512e 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -11,28 +11,34 @@ require('Storage').writeJSON(FILE, settings); } + // Helper method which uses int-based menu item for set of string values + function stringItems(startvalue, writer, values) { + return { + value: (startvalue === undefined ? 0 : values.indexOf(startvalue)), + format: v => values[v], + min: 0, + max: values.length - 1, + wrap: true, + step: 1, + onchange: v => { + writer(values[v]); + writeSettings(); + } + }; + } + + // Helper method which breaks string set settings down to local settings object + function stringInSettings(name, values) { + return stringItems(settings[name], v => settings[name] = v, values); + } + var mainmenu = { "": { "title": "Anton clock" }, "< Back": () => back(), "Seconds...": () => E.showMenu(secmenu), - "ISO8601 date": { - value: (settings.dateAsISO !== undefined ? settings.dateAsISO : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateAsISO = v; - writeSettings(); - } - }, - "Long date": { - value: (settings.longDate !== undefined ? settings.longDate : true), - format: v => v ? "On" : "Off", - onchange: v => { - settings.longDate = v; - writeSettings(); - } - }, + "Date": stringInSettings("dateOnMain", ["Short", "Long", "ISO8601"]), "Show Weekday": { value: (settings.weekDay !== undefined ? settings.weekDay : true), format: v => v ? "On" : "Off", @@ -65,23 +71,16 @@ "title": "Show seconds..." }, "< Back": () => E.showMenu(mainmenu), - "Always": { - value: (settings.secondsAlways !== undefined ? settings.secondsAlways : false), + "Show": stringInSettings("secondsMode", ["Never", "Unlocked", "Always"]), + "With \":\"": { + value: (settings.secondsWithColon !== undefined ? settings.secondsWithColon : false), format: v => v ? "On" : "Off", onchange: v => { - settings.secondsAlways = v; + settings.secondsWithColon = v; writeSettings(); } }, - "If unlocked": { - value: (settings.secondsOnUnlock !== undefined ? settings.secondsOnUnlock : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.secondsOnUnlock = v; - writeSettings(); - } - }, - "Coloured": { + "Color": { value: (settings.secondsColoured !== undefined ? settings.secondsColoured : false), format: v => v ? "On" : "Off", onchange: v => { @@ -89,14 +88,7 @@ writeSettings(); } }, - "With date": { - value: (settings.dateOnSecs !== undefined ? settings.dateOnSecs : false), - format: v => v ? "On" : "Off", - onchange: v => { - settings.dateOnSecs = v; - writeSettings(); - } - } + "Date": stringInSettings("dateOnSecs", ["No", "Year", "Weekday"]) }; // Actually display the menu From ebc7005e372cbd03b6922fcec13d5f8010f0a802 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 21:27:21 +0000 Subject: [PATCH 082/202] Flipper: switch between light and dark theme and vice versa --- apps.json | 15 ++++++++++++++ apps/flipper/flipper.app.js | 39 +++++++++++++++++++++++++++++++++++ apps/flipper/flipper.icon.js | 1 + apps/flipper/flipper.png | Bin 0 -> 644 bytes 4 files changed, 55 insertions(+) create mode 100644 apps/flipper/flipper.app.js create mode 100644 apps/flipper/flipper.icon.js create mode 100644 apps/flipper/flipper.png diff --git a/apps.json b/apps.json index ebafa9c97..a32522fa2 100644 --- a/apps.json +++ b/apps.json @@ -5427,5 +5427,20 @@ {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} ], "data": [{"name":"puzzle15.json"}] + }, + { + "id": "flipper", + "name": "flipper", + "version": "0.01", + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "icon": "flipper.png", + "type": "app", + "tags": "game", + "supports": ["BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"flipper.app.js","url":"flipper.app.js"}, + {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js new file mode 100644 index 000000000..2e7d3551c --- /dev/null +++ b/apps/flipper/flipper.app.js @@ -0,0 +1,39 @@ +const storage = require('Storage'); +let settings = storage.readJSON('setting.json', 1); + +function cl(x) { return g.setColor(x).getColor(); } + +function upd(th) { + g.theme = th; + settings.theme = th; + storage.write('setting.json', settings); + delete g.reset; + g._reset = g.reset; + g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; + g.clear(1); +}; + +function flipTheme() { + if (!g.theme.dark) { + upd({ + fg:cl("#fff"), bg:cl("#000"), + fg2:cl("#0ff"), bg2:cl("#000"), + fgH:cl("#fff"), bgH:cl("#00f"), + dark:true + }); + } else { + upd({ + fg:cl("#000"), bg:cl("#fff"), + fg2:cl("#000"), bg2:cl("#cff"), + fgH:cl("#000"), bgH:cl("#0ff"), + dark:false + }); + } +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +flipTheme(); +setTimeout(load, 20); diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js new file mode 100644 index 000000000..16331c09e --- /dev/null +++ b/apps/flipper/flipper.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); diff --git a/apps/flipper/flipper.png b/apps/flipper/flipper.png new file mode 100644 index 0000000000000000000000000000000000000000..b91543070be72c6a53a11aabec8d779780d2bc11 GIT binary patch literal 644 zcmV-~0(-0O`Ea$39hd$rSFgp06=YM0Il{S zNt_9?Wo4B{?^|t~pJ#}Zrg02ZoGP${lF_V|5I_%73ZmJuT0&*lfPjaY0kbl|Sb3wL z2iZV)c;Qk98Bz=!?CoNy@mQ250PlrNr2`;lAs6C1E3GII=pLkuXTT=w$hHTa{YLQ` z0?xEdlzJYJ3F=Idm0(>vK^Pg(9sT9im&`Mr3Ts-00mn0N`_RDC^9pvhHpzW_4_+18 zL9D7-+xz_(>FX7?nT)LIEeMMfc@TeKdJw5k&EV#IQrPAaCrd~q@cQg1x6LKi2J!@! zbsCWl%(i2A&pkZvWCw5cpu zQ52!tv*A*c5t$$kc$hi6inbEUj%}3*5RIkQdBFF-Ff#srA^Yik31Y^IS-VB@>t~>A ez&Bk3zIg*Y=-nc5eyO+s0000 Date: Wed, 5 Jan 2022 22:04:50 +0000 Subject: [PATCH 083/202] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a32522fa2..07d9c02ae 100644 --- a/apps.json +++ b/apps.json @@ -5432,7 +5432,7 @@ "id": "flipper", "name": "flipper", "version": "0.01", - "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip." + "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", "icon": "flipper.png", "type": "app", "tags": "game", From 71228efb4ba118f8c4c2145174008ca02f329b1c Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:12:16 +0100 Subject: [PATCH 084/202] Update gps-info.js Resolve one FIFO_FULL case and exit App with button press --- apps/gpsinfo/gps-info.js | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index a16d4a04e..467d12a95 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -19,6 +19,7 @@ var lastFix = { var SATinView = 0; var nofBD = 0; var nofGP = 0; +var listenerGPSraw = 1; function formatTime(now) { if (now == undefined) { @@ -93,6 +94,10 @@ function onGPS(fix) { } lastFix = fix; if (fix.fix) { + if (listenerGPSraw == 1) { + Bangle.removeListener('GPS-raw', onGPSraw); + listenerGPSraw = 0; + } var locale = require("locale"); var satellites = fix.satellites; var maidenhead = getMaidenHead(fix.lat,fix.lon); @@ -104,6 +109,10 @@ function onGPS(fix) { layout.sat.label = "Satellites: "+satellites; layout.maidenhead.label = "Maidenhead: "+maidenhead; } else { + if (listenerGPSraw == 0) { + Bangle.on('GPS-raw', onGPSraw); + listenerGPSraw = 1; + } layout.sat.label = fix.satellites; layout.progress.label = "in view: " + SATinView; } @@ -111,15 +120,26 @@ function onGPS(fix) { } function onGPSraw(nmea) { - if (nmea.slice(3,6) == "GSV") { - // console.log(nmea); - if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); - if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); - SATinView = nofBD + nofGP; - } + if (nmea.slice(0,7) == "$BDGSV,") nofBD = Number(nmea.slice(11,13)); + if (nmea.slice(0,7) == "$GPGSV,") nofGP = Number(nmea.slice(11,13)); + SATinView = nofBD + nofGP; } + Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); + +function exitApp() { + Bangle.setGPSPower(0, "app"); + Bangle.removeListener('GPS-raw', onGPSraw); + Bangle.removeListener('GPS', onGPS); + load(); +} + +setWatch(_=>exitApp(), BTN1); +if (global.BTN2) { + setWatch(_=>exitApp(), BTN2); + setWatch(_=>exitApp(), BTN3); +} From b2f844f32704d1863f18409f4da9898cef21f416 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:15:27 +0100 Subject: [PATCH 085/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebafa9c97..7e3d29cdc 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.06", + "version": "0.07", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From 97200f4ac566881ffa01b245c0da6cab61d08904 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:16:33 +0100 Subject: [PATCH 086/202] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 3ff284cb8..284ff7999 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -3,3 +3,4 @@ 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support 0.06: Added number of satellites in view and fixed crash with GPS time +0.07: Resolve one FIFO_FULL case and exit App with button press From f167ab829bf4f6fc1e78437cccbfadcfc984310a Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Wed, 5 Jan 2022 23:17:04 +0100 Subject: [PATCH 087/202] Update ChangeLog --- apps/gpsinfo/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 284ff7999..a3a2fc89a 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -2,5 +2,5 @@ 0.03: Show number of satellites while waiting for fix 0.04: Add Maidenhead readout of GPS location 0.05: Refactor to use 'layout' library for multi-device support -0.06: Added number of satellites in view and fixed crash with GPS time +0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press From c5f77a06926cabc0fe7c7be4d503bd9c0b0e79e1 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:31:21 +0000 Subject: [PATCH 088/202] Flipper: switch between light and dark theme and vice versa --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 07d9c02ae..e643d1c7d 100644 --- a/apps.json +++ b/apps.json @@ -5440,7 +5440,7 @@ "allow_emulator": true, "storage": [ {"name":"flipper.app.js","url":"flipper.app.js"}, - {"name":"flipper.img","url":"flipper.app-icon.js","evaluate":true} + {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] } ] From 4f4cb8aba5eae7542b1f8b5ae7990758592ffc45 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 22:36:45 +0000 Subject: [PATCH 089/202] Flipper: switch between light and dark theme and vice versa --- apps/flipper/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/flipper/ChangeLog diff --git a/apps/flipper/ChangeLog b/apps/flipper/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/flipper/ChangeLog @@ -0,0 +1 @@ +0.01: first release From 1a97767aa32e3c08fe6ee1e7b57be7b639aac5a5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:24:26 -0800 Subject: [PATCH 090/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index bd7f77cef..a52355909 100644 --- a/apps.json +++ b/apps.json @@ -5162,7 +5162,7 @@ { "id": "promenu", "name": "Pro Menu", - "version": "0.01", + "version": "0.02", "description": "Replace the built in menu function. Supports Bangle.js 1 and Bangle.js 2.", "icon": "icon.png", "type": "boot", From 3aada0243dbe45da9b43e38aa40f869a751863c3 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:25:39 -0800 Subject: [PATCH 091/202] Update ChangeLog --- apps/promenu/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 5560f00bc..8d214723c 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Add Bangle.js 2 Support! From 73e3378d25026ed7a268308f031aa8a081d170ba Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:29:05 -0800 Subject: [PATCH 092/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index a52355909..051764016 100644 --- a/apps.json +++ b/apps.json @@ -5171,7 +5171,7 @@ "screenshots": [{"url":"pro-menu-screenshot.png"}], "storage": [ {"name":"promenu.boot.js","url":"boot.js","supports": ["BANGLEJS"]}, - {"name":"promenu.bootb2.js","url":"boot.js","supports": ["BANGLEJS2"]}, + {"name":"promenu.boot.js","url":"bootb2.js","supports": ["BANGLEJS2"]}, {"name":"promenu.img","url":"promenuIcon.js","evaluate":true} ] }, From d54692117792802f2433922d3df61aac1361b65d Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:35:57 -0800 Subject: [PATCH 093/202] fix text overlapping text issue --- apps/promenu/bootb2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/bootb2.js b/apps/promenu/bootb2.js index 096745f34..c84e0d894 100644 --- a/apps/promenu/bootb2.js +++ b/apps/promenu/bootb2.js @@ -74,7 +74,7 @@ E.showMenu = function(items) { g.setFontAlign(-1,-1); var v = item.value; v = loc.translate(""+v); - if(loc.translate(name).length >= 19-v.length && "object" == typeof item){ + if(loc.translate(name).length >= 17-v.length && "object" == typeof item){ if (item.format) v=item.format(v); g.drawString(loc.translate(name).substring(0, 12-v.length)+"...",x+3.7,iy+2.7); }else{ From d330d6dfd568162eb4ca3dce1978e0963420a04f Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 5 Jan 2022 15:41:48 -0800 Subject: [PATCH 094/202] remove exclamation from change log --- apps/promenu/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/promenu/ChangeLog b/apps/promenu/ChangeLog index 8d214723c..b7287cc80 100644 --- a/apps/promenu/ChangeLog +++ b/apps/promenu/ChangeLog @@ -1,2 +1,2 @@ 0.01: New App! -0.02: Add Bangle.js 2 Support! +0.02: Add Bangle.js 2 Support From 84174a270b695e20f01fab6de5f37920f6422e24 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 5 Jan 2022 23:45:22 +0000 Subject: [PATCH 095/202] Flipper: added README --- apps.json | 2 ++ apps/flipper/README.md | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+) create mode 100644 apps/flipper/README.md diff --git a/apps.json b/apps.json index e643d1c7d..e9c4a9f6a 100644 --- a/apps.json +++ b/apps.json @@ -5433,6 +5433,8 @@ "name": "flipper", "version": "0.01", "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", + "readme":"README.md", + "screenshots": [{"url":"flipper.png"}], "icon": "flipper.png", "type": "app", "tags": "game", diff --git a/apps/flipper/README.md b/apps/flipper/README.md new file mode 100644 index 000000000..88025b8b2 --- /dev/null +++ b/apps/flipper/README.md @@ -0,0 +1,20 @@ +# Flipper + +![](flipper.png) + + *A utility to switch from the dark to the light theme and vice versa* + +* If the current theme is dark it will switch to the light theme +* If the current theme is light it will switch to the dark theme +* Combine with the awesome pattern launcher and it saves loads of time + + +## Demo Video + +There's no screenshot but there is a [demo video.](https://espruino.microco.sm/api/v1/files/9caa1afef7e4cce1d9b518af2dd271f1a57c5ecc.mp4) + +## Future Enhancements + +* Nothing left to add + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From d305de0bdc274c8c82a4a76556c506b9c6bfcff8 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 01:59:22 +0100 Subject: [PATCH 096/202] Update widget.js Increase screen update rate when charging, as requested by issue https://github.com/espruino/BangleApps/issues/1137 --- apps/widbatpc/widget.js | 59 ++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 28 deletions(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 5386ffe22..529923386 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -1,6 +1,9 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = {}; - + if (process.env.HWVERSION == 1) { COLORS = { 'white': -1, // White @@ -17,13 +20,13 @@ 'high': "#0f0", // Green 'ok': "#ff0", // Orange 'low': "#f00", // Red - }; + }; } - const SETTINGS_FILE = 'widbatpc.json' + const SETTINGS_FILE = 'widbatpc.json'; - let settings + let settings; function loadSettings() { - settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {} + settings = require('Storage').readJSON(SETTINGS_FILE, 1) || {}; const DEFAULTS = { 'color': 'By Level', 'percentage': true, @@ -32,17 +35,17 @@ 'alwaysoncharge': false, }; Object.keys(DEFAULTS).forEach(k=>{ - if (settings[k]===undefined) settings[k]=DEFAULTS[k] + if (settings[k]===undefined) settings[k]=DEFAULTS[k]; }); } function setting(key) { - if (!settings) { loadSettings() } + if (!settings) { loadSettings(); } return settings[key]; } const levelColor = (l) => { // "charging" is very bright -> percentage is hard to read, "high" is ok(ish) - const green = setting('percentage') ? COLORS.high : COLORS.charging + const green = setting('percentage') ? COLORS.high : COLORS.charging; switch (setting('color')) { case 'Monochrome': return COLORS.white; // no chance of reading the percentage here :-( case 'Green': return green; @@ -59,10 +62,11 @@ if (l >= 15) return COLORS.ok; return COLORS.low; } - } + }; const chargerColor = () => { - return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging - } + return (setting('color') === 'Monochrome') ? COLORS.white : COLORS.charging; + }; + // sets width, returns true if it changed function setWidth() { var w = 40; @@ -77,6 +81,7 @@ WIDGETS["batpc"].width = w; return changed; } + function draw() { // if hidden, don't draw if (!WIDGETS["batpc"].width) return; @@ -106,11 +111,11 @@ if (!setting('percentage')) { return; } - let gfx = g + let gfx = g; if (setting('color') === 'Monochrome') { // draw text inverted on battery level gfx = Graphics.createCallback(g.getWidth(),g.getHeight(), 1, - (x,y) => {g.setPixel(x,y,x<=xl?0:-1)}) + (x,y) => {g.setPixel(x,y,x<=xl?0:-1);}); } gfx.setFontAlign(-1,-1); if (l >= 100) { @@ -122,19 +127,24 @@ gfx.drawString(l, x + 6, y + 4); } } + // reload widget, e.g. when settings have changed function reload() { - loadSettings() + loadSettings(); // need to redraw all widgets, because changing the "charger" setting // can affect the width and mess with the whole widget layout - setWidth() + setWidth(); 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(); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } Bangle.on('charging',function(charging) { @@ -142,20 +152,13 @@ update(); g.flip(); }); - var batteryInterval; + Bangle.on('lcdPower', function(on) { - if (on) { - update(); - // refresh once a minute if LCD on - if (!batteryInterval) - batteryInterval = setInterval(update, 60000); - } else { - if (batteryInterval) { - clearInterval(batteryInterval); - batteryInterval = undefined; - } - } + if (on) update(); }); + + var id = setInterval(()=>WIDGETS["batpc"].draw(), intervalLow); + WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload}; setWidth(); -})() +})(); From d343de172ea4a4a8e8a7b35c1d61af1435ac957e Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:01:54 +0100 Subject: [PATCH 097/202] Update ChangeLog --- apps/widbatpc/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 273e611a4..e70093659 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -12,3 +12,4 @@ 0.13: Fillbar setting added, see README 0.14: Fix drawing the bar when charging 0.15: Added option to always display the icon when charging (useful if 'hide if charge greater than' is enabled) +0.16: Increase screen update rate when charging From 50ae67fcd7127d52ebc7d1eda834a02e91e44da2 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 02:03:30 +0100 Subject: [PATCH 098/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7e3d29cdc..e37326674 100644 --- a/apps.json +++ b/apps.json @@ -936,7 +936,7 @@ "id": "widbatpc", "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", - "version": "0.15", + "version": "0.16", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "icon": "widget.png", "type": "widget", From b9dcd0a8755dcbd463c45df3aa183f07dfc0c955 Mon Sep 17 00:00:00 2001 From: numerist Date: Wed, 5 Jan 2022 21:09:15 -0500 Subject: [PATCH 099/202] Update README.md This description now fits both Bangle watch versions, 1 and 2. --- apps/doztime/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/doztime/README.md b/apps/doztime/README.md index 075b2f66a..2f5b04780 100644 --- a/apps/doztime/README.md +++ b/apps/doztime/README.md @@ -11,4 +11,4 @@ The year itself begins on the December solstice. Because that always happens, th The epoch (year numbering) begins in the last year when the perihelion coincided with the June solstice, near the beginning of the Holocene era. That astronomical basis makes the calendar free from politics, religion, or geography. -While the year number remains cardinal, BTN5 toggles between cardinal and ordinal for the rest of the calendar segments. BTN4 adds or removes a quickly changing digit to or from the clock. +While the year number remains cardinal, tapping on the right side of the watch face toggles between cardinal and ordinal for the rest of the calendar segments. Tapping on the left adds or removes a quickly changing digit to or from the clock. From c2646e5b9f5fca7090c93cc0dbd3f17086b63231 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Wed, 5 Jan 2022 22:28:52 -0800 Subject: [PATCH 100/202] Update resourcer.js Improve character shapes. --- apps/pooqround/resourcer.js | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/apps/pooqround/resourcer.js b/apps/pooqround/resourcer.js index 44186e658..17c35a40d 100644 --- a/apps/pooqround/resourcer.js +++ b/apps/pooqround/resourcer.js @@ -1,6 +1,6 @@ // pooqRoman resource maker // -// Copyright (c) 2021 Stephen P Spackman +// Copyright (c) 2021, 2022 Stephen P Spackman // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -147,18 +147,18 @@ res += prepFont('y10', ` xxx xxx -2-------------------------------- - x xx + x xxx xx xxx xxxx xxx xxxxx xxx xxxxxxx xxx xxxx xxx xxx - xxxx xxxx xxx - xxxx xxxx xxx - xxxx xxxxxxxx xxxxxxx - xxxx xxxxxxxxxxxxxxxxxxx + xxxx xxxx xxxx + xxxx xxxxx xxxx + xxxx xxxxxxx xxxxxx + xxxx xxxxxxxxxxxxxxxxx xxxx xxxxxxxxxxxxxx -xxxx xxxxxxxxxx +xxxx xxxxxxxxx -3-------------------------------- xxx x xxx xxx xx xxx @@ -270,10 +270,10 @@ res += prepFont('y1', ` xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -1---------------------------------------------- xxx - xxx - xxx - xxx x - xxx x + xxx x + xxx xx + xxx xx + xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -282,18 +282,18 @@ res += prepFont('y1', ` xxx xxx -2---------------------------------------------- - x xx + x xxx xx xxx xxxx xxx - xxxxx xxx - xxxxxxx xxx - xxxx xxxx xxx - xxxx xxxxx xxx - xxxx xxxxxxx xxxx - xxxx xxxxxxxxxxxxx xxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - xxxx xxxxxxxxxxxxxxxxxxxxxxxxx -xxxx xxxxxxxxxxxxxx + xxxxxx xxx + xxxxxxxx xxx + xxxx xxxxx xxx + xxxx xxxxxx xxxx + xxxx xxxxxxxx xxxx + xxxx xxxxxxxxxxx xxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + xxxx xxxxxxxxxxxxxxxxxxxxxxxxx +xxxx xxxxxxxxxxxxxxxxx -3---------------------------------------------- xxx x xxx xxx xx xxx @@ -645,12 +645,12 @@ xxxx xxxx -1---------------------------------------------- -xxx x -xxx xx -xxx xxx -xxx xxx -xxx xxxx -xxx xxxx +xxx +xxx x +xxx xx +xxx xx +xxx xxx +xxx xxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx @@ -993,9 +993,9 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx xxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxxx - xxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxxx + xxxxxxxxxxxxxxxxxxx xxxx xxxx xxx From adc5ae007155c61a7bc1ba45c87df40f4ed5c03b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 09:03:35 +0000 Subject: [PATCH 101/202] fix issues with flipper pr --- apps/flipper/flipper.app.js | 2 +- apps/flipper/flipper.icon.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/flipper/flipper.app.js b/apps/flipper/flipper.app.js index 2e7d3551c..7171306b1 100644 --- a/apps/flipper/flipper.app.js +++ b/apps/flipper/flipper.app.js @@ -12,7 +12,7 @@ function upd(th) { g.reset = function(n) { return g._reset().setColor(th.fg).setBgColor(th.bg); }; g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; g.clear(1); -}; +} function flipTheme() { if (!g.theme.dark) { diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/flipper.icon.js index 16331c09e..494072c3c 100644 --- a/apps/flipper/flipper.icon.js +++ b/apps/flipper/flipper.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")); +require("heatshrink").decompress(atob("mEw4X/AAO/mMUzs975K+ggLKysUAYNVqoLFitUoAKBqtQBYkJBIQABqwLEgQLEqtABggJDqkVBaoNCBZQwEgILWgoJENYsVBIcVBYpDEgpSIBYMBKQg6CuogCBY1UgoLCXAQLDqAsDBYhSBqEJHAoLDoEBcQ4LBEwILIMooLdIg4LaVoyaGERLcFao4LIdRAACYYUQBY5RKAH4Ar")) From f6e374838fe654ec27133c2451863acf00e35721 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:01 +0100 Subject: [PATCH 102/202] Update ChangeLog --- apps/gpsinfo/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index a3a2fc89a..8d428ce85 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -4,3 +4,4 @@ 0.05: Refactor to use 'layout' library for multi-device support 0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press +0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway) From f59e97c5fc9eaf1e94a98edaffeec9bd0663782d Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:14 +0100 Subject: [PATCH 103/202] Update gps-info.js Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway). --- apps/gpsinfo/gps-info.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 467d12a95..fdac3d403 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -132,9 +132,6 @@ Bangle.on('GPS', onGPS); Bangle.on('GPS-raw', onGPSraw); function exitApp() { - Bangle.setGPSPower(0, "app"); - Bangle.removeListener('GPS-raw', onGPSraw); - Bangle.removeListener('GPS', onGPS); load(); } From 1df9b03a30aa8e8147ca1ec17b157202ea48ab7f Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 11:04:22 +0100 Subject: [PATCH 104/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e37326674..71fcb3ff8 100644 --- a/apps.json +++ b/apps.json @@ -1501,7 +1501,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.07", + "version": "0.08", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", From aba0d7126b26d1c24435cb89b2bfd24f4b07e581 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 11:08:46 +0100 Subject: [PATCH 105/202] Fix widget height --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index fb4635424..319e99809 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -41,7 +41,7 @@ const colorRed = '#ff0000'; const colorGreen = '#008000'; const colorBlue = '#0000ff'; const colorYellow = '#ffff00'; -const widgetOffset = showWidgets ? 14 : 0; +const widgetOffset = showWidgets ? 24 : 0; const h = g.getHeight() - widgetOffset; const w = g.getWidth(); const hOffset = 30 - widgetOffset; From 66294b3c8a7a0e5ee92c7eeab3ea346e44f314d9 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 11:17:27 +0100 Subject: [PATCH 106/202] Round step distance --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 319e99809..d9a8d8eae 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -175,7 +175,7 @@ function drawStepsDistance(w) { g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(shortValue(stepsDistance), w + 2, h3); + g.drawString(Math.round(shortValue(stepsDistance)), w + 2, h3); g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } From 33deb83a675b744599090325596ee015ea98d6f9 Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 6 Jan 2022 13:01:36 +0100 Subject: [PATCH 107/202] Fix rounding of step distance --- apps/circlesclock/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index d9a8d8eae..099217706 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -155,7 +155,7 @@ function drawStepsDistance(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); const stepDistance = settings.stepLength || 0.8; - const stepsDistance = steps * stepDistance; + const stepsDistance = Math.round(steps * stepDistance); g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -175,7 +175,7 @@ function drawStepsDistance(w) { g.setFont("Vector:12"); g.setFontAlign(0, 0); g.setColor(colorFg); - g.drawString(Math.round(shortValue(stepsDistance)), w + 2, h3); + g.drawString(shortValue(stepsDistance), w + 2, h3); g.drawImage(shoesIconGreen, w - 6, h3 + radiusOuter - 6); } From a9ea028ede2e9fad7e48b4364609c6aaa43f3481 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 12:13:21 +0000 Subject: [PATCH 108/202] fwupdate 0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later Add CRC checks for common bootloaders that we know don't work --- apps.json | 2 +- apps/fwupdate/ChangeLog | 2 ++ apps/fwupdate/custom.html | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 14 deletions(-) diff --git a/apps.json b/apps.json index 33836e05f..8fab1c96e 100644 --- a/apps.json +++ b/apps.json @@ -2,7 +2,7 @@ { "id": "fwupdate", "name": "Firmware Update", - "version": "0.02", + "version": "0.03", "description": "[BETA] Uploads new Espruino firmwares to Bangle.js 2. For now, please use the instructions under https://www.espruino.com/Bangle.js2#firmware-updates", "icon": "app.png", "type": "RAM", diff --git a/apps/fwupdate/ChangeLog b/apps/fwupdate/ChangeLog index 96e7e4e9b..458d695f0 100644 --- a/apps/fwupdate/ChangeLog +++ b/apps/fwupdate/ChangeLog @@ -2,3 +2,5 @@ 0.02: Add support for ZIPs Find and download ZIPs direct from the Espruino website Take 'beta' tag off +0.03: Improve bootloader update safety. Now sets unsafeFlash:1 to allow flash with 2v11 and later + Add CRC checks for common bootloaders that we know don't work diff --git a/apps/fwupdate/custom.html b/apps/fwupdate/custom.html index 8c2008e54..7a1e736e4 100644 --- a/apps/fwupdate/custom.html +++ b/apps/fwupdate/custom.html @@ -60,6 +60,7 @@ function onInit(device) { document.getElementById("fw-unknown").style = "display:none"; document.getElementById("fw-ok").style = ""; } + } function checkForFileOnServer() { @@ -264,6 +265,8 @@ function createJS_app(binary, startAddress, endAddress) { bin32[3] = VERSION; // VERSION! Use this to test ourselves console.log("CRC 0x"+bin32[2].toString(16)); hexJS = "";//`\x10if (E.CRC32(E.memoryArea(${startAddress},${endAddress-startAddress}))==${bin32[2]}) { print("FIRMWARE UP TO DATE!"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1339551013) { print("BOOTLOADER 2v10.219 needs update"); load();}\n`; + hexJS += `\x10if (E.CRC32(E.memoryArea(0xF7000,0x7000))==1207580954) { print("BOOTLOADER 2v10.236 needs update"); load();}\n`; hexJS += '\x10var s = require("Storage");\n'; hexJS += '\x10s.erase(".firmware");\n'; var CHUNKSIZE = 2048; @@ -291,20 +294,14 @@ function createJS_bootloader(binary, startAddress, endAddress) { var chunk = btoa(new Uint8Array(binary.buffer, binary.byteOffset+i, l)); hexJS += '\x10_fw.set(atob("'+chunk+'"), 0x'+(i).toString(16)+');\n'; } -// hexJS += `\x10(function() { -// if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC!"; -// var f = require("Flash"); -// for (var i=${startAddress};i<${endAddress};i+=4096) f.erasePage(i); -// f.write(_fw,${startAddress}); -// E.reboot(); -// })();\n`; - hexJS += `\x10if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; - hexJS += '\x10var f = require("Flash");\n'; + hexJS += `\x10(function() { if (E.CRC32(_fw)!=${crc}) throw "Invalid CRC: 0x"+E.CRC32(_fw).toString(16);\n`; + hexJS += 'E.showMessage("Flashing Bootloader...")\n'; + hexJS += 'E.setFlags({unsafeFlash:1})\n'; + hexJS += 'var f = require("Flash");\n'; for (var i=startAddress;i Date: Thu, 6 Jan 2022 15:15:58 +0100 Subject: [PATCH 109/202] Update ChangeLog --- apps/wid_a_battery_widget/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/ChangeLog b/apps/wid_a_battery_widget/ChangeLog index b04824ae8..8a1538479 100644 --- a/apps/wid_a_battery_widget/ChangeLog +++ b/apps/wid_a_battery_widget/ChangeLog @@ -1,3 +1,4 @@ 1.00: Release for Bangle 2 (2021/11/18) 1.01: Internal id update to wid_* as per Gordon's request (2021/11/21) -1.02: Support dark themes \ No newline at end of file +1.02: Support dark themes +1.03: Increase screen update rate when charging From ae27f50a476a4af463c4333a203ac2f118da2373 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:17:43 +0100 Subject: [PATCH 110/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 958bf71e9..2393e47c3 100644 --- a/apps.json +++ b/apps.json @@ -4477,7 +4477,7 @@ "name": "A Battery Widget (with percentage)", "shortName":"A Battery Widget", "icon": "widget.png", - "version":"1.02", + "version":"1.03", "type": "widget", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", From 5e7afb28273bdf6f72ad8ffae1a484b8016f63fe Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 15:18:45 +0100 Subject: [PATCH 111/202] Increase size of circles and fonts inside Updated screenshots --- apps.json | 2 +- apps/circlesclock/README.md | 5 +++-- apps/circlesclock/app.js | 19 ++++++++++--------- apps/circlesclock/screenshot-dark.png | Bin 0 -> 3857 bytes apps/circlesclock/screenshot-light.png | Bin 0 -> 3823 bytes apps/circlesclock/screenshot.png | Bin 3576 -> 0 bytes 6 files changed, 14 insertions(+), 12 deletions(-) create mode 100644 apps/circlesclock/screenshot-dark.png create mode 100644 apps/circlesclock/screenshot-light.png delete mode 100644 apps/circlesclock/screenshot.png diff --git a/apps.json b/apps.json index f1609bf4f..a2fd1ec9b 100644 --- a/apps.json +++ b/apps.json @@ -5078,7 +5078,7 @@ "version":"0.04", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}], "dependencies": {"widpedom":"app"}, "type": "clock", "tags": "clock", diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 86c388440..9004161d6 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -10,8 +10,9 @@ It can show the following information (this can be configured): * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) -## Screenshot -![Screenshot](screenshot.png) +## Screenshots +![Screenshot dark theme](screenshot-dark.png) +![Screenshot light theme](screenshot-light.png) ## TODO * Show weather information diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 099217706..ac7ae1b3f 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -47,12 +47,13 @@ const w = g.getWidth(); const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); -const h3 = Math.round(8 * h / 8 - hOffset); +const h3 = Math.round(8 * h / 8 - hOffset - 3); const w1 = Math.round(w / 6); const w2 = Math.round(3 * w / 6); const w3 = Math.round(5 * w / 6); -const radiusOuter = 22; -const radiusInner = 16; +const radiusOuter = 25; +const radiusInner = 18; +const circleFont = "Vector:15"; function draw() { g.clear(true); @@ -83,7 +84,7 @@ function draw() { g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8); // date & dow - g.setFont("Vector:20"); + g.setFont("Vector:21"); g.setFontAlign(-1, 0); g.drawString(locale.date(new Date()), w / 10, h2); g.drawString(locale.dow(new Date()), w / 10, h2 + 22); @@ -143,7 +144,7 @@ function drawSteps(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(shortValue(steps), w + 2, h3); @@ -172,7 +173,7 @@ function drawStepsDistance(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(shortValue(stepsDistance), w + 2, h3); @@ -196,7 +197,7 @@ function drawHeartRate(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); @@ -220,7 +221,7 @@ function drawBattery(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont("Vector:12"); + g.setFont(circleFont); g.setFontAlign(0, 0); let icon = powerIcon; @@ -259,7 +260,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = 4; + const size = radiusOuter - radiusInner - 2; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); diff --git a/apps/circlesclock/screenshot-dark.png b/apps/circlesclock/screenshot-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..00c0e3399cf9a1f4fbd299e259d245e7a9519db7 GIT binary patch literal 3857 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 F{TF;GBE$dy literal 0 HcmV?d00001 diff --git a/apps/circlesclock/screenshot-light.png b/apps/circlesclock/screenshot-light.png new file mode 100644 index 0000000000000000000000000000000000000000..af47b30a40681d7515efcf0658d43784a3e87b8d GIT binary patch literal 3823 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 From c7fef8134c24ea748d3c60e77e61b331db73bcd6 Mon Sep 17 00:00:00 2001 From: Hilmar Strauch <56518493+HilmarSt@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:20:09 +0100 Subject: [PATCH 112/202] Update widget.js Increase screen update rate when charging. --- apps/wid_a_battery_widget/widget.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/wid_a_battery_widget/widget.js b/apps/wid_a_battery_widget/widget.js index 8ab644ab3..74c76784d 100644 --- a/apps/wid_a_battery_widget/widget.js +++ b/apps/wid_a_battery_widget/widget.js @@ -1,4 +1,7 @@ (function(){ + const intervalLow = 60000; // update time when not charging + const intervalHigh = 2000; // update time when charging + let COLORS = { 'white': g.theme.dark ? "#000" : "#fff", 'black': g.theme.dark ? "#fff" : "#000", @@ -36,10 +39,14 @@ g.setFontAlign(0,0); g.setFont('6x8'); g.drawString(l, x + 14, y + 10); + + if (Bangle.isCharging()) changeInterval(id, intervalHigh); + else changeInterval(id, intervalLow); } + Bangle.on('charging',function(charging) { draw(); }); - setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), 60000); + var id = setInterval(()=>WIDGETS["wid_a_battery_widget"].draw(), intervalLow); WIDGETS["wid_a_battery_widget"]={area:"tr",width:30,draw:draw}; })(); From ba20a7b51eecc1452c7e5fb62b4964b5d7d875ad Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Thu, 6 Jan 2022 15:37:33 +0100 Subject: [PATCH 113/202] Center clock text & better placement for date texts --- apps/circlesclock/app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index ac7ae1b3f..b5ee61c75 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -79,15 +79,15 @@ function draw() { // time g.setFont("Vector:50"); - g.setFontAlign(-1, -1); + g.setFontAlign(0, -1); g.setColor(colorFg); - g.drawString(locale.time(new Date(), 1), w / 10, h1 + 8); + g.drawString(locale.time(new Date(), 1), w / 2, h1 + 8); // date & dow g.setFont("Vector:21"); g.setFontAlign(-1, 0); - g.drawString(locale.date(new Date()), w / 10, h2); - g.drawString(locale.dow(new Date()), w / 10, h2 + 22); + g.drawString(locale.date(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2); + g.drawString(locale.dow(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2 + 22); drawCircle(1, "steps"); drawCircle(2, "hr"); From fec507c926cef377dbbe95ac701e989328e23b41 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:24:31 +0100 Subject: [PATCH 114/202] Only show plotting of speed if Latitude is available --- apps/recorder/app.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/recorder/app.js b/apps/recorder/app.js index fcd8d6031..5b1c63aef 100644 --- a/apps/recorder/app.js +++ b/apps/recorder/app.js @@ -199,9 +199,10 @@ function viewTrack(filename, info) { menu['Plot Alt.'] = function() { plotGraph(info, "Altitude"); }; - menu['Plot Speed'] = function() { - plotGraph(info, "Speed"); - }; + if (info.fields.includes("Latitude")) + menu['Plot Speed'] = function() { + plotGraph(info, "Speed"); + }; // TODO: steps, heart rate? menu['Erase'] = function() { E.showPrompt("Delete Track?").then(function(v) { From f13aa4f94a40fc20346193c61b08aaada2ec34bf Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:26:57 +0100 Subject: [PATCH 115/202] Adds battery stats --- apps/recorder/widget.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 4d8cdddb1..b9d372ef8 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -82,7 +82,20 @@ draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) }; }, - + bat:function() { + return { + name : "BAT", + fields : ["Battery Percentage", "Battery Voltage", "Charging"], + getValues : () => { + return [E.getBattery(), NRF.getBattery(), Bangle.isCharging()]; + }, + start : () => { + }, + stop : () => { + }, + draw : (x,y) => g.setColor(Bangle.isCharging() ? "#0f0" : "#ff0").drawImage(atob("DAwBAABgH4G4EYG4H4H4H4GIH4AA"),x,y) + }; + }, temp:function() { var core = 0, skin = 0; var hasCore = false; From e60b27a5b01328a22c4cde0670d234f44516b9b4 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:27:24 +0100 Subject: [PATCH 116/202] Actually interpret the file content instead of the name --- apps/recorder/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index b9d372ef8..14e47a60e 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -151,7 +151,7 @@ } }) */ - require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(fn)(recorders)); + require("Storage").list(/^.*\.recorder\.js$/).forEach(fn=>eval(require("Storage").read(fn))(recorders)); return recorders; } From d1d478015ec74d36bc520890e4cc199d7b37a950 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 6 Jan 2022 17:04:24 +0000 Subject: [PATCH 117/202] widpedom 0.21: Memory usage improvements, fix widget initial width (fix #1170) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 53 +++++++++++++++++++---------------------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/apps.json b/apps.json index 8fab1c96e..c60bdbefc 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.20", + "version": "0.21", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index c033ea505..3483c3390 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -20,3 +20,4 @@ Fix issue with widget overwrite in large font mode Memory usage enhancements 0.20: Fix issue where step count would randomly reset +0.21: Memory usage improvements, fix widget initial width (fix #1170) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 0ec0780c9..3a079c066 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -1,5 +1,4 @@ (() => { - const PEDOMFILE = "wpedom.json" // Last time Bangle.on('step' was called let lastUpdate = new Date(); // Last step count when Bangle.on('step' was called @@ -8,19 +7,14 @@ let settings; function loadSettings() { - const d = require('Storage').readJSON(PEDOMFILE, 1) || {}; - settings = d.settings || {}; - } - - function setting(key) { - if (!settings) { loadSettings() } - const DEFAULTS = { + const d = require('Storage').readJSON("wpedom.json", 1) || {}; + settings = Object.assign({ 'goal': 10000, 'progress': false, 'large': false, 'hide': false - } - return (key in settings) ? settings[key] : DEFAULTS[key]; + }, d.settings || {}); + return d; } Bangle.on('step', stepCount => { @@ -31,10 +25,10 @@ if (lastUpdate.getDate() == date.getDate()){ stp_today += steps; } else { - // TODO: could save this to PEDOMFILE for lastUpdate's day? + // TODO: could save this to "wpedom.json" for lastUpdate's day? stp_today = steps; } - if (stp_today === setting('goal') + if (stp_today === settings.goal && !(require('Storage').readJSON('setting.json',1)||{}).quiet) { let b = 3, buzz = () => { if (b--) Bangle.buzz().then(() => setTimeout(buzz, 100)) @@ -51,29 +45,31 @@ }); // When unloading, save state E.on('kill', () => { - if (!settings) { loadSettings() } - let d = { + require("Storage").writeJSON("wpedom.json",{ lastUpdate : lastUpdate.valueOf(), stepsToday : stp_today, settings : settings, - }; - require("Storage").write(PEDOMFILE,d); + }); }); // add your widget - WIDGETS["wpedom"]={area:"tl",width:26, - redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); + WIDGETS["wpedom"]={area:"tl",width:0, + getWidth:function() { let newWidth = 24; - if (setting('hide')) + if (settings.hide) newWidth = 0; else { - if (setting('large')) { + if (settings.large) { newWidth = 12 * stps.length + 3; - if (setting('progress')) + if (settings.progress) newWidth += 24; } } + return newWidth; + }, + redraw:function() { // work out the width, and queue a full redraw if needed + let stps = stp_today.toString(); + let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets this.width = newWidth; @@ -84,14 +80,14 @@ } }, draw:function() { - if (setting('hide')) return; + if (settings.hide) return; if (stp_today > 99999) stp_today = stp_today % 100000; // cap to five digits + comma = 6 characters let stps = stp_today.toString(); g.reset().clearRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background - if (setting('progress')) { + if (settings.progress) { const width = 23, half = 11; - const goal = setting('goal'), left = Math.max(goal-stps,0); + const goal = settings.goal, left = Math.max(goal-stps,0); // blue or dark green g.setColor(left ? "#08f" : "#080").fillCircle(this.x + half, this.y + half, half); if (left) { @@ -113,10 +109,10 @@ } g.reset(); } - if (setting('large')) { + if (settings.large) { g.setFont("6x8",2); g.setFontAlign(-1, 0); - g.drawString(stps, this.x + (setting('progress')?28:4), this.y + 12); + g.drawString(stps, this.x + (settings.progress?28:4), this.y + 12); } else { let w = 24; if (stps.length > 3){ @@ -137,11 +133,12 @@ getSteps:()=>stp_today }; // Load data at startup - let pedomData = require("Storage").readJSON(PEDOMFILE,1); + let pedomData = loadSettings(); if (pedomData) { if (pedomData.lastUpdate) lastUpdate = new Date(pedomData.lastUpdate); stp_today = pedomData.stepsToday|0; delete pedomData; } + WIDGETS["wpedom"].width = WIDGETS["wpedom"].getWidth(); })() From c8126f5ce4302c85ddbda9bb4f5993dda72e0d3d Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:04:41 +0100 Subject: [PATCH 118/202] Changed icons and colors for better visibility --- apps/recorder/widget.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 14e47a60e..34a6ca488 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -48,7 +48,7 @@ Bangle.removeListener('GPS', onGPS); Bangle.setGPSPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasFix?"#0ff":"#888").drawImage(atob("DAyBAAACADgDuBOAeA4AzAHADgAAAA=="),x,y) + draw : (x,y) => g.setColor(hasFix?"#0f0":"#f88").drawImage(atob("DAwBEAKARAKQE4DwHkPqPRGKAEAA"),x,y) }; }, hrm:function() { @@ -79,7 +79,7 @@ Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#888").drawImage(atob("DAyBAAAAAD/H/n/n/j/D/B+AYAAAAA=="),x,y) + draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { @@ -119,7 +119,7 @@ hasCore = false; Bangle.removeListener('CoreTemp', onCore); }, - draw : (x,y) => g.setColor(hasCore?"#0f0":"#888").drawImage(atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),x,y) + draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAwBAAAOAKPOfgZgZgZgZgfgPAAA"),x,y) }; }, steps:function() { @@ -134,7 +134,7 @@ }, start : () => { lastSteps = Bangle.getStepCount(); }, stop : () => {}, - draw : (x,y) => g.reset().drawImage(atob("DAyBAAADDHnnnnnnnnnnjDmDnDnAAA=="),x,y) + draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y) }; } // TODO: recAltitude from pressure sensor From 2c2141c9ec6beef3590c4082399e5dafe5421d53 Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:20:14 +0200 Subject: [PATCH 119/202] Initial version of Ruuvi Watch Added Ruuvi Watch, an app to watch the status of RuuviTags in range. --- apps.json | 13 +++ apps/ruuviwatch/ChangeLog | 1 + apps/ruuviwatch/README.md | 25 +++++ apps/ruuviwatch/ruuviwatch.app-icon.js | 1 + apps/ruuviwatch/ruuviwatch.app.js | 150 +++++++++++++++++++++++++ apps/ruuviwatch/ruuviwatch.png | Bin 0 -> 692 bytes 6 files changed, 190 insertions(+) create mode 100644 apps/ruuviwatch/ChangeLog create mode 100644 apps/ruuviwatch/README.md create mode 100644 apps/ruuviwatch/ruuviwatch.app-icon.js create mode 100644 apps/ruuviwatch/ruuviwatch.app.js create mode 100644 apps/ruuviwatch/ruuviwatch.png diff --git a/apps.json b/apps.json index 833c3505e..15654f26a 100644 --- a/apps.json +++ b/apps.json @@ -5448,5 +5448,18 @@ {"name":"flipper.app.js","url":"flipper.app.js"}, {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] + }, + { "id": "ruuviwatch", + "name": "Ruuvi Watch", + "shortName":"Ruuvi Watch", + "icon": "ruuviwatch.png", + "version":"1.00", + "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", + "readme":"README.md", + "tags": "bluetooth", + "storage": [ + {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, + {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} + ] } ] diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog new file mode 100644 index 000000000..8a8ec68d5 --- /dev/null +++ b/apps/ruuviwatch/ChangeLog @@ -0,0 +1 @@ +1.00: Hello Ruuvi Watch! \ No newline at end of file diff --git a/apps/ruuviwatch/README.md b/apps/ruuviwatch/README.md new file mode 100644 index 000000000..bf4358267 --- /dev/null +++ b/apps/ruuviwatch/README.md @@ -0,0 +1,25 @@ +# Ruuvi Watch + +Watch the status of [RuuviTags](https://ruuvi.com) in range. + + - Id + - Temperature (°C) + - Humidity (%) + - Pressure (hPa) + - Battery voltage + + Also shows how "fresh" the data is (age of reading). + + ## Usage + + - Scans for devices when launched and every N seconds. + - Page trough devices with BTN1/BTN3. + - Trigger scan with BTN2. + +## Todo / ideas + + - Allow to "name" known devices + - Prevent flicker when updating + - Include more data + - Support older Ruuvi protocols + diff --git a/apps/ruuviwatch/ruuviwatch.app-icon.js b/apps/ruuviwatch/ruuviwatch.app-icon.js new file mode 100644 index 000000000..7ed27ef6c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/ABMP/4ACCyIVDAAXwCyoYPIggAFCx4oEDBw/JJJguCBhAwLBZYjKBQQeGCIYNHB45bIBw4gIRgw+NC4wwJJ5YRLC5DzFCJBGMEYoSEFxoMEBQIXEF4gVFF5QcEC553JC5QRITgy/NVxIXGf5QlFIwy4IGBQuFC5JhGCwpGGERZOEBQ4MEDAwJJGAzdJCxLVJFxoYLCxoYICx6/GCqAA/AH4A/ACA")) \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js new file mode 100644 index 000000000..9f5e03b4c --- /dev/null +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -0,0 +1,150 @@ +require("Storage").write("ruuviwatch.info",{ + "id":"ruuviwatch", + "name":"Ruuvi Watch", + "src":"ruuviwatch.app.js", + "icon":"ruuviwatch.img" + }); + + const lookup = {}; + const ruuvis = []; + let current = 0; + + function int2Hex (str) { + return ('0' + str.toString(16).toUpperCase()).slice(-2); + } + + function p(data) { + const OFFSET = 7; // 0-4 header, 5-6 Ruuvi id + const robject = {}; + robject.version = data[OFFSET]; + + let temperature = (data[OFFSET+1] << 8) | (data[OFFSET+2] & 0xff); + if (temperature > 32767) { + temperature -= 65534; + } + robject.temperature = temperature / 200.0; + + robject.humidity = (((data[OFFSET+3] & 0xff) << 8) | (data[OFFSET+4] & 0xff)) / 400.0; + robject.pressure = ((((data[OFFSET+5] & 0xff) << 8) | (data[OFFSET+6] & 0xff)) + 50000) / 100.0; + + let accelerationX = (data[OFFSET+7] << 8) | (data[OFFSET+8] & 0xff); + if (accelerationX > 32767) accelerationX -= 65536; // two's complement + robject.accelerationX = accelerationX / 1000.0; + + let accelerationY = (data[OFFSET+9] << 8) | (data[OFFSET+10] & 0xff); + if (accelerationY > 32767) accelerationY -= 65536; // two's complement + robject.accelerationY = accelerationY / 1000.0; + + let accelerationZ = (data[OFFSET+11] << 8) | (data[OFFSET+12] & 0xff); + if (accelerationZ > 32767) accelerationZ -= 65536; // two's complement + robject.accelerationZ = accelerationZ / 1000.0; + + const powerInfo = ((data[OFFSET+13] & 0xff) << 8) | (data[OFFSET+14] & 0xff); + robject.battery = ((powerInfo >>> 5) + 1600) / 1000.0; + robject.txPower = (powerInfo & 0b11111) * 2 - 40; + robject.movementCounter = data[OFFSET+15] & 0xff; + robject.measurementSequenceNumber = ((data[OFFSET+16] & 0xff) << 8) | (data[OFFSET+17] & 0xff); + + robject.mac = [ + int2Hex(data[OFFSET+18]), + int2Hex(data[OFFSET+19]), + int2Hex(data[OFFSET+20]), + int2Hex(data[OFFSET+21]), + int2Hex(data[OFFSET+22]), + int2Hex(data[OFFSET+23]) + ].join(':'); + + robject.name = "Ruuvi " + int2Hex(data[OFFSET+22]) + int2Hex(data[OFFSET+23]); + return robject; + } + + function getAge(created) { + const now = new Date().getTime(); + const ago = ((now - created) / 1000).toFixed(0); + return ago > 0 ? ago + "s ago" : "now"; + } + + function redraw() { + if (ruuvis.length > 0 && ruuvis[current]) { + const ruuvi = ruuvis[current]; + g.clear(); + g.setFontAlign(0,0); + g.setFont("Vector",12); + g.drawString(" (" + (current+1) + "/" + ruuvis.length + ")", g.getWidth()/2, 10); + g.setFont("Vector",20); + g.drawString(ruuvi.name, g.getWidth()/2, 30); + g.setFont("Vector",12); + const age = getAge(ruuvi.time); + if(age > (5*60)) { + g.setColor("#ff0000"); + } else if (age > 60) { + g.setColor("#f39c12"); + } else { + g.setColor("#2ecc71"); + } + g.drawString(age, g.getWidth()/2, 50); + g.setColor("#ffffff"); + g.setFont("Vector",60); + g.drawString(ruuvi.temperature.toFixed(2) + "°c", g.getWidth()/2, g.getHeight()/2); + g.setFontAlign(0,1); + g.setFont("Vector",20); + g.drawString(ruuvi.humidity + "% " + ruuvi.pressure + "hPa ", g.getWidth()/2, g.getHeight()-30); + g.setFont("Vector",12); + g.drawString(ruuvi.battery + "v", g.getWidth()/2, g.getHeight()-10); + } else { + g.clear(); + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + g.setFontAlign(0,0); + g.setFont("Vector",16); + g.drawString("Looking for Ruuvi...", g.getWidth()/2, g.getHeight()/2 + 50); + } + } + + function scan() { + NRF.findDevices(function(devices) { + let foundNew = false; + devices.forEach(device => { + const data = p(device.data); + data.time = new Date().getTime(); + const idx = lookup[data.name]; + if (idx !== undefined) { + ruuvis[idx] = data; + } else { + lookup[data.name] = ruuvis.push(data)-1; + foundNew = true; + } + }); + redraw(); + if (foundNew) { + Bangle.buzz(); + g.flip(); + } + + }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); + } + + g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); + + var drawInterval = setInterval(redraw, 1000); + var scanInterval = setInterval(scan, 10000); + setWatch(() => { + current--; + if (current < 0) { + current = ruuvis.length-1; + } + redraw(); + }, BTN1, {repeat:true}); + + setWatch(() => { + scan(); + }, BTN2, {repeat:true}); + + setWatch(() => { + current++; + if (current >= ruuvis.length) { + current = 0; + } + redraw(); + }, BTN3, {repeat:true}); + + scan(); \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png new file mode 100644 index 0000000000000000000000000000000000000000..3a5d0954952c77bbe18348240ff7313dcc1e8915 GIT binary patch literal 692 zcmV;l0!#ggP)!VNEuuo9P$>Ll4zvRRj_#*&Ry+IU%mlmf9PGcdKZnENFMS7G;?`N`?20^m``($M zufPX(Heet6Pwj{cc2*`f1=EhsnLZNCRUab>49*^$RhZYr(%**v$3&+M?M(=NjU;X} z^?WfNBb}&eFGAHg#@xgiZ4(maIMG%h&-adY#Obv{ob~HMNZwDQ-wI#5sH`8Y9+CO& zb-_>5{E=`@jgWk$^f!>XfLY|huL3`%8qyMiFDo%2b9X?TG13VxzOH!S7nQp5cREL; zxkUUc@I^eP0&`ni_LhcuK5MWMjhboylpD0A6+qq^mvjjoZg)CKjYoBF<3W4qnG|}1 z%7+oRqy+Pvw}@X8SQOe;<%9RbK9B-zM4|t*a2chBCq_Sc5<)-UImU$cnek~Tqqm+q z5v0R<`iO3w)Bfh<=km00ik<^t=4b{+(3H*rLn#F3E8_Q!S+)4+#xJ z9|`1j!BujC{-kc{vq1b=B$okS{KWW(b#J5Mu9U+ruhX88jOumT*+2I}{X&I8p-?FN abY20-1jwJ!GdeE-0000 Date: Thu, 6 Jan 2022 21:27:40 +0200 Subject: [PATCH 120/202] Add "supports" for Ruuvi Watch Add the "supports" section to apps.json for Ruuvi Watch. --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 15654f26a..f86d3bcf8 100644 --- a/apps.json +++ b/apps.json @@ -5457,6 +5457,7 @@ "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", + "supports": ["BANGLEJS"], "storage": [ {"name":"ruuviwatch.app.js","url":"ruuviwatch.app.js"}, {"name":"ruuviwatch.img","url":"ruuviwatch.app-icon.js","evaluate":true} From 3558049233e1ecc75b477ccc7cfef588fc9b50f8 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Thu, 6 Jan 2022 20:35:28 +0100 Subject: [PATCH 121/202] Update README.md --- apps/mmind/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index 0623459f7..ea584b7e7 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -1,6 +1,6 @@ # Mastermind -Play the classic mind game mastermind on your Bangles 2. +Play the classic mind game mastermind on your Bangle 2. ![](screenshot_mmind.png) From 28bb2f73e0d9293c717f080889d7f8f946c2ebae Mon Sep 17 00:00:00 2001 From: Marc Englund Date: Thu, 6 Jan 2022 21:42:43 +0200 Subject: [PATCH 122/202] Visual fixes Make apploader logo black. Clear gfx before drawing logo on startup. --- apps.json | 2 +- apps/ruuviwatch/ChangeLog | 3 ++- apps/ruuviwatch/ruuviwatch.app.js | 1 + apps/ruuviwatch/ruuviwatch.png | Bin 692 -> 665 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index f86d3bcf8..6761dd47e 100644 --- a/apps.json +++ b/apps.json @@ -5453,7 +5453,7 @@ "name": "Ruuvi Watch", "shortName":"Ruuvi Watch", "icon": "ruuviwatch.png", - "version":"1.00", + "version":"1.01", "description": "Keep an eye on RuuviTag devices (https://ruuvi.com). Only shows RuuviTags using the v5 format.", "readme":"README.md", "tags": "bluetooth", diff --git a/apps/ruuviwatch/ChangeLog b/apps/ruuviwatch/ChangeLog index 8a8ec68d5..ebde871fa 100644 --- a/apps/ruuviwatch/ChangeLog +++ b/apps/ruuviwatch/ChangeLog @@ -1 +1,2 @@ -1.00: Hello Ruuvi Watch! \ No newline at end of file +1.00: Hello Ruuvi Watch! +1.01: Clear gfx on startup. \ No newline at end of file diff --git a/apps/ruuviwatch/ruuviwatch.app.js b/apps/ruuviwatch/ruuviwatch.app.js index 9f5e03b4c..46218a323 100644 --- a/apps/ruuviwatch/ruuviwatch.app.js +++ b/apps/ruuviwatch/ruuviwatch.app.js @@ -123,6 +123,7 @@ require("Storage").write("ruuviwatch.info",{ }, {timeout : 2000, filters : [{ manufacturerData:{0x0499:{}} }] }); } + g.clear(); g.drawImage(require("Storage").read("ruuviwatch.img"), g.getWidth()/2-24, g.getHeight()/2-24); var drawInterval = setInterval(redraw, 1000); diff --git a/apps/ruuviwatch/ruuviwatch.png b/apps/ruuviwatch/ruuviwatch.png index 3a5d0954952c77bbe18348240ff7313dcc1e8915..3737a7e8cb955bc7747861ed1eba36682f99885e 100644 GIT binary patch delta 590 zcmV-U0TLBDAveCk^&%HVS#^jDn$zM7sUQo?^paMm!hfAnRwqvYoz)hXvrrKB zy8qqh!{AQU(BL!K^}olUtd8IpvBr#SnTcE`HKw6(37GP~!wgi6^8@Ck#vRTD6};O< z8-cCHb!J_)8u<732J|*fszeDo_?6IJfj_8w(1#qoe`-sWh(O^s6Di%n*D_s2iir8e z$y2z^KuqQb3V($A{@!E10-eMnH1Uy`D5a%sAiKP@$H$r&-y(9-8fj4bIHjA_h&a^a z8?r?j4P?O&+ag3KwTUV3n4%x=`%K^zLQ8GTXix_kUlSFg#cc;8*%8hwgfU1D{uJv9ct&i1iuJLB@Up2FPY$LOrU0hs5~|bmrs)46)}C_ znz7k4^VFDu9phYls61%!TW^+sWCLyw8t|=9Ar1}xS>}xCe^p5o{Fj!?VJRR910 delta 617 zcmV-v0+#)m1+)c_R)0xJL_t(|0qvOWZR0QuhM5gAf;Kphpb@-*Z-Zuoc!PKYcZ1#r zz72dgfxAJv!CMJd(7+`n%6311>H&!Si1?DCJ}sg`p-?FNWDc|g0FLgba#lP0<;(=T z@f_^Gvp4rj?S4r63kT} zBMA)79-LK}*TmA_hX2Pzrw#2*2!4$uZZq|KF&-nGsA(@k)i}o7#2IZ966QG3Rv^#! zj&{W9wL+Zr>q1E0Pov)oU%RNRAFUpd`R#SVPt*L7a88Yoe5Ld^khy?aXmWFvgYp@ZGnrZ)( z8?>brK;9acbO{}9cRERpM|E%GL3`+#6ncZohY`1=1oND?h+h*}6xvqhgZINekOFK( zq5rgS8Ks6NMn8EHLO9aumStOSMU;M=Q zh;?tH;;xj#F0a#`kc{ee+Sxz%Lj6L8LZMJ7{B&Lc$OOor(K9+P00000NkvXXu0mjf Dtw1bu From 32fb5dc58e272b88810dc58236e003b9eada25d4 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 21:39:23 +0000 Subject: [PATCH 123/202] Limelight: configurable analogue clock --- apps.json | 15 ++ apps/limelight/ChangeLog | 1 + apps/limelight/README.md | 11 ++ apps/limelight/limelight.app.js | 187 ++++++++++++++++++++++++ apps/limelight/limelight.icon.js | 1 + apps/limelight/limelight.png | Bin 0 -> 929 bytes apps/limelight/limelight.settings.js | 67 +++++++++ apps/limelight/screenshot_limelight.png | Bin 0 -> 2180 bytes 8 files changed, 282 insertions(+) create mode 100644 apps/limelight/ChangeLog create mode 100644 apps/limelight/README.md create mode 100644 apps/limelight/limelight.app.js create mode 100644 apps/limelight/limelight.icon.js create mode 100644 apps/limelight/limelight.png create mode 100644 apps/limelight/limelight.settings.js create mode 100644 apps/limelight/screenshot_limelight.png diff --git a/apps.json b/apps.json index 833c3505e..c4d7624be 100644 --- a/apps.json +++ b/apps.json @@ -5448,5 +5448,20 @@ {"name":"flipper.app.js","url":"flipper.app.js"}, {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} ] + }, + { + "id": "limelight", + "name": "Limelight Clock", + "version": "0.01", + "description": " Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "icon": "limelight.png", + "screenshots": [{"url":"screenshot_limelight.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS","BANGLEJS2"], + "storage": [ + {"name":"limelight.app.js","url":"app.js"}, + {"name":"limelight.img","url":"icon.js","evaluate":true} + ] } ] diff --git a/apps/limelight/ChangeLog b/apps/limelight/ChangeLog new file mode 100644 index 000000000..9db0e26c5 --- /dev/null +++ b/apps/limelight/ChangeLog @@ -0,0 +1 @@ +0.01: first release diff --git a/apps/limelight/README.md b/apps/limelight/README.md new file mode 100644 index 000000000..7d80ed985 --- /dev/null +++ b/apps/limelight/README.md @@ -0,0 +1,11 @@ +# Limelight + * Simple configurable analogie clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + +![](screenshot_limelight.jpg) + +* Selection of different fonts +* 100 less lines of code, demonstrating that there is no need for a custom widget draw method + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS +Forum](http://forum.espruino.com/microcosms/1424/) + diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js new file mode 100644 index 000000000..a1af79466 --- /dev/null +++ b/apps/limelight/limelight.app.js @@ -0,0 +1,187 @@ +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// fonts.google.com +Graphics.prototype.setFontLimelight = function(scale) { + // Actual height 28 (28 - 1) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAeAAAAAD8AAAAAf4AAAAB/gAAAAH+AAAAAf4AAAAB/gAAAAD8AAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAPwAAAAH8AAAAD+AAAAD+AAAAB/AAAAA/gAAAAfwAAAAD4AAAAAMAAAAAAAAAAAAAAAAAAAAA/gAAAA//wAAAP//wAAB///wAAP///gAA///+AAH///8AAf///4AD////gAP///+AA////4AD////gAMAAAGAAwAAAYADAAABgAMAAAGAAwAAAwABgAADAAHAAAYAAOAADgAAeAA8AAAfh/AAAAf/wAAAAHgAAAAAAAAAAGAAAAAAYAAAAABAAAAAAMAAAAAAwAAAAAD///+AAf///4AB////gAH///+AAf///4AD////gAP///+AA////4AH////gAf///+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgABAAAeAAOAAH4AAwAA/gAGAAP+AAYAB/4ADAAf/gAMAD/+AAwAf/4ADAH//gAMA//+AAwH//4ADB//9gAOP//GAA///wYAD//+BgAH//gGAAf/8AYAA//ABgAB/4AGAAD+AAYAADAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAHAAAwAAGAAHAAAMAAYAAAwADAEABgAMAwAGAAwDAAYADAMABgAMAwAGAAwDAAYAD////gAP///+AA////4AD////gAP///8AAf///wAB/7//AAD/H/4AAP4f/AAAPA/4AAAAA+AAAAAAAAAAAAAAAAAAAGAAAAAB8AAAAAPwAAAADzAAAAAcMAAAAHgwAAAA8DAAAAHAMAAAB4AwAAAOADAAADwAMAAAcAAwAAD///+AA////4AD////gAP///+AA////4AD////gAP///+AA////4AD////gAP///+AAAAAMAAAAAAwAAAAADAAAAAAcAAAAAAgAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAHAAAH4AOAAP/gAcAA+GAAwADAwABgAMDAAGAAwMAAYADAwABgAMDAAGAAwMAAYADA///gAMD//+AAwP//4ADA///AAMB//8AAwH//wADAP/+AAIAf/wAAAA/+AAAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAD/8AAAA//8AAAH//4AAB///wAAH///gAA////AAH///8AAf///4AD////gAP///+AAwAAAYADAYABgAMBgAGAAwGAAYADAYABgAMBgAGAAwGAAwABgYADAAHAwAYAAMDgHAAAAHh4AAAAP/AAAAAHgAAAAAAAAAAAAAAAA+AAAAAD4AAAAAMAAAAAAwAAAAADAAAAAAMAA/+AAwB//4ADB///gAM///+AA////4AD////gAP///+AA////4AD////gAP///+AA////4AD//+AAAP/wAAAA/wAAAAD4AAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHwAAA/g/wAAH/GDgAA/+wGAAD//AMAAf/4AwAB//gBgAP//AGAAx/+AYADD/4BgAMH/wGAAwP/AYACA/+BgAMB/8GAAwD/wYADAP/jgAMBf/+AAYH//wABgz//AADHH/4AAH4f/gAAOA/8AAAAB/AAAAAAwAAAAAAAAAAAAAAAAAeAAAAAH/AAAAB8eAAAAGAcBgAAwAwHAAGABgMAAYAGAYADAAIBgAMAAwGAAwADAYADAAYBgAMAAgGAAwAAAYAD////gAP///+AA////wAB////AAH///4AAP///AAA///8AAA///AAAB//4AAAB/+AAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfAeAAAD8D8AAAf4f4AAB/h/gAAH+H+AAAf4f4AAB/h/gAAD8D8AAAHgHgAAAAAAAAAAAAAAA="), 46, atob("DQ0aExgZHRkbGBsbDQ=="), 40+(scale<<8)+(1<<16)); +} + +// fonts.google.com +Graphics.prototype.setFontGochiHand = function(scale) { + // Actual height 29 (31 - 3) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAB4AAAAAD4AAAAAB4AAAAAB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAH/gAAAD//gAAD///gAD///+AAH///AAAH//gAAAH/wAAAAHwAAAAAAAAwAAAAAP+AAAAA//gAAAB//wAAAD//4AAAD8P4AAAHwD8AAAHgB8AAAPgA8AAAPAA8AAAPAA8AAAPAA8AAAPgA8AAAPgA8AAAPgB8AAAHwB4AAAH4D4AAAD+PwAAAD//gAAAB//gAAAA/+AAAAAP8AAAAAAAAAAAAAAAAAAAcAAAAAA8AAAAAB8AAAAAD4AAAAAD4AAAAAHwAAAAAHgAAAAAPgAAAAAPgAAAAAf/AAAAAf//wAAAP//wAAAH//wAAAAf/wAAAAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAA8AAAeAB8AAA+AD8AAB+AH8AAB4AP8AAD4AP8AADwAf8AADwB+8AAD4D88AAD4H48AAD//w+AAB//g+AAB//A+AAA/8A+AAAPwA+AAAAAA+AAAAAAcAAAAAAIAAAAAAAAAA8AAAAAB8AAAAAB8AAAAAB4AHgAAD4AHwAAD4AH4AADwPH8AADwfB8AADwfA8AAD4fA+AAD4fA+AAB//A+AAB//A+AAA//A8AAA//x8AAAPP/8AAAAH/4AAAAD/wAAAAB/gAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAH8AAAAAP+AAAAA/+AAAAB/+AAAAD8+AAAAP4+AAAB/weAAAD/weAAAD/8eAAAB///AAAA///AAAAH//8AAAAf//AAAAD//AAAAAf/AAAAAf+AAAAAfAAAAAAMAAAAAAAAAAAAAAAAAAPA/gAAAfh/wAAA/x/4AAA/x/4AAB/4/8AAB74B8AAB58A8AAB58A+AAB5+A+AAB4+A+AAB4+A+AAB4fA+AAB4fg+AAB4Pg8AAB4P58AAB4H/4AAB4D/4AAB4D/wAAAQA/gAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAB/+AAAAD//gAAAH//gAAAPwfwAAAPgf4AAAfAf4AAAeA/8AAAeA98AAAeA88AAAfB48AAAfB48AAAPB48AAAOB48AAAAB98AAAAB/8AAAAA/4AAAAA/wAAAAAfgAAA8AAAAAA8BAAAAA8HgAAAA8HgAAAA8HgAAAA8HgAAAA8HgAAAA+HgAAAA+HgAAAA+HgAAAAfHgAAAAf//+AAAf//+AAAP//+AAAH//8AAAAPwAAAAAHgAAAAAHwAAAAAHwAAAAAHwAAAAADwAAAAADgAAAAAAAAAAAAAAAAAAAB/AAAAP3/wAAAf//wAAA///4AAA//D8AAB9+B8AAB4+A8AAB4+A+AAB4+A+AAB4+A+AAB8+A+AAB8+A+AAA/+A8AAA//A8AAAf/x8AAAP//4AAAH//wAAAAD/gAAAAB/AAAAAAAAAAAAAAAAAAD/AAAAAD/gAAAAH/gAAAAP/wAAAAPHwAAAAPDwAAAAeDwAAAAeDwAAAAeDwAAAAeHwAAAAeHgAAAAePgAAAAefAAAAAf/AAAAAf///gAAf///wAAP///wAAP///gAAH8AAAAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8BwAAAA8B4AAAA+D4AAAA8B4AAAAcB4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DQoYERUWFBYVFhcVDQ=="), 42+(scale<<8)+(1<<16)); +} + +// free for commercial use +// https://www.1001fonts.com/search.html?search=Grenadier+NF +Graphics.prototype.setFontGrenadierNF = function(scale) { + // Actual height 39 (39 - 1) + g.setFontCustom(atob("AAAAAAAAAAAAB4AAAAAAPAAAAAAB4AAAAAAAAAAAAAAAAAAAAAAEAAAAAAPgAAAAA/8AAAAB//gAAAD//4AAAP//wAAAf//AAAB//+AAAD//8AAAB//wAAAAP/gAAAAB+AAAAAAMAAAAAAAAAAAAAAAAB4AAAAAD/8AAAAB//4AAAA///wAAAP8D/AAAD8AD8AAA/AAPwAAPgAAfAAD4AAB8AAeAAAHgAHwAAA+AA8AAADwAHgAAAeAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APAAAAPAB4AAAB4APgAAAfAA8AAADwAHwAAA+AAeAAAHgAD4AAB8AAPgAAfAAA+AAHwAAD8AD8AAAP8D/AAAA///wAAAD//8AAAAH/+AAAAAD8AAAAAAAAAAAAAAAAAAABAAAAAAAcAAAAAAHwAAAAAB8AAAAAAfgAAAAAH/////AB/////4AP/////AB/////4AAAAAAAAAAAAAAAAAAAAADAAAAAAA4APAAAAPAB4AAAD4APAAAA/AB4AAAP4APAAAD/AB8AAA/4AHgAAPvAA8AAD54ADwAB+PAAfAAfh4AB8AH4PAAPwD+B4AA///gPAAD//wB4AAH/4APAAAP8AAAAAAAAAAAAAAAAAAAPAAAAHAB4AAAB4APAAAAPAB4PAAB4APB4AAPAB+/gAB4AH/8AAfAAf/wADwAB/fAA+AABD8APgAAAPwH4AAAA//+AAAAD//gAAAAH/4AAAAAP8AAAAAAAAAAAAAAAAAAAAAAYAAAAAAPAAAAAAH4AAAAAD/AAAAAB/4AAAAA//AAAAAf94AAAAH+PAAAAD/B4AAAB/gPAAAA/wB4AAAf8APAAAP////4AH/////AD/////4AAAAAPAAAAAAA4AAAAAAAAAAAAAAAAAAAIAAPAAAPAAB4AAf4AAPAA//gAB4AP/8AAPAB/3gAB4APg8AAfAB4DwADwAPAfAA+AB4B8APgAPAP4H4AB4A//+AAPAB//gAB4AH/4AAAAAP8AAAAAAAAAAAAAB4AAAAAD/4AAAAA//wAAAAf//AAAAP+H8AAAH+AHwAAB/gAfAAA/4AB4AAf+AAPAAP/wAA8AH+eAAHgB/ngAA8APw8AAHgB4HgAA8AMA8AAHgAADwAA8AAAeAAPgAAD4AB4AAAPgAfAAAA+AHwAAAH4D8AAAAf//AAAAB//wAAAAD/8AAAAAH8AAAAAAAAAAAAAAAAAAAAAAAYAAAAAAfAB4AAAP4APAAAH/AB4AAH/gAPAAD/wAB4AD/wAAPAB/4AAB4A/8AAAPA/8AAAB4f+AAAAPP+AAAAB//AAAAAP/gAAAAB/gAAAAAPwAAAAAB4AAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAD/gAAAAB//AAAAAf/+AAAAH//4AAAB+AfgAA+fAB8AAP/wAHwAD/+AAeAA//gAB4APj8AAPAB4PAAB4APB4AAPAB4PAAB4APB4AAPAB8fgAB4AH/8AAPAAf/wADwAB/eAA+AADj4APgAAAPwD8AAAA///AAAAD//wAAAAP/4AAAAAf8AAAAAAAAAAAB4AAAAAB/4AAAAA//wAAAAP//AAAAD+H8AAAA/AHwAAAHgAfAAAB8AB4AAAPAAHgAADwAA8AAAeAAHgBADwAAeA4AeAADwfADwAAeP4AeAAD3+ADwAA9/gAfAAH/wAB4AB/4AAPgAf8AAA+AH+AAAD8B/gAAAP//wAAAA//4AAAAD/8AAAAAD+AAAAAAAAAAAAAAAAAAAAAAAeB4AAAADwPAAAAAeB4AAAAAAAAAAAAAAAA=="), 46, atob("Bg4kChURExEaFBoaBg=="), 45+(scale<<8)+(1<<16)); +} + +// fonts.google.com +Graphics.prototype.setFontMonoton = function(scale) { + // Actual height 38 (37 - 0) + g.setFontCustom(atob("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"), 46, atob("ChIiERcYGRwfGSAfCw=="), 40+(scale<<8)+(1<<16)); +} + +function loadSettings() { + settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; + settings.secondhand = settings.secondhand||false; + settings.font = settings.font||"Limelight"; + settings.vector = settings.vector||false; + settings.vector_size = settings.vector_size||42; + UPDATE_PERIOD = (settings.secondhand ? 1000 : 60000); +} + +var UPDATE_PERIOD; +var drawTimeout; + +const CenterX = g.getWidth()/2; +const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); +const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; + +function debug(o) { + //console.log(o); +} + +debug("limelight.app.js"); +debug("CenterX=" + CenterX); +debug("CenterY=" + CenterY); +debug("outerRadius=" + outerRadius); +debug("y12=" + (CenterY - outerRadius)); +debug("y6=" + (CenterY + outerRadius)); + +const HourHandLength = outerRadius * 0.5; +const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; +const MinuteHandLength = outerRadius * 0.7; +const MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; +const SecondHandLength = outerRadius * 0.9; +const SecondHandOffset = 6; + +const twoPi = 2*Math.PI; +const Pi = Math.PI; +const halfPi = Math.PI/2; + +let HourHandPolygon = [ + -halfHourHandWidth,halfHourHandWidth, + -halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth, +]; + +let MinuteHandPolygon = [ + -halfMinuteHandWidth,halfMinuteHandWidth, + -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth, +]; + +let transformedPolygon = new Array(HourHandPolygon.length); + +function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { + let sPhi = Math.sin(Phi), cPhi = Math.cos(Phi), x,y; + + for (let i = 0, l = originalPolygon.length; i < l; i+=2) { + x = originalPolygon[i]; + y = originalPolygon[i+1]; + + transformedPolygon[i] = OriginX + x*cPhi + y*sPhi; + transformedPolygon[i+1] = OriginY + x*sPhi - y*cPhi; + } +} + +function setHandsFont() { + if (settings.vector) { + g.setFont('Vector', settings.vector_size); + return; + } + + if (settings.font == "GochiHand") + g.setFontGochiHand(); + else if (settings.font == "Grenadier") + g.setFontCabinSketch(); + else if (settings.font == "Monoton") + g.setFontMonoton(); + else + g.setFontLimelight(); +} + +function drawNumbers() { + g.setColor(g.theme.fg); + setNumbersFont(); + + g.setFontAlign(0,-1); + g.drawString('12', CenterX, CenterY - outerRadius); + + g.setFontAlign(1,0); + g.drawString('3', CenterX + outerRadius, CenterY); + + g.setFontAlign(0,1); + g.drawString('6', CenterX, CenterY + outerRadius); + + g.setFontAlign(-1,0); + g.drawString('9', CenterX - outerRadius,CenterY); +} + +function drawHands () { + let now = new Date(); + let Hours = now.getHours() % 12; + let Minutes = now.getMinutes(); + let Seconds = now.getSeconds(); + + let HoursAngle = (Hours+(Minutes/60))/12 * twoPi - Pi; + let MinutesAngle = (Minutes/60) * twoPi - Pi; + let SecondsAngle = (Seconds/60) * twoPi - Pi; + + g.setColor(g.theme.fg); + transformPolygon(HourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + transformPolygon(MinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + + if (settings.secondhand) { + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + g.setColor('#FF0000'); + g.drawLine( + CenterX + SecondHandOffset*sPhi, + CenterY - SecondHandOffset*cPhi, + CenterX - SecondHandLength*sPhi, + CenterY + SecondHandLength*cPhi + ); + } +} + +function draw() { + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + drawHands(); + drawNumbers(); + queueDraw(); +} + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, UPDATE_PERIOD - (Date.now() % UPDATE_PERIOD)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +loadSettings(); +Bangle.setUI('clock'); +draw(); diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js new file mode 100644 index 000000000..06f93e2ef --- /dev/null +++ b/apps/limelight/limelight.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) diff --git a/apps/limelight/limelight.png b/apps/limelight/limelight.png new file mode 100644 index 0000000000000000000000000000000000000000..cf057046be6eca51564a213bc3e7307271464009 GIT binary patch literal 929 zcmV;S177@zP)hL^4Q9~j~`7LX9JB(!Q` zf!g{&{RcFW&Q~mny+EQd5wRkG(GU|*v#i00#krWf=gz{s+-Te{nPTqF`ObG{=bo84 z7wV|v|Hht3JPkk}FaUG|9Y7m!Ao=|p@Bx?yW`SwoCGazne{UQEt^-TJmSbB2t^w^e zR}HiRcY*JgVs~m~;0|!8R^p4mY6RiBtpaENr0^Uv>(vCT0r!Cspcg0r`;t~jo{azx zfb|`CCKF##(F8oL;_xjnl#FrV8%ADg6Xz30z8#UnEWQMc5jI;nU_9Z{{Eq{QD8L7t!&STXpy9ZFm@kj^1Fem7{l-O!eBYr8>b)d^b3W}9W~#A6U*g95Oi>^=c4 z)~Zv`8K;EXvhfK3pp)!7am&FTkR7(HNX8sFd;lS+^%_N}!U1DH{Ly|K9>B#6_hueBM`PvzgXPMrIx>vGBiU)6Z4 zEpn3sb9fkCLB-z-YcKpmwJ#|r9RWl zC5~dFfRx^~zcZo4lLpcS%$dU%U1Vo|3%C)3JcraOHF*iC9^?bK^S~v{rNu|U-T>|j zG$FN0?PUAC7)9=|wrEE3yiS#A@zILA+sGlcN|VDaIFIb+1>`8+h@2|>kwB-& z?yx%JM4NdN29eBAO@MFvNQ4*G7A;7*Pj7ZUZ3CJ0gS8T$MjKKwTeK9b&o&dl(GUSK zKeKitb( font_options[v], + onchange: v => { + s.font = font_options[v]; + save(); + }, + }, + 'Vector Font': { + value: s.vector, + format: () => (s.vector ? 'Yes' : 'No'), + onchange: () => { + s.vector = !s.vector; + save(); + }, + }, + 'Vector Size': { + value: settings.vector_size, + min: 24, + max: 56, + step: 6, + onchange: v => { + settings.vector_size = v; + save(); + } + }, + 'Second Hand': { + value: s.secondhand, + format: () => (s.secondhand ? 'Yes' : 'No'), + onchange: () => { + s.secondhand = !s.secondhand; + save(); + }, + } + }); +}) diff --git a/apps/limelight/screenshot_limelight.png b/apps/limelight/screenshot_limelight.png new file mode 100644 index 0000000000000000000000000000000000000000..9affc3d1cbb9be291270cb57cd1474e03b685ea3 GIT binary patch literal 2180 zcmeHJ`!m~#7LSNFq7QG4TD79mCYD=m?;?bf2t`|^K}kwI(xOFMA!V(vUOPogqtPx) zwBp$kY0?!DtKZ#A>(yv(SCxupNUsVNgnHLaXZH8|2i$vR&iR}<^O^a~oSE~PlXvO_ zX(z%Q0f9hv`uY$~YmoOf;oCH|S*W0DK?8cLOw|IFED~c|;Q4-U9~) zer&36Ls`wW^pT=>0|PeRk*>q{zySHX*^Cw=)L&!OKwFX}`itSpWNT98-xPg%uxZ<5 zs4MIF3-B+3s;8nnb6!6g&&Cpa+netS1h0@1+9x^o^0CFRvPq};>_>>_ZU z^1+0+VpY!T_nuaB-G<4tc0hj`xNIi=Nb0$X6B|dI`!*XiiH{KIX!W3AIF)I_YHC0? zbzFaCdNd5rTTD0tqjs>*4Q6j_N5VJGd`Wap>^nK$QqHQy7kg+re6g|DC0~!VyRF}$ zs~d`J@2uK8Z5(?}GCJSdq&tTthCA$jc@WOi#vUksati`=@H!c#qXi?MvWZ4&!Kgp6 z|3E!L|0sk!f72+0wg`jAzle+B=E23oV;>ea@8C&%B^1r0nM8 zj{NDAH%t<8(mwMdaQM{Y0)|fDd%PJ!m6*RfW70f=EWgz*_4EDvM7(22ZUfb9eyW$U z2A9r5)rc5$JIRf7+o#yyL0S+xWI+-2!RS5HBLL3q0QT~c1e>I5oBgs!cZ)U+tc$FNDaHL27xA$IjEyF>+Y?g%2qrelFW z)-KN!oDW9fX!kErM5lo?mQdZY$Crc0_b!XFyvOaOZC7HUMSr{mgLPl&o*d*@qtD*h zp|&SeM6aQwR~T{j`9lKXSbx={^{M`XH>fh9-&5}BK>!ts>t6RQ(hr-b#gvLZH$LNz z^1%@1@?ITwspu=E7(^|23ma#+j#sJZ_R$xT8^kK&-M~u%3G#-?Xy%yPt0R-FC6w=o6mQcEU8hw(~o#iq-) zJkx57KP%jg`l*f|i5M$sOGL3tkeoy^VTuV2W8b>0M{SpgGTak# zL6mh`f#X`vq!PUZKg5%iBebwuu$J-KpUWW7$9cuH{n;RS)Hq1v-A4l#8e#fx^M5%X zuQ4p!#XN#^;Ro4;+U8O|1uO zZL`7nDn*!vVe);~pBkGBV7dNZ?0;vCD`qy|{M+>()y}q>w*ulzJVD@kM&|qnB+=s~ literal 0 HcmV?d00001 From e5dad4094be9e05a723850bafdad2c19548b1623 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 21:58:44 +0000 Subject: [PATCH 124/202] fixed apps.json for limelight --- apps.json | 4 ++-- apps/limelight/README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index c4d7624be..98ce3e5d5 100644 --- a/apps.json +++ b/apps.json @@ -5460,8 +5460,8 @@ "tags": "clock", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"limelight.app.js","url":"app.js"}, - {"name":"limelight.img","url":"icon.js","evaluate":true} + {"name":"limelight.app.js","url":"limelight.app.js"}, + {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } ] diff --git a/apps/limelight/README.md b/apps/limelight/README.md index 7d80ed985..aa0c359b9 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,5 +1,5 @@ # Limelight - * Simple configurable analogie clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* ![](screenshot_limelight.jpg) From 59c7cb49d6d33cb87a95d85440105faf64532698 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 22:10:56 +0000 Subject: [PATCH 125/202] limelight fixed apps.json, added settings file --- apps.json | 1 + apps/limelight/limelight.app.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/apps.json b/apps.json index 98ce3e5d5..64b5c358e 100644 --- a/apps.json +++ b/apps.json @@ -5461,6 +5461,7 @@ "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"limelight.app.js","url":"limelight.app.js"}, + {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index a1af79466..f17114f2d 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -27,6 +27,8 @@ Graphics.prototype.setFontMonoton = function(scale) { g.setFontCustom(atob("AAAAAAAAAAEkAAAAAbYAAAABtgAAAAG2AAAAAbYAAAABtgAAAAG2AAAAASQAAAAAAAAAAAAAAAAAAAB4AAAAB/gAAAB/gAAAB/h4AAB/h/AAB/h/CAB/h/D4B/h/D/B/j/D/APj/D/AAD/D/AAB/D/AAAPD/AAAAD/AAAAB/AAAAAPAAAAAAAAAAAAAAAAAAAAAD/wAAAB//4AAAfAD4AAHj/x4AA5//5wAHfAB5gAzj/5zAHc//5mAbvDBzcDdz/zmwNu+HzZhs3ADu2G2YAHbYbbAANthtsAA2yG2wABtsbbAAG2xtsAA2yG2wADbYbZgAdthm3ADs2DZv/92wM3P/O7AbvAD3YB3P/87gDvP/HMAHPgD7gAOP/+cAAfH+HgAAfgH4AAAf/+AAAAD+AAAAAAAAAAAAAAAAbYAAAABtgAAAAG2AAAAAbYAAAABt////wG3////AbYAAAABt////wG3////AbYAAAABt////wG3////AbYAAAABt////wEn///+AAAAAAAAAAAAAADQAAAUgdoAAF7BtsAA3sG2wAOewbbAB17BtsAc3sG2wDnewbbAdx7BtsHO3sG2w7newbbPd57Btv3OXsGzc73ewZuPc57A2f3nHsDMc5wewG8POB7Ac/zgHsA4Y8AewB+fABSAB/wAAAAAAAAAAAAAAAAA0AAAAsHbAAAbYbbAANthtsAA22G2wADbYbbJJNthts22W2G2zbZpIbbNtm2xts22bbG2zbZJIbbNttthtv2322Gzfbu7YNuO3HZg3f7P5sDuf2OMwGeHPHmAO/2f8wAccOOOAA/PfvwAA/4f8AAAAAAAAAAAAAAAAABkgAAAA/bAAAAPtsAAAD52wAAA8fbAAAfH9sAAHz42wAB8+fbAAePn9sADjx82wAJ8ePbAAfPj9sADz482wAI+fDbAAfHwNsADx8A2wAM+D/b+APgP9v4D4AA2wAMAD/b+AAAP9v4AAAA2wAAAADSAAAAAAAAAAAAAAAAAAAAMAaf/8AwBt//wJgG2AAA3Abf/8JsBt//w2wG2AABtgbf/822BtgADbYG2NvNtgbY28SSBtjbxtsG2NvG2gbY28SSBtjbzbYG2Nv9tgbY23m2BtjNg2YG2Gz+bAbYZnzcBtgzg5gG2Dn/MASQHHzgAAAPg8AAAAP/gAAAAHwAAAAAAAAAAAAAAAAA//4AAAf//8AAHgAB4AA4//44AGf//5wAzgAB7AGY//52AbP//7MDZwABmwNu//zZhs3//m2G25LTbYbbN7Nthts3sSSG2zexpIbbN7G2xts3sSaG2zezbYbbN7Nthts3v22GbDbezYNsG+HbA3Qbf7sBsB3edgGQDPHuAMAGf9wAQAOOOAAAAfvwAAAAf8AAAAAAAAAAAAAABtgAAAAG2AAAAAbYAAAABtgAAAAG2AAAAAbYAAAMBtgAAPwG2AAP8AbYAf4cBtgf4fwG0f4f4Aaf4f4cAf4f4fwH4f4f4AYf4f4cA/4/w/wHw/w/wAQ/w/wAA/w/wAAHw/wAAAQ/wAAAA/wAAAAHwAAAAAAAAAAAAAAAAAAAA+AfAAAf/P/gADwPwHgA5/OfnAHP+f/OAZwO4HYDM+d/MwNn+3/bBuwZsM2G2e2+bYbb7b9thtskk2yG2zbZtobbNtm2xts22bbG2zbZtsbbNtm2xts22bbG2zbZNsbbNttshtv2322GzfZu7YNuO3HZg3f7v5sBud3OcwHfPvHmAOf3P8wAcAeAOAAf///wAA/4f8AAAAAAAAAAAAAAAAfwAAAAH/wAAAA4DwAIAGfzgAwAz/3AJgGYDsA2AzP2YDsDZz9g2wNszbDNhs3ns22G2zezbYbbN5NthtsTkSSG2xORtMbbE5G2xts3sySG2zezbYbbN7Nths2ABm2Cbf/+3YNmf/nbAzeAB7MBuf/+dgHcP/DuAO///9wAc///OAA8AADwAA///8AAA///AAAAAAAAAAAAAAAAAAAAAAA2xtgAADbG2AAANsbYAAA2xtgAADbG2AAANsbYAAAkhJAAAAAAAAAAAAAAAA"), 46, atob("ChIiERcYGRwfGSAfCw=="), 40+(scale<<8)+(1<<16)); } +const SETTINGS_FILE = "limelight.json"; + function loadSettings() { settings = require("Storage").readJSON(SETTINGS_FILE,1)||{}; settings.secondhand = settings.secondhand||false; From 33a10e53932fa730c0493a93d6e7c7f08511ed99 Mon Sep 17 00:00:00 2001 From: "Dirk Hillbrecht (home)" Date: Thu, 6 Jan 2022 22:58:12 +0100 Subject: [PATCH 126/202] ptlaunch: Improve documentation --- apps/ptlaunch/README.md | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index cf75315a9..12c205980 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -2,11 +2,19 @@ Directly launch apps from the clock screen with custom patterns. -## Usage +## Installation and Usage + +Install Pattern Launcher alongside your main laucher app. +_Do not delete that launcher!_ +Pattern Launcher is designed as an additional app launching utility, not as a replacement for the main launcher. + +In the main launcher, start Pattern Launcher in the app menu to assign the pattern configuration (see below). +Note that this actually among the applications, _not_ in the application settings! Create patterns and link them to apps in the Pattern Launcher app. Then launch the linked apps directly from the clock screen by simply drawing the desired pattern. +Note that this does only work in the clock screen, not if other applications run. ## Add Pattern Screenshots @@ -28,7 +36,8 @@ Then launch the linked apps directly from the clock screen by simply drawing the ## Detailed Steps -From the main menu you can: +The main menu of Pattern Launcher is accessible from the _application_ starter of the main launcher. +From there you can: - Add a new pattern and link it to an app (first entry) - To create a new pattern first select "Add Pattern" @@ -60,6 +69,16 @@ Make sure the watch is unlocked before you start drawing. If this bothers you, y Please note that drawing on the clock screen will not visually show the pattern you drew. It will start the app as soon as the pattern was recognized - this might take 1 or 2 seconds! If still nothing happens, that might be a bug, sorry! +4. Where can I configure the patterns? + +You have to start the "Pattern Launcher" app from the main app launcher's app selection. + +5. Do I have to delete my former app launcher so that Pattern Launcher is the only installed launcher? + +No! Pattern Launcher works alongside another "main" launcher. +If you have deleted that one, you do not have a general purpose app launcher any more and cannot access Pattern Launcher's configuration. +If you already have deleted your main launcher accidentially, just reinstall it from the app loader. + ## Authors Initial creation: [crazysaem](https://github.com/crazysaem) @@ -67,3 +86,5 @@ Initial creation: [crazysaem](https://github.com/crazysaem) Improve pattern detection code readability: [PaddeK](http://forum.espruino.com/profiles/117930/) Improve pattern rendering: [HughB](http://forum.espruino.com/profiles/167235/) + +Doc additions: [dirkhillbrecht](http://forum.espruino.com/profiles/182498/) From cc7cbd24e1a7de0115fb87bb9250cc449865109c Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 22:18:46 +0000 Subject: [PATCH 127/202] limelight fixes --- apps/limelight/limelight.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index f17114f2d..c4a599c96 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -95,7 +95,7 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function setHandsFont() { +function setNumbersFont() { if (settings.vector) { g.setFont('Vector', settings.vector_size); return; From bce36e9afc5e8e68ac508c11436bfe7c160020dd Mon Sep 17 00:00:00 2001 From: hughbarney Date: Thu, 6 Jan 2022 23:29:38 +0000 Subject: [PATCH 128/202] limelight fixes --- apps.json | 2 +- apps/limelight/limelight.app.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 64b5c358e..3e63507c7 100644 --- a/apps.json +++ b/apps.json @@ -5453,7 +5453,7 @@ "id": "limelight", "name": "Limelight Clock", "version": "0.01", - "description": " Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", "screenshots": [{"url":"screenshot_limelight.png"}], "type": "clock", diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index c4a599c96..af4a99a38 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -46,7 +46,7 @@ const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; function debug(o) { - //console.log(o); + console.log(o); } debug("limelight.app.js"); @@ -55,6 +55,7 @@ debug("CenterY=" + CenterY); debug("outerRadius=" + outerRadius); debug("y12=" + (CenterY - outerRadius)); debug("y6=" + (CenterY + outerRadius)); +debug("appRect=" + Bangle.appRect); const HourHandLength = outerRadius * 0.5; const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; From a31b22d3fbad98d3b325fc7f46e4a1c8bfd5f292 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 00:38:15 +0000 Subject: [PATCH 129/202] limelight sorted icon and png --- apps/limelight/limelight.app.js | 42 +++++++++++++++++---------- apps/limelight/limelight.icon.js | 2 +- apps/limelight/limelight.png | Bin 929 -> 318 bytes apps/limelight/limelight.settings.js | 6 ++-- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index af4a99a38..f41b050d1 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -41,6 +41,16 @@ function loadSettings() { var UPDATE_PERIOD; var drawTimeout; + +/* + * This calculation assumes that there will never be widgets on the + * bottom but it could just as easily be adjusted. If only 1 widget + * is loaded at the top Bangle.appRect changes to report as if + * widgets were loaded at the bottom as well. The other option would + * be for Bangle.appRect to adjust for different combinations EG: no + * widgets, wigets on top, widgets on bottom and widgets on top and + * bottom areas. + */ const CenterX = g.getWidth()/2; const CenterY = (g.getHeight()/2) + (Bangle.appRect.y/2); const outerRadius = (g.getHeight() - Bangle.appRect.y)/2; @@ -96,22 +106,6 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function setNumbersFont() { - if (settings.vector) { - g.setFont('Vector', settings.vector_size); - return; - } - - if (settings.font == "GochiHand") - g.setFontGochiHand(); - else if (settings.font == "Grenadier") - g.setFontCabinSketch(); - else if (settings.font == "Monoton") - g.setFontMonoton(); - else - g.setFontLimelight(); -} - function drawNumbers() { g.setColor(g.theme.fg); setNumbersFont(); @@ -157,6 +151,22 @@ function drawHands () { } } +function setNumbersFont() { + if (settings.vector) { + g.setFont('Vector', settings.vector_size); + return; + } + + if (settings.font == "GochiHand") + g.setFontGochiHand(); + else if (settings.font == "Grenadier") + g.setFontGrenadierNF(); + else if (settings.font == "Monoton") + g.setFontMonoton(); + else + g.setFontLimelight(); +} + function draw() { g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js index 06f93e2ef..9e886bbf8 100644 --- a/apps/limelight/limelight.icon.js +++ b/apps/limelight/limelight.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwIdah/wAof//4ECgYFB4AFBg4FB8AFBj/wh/4AoM/wEB/gFBvwCEBAU/AQP4gfAj8AgPwAoMPwED8AFBg/AAYIBDA4ngg4TB4EBApkPKgJSBJQIFTMgIFCJIIFDKoIFEvgFBGoMAnw7DP4IFEh+BAoItBg+DNIQwBMIaeCKoKxCPoIzCEgKVHUIqtFXIrFFaIrdFdIwAV")) +require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")); diff --git a/apps/limelight/limelight.png b/apps/limelight/limelight.png index cf057046be6eca51564a213bc3e7307271464009..b1744b28eab888dc537519f74401e020471b0b7e 100644 GIT binary patch literal 318 zcmV-E0m1%>P)Px#_(?=TR9Hvtn9&M=APhz4|9`Y$B#4yV%`Fpd&#{ij>(r8nWZCFR1P-1p8V(jL zG`x-Bobm3MQkhuWGaU&HXpd+Cp8{@SpFWNZNCWNyJo@0TfRPj;z@-jqdCD+>0RuGL zOF}Y?=J(8c^zrfySOe=0{06st<7ffCfOR)~x5!5W(Z*ppa2=oqeEFi&LKE21hc%Xe zV;DUE5txza445KOHv^=9qB|f`%e--H3yiF6#4u{tY`DhChL^4Q9~j~`7LX9JB(!Q` zf!g{&{RcFW&Q~mny+EQd5wRkG(GU|*v#i00#krWf=gz{s+-Te{nPTqF`ObG{=bo84 z7wV|v|Hht3JPkk}FaUG|9Y7m!Ao=|p@Bx?yW`SwoCGazne{UQEt^-TJmSbB2t^w^e zR}HiRcY*JgVs~m~;0|!8R^p4mY6RiBtpaENr0^Uv>(vCT0r!Cspcg0r`;t~jo{azx zfb|`CCKF##(F8oL;_xjnl#FrV8%ADg6Xz30z8#UnEWQMc5jI;nU_9Z{{Eq{QD8L7t!&STXpy9ZFm@kj^1Fem7{l-O!eBYr8>b)d^b3W}9W~#A6U*g95Oi>^=c4 z)~Zv`8K;EXvhfK3pp)!7am&FTkR7(HNX8sFd;lS+^%_N}!U1DH{Ly|K9>B#6_hueBM`PvzgXPMrIx>vGBiU)6Z4 zEpn3sb9fkCLB-z-YcKpmwJ#|r9RWl zC5~dFfRx^~zcZo4lLpcS%$dU%U1Vo|3%C)3JcraOHF*iC9^?bK^S~v{rNu|U-T>|j zG$FN0?PUAC7)9=|wrEE3yiS#A@zILA+sGlcN|VDaIFIb+1>`8+h@2|>kwB-& z?yx%JM4NdN29eBAO@MFvNQ4*G7A;7*Pj7ZUZ3CJ0gS8T$MjKKwTeK9b&o&dl(GUSK zKeKitb( { - settings.vector_size = v; + s.vector_size = v; save(); } }, From 32a1d048770859131aadb4b34fb58ed37ff61b89 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:00:22 +0000 Subject: [PATCH 130/202] Limelight - screenshots --- apps/limelight/README.md | 11 +++++++++-- apps/limelight/screenshot_gochihand.png | Bin 0 -> 2332 bytes apps/limelight/screenshot_grenadier.png | Bin 0 -> 2376 bytes apps/limelight/screenshot_limelight.png | Bin 2180 -> 2425 bytes apps/limelight/screenshot_monoton.png | Bin 0 -> 3032 bytes 5 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 apps/limelight/screenshot_gochihand.png create mode 100644 apps/limelight/screenshot_grenadier.png create mode 100644 apps/limelight/screenshot_monoton.png diff --git a/apps/limelight/README.md b/apps/limelight/README.md index aa0c359b9..f1cc52092 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,11 +1,18 @@ # Limelight * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* -![](screenshot_limelight.jpg) +![](screenshot_limelight.png) * Selection of different fonts +* Settings menu where you can select font, or switch to Vector font and try a range of sizes * 100 less lines of code, demonstrating that there is no need for a custom widget draw method -Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS +![](screenshot_gochihand.png) +![](screenshot_monoton.png) +![](screenshot_grenadier.png) + +Many thanks for @Andreas_Rozek for his pioneering work on building a toolkit for the Bangle 2. + +Limelight Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/limelight/screenshot_gochihand.png b/apps/limelight/screenshot_gochihand.png new file mode 100644 index 0000000000000000000000000000000000000000..af405c0f8406505893cedcbac16da25ea1e27804 GIT binary patch literal 2332 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 BY>NN@ literal 2180 zcmeHJ`!m~#7LSNFq7QG4TD79mCYD=m?;?bf2t`|^K}kwI(xOFMA!V(vUOPogqtPx) zwBp$kY0?!DtKZ#A>(yv(SCxupNUsVNgnHLaXZH8|2i$vR&iR}<^O^a~oSE~PlXvO_ zX(z%Q0f9hv`uY$~YmoOf;oCH|S*W0DK?8cLOw|IFED~c|;Q4-U9~) zer&36Ls`wW^pT=>0|PeRk*>q{zySHX*^Cw=)L&!OKwFX}`itSpWNT98-xPg%uxZ<5 zs4MIF3-B+3s;8nnb6!6g&&Cpa+netS1h0@1+9x^o^0CFRvPq};>_>>_ZU z^1+0+VpY!T_nuaB-G<4tc0hj`xNIi=Nb0$X6B|dI`!*XiiH{KIX!W3AIF)I_YHC0? zbzFaCdNd5rTTD0tqjs>*4Q6j_N5VJGd`Wap>^nK$QqHQy7kg+re6g|DC0~!VyRF}$ zs~d`J@2uK8Z5(?}GCJSdq&tTthCA$jc@WOi#vUksati`=@H!c#qXi?MvWZ4&!Kgp6 z|3E!L|0sk!f72+0wg`jAzle+B=E23oV;>ea@8C&%B^1r0nM8 zj{NDAH%t<8(mwMdaQM{Y0)|fDd%PJ!m6*RfW70f=EWgz*_4EDvM7(22ZUfb9eyW$U z2A9r5)rc5$JIRf7+o#yyL0S+xWI+-2!RS5HBLL3q0QT~c1e>I5oBgs!cZ)U+tc$FNDaHL27xA$IjEyF>+Y?g%2qrelFW z)-KN!oDW9fX!kErM5lo?mQdZY$Crc0_b!XFyvOaOZC7HUMSr{mgLPl&o*d*@qtD*h zp|&SeM6aQwR~T{j`9lKXSbx={^{M`XH>fh9-&5}BK>!ts>t6RQ(hr-b#gvLZH$LNz z^1%@1@?ITwspu=E7(^|23ma#+j#sJZ_R$xT8^kK&-M~u%3G#-?Xy%yPt0R-FC6w=o6mQcEU8hw(~o#iq-) zJkx57KP%jg`l*f|i5M$sOGL3tkeoy^VTuV2W8b>0M{SpgGTak# zL6mh`f#X`vq!PUZKg5%iBebwuu$J-KpUWW7$9cuH{n;RS)Hq1v-A4l#8e#fx^M5%X zuQ4p!#XN#^;Ro4;+U8O|1uO zZL`7nDn*!vVe);~pBkGBV7dNZ?0;vCD`qy|{M+>()y}q>w*ulzJVD@kM&|qnB+=s~ diff --git a/apps/limelight/screenshot_monoton.png b/apps/limelight/screenshot_monoton.png new file mode 100644 index 0000000000000000000000000000000000000000..d17d9bd26e9795c28c427f37ca8407db63b3f5b8 GIT binary patch literal 3032 zcmcJR`8U*y8^=GNkHMHxjJ+Dfbdhzs8d2E>Nw$!6G>v3WQ3@0Jj4n|cuRMxQ# z#pt8UO^d9PU4s-MDT9mZ>weGq{t4e7p67kev%JoE&Uwyxp2U-OmOC)JF#rJUusUw; zxUH;z4K1|os~bO1w*|cHXh{aD-s0x~0DITU-1Jlgbun-B>Vlf6dGoJd#g{V-mCVrO z5-fX%ixD!H(at?Avk`Gd}BrEcAa6w8o%K#c##rUfSuvJrQbUf;+GC&xS!^Njf= z&Kp?i-36)$C{~()O|DuT#+|5I=$i9PQx!xyf1Gs8BplSVW!glTm&zwTiZTDAE_-Rk z^4tPl5FH|*47Msf?@ZDKwdc!ja|>jk%3Q~eAV$z)#ZS^^!VvymH30sch~LkXEEA>BF zJHx=kS5|(m8YXbHOYZj)braZW=0RP#^j^eO6gd(D;h4!%XNY^H+F#eSu@4*tW(|8O&{k7TRF_+shqJ@><)?w=3eJv8$kWKHRe{{InfFup;N~Gz6 zUm9ep_R7d_SM75tPr<>Y_o#^6y^swI3g!oqVaAxhb0394dREa&zl3I0r8cQ<)>(XP zN-$#&qFMQPs3Pc~G_Thd`{mc?mrBUfV{-tZ((Fm9!|F|j&xL?(Kz$J6PN#7P*K|87 zT20QbJJ)3$R}Z6!B^fQ5MAWq8`l((YZq&{YBGPN(*1hHnKNYk0A}|#l;lUk<`jhJV zT|hHjKTu#5vRaHuRdV|nZfa>=p6jRA5rffEHMGFGn*9|lC^ zvczd7#ySWm)Q~p323d*QpoxWfvNVKb8;jXanTR2sbvuy(W0j~ZPPGgur1lN)T>1n# ziQ1y8HN`-o*>Aubj41jZjSPc0L!b^4c&_p<(_D_Xw%Ky1yI@{wFOujH6a9YItBO{i z$b}n`xXgsW_s%;)RNDW@lnw2lG-On&fBjAJl7x|6_DcYKdrI#6CG^ND4=}Id!gwyLc7TOfN%tDVDqfxZX7V z!te}*jAq&Da7VBqOOuMvD_(U)(@rbjvrs{Nd}B2~!O}y2KMc&cuA3c6E1N#vmNHr?_5-qu^}-6d_%5I;NU)-x8OL474{g z4f{Xs|$#rh%Ry`6Son2A8ZV<$RKYi-X%Mc(szg%YKo) z?^U7mjK=YRyXrNT!mt z65s1#a725nx9CO{4T}nIKakV!7&jXGXZmyiV64=1M3MrvC`1g353Rt}5w+u}u^hyO- zjeTP>W>f8p!-qzUaz&$KIN8^-i!B1|8gAr$6DcTNH>v9Q`R z(uWJ$!Cbv8-Qy8YUv;-om#57YS#O3{N_5)_a{Ttgxskfnm$yj@(R~3W7kHKwEqAEj zo(VbfgE!qifcc$vP8g)OIW+jet+xxn~Z*$>c+53Np$zg$BGyI|}<4wo0 z4h1!Yulc#=;DynfxTro~Qf)!R=|KIoQuu1WSC~Uabi6Itgu(|Xxm_Wh&;P#Wk4?>< zKLwLgN~Fx~3EftUMjFfY;@P}XKH~pM`C9ZWzW!P~|1s9gnfO4F6O!F)CzD0uAgrOcg?M=#RRGavKgJjP`Qk@i3fowI0a zeQa%X2>SglGJNOoiLdW?%Ccd>T*C~;^NXI}`aYtDvL<>*J8&US1iYj?52zwSh7J*_ zCvtw|IGD*6eqL#c><+Ns{(UpD;?|Fg-5Ak8 zKTz&TLK=I#YAarmxMFz^Ms}C))A0Gstnw_YFgGpdh@@IYE%ZrpQ9|@M@#1S9 z2~hM!OVdEYK4WHyw(%dp5y!F7fRvFNRO2zbm)-pacfT5L2OHAZuT$g`*p>>x9D~fp zE+T}tAwi0@l5Om^Of Date: Fri, 7 Jan 2022 01:02:43 +0000 Subject: [PATCH 131/202] Limelight - screenshots --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 3e63507c7..00a2b9860 100644 --- a/apps.json +++ b/apps.json @@ -5455,6 +5455,7 @@ "version": "0.01", "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", + "readme":"README.md", "screenshots": [{"url":"screenshot_limelight.png"}], "type": "clock", "tags": "clock", From 0dec5b608a9bb374a5be61b503e7032599cafbf2 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:07:20 +0000 Subject: [PATCH 132/202] Limelight - apps.json update --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 00a2b9860..91ef1450a 100644 --- a/apps.json +++ b/apps.json @@ -5451,9 +5451,9 @@ }, { "id": "limelight", - "name": "Limelight Clock", + "name": "Limelight", "version": "0.01", - "description": "Simple configurable analogue clock based on the work of @Andreas_Rozek (Simple_Clock)", + "description": "Simple analogue clock (with configurable fonts) based on the work of @Andreas_Rozek (Simple_Clock)", "icon": "limelight.png", "readme":"README.md", "screenshots": [{"url":"screenshot_limelight.png"}], From 673865b31460864fc4c7d35a603e58a033e02786 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:23:48 -0800 Subject: [PATCH 133/202] Update app.js MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unnecessary keywords. Remove autolight, since the system once again provides this service. Add optional autorotate while charging. Distinguish ‘slow’ second hand from regular second hand, visually. Tweak fonts. --- apps/pooqround/app.js | 195 ++++++++++++++++++++++++------------------ 1 file changed, 111 insertions(+), 84 deletions(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index 22cf5ff79..b0c7592f2 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -25,8 +25,8 @@ // // This only works for Bangle 2. -const isString = x => typeof x === 'string'; -const imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; +const isString = x => typeof x === 'string', + imageWidth = i => isString(i) ? i.charCodeAt(0) : i.width; ////////////////////////////////////////////////////////////////////////////// /* System integration */ @@ -115,9 +115,9 @@ class RoundOptions extends Options { onchange: x => this.calendric = x, format: x => ['none', 'day', 'date', 'both', 'month', 'full'][x], }, - 'Auto-Illum.': { - init: _ => this.autolight, - onchange: x => this.autolight = x + 'Autorotate': { + init: _ => this.autorotate, + onchange: x => this.autorotate = x }, Defaults: _ => {this.reset(); this.interact();} }); @@ -133,7 +133,7 @@ RoundOptions.defaults = { calendric: 5, dayFg: '#fff', nightFg: '#000', - autolight: true, + autorotate: true, }; ////////////////////////////////////////////////////////////////////////////// @@ -144,29 +144,29 @@ const dec = x => E.toString(heatshrink.decompress(atob(x))); const y10F = [ dec( 'g///EAh////AA4IIBgPwgE+gAOBg/AngXB+EPAYM8gfggEfgF8D4OAj4dB8EDAYI' + - 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUYgECCIZlBAY' + - 'N4CoRUBIoMP8AZBge8CgMB8+BCAPw+F/gf8jxDB/0D4BGBEQMPAYIeBoAfBnEwge' + - 'Ah0cB4MDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMO4P8LwM/XAJLBT' + - 'gY7BAAN/wC9CQwV+jwDB/4pBgP/EQKYBBIIxBPQP+SATfCIYIiCO4I9BBwM//hlB' + - 'PQJlCwYGBTAPgIgM4CYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+' + - 'BAYJyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwn4yBnhxBGQJxBGQK5BGQKWDOwUACAM' + - 'D/BDCNYPg///8E5HwR2BIwMDSgK0FSocMAYTLBAAYpBQAPnDwJGBEwK+B/hlB+F8' + - 'TARABTAJABTAPBMoR+BMoKXBDoX5DwIuBMoUPS4THCGwJbBhAaBvh5B+EHwPAOwP' + - 'guA1BvCcB4E8nxlBn1/VoIyBwDKBO4SGCgA=' + 'fBBAISBAAMOAYUB4AECnEAkAuBgEQBAPgIYX8IYX/wYDCEwIiMMgUcgECCIZlBAY' + + 'N4CoRUBIoMP8AZBge8MoMB8+B8B4B+E/gf4jw/B/kD4ADBEQMPSYXgoAfBnEwgeA' + + 'hw7BvEDx4PBgHn4EB8E7LQM8h/eJ4MDBgIpB+H+g/wnE/WwMMG4ReBn4zBJYKcDH' + + '4IABv+AXoSGCv0eAYP/FIMB/4iBTAIJBGIJ6B/yQCb4RDBEQTlBHoIOBn51BwC+B' + + 'MoWDAwKYBRgKYBCYM8hwKBMoODegPA8F+gZlBewP4hz/BE4QrBGgM/LAV//4+BAY' + + 'JyBPwM/KQMeGQMPFwM8H4UHBIPwGQNwZgPwnhxBGQJxBGQK5BGQKWDOwUACALlBI' + + 'YRrB8H///gnI+COwJGBgaUBWgqVDhgDCZYIADFIKAB84eBIwImBXwP8MoPwviYCI' + + 'AKYBIAKYB4JlCPwJlBS4IdC/IeBFwJlCh6XCY4Q2BLYMIDQN8PIPwg+B4B2B8FwG' + + 'oN4TgPAnk+MoM+v6tBGQOAZQJ3CQwUAA' ), 48, dec('hgAI'), 34 ];const y1F = [ dec( - 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnAFEj' + - 'gFEh0AhA1EiAFCgeAFIf/4A1DFQIED/5MDGB6OEjAECHIIYDhkAuAFCjwFEj6DEn' + - '+AAod74AFD/PgvAtC+Hwv/wgZSBvEfLwc8RISOBGAJsBVAXgggEBE4PgIgJLC8E8' + - 'I4fgXQS/B8IhBGwOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQJCB/DMDMoMBboYVBKo' + - 'IDBSYeAAoYlCAATpEg/4Xwc/QIcPFoJcBQIP8GILXCDYLXBbId//BeCL4QwDgIwD' + - 'AAIXBDAQfCEYSPBAoaPCPQKPCAoZgBAoYvBAoIXBBAIFB/ALDEoJHBAoaPDaQSPB' + - 'AoKcBJgY9DTQX/EoKmCC4SyCYYJJB+CHBj+Aj8ASYJNBBINwIIOAM4ILDAYN/wAB' + - 'BB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBAgaNCYwgFEbAkAwAFEc4S' + - 'PCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh4FDMoQ1DK4ZBBMQIDBJY' + - 'bWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwRCvEBF4IdB+E/OIp9CJgZ' + - 'BCQQUAA=' + 'g//AAPggE/AoX8gF/AoX+gF8CoU+gHwAoUPgAZBEIQFGCIodFFIo1FIIoADnEAgQ' + + 'FCjkAgwFCh0Ahg1EBoIABgeAFIf/4A1DFQIED/5MDGAYADEQYwDRwgMDhAYEH4Nw' + + 'AoUeAok/QYl/wAFD/fAHgUD+PgvAFBj/g+E/4EBLAN4j5SCgE8h4EB/AwCAoOAVA' + + 'PgggeBFoPgQgRLB8E8I4fgXQS/B8KwBMgOA8YFCgfA9+eAoMB4H/j/ACIPA/kPCQ' + + 'JIB/DMDMoJSBboQVBKoIDBSYZOBAAQlCAATpEg/4Xwc/QIZyBwBcBgf//gxBa4Qb' + + 'Ba4LZDv/4LwRfCGAcBGAYABC4IYCD4QjCR4IFDR4R6BR4QFDMAIFDF4IFBC4IIBA' + + 'oLEBBYQlBI4IFDR4ZrBR4QFBTgJMDHoaaCdQSmCC4SyCYYJJB+CHBj+Aj8ASYJNB' + + 'BINwIIOAM4ILDAYN/wABBB4JBBI45vCRYgADApEHL4pHB8AECFIPhAYLCCAggFBA' + + 'gaNCYwgFEbAkAwAFEc4SPCj/+LIKPBv6PEAoRnBFIMDFYLXCKoTLDa4YRDBYIdDh' + + '4FDMoQ1DK4ZBBMQIDBJYbWBFIMEIIQpBgxxBgZRBh8AAYN8AoQVBjgbBAoTZBvwR' + + 'CvEBF4IdB+E/OIp9CJgZBCQQUAA=' ), 48, dec('hgAI'), 48 ];const y10sF = [ dec( @@ -194,20 +194,20 @@ const y10F = [ ];const d1F = [ dec( 'AB1/+AECj///4FCAgP/8EAgf/4F//EAg4CBgf8gEPwAUBn0AhwaCAYMeAoUPgEcA' + - 'oUHAowRFDoopFGopBFJopZGBgIKCABlAIIcA4AFDgIFEgZBCAoMHAohVBAoY6CHg' + - 'U/Aol/AogADGoQFUABEMAQM/AQN8bIRZBRgJ5BLILhBgP3LIcD84rDg/HWYcPw4F' + - 'Dj4PBAoU+Aol8Aon4PocB+CJDgfgAoXgh/ATYX4v+AU4X//w/DbYQFCCwJ3PvDIE' + - 'NYQCCdoJ6CgfAiCGCI4NwgEeFwISCLoMeJwJdCnkfHYd4v4FD+f5AoUB9/BAoUD/' + - '4jCh8HG4IpCh5DBAIMeE4Q/BvjMCfoP8Z4Uf//wCgInB/5lCABs+AoicBAAUDAok' + - 'P9wFDv+OCAjUCHQP4AoY5BAoUHEIIFCv5JBAoLQBLQYqEApQpDArIAJv5IBnBTCV' + - '4McJAQFBcYLvBB4IkBd4N4cYQBBeoLdBCYIFDngFECoIFDOwIdCc4QpCFwIZCjwu' + - 'BEoU8FwIxCvAIBEIPB+AUBJIP/8AmBLYWAd4RnBdx4XCcYf/Dgn//AuEP4LjBXoJ' + - 'AC//vQYT0BBIKDC+CZBOIM/wAFDVYIFCgIrBAoUDPoIdCO4QnBaQYnBGoQVBIIZI' + - 'CJoTNCLIY4CAYIaDAAKRCAASRDAAIaEYAQtDYAI5DRgZFCAAYuCQoQuBAgIFBvEH' + - 'AgIFB+CgBAAMB86lE76EBFwX/GocPNoYmBIwk/HQl8LpIAQRId/SoYDB4ZJCUoPn' + - 'VoUHwP3Y4YYBY4k+Y4h5BdILhBd4YFFCIodFFIo1FIIpNFLIplGAArMFn6oBHYMA' + - 'DYQFBgP5E4IFBgfgUgIFCwBZBEAL1BPYZbDA4Z7DLYRtCBYYlDBoIxCEYMBHoIvC' + - 'HAI7Dh5PBI4X/LIX//7+Dn52Eh4QCA==' + 'oUHAowRFDoopFGopBFJopZGBgIKCAB5BBgA1CAoMBAokDCIgTCAYRTDAoI6CHgU/' + + 'Aol/Aog1GAqgAIhgCBn4CBvjZCLIKMBPIJZBcIMB+4lBMoMD84rDg/HL4cPw4FDj' + + '5rEnwFEvgFE/AFBaYMB+CJCwED8AFC8EP4CbC/F/wCnC//+H4bbCAoQWBO594EAI' + + 'TBgBrCAQTtBPQUD4EQQwRHBuEAjwuBCQRdBjxOBLoU8j47DvF/Aofz/IFCgPv4IF' + + 'Cgf/EYUPg43BFIUPIYIBBjwnCH4N8ZgT9B/jPCj//+AUBE4P/MoQANnwFETgIACg' + + 'YFEh/uAod/xwQEagQ6B/AFDHIIFCg4hBAoV/JIIFBaAJaDFQgFKFIYFZABN/JAM4' + + 'KYSvBjhICAoLjBd4IPBEgLvBvDjCAIL1BboITBAoc8AogVBAoZ2BDoTnCFIQuBDI' + + 'UeFwIlCnguBGIV4BAIhB4PwCgJJB//gEwJbCwDvCM4LuPC4TjD/4cE//4Fwh/BcY' + + 'K9BIAX/96DCegIJBQYXwTIJxBn+AAoarBAoUBFYIFCgZ9BDoR3CE4LSDE4I1CCoJ' + + 'BDJARNCZoRZDHAQDBDQYABSIQACSIYABDQjACFobABHIaMDIoQADFwSFCFwIEBAo' + + 'N4g4EBAoPwUAIABgPnUonfQgIuC/41Dh5tDEwJGEn46EvhdJACCJDv6VDAYPDJIS' + + 'lB86tCg+B+7HDDALHEnzHEPILpBcILvDAooRFDoopFGopBFJopZFMowAFZgs/VAI' + + '7BgAbCAoMB/InBAoMD8CkBAoWALIIgBeoJ7DLYYHDPYZbCNoQLDEoYNBGIQjBgI9' + + 'BF4Q4BHYcPJ4JHC/5ZC///fwc/OwkPCAQA==' ), 48, dec('ikPigAGA'), 48 ];const dowF = [ dec( @@ -220,10 +220,10 @@ const y10F = [ 'kDMIgeBFIQEBBYRTBCAZ3FAggAMg4zEj7LEn7LEv++AodzxwFD+ePAofjw4FVDoo' + 'pFv+eIImcJomYLImAAoZeEAtTyBAAQFEVYIFDSQIvhAojaCFwgABh4YEngFEuAqJ' + 'gPAAocDApYuEgP/fgl/+B9HAAv+Aon8HQMOIAkeAokcAohaDAoM4Aol4AohmDAoJ' + - 'BDAoJsDAo7vhABbJDAo9/AojEFMYbKMArCBDFI41FWIYABggFEgbuCDYMPLIQbBj' + - '//wBdCn0H4DZCvEBb4YZBdYZBBAofgCIQFDDoIFFDoPggYFBF4IFBGoI7B+AFCE4' + - 'NwCIIlCuAdBIYU4gPwn5VBjC7B/y0Dv/4YwcPCwMAjJlCAAM584FDufDCAUA8eBA' + - 'p/zC4n5EYj1BAoc//4RDU4IFDA==' + 'BDAoJsDAo7vhABZuBQYoFDv4FEYgpjDZRgFYGYYpHGoqxDAAMEAokDdwQbBh//DY' + + 'cf/+ALoU+g/AbIV4gLfDDILrDIIIFD8ARCAoYdBAoodB8EDAoIvBAoI1BHYPwAoQ' + + 'nBuARBEoVwDoJDCnEB+E/KoMYXYP+Wgd//DGDh4WBgEZMoQABnPnAodz4YQCgHjw' + + 'IFP+YXE/IjEeoIFDn//CIanBAoY=' ), 48, dec('kElkMljsljw='), 48 ];const mF = [ dec( @@ -322,21 +322,20 @@ class Round { this.r = this.xc - this.minR; } - reset(clear) {this.state = {}; clear && this.g.clear(true);} + reset(clear) {this.state = {}; clear == null || this.g.clear(true).setRotation(clear);} doIcons(which) { this.state[which] = null; - this.render(new Date()); // Not quite right, I think. } enhanceUntil(t) {this.enhance = t;} pie(f, a0, a1, invert) { if (!invert) return this.pie(f, a1, a0 + 1, true); - let t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); + const t0 = Math.tan(a0 * 2 * Math.PI), t1 = Math.tan(a1 * 2 * Math.PI); let i0 = Math.floor(a0 * 4 + 0.5), i1 = Math.floor(a1 * 4 + 0.5); - let x = f.getWidth() / 2, y = f.getHeight() / 2; - let poly = [ + const x = f.getWidth() / 2, y = f.getHeight() / 2; + const poly = [ x + (i1 & 2 ? -x : x) * (i1 & 1 ? 1 : t1), y + (i1 & 2 ? y : -y) / (i1 & 1 ? t1 : 1), x, @@ -348,16 +347,17 @@ class Round { for (i0++; i0 <= i1; i0++) poly.push( 3 * i0 & 2 ? f.getWidth() : 0, i0 & 2 ? f.getHeight() : 0 ); - f.setColor(0).fillPoly(poly); + return f.setColor(0).fillPoly(poly); } hand(t, d, c0, r0, c1, r1) { + const g = this.g; t *= Math.PI / 30; - const r = this.r; - const z = 2 * r0 + 1; - const x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t); - const x0 = x - r0, y0 = y - r0; - d = d ? d[0] : Graphics.createArrayBuffer(z, z, 16, {msb: true}); + const r = this.r, + z = 2 * r0 + 1, + x = this.xc + r * Math.sin(t), y = this.yc - r * Math.cos(t), + x0 = x - r0, y0 = y - r0; + d = d ? d[0] : Graphics.createArrayBuffer(z, z, 4, {msb: true}); for (let i = 0; i < z; i++) for (let j = 0; j < z; j++) { d.setPixel(i, j, g.getPixel(x0 + i, y0 + j)); } @@ -366,24 +366,20 @@ class Round { return [d, x0, y0]; } - render(d) { - const g = this.g; - const b = this.b, bI = this.bI; - const c = this.c, cI = this.cI; - const e = d < this.enhance; - const state = this.state; - const options = this.options; - const cal = options.calendric; - const res = options.resolution; - const dow = (e || cal == 1 || cal > 2) && d.getDay(); - const ts = res < 2 && d.getSeconds(); - const tm = (e || res < 3) && d.getMinutes() + ts / 60; - const th = d.getHours() + d.getMinutes() / 60; - const dd = (e || cal > 1) && d.getDate(); - const dm = (e || cal > 3) && d.getMonth(); - const dy = (e || cal > 4) && d.getFullYear(); - const xc = this.xc, yc = this.yc, r = this.r; - const dlr = xc * 3/4, dlw = 8, dlhw = 4; + render(d, rate) { + const g = this.g, b = this.b, bI = this.bI, c = this.c, cI = this.cI, + e = d < this.enhance, + state = this.state, options = this.options, + cal = options.calendric, res = options.resolution, + dow = (e || cal === 1 || cal > 2) && d.getDay(), + ts = res < 2 && d.getSeconds(), + tm = (e || res < 3) && d.getMinutes() + ts / 60, + th = d.getHours() + d.getMinutes() / 60, + dd = (e || cal > 1) && d.getDate(), + dm = (e || cal > 3) && d.getMonth(), + dy = (e || cal > 4) && d.getFullYear(); + const xc = this.xc, yc = this.yc, r = this.r, + dlr = xc * 3/4, dlw = 8, dlhw = 4; // Restore saveunders for fast-moving, overdrawing indicators. if (state.sd) g.drawImage.apply(g, state.sd); @@ -397,10 +393,10 @@ class Round { state.dow = dow; } - const locked = Bangle.isLocked(); - const charging = Bangle.isCharging(); - const battery = E.getBattery(); - const HRMOn = Bangle.isHRMOn(); + const locked = Bangle.isLocked(), + charging = Bangle.isCharging(), + battery = E.getBattery(), + HRMOn = Bangle.isHRMOn(); if (dy !== state.dy || locked !== state.locked || charging !== state.charging || @@ -463,6 +459,7 @@ class Round { this.hand(tm, state.md, g.theme.bg, this.minR, g.theme.fg, this.minR - 1) : null; state.sd = ts === +ts ? + rate > 1000 ? this.hand(ts, state.sd, g.theme.fg2, this.secR, g.theme.bg, 2) : this.hand(ts, state.sd, g.theme.fg2, this.secR) : null; } @@ -482,7 +479,18 @@ class Clock { this.listeners = { lcdPower: on => on ? this.active() : this.inactive(), - charging: () => {face.doIcons('charging'); this.active();}, + charging: on => { + face.doIcons('charging'); + if (on) { + this.listeners.accel = + a => this.orientation(a) === this.attitude || this.active(); + Bangle.on('accel', this.listeners.accel); + } else { + Bangle.removeListener('accel', this.listeners.accel); + delete this.listeners.accel; + } + this.active(); + }, lock: () => {face.doIcons('locked'); this.active();}, faceUp: up => { this.conservative = !up; @@ -498,20 +506,23 @@ class Clock { if (e.y - this.e0.y < -50) { this.options.resolution > 0 && this.options.resolution--; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (e.y - this.e0.y > 50) { this.options.resolution < this.timescales.length - 1 && this.options.resolution++; this.rates.clock = this.timescales[this.options.resolution]; + this.ack(); this.active(); } else if (this.yX - this.yN < 20) { const now = new Date(); if (now - this.t0 < 250) { + this.ack(); face.enhanceUntil(now + 30000); - face.render(now); + this.active(); } else if (now - this.t0 > 500) { this.stop(); - this.options.interact(); + this.ack().then(_ => this.options.interact()); } } this.t0 = null; @@ -524,9 +535,25 @@ class Clock { }; } + ack() { + return Bangle.buzz(33); + } + + orientation(a) { + return Math.abs(a.z) < 0.85 ? + Math.abs(a.y) > Math.abs(a.x) ? a.y < 0 ? 0 : 2 : a.x > 0 ? 1 : 3 : + 0; + } + + rotation() { + return this.options.autorotate && Bangle.isCharging() ? + this.orientation(Bangle.getAccel()) : + 0; + } + redraw(rate) { const now = this.updated = new Date(); - if (this.refresh) this.face.reset(true); + if (this.refresh) this.face.reset(this.attitude = this.rotation()); this.refresh = false; rate = this.face.render(now, rate); if (rate !== this.rates.face) { @@ -541,13 +568,13 @@ class Clock { this.exception && clearTimeout(this.exception); this.interval && clearInterval(this.interval); this.timeout = this.exception = this.interval = this.rate = null; - this.face.reset(false); // Cancel any ongoing background rendering + this.face.reset(); // Cancel any ongoing background rendering return this; } active() { - const prev = this.rate; - const now = Date.now(); + const prev = this.rate, + now = Date.now(); let rate = Infinity; for (const k in this.rates) { let r = this.rates[k]; From b878ae1f24b7e384851b3ea5a63785748cd87456 Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:25:01 -0800 Subject: [PATCH 134/202] Update ChangeLog --- apps/pooqround/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 8eb91cf97..17004449d 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,2 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. From 3068a647d63f0425751305f0da08f03e039d582e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:28:32 -0800 Subject: [PATCH 135/202] Update README.md --- apps/pooqround/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/pooqround/README.md b/apps/pooqround/README.md index d413fd88e..6f6bafa69 100644 --- a/apps/pooqround/README.md +++ b/apps/pooqround/README.md @@ -20,8 +20,7 @@ you can quickly alter the number of ‘hands’ on the display. When the watch i or down to remove the distraction. There's also a setting that displays the second hand, but only if the watch is perfectly face-to-the-sky, in case you want the ability to check the _exact_ time, hands free, without the impact on battery life this usually entails. -In some versions of the Bangle.js firmware, the backlight doesn't come on automatically when you twist your wrist. There's currently a workaround -for this integrated into the watchface; you can disable it in the menu, if you prefer. +While charging the main display automatically rotates so that noon is up. This can be disabled. ## Limitations From 9811ada68d1c62e55cd8b18d87beea1d7e00639e Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:29:39 -0800 Subject: [PATCH 136/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 8b4e86d52..40e92d201 100644 --- a/apps.json +++ b/apps.json @@ -4943,7 +4943,7 @@ { "id": "pooqround", "name": "pooq Round watch face", "shortName":"pooq Round", - "version":"0.01", + "version":"0.02", "description": "A 24 hour analogue watchface with high legibility and a novel style.", "icon": "app.png", "type": "clock", From 99c7dba8f2100d247afabaec694e874a448bb06b Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 17:43:05 -0800 Subject: [PATCH 137/202] Update ChangeLog --- apps/pooqround/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/pooqround/ChangeLog b/apps/pooqround/ChangeLog index 17004449d..bc35b69df 100644 --- a/apps/pooqround/ChangeLog +++ b/apps/pooqround/ChangeLog @@ -1,3 +1,3 @@ 0.00: Initial check-in. 0.01: Add tap-to-decorate feature. Bugfixes. -0.02: Add autorotate while charging. Remove autolight. Tweak fonts. +0.02: Add autorotate while charging. Remove autolight. Tweak fonts. Add some haptic feedback on touchscreen operations. From fe66e54b4fdfc7b9f34bb8874c57bf537287cf45 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 01:48:39 +0000 Subject: [PATCH 138/202] Limelight fix icon --- apps/limelight/limelight.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/limelight.icon.js b/apps/limelight/limelight.icon.js index 9e886bbf8..f7e74db90 100644 --- a/apps/limelight/limelight.icon.js +++ b/apps/limelight/limelight.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")); +require("heatshrink").decompress(atob("lksgIqngf/wAFC//+AgUch/4AgMBwAQEh/8Dgf/4AKOEAQKCAYUB//gAoU/DQkPBQYVBGx5SDBQIbDBR0GEAlgFYcHGwh4B+CDHRwL04")) \ No newline at end of file From 328f2d0e09163b93ba238ddbd8751500b14dc88a Mon Sep 17 00:00:00 2001 From: stephenPspackman <93166870+stephenPspackman@users.noreply.github.com> Date: Thu, 6 Jan 2022 22:40:34 -0800 Subject: [PATCH 139/202] Update app.js Remove internal autolight logic. --- apps/pooqround/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/pooqround/app.js b/apps/pooqround/app.js index b0c7592f2..06e208e61 100644 --- a/apps/pooqround/app.js +++ b/apps/pooqround/app.js @@ -496,7 +496,6 @@ class Clock { this.conservative = !up; this.active(); }, - twist: _ => this.options.autolight && Bangle.setLCDPower(true), drag: e => { if (this.t0) { if (e.b) { From 341080e09b3ad310cd2eb9e0f74f117bf121fd01 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 7 Jan 2022 08:53:32 +0000 Subject: [PATCH 140/202] widpedom 0.22: Fix 'stps' regression for 0.21 (fix #1233) --- apps.json | 2 +- apps/widpedom/ChangeLog | 1 + apps/widpedom/widget.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 7fc5145aa..6b81f6a41 100644 --- a/apps.json +++ b/apps.json @@ -1590,7 +1590,7 @@ { "id": "widpedom", "name": "Pedometer widget", - "version": "0.21", + "version": "0.22", "description": "Daily pedometer widget", "icon": "widget.png", "type": "widget", diff --git a/apps/widpedom/ChangeLog b/apps/widpedom/ChangeLog index 3483c3390..54f6b203b 100644 --- a/apps/widpedom/ChangeLog +++ b/apps/widpedom/ChangeLog @@ -21,3 +21,4 @@ Memory usage enhancements 0.20: Fix issue where step count would randomly reset 0.21: Memory usage improvements, fix widget initial width (fix #1170) +0.22: Fix 'stps' regression for 0.21 (fix #1233) diff --git a/apps/widpedom/widget.js b/apps/widpedom/widget.js index 3a079c066..cc7fdb579 100644 --- a/apps/widpedom/widget.js +++ b/apps/widpedom/widget.js @@ -55,6 +55,7 @@ // add your widget WIDGETS["wpedom"]={area:"tl",width:0, getWidth:function() { + let stps = stp_today.toString(); let newWidth = 24; if (settings.hide) newWidth = 0; @@ -68,7 +69,6 @@ return newWidth; }, redraw:function() { // work out the width, and queue a full redraw if needed - let stps = stp_today.toString(); let newWidth = this.getWidth(); if (newWidth!=this.width) { // width has changed, re-layout all widgets From aa47b7fa99cceb520f7684a8e05bd995fd828de1 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 09:53:40 +0100 Subject: [PATCH 141/202] Hopefully fix bug where no HRM data is received --- apps/circlesclock/app.js | 67 +++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 32 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index b5ee61c75..392fa4287 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -9,6 +9,7 @@ const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmA const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); let settings; + function loadSettings() { settings = require("Storage").readJSON("circlesclock.json", 1) || { 'minHR': 40, @@ -60,10 +61,10 @@ function draw() { if (!showWidgets) { /* - * we are not drawing the widgets as we are taking over the whole screen - * so we will blank out the draw() functions of each widget and change the - * area to the top bar doesn't get cleared. - */ + * we are not drawing the widgets as we are taking over the whole screen + * so we will blank out the draw() functions of each widget and change the + * area to the top bar doesn't get cleared. + */ if (WIDGETS && typeof WIDGETS === "object") { for (let wd of WIDGETS) { wd.draw = () => {}; @@ -97,7 +98,7 @@ function draw() { function drawCircle(index, defaultType) { const type = settings['circle' + index] || defaultType; - const w = index == 1 ? w1: index == 2 ? w2 : w3; + const w = index == 1 ? w1 : index == 2 ? w2 : w3; switch (type) { case "steps": @@ -114,12 +115,13 @@ function drawCircle(index, defaultType) { break; } } + function getCirclePosition(type, defaultPos) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i == 1 ? w1: i == 2 ? w2 : w3; + if (setting == type) return i == 1 ? w1 : i == 2 ? w2 : w3; } - return defaultPos; + return defaultPos || undefined; } function isCircleEnabled(type) { @@ -229,8 +231,7 @@ function drawBattery(w) { if (Bangle.isCharging()) { color = colorGreen; icon = powerIconGreen; - } - else { + } else { if (settings.batteryWarn != undefined && battery <= settings.batteryWarn) { color = colorRed; icon = powerIconRed; @@ -289,39 +290,41 @@ function getSteps() { return 0; } +function enableHRMSensor() { + Bangle.setHRMPower(1, "circleclock"); + if (hrtValue == undefined) { + hrtValue = '...'; + drawHeartRate(); + } +} + Bangle.on('lock', function(isLocked) { if (!isLocked) { if (isCircleEnabled("hr")) { - Bangle.setHRMPower(1, "watch"); - if (hrtValue == undefined) { - hrtValue = '...'; - drawHeartRate(); - } + enableHRMSensor(); } draw(); } else { - if (isCircleEnabled("hr")) { - Bangle.setHRMPower(0, "watch"); - } + Bangle.setHRMPower(0, "circleclock"); } }); -if (isCircleEnabled("hr")) { - Bangle.on('HRM', function(hrm) { - //if(hrm.confidence > 90){ - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} - }); -} -if (isCircleEnabled("battery")) { - Bangle.on('charging', function(charging) { - drawBattery(); - }); +Bangle.on('HRM', function(hrm) { + if (isCircleEnabled("hr")) { + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + } +}); + + +Bangle.on('charging', function(charging) { + if (isCircleEnabled("battery")) drawBattery(); +}); + +if (isCircleEnabled("hr")) { + enableHRMSensor(); } Bangle.setUI("clock"); From 2f16365e6cf6b4ad9717770e4103b6d52a4f6fe2 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:26:45 +0100 Subject: [PATCH 142/202] Redraw background rectangle before drawing circles (fixes graphical glitch) --- apps/circlesclock/app.js | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 392fa4287..4f2fea4ab 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -131,6 +131,11 @@ function isCircleEnabled(type) { function drawSteps(w) { if (!w) w = getCirclePosition("steps", w1); const steps = getSteps(); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -160,6 +165,10 @@ function drawStepsDistance(w) { const stepDistance = settings.stepLength || 0.8; const stepsDistance = Math.round(steps * stepDistance); + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -185,6 +194,11 @@ function drawStepsDistance(w) { function drawHeartRate(w) { if (!w) w = getCirclePosition("hr", w2); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -210,6 +224,11 @@ function drawHeartRate(w) { function drawBattery(w) { if (!w) w = getCirclePosition("battery", w3); const battery = E.getBattery(); + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); @@ -319,6 +338,12 @@ Bangle.on('HRM', function(hrm) { }); +Bangle.setUI("clock"); +Bangle.loadWidgets(); + +draw(); +setInterval(draw, 60000); + Bangle.on('charging', function(charging) { if (isCircleEnabled("battery")) drawBattery(); }); @@ -326,9 +351,3 @@ Bangle.on('charging', function(charging) { if (isCircleEnabled("hr")) { enableHRMSensor(); } - -Bangle.setUI("clock"); -Bangle.loadWidgets(); - -draw(); -setInterval(draw, 60000); From 96802b0bd48e50ba721b157590d23e3fad8963dd Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:32:39 +0100 Subject: [PATCH 143/202] Make min- & maxHR settings more granular --- apps/circlesclock/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index 95ebc17db..a16bb99a8 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -15,7 +15,7 @@ value: "minHR" in settings ? settings.minHR : 40, min: 0, max : 250, - step: 10, + step: 5, format: x => { return x; }, @@ -25,7 +25,7 @@ value: "maxHR" in settings ? settings.maxHR : 200, min: 20, max : 250, - step: 10, + step: 5, format: x => { return x; }, From c47cabe156e3e03756492be8ed34b8bc31854d98 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 10:43:06 +0100 Subject: [PATCH 144/202] Update ChangeLog --- apps/circlesclock/ChangeLog | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index f416929ac..4230c1468 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -1,4 +1,7 @@ 0.01: New clock 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes -0.04: Make configurable what to show in each circle; add step distance circle; allow switching visibility of widgets +0.04: Make configurable what to show in each circle + Add step distance circle + Allow switching visibility of widgets + Make circles and text slightly bigger From 95c3b70af4c8d0873b5ec61636136738ca508477 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 19:06:07 +0100 Subject: [PATCH 145/202] Log confidence alongside heartrate instead of discarding confidence 0 samples --- apps/recorder/widget.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 34a6ca488..8f82f1f37 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -53,33 +53,29 @@ }, hrm:function() { var bpm = 0, bpmConfidence = 0; - var hasBPM = false; function onHRM(h) { if (h.confidence >= bpmConfidence) { bpmConfidence = h.confidence; bpm = h.bpm; - if (bpmConfidence) hasBPM = true; } } return { name : "HR", - fields : ["Heartrate"], + fields : ["Heartrate", "Confidence"], getValues : () => { - var r = [bpmConfidence?bpm:""]; + var r = [bpm,bpmConfidence]; bpm = 0; bpmConfidence = 0; return r; }, start : () => { - hasBPM = false; Bangle.on('HRM', onHRM); Bangle.setHRMPower(1,"recorder"); }, stop : () => { - hasBPM = false; Bangle.removeListener('HRM', onHRM); Bangle.setHRMPower(0,"recorder"); }, - draw : (x,y) => g.setColor(hasBPM?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + draw : (x,y) => g.setColor(Bangle.isHRMOn()?"#f00":"#f88").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) }; }, bat:function() { From 089f0cd4386c24a9d05fd9bd258ed436fd375253 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:39:39 +0100 Subject: [PATCH 146/202] Emit additional BTHRM event and allow overwriting HRM optionally --- apps.json | 3 +- apps/bthrm/boot.js | 65 ++++++++++++++++++++++++++++++++---------- apps/bthrm/settings.js | 33 +++++++++++++++++++++ 3 files changed, 85 insertions(+), 16 deletions(-) create mode 100644 apps/bthrm/settings.js diff --git a/apps.json b/apps.json index 95c7b4bbc..6aa109142 100644 --- a/apps.json +++ b/apps.json @@ -1049,7 +1049,8 @@ "readme": "README.md", "storage": [ {"name":"bthrm.boot.js","url":"boot.js"}, - {"name":"bthrm.img","url":"app-icon.js","evaluate":true} + {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, + {"name":"bthrm.settings.js","url":"settings.js"} ] }, { diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 88e574480..0aa8d5c96 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -2,24 +2,43 @@ var log = function() {};//print var gatt; var status; - - Bangle.isHRMOn = function() { + + var origIsHRMOn = Bangle.isHRMOn; + + Bangle.isBTHRMOn = function(){ return (status=="searching" || status=="connecting") || (gatt!==undefined); } - Bangle.setHRMPower = function(isOn, app) { + + Bangle.isHRMOn = function() { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + + print(settings); + if (settings.enabled && !settings.replace){ + return origIsHRMOn(); + } else if (settings.enabled && settings.replace){ + return Bangle.isBTHRMOn(); + } + return origIsHRMOn() || Bangle.isBTHRMOn(); + } + + Bangle.setBTHRMPower = function(isOn, app) { + + + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + // Do app power handling if (!app) app="?"; - log("setHRMPower ->", isOn, app); + log("setBTHRMPower ->", isOn, app); if (Bangle._PWR===undefined) Bangle._PWR={}; - if (Bangle._PWR.HRM===undefined) Bangle._PWR.HRM=[]; - if (isOn && !Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM.push(app); - if (!isOn && Bangle._PWR.HRM.includes(app)) Bangle._PWR.HRM = Bangle._PWR.HRM.filter(a=>a!=app); - isOn = Bangle._PWR.HRM.length; + if (Bangle._PWR.BTHRM===undefined) Bangle._PWR.BTHRM=[]; + if (isOn && !Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM.push(app); + if (!isOn && Bangle._PWR.BTHRM.includes(app)) Bangle._PWR.BTHRM = Bangle._PWR.BTHRM.filter(a=>a!=app); + isOn = Bangle._PWR.BTHRM.length; // so now we know if we're really on if (isOn) { - log("setHRMPower on", app); - if (!Bangle.isHRMOn()) { - log("HRM not already on"); + log("setBTHRMPower on", app); + if (!Bangle.isBTHRMOn()) { + log("BTHRM not already on"); status = "searching"; NRF.requestDevice({ filters: [{ services: ['180D'] }] }).then(function(device) { log("Found device "+device.id); @@ -49,7 +68,11 @@ if (flags&16) { var interval = dv.getUint16(idx,1); // in milliseconds }*/ - Bangle.emit('HRM',{ + + + var eventName = settings.replace ? "HRM" : "BTHRM"; + + Bangle.emit(eventName, { bpm:bpm, confidence:100 }); @@ -65,15 +88,27 @@ }); } } else { // not on - log("setHRMPower off", app); + log("setBTHRMPower off", app); if (gatt) { - log("HRM connected - disconnecting"); + log("BTHRM connected - disconnecting"); status = undefined; try {gatt.disconnect();}catch(e) { - log("HRM disconnect error", e); + log("BTHRM disconnect error", e); } gatt = undefined; } } }; + + var origSetHRMPower = Bangle.setHRMPower; + + Bangle.setHRMPower = function(isOn, app) { + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + if (settings.enabled || !isOn){ + Bangle.setBTHRMPower(isOn, app); + } + if (settings.enabled && !settings.replace || !isOn){ + origSetHRMPower(isOn, app); + } + } })(); diff --git a/apps/bthrm/settings.js b/apps/bthrm/settings.js new file mode 100644 index 000000000..8cb00614e --- /dev/null +++ b/apps/bthrm/settings.js @@ -0,0 +1,33 @@ +(function(back) { + var FILE = "bthrm.json"; + + var settings = Object.assign({ + enabled: true, + replace: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + '': { 'title': 'Bluetooth HRM' }, + '< Back': back, + 'Use BT HRM': { + value: !!settings.enabled, + format: v => settings.enabled ? "On" : "Off", + onchange: v => { + settings.enabled = v; + writeSettings(); + } + }, + 'Use HRM event': { + value: !!settings.replace, + format: v => settings.replace ? "On" : "Off", + onchange: v => { + settings.replace = v; + writeSettings(); + } + } + }); +}) From 55c7ed5dd8b7273baae42606e66b926126592ebd Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:41:26 +0100 Subject: [PATCH 147/202] Adds app to check status of BT/HRM --- apps.json | 3 ++- apps/bthrm/bthrm.js | 61 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 apps/bthrm/bthrm.js diff --git a/apps.json b/apps.json index 6aa109142..c3001a31d 100644 --- a/apps.json +++ b/apps.json @@ -1043,11 +1043,12 @@ "version": "0.01", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", - "type": "boot", + "type": "app", "tags": "health,bluetooth", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ + {"name":"bthrm.app.js","url":"bthrm.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js new file mode 100644 index 000000000..7c80c735f --- /dev/null +++ b/apps/bthrm/bthrm.js @@ -0,0 +1,61 @@ +var btm = g.getHeight()-1; +var eventInt = null; +var eventBt = null; +var counterInt = 0; +var counterBt = 0; + + +function draw(y, event, type, counter) { + var px = g.getWidth()/2; + g.reset(); + g.setFontAlign(0,0); + g.clearRect(0,y,g.getWidth(),y+80); + if (type == null || event == null || counter == 0) return; + var str = event.bpm + ""; + g.setFontVector(40).drawString(str,px,y+20); + str = "Confidence: " + event.confidence; + g.setFontVector(12).drawString(str,px,y+50); + str = "Event: " + type; + g.setFontVector(12).drawString(str,px,y+60); +} + +function onBtHrm(e) { + print("Event for BT " + JSON.stringify(e)); + counterBt += 5; + eventBt = e; +} + +function onHrm(e) { + print("Event for Int " + JSON.stringify(e)); + counterInt += 5; + eventInt = e; +} + +Bangle.on('BTHRM', onBtHrm); +Bangle.on('HRM', onHrm); + +Bangle.setHRMPower(1,'bthrm') +Bangle.setBTHRMPower(1,'bthrm') + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +g.reset().setFont("6x8",2).setFontAlign(0,0); +g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); + +function drawInt(){ + counterInt--; + if (counterInt < 0) counterInt = 0; + if (counterInt > 5) counterInt = 5; + draw(24, eventInt, "HRM", counterInt); +} +function drawBt(){ + counterBt--; + if (counterBt < 0) counterBt = 0; + if (counterBt > 5) counterBt = 5; + draw(100, eventBt, "BTHRM", counterBt); +} + +var interval = setInterval(drawInt, 1000); +var interval = setInterval(drawBt, 1000); From 3baf11613b242807dcdd9060eab60b1e9ddf4645 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:42:29 +0100 Subject: [PATCH 148/202] Adds recorder app plugin to record the BTHRM event --- apps.json | 1 + apps/bthrm/recorder.js | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 apps/bthrm/recorder.js diff --git a/apps.json b/apps.json index c3001a31d..7c9cbffdd 100644 --- a/apps.json +++ b/apps.json @@ -1049,6 +1049,7 @@ "readme": "README.md", "storage": [ {"name":"bthrm.app.js","url":"bthrm.js"}, + {"name":"bthrm.recorder.js","url":"recorder.js"}, {"name":"bthrm.boot.js","url":"boot.js"}, {"name":"bthrm.img","url":"app-icon.js","evaluate":true}, {"name":"bthrm.settings.js","url":"settings.js"} diff --git a/apps/bthrm/recorder.js b/apps/bthrm/recorder.js new file mode 100644 index 000000000..40f64a676 --- /dev/null +++ b/apps/bthrm/recorder.js @@ -0,0 +1,27 @@ +(function(recorders) { + recorders.bthrm = function() { + var bpm = 0; + function onHRM(h) { + bpm = h.bpm; + } + return { + name : "BTHR", + fields : ["BT Heartrate"], + getValues : () => { + result = [bpm]; + bpm = 0; + return result; + }, + start : () => { + Bangle.on('BTHRM', onHRM); + Bangle.setBTHRMPower(1,"recorder"); + }, + stop : () => { + Bangle.removeListener('BTHRM', onHRM); + Bangle.setBTHRMPower(0,"recorder"); + }, + draw : (x,y) => g.setColor(Bangle.isBTHRMOn()?"#00f":"#88f").drawImage(atob("DAwBAAAAMMeef+f+f+P8H4DwBgAA"),x,y) + }; + } +}) + From 47cc9434a30c299eb49820ee95a76e258a021592 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:32:25 +0100 Subject: [PATCH 149/202] Bump version and changelog --- apps.json | 2 +- apps/recorder/ChangeLog | 4 ++++ apps/recorder/README.md | 5 +++-- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 958bf71e9..95c7b4bbc 100644 --- a/apps.json +++ b/apps.json @@ -768,7 +768,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.05", + "version": "0.06", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index bedc63141..dbf086f7d 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -4,3 +4,7 @@ 0.03: Fix theme and maps/graphing if no GPS 0.04: Multiple bugfixes 0.05: Add recording for coresensor +0.06: Add recording for battery stats + Fix execution of other recorders (*.recorder.js) + Modified icons and colors for better visibility + Only show plotting speed if Latitude is available diff --git a/apps/recorder/README.md b/apps/recorder/README.md index 4a4561f1c..87be34424 100644 --- a/apps/recorder/README.md +++ b/apps/recorder/README.md @@ -16,7 +16,8 @@ You can record * **Time** The current time * **GPS** GPS Latitude, Longitude and Altitude * **Steps** Steps counted by the step counter -* **HR** Heart rate +* **HR** Heart rate and confidence +* **BAT** Battery percentage and voltage * **Core** CoreTemp body temperature **Note:** It is possible for other apps to record information using this app @@ -25,4 +26,4 @@ function in `widget.js` for more information. ## Tips -When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a grey satellite symbol, which you will see turn red when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. +When recording GPS, it usually takes several minutes for the watch to get a [GPS fix](https://en.wikipedia.org/wiki/Time_to_first_fix). There is a red satellite symbol, which you will see turn green when you get an actual GPS Fix. You can [upload assistant files](https://banglejs.com/apps/#assisted%20gps%20update) to speed up the time spent on getting a GPS fix. From 01d236b761c61819aa16d5fa75dd55877dd9289a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 6 Jan 2022 17:44:44 +0100 Subject: [PATCH 150/202] Bump version and changelog --- apps.json | 2 +- apps/bthrm/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 7c9cbffdd..3601aeca4 100644 --- a/apps.json +++ b/apps.json @@ -1040,7 +1040,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.01", + "version": "0.02", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 5560f00bc..27a58dd78 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -1 +1,4 @@ 0.01: New App! +0.02: Make overriding the HRM event optional + Emit BTHRM event for external sensor + Add recorder app plugin From b0238957b6be2c3ec4b41bcd214c1b25919ff39c Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 12:56:53 +0100 Subject: [PATCH 151/202] fix update mmind.icon,js from 176px to 48px --- apps/mmind/mmind.icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mmind/mmind.icon.js b/apps/mmind/mmind.icon.js index 976243b48..17c28ba0f 100644 --- a/apps/mmind/mmind.icon.js +++ b/apps/mmind/mmind.icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("2GwxH+64A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A6gAAFEf5I/VtpEcEcZI/Dw4PbCQu0AApnZDIUeAAqLaDQUFAApIc3IAFEabHPa6StJWLKtJWLStJWLKtJWKieFChIPPCYquKWAZmUVxSwDV6quKWAYjUVxSwDVqQUIB56uTWCiuOWCquOWCiuOWByaFV5oPLVyiwSVyCwTVyCwSVyCwNTIqvMB5iv/V/6vQUpQPTVyqwQVySwRVySwQVySwNT6Kv/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V/6vvWCZBSV0CwUJCSuhV/6v/V/4PPWCBBRWCIjSWCJIUV0CvfWB6KTWB4jUWB5IWVz6viWBYdPEZCuMV6ywLJDCuMV+SxLRKyxMEbKxKJDitXCAQALB6AoTRS4jkJHyvoFRCJZEcxI8V9DyZEdpI/ZaQpTB4W0AApnZDIUFAAqLaDQXSAApIckYAFEaTLPbaatJWLKtJWLStJWLKtJWKaeKDAgPPEgyuKWAZmUVxSwDV6quKWAYjUVxSwDV7AZDB56uSWCiuOWCquOWCiuOWByWJBAoPPVyiwSVyCwTVyCwSVyCwNSpIKLB5qv/V/6vuVySwQVySwRVySwQVySwMV/6v/V/6uRV/6v/V8wNDV/6v/V9SuJV/6v/V8atEV/6v/V9KtLV/6v/V8SuNWCiKPWCYjQWCZISVzavSVopGLV/6v/V8RDPVz6wSEaSwRJCiuaV6KuSWCCKTWB4jUWB5IWVzKvKVAyuTCgauMMyqwLEaokDVxhIWVxgjNT46uKIiytcWJojZWJRIcVqygGAA4OOFhYUUJbIjYJH4bOV7AaIRLIjmJH4bMV7QA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A+goAHEbUeAA5s/ADO0ADitRWLStIWP6v/VxywWVxiw/V/quOWCiuOWH6v7VyCwSVyCw/V/6v/AH6vpVySwQVySw/V/6v/ABMAAAaXeEa6v/V+SKEWDwjYV/6v/V/6v/V/6v/V/6v/V/6v/V/6v/V+SMFVzgjZV/6vzAHaviWCZHQV36v/V/6v/V/awRJCSu/V/6vLWB5JUV36v/V5awNJSyu/V/6vLWJRMaVv6v/V5YA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4AkA=")) +require("heatshrink").decompress(atob("mEwxH+64A/AEOBq2sBAusqwJHCaQFDAYlP2m0yGBCIkSj0eiWHBIkDgsFgYTE01v3O5t4mC1krgAEBq0ACYQuCAANsHIcxFwIwCEocsFwIwCBIYuCAANQF4QwBOgQABAgNIF4ZgELwQvCHIcCF4cEKwYvEt45DF4QwCL5YvFL5ITDF6OstheCvTjEjAuBjDJFX4UEq4TEyguBygTEF4dWBIeskkkqwQDDgUGgwaEBIUBgITHkslCYeBd4MrqwDBAgIuBcwRVGNIVs0oJEv3S6V+CYmIisjkcVZAYpBgDyBAAJFBFwTlGZIolDqouBGAQJDFwQABmRfCFAICCGwXXhgvDMAheCfI1UF4eoKwYvEiovHSoJfLF4pfJCYYvN1gwBAYMSLwVcbQmQFwOQZIq/C1GACYkcFwMcCYQoCLYNWF4KPBDgNWmIkEBIVPp5TDBIdWqoTHmUyCYlWRQTwCD4wA/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AH4A/AHmy2QJH6PRBI/Q6AkOCAIAFBINDjwABGInR3+53O/GIu72gABGJnQCAQAE69oFwQABCYfFFwIwCBIfCDIe7FIus1gvXLwQACLw4aCAAkAgAvcL4gvLq1WF5uyFwdoCYfLF4fLDpHCX6owBtFoxoUF6PF4ruFDwPC4XJFxbSCAAwVNAH4ARA")) From 2fe1ea524d2d6c0882edcd04ed96c39772aa30df Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 13:15:54 +0100 Subject: [PATCH 152/202] correct some typo's --- apps/mmind/README.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/apps/mmind/README.md b/apps/mmind/README.md index ea584b7e7..8060b95f6 100644 --- a/apps/mmind/README.md +++ b/apps/mmind/README.md @@ -7,15 +7,14 @@ Play the classic mind game mastermind on your Bangle 2. ## Game The game will start when run. -Four colors pins are randomly choosen and kept secret. -You need to find the secret by scoring your choise within 6 turns. +Four colors pins are randomly chosen and kept secret. +You need to find the secret by scoring your choice within 6 turns. The game makes use of touch features. ## Play -The screen needs to be unlocked. Select one of the dots, the color menu will show, select a colour for the pin. -If all pins are choosen with a color the red button will turn green. +If all pins are chosen with a color the red button will turn green. Hit the green button and your play will be scored and listed from the top. The first digit shows the number of pins with the correct color and in the right place. The second digit gives the number of pins with the correct color but in the wrong place. @@ -24,12 +23,9 @@ The blue button will start a new game. ## Requests - -This is the first version, things to add are:/ -Add a menu to change game options like the number of colors, allow double colors, 5 pins per row./ -Add feature to drag screen up and down to see more scores./ -Timer and high score./ +This is the first version, things to add are: +Add a menu to change game options like the number of colors, allow double colors, 5 pins per row. Add feature to drag screen up and down to see more scores. Timer and high score. +Any other fearures or remarks, let me know @psbest. ## Creator - This game is created by Peter Slendebroek. From 2397f5957acc41e9eb91c4da6e65d50901debcca Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 13:30:09 +0100 Subject: [PATCH 153/202] Add weather functionality Improve circle position finding --- apps/circlesclock/ChangeLog | 2 +- apps/circlesclock/README.md | 4 +- apps/circlesclock/app.js | 138 +++++++++++++++++++++++++++++----- apps/circlesclock/settings.js | 10 +-- 4 files changed, 126 insertions(+), 28 deletions(-) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 4230c1468..ca1da6e21 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -2,6 +2,6 @@ 0.02: Fix icon & add battery warn functionality 0.03: Theming support & minor fixes 0.04: Make configurable what to show in each circle - Add step distance circle + Add step distance and weather Allow switching visibility of widgets Make circles and text slightly bigger diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 9004161d6..a071efcf5 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -9,14 +9,12 @@ It can show the following information (this can be configured): * Steps distance (depending on steps) * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) + * Weather (requires [weather app](https://banglejs.com/apps/#weather)) ## Screenshots ![Screenshot dark theme](screenshot-dark.png) ![Screenshot light theme](screenshot-light.png) -## TODO -* Show weather information - ## Creator Marco ([myxor](https://github.com/myxor)) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 4f2fea4ab..23be307b9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -1,5 +1,6 @@ const locale = require("locale"); const heatshrink = require("heatshrink"); +const storage = require("Storage"); const shoesIcon = heatshrink.decompress(atob("h0OwYJGgmAAgUBkgECgVJB4cSoAUDyEBkARDpADBhMAyQRBgVAkgmDhIUDAAuQAgY1DAAYA=")); const shoesIconGreen = heatshrink.decompress(atob("h0OwYJGhIEDgVIAgUEyQKDkmACgcggVACIeQAYMSgIRCgmApIbDiQUDAAkBkAFDGoYAD")); @@ -8,10 +9,19 @@ const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbB const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); +const weatherCloudy = heatshrink.decompress(atob("h0OwYPMgfwAgU//4FCv///+Ag4DB//gh4EC//jAgYAK+IED8EBAgXAHpQA==")); +const weatherSunny = heatshrink.decompress(atob("h0OwYKHhuAAYM2AQkA7AOD2wFCgdt20AgOA7dtwHAC4PbsAUGgFt2ApIAAgIIA==")); +const weatherPartlyCloudy = heatshrink.decompress(atob("h0OwYOLg4FEn/8AgV+g/gAgMcgE48EB48f/wJBgP/gfwgEDBAIRBC4UH/kB4AmC8F+C4X4gf/AAIaBAAgA==")); +const weatherRainy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIXD8ARB/kAnED+P/8f+BgNwnARCjkOAgUH/+AAoU/IQ4A=")); +const weatherPartlyRainy = heatshrink.decompress(atob("h0OwYJGjkAnAFCj+AAgU//4FCuEA8EAg8ch/4gEB4////AAoIIBCIMD/wgCg4bBg/8BwMD+AgBh4ZBDQf/FIIABh4IBgAA==")); +const weatherSnowy = heatshrink.decompress(atob("h0OwYKHh/AAgUD+AKD/gIDn4LC/4ABBYX8DQYODgYPCAoIOCEAgpGDQRCHA=")); +const weatherFoggy = heatshrink.decompress(atob("h0OwYPMj/+AgU4gFwgED+ACBwEH8AMB/kB4AEBBAYAHg////H/+ABQl+n4LB/A9K")); +const weatherStormy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIRBBwPgAQMcgE4gfwn8D/wpGCgQAQA")); + let settings; function loadSettings() { - settings = require("Storage").readJSON("circlesclock.json", 1) || { + settings = storage.readJSON("circlesclock.json", 1) || { 'minHR': 40, 'maxHR': 200, 'stepGoal': 10000, @@ -48,13 +58,12 @@ const w = g.getWidth(); const hOffset = 30 - widgetOffset; const h1 = Math.round(1 * h / 5 - hOffset); const h2 = Math.round(3 * h / 5 - hOffset); -const h3 = Math.round(8 * h / 8 - hOffset - 3); -const w1 = Math.round(w / 6); -const w2 = Math.round(3 * w / 6); -const w3 = Math.round(5 * w / 6); +const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position +const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / 6)]; // cirle x positions const radiusOuter = 25; const radiusInner = 18; const circleFont = "Vector:15"; +const circleFontSmall = "Vector:13"; function draw() { g.clear(true); @@ -90,16 +99,17 @@ function draw() { g.drawString(locale.date(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2); g.drawString(locale.dow(new Date()), w > 180 ? 2 * w / 10 : w / 10, h2 + 22); - drawCircle(1, "steps"); - drawCircle(2, "hr"); - drawCircle(3, "battery"); + drawCircle(1); + drawCircle(2); + drawCircle(3); } +const defaultCircleTypes = ["steps", "hr", "battery"]; -function drawCircle(index, defaultType) { - const type = settings['circle' + index] || defaultType; - const w = index == 1 ? w1 : index == 2 ? w2 : w3; - +function drawCircle(index) { + let type = settings['circle' + index]; + if (!type) type = defaultCircleTypes[index - 1]; + const w = getCirclePosition(type); switch (type) { case "steps": drawSteps(w); @@ -113,15 +123,21 @@ function drawCircle(index, defaultType) { case "battery": drawBattery(w); break; + case "weather": + drawWeather(w); + break; } } -function getCirclePosition(type, defaultPos) { +function getCirclePosition(type) { for (let i = 1; i <= 3; i++) { const setting = settings['circle' + i]; - if (setting == type) return i == 1 ? w1 : i == 2 ? w2 : w3; + if (setting == type) return circlePosX[i - 1]; } - return defaultPos || undefined; + for (let i = 0; i < defaultCircleTypes.length; i++) { + if (type == defaultCircleTypes[i]) return circlePosX[i]; + } + return undefined; } function isCircleEnabled(type) { @@ -129,7 +145,7 @@ function isCircleEnabled(type) { } function drawSteps(w) { - if (!w) w = getCirclePosition("steps", w1); + if (!w) w = getCirclePosition("steps"); const steps = getSteps(); // Draw rectangle background: @@ -160,7 +176,7 @@ function drawSteps(w) { } function drawStepsDistance(w) { - if (!w) w = getCirclePosition("steps", w1); + if (!w) w = getCirclePosition("steps"); const steps = getSteps(); const stepDistance = settings.stepLength || 0.8; const stepsDistance = Math.round(steps * stepDistance); @@ -193,7 +209,7 @@ function drawStepsDistance(w) { } function drawHeartRate(w) { - if (!w) w = getCirclePosition("hr", w2); + if (!w) w = getCirclePosition("hr"); // Draw rectangle background: g.setColor(colorBg); @@ -222,7 +238,7 @@ function drawHeartRate(w) { } function drawBattery(w) { - if (!w) w = getCirclePosition("battery", w3); + if (!w) w = getCirclePosition("battery"); const battery = E.getBattery(); // Draw rectangle background: @@ -262,6 +278,85 @@ function drawBattery(w) { g.drawImage(icon, w - 6, h3 + radiusOuter - 6); } +function drawWeather(w) { + if (!w) w = getCirclePosition("weather"); + const weather = getWeather(); + const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + const code = weather ? weather.code : -1; + + // Draw rectangle background: + g.setColor(colorBg); + g.fillRect(w - radiusOuter - 3, h3 - radiusOuter - 3, w + radiusOuter + 3, h3 + radiusOuter + 3); + + g.setColor(colorGrey); + g.fillCircle(w, h3, radiusOuter); + + g.setColor(colorBg); + g.fillCircle(w, h3, radiusInner); + + g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + + const content = tempString ? tempString : "?"; + g.setFont(content.length < 4 ? circleFont : circleFontSmall); + g.setFontAlign(0, 0); + g.setColor(colorFg); + g.drawString(content, w, h3); + + if (code > 0) { + const icon = getWeatherIconByCode(code); + if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 6); + } +} + +/* + * Choose weather icon to display based on weather conditition code + * https://openweathermap.org/weather-conditions#Weather-Condition-Codes-2 + */ +function getWeatherIconByCode(code) { + const codeGroup = Math.round(code / 100); + switch (codeGroup) { + case 2: + return weatherStormy; + case 3: + return weatherCloudy; + case 5: + switch (code) { + case 511: + return weatherSnowy; + case 520: + return weatherPartlyRainy; + case 521: + return weatherPartlyRainy; + case 522: + return weatherPartlyRainy; + case 531: + return weatherPartlyRainy; + default: + return weatherRainy; + } + break; + case 6: + return weatherSnowy; + case 7: + return weatherFoggy; + case 8: + switch (code) { + case 800: + return weatherSunny; + case 801: + return weatherPartlyCloudy; + case 802: + return weatherPartlyCloudy; + default: + return weatherCloudy; + } + break; + default: + return undefined; + } + return undefined; +} + function radians(a) { return a * Math.PI / 180; } @@ -309,6 +404,11 @@ function getSteps() { return 0; } +function getWeather() { + const jsonWeather = storage.readJSON('weather.json'); + return jsonWeather && jsonWeather.weather ? jsonWeather.weather : undefined; +} + function enableHRMSensor() { Bangle.setHRMPower(1, "circleclock"); if (hrtValue == undefined) { diff --git a/apps/circlesclock/settings.js b/apps/circlesclock/settings.js index a16bb99a8..ac4215a8a 100644 --- a/apps/circlesclock/settings.js +++ b/apps/circlesclock/settings.js @@ -6,8 +6,8 @@ settings[key] = value; storage.write(SETTINGS_FILE, settings); } - var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery"]; - var namesCircleTypes = ["steps", "distance", "heart", "battery"]; + var valuesCircleTypes = ["steps", "stepsDist", "hr", "battery", "weather"]; + var namesCircleTypes = ["steps", "distance", "heart", "battery", "weather"]; E.showMenu({ '': { 'title': 'circlesclock' }, '< Back': back, @@ -78,19 +78,19 @@ }, 'left': { value: settings.circle1 ? valuesCircleTypes.indexOf(settings.circle1) : 0, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle1', valuesCircleTypes[x]), }, 'middle': { value: settings.circle2 ? valuesCircleTypes.indexOf(settings.circle2) : 2, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle2', valuesCircleTypes[x]), }, 'right': { value: settings.circle3 ? valuesCircleTypes.indexOf(settings.circle3) : 3, - min: 0, max: 3, + min: 0, max: 4, format: v => namesCircleTypes[v], onchange: x => save('circle3', valuesCircleTypes[x]), } From 209d05e6d68c5748f80b98298aaba1cacc68292a Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:24:36 +0100 Subject: [PATCH 154/202] Fix alarm not activating --- apps/qalarm/qalarm.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/qalarm/qalarm.js b/apps/qalarm/qalarm.js index 6b31ba645..8e82be186 100644 --- a/apps/qalarm/qalarm.js +++ b/apps/qalarm/qalarm.js @@ -143,7 +143,7 @@ let alarms = require("Storage").readJSON("qalarm.json", 1) || []; let active = alarms.filter( (alarm) => alarm.on && - alarm.t < t && + alarm.t <= t && alarm.last != time.getDate() && (alarm.timer || alarm.daysOfWeek[time.getDay()]) ); From 426ba76ad4012f14072d1694d36510977346665d Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:25:15 +0100 Subject: [PATCH 155/202] Update ChangeLog --- apps/qalarm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/qalarm/ChangeLog b/apps/qalarm/ChangeLog index fb6c751bb..b9be6039d 100644 --- a/apps/qalarm/ChangeLog +++ b/apps/qalarm/ChangeLog @@ -3,3 +3,4 @@ 0.03: Fix unfreed memory, and clearInterval that disabled all clocks at midnight Fix app icon Change menu order so 'back' is at the top +0.04: Fix alarm not activating sometimes. From ab00b477fd39f0304c12cdf407fcbd2d9fa42c16 Mon Sep 17 00:00:00 2001 From: Qucchia <45072410+qucchia@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:25:55 +0100 Subject: [PATCH 156/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..e0c85c2f3 100644 --- a/apps.json +++ b/apps.json @@ -4422,7 +4422,7 @@ "name": "Q Alarm and Timer", "shortName": "Q Alarm", "icon": "app.png", - "version": "0.03", + "version": "0.04", "description": "Alarm and timer app with days of week and 'hard' option.", "tags": "tool,alarm,widget", "supports": ["BANGLEJS", "BANGLEJS2"], From ea71f6a0ead902813e91d065363bcf6b288b7b70 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:39:45 +0100 Subject: [PATCH 157/202] Swedish localisation with English text (en_SE) --- apps/locale/locales.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index cf511c54f..fea217efe 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -283,6 +283,24 @@ var locales = { day: "söndag,måndag,tisdag,onsdag,torsdag,fredag,lördag", trans: { yes: "ja", Yes: "Ja", no: "nej", No: "Nej", ok: "ok", on: "on", off: "off" } }, + "en_SE": { // Swedish localisation with English text + lang: "en_SE", + decimal_point: ",", + thousands_sep: ".", + currency_symbol: "kr", + int_curr_symbol: "SKR", + speed: 'kmh', + distance: { "0": "m", "1": "km" }, + temperature: '°C', + ampm: { 0: "", 1: "" }, + timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, + datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // Sunday 1 March 2020 // 2020-03-01 + abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", + month: "January,February,March,April,May,June,July,August,September,October,November,December", + abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", + day: "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday", + // No translation for english... + }, "en_NZ": { lang: "en_NZ", decimal_point: ".", From efc8845c13434357cb7b1afd0d3d1058e572ebce Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:42:29 +0100 Subject: [PATCH 158/202] Update ChangeLog --- apps/locale/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 448f8119a..1b6f82671 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -14,3 +14,4 @@ 0.12: Fixed nl_NL formatting, because the full months won't fit on the Bangle.js2's screen 0.13: Now use shorter de_DE date format to more closely match other languages for size 0.14: Added some first translations for Messages in nl_NL +0.15: Added Swedish localisation with English text From 0a4f2dd5b928528d97194bdcee601c380b881b87 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Fri, 7 Jan 2022 16:43:12 +0100 Subject: [PATCH 159/202] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..f5a17c37d 100644 --- a/apps.json +++ b/apps.json @@ -218,7 +218,7 @@ { "id": "locale", "name": "Languages", - "version": "0.14", + "version": "0.15", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", From 9e0bef98ae313ccabc7117545f56d302953f7ec9 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:44:54 +0100 Subject: [PATCH 160/202] Add combination HID to bootupdate. --- apps/boot/bootupdate.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 664d64ee7..1b826de5a 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -18,6 +18,7 @@ boot += `var bleServices = {}, bleServiceOptions = { uart : true};\n`; if (s.ble!==false) { if (s.HID) { // Human interface device if (s.HID=="joy") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBKEBCQGhAAUJGQEpBRUAJQGVBXUBgQKVA3UBgQMFAQkwCTEVgSV/dQiVAoECwMA="));`; + else if (s.HID=="com") boot += `Bangle.HID = E.toUint8Array(atob("BQEJAqEBhQEJAaEABQkZASkFFQAlAZUFdQGBApUBdQOBAwUBCTAJMQk4FYElf3UIlQOBBgUMCjgCFYElf3UIlQGBBsDABQEJBqEBhQIFBxngKecVACUBdQGVCIECdQiVAYEBGQApcxUAJXOVBXUIgQDA"));` else if (s.HID=="kb") boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBBQcZ4CnnFQAlAXUBlQiBApUBdQiBAZUFdQEFCBkBKQWRApUBdQORAZUGdQgVACVzBQcZAClzgQAJBRUAJv8AdQiVArECwA=="));` else /*kbmedia*/boot += `Bangle.HID = E.toUint8Array(atob("BQEJBqEBhQIFBxngKecVACUBdQGVCIEClQF1CIEBlQV1AQUIGQEpBZEClQF1A5EBlQZ1CBUAJXMFBxkAKXOBAAkFFQAm/wB1CJUCsQLABQwJAaEBhQEVACUBdQGVAQm1gQIJtoECCbeBAgm4gQIJzYECCeKBAgnpgQIJ6oECwA=="));`; boot += `bleServiceOptions.hid=Bangle.HID;\n`; From 47da82a547e82e29228c3d0a86c2992e71fafb90 Mon Sep 17 00:00:00 2001 From: 7kasper <7kasper@users.noreply.github.com> Date: Fri, 7 Jan 2022 16:48:15 +0100 Subject: [PATCH 161/202] Add HID option to settings. --- apps/setting/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 4bdf7f304..27ce24e50 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -154,8 +154,8 @@ function showAlertsMenu() { function showBLEMenu() { - var hidV = [false, "kbmedia", "kb", "joy"]; - var hidN = ["Off", "Kbrd & Media", "Kbrd","Joystick"]; + var hidV = [false, "kbmedia", "kb", "com", "joy"]; + var hidN = ["Off", "Kbrd & Media", "Kbrd", "Kbrd & Mouse" ,"Joystick"]; E.showMenu({ '': { 'title': 'Bluetooth' }, '< Back': ()=>showMainMenu(), From 83debe93ee54ef1d01f78e572dc2c1a2d7dee66e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 18:21:36 +0100 Subject: [PATCH 162/202] Bigger weather icons & a bit thinner circles --- apps/circlesclock/app.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 23be307b9..f93a283f2 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -9,14 +9,14 @@ const powerIcon = heatshrink.decompress(atob("h0OwYQNsAED7AEDmwEDtu2AgUbtuABwXbB const powerIconGreen = heatshrink.decompress(atob("h0OwYQNkAEDpAEDiQEDkmSAgUJkmABwVJBIUEyVAAoYOCgEBFIgODABI")); const powerIconRed = heatshrink.decompress(atob("h0OwYQNoAEDyAEDkgEDpIFDiVJBweSAgUJkmAAoYZDgQpEBwYAJA")); -const weatherCloudy = heatshrink.decompress(atob("h0OwYPMgfwAgU//4FCv///+Ag4DB//gh4EC//jAgYAK+IED8EBAgXAHpQA==")); -const weatherSunny = heatshrink.decompress(atob("h0OwYKHhuAAYM2AQkA7AOD2wFCgdt20AgOA7dtwHAC4PbsAUGgFt2ApIAAgIIA==")); -const weatherPartlyCloudy = heatshrink.decompress(atob("h0OwYOLg4FEn/8AgV+g/gAgMcgE48EB48f/wJBgP/gfwgEDBAIRBC4UH/kB4AmC8F+C4X4gf/AAIaBAAgA==")); -const weatherRainy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIXD8ARB/kAnED+P/8f+BgNwnARCjkOAgUH/+AAoU/IQ4A=")); +const weatherCloudy = heatshrink.decompress(atob("iEQwYWTgP//+AAoMPAoPwAoN/AocfAgP//0AAgQAB/AFEABgdDAAMDDohMRA")); +const weatherSunny = heatshrink.decompress(atob("iEQwYLIg3AAgVgAQMMAo8Am3YAgUB23bAoUNAoIUBjYFCsOwBYoFDDpFgHYI1JI4gFGAAYA=")); +const weatherPartlyCloudy = heatshrink.decompress(atob("iEQwYQNv0AjgGDn4EDh///gFChwREC4MfxwIBv0//+AC4X4j4FCv/AgfwgED/wIBuAaBBwgFDgP4gf/AAXABwIEBDQQAEA==")); +const weatherRainy = heatshrink.decompress(atob("iEQwYLIg/gAgUB///wAFBh/AgfwgED/wIBuEAj4OCv0AjgaCh/4AocAnAFBFIU4EAM//gRBEAIOBhw1C/AmDAosAC4JNIAAg")); const weatherPartlyRainy = heatshrink.decompress(atob("h0OwYJGjkAnAFCj+AAgU//4FCuEA8EAg8ch/4gEB4////AAoIIBCIMD/wgCg4bBg/8BwMD+AgBh4ZBDQf/FIIABh4IBgAA==")); -const weatherSnowy = heatshrink.decompress(atob("h0OwYKHh/AAgUD+AKD/gIDn4LC/4ABBYX8DQYODgYPCAoIOCEAgpGDQRCHA=")); -const weatherFoggy = heatshrink.decompress(atob("h0OwYPMj/+AgU4gFwgED+ACBwEH8AMB/kB4AEBBAYAHg////H/+ABQl+n4LB/A9K")); -const weatherStormy = heatshrink.decompress(atob("h0OwYKHh/AAgX8AoUB/EAuEAj/wgEDwEHCIX/wIRBBwPgAQMcgE4gfwn8D/wpGCgQAQA")); +const weatherSnowy = heatshrink.decompress(atob("iEQwYROn/8AocH8AECuAFBh0Agf+CIN/4EDx/4j/x4EAgIIBwAXBAogRFDoopFGoxBGABIA=")); +const weatherFoggy = heatshrink.decompress(atob("iEQwYROn/8AgUB/EfwAFBh/AgfwgED/wIBuEABwd/4EcDQgFDgE4Fosf///8f//A/Lj/xCQIRNA=")); +const weatherStormy = heatshrink.decompress(atob("iEQwYLIg/gAgUB///wAFBh/AgfwgED/wIBuEAj4OCv0AjgaCh/4AoX8gE4AoQpBnAdBF4IRBDQMH/kOHgY7DAo4AOA==")); let settings; @@ -61,7 +61,7 @@ const h2 = Math.round(3 * h / 5 - hOffset); const h3 = Math.round(8 * h / 8 - hOffset - 3); // circle y position const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / 6)]; // cirle x positions const radiusOuter = 25; -const radiusInner = 18; +const radiusInner = 20; const circleFont = "Vector:15"; const circleFontSmall = "Vector:13"; @@ -292,9 +292,9 @@ function drawWeather(w) { g.fillCircle(w, h3, radiusOuter); g.setColor(colorBg); - g.fillCircle(w, h3, radiusInner); + g.fillCircle(w, h3, radiusInner + 1); // the weather circle is thinner - g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); + g.fillPoly([w, h3, w - 25, h3 + radiusOuter + 5, w + 25, h3 + radiusOuter + 5]); const content = tempString ? tempString : "?"; g.setFont(content.length < 4 ? circleFont : circleFontSmall); @@ -304,7 +304,7 @@ function drawWeather(w) { if (code > 0) { const icon = getWeatherIconByCode(code); - if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 6); + if (icon) g.drawImage(icon, w - 6, h3 + radiusOuter - 10); } } @@ -375,7 +375,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = radiusOuter - radiusInner - 2; + const size = radiusOuter - radiusInner - 3; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); From 8bbe2a43b40a2a2f6bc48b17f934ac2c413a3a86 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Fri, 7 Jan 2022 18:33:09 +0100 Subject: [PATCH 163/202] Same size for every circle --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index f93a283f2..6d408fd59 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -292,7 +292,7 @@ function drawWeather(w) { g.fillCircle(w, h3, radiusOuter); g.setColor(colorBg); - g.fillCircle(w, h3, radiusInner + 1); // the weather circle is thinner + g.fillCircle(w, h3, radiusInner); g.fillPoly([w, h3, w - 25, h3 + radiusOuter + 5, w + 25, h3 + radiusOuter + 5]); From 6a72aafc1919f4440051a20424c13dd12953e635 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Fri, 7 Jan 2022 20:18:17 +0100 Subject: [PATCH 164/202] layout: use 'col' for btn label/image --- modules/Layout.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/Layout.js b/modules/Layout.js index 65e9a8dc8..cb64183ea 100644 --- a/modules/Layout.js +++ b/modules/Layout.js @@ -34,7 +34,7 @@ layoutObject has: optional `scale` specifies if image should be scaled up or not * `"custom"` - a custom block where `render(layoutObj)` is called to render * `"h"` - Horizontal layout, `c` is an array of more `layoutObject` - * `"v"` - Veritical layout, `c` is an array of more `layoutObject` + * `"v"` - Vertical layout, `c` is an array of more `layoutObject` * A `id` field. If specified the object is added with this name to the returned `layout` object, so can be referenced as `layout.foo` * A `font` field, eg `6x8` or `30%` to use a percentage of screen height @@ -261,6 +261,7 @@ Layout.prototype.render = function (l) { x,y+4 ], bg = l.selected?g.theme.bgH:g.theme.bg2; g.setColor(bg).fillPoly(poly).setColor(l.selected ? g.theme.fgH : g.theme.fg2).drawPoly(poly); + if (l.col) g.setColor(l.col); if (l.src) g.setBgColor(bg).drawImage("function"==typeof l.src?l.src():l.src, l.x + 10 + (0|l.pad), l.y + 8 + (0|l.pad)); else g.setFont("6x8",2).setFontAlign(0,0,l.r).drawString(l.label,l.x+l.w/2,l.y+l.h/2); }, "img":function(l){ From a3d1494318039c39d464204cc654e76cf321dc53 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 20:34:23 +0100 Subject: [PATCH 165/202] update tags mmind , remove spaces. --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 663cb1ae3..5dd4331f9 100644 --- a/apps.json +++ b/apps.json @@ -5134,7 +5134,7 @@ "version":"0.01", "description": "This is the classic game for masterminds", "type": "game", - "tags": "mastermind, game, classic", + "tags": "game,app", "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, From 0ee13c2fffc9902cb9d9351004491fe7da7ee768 Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Fri, 7 Jan 2022 21:05:46 +0100 Subject: [PATCH 166/202] added screenshot to mmind app --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 5dd4331f9..3321f822f 100644 --- a/apps.json +++ b/apps.json @@ -5133,6 +5133,7 @@ "icon": "mmind.png", "version":"0.01", "description": "This is the classic game for masterminds", + "screenshots": [{"url":"screenshot_mmind.png"}], "type": "game", "tags": "game,app", "readme":"README.md", From c8ea4c55b3e743ceee9350a091fcd80d63023826 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 22:43:49 +0000 Subject: [PATCH 167/202] Limelight, switched to bolted hands, redid screenshots --- apps/limelight/README.md | 1 + apps/limelight/limelight.app.js | 98 +++++++++++++++++------- apps/limelight/screenshot_gochihand.png | Bin 2332 -> 2452 bytes apps/limelight/screenshot_grenadier.png | Bin 2376 -> 2646 bytes apps/limelight/screenshot_limelight.png | Bin 2425 -> 2573 bytes apps/limelight/screenshot_monoton.png | Bin 3032 -> 2993 bytes 6 files changed, 71 insertions(+), 28 deletions(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index f1cc52092..e84714403 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -6,6 +6,7 @@ * Selection of different fonts * Settings menu where you can select font, or switch to Vector font and try a range of sizes * 100 less lines of code, demonstrating that there is no need for a custom widget draw method +* Full screen options (widgets loaded but not displayed) ![](screenshot_gochihand.png) ![](screenshot_monoton.png) diff --git a/apps/limelight/limelight.app.js b/apps/limelight/limelight.app.js index 2d4ce5a43..20d79deeb 100644 --- a/apps/limelight/limelight.app.js +++ b/apps/limelight/limelight.app.js @@ -1,3 +1,14 @@ +/* + * Limelight analoguce clock with bolted hands + * Based on the work of @Andreas_Rozek + * [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock) + * + * . Demonstrates simpler approach to establishing the available size of the appRect in relation + * to widgets, avoids having to take on the responsibility for managing the widget draw. + * . Demonstrates a settings menu and various configuration options + * . Demonstrates fullscreen verses, widgets and app area. + * + */ g.clear(); @@ -78,7 +89,7 @@ if (settings.fullscreen) { } function debug(o) { - console.log(o); + //console.log(o); } debug("limelight.app.js"); @@ -88,35 +99,54 @@ debug("outerRadius=" + outerRadius); debug("y12=" + (CenterY - outerRadius)); debug("y6=" + (CenterY + outerRadius)); -const HourHandLength = outerRadius * 0.5; -const HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; -const MinuteHandLength = outerRadius * 0.7; -const MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; -const SecondHandLength = outerRadius * 0.9; -const SecondHandOffset = 6; +let HourHandLength = outerRadius * 0.5; +let HourHandWidth = 2*5, halfHourHandWidth = HourHandWidth/2; -const twoPi = 2*Math.PI; -const Pi = Math.PI; -const halfPi = Math.PI/2; +let MinuteHandLength = outerRadius * 0.7; +let MinuteHandWidth = 2*3, halfMinuteHandWidth = MinuteHandWidth/2; -let HourHandPolygon = [ - -halfHourHandWidth,halfHourHandWidth, - -halfHourHandWidth,halfHourHandWidth-HourHandLength, - halfHourHandWidth,halfHourHandWidth-HourHandLength, - halfHourHandWidth,halfHourHandWidth, +let SecondHandLength = outerRadius * 0.9; +let SecondHandOffset = halfHourHandWidth + 10; + +let outerBoltRadius = halfHourHandWidth + 2, innerBoltRadius = outerBoltRadius - 4; +let HandOffset = outerBoltRadius + 4; + +let twoPi = 2*Math.PI, deg2rad = Math.PI/180; +let Pi = Math.PI; +let halfPi = Math.PI/2; + +let sin = Math.sin, cos = Math.cos; + +let sine = [0, sin(30*deg2rad), sin(60*deg2rad), 1]; + +let HandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0], ]; -let MinuteHandPolygon = [ - -halfMinuteHandWidth,halfMinuteHandWidth, - -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, - halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, - halfMinuteHandWidth,halfMinuteHandWidth, -]; +let HourHandPolygon = new Array(HandPolygon.length); +for (let i = 0, l = HandPolygon.length; i < l; i+=2) { + HourHandPolygon[i] = halfHourHandWidth*HandPolygon[i]; + HourHandPolygon[i+1] = halfHourHandWidth*HandPolygon[i+1]; + if (i < l/2) { HourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { HourHandPolygon[i+1] += HandOffset; } +} +let MinuteHandPolygon = new Array(HandPolygon.length); +for (let i = 0, l = HandPolygon.length; i < l; i+=2) { + MinuteHandPolygon[i] = halfMinuteHandWidth*HandPolygon[i]; + MinuteHandPolygon[i+1] = halfMinuteHandWidth*HandPolygon[i+1]; + if (i < l/2) { MinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { MinuteHandPolygon[i+1] += HandOffset; } +} -let transformedPolygon = new Array(HourHandPolygon.length); +/**** transforme polygon ****/ + +let transformedPolygon = new Array(HandPolygon.length); function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { - let sPhi = Math.sin(Phi), cPhi = Math.cos(Phi), x,y; + let sPhi = sin(Phi), cPhi = cos(Phi), x,y; for (let i = 0, l = originalPolygon.length; i < l; i+=2) { x = originalPolygon[i]; @@ -127,8 +157,11 @@ function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { } } -function drawHands () { +/**** draw clock hands ****/ + +function drawClockHands () { let now = new Date(); + let Hours = now.getHours() % 12; let Minutes = now.getMinutes(); let Seconds = now.getSeconds(); @@ -138,14 +171,17 @@ function drawHands () { let SecondsAngle = (Seconds/60) * twoPi - Pi; g.setColor(g.theme.fg); + transformPolygon(HourHandPolygon, CenterX,CenterY, HoursAngle); g.fillPoly(transformedPolygon); + transformPolygon(MinuteHandPolygon, CenterX,CenterY, MinutesAngle); g.fillPoly(transformedPolygon); + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + if (settings.secondhand) { - let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); - g.setColor('#FF0000'); + g.setColor(g.theme.fg2); g.drawLine( CenterX + SecondHandOffset*sPhi, CenterY - SecondHandOffset*cPhi, @@ -153,6 +189,13 @@ function drawHands () { CenterY + SecondHandLength*cPhi ); } + + g.setColor(g.theme.fg); + g.fillCircle(CenterX,CenterY, outerBoltRadius); + + g.setColor(g.theme.bg); + g.drawCircle(CenterX,CenterY, outerBoltRadius); + g.fillCircle(CenterX,CenterY, innerBoltRadius); } function setNumbersFont() { @@ -192,7 +235,7 @@ function draw() { g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); - drawHands(); + drawClockHands(); drawNumbers(); queueDraw(); } @@ -216,6 +259,5 @@ Bangle.on('lcdPower',on=>{ } }); -loadSettings(); Bangle.setUI('clock'); draw(); diff --git a/apps/limelight/screenshot_gochihand.png b/apps/limelight/screenshot_gochihand.png index af405c0f8406505893cedcbac16da25ea1e27804..244b008dc2f56804bcb252a7f89dd49339c6e0f7 100644 GIT binary patch literal 2452 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 O2pnu&PtdK18UF>*lD-=N delta 2353 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 Ce0p>M literal 2425 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 BY>NN@ diff --git a/apps/limelight/screenshot_monoton.png b/apps/limelight/screenshot_monoton.png index d17d9bd26e9795c28c427f37ca8407db63b3f5b8..e75b11f5daaceca3fc7ee629ee942e822dca01bb 100644 GIT binary patch delta 2974 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 Date: Fri, 7 Jan 2022 23:46:24 +0100 Subject: [PATCH 168/202] menuwheel: override Bangle.setUI to clear up touch handler Because apps/libraries expect setUI to clean up touch handlers. --- apps.json | 2 +- apps/menuwheel/ChangeLog | 1 + apps/menuwheel/boot.js | 10 ++++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..56691d2d4 100644 --- a/apps.json +++ b/apps.json @@ -4805,7 +4805,7 @@ { "id": "menuwheel", "name": "Wheel Menus", - "version": "0.01", + "version": "0.02", "description": "Replace Bangle.js 2's menus with a version that contains variable-size text and a back button", "readme": "README.md", "icon": "icon.png", diff --git a/apps/menuwheel/ChangeLog b/apps/menuwheel/ChangeLog index defdb5049..050cf2049 100644 --- a/apps/menuwheel/ChangeLog +++ b/apps/menuwheel/ChangeLog @@ -1 +1,2 @@ 0.01: New menu! +0.02: Clean up touch handler in setUI diff --git a/apps/menuwheel/boot.js b/apps/menuwheel/boot.js index 3e708e9a8..deb15264d 100644 --- a/apps/menuwheel/boot.js +++ b/apps/menuwheel/boot.js @@ -1,8 +1,5 @@ E.showMenu = function(items) { g.clearRect(Bangle.appRect); // clear screen if no menu supplied - // clean up back button listener - if (Bangle.backHandler) Bangle.removeListener('touch', Bangle.backHandler) - delete Bangle.backHandler; if (!items) { Bangle.setUI(); return; @@ -206,8 +203,13 @@ E.showMenu = function(items) { if (b===1) back(); } } - // note: backHandler is cleaned up at the top of this file Bangle.on('touch', Bangle.backHandler); } return l; }; +// setUI now also needs to clear up our back button touch handler +Bangle.setUI = (old => function() { + if (Bangle.backHandler) Bangle.removeListener("touch", Bangle.backHandler); + delete Bangle.backHandler; + return old.apply(this, arguments); +})(Bangle.setUI); \ No newline at end of file From ebfedfd18b1220b00cc6cf7ec64663e56d440377 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 22:55:43 +0000 Subject: [PATCH 169/202] fixed apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ddacceca..7d0789953 100644 --- a/apps.json +++ b/apps.json @@ -5483,4 +5483,4 @@ {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] } -} +] From 2a2c26393fafe60c5509f15157fed98d575023e5 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 23:11:14 +0000 Subject: [PATCH 170/202] limelight README tweak --- apps/limelight/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index e84714403..e7c13a139 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -5,14 +5,14 @@ * Selection of different fonts * Settings menu where you can select font, or switch to Vector font and try a range of sizes -* 100 less lines of code, demonstrating that there is no need for a custom widget draw method -* Full screen options (widgets loaded but not displayed) +* Reduction by 100 lines of code, demonstrating that there is no need for a custom widget draw method +* Full screen option (widgets are loaded but not displayed) ![](screenshot_gochihand.png) ![](screenshot_monoton.png) ![](screenshot_grenadier.png) -Many thanks for @Andreas_Rozek for his pioneering work on building a toolkit for the Bangle 2. +Many thanks for @Andreas_Rozek for his pioneering work on building an analogue clock toolkit for the Bangle 2. Limelight Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From 597efeab00c8f9a9caf106e6c366e2c66dfefbf4 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 7 Jan 2022 23:14:15 +0000 Subject: [PATCH 171/202] limelight README tweak --- apps/limelight/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/limelight/README.md b/apps/limelight/README.md index e7c13a139..49b858127 100644 --- a/apps/limelight/README.md +++ b/apps/limelight/README.md @@ -1,5 +1,5 @@ # Limelight - * Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* + *Simple configurable analogue clock based on the work of @Andreas_Rozek [Simple_Clock](https://github.com/espruino/BangleApps/tree/master/apps/simple_clock)* ![](screenshot_limelight.png) From 049555a08dd3083b956c8df0e44575f9148e5add Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sat, 8 Jan 2022 00:25:43 +0000 Subject: [PATCH 172/202] Simplest, switched to queueDraw() method, update once per minute --- apps.json | 2 +- apps/simplest/ChangeLog | 1 + apps/simplest/app.js | 66 ++++++++++++++++++++++++++++++----------- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/apps.json b/apps.json index 7d0789953..1f4e983e6 100644 --- a/apps.json +++ b/apps.json @@ -3794,7 +3794,7 @@ { "id": "simplest", "name": "Simplest Clock", - "version": "0.03", + "version": "0.04", "description": "The simplest working clock, acts as a tutorial piece", "icon": "simplest.png", "screenshots": [{"url":"screenshot_simplest.png"}], diff --git a/apps/simplest/ChangeLog b/apps/simplest/ChangeLog index f37015d6a..c5ceb7a44 100644 --- a/apps/simplest/ChangeLog +++ b/apps/simplest/ChangeLog @@ -1,3 +1,4 @@ 0.01: Modified for use with new bootloader and firmware 0.02: Use Bangle.setUI for button/launcher handling 0.03: Fix display for Bangle 2 +0.04: Use queueDraw(), update every minute, respect theme, use Lato font diff --git a/apps/simplest/app.js b/apps/simplest/app.js index 68564ff33..85ccc1509 100644 --- a/apps/simplest/app.js +++ b/apps/simplest/app.js @@ -1,28 +1,60 @@ - const h = g.getHeight(); const w = g.getWidth(); -function draw() { - var d = new Date(); - var da = d.toString().split(" "); - var time = da[4].substr(0,5); - - g.reset(); - g.clearRect(0, 30, w, 99); - g.setFontAlign(0, -1); - g.setFont("Vector", w/3); - g.drawString(time, w/2, 40); +// from fonts.google.com +Graphics.prototype.setFontLato = function(scale) { + // Actual height 50 (53 - 4) + this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAP4AAAAAAAAD/gAAAAAAAAf8AAAAAAAAD/gAAAAAAAAP4AAAAAAAAB/AAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAfAAAAAAAAAf4AAAAAAAAP/AAAAAAAAP/wAAAAAAAH/4AAAAAAAH/8AAAAAAAH/8AAAAAAAD/+AAAAAAAD/+AAAAAAAB//AAAAAAAB//AAAAAAAA//gAAAAAAA//gAAAAAAAf/gAAAAAAAf/wAAAAAAAP/wAAAAAAAP/4AAAAAAAH/4AAAAAAAB/8AAAAAAAAf8AAAAAAAAD+AAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//gAAAAAAf///gAAAAAf////gAAAAH/////AAAAD/////8AAAA//////wAAAP/4AB//AAAD/wAAA/8AAA/wAAAA/wAAH8AAAAD+AAB/AAAAAP4AAPwAAAAA/AAB8AAAAAD4AAPgAAAAAfAAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAPgAAAAAfAAB+AAAAAH4AAPwAAAAA/AAA/AAAAAPwAAH+AAAAH+AAAf8AAAB/gAAD/4AAB/8AAAP//gf//AAAA//////wAAAB/////4AAAAH////+AAAAAP////AAAAAAP///AAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADgAAAAAAAAA+AAAAAAAAAPwAAAD4AAAD+AAAAfAAAA/gAAAD4AAAP4AAAAfAAAD+AAAAD4AAA/wAAAAfAAAH8AAAAD4AAB/AAAAAfAAAfwAAAAD4AAH8AAAAAfAAB///////4AAP///////AAB///////4AAP///////AAB///////4AAP///////AAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAHAAAAD4AAAH4AAAA/AAAB/AAAAP4AAA/4AAAD/AAAP/AAAA/4AAD/4AAAP/AAAf4AAAD/4AAH8AAAA//AAA/AAAAP74AAPwAAAD+fAAB+AAAA/n4AAPgAAAP4/AAD8AAAD+H4AAfgAAA/g/AAD8AAAP4H4AAfgAAD+A/AAD8AAA/gH4AAfgAAP4A/AAB8AAH+AH4AAPwAB/gA/AAB/AA/4AH4AAH8Af+AA/AAA////gAH4AAD///wAA/AAAP//8AAH4AAA///AAA/AAAD//gAAH4AAAH/wAAA/AAAAHwAAAD4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAA8AAAAAPAAAP4AAAAP4AAB/gAAAD/AAAP/AAAA/4AAB/4AAAP/AAAD/gAAD/wAAAH+AAA/wAAAAfwAAH8AAAAB/AAB/AAAAAH4AAPwAAAAAfAAB8AAAAAD8AAPgADwAAfgAD8AAeAAD8AAfgADwAAfgAD8AAfAAD8AAfgAH4AAfgAD8AA/AAD8AAPgAH4AAfAAB+AB/gAH4AAPwAP8AA/AAB/AD/wAPwAAH+B+/AH+AAA///3+D/gAAD//8f//8AAAP//D///AAAA//wP//wAAAB/8A//8AAAAD8AB/+AAAAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAH4AAAAAAAAD/AAAAAAAAA/4AAAAAAAAP/AAAAAAAAH/4AAAAAAAB//AAAAAAAAf74AAAAAAAP+fAAAAAAAD/D4AAAAAAA/wfAAAAAAAf8D4AAAAAAH+AfAAAAAAD/gD4AAAAAA/4AfAAAAAAP8AD4AAAAAH/AAfAAAAAB/gAD4AAAAAf4AAfAAAAAP+AAD4AAAAD/AAAfAAAAA/wAAD4AAAAP///////AAB///////4AAP///////AAB///////4AAP///////AAB///////4AAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA4AAAAAAAAAPgAAAAB/AAD8AAAAH/4AAfwAAA///AAB+AAB///4AAP4AAP///AAA/AAB///4AAH4AAP/gfAAAfAAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AH4AAD4AAPwA/AAAfAAB+AH4AAH4AAPwAfgAB/AAB+AD8AAfwAAPwAf4AH+AAB+AB/gD/gAAPwAP///4AAB+AA///+AAAPgAD///gAAB8AAP//4AAAPAAAf/8AAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAAB//gAAAAAAA///AAAAAAAf//8AAAAAAH///4AAAAAD////AAAAAA//gf8AAAAAP/wAfwAAAAH/8AB+AAAAB//AAH4AAAA//wAA/AAAAP+8AAD4AAAD/ngAAfgAAB/58AAD8AAAf8PgAAfgAAH/B8AAD8AAD/wPgAAfgAA/8B8AAD8AAP+APgAAfAAB/gB8AAD4AAP4APwAA/AAB8AB+AAH4AAPAAH4AB+AABwAA/wA/wAAIAAD/gf8AAAAAAf///AAAAAAB///wAAAAAAH//8AAAAAAAf//AAAAAAAA//gAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAAPgAAAAAAAAB+AAAAAAAAAPwAAAAAAAAB+AAAAAAAAAPwAAAAADAAB+AAAAAB4AAPwAAAAA/AAB+AAAAAf4AAPwAAAAP/AAB+AAAAH/4AAPwAAAD/+AAB+AAAB//AAAPwAAA//gAAB+AAAf/wAAAPwAAP/4AAAB+AAH/8AAAAPwAD/+AAAAB+AB//AAAAAPwA//gAAAAB+Af/gAAAAAPwP/wAAAAAB+H/4AAAAAAPz/8AAAAAAB//+AAAAAAAP//AAAAAAAB//gAAAAAAAP/wAAAAAAAB/4AAAAAAAAP8AAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAHgAP/4AAAAH/gD//gAAAD//A///AAAA//8P//4AAAP//z///gAAD//+fwP+AAA/4f/4AfwAAH4A/+AB/AAB+AB/gAH4AAPgAH8AAfAAB8AA/AAD4AAfgAH4AAfgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAD8AAPgAH4AAfAAB8AA/gAD4AAPwAP8AA/AAA/AD/wAH4AAH8B//AB+AAAf//78A/wAAD//+f//8AAAP//h///gAAA//4P//4AAAB/+A//+AAAAD/AD//gAAAAAAAH/wAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAf/gAAAAAAAP/+AAAAAAAD//8AAAAAAA///wAAAAAAP///AAAAAAD///4AADAAA/wB/gAA4AAH8AD8AAPAAB/AAPwAH4AAPwAB+AB/AAB8AAHwAf4AAPgAA+AP/AAD8AAHwD/wAAfgAA+A/8AAD8AAHwf+AAAfgAA+H/gAAD8AAHx/wAAAPgAA8/8AAAB8AAPv/AAAAPwAB//gAAAB/AAf/4AAAAH8AH/8AAAAA/wD//AAAAAD////gAAAAAP///4AAAAAA///8AAAAAAD//+AAAAAAAH//AAAAAAAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAHwAAAAB+AAB/AAAAAf4AAP4AAAAD/AAD/gAAAAf4AAf8AAAAD/AAB/AAAAAPwAAP4AAAAA8AAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DRclJSUlJSUlJSUlEA=="), 63+(scale<<8)+(1<<16)); + return this; } -// handle switch display on by pressing BTN1 -Bangle.on('lcdPower', function(on) { - if (on) draw(); +function draw() { + var date = new Date(); + var timeStr = require("locale").time(date,1); + var dateStr = require("locale").date(date).toUpperCase(); + + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(Bangle.appRect); + + g.setFontLato(); + g.setFontAlign(0, -1); + g.setColor(g.theme.fg); + g.drawString(timeStr, w/2, h/3); + + g.setFont("6x8",2); + g.setFontAlign(0,0) + g.drawString(dateStr, w/2, h - 24 - 24); + + queueDraw(); +} + +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +// Stop updates when LCD is off, restart when on +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } }); g.clear(); +// Show launcher when middle button pressed +Bangle.setUI("clock"); +// Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); -setInterval(draw, 15000); // refresh every 15s draw(); -// Show launcher when button pressed -Bangle.setUI("clock"); From 968e7b5840fdf95f1b3b5300a964b77ab788ab8a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sat, 8 Jan 2022 10:25:24 +0100 Subject: [PATCH 173/202] Make text size in heart rate circle slightly bigger as it does not have any units --- apps/circlesclock/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 6d408fd59..3843d5dda 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -63,6 +63,7 @@ const circlePosX = [Math.round(w / 6), Math.round(3 * w / 6), Math.round(5 * w / const radiusOuter = 25; const radiusInner = 20; const circleFont = "Vector:15"; +const circleFontBig = "Vector:16"; const circleFontSmall = "Vector:13"; function draw() { @@ -229,7 +230,7 @@ function drawHeartRate(w) { g.fillPoly([w, h3, w - 15, h3 + radiusOuter + 5, w + 15, h3 + radiusOuter + 5]); - g.setFont(circleFont); + g.setFont(circleFontBig); g.setFontAlign(0, 0); g.setColor(colorFg); g.drawString(hrtValue != undefined ? hrtValue : "-", w, h3); From 04129c82818dbd956ed4f7b13d103b7754a02a1e Mon Sep 17 00:00:00 2001 From: Peter Slendebroek Date: Sat, 8 Jan 2022 13:58:47 +0100 Subject: [PATCH 174/202] changed type to app of mmind app --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3321f822f..5153e3deb 100644 --- a/apps.json +++ b/apps.json @@ -5134,8 +5134,8 @@ "version":"0.01", "description": "This is the classic game for masterminds", "screenshots": [{"url":"screenshot_mmind.png"}], - "type": "game", - "tags": "game,app", + "type": "app", + "tags": "game", "readme":"README.md", "supports": ["BANGLEJS2"], "allow_emulator": true, From a1ebca296cf3f09ab8974610c23307ffb5cf76f9 Mon Sep 17 00:00:00 2001 From: Marcus Olsson Date: Sat, 8 Jan 2022 21:15:32 +0100 Subject: [PATCH 175/202] Fixed sv_SE formatting Long date does not work well for Bangle.js2 This aligns with default locale en_GB. --- apps.json | 2 +- apps/locale/ChangeLog | 1 + apps/locale/locales.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..f5a17c37d 100644 --- a/apps.json +++ b/apps.json @@ -218,7 +218,7 @@ { "id": "locale", "name": "Languages", - "version": "0.14", + "version": "0.15", "description": "Translations for different countries", "icon": "locale.png", "type": "locale", diff --git a/apps/locale/ChangeLog b/apps/locale/ChangeLog index 448f8119a..198322fb2 100644 --- a/apps/locale/ChangeLog +++ b/apps/locale/ChangeLog @@ -14,3 +14,4 @@ 0.12: Fixed nl_NL formatting, because the full months won't fit on the Bangle.js2's screen 0.13: Now use shorter de_DE date format to more closely match other languages for size 0.14: Added some first translations for Messages in nl_NL +0.15: Fixed sv_SE formatting, long date does not work well for Bangle.js2 diff --git a/apps/locale/locales.js b/apps/locale/locales.js index cf511c54f..1626b744f 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -276,7 +276,7 @@ var locales = { temperature: "°C", ampm: { 0: "fm", 1: "em" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // söndag 1 mars 2020 // 2020-03-01 + datePattern: { 0: "%b %d %Y", "1": "%Y-%m-%d" }, // feb 1 2020 // 2020-03-01 abmonth: "jan,feb,mars,apr,maj,juni,juli,aug,sep,okt,nov,dec", month: "januari,februari,mars,april,maj,juni,juli,augusti,september,oktober,november,december", abday: "sön,mån,tis,ons,tors,fre,lör", From 4341efb46a358612bce0c11ca259abd0109f374d Mon Sep 17 00:00:00 2001 From: hughbarney Date: Sat, 8 Jan 2022 20:43:06 +0000 Subject: [PATCH 176/202] Updated simplest to make it simpler, tweak to Pastel to make it cycle better --- apps.json | 4 ++-- apps/pastel/ChangeLog | 1 + apps/pastel/pastel.app.js | 2 +- apps/simplest/ChangeLog | 2 ++ apps/simplest/app.js | 27 +++++++++++---------------- 5 files changed, 17 insertions(+), 19 deletions(-) diff --git a/apps.json b/apps.json index 1f4e983e6..2d87b2f73 100644 --- a/apps.json +++ b/apps.json @@ -3794,7 +3794,7 @@ { "id": "simplest", "name": "Simplest Clock", - "version": "0.04", + "version": "0.05", "description": "The simplest working clock, acts as a tutorial piece", "icon": "simplest.png", "screenshots": [{"url":"screenshot_simplest.png"}], @@ -4215,7 +4215,7 @@ "id": "pastel", "name": "Pastel Clock", "shortName": "Pastel", - "version": "0.10", + "version": "0.11", "description": "A Configurable clock with custom fonts, background and weather display. Has a cyclic information line that includes, day, date, battery, sunrise and sunset times", "icon": "pastel.png", "dependencies": {"mylocation":"app", "widpedom":"app","weather":"app"}, diff --git a/apps/pastel/ChangeLog b/apps/pastel/ChangeLog index 627531f03..00090fcd1 100644 --- a/apps/pastel/ChangeLog +++ b/apps/pastel/ChangeLog @@ -8,3 +8,4 @@ 0.08: Added dependancy on MyLocation 0.09: Added dependancy on Pedometer Widget 0.10: Added Weather line, fixed issues on a Bangle 1, update every minute +0.11: Changed cycle on minute to prevInfo to avoid the 2nd one being the blank line diff --git a/apps/pastel/pastel.app.js b/apps/pastel/pastel.app.js index db60a2738..3e64cdd9c 100644 --- a/apps/pastel/pastel.app.js +++ b/apps/pastel/pastel.app.js @@ -255,7 +255,7 @@ function queueDraw() { if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; - nextInfo(); + prevInfo(); draw(); }, 60000 - (Date.now() % 60000)); } diff --git a/apps/simplest/ChangeLog b/apps/simplest/ChangeLog index c5ceb7a44..e7ab5f2c3 100644 --- a/apps/simplest/ChangeLog +++ b/apps/simplest/ChangeLog @@ -2,3 +2,5 @@ 0.02: Use Bangle.setUI for button/launcher handling 0.03: Fix display for Bangle 2 0.04: Use queueDraw(), update every minute, respect theme, use Lato font +0.05: Decided against custom font as it inceases the code size + minimalism is useful when narrowing down issues diff --git a/apps/simplest/app.js b/apps/simplest/app.js index 85ccc1509..582c4c2d5 100644 --- a/apps/simplest/app.js +++ b/apps/simplest/app.js @@ -1,31 +1,19 @@ const h = g.getHeight(); const w = g.getWidth(); -// from fonts.google.com -Graphics.prototype.setFontLato = function(scale) { - // Actual height 50 (53 - 4) - this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+AAAAAAAAAP4AAAAAAAAD/gAAAAAAAAf8AAAAAAAAD/gAAAAAAAAP4AAAAAAAAB/AAAAAAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4AAAAAAAAAfAAAAAAAAAf4AAAAAAAAP/AAAAAAAAP/wAAAAAAAH/4AAAAAAAH/8AAAAAAAH/8AAAAAAAD/+AAAAAAAD/+AAAAAAAB//AAAAAAAB//AAAAAAAA//gAAAAAAA//gAAAAAAAf/gAAAAAAAf/wAAAAAAAP/wAAAAAAAP/4AAAAAAAH/4AAAAAAAB/8AAAAAAAAf8AAAAAAAAD+AAAAAAAAAeAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//gAAAAAAf///gAAAAAf////gAAAAH/////AAAAD/////8AAAA//////wAAAP/4AB//AAAD/wAAA/8AAA/wAAAA/wAAH8AAAAD+AAB/AAAAAP4AAPwAAAAA/AAB8AAAAAD4AAPgAAAAAfAAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAfgAAAAAfgAD8AAAAAD8AAPgAAAAAfAAB+AAAAAH4AAPwAAAAA/AAA/AAAAAPwAAH+AAAAH+AAAf8AAAB/gAAD/4AAB/8AAAP//gf//AAAA//////wAAAB/////4AAAAH////+AAAAAP////AAAAAAP///AAAAAAAD/8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAADgAAAAAAAAA+AAAAAAAAAPwAAAD4AAAD+AAAAfAAAA/gAAAD4AAAP4AAAAfAAAD+AAAAD4AAA/wAAAAfAAAH8AAAAD4AAB/AAAAAfAAAfwAAAAD4AAH8AAAAAfAAB///////4AAP///////AAB///////4AAP///////AAB///////4AAP///////AAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAHAAAAD4AAAH4AAAA/AAAB/AAAAP4AAA/4AAAD/AAAP/AAAA/4AAD/4AAAP/AAAf4AAAD/4AAH8AAAA//AAA/AAAAP74AAPwAAAD+fAAB+AAAA/n4AAPgAAAP4/AAD8AAAD+H4AAfgAAA/g/AAD8AAAP4H4AAfgAAD+A/AAD8AAA/gH4AAfgAAP4A/AAB8AAH+AH4AAPwAB/gA/AAB/AA/4AH4AAH8Af+AA/AAA////gAH4AAD///wAA/AAAP//8AAH4AAA///AAA/AAAD//gAAH4AAAH/wAAA/AAAAHwAAAD4AAAAAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAA8AAAAAPAAAP4AAAAP4AAB/gAAAD/AAAP/AAAA/4AAB/4AAAP/AAAD/gAAD/wAAAH+AAA/wAAAAfwAAH8AAAAB/AAB/AAAAAH4AAPwAAAAAfAAB8AAAAAD8AAPgADwAAfgAD8AAeAAD8AAfgADwAAfgAD8AAfAAD8AAfgAH4AAfgAD8AA/AAD8AAPgAH4AAfAAB+AB/gAH4AAPwAP8AA/AAB/AD/wAPwAAH+B+/AH+AAA///3+D/gAAD//8f//8AAAP//D///AAAA//wP//wAAAB/8A//8AAAAD8AB/+AAAAAAAAD+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAAAAAAH4AAAAAAAAD/AAAAAAAAA/4AAAAAAAAP/AAAAAAAAH/4AAAAAAAB//AAAAAAAAf74AAAAAAAP+fAAAAAAAD/D4AAAAAAA/wfAAAAAAAf8D4AAAAAAH+AfAAAAAAD/gD4AAAAAA/4AfAAAAAAP8AD4AAAAAH/AAfAAAAAB/gAD4AAAAAf4AAfAAAAAP+AAD4AAAAD/AAAfAAAAA/wAAD4AAAAP///////AAB///////4AAP///////AAB///////4AAP///////AAB///////4AAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAfAAAAAAAAAD4AAAAAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAA4AAAAAAAAAPgAAAAB/AAD8AAAAH/4AAfwAAA///AAB+AAB///4AAP4AAP///AAA/AAB///4AAH4AAP/gfAAAfAAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AHwAAD8AAPwA+AAAfgAB+AH4AAD4AAPwA/AAAfAAB+AH4AAH4AAPwAfgAB/AAB+AD8AAfwAAPwAf4AH+AAB+AB/gD/gAAPwAP///4AAB+AA///+AAAPgAD///gAAB8AAP//4AAAPAAAf/8AAAAAAAA/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/gAAAAAAAB//gAAAAAAA///AAAAAAAf//8AAAAAAH///4AAAAAD////AAAAAA//gf8AAAAAP/wAfwAAAAH/8AB+AAAAB//AAH4AAAA//wAA/AAAAP+8AAD4AAAD/ngAAfgAAB/58AAD8AAAf8PgAAfgAAH/B8AAD8AAD/wPgAAfgAA/8B8AAD8AAP+APgAAfAAB/gB8AAD4AAP4APwAA/AAB8AB+AAH4AAPAAH4AB+AABwAA/wA/wAAIAAD/gf8AAAAAAf///AAAAAAB///wAAAAAAH//8AAAAAAAf//AAAAAAAA//gAAAAAAAB/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAAPgAAAAAAAAB+AAAAAAAAAPwAAAAAAAAB+AAAAAAAAAPwAAAAADAAB+AAAAAB4AAPwAAAAA/AAB+AAAAAf4AAPwAAAAP/AAB+AAAAH/4AAPwAAAD/+AAB+AAAB//AAAPwAAA//gAAB+AAAf/wAAAPwAAP/4AAAB+AAH/8AAAAPwAD/+AAAAB+AB//AAAAAPwA//gAAAAB+Af/gAAAAAPwP/wAAAAAB+H/4AAAAAAPz/8AAAAAAB//+AAAAAAAP//AAAAAAAB//gAAAAAAAP/wAAAAAAAB/4AAAAAAAAP8AAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf8AAAAAHgAP/4AAAAH/gD//gAAAD//A///AAAA//8P//4AAAP//z///gAAD//+fwP+AAA/4f/4AfwAAH4A/+AB/AAB+AB/gAH4AAPgAH8AAfAAB8AA/AAD4AAfgAH4AAfgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAB8AAfAAD4AAPgAD4AAfAAD8AAPgAH4AAfAAB8AA/gAD4AAPwAP8AA/AAA/AD/wAH4AAH8B//AB+AAAf//78A/wAAD//+f//8AAAP//h///gAAA//4P//4AAAB/+A//+AAAAD/AD//gAAAAAAAH/wAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAAAAAAAf/gAAAAAAAP/+AAAAAAAD//8AAAAAAA///wAAAAAAP///AAAAAAD///4AADAAA/wB/gAA4AAH8AD8AAPAAB/AAPwAH4AAPwAB+AB/AAB8AAHwAf4AAPgAA+AP/AAD8AAHwD/wAAfgAA+A/8AAD8AAHwf+AAAfgAA+H/gAAD8AAHx/wAAAPgAA8/8AAAB8AAPv/AAAAPwAB//gAAAB/AAf/4AAAAH8AH/8AAAAA/wD//AAAAAD////gAAAAAP///4AAAAAA///8AAAAAAD//+AAAAAAAH//AAAAAAAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAHwAAAAB+AAB/AAAAAf4AAP4AAAAD/AAD/gAAAAf4AAf8AAAAD/AAB/AAAAAPwAAP4AAAAA8AAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="), 46, atob("DRclJSUlJSUlJSUlEA=="), 63+(scale<<8)+(1<<16)); - return this; -} - function draw() { var date = new Date(); var timeStr = require("locale").time(date,1); - var dateStr = require("locale").date(date).toUpperCase(); g.reset(); g.setColor(g.theme.bg); g.fillRect(Bangle.appRect); - g.setFontLato(); - g.setFontAlign(0, -1); + g.setFont('Vector', w/3); + g.setFontAlign(0, 0); g.setColor(g.theme.fg); - g.drawString(timeStr, w/2, h/3); + g.drawString(timeStr, w/2, h/2); - g.setFont("6x8",2); - g.setFontAlign(0,0) - g.drawString(dateStr, w/2, h - 24 - 24); - queueDraw(); } @@ -52,8 +40,15 @@ Bangle.on('lcdPower',on=>{ }); g.clear(); + // Show launcher when middle button pressed -Bangle.setUI("clock"); +//Bangle.setUI("clock"); +// use clockupdown as it tests for issue #1249 +Bangle.setUI("clockupdown", btn=> { + draw(); +}); + + // Load widgets Bangle.loadWidgets(); Bangle.drawWidgets(); From 72eb12827255b12926d82cd825871349cdcea5b7 Mon Sep 17 00:00:00 2001 From: Didgeridoohan Date: Sun, 9 Jan 2022 07:32:57 +0100 Subject: [PATCH 177/202] Tweak long date --- 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 fea217efe..fce2b8c2a 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -294,7 +294,7 @@ var locales = { temperature: '°C', ampm: { 0: "", 1: "" }, timePattern: { 0: "%HH:%MM:%SS ", 1: "%HH:%MM" }, - datePattern: { 0: "%A %B %d %Y", "1": "%Y-%m-%d" }, // Sunday 1 March 2020 // 2020-03-01 + datePattern: { 0: "%B %d %Y", "1": "%Y-%m-%d" }, // March 1 2020 // 2020-03-01 abmonth: "Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec", month: "January,February,March,April,May,June,July,August,September,October,November,December", abday: "Sun,Mon,Tue,Wed,Thu,Fri,Sat", From 6896b282b2ac83fdf6c4149ff463493a5b8c07a6 Mon Sep 17 00:00:00 2001 From: The Dod Date: Sun, 9 Jan 2022 14:17:14 +0200 Subject: [PATCH 178/202] Rewrite mkFourTwentyTz in JS (instead of Python) --- apps/ftclock/.gitignore | 4 + apps/ftclock/README.md | 18 +- apps/ftclock/fourTwentyTz.js | 997 +++++++++++++++------------------ apps/ftclock/mkFourTwentyTz.js | 74 +++ apps/ftclock/mkFourTwentyTz.py | 46 -- apps/ftclock/package.json | 15 + 6 files changed, 568 insertions(+), 586 deletions(-) create mode 100644 apps/ftclock/.gitignore create mode 100644 apps/ftclock/mkFourTwentyTz.js delete mode 100644 apps/ftclock/mkFourTwentyTz.py create mode 100644 apps/ftclock/package.json diff --git a/apps/ftclock/.gitignore b/apps/ftclock/.gitignore new file mode 100644 index 000000000..b384cf1f2 --- /dev/null +++ b/apps/ftclock/.gitignore @@ -0,0 +1,4 @@ +timezonedb.csv.zip +country.csv +zone.csv +timezone.csv diff --git a/apps/ftclock/README.md b/apps/ftclock/README.md index 665a7693d..f30151552 100644 --- a/apps/ftclock/README.md +++ b/apps/ftclock/README.md @@ -4,12 +4,20 @@ A clock that tells when and where it's going to be [4:20](https://en.wikipedia.o ![screensot](screenshot.png) ![screenshot at 4:20](screenshot1.png) -## Note +## Generating `fourTwentyTz.js` -Once in a while, there'd be updates to the [timezone database](https://timezonedb.com/download) which -would require updating `fourTwentyTz.js`. I'll do my best to release a new version every time this happens, -but if you ever need to do this yourself, just run `python mkFourTwentyTz.py` (after downloading the timezone CSV files. -See comment at the top of the script). +Once in a while we need to regenerate it for 2 reasons: + +* One or more places got in or out of daylight saving time (DST) mode. +* The database saying _when_ places enter/exit DST mode got updated. + +I'll do my best to release a new version every time this happens, +but if you ever need to do this yourself, here's how: + +* `cd` to the `ftclock` folder +* If you haven't done so yet, run `npm install` there (this would create the `node_modules` folder). +* Get and unzip the latest `timezone.csv.zip` from https://timezonedb.com/download +* Run `npm run make` ## Creator diff --git a/apps/ftclock/fourTwentyTz.js b/apps/ftclock/fourTwentyTz.js index e41f3fdd0..cebab42cb 100644 --- a/apps/ftclock/fourTwentyTz.js +++ b/apps/ftclock/fourTwentyTz.js @@ -1,536 +1,463 @@ -// Generated by mk420tz.py - see https://github.com/thedod/BangleApps/420clock -// (version: Sat Dec 18 10:17:32 2021) +// Generated by mkFourTwentyTz.js // Data source: https://timezonedb.com/files/timezonedb.csv.zip -// (version: Sat Oct 16 01:48:14 2021) -exports.timezones = [ - [ - 1380, - [ - "Azores, Portugal", - "Cape Verde, Cabo Verde", - "Scoresbysund, Greenland" - ] - ], - [ - 1320, - [ - "Noronha, Brazil", - "South Georgia, South Georgia and the South Sandwich Islands" - ] - ], - [ - 1260, - [ - "Araguaina, Brazil", - "Asuncion, Paraguay", - "Bahia, Brazil", - "Belem, Brazil", - "Buenos Aires, Argentina", - "Catamarca, Argentina", - "Cayenne, French Guiana", - "Cordoba, Argentina", - "Fortaleza, Brazil", - "Jujuy, Argentina", - "La Rioja, Argentina", - "Maceio, Brazil", - "Mendoza, Argentina", - "Miquelon, Saint Pierre and Miquelon", - "Montevideo, Uruguay", - "Nuuk, Greenland", - "Palmer, Antarctica", - "Paramaribo, Suriname", - "Punta Arenas, Chile", - "Recife, Brazil", - "Rio Gallegos, Argentina", - "Rothera, Antarctica", - "Salta, Argentina", - "San Juan, Argentina", - "San Luis, Argentina", - "Santarem, Brazil", - "Santiago, Chile", - "Sao Paulo, Brazil", - "Stanley, Falkland Islands (Malvinas)", - "Tucuman, Argentina", - "Ushuaia, Argentina" - ] - ], - [ - 1200, - [ - "Anguilla, AI", - "Antigua, Antigua and Barbuda", - "Aruba, AW", - "Barbados, BB", - "Bermuda, BM", - "Blanc-Sablon, Canada", - "Boa Vista, Brazil", - "Campo Grande, Brazil", - "Caracas, Venezuela (Bolivarian Republic of)", - "Cuiaba, Brazil", - "Curacao, Cura\u00e7ao", - "Dominica, DM", - "Glace Bay, Canada", - "Goose Bay, Canada", - "Grenada, GD", - "Guadeloupe, GP", - "Guyana, GY", - "Halifax, Canada", - "Kralendijk, Bonaire, Sint Eustatius and Saba", - "La Paz, Bolivia (Plurinational State of)", - "Lower Princes, Sint Maarten (Dutch part)", - "Manaus, Brazil", - "Marigot, Saint Martin (French part)", - "Martinique, MQ", - "Moncton, Canada", - "Montserrat, MS", - "Port of Spain, Trinidad and Tobago", - "Porto Velho, Brazil", - "Puerto Rico, PR", - "Santo Domingo, Dominican Republic", - "St Barthelemy, Saint Barth\u00e9lemy", - "St Kitts, Saint Kitts and Nevis", - "St Lucia, Saint Lucia", - "St Thomas, Virgin Islands (U.S.)", - "St Vincent, Saint Vincent and the Grenadines", - "Thule, Greenland", - "Tortola, Virgin Islands (British)" - ] - ], - [ - 1140, - [ - "Atikokan, Canada", - "Bogota, Colombia", - "Cancun, Mexico", - "Cayman, Cayman Islands", - "Detroit, United States of America", - "Easter, Chile", - "Eirunepe, Brazil", - "Grand Turk, Turks and Caicos Islands", - "Guayaquil, Ecuador", - "Havana, Cuba", - "Indianapolis, Indiana", - "Iqaluit, Canada", - "Jamaica, JM", - "Lima, Peru", - "Louisville, Kentucky", - "Marengo, Indiana", - "Monticello, Kentucky", - "Nassau, Bahamas", - "New York, United States of America", - "Nipigon, Canada", - "Panama, PA", - "Pangnirtung, Canada", - "Petersburg, Indiana", - "Port-au-Prince, Haiti", - "Rio Branco, Brazil", - "Thunder Bay, Canada", - "Toronto, Canada", - "Vevay, Indiana", - "Vincennes, Indiana", - "Winamac, Indiana" - ] - ], - [ - 1080, - [ - "Bahia Banderas, Mexico", - "Belize, BZ", - "Beulah, North Dakota", - "Center, North Dakota", - "Chicago, United States of America", - "Costa Rica, CR", - "El Salvador, SV", - "Galapagos, Ecuador", - "Guatemala, GT", - "Knox, Indiana", - "Managua, Nicaragua", - "Matamoros, Mexico", - "Menominee, United States of America", - "Merida, Mexico", - "Mexico City, Mexico", - "Monterrey, Mexico", - "New Salem, North Dakota", - "Rainy River, Canada", - "Rankin Inlet, Canada", - "Regina, Canada", - "Resolute, Canada", - "Swift Current, Canada", - "Tegucigalpa, Honduras", - "Tell City, Indiana", - "Winnipeg, Canada" - ] - ], - [ - 1020, - [ - "Boise, United States of America", - "Cambridge Bay, Canada", - "Chihuahua, Mexico", - "Creston, Canada", - "Dawson Creek, Canada", - "Dawson, Canada", - "Denver, United States of America", - "Edmonton, Canada", - "Fort Nelson, Canada", - "Hermosillo, Mexico", - "Inuvik, Canada", - "Mazatlan, Mexico", - "Ojinaga, Mexico", - "Phoenix, United States of America", - "Whitehorse, Canada", - "Yellowknife, Canada" - ] - ], - [ - 960, - [ - "Los Angeles, United States of America", - "Pitcairn, PN", - "Tijuana, Mexico", - "Vancouver, Canada" - ] - ], - [ - 900, - [ - "Anchorage, United States of America", - "Gambier, French Polynesia", - "Juneau, United States of America", - "Metlakatla, United States of America", - "Nome, United States of America", - "Sitka, United States of America", - "Yakutat, United States of America" - ] - ], - [ - 840, - [ - "Adak, United States of America", - "Honolulu, United States of America", - "Kiritimati, Kiribati", - "Rarotonga, Cook Islands", - "Tahiti, French Polynesia" - ] - ], - [ - 780, - [ - "Apia, Samoa", - "Auckland, New Zealand", - "Fakaofo, Tokelau", - "Kanton, Kiribati", - "McMurdo, Antarctica", - "Midway, United States Minor Outlying Islands", - "Niue, NU", - "Pago Pago, American Samoa", - "Tongatapu, Tonga" - ] - ], - [ - 720, - [ - "Anadyr, Russian Federation", - "Fiji, FJ", - "Funafuti, Tuvalu", - "Kamchatka, Russian Federation", - "Kwajalein, Marshall Islands", - "Majuro, Marshall Islands", - "Nauru, NR", - "Norfolk, Norfolk Island", - "Tarawa, Kiribati", - "Wake, United States Minor Outlying Islands", - "Wallis, Wallis and Futuna" - ] - ], - [ - 660, - [ - "Bougainville, Papua New Guinea", - "Casey, Antarctica", - "Efate, Vanuatu", - "Guadalcanal, Solomon Islands", - "Hobart, Australia", - "Kosrae, Micronesia (Federated States of)", - "Lord Howe, Australia", - "Macquarie, Australia", - "Magadan, Russian Federation", - "Melbourne, Australia", - "Noumea, New Caledonia", - "Pohnpei, Micronesia (Federated States of)", - "Sakhalin, Russian Federation", - "Srednekolymsk, Russian Federation", - "Sydney, Australia" - ] - ], - [ - 600, - [ - "Brisbane, Australia", - "Chuuk, Micronesia (Federated States of)", - "DumontDUrville, Antarctica", - "Guam, GU", - "Lindeman, Australia", - "Port Moresby, Papua New Guinea", - "Saipan, Northern Mariana Islands", - "Ust-Nera, Russian Federation", - "Vladivostok, Russian Federation" - ] - ], - [ - 540, - [ - "Chita, Russian Federation", - "Dili, Timor-Leste", - "Jayapura, Indonesia", - "Khandyga, Russian Federation", - "Palau, PW", - "Pyongyang, Korea (Democratic People's Republic of)", - "Seoul, Korea, Republic of", - "Tokyo, Japan", - "Yakutsk, Russian Federation" - ] - ], - [ - 480, - [ - "Brunei, Brunei Darussalam", - "Choibalsan, Mongolia", - "Hong Kong, HK", - "Irkutsk, Russian Federation", - "Kuala Lumpur, Malaysia", - "Kuching, Malaysia", - "Macau, Macao", - "Makassar, Indonesia", - "Manila, Philippines", - "Perth, Australia", - "Shanghai, China", - "Singapore, SG", - "Taipei, Taiwan, Province of China", - "Ulaanbaatar, Mongolia" - ] - ], - [ - 420, - [ - "Bangkok, Thailand", - "Barnaul, Russian Federation", - "Christmas, Christmas Island", - "Davis, Antarctica", - "Ho Chi Minh, Viet Nam", - "Hovd, Mongolia", - "Jakarta, Indonesia", - "Krasnoyarsk, Russian Federation", - "Novokuznetsk, Russian Federation", - "Novosibirsk, Russian Federation", - "Phnom Penh, Cambodia", - "Pontianak, Indonesia", - "Tomsk, Russian Federation", - "Vientiane, Lao People's Democratic Republic" - ] - ], - [ - 360, - [ - "Almaty, Kazakhstan", - "Bishkek, Kyrgyzstan", - "Chagos, British Indian Ocean Territory", - "Dhaka, Bangladesh", - "Omsk, Russian Federation", - "Qostanay, Kazakhstan", - "Thimphu, Bhutan", - "Urumqi, China", - "Vostok, Antarctica" - ] - ], - [ - 300, - [ - "Aqtau, Kazakhstan", - "Aqtobe, Kazakhstan", - "Ashgabat, Turkmenistan", - "Atyrau, Kazakhstan", - "Dushanbe, Tajikistan", - "Karachi, Pakistan", - "Kerguelen, French Southern Territories", - "Maldives, MV", - "Mawson, Antarctica", - "Oral, Kazakhstan", - "Qyzylorda, Kazakhstan", - "Samarkand, Uzbekistan", - "Tashkent, Uzbekistan", - "Yekaterinburg, Russian Federation" - ] - ], - [ - 240, - [ - "Astrakhan, Russian Federation", - "Baku, Azerbaijan", - "Dubai, United Arab Emirates", - "Mahe, Seychelles", - "Mauritius, MU", - "Muscat, Oman", - "Reunion, R\u00e9union", - "Samara, Russian Federation", - "Saratov, Russian Federation", - "Tbilisi, Georgia", - "Ulyanovsk, Russian Federation", - "Yerevan, Armenia" - ] - ], - [ - 180, - [ - "Addis Ababa, Ethiopia", - "Aden, Yemen", - "Antananarivo, Madagascar", - "Asmara, Eritrea", - "Baghdad, Iraq", - "Bahrain, BH", - "Comoro, Comoros", - "Dar es Salaam, Tanzania, United Republic of", - "Djibouti, DJ", - "Istanbul, Turkey", - "Kampala, Uganda", - "Kirov, Russian Federation", - "Kuwait, KW", - "Mayotte, YT", - "Minsk, Belarus", - "Mogadishu, Somalia", - "Moscow, Russian Federation", - "Nairobi, Kenya", - "Qatar, QA", - "Riyadh, Saudi Arabia", - "Simferopol, Ukraine", - "Syowa, Antarctica", - "Volgograd, Russian Federation" - ] - ], - [ - 120, - [ - "Amman, Jordan", - "Athens, Greece", - "Beirut, Lebanon", - "Blantyre, Malawi", - "Bucharest, Romania", - "Bujumbura, Burundi", - "Cairo, Egypt", - "Chisinau, Moldova, Republic of", - "Damascus, Syrian Arab Republic", - "Famagusta, Cyprus", - "Gaborone, Botswana", - "Gaza, Palestine, State of", - "Harare, Zimbabwe", - "Hebron, Palestine, State of", - "Helsinki, Finland", - "Jerusalem, Israel", - "Johannesburg, South Africa", - "Juba, South Sudan", - "Kaliningrad, Russian Federation", - "Khartoum, Sudan", - "Kiev, Ukraine", - "Kigali, Rwanda", - "Lubumbashi, Congo, Democratic Republic of the", - "Lusaka, Zambia", - "Maputo, Mozambique", - "Mariehamn, \u00c5land Islands", - "Maseru, Lesotho", - "Mbabane, Eswatini", - "Nicosia, Cyprus", - "Riga, Latvia", - "Sofia, Bulgaria", - "Tallinn, Estonia", - "Tripoli, Libya", - "Uzhgorod, Ukraine", - "Vilnius, Lithuania", - "Windhoek, Namibia", - "Zaporozhye, Ukraine" - ] - ], - [ - 60, - [ - "Algiers, Algeria", - "Amsterdam, Netherlands", - "Andorra, AD", - "Bangui, Central African Republic", - "Belgrade, Serbia", - "Berlin, Germany", - "Bratislava, Slovakia", - "Brazzaville, Congo", - "Brussels, Belgium", - "Budapest, Hungary", - "Busingen, Germany", - "Casablanca, Morocco", - "Ceuta, Spain", - "Copenhagen, Denmark", - "Douala, Cameroon", - "El Aaiun, Western Sahara", - "Gibraltar, GI", - "Kinshasa, Congo, Democratic Republic of the", - "Lagos, Nigeria", - "Libreville, Gabon", - "Ljubljana, Slovenia", - "Longyearbyen, Svalbard and Jan Mayen", - "Luanda, Angola", - "Luxembourg, LU", - "Madrid, Spain", - "Malabo, Equatorial Guinea", - "Malta, MT", - "Monaco, MC", - "Ndjamena, Chad", - "Niamey, Niger", - "Oslo, Norway", - "Paris, France", - "Podgorica, Montenegro", - "Porto-Novo, Benin", - "Prague, Czechia", - "Rome, Italy", - "San Marino, SM", - "Sarajevo, Bosnia and Herzegovina", - "Skopje, North Macedonia", - "Stockholm, Sweden", - "Tirane, Albania", - "Tunis, Tunisia", - "Vaduz, Liechtenstein", - "Vatican, Holy See", - "Vienna, Austria", - "Warsaw, Poland", - "Zagreb, Croatia", - "Zurich, Switzerland" - ] - ], - [ - 0, - [ - "Abidjan, C\u00f4te d'Ivoire", - "Accra, Ghana", - "Bamako, Mali", - "Banjul, Gambia", - "Bissau, Guinea-Bissau", - "Canary, Spain", - "Conakry, Guinea", - "Dakar, Senegal", - "Danmarkshavn, Greenland", - "Dublin, Ireland", - "Faroe, Faroe Islands", - "Freetown, Sierra Leone", - "Guernsey, GG", - "Isle of Man, IM", - "Jersey, JE", - "Lisbon, Portugal", - "Lome, Togo", - "London, United Kingdom of Great Britain and Northern Ireland", - "Madeira, Portugal", - "Monrovia, Liberia", - "Nouakchott, Mauritania", - "Ouagadougou, Burkina Faso", - "Reykjavik, Iceland", - "Sao Tome, Sao Tome and Principe", - "St Helena, Saint Helena, Ascension and Tristan da Cunha", - "Troll, Antarctica" - ] - ] -]; +// Sun Jan 09 2022 13:21:47 GMT+0200 (Israel Standard Time) +exports.timezones = { + "0": [ + "Troll, Antarctica", + "Ouagadougou, Burkina Faso", + "Abidjan, Côte d'Ivoire", + "Canary, Spain", + "Faroe, Faroe Islands", + "London, United Kingdom of Great Britain and Northern Ireland", + "Guernsey, Guernsey", + "Accra, Ghana", + "Danmarkshavn, Greenland", + "Banjul, Gambia", + "Conakry, Guinea", + "Bissau, Guinea-Bissau", + "Dublin, Ireland", + "Isle of_Man, Isle of Man", + "Reykjavik, Iceland", + "Jersey, Jersey", + "Monrovia, Liberia", + "Bamako, Mali", + "Nouakchott, Mauritania", + "Lisbon, Portugal", + "Madeira, Portugal", + "St Helena, Saint Helena, Ascension and Tristan da Cunha", + "Freetown, Sierra Leone", + "Dakar, Senegal", + "Sao Tome, Sao Tome and Principe", + "Lome, Togo" + ], + "60": [ + "Andorra, Andorra", + "Tirane, Albania", + "Luanda, Angola", + "Vienna, Austria", + "Sarajevo, Bosnia and Herzegovina", + "Brussels, Belgium", + "Porto-Novo, Benin", + "Kinshasa, Congo, Democratic Republic of the", + "Bangui, Central African Republic", + "Brazzaville, Congo", + "Zurich, Switzerland", + "Douala, Cameroon", + "Prague, Czechia", + "Berlin, Germany", + "Busingen, Germany", + "Copenhagen, Denmark", + "Algiers, Algeria", + "El Aaiun, Western Sahara", + "Madrid, Spain", + "Ceuta, Spain", + "Paris, France", + "Libreville, Gabon", + "Gibraltar, Gibraltar", + "Malabo, Equatorial Guinea", + "Zagreb, Croatia", + "Budapest, Hungary", + "Rome, Italy", + "Vaduz, Liechtenstein", + "Luxembourg, Luxembourg", + "Casablanca, Morocco", + "Monaco, Monaco", + "Podgorica, Montenegro", + "Skopje, North Macedonia", + "Malta, Malta", + "Niamey, Niger", + "Lagos, Nigeria", + "Amsterdam, Netherlands", + "Oslo, Norway", + "Warsaw, Poland", + "Belgrade, Serbia", + "Stockholm, Sweden", + "Ljubljana, Slovenia", + "Longyearbyen, Svalbard and Jan Mayen", + "Bratislava, Slovakia", + "San Marino, San Marino", + "Ndjamena, Chad", + "Tunis, Tunisia", + "Vatican, Holy See" + ], + "120": [ + "Mariehamn, Åland Islands", + "Sofia, Bulgaria", + "Bujumbura, Burundi", + "Gaborone, Botswana", + "Lubumbashi, Congo, Democratic Republic of the", + "Nicosia, Cyprus", + "Famagusta, Cyprus", + "Tallinn, Estonia", + "Cairo, Egypt", + "Helsinki, Finland", + "Athens, Greece", + "Jerusalem, Israel", + "Amman, Jordan", + "Beirut, Lebanon", + "Maseru, Lesotho", + "Vilnius, Lithuania", + "Riga, Latvia", + "Tripoli, Libya", + "Chisinau, Moldova, Republic of", + "Blantyre, Malawi", + "Maputo, Mozambique", + "Windhoek, Namibia", + "Gaza, Palestine, State of", + "Hebron, Palestine, State of", + "Bucharest, Romania", + "Kaliningrad, Russian Federation", + "Kigali, Rwanda", + "Khartoum, Sudan", + "Juba, South Sudan", + "Damascus, Syrian Arab Republic", + "Mbabane, Eswatini", + "Kiev, Ukraine", + "Uzhgorod, Ukraine", + "Zaporozhye, Ukraine", + "Johannesburg, South Africa", + "Lusaka, Zambia", + "Harare, Zimbabwe" + ], + "180": [ + "Syowa, Antarctica", + "Bahrain, Bahrain", + "Minsk, Belarus", + "Djibouti, Djibouti", + "Asmara, Eritrea", + "Addis Ababa, Ethiopia", + "Baghdad, Iraq", + "Nairobi, Kenya", + "Comoro, Comoros", + "Kuwait, Kuwait", + "Antananarivo, Madagascar", + "Qatar, Qatar", + "Moscow, Russian Federation", + "Simferopol, Ukraine", + "Kirov, Russian Federation", + "Volgograd, Russian Federation", + "Riyadh, Saudi Arabia", + "Mogadishu, Somalia", + "Istanbul, Turkey", + "Dar es_Salaam, Tanzania, United Republic of", + "Kampala, Uganda", + "Aden, Yemen", + "Mayotte, Mayotte" + ], + "240": [ + "Dubai, United Arab Emirates", + "Yerevan, Armenia", + "Baku, Azerbaijan", + "Tbilisi, Georgia", + "Mauritius, Mauritius", + "Muscat, Oman", + "Reunion, Réunion", + "Astrakhan, Russian Federation", + "Saratov, Russian Federation", + "Ulyanovsk, Russian Federation", + "Samara, Russian Federation", + "Mahe, Seychelles" + ], + "300": [ + "Mawson, Antarctica", + "Qyzylorda, Kazakhstan", + "Aqtobe, Kazakhstan", + "Aqtau, Kazakhstan", + "Atyrau, Kazakhstan", + "Oral, Kazakhstan", + "Maldives, Maldives", + "Karachi, Pakistan", + "Yekaterinburg, Russian Federation", + "Kerguelen, French Southern Territories", + "Dushanbe, Tajikistan", + "Ashgabat, Turkmenistan", + "Samarkand, Uzbekistan", + "Tashkent, Uzbekistan" + ], + "360": [ + "Vostok, Antarctica", + "Dhaka, Bangladesh", + "Thimphu, Bhutan", + "Urumqi, China", + "Chagos, British Indian Ocean Territory", + "Bishkek, Kyrgyzstan", + "Almaty, Kazakhstan", + "Qostanay, Kazakhstan", + "Omsk, Russian Federation" + ], + "420": [ + "Davis, Antarctica", + "Christmas, Christmas Island", + "Jakarta, Indonesia", + "Pontianak, Indonesia", + "Phnom Penh, Cambodia", + "Vientiane, Lao People's Democratic Republic", + "Hovd, Mongolia", + "Novosibirsk, Russian Federation", + "Barnaul, Russian Federation", + "Tomsk, Russian Federation", + "Novokuznetsk, Russian Federation", + "Krasnoyarsk, Russian Federation", + "Bangkok, Thailand", + "Ho Chi_Minh, Viet Nam" + ], + "480": [ + "Perth, Australia", + "Brunei, Brunei Darussalam", + "Shanghai, China", + "Hong Kong, Hong Kong", + "Makassar, Indonesia", + "Ulaanbaatar, Mongolia", + "Choibalsan, Mongolia", + "Macau, Macao", + "Kuala Lumpur, Malaysia", + "Kuching, Malaysia", + "Manila, Philippines", + "Irkutsk, Russian Federation", + "Singapore, Singapore", + "Taipei, Taiwan, Province of China" + ], + "540": [ + "Jayapura, Indonesia", + "Tokyo, Japan", + "Pyongyang, Korea (Democratic People's Republic of)", + "Seoul, Korea, Republic of", + "Palau, Palau", + "Chita, Russian Federation", + "Yakutsk, Russian Federation", + "Khandyga, Russian Federation", + "Dili, Timor-Leste" + ], + "600": [ + "DumontDUrville, Antarctica", + "Brisbane, Australia", + "Lindeman, Australia", + "Chuuk, Micronesia (Federated States of)", + "Guam, Guam", + "Saipan, Northern Mariana Islands", + "Port Moresby, Papua New Guinea", + "Vladivostok, Russian Federation", + "Ust-Nera, Russian Federation" + ], + "660": [ + "Casey, Antarctica", + "Lord Howe, Australia", + "Macquarie, Australia", + "Hobart, Australia", + "Melbourne, Australia", + "Sydney, Australia", + "Pohnpei, Micronesia (Federated States of)", + "Kosrae, Micronesia (Federated States of)", + "Noumea, New Caledonia", + "Bougainville, Papua New Guinea", + "Magadan, Russian Federation", + "Sakhalin, Russian Federation", + "Srednekolymsk, Russian Federation", + "Guadalcanal, Solomon Islands", + "Efate, Vanuatu" + ], + "720": [ + "Tarawa, Kiribati", + "Majuro, Marshall Islands", + "Kwajalein, Marshall Islands", + "Norfolk, Norfolk Island", + "Nauru, Nauru", + "Kamchatka, Russian Federation", + "Anadyr, Russian Federation", + "Funafuti, Tuvalu", + "Wake, United States Minor Outlying Islands", + "Wallis, Wallis and Futuna" + ], + "780": [ + "McMurdo, Antarctica", + "Pago Pago, American Samoa", + "Fiji, Fiji", + "Kanton, Kiribati", + "Niue, Niue", + "Auckland, New Zealand", + "Fakaofo, Tokelau", + "Tongatapu, Tonga", + "Midway, United States Minor Outlying Islands", + "Apia, Samoa" + ], + "840": [ + "Rarotonga, Cook Islands", + "Kiritimati, Kiribati", + "Tahiti, French Polynesia", + "Adak, United States of America", + "Honolulu, United States of America" + ], + "900": [ + "Gambier, French Polynesia", + "Anchorage, United States of America", + "Juneau, United States of America", + "Sitka, United States of America", + "Metlakatla, United States of America", + "Yakutat, United States of America", + "Nome, United States of America" + ], + "960": [ + "Vancouver, Canada", + "Tijuana, Mexico", + "Pitcairn, Pitcairn", + "Los Angeles, United States of America" + ], + "1020": [ + "Edmonton, Canada", + "Cambridge Bay, Canada", + "Yellowknife, Canada", + "Inuvik, Canada", + "Creston, Canada", + "Dawson Creek, Canada", + "Fort Nelson, Canada", + "Whitehorse, Canada", + "Dawson, Canada", + "Mazatlan, Mexico", + "Chihuahua, Mexico", + "Ojinaga, Mexico", + "Hermosillo, Mexico", + "Denver, United States of America", + "Boise, United States of America", + "Phoenix, United States of America" + ], + "1080": [ + "Belize, Belize", + "Winnipeg, Canada", + "Rainy River, Canada", + "Resolute, Canada", + "Rankin Inlet, Canada", + "Regina, Canada", + "Swift Current, Canada", + "Costa Rica, Costa Rica", + "Galapagos, Ecuador", + "Guatemala, Guatemala", + "Tegucigalpa, Honduras", + "Mexico City, Mexico", + "Merida, Mexico", + "Monterrey, Mexico", + "Matamoros, Mexico", + "Bahia Banderas, Mexico", + "Managua, Nicaragua", + "El Salvador, El Salvador", + "Chicago, United States of America", + "Tell City, Indiana", + "Knox, Indiana", + "Menominee, United States of America", + "Center, North Dakota", + "New_Salem, North Dakota", + "Beulah, North Dakota" + ], + "1140": [ + "Eirunepe, Brazil", + "Rio Branco, Brazil", + "Nassau, Bahamas", + "Toronto, Canada", + "Nipigon, Canada", + "Thunder Bay, Canada", + "Iqaluit, Canada", + "Pangnirtung, Canada", + "Atikokan, Canada", + "Easter, Chile", + "Bogota, Colombia", + "Havana, Cuba", + "Guayaquil, Ecuador", + "Port-au-Prince, Haiti", + "Jamaica, Jamaica", + "Cayman, Cayman Islands", + "Cancun, Mexico", + "Panama, Panama", + "Lima, Peru", + "Grand Turk, Turks and Caicos Islands", + "New York, United States of America", + "Detroit, United States of America", + "Louisville, Kentucky", + "Monticello, Kentucky", + "Indianapolis, Indiana", + "Vincennes, Indiana", + "Winamac, Indiana", + "Marengo, Indiana", + "Petersburg, Indiana", + "Vevay, Indiana" + ], + "1200": [ + "Antigua, Antigua and Barbuda", + "Anguilla, Anguilla", + "Aruba, Aruba", + "Barbados, Barbados", + "St Barthelemy, Saint Barthélemy", + "Bermuda, Bermuda", + "La Paz, Bolivia (Plurinational State of)", + "Kralendijk, Bonaire, Sint Eustatius and Saba", + "Campo Grande, Brazil", + "Cuiaba, Brazil", + "Porto Velho, Brazil", + "Boa Vista, Brazil", + "Manaus, Brazil", + "Halifax, Canada", + "Glace Bay, Canada", + "Moncton, Canada", + "Goose Bay, Canada", + "Blanc-Sablon, Canada", + "Curacao, Curaçao", + "Dominica, Dominica", + "Santo Domingo, Dominican Republic", + "Grenada, Grenada", + "Thule, Greenland", + "Guadeloupe, Guadeloupe", + "Guyana, Guyana", + "St Kitts, Saint Kitts and Nevis", + "St Lucia, Saint Lucia", + "Marigot, Saint Martin (French part)", + "Martinique, Martinique", + "Montserrat, Montserrat", + "Puerto Rico, Puerto Rico", + "Lower Princes, Sint Maarten (Dutch part)", + "Port of_Spain, Trinidad and Tobago", + "St Vincent, Saint Vincent and the Grenadines", + "Caracas, Venezuela (Bolivarian Republic of)", + "Tortola, Virgin Islands (British)", + "St Thomas, Virgin Islands (U.S.)" + ], + "1260": [ + "Palmer, Antarctica", + "Rothera, Antarctica", + "Buenos Aires, Argentina", + "Cordoba, Argentina", + "Salta, Argentina", + "Jujuy, Argentina", + "Tucuman, Argentina", + "Catamarca, Argentina", + "La Rioja, Argentina", + "San Juan, Argentina", + "Mendoza, Argentina", + "San Luis, Argentina", + "Rio Gallegos, Argentina", + "Ushuaia, Argentina", + "Belem, Brazil", + "Fortaleza, Brazil", + "Recife, Brazil", + "Araguaina, Brazil", + "Maceio, Brazil", + "Bahia, Brazil", + "Sao Paulo, Brazil", + "Santarem, Brazil", + "Santiago, Chile", + "Punta Arenas, Chile", + "Stanley, Falkland Islands (Malvinas)", + "Cayenne, French Guiana", + "Nuuk, Greenland", + "Miquelon, Saint Pierre and Miquelon", + "Asuncion, Paraguay", + "Paramaribo, Suriname", + "Montevideo, Uruguay" + ], + "1320": [ + "Noronha, Brazil", + "South Georgia, South Georgia and the South Sandwich Islands" + ], + "1380": [ + "Cape Verde, Cabo Verde", + "Scoresbysund, Greenland", + "Azores, Portugal" + ] +} \ No newline at end of file diff --git a/apps/ftclock/mkFourTwentyTz.js b/apps/ftclock/mkFourTwentyTz.js new file mode 100644 index 000000000..dd199523a --- /dev/null +++ b/apps/ftclock/mkFourTwentyTz.js @@ -0,0 +1,74 @@ +let fs = require('fs'); +let csv = require('csv'); + +let countries = {}, + zones = {}, + offsdict = {}, + now = Date.now(); // we need this to find zone's current DST state + +function handleWrite(err,bytes) { + if (err) { + console.log(`Error writing to file ${err}`); + } +} + +console.log("Generating fourTwentyTz.js..."); +fs.createReadStream(__dirname+'/country.csv') + .pipe(csv.parse()) + .on('data', (r) => { + countries[r[0]] = r[1]; + }) + .on('end', () => { + fs.createReadStream(__dirname+'/zone.csv') + .pipe(csv.parse()) + .on('data', (r) => { + let parts = r[2].replace('_',' ').split('/'); + let city = parts[parts.length-1]; + let country =''; + if (parts.length>2) { // e.g. America/North_Dakota/New_Salem + country = parts[1]; // e.g. North Dakota + } else { + country = countries[r[1]]; // e.g. United States + } + zones[parseInt(r[0])] = {"name": `${city}, ${country}`}; + }) + .on('end', () => { + fs.createReadStream(__dirname+'/timezone.csv') + .pipe(csv.parse()) + .on('data', (r) => { + code = parseInt(r[0]); + if (!(code in zones)) return; + starttime = parseInt(r[2] || "0"); // Bugger. They're feeding us blanks for UTC now + offs = parseInt(r[3]); + if (offs<0) { + offs += 60*60*24; + } + zone = zones[code]; + if (starttime { + for (z in zones) { + zone = zones[z]; + if (zone.offs%60) continue; // One a dem funky timezones. Ignore. + zonelist = offsdict[zone.offs] || []; + zonelist.push(zone.name); + offsdict[zone.offs] = zonelist; + } + fs.open("fourTwentyTz.js","w", (err, fd) => { + if (err) { + console.log("Can't open output file"); + return; + } + fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite); + fs.write(fd, `// ${Date()}\n`, handleWrite); + fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite); + fs.write(fd, "exports.timezones = ", handleWrite); + fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite); + console.log('Done.'); + }); + }) + }) + }); diff --git a/apps/ftclock/mkFourTwentyTz.py b/apps/ftclock/mkFourTwentyTz.py deleted file mode 100644 index 713b68059..000000000 --- a/apps/ftclock/mkFourTwentyTz.py +++ /dev/null @@ -1,46 +0,0 @@ -# Generates fourTwentyTz.js from time zone csv files -# get latest files from https://timezonedb.com/download -import csv,json,time,os,math -countries = {} -for r in csv.reader(open("country.csv")): - countries[r[0]] = r[1] -zones = {} -for r in csv.reader(open("zone.csv")): - parts = r[2].replace('_',' ').split('/') - city = parts[-1] - if len(parts)>2: # e.g. America/North_Dakota/New_Salem - country = parts[1] # e.g. North Dakota - else: # e.g. America/Denver - country = countries[r[1]] # e.g. United States - if country==city: # Avoid awkward searches like "Anguilla, Anguilla" - country = r[1] # Use code instead - zones[int(r[0])] = {"name":', '.join((city,country))} -now = int(time.time()) -for r in csv.reader(open("timezone.csv")): - code = int(r[0]) - if code not in zones: - continue - starttime = int(r[2] or "0") # Bugger. They're feeding us blanks for UTC now - offs = int(r[3]) - if offs < 0: - offs += 60*60*24 - d = zones[code] - if starttime Date: Sun, 9 Jan 2022 13:42:01 +0100 Subject: [PATCH 179/202] Fix drawing of full circle --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 3843d5dda..1f6cc75ab 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -372,7 +372,7 @@ function drawGauge(cx, cy, percent, color) { if (percent > 1) percent = 1; var startrot = -offset; - var endrot = startrot - ((end - offset) * percent) - 15; + var endrot = startrot - ((end - offset) * percent) - 35; g.setColor(color); From 05f0d3003a32df7e1e95bfd72d679d9edc333097 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sun, 9 Jan 2022 13:45:50 +0100 Subject: [PATCH 180/202] Fix minor glitch in circle drawing --- apps/circlesclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 1f6cc75ab..91d4937c4 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -376,7 +376,7 @@ function drawGauge(cx, cy, percent, color) { g.setColor(color); - const size = radiusOuter - radiusInner - 3; + const size = radiusOuter - radiusInner - 2; // draw gauge for (i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); From 6f1b1093621a20aba705cbe483222013c416f1b4 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Sun, 9 Jan 2022 13:46:12 +0100 Subject: [PATCH 181/202] Add TODOs to README --- apps/circlesclock/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index a071efcf5..9aaa4bc8e 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -15,6 +15,10 @@ It can show the following information (this can be configured): ![Screenshot dark theme](screenshot-dark.png) ![Screenshot light theme](screenshot-light.png) +# TODO +* Add sunrise and sunset +* Display moon instead of sun during night on weather circle + ## Creator Marco ([myxor](https://github.com/myxor)) From 992b1e6564777d5d4e3bb012594ee5c030953393 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 9 Jan 2022 18:55:33 +0100 Subject: [PATCH 182/202] Bumped wohrm version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index ebe193f3a..c155f9262 100644 --- a/apps.json +++ b/apps.json @@ -1717,7 +1717,7 @@ { "id": "wohrm", "name": "Workout HRM", - "version": "0.09-rc10", + "version": "0.09", "description": "Workout heart rate monitor notifies you with a buzz if your heart rate goes above or below the set limits.", "icon": "app.png", "type": "app", From 707118ffbbc92dc8869b5643fce60847521ef530 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Sun, 9 Jan 2022 19:04:00 +0100 Subject: [PATCH 183/202] Bumped Hand Wash Timer version number --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 6fbc82e8b..b73cfe0e6 100644 --- a/apps.json +++ b/apps.json @@ -1893,7 +1893,7 @@ { "id": "widhwt", "name": "Hand Wash Timer", - "version": "0.02-rc10", + "version": "0.02", "description": "On Bangle.js 1 swipe your wrist over the watch face to start your personal Bangle.js 1 hand wash timer. On Bangle.js2 the Pattern Launcher is recommended to start the timer. Start washing after the short buzz and stop after the long buzz 35sec. later.", "icon": "widget.png", "type": "widget", From 20406ca29cadef7492c6cdc3e6a06ca134252259 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 10 Jan 2022 00:11:24 +0100 Subject: [PATCH 184/202] Clock can optionally show ISO-8601 calendar weeknumber --- apps.json | 2 +- apps/antonclk/ChangeLog | 3 +++ apps/antonclk/README.md | 3 +-- apps/antonclk/app.js | 38 +++++++++++++++++++++++++++++--------- apps/antonclk/settings.js | 8 ++++++++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/apps.json b/apps.json index 3fc0616da..c2180b91d 100644 --- a/apps.json +++ b/apps.json @@ -4242,7 +4242,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.04", + "version": "0.05", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index 668047d7a..fdf20c175 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -2,3 +2,6 @@ 0.02: Load widgets after setUI so widclk knows when to hide 0.03: Clock now shows day of week under date. 0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. +0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off) + when weekday name "Off": week #: + when weekday name "On": weekday name is cut at 6th position and .# is added \ No newline at end of file diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 41d3e4559..fa4cc4919 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,8 +40,7 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -* **Uppercase** - Weekday name and month name in the long format are converted to upper case letters. -This can improve readability. +**Show Weeknumber** - Weeknumber (ISO-8601) is shown. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. Otherwise, a scaled version of the built-in 6x8 pixels font is used. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 1f3e49792..be6c23789 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -19,6 +19,7 @@ var secondsWithColon; var dateOnMain; var dateOnSecs; var weekDay; +var calWeek; var upperCase; var vectorFont; @@ -29,22 +30,25 @@ var secondsScreen = true; var isBangle1 = (g.getWidth() == 240); -/* For development purposes +//For development purposes +/* require('Storage').writeJSON(SETTINGSFILE, { - secondsMode: "Always", // "Never", "Unlocked", "Always" + secondsMode: "Unlocked", // "Never", "Unlocked", "Always" secondsColoured: true, secondsWithColon: true, dateOnMain: "Long", // "Short", "Long", "ISO8601" dateOnSecs: "Year", // "No", "Year", "Weekday", LEGACY: true/false weekDay: true, + calWeek: true, upperCase: true, vectorFont: true, }); -/* */ +*/ -/* OR (also for development purposes) +// OR (also for development purposes) +/* require('Storage').erase(SETTINGSFILE); -/* */ +*/ // Helper method for loading the settings function def(value, def) { @@ -60,6 +64,7 @@ function loadSettings() { dateOnMain = def(settings.dateOnMain, "Long"); dateOnSecs = def(settings.dateOnSecs, "Year"); weekDay = def(settings.weekDay, true); + calWeek = def(settings.calWeek, false); upperCase = def(settings.upperCase, true); vectorFont = def(settings.vectorFont, false); @@ -99,6 +104,18 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } +function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + function doColor() { return !isBangle1 && !Bangle.isLocked() && secondsColoured; } @@ -169,11 +186,14 @@ function draw() { else g.setFont("6x8", 2); g.drawString(dateStr, x, y); - if (weekDay) { - var dowStr = require("locale").dow(date); + if (weekDay || calWeek) { + var dowwumStr = require("locale").dow(date); + dowwumStr = "thursday"; + if (calWeek) + dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); if (upperCase) - dowStr = dowStr.toUpperCase(); - g.drawString(dowStr, x, y + (vectorFont ? 26 : 16)); + dowwumStr = dowwumStr.toUpperCase(); + g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); } } diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 08fde512e..293aa0438 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -47,6 +47,14 @@ writeSettings(); } }, + "Show Weeknumber": { + value: (settings.weekNum !== undefined ? settings.weekNum : true), + format: v => v ? "On" : "Off", + onchange: v => { + settings.weekNum = v; + writeSettings(); + } + }, "Uppercase": { value: (settings.upperCase !== undefined ? settings.upperCase : false), format: v => v ? "On" : "Off", From d06283137995b78bb126e1861a6a2a81f0d80c1a Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 10 Jan 2022 08:47:52 +0000 Subject: [PATCH 185/202] Changelog for #1240 0.41: Add Keyboard and Mouse Bluetooth HID option --- apps.json | 2 +- apps/boot/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 2493ac6cb..2a51fc0ae 100644 --- a/apps.json +++ b/apps.json @@ -16,7 +16,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.40", + "version": "0.41", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader", diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index d6619822b..702a8091e 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -44,3 +44,4 @@ 0.38: Option to log to file if settings.log==2 0.39: Fix passkey support (fix https://github.com/espruino/Espruino/issues/2035) 0.40: Bootloader now rebuilds for new firmware versions +0.41: Add Keyboard and Mouse Bluetooth HID option From eaaddae9465af1c1bcc3c409b874f4806343c498 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 10 Jan 2022 14:06:50 +0000 Subject: [PATCH 186/202] fix broken instagram icon --- apps/messages/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messages/app.js b/apps/messages/app.js index e36bb699e..6e51c2b33 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -83,7 +83,7 @@ function getMessageImage(msg) { if (s=="calendar") return atob("GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgAGB//+B//+B//+B9m2B//+B//+Btm2B//+B//+Btm+B//+B//+A//8AAAAAAAAAAAAA=="); if (s=="facebook") return getFBIcon(); if (s=="hangouts") return atob("FBaBAAH4AH/gD/8B//g//8P//H5n58Y+fGPnxj5+d+fmfj//4//8H//B//gH/4A/8AA+AAHAABgAAAA="); - if (s=="instagram") return atob("GBiBAf////////////////wAP/n/n/P/z/f/b/eB7/c87/d+7/d+7/d+7/d+7/c87/eB7/f/7/P/z/n/n/wAP////////////////w=="); + if (s=="instagram") return atob("GBiBAAAAAAAAAAAAAAAAAAP/wAYAYAwAMAgAkAh+EAjDEAiBEAiBEAiBEAiBEAjDEAh+EAgAEAwAMAYAYAP/wAAAAAAAAAAAAAAAAA=="); if (s=="gmail") return getNotificationImage(); if (s=="google home") return atob("GBiCAAAAAAAAAAAAAAAAAAAAAoAAAAAACqAAAAAAKqwAAAAAqroAAAACquqAAAAKq+qgAAAqr/qoAACqv/6qAAKq//+qgA6r///qsAqr///6sAqv///6sAqv///6sAqv///6sA6v///6sA6v///qsA6qqqqqsA6qqqqqsA6qqqqqsAP7///vwAAAAAAAAAAAAAAAAA=="); if (s=="mail") return getNotificationImage(); From 0f2a58dddefe92c6377ebb35d433800036eb54e5 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:31:37 -0700 Subject: [PATCH 187/202] Adding current weather to lcars --- apps/lcars/lcars.app.js | 9 +++++++++ apps/lcars/lcars.settings.js | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 167adad2d..4e1073723 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,5 +1,6 @@ const SETTINGS_FILE = "lcars.setting.json"; const Storage = require("Storage"); +const weather = require('weather'); // ...and overwrite them with any saved values @@ -145,6 +146,14 @@ function printData(key, y, c){ text = "VREF"; value = E.getAnalogVRef().toFixed(2) + "V"; + } else if (key == "Weather"){ + text = "TEMP"; + const w = weather.get(); + if (!w) { + value = "ERR"; + } else { + value = require('locale').temp(w.temp-273.15); // applies conversion + } } g.setColor(c); diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 0d004b002..b1fceb518 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -18,7 +18,7 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF"]; + var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF", "Weather"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, From 05215fab73314fca30696445cfe986b06b3c0d43 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:38:26 -0700 Subject: [PATCH 188/202] Updating version info for lcars --- apps.json | 2 +- apps/lcars/ChangeLog | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 389603249..8f1783f10 100644 --- a/apps.json +++ b/apps.json @@ -4498,7 +4498,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.09", + "version":"0.10", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index f5d8346da..8a8970124 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -6,4 +6,5 @@ 0.06: Fix - Alarm disabled, if clock was closed. 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. -0.09: Tab anywhere to open the launcher. \ No newline at end of file +0.09: Tab anywhere to open the launcher. +0.10: Added getting the gadgetbridge weather \ No newline at end of file From 78dc343afafa8abfaf5fcc391353473028d015c8 Mon Sep 17 00:00:00 2001 From: Jon Warrington Date: Mon, 10 Jan 2022 11:48:57 -0700 Subject: [PATCH 189/202] Fixing a problem with the lcars settings --- apps/lcars/lcars.settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index b1fceb518..a0e54f9b4 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -25,7 +25,7 @@ '< Back': back, 'Row 1': { value: 0 | data_options.indexOf(settings.dataRow1), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow1 = data_options[v]; @@ -34,7 +34,7 @@ }, 'Row 2': { value: 0 | data_options.indexOf(settings.dataRow2), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow2 = data_options[v]; @@ -43,7 +43,7 @@ }, 'Row 3': { value: 0 | data_options.indexOf(settings.dataRow3), - min: 0, max: 4, + min: 0, max: 5, format: v => data_options[v], onchange: v => { settings.dataRow3 = data_options[v]; From 791f88b0613b1776793ee478f11f6aad22a03b70 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 10 Jan 2022 20:27:40 +0100 Subject: [PATCH 190/202] New widget: Heart rate alarm --- apps.json | 16 +++++++++++ apps/hralarm/ChangeLog | 1 + apps/hralarm/README.md | 15 +++++++++++ apps/hralarm/settings.js | 57 +++++++++++++++++++++++++++++++++++++++ apps/hralarm/widget.js | 27 +++++++++++++++++++ apps/hralarm/widget.png | Bin 0 -> 12944 bytes 6 files changed, 116 insertions(+) create mode 100644 apps/hralarm/ChangeLog create mode 100644 apps/hralarm/README.md create mode 100644 apps/hralarm/settings.js create mode 100644 apps/hralarm/widget.js create mode 100644 apps/hralarm/widget.png diff --git a/apps.json b/apps.json index 389603249..08d6113d4 100644 --- a/apps.json +++ b/apps.json @@ -1351,6 +1351,22 @@ {"name":"pparrot.img","url":"party-parrot-icon.js","evaluate":true} ] }, + { + "id": "hralarm", + "name": "Heart rate alarm", + "shortName":"HR Alarm", + "version":"0.01", + "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", + "icon": "widget.png", + "type": "widget", + "tags": "widget", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"hralarm.wid.js","url":"widget.js"}, + {"name":"hralarm.settings.js","url":"settings.js"} + ] + }, { "id": "hrings", "name": "Hypno Rings", diff --git a/apps/hralarm/ChangeLog b/apps/hralarm/ChangeLog new file mode 100644 index 000000000..4c21f3ace --- /dev/null +++ b/apps/hralarm/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/hralarm/README.md b/apps/hralarm/README.md new file mode 100644 index 000000000..37b14ad9d --- /dev/null +++ b/apps/hralarm/README.md @@ -0,0 +1,15 @@ +# Heart rate alarm + +This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits. + +## Usage + +Configure the heart rate limits in the apps settings. This widget uses both 'HRM' and 'BTHRM' events. + +## Features + +Long vibration every 10 seconds on reaching upper limit, short vibrations between upper limit and warning threshold and an single vibration when reaching the lower limit again. + +## Requests/Creator + +https://github.com/halemmerich diff --git a/apps/hralarm/settings.js b/apps/hralarm/settings.js new file mode 100644 index 000000000..3158ab8b7 --- /dev/null +++ b/apps/hralarm/settings.js @@ -0,0 +1,57 @@ +(function(back) { + var FILE = "hralarm.json"; + + var settings = Object.assign({ + enabled: false, + upper: 180, + warning: 170, + lower: 150, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + E.showMenu({ + '': { 'title': 'HR Alarm' }, + '< Back': back, + 'Enabled': { + value: !!settings.enabled, + format: v => settings.enabled ? "On" : "Off", + onchange: v => { + settings.enabled = v; + writeSettings(); + } + }, + 'Upper limit': { + value: settings.upper, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.upper = v; + writeSettings(); + } + }, + 'Lower limit': { + value: settings.lower, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.lower = v; + writeSettings(); + } + }, + 'Warning at': { + value: settings.warning, + min: 0, + step:5, + max: 300, + onchange: v => { + settings.warning = v; + writeSettings(); + } + } + }); +}) diff --git a/apps/hralarm/widget.js b/apps/hralarm/widget.js new file mode 100644 index 000000000..30a94fdf2 --- /dev/null +++ b/apps/hralarm/widget.js @@ -0,0 +1,27 @@ +(() => { + var settings = require('Storage').readJSON("hralarm.json", true) || {}; + if (!settings.enabled){ Bangle.setHRMPower(0, 'hralarm'); return; } + Bangle.setHRMPower(1, 'hralarm'); + var hitLimit = 0; + var checkHr = function(hr){ + if (hr.bpm > settings.warning && hr.bpm <= settings.upper){ + Bangle.buzz(100, 1); + } + if (hitLimit < getTime() && hr.bpm > settings.upper){ + hitLimit = getTime() + 10; + Bangle.buzz(2000, 1); + } + if (hitLimit > 0 && hr.bpm < settings.lower){ + hitLimit = 0; + Bangle.buzz(500, 1); + } + }; + Bangle.on("HRM", checkHr); + Bangle.on("BTHRM", checkHr); + + WIDGETS["hralarm"]={ + area:"tl", + width: 0, + draw: function(){} + }; +})() diff --git a/apps/hralarm/widget.png b/apps/hralarm/widget.png new file mode 100644 index 0000000000000000000000000000000000000000..726cf3f9bb528f4a8aecd0fba7e4862f4cc4ec2d GIT binary patch literal 12944 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 Date: Mon, 10 Jan 2022 13:47:50 -0700 Subject: [PATCH 191/202] Incrementing the version number --- apps.json | 2 +- apps/lcars/ChangeLog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 8f1783f10..658adaaa8 100644 --- a/apps.json +++ b/apps.json @@ -4498,7 +4498,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.10", + "version":"0.11", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 8a8970124..ad5330b26 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -7,4 +7,4 @@ 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. -0.10: Added getting the gadgetbridge weather \ No newline at end of file +0.11: Added getting the gadgetbridge weather \ No newline at end of file From 53f787fff740d10efb6c10efed3b828fbf7130e8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 10 Jan 2022 22:02:29 +0100 Subject: [PATCH 192/202] Lap Counter - Use themeable icon --- apps.json | 2 +- apps/lapcounter/ChangeLog | 1 + apps/lapcounter/app-icon.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 389603249..af3bb44d8 100644 --- a/apps.json +++ b/apps.json @@ -5046,7 +5046,7 @@ { "id": "lapcounter", "name": "Lap Counter", - "version": "0.01", + "version": "0.02", "description": "Click button to count laps. Shows count and total time snapshot (like a stopwatch, but laid back).", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/apps/lapcounter/ChangeLog b/apps/lapcounter/ChangeLog index 9db0e26c5..146ff1b05 100644 --- a/apps/lapcounter/ChangeLog +++ b/apps/lapcounter/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: Themeable app icon diff --git a/apps/lapcounter/app-icon.js b/apps/lapcounter/app-icon.js index a443b3a41..354c07124 100644 --- a/apps/lapcounter/app-icon.js +++ b/apps/lapcounter/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwkBiIA/AH4A/AAkQgEBAREAC6oABdZQXkI6wuKC5iPUFxoXIOpoX/C6QFCC6IsCC6ZEDC/4XcPooXOFgoXQIgwX/C7IUFC5wsIC5ouCC6hcJC5h1DF9YwBChCPOAH4A/AH4Ap")) +require("heatshrink").decompress(atob("mEwwI0xg+evPsAon+ApX8Aon4AonwAod78AFDv4FWvoFE/IFDz4FXvIFD3wFE/wFW7wFDh5xBAoUfAok/Aol/BZUXAogA6A=")) From 52647e7a8a9650e7e22389aedc3cfae80a92ecc0 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:08:06 +0100 Subject: [PATCH 193/202] fixed typo in readme.md --- apps/antonclk/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index fa4cc4919..c2c8b917e 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,7 +40,10 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -**Show Weeknumber** - Weeknumber (ISO-8601) is shown. +* **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) +when weekday name "Off" it displays week #: +when weekday name "On": weekday name is cut at 6th position and .# is added +If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. Otherwise, a scaled version of the built-in 6x8 pixels font is used. From 1a21358f2be7fe4f5dcdddb324c14e1f698aa610 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:12:04 +0100 Subject: [PATCH 194/202] Updated readme.md typo / format --- apps/antonclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index c2c8b917e..38a42aa22 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,8 +41,8 @@ The main menu contains several settings covering Anton clock in general. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -when weekday name "Off" it displays week #: -when weekday name "On": weekday name is cut at 6th position and .# is added +If "Show Weekday" is "Off" the week-number is displayed as week #:. +If "Show Weekday" is "On" the weekday name is cut at 6th position and .# is added. If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. From 3e458115046ec7182edb00871ca3077f1253728d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:13:34 +0100 Subject: [PATCH 195/202] Updated readme.md type / format --- apps/antonclk/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 38a42aa22..85c03788d 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -41,8 +41,8 @@ The main menu contains several settings covering Anton clock in general. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. * **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -If "Show Weekday" is "Off" the week-number is displayed as week #:. -If "Show Weekday" is "On" the weekday name is cut at 6th position and .# is added. +If "Show Weekday" is "Off" the week-number is displayed as "week #:". +If "Show Weekday" is "On" the weekday name is cut at 6th position and suffixed with ".#". If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. From dcc4dc8e66c43eaf7bc0d54128e790572d904ee8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 11 Jan 2022 00:16:40 +0100 Subject: [PATCH 196/202] app.js - bugfix: removed codefragement testdata "thursday" added todo for locale "week" --- apps/antonclk/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index be6c23789..05758cbfd 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -188,9 +188,8 @@ function draw() { g.drawString(dateStr, x, y); if (weekDay || calWeek) { var dowwumStr = require("locale").dow(date); - dowwumStr = "thursday"; if (calWeek) - dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); + dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week" if (upperCase) dowwumStr = dowwumStr.toUpperCase(); g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); From 7905d3cffc5a268635e13baa0b05cbdd97b9ddc1 Mon Sep 17 00:00:00 2001 From: BartS23 <10829389+BartS23@users.noreply.github.com> Date: Mon, 10 Jan 2022 16:11:09 +0100 Subject: [PATCH 197/202] Reduce FIFO_FULL messages 1. the lazy layout rendering takes too much time. 2. enable the gps at the end of the file. 3. save SATinView to detect changes. --- apps/gpsinfo/gps-info.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index fdac3d403..79acc05fe 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -4,7 +4,7 @@ function satelliteImage() { var Layout = require("Layout"); var layout; -Bangle.setGPSPower(1, "app"); +//Bangle.setGPSPower(1, "app"); E.showMessage("Loading..."); // avoid showing rubbish on screen var lastFix = { @@ -19,7 +19,7 @@ var lastFix = { var SATinView = 0; var nofBD = 0; var nofGP = 0; -var listenerGPSraw = 1; +var listenerGPSraw = 0; function formatTime(now) { if (now == undefined) { @@ -87,12 +87,12 @@ function onGPS(fix) { {type:"txt", font:"6x8", pad:3, label:"Satellites used" } ]}, {type:"txt", font:"6x8", label:"", fillx:true, id:"progress" } - ]},{lazy:true}); + ]},{lazy:false}); } g.clearRect(0,24,g.getWidth(),g.getHeight()); layout.render(); } - lastFix = fix; + //lastFix = fix; if (fix.fix) { if (listenerGPSraw == 1) { Bangle.removeListener('GPS-raw', onGPSraw); @@ -108,6 +108,7 @@ function onGPS(fix) { layout.time.label = "Time: "+formatTime(fix.time); layout.sat.label = "Satellites: "+satellites; layout.maidenhead.label = "Maidenhead: "+maidenhead; + layout.render(); } else { if (listenerGPSraw == 0) { Bangle.on('GPS-raw', onGPSraw); @@ -116,7 +117,15 @@ function onGPS(fix) { layout.sat.label = fix.satellites; layout.progress.label = "in view: " + SATinView; } - layout.render(); + //layout.render(); + + if (listenerGPSraw == 0 && !fix.fix) { + setTimeout(() => Bangle.on('GPS-raw', onGPSraw), 10); + listenerGPSraw = 1; + } + + lastFix = fix; + lastFix.SATinView = SATinView; } function onGPSraw(nmea) { @@ -129,7 +138,8 @@ function onGPSraw(nmea) { Bangle.loadWidgets(); Bangle.drawWidgets(); Bangle.on('GPS', onGPS); -Bangle.on('GPS-raw', onGPSraw); +//Bangle.on('GPS-raw', onGPSraw); +Bangle.setGPSPower(1, "app"); function exitApp() { load(); From 8053de33079cc96be65ed2bb1f82557dc1dc0006 Mon Sep 17 00:00:00 2001 From: BartS23 <10829389+BartS23@users.noreply.github.com> Date: Mon, 10 Jan 2022 20:37:22 +0100 Subject: [PATCH 198/202] Fix layout and double enabling of event GPS-raw --- apps/gpsinfo/gps-info.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 79acc05fe..f4521f265 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -110,12 +110,16 @@ function onGPS(fix) { layout.maidenhead.label = "Maidenhead: "+maidenhead; layout.render(); } else { - if (listenerGPSraw == 0) { - Bangle.on('GPS-raw', onGPSraw); - listenerGPSraw = 1; + if (fix.satelites != lastFix.satelites) { + layout.clear(layout.sat); + layout.sat.label = fix.satellites; + layout.render(layout.sat); + } + if (SATinView != lastFix.SATinView) { + layout.clear(layout.progress); + layout.progress.label = "in view: " + SATinView; + layout.render(layout.progress); } - layout.sat.label = fix.satellites; - layout.progress.label = "in view: " + SATinView; } //layout.render(); From 0c0d7e9dd17ee2565aebe20682a82af66944bc94 Mon Sep 17 00:00:00 2001 From: Romek Date: Tue, 11 Jan 2022 11:10:54 +0100 Subject: [PATCH 199/202] Update changelog and version --- apps.json | 2 +- apps/gpsinfo/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 02076497e..57934dff3 100644 --- a/apps.json +++ b/apps.json @@ -1520,7 +1520,7 @@ { "id": "gpsinfo", "name": "GPS Info", - "version": "0.08", + "version": "0.09", "description": "An application that displays information about altitude, lat/lon, satellites and time", "icon": "gps-info.png", "type": "app", diff --git a/apps/gpsinfo/ChangeLog b/apps/gpsinfo/ChangeLog index 8d428ce85..414b9d9fb 100644 --- a/apps/gpsinfo/ChangeLog +++ b/apps/gpsinfo/ChangeLog @@ -5,3 +5,4 @@ 0.06: Add number of satellites in view and fix crash with GPS time 0.07: Resolve one FIFO_FULL case and exit App with button press 0.08: Leave GPS power switched on on exit (will switch off after 0.5 seconds anyway) +0.09: Fix FIFO_FULL error From d59db5ba381941c14abc0676c2fb174063a2e2d9 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 11:48:10 +0100 Subject: [PATCH 200/202] Show correct percentage values in circles --- apps.json | 2 +- apps/circlesclock/ChangeLog | 1 + apps/circlesclock/app.js | 13 ++++++------- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/apps.json b/apps.json index 02076497e..8d1e481a1 100644 --- a/apps.json +++ b/apps.json @@ -5097,7 +5097,7 @@ { "id": "circlesclock", "name": "Circles clock", "shortName":"Circles clock", - "version":"0.04", + "version":"0.05", "description": "A clock with circles for different data at the bottom in a probably familiar style", "icon": "app.png", "screenshots": [{"url":"screenshot-dark.png"}, {"url":"screenshot-light.png"}], diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index ca1da6e21..86b77bb6f 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -5,3 +5,4 @@ Add step distance and weather Allow switching visibility of widgets Make circles and text slightly bigger +0.05: Show correct percentage values in circles diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 91d4937c4..de7bc73f9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -363,22 +363,21 @@ function radians(a) { } function drawGauge(cx, cy, percent, color) { - let offset = 30; - let end = 300; - var i = 0; - var r = radiusInner + 3; + const offset = 15; + const end = 345; + const r = radiusInner + 3; if (percent <= 0) return; if (percent > 1) percent = 1; - var startrot = -offset; - var endrot = startrot - ((end - offset) * percent) - 35; + const startrot = -offset; + const endrot = startrot - ((end - offset) * percent); g.setColor(color); const size = radiusOuter - radiusInner - 2; // draw gauge - for (i = startrot; i > endrot - size; i -= size) { + for (let i = startrot; i > endrot - size; i -= size) { x = cx + r * Math.sin(radians(i)); y = cy + r * Math.cos(radians(i)); g.fillCircle(x, y, size); From d12a415740bd5236d9d475551a9fac69e2bee62a Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 13:52:19 +0100 Subject: [PATCH 201/202] Show humidity as weather circle data --- apps/circlesclock/README.md | 3 +++ apps/circlesclock/app.js | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/apps/circlesclock/README.md b/apps/circlesclock/README.md index 9aaa4bc8e..c3704e3d7 100644 --- a/apps/circlesclock/README.md +++ b/apps/circlesclock/README.md @@ -10,6 +10,9 @@ It can show the following information (this can be configured): * Heart rate (automatically updates when screen is on and unlocked) * Battery (including charging status and battery low warning) * Weather (requires [weather app](https://banglejs.com/apps/#weather)) + * Humidity as circle progress + * Temperature inside circle + * Condition as icon below circle ## Screenshots ![Screenshot dark theme](screenshot-dark.png) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index de7bc73f9..822802afa 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -283,6 +283,7 @@ function drawWeather(w) { if (!w) w = getCirclePosition("weather"); const weather = getWeather(); const tempString = weather ? locale.temp(weather.temp - 273.15) : undefined; + const humidity = weather ? weather.hum : undefined; const code = weather ? weather.code : -1; // Draw rectangle background: @@ -292,6 +293,10 @@ function drawWeather(w) { g.setColor(colorGrey); g.fillCircle(w, h3, radiusOuter); + if (humidity >= 0) { + drawGauge(w, h3, humidity / 100, colorYellow); + } + g.setColor(colorBg); g.fillCircle(w, h3, radiusInner); From a29dbeedd3cf3b0084999fca59244d739bb0ee4b Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 14:08:48 +0100 Subject: [PATCH 202/202] Update changelog --- apps/circlesclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/circlesclock/ChangeLog b/apps/circlesclock/ChangeLog index 86b77bb6f..5464a8103 100644 --- a/apps/circlesclock/ChangeLog +++ b/apps/circlesclock/ChangeLog @@ -6,3 +6,4 @@ Allow switching visibility of widgets Make circles and text slightly bigger 0.05: Show correct percentage values in circles + Show humidity as weather circle data