From bf9f0e4db721e8b5d56517725f4df250dfedf3e3 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Wed, 8 Dec 2021 20:38:15 +0100 Subject: [PATCH 01/38] Workaround call notifications with gadgetbridge I have missed a few calls as my watch didn't inform me about them. Using gbdebug it turns out the cmd left empty. --- apps/gbridge/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index 53f832b07..dc10587e1 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -184,7 +184,7 @@ case "call": var note = { size: 55, title: event.name, id: "call", body: event.number, icon:require("heatshrink").decompress(atob("jEYwIMJj4CCwACJh4CCCIMOAQMGAQMHAQMDAQMBCIMB4PwgHz/EAn4CBj4CBg4CBgACCAAw="))} - if (event.cmd === "incoming") { + if (event.cmd === "incoming" || event.cmd === "") { require("notify").show(note); if (!(require('Storage').readJSON('setting.json',1)||{}).quiet) { Bangle.buzz(); From c88121daf8341392f5b7d59a308ee77a98cd5eaf Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Wed, 8 Dec 2021 21:05:21 +0100 Subject: [PATCH 02/38] Bumbed gbridge version --- apps.json | 2 +- apps/gbridge/ChangeLog | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e5d6dad8a..611a78923 100644 --- a/apps.json +++ b/apps.json @@ -282,7 +282,7 @@ { "id": "gbridge", "name": "Gadgetbridge", - "version": "0.24", + "version": "0.25", "description": "The default notification handler for Gadgetbridge notifications from Android. This will eventually be replaced by the 'Android' app.", "icon": "app.png", "type": "widget", diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index fddb1eb80..5a08af49f 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -24,3 +24,4 @@ 0.22: Respect Quiet Mode 0.23: Allow notification dismiss to remove from phone too 0.24: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) +0.25: workaround call notification From dfe753d306bf12f9b1ff58f8a8a2e57aa995de60 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Fri, 10 Dec 2021 23:33:47 +0900 Subject: [PATCH 03/38] Create awairmonitor/app.js --- apps/awairmonitor/app.js | 97 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 apps/awairmonitor/app.js diff --git a/apps/awairmonitor/app.js b/apps/awairmonitor/app.js new file mode 100644 index 000000000..19905de13 --- /dev/null +++ b/apps/awairmonitor/app.js @@ -0,0 +1,97 @@ +Graphics.prototype.setFontMichroma36 = function() { +g.setFontCustom(atob("AAAAAAAAAAAAAAAAeAAAAAeAAAAAeAAAAAeAAAAAAAAAAAAAAAAAAAAAAAGAAAAA+AAAAD+AAAAP+AAAA/8AAAD/wAAAf/AAAB/4AAAH/gAAAf+AAAB/4AAAH/gAAAf+AAAAfwAAAAfAAAAAcAAAAAAAAAAAAAAAAAAAAAAAA///AAD///wAH///4AP///8APwAD+APAAAeAeAAAeAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAPAeAAAeAPAAAeAPwAD+AP///8AH///4AD///wAA///AAAAAAAAAAAAAAAAAAAAAEAAAAAOAAAAAfAAAAA+AAAAB8AAAAD8AAAAH4AAAAPwAAAAPgAAAAfAAAAAf///+Af///+Af///+Af///+AAAAAAAAAAAAAAAAAAAAAAAAAA/Af+AD/A/+AH/B/+AP/D/+APwD4eAPADweAfADweAeADweAeADweAeADweAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAHgeAeAPgeAeAPAeAeAPAeAeAPAeAeAPAeAfAPAeAPw/AeAP/+AeAH/+AeAD/8AeAB/wAOAAAAAAAAAAAAAAAAAAAAAAAAAB8APgAD8AP4AH8AP8AP8AP8APgAB+AfAAAeAeAAAeAeAAAPAeAAAPAeAAAPAeAAAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAPAeAeAeAfAeAeAPx/h+AP///+AH///8AD///4AB/h/gAAAAAAAAAAAAAAAAAAAAAAeAAAAA/AAAAA/AAAAB/AAAAD/AAAAH/AAAAPvAAAAPPAAAAfPAAAA+PAAAB8PAAAD4PAAADwPAAAHwPAAAPgPAAAfAPAAA+APAAA8APAAB8APAAD4APAAHwAPAAPgAPAAPAAPAAfAAPAAf///+Af///+Af///+Af///+AAAAPAAAAAPAAAAAPAAAAAPAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAf/8PgAf/8P4Af/8P8Af/8P8AeB4A+AeB4AeAeDwAeAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAPAeDwAfAeDwAeAeD4A+AeD+D+AeB//8AeB//4AeA//4AAAP/AAAAAAAAAAAAAAAAAAAAAAAAAAA///AAD///wAH///4AH///8AP4fB+APAeAeAfA8AeAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAfA8APAPA+AeAPgeAeAP8fh+AH8f/8AD8P/8AA8H/4AAAB/gAAAAAAAAAAAAAAAAAAAAAAAAAeAAAAAeAAAAAeAAAAAeAAAAAeAAAAAeAAACAeAAAGAeAAAOAeAAAeAeAAA+AeAAD+AeAAH8AeAAP4AeAAfwAeAA/gAeAB/AAeAD+AAeAP4AAeAfwAAeA/gAAeB/AAAeD+AAAeH8AAAefwAAAe/gAAAf/AAAAf+AAAAf8AAAAf4AAAAfgAAAAfAAAAAAAAAAAAAAAAAAAAAAAAAAMAAB+B/wAD/j/4AH/3/8AP///+AP//A+AfB+AeAeA+AeAeA+APAeA+APAeA+APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA8APAeA+APAeA+APAeA+APAeA+AOAeA+AeAPh/A+AP///+AP/3/8AH/3/8AB/D/wAAAA/AAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAD/4HAAH/8HwAP/+H4AP5/H8AfAfA8AeAPAeAeAPAeAeAPAeAeAHgfAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHgPAeAHAPAeAPAOAeAPAeAPAPAeAPwfB+AP///8AH///4AD///wAA///AAAAAAAAAAAAAAAAAAAAAAAAAAAB8DwAAB8HwAAB8HwAAB8DwAAAAAAAAAAAAA"), 46, atob("CBIkESMjJCMjIyMjCA=="), 36+(1<<8)+(1<<16)); +}; + +var drawTimeout; + +function queueNextDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 1000 - (Date.now() % 1000)); +} + +var locale = require("locale"); + +var bt_current_co2 = 0; +var bt_current_voc = 0; +var bt_current_pm25 = 0; +var bt_current_humi = 0; +var bt_current_temp = 0; +var bt_last_update = 0; + +var last_update = 0; +var bt_co2_history = new Array(10).fill(0); +var bt_voc_history = new Array(10).fill(0); +var bt_pm25_history = new Array(10).fill(0); +var bt_humi_history = new Array(10).fill(0); +var bt_temp_history = new Array(10).fill(0); + +var internal_last_update = -1; + +function draw() { + g.reset().clearRect(0,24,g.getWidth(),g.getHeight()); + + var date = new Date(); + g.setFontAlign(0,0); + g.setFont("Michroma36").drawString(locale.time(date,1), g.getWidth()/2, 56); + + g.setFont("6x8"); + g.drawString(locale.date(new Date(),1), g.getWidth()/2, 80); + + g.setFont("6x8"); + g.drawString("CO2", 20, 100); + g.drawString("VOC", 55, 100); + g.drawString("PM25", 90, 100); + g.drawString("Humi", 125, 100); + g.drawString("Temp", 160, 100); + + g.setFont("HaxorNarrow7x17"); + g.drawString(""+bt_current_co2, 18, 110); + g.drawString(""+bt_current_voc, 53, 110); + g.drawString(""+bt_current_pm25, 88, 110); + g.drawString(""+bt_current_humi, 123, 110); + g.drawString(""+bt_current_temp, 158, 110); + + if (last_update != bt_last_update) { + last_update = bt_last_update; + internal_last_update = last_update; + if (last_update % 10 == 0) { + bt_co2_history.shift(); bt_co2_history.push(bt_current_co2); + bt_voc_history.shift(); bt_voc_history.push(bt_current_voc); + bt_pm25_history.shift(); bt_pm25_history.push(bt_current_pm25); + bt_humi_history.shift(); bt_humi_history.push(bt_current_humi); + bt_temp_history.shift(); bt_temp_history.push(bt_current_temp); + } + } + + if (internal_last_update == -1) { + g.drawString("Waiting for connection", 88, 164); + } else if (internal_last_update > last_update + 5) { + g.drawString("Trying to reconnect since " + (internal_last_update - last_update), 88, 164); + } + + + for (i = 0; i < 10; i++) { + // max height = 32 + g.drawLine(10+i*2, 150-(Math.min(Math.max(bt_co2_history[i],400), 1200)-400)/25, 10+i*2, 150); + g.drawLine(45+i*2, 150-(Math.min(Math.max(bt_voc_history[i],0), 1440)-0)/45, 45+i*2, 150); + g.drawLine(80+i*2, 150-(Math.min(Math.max(bt_pm25_history[i],0), 32)-0)/1, 80+i*2, 150); + g.drawLine(115+i*2, 150-(Math.min(Math.max(bt_humi_history[i],20), 60)-20)/1.25, 115+i*2, 150); + g.drawLine(150+i*2, 150-(Math.min(Math.max(bt_temp_history[i],16), 32)-16)*2, 150+i*2, 150); + + // target humidity level + g.setColor("#00F").drawLine(115, 150-(40-20)/1.25, 115+18, 150-(40-20)/1.25); + } + + if (internal_last_update != -1) { internal_last_update++; } + queueNextDraw(); +} + +// init +require("FontHaxorNarrow7x17").add(Graphics); +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +draw(); From b88223ed0ddc9594698cb877ae25d248cd165afc Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 00:02:39 +0900 Subject: [PATCH 04/38] AwairMonitor: fixed graph color and temperature scale --- apps/awairmonitor/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/awairmonitor/app.js b/apps/awairmonitor/app.js index 19905de13..a5a1d1a72 100644 --- a/apps/awairmonitor/app.js +++ b/apps/awairmonitor/app.js @@ -79,10 +79,11 @@ function draw() { g.drawLine(45+i*2, 150-(Math.min(Math.max(bt_voc_history[i],0), 1440)-0)/45, 45+i*2, 150); g.drawLine(80+i*2, 150-(Math.min(Math.max(bt_pm25_history[i],0), 32)-0)/1, 80+i*2, 150); g.drawLine(115+i*2, 150-(Math.min(Math.max(bt_humi_history[i],20), 60)-20)/1.25, 115+i*2, 150); - g.drawLine(150+i*2, 150-(Math.min(Math.max(bt_temp_history[i],16), 32)-16)*2, 150+i*2, 150); + g.drawLine(150+i*2, 150-(Math.min(Math.max(bt_temp_history[i],19), 27)-19)*4, 150+i*2, 150); // target humidity level g.setColor("#00F").drawLine(115, 150-(40-20)/1.25, 115+18, 150-(40-20)/1.25); + g.reset(); } if (internal_last_update != -1) { internal_last_update++; } From 60eb8ef7ecf856e49331c514458ae188f9d9f8b5 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 00:10:37 +0900 Subject: [PATCH 05/38] AwairMonitor: screenshot --- apps/awairmonitor/screenshot.png | Bin 0 -> 3974 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/awairmonitor/screenshot.png diff --git a/apps/awairmonitor/screenshot.png b/apps/awairmonitor/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..51ca0aa44aa953c2748c61795b163b1e7851cb68 GIT binary patch literal 3974 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 literal 0 HcmV?d00001 From 854d2f9ade63f8e6ca459d290caa6bc176254feb Mon Sep 17 00:00:00 2001 From: crazysaem Date: Fri, 10 Dec 2021 14:41:49 +0000 Subject: [PATCH 06/38] ptlaunch: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns. --- apps.json | 2 +- apps/ptlaunch/ChangeLog | 1 + apps/ptlaunch/README.md | 1 + apps/ptlaunch/app.js | 13 +++++++++++++ 4 files changed, 16 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd2e14e60..af47e5a48 100644 --- a/apps.json +++ b/apps.json @@ -4829,7 +4829,7 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.02", + "version": "0.03", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", "tags": "tools", diff --git a/apps/ptlaunch/ChangeLog b/apps/ptlaunch/ChangeLog index f50936885..f93cedeab 100644 --- a/apps/ptlaunch/ChangeLog +++ b/apps/ptlaunch/ChangeLog @@ -1,2 +1,3 @@ 0.01: Initial creation of the pattern launch app 0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings +0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns. diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index a69492782..af91658a5 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -18,6 +18,7 @@ From the main menu you can: - Add a new pattern and link it to an app (first entry) - To create a new pattern first select "Add Pattern" - Now draw any pattern you like, this will later launch the linked app from the clock screen + - You can also draw a single-circle pattern (meaning a single tap on one circle) instead of drawing a 'complex' pattern - If you don't like the pattern, simply re-draw it. The previous pattern will be discarded. - If you are happy with the pattern tap on screen or press the button to continue - Now select the app you want to launch with the pattern. diff --git a/apps/ptlaunch/app.js b/apps/ptlaunch/app.js index 8ba1adf81..f5fad7897 100644 --- a/apps/ptlaunch/app.js +++ b/apps/ptlaunch/app.js @@ -147,13 +147,26 @@ var createPattern = () => { setWatch(() => finishHandler(), BTN); setTimeout(() => Bangle.on("tap", finishHandler), 250); + positions = []; var dragHandler = (position) => { + log(position); positions.push(position); debounce().then(() => { if (isFinished) { return; } + + // This might actually be a 'tap' event. + // Use this check in addition to the actual tap handler to make it more reliable + if (pattern.length > 0 && positions.length === 2) { + if (positions[0].x === positions[1].x && positions[0].y === positions[1].y) { + finishHandler(); + positions = []; + return; + } + } + E.showMessage("Calculating..."); var t0 = Date.now(); From 31a4d05cb365b6e8b37d35f23848214de068b8ee Mon Sep 17 00:00:00 2001 From: crazysaem Date: Fri, 10 Dec 2021 17:48:25 +0000 Subject: [PATCH 07/38] ptlaunch: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible. --- apps.json | 2 +- apps/ptlaunch/ChangeLog | 1 + apps/ptlaunch/README.md | 20 +- apps/ptlaunch/app.js | 314 +++++++++++++++++++++-------- apps/ptlaunch/main_menu.png | Bin 2840 -> 0 bytes apps/ptlaunch/main_menu_add.png | Bin 0 -> 3017 bytes apps/ptlaunch/main_menu_manage.png | Bin 0 -> 2955 bytes apps/ptlaunch/manage_patterns.png | Bin 0 -> 2670 bytes 8 files changed, 249 insertions(+), 88 deletions(-) delete mode 100644 apps/ptlaunch/main_menu.png create mode 100644 apps/ptlaunch/main_menu_add.png create mode 100644 apps/ptlaunch/main_menu_manage.png create mode 100644 apps/ptlaunch/manage_patterns.png diff --git a/apps.json b/apps.json index af47e5a48..65ef9bcea 100644 --- a/apps.json +++ b/apps.json @@ -4829,7 +4829,7 @@ "id": "ptlaunch", "name": "Pattern Launcher", "shortName": "Pattern Launcher", - "version": "0.03", + "version": "0.10", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", "tags": "tools", diff --git a/apps/ptlaunch/ChangeLog b/apps/ptlaunch/ChangeLog index f93cedeab..de38d715a 100644 --- a/apps/ptlaunch/ChangeLog +++ b/apps/ptlaunch/ChangeLog @@ -1,3 +1,4 @@ 0.01: Initial creation of the pattern launch app 0.02: Turn on lcd when launching an app if the lock screen was disabled in the settings 0.03: Make tap to confirm new pattern more reliable. Also allow for easier creation of single circle patterns. +0.10: Improve the management of existing patterns: Draw the linked pattern on the left hand side of the app name within a scroller, similar to the default launcher. Slighlty clean up the code to make it less horrible. \ No newline at end of file diff --git a/apps/ptlaunch/README.md b/apps/ptlaunch/README.md index af91658a5..8d61afece 100644 --- a/apps/ptlaunch/README.md +++ b/apps/ptlaunch/README.md @@ -8,12 +8,19 @@ 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. -## Screenshots and detailed steps +## Add Pattern Screenshots -![](main_menu.png) +![](main_menu_add.png) ![](add_pattern.png) ![](select_app.png) +## Manage Pattern Screenshots + +![](main_menu_manage.png) +![](manage_patterns.png) + +## Detailed Steps + From the main menu you can: - Add a new pattern and link it to an app (first entry) - To create a new pattern first select "Add Pattern" @@ -23,11 +30,10 @@ From the main menu you can: - If you are happy with the pattern tap on screen or press the button to continue - Now select the app you want to launch with the pattern. - Note, you can bind multiple patterns to the same app. -- Remove linked patterns (second entry) - - To remove a pattern first select "Remove Pattern" - - You will now see a list of apps that have patterns linked to them - - Simply select the app that you want to unlink. This will remove the saved pattern, but not the app itself! - - Note, that you can not actually preview the patterns. This makes removing patterns that are linked to the same app annoying. sorry! +- Manage created patterns (second entry) + - To manage your patterns first select "Manage Patterns" + - You will now see a scrollabe list of patterns + linked apps + - If you want to deletion a pattern (and unlink the app) simply tap on it, and confirm the deletion - Disable the lock screen on the clock screen from the settings (third entry) - To launch the app from the pattern on the clock screen the watch must be unlocked. - If this annoys you, you can disable the lock on the clock screen from the setting here diff --git a/apps/ptlaunch/app.js b/apps/ptlaunch/app.js index f5fad7897..1d3a07674 100644 --- a/apps/ptlaunch/app.js +++ b/apps/ptlaunch/app.js @@ -1,5 +1,3 @@ -var storage = require("Storage"); - var DEBUG = false; var log = (message) => { if (DEBUG) { @@ -7,20 +5,7 @@ var log = (message) => { } }; -var CIRCLE_RADIUS = 25; -var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; - -var CIRCLES = [ - { x: 25, y: 25, i: 0 }, - { x: 87, y: 25, i: 1 }, - { x: 150, y: 25, i: 2 }, - { x: 25, y: 87, i: 3 }, - { x: 87, y: 87, i: 4 }, - { x: 150, y: 87, i: 5 }, - { x: 25, y: 150, i: 6 }, - { x: 87, y: 150, i: 7 }, - { x: 150, y: 150, i: 8 }, -]; +var storage = require("Storage"); var showMainMenu = () => { log("loading patterns"); @@ -73,17 +58,32 @@ var showMainMenu = () => { }); }); }, - "Remove Pattern": () => { + "Manage Patterns": () => { log("selecting pattern through app"); - getStoredPatternViaApp(storedPatterns).then((pattern) => { - E.showMessage("Deleting..."); - delete storedPatterns[pattern]; - storage.writeJSON("ptlaunch.patterns.json", storedPatterns); - showMainMenu(); + showScrollerContainingAppsWithPatterns().then((selected) => { + var pattern = selected.pattern; + var appName = selected.appName; + if (pattern === "back") { + showMainMenu(); + } else { + E.showPrompt(appName + "\n\npattern:\n" + pattern, { + title: "Delete?", + buttons: { Yes: true, No: false }, + }).then((confirm) => { + if (confirm) { + E.showMessage("Deleting..."); + delete storedPatterns[pattern]; + storage.writeJSON("ptlaunch.patterns.json", storedPatterns); + showMainMenu(); + } else { + showMainMenu(); + } + }); + } }); }, Settings: () => { - var settings = storedPatterns["settings"] || {}; + var settings = storedPatterns.settings || {}; var settingsmenu = { "": { @@ -98,7 +98,7 @@ var showMainMenu = () => { if (settings.lockDisabled) { settingsmenu["Enable lock"] = () => { settings.lockDisabled = false; - storedPatterns["settings"] = settings; + storedPatterns.settings = settings; Bangle.setOptions({ lockTimeout: 1000 * 30 }); storage.writeJSON("ptlaunch.patterns.json", storedPatterns); showMainMenu(); @@ -106,7 +106,7 @@ var showMainMenu = () => { } else { settingsmenu["Disable lock"] = () => { settings.lockDisabled = true; - storedPatterns["settings"] = settings; + storedPatterns.settings = settings; storage.writeJSON("ptlaunch.patterns.json", storedPatterns); Bangle.setOptions({ lockTimeout: 1000 * 60 * 60 * 24 * 365 }); showMainMenu(); @@ -119,9 +119,7 @@ var showMainMenu = () => { E.showMenu(mainmenu); }; -var drawCircle = (circle) => { - g.fillCircle(circle.x, circle.y, CIRCLE_RADIUS); -}; +showMainMenu(); var positions = []; var createPattern = () => { @@ -160,13 +158,16 @@ var createPattern = () => { // This might actually be a 'tap' event. // Use this check in addition to the actual tap handler to make it more reliable if (pattern.length > 0 && positions.length === 2) { - if (positions[0].x === positions[1].x && positions[0].y === positions[1].y) { + if ( + positions[0].x === positions[1].x && + positions[0].y === positions[1].y + ) { finishHandler(); positions = []; return; } } - + E.showMessage("Calculating..."); var t0 = Date.now(); @@ -354,54 +355,217 @@ var getSelectedApp = () => { }); }; -var getStoredPatternViaApp = (storedPatterns) => { - E.showMessage("Loading patterns..."); - log("getStoredPatternViaApp"); +////// +// manage pattern related variables and functions +// - draws all saved patterns and their linked app names +// - uses the scroller to allow the user to browse through them +////// + +var scrollerFont = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; + +var drawBackButton = (r) => { + g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1); + g.setFont(scrollerFont) + .setFontAlign(-1, 0) + .drawString("< Back", 64, r.y + 32); +}; + +var drawAppWithPattern = (i, r, storedPatterns) => { + log("draw app with pattern"); + log({ i: i, r: r, storedPatterns: storedPatterns }); + var storedPattern = storedPatterns[i]; + var pattern = storedPattern.pattern; + var app = storedPattern.app; + + g.clearRect(r.x, r.y, r.x + r.w - 1, r.y + r.h - 1); + + g.drawLine(r.x, r.y, 176, r.y); + + drawCirclesWithPattern(pattern, 0.33, { x: 1, y: 3 + r.y }); + + g.setColor(0, 0, 0); + var appName = g.wrapString(app.name, g.getWidth() - 64).join("\n"); + g.setFont(scrollerFont) + .setFontAlign(-1, 0) + .drawString(appName, 64, r.y + 32); +}; + +var showScrollerContainingAppsWithPatterns = () => { + var storedPatternsArray = getStoredPatternsArray(); + log("drawing scroller for stored patterns"); + log(storedPatternsArray); + log(storedPatternsArray.length); + + g.clear(); + + var c = Math.max(storedPatternsArray.length + 1, 3); + return new Promise((resolve) => { - var selectPatternMenu = { - "": { - title: "Select App", - }, - "< Cancel": () => { - log("cancel"); - showMainMenu(); - }, - }; - - log(storedPatterns); - var patterns = Object.keys(storedPatterns); - log(patterns); - - patterns.forEach((pattern) => { - if (pattern) { - if (storedPatterns[pattern]) { - var app = storedPatterns[pattern].app; - if (!!app && !!app.name) { - var appName = app.name; - var i = 0; - while (appName in selectPatternMenu[app.name]) { - appName = app.name + i; - i++; - } - selectPatternMenu[appName] = () => { - log("pattern via app selected"); - log(pattern); - log(app); - resolve(pattern); - }; - } + E.showScroller({ + h: 64, + c: c, + draw: (i, r) => { + log("draw"); + log({ i: i, r: r }); + if (i <= 0) { + drawBackButton(r); + } else if (i <= storedPatternsArray.length) { + drawAppWithPattern(i - 1, r, storedPatternsArray); } - } + }, + select: (i) => { + log("selected: " + i); + var pattern = "back"; + var appName = ""; + if (i > 0) { + var storedPattern = storedPatternsArray[i - 1]; + pattern = storedPattern.pattern.join(""); + appName = storedPattern.app.name; + } + resolve({ pattern: pattern, appName: appName }); + }, }); - - E.showMenu(selectPatternMenu); }); }; -showMainMenu(); +////// +// storage related functions: +// - stored patterns +// - stored settings +////// + +var getStoredPatternsMap = () => { + log("loading stored patterns map"); + var storedPatternsMap = storage.readJSON("ptlaunch.patterns.json", 1) || {}; + delete storedPatternsMap.settings; + log(storedPatternsMap); + return storedPatternsMap; +}; + +var getStoredPatternsArray = () => { + var storedPatternsMap = getStoredPatternsMap(); + log("converting stored patterns map to array"); + var patterns = Object.keys(storedPatternsMap); + var storedPatternsArray = []; + for (var i = 0; i < patterns.length; i++) { + var pattern = "" + patterns[i]; + storedPatternsArray.push({ + pattern: pattern + .split("") + .map((circleIndex) => parseInt(circleIndex, 10)), + app: storedPatternsMap[pattern].app, + }); + } + log(storedPatternsArray); + return storedPatternsArray; +}; ////// -// lib functions +// circle related variables and functions: +// - the circle array itself +// - the radius and the squared radius of the circles +// - circle draw function +////// + +var CIRCLE_RADIUS = 25; +var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; + +var CIRCLES = [ + { x: 25, y: 25, i: 0 }, + { x: 87, y: 25, i: 1 }, + { x: 150, y: 25, i: 2 }, + { x: 25, y: 87, i: 3 }, + { x: 87, y: 87, i: 4 }, + { x: 150, y: 87, i: 5 }, + { x: 25, y: 150, i: 6 }, + { x: 87, y: 150, i: 7 }, + { x: 150, y: 150, i: 8 }, +]; + +var drawCircle = (circle, drawBuffer, scale) => { + if (!drawBuffer) { + drawBuffer = g; + } + if (!scale) { + scale = 1; + } + + var x = circle.x * scale; + var y = circle.y * scale; + var r = CIRCLE_RADIUS * scale; + + log("drawing circle"); + log({ x: x, y: y, r: r }); + + drawBuffer.fillCircle(x, y, r); +}; + +var cachedCirclesDrawings = {}; +var drawCirclesWithPattern = (pattern, scale, offset) => { + if (!pattern || pattern.length === 0) { + pattern = []; + } + if (!scale) { + scale = 1; + } + if (!offset) { + offset = { x: 0, y: 0 }; + } + + log("drawing circles with pattern, scale and offset"); + log(pattern); + log(scale); + log(offset); + + // cache drawn patterns. especially useful for the manage pattern menu + var image = cachedCirclesDrawings[pattern.join("")]; + if (!image) { + var drawBuffer = Graphics.createArrayBuffer( + g.getWidth() * scale, + g.getHeight() * scale, + 1, + { msb: true } + ); + + drawBuffer.setColor(1); + CIRCLES.forEach((circle) => drawCircle(circle, drawBuffer, scale)); + + drawBuffer.setColor(0); + drawBuffer.setFontAlign(0, 0); + drawBuffer.setFont("6x8", 4 * scale); + pattern.forEach((circleIndex, patternIndex) => { + var circle = CIRCLES[circleIndex]; + drawBuffer.drawString( + patternIndex + 1, + circle.x * scale, + circle.y * scale + ); + }); + + image = { + width: drawBuffer.getWidth(), + height: drawBuffer.getHeight(), + bpp: 1, + buffer: drawBuffer.buffer, + }; + cachedCirclesDrawings[pattern.join("")] = image; + } + + g.drawImage(image, offset.x, offset.y); +}; + +var cloneCirclesArray = () => { + var circlesClone = Array(CIRCLES.length); + + for (var i = 0; i < CIRCLES.length; i++) { + circlesClone[i] = CIRCLES[i]; + } + + return circlesClone; +}; + +////// +// misc lib functions ////// var debounceTimeoutId; @@ -417,13 +581,3 @@ var debounce = (delay) => { }, delay || 500); }); }; - -var cloneCirclesArray = () => { - var circlesClone = Array(CIRCLES.length); - - for (var i = 0; i < CIRCLES.length; i++) { - circlesClone[i] = CIRCLES[i]; - } - - return circlesClone; -}; diff --git a/apps/ptlaunch/main_menu.png b/apps/ptlaunch/main_menu.png deleted file mode 100644 index a4ecebb0f4ba586eba902bf1699e9b5f9dbe683a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2840 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

BuR#Ni`xQKMeD4CN`aq@@yCr#EN| zXM3p(!XEXSM&}j~3WxF>c%s7`*=*O(m;jXCtaS$LbHvY}D=ubMpj0W9S4|C__ZD^X?b&Dl zf32~jlfV7s75is4?qTxkaVnq-&x1~V1Si930Q+8;h0DGQR<*1-FuGMQ;Ypo?KLmIi zP@xJ|CY%CfEqCvE$=qggrCPg7>gc3GJ)0(%4t)|eqVEh?M)pfUvjhb?zmfY X?!HdU=uwls-yE>EurV(+#oqrf=&qfN literal 0 HcmV?d00001 diff --git a/apps/ptlaunch/main_menu_manage.png b/apps/ptlaunch/main_menu_manage.png new file mode 100644 index 0000000000000000000000000000000000000000..a6aee1427079693d3389120a2f291c6b34c92dfe GIT binary patch literal 2955 zcmd^>`#;l<7sub*8glPrBy3XYlTv6dxh64PWJcS0{ii*82_sN-n3JPh5z@%;ZVpSvJZkR&&2P`b-8N z!~_f=k0$qip6;@C>HRE9H_gasUR+K1DLHP$Edr~7YKx-Jte>Uo1IH2R1;&WBwJZp& zNmw#I$|fOg*l0fusg^(H6K|9ol{OzMoX)XgN$!rJZ>N-r%9ivUKgC%A zi+FS2QcIBNSm+%eN$|qO#(cTpVb!AgDeVQH#%vkso00Q{j)K7p81zC)~u>fwa!OE`^gIbpa7yS z&3=tNF=9{2G}S_eF5qkC&Hyr<57|7&#HWv2cYc)=88#jWBL<}G4$E%NWqZowQ%+PB z%<$k@KD=jDoJm0}SQPhFab6UL*mW7C9b-P;X&av5EswWwt}apJR=QpV{I-=l;y_u} zI4>sS@2t`+?U%x#Fh&*NVvWY;cgc@ocg5aN@7Ng?>OPA6^fqrh{2!*%(I7K3@JeC0 zR$C`kzHzUCggB+6O$+`0u%=0DUOsMtUJWzf_v(d`Oo;pD7Eam zf8d)#M&mi>b*a_RH;;Lr}1ZXEUtO&+` z1_sBuct6xAp#U#moR{8HRFG;0c)6E>!C8zm)I$e%Q@n4uSW6TYu)YVO>{k>3Bhegl zKD3+iKbV1S+KKg(7h!7%?Zw10-iRrQnRjxXQz%f!YAG%c6nZn-$Kyj(b=H%h)qo$x zv6N8b+7~POC$msEfAQ&duBIF;y@LGkMzbD*^oMdFGznw}0rwZmlG833O|KhZ*5A$< zJFc#tc`cc}fL$9Tggn56OC?HHe{lOMg$hHqQPnruR)Wy9jjg#rYO7f+)_6TCUBQ|eF z+S^0s&AQ=g9u5)AaZb{qT@76t%2fP!Is>gX4{aDy{5wg%S7TX{r*7UpRAIC(J71R2 zU_lOl!%%C$eSgg?Jz#Q~TMyP>HBK30yO>;(QDv#^tmO1W9a@zVbrwBwI#(V{P6vU8 zYV1Pv13)0X!GEMn+oe)DR}&AwHTGCsBKR1;LDH%rkibs>ZYXq*Z@hRzP+=j%Y)q8O2>MeS`XduT zU)(`gd>;Ga{0^c)vqmIKH9X0Dv4MqLDo8wz>Y`~p0im8f8aQ0)ogACi1}3^3IUGPI zp<+pP=CzrH1BLx^Qsz-a<%;^g34lxdcHM`v;JQU6kYH}xBYL_>#qFl^cma%dY&$gWw`C8 z+c}WGlgR)3<4T(E4<_IjU2O8RWuw=-?ybiP{TN6DxwmJDgngb-VY0;zrXOLLx`o*( zgNQ(15U94y{*0>8{K}7$8V7s_UI=hoST!ko*;qn^i{;7u2g4at<#7yz#uy|Z8alQfB);}oT0Ok`&@nC-t_Ji!>`@tdu?aE@;Vfs^SM+b42vMg>eyjTiNk_GgRA$nw2i1N^l>+HYSbCH4AVN*Tg!{$hImDIwt)CCTh)$rcCglW zQJgka=B9n7Z${wOgLNy1(Yqr<3b|?Fck`%nGhYUhnyw4aAG%j=9BHibq2sdGM1nlt zBk0s~Nwp|EELqh&{XYky1*{m;&x$jFY}d?1&Y!7y9KFh(i)4ql@+K{nyhK&(1^yVp z-+-}0t;=qp#CY8Yz`GB}cAE3_E^n;RcL?5~W3$@C4a`l?i0K3*JdS^DGs(DJFZih( zD9sID%?w#JO{PN60QH*r5N&uSuNBt;-L$|mDLecgn=8xQnJv2Uv zlC2~+?o?o?Ts@JK_}NNlXP!8N$|`4$IlX)|I$_{xZCR`o?U`?1jJC5=nZFBS493Xu zL+*Rw?4ct`PXmC$rw;oC$yU(Xz~bJLdW~58xhKMr-dmG?pGr4X0`maX$f#-X;LRc) zxqKzD+STMWen?l?*jRC{t1hzgc>P_Q^@Y%VMoMsv=EkQ9W%jqhUm^?380}8Yjb>)u z8?gF9Fie1WQQA=&g|H4w+tkdG%K=p;-zQ~b%U`FP+C&${4eu(mXaoAGn+LPN zarinB@zQ>_=7)Fi&AJtR{|k(uf`pFc&5Yhdqp|>nZUvYXB)0gF?{NRsPpwFzNzG_T z_&XZjY*=yp5P~**|HOJ5@uK-vyM4>A6&yakQgOch8ZrkJ%=S4^rs%0h2&yM04FPbz z&l5VXV}%FjztIl}o>l!oU-f{bF<*7zb_*`a#RVJt_0X?PXYhcl{9x+m-)bQ0HDjj+ zQM}wFGMI}(Ms*Jm>Owr{jNgC7S_e(bHMy_8A0S*p6Zv;^2WJlStcXln{jkH^(*mwr z45Nx|J&HX$`&tr>>u>kfP;#Lv0U5seuvuLEbGssoYtNIjeLFAidenVqhv0XUk#4S8 zq!yUJfEkSC{AqAlz*^!gA!HavbBpC+LFpBd9}N&sCEjU)UQ^Ir)H0wf#_K=34$^xs ztaVY4)()k<@&{74R_p*DjL_Kf&G(ZFK>^A5P!;u7T4o?#^r{Z1R5r?G}>H literal 0 HcmV?d00001 diff --git a/apps/ptlaunch/manage_patterns.png b/apps/ptlaunch/manage_patterns.png new file mode 100644 index 0000000000000000000000000000000000000000..82b10ad43a60ea3b38c39c2bb1f4491235f0dabc GIT binary patch literal 2670 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 Date: Fri, 10 Dec 2021 17:53:58 +0000 Subject: [PATCH 08/38] ptlaunch: try to improve the code slightly --- apps/ptlaunch/app.js | 77 ++++++++++++++++++++++++++++--------------- apps/ptlaunch/boot.js | 76 ++++++++++++++++++------------------------ 2 files changed, 83 insertions(+), 70 deletions(-) diff --git a/apps/ptlaunch/app.js b/apps/ptlaunch/app.js index 1d3a07674..b5a3bf610 100644 --- a/apps/ptlaunch/app.js +++ b/apps/ptlaunch/app.js @@ -1,9 +1,4 @@ var DEBUG = false; -var log = (message) => { - if (DEBUG) { - console.log(JSON.stringify(message)); - } -}; var storage = require("Storage"); @@ -21,7 +16,7 @@ var showMainMenu = () => { }, "Add Pattern": () => { log("creating pattern"); - createPattern().then((pattern) => { + recognizeAndDrawPattern().then((pattern) => { log("got pattern"); log(pattern); log(pattern.length); @@ -119,10 +114,8 @@ var showMainMenu = () => { E.showMenu(mainmenu); }; -showMainMenu(); - var positions = []; -var createPattern = () => { +var recognizeAndDrawPattern = () => { return new Promise((resolve) => { E.showMenu(); g.clear(); @@ -283,18 +276,7 @@ var createPattern = () => { log("redrawing"); g.clear(); - g.setColor(0, 0, 0); - CIRCLES.forEach((circle) => drawCircle(circle)); - - g.setColor(1, 1, 1); - g.setFontAlign(0, 0); - g.setFont("6x8", 4); - pattern.forEach((circleIndex, patternIndex) => { - var circle = CIRCLES[circleIndex]; - g.drawString(patternIndex + 1, circle.x, circle.y); - }); - var t2 = Date.now(); - log(t2 - t0); + drawCirclesWithPattern(pattern); }); }; @@ -381,13 +363,23 @@ var drawAppWithPattern = (i, r, storedPatterns) => { g.drawLine(r.x, r.y, 176, r.y); - drawCirclesWithPattern(pattern, 0.33, { x: 1, y: 3 + r.y }); + drawCirclesWithPattern(pattern, { + enableCaching: true, + scale: 0.33, + offset: { x: 1, y: 3 + r.y }, + }); g.setColor(0, 0, 0); - var appName = g.wrapString(app.name, g.getWidth() - 64).join("\n"); + if (!storedPattern.wrappedAppName) { + storedPattern.wrappedAppName = g + .wrapString(app.name, g.getWidth() - 64) + .join("\n"); + } + log(g.getWidth()); + log(storedPattern.wrappedAppName); g.setFont(scrollerFont) .setFontAlign(-1, 0) - .drawString(appName, 64, r.y + 32); + .drawString(storedPattern.wrappedAppName, 64, r.y + 32); }; var showScrollerContainingAppsWithPatterns = () => { @@ -422,6 +414,7 @@ var showScrollerContainingAppsWithPatterns = () => { pattern = storedPattern.pattern.join(""); appName = storedPattern.app.name; } + clearCircleDrawingCache(); resolve({ pattern: pattern, appName: appName }); }, }); @@ -501,10 +494,24 @@ var drawCircle = (circle, drawBuffer, scale) => { }; var cachedCirclesDrawings = {}; -var drawCirclesWithPattern = (pattern, scale, offset) => { + +var clearCircleDrawingCache = () => { + cachedCirclesDrawings = {}; +}; + +var drawCirclesWithPattern = (pattern, options) => { if (!pattern || pattern.length === 0) { pattern = []; } + if (!options) { + options = {}; + } + var enableCaching = options.enableCaching; + var scale = options.scale; + var offset = options.offset; + if (!enableCaching) { + enableCaching = false; + } if (!scale) { scale = 1; } @@ -520,6 +527,7 @@ var drawCirclesWithPattern = (pattern, scale, offset) => { // cache drawn patterns. especially useful for the manage pattern menu var image = cachedCirclesDrawings[pattern.join("")]; if (!image) { + log("circle image not cached"); var drawBuffer = Graphics.createArrayBuffer( g.getWidth() * scale, g.getHeight() * scale, @@ -548,7 +556,12 @@ var drawCirclesWithPattern = (pattern, scale, offset) => { bpp: 1, buffer: drawBuffer.buffer, }; - cachedCirclesDrawings[pattern.join("")] = image; + + if (enableCaching) { + cachedCirclesDrawings[pattern.join("")] = image; + } + } else { + log("using cached circle image"); } g.drawImage(image, offset.x, offset.y); @@ -568,6 +581,12 @@ var cloneCirclesArray = () => { // misc lib functions ////// +var log = (message) => { + if (DEBUG) { + console.log(JSON.stringify(message)); + } +}; + var debounceTimeoutId; var debounce = (delay) => { if (debounceTimeoutId) { @@ -581,3 +600,9 @@ var debounce = (delay) => { }, delay || 500); }); }; + +////// +// run main function +////// + +showMainMenu(); diff --git a/apps/ptlaunch/boot.js b/apps/ptlaunch/boot.js index 14d390b13..a23607768 100644 --- a/apps/ptlaunch/boot.js +++ b/apps/ptlaunch/boot.js @@ -5,21 +5,6 @@ var log = (message) => { } }; -var CIRCLE_RADIUS = 25; -var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; - -var CIRCLES = [ - { x: 25, y: 25, i: 0 }, - { x: 87, y: 25, i: 1 }, - { x: 150, y: 25, i: 2 }, - { x: 25, y: 87, i: 3 }, - { x: 87, y: 87, i: 4 }, - { x: 150, y: 87, i: 5 }, - { x: 25, y: 150, i: 6 }, - { x: 87, y: 150, i: 7 }, - { x: 150, y: 150, i: 8 }, -]; - var storedPatterns; var positions = []; var dragHandler = (position) => { @@ -28,7 +13,20 @@ var dragHandler = (position) => { debounce().then(() => { log(positions.length); - var circlesClone = cloneCirclesArray(); + var CIRCLE_RADIUS = 25; + var CIRCLE_RADIUS_2 = CIRCLE_RADIUS * CIRCLE_RADIUS; + + var circles = [ + { x: 25, y: 25, i: 0 }, + { x: 87, y: 25, i: 1 }, + { x: 150, y: 25, i: 2 }, + { x: 25, y: 87, i: 3 }, + { x: 87, y: 87, i: 4 }, + { x: 150, y: 87, i: 5 }, + { x: 25, y: 150, i: 6 }, + { x: 87, y: 150, i: 7 }, + { x: 150, y: 150, i: 8 }, + ]; var pattern = []; var step = Math.floor(positions.length / 100) + 1; @@ -38,92 +36,92 @@ var dragHandler = (position) => { for (var i = 0; i < positions.length; i += step) { p = positions[i]; - circle = circlesClone[0]; + circle = circles[0]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(0, 1); + circles.splice(0, 1); } } - circle = circlesClone[1]; + circle = circles[1]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(1, 1); + circles.splice(1, 1); } } - circle = circlesClone[2]; + circle = circles[2]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(2, 1); + circles.splice(2, 1); } } - circle = circlesClone[3]; + circle = circles[3]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(3, 1); + circles.splice(3, 1); } } - circle = circlesClone[4]; + circle = circles[4]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(4, 1); + circles.splice(4, 1); } } - circle = circlesClone[5]; + circle = circles[5]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(5, 1); + circles.splice(5, 1); } } - circle = circlesClone[6]; + circle = circles[6]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(6, 1); + circles.splice(6, 1); } } - circle = circlesClone[7]; + circle = circles[7]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(7, 1); + circles.splice(7, 1); } } - circle = circlesClone[8]; + circle = circles[8]; if (circle) { a = p.x - circle.x; b = p.y - circle.y; if (CIRCLE_RADIUS_2 - (a * a + b * b) >= 0) { pattern.push(circle.i); - circlesClone.splice(8, 1); + circles.splice(8, 1); } } } @@ -163,16 +161,6 @@ var debounce = (delay) => { }); }; -var cloneCirclesArray = () => { - var circlesClone = Array(CIRCLES.length); - - for (var i = 0; i < CIRCLES.length; i++) { - circlesClone[i] = CIRCLES[i]; - } - - return circlesClone; -}; - (function () { var sui = Bangle.setUI; Bangle.setUI = function (mode, cb) { From 5ff04c50ac2660338e1c73640cc575a49d527802 Mon Sep 17 00:00:00 2001 From: crazysaem Date: Fri, 10 Dec 2021 21:53:17 +0000 Subject: [PATCH 09/38] ptlaunch: add screenshot --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 65ef9bcea..2206af8cb 100644 --- a/apps.json +++ b/apps.json @@ -4832,6 +4832,7 @@ "version": "0.10", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", + "screenshots": [{"url":"manage_patterns.png"}], "tags": "tools", "supports": ["BANGLEJS2"], "readme": "README.md", From 8f0d9f310cdc75402fc0de6b9aacc232cdccad82 Mon Sep 17 00:00:00 2001 From: crazysaem Date: Fri, 10 Dec 2021 21:57:02 +0000 Subject: [PATCH 10/38] ptlaunch: add all screenshots --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 2206af8cb..24c1843a5 100644 --- a/apps.json +++ b/apps.json @@ -4832,7 +4832,7 @@ "version": "0.10", "description": "Directly launch apps from the clock screen with custom patterns.", "icon": "app.png", - "screenshots": [{"url":"manage_patterns.png"}], + "screenshots": [{"url":"main_menu_add.png"}, {"url":"add_pattern.png"}, {"url":"select_app.png"}, {"url":"main_menu_manage.png"}, {"url":"manage_patterns.png"}], "tags": "tools", "supports": ["BANGLEJS2"], "readme": "README.md", From 13e68ec8b415ebe39c5cd65484bf6eaadc53601d Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 12:55:38 +0900 Subject: [PATCH 11/38] Awair Monitor: icon --- apps/awairmonitor/app.png | Bin 0 -> 3096 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/awairmonitor/app.png diff --git a/apps/awairmonitor/app.png b/apps/awairmonitor/app.png new file mode 100644 index 0000000000000000000000000000000000000000..26a5d0cff8c5401381ac47e33622a02930bb0d77 GIT binary patch literal 3096 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 literal 0 HcmV?d00001 From 7152cd6d1b5382cd3a806d077ede8842bddc0130 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 13:26:38 +0900 Subject: [PATCH 12/38] Awair Monitor: awair_to_bangle.html --- apps/awairmonitor/awair_to_bangle.html | 195 +++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 apps/awairmonitor/awair_to_bangle.html diff --git a/apps/awairmonitor/awair_to_bangle.html b/apps/awairmonitor/awair_to_bangle.html new file mode 100644 index 000000000..2926cca9e --- /dev/null +++ b/apps/awairmonitor/awair_to_bangle.html @@ -0,0 +1,195 @@ + + + + + + + + + + +

+How to use +

+Step 1: Enable the Local API on your Awair: https://support.getawair.com/hc/en-us/articles/360049221014-Awair-Local-API-Feature +

+Step 2: Modify this HTML file to input the IP address of your Awair on top (const awair_ip_1 = "192.168.xx.xx") +

+Step 3: Launch the Awair Monitor app on your BangleJS +

+Step 4: Click "Connect BangleJS" +

+Step 5: Optionally, open the web inspector's console (Right click > Inspector > Console) to read the bluetooth logs +

+ +
+ + +
+ +

+ +
+
+
+
+
+ + From ebf62e8328880e100764edecf1a1adeef73a47a4 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 13:28:42 +0900 Subject: [PATCH 13/38] Create ChangeLog --- apps/awairmonitor/ChangeLog | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/awairmonitor/ChangeLog diff --git a/apps/awairmonitor/ChangeLog b/apps/awairmonitor/ChangeLog new file mode 100644 index 000000000..0cc9a42b0 --- /dev/null +++ b/apps/awairmonitor/ChangeLog @@ -0,0 +1 @@ +0.01: Beta version for Bangle 2 paired with Chrome (2021/12/11) From 2c77ea939af700526c16836ffd781bebb8f7c1bb Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 13:51:19 +0900 Subject: [PATCH 14/38] Create README.md --- apps/awairmonitor/README.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 apps/awairmonitor/README.md diff --git a/apps/awairmonitor/README.md b/apps/awairmonitor/README.md new file mode 100644 index 000000000..09434bcde --- /dev/null +++ b/apps/awairmonitor/README.md @@ -0,0 +1,20 @@ +# Awair Monitor + +Display the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device. + +* What you need: + * A BangleJS 2 + * An Awair device [with local API enabled](https://support.getawair.com/hc/en-us/articles/360049221014-Awair-Local-API-Feature) + * The web app [awair_to_bangle.html](awairmonitor/awair_to_bangle.html) that will retrive the data from your Awair device and sent it to your BangleJS 2 through Chrome's Bluetooth LE connection +* How to get started + * Open awair_to_bangle.html with a text/code editor and input the IP address of your Awair on top (const awair_ip_1 = "192.168.xx.xx") + * Launch the Awair Monitor app on your BangleJS + * Open awair_to_bangle.html on Chrome and click "Connect BangleJS" - it connects to your watch the same way as the Bangle app store + * Once connected to the watch with the app running, the watch app is updated once per second + +![](screenshot.png) + +## Creator +[@alainsaas](https://github.com/alainsaas) + +Contributions are welcome, send me your Pull Requests! From 0bfbf34e20c18f7f2206a32296d6e3e3f31103d5 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 13:52:14 +0900 Subject: [PATCH 15/38] Update README.md --- apps/awairmonitor/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/awairmonitor/README.md b/apps/awairmonitor/README.md index 09434bcde..98f5bee75 100644 --- a/apps/awairmonitor/README.md +++ b/apps/awairmonitor/README.md @@ -1,6 +1,6 @@ # Awair Monitor -Display the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device. +Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device. * What you need: * A BangleJS 2 From b99024f9caa9b4fa44a6d9a353734794e6bc075c Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Thu, 9 Dec 2021 21:14:31 +0100 Subject: [PATCH 16/38] Fix gbridge inflating steps --- apps/gbridge/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gbridge/widget.js b/apps/gbridge/widget.js index dc10587e1..7cb7147ec 100644 --- a/apps/gbridge/widget.js +++ b/apps/gbridge/widget.js @@ -262,7 +262,7 @@ // Send a summary of activity to Gadgetbridge function sendActivity(hrm) { var steps = currentSteps - lastSentSteps; - lastSentSteps = 0; + lastSentSteps = currentSteps; gbSend({ t: "act", stp: steps, hrm:hrm }); } From 8ef3a6a1a6327caeba441a35c3e09b526c6c1d17 Mon Sep 17 00:00:00 2001 From: Adam Schmalhofer Date: Thu, 9 Dec 2021 21:22:44 +0100 Subject: [PATCH 17/38] Updated gbride changelog --- apps/gbridge/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/gbridge/ChangeLog b/apps/gbridge/ChangeLog index 5a08af49f..67d421f33 100644 --- a/apps/gbridge/ChangeLog +++ b/apps/gbridge/ChangeLog @@ -25,3 +25,4 @@ 0.23: Allow notification dismiss to remove from phone too 0.24: tag HRM power requests to allow this to work alongside other widgets/apps (fix #799) 0.25: workaround call notification + Fix inflated step number From 653156c0e684a6e6917d1b97d5ea7a13e9ae83b7 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 18:53:59 +0900 Subject: [PATCH 18/38] Create app-icon.js --- apps/awairmonitor/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/awairmonitor/app-icon.js diff --git a/apps/awairmonitor/app-icon.js b/apps/awairmonitor/app-icon.js new file mode 100644 index 000000000..9d4dcf4a3 --- /dev/null +++ b/apps/awairmonitor/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgP/AD38g4FD8EAAoeAgE/AoUD/EfAgP+AYMPDgQPBw4FB/F///DAoPwAQPjAQPBAQPxDgJVCAoP4gYaCCwIcBAoM/8P8h0HjEP8f4h0Gp0H4/44lj5+H4/54lzj/jx/5/lyDgIFDh/xAoQRBAoXsuY8Bx4jCAoeEkYFB447CAoRxBOAPxM4RmC8IFD4ZZD/8H/DHDh/+AoaSBUAIABCoYATVwS2Ct4FE84REXQQLCk4RJAo0XGxY=")) From d55ef2cd018eb901459e8cf23cc238e96e8b70aa Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 19:01:34 +0900 Subject: [PATCH 19/38] Update apps.json --- apps.json | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd2e14e60..1c43ffdad 100644 --- a/apps.json +++ b/apps.json @@ -4857,5 +4857,19 @@ {"name":"clicompleteclk.app.js","url":"app.js"}, {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true} ] -} +}, + { + "id":"awairmonitor", + "name":"Awair Monitor", + "icon": "app.png", + "version":"0.01", + "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", + "tags": "tool,health", + "readme":"README.md", + "supports":["BANGLEJS2"], + "storage": [ + {"name":"awairmonitor.app.js","url":"app.js"}, + {"name":"awairmonitor.img","url":"app-icon.js","evaluate":true} + ] + } ] From c7177a6aec18d8737d88fc4c353796be7ac85ba5 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 19:09:14 +0900 Subject: [PATCH 20/38] Update README.md --- apps/awairmonitor/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/awairmonitor/README.md b/apps/awairmonitor/README.md index 98f5bee75..8d6e25633 100644 --- a/apps/awairmonitor/README.md +++ b/apps/awairmonitor/README.md @@ -5,7 +5,7 @@ Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awai * What you need: * A BangleJS 2 * An Awair device [with local API enabled](https://support.getawair.com/hc/en-us/articles/360049221014-Awair-Local-API-Feature) - * The web app [awair_to_bangle.html](awairmonitor/awair_to_bangle.html) that will retrive the data from your Awair device and sent it to your BangleJS 2 through Chrome's Bluetooth LE connection + * The web app [awair_to_bangle.html](awair_to_bangle.html) that will retrive the data from your Awair device and sent it to your BangleJS 2 through Chrome's Bluetooth LE connection * How to get started * Open awair_to_bangle.html with a text/code editor and input the IP address of your Awair on top (const awair_ip_1 = "192.168.xx.xx") * Launch the Awair Monitor app on your BangleJS From 93f28915481cb167e58c462c69133f90d2eadd92 Mon Sep 17 00:00:00 2001 From: Alain Saas Date: Sat, 11 Dec 2021 19:10:02 +0900 Subject: [PATCH 21/38] Update apps.json --- apps.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps.json b/apps.json index 1c43ffdad..e70e95454 100644 --- a/apps.json +++ b/apps.json @@ -4862,6 +4862,7 @@ "id":"awairmonitor", "name":"Awair Monitor", "icon": "app.png", + "allow_emulator": true, "version":"0.01", "description": "Displays the level of CO2, VOC, PM 2.5, Humidity and Temperature, from your Awair device.", "tags": "tool,health", From 6c61c17d2b614c56cc20692484a498fc73b24a30 Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 11:14:45 +0100 Subject: [PATCH 22/38] Copy offset and font size changes from wclock to handle Bangle.js 2 --- apps/impwclock/clock-impword.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index 5492eac15..c9a7bfae3 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -34,14 +34,16 @@ const timeOfDay = { }; -// offsets and increments -const xs = 35; -const ys = 31; -const dy = 22; -const dx = 25; +var big = g.getWidth()>200; +// offsets and incerments +const xs = big ? 35 : 20; +const ys = big ? 31 : 28; +const dx = big ? 25 : 20; +const dy = big ? 22 : 16; + // font size and color -const fontSize = 3; // "6x8" +const fontSize = big ? 3 : 2; // "6x8" const passivColor = 0x3186 /*grey*/ ; const activeColorNight = 0xF800 /*red*/ ; const activeColorDay = 0xFFFF /* white */; From f4dbe714a43f06cf71e9ac71dd70ecda0e211b12 Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 11:24:46 +0100 Subject: [PATCH 23/38] Impwclock support for Bangle.js2 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd2e14e60..f88715659 100644 --- a/apps.json +++ b/apps.json @@ -538,7 +538,7 @@ "icon": "clock-impword.png", "type": "clock", "tags": "clock", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "screenshots": [{"url":"bangle1-impercise-word-clock-screenshot.png"}], "allow_emulator": true, "storage": [ From 3df8f688af48d9d137ccfb34fe949146d18c5873 Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 11:30:36 +0100 Subject: [PATCH 24/38] Changes for BangleJs2 --- apps/impwclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/impwclock/ChangeLog b/apps/impwclock/ChangeLog index 0592d4d04..7bc119426 100644 --- a/apps/impwclock/ChangeLog +++ b/apps/impwclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Stopped watchface from flashing every interval 0.03: Move to Bangle.setUI to launcher support +0.04: Tweaks for compatibility with BangleJS2 From 203a78ce3da754143887e48ac50e3187468b0545 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 12:19:14 +0100 Subject: [PATCH 25/38] Update app.js * Support for "6x8:2" font * Update steps and heart rate when (un)locking the screen --- apps/clicompleteclk/app.js | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index 7fbdabcc1..9ab7688ac 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -1,13 +1,14 @@ const storage = require('Storage'); const locale = require("locale"); -const font = "12x20"; -const fontsize = 1; +const font12 = g.getFonts().includes("12x20"); +const font = font12 ? "12x20" : "6x8:2"; +const fontsize = font12 ? 1: 2; const fontheight = 19; const marginTop = 10; const marginLeftTopic = 3; // margin of topics -const marginLeftData = 68; // margin of data values +const marginLeftData = font12 ? 62 : 75; // margin of data values const topicColor = g.theme.dark ? "#fff" : "#000"; const textColor = g.theme.dark ? "#0f0" : "#080"; @@ -17,6 +18,7 @@ let hrtValueIsOld = false; let localTempValue; let weatherTempString; let lastHeartRateRowIndex; +let lastStepsRowIndex; // timeout used to update every minute var drawTimeout; @@ -60,12 +62,10 @@ function drawInfo(now) { writeLine(locale.date(now,1),i); i++; - /* - writeLineTopic("BAT", i); + writeLineTopic("BATT", i); const b = E.getBattery(); - writeLine(b + "%", i); // TODO make bars + writeLine(b + "%", i); i++; - */ // weather const weatherJson = getWeather(); @@ -83,15 +83,20 @@ function drawInfo(now) { i++; } - // steps + drawSteps(i); + + drawHeartRate(i); +} + +function drawSteps(i) { + if (i == undefined) + i = lastStepsRowIndex; const steps = getSteps(); if (steps != undefined) { writeLineTopic("STEP", i); writeLine(steps, i); - i++; } - - drawHeartRate(i); + lastStepsRowIndex = i; } function drawHeartRate(i) { @@ -164,6 +169,8 @@ Bangle.on('lock', function(isLocked) { hrtValueIsOld = true; Bangle.setHRMPower(0,"clicompleteclk"); } + // Update steps and heart rate + drawSteps(); drawHeartRate(); }); From 12ab36c30faaee0e0d0e709c427fb93afe172ad4 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 12:30:52 +0100 Subject: [PATCH 26/38] Update app.js Adjust margins --- apps/clicompleteclk/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index 9ab7688ac..ebb17c865 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -2,13 +2,13 @@ const storage = require('Storage'); const locale = require("locale"); const font12 = g.getFonts().includes("12x20"); -const font = font12 ? "12x20" : "6x8:2"; +const font = font12 ? "12x20" : "6x8"; const fontsize = font12 ? 1: 2; const fontheight = 19; -const marginTop = 10; +const marginTop = 5; const marginLeftTopic = 3; // margin of topics -const marginLeftData = font12 ? 62 : 75; // margin of data values +const marginLeftData = font12 ? 64 : 75; // margin of data values const topicColor = g.theme.dark ? "#fff" : "#000"; const textColor = g.theme.dark ? "#0f0" : "#080"; From 4862219a2fe9a600632d2de942423af26fa2542b Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 12:53:55 +0100 Subject: [PATCH 27/38] Toggle digital time when BangleJS2 screen touched. --- apps/impwclock/clock-impword.js | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index c9a7bfae3..111728891 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -2,7 +2,7 @@ A remix of word clock by Gordon Williams https://github.com/gfwilliams - Changes the representation of time to be more general -- Shows accurate digital time when button 1 is pressed +- Shows accurate digital time when button 1 is pressed or */ /* jshint esversion: 6 */ @@ -35,7 +35,7 @@ const timeOfDay = { var big = g.getWidth()>200; -// offsets and incerments +// offsets and increments const xs = big ? 35 : 20; const ys = big ? 31 : 28; const dx = big ? 25 : 20; @@ -140,15 +140,14 @@ function drawWordClock() { hidxPrev = hidx; } - // Display digital time while button 1 is pressed - g.clearRect(0, 215, 240, 240); + // Display digital time when button is pressed or screen touched + g.clearRect(0, big ? 215 : 160, big ? 240 : 176, big ? 240 : 176); if (showDigitalTime){ g.setColor(activeColor); - g.drawString(time, 120, 215); + g.drawString(time, big ? 120 : 90, big ? 215 : 160); } } - Bangle.on('lcdPower', function(on) { if (on) drawWordClock(); }); @@ -166,10 +165,13 @@ if (global.BTN3) setWatch(function() { }, BTN1, {repeat:true,edge:"both"}); // If LCD pressed (on Bangle.js 2) draw digital time -Bangle.on('drag',e=>{ +Bangle.on('touch',e=>{ var pressed = e.b!=0; - if (pressed!=showDigitalTime) { - showDigitalTime = pressed; + if (showDigitalTime){ + showDigitalTime = false; + drawWordClock(); + } else { + showDigitalTime = true; drawWordClock(); } }); From 2f7e81fea87f18af102a1844d8b805a98c18bb86 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 12:55:16 +0100 Subject: [PATCH 28/38] Create settings.js Initial settings file --- apps/clicompleteclk/settings.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 apps/clicompleteclk/settings.js diff --git a/apps/clicompleteclk/settings.js b/apps/clicompleteclk/settings.js new file mode 100644 index 000000000..ab92dbdd6 --- /dev/null +++ b/apps/clicompleteclk/settings.js @@ -0,0 +1,20 @@ +(function(back) { + const storage = require('Storage'); + let settings = storage.readJSON('clicompleteclk.json', 1) || {}; + function save(key, value) { + settings[key] = value; + storage.write('clicompleteclk.json', settings); + } + E.showMenu({ + '': { 'title': 'CLI complete clk' }, + 'Show battery': { + value: "battery" in settings ? settings.battery : false, + format: () => (settings.battery ? 'Yes' : 'No'), + onchange: () => { + settings.battery = !settings.battery + save('battery', settings.battery); + }, + }, + '< Back': back, + }); +}); From dc84156055b81be1c403e9cea6e7f49d8efaa1ad Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 13:03:21 +0100 Subject: [PATCH 29/38] Change to handling of digital time display Remove code for BangleJS physical button. Replace with code to toggle display of accurate time based on screen touch that works for both BangleJS and BangleJS2 Stop displaying accurate digital time when new imprecise era begins. --- apps/impwclock/clock-impword.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/apps/impwclock/clock-impword.js b/apps/impwclock/clock-impword.js index 111728891..8bb5da6ba 100644 --- a/apps/impwclock/clock-impword.js +++ b/apps/impwclock/clock-impword.js @@ -2,7 +2,7 @@ A remix of word clock by Gordon Williams https://github.com/gfwilliams - Changes the representation of time to be more general -- Shows accurate digital time when button 1 is pressed or +- Toggles showing of accurate digital time when screen touched. */ /* jshint esversion: 6 */ @@ -117,6 +117,8 @@ function drawWordClock() { // check whether we need to redraw the watchface if (hidx !== hidxPrev) { + // Turn off showDigitalTime + showDigitalTime = false; // draw allWords var c; var y = ys; @@ -158,15 +160,9 @@ Bangle.drawWidgets(); setInterval(drawWordClock, 1E4); drawWordClock(); -// Show digital time while top button is pressed (if we have physical buttons) -if (global.BTN3) setWatch(function() { - showDigitalTime = BTN1.read(); - drawWordClock(); -}, BTN1, {repeat:true,edge:"both"}); -// If LCD pressed (on Bangle.js 2) draw digital time +// If LCD pressed, toggle drawing digital time Bangle.on('touch',e=>{ - var pressed = e.b!=0; if (showDigitalTime){ showDigitalTime = false; drawWordClock(); From 05a00c95251b28c3c20b9fced51295416ce7ba48 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:03:44 +0100 Subject: [PATCH 30/38] Update apps.json Add settings and data to apps.json --- apps.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index fd2e14e60..9e095e918 100644 --- a/apps.json +++ b/apps.json @@ -4855,7 +4855,9 @@ "readme": "README.md", "storage": [ {"name":"clicompleteclk.app.js","url":"app.js"}, - {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true} - ] + {"name":"clicompleteclk.img","url":"app-icon.js","evaluate":true}, + {"name":"clicompleteclk.settings.js","url":"settings.js"} + ], + "data": [{"name":"clicompleteclk.json"}] } ] From 5b16eb20f871f7e95018be62936f3b7ed6162d94 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:12:30 +0100 Subject: [PATCH 31/38] Update settings.js Extend settings --- apps/clicompleteclk/settings.js | 36 ++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/apps/clicompleteclk/settings.js b/apps/clicompleteclk/settings.js index ab92dbdd6..7e3d64709 100644 --- a/apps/clicompleteclk/settings.js +++ b/apps/clicompleteclk/settings.js @@ -11,10 +11,44 @@ value: "battery" in settings ? settings.battery : false, format: () => (settings.battery ? 'Yes' : 'No'), onchange: () => { - settings.battery = !settings.battery + settings.battery = !settings.battery; save('battery', settings.battery); }, }, + 'Battery warn level': { + value: "batteryLvl" in settings ? settings.batteryLvl : 30, + min: 0, + max : 100, + step: 10, + format: x => { + return x + "%"; + }, + onchange: x => save('batteryLvl', x), + }, + 'Show weather': { + value: "weather" in settings ? settings.weather : false, + format: () => (settings.batweathertery ? 'Yes' : 'No'), + onchange: () => { + settings.weather = !settings.weather; + save('weather', settings.weather); + }, + }, + 'Show steps': { + value: "steps" in settings ? settings.steps : false, + format: () => (settings.steps ? 'Yes' : 'No'), + onchange: () => { + settings.steps = !settings.steps; + save('steps', settings.steps); + }, + }, + 'Show heartrate': { + value: "heartrate" in settings ? settings.heartrate : false, + format: () => (settings.heartrate ? 'Yes' : 'No'), + onchange: () => { + settings.heartrate = !settings.heartrate; + save('heartrate', settings.heartrate); + }, + }, '< Back': back, }); }); From 2a918b6c1368be8f409027d3bf9bc039de0a072c Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:14:13 +0100 Subject: [PATCH 32/38] Update apps.json Increase version --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 9e095e918..172a9ddc0 100644 --- a/apps.json +++ b/apps.json @@ -4845,7 +4845,7 @@ { "id": "clicompleteclk", "name": "CLI complete clock", "shortName":"CLI cmplt clock", - "version":"0.02", + "version":"0.03", "description": "Command line styled clock with lots of information", "icon": "app.png", "allow_emulator": true, From dfc46898c3e82737b91e0d7ca4b084bf482f87a2 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:21:45 +0100 Subject: [PATCH 33/38] Update app.js * Use settings to toggle visibility of elements * If heart rate should be hidden we do not enable HRM power * Show battery value in red if value below threshold --- apps/clicompleteclk/app.js | 115 ++++++++++++++++++++++++++----------- 1 file changed, 81 insertions(+), 34 deletions(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index ebb17c865..8952c88a6 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -12,22 +12,49 @@ const marginLeftData = font12 ? 64 : 75; // margin of data values const topicColor = g.theme.dark ? "#fff" : "#000"; const textColor = g.theme.dark ? "#0f0" : "#080"; +const textColorRed = g.theme.dark ? "#FF0000" : "#FF0000"; let hrtValue; let hrtValueIsOld = false; + let localTempValue; let weatherTempString; let lastHeartRateRowIndex; let lastStepsRowIndex; +let i = 2; + +let settings; + +function loadSettings() { + settings = storage.readJSON('weather.json', 1) || {}; +} + +function setting(key) { + if (!settings) { loadSettings(); } + const DEFAULTS = { + 'battery': true, + 'batteryLvl': 30, + 'weather': true, + 'steps': true, + 'heartrate': true + }; + return (key in settings) ? settings[key] : DEFAULTS[key]; +} + + +let showBattery = setting('battery'); +let batteryWarnLevel = setting('batteryLvl'); +let showWeather = setting('weather'); +let showSteps = setting('steps'); +let showHeartRate = setting('heartrate'); + -// 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; - drawAll(false); + drawAll(true); }, 60000 - (Date.now() % 60000)); } @@ -44,15 +71,13 @@ function updateTime(now){ if (!Bangle.isLCDOn()) return; writeLineTopic("TIME", 1); writeLine(locale.time(now,1),1); - if(now.getMinutes() == 0) - drawInfo(now); } function drawInfo(now) { - if (now == undefined) + if (now == undefined) now = new Date(); - let i = 2; + i = 2; writeLineTopic("DOWK", i); writeLine(locale.dow(now),i); @@ -62,12 +87,28 @@ function drawInfo(now) { writeLine(locale.date(now,1),i); i++; - writeLineTopic("BATT", i); - const b = E.getBattery(); - writeLine(b + "%", i); - i++; + if (showBattery) { + writeLineTopic("BATT", i); + const b = E.getBattery(); + writeLine(b + "%", i, b > batteryWarnLevel ? textColor : textColorRed); + i++; + } - // weather + if (showWeather) { + drawWeather(); + } + + if (showSteps) { + drawSteps(i); + i++; + } + + if (showHeartRate) { + drawHeartRate(i); + } +} + +function drawWeather() { const weatherJson = getWeather(); if(weatherJson && weatherJson.weather){ const currentWeather = weatherJson.weather; @@ -82,13 +123,10 @@ function drawInfo(now) { writeLine(weatherTempValue,i); i++; } - - drawSteps(i); - - drawHeartRate(i); } function drawSteps(i) { + if (!showSteps) return; if (i == undefined) i = lastStepsRowIndex; const steps = getSteps(); @@ -100,6 +138,7 @@ function drawSteps(i) { } function drawHeartRate(i) { + if (!showHeartRate) return; if (i == undefined) i = lastHeartRateRowIndex; writeLineTopic("HRTM", i); @@ -160,14 +199,18 @@ function getWeather() { // turn on HRM when the LCD is unlocked Bangle.on('lock', function(isLocked) { if (!isLocked) { - Bangle.setHRMPower(1,"clicompleteclk"); - if (hrtValue == undefined) - hrtValue = "..."; - else - hrtValueIsOld = true; + if (showHeartRate) { + Bangle.setHRMPower(1,"clicompleteclk"); + if (hrtValue == undefined) + hrtValue = "..."; + else + hrtValueIsOld = true; + } } else { - hrtValueIsOld = true; - Bangle.setHRMPower(0,"clicompleteclk"); + if (showHeartRate) { + hrtValueIsOld = true; + Bangle.setHRMPower(0,"clicompleteclk"); + } } // Update steps and heart rate drawSteps(); @@ -178,22 +221,26 @@ Bangle.on('lcdPower',function(on) { if (on) { drawAll(true); } else { - hrtValueIsOld = true; + if (showHeartRate) { + hrtValueIsOld = true; + } if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = undefined; } }); -Bangle.on('HRM', function(hrm) { - //if(hrm.confidence > 90){ - hrtValueIsOld = false; - hrtValue = hrm.bpm; - if (Bangle.isLCDOn()) - drawHeartRate(); - //} else { - // hrtValue = undefined; - //} -}); +if (showHeartRate) { + Bangle.on('HRM', function(hrm) { + //if(hrm.confidence > 90){ + hrtValueIsOld = false; + hrtValue = hrm.bpm; + if (Bangle.isLCDOn()) + drawHeartRate(); + //} else { + // hrtValue = undefined; + //} + }); +} g.clear(); Bangle.setUI("clock"); From 7dcc5385e2309ec4ebf6ab502138f2de2cdfebcd Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:24:30 +0100 Subject: [PATCH 34/38] Update settings.js Fix settings --- apps/clicompleteclk/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/clicompleteclk/settings.js b/apps/clicompleteclk/settings.js index 7e3d64709..2df20ed3e 100644 --- a/apps/clicompleteclk/settings.js +++ b/apps/clicompleteclk/settings.js @@ -15,7 +15,7 @@ save('battery', settings.battery); }, }, - 'Battery warn level': { + 'Battery warn': { value: "batteryLvl" in settings ? settings.batteryLvl : 30, min: 0, max : 100, @@ -27,7 +27,7 @@ }, 'Show weather': { value: "weather" in settings ? settings.weather : false, - format: () => (settings.batweathertery ? 'Yes' : 'No'), + format: () => (settings.weather ? 'Yes' : 'No'), onchange: () => { settings.weather = !settings.weather; save('weather', settings.weather); From 29ba4fab0a5d0915e24b5b57c5b304f1ab315910 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:28:21 +0100 Subject: [PATCH 35/38] Update app.js Let's load correct settings :) --- apps/clicompleteclk/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index 8952c88a6..f473d440b 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -26,7 +26,7 @@ let i = 2; let settings; function loadSettings() { - settings = storage.readJSON('weather.json', 1) || {}; + settings = storage.readJSON('clicompleteclk.json', 1) || {}; } function setting(key) { @@ -246,4 +246,5 @@ g.clear(); Bangle.setUI("clock"); Bangle.loadWidgets(); Bangle.drawWidgets(); +loadSettings(); drawAll(true); From aeea8241ba8a8eab0183406f0d9304d28ed53947 Mon Sep 17 00:00:00 2001 From: Marco H Date: Sat, 11 Dec 2021 13:29:42 +0100 Subject: [PATCH 36/38] Update README.md --- apps/clicompleteclk/README.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/clicompleteclk/README.md b/apps/clicompleteclk/README.md index 62fdbbc61..8b8094633 100644 --- a/apps/clicompleteclk/README.md +++ b/apps/clicompleteclk/README.md @@ -3,12 +3,14 @@ Command line styled clock with lots of information: It can show the following (depending on availability) information: -* Time -* Day of week -* Date -* Weather conditions and temperature (requires app [Weather](https://banglejs.com/apps/#weather)) -* Steps (requires app [Health Tracking](https://banglejs.com/apps/#health%20tracking) or a step widget) -* Heart rate (when screen is on and unlocked) +* Time data: + * Time + * Day of week + * Date +* Additional information (can be toggled via settings): + * Weather conditions and temperature (requires app [Weather](https://banglejs.com/apps/#weather)) + * Steps (requires app [Health Tracking](https://banglejs.com/apps/#health%20tracking) or a step widget) + * Heart rate (when screen is on and unlocked) ## TODO * Make time font bigger From 159ba0cece7d3b3504b5ca3fefdcb8d776562881 Mon Sep 17 00:00:00 2001 From: Amos Blanton Date: Sat, 11 Dec 2021 21:03:22 +0100 Subject: [PATCH 37/38] Touch screen instead of button. --- apps/impwclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/impwclock/README.md b/apps/impwclock/README.md index 30e42c95e..ac1341097 100644 --- a/apps/impwclock/README.md +++ b/apps/impwclock/README.md @@ -1,4 +1,4 @@ # Imprecise Word Clock -This clock tells time in very rough approximation, as in "Late morning" or "Early afternoon." Good for vacations and weekends. Press button 1 to see the time in accurate, digital form. But do you really need to know the exact time? +This clock tells time in very rough approximation, as in "Late morning" or "Early afternoon." Good for vacations and weekends. Touch the screen to see the time in accurate, digital form. But do you really need to know the exact time? From 15ac03f866e89fc4a9761300af7d083e2eafeaae Mon Sep 17 00:00:00 2001 From: Marco H Date: Mon, 13 Dec 2021 08:51:10 +0100 Subject: [PATCH 38/38] Update app.js Below threshold means below :) --- apps/clicompleteclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/clicompleteclk/app.js b/apps/clicompleteclk/app.js index f473d440b..a39b37e58 100644 --- a/apps/clicompleteclk/app.js +++ b/apps/clicompleteclk/app.js @@ -90,7 +90,7 @@ function drawInfo(now) { if (showBattery) { writeLineTopic("BATT", i); const b = E.getBattery(); - writeLine(b + "%", i, b > batteryWarnLevel ? textColor : textColorRed); + writeLine(b + "%", i, b < batteryWarnLevel ? textColorRed : textColor); i++; }