From 6ac1713122cddf6ea5c236fbb1ecf96f3a60ea16 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 24 Feb 2023 15:46:35 +0000 Subject: [PATCH 01/61] 0.11: Change level for medium charge (50% -> 40%), and darken color on light themes as yellow was almost invisible --- apps/widbat/ChangeLog | 1 + apps/widbat/metadata.json | 2 +- apps/widbat/widget.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/widbat/ChangeLog b/apps/widbat/ChangeLog index 59c58af32..cb11b1be9 100644 --- a/apps/widbat/ChangeLog +++ b/apps/widbat/ChangeLog @@ -7,3 +7,4 @@ 0.08: Ensure battery updates every 60s even if LCD was on at boot and stays on 0.09: Misc speed/memory tweaks 0.10: Color changes due to the battery level +0.11: Change level for medium charge (50% -> 40%), and darken color on light themes as yellow was almost invisible diff --git a/apps/widbat/metadata.json b/apps/widbat/metadata.json index 5f0d1b7d1..0151fcbd7 100644 --- a/apps/widbat/metadata.json +++ b/apps/widbat/metadata.json @@ -1,7 +1,7 @@ { "id": "widbat", "name": "Battery Level Widget", - "version": "0.10", + "version": "0.11", "description": "Show the current battery level and charging status in the top right of the clock", "icon": "widget.png", "type": "widget", diff --git a/apps/widbat/widget.js b/apps/widbat/widget.js index 7fce16335..98eb09227 100644 --- a/apps/widbat/widget.js +++ b/apps/widbat/widget.js @@ -33,7 +33,7 @@ g.setColor(g.theme.fg).fillRect(x,y+2,x+s-4,y+21).clearRect(x+2,y+4,x+s-6,y+19).fillRect(x+s-3,y+10,x+s,y+14); var battery = E.getBattery(); if(battery < 20) {g.setColor("#f00");} - else if (battery < 50) {g.setColor("#ff0");} + else if (battery < 40) {g.setColor(g.theme.dark ? "#ff0" : "#f80");} else {g.setColor("#0f0");} g.fillRect(x+4,y+6,x+4+battery*(s-12)/100,y+17); }}; From ad6e2f71080f997e76c5a6c65aa594babb4477ff Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 24 Feb 2023 20:03:19 +0100 Subject: [PATCH 02/61] tweak clearRect width to not clear the indicator segment --- apps/runplus/karvonnen.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/runplus/karvonnen.js b/apps/runplus/karvonnen.js index 7e7c07050..f50bd221b 100644 --- a/apps/runplus/karvonnen.js +++ b/apps/runplus/karvonnen.js @@ -67,7 +67,7 @@ // HR data: large, readable, in the middle of the screen function drawHR() { g.setFontAlign(-1,0,0); - g.clearRect(Rdiv(x,11/4),Rdiv(y,2)-25,Rdiv(x,11/4)+50*2,Rdiv(y,2)+25); + g.clearRect(Rdiv(x,11/4),Rdiv(y,2)-25,Rdiv(x,11/4)+50*2-14,Rdiv(y,2)+25); g.setColor(g.theme.fg); g.setFont("Vector",50); g.drawString(hr, Rdiv(x,11/4), Rdiv(y,2)+4); From a73543365211cc824106a0d0618ed7684ddf4ce6 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 24 Feb 2023 21:02:45 +0100 Subject: [PATCH 03/61] bump version --- apps/runplus/ChangeLog | 3 ++- apps/runplus/metadata.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/runplus/ChangeLog b/apps/runplus/ChangeLog index d3426428d..f47bcc720 100644 --- a/apps/runplus/ChangeLog +++ b/apps/runplus/ChangeLog @@ -13,4 +13,5 @@ 0.12: Fix for recorder not stopping at end of run. Bug introduced in 0.11 0.13: Revert #1578 (stop duplicate entries) as with 2v12 menus it causes other boxes to be wiped (fix #1643) 0.14: Fix Bangle.js 1 issue where after the 'overwrite track' menu, the start/stop button stopped working -0.15: Diverge from the standard "Run" app. Swipe to intensity interface a la Karvonnen (curtesy of FTeacher at https://github.com/f-teacher) +0.15: Diverge from the standard "Run" app. Swipe to intensity interface a la Karvonen (curtesy of FTeacher at https://github.com/f-teacher) +0.16: Don't clear zone 2b indicator segment when updating HRM reading. diff --git a/apps/runplus/metadata.json b/apps/runplus/metadata.json index 15492e20c..a28d36674 100644 --- a/apps/runplus/metadata.json +++ b/apps/runplus/metadata.json @@ -1,7 +1,7 @@ { "id": "runplus", "name": "Run+", - "version": "0.15", + "version": "0.16", "description": "Displays distance, time, steps, cadence, pace and more for runners. Based on the Run app, but extended with additional screen for heart rate interval training.", "icon": "app.png", "tags": "run,running,fitness,outdoors,gps,karvonnen", From 7f20125fd949534fa2517a9a558727987167b13f Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 24 Feb 2023 21:54:49 +0100 Subject: [PATCH 04/61] powermanager - Fix wrapping of deferred functions with parameters --- apps/powermanager/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/powermanager/boot.js b/apps/powermanager/boot.js index c931a243b..40487a5bf 100644 --- a/apps/powermanager/boot.js +++ b/apps/powermanager/boot.js @@ -84,7 +84,7 @@ if (!a.__wrapped){ wrapped = ()=>{ let start = Date.now(); - let result = a.apply(undefined, arguments.slice(1)); + let result = a.apply(undefined, arguments.slice(2)); // function arguments for deferred calls start at index 2, first is function, second is time let end = Date.now()-start; let f = a.toString().substring(0,100); if (settings.logDetails) logDeferred(t, end, f); From eab7ae25d9eaa25ac493842e4e41dbb5bc8a34b9 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 24 Feb 2023 21:56:48 +0100 Subject: [PATCH 05/61] powermanager - Bump version --- apps/powermanager/ChangeLog | 1 + apps/powermanager/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/powermanager/ChangeLog b/apps/powermanager/ChangeLog index a43558c3f..dbe102958 100644 --- a/apps/powermanager/ChangeLog +++ b/apps/powermanager/ChangeLog @@ -7,3 +7,4 @@ 0.06: Allow logging of some things using power Add widget for live monitoring of power use 0.07: Convert Yes/No On/Off in settings to checkboxes +0.08: Fix the wrapping of intervals/timeouts with parameters \ No newline at end of file diff --git a/apps/powermanager/metadata.json b/apps/powermanager/metadata.json index ca5a9f00b..2229629a9 100644 --- a/apps/powermanager/metadata.json +++ b/apps/powermanager/metadata.json @@ -2,7 +2,7 @@ "id": "powermanager", "name": "Power Manager", "shortName": "Power Manager", - "version": "0.07", + "version": "0.08", "description": "Allow configuration of warnings and thresholds for battery charging and display.", "icon": "app.png", "type": "bootloader", From 0db11e57073acc846d047b07005b4dd384969229 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 12:40:25 +0100 Subject: [PATCH 06/61] write to correct settings file --- apps/runplus/ChangeLog | 1 + apps/runplus/settings.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/runplus/ChangeLog b/apps/runplus/ChangeLog index f47bcc720..3eeb31733 100644 --- a/apps/runplus/ChangeLog +++ b/apps/runplus/ChangeLog @@ -15,3 +15,4 @@ 0.14: Fix Bangle.js 1 issue where after the 'overwrite track' menu, the start/stop button stopped working 0.15: Diverge from the standard "Run" app. Swipe to intensity interface a la Karvonen (curtesy of FTeacher at https://github.com/f-teacher) 0.16: Don't clear zone 2b indicator segment when updating HRM reading. +Write to correct settings file, fixing settings not working. diff --git a/apps/runplus/settings.js b/apps/runplus/settings.js index 050eed4b8..cd72022be 100644 --- a/apps/runplus/settings.js +++ b/apps/runplus/settings.js @@ -1,5 +1,5 @@ (function(back) { - const SETTINGS_FILE = "run.json"; + const SETTINGS_FILE = "runplus.json"; var ExStats = require("exstats"); var statsList = ExStats.getList(); statsList.unshift({name:"-",id:""}); // add blank menu item From 3d21d2bef438a9e992905137829259dbfd402b77 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 12:54:10 +0100 Subject: [PATCH 07/61] contributors appended to readme --- apps/runplus/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/runplus/README.md b/apps/runplus/README.md index 7f645b518..659cd964d 100644 --- a/apps/runplus/README.md +++ b/apps/runplus/README.md @@ -67,3 +67,10 @@ app loader, the module is automatically included in the app's source. However when developing via the IDE the module won't get pulled in by default. There are some options to fix this easily - please check out the [modules README.md file](https://github.com/espruino/BangleApps/blob/master/modules/README.md) +## Contributors (Run and Run+) +gfwilliams +hughbarney +GrandVizierOlaf +BartS23 +f-teacher +thyttan From 290fd81f46e60e46cdd3ee2a2c36d6e663e16bab Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sat, 25 Feb 2023 13:13:04 +0100 Subject: [PATCH 08/61] powermanager - Fix drawing on hidden widgets when LCD brightness is changed --- apps/powermanager/ChangeLog | 3 ++- apps/powermanager/widget.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/powermanager/ChangeLog b/apps/powermanager/ChangeLog index dbe102958..ee31195b2 100644 --- a/apps/powermanager/ChangeLog +++ b/apps/powermanager/ChangeLog @@ -7,4 +7,5 @@ 0.06: Allow logging of some things using power Add widget for live monitoring of power use 0.07: Convert Yes/No On/Off in settings to checkboxes -0.08: Fix the wrapping of intervals/timeouts with parameters \ No newline at end of file +0.08: Fix the wrapping of intervals/timeouts with parameters + Fix the widget drawing if widgets are hidden and Bangle.setLCDBrightness is called \ No newline at end of file diff --git a/apps/powermanager/widget.js b/apps/powermanager/widget.js index 116f1703e..3147c40ac 100644 --- a/apps/powermanager/widget.js +++ b/apps/powermanager/widget.js @@ -24,7 +24,7 @@ currently-running apps */ let brightnessSetting = settings.brightness || 1; Bangle.setLCDBrightness = ((o) => (a) => { brightnessSetting = a; - draw(WIDGETS.powermanager); + WIDGETS.powermanager.draw(WIDGETS.powermanager); return o(a); })(Bangle.setLCDBrightness); From 4a4c9315710f38d76c34a4b62c75acededab25ab Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 13:47:51 +0100 Subject: [PATCH 09/61] add to the instruction for # of handlers i readme --- apps/backswipe/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/apps/backswipe/README.md b/apps/backswipe/README.md index 1611263bb..21aa357b3 100644 --- a/apps/backswipe/README.md +++ b/apps/backswipe/README.md @@ -10,6 +10,12 @@ Standard # of drag handlers: 0-10 (Default: 0, must be changed for backswipe to Standard # of handlers settings are used to fine tune when backswipe should trigger the back function. E.g. when using a keyboard that works on drags, we don't want the backswipe to trigger when we just wanted to select a letter. This might not be able to cover all cases however. +To get an indication for standard # of handlers `Bangle["#onswipe"]` and `Bangle["#ondrag"]` can be entered in the [Espruino Web IDE](https://www.espruino.com/ide) console field. They return `undefined` if no handler is active, a function if one is active, or a list of functions if multiple are active. Calling this on the clock app is a good start. + +## TODO + +- Possibly add option to tweak standard # of handlers on per app basis. + ## Creator Kedlub From 21c928ba8796470aa60fea568fecaee356a73c4c Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 17:51:08 +0100 Subject: [PATCH 10/61] add tag karvonen --- apps/runplus/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/runplus/metadata.json b/apps/runplus/metadata.json index a28d36674..2c221e0d4 100644 --- a/apps/runplus/metadata.json +++ b/apps/runplus/metadata.json @@ -4,7 +4,7 @@ "version": "0.16", "description": "Displays distance, time, steps, cadence, pace and more for runners. Based on the Run app, but extended with additional screen for heart rate interval training.", "icon": "app.png", - "tags": "run,running,fitness,outdoors,gps,karvonnen", + "tags": "run,running,fitness,outdoors,gps,karvonen,karvonnen", "supports": [ "BANGLEJS2" ], From 5e1857d963975e238af2a8825d0f2f3108c56901 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 18:13:50 +0100 Subject: [PATCH 11/61] change spelling karvonnen -> karvonen in app.js, karvonen.js --- apps/runplus/app.js | 26 +++++++++++----------- apps/runplus/{karvonnen.js => karvonen.js} | 12 +++++----- 2 files changed, 19 insertions(+), 19 deletions(-) rename apps/runplus/{karvonnen.js => karvonen.js} (96%) diff --git a/apps/runplus/app.js b/apps/runplus/app.js index 15e042759..06270850f 100644 --- a/apps/runplus/app.js +++ b/apps/runplus/app.js @@ -2,7 +2,7 @@ let wu = require("widget_utils"); let runInterval; -let karvonnenActive = false; +let karvonenActive = false; // Run interface wrapped in a function let ExStats = require("exstats"); let B2 = process.env.HWVERSION===2; @@ -121,7 +121,7 @@ lc.push({ type:"h", filly:1, c:[ // Now calculate the layout let layout = new Layout( { type:"v", c: lc -},{lazy:true, btns:[{ label:"START", cb: ()=>{if (karvonnenActive) {stopKarvonnenUI();run();} onStartStop();}, id:"button"}]}); +},{lazy:true, btns:[{ label:"START", cb: ()=>{if (karvonenActive) {stopKarvonenUI();run();} onStartStop();}, id:"button"}]}); delete lc; layout.render(); @@ -150,7 +150,7 @@ Bangle.on("GPS", function(fix) { } }); -// run() function used to switch between traditional run UI and karvonnen UI +// run() function used to switch between traditional run UI and karvonen UI function run() { wu.show(); layout.lazy = false; @@ -160,35 +160,35 @@ function run() { if (!runInterval){ runInterval = setInterval(function() { layout.clock.label = locale.time(new Date(),1); - if (!isMenuDisplayed && !karvonnenActive) layout.render(); + if (!isMenuDisplayed && !karvonenActive) layout.render(); }, 1000); } } run(); /////////////////////////////////////////////// -// Karvonnen +// Karvonen /////////////////////////////////////////////// function stopRunUI() { // stop updating and drawing the traditional run app UI clearInterval(runInterval); runInterval = undefined; - karvonnenActive = true; + karvonenActive = true; } -function stopKarvonnenUI() { +function stopKarvonenUI() { g.reset().clear(); - clearInterval(karvonnenInterval); - karvonnenInterval = undefined; - karvonnenActive = false; + clearInterval(karvonenInterval); + karvonenInterval = undefined; + karvonenActive = false; } -let karvonnenInterval; +let karvonenInterval; // Define the function to go back and forth between the different UI's function swipeHandler(LR,_) { - if (LR==-1 && karvonnenActive && !isMenuDisplayed) {stopKarvonnenUI(); run();} - if (LR==1 && !karvonnenActive && !isMenuDisplayed) {stopRunUI(); karvonnenInterval = eval(require("Storage").read("runplus_karvonnen"))(settings.HRM, exs.stats.bpm);} + if (LR==-1 && karvonenActive && !isMenuDisplayed) {stopKarvonenUI(); run();} + if (LR==1 && !karvonenActive && !isMenuDisplayed) {stopRunUI(); karvonenInterval = eval(require("Storage").read("runplus_karvonen"))(settings.HRM, exs.stats.bpm);} } // Listen for swipes with the swipeHandler Bangle.on("swipe", swipeHandler); diff --git a/apps/runplus/karvonnen.js b/apps/runplus/karvonen.js similarity index 96% rename from apps/runplus/karvonnen.js rename to apps/runplus/karvonen.js index f50bd221b..de81494bb 100644 --- a/apps/runplus/karvonnen.js +++ b/apps/runplus/karvonen.js @@ -1,6 +1,6 @@ -(function karvonnen(hrmSettings, exsHrmStats) { +(function karvonen(hrmSettings, exsHrmStats) { //This app is an extra feature implementation for the Run.app of the bangle.js. It's called run+ - //The calculation of the Heart Rate Zones is based on the Karvonnen method. It requires to know maximum and minimum heart rates. More precise calculation methods require a lab. + //The calculation of the Heart Rate Zones is based on the Karvonen method. It requires to know maximum and minimum heart rates. More precise calculation methods require a lab. //Other methods are even more approximative. let wu = require("widget_utils"); wu.hide(); @@ -56,7 +56,7 @@ let hr = exsHrmStats.getValue(); let hr1 = hr; // These letiables display next and previous HR zone. - //get the hrzones right. The calculation of the Heart rate zones here is based on the Karvonnen method + //get the hrzones right. The calculation of the Heart rate zones here is based on the Karvonen method //60-70% of HRR+minHR = zone2. //70-80% of HRR+minHR = zone3. //80-90% of HRR+minHR = zone4. //90-99% of HRR+minHR = zone5. //=>99% of HRR+minHR = serious risk of heart attack let minzone2 = hrr * 0.6 + minhr; let maxzone2 = hrr * 0.7 + minhr; @@ -207,9 +207,9 @@ initDraw(); // check for updates every second. - karvonnenInterval = setInterval(function() { - if (!isMenuDisplayed && karvonnenActive) updateUI(); + karvonenInterval = setInterval(function() { + if (!isMenuDisplayed && karvonenActive) updateUI(); }, 1000); - return karvonnenInterval; + return karvonenInterval; }) From 4199f8a4fcd0ce7b4e33a27ed2583bbff060e107 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 25 Feb 2023 18:16:25 +0100 Subject: [PATCH 12/61] spelling karvonnen -> karvonen in metadata --- apps/runplus/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/runplus/metadata.json b/apps/runplus/metadata.json index 2c221e0d4..017a52ac3 100644 --- a/apps/runplus/metadata.json +++ b/apps/runplus/metadata.json @@ -29,8 +29,8 @@ "url": "settings.js" }, { - "name": "runplus_karvonnen", - "url": "karvonnen.js" + "name": "runplus_karvonen", + "url": "karvonen.js" } ], "data": [ From 9403bf05b01176da217388ddb435f7cbadf2ab5c Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sun, 29 Jan 2023 23:01:52 +0000 Subject: [PATCH 13/61] clock_info.d.ts .app addition --- typescript/types/clock_info.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/typescript/types/clock_info.d.ts b/typescript/types/clock_info.d.ts index 9b664a6dc..06a2d400b 100644 --- a/typescript/types/clock_info.d.ts +++ b/typescript/types/clock_info.d.ts @@ -44,6 +44,7 @@ declare module ClockInfo { w: number, h: number, draw(itm: MenuItem, info: Item, options: InteractiveOptions): void, + app?: string, // used to remember clock_info locations, per app }; type InteractiveOptions = From b19dd38dbb218eb1f1237c3d7f1e9a22c7162de0 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Fri, 13 Jan 2023 22:11:09 +0000 Subject: [PATCH 14/61] widlockunlock: handle widget tap to lock --- apps/widlockunlock/ChangeLog | 1 + apps/widlockunlock/metadata.json | 4 +-- apps/widlockunlock/widget.js | 45 ++++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 7 deletions(-) diff --git a/apps/widlockunlock/ChangeLog b/apps/widlockunlock/ChangeLog index b4d1ae593..b5efcaa86 100644 --- a/apps/widlockunlock/ChangeLog +++ b/apps/widlockunlock/ChangeLog @@ -1 +1,2 @@ 0.01: First commit +0.02: Add tap-to-lock functionality diff --git a/apps/widlockunlock/metadata.json b/apps/widlockunlock/metadata.json index d701279b9..cc4fa76cd 100644 --- a/apps/widlockunlock/metadata.json +++ b/apps/widlockunlock/metadata.json @@ -1,8 +1,8 @@ { "id": "widlockunlock", "name": "Lock/Unlock Widget", - "version": "0.01", - "description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise", + "version": "0.02", + "description": "On devices with always-on display (Bangle.js 2) this displays lock icon whenever the display is locked, or an unlock icon otherwise. Tap to lock the lcd", "icon": "widget.png", "type": "widget", "tags": "widget,lock", diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index 0716a9edf..21461b4a5 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,6 +1,41 @@ -Bangle.on("lockunlock", function() { - Bangle.drawWidgets(); +WIDGETS["lockunlock"] = { + area: "tl", + sortorder: 10, + width: 14, + draw: w => { + g.reset() + .drawImage( + atob(Bangle.isLocked() + ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" + : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), + w.x + 1, + w.y + 3 + ); + }, +}; +Bangle.on("lock", () => Bangle.drawWidgets()); + +Bangle.on('touch', (_btn, xy) => { + const oversize = 5; + + const w = WIDGETS.lockunlock; + + const x = xy.x; + const y = xy.y; + + if(w.x - oversize <= x && x < w.x + 14 + oversize + && w.y - oversize <= y && y < w.y + 24 + oversize) + { + Bangle.setLocked(true); + + const backlightTimeout = Bangle.getOptions().backlightTimeout; // ms + + // seems to be a race/if we don't give the firmware enough time, + // it won't timeout the backlight and we'll restore it in our setTimeout below + Bangle.setOptions({ backlightTimeout: 100 }); + + setTimeout(() => { + Bangle.setOptions({ backlightTimeout }); + }, 300); + } }); -WIDGETS["lockunlock"]={area:"tl",sortorder:10,width:14,draw:function(w) { - g.reset().drawImage(atob(Bangle.isLocked() ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x+1, w.y+3); -}}; From c84d3fa2c0a063e79a5a353d84e81a786938e6d2 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 25 Feb 2023 21:56:34 +0000 Subject: [PATCH 15/61] widlockunlock: setting for location --- apps/widlockunlock/metadata.json | 3 ++- apps/widlockunlock/settings.js | 29 ++++++++++++++++++++++++ apps/widlockunlock/settings.ts | 39 ++++++++++++++++++++++++++++++++ apps/widlockunlock/widget.js | 6 ++++- 4 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 apps/widlockunlock/settings.js create mode 100644 apps/widlockunlock/settings.ts diff --git a/apps/widlockunlock/metadata.json b/apps/widlockunlock/metadata.json index cc4fa76cd..daeefbc69 100644 --- a/apps/widlockunlock/metadata.json +++ b/apps/widlockunlock/metadata.json @@ -8,6 +8,7 @@ "tags": "widget,lock", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"widlockunlock.wid.js","url":"widget.js"} + {"name":"widlockunlock.wid.js","url":"widget.js"}, + {"name":"widlockunlock.settings.js","url":"settings.js"} ] } diff --git a/apps/widlockunlock/settings.js b/apps/widlockunlock/settings.js new file mode 100644 index 000000000..0c3a82c39 --- /dev/null +++ b/apps/widlockunlock/settings.js @@ -0,0 +1,29 @@ +"use strict"; +(function (back) { + var storage = require('Storage'); + var filename = 'lockunlock.settings.json'; + var settings = Object.assign(storage.readJSON(filename, true) || {}, { location: "tl" }); + var save = function () { + return storage.writeJSON(filename, settings); + }; + var locations = ["tl", "tr"]; + var menu = { + '': { 'title': 'Lock/Unlock' }, + '< Back': back, + 'Location': { + value: (function () { + var i = locations.indexOf(settings.location); + return i < 0 ? 0 : i; + })(), + min: 0, + max: locations.length - 1, + wrap: true, + format: function (v) { return locations[v]; }, + onchange: function (v) { + settings.location = locations[v]; + save(); + }, + }, + }; + E.showMenu(menu); +}); diff --git a/apps/widlockunlock/settings.ts b/apps/widlockunlock/settings.ts new file mode 100644 index 000000000..b2b1dc02e --- /dev/null +++ b/apps/widlockunlock/settings.ts @@ -0,0 +1,39 @@ +((back: () => void) => { + type Location = "tl" | "tr"; + type Settings = { + location: Location; + }; + + const storage = require('Storage'); + + const filename = 'lockunlock.settings.json'; + const settings: Settings = Object.assign( + storage.readJSON(filename, true) || {}, + { location: "tl" } + ); + + const save = () => + storage.writeJSON(filename, settings); + + const locations: Array = [ "tl", "tr" ]; + + const menu = { + '': { 'title': 'Lock/Unlock' }, + '< Back': back, + 'Location': { + value: (() => { + const i = locations.indexOf(settings.location); + return i < 0 ? 0 : i; + })(), + min: 0, + max: locations.length - 1, + wrap: true, + format: (v: number) => locations[v]!, + onchange: (v: number) => { + settings.location = locations[v]!; + save(); + }, + }, + }; + E.showMenu(menu); +}); diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index 21461b4a5..f7f872a5e 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,5 +1,9 @@ WIDGETS["lockunlock"] = { - area: "tl", + area: (() => { + const settings = require("Storage") + .readJSON("lockunlock.settings.json", true) || {}; + return settings.location || "tl"; + })(), sortorder: 10, width: 14, draw: w => { From 92fd9133fbea07217c45e4f4e6ab181182e5eb23 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 25 Feb 2023 21:58:53 +0000 Subject: [PATCH 16/61] Regenerate main.d.ts - Widget types --- apps/widChargingStatus/widget.ts | 4 ++-- typescript/types/main.d.ts | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/widChargingStatus/widget.ts b/apps/widChargingStatus/widget.ts index 02f3cd8d4..a161d5408 100644 --- a/apps/widChargingStatus/widget.ts +++ b/apps/widChargingStatus/widget.ts @@ -6,11 +6,11 @@ ); const iconWidth = 18; - function draw(this: { x: number; y: number }) { + function draw(this: { x?: number; y?: number }) { g.reset(); if (Bangle.isCharging()) { g.setColor('#FD0'); - g.drawImage(icon, this.x + 1, this.y + 1, { + g.drawImage(icon, this.x! + 1, this.y! + 1, { scale: 0.6875, }); } diff --git a/typescript/types/main.d.ts b/typescript/types/main.d.ts index 1505c6f5a..d33c905d0 100644 --- a/typescript/types/main.d.ts +++ b/typescript/types/main.d.ts @@ -83,7 +83,10 @@ type WidgetArea = "tl" | "tr" | "bl" | "br"; type Widget = { area: WidgetArea; width: number; - draw: (this: { x: number; y: number }) => void; + sortorder?: number; + draw: (this: Widget, w: Widget) => void; + x?: number; + y?: number; }; declare const WIDGETS: { [key: string]: Widget }; From 6a21608322d2a605e273b8b74cf7227129d152ee Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 25 Feb 2023 21:58:12 +0000 Subject: [PATCH 17/61] widlockunlock: convert to typescript --- apps/widlockunlock/widget.js | 73 +++++++++++++++--------------------- apps/widlockunlock/widget.ts | 46 +++++++++++++++++++++++ 2 files changed, 77 insertions(+), 42 deletions(-) create mode 100644 apps/widlockunlock/widget.ts diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index f7f872a5e..e4569f511 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,45 +1,34 @@ +"use strict"; WIDGETS["lockunlock"] = { - area: (() => { - const settings = require("Storage") - .readJSON("lockunlock.settings.json", true) || {}; - return settings.location || "tl"; - })(), - sortorder: 10, - width: 14, - draw: w => { - g.reset() - .drawImage( - atob(Bangle.isLocked() - ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" - : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), - w.x + 1, - w.y + 3 - ); - }, + area: (function () { + var _a; + var settings = require("Storage") + .readJSON("lockunlock.settings.json", true) || {}; + return (_a = settings.location) !== null && _a !== void 0 ? _a : "tl"; + })(), + sortorder: 10, + width: 14, + draw: function (w) { + g.reset() + .drawImage(atob(Bangle.isLocked() + ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" + : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x + 1, w.y + 3); + }, }; -Bangle.on("lock", () => Bangle.drawWidgets()); - -Bangle.on('touch', (_btn, xy) => { - const oversize = 5; - - const w = WIDGETS.lockunlock; - - const x = xy.x; - const y = xy.y; - - if(w.x - oversize <= x && x < w.x + 14 + oversize - && w.y - oversize <= y && y < w.y + 24 + oversize) - { - Bangle.setLocked(true); - - const backlightTimeout = Bangle.getOptions().backlightTimeout; // ms - - // seems to be a race/if we don't give the firmware enough time, - // it won't timeout the backlight and we'll restore it in our setTimeout below - Bangle.setOptions({ backlightTimeout: 100 }); - - setTimeout(() => { - Bangle.setOptions({ backlightTimeout }); - }, 300); - } +Bangle.on("lock", function () { return Bangle.drawWidgets(); }); +Bangle.on("touch", function (_btn, e) { + var oversize = 5; + if (!e) + return; + var x = e.x, y = e.y; + var w = WIDGETS["lockunlock"]; + if (w.x - oversize <= x && x < w.x + 14 + oversize + && w.y - oversize <= y && y < w.y + 24 + oversize) { + Bangle.setLocked(true); + var backlightTimeout_1 = Bangle.getOptions().backlightTimeout; + Bangle.setOptions({ backlightTimeout: 100 }); + setTimeout(function () { + Bangle.setOptions({ backlightTimeout: backlightTimeout_1 }); + }, 300); + } }); diff --git a/apps/widlockunlock/widget.ts b/apps/widlockunlock/widget.ts new file mode 100644 index 000000000..5dd1c93e9 --- /dev/null +++ b/apps/widlockunlock/widget.ts @@ -0,0 +1,46 @@ +WIDGETS["lockunlock"] = { + area: (() => { + const settings = require("Storage") + .readJSON("lockunlock.settings.json", true) || {}; + return settings.location ?? "tl"; + })(), + sortorder: 10, + width: 14, + draw: w => { + g.reset() + .drawImage( + atob(Bangle.isLocked() + ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" + : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), + w.x! + 1, + w.y! + 3 + ); + }, +}; + +Bangle.on("lock", () => Bangle.drawWidgets()); + +Bangle.on("touch", (_btn, e) => { + const oversize = 5; + + if (!e) return; + const { x, y } = e; + + const w = WIDGETS["lockunlock"]!; + + if(w.x! - oversize <= x && x < w.x! + 14 + oversize + && w.y! - oversize <= y && y < w.y! + 24 + oversize) + { + Bangle.setLocked(true); + + const { backlightTimeout } = Bangle.getOptions(); // ms + + // seems to be a race/if we don't give the firmware enough time, + // it won't timeout the backlight and we'll restore it in our setTimeout below + Bangle.setOptions({ backlightTimeout: 100 }); + + setTimeout(() => { + Bangle.setOptions({ backlightTimeout }); + }, 300); + } +}); From e44e4c0274df593da6fea68ed9a270329cd18c81 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 25 Feb 2023 22:23:10 +0000 Subject: [PATCH 18/61] Regenerate main.d.ts - fromEntries & getOwnPropertyDescriptors --- typescript/types/main.d.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/typescript/types/main.d.ts b/typescript/types/main.d.ts index 1505c6f5a..8a9273a76 100644 --- a/typescript/types/main.d.ts +++ b/typescript/types/main.d.ts @@ -8688,6 +8688,15 @@ interface ObjectConstructor { */ entries(object: any): Array<[string, any]>; + /** + * Transforms an array of key-value pairs into an object + * + * @param {any} entries - An array of `[key,value]` pairs to be used to create an object + * @returns {any} An object containing all the specified pairs + * @url http://www.espruino.com/Reference#l_Object_fromEntries + */ + fromEntries(entries: any): any; + /** * Creates a new object with the specified prototype object and properties. * properties are currently unsupported. @@ -8709,6 +8718,15 @@ interface ObjectConstructor { */ getOwnPropertyDescriptor(obj: any, name: any): any; + /** + * Get information on all properties in the object (from `Object.getOwnPropertyDescriptor`), or just `{}` if no properties + * + * @param {any} obj - The object + * @returns {any} An object containing all the property descriptors of an object + * @url http://www.espruino.com/Reference#l_Object_getOwnPropertyDescriptors + */ + getOwnPropertyDescriptors(obj: any): any; + /** * Add a new property to the Object. 'Desc' is an object with the following fields: * * `configurable` (bool = false) - can this property be changed/deleted (not From 9f4e4bc98137ca81e3b76ede8a84e555ad6c9db3 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Sat, 25 Feb 2023 23:20:53 +0000 Subject: [PATCH 19/61] Regenerate object.call types --- typescript/types/main.d.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/typescript/types/main.d.ts b/typescript/types/main.d.ts index 8a9273a76..a48ce7565 100644 --- a/typescript/types/main.d.ts +++ b/typescript/types/main.d.ts @@ -8963,32 +8963,32 @@ interface Function { /** * This executes the function with the supplied 'this' argument and parameters * - * @param {any} this - The value to use as the 'this' argument when executing the function + * @param {any} thisArg - The value to use as the 'this' argument when executing the function * @param {any} params - Optional Parameters * @returns {any} The return value of executing this function * @url http://www.espruino.com/Reference#l_Function_call */ - call(this: any, ...params: any[]): any; + call(thisArg: any, ...params: any[]): any; /** * This executes the function with the supplied 'this' argument and parameters * - * @param {any} this - The value to use as the 'this' argument when executing the function + * @param {any} thisArg - The value to use as the 'this' argument when executing the function * @param {any} args - Optional Array of Arguments * @returns {any} The return value of executing this function * @url http://www.espruino.com/Reference#l_Function_apply */ - apply(this: any, args: any): any; + apply(thisArg: any, args: ArrayLike): any; /** * This executes the function with the supplied 'this' argument and parameters * - * @param {any} this - The value to use as the 'this' argument when executing the function + * @param {any} thisArg - The value to use as the 'this' argument when executing the function * @param {any} params - Optional Default parameters that are prepended to the call * @returns {any} The 'bound' function * @url http://www.espruino.com/Reference#l_Function_bind */ - bind(this: any, ...params: any[]): any; + bind(thisArg: any, ...params: any[]): any; } /** From dd0f88245a2b791c2f5f2af50263a53941ef6803 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 26 Feb 2023 09:08:28 +0100 Subject: [PATCH 20/61] widalarmeta: use less cpu time each minute Remember next alarm to reduce calculation amount Redraw only every hour when no alarm in next 24h --- apps/widalarmeta/ChangeLog | 2 ++ apps/widalarmeta/metadata.json | 2 +- apps/widalarmeta/widget.js | 43 ++++++++++++++++++++++++---------- 3 files changed, 34 insertions(+), 13 deletions(-) diff --git a/apps/widalarmeta/ChangeLog b/apps/widalarmeta/ChangeLog index 66b9a4b8e..4bcf6ec69 100644 --- a/apps/widalarmeta/ChangeLog +++ b/apps/widalarmeta/ChangeLog @@ -6,3 +6,5 @@ Update to match the default alarm widget, and not show itself when an alarm is hidden. 0.04: Fix check for active alarm 0.05: Convert Yes/No On/Off in settings to checkboxes +0.06: Remember next alarm to reduce calculation amount + Redraw only every hour when no alarm in next 24h diff --git a/apps/widalarmeta/metadata.json b/apps/widalarmeta/metadata.json index 20b54d7c8..a3d2e8adb 100644 --- a/apps/widalarmeta/metadata.json +++ b/apps/widalarmeta/metadata.json @@ -2,7 +2,7 @@ "id": "widalarmeta", "name": "Alarm & Timer ETA", "shortName": "Alarm ETA", - "version": "0.05", + "version": "0.06", "description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).", "icon": "widget.png", "type": "widget", diff --git a/apps/widalarmeta/widget.js b/apps/widalarmeta/widget.js index 3ad2e6ad2..d2e293bc7 100644 --- a/apps/widalarmeta/widget.js +++ b/apps/widalarmeta/widget.js @@ -1,6 +1,5 @@ (() => { require("Font5x9Numeric7Seg").add(Graphics); - const alarms = require("Storage").readJSON("sched.json",1) || []; const config = Object.assign({ maxhours: 24, drawBell: false, @@ -8,17 +7,37 @@ }, require("Storage").readJSON("widalarmeta.json",1) || {}); function draw() { - const times = alarms - .map(alarm => - alarm.hidden !== true - && require("sched").getTimeToAlarm(alarm) - ) - .filter(a => a !== undefined); - const next = times.length > 0 ? Math.min.apply(null, times) : 0; + if (this.nextAlarm === undefined) { + const getNextAlarm = (date) => { + const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); + this.numActiveAlarms = alarms.length; + const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); + const eta = times.length > 0 ? Math.min.apply(null, times) : 0; + if (eta !== Number.POSITIVE_INFINITY) { + const idx = times.indexOf(eta); + const alarm = alarms[idx]; + delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory + return alarm; + } + }; // getNextAlarm + + let alarm = getNextAlarm(); + if (alarm === undefined) { + // try again with next hour + const nextHour = new Date(); + nextHour.setHours(nextHour.getHours()+1); + alarm = getNextAlarm(nextHour); + } + if (alarm !== undefined) { + this.nextAlarm = alarm; + } + } + const next = this.nextAlarm !== undefined ? require("sched").getTimeToAlarm(this.nextAlarm) : 0; + let calcWidth = 0; let drawSeconds = false; - if (next > 0 && next < config.maxhours*60*60*1000) { + if (next > 0 && next <= config.maxhours*60*60*1000) { const hours = Math.floor((next-1) / 3600000).toString(); const minutes = Math.floor(((next-1) % 3600000) / 60000).toString(); const seconds = Math.floor(((next-1) % 60000) / 1000).toString(); @@ -39,7 +58,7 @@ if (drawSeconds) { calcWidth += 3*5; } - } else if (config.drawBell && alarms.some(alarm=>alarm.on&&(alarm.hidden!==true))) { + } else if (config.drawBell && this.numActiveAlarms > 0) { // next alarm too far in future, draw only widalarm bell g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y); calcWidth = 24; @@ -51,8 +70,8 @@ Bangle.drawWidgets(); } - // redraw next full minute or second - const period = drawSeconds ? 1000 : 60000; + // redraw next hour when no alarm else full minute or second + const period = next === 0 ? 3600000 : (drawSeconds ? 1000 : 60000); let timeout = next > 0 ? next % period : period - (Date.now() % period); if (timeout === 0) { timeout += period; From 3ca236d83553e66eb09eac9f2262e95e0cc9e114 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 26 Feb 2023 09:28:45 +0100 Subject: [PATCH 21/61] widalarmeta: Move getNextAlarm --- apps/widalarmeta/widget.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/widalarmeta/widget.js b/apps/widalarmeta/widget.js index d2e293bc7..8fab6fde7 100644 --- a/apps/widalarmeta/widget.js +++ b/apps/widalarmeta/widget.js @@ -6,21 +6,21 @@ showSeconds: 0, // 0=never, 1=only when display is unlocked, 2=for less than a minute }, require("Storage").readJSON("widalarmeta.json",1) || {}); + function getNextAlarm(date) { + const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); + WIDGETS["widalarmeta"].numActiveAlarms = alarms.length; + const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); + const eta = times.length > 0 ? Math.min.apply(null, times) : 0; + if (eta !== Number.POSITIVE_INFINITY) { + const idx = times.indexOf(eta); + const alarm = alarms[idx]; + delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory + return alarm; + } + } // getNextAlarm + function draw() { if (this.nextAlarm === undefined) { - const getNextAlarm = (date) => { - const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); - this.numActiveAlarms = alarms.length; - const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); - const eta = times.length > 0 ? Math.min.apply(null, times) : 0; - if (eta !== Number.POSITIVE_INFINITY) { - const idx = times.indexOf(eta); - const alarm = alarms[idx]; - delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory - return alarm; - } - }; // getNextAlarm - let alarm = getNextAlarm(); if (alarm === undefined) { // try again with next hour From b8e0222315e9ae5d5976d3c17e3ffac3759bd739 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 26 Feb 2023 10:06:43 +0100 Subject: [PATCH 22/61] widbatpc: Only redraw when values change --- apps/widbatpc/ChangeLog | 1 + apps/widbatpc/metadata.json | 2 +- apps/widbatpc/widget.js | 14 ++++++++++++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/apps/widbatpc/ChangeLog b/apps/widbatpc/ChangeLog index 97da2cba6..3592656a9 100644 --- a/apps/widbatpc/ChangeLog +++ b/apps/widbatpc/ChangeLog @@ -15,3 +15,4 @@ 0.16: Increase screen update rate when charging 0.17: Add option 'Remove Jitter'='Drop only' to prevent percentage from getting up again when not charging Add option to disable vibration when charger connects +0.18: Only redraw when values change diff --git a/apps/widbatpc/metadata.json b/apps/widbatpc/metadata.json index cb47475cb..d361da442 100644 --- a/apps/widbatpc/metadata.json +++ b/apps/widbatpc/metadata.json @@ -2,7 +2,7 @@ "id": "widbatpc", "name": "Battery Level Widget (with percentage)", "shortName": "Battery Widget", - "version": "0.17", + "version": "0.18", "description": "Show the current battery level and charging status in the top right of the clock, with charge percentage", "icon": "widget.png", "type": "widget", diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index 7f483c960..eff619f0e 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -86,7 +86,7 @@ return changed; } - function draw() { + function draw(fromIntervall) { // if hidden, don't draw if (!WIDGETS["batpc"].width) return; // else... @@ -103,6 +103,14 @@ l = prevMin; } } + + if (fromIntervall === true && this.prevLevel === l && this.prevCharging === Bangle.isCharging()) { + return; // unchanged, do nothing + } + + this.prevLevel = l; + this.prevCharging = Bangle.isCharging(); + const c = levelColor(l); if (Bangle.isCharging() && setting('charger')) { @@ -149,6 +157,8 @@ // can affect the width and mess with the whole widget layout setWidth(); g.clear(); + WIDGETS["batpc"].prevLevel = undefined; + WIDGETS["batpc"].prevCharging = undefined; Bangle.drawWidgets(); } @@ -173,7 +183,7 @@ if (on) update(); }); - var id = setInterval(()=>WIDGETS["batpc"].draw(), intervalLow); + var id = setInterval(()=>WIDGETS["batpc"].draw(true), intervalLow); WIDGETS["batpc"]={area:"tr",width:40,draw:draw,reload:reload}; setWidth(); From c835650c4422e7fc166e3e1ac0d8aae61bbd100c Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 26 Feb 2023 10:28:18 +0100 Subject: [PATCH 23/61] widbatpc fixes --- apps/widbatpc/widget.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/widbatpc/widget.js b/apps/widbatpc/widget.js index eff619f0e..b508cce8b 100644 --- a/apps/widbatpc/widget.js +++ b/apps/widbatpc/widget.js @@ -86,7 +86,7 @@ return changed; } - function draw(fromIntervall) { + function draw(fromInterval) { // if hidden, don't draw if (!WIDGETS["batpc"].width) return; // else... @@ -104,7 +104,7 @@ } } - if (fromIntervall === true && this.prevLevel === l && this.prevCharging === Bangle.isCharging()) { + if (fromInterval === true && this.prevLevel === l && this.prevCharging === Bangle.isCharging()) { return; // unchanged, do nothing } @@ -157,8 +157,6 @@ // can affect the width and mess with the whole widget layout setWidth(); g.clear(); - WIDGETS["batpc"].prevLevel = undefined; - WIDGETS["batpc"].prevCharging = undefined; Bangle.drawWidgets(); } From 9e7f22df008cc79587de22ab991473554f2bee7f Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 11:39:07 +0100 Subject: [PATCH 24/61] powermanager - Add powermanager.json to metadata --- apps/powermanager/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/powermanager/metadata.json b/apps/powermanager/metadata.json index 2229629a9..5487c2278 100644 --- a/apps/powermanager/metadata.json +++ b/apps/powermanager/metadata.json @@ -20,6 +20,7 @@ "data": [ {"name":"powermanager.hw.json"}, {"name":"powermanager.def.json"}, + {"name":"powermanager.json"}, {"name":"powermanager.log"} ] } From 11e31f4bbec74111ce5778257490ff86f8477a37 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sat, 25 Feb 2023 15:00:57 +0100 Subject: [PATCH 25/61] messagesoverlay - Initial fork of messages_light with drawing to overlay --- apps/messagesoverlay/ChangeLog | 1 + apps/messagesoverlay/README.md | 11 + apps/messagesoverlay/app-icon.js | 1 + apps/messagesoverlay/app-icon.png | Bin 0 -> 2841 bytes apps/messagesoverlay/app.png | Bin 0 -> 2300 bytes apps/messagesoverlay/boot.js | 7 + apps/messagesoverlay/lib.js | 438 +++++++++++++++++++++++++++++ apps/messagesoverlay/metadata.json | 18 ++ apps/messagesoverlay/settings.js | 1 + 9 files changed, 477 insertions(+) create mode 100644 apps/messagesoverlay/ChangeLog create mode 100644 apps/messagesoverlay/README.md create mode 100644 apps/messagesoverlay/app-icon.js create mode 100644 apps/messagesoverlay/app-icon.png create mode 100644 apps/messagesoverlay/app.png create mode 100644 apps/messagesoverlay/boot.js create mode 100644 apps/messagesoverlay/lib.js create mode 100644 apps/messagesoverlay/metadata.json create mode 100644 apps/messagesoverlay/settings.js diff --git a/apps/messagesoverlay/ChangeLog b/apps/messagesoverlay/ChangeLog new file mode 100644 index 000000000..da98bfbce --- /dev/null +++ b/apps/messagesoverlay/ChangeLog @@ -0,0 +1 @@ +0.01: Initial fork from messages_light \ No newline at end of file diff --git a/apps/messagesoverlay/README.md b/apps/messagesoverlay/README.md new file mode 100644 index 000000000..00fe39bd0 --- /dev/null +++ b/apps/messagesoverlay/README.md @@ -0,0 +1,11 @@ +# Messages app + +This app handles the display of messages and message notifications. + +It is a GUI replacement for the `messages` apps. + + +## Creator + +Rarder44 + diff --git a/apps/messagesoverlay/app-icon.js b/apps/messagesoverlay/app-icon.js new file mode 100644 index 000000000..7d1da35c9 --- /dev/null +++ b/apps/messagesoverlay/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA/4ACBIMQwhL/ABMBqoAEoALDioLFqgLDBQoABERIkEBZcFBY9QBYVe1QAB1YLGrSlC/YLGrYHCr4Lrr9drpLC1oLEAAN5rxKB/ILHEYV5EY4LIHYoLorRaBqoPCBYlfUoXrBYwGBrdeDIILIvXVBZFa1I+CBY/5BZIHBBwOq1ILGrXVvf//oLGq+trLLFBYVVvQxCBY9XJIQLCgILDHoVVoALHAAQLCgALHBQUAioKFqgLDEgwiDAH4AGA")) \ No newline at end of file diff --git a/apps/messagesoverlay/app-icon.png b/apps/messagesoverlay/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c9b4b62ac2eadee63a98380856f9337d0050578a GIT binary patch literal 2841 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 literal 0 HcmV?d00001 diff --git a/apps/messagesoverlay/boot.js b/apps/messagesoverlay/boot.js new file mode 100644 index 000000000..7731d608a --- /dev/null +++ b/apps/messagesoverlay/boot.js @@ -0,0 +1,7 @@ +//override require to filter require("message") +global.require_real=global.require; +global.require = (_require => file => { + if (file==="messages") file = "messagesoverlay"; + return _require(file); +})(require); + diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js new file mode 100644 index 000000000..167d68134 --- /dev/null +++ b/apps/messagesoverlay/lib.js @@ -0,0 +1,438 @@ +/* MESSAGES is a list of: + {id:int, + src, + title, + subject, + body, + sender, + tel:string, + new:true // not read yet + } +*/ + + +let lockListener; + +let LOG = function() { + print.apply(null, arguments); +}; + +let settings = (() => { + let tmp = {}; + tmp.NewEventFileName = "messagesoverlay.NewEvent.json"; + + tmp.fontSmall = "6x8"; + tmp.fontMedium = g.getFonts().includes("Vector") ? "Vector:16" : "6x8:2"; + tmp.fontBig = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; + tmp.fontLarge = g.getFonts().includes("6x15") ? "6x15:2" : "6x8:4"; + + tmp.colLock = g.theme.dark ? "#ff0000" : "#ff0000"; + + tmp.quiet = ((require('Storage').readJSON('settings.json', 1) || {}).quiet); + + return tmp; +})(); +let EventQueue = []; +let callInProgress = false; + + +let manageEvent = function(ovr, event) { + event.new = true; + + LOG("manageEvent"); + if (event.id == "call") { + showCall(ovr, event); + return; + } + switch (event.t) { + case "add": + EventQueue.unshift(event); + + if (!callInProgress) + showMessage(ovr, event); + break; + + case "modify": + let find = false; + EventQueue.forEach(element => { + if (element.id == event.id) { + find = true; + Object.assign(element, event); + } + }); + if (!find) + EventQueue.unshift(event); + + if (!callInProgress) + showMessage(ovr, event); + break; + + case "remove": + if (EventQueue.length == 0 && !callInProgress) + next(ovr); + + if (!callInProgress && EventQueue[0] !== undefined && EventQueue[0].id == event.id) + next(ovr); + + else { + let newEventQueue = []; + EventQueue.forEach(element => { + if (element.id != event.id) + newEventQueue.push(element); + }); + EventQueue = newEventQueue; + } + + break; + case "musicstate": + case "musicinfo": + + break; + } +}; + +let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ + ovr.setBgColor(ovr.theme.bg2); + ovr.clearRect(0,0,ovr.getWidth(),40); + + ovr.setColor(ovr.theme.fg2); + ovr.setFont(settings.fontSmall); + ovr.setFontAlign(0,-1); + ovr.drawString(src, ovr.getWidth()/2, 2); + + ovr.setFont(titleFont); + ovr.drawString(title, ovr.getWidth()/2, 12); + + let x = 150; + let y = 5; + let w = 22; + let h = 30; + var poly = [ + x,y+4, + x+4,y, + x+w-5,y, + x+w-1,y+4, + x+w-1,y+h-5, + x+w-5,y+h-1, + x+4,y+h-1, + x,y+h-5, + x,y+4 + ]; + ovr.setColor(ovr.theme.fg2); + ovr.drawPoly(poly,true); + ovr.drawString("X",160,10); + + ovr.setColor(iconcolor); + ovr.setBgColor("#fff"); + ovr.drawImage(icon,10,10); +}; + +let showMessage = function(ovr, msg) { + LOG("showMessage"); + LOG(msg); + ovr.setBgColor(settings.colBg); + + + if (typeof msg.CanScrollDown === "undefined") + msg.CanScrollDown = false; + if (typeof msg.CanScrollUp === "undefined") + msg.CanScrollUp = false; + + // Normal text message display + let title = msg.title, + titleFont = settings.fontLarge, + lines; + if (title) { + let w = ovr.getWidth() - 48; + if (ovr.setFont(titleFont).stringWidth(title) > w) + titleFont = settings.fontMedium; + if (ovr.setFont(titleFont).stringWidth(title) > w) { + lines = ovr.wrapString(title, w); + title = (lines.length > 2) ? lines.slice(0, 2).join("\n") + "..." : lines.join("\n"); + } + } + + drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg)); + + if (!settings.quiet && msg.new) { + msg.new = false; + Bangle.buzz(); + } + + PrintMessageStrings(ovr, msg); +}; + +let DrawLock = function(ovr) { + if (Bangle.isLocked()) + ovr.setColor(settings.colLock); + else + ovr.setColor(ovr.theme.bg2); + ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1); + ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2); + Bangle.setLCDOverlay(ovr,0,0); +}; + +let showCall = function(ovr, msg) { + LOG("showCall"); + LOG(msg); + + if (msg.t == "remove") { + LOG("hide call screen"); + next(ovr); //dont shift + return; + } + + callInProgress = true; + + let title = msg.title, + titleFont = settings.fontLarge, + lines; + if (title) { + let w = ovr.getWidth() - 48; + if (ovr.setFont(titleFont).stringWidth(title) > w) + titleFont = settings.fontMedium; + if (ovr.setFont(titleFont).stringWidth(title) > w) { + lines = ovr.wrapString(title, w); + title = (lines.length > 2) ? lines.slice(0, 2).join("\n") + "..." : lines.join("\n"); + } + } + + drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg)); + + StopBuzzCall(); + if (!settings.quiet) { + if (msg.new) { + msg.new = false; + CallBuzzTimer = setInterval(function() { + Bangle.buzz(500); + }, 1000); + + Bangle.buzz(500); + } + } + PrintMessageStrings(ovr, msg); +}; + +let next = function(ovr) { + LOG("next"); + StopBuzzCall(); + + if (!callInProgress) + EventQueue.shift(); + + callInProgress = false; + if (EventQueue.length == 0) { + LOG("no element in queue - closing"); + cleanup(); + return; + } + + showMessage(ovr, EventQueue[0]); +}; + +let showMapMessage = function(ovr, msg) { + ovr.clearRect(Bangle.appRect); + PrintMessageStrings(ovr, { + body: "Not implemented!" + }); +}; + +let CallBuzzTimer = null; +let StopBuzzCall = function() { + if (CallBuzzTimer) { + clearInterval(CallBuzzTimer); + CallBuzzTimer = null; + } +}; + +let DrawTriangleUp = function(ovr) { + ovr.reset(); + ovr.fillPoly([169, 46, 164, 56, 174, 56]); +}; + +let DrawTriangleDown = function(ovr) { + ovr.reset(); + ovr.fillPoly([169, 170, 164, 160, 174, 160]); +}; + +let ScrollUp = function(ovr, msg) { + msg = EventQueue[0]; + + if (typeof msg.FirstLine === "undefined") + msg.FirstLine = 0; + if (typeof msg.CanScrollUp === "undefined") + msg.CanScrollUp = false; + + if (!msg.CanScrollUp) return; + + msg.FirstLine = msg.FirstLine > 0 ? msg.FirstLine - 1 : 0; + + PrintMessageStrings(ovr, msg); +}; + +let ScrollDown = function(ovr, msg) { + msg = EventQueue[0]; + if (typeof msg.FirstLine === "undefined") + msg.FirstLine = 0; + if (typeof msg.CanScrollDown === "undefined") + msg.CanScrollDown = false; + + if (!msg.CanScrollDown) return; + + msg.FirstLine = msg.FirstLine + 1; + PrintMessageStrings(ovr, msg); +}; + +let PrintMessageStrings = function(ovr, msg) { + let MyWrapString = function(str, maxWidth) { + str = str.replace("\r\n", "\n").replace("\r", "\n"); + return ovr.wrapString(str, maxWidth); + }; + + if (typeof msg.FirstLine === "undefined") msg.FirstLine = 0; + + let bodyFont = typeof msg.bodyFont === "undefined" ? settings.fontMedium : msg.bodyFont; + let Padding = 2; + if (typeof msg.lines === "undefined") { + ovr.setFont(bodyFont); + msg.lines = MyWrapString(msg.body, ovr.getWidth() - (Padding * 2)); + if (msg.lines.length <= 2) { + bodyFont = ovr.getFonts().includes("Vector") ? "Vector:20" : "6x8:3"; + ovr.setFont(bodyFont); + msg.lines = MyWrapString(msg.body, ovr.getWidth() - (Padding * 2)); + msg.bodyFont = bodyFont; + } + } + + let NumLines = 9; + let linesToPrint = (msg.lines.length > NumLines) ? msg.lines.slice(msg.FirstLine, msg.FirstLine + NumLines) : msg.lines; + + + let yText = 40; + + ovr.setBgColor(ovr.theme.bg); + ovr.clearRect(0, yText, 176, 176); + let xText = Padding; + yText += Padding; + ovr.setFont(bodyFont); + let HText = ovr.getFontHeight(); + + yText = ((176 - yText) / 2) - (linesToPrint.length * HText / 2) + yText; + + if (linesToPrint.length <= 2) { + ovr.setFontAlign(0, -1); + xText = ovr.getWidth() / 2; + } else + ovr.setFontAlign(-1, -1); + + + linesToPrint.forEach((line, i) => { + ovr.drawString(line, xText, yText + HText * i); + }); + + if (msg.FirstLine != 0) { + msg.CanScrollUp = true; + DrawTriangleUp(ovr); + } else + msg.CanScrollUp = false; + + if (msg.FirstLine + linesToPrint.length < msg.lines.length) { + msg.CanScrollDown = true; + DrawTriangleDown(ovr); + } else + msg.CanScrollDown = false; +}; + +let doubleTapUnlock = function(data) { + if (data.double) + { + Bangle.setLocked(false); + Bangle.setLCDPower(1); + } +}; + +let getTouchHandler = function(ovr){ + return (button, xy) => { + if (xy.y < 40){ + next(ovr); + } else if (xy.y < (ovr.getHeight() - 40)/2) { + ScrollUp(ovr); + } else { + ScrollDown(ovr); + } + }; +}; + +let touchHandler; + +let cleanup = function(){ + if (lockListener) { + Bangle.removeListener("lock", lockListener); + lockListener = undefined; + } + if (touchBack){ + Bangle["#ontouch"]=touchBack; + LOG("Restored touch handlers:", touchBack); + touchBack = undefined; + } + + Bangle.removeListener("tap", doubleTapUnlock); + if (touchHandler) Bangle.removeListener("touch", touchHandler); + Bangle.setLCDOverlay(); +}; + +let touchBack; + +let main = function(ovr, event) { + LOG("Main", event, settings); + if (!lockListener) { + lockListener = function (){ + DrawLock(ovr); + }; + Bangle.on('lock', lockListener); + } + + touchBack = Bangle["#ontouch"]; + Bangle.removeAllListeners("touch"); + + Bangle.on('tap', doubleTapUnlock); + if (touchHandler) Bangle.removeListener("touch",touchHandler); + touchHandler = getTouchHandler(ovr); + Bangle.on('touch', touchHandler); + + if (event !== undefined){ + manageEvent(ovr, event); + Bangle.setLCDPower(1); + DrawLock(ovr); + Bangle.setLCDOverlay(ovr,0,0); + } else { + LOG("No event given"); + cleanup(); + } +}; + +exports.pushMessage = function(event) { + if( event.id=="music") return require_real("messages").pushMessage(event); + + let ovr = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 4, { + msb: true + }); + + let _g = g; + g = ovr; + + ovr.theme = g.theme; + if(event.t=="remove") return; + main(ovr, event); + Bangle.setLCDOverlay(ovr, 0, 0); + + g = _g; +}; + + +//Call original message library +exports.clearAll = function() { return require_real("messages").clearAll();}; +exports.getMessages = function() { return require_real("messages").getMessages();}; +exports.status = function() { return require_real("messages").status();}; +exports.buzz = function() { return require_real("messages").buzz(msgSrc);}; +exports.stopBuzz = function() { return require_real("messages").stopBuzz();}; \ No newline at end of file diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json new file mode 100644 index 000000000..c1dc97bd9 --- /dev/null +++ b/apps/messagesoverlay/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "messagesoverlay", + "name": "Messages Overlay", + "version": "0.01", + "description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)", + "icon": "app.png", + "type": "app", + "tags": "tool,system", + "supports": ["BANGLEJS2"], + "dependencies" : { "messageicons":"module","messages":"app" }, + "readme": "README.md", + "storage": [ + {"name":"messagesoverlay.settings.js","url":"settings.js"}, + {"name":"messagesoverlay.img","url":"app-icon.js","evaluate":true}, + {"name":"messagesoverlay","url":"lib.js"}, + {"name":"messagesoverlay.boot.js","url":"boot.js"} + ] +} diff --git a/apps/messagesoverlay/settings.js b/apps/messagesoverlay/settings.js new file mode 100644 index 000000000..b7197c70a --- /dev/null +++ b/apps/messagesoverlay/settings.js @@ -0,0 +1 @@ +eval(require("Storage").read("messages.settings.js")); From 730da3f52dd8f9d11880fced58e35607a1f820c0 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 09:51:45 +0100 Subject: [PATCH 26/61] messagesoverlay - Show popup a litte smaller than full screen --- apps/messagesoverlay/lib.js | 63 ++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 167d68134..e79ab6264 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -10,6 +10,10 @@ } */ +const ovrx = 10; +const ovry = 10; +const ovrw = g.getWidth()-2*ovrx; +const ovrh = g.getHeight()-2*ovry; let lockListener; @@ -91,22 +95,7 @@ let manageEvent = function(ovr, event) { } }; -let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ - ovr.setBgColor(ovr.theme.bg2); - ovr.clearRect(0,0,ovr.getWidth(),40); - - ovr.setColor(ovr.theme.fg2); - ovr.setFont(settings.fontSmall); - ovr.setFontAlign(0,-1); - ovr.drawString(src, ovr.getWidth()/2, 2); - - ovr.setFont(titleFont); - ovr.drawString(title, ovr.getWidth()/2, 12); - - let x = 150; - let y = 5; - let w = 22; - let h = 30; +let roundedRect = function(ovr, x,y,w,h,filled){ var poly = [ x,y+4, x+4,y, @@ -118,13 +107,29 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ x,y+h-5, x,y+4 ]; - ovr.setColor(ovr.theme.fg2); ovr.drawPoly(poly,true); - ovr.drawString("X",160,10); + if (filled) ovr.fillPoly(poly,true); +}; + +let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ + ovr.setBgColor(ovr.theme.bg2); + ovr.clearRect(0,0,ovr.getWidth(),40); + + ovr.setColor(ovr.theme.fg2); + ovr.setFont(settings.fontSmall); + ovr.setFontAlign(0,-1); + ovr.drawString(src, (ovr.getWidth()-ovrx)/2, 2); + + ovr.setFont(titleFont); + ovr.drawString(title, (ovr.getWidth()-ovrx)/2, 12); + + ovr.setColor(ovr.theme.fg2); + roundedRect(ovr, ovr.getWidth()-26,5,22,30,false); + ovr.drawString("X",ovr.getWidth()-16,10); ovr.setColor(iconcolor); ovr.setBgColor("#fff"); - ovr.drawImage(icon,10,10); + ovr.drawImage(icon,8,8); }; let showMessage = function(ovr, msg) { @@ -169,7 +174,7 @@ let DrawLock = function(ovr) { ovr.setColor(ovr.theme.bg2); ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1); ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2); - Bangle.setLCDOverlay(ovr,0,0); + Bangle.setLCDOverlay(ovr,10,10); }; let showCall = function(ovr, msg) { @@ -188,7 +193,7 @@ let showCall = function(ovr, msg) { titleFont = settings.fontLarge, lines; if (title) { - let w = ovr.getWidth() - 48; + let w = ovr.getWidth() - 40; if (ovr.setFont(titleFont).stringWidth(title) > w) titleFont = settings.fontMedium; if (ovr.setFont(titleFont).stringWidth(title) > w) { @@ -304,20 +309,20 @@ let PrintMessageStrings = function(ovr, msg) { } } - let NumLines = 9; + let NumLines = 7; let linesToPrint = (msg.lines.length > NumLines) ? msg.lines.slice(msg.FirstLine, msg.FirstLine + NumLines) : msg.lines; let yText = 40; ovr.setBgColor(ovr.theme.bg); - ovr.clearRect(0, yText, 176, 176); + ovr.clearRect(0, yText, ovrw, ovrh); let xText = Padding; yText += Padding; ovr.setFont(bodyFont); let HText = ovr.getFontHeight(); - yText = ((176 - yText) / 2) - (linesToPrint.length * HText / 2) + yText; + yText = ((ovrh - yText) / 2) - (linesToPrint.length * HText / 2) + yText; if (linesToPrint.length <= 2) { ovr.setFontAlign(0, -1); @@ -353,9 +358,9 @@ let doubleTapUnlock = function(data) { let getTouchHandler = function(ovr){ return (button, xy) => { - if (xy.y < 40){ + if (xy.y < ovry + 40){ next(ovr); - } else if (xy.y < (ovr.getHeight() - 40)/2) { + } else if (xy.y < (ovry + ovr.getHeight() - 40)/2) { ScrollUp(ovr); } else { ScrollDown(ovr); @@ -404,7 +409,7 @@ let main = function(ovr, event) { manageEvent(ovr, event); Bangle.setLCDPower(1); DrawLock(ovr); - Bangle.setLCDOverlay(ovr,0,0); + Bangle.setLCDOverlay(ovr,10,10); } else { LOG("No event given"); cleanup(); @@ -414,7 +419,7 @@ let main = function(ovr, event) { exports.pushMessage = function(event) { if( event.id=="music") return require_real("messages").pushMessage(event); - let ovr = Graphics.createArrayBuffer(g.getWidth(), g.getHeight(), 4, { + let ovr = Graphics.createArrayBuffer(ovrw, ovrh, 4, { msb: true }); @@ -424,7 +429,7 @@ exports.pushMessage = function(event) { ovr.theme = g.theme; if(event.t=="remove") return; main(ovr, event); - Bangle.setLCDOverlay(ovr, 0, 0); + Bangle.setLCDOverlay(ovr, 10, 10); g = _g; }; From a9fd2420e29dd12a37f06e1e2d52bfd2670ce6b8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 10:19:31 +0100 Subject: [PATCH 27/61] messagesoverlay - Stop swipes and drags interacting with the running app --- apps/messagesoverlay/lib.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index e79ab6264..c64a23327 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -377,9 +377,16 @@ let cleanup = function(){ } if (touchBack){ Bangle["#ontouch"]=touchBack; - LOG("Restored touch handlers:", touchBack); touchBack = undefined; } + if (swipeBack){ + Bangle["#onswipe"]=swipeBack; + swipeBack = undefined; + } + if (dragBack){ + Bangle["#ondrag"]=dragBack; + dragBack = undefined; + } Bangle.removeListener("tap", doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch", touchHandler); @@ -387,6 +394,8 @@ let cleanup = function(){ }; let touchBack; +let swipeBack; +let dragBack; let main = function(ovr, event) { LOG("Main", event, settings); @@ -399,6 +408,10 @@ let main = function(ovr, event) { touchBack = Bangle["#ontouch"]; Bangle.removeAllListeners("touch"); + swipeBack = Bangle["#onswipe"]; + Bangle.removeAllListeners("swipe"); + dragBack = Bangle["#ondrag"]; + Bangle.removeAllListeners("drag"); Bangle.on('tap', doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch",touchHandler); From 8a3ab237fc85fb4681771c647b1c00b37e880993 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 10:25:29 +0100 Subject: [PATCH 28/61] messagesoverlay - Refactor backing up and restoring handlers --- apps/messagesoverlay/lib.js | 40 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index c64a23327..c36bfff51 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -370,32 +370,33 @@ let getTouchHandler = function(ovr){ let touchHandler; +let restoreHandler = function(event){ + if (backup[event]){ + Bangle["#on" + event]=backup[event]; + backup[event] = undefined; + } +}; + +let backupHandler = function(event){ + backup[event] = Bangle["#on" + event]; + Bangle.removeAllListeners(event); +}; + let cleanup = function(){ if (lockListener) { Bangle.removeListener("lock", lockListener); lockListener = undefined; } - if (touchBack){ - Bangle["#ontouch"]=touchBack; - touchBack = undefined; - } - if (swipeBack){ - Bangle["#onswipe"]=swipeBack; - swipeBack = undefined; - } - if (dragBack){ - Bangle["#ondrag"]=dragBack; - dragBack = undefined; - } + restoreHandler("touch"); + restoreHandler("swipe"); + restoreHandler("drag"); Bangle.removeListener("tap", doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch", touchHandler); Bangle.setLCDOverlay(); }; -let touchBack; -let swipeBack; -let dragBack; +let backup = {}; let main = function(ovr, event) { LOG("Main", event, settings); @@ -406,12 +407,9 @@ let main = function(ovr, event) { Bangle.on('lock', lockListener); } - touchBack = Bangle["#ontouch"]; - Bangle.removeAllListeners("touch"); - swipeBack = Bangle["#onswipe"]; - Bangle.removeAllListeners("swipe"); - dragBack = Bangle["#ondrag"]; - Bangle.removeAllListeners("drag"); + backupHandler("touch"); + backupHandler("swipe"); + backupHandler("drag"); Bangle.on('tap', doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch",touchHandler); From e5352839c0550887ac44d63d946f3cdcbd340b94 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 10:43:46 +0100 Subject: [PATCH 29/61] messagesoverlay - Use only theme colors --- apps/messagesoverlay/lib.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index c36bfff51..7b207785b 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -30,8 +30,6 @@ let settings = (() => { tmp.fontBig = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; tmp.fontLarge = g.getFonts().includes("6x15") ? "6x15:2" : "6x8:4"; - tmp.colLock = g.theme.dark ? "#ff0000" : "#ff0000"; - tmp.quiet = ((require('Storage').readJSON('settings.json', 1) || {}).quiet); return tmp; @@ -169,9 +167,9 @@ let showMessage = function(ovr, msg) { let DrawLock = function(ovr) { if (Bangle.isLocked()) - ovr.setColor(settings.colLock); + ovr.setColor(ovr.theme.fgH); else - ovr.setColor(ovr.theme.bg2); + ovr.setColor(ovr.theme.fg); ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1); ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2); Bangle.setLCDOverlay(ovr,10,10); From f055b642a93cd064b6c30e0315c8f5ea551a148b Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 11:03:25 +0100 Subject: [PATCH 30/61] messagesoverlay - Fix scrolling --- apps/messagesoverlay/lib.js | 145 +++++++++++++++++++----------------- 1 file changed, 78 insertions(+), 67 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 7b207785b..fab4709d4 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -18,12 +18,11 @@ const ovrh = g.getHeight()-2*ovry; let lockListener; let LOG = function() { - print.apply(null, arguments); + //print.apply(null, arguments); }; let settings = (() => { let tmp = {}; - tmp.NewEventFileName = "messagesoverlay.NewEvent.json"; tmp.fontSmall = "6x8"; tmp.fontMedium = g.getFonts().includes("Vector") ? "Vector:16" : "6x8:2"; @@ -34,9 +33,9 @@ let settings = (() => { return tmp; })(); -let EventQueue = []; -let callInProgress = false; +let eventQueue = []; +let callInProgress = false; let manageEvent = function(ovr, event) { event.new = true; @@ -48,7 +47,7 @@ let manageEvent = function(ovr, event) { } switch (event.t) { case "add": - EventQueue.unshift(event); + eventQueue.unshift(event); if (!callInProgress) showMessage(ovr, event); @@ -56,33 +55,33 @@ let manageEvent = function(ovr, event) { case "modify": let find = false; - EventQueue.forEach(element => { + eventQueue.forEach(element => { if (element.id == event.id) { find = true; Object.assign(element, event); } }); if (!find) - EventQueue.unshift(event); + eventQueue.unshift(event); if (!callInProgress) showMessage(ovr, event); break; case "remove": - if (EventQueue.length == 0 && !callInProgress) + if (eventQueue.length == 0 && !callInProgress) next(ovr); - if (!callInProgress && EventQueue[0] !== undefined && EventQueue[0].id == event.id) + if (!callInProgress && eventQueue[0] !== undefined && eventQueue[0].id == event.id) next(ovr); else { - let newEventQueue = []; - EventQueue.forEach(element => { + let neweventQueue = []; + eventQueue.forEach(element => { if (element.id != event.id) - newEventQueue.push(element); + neweventQueue.push(element); }); - EventQueue = newEventQueue; + eventQueue = neweventQueue; } break; @@ -132,14 +131,13 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ let showMessage = function(ovr, msg) { LOG("showMessage"); - LOG(msg); ovr.setBgColor(settings.colBg); - if (typeof msg.CanScrollDown === "undefined") - msg.CanScrollDown = false; - if (typeof msg.CanScrollUp === "undefined") - msg.CanScrollUp = false; + if (typeof msg.CanscrollDown === "undefined") + msg.CanscrollDown = false; + if (typeof msg.CanscrollUp === "undefined") + msg.CanscrollUp = false; // Normal text message display let title = msg.title, @@ -162,10 +160,10 @@ let showMessage = function(ovr, msg) { Bangle.buzz(); } - PrintMessageStrings(ovr, msg); + drawMessage(ovr, msg); }; -let DrawLock = function(ovr) { +let drawBorder = function(ovr) { if (Bangle.isLocked()) ovr.setColor(ovr.theme.fgH); else @@ -202,91 +200,92 @@ let showCall = function(ovr, msg) { drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg)); - StopBuzzCall(); + stopCallBuzz(); if (!settings.quiet) { if (msg.new) { msg.new = false; - CallBuzzTimer = setInterval(function() { + callBuzzTimer = setInterval(function() { Bangle.buzz(500); }, 1000); Bangle.buzz(500); } } - PrintMessageStrings(ovr, msg); + drawMessage(ovr, msg); }; let next = function(ovr) { LOG("next"); - StopBuzzCall(); + stopCallBuzz(); if (!callInProgress) - EventQueue.shift(); + eventQueue.shift(); callInProgress = false; - if (EventQueue.length == 0) { + if (eventQueue.length == 0) { LOG("no element in queue - closing"); cleanup(); return; } - showMessage(ovr, EventQueue[0]); + showMessage(ovr, eventQueue[0]); }; let showMapMessage = function(ovr, msg) { ovr.clearRect(Bangle.appRect); - PrintMessageStrings(ovr, { + drawMessage(ovr, { body: "Not implemented!" }); }; -let CallBuzzTimer = null; -let StopBuzzCall = function() { - if (CallBuzzTimer) { - clearInterval(CallBuzzTimer); - CallBuzzTimer = null; +let callBuzzTimer = null; +let stopCallBuzz = function() { + if (callBuzzTimer) { + clearInterval(callBuzzTimer); + callBuzzTimer = null; } }; -let DrawTriangleUp = function(ovr) { +let drawTriangleUp = function(ovr) { ovr.reset(); - ovr.fillPoly([169, 46, 164, 56, 174, 56]); + ovr.fillPoly([ovr.getWidth()-9, 46,ovr.getWidth()-14, 56,ovr.getWidth()-4, 56]); }; -let DrawTriangleDown = function(ovr) { +let drawTriangleDown = function(ovr) { ovr.reset(); - ovr.fillPoly([169, 170, 164, 160, 174, 160]); + ovr.fillPoly([ovr.getWidth()-9, ovr.getHeight()-6, ovr.getWidth()-14, ovr.getHeight()-16, ovr.getWidth()-4, ovr.getHeight()-16]); }; -let ScrollUp = function(ovr, msg) { - msg = EventQueue[0]; - +let scrollUp = function(ovr) { + msg = eventQueue[0]; + LOG("up", msg); if (typeof msg.FirstLine === "undefined") msg.FirstLine = 0; - if (typeof msg.CanScrollUp === "undefined") - msg.CanScrollUp = false; + if (typeof msg.CanscrollUp === "undefined") + msg.CanscrollUp = false; - if (!msg.CanScrollUp) return; + if (!msg.CanscrollUp) return; msg.FirstLine = msg.FirstLine > 0 ? msg.FirstLine - 1 : 0; - PrintMessageStrings(ovr, msg); + drawMessage(ovr, msg); }; -let ScrollDown = function(ovr, msg) { - msg = EventQueue[0]; +let scrollDown = function(ovr) { + msg = eventQueue[0]; + LOG("down", msg); if (typeof msg.FirstLine === "undefined") msg.FirstLine = 0; - if (typeof msg.CanScrollDown === "undefined") - msg.CanScrollDown = false; + if (typeof msg.CanscrollDown === "undefined") + msg.CanscrollDown = false; - if (!msg.CanScrollDown) return; + if (!msg.CanscrollDown) return; msg.FirstLine = msg.FirstLine + 1; - PrintMessageStrings(ovr, msg); + drawMessage(ovr, msg); }; -let PrintMessageStrings = function(ovr, msg) { +let drawMessage = function(ovr, msg) { let MyWrapString = function(str, maxWidth) { str = str.replace("\r\n", "\n").replace("\r", "\n"); return ovr.wrapString(str, maxWidth); @@ -295,7 +294,7 @@ let PrintMessageStrings = function(ovr, msg) { if (typeof msg.FirstLine === "undefined") msg.FirstLine = 0; let bodyFont = typeof msg.bodyFont === "undefined" ? settings.fontMedium : msg.bodyFont; - let Padding = 2; + let Padding = 3; if (typeof msg.lines === "undefined") { ovr.setFont(bodyFont); msg.lines = MyWrapString(msg.body, ovr.getWidth() - (Padding * 2)); @@ -308,13 +307,13 @@ let PrintMessageStrings = function(ovr, msg) { } let NumLines = 7; - let linesToPrint = (msg.lines.length > NumLines) ? msg.lines.slice(msg.FirstLine, msg.FirstLine + NumLines) : msg.lines; + let linesToPrint = (msg.lines.length > NumLines) ? msg.lines.slice(msg.FirstLine, msg.FirstLine + NumLines) : msg.lines; let yText = 40; ovr.setBgColor(ovr.theme.bg); - ovr.clearRect(0, yText, ovrw, ovrh); + ovr.clearRect(2, yText, ovrw-2, ovrh-2); let xText = Padding; yText += Padding; ovr.setFont(bodyFont); @@ -334,16 +333,17 @@ let PrintMessageStrings = function(ovr, msg) { }); if (msg.FirstLine != 0) { - msg.CanScrollUp = true; - DrawTriangleUp(ovr); + msg.CanscrollUp = true; + drawTriangleUp(ovr); } else - msg.CanScrollUp = false; + msg.CanscrollUp = false; if (msg.FirstLine + linesToPrint.length < msg.lines.length) { - msg.CanScrollDown = true; - DrawTriangleDown(ovr); + msg.CanscrollDown = true; + drawTriangleDown(ovr); } else - msg.CanScrollDown = false; + msg.CanscrollDown = false; + Bangle.setLCDOverlay(ovr,ovrx,ovry); }; let doubleTapUnlock = function(data) { @@ -354,19 +354,26 @@ let doubleTapUnlock = function(data) { } }; +let getSwipeHandler = function(ovr){ + return (lr, ud) => { + if (ud == 1) { + scrollUp(ovr); + } else if (ud == -1){ + scrollDown(ovr); + } + }; +}; + let getTouchHandler = function(ovr){ - return (button, xy) => { + return (_, xy) => { if (xy.y < ovry + 40){ next(ovr); - } else if (xy.y < (ovry + ovr.getHeight() - 40)/2) { - ScrollUp(ovr); - } else { - ScrollDown(ovr); } }; }; let touchHandler; +let swipeHandler; let restoreHandler = function(event){ if (backup[event]){ @@ -391,6 +398,7 @@ let cleanup = function(){ Bangle.removeListener("tap", doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch", touchHandler); + if (swipeHandler) Bangle.removeListener("swipe", swipeHandler); Bangle.setLCDOverlay(); }; @@ -400,7 +408,7 @@ let main = function(ovr, event) { LOG("Main", event, settings); if (!lockListener) { lockListener = function (){ - DrawLock(ovr); + drawBorder(ovr); }; Bangle.on('lock', lockListener); } @@ -411,13 +419,16 @@ let main = function(ovr, event) { Bangle.on('tap', doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch",touchHandler); + if (swipeHandler) Bangle.removeListener("swipe",swipeHandler); touchHandler = getTouchHandler(ovr); + swipeHandler = getSwipeHandler(ovr); Bangle.on('touch', touchHandler); + Bangle.on('swipe', swipeHandler); if (event !== undefined){ manageEvent(ovr, event); Bangle.setLCDPower(1); - DrawLock(ovr); + drawBorder(ovr); Bangle.setLCDOverlay(ovr,10,10); } else { LOG("No event given"); From 6944fcece4ff1213bdfb7758a7ddb44581f17adf Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 11:51:16 +0100 Subject: [PATCH 31/61] messagesoverlay - Remove unused icon --- apps/messagesoverlay/app-icon.js | 1 - apps/messagesoverlay/metadata.json | 1 - 2 files changed, 2 deletions(-) delete mode 100644 apps/messagesoverlay/app-icon.js diff --git a/apps/messagesoverlay/app-icon.js b/apps/messagesoverlay/app-icon.js deleted file mode 100644 index 7d1da35c9..000000000 --- a/apps/messagesoverlay/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEw4UA/4ACBIMQwhL/ABMBqoAEoALDioLFqgLDBQoABERIkEBZcFBY9QBYVe1QAB1YLGrSlC/YLGrYHCr4Lrr9drpLC1oLEAAN5rxKB/ILHEYV5EY4LIHYoLorRaBqoPCBYlfUoXrBYwGBrdeDIILIvXVBZFa1I+CBY/5BZIHBBwOq1ILGrXVvf//oLGq+trLLFBYVVvQxCBY9XJIQLCgILDHoVVoALHAAQLCgALHBQUAioKFqgLDEgwiDAH4AGA")) \ No newline at end of file diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index c1dc97bd9..4b9966adb 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -11,7 +11,6 @@ "readme": "README.md", "storage": [ {"name":"messagesoverlay.settings.js","url":"settings.js"}, - {"name":"messagesoverlay.img","url":"app-icon.js","evaluate":true}, {"name":"messagesoverlay","url":"lib.js"}, {"name":"messagesoverlay.boot.js","url":"boot.js"} ] From 86fce14cc62bb35dbd5a797182a92d9ca899c3f7 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 11:55:18 +0100 Subject: [PATCH 32/61] messagesoverlay - Set type to bootloader --- apps/messagesoverlay/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index 4b9966adb..7474cf4c1 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -4,7 +4,7 @@ "version": "0.01", "description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)", "icon": "app.png", - "type": "app", + "type": "bootloader", "tags": "tool,system", "supports": ["BANGLEJS2"], "dependencies" : { "messageicons":"module","messages":"app" }, From 72d440a20ca2d0e176e370ed864ada9b760cbe34 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 13:07:00 +0100 Subject: [PATCH 33/61] messagesoverlay - Adds screenshots and more README --- apps/messagesoverlay/README.md | 14 ++++++++++---- apps/messagesoverlay/metadata.json | 3 ++- apps/messagesoverlay/screen_call.png | Bin 0 -> 3778 bytes apps/messagesoverlay/screen_message.png | Bin 0 -> 4510 bytes 4 files changed, 12 insertions(+), 5 deletions(-) create mode 100644 apps/messagesoverlay/screen_call.png create mode 100644 apps/messagesoverlay/screen_message.png diff --git a/apps/messagesoverlay/README.md b/apps/messagesoverlay/README.md index 00fe39bd0..aa4c0d49e 100644 --- a/apps/messagesoverlay/README.md +++ b/apps/messagesoverlay/README.md @@ -1,11 +1,17 @@ -# Messages app +# Messages overlay app -This app handles the display of messages and message notifications. +This app handles the display of messages and message notifications as an overlay pop up. -It is a GUI replacement for the `messages` apps. +It is a GUI replacement for the `messages` apps. +Messages are ephemeral and not stored on the Bangle. + +## Usage + +Close app by tapping the X and scroll by swiping. The border of the pop up changes color if the Bangle is locked. The color depends on your currently active theme. ## Creator -Rarder44 +[halemmerich](https://github.com/halemmerich) +Forked from messages_light by Rarder44 diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index 7474cf4c1..9efe95d26 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -13,5 +13,6 @@ {"name":"messagesoverlay.settings.js","url":"settings.js"}, {"name":"messagesoverlay","url":"lib.js"}, {"name":"messagesoverlay.boot.js","url":"boot.js"} - ] + ], + "screenshots": [{"url":"screen_call.png"} ,{"url":"screen_message.png"} ] } diff --git a/apps/messagesoverlay/screen_call.png b/apps/messagesoverlay/screen_call.png new file mode 100644 index 0000000000000000000000000000000000000000..45326b37ee8a68a5f8c011537549cfd8ce7d8c0a GIT binary patch literal 3778 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 literal 0 HcmV?d00001 diff --git a/apps/messagesoverlay/screen_message.png b/apps/messagesoverlay/screen_message.png new file mode 100644 index 0000000000000000000000000000000000000000..f3cc3b6e52ed0d643a34fc9d81d44e06a493205d GIT binary patch literal 4510 zcmV;P5n=9$P)YMf0?CTAFbf057&J_?2ZB*k8^a(4 zV9cmQO>GzeV?||ZvWAFb0S2IF=j}|^B|g|wQmWv; z`eR^b4A@wMxVr~ZL8+GX!1g0Z6H)+Qa=@$nR_%6hWd|L8Tg*ML2UgG3ZTE&qaZZ$Jp7>KsgZ z0GAtuP!Q*VI0R<<34O1|pbap(d5V!KY3gWhQ zi6R89eT%Wh(yBuxAXeJ&J`lH7*exwPlmp@(;8icI9JmRHdwO0e5c{)i^!M0nG*zaC zU*@*8mly7#Z(cY=xh05aqYbI4;hG1DBfHE6;Zssh3fR^$_0kA?tzf(ZN-~X!y z@sGd$41%~Ncti8;rPHB3JQ(L39M8t_>a$JQP;5E?W*scBsPic=E1`Uvi9d7O+6u(} zTchM0K2WVQ^>MjgJS}{NB0@qASPO1$9kCD}Q|g=-%a$_glm7yC#1d3%Vb z)KjJED!Dn_I&%4BZd+$~v(WLGPj8nL;#&{yMgZ|_?al3jAN^opuiX#e< z^17eknKd@t4!jZ|4h`I>7yh{Hly6#4In&#%B(FT7;P7J^;L9F0? z-&i1qBPX#*WH9G2h3#()F%JX4YHCss1o~SHMDV#-H*G%@%x}{|sLgGxCD_D>9S=s}1jg^%AI!Xk4ec zq`0q!(bS$Yx(fLgz%lT~D8%=_-{$+@&)7TpllnR;h?4-0$<&nhs?A`@MV(3^wy29n zUIqqm3cMPHP#Zo9;cFi#eUMs_K{=%F%|iS#=J87FNtNTaJye%Od+GN%=c?(`tD+Fp z%TjL}`mPqdv72&Nrly{fa%BsrhRZc;>*18E<;Jv5zrD2{ zvR9v`1#qvy8s|pd0hxQFLUpuw)u!sS?fw4uTjbom`ZN`QV}mssNY;srdXK5Gw}k? zn<1s)Eh$qY<|)zZ`Z|W3b91g&s_q=^@tsG0+Zw;99+-Z2r1a+(2`ob`PN09s@HwdATA~5X~~CM@y6U&I{m$uCvMTNPYwHB#5|k~?exaqX@YZf zyd`C7fs}I|PQN9~mDHVkKW3*NNj-3iLX_~hR%Ik81ou26>X}=&{k0ULh2FKajP#9f z(T0}V-%kbc8Uw9rfIq`#pV-(a1ftpgu|HEDZ2zbBMjJIQ?1ynY3 z1+Use9D*B#uuc|t*n@$CHUOZ4Sgk*Pk%#WX0~<5}EyM<10AtM0Fejv=*%)t(9V3-% zH}_nz&{1jm+FZYC@xTF|p40{Rj@fOCfgQYP++=>6=M9H2TIp0v>#5bmKB1}A0pSe| zrnDA4Uc7_&&_ejgPcdnZ2DL`po11I5RukJ(Q>%M!w=rFcJYd6vJl+(Myq!BbMfkUT=0GdV^%Q6Ab|DA*I5h3 zOh!xZn4{g5Nae5Gb|4DjQ;7gJ7lXLZycq)_@LqT^Pq!~x`N4jSH<6J`dwb=-l{nYaAXb3afp=rF zaM6`5n>$W>Z8f#0*u&;%?OX&NzuO}g#9ifscfMOq?E%i<55tZy+7{|vj!9=wpsI}& zf`AKnfr59(>~j1vh+xMb$v-)=pDBOw+g2M}9s%YQlOckE?aRaAu3*pxfR+EM4d#Wd z=e43Ty!_FbN-hXQG`A;5?=wXX-WKH`+B0VWw@qr`f!W19__|BI?oy=o6n(I<2D)qP z>2NpolaCETTjFsH_O52x{BUqx}9G=T9o0HFY8f|iNH5(c* zuzO(i!WZ5Q958MWN2ANV(Io>KiS|k5Z)?$~5%U*!d+L~j#!G?JE4oypD{*n|HbvpKPwGas=+mqCZ7zj4 z)@Z^$bUX37o?1)a;lgbwP70vXIfPrCoAVHGVy+V4%X#>EBn_8GFuDV|7=?(e8Y0gD zXm&IK?mL?&d^&G1q=88|Fo{68$Hpfy)b71zk3Bwm^y6tKd^eU`U8N6%D70SK58|Gq zF$lX-KDMN2HO3Cw#?b@U0)UgdOl@pC7{r$MY!~%hk6WVaIaM62HUND^vpRr>(ac%Ia+Dyaf~@(>yGLSnYXZV$`Jp+ z%o`!4$(07LbeR@9-IlqPOWSjI{@4Q`1>WPWe@w!`H9~=47TEJb022BOZY5wK+Q=Hc zZAl;&ZKj(nXnALjU?O)eT zJDa>Dc#c%g-kJDtPm|=f(pD?kOmGN7UC)RD8nVfY!A%c*QV4J+HLg?4hDGc{9Se1? zm3Fp8nVu%4RUW;cw_Z1pbaG3`e*S5p9{3uH3-1v(x*oU}-);?JiT3vFr|7vL{FOf> z11DmJ*YZa&`S1NH{!M4K)WUCJ5di<(>careNFeRV(z9pgK{D6uhS2<<)zq4S*Ym6~ zhfI}fTV99=$Bo5-)zo^@6u3~^b0e)YGY_6?jkY~BNM1C>uUZ7Sy}?Vr1t4)?gkANs z?_6I?8fF;%mb6iKBI+E8@CRp>73^+!IXQ=y2}QRSPaVqC-jfS_hoRo%mIwp*Gd=?ksSK+Yb!qOon zE|5!Jc|G;BHP__n{*4Y~e|DJuZuk3MoWY%s;6s0@GZ||A;Y&dajvnny8N43fg_5y@ z!>6Yi06fY4dR&v)xh;PP2SM;2$#{;fW}Qu4(4iBlo75^PbSY?3`s3I!(&uVU-4&aY`Xix@BlbXA?ON zcx$x2T-|U^?zP%HxS@08^2gjZNb%F$ezn#S=gtDAj`6p@077kHUwynB;Ee#bGzQGc zC(FHwt){AH*9%DQEuC9$Zap;*YIIrswxsCHixvWLjuNd!K3NGJFSm^;y|47Ew6^}5 z9LFtm#3dT>(*7TG7-19h0Mh+9(b;yZ!~@ST$a~vhaTFbKO30LZ&8fl{q8`}M0+WC- z(yTlvdXbx?<5YX)z%G{98o(F?Fsr-6iyyAQJ-Odpyl(_<+q(@?*QK`I96D2T4tG;} zx}*rnWQI96wtspx21my$rS+|;i(9U>E}8RMZ=oa3(L+}c=*Sir%aNA-_=~%)NP5ff z(8cS;-CFZw$^Nver=^a#Jsrd?&;Tb!*K;k=zMX*02uwD8@kw;8c)a9qEwr#Lw6m>1 zETun|yeBc@weZ5L}temF{Rcum Date: Sun, 26 Feb 2023 13:09:36 +0100 Subject: [PATCH 34/61] messagesoverlay - Tweak font sizes and positions --- apps/messagesoverlay/lib.js | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index fab4709d4..8ba1a17a3 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -25,9 +25,9 @@ let settings = (() => { let tmp = {}; tmp.fontSmall = "6x8"; - tmp.fontMedium = g.getFonts().includes("Vector") ? "Vector:16" : "6x8:2"; - tmp.fontBig = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; - tmp.fontLarge = g.getFonts().includes("6x15") ? "6x15:2" : "6x8:4"; + tmp.fontMedium = "Vector:16"; + tmp.fontBig = "Vector:20"; + tmp.fontLarge = "Vector:30"; tmp.quiet = ((require('Storage').readJSON('settings.json', 1) || {}).quiet); @@ -110,22 +110,26 @@ let roundedRect = function(ovr, x,y,w,h,filled){ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ ovr.setBgColor(ovr.theme.bg2); - ovr.clearRect(0,0,ovr.getWidth(),40); + ovr.clearRect(0,0,ovr.getWidth(),39); ovr.setColor(ovr.theme.fg2); ovr.setFont(settings.fontSmall); ovr.setFontAlign(0,-1); - ovr.drawString(src, (ovr.getWidth()-ovrx)/2, 2); + ovr.drawString(src, (ovr.getWidth()+35-26)/2, 2); + ovr.setFontAlign(0,0); ovr.setFont(titleFont); - ovr.drawString(title, (ovr.getWidth()-ovrx)/2, 12); + ovr.drawString(title, (ovr.getWidth()+35-26)/2, 39/2 + 6); ovr.setColor(ovr.theme.fg2); - roundedRect(ovr, ovr.getWidth()-26,5,22,30,false); - ovr.drawString("X",ovr.getWidth()-16,10); + ovr.setFont(settings.fontMedium); + roundedRect(ovr, ovr.getWidth()-26,5,22,30,false); + ovr.drawString("X",ovr.getWidth()-14,21); + + ovr.setColor("#888"); + roundedRect(ovr, 5,5,30,30,true); ovr.setColor(iconcolor); - ovr.setBgColor("#fff"); ovr.drawImage(icon,8,8); }; @@ -144,7 +148,7 @@ let showMessage = function(ovr, msg) { titleFont = settings.fontLarge, lines; if (title) { - let w = ovr.getWidth() - 48; + let w = ovr.getWidth() - 35 - 26; if (ovr.setFont(titleFont).stringWidth(title) > w) titleFont = settings.fontMedium; if (ovr.setFont(titleFont).stringWidth(title) > w) { @@ -189,7 +193,7 @@ let showCall = function(ovr, msg) { titleFont = settings.fontLarge, lines; if (title) { - let w = ovr.getWidth() - 40; + let w = ovr.getWidth() - 35 -26; if (ovr.setFont(titleFont).stringWidth(title) > w) titleFont = settings.fontMedium; if (ovr.setFont(titleFont).stringWidth(title) > w) { @@ -313,6 +317,7 @@ let drawMessage = function(ovr, msg) { let yText = 40; ovr.setBgColor(ovr.theme.bg); + ovr.setColor(ovr.theme.fg); ovr.clearRect(2, yText, ovrw-2, ovrh-2); let xText = Padding; yText += Padding; @@ -321,7 +326,7 @@ let drawMessage = function(ovr, msg) { yText = ((ovrh - yText) / 2) - (linesToPrint.length * HText / 2) + yText; - if (linesToPrint.length <= 2) { + if (linesToPrint.length <= 3) { ovr.setFontAlign(0, -1); xText = ovr.getWidth() / 2; } else From 54e9704e3cb6d18843d6a6389bd62aabcf47c7a2 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 13:47:39 +0100 Subject: [PATCH 35/61] messagesoverlay - Tweak source and title texts --- apps/messagesoverlay/lib.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 8ba1a17a3..286e5e26f 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -115,11 +115,17 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ ovr.setColor(ovr.theme.fg2); ovr.setFont(settings.fontSmall); ovr.setFontAlign(0,-1); - ovr.drawString(src, (ovr.getWidth()+35-26)/2, 2); + + let textCenter = (ovr.getWidth()+35-26)/2; + + if (src) { + while (ovr.stringWidth(src) > ovr.getWidth()-80) src = src.substring(0,src.length-2); + ovr.drawString(src + "...", textCenter, 2); + } ovr.setFontAlign(0,0); ovr.setFont(titleFont); - ovr.drawString(title, (ovr.getWidth()+35-26)/2, 39/2 + 6); + if (title) ovr.drawString(title, textCenter, 39/2 + 6); ovr.setColor(ovr.theme.fg2); From 7ff5796fde259cb8c0048d7995eb04c2f8f501d9 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 14:05:01 +0100 Subject: [PATCH 36/61] powermanager - Catch the case of the wrapped function being a string --- apps/powermanager/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/powermanager/boot.js b/apps/powermanager/boot.js index 40487a5bf..f3e3f718f 100644 --- a/apps/powermanager/boot.js +++ b/apps/powermanager/boot.js @@ -77,7 +77,7 @@ let functions = {}; let wrapDeferred = ((o,t) => (a) => { - if (a == eval){ + if (a == eval || typeof a == "string") { return o.apply(this, arguments); } else { let wrapped = a; From c16a9b11033dc8b97fe4ad37c278d16ce799c65a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 15:23:41 +0100 Subject: [PATCH 37/61] messagesoverlay - Use less memory if messages are stacked --- apps/messagesoverlay/lib.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 286e5e26f..6a4dd7e26 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -411,6 +411,7 @@ let cleanup = function(){ if (touchHandler) Bangle.removeListener("touch", touchHandler); if (swipeHandler) Bangle.removeListener("swipe", swipeHandler); Bangle.setLCDOverlay(); + ovr = undefined; }; let backup = {}; @@ -447,12 +448,18 @@ let main = function(ovr, event) { } }; +let ovr; + exports.pushMessage = function(event) { if( event.id=="music") return require_real("messages").pushMessage(event); - let ovr = Graphics.createArrayBuffer(ovrw, ovrh, 4, { - msb: true - }); + if (!ovr) { + ovr = Graphics.createArrayBuffer(ovrw, ovrh, 4, { + msb: true + }); + } else { + ovr.clear(); + } let _g = g; g = ovr; From 3ef8ede109a0cf1f0044eed7f810e64cf8a76d42 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 15:53:00 +0100 Subject: [PATCH 38/61] messagesoverlay - Fix leaking memory --- apps/messagesoverlay/lib.js | 37 +++++++++++++++++-------------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 6a4dd7e26..e953022b3 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -76,12 +76,11 @@ let manageEvent = function(ovr, event) { next(ovr); else { - let neweventQueue = []; + eventQueue.length = 0; // empty existing queue eventQueue.forEach(element => { if (element.id != event.id) neweventQueue.push(element); }); - eventQueue = neweventQueue; } break; @@ -143,7 +142,6 @@ let showMessage = function(ovr, msg) { LOG("showMessage"); ovr.setBgColor(settings.colBg); - if (typeof msg.CanscrollDown === "undefined") msg.CanscrollDown = false; if (typeof msg.CanscrollUp === "undefined") @@ -214,6 +212,7 @@ let showCall = function(ovr, msg) { if (!settings.quiet) { if (msg.new) { msg.new = false; + if (callBuzzTimer) clearInterval(callBuzzTimer); callBuzzTimer = setInterval(function() { Bangle.buzz(500); }, 1000); @@ -252,7 +251,7 @@ let callBuzzTimer = null; let stopCallBuzz = function() { if (callBuzzTimer) { clearInterval(callBuzzTimer); - callBuzzTimer = null; + callBuzzTimer = undefined; } }; @@ -357,14 +356,6 @@ let drawMessage = function(ovr, msg) { Bangle.setLCDOverlay(ovr,ovrx,ovry); }; -let doubleTapUnlock = function(data) { - if (data.double) - { - Bangle.setLocked(false); - Bangle.setLCDPower(1); - } -}; - let getSwipeHandler = function(ovr){ return (lr, ud) => { if (ud == 1) { @@ -394,6 +385,7 @@ let restoreHandler = function(event){ }; let backupHandler = function(event){ + if (eventQueue.length > 1 && ovr) return; // do not backup, overlay is already up backup[event] = Bangle["#on" + event]; Bangle.removeAllListeners(event); }; @@ -407,9 +399,14 @@ let cleanup = function(){ restoreHandler("swipe"); restoreHandler("drag"); - Bangle.removeListener("tap", doubleTapUnlock); - if (touchHandler) Bangle.removeListener("touch", touchHandler); - if (swipeHandler) Bangle.removeListener("swipe", swipeHandler); + if (touchHandler) { + Bangle.removeListener("touch", touchHandler); + touchHandler = undefined; + } + if (swipeHandler) { + Bangle.removeListener("swipe", swipeHandler); + swipeHandler = undefined; + } Bangle.setLCDOverlay(); ovr = undefined; }; @@ -418,18 +415,17 @@ let backup = {}; let main = function(ovr, event) { LOG("Main", event, settings); + if (!lockListener) { lockListener = function (){ drawBorder(ovr); }; Bangle.on('lock', lockListener); } - backupHandler("touch"); backupHandler("swipe"); backupHandler("drag"); - Bangle.on('tap', doubleTapUnlock); if (touchHandler) Bangle.removeListener("touch",touchHandler); if (swipeHandler) Bangle.removeListener("swipe",swipeHandler); touchHandler = getTouchHandler(ovr); @@ -441,7 +437,10 @@ let main = function(ovr, event) { manageEvent(ovr, event); Bangle.setLCDPower(1); drawBorder(ovr); - Bangle.setLCDOverlay(ovr,10,10); + if (eventQueue.length>=1) + Bangle.setLCDOverlay(ovr,10,10); + else + Bangle.setLCDOverlay(); } else { LOG("No event given"); cleanup(); @@ -465,9 +464,7 @@ exports.pushMessage = function(event) { g = ovr; ovr.theme = g.theme; - if(event.t=="remove") return; main(ovr, event); - Bangle.setLCDOverlay(ovr, 10, 10); g = _g; }; From b14afaa891e0e826c451e5fec7fe4c7ee1e2a14f Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 17:00:48 +0100 Subject: [PATCH 39/61] messageoverlay - Fix call notification not being shown --- apps/messagesoverlay/lib.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index e953022b3..123a42def 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -109,7 +109,7 @@ let roundedRect = function(ovr, x,y,w,h,filled){ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ ovr.setBgColor(ovr.theme.bg2); - ovr.clearRect(0,0,ovr.getWidth(),39); + ovr.clearRect(2,2,ovr.getWidth()-3,37); ovr.setColor(ovr.theme.fg2); ovr.setFont(settings.fontSmall); @@ -434,13 +434,9 @@ let main = function(ovr, event) { Bangle.on('swipe', swipeHandler); if (event !== undefined){ + drawBorder(ovr); manageEvent(ovr, event); Bangle.setLCDPower(1); - drawBorder(ovr); - if (eventQueue.length>=1) - Bangle.setLCDOverlay(ovr,10,10); - else - Bangle.setLCDOverlay(); } else { LOG("No event given"); cleanup(); From 420c839a5be8584c37c3815d151070fd70272584 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 18:40:37 +0100 Subject: [PATCH 40/61] messagesoverlay - Add hint regarding wrong colors --- apps/messagesoverlay/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/messagesoverlay/README.md b/apps/messagesoverlay/README.md index aa4c0d49e..e267d4481 100644 --- a/apps/messagesoverlay/README.md +++ b/apps/messagesoverlay/README.md @@ -10,6 +10,9 @@ Messages are ephemeral and not stored on the Bangle. Close app by tapping the X and scroll by swiping. The border of the pop up changes color if the Bangle is locked. The color depends on your currently active theme. +## Firmware hint +Current stable firmware draws incorrect colors for emojis. Nightly firmware builds correct this. + ## Creator [halemmerich](https://github.com/halemmerich) From 0a9d8eb9b32b9ad3683aed03259a7676d99f1120 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 18:51:23 +0100 Subject: [PATCH 41/61] messagesoverlay - Fix quiet mode being ignored --- apps/messagesoverlay/lib.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 123a42def..80e79f2d7 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -21,6 +21,10 @@ let LOG = function() { //print.apply(null, arguments); }; +let isQuiet = function(){ + return (require('Storage').readJSON('setting.json', 1) || {}).quiet; +}; + let settings = (() => { let tmp = {}; @@ -29,8 +33,6 @@ let settings = (() => { tmp.fontBig = "Vector:20"; tmp.fontLarge = "Vector:30"; - tmp.quiet = ((require('Storage').readJSON('settings.json', 1) || {}).quiet); - return tmp; })(); @@ -163,7 +165,7 @@ let showMessage = function(ovr, msg) { drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg)); - if (!settings.quiet && msg.new) { + if (!isQuiet() && msg.new) { msg.new = false; Bangle.buzz(); } @@ -209,7 +211,7 @@ let showCall = function(ovr, msg) { drawScreen(ovr, title, titleFont, msg.src || /*LANG*/ "Message", require("messageicons").getColor(msg), require("messageicons").getImage(msg)); stopCallBuzz(); - if (!settings.quiet) { + if (!isQuiet()) { if (msg.new) { msg.new = false; if (callBuzzTimer) clearInterval(callBuzzTimer); From c184687089e71500a23dac2d8ff2789f90e9d6a8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 19:09:21 +0100 Subject: [PATCH 42/61] messagesoverlay - Do not light up LCD if quiet mode is on --- apps/messagesoverlay/lib.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 80e79f2d7..f77aa87e4 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -180,7 +180,8 @@ let drawBorder = function(ovr) { ovr.setColor(ovr.theme.fg); ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1); ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2); - Bangle.setLCDOverlay(ovr,10,10); + Bangle.setLCDOverlay(ovr,ovrx,ovry); + if (!isQuiet()) Bangle.setLCDPower(1); }; let showCall = function(ovr, msg) { @@ -356,6 +357,7 @@ let drawMessage = function(ovr, msg) { } else msg.CanscrollDown = false; Bangle.setLCDOverlay(ovr,ovrx,ovry); + if (!isQuiet()) Bangle.setLCDPower(1); }; let getSwipeHandler = function(ovr){ @@ -438,7 +440,6 @@ let main = function(ovr, event) { if (event !== undefined){ drawBorder(ovr); manageEvent(ovr, event); - Bangle.setLCDPower(1); } else { LOG("No event given"); cleanup(); From 16a3af8d1b9f28294adbc50fefee2920d915d178 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 19:22:11 +0100 Subject: [PATCH 43/61] messagesoverlay - Finetune fonts --- apps/messagesoverlay/lib.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index f77aa87e4..71926ce59 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -16,20 +16,22 @@ const ovrw = g.getWidth()-2*ovrx; const ovrh = g.getHeight()-2*ovry; let lockListener; +let quiet; let LOG = function() { //print.apply(null, arguments); }; let isQuiet = function(){ - return (require('Storage').readJSON('setting.json', 1) || {}).quiet; + if (quiet == undefined) quiet = (require('Storage').readJSON('setting.json', 1) || {}).quiet; + return quiet; }; let settings = (() => { let tmp = {}; tmp.fontSmall = "6x8"; - tmp.fontMedium = "Vector:16"; + tmp.fontMedium = "Vector:14"; tmp.fontBig = "Vector:20"; tmp.fontLarge = "Vector:30"; @@ -126,12 +128,13 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ ovr.setFontAlign(0,0); ovr.setFont(titleFont); - if (title) ovr.drawString(title, textCenter, 39/2 + 6); + if (title) ovr.drawString(title, textCenter, 38/2 + 5); ovr.setColor(ovr.theme.fg2); ovr.setFont(settings.fontMedium); roundedRect(ovr, ovr.getWidth()-26,5,22,30,false); + ovr.setFont("Vector:16"); ovr.drawString("X",ovr.getWidth()-14,21); ovr.setColor("#888"); @@ -244,7 +247,7 @@ let next = function(ovr) { }; let showMapMessage = function(ovr, msg) { - ovr.clearRect(Bangle.appRect); + ovr.clearRect(2,2,ovr.getWidth()-3,ovr.getHeight()-3); drawMessage(ovr, { body: "Not implemented!" }); @@ -326,7 +329,7 @@ let drawMessage = function(ovr, msg) { ovr.setBgColor(ovr.theme.bg); ovr.setColor(ovr.theme.fg); - ovr.clearRect(2, yText, ovrw-2, ovrh-2); + ovr.clearRect(2, yText, ovrw-3, ovrh-3); let xText = Padding; yText += Padding; ovr.setFont(bodyFont); @@ -413,6 +416,7 @@ let cleanup = function(){ } Bangle.setLCDOverlay(); ovr = undefined; + quiet = undefined; }; let backup = {}; From 22259d13bea6528dce4339bb73619c628ab76b84 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 26 Feb 2023 20:00:20 +0100 Subject: [PATCH 44/61] widalarmeta: Draw bell only once --- apps/widalarmeta/widget.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/apps/widalarmeta/widget.js b/apps/widalarmeta/widget.js index 8fab6fde7..750ae5d98 100644 --- a/apps/widalarmeta/widget.js +++ b/apps/widalarmeta/widget.js @@ -19,7 +19,7 @@ } } // getNextAlarm - function draw() { + function draw(fromInterval) { if (this.nextAlarm === undefined) { let alarm = getNextAlarm(); if (alarm === undefined) { @@ -58,10 +58,14 @@ if (drawSeconds) { calcWidth += 3*5; } + this.bellVisible = false; } else if (config.drawBell && this.numActiveAlarms > 0) { - // next alarm too far in future, draw only widalarm bell - g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y); calcWidth = 24; + // next alarm too far in future, draw only widalarm bell + if (this.bellVisible !== true || fromInterval !== true) { + g.reset().drawImage(atob("GBgBAAAAAAAAABgADhhwDDwwGP8YGf+YMf+MM//MM//MA//AA//AA//AA//AA//AA//AB//gD//wD//wAAAAADwAABgAAAAAAAAA"),this.x,this.y); + this.bellVisible = true; + } } if (this.width !== calcWidth) { @@ -81,8 +85,8 @@ clearTimeout(this.timeoutId); } this.timeoutId = setTimeout(()=>{ - this.timeoutId = undefined; - this.draw(); + WIDGETS["widalarmeta"].timeoutId = undefined; + WIDGETS["widalarmeta"].draw(true); }, timeout); } /* draw */ From f62da73c55ab4255624cad036e621e4ea49f250d Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 20:02:20 +0100 Subject: [PATCH 45/61] messagesoverlay - Remove unused settings --- apps/messagesoverlay/lib.js | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 71926ce59..c8fefc190 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -27,16 +27,12 @@ let isQuiet = function(){ return quiet; }; -let settings = (() => { - let tmp = {}; - - tmp.fontSmall = "6x8"; - tmp.fontMedium = "Vector:14"; - tmp.fontBig = "Vector:20"; - tmp.fontLarge = "Vector:30"; - - return tmp; -})(); +let settings = { + fontSmall:"6x8", + fontMedium:"Vector:14", + fontBig:"Vector:20", + fontLarge:"Vector:30", +}; let eventQueue = []; let callInProgress = false; @@ -145,7 +141,7 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ let showMessage = function(ovr, msg) { LOG("showMessage"); - ovr.setBgColor(settings.colBg); + ovr.setBgColor(ovr.theme.bg); if (typeof msg.CanscrollDown === "undefined") msg.CanscrollDown = false; From 54051d5ab1bde2d87bbb7f53c5d9b8ff89b02889 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 20:03:35 +0100 Subject: [PATCH 46/61] messagesoverlay - Do not add ... to every source --- apps/messagesoverlay/lib.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index c8fefc190..bb7580750 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -118,8 +118,10 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ let textCenter = (ovr.getWidth()+35-26)/2; if (src) { - while (ovr.stringWidth(src) > ovr.getWidth()-80) src = src.substring(0,src.length-2); - ovr.drawString(src + "...", textCenter, 2); + let shortened = src; + while (ovr.stringWidth(shortened) > ovr.getWidth()-80) shortened = shortened.substring(0,shortened.length-2); + if (shortened.length != src.length) shortened += "..."; + ovr.drawString(shortened, textCenter, 2); } ovr.setFontAlign(0,0); From 4ea368416d51c6ebfc8709a845244d7eb3e08575 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 21:17:58 +0100 Subject: [PATCH 47/61] messagesoverlay - Add low memory mode --- apps/messagesoverlay/README.md | 4 ++++ apps/messagesoverlay/lib.js | 28 ++++++++++++++++++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/apps/messagesoverlay/README.md b/apps/messagesoverlay/README.md index e267d4481..8ce1cc64d 100644 --- a/apps/messagesoverlay/README.md +++ b/apps/messagesoverlay/README.md @@ -13,6 +13,10 @@ Close app by tapping the X and scroll by swiping. The border of the pop up chang ## Firmware hint Current stable firmware draws incorrect colors for emojis. Nightly firmware builds correct this. +## Low memory mode + +If free memory is below 2000 blocks, the overlay automatically only uses 1 bit depth. Default uses roundabout 1300 blocks, while low memory mode uses about 600. + ## Creator [halemmerich](https://github.com/halemmerich) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index bb7580750..cc6b63176 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -14,6 +14,7 @@ const ovrx = 10; const ovry = 10; const ovrw = g.getWidth()-2*ovrx; const ovrh = g.getHeight()-2*ovry; +let _g = g; let lockListener; let quiet; @@ -37,6 +38,15 @@ let settings = { let eventQueue = []; let callInProgress = false; +let show = function(ovr){ + let img = ovr; + if (ovr.getBPP() == 1) { + img = ovr.asImage(); + img.palette = new Uint16Array([_g.theme.fg,_g.theme.bg]); + } + Bangle.setLCDOverlay(img, ovrx, ovry); +}; + let manageEvent = function(ovr, event) { event.new = true; @@ -137,7 +147,7 @@ let drawScreen = function(ovr, title, titleFont, src, iconcolor, icon){ ovr.setColor("#888"); roundedRect(ovr, 5,5,30,30,true); - ovr.setColor(iconcolor); + ovr.setColor(ovr.getBPP() != 1 ? iconcolor : ovr.theme.bg2); ovr.drawImage(icon,8,8); }; @@ -181,7 +191,7 @@ let drawBorder = function(ovr) { ovr.setColor(ovr.theme.fg); ovr.drawRect(0,0,ovr.getWidth()-1,ovr.getHeight()-1); ovr.drawRect(1,1,ovr.getWidth()-2,ovr.getHeight()-2); - Bangle.setLCDOverlay(ovr,ovrx,ovry); + show(ovr); if (!isQuiet()) Bangle.setLCDPower(1); }; @@ -357,7 +367,7 @@ let drawMessage = function(ovr, msg) { drawTriangleDown(ovr); } else msg.CanscrollDown = false; - Bangle.setLCDOverlay(ovr,ovrx,ovry); + show(ovr); if (!isQuiet()) Bangle.setLCDPower(1); }; @@ -453,18 +463,24 @@ let ovr; exports.pushMessage = function(event) { if( event.id=="music") return require_real("messages").pushMessage(event); + bpp = 4; + if (process.memory().free < 2000) bpp = 1; + if (!ovr) { - ovr = Graphics.createArrayBuffer(ovrw, ovrh, 4, { + ovr = Graphics.createArrayBuffer(ovrw, ovrh, bpp, { msb: true }); } else { ovr.clear(); } - let _g = g; g = ovr; - ovr.theme = g.theme; + if (bpp == 4) + ovr.theme = g.theme; + else + ovr.theme = { fg:0, bg:1, fg2:1, bg2:0, fgH:1, bgH:0 }; + main(ovr, event); g = _g; From 868e5edc49d26b861781c29f17652c62fc2664ca Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 26 Feb 2023 22:19:57 +0100 Subject: [PATCH 48/61] powermanager - Adds some todos to readme --- apps/powermanager/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/powermanager/README.md b/apps/powermanager/README.md index 043b5ca8c..804e986e7 100644 --- a/apps/powermanager/README.md +++ b/apps/powermanager/README.md @@ -19,6 +19,14 @@ You can switch on logging in the options to diagnose unexpected power use. Curre Do not use trace logging for extended time, it uses a lot of storage and can fill up the flash quite quick. +### TODO + +* Wrap functions given as strings to setTimeout/setInterval +* Handle eval in setTimeout/setInterval +* Track functions executed as event handlers +* Track buzzer +* Modify browser interface to estimate power use like widget does + ## Internals Battery calibration offset is set by writing `batFullVoltage` in setting.json From 9b46c300f2598b1910f499dc393c9175a1eb8a42 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 27 Feb 2023 09:38:22 +0000 Subject: [PATCH 49/61] oops --- apps/runplus/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/runplus/app.js b/apps/runplus/app.js index fef851602..9d7010e6c 100644 --- a/apps/runplus/app.js +++ b/apps/runplus/app.js @@ -63,7 +63,6 @@ function setStatus(running) { function onStartStop() { let running = !exs.state.active; let prepPromises = []; -https://github.com/espruino/BangleApps/pull/2600/conflict?name=apps%252Frunplus%252Fapp.js&ancestor_oid=15e0427592259f3112ee70d43bc7ce6fab20e1d8&base_oid=06270850f707ea94957a2990fb83425e7dc68d7f&head_oid=633e47983e015446796f69837501c8fc72255031 // start/stop recording // Do this first in case recorder needs to prompt for // an overwrite before we start tracking exstats From cc24cb5bb307441d3a2712c77b31ebada71bc2f3 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 27 Feb 2023 13:17:41 +0000 Subject: [PATCH 50/61] 0.07: Ensure barometer gets turned off after a few readings (isBarometerOn broken in 2v16) --- apps/widbaroalarm/ChangeLog | 1 + apps/widbaroalarm/metadata.json | 2 +- apps/widbaroalarm/widget.js | 54 ++++++++++++++++----------------- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/apps/widbaroalarm/ChangeLog b/apps/widbaroalarm/ChangeLog index 2dfe8336d..3b2ae75c4 100644 --- a/apps/widbaroalarm/ChangeLog +++ b/apps/widbaroalarm/ChangeLog @@ -7,3 +7,4 @@ Show difference of last measurement to pressure average of the the last three hours in the widget Only use valid pressure values 0.06: Fix exception +0.07: Ensure barometer gets turned off after a few readings (isBarometerOn broken in 2v16) diff --git a/apps/widbaroalarm/metadata.json b/apps/widbaroalarm/metadata.json index ba6c47b37..0a6ddd71e 100644 --- a/apps/widbaroalarm/metadata.json +++ b/apps/widbaroalarm/metadata.json @@ -2,7 +2,7 @@ "id": "widbaroalarm", "name": "Barometer Alarm Widget", "shortName": "Barometer Alarm", - "version": "0.06", + "version": "0.07", "description": "A widget that can alarm on when the pressure reaches defined thresholds.", "icon": "widget.png", "type": "widget", diff --git a/apps/widbaroalarm/widget.js b/apps/widbaroalarm/widget.js index d877c4384..d65a1c09c 100644 --- a/apps/widbaroalarm/widget.js +++ b/apps/widbaroalarm/widget.js @@ -211,6 +211,28 @@ function calculcate3hAveragePressure() { } } +function barometerPressureHandler(e) { + const MEDIANLENGTH = 20; + while (currentPressures.length > MEDIANLENGTH) + currentPressures.pop(); + + const pressure = e.pressure; + if (isValidPressureValue(pressure)) { + currentPressures.unshift(pressure); + median = currentPressures.slice().sort(); + + if (median.length > 10) { + var mid = median.length >> 1; + medianPressure = Math.round(E.sum(median.slice(mid - 4, mid + 5)) / 9); + if (medianPressure > 0) { + turnOff(); + draw(); + handlePressureValue(medianPressure); + } + } + } +} + /* turn on barometer power take multiple measurements @@ -219,37 +241,15 @@ function calculcate3hAveragePressure() { turn off barometer power */ function getPressureValue() { - if (stop) - return; - const MEDIANLENGTH = 20; + if (stop) return; Bangle.setBarometerPower(true, "widbaroalarm"); - Bangle.on('pressure', function(e) { - while (currentPressures.length > MEDIANLENGTH) - currentPressures.pop(); - - const pressure = e.pressure; - if (isValidPressureValue(pressure)) { - currentPressures.unshift(pressure); - median = currentPressures.slice().sort(); - - if (median.length > 10) { - var mid = median.length >> 1; - medianPressure = Math.round(E.sum(median.slice(mid - 4, mid + 5)) / 9); - if (medianPressure > 0) { - turnOff(); - draw(); - handlePressureValue(medianPressure); - } - } - } - }); - - setTimeout(function() { turnOff(); }, 30000); + Bangle.on('pressure', barometerPressureHandler); + setTimeout(turnOff, 30000); } function turnOff() { - if (Bangle.isBarometerOn()) - Bangle.setBarometerPower(false, "widbaroalarm"); + Bangle.removeListener('pressure', barometerPressureHandler); + Bangle.setBarometerPower(false, "widbaroalarm"); } function draw() { From a3addeebb28fc0e5bc463f79cc9ec6dccff48357 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Mon, 27 Feb 2023 19:43:42 +0100 Subject: [PATCH 51/61] widalarmeta: Fix when no alarms are present --- apps/widalarmeta/ChangeLog | 1 + apps/widalarmeta/metadata.json | 2 +- apps/widalarmeta/widget.js | 16 +++++++++------- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/apps/widalarmeta/ChangeLog b/apps/widalarmeta/ChangeLog index 4bcf6ec69..2b74766c8 100644 --- a/apps/widalarmeta/ChangeLog +++ b/apps/widalarmeta/ChangeLog @@ -8,3 +8,4 @@ 0.05: Convert Yes/No On/Off in settings to checkboxes 0.06: Remember next alarm to reduce calculation amount Redraw only every hour when no alarm in next 24h +0.07: Fix when no alarms are present diff --git a/apps/widalarmeta/metadata.json b/apps/widalarmeta/metadata.json index a3d2e8adb..6b3d8978b 100644 --- a/apps/widalarmeta/metadata.json +++ b/apps/widalarmeta/metadata.json @@ -2,7 +2,7 @@ "id": "widalarmeta", "name": "Alarm & Timer ETA", "shortName": "Alarm ETA", - "version": "0.06", + "version": "0.07", "description": "A widget that displays the time to the next Alarm or Timer in hours and minutes, maximum 24h (configurable).", "icon": "widget.png", "type": "widget", diff --git a/apps/widalarmeta/widget.js b/apps/widalarmeta/widget.js index 750ae5d98..0104eb3b1 100644 --- a/apps/widalarmeta/widget.js +++ b/apps/widalarmeta/widget.js @@ -9,13 +9,15 @@ function getNextAlarm(date) { const alarms = (require("Storage").readJSON("sched.json",1) || []).filter(alarm => alarm.on && alarm.hidden !== true); WIDGETS["widalarmeta"].numActiveAlarms = alarms.length; - const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); - const eta = times.length > 0 ? Math.min.apply(null, times) : 0; - if (eta !== Number.POSITIVE_INFINITY) { - const idx = times.indexOf(eta); - const alarm = alarms[idx]; - delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory - return alarm; + if (alarms.length > 0) { + const times = alarms.map(alarm => require("sched").getTimeToAlarm(alarm, date) || Number.POSITIVE_INFINITY); + const eta = Math.min.apply(null, times); + if (eta !== Number.POSITIVE_INFINITY) { + const idx = times.indexOf(eta); + const alarm = alarms[idx]; + delete alarm.msg; delete alarm.id; delete alarm.data; // free some memory + return alarm; + } } } // getNextAlarm From 63711f6a0ccfe003deb712ff5708f56e1aebf7db Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 27 Feb 2023 20:13:57 +0000 Subject: [PATCH 52/61] Revert "widlockunlock: convert to typescript" This reverts commit 6a21608322d2a605e273b8b74cf7227129d152ee. --- apps/widlockunlock/widget.js | 73 +++++++++++++++++++++--------------- apps/widlockunlock/widget.ts | 46 ----------------------- 2 files changed, 42 insertions(+), 77 deletions(-) delete mode 100644 apps/widlockunlock/widget.ts diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index e4569f511..f7f872a5e 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,34 +1,45 @@ -"use strict"; WIDGETS["lockunlock"] = { - area: (function () { - var _a; - var settings = require("Storage") - .readJSON("lockunlock.settings.json", true) || {}; - return (_a = settings.location) !== null && _a !== void 0 ? _a : "tl"; - })(), - sortorder: 10, - width: 14, - draw: function (w) { - g.reset() - .drawImage(atob(Bangle.isLocked() - ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" - : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x + 1, w.y + 3); - }, + area: (() => { + const settings = require("Storage") + .readJSON("lockunlock.settings.json", true) || {}; + return settings.location || "tl"; + })(), + sortorder: 10, + width: 14, + draw: w => { + g.reset() + .drawImage( + atob(Bangle.isLocked() + ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" + : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), + w.x + 1, + w.y + 3 + ); + }, }; -Bangle.on("lock", function () { return Bangle.drawWidgets(); }); -Bangle.on("touch", function (_btn, e) { - var oversize = 5; - if (!e) - return; - var x = e.x, y = e.y; - var w = WIDGETS["lockunlock"]; - if (w.x - oversize <= x && x < w.x + 14 + oversize - && w.y - oversize <= y && y < w.y + 24 + oversize) { - Bangle.setLocked(true); - var backlightTimeout_1 = Bangle.getOptions().backlightTimeout; - Bangle.setOptions({ backlightTimeout: 100 }); - setTimeout(function () { - Bangle.setOptions({ backlightTimeout: backlightTimeout_1 }); - }, 300); - } +Bangle.on("lock", () => Bangle.drawWidgets()); + +Bangle.on('touch', (_btn, xy) => { + const oversize = 5; + + const w = WIDGETS.lockunlock; + + const x = xy.x; + const y = xy.y; + + if(w.x - oversize <= x && x < w.x + 14 + oversize + && w.y - oversize <= y && y < w.y + 24 + oversize) + { + Bangle.setLocked(true); + + const backlightTimeout = Bangle.getOptions().backlightTimeout; // ms + + // seems to be a race/if we don't give the firmware enough time, + // it won't timeout the backlight and we'll restore it in our setTimeout below + Bangle.setOptions({ backlightTimeout: 100 }); + + setTimeout(() => { + Bangle.setOptions({ backlightTimeout }); + }, 300); + } }); diff --git a/apps/widlockunlock/widget.ts b/apps/widlockunlock/widget.ts deleted file mode 100644 index 5dd1c93e9..000000000 --- a/apps/widlockunlock/widget.ts +++ /dev/null @@ -1,46 +0,0 @@ -WIDGETS["lockunlock"] = { - area: (() => { - const settings = require("Storage") - .readJSON("lockunlock.settings.json", true) || {}; - return settings.location ?? "tl"; - })(), - sortorder: 10, - width: 14, - draw: w => { - g.reset() - .drawImage( - atob(Bangle.isLocked() - ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" - : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), - w.x! + 1, - w.y! + 3 - ); - }, -}; - -Bangle.on("lock", () => Bangle.drawWidgets()); - -Bangle.on("touch", (_btn, e) => { - const oversize = 5; - - if (!e) return; - const { x, y } = e; - - const w = WIDGETS["lockunlock"]!; - - if(w.x! - oversize <= x && x < w.x! + 14 + oversize - && w.y! - oversize <= y && y < w.y! + 24 + oversize) - { - Bangle.setLocked(true); - - const { backlightTimeout } = Bangle.getOptions(); // ms - - // seems to be a race/if we don't give the firmware enough time, - // it won't timeout the backlight and we'll restore it in our setTimeout below - Bangle.setOptions({ backlightTimeout: 100 }); - - setTimeout(() => { - Bangle.setOptions({ backlightTimeout }); - }, 300); - } -}); From c4d571347134dfa9821362985567b184e47ef771 Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 27 Feb 2023 20:16:36 +0000 Subject: [PATCH 53/61] Revert "widlockunlock: setting for location" This reverts commit c84d3fa2c0a063e79a5a353d84e81a786938e6d2. --- apps/widlockunlock/metadata.json | 3 +-- apps/widlockunlock/settings.js | 29 ------------------------ apps/widlockunlock/settings.ts | 39 -------------------------------- apps/widlockunlock/widget.js | 6 +---- 4 files changed, 2 insertions(+), 75 deletions(-) delete mode 100644 apps/widlockunlock/settings.js delete mode 100644 apps/widlockunlock/settings.ts diff --git a/apps/widlockunlock/metadata.json b/apps/widlockunlock/metadata.json index daeefbc69..cc4fa76cd 100644 --- a/apps/widlockunlock/metadata.json +++ b/apps/widlockunlock/metadata.json @@ -8,7 +8,6 @@ "tags": "widget,lock", "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ - {"name":"widlockunlock.wid.js","url":"widget.js"}, - {"name":"widlockunlock.settings.js","url":"settings.js"} + {"name":"widlockunlock.wid.js","url":"widget.js"} ] } diff --git a/apps/widlockunlock/settings.js b/apps/widlockunlock/settings.js deleted file mode 100644 index 0c3a82c39..000000000 --- a/apps/widlockunlock/settings.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; -(function (back) { - var storage = require('Storage'); - var filename = 'lockunlock.settings.json'; - var settings = Object.assign(storage.readJSON(filename, true) || {}, { location: "tl" }); - var save = function () { - return storage.writeJSON(filename, settings); - }; - var locations = ["tl", "tr"]; - var menu = { - '': { 'title': 'Lock/Unlock' }, - '< Back': back, - 'Location': { - value: (function () { - var i = locations.indexOf(settings.location); - return i < 0 ? 0 : i; - })(), - min: 0, - max: locations.length - 1, - wrap: true, - format: function (v) { return locations[v]; }, - onchange: function (v) { - settings.location = locations[v]; - save(); - }, - }, - }; - E.showMenu(menu); -}); diff --git a/apps/widlockunlock/settings.ts b/apps/widlockunlock/settings.ts deleted file mode 100644 index b2b1dc02e..000000000 --- a/apps/widlockunlock/settings.ts +++ /dev/null @@ -1,39 +0,0 @@ -((back: () => void) => { - type Location = "tl" | "tr"; - type Settings = { - location: Location; - }; - - const storage = require('Storage'); - - const filename = 'lockunlock.settings.json'; - const settings: Settings = Object.assign( - storage.readJSON(filename, true) || {}, - { location: "tl" } - ); - - const save = () => - storage.writeJSON(filename, settings); - - const locations: Array = [ "tl", "tr" ]; - - const menu = { - '': { 'title': 'Lock/Unlock' }, - '< Back': back, - 'Location': { - value: (() => { - const i = locations.indexOf(settings.location); - return i < 0 ? 0 : i; - })(), - min: 0, - max: locations.length - 1, - wrap: true, - format: (v: number) => locations[v]!, - onchange: (v: number) => { - settings.location = locations[v]!; - save(); - }, - }, - }; - E.showMenu(menu); -}); diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index f7f872a5e..21461b4a5 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,9 +1,5 @@ WIDGETS["lockunlock"] = { - area: (() => { - const settings = require("Storage") - .readJSON("lockunlock.settings.json", true) || {}; - return settings.location || "tl"; - })(), + area: "tl", sortorder: 10, width: 14, draw: w => { From 96b8e9a3e83593ba0cbc78317d66152bdf2544bf Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Mon, 27 Feb 2023 20:19:47 +0000 Subject: [PATCH 54/61] Restore original widlockunlock object --- apps/widlockunlock/widget.js | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/apps/widlockunlock/widget.js b/apps/widlockunlock/widget.js index 21461b4a5..cfbbc87a3 100644 --- a/apps/widlockunlock/widget.js +++ b/apps/widlockunlock/widget.js @@ -1,18 +1,3 @@ -WIDGETS["lockunlock"] = { - area: "tl", - sortorder: 10, - width: 14, - draw: w => { - g.reset() - .drawImage( - atob(Bangle.isLocked() - ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" - : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), - w.x + 1, - w.y + 3 - ); - }, -}; Bangle.on("lock", () => Bangle.drawWidgets()); Bangle.on('touch', (_btn, xy) => { @@ -39,3 +24,6 @@ Bangle.on('touch', (_btn, xy) => { }, 300); } }); +WIDGETS["lockunlock"]={area:"tl",sortorder:10,width:14,draw:function(w) { + g.reset().drawImage(atob(Bangle.isLocked() ? "DBGBAAAA8DnDDCBCBP////////n/n/n//////z/A" : "DBGBAAAA8BnDDCBABP///8A8A8Y8Y8Y8A8A//z/A"), w.x+1, w.y+3); +}}; From 293b0d1b4394d770159a0b697170eb2281053b8f Mon Sep 17 00:00:00 2001 From: dapgo Date: Mon, 27 Feb 2023 21:36:54 +0100 Subject: [PATCH 55/61] tempmonitor v3 Added Stop/start recording, change BG color, filesize info. Pending long press events for v4 --- apps/tempmonitor/ChangeLog | 1 + apps/tempmonitor/README.md | 34 +++- apps/tempmonitor/bangle.js2_UI.png | Bin 0 -> 74846 bytes apps/tempmonitor/bangle.js_UI.png | Bin 0 -> 124186 bytes apps/tempmonitor/metadata.json | 2 +- apps/tempmonitor/tempmonitor.app.js | 263 +++++++++++++++++++++++----- apps/tempmonitor/tempmonitor.info | 2 +- 7 files changed, 249 insertions(+), 53 deletions(-) create mode 100644 apps/tempmonitor/bangle.js2_UI.png create mode 100644 apps/tempmonitor/bangle.js_UI.png diff --git a/apps/tempmonitor/ChangeLog b/apps/tempmonitor/ChangeLog index 99fe6a77d..af69e6e0a 100644 --- a/apps/tempmonitor/ChangeLog +++ b/apps/tempmonitor/ChangeLog @@ -1,2 +1,3 @@ 0.01: 1st version: saves values to csv 0.02: added HTML interface +0.03: Added Stop/start recording, change BG color, filesize info diff --git a/apps/tempmonitor/README.md b/apps/tempmonitor/README.md index a956f0e0f..21b570af9 100644 --- a/apps/tempmonitor/README.md +++ b/apps/tempmonitor/README.md @@ -9,6 +9,12 @@ Bangle JS1 ![](photo_banglejs1.jpg) +UI for bangleJS1 +![](bangle.js_UI.png) + +UI for bangleJS2 +![](bangle.js2_UI.png) + Screenshot BJS2 ![](ss_emul_bjs2.png) @@ -33,15 +39,31 @@ Download the CSV file and process in your favourite spreadsheet software ## Features -Colours, all inputs , graph, widgets loaded -Counter for Times Display +- Cross compatibility (JS1,JS2) and widgets compatibility +- BG/FG Colour, Export to file and counter of saved records per session +- File operations: Info, delete (no yet) +## Pending/future Features +- Buttons layout: btn txt(BJS1) , on screen button (BJS2) +- Long press touch to delete file (BJS1,BJS2) +- File operations: Delete -## Controls - -exit: left side +## Controls/UI + - Left area: Back/Exit/launcher + - BTN3 (long press)(BJS1): default Exit/kill app + - BTN1 (BJS2): "Launcher" / open "Messages" + - BTN2 (BJS1): "Launcher" / open "Messages" + - BTN1 (BJS1): Change FG Color + - BTN3 (BJS1): Change BG Color + - Right area: Change FG Color + - Swipe left: Change BG Color + - Swipe right: Increase/Decrease Hour circle/Points + + ## Creator -Daniel Perez \ No newline at end of file +Daniel Perez +For suggestions or feedback +https://github.com/dapgo/my_espruino_smartwatch_things \ No newline at end of file diff --git a/apps/tempmonitor/bangle.js2_UI.png b/apps/tempmonitor/bangle.js2_UI.png new file mode 100644 index 0000000000000000000000000000000000000000..ecfc31da8d0fe6594f77de98b927a3c68b9531e7 GIT binary patch literal 74846 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 literal 0 HcmV?d00001 diff --git a/apps/tempmonitor/bangle.js_UI.png b/apps/tempmonitor/bangle.js_UI.png new file mode 100644 index 0000000000000000000000000000000000000000..4b114b72c9f0d67f51e4ac84466f24bd3e4cffae GIT binary patch literal 124186 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 literal 0 HcmV?d00001 diff --git a/apps/tempmonitor/metadata.json b/apps/tempmonitor/metadata.json index dafb70f27..45d4d2c35 100644 --- a/apps/tempmonitor/metadata.json +++ b/apps/tempmonitor/metadata.json @@ -1,7 +1,7 @@ { "id": "tempmonitor", "name": "Temperature monitor", - "version": "0.02", + "version": "0.03", "description": "Displays the current temperature and stores in a CSV file", "icon": "app.png", "tags": "tool", diff --git a/apps/tempmonitor/tempmonitor.app.js b/apps/tempmonitor/tempmonitor.app.js index 62a4fee67..fd541f7cd 100644 --- a/apps/tempmonitor/tempmonitor.app.js +++ b/apps/tempmonitor/tempmonitor.app.js @@ -1,42 +1,69 @@ // Temperature monitor that saves a log of measures // standalone ver for developer, to remove testing lines // delimiter ; (excel) or , (oldscool) +/* REFACTOR and remove commented code related to +SetUI, Layout, and setWatch( function(b) { }, BTN1, { repeat: true, edge:'falling' }) +*/ { -var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail +var v_mode_debug=2; //, 0=no, 1 min, 2 prone detail //var required for drawing with dynamic screen var rect = Bangle.appRect; var history = []; -var readFreq=5000; //ms //PEND add to settings -var saveFreq=60000; //ms 1min +var readFreq=4000; //ms //PEND add to settings +if (v_mode_debug>0) var saveFreq=6000; //ms for testin 6sec +else var saveFreq=60000; //ms 1min var v_saveToFile= new Boolean(true); //true save //false //with upload file º is not displayed properly //with upload RAM º is displayed var v_t_symbol="";//ºC var v_saved_entries=0; -var filename ="temphistory.csv"; +var v_filename ="temphistory.csv"; var lastMeasure = new String(); var v_model=process.env.BOARD; +var v_color_erase=g.getBgColor(); //original BG color overwritten on SetVariables +var v_color=g.getColor();//original FG color +var id_rec_intv; //var for the recording interval +if (readFreq>saveFreq) console.log("Read refresh freq should be higher than saving"); +if (v_mode_debug>0) console.log("original BG/FG color="+v_color_erase+" / "+v_color); + + + +function SetVariables(){ //EMSCRIPTEN,EMSCRIPTEN2 if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') { v_font_size1=16; - v_font_size2=60; - //g.setColor("#0ff"); //light color + v_font_size2=50; }else{ - v_font_size1=11; - v_font_size2=40; - //g.setColor("#000"); //black or dark + //Banglejs2 or others + v_font_size1=11; //too small? + v_font_size2=40; } + //overwriting default BG, is better detect? + if (g.theme.dark==1) v_color_erase=0x0000; //dynamic; //bg black + else if (g.theme.dark==0) v_color_erase=0xFFFF; //dynamic; //bg white +} -function onTemperature(v_temp) { - if (v_mode_debug>1) console.log("v_temp in "+v_temp); +//print result +function printTemperature(v_temp) { + if (v_mode_debug>1) console.log("v_temp in "+v_temp+" entries "+v_saved_entries); ClearBox(); //g.setFont("6x8",2).setFontAlign(0,0); g.setFontVector(v_font_size1).setFontAlign(0,0); - var x = (rect.x+rect.x2)/2; + var x = (rect.x+(rect.x2-60))/2;//-60 space for graph and layout buttons var y = (rect.y+rect.y2)/2 + 20; - g.drawString("Records: "+v_saved_entries, x, rect.y+35); - g.drawString("Temperature:", x, rect.y+37+v_font_size1); + + if (v_saveToFile==true) { + // if (v_mode_debug>0) console.log("prev color="+v_color); + printInfo("Recording : "+v_saved_entries, '#CC3333',x,rect.y+30); + //g.setColor('#CC3333'); //red + // g.drawString("Recording : "+v_saved_entries, x, rect.y+35); + //g.setColor(v_color);//restore default color + } + else printInfo("Rec paused : "+v_saved_entries, v_color,x,rect.y+30); + //else g.drawString("Rec paused : "+v_saved_entries, x, rect.y+35); + //space for printing info + g.drawString("Temperature:", x, rect.y+45+(v_font_size1*2)); //dynamic font (g.getWidth() > 200 ? 60 : 40) g.setFontVector(v_font_size2).setFontAlign(0,0); // Avg of temperature readings @@ -48,34 +75,69 @@ function onTemperature(v_temp) { lastMeasure=avrTemp.toString(); if (lastMeasure.length>4) lastMeasure=lastMeasure.substr(0,4); //DRAW temperature in the center - g.drawString(" ", x-20, y); - g.drawString(v_temp+v_t_symbol, x-20, y); + //remove g.drawString(" ", x-20, y); + g.drawString(v_temp+v_t_symbol, x, y); g.flip(); } // from: BJS2 pressure sensor, BJS1 inbuilt thermistor -function drawTemperature() { +function getTemperature() { if(v_model.substr(0,10)!='EMSCRIPTEN'){ if (Bangle.getPressure) { - Bangle.getPressure().then(p =>{if (p) onTemperature(p);}); - } else onTemperature(E.getTemperature()); + Bangle.getPressure().then(p =>{if (p) printTemperature(p);}); + } else printTemperature(E.getTemperature()); } - else onTemperature(11);//fake temp for emulators + else printTemperature(11.25);//fake temperature medition for emulators } -function saveToFile() { +/* Note that it changes BG and also FG to an opposite*/ +function changeBGcolor(){ + //pend to refactor + if (v_mode_debug>1) console.log("before BG/FG "+v_color_erase+" /"+v_color); + v_color_erase=0xFFFF-v_color_erase; + v_color=0xFFFF-v_color; + if (v_mode_debug>1) console.log("after result BG/FG "+v_color_erase+" /"+v_color); + //g.setColor(color_result); + g.setBgColor(v_color_erase);// 0 white, 1 black + g.setColor(v_color); + //move to event? + ClearScreen(); + ClearBox(); + drawGraph(); + getTemperature(); + //setDrawLayout(); //uncomment if layout can work with setUI + //g.clear();//impact on widgets +} + +function saveToFile(){ //input global vars: lastMeasure var a=new Date(); var strlastSaveTime=new String(); strlastSaveTime=a.toISOString(); //strlastSaveTime=strlastSaveTime.concat(a.getFullYear(),a.getMonth()+1,a.getDate(),a.getHours(),a.getMinutes());; - if (v_mode_debug==1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure); + if (v_mode_debug>1) console.log("saving="+strlastSaveTime+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure); if (v_saveToFile==true){ - //write(strlastSaveTime+";"+ - require("Storage").open(filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n"); - //(getTime()+","); - v_saved_entries=v_saved_entries+1; + //write(strlastSaveTime+";"+ + //var f = require("Storage").open(v_filename,"r"); + // f=require("Storage").read(v_filename+"\1");//suffix required load completely!! + //note that .read uses Storage Class .open uses StorageFile Class , difference in file chunks + // if (v_mode_debug>0) console.log("f "+f); + var f = require("Storage").open(v_filename,"r"); + if ((v_mode_debug>0) && (v_saved_entries==0)) console.log("file info:"+f); + if (f.len>0) { + if (!f) { + require("Storage").open(v_filename,"w").write("Month;Day;Time;Temp"+"\n"); + if (v_mode_debug>0) console.log("not exist but created "+f); + } + else{ + require("Storage").open(v_filename,"a").write((a.getMonth()+1)+";"+a.getDate()+";"+a.getHours()+":"+a.getMinutes()+";"+lastMeasure+"\n"); + //(getTime()+","); + v_saved_entries=v_saved_entries+1; + if (v_mode_debug>1) console.log("append to already exist "+f.name+" , "+v_saved_entries); + }; + } } -} + else if (v_mode_debug>0) console.log("recording mode stopped"); +}; function drawGraph(){ var img_obj_thermo = { @@ -83,17 +145,19 @@ function drawGraph(){ transparent : 0, buffer : require("heatshrink").decompress(atob("AEFt2AMKm3bsAMJjdt23ABhEB+/7tgaJ///DRUP//7tuADRP923YDRXbDRfymwaJhu/koaK7eyiwaK3cLDRlWDRY1NKBY1Ztu5kjmJg3cyVI7YMHgdu5Mkyu2fxHkyVJjdgDRFJkmRDRPsDQNbDQ5QBGoONKBJrBoxQIQwO2eRcbtu24AMIFIQLJAH4AMA==")) }; - g.drawImage(img_obj_thermo,rect.x2-50,rect.y2/2); + g.drawImage(img_obj_thermo,rect.x2-60,rect.y2/2); g.flip(); } function ClearScreen(){ //avoid widget areas - g.reset(1).clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24); + g.setBgColor(v_color_erase); + g.clearRect(rect.x, rect.y+24, rect.x2, rect.y2-24); g.flip(); } function ClearBox(){ //custom boxarea , left space for static graph at right - g.reset(1).clearRect(rect.x, rect.y+24, rect.x2-50, rect.y2-24); + g.setBgColor(v_color_erase); + g.clearRect(rect.x, rect.y+24, rect.x2-60, rect.y2-24); g.flip(); } function introPage(){ @@ -109,30 +173,139 @@ function introPage(){ g.drawString("Read freq(ms): "+readFreq, x, y ); g.drawString("Save to file: "+v_saveToFile, x, y+ ((v_font_size1*1)+2) ); g.drawString("Save freq(ms):"+saveFreq, x, y+((v_font_size1*2)+2) ); - fr=require("Storage").read(filename+"\1");//suffix required - if (fr) g.drawString("Current filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) ); + fr=require("Storage").read(v_filename+"\1");//suffix required + if (fr) g.drawString("Filesize:"+fr.length.toString()+"kb", x, y+((v_font_size1*3)+2) ); else g.drawString("File not exist", x, y+((v_font_size1*3)+2)); } +function printInfo(pmsg, pcolor,px,py){ + g.setColor(pcolor); + g.setFontVector(v_font_size1).setFontAlign(0,0); + g.drawString(pmsg, px,py+v_font_size1); + g.setColor(v_color);//restore default color +} +function toggleRecMode(duration, exectime){ + //bydefault float, standard epoch requires *1000 + if (v_mode_debug>0) console.log("duration"+duration); + if (duration>2) { //delete file + var x = (rect.x+(rect.x2-60))/2; + printInfo("Deleting file",'#CC3333',x, rect.y+32+v_font_size1); + // g.setColor('#CC3333'); //red + + //too long "Deleting file: "+v_filename, + // for StorageFiles created with require("Storage").open(filename, ...) + //require("Storage").erase(v_filename); + //TODO refactor in a new function + //var mifile = require("Storage").open(v_filename,"w"); + var mifile = require("Storage").open("temphistory.csv","w"); + var v_output=mifile.erase(); + //mifile.StorageFile.erase(); + if (v_mode_debug>0) console.log("output"+v_output); + setTimeout(function() { if (v_mode_debug>0) console.log("pause for 1 sec");},1000); + return; //leave this function + } + if (v_saveToFile) v_saveToFile=false; + else v_saveToFile=true; + if (v_mode_debug>0) console.log("recording? "+v_saveToFile); + setRecordingFreq(); +} + +function setRecordingFreq(){ + if (v_saveToFile==true) { //TODO now start on false btn will no enable + id_rec_intv=setInterval(function() { + saveToFile(); + }, saveFreq); //ms + if (v_mode_debug>0) console.log("interval id / frq"+id_rec_intv+" / "+saveFreq); + } + else if (id_rec_intv){ + clearInterval(id_rec_intv); + if (v_mode_debug>0) console.log("rec interval removed, id "+id_rec_intv); + id_rec_intv=0; // to reset var + } +} + +function UserInput(){ + //theoretically incompatible with Layout + Bangle.setUI({ + mode : "custom", + //adds a back icon on top widget area + back : function() {load();}, + //touch : function(n,e) {}, // optional - handler for 'touch' events + // righ/Left 1/-1 , updown + swipe : function(dir_rl,dir_ud) { + if(dir_rl == 1) { + if (v_mode_debug>0) console.log("swipe right: "); + getFileInfo(v_filename); + } + else if (dir_rl == -1){ + if (v_mode_debug>0) console.log("swipe left: "); + changeBGcolor(); + } + }, + touch : function(tzone,tobj){ + if ((process.env.HWVERSION == 2)&&(v_mode_debug>0)){ + console.log("tobj x,y,type : "+tobj.x+" "+tobj.y+" "+tobj.type); + } + switch(tzone){ + //case 1: //left , back managed by setUI + case 2: // right disable/enable recording + toggleRecMode(0); //toggleRecMode(duration, exectime) + break; + // case 3: console.log("Touch 3 aka 1+2 not for BJS1 emul");//center 1+2 + // break; + } + }, + //inferior to + btn : function(btn) { + if(btn == 1) { + if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') toggleRecMode(1); //console.log("btn1 BJS1"); + else mainBtnShortcut(); //console.log("btn1 BJS2"); + } + else if (btn == 2) mainBtnShortcut(); //console.log("btn2 BJS1"); + else if (btn == 3) changeBGcolor(); //console.log("btn3 BJS1"); + } + }); //endof setUI + + +function mainBtnShortcut() { + //if messages app installed shortcut otherwise default access to launcher + if (require("Storage").read("messagegui.app.js")===undefined) + { + if (require("Storage").read("messagelist.app.js")===undefined) Bangle.showLauncher(); // implies btn2(js1) btn(js2)- launcher + else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagelist.app.js"); + else load("messagelist.app.js"); + } + else if (v_model=='BANGLEJS'||v_model=='EMSCRIPTEN') load("messagegui.app.js"); + else load("messagegui.app.js"); + } + + +// Show file size +function getFileInfo(v_filename) { + var f = require("Storage").open(v_filename,"r"); + //todo refactor and reuse common code + g.setFontVector(v_font_size1).setFontAlign(0,0); + var x = (rect.x+(rect.x2-60))/2; + printInfo("file size:"+f.len,v_color,x, rect.y+32+v_font_size1); + // g.drawString("file size:"+f.len, x, rect.y+37+v_font_size1); + if (v_mode_debug>0) console.log("file "+v_filename+" size: "+f.len); +}// not used + + //MAIN +SetVariables(); Bangle.loadWidgets(); -Bangle.setUI({ - mode : "custom", - back : function() {load();} -}); ClearScreen(); introPage(); +//setDrawLayout(); //uncomment if layout can work with setUI + +UserInput(); //inc SetUI and back icon + setInterval(function() { - drawTemperature(); + getTemperature(); }, readFreq); //ms -if (v_saveToFile==true) { - setInterval(function() { - saveToFile(); - }, saveFreq); //ms -} -setTimeout(ClearScreen, 3500); -setTimeout(drawGraph,4000); -setTimeout(drawTemperature,4500); +setRecordingFreq(); + } \ No newline at end of file diff --git a/apps/tempmonitor/tempmonitor.info b/apps/tempmonitor/tempmonitor.info index 1824c5c86..f31704b57 100644 --- a/apps/tempmonitor/tempmonitor.info +++ b/apps/tempmonitor/tempmonitor.info @@ -1 +1 @@ -{"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.01","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"} \ No newline at end of file +{"id":"tempmonitor","name":"tempmonitor","src":"tempmonitor.app.js","icon":"tempmonitor.img","version":"0.03","files":"tempmonitor.info,tempmonitor.app.js,tempmonitor.img"} \ No newline at end of file From 56a845f6308ddf3f97985910c2cc5492e4151cce Mon Sep 17 00:00:00 2001 From: dapgo Date: Mon, 27 Feb 2023 21:39:39 +0100 Subject: [PATCH 56/61] tempmonitor v3 Beside new functions, info about modedebug --- apps/tempmonitor/README.md | 1 + apps/tempmonitor/tempmonitor.app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/tempmonitor/README.md b/apps/tempmonitor/README.md index 21b570af9..e50ac07cb 100644 --- a/apps/tempmonitor/README.md +++ b/apps/tempmonitor/README.md @@ -36,6 +36,7 @@ Screenshot data file content Open and see a temperature in the screen Download the CSV file and process in your favourite spreadsheet software +if you have any problem enable the modedebug in code; v_mode_debug=1 or 2 ## Features diff --git a/apps/tempmonitor/tempmonitor.app.js b/apps/tempmonitor/tempmonitor.app.js index fd541f7cd..4136c5cde 100644 --- a/apps/tempmonitor/tempmonitor.app.js +++ b/apps/tempmonitor/tempmonitor.app.js @@ -5,7 +5,7 @@ SetUI, Layout, and setWatch( function(b) { }, BTN1, { repeat: true, edge:'falling' }) */ { -var v_mode_debug=2; //, 0=no, 1 min, 2 prone detail +var v_mode_debug=0; //, 0=no, 1 min, 2 prone detail //var required for drawing with dynamic screen var rect = Bangle.appRect; var history = []; From a314fa558080c403825ed09149ecb314748350a5 Mon Sep 17 00:00:00 2001 From: dapgo Date: Mon, 27 Feb 2023 21:54:36 +0100 Subject: [PATCH 57/61] Update tempmonitor.app.js small issue caused by removing comments --- apps/tempmonitor/tempmonitor.app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/tempmonitor/tempmonitor.app.js b/apps/tempmonitor/tempmonitor.app.js index 4136c5cde..298305e8c 100644 --- a/apps/tempmonitor/tempmonitor.app.js +++ b/apps/tempmonitor/tempmonitor.app.js @@ -265,6 +265,7 @@ function UserInput(){ } }); //endof setUI +}; function mainBtnShortcut() { //if messages app installed shortcut otherwise default access to launcher From 7c048bc2322acc4826c3b03cb2c2a7ba4376fbe3 Mon Sep 17 00:00:00 2001 From: dapgo Date: Mon, 27 Feb 2023 21:57:42 +0100 Subject: [PATCH 58/61] Update tempmonitor.app.js minor typo errors --- apps/tempmonitor/tempmonitor.app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/tempmonitor/tempmonitor.app.js b/apps/tempmonitor/tempmonitor.app.js index 298305e8c..9a6e85645 100644 --- a/apps/tempmonitor/tempmonitor.app.js +++ b/apps/tempmonitor/tempmonitor.app.js @@ -133,11 +133,11 @@ function saveToFile(){ //(getTime()+","); v_saved_entries=v_saved_entries+1; if (v_mode_debug>1) console.log("append to already exist "+f.name+" , "+v_saved_entries); - }; + } } } else if (v_mode_debug>0) console.log("recording mode stopped"); -}; +} function drawGraph(){ var img_obj_thermo = { @@ -265,7 +265,7 @@ function UserInput(){ } }); //endof setUI -}; +} function mainBtnShortcut() { //if messages app installed shortcut otherwise default access to launcher From 43448e42c9a6bb636bca29b5f87cec3e9df7f61e Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 27 Feb 2023 23:31:10 +0100 Subject: [PATCH 59/61] messagesoverlay - Fix handlers being restored incorrectly if message removed --- apps/messagesoverlay/ChangeLog | 3 ++- apps/messagesoverlay/lib.js | 35 ++++++++++-------------------- apps/messagesoverlay/metadata.json | 2 +- 3 files changed, 15 insertions(+), 25 deletions(-) diff --git a/apps/messagesoverlay/ChangeLog b/apps/messagesoverlay/ChangeLog index da98bfbce..d557bc5e1 100644 --- a/apps/messagesoverlay/ChangeLog +++ b/apps/messagesoverlay/ChangeLog @@ -1 +1,2 @@ -0.01: Initial fork from messages_light \ No newline at end of file +0.01: Initial fork from messages_light +0.02: Fix touch/drag/swipe handlers not being restored correctly if a message is removed diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index cc6b63176..5c0f50f1c 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -389,19 +389,17 @@ let getTouchHandler = function(ovr){ }; }; -let touchHandler; -let swipeHandler; - let restoreHandler = function(event){ - if (backup[event]){ - Bangle["#on" + event]=backup[event]; - backup[event] = undefined; - } + LOG("Restore", event, backup[event]); + Bangle.removeAllListeners(event); + Bangle["#on" + event]=backup[event]; + backup[event] = undefined; }; let backupHandler = function(event){ - if (eventQueue.length > 1 && ovr) return; // do not backup, overlay is already up + if (backupDone) return; // do not backup, overlay is already up backup[event] = Bangle["#on" + event]; + LOG("Backed up", backup[event]); Bangle.removeAllListeners(event); }; @@ -414,21 +412,16 @@ let cleanup = function(){ restoreHandler("swipe"); restoreHandler("drag"); - if (touchHandler) { - Bangle.removeListener("touch", touchHandler); - touchHandler = undefined; - } - if (swipeHandler) { - Bangle.removeListener("swipe", swipeHandler); - swipeHandler = undefined; - } Bangle.setLCDOverlay(); + backupDone = false; ovr = undefined; quiet = undefined; }; let backup = {}; +let backupDone = false; + let main = function(ovr, event) { LOG("Main", event, settings); @@ -441,13 +434,9 @@ let main = function(ovr, event) { backupHandler("touch"); backupHandler("swipe"); backupHandler("drag"); - - if (touchHandler) Bangle.removeListener("touch",touchHandler); - if (swipeHandler) Bangle.removeListener("swipe",swipeHandler); - touchHandler = getTouchHandler(ovr); - swipeHandler = getSwipeHandler(ovr); - Bangle.on('touch', touchHandler); - Bangle.on('swipe', swipeHandler); + backupDone=true; + Bangle.on('touch', getTouchHandler(ovr)); + Bangle.on('swipe', getSwipeHandler(ovr)); if (event !== undefined){ drawBorder(ovr); diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index 9efe95d26..9fe5befe5 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -1,7 +1,7 @@ { "id": "messagesoverlay", "name": "Messages Overlay", - "version": "0.01", + "version": "0.02", "description": "An overlay based implementation of a messages UI (display notifications from iOS and Gadgetbridge/Android)", "icon": "app.png", "type": "bootloader", From c440a5d143d93c4659009ca875faaec602c57ccd Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Mon, 27 Feb 2023 23:33:47 +0100 Subject: [PATCH 60/61] messagesoverlay - Remove unused files --- apps/messagesoverlay/app-icon.png | Bin 2841 -> 0 bytes apps/messagesoverlay/metadata.json | 1 - apps/messagesoverlay/settings.js | 1 - 3 files changed, 2 deletions(-) delete mode 100644 apps/messagesoverlay/app-icon.png delete mode 100644 apps/messagesoverlay/settings.js diff --git a/apps/messagesoverlay/app-icon.png b/apps/messagesoverlay/app-icon.png deleted file mode 100644 index c9b4b62ac2eadee63a98380856f9337d0050578a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2841 zcmbVO2~<;O8VwW_P{0MW6~X6o5Ja<*9YV;4CXfY@e4Qhfi(JV|afbZ2e!VsnszzUX}CO1gXY%Dh4h$iL7 zCnNb9gr|aqQBb6X4-)85lM=G%w0eSX5y1U<`QY02m3=m`@Pj6CM$a-ReBZCwr5F=(VVYnW$WmIP3 zW|II0o!Tkr49>KAVn8M!7}cUQQ0Ww!jgkW>m;W_Xr*onSQzH7h-?t_vlJg8GH4!Cn zvk^f7e1fACVUp#576-__N3bjh)tj8*D#RIUFdMb~GN}+Mszr4GMgUfHXP<^_+=LU^ z_&Y>!zIIAs;7g3C(u5n6aa`+|a)KiZ#9&YuP^bdatMFW6l8w+n04i0QPyq}^4u(x9 z)49oXCO@3Zr*kLM=zJQ@4wd67Or7^OC~yZo{0%7Zn@VX?z7JR~=TFlUCZ!%hr%44c zXo`YiDn1iIkW7TmA}iH24w=hha>-mSM@>c$6`O&mG8sIcvcE47FU1kFO+H7w3dGCU zY;KH`$76t4KxYBnsu*a(2$(}2F zXDrp(Oe{tK$K(yH=_GXFz?BvQy#cTDm56P93SdGBdWHuczOCW+8<{<6ZZ-;1zUjC( zY-EQKxZ0GfG@_y`Fy8;|XnPQnt<-0sV85ioHkwr1&SK|9wd?|pq|Ft7J zg26UxyL9gF;Kun2f$9NGBiR4XM8;txk{eh8qU7wQe{MP-m#*+@65?a0HjNV*cDUTG zu8Ll^eoD!3&%e#y-nwGQ_^@xM?-@pm2%gLlk5XD3^-Qgq zbl1=CRB7zKZ7l~co#GY?ZywEiP+$&g9vyTfqVu0b<2BynwncYmNlU7R&fV*o?myps z=NQ}3>`^!P$OkXod|Yat@FII(_|)wV^~xG2FN@vYG#(a~$HpG;6%FqiIeaSo#q?#w zF_%8C$mww6Y_ae=2V%^I)-9L%qE#DmEWF#7j;I76{rd zTOh@mj9XBWUuiUykz-uBa^;Lw@)C_an89F7dA!G3GNtMCX)kwo_vO!SUca7@mR3=> zBi?Ixahrbh!7BlpT(h~nsbft-=-Q9Jvs&Xc8qL|4cUr@{?%Y}NeM*X)&pCbOO#P;L zKit5=T;t;63Z6YIH*i;+QzHu&bf=$S357E;tm~_Vfq{XSfB7Z&p^#1&6&5y*r|fe3 zRm&EC`SYP1?%0*zpZw!KZ;_wBzkg)@I&OID)vGHaqJn04X5)BMN6+dFqj=Se^7FY- zQ7c;`A|jg49X;}3%jV4={=3j<+`d)3b?GD*y*0r4d!S~1pQ5U=@@yTel-dz95mxYI z-qgY2v?C=OHg3#&^>T4RNKQoV-K$^j-5YkG?T@nb{Vhvw%|5=m==tM&-`3W~%$++o zeGxQl+u_5Nt*xy@eGx~QuQYb)4QTRW=p+BnT;9vvMW zCbPMwuC5FWEF+_6`SRtHM>cp!TsOyu#P3e}y}T{xdCbI+ke;UnGiJ_AN=!WQiSM}k z`A1c1^_-JW+ON*$F655YYPCT4<`XAeN$0l;n>rt?*|J4<%CGVpRX~bg>DOPAA3b_x z>1lT-`HqWX%A+a*&#(13vgAc&Z?8Er$amkqeGhwkYZ@93v=&+{n~onB`S|#>|7NvX zz3-)NkRJOp=hDTC;+!0IT3T9NI%Qr%LHU*2s9t|J@zt6&!;@2F`{2a%bZsA#vo=2D zvllNG=k<24zuwt71nTYWWw2QOag9|~RbN$Cho)H<=5>2M=?sInix1b=2XisTK=yRXNJ5D7X{LV7^N%3Vxr#PB-UlF8y-@3E}la zmq?2vZ~5i=%S3SR)A?n|E3TB5bwT74 Date: Tue, 28 Feb 2023 07:57:06 +0100 Subject: [PATCH 61/61] messagesoverlay - Only add listeners once --- apps/messagesoverlay/lib.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/messagesoverlay/lib.js b/apps/messagesoverlay/lib.js index 5c0f50f1c..2d5feae94 100644 --- a/apps/messagesoverlay/lib.js +++ b/apps/messagesoverlay/lib.js @@ -434,9 +434,11 @@ let main = function(ovr, event) { backupHandler("touch"); backupHandler("swipe"); backupHandler("drag"); + if (!backupDone){ + Bangle.on('touch', getTouchHandler(ovr)); + Bangle.on('swipe', getSwipeHandler(ovr)); + } backupDone=true; - Bangle.on('touch', getTouchHandler(ovr)); - Bangle.on('swipe', getSwipeHandler(ovr)); if (event !== undefined){ drawBorder(ovr);