From f627b860da269148017badadf080ce1610a69070 Mon Sep 17 00:00:00 2001 From: storm64 Date: Mon, 12 Sep 2022 23:09:33 +0200 Subject: [PATCH 01/73] [sleeplogalarm] First files --- apps/sleeplogalarm/ChangeLog | 1 + apps/sleeplogalarm/README.md | 47 ++++++++++++++++++++++++++++ apps/sleeplogalarm/app.png | Bin 0 -> 698 bytes apps/sleeplogalarm/metadata.json | 16 ++++++++++ apps/sleeplogalarm/settings.js | 52 +++++++++++++++++++++++++++++++ apps/sleeplogalarm/widget.js | 4 +++ 6 files changed, 120 insertions(+) create mode 100644 apps/sleeplogalarm/ChangeLog create mode 100644 apps/sleeplogalarm/README.md create mode 100644 apps/sleeplogalarm/app.png create mode 100644 apps/sleeplogalarm/metadata.json create mode 100644 apps/sleeplogalarm/settings.js create mode 100644 apps/sleeplogalarm/widget.js diff --git a/apps/sleeplogalarm/ChangeLog b/apps/sleeplogalarm/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/sleeplogalarm/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md new file mode 100644 index 000000000..672c4238f --- /dev/null +++ b/apps/sleeplogalarm/README.md @@ -0,0 +1,47 @@ +# Sleep Log Alarm + +This widget searches for active alarms and raises the alarm event up to the defined time earlier, if in a light sleep phase. + +--- +### App Usage +--- + +#### Inside the settings: !!! dummy entries !!! + - __Thresholds__ submenu + Changes take effect from now on, not retrospective! + - __Max Awake__ | maximal awake duration + _10min_ / _20min_ / ... / __60min__ / ... / _120min_ + - __Min Consecutive__ | minimal consecutive sleep duration + _10min_ / _20min_ / ... / __30min__ / ... / _120min_ + - __Deep Sleep__ | deep sleep threshold + _30_ / _31_ / ... / __100__ / ... / _200_ + - __Light Sleep__ | light sleep threshold + _100_ / _110_ / ... / __200__ / ... / _400_ + - __Reset to Default__ | reset to bold values above + - __BreakToD__ | time of day to break view + _0:00_ / _1:00_ / ... / __12:00__ / ... / _23:00_ + - __App Timeout__ | app specific lock timeout + __0s__ / _10s_ / ... / _120s_ + - __Enabled__ | completely en-/disables the background service + __on__ / _off_ + +--- +### Worth Mentioning +--- + +#### To do list +- widget.js +- settings.js +- README.md + +#### Requests, Bugs and Feedback +Please leave requests and bug reports by raising an issue at [github.com/storm64/BangleApps](https://github.com/storm64/BangleApps) (or send me a [mail](mailto:banglejs@storm64.de)). + +#### Creator +Storm64 ([Mail](mailto:banglejs@storm64.de), [github](https://github.com/storm64)) + +#### Attributions +The app icon is downloaded from [https://icons8.com](https://icons8.com). + +#### License +[MIT License](LICENSE) diff --git a/apps/sleeplogalarm/app.png b/apps/sleeplogalarm/app.png new file mode 100644 index 0000000000000000000000000000000000000000..bb7f11f67bf96368c6c8994d43608a3c9ece108d GIT binary patch literal 698 zcmV;r0!96aP)>_62_vrVs7$x%)KEhY2bLH`8}|aP+4?loNZgNtQ$xdbF(5^0LHrv z*+n$Jo?TtG5znfDhWMwg>pnPhA64bntJ|$Z7122xCSpMsXp$@DCL257wkfKLqTb6Of7R0_aEmw-F2N`7O;DfXna3pU>Y z0M@gs%k^p^C2$Ye0)950Efu{>yq>Zp9zw{#ps}8TLDSP+NXwZdb@vg%IRJ!BR2F1v ztrChl1B^4EU9T=yX`_vGYC;HyCw zeu2ImiyxT3@-F?QwZq&%vuyl1->))54uWLrwWsTPj9&& zHGOc%+hA@$WdZo^)AJ3j-3%Zq5XJ^%YOO*nb_#d~{AfH&XzjFIc>XCYfq&KIZSXsZ zKc4t(wAhPlZ!AdKpR1K@o92-}iAUamQ3?G^crTVCpMl80uo-y+Mwhu^{gIh`P)0rj gk%5Sah=~82Kj4M5noGmPng9R*07*qoM6N<$f_3Oc+5i9m literal 0 HcmV?d00001 diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json new file mode 100644 index 000000000..7b3c15818 --- /dev/null +++ b/apps/sleeplogalarm/metadata.json @@ -0,0 +1,16 @@ +{ + "id":"sleeplogalarm", + "name":"Sleep Log Alarm", + "shortName": "SleepLogAlarm", + "version": "0.01", + "description": "Enhance your morning and let your alarms wake you up when you are in light sleep.", + "icon": "app.png", + "type": "widget", + "tags": "tool,widget", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name": "sleeplogalarm.wid.js", "url": "widget.js"}, + {"name": "sleeplogalarm.settings.js", "url": "settings.js"} + ] +} diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js new file mode 100644 index 000000000..c4f13d63f --- /dev/null +++ b/apps/sleeplogalarm/settings.js @@ -0,0 +1,52 @@ +(function(back) { + // define settings filename + var filename = "sleeplogalarm.json"; + + // define default vaules + var defaults = { + }; + + // assign loaded settings to default values + var settings = Object.assign(defaults, require("Storage").readJSON(filename, true) || {}); + + // write change to storage + function writeSetting() { + require("Storage").writeJSON(filename, settings); + } + + // show main menu + function showMain(selected) { + // set menu + var mainMenu = { + "": { + title: "Sleep Log Alarm", + selected: selected + }, + /*LANG*/"< Back": () => back(), + /*LANG*/"up to": { + value: settings.earlier, + step: 10, + min: 10, + max: 120, + wrap: true, + noList: true, + format: v => v + "min earlier", + onchange: v => { + settings.earlier = v; + writeSetting(); + } + }, + /*LANG*/"Enabled": { + value: settings.enabled, + onchange: v => { + settings.enabled = v; + writeSetting(); + } + } + }; + var menu = E.showMenu(mainMenu); + } + + // draw main menu + showMain(); +}) diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js new file mode 100644 index 000000000..42e9bcd0a --- /dev/null +++ b/apps/sleeplogalarm/widget.js @@ -0,0 +1,4 @@ +// sleeplog.status values: +// undefined = service stopped, 0 = unknown, 1 = not worn, 2 = awake, 3 = light sleep, 4 = deep sleep +// sleeplog.consecutive values: +// undefined = service stopped, 0 = unknown, 1 = no consecutive sleep, 2 = consecutive sleep From 94c60a731be69e7bfb1bfd21d9b61724db7312bc Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Fri, 21 Oct 2022 13:28:54 +0200 Subject: [PATCH 02/73] Create widtick.wid.js --- apps/widtick/widtick.wid.js | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 apps/widtick/widtick.wid.js diff --git a/apps/widtick/widtick.wid.js b/apps/widtick/widtick.wid.js new file mode 100644 index 000000000..c59ae5dfb --- /dev/null +++ b/apps/widtick/widtick.wid.js @@ -0,0 +1,8 @@ +(()=>{ + setInterval(()=>{Bangle.buzz(5,1);},1000); + WIDGETS.tick = { + area: "tr", + width: 0, + draw: ()=>{} + }; +})(); From 716b2e454aab6777a5bdfdcd9ce7b1197210c5af Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 01:18:02 +0100 Subject: [PATCH 03/73] [sleeplogalarm] Add triger, widget code --- apps/sleeplogalarm/trigger.js | 75 +++++++++++++++++++++++++++++++++++ apps/sleeplogalarm/widget.js | 59 +++++++++++++++++++++++++-- 2 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 apps/sleeplogalarm/trigger.js diff --git a/apps/sleeplogalarm/trigger.js b/apps/sleeplogalarm/trigger.js new file mode 100644 index 000000000..d80a86f3d --- /dev/null +++ b/apps/sleeplogalarm/trigger.js @@ -0,0 +1,75 @@ +exports = function(now, tNow) { + // define settings + var settings = Object.assign({ + from: 4, // 0400 + to: 8, // 0800 + earlier: 6E4 * 30, + msgAsPrefix: true, + disableOnAlarm: false, // !!! not available if alarm is at the next day + msg: "...\n", + vibrate: "..", + as: true + }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); + + // calculate then date + var then = new Date(now + settings.earlier); + + // load library + var sched = require("sched"); + + // define function to return first active alarm in range to come + function firstActiveAlarm(allAlarms) { + return (sched.getActiveAlarms(allAlarms.filter( + // filter for active alarms, ... + a => a.on && !a.timer && + // after now+10s and in alarm range + a.t > tNow && a.t >= settings.from * 36E5 && a.t <= settings.to * 36E5 + ), then) || []).sort((a, b) => a.t > b.t)[0]; + } + + // read all alarms + var allAlarms = sched.getAlarms(); + + // find first active alarm + var alarm = firstActiveAlarm(allAlarms); + + // return if no alarm is found + if (!alarm) return; + + // disable early triggered alarm if set and now and then on the same day + if (settings.disableOnAlarm && now.getDate() === then.getDate()) { + // add indexes to find alarm to temporary disable + allAlarms = allAlarms.map((a, idx) => { + a.idx = idx; + return a; + }); + // get index of first active alarm + var idx = firstActiveAlarm(allAlarms).idx; + // set this alarms last to then + allAlarms[idx].last = then.getDate(); + // remove added indexes + allAlarms = allAlarms.map(a => { + delete a.idx; + return a; + }); + } + + // add new alarm for now with data from found alarm + allAlarms.push({ + id: "sleeplog", + appid: "sleeplog", + on: true, + t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), + dow: 127, + msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), + vibrate: settings.vibrate || alarm.vibrate, + as: settings.as, + del: true + }); + + // write changes + sched.setAlarms(allAlarms); + + // trigger sched.js + load("sched.js"); +}; \ No newline at end of file diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 42e9bcd0a..a7190768c 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,4 +1,55 @@ -// sleeplog.status values: -// undefined = service stopped, 0 = unknown, 1 = not worn, 2 = awake, 3 = light sleep, 4 = deep sleep -// sleeplog.consecutive values: -// undefined = service stopped, 0 = unknown, 1 = no consecutive sleep, 2 = consecutive sleep +// check if sleeplog is available and any alarm is active +if (typeof (global.sleeplog || {}).onChange === "object" && + (require("Storage").readJSON("sched.json", 1) || []).some(a => a.on && !a.timer)) { + + // read settings to calculate alarm range + var settings = Object.assign({ + enabled: true, + hide: false, + drawRange: true, + from: 4, // 0400 + to: 8, // 0800 + earlier: 6E4 * 30 + }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); + + // abort if not enabled in settings + if (!settings.enabled) return; + + // setup widget depending on settings + WIDGETS.sleeplogalarm = { + area: "tl", + width: 0, + from: settings.from, + to: settings.to, + earlier: settings.earlier, + draw: function() { + if (this.width) g.reset().setColor(1, 1, 0).drawImage(atob(""), this.x, this.y + this.width - 8); + if (this.width > 8) { + g.setFont().setFontAllign(); + g.drwaString(this.from, this.x + 6, this.y); + g.drwaString(this.to, this.x + 18, this.y); + } + } + }; + + // set widget width and draw + WIDGETS.sleeplogalarm.width = settings.hide ? 0 : settings.drawRange ? 24 : 8; + WIDGETS.sleeplogalarm.draw(); + + // add sleeplogalarm function to onChange + sleeplog.onChange.push(function(data) { + // abort if not changed from deep sleep to light sleep or awake + if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; + + // get now and calculate time of now + var now = new Date(); + var tNow = (now.getHours() * 3600000) + (now.getMinutes() * 60000) + (now.getSeconds() * 1000); + + // abort if now is outside the possible alarm range + if (tNow + WIDGETS.sleeplogalarm.earlier < WIDGETS.sleeplogalarm.from * 36E5 || + tNow + WIDGETS.sleeplogalarm.earlier >= WIDGETS.sleeplogalarm.to * 36E5) return; + + // execute trigger function + require("sleeplogalarm.trigger.js")(now, tNow); + }); +} From a07747ca2577309100fbbaa2541729573b263ef5 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 13:12:22 +0100 Subject: [PATCH 04/73] [sleeplogalarm] Setup widget and app.png --- apps/sleeplogalarm/app.png | Bin 698 -> 8089 bytes apps/sleeplogalarm/metadata.json | 5 ++-- apps/sleeplogalarm/trigger.js | 6 ++--- apps/sleeplogalarm/widget.js | 38 +++++++++++++++++++------------ 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/apps/sleeplogalarm/app.png b/apps/sleeplogalarm/app.png index bb7f11f67bf96368c6c8994d43608a3c9ece108d..6efb22a3f666817408264ec02731f4ac13d1ffe8 100644 GIT binary patch literal 8089 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 delta 675 zcmV;U0$lx>Ke`2wBYyw}VoOIv0RI600RN!9r;`8x0&ht~K~!jg?U%o6Q&AMhKPOFG zv;_sbWislhe}R)IHI*dQb~iZGK^F&$gM$u&AP!v|%pYJad2Q1oK|48!OL1|C;39%j z6sgt4B=0yhf#l_--sIhv7>_5`V^`xngeecg(#ZDrw+& zqxn6skx*H5W}IzXv8)?N7jv^BS^&no4B16Azn)!Pwh_;&frj{}t?NEGb01aZ)~nmC zLlx0E8zy2w7if|z<|Z3E-?k~LilW}(f=Xd(Y4&K)xbdJ1G-=d)N7;CGzLkl1qIw;; z6C|#+42a6KUw?Zk>rl!%zH=0O=k$U#1HiF9=A?oKwP~QE&_kNjhD`$>1~jJ)n+Dc< zouHznph2w}NT@6VyQbp>c4A}hV$itO3^+5+HllgV>RMfueCcB8YtXnIC$T>EId$gE zPweTH%w<#xz(kjTJFZH8W5y}=q_hh*-vI#Dv#ZPXYJVana1Yo5em0&h6}?Nmp0Xt# zLdd|Nv7UiJ)6-o@%b6r~_YuN50EA6c7G!Fz5{fzlj5DC+OcK|9i*Sj(yZ$&z7WB22 zGs*BI?vHr}_ICb=PtRdo_aQL%sTPj9&&HGOc%+hA@$WdZo^)AJ3j-3%Zq5XJ^% zYOO*nb_#d~{AfH&XzjFIc>XCYfq&KIZSXsZKc4t(wAhPlZ!AdKpR1K@o92-}iAUam zQ3?G^crTVCpMl80uo-y+Mwhu^{gIh`P)0rjksN`Dh=_>)n?K-%w3 { diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index a7190768c..34453497b 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -7,37 +7,45 @@ if (typeof (global.sleeplog || {}).onChange === "object" && enabled: true, hide: false, drawRange: true, + color: g.theme.dark ? 65504 : 31, // yellow or blue from: 4, // 0400 to: 8, // 0800 - earlier: 6E4 * 30 + earlier: 30 }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); // abort if not enabled in settings if (!settings.enabled) return; - // setup widget depending on settings + // insert neccessary settings into widget WIDGETS.sleeplogalarm = { area: "tl", width: 0, + drawRange: settings.drawRange, + color: settings.color, from: settings.from, to: settings.to, earlier: settings.earlier, - draw: function() { - if (this.width) g.reset().setColor(1, 1, 0).drawImage(atob(""), this.x, this.y + this.width - 8); - if (this.width > 8) { - g.setFont().setFontAllign(); - g.drwaString(this.from, this.x + 6, this.y); - g.drwaString(this.to, this.x + 18, this.y); - } - } + draw: ()=>{} }; + // setup widget depending if not hidden + if (!settings.hide) { + WIDGETS.sleeplogalarm.width = 8; + WIDGETS.sleeplogalarm.draw = function() { + g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); + if (this.drawRange) { + require("Font4x5Numeric").add(Graphics); + g.setFont("4x5Numeric").drawString(this.from, this.x + 1, this.y + 12); + g.setFontAlign(1, 1).drawString(this.to, this.x + this.width + 1, this.y + 23); + } + }; + } + // set widget width and draw - WIDGETS.sleeplogalarm.width = settings.hide ? 0 : settings.drawRange ? 24 : 8; WIDGETS.sleeplogalarm.draw(); // add sleeplogalarm function to onChange - sleeplog.onChange.push(function(data) { + sleeplog.onChange.sleeplogalarm = function(data) { // abort if not changed from deep sleep to light sleep or awake if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; @@ -46,10 +54,10 @@ if (typeof (global.sleeplog || {}).onChange === "object" && var tNow = (now.getHours() * 3600000) + (now.getMinutes() * 60000) + (now.getSeconds() * 1000); // abort if now is outside the possible alarm range - if (tNow + WIDGETS.sleeplogalarm.earlier < WIDGETS.sleeplogalarm.from * 36E5 || - tNow + WIDGETS.sleeplogalarm.earlier >= WIDGETS.sleeplogalarm.to * 36E5) return; + if (tNow + WIDGETS.sleeplogalarm.earlier * 6E4 < WIDGETS.sleeplogalarm.from * 36E5 || + tNow + WIDGETS.sleeplogalarm.earlier * 6E4 >= WIDGETS.sleeplogalarm.to * 36E5) return; // execute trigger function require("sleeplogalarm.trigger.js")(now, tNow); - }); + }; } From 57f06969988d7d1f01033ad3ca23f1e977af4dff Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 15:14:53 +0100 Subject: [PATCH 05/73] [sleeplogalarm] Add settings and dependency --- apps/sleeplogalarm/README.md | 20 +++-- apps/sleeplogalarm/metadata.json | 1 + apps/sleeplogalarm/settings.js | 128 ++++++++++++++++++++++++++++--- 3 files changed, 129 insertions(+), 20 deletions(-) diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 672c4238f..42c2d6074 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -7,22 +7,22 @@ This widget searches for active alarms and raises the alarm event up to the defi --- #### Inside the settings: !!! dummy entries !!! - - __Thresholds__ submenu + - __Thresholds__ submenu Changes take effect from now on, not retrospective! - - __Max Awake__ | maximal awake duration + - __Max Awake__ | maximal awake duration _10min_ / _20min_ / ... / __60min__ / ... / _120min_ - - __Min Consecutive__ | minimal consecutive sleep duration + - __Min Consecutive__ | minimal consecutive sleep duration _10min_ / _20min_ / ... / __30min__ / ... / _120min_ - - __Deep Sleep__ | deep sleep threshold + - __Deep Sleep__ | deep sleep threshold _30_ / _31_ / ... / __100__ / ... / _200_ - - __Light Sleep__ | light sleep threshold - _100_ / _110_ / ... / __200__ / ... / _400_ + - __Light Sleep__ | light sleep threshold + _100_ / _110_ / ... / __200__ / ... / _400_ - __Reset to Default__ | reset to bold values above - - __BreakToD__ | time of day to break view + - __BreakToD__ | time of day to break view _0:00_ / _1:00_ / ... / __12:00__ / ... / _23:00_ - - __App Timeout__ | app specific lock timeout + - __App Timeout__ | app specific lock timeout __0s__ / _10s_ / ... / _120s_ - - __Enabled__ | completely en-/disables the background service + - __Enabled__ | completely en-/disables the background service __on__ / _off_ --- @@ -30,8 +30,6 @@ This widget searches for active alarms and raises the alarm event up to the defi --- #### To do list -- widget.js -- settings.js - README.md #### Requests, Bugs and Feedback diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 3ea566acb..198d8e07a 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -8,6 +8,7 @@ "type": "widget", "tags": "tool,widget", "supports": ["BANGLEJS2"], + "dependencies": {"sleeplog": "app"}, "readme": "README.md", "storage": [ {"name": "sleeplogalarm.settings.js", "url": "settings.js"}, diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index c4f13d63f..38a1e5ab5 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -1,19 +1,66 @@ (function(back) { // define settings filename - var filename = "sleeplogalarm.json"; + var filename = "sleeplogalarm.settings.json"; - // define default vaules - var defaults = { - }; - - // assign loaded settings to default values - var settings = Object.assign(defaults, require("Storage").readJSON(filename, true) || {}); + // define settings + var settings = Object.assign({ + enabled: true, + hide: false, + drawRange: true, + color: g.theme.dark ? 65504 : 31, // yellow or blue + from: 4, // 0400 + to: 8, // 0800 + earlier: 30, + disableOnAlarm: false, // !!! not available if alarm is at the next day + msgAsPrefix: true, + msg: "...\n", + vibrate: "..", + as: true + }, require("Storage").readJSON(filename, true) || {}); // write change to storage function writeSetting() { require("Storage").writeJSON(filename, settings); } + // show widget menu + function showWidMenu() { + // set menu + var widgetMenu = { + "": { + title: "Widget Settings" + }, + /*LANG*/"< Back": () => showMain(7), + /*LANG*/"hide complete": { + value: settings.hide, + onchange: v => { + settings.hide = v; + writeSetting(); + } + }, + /*LANG*/"draw time range": { + value: settings.drawRange, + onchange: v => { + settings.drawRange = v; + writeSetting(); + } + }, + /*LANG*/"color": { + colors: [63488, 65504, 2016, 2047, 31, 63519, 0, 65535], + value: this.colors.indexOf(settings.color), + min: 0, + max: this.colors.length -1, + wrap: true, + format: v => ["red", "yellow", "green", "cyan", "blue", "magenta", "black", "white"][v], + onchange: v => { + settings.color = this.colors[v]; + writeSetting(); + } + } + }; + var menu = E.showMenu(widgetMenu); + } + // show main menu function showMain(selected) { // set menu @@ -23,19 +70,82 @@ selected: selected }, /*LANG*/"< Back": () => back(), - /*LANG*/"up to": { + /*LANG*/"from": { + value: settings.from, + min: 0, + max: 23, + wrap: true, + noList: true, + format: v => v + ":00", + onchange: v => { + settings.from = v; + writeSetting(); + } + }, + /*LANG*/"to": { + value: settings.to, + min: 1, + max: 24, + wrap: true, + noList: true, + format: v => v + ":00", + onchange: v => { + settings.to = v; + writeSetting(); + } + }, + /*LANG*/"erlier": { value: settings.earlier, step: 10, min: 10, max: 120, wrap: true, noList: true, - format: v => v + "min earlier", + format: v => v + "min", onchange: v => { settings.earlier = v; writeSetting(); } }, + /*LANG*/"disable on alarm": { + value: settings.disableOnAlarm, + onchange: v => { + settings.disableOnAlarm = v; + writeSetting(); + } + }, + /*LANG*/"message as prefix": { + value: settings.msgAsPrefix, + onchange: v => { + settings.msgAsPrefix = v; + writeSetting(); + } + }, + /*LANG*/"msg": { + value: settings.msg, + format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, + // setTimeout required to load after menu refresh + onchange: () => setTimeout(msg => { + if (require("Storage").read("textinput")) { + g.clear(); + require("textinput").input({text: msg}).then(result => { + settings.msg = result; + writeSetting(); + showMenu(7); + }); + } else { + E.showAlert(/*LANG*/"No keyboard app installed").then(() => showMenu(7)); + } + }), + }, + /*LANG*/"vibration pattern": require("buzz_menu.js").pattern( + settings.vibrate, + v => { + settings.vibrate = v; + writeSetting(); + } + ), + /*LANG*/"Widget Settings": () => showWidMenu(), /*LANG*/"Enabled": { value: settings.enabled, onchange: v => { From 9b8895a259430bada5e9f3f00e11db0af6250ab5 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 16:52:35 +0100 Subject: [PATCH 06/73] [sleeplogalarm] Rewrite widget.js --- apps/sleeplogalarm/widget.js | 85 +++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 40 deletions(-) diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 34453497b..09f29e906 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,20 +1,16 @@ -// check if sleeplog is available and any alarm is active -if (typeof (global.sleeplog || {}).onChange === "object" && - (require("Storage").readJSON("sched.json", 1) || []).some(a => a.on && !a.timer)) { +// read settings to calculate alarm range +var settings = Object.assign({ + enabled: true, + hide: false, + drawRange: true, + color: g.theme.dark ? 65504 : 31, // yellow or blue + from: 4, // 0400 + to: 8, // 0800 + earlier: 30 +}, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - // read settings to calculate alarm range - var settings = Object.assign({ - enabled: true, - hide: false, - drawRange: true, - color: g.theme.dark ? 65504 : 31, // yellow or blue - from: 4, // 0400 - to: 8, // 0800 - earlier: 30 - }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - - // abort if not enabled in settings - if (!settings.enabled) return; +// check if enabled in settings +if (settings.enabled) { // insert neccessary settings into widget WIDGETS.sleeplogalarm = { @@ -25,39 +21,48 @@ if (typeof (global.sleeplog || {}).onChange === "object" && from: settings.from, to: settings.to, earlier: settings.earlier, - draw: ()=>{} - }; - - // setup widget depending if not hidden - if (!settings.hide) { - WIDGETS.sleeplogalarm.width = 8; - WIDGETS.sleeplogalarm.draw = function() { + draw: function () { + // draw zzz g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); + // draw alarm range times if enabled if (this.drawRange) { require("Font4x5Numeric").add(Graphics); g.setFont("4x5Numeric").drawString(this.from, this.x + 1, this.y + 12); g.setFontAlign(1, 1).drawString(this.to, this.x + this.width + 1, this.y + 23); } - }; - } + }, + reload: function () { + // abort if onChange is not available + if (typeof (global.sleeplog || {}).onChange === "object") return; - // set widget width and draw - WIDGETS.sleeplogalarm.draw(); + // abort if no alarm exists inside range + if (!(require("Storage").readJSON("sched.json", 1) || []) + .filter(a => a.on && !a.timer) + .some(a => a.t >= this.from * 36E5 && a.t < this.to * 36E5)) return; - // add sleeplogalarm function to onChange - sleeplog.onChange.sleeplogalarm = function(data) { - // abort if not changed from deep sleep to light sleep or awake - if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; + // set widget width if not hidden + if (!this.hidden) this.width = 8; - // get now and calculate time of now - var now = new Date(); - var tNow = (now.getHours() * 3600000) + (now.getMinutes() * 60000) + (now.getSeconds() * 1000); + // insert sleeplogalarm function to onChange + sleeplog.onChange.sleeplogalarm = function (data) { + // abort if not changed from deep sleep to light sleep or awake + if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; - // abort if now is outside the possible alarm range - if (tNow + WIDGETS.sleeplogalarm.earlier * 6E4 < WIDGETS.sleeplogalarm.from * 36E5 || - tNow + WIDGETS.sleeplogalarm.earlier * 6E4 >= WIDGETS.sleeplogalarm.to * 36E5) return; + // get cahed data, now and calculate time of now + var data = WIDGET.sleeplogalarm; + var now = new Date(); + var tNow = (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000); - // execute trigger function - require("sleeplogalarm.trigger.js")(now, tNow); + // abort if now is outside the possible alarm range + if (tNow + data.earlier * 6E4 < data.from * 36E5 || + tNow + data.earlier * 6E4 >= data.to * 36E5) return; + + // execute trigger function + require("sleeplogalarm.trigger.js")(now, tNow); + }; + } }; -} + + // load widget + WIDGETS.sleeplogalarm.reload(); +}; \ No newline at end of file From 3b54d3b1a914270c20d97d6c1e42fa41adbbb842 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 17:06:35 +0100 Subject: [PATCH 07/73] [sleeplogalarm] Correct typo --- apps/sleeplogalarm/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 09f29e906..741101222 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -65,4 +65,4 @@ if (settings.enabled) { // load widget WIDGETS.sleeplogalarm.reload(); -}; \ No newline at end of file +} \ No newline at end of file From 88468dc6c3677009afa1e78663623fab980a1156 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 18:25:18 +0100 Subject: [PATCH 08/73] [sleeplogalarm] Include font in widget + edit settings --- apps/sleeplogalarm/settings.js | 46 ++++++++++++++++++---------------- apps/sleeplogalarm/widget.js | 15 +++++------ 2 files changed, 33 insertions(+), 28 deletions(-) diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 38a1e5ab5..8b6bd96aa 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -12,8 +12,8 @@ to: 8, // 0800 earlier: 30, disableOnAlarm: false, // !!! not available if alarm is at the next day - msgAsPrefix: true, msg: "...\n", + msgAsPrefix: true, vibrate: "..", as: true }, require("Storage").readJSON(filename, true) || {}); @@ -23,6 +23,10 @@ require("Storage").writeJSON(filename, settings); } + // define color values and names + var colName = ["red", "yellow", "green", "cyan", "blue", "magenta", "black", "white"]; + var colVal = [63488, 65504, 2016, 2047, 31, 63519, 0, 65535]; + // show widget menu function showWidMenu() { // set menu @@ -46,14 +50,13 @@ } }, /*LANG*/"color": { - colors: [63488, 65504, 2016, 2047, 31, 63519, 0, 65535], - value: this.colors.indexOf(settings.color), + value: colVal.indexOf(settings.color), min: 0, - max: this.colors.length -1, + max: colVal.length -1, wrap: true, - format: v => ["red", "yellow", "green", "cyan", "blue", "magenta", "black", "white"][v], + format: v => colName[v], onchange: v => { - settings.color = this.colors[v]; + settings.color = colVal[v]; writeSetting(); } } @@ -70,7 +73,7 @@ selected: selected }, /*LANG*/"< Back": () => back(), - /*LANG*/"from": { + /*LANG*/"time from": { value: settings.from, min: 0, max: 23, @@ -82,7 +85,7 @@ writeSetting(); } }, - /*LANG*/"to": { + /*LANG*/"time to": { value: settings.to, min: 1, max: 24, @@ -114,31 +117,32 @@ writeSetting(); } }, - /*LANG*/"message as prefix": { - value: settings.msgAsPrefix, - onchange: v => { - settings.msgAsPrefix = v; - writeSetting(); - } - }, /*LANG*/"msg": { value: settings.msg, format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, // setTimeout required to load after menu refresh - onchange: () => setTimeout(msg => { + onchange: () => setTimeout((msg, cb) => { if (require("Storage").read("textinput")) { g.clear(); require("textinput").input({text: msg}).then(result => { settings.msg = result; writeSetting(); - showMenu(7); + cb(7); }); } else { - E.showAlert(/*LANG*/"No keyboard app installed").then(() => showMenu(7)); + E.showAlert(/*LANG*/"No keyboard app installed").then(() => cb(7)); } - }), + }, 0, settings.msg, showMain), }, - /*LANG*/"vibration pattern": require("buzz_menu.js").pattern( + /*LANG*/"msg:": { + value: settings.msgAsPrefix, + format: v => v ? "add as prefix" : "replace msg", + onchange: v => { + settings.msgAsPrefix = v; + writeSetting(); + } + }, + /*LANG*/"vibration pattern": require("buzz_menu").pattern( settings.vibrate, v => { settings.vibrate = v; @@ -159,4 +163,4 @@ // draw main menu showMain(); -}) +})() \ No newline at end of file diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 741101222..083063318 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,5 +1,5 @@ // read settings to calculate alarm range -var settings = Object.assign({ +settings = Object.assign({ // if using var here settings will always be undefined enabled: true, hide: false, drawRange: true, @@ -26,14 +26,15 @@ if (settings.enabled) { g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); // draw alarm range times if enabled if (this.drawRange) { - require("Font4x5Numeric").add(Graphics); - g.setFont("4x5Numeric").drawString(this.from, this.x + 1, this.y + 12); + // directly include Font4x5Numeric + g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5); + g.drawString(this.from, this.x + 1, this.y + 12); g.setFontAlign(1, 1).drawString(this.to, this.x + this.width + 1, this.y + 23); } }, reload: function () { // abort if onChange is not available - if (typeof (global.sleeplog || {}).onChange === "object") return; + if (typeof (global.sleeplog || {}).onChange !== "object") return; // abort if no alarm exists inside range if (!(require("Storage").readJSON("sched.json", 1) || []) @@ -49,13 +50,13 @@ if (settings.enabled) { if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; // get cahed data, now and calculate time of now - var data = WIDGET.sleeplogalarm; + var settings = WIDGET.sleeplogalarm; var now = new Date(); var tNow = (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000); // abort if now is outside the possible alarm range - if (tNow + data.earlier * 6E4 < data.from * 36E5 || - tNow + data.earlier * 6E4 >= data.to * 36E5) return; + if (tNow + settings.earlier * 6E4 < settings.from * 36E5 || + tNow + settings.earlier * 6E4 >= settings.to * 36E5) return; // execute trigger function require("sleeplogalarm.trigger.js")(now, tNow); From f193e5d9a1ea80c19c6f96546c17f2f6a947d905 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 23:16:00 +0100 Subject: [PATCH 09/73] [sleeplogalarm] Improve settings --- apps/sleeplogalarm/settings.js | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 8b6bd96aa..8719761dd 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -23,26 +23,26 @@ require("Storage").writeJSON(filename, settings); } - // define color values and names - var colName = ["red", "yellow", "green", "cyan", "blue", "magenta", "black", "white"]; - var colVal = [63488, 65504, 2016, 2047, 31, 63519, 0, 65535]; - // show widget menu function showWidMenu() { + // define color values and names + var colName = ["red", "yellow", "green", "cyan", "blue", "magenta", "black", "white"]; + var colVal = [63488, 65504, 2016, 2047, 31, 63519, 0, 65535]; + // set menu var widgetMenu = { "": { title: "Widget Settings" }, /*LANG*/"< Back": () => showMain(7), - /*LANG*/"hide complete": { + /*LANG*/"hide": { value: settings.hide, onchange: v => { settings.hide = v; writeSetting(); } }, - /*LANG*/"draw time range": { + /*LANG*/"time range": { value: settings.drawRange, onchange: v => { settings.drawRange = v; @@ -104,13 +104,13 @@ max: 120, wrap: true, noList: true, - format: v => v + "min", + format: v => v + /*LANG*/"min", onchange: v => { settings.earlier = v; writeSetting(); } }, - /*LANG*/"disable on alarm": { + /*LANG*/"disable alarm": { value: settings.disableOnAlarm, onchange: v => { settings.disableOnAlarm = v; @@ -134,22 +134,21 @@ } }, 0, settings.msg, showMain), }, - /*LANG*/"msg:": { + /*LANG*/"msg as prefix": { value: settings.msgAsPrefix, - format: v => v ? "add as prefix" : "replace msg", onchange: v => { settings.msgAsPrefix = v; writeSetting(); } }, - /*LANG*/"vibration pattern": require("buzz_menu").pattern( + /*LANG*/"vib pattern": require("buzz_menu").pattern( settings.vibrate, v => { settings.vibrate = v; writeSetting(); } ), - /*LANG*/"Widget Settings": () => showWidMenu(), + /*LANG*/"Widget": () => showWidMenu(), /*LANG*/"Enabled": { value: settings.enabled, onchange: v => { @@ -163,4 +162,4 @@ // draw main menu showMain(); -})() \ No newline at end of file +}) From 53aaf929ef680f0627b5e3036f60b8bd24fb57cf Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 10 Nov 2022 23:56:03 +0100 Subject: [PATCH 10/73] [sleeplogalarm] Correct widget --- apps/sleeplogalarm/trigger.js | 2 +- apps/sleeplogalarm/widget.js | 11 ++++------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/sleeplogalarm/trigger.js b/apps/sleeplogalarm/trigger.js index 54135b649..cc4dd6f12 100644 --- a/apps/sleeplogalarm/trigger.js +++ b/apps/sleeplogalarm/trigger.js @@ -23,7 +23,7 @@ exports = function(now, tNow) { // filter for active alarms, ... a => a.on && !a.timer && // after now+10s and in alarm range - a.t > tNow && a.t >= settings.from * 36E5 && a.t <= settings.to * 36E5 + a.t > tNow && a.t >= settings.from * 36E5 && a.t < settings.to * 36E5 ), then) || []).sort((a, b) => a.t > b.t)[0]; } diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 083063318..5ccc57cda 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -50,16 +50,13 @@ if (settings.enabled) { if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; // get cahed data, now and calculate time of now - var settings = WIDGET.sleeplogalarm; + var settings = WIDGETS.sleeplogalarm; var now = new Date(); var tNow = (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000); - // abort if now is outside the possible alarm range - if (tNow + settings.earlier * 6E4 < settings.from * 36E5 || - tNow + settings.earlier * 6E4 >= settings.to * 36E5) return; - - // execute trigger function - require("sleeplogalarm.trigger.js")(now, tNow); + // execute trigger function if now is inside the alarm range + if (tNow + settings.earlier * 6E4 >= settings.from * 36E5 && + tNow < settings.to * 36E5) require("sleeplogalarm.trigger.js")(now, tNow); }; } }; From f253d344fb10a50c270a22e9f4d984bb84e7e40f Mon Sep 17 00:00:00 2001 From: storm64 Date: Fri, 11 Nov 2022 17:17:07 +0100 Subject: [PATCH 11/73] [sleeplogalarm] Reworking wid->lib ... --- apps/sleeplogalarm/lib.js | 133 +++++++++++++++++++++++++++++++ apps/sleeplogalarm/metadata.json | 2 +- apps/sleeplogalarm/settings.js | 7 ++ apps/sleeplogalarm/trigger.js | 75 ----------------- apps/sleeplogalarm/widget.js | 56 +++---------- 5 files changed, 150 insertions(+), 123 deletions(-) create mode 100644 apps/sleeplogalarm/lib.js delete mode 100644 apps/sleeplogalarm/trigger.js diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js new file mode 100644 index 000000000..d7375f79a --- /dev/null +++ b/apps/sleeplogalarm/lib.js @@ -0,0 +1,133 @@ +// load library +var sched = require("sched"); + +// find next active alarm in range +function getNextAlarm(allAlarms, from, to, withId) { + if (withId) allAlarms = allAlarms.map((a, idx) => { + a.idx = idx; + return a; + }); + // return next + return sched.getActiveAlarms( + // filter for active alarms in range + allAlarms.filter(a => a.on && !a.timer && a.t >= from && a.t < to) + ).map(a => { + // add time to alarm + a.tTo = sched.getTimeToAlarm(a); + return a; + // sort to get next alarm first + }).sort((a, b) => a.tTo - b.tTo)[0] || {}; +} + +// calculate a time from its date +function dateToTime(date) { + return ((date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds()) * 1000; +} + +exports = { + // function to read settings with defaults + getSettings: function() { + return Object.assign({ + enabled: true, + hide: false, + drawTime: true, + color: g.theme.dark ? 65504 : 31, // yellow or blue + from: 4, // 0400 + to: 8, // 0800 + earlier: 30, + msgAsPrefix: true, + disableOnAlarm: false, // !!! not available if alarm is at the next day + msg: "...\n", + vibrate: "..", + as: true + }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); + }, + + // widget reload function + widReload: function() { + // abort if onChange is not available + if (typeof (global.sleeplog || {}).onChange !== "object") return; + + // read settings to calculate alarm range + var settings = this.getSettings(); + + // set the alarm time + this.time = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5).t; + + // abort if no alarm time could be found inside range + if (!this.time) return; + + // set widget width if not hidden + if (!this.hidden) this.width = 8; + + // insert sleeplogalarm function to onChange + sleeplog.onChange.sleeplogalarm = function (data) { + // abort if not changed from deep sleep to light sleep or awake + if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; + + // get settings from widget, now and calculate time of now + var settings = WIDGETS.sleeplogalarm; + var now = new Date(); + var tNow = dateToTime(now); + + // execute trigger function if inside the alarm range + if (tNow >= settings.time - settings.earlier * 6E4 && + tNow < settings.time) require("sleeplogalarm").trigger(now, tNow); + }; + }, + + // trigger function + trigger: function(now, tNow) { + // define settings + var settings = this.getSettings(); + + // calculate then date + var then = new Date(now + settings.earlier * 6E4); + + // read all alarms + var allAlarms = sched.getAlarms(); + + // find first active alarm + var alarm = firstActiveAlarm(allAlarms); + + // return if no alarm is found + if (!alarm) return; + + // disable early triggered alarm if set and now and then on the same day + if (settings.disableOnAlarm && now.getDate() === then.getDate()) { + // add indexes to find alarm to temporary disable + allAlarms = allAlarms.map((a, idx) => { + a.idx = idx; + return a; + }); + // get index of first active alarm + var idx = firstActiveAlarm(allAlarms).idx; + // set this alarms last to then + allAlarms[idx].last = then.getDate(); + // remove added indexes + allAlarms = allAlarms.map(a => { + delete a.idx; + return a; + }); + } + + // add new alarm for now with data from found alarm + allAlarms.push({ + id: "sleeplog", + appid: "sleeplog", + on: true, + t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), + dow: 127, + msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), + vibrate: settings.vibrate || alarm.vibrate, + as: settings.as, + del: true + }); + + // write changes + sched.setAlarms(allAlarms); + + // trigger sched.js + load("sched.js"); + } +}; \ No newline at end of file diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 198d8e07a..fc1d546da 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -11,8 +11,8 @@ "dependencies": {"sleeplog": "app"}, "readme": "README.md", "storage": [ + {"name": "sleeplogalarm", "url": "lib.js"}, {"name": "sleeplogalarm.settings.js", "url": "settings.js"}, - {"name": "sleeplogalarm.trigger.js", "url": "trigger.js"}, {"name": "sleeplogalarm.wid.js", "url": "widget.js"} ] } diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 8719761dd..f6787f3bd 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -148,6 +148,13 @@ writeSetting(); } ), + /*LANG*/"auto snooze": { + value: settings.as, + onchange: v => { + settings.as = v; + writeSetting(); + } + }, /*LANG*/"Widget": () => showWidMenu(), /*LANG*/"Enabled": { value: settings.enabled, diff --git a/apps/sleeplogalarm/trigger.js b/apps/sleeplogalarm/trigger.js deleted file mode 100644 index cc4dd6f12..000000000 --- a/apps/sleeplogalarm/trigger.js +++ /dev/null @@ -1,75 +0,0 @@ -exports = function(now, tNow) { - // define settings - var settings = Object.assign({ - from: 4, // 0400 - to: 8, // 0800 - earlier: 30, - msgAsPrefix: true, - disableOnAlarm: false, // !!! not available if alarm is at the next day - msg: "...\n", - vibrate: "..", - as: true - }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - - // calculate then date - var then = new Date(now + settings.earlier * 6E4); - - // load library - var sched = require("sched"); - - // define function to return first active alarm in range to come - function firstActiveAlarm(allAlarms) { - return (sched.getActiveAlarms(allAlarms.filter( - // filter for active alarms, ... - a => a.on && !a.timer && - // after now+10s and in alarm range - a.t > tNow && a.t >= settings.from * 36E5 && a.t < settings.to * 36E5 - ), then) || []).sort((a, b) => a.t > b.t)[0]; - } - - // read all alarms - var allAlarms = sched.getAlarms(); - - // find first active alarm - var alarm = firstActiveAlarm(allAlarms); - - // return if no alarm is found - if (!alarm) return; - - // disable early triggered alarm if set and now and then on the same day - if (settings.disableOnAlarm && now.getDate() === then.getDate()) { - // add indexes to find alarm to temporary disable - allAlarms = allAlarms.map((a, idx) => { - a.idx = idx; - return a; - }); - // get index of first active alarm - var idx = firstActiveAlarm(allAlarms).idx; - // set this alarms last to then - allAlarms[idx].last = then.getDate(); - // remove added indexes - allAlarms = allAlarms.map(a => { - delete a.idx; - return a; - }); - } - - // add new alarm for now with data from found alarm - allAlarms.push({ - id: "sleeplog", - appid: "sleeplog", - on: true, - t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), - dow: 127, - msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), - vibrate: settings.vibrate || alarm.vibrate, - as: settings.as, - del: true - }); - - // write changes - sched.setAlarms(allAlarms); - - // trigger sched.js - load("sched.js"); -}; \ No newline at end of file diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 5ccc57cda..d0e60b488 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,64 +1,26 @@ -// read settings to calculate alarm range -settings = Object.assign({ // if using var here settings will always be undefined - enabled: true, - hide: false, - drawRange: true, - color: g.theme.dark ? 65504 : 31, // yellow or blue - from: 4, // 0400 - to: 8, // 0800 - earlier: 30 -}, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); - // check if enabled in settings -if (settings.enabled) { +if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enabled: true}).enabled) { // insert neccessary settings into widget WIDGETS.sleeplogalarm = { area: "tl", width: 0, - drawRange: settings.drawRange, + drawTime: settings.drawTime, color: settings.color, - from: settings.from, - to: settings.to, + time: 0, earlier: settings.earlier, draw: function () { // draw zzz g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); - // draw alarm range times if enabled - if (this.drawRange) { + // draw time of alarm if enabled + if (this.drawTime && this.time) { // directly include Font4x5Numeric - g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5); - g.drawString(this.from, this.x + 1, this.y + 12); - g.setFontAlign(1, 1).drawString(this.to, this.x + this.width + 1, this.y + 23); + g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); + g.drawString(0|(this.time / 36E5), this.x + this.width + 1, this.y + 12); + g.drawString(0|((this.time / 36E5)%1 * 60), this.x + this.width + 1, this.y + 23); } }, - reload: function () { - // abort if onChange is not available - if (typeof (global.sleeplog || {}).onChange !== "object") return; - - // abort if no alarm exists inside range - if (!(require("Storage").readJSON("sched.json", 1) || []) - .filter(a => a.on && !a.timer) - .some(a => a.t >= this.from * 36E5 && a.t < this.to * 36E5)) return; - - // set widget width if not hidden - if (!this.hidden) this.width = 8; - - // insert sleeplogalarm function to onChange - sleeplog.onChange.sleeplogalarm = function (data) { - // abort if not changed from deep sleep to light sleep or awake - if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; - - // get cahed data, now and calculate time of now - var settings = WIDGETS.sleeplogalarm; - var now = new Date(); - var tNow = (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000); - - // execute trigger function if now is inside the alarm range - if (tNow + settings.earlier * 6E4 >= settings.from * 36E5 && - tNow < settings.to * 36E5) require("sleeplogalarm.trigger.js")(now, tNow); - }; - } + reload: require("sleeplogalarm").widReload() }; // load widget From e92bd01fc8b50cb7ed53d2e5f404c6705f7d9b4f Mon Sep 17 00:00:00 2001 From: storm64 Date: Sat, 12 Nov 2022 00:16:39 +0100 Subject: [PATCH 12/73] [sleeplogalarm] Finish transfer to lib --- apps/sleeplogalarm/lib.js | 34 +++++++++++----------------------- apps/sleeplogalarm/settings.js | 22 +++------------------- apps/sleeplogalarm/widget.js | 22 ++++++++++++++-------- 3 files changed, 28 insertions(+), 50 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index d7375f79a..d5fb87a65 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -19,11 +19,6 @@ function getNextAlarm(allAlarms, from, to, withId) { }).sort((a, b) => a.tTo - b.tTo)[0] || {}; } -// calculate a time from its date -function dateToTime(date) { - return ((date.getHours() * 60 + date.getMinutes()) * 60 + date.getSeconds()) * 1000; -} - exports = { // function to read settings with defaults getSettings: function() { @@ -68,7 +63,7 @@ exports = { // get settings from widget, now and calculate time of now var settings = WIDGETS.sleeplogalarm; var now = new Date(); - var tNow = dateToTime(now); + var tNow = ((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000; // execute trigger function if inside the alarm range if (tNow >= settings.time - settings.earlier * 6E4 && @@ -78,32 +73,25 @@ exports = { // trigger function trigger: function(now, tNow) { - // define settings + // read settings var settings = this.getSettings(); - // calculate then date - var then = new Date(now + settings.earlier * 6E4); - // read all alarms var allAlarms = sched.getAlarms(); // find first active alarm - var alarm = firstActiveAlarm(allAlarms); + var alarm = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5, settings.disableOnAlarm); // return if no alarm is found if (!alarm) return; - // disable early triggered alarm if set and now and then on the same day - if (settings.disableOnAlarm && now.getDate() === then.getDate()) { - // add indexes to find alarm to temporary disable - allAlarms = allAlarms.map((a, idx) => { - a.idx = idx; - return a; - }); - // get index of first active alarm - var idx = firstActiveAlarm(allAlarms).idx; - // set this alarms last to then - allAlarms[idx].last = then.getDate(); + // get date of the alarm + var aDate = new Date(now + alarm.tTo).getDate(); + + // disable earlier triggered alarm if set and on the same day + if (settings.disableOnAlarm && now.getDate() === aDate) { + // set alarms last to today + allAlarms[alarm.idx].last = aDate; // remove added indexes allAlarms = allAlarms.map(a => { delete a.idx; @@ -116,7 +104,7 @@ exports = { id: "sleeplog", appid: "sleeplog", on: true, - t: (((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000), + t: tNow, dow: 127, msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), vibrate: settings.vibrate || alarm.vibrate, diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index f6787f3bd..2447a20aa 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -1,26 +1,10 @@ (function(back) { - // define settings filename - var filename = "sleeplogalarm.settings.json"; - - // define settings - var settings = Object.assign({ - enabled: true, - hide: false, - drawRange: true, - color: g.theme.dark ? 65504 : 31, // yellow or blue - from: 4, // 0400 - to: 8, // 0800 - earlier: 30, - disableOnAlarm: false, // !!! not available if alarm is at the next day - msg: "...\n", - msgAsPrefix: true, - vibrate: "..", - as: true - }, require("Storage").readJSON(filename, true) || {}); + // read settings + var settings = require("sleeplogalarm").getSettings(); // write change to storage function writeSetting() { - require("Storage").writeJSON(filename, settings); + require("Storage").writeJSON("sleeplogalarm.settings.json", settings); } // show widget menu diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index d0e60b488..ee5e06fcb 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,5 +1,7 @@ // check if enabled in settings if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enabled: true}).enabled) { + // read settings + var settings = require("sleeplogalarm").getSettings(); // insert neccessary settings into widget WIDGETS.sleeplogalarm = { @@ -11,18 +13,22 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable earlier: settings.earlier, draw: function () { // draw zzz - g.reset().setColor(this.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); - // draw time of alarm if enabled - if (this.drawTime && this.time) { - // directly include Font4x5Numeric - g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); - g.drawString(0|(this.time / 36E5), this.x + this.width + 1, this.y + 12); - g.drawString(0|((this.time / 36E5)%1 * 60), this.x + this.width + 1, this.y + 23); - } + g.reset().setColor(settings.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); + // call function to draw the time of alarm if a alarm is found + if (this.time) this.drawTime(this.time); }, + drawTime: () => {}, reload: require("sleeplogalarm").widReload() }; + // add function to draw the time of alarm if enabled + if (this.drawTime) WIDGETS.sleeplogalarm.drawTime = function(time) { + // directly include Font4x5Numeric + g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); + g.drawString(0|(time / 36E5), this.x + this.width + 1, this.y + 12); + g.drawString(0|((time / 36E5)%1 * 60), this.x + this.width + 1, this.y + 23); + }; + // load widget WIDGETS.sleeplogalarm.reload(); } \ No newline at end of file From bc99316979698bf6d3f2274bccab02d67da8d000 Mon Sep 17 00:00:00 2001 From: storm64 Date: Sat, 12 Nov 2022 00:19:36 +0100 Subject: [PATCH 13/73] [sleeplogalarm] Clear dublicates in widget --- apps/sleeplogalarm/widget.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index ee5e06fcb..a8bedaa13 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -7,8 +7,6 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable WIDGETS.sleeplogalarm = { area: "tl", width: 0, - drawTime: settings.drawTime, - color: settings.color, time: 0, earlier: settings.earlier, draw: function () { From 111a194e573dd212c4e8541f1609581de9c417ef Mon Sep 17 00:00:00 2001 From: storm64 Date: Sat, 12 Nov 2022 01:42:31 +0100 Subject: [PATCH 14/73] [sleeplogalarm] Corrections, prevent retrigger --- apps/sleeplogalarm/lib.js | 25 +++++++++++++++---------- apps/sleeplogalarm/widget.js | 10 +++++----- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index d5fb87a65..7f513221f 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -7,16 +7,15 @@ function getNextAlarm(allAlarms, from, to, withId) { a.idx = idx; return a; }); - // return next - return sched.getActiveAlarms( - // filter for active alarms in range - allAlarms.filter(a => a.on && !a.timer && a.t >= from && a.t < to) - ).map(a => { - // add time to alarm + // return next active alarms in range + return allAlarms.filter( + a => a.on && !a.timer && a.t >= from && a.t < to + ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; - // sort to get next alarm first - }).sort((a, b) => a.tTo - b.tTo)[0] || {}; + }).filter(a => a.tTo // filter non active alarms + // sort to get next alarm first + ).sort((a, b) => a.tTo - b.tTo)[0] || {}; } exports = { @@ -44,7 +43,7 @@ exports = { if (typeof (global.sleeplog || {}).onChange !== "object") return; // read settings to calculate alarm range - var settings = this.getSettings(); + var settings = exports.getSettings(); // set the alarm time this.time = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5).t; @@ -55,6 +54,9 @@ exports = { // set widget width if not hidden if (!this.hidden) this.width = 8; + // abort if already alarmed for this alarm + if (sleeplog.onChange.sleeplogalarm == this.time) return; + // insert sleeplogalarm function to onChange sleeplog.onChange.sleeplogalarm = function (data) { // abort if not changed from deep sleep to light sleep or awake @@ -74,7 +76,7 @@ exports = { // trigger function trigger: function(now, tNow) { // read settings - var settings = this.getSettings(); + var settings = exports.getSettings(); // read all alarms var allAlarms = sched.getAlarms(); @@ -82,6 +84,9 @@ exports = { // find first active alarm var alarm = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5, settings.disableOnAlarm); + // clear sleeplog.onChange function and set alarm time to prevent resetting for this alarm + sleeplog.onChange.sleeplogalarm = alarm.t; + // return if no alarm is found if (!alarm) return; diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index a8bedaa13..96f4e7740 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -1,7 +1,7 @@ // check if enabled in settings if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enabled: true}).enabled) { // read settings - var settings = require("sleeplogalarm").getSettings(); + settings = require("sleeplogalarm").getSettings(); // is undefined if used with var // insert neccessary settings into widget WIDGETS.sleeplogalarm = { @@ -13,17 +13,17 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable // draw zzz g.reset().setColor(settings.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); // call function to draw the time of alarm if a alarm is found - if (this.time) this.drawTime(this.time); + if (this.time) this.drawTime(this.time + 1); }, drawTime: () => {}, - reload: require("sleeplogalarm").widReload() + reload: require("sleeplogalarm").widReload }; // add function to draw the time of alarm if enabled - if (this.drawTime) WIDGETS.sleeplogalarm.drawTime = function(time) { + if (settings.drawTime) WIDGETS.sleeplogalarm.drawTime = function(time) { // directly include Font4x5Numeric g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); - g.drawString(0|(time / 36E5), this.x + this.width + 1, this.y + 12); + g.drawString(0|(time / 36E5), this.x + this.width + 1, this.y + 17); g.drawString(0|((time / 36E5)%1 * 60), this.x + this.width + 1, this.y + 23); }; From 8d54208aded24279c2cfff3e238de828642b33a5 Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 16 Nov 2022 23:24:43 +0100 Subject: [PATCH 15/73] [sleeplogalarm] Update using sleeplog.trigger --- apps/sleeplogalarm/lib.js | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 7f513221f..ea19d04e2 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -39,8 +39,8 @@ exports = { // widget reload function widReload: function() { - // abort if onChange is not available - if (typeof (global.sleeplog || {}).onChange !== "object") return; + // abort if trigger object is not available + if (typeof (global.sleeplog || {}).trigger !== "object") return; // read settings to calculate alarm range var settings = exports.getSettings(); @@ -55,26 +55,22 @@ exports = { if (!this.hidden) this.width = 8; // abort if already alarmed for this alarm - if (sleeplog.onChange.sleeplogalarm == this.time) return; + if ((sleeplog.trigger.sleeplogalarm || {}).last == this.time) return; - // insert sleeplogalarm function to onChange - sleeplog.onChange.sleeplogalarm = function (data) { - // abort if not changed from deep sleep to light sleep or awake - if (data.prevStatus !== 4 || !(data.status === 3 || data.status === 2)) return; - - // get settings from widget, now and calculate time of now - var settings = WIDGETS.sleeplogalarm; - var now = new Date(); - var tNow = ((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000; - - // execute trigger function if inside the alarm range - if (tNow >= settings.time - settings.earlier * 6E4 && - tNow < settings.time) require("sleeplogalarm").trigger(now, tNow); + // insert sleeplogalarm conditions and function + sleeplog.trigger.sleeplogalarm = { + from: settings.time - settings.earlier * 6E4, + to: settings.time - 1, + fn: function (data) { + // execute trigger function if on light sleep or awake + if (data.status === 3 || data.status === 2) + require("sleeplogalarm").trigger(); + } }; }, // trigger function - trigger: function(now, tNow) { + trigger: function(tNow) { // read settings var settings = exports.getSettings(); @@ -84,12 +80,15 @@ exports = { // find first active alarm var alarm = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5, settings.disableOnAlarm); - // clear sleeplog.onChange function and set alarm time to prevent resetting for this alarm - sleeplog.onChange.sleeplogalarm = alarm.t; + // clear sleeplog.trigger object and set alarm time to prevent resetting for this alarm + sleeplog.trigger.sleeplogalarm = {last: alarm.t}; // return if no alarm is found if (!alarm) return; + // get now + var now = new Date(); + // get date of the alarm var aDate = new Date(now + alarm.tTo).getDate(); @@ -109,7 +108,7 @@ exports = { id: "sleeplog", appid: "sleeplog", on: true, - t: tNow, + t: ((time.getHours() * 60 + time.getMinutes()) * 60 + time.getSeconds()) * 1000, dow: 127, msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), vibrate: settings.vibrate || alarm.vibrate, From 550b95d9692304262314901bf8f1edbe5b8c594f Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 09:33:00 +0100 Subject: [PATCH 16/73] [sleeplogalarm] Correct times in sleeplog.trigger --- apps/sleeplogalarm/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index ea19d04e2..7701d2624 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -59,8 +59,8 @@ exports = { // insert sleeplogalarm conditions and function sleeplog.trigger.sleeplogalarm = { - from: settings.time - settings.earlier * 6E4, - to: settings.time - 1, + from: this.time - settings.earlier * 6E4, + to: this.time - 1, fn: function (data) { // execute trigger function if on light sleep or awake if (data.status === 3 || data.status === 2) From 572020430773ce2f753bb964ff0d2bf5855bda14 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 10:32:55 +0100 Subject: [PATCH 17/73] [sleeplogalarm] Correct t inside created alarm --- apps/sleeplogalarm/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 7701d2624..25bdfdbe4 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -70,7 +70,7 @@ exports = { }, // trigger function - trigger: function(tNow) { + trigger: function() { // read settings var settings = exports.getSettings(); @@ -108,7 +108,7 @@ exports = { id: "sleeplog", appid: "sleeplog", on: true, - t: ((time.getHours() * 60 + time.getMinutes()) * 60 + time.getSeconds()) * 1000, + t: ((now.getHours() * 60 + now.getMinutes()) * 60 + now.getSeconds()) * 1000, dow: 127, msg: settings.msg + (settings.msgAsPrefix ? alarm.msg || "" : ""), vibrate: settings.vibrate || alarm.vibrate, From 8800ba8fdaec6898be8fe015ab5c586f72473b9e Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 15:16:18 +0100 Subject: [PATCH 18/73] [sleeplogalarm] Reorder settings + filter for msg --- apps/sleeplogalarm/lib.js | 25 +++--- apps/sleeplogalarm/settings.js | 134 ++++++++++++++++++++------------- apps/sleeplogalarm/widget.js | 4 +- 3 files changed, 95 insertions(+), 68 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 25bdfdbe4..8beb64ffd 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -2,14 +2,14 @@ var sched = require("sched"); // find next active alarm in range -function getNextAlarm(allAlarms, from, to, withId) { +function getNextAlarm(allAlarms, from, to, msg, withId) { if (withId) allAlarms = allAlarms.map((a, idx) => { a.idx = idx; return a; }); // return next active alarms in range return allAlarms.filter( - a => a.on && !a.timer && a.t >= from && a.t < to + a => a.on && !a.timer && a.t >= from && a.t < to && (!msg || a.msg.includes(msg)) ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; @@ -23,17 +23,18 @@ exports = { getSettings: function() { return Object.assign({ enabled: true, - hide: false, - drawTime: true, - color: g.theme.dark ? 65504 : 31, // yellow or blue - from: 4, // 0400 - to: 8, // 0800 earlier: 30, + filter_from: 0, + filter_to: 24, + filter_msg: "", + vibrate: "..", + msg: "...\n", msgAsPrefix: true, disableOnAlarm: false, // !!! not available if alarm is at the next day - msg: "...\n", - vibrate: "..", - as: true + as: true, + wid_hide: false, + wid_time: true, + wid_color: g.theme.dark ? 65504 : 31, // yellow or blue }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); }, @@ -46,7 +47,7 @@ exports = { var settings = exports.getSettings(); // set the alarm time - this.time = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5).t; + this.time = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings,filter_msg).t; // abort if no alarm time could be found inside range if (!this.time) return; @@ -78,7 +79,7 @@ exports = { var allAlarms = sched.getAlarms(); // find first active alarm - var alarm = getNextAlarm(sched.getAlarms(), settings.from * 36E5, settings.to * 36E5, settings.disableOnAlarm); + var alarm = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings,filter_msg, settings.disableOnAlarm); // clear sleeplog.trigger object and set alarm time to prevent resetting for this alarm sleeplog.trigger.sleeplogalarm = {last: alarm.t}; diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 2447a20aa..c62f6a273 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -7,6 +7,66 @@ require("Storage").writeJSON("sleeplogalarm.settings.json", settings); } + // read input from keyboard + function readInput(setting, retPos, cb) { + setTimeout((setting, retPos, cb) => { + if (require("Storage").read("textinput")) { + g.clear(); + require("textinput").input({text: settings[setting]}).then(result => { + settings[setting] = result; + writeSetting(); + cb(retPos); + }); + } else { + E.showAlert(/*LANG*/"No keyboard app installed").then(() => cb(retPos)); + } + }, 0, setting, retPos, cb); + } + + // show widget menu + function showFilterMenu() { + // set menu + var filterMenu = { + "": { + title: "Filter Alarm" + }, + /*LANG*/"< Back": () => showMain(2), + /*LANG*/"time from": { + value: settings.filter_from, + step: 0.25, + min: 0, + max: 23, + wrap: true, + noList: true, + format: v => 0|v + ":" + ("" + 0|(v%1 * 60)).padStart(2, "0"), + onchange: v => { + settings.filter_from = v; + writeSetting(); + } + }, + /*LANG*/"time to": { + value: settings.filter_to, + step: 0.25, + min: 1, + max: 24, + wrap: true, + noList: true, + format: v => 0|v + ":" + ("" + 0|(v%1 * 60)).padStart(2, "0"), + onchange: v => { + settings.filter_to = v; + writeSetting(); + } + }, + /*LANG*/"msg includes": { + value: settings.filter_msg, + format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, + // setTimeout required to load after menu refresh + onchange: () => readInput("filter_msg", 3, showFilterMenu) + } + }; + var menu = E.showMenu(filterMenu); + } + // show widget menu function showWidMenu() { // define color values and names @@ -18,29 +78,29 @@ "": { title: "Widget Settings" }, - /*LANG*/"< Back": () => showMain(7), + /*LANG*/"< Back": () => showMain(8), /*LANG*/"hide": { - value: settings.hide, + value: settings.wid_hide, onchange: v => { - settings.hide = v; + settings.wid_hide = v; writeSetting(); } }, - /*LANG*/"time range": { - value: settings.drawRange, + /*LANG*/"show time": { + value: settings.wid_time, onchange: v => { - settings.drawRange = v; + settings.wid_time = v; writeSetting(); } }, /*LANG*/"color": { - value: colVal.indexOf(settings.color), + value: colVal.indexOf(settings.wid_color), min: 0, max: colVal.length -1, wrap: true, format: v => colName[v], onchange: v => { - settings.color = colVal[v]; + settings.wid_color = colVal[v]; writeSetting(); } } @@ -57,30 +117,6 @@ selected: selected }, /*LANG*/"< Back": () => back(), - /*LANG*/"time from": { - value: settings.from, - min: 0, - max: 23, - wrap: true, - noList: true, - format: v => v + ":00", - onchange: v => { - settings.from = v; - writeSetting(); - } - }, - /*LANG*/"time to": { - value: settings.to, - min: 1, - max: 24, - wrap: true, - noList: true, - format: v => v + ":00", - onchange: v => { - settings.to = v; - writeSetting(); - } - }, /*LANG*/"erlier": { value: settings.earlier, step: 10, @@ -94,29 +130,19 @@ writeSetting(); } }, - /*LANG*/"disable alarm": { - value: settings.disableOnAlarm, - onchange: v => { - settings.disableOnAlarm = v; + /*LANG*/"Filter Alarm": () => showFilterMenu(), + /*LANG*/"vib pattern": require("buzz_menu").pattern( + settings.vibrate, + v => { + settings.vibrate = v; writeSetting(); } - }, + ), /*LANG*/"msg": { value: settings.msg, format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, // setTimeout required to load after menu refresh - onchange: () => setTimeout((msg, cb) => { - if (require("Storage").read("textinput")) { - g.clear(); - require("textinput").input({text: msg}).then(result => { - settings.msg = result; - writeSetting(); - cb(7); - }); - } else { - E.showAlert(/*LANG*/"No keyboard app installed").then(() => cb(7)); - } - }, 0, settings.msg, showMain), + onchange: () => readInput("msg", 4, showMain) }, /*LANG*/"msg as prefix": { value: settings.msgAsPrefix, @@ -125,13 +151,13 @@ writeSetting(); } }, - /*LANG*/"vib pattern": require("buzz_menu").pattern( - settings.vibrate, - v => { - settings.vibrate = v; + /*LANG*/"disable alarm": { + value: settings.disableOnAlarm, + onchange: v => { + settings.disableOnAlarm = v; writeSetting(); } - ), + }, /*LANG*/"auto snooze": { value: settings.as, onchange: v => { diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 96f4e7740..991238140 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -11,7 +11,7 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable earlier: settings.earlier, draw: function () { // draw zzz - g.reset().setColor(settings.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); + g.reset().setColor(settings.wid_color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); // call function to draw the time of alarm if a alarm is found if (this.time) this.drawTime(this.time + 1); }, @@ -20,7 +20,7 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable }; // add function to draw the time of alarm if enabled - if (settings.drawTime) WIDGETS.sleeplogalarm.drawTime = function(time) { + if (settings.wid_time) WIDGETS.sleeplogalarm.drawTime = function(time) { // directly include Font4x5Numeric g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); g.drawString(0|(time / 36E5), this.x + this.width + 1, this.y + 17); From 67d6da813ec9d599274e285d32bcd2320992a19b Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 16:32:47 +0100 Subject: [PATCH 19/73] [sleeplogalarm] Correct typo --- apps/sleeplogalarm/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 8beb64ffd..f38945fb4 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -47,7 +47,7 @@ exports = { var settings = exports.getSettings(); // set the alarm time - this.time = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings,filter_msg).t; + this.time = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings.filter_msg).t; // abort if no alarm time could be found inside range if (!this.time) return; @@ -79,7 +79,7 @@ exports = { var allAlarms = sched.getAlarms(); // find first active alarm - var alarm = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings,filter_msg, settings.disableOnAlarm); + var alarm = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings.filter_msg, settings.disableOnAlarm); // clear sleeplog.trigger object and set alarm time to prevent resetting for this alarm sleeplog.trigger.sleeplogalarm = {last: alarm.t}; From 9def5a8ee3f427c7cbc440e761f93ece12835c9c Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 17:09:18 +0100 Subject: [PATCH 20/73] [sleeplogalarm] Don't show own alarm --- apps/sleeplogalarm/lib.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index f38945fb4..716c69c3d 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -9,7 +9,8 @@ function getNextAlarm(allAlarms, from, to, msg, withId) { }); // return next active alarms in range return allAlarms.filter( - a => a.on && !a.timer && a.t >= from && a.t < to && (!msg || a.msg.includes(msg)) + a => a.on && !a.timer && a.id !== "sleeplog" && + a.t >= from && a.t < to && (!msg || a.msg.includes(msg)) ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; From c25750ebc1df501162113462cdd70b569bd3092b Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 17:44:36 +0100 Subject: [PATCH 21/73] [sleeplogalarm] Correct times display in settings --- apps/sleeplogalarm/settings.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index c62f6a273..fe774c3b2 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -38,7 +38,7 @@ max: 23, wrap: true, noList: true, - format: v => 0|v + ":" + ("" + 0|(v%1 * 60)).padStart(2, "0"), + format: v => (0|v) + ":" + ("" + (0|(v%1 * 60))).padStart(2, "0"), onchange: v => { settings.filter_from = v; writeSetting(); @@ -51,7 +51,7 @@ max: 24, wrap: true, noList: true, - format: v => 0|v + ":" + ("" + 0|(v%1 * 60)).padStart(2, "0"), + format: v => (0|v) + ":" + ("" + (0|(v%1 * 60))).padStart(2, "0"), onchange: v => { settings.filter_to = v; writeSetting(); From a49f902f027cffe2cd48d5243cbce7b11f5f625b Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 17 Nov 2022 17:52:18 +0100 Subject: [PATCH 22/73] [sleeplogalarm] Adjust default filter times --- apps/sleeplogalarm/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 716c69c3d..739670673 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -25,8 +25,8 @@ exports = { return Object.assign({ enabled: true, earlier: 30, - filter_from: 0, - filter_to: 24, + filter_from: 3, + filter_to: 12, filter_msg: "", vibrate: "..", msg: "...\n", From 69d0890cfa86d3ee8654e24c1f2df052de9db6d9 Mon Sep 17 00:00:00 2001 From: storm64 Date: Fri, 18 Nov 2022 15:26:15 +0100 Subject: [PATCH 23/73] [sleeplogalarm] Alarm only once each alarm --- apps/sleeplogalarm/lib.js | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 739670673..f899ae54e 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -2,15 +2,19 @@ var sched = require("sched"); // find next active alarm in range -function getNextAlarm(allAlarms, from, to, msg, withId) { +function getNextAlarm(allAlarms, fo, withId) { if (withId) allAlarms = allAlarms.map((a, idx) => { a.idx = idx; return a; }); - // return next active alarms in range + // return next active alarms in range, filter for + // active, not timer, not own alarm, + // after from, before to, includes msg + // not lastTime, not lastDay return allAlarms.filter( a => a.on && !a.timer && a.id !== "sleeplog" && - a.t >= from && a.t < to && (!msg || a.msg.includes(msg)) + a.t >= fo.from && a.t < fo.to && (!fo.msg || a.msg.includes(fo.msg)) && + fo.lastTime !== a.t && fo.lastDay !== a.last ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; @@ -48,7 +52,13 @@ exports = { var settings = exports.getSettings(); // set the alarm time - this.time = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings.filter_msg).t; + this.time = getNextAlarm(sched.getAlarms(), { + from: settings.filter_from * 36E5, + to: settings.filter_to * 36E5, + msg: settings.filter_msg, + lastTime: settings.lastTime, + lastDay: settings.lastDay + }).t; // abort if no alarm time could be found inside range if (!this.time) return; @@ -56,9 +66,6 @@ exports = { // set widget width if not hidden if (!this.hidden) this.width = 8; - // abort if already alarmed for this alarm - if ((sleeplog.trigger.sleeplogalarm || {}).last == this.time) return; - // insert sleeplogalarm conditions and function sleeplog.trigger.sleeplogalarm = { from: this.time - settings.earlier * 6E4, @@ -80,10 +87,13 @@ exports = { var allAlarms = sched.getAlarms(); // find first active alarm - var alarm = getNextAlarm(sched.getAlarms(), settings.filter_from * 36E5, settings.filter_to * 36E5, settings.filter_msg, settings.disableOnAlarm); - - // clear sleeplog.trigger object and set alarm time to prevent resetting for this alarm - sleeplog.trigger.sleeplogalarm = {last: alarm.t}; + var alarm = getNextAlarm(sched.getAlarms(), { + from: settings.filter_from * 36E5, + to: settings.filter_to * 36E5, + msg: settings.filter_msg, + lastTime: settings.lastTime, + lastDay: settings.lastDay + }, settings.disableOnAlarm); // return if no alarm is found if (!alarm) return; @@ -118,6 +128,11 @@ exports = { del: true }); + // save time of alarm and this day to prevent triggering for the same alarm again + settings.lastTime = alarm.t; + settings.lastDay = now.getDay(); + require("Storage").writeJSON("sleeplogalarm.settings.json", settings); + // write changes sched.setAlarms(allAlarms); From 8c4c514059dd4daa83040509041f2c8189c77c47 Mon Sep 17 00:00:00 2001 From: storm64 Date: Fri, 18 Nov 2022 23:08:41 +0100 Subject: [PATCH 24/73] [sleeplogalarm] Add setting + explanations, icon --- apps/sleeplogalarm/ChangeLog | 1 + apps/sleeplogalarm/README.md | 49 +++++++++++++++++++------------ apps/sleeplogalarm/app.png | Bin 8089 -> 9048 bytes apps/sleeplogalarm/lib.js | 11 ++++--- apps/sleeplogalarm/metadata.json | 2 +- apps/sleeplogalarm/settings.js | 17 +++++++---- 6 files changed, 52 insertions(+), 28 deletions(-) diff --git a/apps/sleeplogalarm/ChangeLog b/apps/sleeplogalarm/ChangeLog index 5560f00bc..0030c8783 100644 --- a/apps/sleeplogalarm/ChangeLog +++ b/apps/sleeplogalarm/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Add "from Consec."-setting \ No newline at end of file diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 42c2d6074..184eb4b53 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -1,27 +1,40 @@ # Sleep Log Alarm -This widget searches for active alarms and raises the alarm event up to the defined time earlier, if in a light sleep phase. +This widget searches for active alarms and raises an own alarm event up to the defined time earlier, if in light sleep or awake phase. Optional the earlier alarm will only be triggered if comming from or in consecutive sleep. The settings of the earlier alarm can be adjusted and it is possible to filter the targeting alarms by time and message. By default the time of the targeting alarm is displayed inside the widget which can be adjusted, too. --- -### App Usage +### Settings --- -#### Inside the settings: !!! dummy entries !!! - - __Thresholds__ submenu - Changes take effect from now on, not retrospective! - - __Max Awake__ | maximal awake duration - _10min_ / _20min_ / ... / __60min__ / ... / _120min_ - - __Min Consecutive__ | minimal consecutive sleep duration - _10min_ / _20min_ / ... / __30min__ / ... / _120min_ - - __Deep Sleep__ | deep sleep threshold - _30_ / _31_ / ... / __100__ / ... / _200_ - - __Light Sleep__ | light sleep threshold - _100_ / _110_ / ... / __200__ / ... / _400_ - - __Reset to Default__ | reset to bold values above - - __BreakToD__ | time of day to break view - _0:00_ / _1:00_ / ... / __12:00__ / ... / _23:00_ - - __App Timeout__ | app specific lock timeout - __0s__ / _10s_ / ... / _120s_ + - __earlier__ | duration to trigger alarm earlier + _10min_ / _20min_ / __30min__ / ... / _120min_ + - __from Consec.__ | only trigger if comming from consecutive sleep + _on_ / __off__ + - __vib pattern__ | vibration pattern for the earlier alarm + __..__ / ... + - __msg__ | customized message for the earlier alarm + __...__ / ... + - __msg as prefix__ | use the customized message as prefix to the original message or replace it comlpetely if disabled + __on__ / _off_ + - __disable alarm__ | if enabled the original alarm will be disabled + _on_ / __off__ + This feature does not work for alarms on the next day! + - __auto snooze__ | auto snooze option for the earlier alarm + __on__ / _off_ + - __Filter Alarm__ submenu + - __time from__ | exclude alarms before this time + _0:00_ / _0:15_ / ... / __3:00__ / ... / _24:00_ + - __time to__ | exclude alarms after this time + _0:00_ / _0:15_ / ... / __12:00__ / ... / _24:00_ + - __msg includes__ | include only alarms including this string in msg + __""__ / ... + - __Widget__ submenu + - __hide__ | completely hide the widget + _on_ / __off__ + - __show time__ | show the time of the targeting alarm + __on__ / _off_ + - __color__ | color of the widget + _red_ / __yellow__ / ... / _white_ - __Enabled__ | completely en-/disables the background service __on__ / _off_ diff --git a/apps/sleeplogalarm/app.png b/apps/sleeplogalarm/app.png index 6efb22a3f666817408264ec02731f4ac13d1ffe8..1a8e53865734de9ba90390a489ea54ddaa4a12ec 100644 GIT binary patch delta 5615 zcmVaB^>EX>4U6ba`-PAZ2)IW&i+q+SQs{b{jE| zgx|S}SprG$x*T55nH|jX=L6YxY{#*k{PQwatd`U*HVG7}3Uti+pa0(Gzxatc1ruT} zsitK42{lyTcv0;AY3JG5aGuYPJg0d7?sM~c!t;^*y0WC_`hS8S6 z82mCm^TPY#<$PEq`|1aIa}xC7w$D;!N+F};q&9w~3d`1{?q>)D%b+qZHO!#A_nP-`Gw&fO3T7O~1l~!J5)zvmo+hTUuai^Vk*>$(q ztUYP{?eP~`b5GX%$&_B0U$e%iIlm0ylun}NjD&d;92w7=0s!qbXSTQyyk<^wW~*{t z^h`2p&Zg6hk-@N>kK4WE&iI>A&D?*KH{g)$ z)qe`r$N5#7FHObnx1;&fiN8Jm-wed+jom?d-PG~wlL!V-6-sp#-Xq9b=Ecq8c64#t zyoc{$ro4$y8nV}3viDXMk&uUky{jvW4;jvZPV(P&3`Ca0g2!idL>GbpQ*{#SQqkPD za-rVsMj&VPan3nr8r$^&d%)pI(G{G`8Gmxq%U5r9W*Koe1%@BhPrsJyDU`{TFr+x& ztsuHgXk;>-Wycu94^%t5PQp8#1d*tNujQ0ZsI<;SV^ceL zidplybMCciTpCfR+h~@%)%bMkR*&N#pe^o~MYA#kS?Sfg%$h)p*0IN*KzY4zr$j`( zA+&ozb>L#;qyvFu!nPsE2_cdPsbh_?a0Sb!2HflDUdqrq^Sy^n7>oIj%YUAs;>I6o ztx#zYcojcSt*Ei_VWm?mQK<=>X8=vC@Hi+q!OPKO!RpAhQAIVHTqF9?Z_&;JFUmG+ z+2*$9sjfwdl)MAXtLcgHAaQ%$dSbz z!m{=~WvTVMq$ON!JS(Ck!Nx?k#$01J3L$XQkurA;5w$2W2c!moMd}VEi7O&}B~Wi8 zAjs9&(SVh#9_J}v7-vj>sMMn^Yl9PjM!l41>p+)qvtiq*StDhhUw?=wnstbP_KcW$ zPAe{Ys14#22<2pE446XX6k35ZG89x==blOU8vF*0OyHjh*%VtwK~YbDlFUMY+6umG zWDrIoR6Ge>Iku;qQr(1=K;}JjL$Xo5R5b~4SQX(E1kc|Sbels<@LpYsbdS+#zExBX$>c678!8&A z8CNkLy)fTO=%)%AXv%P89z58Neuri1_M>P8pWtlj+m@}gf^EwUR1dgz9jV&39_(WQ z;o;fF?5o#=xso&t=8sF$~f{z5bRT<(9DU(=vOY^1B5 zTF(~6NXI!2@qY+Ua{vH^OmhT9>_o#yashUaZR33>DeraVZX6cDBODY;ht`??ka?!Q z9CKk3Fv6nXqXIk9E524A=^=Ql2PFsd4LkfI2bNb>6UivhayhVa7d`$L)bt<*;v!YE zm+BFz9;gU9+co(rYhJZ=Qo561U-?=BJ!)%wKjlx@1%Cn5@;BUy5+SvS@>N+S=a`_> zN*va~dPmxb<(!;n{Q%4Jbz3N$s9Oj$bcVsS%&k5tsh<(CICCd+{0D%i{`5>@I zZIbE>0;RRt-36eXRk|rw5m;#j=;uzxbYkJuxqnWLDKIf^tcGa?{)$s`&xJe?YML0O6{;0g~w{-CGRDSNC%r0P}p@k2-)1O&e^0 z${nFUa(6C8@Gd|LY|&|)5i7Kx-Uxf>YEWx{074h;yw;6I^YY@~k8!qLf)Q27{8k^q zN`JsvXTgs zlG~^FyLEWT4DYgNl*>ThbEms8Lc32WA=tPVW|+3klELY%Uw8{|7jndb$gwoK#kQ6lP6=~0P8fpV|g-++;et)ek&{f#oX4V;}T?GfG5T$~D^a$Dn&I&q?$4>>=`yX-b-Q^M5s<`Rwe!3}`-1@!J7U zAYUXt$&19B@M!#8<;zUftuAUjePKI0MfvuHr3{+ma{ic6g{Dmzu+w5VWPcwgKr7>+ zi54M4rNO62U;@bMHz7BFQ1-sy;UfrIugs?OD+hQNl#2Hw4=YKIX*6m{)&|PXLHXIKF;+)Oe8oRVAYP@HmgRLQBTcLi|Paq_% zL;k2SuEXh$TnCe}?9#O*hkxWCu8w1K1FPJ67zpNQ4o1vDy|aE#;@Z?z=9{x-78~$b zWY|YFolp|O;6%8KQ3s9r95%bHRjh6Drey*)o)(b#(+hNNO8-YkkYtcfT4tJ3*qYvr z?(l3McHJYxL-ylbKAe9}>K_){&L=nxt%*aoIJSC5&XH$YTtir4O@9GmYMa)&=*`+k zX_f?WVNDGk-5C$>b*~LK2ocSNH^-~qn3zHPh^pys0UbI>+R>}nGPK530W=WhifN^L z&km*;{PSLS*>kWkl0#Ld30t-}bk6PysOwGphWD)V$z`UhkbGU%Vq0I}}A zZXDg&YLRF2HPHvhv+>WpX2sQ7%ooBURF|Py8Cls9x3ghrgt*aK5v6C_GpNBV>+X6U z6}M;C)4$A^L{b~(uCfRY`ATJdvzK8{f22}L)9=ey=HL9WXMaV*u+meTR*V}yVXFc_@p5WsH-p#KO_QkFJRG&V?c)(P4srhKVG?Seu3b;M z0m=ZPZp~v4bbtQ{iB?e#qI}N%t9tp0F;FH*a!DR(94oxN3mES2Oo{o){-^#yxKjwO zqSM{k>&1JyvO#XSs{wQ)o#1-pKtrwOfqH^01oR#e8JeuHa=L4_x?S-N&Z&z|BTjhku?VIa(m4W_q6^08z#4(1DuD z0cs}H<(5(=(281<6&2y3`vEIbBDE=B#iV=%cdhl%6~zloEJDDHdrKt`j5m!v{n%7x zZRXkD9q)Y?JY9@$j ztY(Vtxqqo@&?@WJEJ!0N;*gVHeB)LnEZFzX6-YetHD+zOOY z%Ma!7_sE%llfx%+S_Qh*h3B}zhG|>6&8K=bmfv13_|tiMH9$|-h}(rQD`s?Rp<>El z2qttlO6W>@ZMWImEmg+Lx^~EPeSX&bI)9D97%3x7>g9ka=7^gX)rz-k*mt|`O!1i@ zMy8wg%>|tQwF39~^mRMYoH;6GJaeS5&m>hB*K^S~*PNx8pRDC4=`f#N@astD|4CWAO@;aM{NI%ME00}L(f@+;k$=X_ z!(;DR>}wADl)}uv^!T5(_~vhV{PPy0f~1#^hQs{pe;L@VJ|1^;OHR#aitsOjV169U zZ&b?sldS!}8Hlh!1OE$KJw3LvMw~AI00D$)LqkwWLqi~Na&Km7Y-Iodc$|HaJxIeq z9K~N-rJ@xv%Of!R;eYb`Bu1oUkK7uPLK-UBXo zfZ-=yG9*U|(Ddi?!220}Qx+Jw1-jSV-kSS3eE`zbRq_TnI0VKEl)dip?ymOU{yo#| z?+4Z-a?Y>o)SCbR4p(VZSaeuTOgdw4Z7yMCZ(?OGcx`Y100000JhQJ4ZvrG`VKiZ7 zGc`9YF)}w|Ei^e|F)cY`VPq{ZW-~Z7G&nF}Gc{$CLK2E9OlfX)cp?fQARtFcO;9>i zX>DawbYX39Jt8qSHaIviIWaaeGch+aG%=I-5^)MRR5CLN6RlYSH)5I9saGdeIfIxsRTFflqXFternM?+Ro22t-wA)ns8uVkk39e*&>G@C7g=6eLtZKY)#ep(`N4 zf+`^~(Z+uaG$?Z25E5TvsGk(6suSnEyLWdEU}0e{8lEE>o+BvVQPM#&{C(;AjOv+L z;JP9q6N!?Pvyhc^6ii3-qlA94jOyMjg1Bza>$oQu0l$gfh2wo+s%&Ht#VMjM6K?u0 zn!Zbt1+5keArlTo$^R8z#Btt^5>}Dd)rm+lpdx>)ssSSgS)7QdrHq}#vuZ#kgaVv$ zbE?A4ML-_pwRIs?Ur$m4Iy%wR2I3e~WLSH)(5yqrnA2!c$ee+qK{f{{zX4KbK=fJ_ zjDsUEY)+o;L$D63cL!NdtmFbjuT?=1+yN*{%R_KpWwrB1vn})$`LbeV1wn8KVCQ7b zr}}?@e+R_PLTRzRd%yjXPC#fIHEP6xUIJKaJo*p-T#7a-a&pW@`Z>VRk6G>IBw#tc z0Kqx{hKiL}h|xh&b0Dz*R__kLc@@AJfVatY3Ncz|TUSp;PvVEw=R})b@86OW-WxdV zU!8^K<1l9wVd-FLEo24EyMR)f!pRFs8j2sakQHEIVPWy7@d+`4!)mABSEc{}002ov JPDHLkV1l9g&OHDC delta 4759 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 diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index f899ae54e..71210f98b 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -29,14 +29,15 @@ exports = { return Object.assign({ enabled: true, earlier: 30, - filter_from: 3, - filter_to: 12, - filter_msg: "", + fromConsec: false, vibrate: "..", msg: "...\n", msgAsPrefix: true, disableOnAlarm: false, // !!! not available if alarm is at the next day as: true, + filter_from: 3, + filter_to: 12, + filter_msg: "", wid_hide: false, wid_time: true, wid_color: g.theme.dark ? 65504 : 31, // yellow or blue @@ -72,7 +73,9 @@ exports = { to: this.time - 1, fn: function (data) { // execute trigger function if on light sleep or awake - if (data.status === 3 || data.status === 2) + // and if set if comming from consecutive + if ((data.status === 3 || data.status === 2) && !settings.fromConsec || + data.consecutive === 3 || data.prevConsecutive === 3) require("sleeplogalarm").trigger(); } }; diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index fc1d546da..1a37ffcbf 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -2,7 +2,7 @@ "id":"sleeplogalarm", "name":"Sleep Log Alarm", "shortName": "SleepLogAlarm", - "version": "0.01", + "version": "0.02", "description": "Enhance your morning and let your alarms wake you up when you are in light sleep.", "icon": "app.png", "type": "widget", diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index fe774c3b2..3a37b7274 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -30,12 +30,12 @@ "": { title: "Filter Alarm" }, - /*LANG*/"< Back": () => showMain(2), + /*LANG*/"< Back": () => showMain(8), /*LANG*/"time from": { value: settings.filter_from, step: 0.25, min: 0, - max: 23, + max: 24, wrap: true, noList: true, format: v => (0|v) + ":" + ("" + (0|(v%1 * 60))).padStart(2, "0"), @@ -47,7 +47,7 @@ /*LANG*/"time to": { value: settings.filter_to, step: 0.25, - min: 1, + min: 0, max: 24, wrap: true, noList: true, @@ -78,7 +78,7 @@ "": { title: "Widget Settings" }, - /*LANG*/"< Back": () => showMain(8), + /*LANG*/"< Back": () => showMain(9), /*LANG*/"hide": { value: settings.wid_hide, onchange: v => { @@ -130,7 +130,13 @@ writeSetting(); } }, - /*LANG*/"Filter Alarm": () => showFilterMenu(), + /*LANG*/"from Consec.": { + value: settings.fromConsec, + onchange: v => { + settings.fromConsec = v; + writeSetting(); + } + }, /*LANG*/"vib pattern": require("buzz_menu").pattern( settings.vibrate, v => { @@ -165,6 +171,7 @@ writeSetting(); } }, + /*LANG*/"Filter Alarm": () => showFilterMenu(), /*LANG*/"Widget": () => showWidMenu(), /*LANG*/"Enabled": { value: settings.enabled, From 7ef5152c17492acdcae407e5b9b1377e0e6a06d9 Mon Sep 17 00:00:00 2001 From: storm64 Date: Fri, 18 Nov 2022 23:31:10 +0100 Subject: [PATCH 25/73] [sleeplogalarm] Clear ToDo-list --- apps/sleeplogalarm/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 184eb4b53..73847d6f1 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -42,9 +42,6 @@ This widget searches for active alarms and raises an own alarm event up to the d ### Worth Mentioning --- -#### To do list -- README.md - #### Requests, Bugs and Feedback Please leave requests and bug reports by raising an issue at [github.com/storm64/BangleApps](https://github.com/storm64/BangleApps) (or send me a [mail](mailto:banglejs@storm64.de)). From ad7161cc93ddfe668d71a5045b240017b0402791 Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 23 Nov 2022 18:11:42 +0100 Subject: [PATCH 26/73] [sleeplogalarm] Correct filter for last alarm --- apps/sleeplogalarm/ChangeLog | 3 ++- apps/sleeplogalarm/lib.js | 14 +++++++------- apps/sleeplogalarm/metadata.json | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/apps/sleeplogalarm/ChangeLog b/apps/sleeplogalarm/ChangeLog index 0030c8783..48d9a161d 100644 --- a/apps/sleeplogalarm/ChangeLog +++ b/apps/sleeplogalarm/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! -0.02: Add "from Consec."-setting \ No newline at end of file +0.02: Add "from Consec."-setting +0.03: Correct how to ignore last triggered alarm \ No newline at end of file diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 71210f98b..aaa97feed 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -8,13 +8,13 @@ function getNextAlarm(allAlarms, fo, withId) { return a; }); // return next active alarms in range, filter for - // active, not timer, not own alarm, - // after from, before to, includes msg - // not lastTime, not lastDay + // active && not timer && not own alarm && + // after from && before to && includes msg && + // lastDate not today || after lastTime return allAlarms.filter( a => a.on && !a.timer && a.id !== "sleeplog" && a.t >= fo.from && a.t < fo.to && (!fo.msg || a.msg.includes(fo.msg)) && - fo.lastTime !== a.t && fo.lastDay !== a.last + fo.lastDate !== new Date().getDate() || a.t > fo.lastTime ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; @@ -58,7 +58,7 @@ exports = { to: settings.filter_to * 36E5, msg: settings.filter_msg, lastTime: settings.lastTime, - lastDay: settings.lastDay + lastDate: settings.lastDate }).t; // abort if no alarm time could be found inside range @@ -95,7 +95,7 @@ exports = { to: settings.filter_to * 36E5, msg: settings.filter_msg, lastTime: settings.lastTime, - lastDay: settings.lastDay + lastDate: settings.lastDate }, settings.disableOnAlarm); // return if no alarm is found @@ -133,7 +133,7 @@ exports = { // save time of alarm and this day to prevent triggering for the same alarm again settings.lastTime = alarm.t; - settings.lastDay = now.getDay(); + settings.lastDate = now.getDay(); require("Storage").writeJSON("sleeplogalarm.settings.json", settings); // write changes diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 1a37ffcbf..813f0fe18 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -2,7 +2,7 @@ "id":"sleeplogalarm", "name":"Sleep Log Alarm", "shortName": "SleepLogAlarm", - "version": "0.02", + "version": "0.03", "description": "Enhance your morning and let your alarms wake you up when you are in light sleep.", "icon": "app.png", "type": "widget", From ec37f35622e595906d333be184ae7fb8072eca06 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 24 Nov 2022 13:29:52 +0100 Subject: [PATCH 27/73] [sleeplogalarm] Replace getDay with getDate --- apps/sleeplogalarm/lib.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index aaa97feed..3162c3f86 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -18,7 +18,7 @@ function getNextAlarm(allAlarms, fo, withId) { ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; - }).filter(a => a.tTo // filter non active alarms + }).filter(a => a.tTo // filter non active alarms // sort to get next alarm first ).sort((a, b) => a.tTo - b.tTo)[0] || {}; } @@ -133,7 +133,7 @@ exports = { // save time of alarm and this day to prevent triggering for the same alarm again settings.lastTime = alarm.t; - settings.lastDate = now.getDay(); + settings.lastDate = now.getDate(); require("Storage").writeJSON("sleeplogalarm.settings.json", settings); // write changes From beab5405c73af3d8bfb91b7b8293f34ff7d6d19e Mon Sep 17 00:00:00 2001 From: storm64 Date: Mon, 28 Nov 2022 00:08:21 +0100 Subject: [PATCH 28/73] [sleeplogalarm] Correct filtering improve settings --- apps/sleeplogalarm/ChangeLog | 3 +- apps/sleeplogalarm/README.md | 3 +- apps/sleeplogalarm/lib.js | 64 +++++++++++++++----------------- apps/sleeplogalarm/metadata.json | 2 +- apps/sleeplogalarm/settings.js | 63 ++++++++++++++++--------------- apps/sleeplogalarm/widget.js | 4 +- 6 files changed, 69 insertions(+), 70 deletions(-) diff --git a/apps/sleeplogalarm/ChangeLog b/apps/sleeplogalarm/ChangeLog index 48d9a161d..80f8bd7e4 100644 --- a/apps/sleeplogalarm/ChangeLog +++ b/apps/sleeplogalarm/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Add "from Consec."-setting -0.03: Correct how to ignore last triggered alarm \ No newline at end of file +0.03: Correct how to ignore last triggered alarm +0.04: Make "disable alarm" possible on next day; correct alarm filtering; improve settings \ No newline at end of file diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 73847d6f1..29520dd09 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -17,8 +17,7 @@ This widget searches for active alarms and raises an own alarm event up to the d - __msg as prefix__ | use the customized message as prefix to the original message or replace it comlpetely if disabled __on__ / _off_ - __disable alarm__ | if enabled the original alarm will be disabled - _on_ / __off__ - This feature does not work for alarms on the next day! + _on_ / __off__ - __auto snooze__ | auto snooze option for the earlier alarm __on__ / _off_ - __Filter Alarm__ submenu diff --git a/apps/sleeplogalarm/lib.js b/apps/sleeplogalarm/lib.js index 3162c3f86..343e811af 100644 --- a/apps/sleeplogalarm/lib.js +++ b/apps/sleeplogalarm/lib.js @@ -9,18 +9,23 @@ function getNextAlarm(allAlarms, fo, withId) { }); // return next active alarms in range, filter for // active && not timer && not own alarm && - // after from && before to && includes msg && - // lastDate not today || after lastTime - return allAlarms.filter( + // after from && before to && includes msg + var ret = allAlarms.filter( a => a.on && !a.timer && a.id !== "sleeplog" && - a.t >= fo.from && a.t < fo.to && (!fo.msg || a.msg.includes(fo.msg)) && - fo.lastDate !== new Date().getDate() || a.t > fo.lastTime + a.t >= fo.from && a.t < fo.to && (!fo.msg || a.msg.includes(fo.msg)) ).map(a => { // add time to alarm a.tTo = sched.getTimeToAlarm(a); return a; }).filter(a => a.tTo // filter non active alarms // sort to get next alarm first - ).sort((a, b) => a.tTo - b.tTo)[0] || {}; + ).sort((a, b) => a.tTo - b.tTo); + // prevent triggering for an already triggered alarm again if available + if (fo.lastDate) { + var toLast = fo.lastDate - new Date().valueOf() + 1000; + if (toLast > 0) ret = ret.filter(a => a.tTo > toLast); + } + // return first entry + return ret[0] || {}; } exports = { @@ -35,12 +40,16 @@ exports = { msgAsPrefix: true, disableOnAlarm: false, // !!! not available if alarm is at the next day as: true, - filter_from: 3, - filter_to: 12, - filter_msg: "", - wid_hide: false, - wid_time: true, - wid_color: g.theme.dark ? 65504 : 31, // yellow or blue + filter: { + from: 3 * 36E5, + to: 12 * 36E5, + msg: "" + }, + wid: { + hide: false, + time: true, + color: g.theme.dark ? 65504 : 31 // yellow or blue + } }, require("Storage").readJSON("sleeplogalarm.settings.json", true) || {}); }, @@ -53,13 +62,7 @@ exports = { var settings = exports.getSettings(); // set the alarm time - this.time = getNextAlarm(sched.getAlarms(), { - from: settings.filter_from * 36E5, - to: settings.filter_to * 36E5, - msg: settings.filter_msg, - lastTime: settings.lastTime, - lastDate: settings.lastDate - }).t; + this.time = getNextAlarm(sched.getAlarms(), settings.filter).t; // abort if no alarm time could be found inside range if (!this.time) return; @@ -90,13 +93,7 @@ exports = { var allAlarms = sched.getAlarms(); // find first active alarm - var alarm = getNextAlarm(sched.getAlarms(), { - from: settings.filter_from * 36E5, - to: settings.filter_to * 36E5, - msg: settings.filter_msg, - lastTime: settings.lastTime, - lastDate: settings.lastDate - }, settings.disableOnAlarm); + var alarm = getNextAlarm(sched.getAlarms(), settings.filter, settings.disableOnAlarm); // return if no alarm is found if (!alarm) return; @@ -105,12 +102,12 @@ exports = { var now = new Date(); // get date of the alarm - var aDate = new Date(now + alarm.tTo).getDate(); + var aDate = new Date(now + alarm.tTo); - // disable earlier triggered alarm if set and on the same day - if (settings.disableOnAlarm && now.getDate() === aDate) { - // set alarms last to today - allAlarms[alarm.idx].last = aDate; + // disable earlier triggered alarm if set + if (settings.disableOnAlarm) { + // set alarms last to the day it would trigger + allAlarms[alarm.idx].last = aDate.getDate(); // remove added indexes allAlarms = allAlarms.map(a => { delete a.idx; @@ -131,9 +128,8 @@ exports = { del: true }); - // save time of alarm and this day to prevent triggering for the same alarm again - settings.lastTime = alarm.t; - settings.lastDate = now.getDate(); + // save date of the alarm to prevent triggering for the same alarm again + settings.filter.lastDate = aDate.valueOf(); require("Storage").writeJSON("sleeplogalarm.settings.json", settings); // write changes diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 813f0fe18..1930a0ee3 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -2,7 +2,7 @@ "id":"sleeplogalarm", "name":"Sleep Log Alarm", "shortName": "SleepLogAlarm", - "version": "0.03", + "version": "0.04", "description": "Enhance your morning and let your alarms wake you up when you are in light sleep.", "icon": "app.png", "type": "widget", diff --git a/apps/sleeplogalarm/settings.js b/apps/sleeplogalarm/settings.js index 3a37b7274..1f3a13272 100644 --- a/apps/sleeplogalarm/settings.js +++ b/apps/sleeplogalarm/settings.js @@ -8,19 +8,16 @@ } // read input from keyboard - function readInput(setting, retPos, cb) { - setTimeout((setting, retPos, cb) => { + function readInput(v, cb) { + // setTimeout required to load after menu refresh + setTimeout((v, cb) => { if (require("Storage").read("textinput")) { g.clear(); - require("textinput").input({text: settings[setting]}).then(result => { - settings[setting] = result; - writeSetting(); - cb(retPos); - }); + require("textinput").input({text: v}).then(v => cb(v)); } else { - E.showAlert(/*LANG*/"No keyboard app installed").then(() => cb(retPos)); + E.showAlert(/*LANG*/"No keyboard app installed").then(() => cb()); } - }, 0, setting, retPos, cb); + }, 0, v, cb); } // show widget menu @@ -32,36 +29,39 @@ }, /*LANG*/"< Back": () => showMain(8), /*LANG*/"time from": { - value: settings.filter_from, - step: 0.25, + value: settings.filter.from / 6E4, + step: 10, min: 0, - max: 24, + max: 1440, wrap: true, noList: true, - format: v => (0|v) + ":" + ("" + (0|(v%1 * 60))).padStart(2, "0"), + format: v => (0|v/60) + ":" + ("" + (v%60)).padStart(2, "0"), onchange: v => { - settings.filter_from = v; + settings.filter.from = v * 6E4; writeSetting(); } }, /*LANG*/"time to": { - value: settings.filter_to, - step: 0.25, + value: settings.filter.to / 6E4, + step: 10, min: 0, - max: 24, + max: 1440, wrap: true, noList: true, - format: v => (0|v) + ":" + ("" + (0|(v%1 * 60))).padStart(2, "0"), + format: v => (0|v/60) + ":" + ("" + (v%60)).padStart(2, "0"), onchange: v => { - settings.filter_to = v; + settings.filter.to = v * 6E4; writeSetting(); } }, /*LANG*/"msg includes": { - value: settings.filter_msg, + value: settings.filter.msg, format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, - // setTimeout required to load after menu refresh - onchange: () => readInput("filter_msg", 3, showFilterMenu) + onchange: v => readInput(v, v => { + settings.filter.msg = v; + writeSetting(); + showFilterMenu(3); + }) } }; var menu = E.showMenu(filterMenu); @@ -80,27 +80,27 @@ }, /*LANG*/"< Back": () => showMain(9), /*LANG*/"hide": { - value: settings.wid_hide, + value: settings.wid.hide, onchange: v => { - settings.wid_hide = v; + settings.wid.hide = v; writeSetting(); } }, /*LANG*/"show time": { - value: settings.wid_time, + value: settings.wid.time, onchange: v => { - settings.wid_time = v; + settings.wid.time = v; writeSetting(); } }, /*LANG*/"color": { - value: colVal.indexOf(settings.wid_color), + value: colVal.indexOf(settings.wid.color), min: 0, max: colVal.length -1, wrap: true, format: v => colName[v], onchange: v => { - settings.wid_color = colVal[v]; + settings.wid.color = colVal[v]; writeSetting(); } } @@ -147,8 +147,11 @@ /*LANG*/"msg": { value: settings.msg, format: v => !v ? "" : v.length > 6 ? v.substring(0, 6)+"..." : v, - // setTimeout required to load after menu refresh - onchange: () => readInput("msg", 4, showMain) + onchange: v => readInput(v, v => { + settings.msg = v; + writeSetting(); + showMenu(4); + }) }, /*LANG*/"msg as prefix": { value: settings.msgAsPrefix, diff --git a/apps/sleeplogalarm/widget.js b/apps/sleeplogalarm/widget.js index 991238140..e3171751f 100644 --- a/apps/sleeplogalarm/widget.js +++ b/apps/sleeplogalarm/widget.js @@ -11,7 +11,7 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable earlier: settings.earlier, draw: function () { // draw zzz - g.reset().setColor(settings.wid_color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); + g.reset().setColor(settings.wid.color).drawImage(atob("BwoBD8SSSP4EEEDg"), this.x + 1, this.y); // call function to draw the time of alarm if a alarm is found if (this.time) this.drawTime(this.time + 1); }, @@ -20,7 +20,7 @@ if ((require("Storage").readJSON("sleeplogalarm.settings.json", true) || {enable }; // add function to draw the time of alarm if enabled - if (settings.wid_time) WIDGETS.sleeplogalarm.drawTime = function(time) { + if (settings.wid.time) WIDGETS.sleeplogalarm.drawTime = function(time) { // directly include Font4x5Numeric g.setFontCustom(atob("CAZMA/H4PgvXoK1+DhPg7W4P1uCEPg/X4O1+AA=="), 46, atob("AgQEAgQEBAQEBAQE"), 5).setFontAlign(1, 1); g.drawString(0|(time / 36E5), this.x + this.width + 1, this.y + 17); From 4283fa2d9d16b3d59625517431d29ea3de72b8b5 Mon Sep 17 00:00:00 2001 From: storm64 Date: Mon, 28 Nov 2022 21:54:21 +0100 Subject: [PATCH 29/73] [sleeplogalarm] Add dependency in README --- apps/sleeplogalarm/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 29520dd09..09a30b7eb 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -1,6 +1,8 @@ # Sleep Log Alarm -This widget searches for active alarms and raises an own alarm event up to the defined time earlier, if in light sleep or awake phase. Optional the earlier alarm will only be triggered if comming from or in consecutive sleep. The settings of the earlier alarm can be adjusted and it is possible to filter the targeting alarms by time and message. By default the time of the targeting alarm is displayed inside the widget which can be adjusted, too. +This widget searches for active alarms and raises an own alarm event up to the defined time earlier, if in light sleep or awake phase. Optional the earlier alarm will only be triggered if comming from or in consecutive sleep. The settings of the earlier alarm can be adjusted and it is possible to filter the targeting alarms by time and message. By default the time of the targeting alarm is displayed inside the widget which can be adjusted, too. + +_This widget does not detect sleep by its own and requires the [sleeplog](/apps/?id=sleeplog) app to be installed._ --- ### Settings From 59c745a743512ed1b4bb16a3d62142f38610c17e Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 30 Nov 2022 22:05:38 +0100 Subject: [PATCH 30/73] [sleeplogalarm] Add sched dependency --- apps/sleeplogalarm/README.md | 2 +- apps/sleeplogalarm/metadata.json | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/sleeplogalarm/README.md b/apps/sleeplogalarm/README.md index 09a30b7eb..005377fb1 100644 --- a/apps/sleeplogalarm/README.md +++ b/apps/sleeplogalarm/README.md @@ -2,7 +2,7 @@ This widget searches for active alarms and raises an own alarm event up to the defined time earlier, if in light sleep or awake phase. Optional the earlier alarm will only be triggered if comming from or in consecutive sleep. The settings of the earlier alarm can be adjusted and it is possible to filter the targeting alarms by time and message. By default the time of the targeting alarm is displayed inside the widget which can be adjusted, too. -_This widget does not detect sleep by its own and requires the [sleeplog](/apps/?id=sleeplog) app to be installed._ +_This widget does not detect sleep on its own and can not create alarms. It requires the [sleeplog](/apps/?id=sleeplog) app and any alarm app that uses [sched](/apps/?id=sched) to be installed._ --- ### Settings diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 1930a0ee3..235c1ecc1 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -8,7 +8,10 @@ "type": "widget", "tags": "tool,widget", "supports": ["BANGLEJS2"], - "dependencies": {"sleeplog": "app"}, + "dependencies": [ + {"scheduler": "type"}, + {"sleeplog": "app"} + ], "readme": "README.md", "storage": [ {"name": "sleeplogalarm", "url": "lib.js"}, From 439ecd703d5207b0f01d22f1c198b795328419ee Mon Sep 17 00:00:00 2001 From: storm64 Date: Wed, 30 Nov 2022 22:31:55 +0100 Subject: [PATCH 31/73] [sleeplogalarm] Correct dependencies in metadata --- apps/sleeplogalarm/metadata.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/sleeplogalarm/metadata.json b/apps/sleeplogalarm/metadata.json index 235c1ecc1..fd85507e6 100644 --- a/apps/sleeplogalarm/metadata.json +++ b/apps/sleeplogalarm/metadata.json @@ -8,10 +8,10 @@ "type": "widget", "tags": "tool,widget", "supports": ["BANGLEJS2"], - "dependencies": [ - {"scheduler": "type"}, - {"sleeplog": "app"} - ], + "dependencies": { + "scheduler": "type", + "sleeplog": "app" + }, "readme": "README.md", "storage": [ {"name": "sleeplogalarm", "url": "lib.js"}, From 6b6dc4b14e861e53aef4b3f40f846301ff0c4f9f Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 17 Nov 2022 18:17:37 +0100 Subject: [PATCH 32/73] bthrm - Show internal values if replacing HRM --- apps/bthrm/bthrm.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index fadf2a5d8..84fce927c 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -91,7 +91,12 @@ function onHrm(e) { var settings = require('Storage').readJSON("bthrm.json", true) || {}; Bangle.on('BTHRM', onBtHrm); -Bangle.on('HRM', onHrm); + +if (settings.replace){ + Bangle.on('HRM_int', onHrm); +} else { + Bangle.on('HRM', onHrm); +} Bangle.setHRMPower(1,'bthrm'); if (!(settings.startWithHrm)){ From 1530ed39154de83e0e64e2fee49bd255f300f74e Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Thu, 1 Dec 2022 22:49:02 +0100 Subject: [PATCH 33/73] bthrm - Reimplement viewer app with layout --- apps/bthrm/bthrm.js | 191 ++++++++++++++++++++++++++++++++------------ 1 file changed, 139 insertions(+), 52 deletions(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 84fce927c..05bf323a5 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -1,5 +1,9 @@ var intervalInt; var intervalBt; +var intervalAgg; + +const BPM_FONT_SIZE="19%"; +const VALUE_TIMEOUT=3000; var BODY_LOCS = { 0: 'Other', @@ -7,40 +11,123 @@ var BODY_LOCS = { 2: 'Wrist', 3: 'Finger', 4: 'Hand', - 5: 'Ear Lobe', + 5: 'Earlobe', 6: 'Foot', +}; + +var Layout = require("Layout"); + +function border(l,c) { + g.setColor(c).drawLine(l.x+l.w*0.05, l.y-4, l.x+l.w*0.95, l.y-4); + c++; } -function clear(y){ - g.reset(); - g.clearRect(0,y,g.getWidth(),y+75); -} - -function draw(y, type, event) { - clear(y); - var px = g.getWidth()/2; - var str = event.bpm + ""; - g.reset(); - g.setFontAlign(0,0); - g.setFontVector(40).drawString(str,px,y+20); - str = "Event: " + type; - if (type === "HRM") { - str += " Confidence: " + event.confidence; - g.setFontVector(12).drawString(str,px,y+40); - str = " Source: " + (event.src ? event.src : "internal"); - g.setFontVector(12).drawString(str,px,y+50); +function getRow(id, text, additionalInfo){ + let additional = []; + let l = { + type:"h", c: [ + { + type:"v", + width: g.getWidth()*0.4, + c: [ + {type:"txt", halign:1, font:"8%", label:text, id:id+"text" }, + {type:"txt", halign:1, font:BPM_FONT_SIZE, label:"--", id:id, bgCol: g.theme.bg } + ] + },{ + type:undefined, fillx:1 + },{ + type:"v", + valign: -1, + width: g.getWidth()*0.45, + c: additional + },{ + type:undefined, width:g.getWidth()*0.05 + } + ] + }; + for (let i of additionalInfo){ + let label = {type:"txt", font:"6x8", label:i + ":" }; + let value = {type:"txt", font:"6x8", label:"--", id:id + i }; + additional.push({type:"h", halign:-1, c:[ label, {type:undefined, fillx:1}, value ]}); } - if (type === "BTHRM"){ - if (event.battery) str += " Bat: " + (event.battery ? event.battery : ""); - g.setFontVector(12).drawString(str,px,y+40); - str= ""; - if (event.location) str += "Loc: " + BODY_LOCS[event.location]; - if (event.rr && event.rr.length > 0) str += " RR: " + event.rr.join(","); - g.setFontVector(12).drawString(str,px,y+50); - str= ""; - if (event.contact) str += " Contact: " + event.contact; - if (event.energy) str += " kJoule: " + event.energy.toFixed(0); - g.setFontVector(12).drawString(str,px,y+60); + + return l; +} + +var layout = new Layout( { + type:"v", c: [ + getRow("int", "INT", ["Confidence"]), + getRow("agg", "HRM", ["Confidence", "Source"]), + getRow("bt", "BT", ["Battery","Location","Contact", "RR", "Energy"]), + { type:undefined, height:8 } //dummy to protect debug output + ] +}, { + lazy:true +}); + +var int,agg,bt; +var firstEvent = true; + +var drawTimeout; +function draw(){ + + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 1000); + + if (!(int || agg || bt)) return; + + if (firstEvent) { + g.clearRect(Bangle.appRect); + firstEvent = false; + } + + if (int){ + layout.int.label = int.bpm; + if (!isNaN(int.confidence)) layout.intConfidence.label = int.confidence; + } else { + layout.int.label = "--"; + layout.intConfidence.label = "--"; + } + + if (agg){ + layout.agg.label = agg.bpm; + if (!isNaN(agg.confidence)) layout.aggConfidence.label = agg.confidence; + if (agg.src) layout.aggSource.label = agg.src; + } else { + layout.agg.label = "--"; + layout.aggConfidence.label = "--"; + layout.aggSource.label = "--"; + } + + if (bt) { + layout.bt.label = bt.bpm; + if (bt.battery) layout.btBattery.label = bt.battery; + if (bt.rr) layout.btRR.label = bt.rr.join(","); + if (bt.location) layout.btLocation.label = BODY_LOCS[bt.location]; + if (bt.contact !== undefined) layout.btContact.label = bt.contact ? "Yes":"No"; + if (bt.energy) layout.btEnergy.label = bt.energy.toFixed(0) + "kJ"; + } else { + layout.bt.label = "--"; + layout.btBattery.label = "--"; + layout.btRR.label = "--"; + layout.btLocation.label = "--"; + layout.btContact.label = "--"; + layout.btEnergy.label = "--"; + } + + layout.update(); + layout.render(); + let first = true; + for (let c of layout.l.c){ + if (first) { + first = false; + continue; + } + if (c.type && c.type == "h") + border(c,g.theme.fg); } } @@ -57,11 +144,7 @@ function showStatusInfo(txt) { } function onBtHrm(e) { - if (firstEventBt){ - clear(24); - firstEventBt = false; - } - draw(100, "BTHRM", e); + bt = e; if (e.bpm === 0){ Bangle.buzz(100,0.2); } @@ -69,34 +152,37 @@ function onBtHrm(e) { clearInterval(intervalBt); } intervalBt = setInterval(()=>{ - clear(100); - }, 2000); + bt = undefined; + }, VALUE_TIMEOUT); } -function onHrm(e) { - if (firstEventInt){ - clear(24); - firstEventInt = false; - } - draw(24, "HRM", e); +function onInt(e) { + int = e; if (intervalInt){ clearInterval(intervalInt); } intervalInt = setInterval(()=>{ - clear(24); - }, 2000); + int = undefined; + }, VALUE_TIMEOUT); +} + +function onAgg(e) { + agg = e; + if (intervalAgg){ + clearInterval(intervalAgg); + } + intervalAgg = setInterval(()=>{ + agg = undefined; + }, VALUE_TIMEOUT); } var settings = require('Storage').readJSON("bthrm.json", true) || {}; Bangle.on('BTHRM', onBtHrm); +Bangle.on('HRM_int', onInt); +Bangle.on('HRM', onAgg); -if (settings.replace){ - Bangle.on('HRM_int', onHrm); -} else { - Bangle.on('HRM', onHrm); -} Bangle.setHRMPower(1,'bthrm'); if (!(settings.startWithHrm)){ @@ -108,10 +194,11 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); if (Bangle.setBTHRMPower){ g.reset().setFont("6x8",2).setFontAlign(0,0); - g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 24); + g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2); + draw(); } else { g.reset().setFont("6x8",2).setFontAlign(0,0); - g.drawString("BTHRM disabled",g.getWidth()/2,g.getHeight()/2 + 32); + g.drawString("BTHRM disabled",g.getWidth()/2,g.getHeight()/2); } E.on('kill', ()=>Bangle.setBTHRMPower(0,'bthrm')); From 48815b249eb197d4b957d8709cee1edec710d320 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Fri, 2 Dec 2022 19:38:51 +0100 Subject: [PATCH 34/73] kbswipe: Support input of numbers To switch between the input of alphabetic and numeric characters tap the widget which displays either "123" or "ABC" closes #1820 --- apps/kbswipe/ChangeLog | 1 + apps/kbswipe/README.md | 2 + apps/kbswipe/lib.js | 130 ++++++++++++++++++++++++++----------- apps/kbswipe/metadata.json | 2 +- 4 files changed, 96 insertions(+), 39 deletions(-) diff --git a/apps/kbswipe/ChangeLog b/apps/kbswipe/ChangeLog index 1804c4a89..05be810cc 100644 --- a/apps/kbswipe/ChangeLog +++ b/apps/kbswipe/ChangeLog @@ -3,3 +3,4 @@ 0.03: Positioning of marker now takes the height of the widget field into account. 0.04: Fix issue if going back without typing. 0.05: Keep drag-function in ram, hopefully improving performance and input reliability somewhat. +0.06: Support input of numbers diff --git a/apps/kbswipe/README.md b/apps/kbswipe/README.md index 3f5575777..1508061d1 100644 --- a/apps/kbswipe/README.md +++ b/apps/kbswipe/README.md @@ -4,6 +4,8 @@ A library that provides the ability to input text by swiping PalmOS Graffiti-sty To get a legend of available characters, just tap the screen. +To switch between the input of alphabetic and numeric characters tap the widget which displays either "123" or "ABC". + ![](key.png) ## Usage diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index fe5f7e977..861d046cb 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -1,47 +1,67 @@ +const INPUT_MODE_ALPHA = 0; +const INPUT_MODE_NUM = 1; + /* To make your own strokes, type: Bangle.on('stroke',print) on the left of the IDE, then do a stroke and copy out the Uint8Array line */ -exports.getStrokes = function(cb) { - cb("a", new Uint8Array([58, 159, 58, 155, 62, 144, 69, 127, 77, 106, 86, 90, 94, 77, 101, 68, 108, 62, 114, 59, 121, 59, 133, 61, 146, 70, 158, 88, 169, 107, 176, 124, 180, 135, 183, 144, 185, 152])); - cb("b", new Uint8Array([51, 47, 51, 77, 56, 123, 60, 151, 65, 163, 68, 164, 68, 144, 67, 108, 67, 76, 72, 43, 104, 51, 121, 74, 110, 87, 109, 95, 131, 117, 131, 140, 109, 152, 88, 157])); - cb("c", new Uint8Array([153, 62, 150, 62, 145, 62, 136, 62, 123, 62, 106, 65, 85, 70, 65, 75, 50, 82, 42, 93, 37, 106, 36, 119, 36, 130, 40, 140, 49, 147, 61, 153, 72, 156, 85, 157, 106, 158, 116, 158])); - cb("d", new Uint8Array([57, 178, 57, 176, 55, 171, 52, 163, 50, 154, 49, 146, 47, 135, 45, 121, 44, 108, 44, 97, 44, 85, 44, 75, 44, 66, 44, 58, 44, 48, 44, 38, 46, 31, 48, 26, 58, 21, 75, 20, 99, 26, 120, 35, 136, 51, 144, 70, 144, 88, 137, 110, 124, 131, 106, 145, 88, 153])); - cb("e", new Uint8Array([150, 72, 141, 69, 114, 68, 79, 69, 48, 77, 32, 81, 31, 85, 46, 91, 73, 95, 107, 100, 114, 103, 83, 117, 58, 134, 66, 143, 105, 148, 133, 148, 144, 148])); - cb("f", new Uint8Array([157, 52, 155, 52, 148, 52, 137, 52, 124, 52, 110, 52, 96, 52, 83, 52, 74, 52, 67, 52, 61, 52, 57, 52, 55, 52, 52, 52, 52, 54, 52, 58, 52, 64, 54, 75, 58, 97, 59, 117, 60, 130])); - cb("g", new Uint8Array([160, 66, 153, 62, 129, 58, 90, 56, 58, 57, 38, 65, 31, 86, 43, 125, 69, 152, 116, 166, 145, 154, 146, 134, 112, 116, 85, 108, 97, 106, 140, 106, 164, 106])); - cb("h", new Uint8Array([58, 50, 58, 55, 58, 64, 58, 80, 58, 102, 58, 122, 58, 139, 58, 153, 58, 164, 58, 171, 58, 177, 58, 179, 58, 181, 58, 180, 58, 173, 58, 163, 59, 154, 61, 138, 64, 114, 68, 95, 72, 84, 80, 79, 91, 79, 107, 82, 123, 93, 137, 111, 145, 130, 149, 147, 150, 154, 150, 159])); - cb("i", new Uint8Array([89, 48, 89, 49, 89, 51, 89, 55, 89, 60, 89, 68, 89, 78, 89, 91, 89, 103, 89, 114, 89, 124, 89, 132, 89, 138, 89, 144, 89, 148, 89, 151, 89, 154, 89, 156, 89, 157, 89, 158])); - cb("j", new Uint8Array([130, 57, 130, 61, 130, 73, 130, 91, 130, 113, 130, 133, 130, 147, 130, 156, 130, 161, 130, 164, 130, 166, 129, 168, 127, 168, 120, 168, 110, 168, 91, 167, 81, 167, 68, 167])); - cb("k", new Uint8Array([149, 63, 147, 68, 143, 76, 136, 89, 126, 106, 114, 123, 100, 136, 86, 147, 72, 153, 57, 155, 45, 152, 36, 145, 29, 131, 26, 117, 26, 104, 27, 93, 30, 86, 35, 80, 45, 77, 62, 80, 88, 96, 113, 116, 130, 131, 140, 142, 145, 149, 148, 153])); - cb("l", new Uint8Array([42, 55, 42, 59, 42, 69, 44, 87, 44, 107, 44, 128, 44, 143, 44, 156, 44, 163, 44, 167, 44, 169, 45, 170, 49, 170, 59, 169, 76, 167, 100, 164, 119, 162, 139, 160, 163, 159])); - cb("m", new Uint8Array([49, 165, 48, 162, 46, 156, 44, 148, 42, 138, 42, 126, 42, 113, 43, 101, 45, 91, 47, 82, 49, 75, 51, 71, 54, 70, 57, 70, 61, 74, 69, 81, 75, 91, 84, 104, 94, 121, 101, 132, 103, 137, 106, 130, 110, 114, 116, 92, 125, 75, 134, 65, 139, 62, 144, 66, 148, 83, 151, 108, 155, 132, 157, 149])); - cb("n", new Uint8Array([50, 165, 50, 160, 50, 153, 50, 140, 50, 122, 50, 103, 50, 83, 50, 65, 50, 52, 50, 45, 50, 43, 52, 52, 57, 67, 66, 90, 78, 112, 93, 131, 104, 143, 116, 152, 127, 159, 135, 160, 141, 150, 148, 125, 154, 96, 158, 71, 161, 56, 162, 49])); - cb("o", new Uint8Array([107, 58, 104, 58, 97, 61, 87, 68, 75, 77, 65, 88, 58, 103, 54, 116, 53, 126, 55, 135, 61, 143, 75, 149, 91, 150, 106, 148, 119, 141, 137, 125, 143, 115, 146, 104, 146, 89, 142, 78, 130, 70, 116, 65, 104, 62])); - cb("p", new Uint8Array([52, 59, 52, 64, 54, 73, 58, 88, 61, 104, 65, 119, 67, 130, 69, 138, 71, 145, 71, 147, 71, 148, 71, 143, 70, 133, 68, 120, 67, 108, 67, 97, 67, 89, 68, 79, 72, 67, 83, 60, 99, 58, 118, 58, 136, 63, 146, 70, 148, 77, 145, 84, 136, 91, 121, 95, 106, 97, 93, 97, 82, 97])); - cb("q", new Uint8Array([95, 59, 93, 59, 88, 59, 79, 59, 68, 61, 57, 67, 50, 77, 48, 89, 48, 103, 50, 117, 55, 130, 65, 140, 76, 145, 85, 146, 94, 144, 101, 140, 105, 136, 106, 127, 106, 113, 100, 98, 92, 86, 86, 79, 84, 75, 84, 72, 91, 69, 106, 67, 126, 67, 144, 67, 158, 67, 168, 67, 173, 67, 177, 67])); - cb("r", new Uint8Array([53, 49, 53, 62, 53, 91, 53, 127, 53, 146, 53, 147, 53, 128, 53, 94, 53, 69, 62, 44, 82, 42, 94, 50, 92, 68, 82, 85, 77, 93, 80, 102, 95, 119, 114, 134, 129, 145, 137, 150])); - cb("s", new Uint8Array([159, 72, 157, 70, 155, 68, 151, 66, 145, 63, 134, 60, 121, 58, 108, 56, 96, 55, 83, 55, 73, 55, 64, 56, 57, 60, 52, 65, 49, 71, 49, 76, 50, 81, 55, 87, 71, 94, 94, 100, 116, 104, 131, 108, 141, 114, 145, 124, 142, 135, 124, 146, 97, 153, 70, 157, 52, 158])); - cb("t", new Uint8Array([45, 55, 48, 55, 55, 55, 72, 55, 96, 55, 120, 55, 136, 55, 147, 55, 152, 55, 155, 55, 157, 55, 158, 56, 158, 60, 156, 70, 154, 86, 151, 102, 150, 114, 148, 125, 148, 138, 148, 146])); - cb("u", new Uint8Array([35, 52, 35, 59, 35, 73, 35, 90, 36, 114, 38, 133, 42, 146, 49, 153, 60, 157, 73, 158, 86, 156, 100, 152, 112, 144, 121, 131, 127, 114, 132, 97, 134, 85, 135, 73, 136, 61, 136, 56])); - cb("v", new Uint8Array([36, 55, 37, 59, 40, 68, 45, 83, 51, 100, 58, 118, 64, 132, 69, 142, 71, 149, 73, 156, 76, 158, 77, 160, 77, 159, 80, 151, 82, 137, 84, 122, 86, 111, 90, 91, 91, 78, 91, 68, 91, 63, 92, 61, 97, 61, 111, 61, 132, 61, 150, 61, 162, 61])); - cb("w", new Uint8Array([33, 58, 34, 81, 39, 127, 44, 151, 48, 161, 52, 162, 57, 154, 61, 136, 65, 115, 70, 95, 76, 95, 93, 121, 110, 146, 119, 151, 130, 129, 138, 84, 140, 56, 140, 45])); - cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); - cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); - cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); +exports.getStrokes = function(mode, cb) { + if (mode === INPUT_MODE_ALPHA) { + cb("a", new Uint8Array([58, 159, 58, 155, 62, 144, 69, 127, 77, 106, 86, 90, 94, 77, 101, 68, 108, 62, 114, 59, 121, 59, 133, 61, 146, 70, 158, 88, 169, 107, 176, 124, 180, 135, 183, 144, 185, 152])); + cb("b", new Uint8Array([51, 47, 51, 77, 56, 123, 60, 151, 65, 163, 68, 164, 68, 144, 67, 108, 67, 76, 72, 43, 104, 51, 121, 74, 110, 87, 109, 95, 131, 117, 131, 140, 109, 152, 88, 157])); + cb("c", new Uint8Array([153, 62, 150, 62, 145, 62, 136, 62, 123, 62, 106, 65, 85, 70, 65, 75, 50, 82, 42, 93, 37, 106, 36, 119, 36, 130, 40, 140, 49, 147, 61, 153, 72, 156, 85, 157, 106, 158, 116, 158])); + cb("d", new Uint8Array([57, 178, 57, 176, 55, 171, 52, 163, 50, 154, 49, 146, 47, 135, 45, 121, 44, 108, 44, 97, 44, 85, 44, 75, 44, 66, 44, 58, 44, 48, 44, 38, 46, 31, 48, 26, 58, 21, 75, 20, 99, 26, 120, 35, 136, 51, 144, 70, 144, 88, 137, 110, 124, 131, 106, 145, 88, 153])); + cb("e", new Uint8Array([150, 72, 141, 69, 114, 68, 79, 69, 48, 77, 32, 81, 31, 85, 46, 91, 73, 95, 107, 100, 114, 103, 83, 117, 58, 134, 66, 143, 105, 148, 133, 148, 144, 148])); + cb("f", new Uint8Array([157, 52, 155, 52, 148, 52, 137, 52, 124, 52, 110, 52, 96, 52, 83, 52, 74, 52, 67, 52, 61, 52, 57, 52, 55, 52, 52, 52, 52, 54, 52, 58, 52, 64, 54, 75, 58, 97, 59, 117, 60, 130])); + cb("g", new Uint8Array([160, 66, 153, 62, 129, 58, 90, 56, 58, 57, 38, 65, 31, 86, 43, 125, 69, 152, 116, 166, 145, 154, 146, 134, 112, 116, 85, 108, 97, 106, 140, 106, 164, 106])); + cb("h", new Uint8Array([58, 50, 58, 55, 58, 64, 58, 80, 58, 102, 58, 122, 58, 139, 58, 153, 58, 164, 58, 171, 58, 177, 58, 179, 58, 181, 58, 180, 58, 173, 58, 163, 59, 154, 61, 138, 64, 114, 68, 95, 72, 84, 80, 79, 91, 79, 107, 82, 123, 93, 137, 111, 145, 130, 149, 147, 150, 154, 150, 159])); + cb("i", new Uint8Array([89, 48, 89, 49, 89, 51, 89, 55, 89, 60, 89, 68, 89, 78, 89, 91, 89, 103, 89, 114, 89, 124, 89, 132, 89, 138, 89, 144, 89, 148, 89, 151, 89, 154, 89, 156, 89, 157, 89, 158])); + cb("j", new Uint8Array([130, 57, 130, 61, 130, 73, 130, 91, 130, 113, 130, 133, 130, 147, 130, 156, 130, 161, 130, 164, 130, 166, 129, 168, 127, 168, 120, 168, 110, 168, 91, 167, 81, 167, 68, 167])); + cb("k", new Uint8Array([149, 63, 147, 68, 143, 76, 136, 89, 126, 106, 114, 123, 100, 136, 86, 147, 72, 153, 57, 155, 45, 152, 36, 145, 29, 131, 26, 117, 26, 104, 27, 93, 30, 86, 35, 80, 45, 77, 62, 80, 88, 96, 113, 116, 130, 131, 140, 142, 145, 149, 148, 153])); + cb("l", new Uint8Array([42, 55, 42, 59, 42, 69, 44, 87, 44, 107, 44, 128, 44, 143, 44, 156, 44, 163, 44, 167, 44, 169, 45, 170, 49, 170, 59, 169, 76, 167, 100, 164, 119, 162, 139, 160, 163, 159])); + cb("m", new Uint8Array([49, 165, 48, 162, 46, 156, 44, 148, 42, 138, 42, 126, 42, 113, 43, 101, 45, 91, 47, 82, 49, 75, 51, 71, 54, 70, 57, 70, 61, 74, 69, 81, 75, 91, 84, 104, 94, 121, 101, 132, 103, 137, 106, 130, 110, 114, 116, 92, 125, 75, 134, 65, 139, 62, 144, 66, 148, 83, 151, 108, 155, 132, 157, 149])); + cb("n", new Uint8Array([50, 165, 50, 160, 50, 153, 50, 140, 50, 122, 50, 103, 50, 83, 50, 65, 50, 52, 50, 45, 50, 43, 52, 52, 57, 67, 66, 90, 78, 112, 93, 131, 104, 143, 116, 152, 127, 159, 135, 160, 141, 150, 148, 125, 154, 96, 158, 71, 161, 56, 162, 49])); + cb("o", new Uint8Array([107, 58, 104, 58, 97, 61, 87, 68, 75, 77, 65, 88, 58, 103, 54, 116, 53, 126, 55, 135, 61, 143, 75, 149, 91, 150, 106, 148, 119, 141, 137, 125, 143, 115, 146, 104, 146, 89, 142, 78, 130, 70, 116, 65, 104, 62])); + cb("p", new Uint8Array([52, 59, 52, 64, 54, 73, 58, 88, 61, 104, 65, 119, 67, 130, 69, 138, 71, 145, 71, 147, 71, 148, 71, 143, 70, 133, 68, 120, 67, 108, 67, 97, 67, 89, 68, 79, 72, 67, 83, 60, 99, 58, 118, 58, 136, 63, 146, 70, 148, 77, 145, 84, 136, 91, 121, 95, 106, 97, 93, 97, 82, 97])); + cb("q", new Uint8Array([95, 59, 93, 59, 88, 59, 79, 59, 68, 61, 57, 67, 50, 77, 48, 89, 48, 103, 50, 117, 55, 130, 65, 140, 76, 145, 85, 146, 94, 144, 101, 140, 105, 136, 106, 127, 106, 113, 100, 98, 92, 86, 86, 79, 84, 75, 84, 72, 91, 69, 106, 67, 126, 67, 144, 67, 158, 67, 168, 67, 173, 67, 177, 67])); + cb("r", new Uint8Array([53, 49, 53, 62, 53, 91, 53, 127, 53, 146, 53, 147, 53, 128, 53, 94, 53, 69, 62, 44, 82, 42, 94, 50, 92, 68, 82, 85, 77, 93, 80, 102, 95, 119, 114, 134, 129, 145, 137, 150])); + cb("s", new Uint8Array([159, 72, 157, 70, 155, 68, 151, 66, 145, 63, 134, 60, 121, 58, 108, 56, 96, 55, 83, 55, 73, 55, 64, 56, 57, 60, 52, 65, 49, 71, 49, 76, 50, 81, 55, 87, 71, 94, 94, 100, 116, 104, 131, 108, 141, 114, 145, 124, 142, 135, 124, 146, 97, 153, 70, 157, 52, 158])); + cb("t", new Uint8Array([45, 55, 48, 55, 55, 55, 72, 55, 96, 55, 120, 55, 136, 55, 147, 55, 152, 55, 155, 55, 157, 55, 158, 56, 158, 60, 156, 70, 154, 86, 151, 102, 150, 114, 148, 125, 148, 138, 148, 146])); + cb("u", new Uint8Array([35, 52, 35, 59, 35, 73, 35, 90, 36, 114, 38, 133, 42, 146, 49, 153, 60, 157, 73, 158, 86, 156, 100, 152, 112, 144, 121, 131, 127, 114, 132, 97, 134, 85, 135, 73, 136, 61, 136, 56])); + cb("v", new Uint8Array([36, 55, 37, 59, 40, 68, 45, 83, 51, 100, 58, 118, 64, 132, 69, 142, 71, 149, 73, 156, 76, 158, 77, 160, 77, 159, 80, 151, 82, 137, 84, 122, 86, 111, 90, 91, 91, 78, 91, 68, 91, 63, 92, 61, 97, 61, 111, 61, 132, 61, 150, 61, 162, 61])); + cb("w", new Uint8Array([33, 58, 34, 81, 39, 127, 44, 151, 48, 161, 52, 162, 57, 154, 61, 136, 65, 115, 70, 95, 76, 95, 93, 121, 110, 146, 119, 151, 130, 129, 138, 84, 140, 56, 140, 45])); + cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); + cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); + cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); + } else if (mode === INPUT_MODE_NUM) { + cb("0", new Uint8Array([105, 63, 97, 63, 80, 63, 62, 64, 52, 69, 47, 79, 47, 94, 48, 111, 55, 125, 74, 138, 100, 141, 126, 137, 148, 129, 158, 119, 161, 107, 161, 98, 159, 92, 154, 87, 149, 82])); + cb("1", new Uint8Array([123, 59, 123, 60, 123, 63, 123, 67, 123, 70, 122, 73, 121, 78, 119, 83, 118, 91, 117, 100, 116, 108, 115, 117, 114, 126, 113, 135, 112, 143, 111, 149, 111, 155, 110, 159])); + cb("2", new Uint8Array([61, 99, 61, 94, 61, 88, 61, 80, 65, 71, 73, 66, 83, 62, 97, 62, 109, 62, 126, 62, 141, 62, 149, 65, 151, 74, 151, 87, 150, 95, 143, 108, 130, 118, 117, 127, 100, 138, 84, 146, 67, 151, 55, 157, 52, 159, 73, 159, 117, 159, 163, 159, 183, 159])); + cb("3", new Uint8Array([69, 62, 78, 56, 98, 49, 121, 49, 141, 54, 149, 58, 150, 65, 148, 74, 143, 82, 126, 92, 114, 98, 119, 100, 135, 105, 143, 117, 142, 135, 123, 149, 105, 155])); + cb("4", new Uint8Array([78, 45, 78, 47, 78, 50, 78, 56, 78, 64, 78, 75, 78, 88, 78, 103, 78, 119, 78, 132, 78, 144, 78, 148, 80, 149, 84, 149, 96, 149, 112, 148, 127, 147, 144, 144, 163, 140, 175, 137])); + cb("5", new Uint8Array([142, 49, 134, 47, 121, 44, 104, 44, 88, 45, 75, 46, 68, 48, 64, 52, 64, 59, 64, 73, 64, 86, 64, 100, 67, 105, 82, 105, 106, 105, 130, 105, 143, 105, 149, 105, 151, 110, 148, 125, 138, 144, 118, 157, 92, 164, 76, 165, 65, 165, 60, 165])); + cb("6", new Uint8Array([161, 47, 151, 47, 133, 47, 108, 48, 85, 52, 65, 59, 53, 72, 46, 89, 44, 107, 49, 133, 71, 151, 100, 156, 118, 152, 120, 141, 108, 132, 84, 127, 70, 126])); + cb("7", new Uint8Array([43, 53, 53, 49, 72, 45, 96, 40, 116, 38, 129, 38, 138, 38, 144, 38, 147, 39, 149, 47, 143, 75, 127, 121, 114, 147, 107, 158, 104, 162, 98, 168, 93, 171])); + cb("8", new Uint8Array([148, 66, 135, 58, 113, 49, 97, 43, 84, 40, 74, 40, 66, 43, 62, 47, 62, 51, 67, 61, 84, 75, 101, 88, 111, 101, 113, 115, 110, 135, 98, 149, 84, 156, 73, 157, 63, 157, 58, 154, 52, 144, 52, 133, 54, 122, 65, 111, 81, 100, 97, 92, 110, 86, 121, 81, 129, 80, 137, 80, 145, 79, 151, 78])); + cb("9", new Uint8Array([146, 57, 146, 52, 146, 46, 143, 42, 135, 41, 123, 41, 107, 45, 92, 49, 83, 53, 78, 62, 89, 82, 110, 94, 126, 94, 139, 88, 147, 81, 151, 74, 152, 75, 152, 80, 152, 88, 152, 101, 152, 121, 152, 140, 152, 154, 152, 165, 152, 171])); + } cb("\b", new Uint8Array([183, 103, 182, 103, 180, 103, 176, 103, 169, 103, 159, 103, 147, 103, 133, 103, 116, 103, 101, 103, 85, 103, 73, 103, 61, 103, 52, 103, 38, 103, 34, 103, 29, 103, 27, 103, 26, 103, 25, 103, 24, 103])); cb(" ", new Uint8Array([39, 118, 40, 118, 41, 118, 44, 118, 47, 118, 52, 118, 58, 118, 66, 118, 74, 118, 84, 118, 94, 118, 104, 117, 114, 116, 123, 116, 130, 116, 144, 116, 149, 116, 154, 116, 158, 116, 161, 116, 163, 116])); }; exports.input = function(options) { options = options||{}; + let input_mode = INPUT_MODE_ALPHA; var text = options.text; if ("string"!=typeof text) text=""; -Bangle.strokes = {}; -exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); + function setupStrokes() { + Bangle.strokes = {}; + exports.getStrokes(input_mode, (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); + } + setupStrokes(); var flashToggle = false; const R = Bangle.appRect; @@ -49,6 +69,7 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); var Rx2; var Ry1; var Ry2; + let flashInterval; function findMarker(strArr) { if (strArr.length == 0) { @@ -101,10 +122,13 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); */ function show() { + if (flashInterval) clearInterval(flashInterval); + flashInterval = undefined; + g.reset(); g.clearRect(R).setColor("#f00"); var n=0; - exports.getStrokes((id,s) => { + exports.getStrokes(input_mode, (id,s) => { var x = n%6; var y = (n-x)/6; s = g.transformVertices(s, {scale:0.16, x:R.x+x*30-4, y:R.y+y*30-4}); @@ -119,22 +143,47 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); if (!flashInterval) flashInterval = setInterval(() => { flashToggle = !flashToggle; - draw(); + draw(false); }, 1000); if (o.stroke!==undefined) { var ch = o.stroke; if (ch=="\b") text = text.slice(0,-1); else text += ch; - g.clearRect(R); + g.clearRect(R); } flashToggle = true; - draw(); + draw(false); } + + // Switches between alphabetic and numeric input + function cycleInput() { + input_mode++; + if (input_mode > INPUT_MODE_NUM) input_mode = 0; + setupStrokes(); + show(); + Bangle.drawWidgets(); + } + Bangle.on('stroke',strokeHandler); g.reset().clearRect(R); show(); draw(false); - var flashInterval; + + // Create Widget to switch between alphabetic and numeric input + WIDGETS.kbswipe={ + area:"tl", + width: 36, // 3 chars 6*2 px/char + draw: function() { + g.reset(); + g.setFont("6x8:2x3"); + g.setColor("#f00"); + if (input_mode === INPUT_MODE_ALPHA) { + g.drawString("123", this.x, this.y); + } else if (input_mode === INPUT_MODE_NUM) { + g.drawString("ABC", this.x, this.y); + } + } + }; return new Promise((resolve,reject) => { var l;//last event @@ -142,11 +191,16 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); "ram"; if (l) g.reset().setColor("#f00").drawLine(l.x,l.y,e.x,e.y); l = e.b ? e : 0; - },touch:() => { - if (flashInterval) clearInterval(flashInterval); - flashInterval = undefined; - show(); + },touch:(n,e) => { + if (WIDGETS.kbswipe && e.x>=WIDGETS.kbswipe.x && e.x=WIDGETS.kbswipe.y && e.y<=WIDGETS.kbswipe.y+24) { + // touch inside widget + cycleInput(); + } else { + show(); + } }, back:()=>{ + delete WIDGETS.kbswipe; Bangle.removeListener("stroke", strokeHandler); if (flashInterval) clearInterval(flashInterval); Bangle.setUI(); diff --git a/apps/kbswipe/metadata.json b/apps/kbswipe/metadata.json index 59622cb96..5e290e1dd 100644 --- a/apps/kbswipe/metadata.json +++ b/apps/kbswipe/metadata.json @@ -1,6 +1,6 @@ { "id": "kbswipe", "name": "Swipe keyboard", - "version":"0.05", + "version":"0.06", "description": "A library for text input via PalmOS style swipe gestures (beta!)", "icon": "app.png", "type":"textinput", From 39860e9bb281a343859d11522fab337f02c3ec40 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Fri, 2 Dec 2022 20:40:15 +0100 Subject: [PATCH 35/73] kbswipe: Support uppercase input --- apps/kbswipe/lib.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index 861d046cb..451cc21b4 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -35,6 +35,7 @@ exports.getStrokes = function(mode, cb) { cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); + cb("SHIFT", new Uint8Array([106, 184, 106, 182, 106, 175, 106, 165, 106, 151, 106, 135, 106, 120, 106, 106, 106, 95, 106, 87, 106, 82, 106, 78, 106, 73, 106, 70, 106, 68, 106, 66, 106, 64])); } else if (mode === INPUT_MODE_NUM) { cb("0", new Uint8Array([105, 63, 97, 63, 80, 63, 62, 64, 52, 69, 47, 79, 47, 94, 48, 111, 55, 125, 74, 138, 100, 141, 126, 137, 148, 129, 158, 119, 161, 107, 161, 98, 159, 92, 154, 87, 149, 82])); cb("1", new Uint8Array([123, 59, 123, 60, 123, 63, 123, 67, 123, 70, 122, 73, 121, 78, 119, 83, 118, 91, 117, 100, 116, 108, 115, 117, 114, 126, 113, 135, 112, 143, 111, 149, 111, 155, 110, 159])); @@ -70,6 +71,7 @@ exports.input = function(options) { var Ry1; var Ry2; let flashInterval; + let shift = false; function findMarker(strArr) { if (strArr.length == 0) { @@ -148,7 +150,8 @@ exports.input = function(options) { if (o.stroke!==undefined) { var ch = o.stroke; if (ch=="\b") text = text.slice(0,-1); - else text += ch; + else if (ch==="SHIFT") { shift=!shift; Bangle.drawWidgets(); } + else text += shift ? ch.toUpperCase() : ch; g.clearRect(R); } flashToggle = true; @@ -159,6 +162,7 @@ exports.input = function(options) { function cycleInput() { input_mode++; if (input_mode > INPUT_MODE_NUM) input_mode = 0; + shift = false; setupStrokes(); show(); Bangle.drawWidgets(); @@ -172,15 +176,15 @@ exports.input = function(options) { // Create Widget to switch between alphabetic and numeric input WIDGETS.kbswipe={ area:"tl", - width: 36, // 3 chars 6*2 px/char + width: 36, // 3 chars, 6*2 px/char draw: function() { g.reset(); g.setFont("6x8:2x3"); g.setColor("#f00"); if (input_mode === INPUT_MODE_ALPHA) { - g.drawString("123", this.x, this.y); + g.drawString(shift ? "ABC" : "abc", this.x, this.y); } else if (input_mode === INPUT_MODE_NUM) { - g.drawString("ABC", this.x, this.y); + g.drawString("123", this.x, this.y); } } }; From e77a5f973c535bbfc2a755ceebdd4dc13c3f82e0 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 2 Dec 2022 19:10:26 +0100 Subject: [PATCH 36/73] bthrm - Emit copies of events when changing --- apps/bthrm/lib.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/apps/bthrm/lib.js b/apps/bthrm/lib.js index f5e0e1e5b..a792167ca 100644 --- a/apps/bthrm/lib.js +++ b/apps/bthrm/lib.js @@ -553,14 +553,15 @@ exports.enable = () => { if (settings.replace){ // register a listener for original HRM events and emit as HRM_int - Bangle.on("HRM", (e) => { - e.modified = true; + Bangle.on("HRM", (o) => { + let e = Object.assign({},o); log("Emitting HRM_int", e); Bangle.emit("HRM_int", e); if (fallbackActive){ // if fallback to internal HRM is active, emit as HRM_R to which everyone listens - log("Emitting HRM_R(int)", e); - Bangle.emit("HRM_R", e); + o.src = "int"; + log("Emitting HRM_R(int)", o); + Bangle.emit("HRM_R", o); } }); @@ -576,6 +577,13 @@ exports.enable = () => { if (name == "HRM") o("HRM_R", cb); else o(name, cb); })(Bangle.removeListener); + } else { + Bangle.on("HRM", (o)=>{ + o.src = "int"; + let e = Object.assign({},o); + log("Emitting HRM_int", e); + Bangle.emit("HRM_int", e); + }); } Bangle.origSetHRMPower = Bangle.setHRMPower; From 85c2f92e0aa816ce8c47f46ea077ae82548b7d90 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 2 Dec 2022 19:15:03 +0100 Subject: [PATCH 37/73] bthrm - Bump version --- apps/bthrm/ChangeLog | 1 + apps/bthrm/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 99cf0c670..000c5e3f8 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -40,3 +40,4 @@ 0.16: Set powerdownRequested correctly on BTHRM power on Additional logging on errors Add debug option for disabling active scanning +0.17: New GUI based on layout library diff --git a/apps/bthrm/metadata.json b/apps/bthrm/metadata.json index 18c34ea33..0977fd755 100644 --- a/apps/bthrm/metadata.json +++ b/apps/bthrm/metadata.json @@ -2,7 +2,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.16", + "version": "0.17", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", From ddbbef2bf814eb254d9fd3969f5c05ddb4e70da1 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 2 Dec 2022 23:50:14 +0100 Subject: [PATCH 38/73] bthrm - Change from timeouts to timestamps for resetting values --- apps/bthrm/bthrm.js | 55 +++++++++------------------------------------ 1 file changed, 11 insertions(+), 44 deletions(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 05bf323a5..e163dd8b7 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -1,7 +1,3 @@ -var intervalInt; -var intervalBt; -var intervalAgg; - const BPM_FONT_SIZE="19%"; const VALUE_TIMEOUT=3000; @@ -19,7 +15,6 @@ var Layout = require("Layout"); function border(l,c) { g.setColor(c).drawLine(l.x+l.w*0.05, l.y-4, l.x+l.w*0.95, l.y-4); - c++; } function getRow(id, text, additionalInfo){ @@ -68,23 +63,17 @@ var layout = new Layout( { var int,agg,bt; var firstEvent = true; -var drawTimeout; function draw(){ - - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, 1000); - if (!(int || agg || bt)) return; - + if (firstEvent) { g.clearRect(Bangle.appRect); firstEvent = false; } - - if (int){ + + let now = Date.now(); + + if (int && int.time > (now - VALUE_TIMEOUT)){ layout.int.label = int.bpm; if (!isNaN(int.confidence)) layout.intConfidence.label = int.confidence; } else { @@ -92,7 +81,7 @@ function draw(){ layout.intConfidence.label = "--"; } - if (agg){ + if (agg && agg.time > (now - VALUE_TIMEOUT)){ layout.agg.label = agg.bpm; if (!isNaN(agg.confidence)) layout.aggConfidence.label = agg.confidence; if (agg.src) layout.aggSource.label = agg.src; @@ -102,7 +91,7 @@ function draw(){ layout.aggSource.label = "--"; } - if (bt) { + if (bt && bt.time > (now - VALUE_TIMEOUT)) { layout.bt.label = bt.bpm; if (bt.battery) layout.btBattery.label = bt.battery; if (bt.rr) layout.btRR.label = bt.rr.join(","); @@ -131,9 +120,6 @@ function draw(){ } } -var firstEventBt = true; -var firstEventInt = true; - // This can get called for the boot code to show what's happening function showStatusInfo(txt) { @@ -145,38 +131,19 @@ function showStatusInfo(txt) { function onBtHrm(e) { bt = e; - if (e.bpm === 0){ - Bangle.buzz(100,0.2); - } - if (intervalBt){ - clearInterval(intervalBt); - } - intervalBt = setInterval(()=>{ - bt = undefined; - }, VALUE_TIMEOUT); + bt.time = Date.now(); } function onInt(e) { int = e; - if (intervalInt){ - clearInterval(intervalInt); - } - intervalInt = setInterval(()=>{ - int = undefined; - }, VALUE_TIMEOUT); + int.time = Date.now(); } function onAgg(e) { agg = e; - if (intervalAgg){ - clearInterval(intervalAgg); - } - intervalAgg = setInterval(()=>{ - agg = undefined; - }, VALUE_TIMEOUT); + agg.time = Date.now(); } - var settings = require('Storage').readJSON("bthrm.json", true) || {}; Bangle.on('BTHRM', onBtHrm); @@ -195,7 +162,7 @@ Bangle.drawWidgets(); if (Bangle.setBTHRMPower){ g.reset().setFont("6x8",2).setFontAlign(0,0); g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2); - draw(); + setInterval(draw, 1000); } else { g.reset().setFont("6x8",2).setFontAlign(0,0); g.drawString("BTHRM disabled",g.getWidth()/2,g.getHeight()/2); From 5308b42db1218457e965d96c05b1fd43c3e63836 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 13:07:33 +0100 Subject: [PATCH 39/73] Update app.js --- apps/contourclock/app.js | 74 +++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/apps/contourclock/app.js b/apps/contourclock/app.js index d5c97edfa..05961d222 100644 --- a/apps/contourclock/app.js +++ b/apps/contourclock/app.js @@ -1,35 +1,45 @@ -var digits = []; -var drawTimeout; -var fontName=""; -var settings = require('Storage').readJSON("contourclock.json", true) || {}; -if (settings.fontIndex==undefined) { - settings.fontIndex=0; - require('Storage').writeJSON("myapp.json", settings); -} +{ + let digits = []; + let drawTimeout; + let fontName=""; + let settings = require('Storage').readJSON("contourclock.json", true) || {}; + if (settings.fontIndex==undefined) { + settings.fontIndex=0; + require('Storage').writeJSON("myapp.json", settings); + } -function queueDraw() { - setTimeout(function() { - draw(); - queueDraw(); - }, 60000 - (Date.now() % 60000)); -} + let queueDraw = function() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + queueDraw(); + }, 60000 - (Date.now() % 60000)); + }; -function draw() { - var date = new Date(); - // Draw day of the week - g.reset(); - g.setFont("Teletext10x18Ascii"); - g.clearRect(0,138,g.getWidth()-1,176); - g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); - // Draw Date - g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); - require('contourclock').drawClock(settings.fontIndex); -} + let draw = function() { + var date = new Date(); + // Draw day of the week + g.reset(); + g.setFont("Teletext10x18Ascii"); + g.clearRect(0,138,g.getWidth()-1,176); + g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); + // Draw Date + g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); + require('contourclock').drawClock(settings.fontIndex); + }; -require("FontTeletext10x18Ascii").add(Graphics); -Bangle.setUI("clock"); -g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); -queueDraw(); -draw(); + require("FontTeletext10x18Ascii").add(Graphics); + g.clear(); + draw(); + Bangle.setUI({mode:"clock", remove:function() { + if (drawTimeout) clearTimeout(drawTimeout); + require("widget_utils").show(); + g.reset(); + g.clear(); + }}); + Bangle.loadWidgets(); + require("widget_utils").swipeOn(); + //Bangle.drawWidgets(); + queueDraw(); +} From 3a65e3f0ef3ac08622668e7f2313ca81f1543766 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 13:08:44 +0100 Subject: [PATCH 40/73] Update metadata.json --- apps/contourclock/metadata.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/contourclock/metadata.json b/apps/contourclock/metadata.json index eb0dd39fb..5a359ade5 100644 --- a/apps/contourclock/metadata.json +++ b/apps/contourclock/metadata.json @@ -1,9 +1,9 @@ { "id": "contourclock", "name": "Contour Clock", "shortName" : "Contour Clock", - "version":"0.27", + "version":"0.28", "icon": "app.png", - "description": "A Minimalist clockface with large Digits. Now with more fonts!", + "description": "A Minimalist clockface with large Digits.", "screenshots" : [{"url":"cc-screenshot-1.png"},{"url":"cc-screenshot-2.png"}], "tags": "clock", "custom": "custom.html", From 51cbb46466fd37b4a84ba35b25d02c92f0914f57 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:04:42 +0100 Subject: [PATCH 41/73] Update contourclock.settings.js --- apps/contourclock/contourclock.settings.js | 98 ++++++++++++++-------- 1 file changed, 64 insertions(+), 34 deletions(-) diff --git a/apps/contourclock/contourclock.settings.js b/apps/contourclock/contourclock.settings.js index a12538fc5..6564cef58 100644 --- a/apps/contourclock/contourclock.settings.js +++ b/apps/contourclock/contourclock.settings.js @@ -1,43 +1,73 @@ (function(back) { - Bangle.removeAllListeners('drag'); + //Bangle.removeAllListeners('drag'); Bangle.setUI(""); var settings = require('Storage').readJSON('contourclock.json', true) || {}; if (settings.fontIndex==undefined) { - settings.fontIndex=0; + settings.fontIndex=0; + settings.widgets=true; + settings.hide=true; + settings.weekday=true; + settings.date=true; require('Storage').writeJSON("myapp.json", settings); } - savedIndex=settings.fontIndex; - saveListener = setWatch(function() { //save changes and return to settings menu - require('Storage').writeJSON('contourclock.json', settings); - Bangle.removeAllListeners('swipe'); - Bangle.removeAllListeners('lock'); - clearWatch(saveListener); - g.clear(); - back(); - }, BTN, { repeat:false, edge:'falling' }); - lockListener = Bangle.on('lock', function () { //discard changes and return to clock - settings.fontIndex=savedIndex; - require('Storage').writeJSON('contourclock.json', settings); - Bangle.removeAllListeners('swipe'); - Bangle.removeAllListeners('lock'); - clearWatch(saveListener); - g.clear(); - load(); - }); - swipeListener = Bangle.on('swipe', function (direction) { - var fontName = require('contourclock').drawClock(settings.fontIndex+direction); - if (fontName) { - settings.fontIndex+=direction; - g.clearRect(0,0,g.getWidth()-1,16); - g.setFont('6x8:2x2').setFontAlign(0,-1).drawString(fontName,g.getWidth()/2,0); - } else { - require('contourclock').drawClock(settings.fontIndex); + E.showMenu({ + "" : { "title" : "ContourClock" }, + "< Back" : () => back(), + 'Widgets': { + value: (settings.widgets !== undefined ? settings.widgets : true), + onchange : v => {settings.widgets=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'hide Widgets': { + value: (settings.hide !== undefined ? settings.hide : true), + onchange : v => {settings.hide=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'Weekday': { + value: (settings.weekday !== undefined ? settings.weekday : true), + onchange : v => {settings.weekday=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'Date': { + value: (settings.date !== undefined ? settings.date : true), + onchange : v => {settings.date=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'set Font': function() { + Bangle.removeAllListeners('drag'); + Bangle.removeAllListeners('touch'); + require("widget_utils").hide(); + savedIndex=settings.fontIndex; + saveListener = setWatch(function() { //save changes and return to settings menu + require('Storage').writeJSON('contourclock.json', settings); + Bangle.removeAllListeners('swipe'); + Bangle.removeAllListeners('lock'); + clearWatch(saveListener); + g.clear(); + //require("widget_utils").show(); + Bangle.load(); + }, BTN, { repeat:false, edge:'falling' }); + lockListener = Bangle.on('lock', function () { //discard changes and return to clock + settings.fontIndex=savedIndex; + require('Storage').writeJSON('contourclock.json', settings); + Bangle.removeAllListeners('swipe'); + Bangle.removeAllListeners('lock'); + clearWatch(saveListener); + g.clear(); + Bangle.load(); + }); + swipeListener = Bangle.on('swipe', function (direction) { + var fontName = require('contourclock').drawClock(settings.fontIndex+direction); + if (fontName) { + settings.fontIndex+=direction; + g.clearRect(0,0,g.getWidth()-1,16); + g.setFont('6x8:2x2').setFontAlign(0,-1).drawString(fontName,g.getWidth()/2,0); + } else { + require('contourclock').drawClock(settings.fontIndex); + } + }); + g.reset(); + g.clear(); + g.setFont('6x8:2x2').setFontAlign(0,-1); + g.drawString(require('contourclock').drawClock(settings.fontIndex),g.getWidth()/2,0); + g.drawString('Swipe - change',g.getWidth()/2,g.getHeight()-36); + g.drawString('BTN - save',g.getWidth()/2,g.getHeight()-18); } }); - g.reset(); - g.clear(); - g.setFont('6x8:2x2').setFontAlign(0,-1); - g.drawString(require('contourclock').drawClock(settings.fontIndex),g.getWidth()/2,0); - g.drawString('Swipe - change',g.getWidth()/2,g.getHeight()-36); - g.drawString('BTN - save',g.getWidth()/2,g.getHeight()-18); }) From 2abdfd991c10785e1a180fdfb29e685b9b78aff1 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:19:04 +0100 Subject: [PATCH 42/73] Update app.js --- apps/contourclock/app.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/apps/contourclock/app.js b/apps/contourclock/app.js index 05961d222..a1dd9f18a 100644 --- a/apps/contourclock/app.js +++ b/apps/contourclock/app.js @@ -5,7 +5,11 @@ let settings = require('Storage').readJSON("contourclock.json", true) || {}; if (settings.fontIndex==undefined) { settings.fontIndex=0; - require('Storage').writeJSON("myapp.json", settings); + settings.widgets=true; + settings.hide=false; + settings.weekday=true; + settings.hideWhenLocked=false; + settings.date=true; require('Storage').writeJSON("myapp.json", settings); } let queueDraw = function() { @@ -23,23 +27,31 @@ g.reset(); g.setFont("Teletext10x18Ascii"); g.clearRect(0,138,g.getWidth()-1,176); - g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); + if (settings.weekday) g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); // Draw Date - g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); + if (settings.date) g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); require('contourclock').drawClock(settings.fontIndex); }; + + if (settings.hideWhenLocked) Bangle.on('lock', function (locked) { + g.clear(); + if (locked) require('contourclock').drawClock(settings.fontIndex); + else draw(); + }); require("FontTeletext10x18Ascii").add(Graphics); g.clear(); draw(); Bangle.setUI({mode:"clock", remove:function() { if (drawTimeout) clearTimeout(drawTimeout); - require("widget_utils").show(); + if (settings.widgets && settings.hide) require("widget_utils").show(); g.reset(); g.clear(); }}); - Bangle.loadWidgets(); - require("widget_utils").swipeOn(); - //Bangle.drawWidgets(); + if (settings.widgets) { + Bangle.loadWidgets(); + if (settings.hide) require("widget_utils").swipeOn(); + else Bangle.drawWidgets(); + } queueDraw(); } From 94eb6f754444fad0d6bbe7098fc9e1d4dca3f0e5 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:26:43 +0100 Subject: [PATCH 43/73] Update contourclock.settings.js --- apps/contourclock/contourclock.settings.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/apps/contourclock/contourclock.settings.js b/apps/contourclock/contourclock.settings.js index 6564cef58..13c5d874f 100644 --- a/apps/contourclock/contourclock.settings.js +++ b/apps/contourclock/contourclock.settings.js @@ -5,9 +5,10 @@ if (settings.fontIndex==undefined) { settings.fontIndex=0; settings.widgets=true; - settings.hide=true; + settings.hide=false; settings.weekday=true; settings.date=true; + settings.hideWhenLocked=false; require('Storage').writeJSON("myapp.json", settings); } E.showMenu({ @@ -18,7 +19,7 @@ onchange : v => {settings.widgets=v; require('Storage').writeJSON('contourclock.json', settings);} }, 'hide Widgets': { - value: (settings.hide !== undefined ? settings.hide : true), + value: (settings.hide !== undefined ? settings.hide : false), onchange : v => {settings.hide=v; require('Storage').writeJSON('contourclock.json', settings);} }, 'Weekday': { @@ -29,6 +30,10 @@ value: (settings.date !== undefined ? settings.date : true), onchange : v => {settings.date=v; require('Storage').writeJSON('contourclock.json', settings);} }, + 'Hide when locked': { + value: (settings.hideWhenLocked !== undefined ? settings.hideWhenLocked : false), + onchange : v => {settings.hideWhenLocked=v; require('Storage').writeJSON('contourclock.json', settings);} + }, 'set Font': function() { Bangle.removeAllListeners('drag'); Bangle.removeAllListeners('touch'); @@ -40,7 +45,6 @@ Bangle.removeAllListeners('lock'); clearWatch(saveListener); g.clear(); - //require("widget_utils").show(); Bangle.load(); }, BTN, { repeat:false, edge:'falling' }); lockListener = Bangle.on('lock', function () { //discard changes and return to clock From cd21548da8c168bc723f00b29ed2af0a3be0c970 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:51:48 +0100 Subject: [PATCH 44/73] Update ChangeLog --- apps/contourclock/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/contourclock/ChangeLog b/apps/contourclock/ChangeLog index d415a604d..98d82e91b 100644 --- a/apps/contourclock/ChangeLog +++ b/apps/contourclock/ChangeLog @@ -7,3 +7,4 @@ 0.25: Fixed a bug that would let widgets change the color of the clock. 0.26: Time formatted to locale 0.27: Fixed the timing code, which sometimes did not update for one minute +0.28: More config options, enabled fast loading From 2ea2983e36ef5e752a713349e895dd9b77b82fe7 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:57:07 +0100 Subject: [PATCH 45/73] Update contourclock.settings.js --- apps/contourclock/contourclock.settings.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/contourclock/contourclock.settings.js b/apps/contourclock/contourclock.settings.js index 13c5d874f..2d8f74fc6 100644 --- a/apps/contourclock/contourclock.settings.js +++ b/apps/contourclock/contourclock.settings.js @@ -1,5 +1,4 @@ (function(back) { - //Bangle.removeAllListeners('drag'); Bangle.setUI(""); var settings = require('Storage').readJSON('contourclock.json', true) || {}; if (settings.fontIndex==undefined) { From 48ddf89913bd959d0f5da2e8d088aafe8b381fa0 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 14:57:48 +0100 Subject: [PATCH 46/73] Update ChangeLog --- apps/contourclock/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contourclock/ChangeLog b/apps/contourclock/ChangeLog index 98d82e91b..387340d5b 100644 --- a/apps/contourclock/ChangeLog +++ b/apps/contourclock/ChangeLog @@ -7,4 +7,4 @@ 0.25: Fixed a bug that would let widgets change the color of the clock. 0.26: Time formatted to locale 0.27: Fixed the timing code, which sometimes did not update for one minute -0.28: More config options, enabled fast loading +0.28: More config options for cleaner look, enabled fast loading From c07d23ce17c89c758a0669298629112b132c6fea Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 21:49:34 +0100 Subject: [PATCH 47/73] Update app.js --- apps/contourclock/app.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/apps/contourclock/app.js b/apps/contourclock/app.js index a1dd9f18a..87eb3e5e8 100644 --- a/apps/contourclock/app.js +++ b/apps/contourclock/app.js @@ -34,14 +34,19 @@ }; if (settings.hideWhenLocked) Bangle.on('lock', function (locked) { - g.clear(); - if (locked) require('contourclock').drawClock(settings.fontIndex); - else draw(); + if (!locked) require("widget_utils").show(); + else { + g.clear(); + if (settings.hide) require("widget_utils").swipeOn(); + else require("widget_utils").hide(); + } + draw(); }); - + require("FontTeletext10x18Ascii").add(Graphics); g.clear(); draw(); + Bangle.setUI({mode:"clock", remove:function() { if (drawTimeout) clearTimeout(drawTimeout); if (settings.widgets && settings.hide) require("widget_utils").show(); From 2b95ba68af50c8c19247f3d72412402fd7e03c94 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sat, 3 Dec 2022 21:50:46 +0100 Subject: [PATCH 48/73] Update app.js --- apps/contourclock/app.js | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/apps/contourclock/app.js b/apps/contourclock/app.js index 87eb3e5e8..8efa406c6 100644 --- a/apps/contourclock/app.js +++ b/apps/contourclock/app.js @@ -25,14 +25,21 @@ var date = new Date(); // Draw day of the week g.reset(); - g.setFont("Teletext10x18Ascii"); - g.clearRect(0,138,g.getWidth()-1,176); - if (settings.weekday) g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); - // Draw Date - if (settings.date) g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); + if ((!settings.hideWhenLocked) || (!Bangle.isLocked())) { + // Draw day of the week + g.setFont("Teletext10x18Ascii"); + g.clearRect(0,138,g.getWidth()-1,176); + if (settings.weekday) g.setFontAlign(0,1).drawString(require("locale").dow(date).toUpperCase(),g.getWidth()/2,g.getHeight()-18); + // Draw Date + if (settings.date) g.setFontAlign(0,1).drawString(require('locale').date(new Date(),1),g.getWidth()/2,g.getHeight()); + } require('contourclock').drawClock(settings.fontIndex); }; + require("FontTeletext10x18Ascii").add(Graphics); + g.clear(); + + draw(); if (settings.hideWhenLocked) Bangle.on('lock', function (locked) { if (!locked) require("widget_utils").show(); else { @@ -42,11 +49,6 @@ } draw(); }); - - require("FontTeletext10x18Ascii").add(Graphics); - g.clear(); - draw(); - Bangle.setUI({mode:"clock", remove:function() { if (drawTimeout) clearTimeout(drawTimeout); if (settings.widgets && settings.hide) require("widget_utils").show(); From 6324ffb378a77d8debd64cf28443946786016092 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 4 Dec 2022 10:56:20 +0100 Subject: [PATCH 49/73] kbswipe: Bug fixes --- apps/kbswipe/lib.js | 71 ++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index 451cc21b4..edc50817a 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -1,5 +1,5 @@ -const INPUT_MODE_ALPHA = 0; -const INPUT_MODE_NUM = 1; +exports.INPUT_MODE_ALPHA = 0; +exports.INPUT_MODE_NUM = 1; /* To make your own strokes, type: @@ -8,7 +8,7 @@ Bangle.on('stroke',print) on the left of the IDE, then do a stroke and copy out the Uint8Array line */ exports.getStrokes = function(mode, cb) { - if (mode === INPUT_MODE_ALPHA) { + if (mode === exports.INPUT_MODE_ALPHA) { cb("a", new Uint8Array([58, 159, 58, 155, 62, 144, 69, 127, 77, 106, 86, 90, 94, 77, 101, 68, 108, 62, 114, 59, 121, 59, 133, 61, 146, 70, 158, 88, 169, 107, 176, 124, 180, 135, 183, 144, 185, 152])); cb("b", new Uint8Array([51, 47, 51, 77, 56, 123, 60, 151, 65, 163, 68, 164, 68, 144, 67, 108, 67, 76, 72, 43, 104, 51, 121, 74, 110, 87, 109, 95, 131, 117, 131, 140, 109, 152, 88, 157])); cb("c", new Uint8Array([153, 62, 150, 62, 145, 62, 136, 62, 123, 62, 106, 65, 85, 70, 65, 75, 50, 82, 42, 93, 37, 106, 36, 119, 36, 130, 40, 140, 49, 147, 61, 153, 72, 156, 85, 157, 106, 158, 116, 158])); @@ -35,18 +35,18 @@ exports.getStrokes = function(mode, cb) { cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); - cb("SHIFT", new Uint8Array([106, 184, 106, 182, 106, 175, 106, 165, 106, 151, 106, 135, 106, 120, 106, 106, 106, 95, 106, 87, 106, 82, 106, 78, 106, 73, 106, 70, 106, 68, 106, 66, 106, 64])); - } else if (mode === INPUT_MODE_NUM) { - cb("0", new Uint8Array([105, 63, 97, 63, 80, 63, 62, 64, 52, 69, 47, 79, 47, 94, 48, 111, 55, 125, 74, 138, 100, 141, 126, 137, 148, 129, 158, 119, 161, 107, 161, 98, 159, 92, 154, 87, 149, 82])); - cb("1", new Uint8Array([123, 59, 123, 60, 123, 63, 123, 67, 123, 70, 122, 73, 121, 78, 119, 83, 118, 91, 117, 100, 116, 108, 115, 117, 114, 126, 113, 135, 112, 143, 111, 149, 111, 155, 110, 159])); - cb("2", new Uint8Array([61, 99, 61, 94, 61, 88, 61, 80, 65, 71, 73, 66, 83, 62, 97, 62, 109, 62, 126, 62, 141, 62, 149, 65, 151, 74, 151, 87, 150, 95, 143, 108, 130, 118, 117, 127, 100, 138, 84, 146, 67, 151, 55, 157, 52, 159, 73, 159, 117, 159, 163, 159, 183, 159])); - cb("3", new Uint8Array([69, 62, 78, 56, 98, 49, 121, 49, 141, 54, 149, 58, 150, 65, 148, 74, 143, 82, 126, 92, 114, 98, 119, 100, 135, 105, 143, 117, 142, 135, 123, 149, 105, 155])); - cb("4", new Uint8Array([78, 45, 78, 47, 78, 50, 78, 56, 78, 64, 78, 75, 78, 88, 78, 103, 78, 119, 78, 132, 78, 144, 78, 148, 80, 149, 84, 149, 96, 149, 112, 148, 127, 147, 144, 144, 163, 140, 175, 137])); - cb("5", new Uint8Array([142, 49, 134, 47, 121, 44, 104, 44, 88, 45, 75, 46, 68, 48, 64, 52, 64, 59, 64, 73, 64, 86, 64, 100, 67, 105, 82, 105, 106, 105, 130, 105, 143, 105, 149, 105, 151, 110, 148, 125, 138, 144, 118, 157, 92, 164, 76, 165, 65, 165, 60, 165])); - cb("6", new Uint8Array([161, 47, 151, 47, 133, 47, 108, 48, 85, 52, 65, 59, 53, 72, 46, 89, 44, 107, 49, 133, 71, 151, 100, 156, 118, 152, 120, 141, 108, 132, 84, 127, 70, 126])); - cb("7", new Uint8Array([43, 53, 53, 49, 72, 45, 96, 40, 116, 38, 129, 38, 138, 38, 144, 38, 147, 39, 149, 47, 143, 75, 127, 121, 114, 147, 107, 158, 104, 162, 98, 168, 93, 171])); - cb("8", new Uint8Array([148, 66, 135, 58, 113, 49, 97, 43, 84, 40, 74, 40, 66, 43, 62, 47, 62, 51, 67, 61, 84, 75, 101, 88, 111, 101, 113, 115, 110, 135, 98, 149, 84, 156, 73, 157, 63, 157, 58, 154, 52, 144, 52, 133, 54, 122, 65, 111, 81, 100, 97, 92, 110, 86, 121, 81, 129, 80, 137, 80, 145, 79, 151, 78])); - cb("9", new Uint8Array([146, 57, 146, 52, 146, 46, 143, 42, 135, 41, 123, 41, 107, 45, 92, 49, 83, 53, 78, 62, 89, 82, 110, 94, 126, 94, 139, 88, 147, 81, 151, 74, 152, 75, 152, 80, 152, 88, 152, 101, 152, 121, 152, 140, 152, 154, 152, 165, 152, 171])); + cb("SHIFT", new Uint8Array([100, 160, 100, 50])); + } else if (mode === exports.INPUT_MODE_NUM) { + cb("0", new Uint8Array([127, 67, 125, 67, 121, 67, 111, 67, 98, 67, 83, 68, 72, 70, 64, 74, 58, 79, 54, 86, 51, 96, 50, 107, 50, 116, 50, 125, 53, 132, 59, 141, 66, 146, 75, 150, 93, 155, 112, 157, 132, 154, 147, 146, 158, 126, 160, 113, 159, 103, 155, 94, 149, 89, 142, 85])); + cb("1", new Uint8Array([100, 50, 100, 160])); + cb("2", new Uint8Array([63, 80, 65, 78, 68, 75, 72, 71, 79, 67, 87, 62, 97, 59, 106, 58, 115, 58, 122, 58, 126, 61, 128, 66, 129, 72, 127, 84, 123, 100, 115, 116, 110, 126, 103, 136, 95, 146, 93, 149, 98, 150, 114, 150, 136, 150, 154, 150])); + cb("3", new Uint8Array([100, 62, 102, 62, 105, 62, 109, 62, 114, 62, 121, 62, 127, 62, 131, 62, 135, 62, 137, 63, 138, 66, 138, 68, 138, 70, 137, 72, 135, 74, 133, 77, 132, 79, 129, 81, 126, 84, 123, 86, 119, 86, 122, 90, 129, 93, 142, 101, 150, 107, 154, 117, 154, 126, 150, 135, 142, 142, 131, 147, 122, 150])); + cb("4", new Uint8Array([93, 61, 93, 63, 93, 68, 93, 75, 93, 84, 93, 93, 93, 101, 93, 113, 93, 126, 93, 137, 93, 144, 93, 149, 93, 151, 93, 154, 93, 156, 94, 157, 96, 157, 103, 157, 120, 157, 141, 157, 161, 157, 176, 157, 182, 157, 185, 157])); + cb("5", new Uint8Array([151, 57, 144, 55, 130, 55, 110, 56, 94, 59, 83, 61, 78, 69, 78, 78, 78, 86, 78, 93, 83, 100, 103, 103, 127, 106, 143, 114, 148, 128, 141, 142, 125, 152, 107, 159, 90, 162, 81, 163])); + cb("6", new Uint8Array([147, 35, 145, 35, 141, 36, 136, 38, 130, 42, 123, 47, 115, 51, 106, 57, 97, 64, 88, 73, 81, 82, 76, 89, 73, 95, 71, 101, 70, 108, 70, 114, 70, 118, 71, 124, 74, 131, 80, 137, 87, 140, 96, 143, 103, 143, 108, 141, 113, 138, 116, 134, 118, 127, 118, 120, 118, 114, 116, 107, 113, 103, 109, 100])); + cb("7", new Uint8Array([66, 69, 69, 69, 75, 67, 83, 66, 95, 66, 108, 63, 121, 61, 132, 61, 141, 61, 147, 61, 151, 61, 154, 61, 156, 61, 158, 61, 160, 61, 162, 61, 162, 63, 161, 67, 156, 85, 147, 112, 137, 135, 129, 151, 124, 158])); + cb("8", new Uint8Array([148, 59, 145, 55, 137, 52, 125, 52, 112, 52, 100, 54, 92, 56, 84, 60, 81, 66, 81, 76, 90, 82, 109, 90, 128, 98, 136, 106, 137, 121, 126, 140, 107, 151, 92, 151, 81, 143, 81, 122, 92, 94, 108, 75, 124, 65])); + cb("9", new Uint8Array([129, 72, 127, 72, 125, 72, 122, 72, 117, 72, 111, 72, 104, 74, 100, 77, 95, 79, 94, 81, 94, 83, 94, 87, 96, 90, 101, 92, 105, 94, 111, 94, 115, 94, 121, 92, 130, 89, 136, 85, 140, 82, 144, 79, 146, 79, 147, 83, 149, 97, 149, 118, 149, 135, 149, 149, 149, 158])); } cb("\b", new Uint8Array([183, 103, 182, 103, 180, 103, 176, 103, 169, 103, 159, 103, 147, 103, 133, 103, 116, 103, 101, 103, 85, 103, 73, 103, 61, 103, 52, 103, 38, 103, 34, 103, 29, 103, 27, 103, 26, 103, 25, 103, 24, 103])); cb(" ", new Uint8Array([39, 118, 40, 118, 41, 118, 44, 118, 47, 118, 52, 118, 58, 118, 66, 118, 74, 118, 84, 118, 94, 118, 104, 117, 114, 116, 123, 116, 130, 116, 144, 116, 149, 116, 154, 116, 158, 116, 161, 116, 163, 116])); @@ -54,7 +54,7 @@ exports.getStrokes = function(mode, cb) { exports.input = function(options) { options = options||{}; - let input_mode = INPUT_MODE_ALPHA; + let input_mode = exports.INPUT_MODE_ALPHA; var text = options.text; if ("string"!=typeof text) text=""; @@ -72,6 +72,7 @@ exports.input = function(options) { var Ry2; let flashInterval; let shift = false; + let lastDrag; function findMarker(strArr) { if (strArr.length == 0) { @@ -140,6 +141,20 @@ exports.input = function(options) { }); } + function isInside(rect, e) { + return e.x>=rect.x && e.x=rect.y && e.y<=rect.y+rect.h; + } + + function isStrokeInAppRect(stroke, rect) { + for(let i=0; i < stroke.length; i+=2) { + if (!isInside(rect, {x: stroke[i], y: stroke[i+1]})) { + return false; + } + } + return true; + } + function strokeHandler(o) { //print(o); if (!flashInterval) @@ -147,13 +162,14 @@ exports.input = function(options) { flashToggle = !flashToggle; draw(false); }, 1000); - if (o.stroke!==undefined) { + if (o.stroke!==undefined && o.xy.length >= 6 && isStrokeInAppRect(o.xy, R)) { var ch = o.stroke; if (ch=="\b") text = text.slice(0,-1); else if (ch==="SHIFT") { shift=!shift; Bangle.drawWidgets(); } else text += shift ? ch.toUpperCase() : ch; - g.clearRect(R); } + lastDrag = undefined; + g.clearRect(R); flashToggle = true; draw(false); } @@ -161,7 +177,7 @@ exports.input = function(options) { // Switches between alphabetic and numeric input function cycleInput() { input_mode++; - if (input_mode > INPUT_MODE_NUM) input_mode = 0; + if (input_mode > exports.INPUT_MODE_NUM) input_mode = 0; shift = false; setupStrokes(); show(); @@ -181,26 +197,27 @@ exports.input = function(options) { g.reset(); g.setFont("6x8:2x3"); g.setColor("#f00"); - if (input_mode === INPUT_MODE_ALPHA) { + if (input_mode === exports.INPUT_MODE_ALPHA) { g.drawString(shift ? "ABC" : "abc", this.x, this.y); - } else if (input_mode === INPUT_MODE_NUM) { + } else if (input_mode === exports.INPUT_MODE_NUM) { g.drawString("123", this.x, this.y); } } }; return new Promise((resolve,reject) => { - var l;//last event Bangle.setUI({mode:"custom", drag:e=>{ "ram"; - if (l) g.reset().setColor("#f00").drawLine(l.x,l.y,e.x,e.y); - l = e.b ? e : 0; + if (isInside(R, e)) { + if (lastDrag) g.reset().setColor("#f00").drawLine(lastDrag.x,lastDrag.y,e.x,e.y); + lastDrag = e.b ? e : 0; + } },touch:(n,e) => { - if (WIDGETS.kbswipe && e.x>=WIDGETS.kbswipe.x && e.x=WIDGETS.kbswipe.y && e.y<=WIDGETS.kbswipe.y+24) { + if (WIDGETS.kbswipe && isInside({x: WIDGETS.kbswipe.x, y: WIDGETS.kbswipe.y, w: WIDGETS.kbswipe.width, h: 24}, e)) { // touch inside widget cycleInput(); - } else { + } else if (isInside(R, e)) { + // touch inside app area show(); } }, back:()=>{ From 2183b53524b0162fa4a692531a386687a630688a Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 4 Dec 2022 11:46:12 +0100 Subject: [PATCH 50/73] kbswipe: Redo some patterns --- apps/kbswipe/lib.js | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index edc50817a..981dc80db 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -31,22 +31,22 @@ exports.getStrokes = function(mode, cb) { cb("t", new Uint8Array([45, 55, 48, 55, 55, 55, 72, 55, 96, 55, 120, 55, 136, 55, 147, 55, 152, 55, 155, 55, 157, 55, 158, 56, 158, 60, 156, 70, 154, 86, 151, 102, 150, 114, 148, 125, 148, 138, 148, 146])); cb("u", new Uint8Array([35, 52, 35, 59, 35, 73, 35, 90, 36, 114, 38, 133, 42, 146, 49, 153, 60, 157, 73, 158, 86, 156, 100, 152, 112, 144, 121, 131, 127, 114, 132, 97, 134, 85, 135, 73, 136, 61, 136, 56])); cb("v", new Uint8Array([36, 55, 37, 59, 40, 68, 45, 83, 51, 100, 58, 118, 64, 132, 69, 142, 71, 149, 73, 156, 76, 158, 77, 160, 77, 159, 80, 151, 82, 137, 84, 122, 86, 111, 90, 91, 91, 78, 91, 68, 91, 63, 92, 61, 97, 61, 111, 61, 132, 61, 150, 61, 162, 61])); - cb("w", new Uint8Array([33, 58, 34, 81, 39, 127, 44, 151, 48, 161, 52, 162, 57, 154, 61, 136, 65, 115, 70, 95, 76, 95, 93, 121, 110, 146, 119, 151, 130, 129, 138, 84, 140, 56, 140, 45])); + cb("w", new Uint8Array([25, 46, 25, 82, 25, 119, 33, 143, 43, 153, 60, 147, 73, 118, 75, 91, 76, 88, 85, 109, 96, 134, 107, 143, 118, 137, 129, 112, 134, 81, 134, 64, 134, 55])); cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); cb("SHIFT", new Uint8Array([100, 160, 100, 50])); } else if (mode === exports.INPUT_MODE_NUM) { - cb("0", new Uint8Array([127, 67, 125, 67, 121, 67, 111, 67, 98, 67, 83, 68, 72, 70, 64, 74, 58, 79, 54, 86, 51, 96, 50, 107, 50, 116, 50, 125, 53, 132, 59, 141, 66, 146, 75, 150, 93, 155, 112, 157, 132, 154, 147, 146, 158, 126, 160, 113, 159, 103, 155, 94, 149, 89, 142, 85])); + cb("0", new Uint8Array([82, 50, 76, 50, 67, 50, 59, 50, 50, 51, 43, 57, 38, 68, 34, 83, 33, 95, 33, 108, 34, 121, 42, 136, 57, 148, 72, 155, 85, 157, 98, 155, 110, 149, 120, 139, 128, 127, 134, 119, 137, 114, 138, 107, 138, 98, 138, 88, 138, 77, 137, 71, 134, 65, 128, 60, 123, 58])); cb("1", new Uint8Array([100, 50, 100, 160])); - cb("2", new Uint8Array([63, 80, 65, 78, 68, 75, 72, 71, 79, 67, 87, 62, 97, 59, 106, 58, 115, 58, 122, 58, 126, 61, 128, 66, 129, 72, 127, 84, 123, 100, 115, 116, 110, 126, 103, 136, 95, 146, 93, 149, 98, 150, 114, 150, 136, 150, 154, 150])); - cb("3", new Uint8Array([100, 62, 102, 62, 105, 62, 109, 62, 114, 62, 121, 62, 127, 62, 131, 62, 135, 62, 137, 63, 138, 66, 138, 68, 138, 70, 137, 72, 135, 74, 133, 77, 132, 79, 129, 81, 126, 84, 123, 86, 119, 86, 122, 90, 129, 93, 142, 101, 150, 107, 154, 117, 154, 126, 150, 135, 142, 142, 131, 147, 122, 150])); - cb("4", new Uint8Array([93, 61, 93, 63, 93, 68, 93, 75, 93, 84, 93, 93, 93, 101, 93, 113, 93, 126, 93, 137, 93, 144, 93, 149, 93, 151, 93, 154, 93, 156, 94, 157, 96, 157, 103, 157, 120, 157, 141, 157, 161, 157, 176, 157, 182, 157, 185, 157])); - cb("5", new Uint8Array([151, 57, 144, 55, 130, 55, 110, 56, 94, 59, 83, 61, 78, 69, 78, 78, 78, 86, 78, 93, 83, 100, 103, 103, 127, 106, 143, 114, 148, 128, 141, 142, 125, 152, 107, 159, 90, 162, 81, 163])); - cb("6", new Uint8Array([147, 35, 145, 35, 141, 36, 136, 38, 130, 42, 123, 47, 115, 51, 106, 57, 97, 64, 88, 73, 81, 82, 76, 89, 73, 95, 71, 101, 70, 108, 70, 114, 70, 118, 71, 124, 74, 131, 80, 137, 87, 140, 96, 143, 103, 143, 108, 141, 113, 138, 116, 134, 118, 127, 118, 120, 118, 114, 116, 107, 113, 103, 109, 100])); - cb("7", new Uint8Array([66, 69, 69, 69, 75, 67, 83, 66, 95, 66, 108, 63, 121, 61, 132, 61, 141, 61, 147, 61, 151, 61, 154, 61, 156, 61, 158, 61, 160, 61, 162, 61, 162, 63, 161, 67, 156, 85, 147, 112, 137, 135, 129, 151, 124, 158])); - cb("8", new Uint8Array([148, 59, 145, 55, 137, 52, 125, 52, 112, 52, 100, 54, 92, 56, 84, 60, 81, 66, 81, 76, 90, 82, 109, 90, 128, 98, 136, 106, 137, 121, 126, 140, 107, 151, 92, 151, 81, 143, 81, 122, 92, 94, 108, 75, 124, 65])); - cb("9", new Uint8Array([129, 72, 127, 72, 125, 72, 122, 72, 117, 72, 111, 72, 104, 74, 100, 77, 95, 79, 94, 81, 94, 83, 94, 87, 96, 90, 101, 92, 105, 94, 111, 94, 115, 94, 121, 92, 130, 89, 136, 85, 140, 82, 144, 79, 146, 79, 147, 83, 149, 97, 149, 118, 149, 135, 149, 149, 149, 158])); + cb("2", new Uint8Array([40, 88, 40, 83, 40, 76, 43, 71, 47, 64, 55, 59, 64, 55, 73, 50, 80, 47, 91, 44, 104, 44, 117, 45, 128, 50, 135, 57, 142, 63, 145, 74, 145, 84, 140, 94, 129, 112, 108, 133, 87, 149, 71, 159, 58, 165, 52, 169, 55, 169, 63, 169, 77, 169, 89, 169, 100, 169, 110, 169, 116, 169])); + cb("3", new Uint8Array([52, 58, 65, 49, 83, 42, 100, 42, 118, 47, 136, 58, 143, 71, 135, 88, 125, 99, 114, 101, 119, 101, 132, 110, 142, 121, 145, 137, 139, 152, 122, 164, 106, 168, 92, 168, 74, 168, 55, 168])); + cb("4", new Uint8Array([37, 58, 37, 60, 37, 64, 37, 69, 37, 75, 37, 86, 37, 96, 37, 105, 37, 112, 37, 117, 37, 122, 37, 126, 37, 128, 38, 129, 40, 129, 45, 129, 48, 129, 53, 129, 67, 129, 85, 129, 104, 129, 119, 129, 129, 129, 136, 129])); + cb("5", new Uint8Array([142, 60, 119, 60, 79, 60, 45, 60, 37, 64, 37, 86, 37, 103, 47, 107, 66, 106, 81, 103, 97, 103, 116, 103, 129, 108, 131, 130, 122, 152, 101, 168, 85, 172, 70, 172, 59, 172])); + cb("6", new Uint8Array([128, 56, 110, 56, 81, 56, 58, 61, 47, 77, 41, 101, 41, 123, 41, 154, 50, 168, 71, 169, 98, 169, 123, 161, 131, 141, 129, 124, 117, 117, 102, 117, 92, 117, 85, 118, 77, 125])); + cb("7", new Uint8Array([47, 38, 48, 38, 53, 38, 66, 38, 85, 38, 103, 38, 117, 38, 125, 38, 129, 38, 134, 41, 135, 47, 135, 54, 135, 66, 131, 93, 124, 126, 116, 149, 109, 161, 105, 168])); + cb("8", new Uint8Array([122, 61, 102, 61, 83, 61, 60, 61, 47, 62, 45, 78, 58, 99, 84, 112, 105, 122, 118, 134, 121, 149, 113, 165, 86, 171, 59, 171, 47, 164, 45, 144, 50, 132, 57, 125, 67, 117, 78, 109, 87, 102, 96, 94, 105, 86, 113, 85])); + cb("9", new Uint8Array([122, 58, 117, 55, 112, 51, 104, 51, 95, 51, 86, 51, 77, 51, 68, 51, 60, 51, 54, 56, 47, 64, 46, 77, 46, 89, 46, 96, 51, 103, 64, 109, 74, 110, 83, 110, 94, 107, 106, 102, 116, 94, 124, 84, 127, 79, 128, 78, 128, 94, 128, 123, 128, 161, 128, 175])); } cb("\b", new Uint8Array([183, 103, 182, 103, 180, 103, 176, 103, 169, 103, 159, 103, 147, 103, 133, 103, 116, 103, 101, 103, 85, 103, 73, 103, 61, 103, 52, 103, 38, 103, 34, 103, 29, 103, 27, 103, 26, 103, 25, 103, 24, 103])); cb(" ", new Uint8Array([39, 118, 40, 118, 41, 118, 44, 118, 47, 118, 52, 118, 58, 118, 66, 118, 74, 118, 84, 118, 94, 118, 104, 117, 114, 116, 123, 116, 130, 116, 144, 116, 149, 116, 154, 116, 158, 116, 161, 116, 163, 116])); @@ -146,7 +146,7 @@ exports.input = function(options) { && e.y>=rect.y && e.y<=rect.y+rect.h; } - function isStrokeInAppRect(stroke, rect) { + function isStrokeInside(rect, stroke) { for(let i=0; i < stroke.length; i+=2) { if (!isInside(rect, {x: stroke[i], y: stroke[i+1]})) { return false; @@ -162,7 +162,7 @@ exports.input = function(options) { flashToggle = !flashToggle; draw(false); }, 1000); - if (o.stroke!==undefined && o.xy.length >= 6 && isStrokeInAppRect(o.xy, R)) { + if (o.stroke!==undefined && o.xy.length >= 6 && isStrokeInside(R, o.xy)) { var ch = o.stroke; if (ch=="\b") text = text.slice(0,-1); else if (ch==="SHIFT") { shift=!shift; Bangle.drawWidgets(); } From fa70e5354c6df1485b546900123022c2a5a930a4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 4 Dec 2022 16:42:24 +0100 Subject: [PATCH 51/73] aiclock -- support clkinfo module and updated icons of some clkinfos... --- apps/aiclock/ChangeLog | 1 + apps/aiclock/README.md | 4 +- apps/aiclock/aiclock.app.js | 285 +++++++++++++++++++++++++++++++----- apps/aiclock/impl.png | Bin 2743 -> 2597 bytes apps/aiclock/impl_2.png | Bin 0 -> 2459 bytes apps/aiclock/impl_3.png | Bin 0 -> 2487 bytes apps/aiclock/metadata.json | 6 +- apps/ha/ChangeLog | 3 +- apps/ha/ha.clkinfo.js | 2 +- apps/ha/metadata.json | 2 +- apps/smpltmr/ChangeLog | 3 +- apps/smpltmr/clkinfo.js | 3 +- apps/smpltmr/metadata.json | 2 +- apps/weather/ChangeLog | 1 + apps/weather/clkinfo.js | 2 +- apps/weather/metadata.json | 2 +- core | 2 +- modules/clock_info.js | 2 +- 18 files changed, 270 insertions(+), 50 deletions(-) create mode 100644 apps/aiclock/impl_2.png create mode 100644 apps/aiclock/impl_3.png diff --git a/apps/aiclock/ChangeLog b/apps/aiclock/ChangeLog index 96b389f6e..fb5aed3e3 100644 --- a/apps/aiclock/ChangeLog +++ b/apps/aiclock/ChangeLog @@ -2,3 +2,4 @@ 0.02: Design improvements and fixes. 0.03: Indicate battery level through line occurrence. 0.04: Use widget_utils module. +0.05: Support for clkinfo. \ No newline at end of file diff --git a/apps/aiclock/README.md b/apps/aiclock/README.md index 9e23de3a6..31dd5aa29 100644 --- a/apps/aiclock/README.md +++ b/apps/aiclock/README.md @@ -10,7 +10,9 @@ The original output of stable diffusion is shown here: My implementation is shown below. Note that horizontal lines occur randomly, but the probability is correlated with the battery level. So if your screen contains only -a few lines its time to charge your bangle again ;) +a few lines its time to charge your bangle again ;) Also note that the upper text +implementes the clkinfo module and can be configured via touch left/right/up/down. +Touch at the center to trigger the selected action. ![](impl.png) diff --git a/apps/aiclock/aiclock.app.js b/apps/aiclock/aiclock.app.js index 5d4e98fcd..b5bb30b9d 100644 --- a/apps/aiclock/aiclock.app.js +++ b/apps/aiclock/aiclock.app.js @@ -1,6 +1,14 @@ -/** +/************************************************ * AI Clock */ + const storage = require('Storage'); + const clock_info = require("clock_info"); + + + + /************************************************ + * Assets + */ require("Font7x11Numeric7Seg").add(Graphics); Graphics.prototype.setFontGochiHand = function(scale) { // Actual height 27 (29 - 3) @@ -13,7 +21,7 @@ Graphics.prototype.setFontGochiHand = function(scale) { return this; } -/* +/************************************************ * Set some important constants such as width, height and center */ var W = g.getWidth(),R=W/2; @@ -21,6 +29,120 @@ var H = g.getHeight(); var cx = W/2; var cy = H/2; var drawTimeout; +var lock_input = false; + + +/************************************************ + * SETTINGS + */ +const SETTINGS_FILE = "aiclock.setting.json"; +let settings = { + menuPosX: 0, + menuPosY: 0, +}; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} + + +/************************************************ + * Menu + */ +function getDate(){ + var date = new Date(); + return ("0"+date.getDate()).substr(-2) + "/" + ("0"+(date.getMonth()+1)).substr(-2) +} + + +// Custom clockItems menu - therefore, its added here and not in a clkinfo.js file. +var clockItems = { + name: getDate(), + img: null, + items: [ + { name: "Week", + get: () => ({ text: "Week " + weekOfYear(), img: null}), + show: function() { clockItems.items[0].emit("redraw"); }, + hide: function () {} + }, + ] + }; + +function weekOfYear() { + var date = new Date(); + date.setHours(0, 0, 0, 0); + // Thursday in current week decides the year. + date.setDate(date.getDate() + 3 - (date.getDay() + 6) % 7); + // January 4 is always in week 1. + var week1 = new Date(date.getFullYear(), 0, 4); + // Adjust to Thursday in week 1 and count number of weeks from date to week1. + return 1 + Math.round(((date.getTime() - week1.getTime()) / 86400000 + - 3 + (week1.getDay() + 6) % 7) / 7); +} + + + +// Load menu +var menu = clock_info.load(); +menu = menu.concat(clockItems); + + + // Ensure that our settings are still in range (e.g. app uninstall). Otherwise reset the position it. + if(settings.menuPosX >= menu.length || settings.menuPosY > menu[settings.menuPosX].items.length ){ + settings.menuPosX = 0; + settings.menuPosY = 0; + } + + // Set draw functions for each item + menu.forEach((menuItm, x) => { + menuItm.items.forEach((item, y) => { + function drawItem() { + // For the clock, we have a special case, as we don't wanna redraw + // immediately when something changes. Instead, we update data each minute + // to save some battery etc. Therefore, we hide (and disable the listener) + // immedeately after redraw... + item.hide(); + + // After drawing the item, we enable inputs again... + lock_input = false; + + var info = item.get(); + drawMenuItem(info.text, info.img); + } + + item.on('redraw', drawItem); + }) + }); + + + function canRunMenuItem(){ + if(settings.menuPosY == 0){ + return false; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + return item.run !== undefined; + } + + + function runMenuItem(){ + if(settings.menuPosY == 0){ + return; + } + + var menuEntry = menu[settings.menuPosX]; + var item = menuEntry.items[settings.menuPosY-1]; + try{ + var ret = item.run(); + if(ret){ + Bangle.buzz(300, 0.6); + } + } catch (ex) { + // Simply ignore it... + } + } + /* * Based on the great multi clock from https://github.com/jeffmer/BangleApps/ @@ -76,7 +198,50 @@ function toAngle(a){ return a } + +function drawMenuItem(text, image){ + if(text == null){ + drawTime(); + return + } + // image = atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="); + + text = String(text); + + g.reset().setBgColor("#fff").setColor("#000"); + g.setFontAlign(0,0); + g.setFont("Vector", 20); + + var imgWidth = image == null ? 0 : 24; + var strWidth = g.stringWidth(text); + var strHeight = text.split('\n').length > 1 ? 40 : Math.max(24, imgWidth+2); + var w = imgWidth + strWidth; + + g.clearRect(cx-w/2-8, 40-strHeight/2-1, cx+w/2+4, 40+strHeight/2) + + // Draw right line as designed by stable diffusion + g.drawLine(cx+w/2+5, 40-strHeight/2-1, cx+w/2+5, 40+strHeight/2); + g.drawLine(cx+w/2+6, 40-strHeight/2-1, cx+w/2+6, 40+strHeight/2); + g.drawLine(cx+w/2+7, 40-strHeight/2-1, cx+w/2+7, 40+strHeight/2); + + // And finally the text + g.drawString(text, cx+imgWidth/2, 42); + g.drawString(text, cx+1+imgWidth/2, 41); + + if(image != null) { + var scale = image.width ? imgWidth / image.width : 1; + g.drawImage(image, W/2 + -strWidth/2-4 - parseInt(imgWidth/2), 41-12, {scale: scale}); + } + + drawTime(); +} + + function drawTime(){ + // Draw digital time first + drawDigits(); + + // And now the analog time var drawHourHand = g.drawRotRect.bind(g,8,12,R-38); var drawMinuteHand = g.drawRotRect.bind(g,6,12,R-12 ); @@ -90,13 +255,6 @@ function drawTime(){ h += date.getMinutes()/60.0; h = parseInt(h*360/12); - // Draw minute and hour bg - g.setColor(g.theme.bg); - drawHourHand(toAngle(h-3)); - drawHourHand(toAngle(h+3)); - drawMinuteHand(toAngle(m-2)); - drawMinuteHand(toAngle(m+3)); - // Draw minute and hour fg g.setColor(g.theme.fg); drawHourHand(h); @@ -104,28 +262,6 @@ function drawTime(){ } - -function drawDate(){ - var date = new Date(); - g.setFontAlign(0,0); - g.setFontGochiHand(); - - var text = ("0"+date.getDate()).substr(-2) + "/" + ("0"+(date.getMonth()+1)).substr(-2); - var w = g.stringWidth(text); - g.setColor(g.theme.bg); - g.fillRect(cx-w/2-4, 20, cx+w/2+4, 40+12); - - g.setColor(g.theme.fg); - // Draw right line as designed by stable diffusion - g.drawLine(cx+w/2+5, 20, cx+w/2+5, 40+12); - g.drawLine(cx+w/2+6, 20, cx+w/2+6, 40+12); - g.drawLine(cx+w/2+7, 20, cx+w/2+7, 40+12); - - // And finally the text - g.drawString(text, cx, 40); -} - - function drawDigits(){ var date = new Date(); @@ -156,20 +292,35 @@ function drawDigits(){ } +function drawDate(){ + var menuEntry = menu[settings.menuPosX]; + + // The first entry is the overview... + if(settings.menuPosY == 0){ + drawMenuItem(menuEntry.name, menuEntry.img); + return; + } + + // Draw item if needed + lock_input = true; + var item = menuEntry.items[settings.menuPosY-1]; + item.show(); +} + + + + function draw(){ // Queue draw in one minute queueDraw(); - g.reset(); g.clearRect(0, 0, g.getWidth(), g.getHeight()); - g.setColor(1,1,1); + drawBackground(); drawDate(); - drawDigits(); - drawTime(); drawCircle(Bangle.isLocked()); } @@ -190,6 +341,68 @@ Bangle.on('lock', function(isLocked) { drawCircle(isLocked); }); +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.22); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.22); + var lower = g.getHeight() - upper; + + var is_upper = e.y < upper; + var is_lower = e.y > lower; + var is_left = e.x < left && !is_upper && !is_lower; + var is_right = e.x > right && !is_upper && !is_lower; + var is_center = !is_upper && !is_lower && !is_left && !is_right; + + if(lock_input){ + return; + } + + if(is_lower){ + Bangle.buzz(40, 0.6); + settings.menuPosY = (settings.menuPosY+1) % (menu[settings.menuPosX].items.length+1); + + draw(); + } + + if(is_upper){ + Bangle.buzz(40, 0.6); + settings.menuPosY = settings.menuPosY-1; + settings.menuPosY = settings.menuPosY < 0 ? menu[settings.menuPosX].items.length : settings.menuPosY; + + draw(); + } + + if(is_right){ + Bangle.buzz(40, 0.6); + settings.menuPosX = (settings.menuPosX+1) % menu.length; + settings.menuPosY = 0; + draw(); + } + + if(is_left){ + Bangle.buzz(40, 0.6); + settings.menuPosY = 0; + settings.menuPosX = settings.menuPosX-1; + settings.menuPosX = settings.menuPosX < 0 ? menu.length-1 : settings.menuPosX; + draw(); + } + + if(is_center){ + if(canRunMenuItem()){ + runMenuItem(); + } + } +}); + + +E.on("kill", function(){ + try{ + storage.write(SETTINGS_FILE, settings); + } catch(ex){ + // If this fails, we still kill the app... + } +}); + /* * Some helpers @@ -203,7 +416,6 @@ function queueDraw() { } - /* * Lets start widgets, listen for btn etc. */ @@ -216,6 +428,7 @@ Bangle.loadWidgets(); * area to the top bar doesn't get cleared. */ require('widget_utils').hide(); + // Clear the screen once, at startup and draw clock g.setTheme({bg:"#fff",fg:"#000",dark:false}).clear(); draw(); diff --git a/apps/aiclock/impl.png b/apps/aiclock/impl.png index 92374b68059bb87f00feb41525d8b6dcb9d91c87..8a9e43e2deabf9a80b9cc59b763db5bf3bf15a47 100644 GIT binary patch delta 2576 zcmV+r3h(u|6{QrAFnz3oV3Pw}!|Il@oGsit1w=6C~Hdwp<%<2gc z^s$ApoK*e%{{H@c_(6f93j6?Y(aMqbR{;P9gwhHCaOv`q{Lkm}VFreSvI+oj+0v2t zcLt^d143m5n1L%-kK8$hfPvZy(1B~$Z~5#2czFbB3jn~i>wmX=_5i#*0<{GI;M(Bv<17Kqr z=)gw7CYz@RxPSWZM(YX8W*DdYsBcC+OW(vv-65mk<4D~b0e~m!4Zst{{eNfxo~ZFm zfGdwCd+rfeAOL<4;O(tFMU*ziz9diViE?~HM*|lfFM9oDXW*W&qoM=wznG0`84c_? zUP*wpmq@MMU!oWe@3VE`XyBsbMFU+9U@MeXd+9QK?tjhz9F3$cUMYZkFnV8W$)z1n zq#65|Q!8fcbOFg#27m)M z+(?(*d^O$eJVNx+Z^e_q+`G2cZhwER{S|PM|CKfX91O4|wDh`k*|z}PiY0*pz=1$y z{1XGx<$p{9RC+xc;A1>(_v>BiTQ`ZLaW$LjN*AqfESCCcr9Mt6-F!$RhG&G(j0wBV zC}^$j9|5}-Ld{zBXx(G^Du9mw9E%}=-@93|bo9yqYu0%WlD2nw%_&50*-rp`HCnW0 z;MQi_*V8(&Xm$Kv+}2p4#e|zUtx`%mFO1spVSnT%&T^^tc5CTWq!m}nOSA(^N&ewawj*2dIEa@bp=YPKZ_Z~KA zA4Igq4bA3~8o+tuXzZQkbi0-8z?M##QFKqWq)jzzoukdbvsR1Gs{x)>RExk7wi3M3 z6@OtQ2LK*XPwRjGH?u0;8g%?&R;`RBS;zrUIVanA~Ex*DNQvOOeEc>(H5)$ zOCC@FfCt3G^?3yV`1u-;!GHpMfAWlM}GmTdQ zOgDDYP|)qQ00VJB8XYOW8ekxH5K+wK^#B8LF(QrWE&(tQ8>uK{z6`)XT!>0Ts!IV3 z#0D~om@Wq}5Emg+nI?~tl|o^bQvm?ZSr@WWDgeMrp)kv-z>+g?s}z>cPi+2thJPXl z&;Wd>0}$tc(vk%LpVR_k3qH@=0&t@SBM@tR89(B{2jB}WH6V_b0gy)({Cohoqv0J8 zb3-@=F#rqt0r41Mv%LXWsqh^jGg2svaXdNNjx_CVc%VQI1$YuSp$@%{unEpjoB{wG zr{y=2=5hwaaiTK=8@25I0zpHp9)HBl!g?VASg+OB@(N&0=RLpG6~q9nFA4zbwE|$H zR(F^Kuu)|?uu-td<^XII7=Vp}O*RK$qrd=c6l}6N02>7cV54A@%>mdbFaR3`n{3X5 zj6i`cM`=9Fh!GxuV|4rzMFTPL#)%HVaayV%2Hse~nSq^p&iHsGPvGpu0DoY+X5A-p z&TwBh0Jf_Kz;@04ctmz#;Pn*(fPK1!Lkz&aLIAK&x4*nbyDI1t<91z?+AA=ce*b^K}`g@mN>iXZ^|P#J+ZMtA^@(a{_QfX$LM9RN5+ zM^_XecFFc1CjcJT&>aDQ-G9>kdk+80ZSS~>0}+6DK)mf+;s87*V1zdi`&9&Bzjk4s z0PL3%fc@HqdIGUeP5}1l7VZVWK1umThEF%Vk|+ScNeV$4J_P{SryE{L6krBUQix+3 z%)|Pk0I*)G+bjWCFEs$`wYt?3h;?!UuuiAjtpHdjIRNW)dc+EdWq;WLSk~wA3NZld>W5Y556f)gJk|XG7&O%iWbDFe09O8OKDF3hL#dN&f^9a| z|Mv2czT)2UmGbnifAjO?BXwaI8ewH%f{0d4$BXKIuJ1Hh-EnpV4tgyHO;&*PcQ= zH9|;mNd?iqZUJa^2iE31!!A9*+KzA*rwYJP>+8W`0a%-lWdqFscaO;oZ1{DinoILt z9oTY|WdT?VTbdb|QwaU<eQeKg-(}6!9P9cJC;;evbJ6`4)*t+IO`}6>N z7khPy8@cq2_-fXn?WmeqBQ~0uIZLi(06upr?Z2f$YUAv7QoNDZJy0BB^Z2*&Ed_A) zW3&+8uy)9!ed{c=RexaZH$6OsmI^ll+*RJvds<%a zou2G*0NA3a(zePegy!Lha>;+pdYeLmO`Ff``vL8m)6c-(yYy86Zs~J3z*^X5*rf;9 zyXdC?w!)+Bcvc;(dF=7E`HYM{*0uEP(*sBd{|CU41I|D!I`BW@S-UU*4?x#)r326Fz*}VL zK?vu-!9Z)nW$VBi5L!TK*W0~Q7rw>J2oa(3MT}}4*eZqglI=N#I6tYoiqZQ#g=XVP z4@az;SnSh3O13OU(@92v8S(7_DBW0jHR$QFzkkLE5ut7;#<>Gq{@p54)B$`{*NMod zmCI2lZ;5(qV#HtS%Sc@xlyMa``t~2tP5z~|Fs5Y1P5Gw;bOVkzOS~tclP11juXV$`r zJAbA?8i2EZ7Gg|hyk{wpW(Ee}StTa!9SWowA?{c#@9{nb0Qh}1U1~)Dyi~d0x7gQy z7UF%SVnrv;v$$lrA61{|_Zq!t()@0agG200{s|MNUMnLSTX!S;Yqc delta 2723 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 literal 0 HcmV?d00001 diff --git a/apps/aiclock/impl_3.png b/apps/aiclock/impl_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c2a036d14b24b0ac1cc982f108f92039254b97f9 GIT binary patch literal 2487 zcmai0X*AUP8~@IX8QG9x(IOhMg~=AlGJ`BB{O6u?-`yAg=bUGG^Ld_go;}gh!dOgrzc2tm%+$olny;Dv z@GcZzR@6?p@D(h?+Sm}3cgfEJAQWV3WMD&fS)j9ni_VA|-P_suGLkbwSAFyR$uIW} zs=8Tz{)z`mejG~v{T?@;Pa4|~^sSIASlyG5qODQ@5QbNgpzi7Q!xGSOOGg;M_#b?Y zI4+ug1yIa}jhBHaqF8!kdvkN*{DrF`>lO->^|hAhRp7*FZ5APlHP!BXE)^VGmRWQL zfV&X${VS}lDLzUTKv6$jS&;w}FwQ{&9%nnVLV@y@P)CA+|3bdY6#NInL~&m2aJhCZ zn>*dAXa5qS!0MjDfzwC4>vAYD-(|MI?$mqbi^P;IcUW^Gh(|CNPbv>1;&7vE>K3Z~p^l6Q~p_5!pN4Rwqt2*S#aTZsKvvIN` zQ-GXt&@UKS;JK}qpy$kaGrMc-*x7(4WZ*N4;kTr0?I4*r4rYGgit>u<^C@S%6Jt(K z)<7D9ZA>w2JUR-HoCZ)fsX+NqPZJ<#eoA{7Zqj{XY}b(Q$P$KV5Qc0bk=o7-;4Wdi zLY8#VjW5rQn0ZK>W4lgt#hzcdl~>H}v@d0;b-?PrtGoL=t`QX=nms(-Q46aZh>xn> zIvK$bAHW>t?BrFZ^j{YyMgQ*QY!mX==DZpK=4Xm4{ZS*Egba*odRIsqCsV(*6Cyoz zSieAe`gkE;#&=NWx_{WOkgk`QKRR)CRgyH{lO`@d`{?Vj zK7c#bc)$&WXDw;$rOC&F@A(dl)? z$W!RF3pYwFxqDB}1k)*2agcLpbetPEEm7AK1DC2~DMy56b5Rs}>}o5FeD|-e ztM-T} z$TLItve--1^h`7yg84GG2(0*B3H#;Ykk$CL4U4Q%!4^3%KQK><>x)?utsG6IG=92{+}CvX?{u`+MpD8Uk1jYqKvb$|1K%^FQZGePf*fFE zrxy?9C}b0s22kh?AfGZz)D#+u-`9JGEy3>!i38AV$6hd|xwUVL$@g|pYm6M(|Ki3; zFjz6fP#(EMz zk5)em&i?uMdN552_+7rM3s3lgVpH$E_+fFUxUJp_I0=l|<>>z$Py;S}OAfcKAr3GC zfsZiJO$T%%#zCMarCMJULOy?eH~5xw;wjKVvye-USk_8^cq2gk(m6l+C&Hyu_;-Q} zGLXh|7fnt}MOl3hi3#Df zgK3kV3KNT84)5Nh3j2w2TcejY6GloBkzsNahT+Fa_1q4^-=uPvpMH}{vgy`IN4oQ_ z*=MQk_+MYjO6$l*fV%VA{RZ zk1oEggUq4`j4I|OT^Q2H3sN+mGiyPm;)}U(W)GFYs5(XlI+0h!Qlt0_dQoe6f@qm~ z_C+5?6uSAwZVt*v>GV+V;BYiO;CD2%H|PvgrK~Tp7m>SVdjh?&zb#FCWKkuTZVIz+ zv{_8NxTAX7Q44Kv*VQ<01r2oLWwI5BXL!x%K}U(lT&R?l__m*FE15TPS#PfFBInX{ zC!ROOr8aA~apE6!ooql|>n@xQNk$O+)Qv|jqX*L_0-gvblQ@4g5~sop4qf*X_UcKU31U&$<_ioG|f#2dMKr6#(3>Jb9>`?pYzyRp@8 zmc1n?9=hR~Sw0S18Ev{F=`DRccw~5KQA?G8|N1hf7LyrK){vqF*K+qq_NXaVwOp(z zK0G1BKdVWN!R9+Ei{-7^By$*l^zX2L<&{GH5<$l;U16Y{JKir1c>QYw8VZ!TsJbvD zXnMA_nj|>3sc_911_JzJwkBY8tlI=T01<{=Tgd+h@;oMQ+ka;FxJo$x69cB_EsV+y HiLw6!gEO)t literal 0 HcmV?d00001 diff --git a/apps/aiclock/metadata.json b/apps/aiclock/metadata.json index 0da23e8ca..1c3c68609 100644 --- a/apps/aiclock/metadata.json +++ b/apps/aiclock/metadata.json @@ -3,7 +3,7 @@ "name": "AI Clock", "shortName":"AI Clock", "icon": "aiclock.png", - "version":"0.04", + "version":"0.05", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "A watch face that was designed by an AI (stable diffusion) and implemented by a human.", @@ -11,7 +11,9 @@ "tags": "clock", "screenshots": [ {"url":"orig.png"}, - {"url":"impl.png"} + {"url":"impl.png"}, + {"url":"impl_2.png"}, + {"url":"impl_3.png"}, ], "storage": [ {"name":"aiclock.app.js","url":"aiclock.app.js"}, diff --git a/apps/ha/ChangeLog b/apps/ha/ChangeLog index a4865be3f..f9ca3c16d 100644 --- a/apps/ha/ChangeLog +++ b/apps/ha/ChangeLog @@ -2,4 +2,5 @@ 0.02: Includeas the ha.lib.js library that can be used by other apps or clocks. 0.03: Added clkinfo for clocks. 0.04: Feedback if clkinfo run is called. -0.05: Clkinfo improvements. \ No newline at end of file +0.05: Clkinfo improvements. +0.06: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/ha/ha.clkinfo.js b/apps/ha/ha.clkinfo.js index 1b1e468d7..d6a0f72a0 100644 --- a/apps/ha/ha.clkinfo.js +++ b/apps/ha/ha.clkinfo.js @@ -4,7 +4,7 @@ var haItems = { name: "Home", - img: atob("GBiBAf/////////n///D//+B//8A//48T/wkD/gkD/A8D+AYB8AYA4eZ4QyZMOyZN+fb5+D/B+B+B+A8B+AYB+AYB+AYB+AYB+A8Bw=="), + img: atob("GBiBAAAAAAAAAAAAAAAYAAA+AAB+AADD4AHb4APD4Afn8A/n+BxmOD0mnA0ksAwAMA+B8A/D8A/n8A/n8A/n8A/n8AAAAAAAAAAAAA=="), items: [] }; diff --git a/apps/ha/metadata.json b/apps/ha/metadata.json index fad052544..089450f55 100644 --- a/apps/ha/metadata.json +++ b/apps/ha/metadata.json @@ -1,7 +1,7 @@ { "id": "ha", "name": "HomeAssistant", - "version": "0.05", + "version": "0.06", "description": "Integrates your BangleJS into HomeAssistant.", "icon": "ha.png", "type": "app", diff --git a/apps/smpltmr/ChangeLog b/apps/smpltmr/ChangeLog index b09100f50..805e8546f 100644 --- a/apps/smpltmr/ChangeLog +++ b/apps/smpltmr/ChangeLog @@ -1,4 +1,5 @@ 0.01: Release 0.02: Rewrite with new interface 0.03: Added clock infos to expose timer functionality to clocks. -0.04: Improvements of clock infos. \ No newline at end of file +0.04: Improvements of clock infos. +0.05: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/smpltmr/clkinfo.js b/apps/smpltmr/clkinfo.js index 1a63a9b7e..c16e6127e 100644 --- a/apps/smpltmr/clkinfo.js +++ b/apps/smpltmr/clkinfo.js @@ -63,10 +63,9 @@ } catch(ex){ } } - var img = atob("GBiBAeAAB+AAB/v/3/v/3/v/3/v/3/v/n/n/H/z+P/48//85//+b//+b//8p//4E//yCP/kBH/oAn/oAX/oAX/oAX/oAX+AAB+AABw==") var smpltmrItems = { name: "Timer", - img: img, + img: atob("GBiBAAB+AAB+AAAYAAAYAAB+AA3/sA+B8A4AcAwMMBgPGBgPmDAPjDAPzDAPzDP/zDP/zDH/jBn/mBj/GAw8MA4AcAeB4AH/gAB+AA=="), items: [ { name: null, diff --git a/apps/smpltmr/metadata.json b/apps/smpltmr/metadata.json index ce526d1ba..2191902de 100644 --- a/apps/smpltmr/metadata.json +++ b/apps/smpltmr/metadata.json @@ -2,7 +2,7 @@ "id": "smpltmr", "name": "Simple Timer", "shortName": "Simple Timer", - "version": "0.04", + "version": "0.05", "description": "A very simple app to start a timer.", "icon": "app.png", "tags": "tool,alarm,timer,clkinfo", diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index aefb903b9..1b6c1b9b5 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -17,3 +17,4 @@ 0.18: Added hasRange to clkinfo. 0.19: Added weather condition to clkinfo. 0.20: Added weather condition with temperature to clkinfo. +0.21: Updated clkinfo icon. \ No newline at end of file diff --git a/apps/weather/clkinfo.js b/apps/weather/clkinfo.js index 339ff39c3..3cdd31c59 100644 --- a/apps/weather/clkinfo.js +++ b/apps/weather/clkinfo.js @@ -28,7 +28,7 @@ //FIXME ranges are somehow arbitrary var weatherItems = { name: "Weather", - img: atob("GBiBAf+///u5//n7//8f/9wHP8gDf/gB//AB/7AH/5AcP/AQH/DwD/uAD84AD/4AA/wAAfAAAfAAAfAAAfgAA/////+bP/+zf/+zfw=="), + img: atob("GBiBAABAAARGAAYEAADgACP4wDf8gAf+AA/+AE/4AG/jwA/v4A8P8AR/8DH/8AH//AP//g///g///g///gf//AAAAABkwABMgABMgA=="), items: [ { name: "conditionWithTemperature", diff --git a/apps/weather/metadata.json b/apps/weather/metadata.json index dd8b6c293..500eac012 100644 --- a/apps/weather/metadata.json +++ b/apps/weather/metadata.json @@ -1,7 +1,7 @@ { "id": "weather", "name": "Weather", - "version": "0.20", + "version": "0.21", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], diff --git a/core b/core index 3a953179b..764197500 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 3a953179b7bb9f574d4e77d5f34b6b7deee1e884 +Subproject commit 76419750083a88ee7a569db3975ae1bdd6dc155a diff --git a/modules/clock_info.js b/modules/clock_info.js index 238888b1c..50968311e 100644 --- a/modules/clock_info.js +++ b/modules/clock_info.js @@ -77,7 +77,7 @@ exports.load = function() { // actual menu var menu = [{ name: "Bangle", - img: atob("GBiBAf8B//4B//4B//4B//4A//x4//n+f/P/P+fPn+fPn+fP3+/Px+/Px+fn3+fzn+f/n/P/P/n+f/x4//4A//4B//4B//4B//8B/w=="), + img: atob("GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="), items: [ { name : "Battery", hasRange : true, From 3673a0d7cf33eea9efc9d14e2eb701e8b16afb98 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 4 Dec 2022 16:43:41 +0100 Subject: [PATCH 52/73] Fixed json file --- apps/aiclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/aiclock/metadata.json b/apps/aiclock/metadata.json index 1c3c68609..1dcda427f 100644 --- a/apps/aiclock/metadata.json +++ b/apps/aiclock/metadata.json @@ -13,7 +13,7 @@ {"url":"orig.png"}, {"url":"impl.png"}, {"url":"impl_2.png"}, - {"url":"impl_3.png"}, + {"url":"impl_3.png"} ], "storage": [ {"name":"aiclock.app.js","url":"aiclock.app.js"}, From 8016e8ec5333ec8fe5ef4b8ea95b4a7428513bf6 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Fri, 2 Dec 2022 23:53:32 +0100 Subject: [PATCH 53/73] bthrm - Correctly handle 0 values --- apps/bthrm/bthrm.js | 6 +++--- apps/bthrm/metadata.json | 1 + apps/bthrm/screen.png | Bin 0 -> 3702 bytes 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 apps/bthrm/screen.png diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index e163dd8b7..b07e7bd37 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -93,11 +93,11 @@ function draw(){ if (bt && bt.time > (now - VALUE_TIMEOUT)) { layout.bt.label = bt.bpm; - if (bt.battery) layout.btBattery.label = bt.battery; + if (!isNaN(bt.battery)) layout.btBattery.label = bt.battery + "%"; if (bt.rr) layout.btRR.label = bt.rr.join(","); - if (bt.location) layout.btLocation.label = BODY_LOCS[bt.location]; + if (!isNaN(bt.location)) layout.btLocation.label = BODY_LOCS[bt.location]; if (bt.contact !== undefined) layout.btContact.label = bt.contact ? "Yes":"No"; - if (bt.energy) layout.btEnergy.label = bt.energy.toFixed(0) + "kJ"; + if (!isNaN(bt.energy)) layout.btEnergy.label = bt.energy.toFixed(0) + "kJ"; } else { layout.bt.label = "--"; layout.btBattery.label = "--"; diff --git a/apps/bthrm/metadata.json b/apps/bthrm/metadata.json index 0977fd755..fea274ff3 100644 --- a/apps/bthrm/metadata.json +++ b/apps/bthrm/metadata.json @@ -5,6 +5,7 @@ "version": "0.17", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", + "screenshots": [{"url":"screen.png"}], "type": "app", "tags": "health,bluetooth,hrm,bthrm", "supports": ["BANGLEJS","BANGLEJS2"], diff --git a/apps/bthrm/screen.png b/apps/bthrm/screen.png new file mode 100644 index 0000000000000000000000000000000000000000..6b6b8522758de6d8a330fbe6184b59517f74360a GIT binary patch literal 3702 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 literal 0 HcmV?d00001 From 90e603b49d1b6fdc55cfc4d4cc3edd3e4389f7f9 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sun, 4 Dec 2022 19:44:17 +0100 Subject: [PATCH 54/73] kbswipe: Redo some patterns --- apps/kbswipe/ChangeLog | 2 +- apps/kbswipe/README.md | 2 ++ apps/kbswipe/lib.js | 10 +++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/kbswipe/ChangeLog b/apps/kbswipe/ChangeLog index 05be810cc..568db372e 100644 --- a/apps/kbswipe/ChangeLog +++ b/apps/kbswipe/ChangeLog @@ -3,4 +3,4 @@ 0.03: Positioning of marker now takes the height of the widget field into account. 0.04: Fix issue if going back without typing. 0.05: Keep drag-function in ram, hopefully improving performance and input reliability somewhat. -0.06: Support input of numbers +0.06: Support input of numbers and uppercase characters. diff --git a/apps/kbswipe/README.md b/apps/kbswipe/README.md index 1508061d1..c4c3fbd99 100644 --- a/apps/kbswipe/README.md +++ b/apps/kbswipe/README.md @@ -6,6 +6,8 @@ To get a legend of available characters, just tap the screen. To switch between the input of alphabetic and numeric characters tap the widget which displays either "123" or "ABC". +To switch between lowercase and uppercase characters do an up swipe. + ![](key.png) ## Usage diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index 981dc80db..75a434999 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -24,7 +24,7 @@ exports.getStrokes = function(mode, cb) { cb("m", new Uint8Array([49, 165, 48, 162, 46, 156, 44, 148, 42, 138, 42, 126, 42, 113, 43, 101, 45, 91, 47, 82, 49, 75, 51, 71, 54, 70, 57, 70, 61, 74, 69, 81, 75, 91, 84, 104, 94, 121, 101, 132, 103, 137, 106, 130, 110, 114, 116, 92, 125, 75, 134, 65, 139, 62, 144, 66, 148, 83, 151, 108, 155, 132, 157, 149])); cb("n", new Uint8Array([50, 165, 50, 160, 50, 153, 50, 140, 50, 122, 50, 103, 50, 83, 50, 65, 50, 52, 50, 45, 50, 43, 52, 52, 57, 67, 66, 90, 78, 112, 93, 131, 104, 143, 116, 152, 127, 159, 135, 160, 141, 150, 148, 125, 154, 96, 158, 71, 161, 56, 162, 49])); cb("o", new Uint8Array([107, 58, 104, 58, 97, 61, 87, 68, 75, 77, 65, 88, 58, 103, 54, 116, 53, 126, 55, 135, 61, 143, 75, 149, 91, 150, 106, 148, 119, 141, 137, 125, 143, 115, 146, 104, 146, 89, 142, 78, 130, 70, 116, 65, 104, 62])); - cb("p", new Uint8Array([52, 59, 52, 64, 54, 73, 58, 88, 61, 104, 65, 119, 67, 130, 69, 138, 71, 145, 71, 147, 71, 148, 71, 143, 70, 133, 68, 120, 67, 108, 67, 97, 67, 89, 68, 79, 72, 67, 83, 60, 99, 58, 118, 58, 136, 63, 146, 70, 148, 77, 145, 84, 136, 91, 121, 95, 106, 97, 93, 97, 82, 97])); + cb("p", new Uint8Array([29, 47, 29, 55, 29, 75, 29, 110, 29, 145, 29, 165, 29, 172, 29, 164, 30, 149, 37, 120, 50, 91, 61, 74, 72, 65, 85, 61, 103, 61, 118, 63, 126, 69, 129, 76, 130, 87, 126, 98, 112, 108, 97, 114, 87, 116])); cb("q", new Uint8Array([95, 59, 93, 59, 88, 59, 79, 59, 68, 61, 57, 67, 50, 77, 48, 89, 48, 103, 50, 117, 55, 130, 65, 140, 76, 145, 85, 146, 94, 144, 101, 140, 105, 136, 106, 127, 106, 113, 100, 98, 92, 86, 86, 79, 84, 75, 84, 72, 91, 69, 106, 67, 126, 67, 144, 67, 158, 67, 168, 67, 173, 67, 177, 67])); cb("r", new Uint8Array([53, 49, 53, 62, 53, 91, 53, 127, 53, 146, 53, 147, 53, 128, 53, 94, 53, 69, 62, 44, 82, 42, 94, 50, 92, 68, 82, 85, 77, 93, 80, 102, 95, 119, 114, 134, 129, 145, 137, 150])); cb("s", new Uint8Array([159, 72, 157, 70, 155, 68, 151, 66, 145, 63, 134, 60, 121, 58, 108, 56, 96, 55, 83, 55, 73, 55, 64, 56, 57, 60, 52, 65, 49, 71, 49, 76, 50, 81, 55, 87, 71, 94, 94, 100, 116, 104, 131, 108, 141, 114, 145, 124, 142, 135, 124, 146, 97, 153, 70, 157, 52, 158])); @@ -33,17 +33,17 @@ exports.getStrokes = function(mode, cb) { cb("v", new Uint8Array([36, 55, 37, 59, 40, 68, 45, 83, 51, 100, 58, 118, 64, 132, 69, 142, 71, 149, 73, 156, 76, 158, 77, 160, 77, 159, 80, 151, 82, 137, 84, 122, 86, 111, 90, 91, 91, 78, 91, 68, 91, 63, 92, 61, 97, 61, 111, 61, 132, 61, 150, 61, 162, 61])); cb("w", new Uint8Array([25, 46, 25, 82, 25, 119, 33, 143, 43, 153, 60, 147, 73, 118, 75, 91, 76, 88, 85, 109, 96, 134, 107, 143, 118, 137, 129, 112, 134, 81, 134, 64, 134, 55])); cb("x", new Uint8Array([56, 63, 56, 67, 57, 74, 60, 89, 66, 109, 74, 129, 85, 145, 96, 158, 107, 164, 117, 167, 128, 164, 141, 155, 151, 140, 159, 122, 166, 105, 168, 89, 170, 81, 170, 73, 169, 66, 161, 63, 141, 68, 110, 83, 77, 110, 55, 134, 47, 145])); - cb("y", new Uint8Array([42, 56, 42, 70, 48, 97, 62, 109, 85, 106, 109, 90, 126, 65, 134, 47, 137, 45, 137, 75, 127, 125, 98, 141, 70, 133, 65, 126, 92, 137, 132, 156, 149, 166])); + cb("y", new Uint8Array([30, 41, 30, 46, 30, 52, 30, 63, 30, 79, 33, 92, 38, 100, 47, 104, 54, 107, 66, 105, 79, 94, 88, 82, 92, 74, 94, 77, 96, 98, 96, 131, 94, 151, 91, 164, 85, 171, 75, 171, 71, 162, 74, 146, 84, 130, 95, 119, 106, 113])); cb("z", new Uint8Array([29, 62, 35, 62, 43, 62, 63, 62, 87, 62, 110, 62, 125, 62, 134, 62, 138, 62, 136, 63, 122, 68, 103, 77, 85, 91, 70, 107, 59, 120, 50, 132, 47, 138, 43, 143, 41, 148, 42, 151, 53, 155, 80, 157, 116, 158, 146, 158, 163, 158])); cb("SHIFT", new Uint8Array([100, 160, 100, 50])); } else if (mode === exports.INPUT_MODE_NUM) { cb("0", new Uint8Array([82, 50, 76, 50, 67, 50, 59, 50, 50, 51, 43, 57, 38, 68, 34, 83, 33, 95, 33, 108, 34, 121, 42, 136, 57, 148, 72, 155, 85, 157, 98, 155, 110, 149, 120, 139, 128, 127, 134, 119, 137, 114, 138, 107, 138, 98, 138, 88, 138, 77, 137, 71, 134, 65, 128, 60, 123, 58])); cb("1", new Uint8Array([100, 50, 100, 160])); - cb("2", new Uint8Array([40, 88, 40, 83, 40, 76, 43, 71, 47, 64, 55, 59, 64, 55, 73, 50, 80, 47, 91, 44, 104, 44, 117, 45, 128, 50, 135, 57, 142, 63, 145, 74, 145, 84, 140, 94, 129, 112, 108, 133, 87, 149, 71, 159, 58, 165, 52, 169, 55, 169, 63, 169, 77, 169, 89, 169, 100, 169, 110, 169, 116, 169])); - cb("3", new Uint8Array([52, 58, 65, 49, 83, 42, 100, 42, 118, 47, 136, 58, 143, 71, 135, 88, 125, 99, 114, 101, 119, 101, 132, 110, 142, 121, 145, 137, 139, 152, 122, 164, 106, 168, 92, 168, 74, 168, 55, 168])); + cb("2", new Uint8Array([40, 79, 46, 74, 56, 66, 68, 58, 77, 49, 87, 45, 100, 45, 111, 46, 119, 50, 128, 58, 133, 71, 130, 88, 120, 106, 98, 128, 69, 150, 50, 162, 42, 167, 43, 168, 58, 169, 78, 170, 93, 170, 103, 170, 109, 170])); + cb("3", new Uint8Array([47, 65, 51, 60, 57, 56, 65, 51, 74, 47, 84, 45, 93, 45, 102, 45, 109, 46, 122, 51, 129, 58, 130, 65, 127, 74, 120, 85, 112, 92, 107, 96, 112, 101, 117, 105, 125, 113, 128, 123, 127, 134, 122, 145, 108, 156, 91, 161, 70, 163, 55, 163])); cb("4", new Uint8Array([37, 58, 37, 60, 37, 64, 37, 69, 37, 75, 37, 86, 37, 96, 37, 105, 37, 112, 37, 117, 37, 122, 37, 126, 37, 128, 38, 129, 40, 129, 45, 129, 48, 129, 53, 129, 67, 129, 85, 129, 104, 129, 119, 129, 129, 129, 136, 129])); cb("5", new Uint8Array([142, 60, 119, 60, 79, 60, 45, 60, 37, 64, 37, 86, 37, 103, 47, 107, 66, 106, 81, 103, 97, 103, 116, 103, 129, 108, 131, 130, 122, 152, 101, 168, 85, 172, 70, 172, 59, 172])); - cb("6", new Uint8Array([128, 56, 110, 56, 81, 56, 58, 61, 47, 77, 41, 101, 41, 123, 41, 154, 50, 168, 71, 169, 98, 169, 123, 161, 131, 141, 129, 124, 117, 117, 102, 117, 92, 117, 85, 118, 77, 125])); + cb("6", new Uint8Array([136, 54, 135, 49, 129, 47, 114, 47, 89, 54, 66, 66, 50, 81, 39, 95, 35, 109, 34, 128, 38, 145, 52, 158, 81, 164, 114, 157, 133, 139, 136, 125, 132, 118, 120, 115, 102, 117, 85, 123])); cb("7", new Uint8Array([47, 38, 48, 38, 53, 38, 66, 38, 85, 38, 103, 38, 117, 38, 125, 38, 129, 38, 134, 41, 135, 47, 135, 54, 135, 66, 131, 93, 124, 126, 116, 149, 109, 161, 105, 168])); cb("8", new Uint8Array([122, 61, 102, 61, 83, 61, 60, 61, 47, 62, 45, 78, 58, 99, 84, 112, 105, 122, 118, 134, 121, 149, 113, 165, 86, 171, 59, 171, 47, 164, 45, 144, 50, 132, 57, 125, 67, 117, 78, 109, 87, 102, 96, 94, 105, 86, 113, 85])); cb("9", new Uint8Array([122, 58, 117, 55, 112, 51, 104, 51, 95, 51, 86, 51, 77, 51, 68, 51, 60, 51, 54, 56, 47, 64, 46, 77, 46, 89, 46, 96, 51, 103, 64, 109, 74, 110, 83, 110, 94, 107, 106, 102, 116, 94, 124, 84, 127, 79, 128, 78, 128, 94, 128, 123, 128, 161, 128, 175])); From 141eb9b90bebf93f8d701a16f25308bdca16db9f Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 4 Dec 2022 18:40:10 +0100 Subject: [PATCH 55/73] widget_utils - Allow setting a time for auto hideout --- modules/widget_utils.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/modules/widget_utils.js b/modules/widget_utils.js index 3440a01d2..33fd303f9 100644 --- a/modules/widget_utils.js +++ b/modules/widget_utils.js @@ -29,6 +29,7 @@ exports.show = function() { /// Remove any intervals/handlers/etc that we might have added. Does NOT re-show widgets that were hidden exports.cleanup = function() { + delete exports.autohide; delete Bangle.appRect; if (exports.swipeHandler) { Bangle.removeListener("swipe", exports.swipeHandler); @@ -50,11 +51,13 @@ exports.cleanup = function() { /** Put widgets offscreen, and allow them to be swiped back onscreen with a downwards swipe. Use .show to undo. +First parameter controls automatic hiding time, 0 equals not hiding at all. +Default value is 2000ms until hiding. Bangle.js 2 only at the moment. */ -exports.swipeOn = function() { +exports.swipeOn = function(autohide) { exports.cleanup(); if (!global.WIDGETS) return; - + exports.autohide=autohide===undefined?2000:autohide; /* TODO: maybe when widgets are offscreen we don't even store them in an offscreen buffer? */ @@ -125,11 +128,13 @@ exports.swipeOn = function() { clearTimeout(exports.hideTimeout); delete exports.hideTimeout; } - if (ud>0 && offset<0) anim(4, function() { + let cb; + if (exports.autohide > 0) cb = function() { exports.hideTimeout = setTimeout(function() { anim(-4); - }, 2000); - }); + }, exports.autohide); + } + if (ud>0 && offset<0) anim(4, cb); if (ud<0 && offset>-24) anim(-4); }; From dba3511e2ab5dad72f5bc008dba91af934287713 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 4 Dec 2022 18:52:43 +0100 Subject: [PATCH 56/73] imageclock - Disable auto hide of widgets --- apps/imageclock/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/imageclock/app.js b/apps/imageclock/app.js index 90c6163cd..374e73070 100644 --- a/apps/imageclock/app.js +++ b/apps/imageclock/app.js @@ -627,7 +627,7 @@ s.pl = {}; Bangle.drawWidgets = ()=>{}; Bangle.loadWidgets(); Bangle.drawWidgets = orig; - require("widget_utils").swipeOn(); + require("widget_utils").swipeOn(0); Bangle.drawWidgets(); } }).catch((e)=>{ From c9dec5ce4a0f83769f3d05475d19e2cf61921819 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:30:35 +0100 Subject: [PATCH 57/73] Create README.md --- apps/contourclock/README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 apps/contourclock/README.md diff --git a/apps/contourclock/README.md b/apps/contourclock/README.md new file mode 100644 index 000000000..dcde447d4 --- /dev/null +++ b/apps/contourclock/README.md @@ -0,0 +1,6 @@ +##New Features: +- Fast load! (only works if your launcher uses widgets) +- widgets, date and weekday are individually configurable +- you can hide widgets, date and weekday for a cleaner look when the watch is locked + +Contact me for bug reports or feature requests: ContourClock@gmx.de From 06e8ba63cac6382bc457484cc3a2fbb04f291389 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:31:04 +0100 Subject: [PATCH 58/73] Update README.md --- apps/contourclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contourclock/README.md b/apps/contourclock/README.md index dcde447d4..ad9f0b880 100644 --- a/apps/contourclock/README.md +++ b/apps/contourclock/README.md @@ -1,4 +1,4 @@ -##New Features: +#New Features: - Fast load! (only works if your launcher uses widgets) - widgets, date and weekday are individually configurable - you can hide widgets, date and weekday for a cleaner look when the watch is locked From df6eda645bdffe43596be3d084fcd8a9dfc5fef7 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:31:13 +0100 Subject: [PATCH 59/73] Update README.md --- apps/contourclock/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/contourclock/README.md b/apps/contourclock/README.md index ad9f0b880..3341439da 100644 --- a/apps/contourclock/README.md +++ b/apps/contourclock/README.md @@ -1,4 +1,4 @@ -#New Features: +# New Features: - Fast load! (only works if your launcher uses widgets) - widgets, date and weekday are individually configurable - you can hide widgets, date and weekday for a cleaner look when the watch is locked From 179e01299574c216afc671164e664b9b92e2c281 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Sun, 4 Dec 2022 20:33:26 +0100 Subject: [PATCH 60/73] Delete apps/widtick directory --- apps/widtick/widtick.wid.js | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 apps/widtick/widtick.wid.js diff --git a/apps/widtick/widtick.wid.js b/apps/widtick/widtick.wid.js deleted file mode 100644 index c59ae5dfb..000000000 --- a/apps/widtick/widtick.wid.js +++ /dev/null @@ -1,8 +0,0 @@ -(()=>{ - setInterval(()=>{Bangle.buzz(5,1);},1000); - WIDGETS.tick = { - area: "tr", - width: 0, - draw: ()=>{} - }; -})(); From 2df4ba30f5928720257e9743141e17b736de1379 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Sun, 4 Dec 2022 21:13:10 +0100 Subject: [PATCH 61/73] gpstrek - Workaround minifier issue --- apps/gpstrek/ChangeLog | 1 + apps/gpstrek/app.js | 6 ++++-- apps/gpstrek/metadata.json | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/gpstrek/ChangeLog b/apps/gpstrek/ChangeLog index c36c23c72..849088c64 100644 --- a/apps/gpstrek/ChangeLog +++ b/apps/gpstrek/ChangeLog @@ -13,3 +13,4 @@ Reconstruct battery voltage by using calibrated batFullVoltage Averaging for smoothing compass headings Save state if route or waypoint has been chosen +0.09: Workaround a minifier issue allowing to install gpstrek with minification enabled diff --git a/apps/gpstrek/app.js b/apps/gpstrek/app.js index b3ec79fd2..1f46ae2b4 100644 --- a/apps/gpstrek/app.js +++ b/apps/gpstrek/app.js @@ -259,7 +259,8 @@ let getCompassSlice = function(compassDataSource){ if (compassDataSource.getPoints){ - for (let p of compassDataSource.getPoints()){ + let points = compassDataSource.getPoints(); //storing this in a variable works around a minifier bug causing a problem in the next line: for(let a of a.getPoints()) + for (let p of points){ g.reset(); var bpos = p.bearing - lastDrawnValue; if (bpos>180) bpos -=360; @@ -285,7 +286,8 @@ let getCompassSlice = function(compassDataSource){ } } if (compassDataSource.getMarkers){ - for (let m of compassDataSource.getMarkers()){ + let markers = compassDataSource.getMarkers(); //storing this in a variable works around a minifier bug causing a problem in the next line: for(let a of a.getMarkers()) + for (let m of markers){ g.reset(); g.setColor(m.fillcolor); let mpos = m.xpos * width; diff --git a/apps/gpstrek/metadata.json b/apps/gpstrek/metadata.json index 3e27a3247..2e2e481af 100644 --- a/apps/gpstrek/metadata.json +++ b/apps/gpstrek/metadata.json @@ -1,7 +1,7 @@ { "id": "gpstrek", "name": "GPS Trekking", - "version": "0.08", + "version": "0.09", "description": "Helper for tracking the status/progress during hiking. Do NOT depend on this for navigation!", "icon": "icon.png", "screenshots": [{"url":"screen1.png"},{"url":"screen2.png"},{"url":"screen3.png"},{"url":"screen4.png"}], From 72bbc3a406a47934f83126410167da2dde8663ec Mon Sep 17 00:00:00 2001 From: m-p-3 Date: Sun, 4 Dec 2022 21:24:33 -0500 Subject: [PATCH 62/73] Bump version 0.01 -> 0.02 --- apps/messageicons/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messageicons/metadata.json b/apps/messageicons/metadata.json index eb907f893..b6ce34f88 100644 --- a/apps/messageicons/metadata.json +++ b/apps/messageicons/metadata.json @@ -1,7 +1,7 @@ { "id": "messageicons", "name": "Message Icons", - "version": "0.01", + "version": "0.02", "description": "Library containing a list of icons and colors for apps", "icon": "app.png", "type": "module", From 768e2cb8f3001287883dc7e05a35e2a842bbcb7c Mon Sep 17 00:00:00 2001 From: m-p-3 Date: Sun, 4 Dec 2022 21:26:22 -0500 Subject: [PATCH 63/73] Update Changelog --- apps/messageicons/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/messageicons/ChangeLog b/apps/messageicons/ChangeLog index 52a4b35a7..fefc6ee6e 100644 --- a/apps/messageicons/ChangeLog +++ b/apps/messageicons/ChangeLog @@ -1 +1,2 @@ 0.01: Moved message icons from messages into standalone library +0.02: Added several new icons and colors From 081f3b8eb69daaf29be29b15ab944a22abc1e4b2 Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Mon, 5 Dec 2022 10:14:17 +0100 Subject: [PATCH 64/73] Update contourclock.settings.js --- apps/contourclock/contourclock.settings.js | 123 ++++++++++----------- 1 file changed, 60 insertions(+), 63 deletions(-) diff --git a/apps/contourclock/contourclock.settings.js b/apps/contourclock/contourclock.settings.js index 2d8f74fc6..f2a75d9b5 100644 --- a/apps/contourclock/contourclock.settings.js +++ b/apps/contourclock/contourclock.settings.js @@ -10,67 +10,64 @@ settings.hideWhenLocked=false; require('Storage').writeJSON("myapp.json", settings); } - E.showMenu({ - "" : { "title" : "ContourClock" }, - "< Back" : () => back(), - 'Widgets': { - value: (settings.widgets !== undefined ? settings.widgets : true), - onchange : v => {settings.widgets=v; require('Storage').writeJSON('contourclock.json', settings);} - }, - 'hide Widgets': { - value: (settings.hide !== undefined ? settings.hide : false), - onchange : v => {settings.hide=v; require('Storage').writeJSON('contourclock.json', settings);} - }, - 'Weekday': { - value: (settings.weekday !== undefined ? settings.weekday : true), - onchange : v => {settings.weekday=v; require('Storage').writeJSON('contourclock.json', settings);} - }, - 'Date': { - value: (settings.date !== undefined ? settings.date : true), - onchange : v => {settings.date=v; require('Storage').writeJSON('contourclock.json', settings);} - }, - 'Hide when locked': { - value: (settings.hideWhenLocked !== undefined ? settings.hideWhenLocked : false), - onchange : v => {settings.hideWhenLocked=v; require('Storage').writeJSON('contourclock.json', settings);} - }, - 'set Font': function() { - Bangle.removeAllListeners('drag'); - Bangle.removeAllListeners('touch'); - require("widget_utils").hide(); - savedIndex=settings.fontIndex; - saveListener = setWatch(function() { //save changes and return to settings menu - require('Storage').writeJSON('contourclock.json', settings); - Bangle.removeAllListeners('swipe'); - Bangle.removeAllListeners('lock'); - clearWatch(saveListener); - g.clear(); - Bangle.load(); - }, BTN, { repeat:false, edge:'falling' }); - lockListener = Bangle.on('lock', function () { //discard changes and return to clock - settings.fontIndex=savedIndex; - require('Storage').writeJSON('contourclock.json', settings); - Bangle.removeAllListeners('swipe'); - Bangle.removeAllListeners('lock'); - clearWatch(saveListener); - g.clear(); - Bangle.load(); - }); - swipeListener = Bangle.on('swipe', function (direction) { - var fontName = require('contourclock').drawClock(settings.fontIndex+direction); - if (fontName) { - settings.fontIndex+=direction; - g.clearRect(0,0,g.getWidth()-1,16); - g.setFont('6x8:2x2').setFontAlign(0,-1).drawString(fontName,g.getWidth()/2,0); - } else { - require('contourclock').drawClock(settings.fontIndex); - } - }); - g.reset(); - g.clear(); - g.setFont('6x8:2x2').setFontAlign(0,-1); - g.drawString(require('contourclock').drawClock(settings.fontIndex),g.getWidth()/2,0); - g.drawString('Swipe - change',g.getWidth()/2,g.getHeight()-36); - g.drawString('BTN - save',g.getWidth()/2,g.getHeight()-18); - } - }); + function mainMenu() { + E.showMenu({ + "" : { "title" : "ContourClock" }, + "< Back" : () => back(), + 'Widgets': { + value: (settings.widgets !== undefined ? settings.widgets : true), + onchange : v => {settings.widgets=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'hide Widgets': { + value: (settings.hide !== undefined ? settings.hide : false), + onchange : v => {settings.hide=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'Weekday': { + value: (settings.weekday !== undefined ? settings.weekday : true), + onchange : v => {settings.weekday=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'Date': { + value: (settings.date !== undefined ? settings.date : true), + onchange : v => {settings.date=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'Hide when locked': { + value: (settings.hideWhenLocked !== undefined ? settings.hideWhenLocked : false), + onchange : v => {settings.hideWhenLocked=v; require('Storage').writeJSON('contourclock.json', settings);} + }, + 'set Font': () => fontMenu() + }); + } + function fontMenu() { + Bangle.setUI(""); + savedIndex=settings.fontIndex; + saveListener = setWatch(function() { //save changes and return to settings menu + require('Storage').writeJSON('contourclock.json', settings); + Bangle.removeAllListeners('swipe'); + Bangle.removeAllListeners('lock'); + mainMenu(); + }, BTN, { repeat:false, edge:'falling' }); + lockListener = Bangle.on('lock', function () { //discard changes and return to clock + settings.fontIndex=savedIndex; + require('Storage').writeJSON('contourclock.json', settings); + Bangle.removeAllListeners('swipe'); + Bangle.removeAllListeners('lock'); + mainMenu(); + }); + swipeListener = Bangle.on('swipe', function (direction) { + var fontName = require('contourclock').drawClock(settings.fontIndex+direction); + if (fontName) { + settings.fontIndex+=direction; + g.clearRect(0,g.getHeight()-36,g.getWidth()-1,g.getHeight()-36+16); + g.setFont('6x8:2x2').setFontAlign(0,-1).drawString(fontName,g.getWidth()/2,g.getHeight()-36); + } else { + require('contourclock').drawClock(settings.fontIndex); + } + }); + g.reset(); + g.clearRect(0,24,g.getWidth()-1,g.getHeight()-1); + g.setFont('6x8:2x2').setFontAlign(0,-1); + g.drawString(require('contourclock').drawClock(settings.fontIndex),g.getWidth()/2,g.getHeight()-36); + g.drawString('Button to save',g.getWidth()/2,g.getHeight()-18); + } + mainMenu(); }) From ca52522fc085e7ce246390a3e4e05a1afcb8280b Mon Sep 17 00:00:00 2001 From: xxDUxx <96152564+xxDUxx@users.noreply.github.com> Date: Mon, 5 Dec 2022 11:03:21 +0100 Subject: [PATCH 65/73] Update metadata.json --- apps/contourclock/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/contourclock/metadata.json b/apps/contourclock/metadata.json index 5a359ade5..6b2b51991 100644 --- a/apps/contourclock/metadata.json +++ b/apps/contourclock/metadata.json @@ -3,6 +3,7 @@ "shortName" : "Contour Clock", "version":"0.28", "icon": "app.png", + "readme": "README.md", "description": "A Minimalist clockface with large Digits.", "screenshots" : [{"url":"cc-screenshot-1.png"},{"url":"cc-screenshot-2.png"}], "tags": "clock", From 596a2be1f8b69cd8bf0cb9b7a9c64f12959fb6ef Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 5 Dec 2022 10:09:40 +0000 Subject: [PATCH 66/73] Update README.md --- apps/slopeclockpp/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/slopeclockpp/README.md b/apps/slopeclockpp/README.md index 8aad8467b..c9e9d523d 100644 --- a/apps/slopeclockpp/README.md +++ b/apps/slopeclockpp/README.md @@ -10,7 +10,7 @@ to change (top right or bottom left). It should change color showing it is selected. * Swipe up or down to cycle through the info screens that can be displayed - when you have finnised tap again towards the centre of the screen to unselect. + when you have finished tap again towards the centre of the screen to unselect. * Swipe left or right to change the type of info screens displayed (by default there is only one type of data so this will have no effect) From 67071d3722f169e45f0da4ed7c21cad9e716d855 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 2 Dec 2022 22:45:10 +0100 Subject: [PATCH 67/73] android - autotranslate some strings --- apps/android/ChangeLog | 3 ++- apps/android/boot.js | 4 ++-- apps/android/metadata.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index e4a3e9de0..86dbdb649 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -16,4 +16,5 @@ 0.16: Bangle.http now fails immediately if there is no Bluetooth connection (fix #2152) 0.17: Now kick off Calendar sync as soon as connected to Gadgetbridge 0.18: Use new message library - If connected to Gadgetbridge, allow GPS forwarding from phone (Gadgetbridge code still not merged) \ No newline at end of file + If connected to Gadgetbridge, allow GPS forwarding from phone (Gadgetbridge code still not merged) +0.19: Add automatic translation for a couple of strings. diff --git a/apps/android/boot.js b/apps/android/boot.js index 8e75241e7..e1e5b028b 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -57,7 +57,7 @@ t:event.cmd=="incoming"?"add":"remove", id:"call", src:"Phone", positive:true, negative:true, - title:event.name||"Call", body:"Incoming call\n"+event.number}); + title:event.name||/*LANG*/"Call", body:/*LANG*/"Incoming call\n"+event.number}); require("messages").pushMessage(event); }, "alarm" : function() { @@ -148,7 +148,7 @@ Bangle.http = (url,options)=>{ options = options||{}; if (!NRF.getSecurityStatus().connected) - return Promise.reject("Not connected to Bluetooth"); + return Promise.reject(/*LANG*/"Not connected to Bluetooth"); if (Bangle.httpRequest === undefined) Bangle.httpRequest={}; if (options.id === undefined) { diff --git a/apps/android/metadata.json b/apps/android/metadata.json index 45c08a75a..d5a45edb7 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.18", + "version": "0.19", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", From 6522e0311da0a767245884eb30918df6547df52e Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 2 Dec 2022 23:06:38 +0100 Subject: [PATCH 68/73] files - autotranslate strings --- apps/files/ChangeLog | 3 ++- apps/files/files.js | 54 ++++++++++++++++++++-------------------- apps/files/metadata.json | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/apps/files/ChangeLog b/apps/files/ChangeLog index 1908f7e5c..4622e6f0f 100644 --- a/apps/files/ChangeLog +++ b/apps/files/ChangeLog @@ -3,4 +3,5 @@ 0.04: Add functionality to sort apps manually or alphabetically ascending/descending. 0.05: Tweaks to help with memory usage 0.06: Reduce memory usage -0.07: Allow negative numbers when manual-sorting \ No newline at end of file +0.07: Allow negative numbers when manual-sorting +0.08: Automatic translation of strings. diff --git a/apps/files/files.js b/apps/files/files.js index e81e9589f..2f7b5c9a1 100644 --- a/apps/files/files.js +++ b/apps/files/files.js @@ -3,20 +3,20 @@ const store = require('Storage'); function showMainMenu() { const mainmenu = { '': { - 'title': 'App Manager', + 'title': /*LANG*/'App Manager', }, '< Back': ()=> {load();}, - 'Sort Apps': () => showSortAppsMenu(), - 'Manage Apps': ()=> showApps(), - 'Compact': () => { - E.showMessage('Compacting...'); + /*LANG*/'Sort Apps': () => showSortAppsMenu(), + /*LANG*/'Manage Apps': ()=> showApps(), + /*LANG*/'Compact': () => { + E.showMessage(/*LANG*/'Compacting...'); try { store.compact(); } catch (e) { } showMainMenu(); }, - 'Free': { + /*LANG*/'Free': { value: undefined, format: (v) => { return store.getFree(); @@ -65,13 +65,13 @@ function eraseData(info) { }); } function eraseApp(app, files,data) { - E.showMessage('Erasing\n' + app.name + '...'); + E.showMessage(/*LANG*/'Erasing\n' + app.name + '...'); var info = store.readJSON(app.id + ".info", 1)||{}; if (files) eraseFiles(info); if (data) eraseData(info); } function eraseOne(app, files,data){ - E.showPrompt('Erase\n'+app.name+'?').then((v) => { + E.showPrompt(/*LANG*/'Erase\n'+app.name+'?').then((v) => { if (v) { Bangle.buzz(100, 1); eraseApp(app, files, data); @@ -82,7 +82,7 @@ function eraseOne(app, files,data){ }); } function eraseAll(apps, files,data) { - E.showPrompt('Erase all?').then((v) => { + E.showPrompt(/*LANG*/'Erase all?').then((v) => { if (v) { Bangle.buzz(100, 1); apps.forEach(app => eraseApp(app, files, data)); @@ -99,11 +99,11 @@ function showAppMenu(app) { '< Back': () => showApps(), }; if (app.hasData) { - appmenu['Erase Completely'] = () => eraseOne(app, true, true); - appmenu['Erase App,Keep Data'] = () => eraseOne(app, true, false); - appmenu['Only Erase Data'] = () => eraseOne(app, false, true); + appmenu[/*LANG*/'Erase Completely'] = () => eraseOne(app, true, true); + appmenu[/*LANG*/'Erase App,Keep Data'] = () => eraseOne(app, true, false); + appmenu[/*LANG*/'Only Erase Data'] = () => eraseOne(app, false, true); } else { - appmenu['Erase'] = () => eraseOne(app, true, false); + appmenu[/*LANG*/'Erase'] = () => eraseOne(app, true, false); } E.showMenu(appmenu); } @@ -111,7 +111,7 @@ function showAppMenu(app) { function showApps() { const appsmenu = { '': { - 'title': 'Apps', + 'title': /*LANG*/'Apps', }, '< Back': () => showMainMenu(), }; @@ -128,17 +128,17 @@ function showApps() { menu[app.name] = () => showAppMenu(app); return menu; }, appsmenu); - appsmenu['Erase All'] = () => { + appsmenu[/*LANG*/'Erase All'] = () => { E.showMenu({ - '': {'title': 'Erase All'}, - 'Erase Everything': () => eraseAll(list, true, true), - 'Erase Apps,Keep Data': () => eraseAll(list, true, false), - 'Only Erase Data': () => eraseAll(list, false, true), + '': {'title': /*LANG*/'Erase All'}, + /*LANG*/'Erase Everything': () => eraseAll(list, true, true), + /*LANG*/'Erase Apps,Keep Data': () => eraseAll(list, true, false), + /*LANG*/'Only Erase Data': () => eraseAll(list, false, true), '< Back': () => showApps(), }); }; } else { - appsmenu['...No Apps...'] = { + appsmenu[/*LANG*/'...No Apps...'] = { value: undefined, format: ()=> '', onchange: ()=> {} @@ -150,16 +150,16 @@ function showApps() { function showSortAppsMenu() { const sorterMenu = { '': { - 'title': 'App Sorter', + 'title': /*LANG*/'App Sorter', }, '< Back': () => showMainMenu(), - 'Sort: manually': ()=> showSortAppsManually(), - 'Sort: alph. ASC': () => { - E.showMessage('Sorting:\nAlphabetically\nascending ...'); + /*LANG*/'Sort: manually': ()=> showSortAppsManually(), + /*LANG*/'Sort: alph. ASC': () => { + E.showMessage(/*LANG*/'Sorting:\nAlphabetically\nascending ...'); sortAlphabet(false); }, 'Sort: alph. DESC': () => { - E.showMessage('Sorting:\nAlphabetically\ndescending ...'); + E.showMessage(/*LANG*/'Sorting:\nAlphabetically\ndescending ...'); sortAlphabet(true); } }; @@ -169,7 +169,7 @@ function showSortAppsMenu() { function showSortAppsManually() { const appsSorterMenu = { '': { - 'title': 'Sort: manually', + 'title': /*LANG*/'Sort: manually', }, '< Back': () => showSortAppsMenu(), }; @@ -186,7 +186,7 @@ function showSortAppsManually() { return menu; }, appsSorterMenu); } else { - appsSorterMenu['...No Apps...'] = { + appsSorterMenu[/*LANG*/'...No Apps...'] = { value: undefined, format: ()=> '', onchange: ()=> {} diff --git a/apps/files/metadata.json b/apps/files/metadata.json index ac73a7717..a53f914e6 100644 --- a/apps/files/metadata.json +++ b/apps/files/metadata.json @@ -1,7 +1,7 @@ { "id": "files", "name": "App Manager", - "version": "0.07", + "version": "0.08", "description": "Show currently installed apps, free space, and allow their deletion from the watch", "icon": "files.png", "tags": "tool,system,files", From db38c197015b4e3e4e93f19b82f70d3e0271c7df Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 2 Dec 2022 23:15:20 +0100 Subject: [PATCH 69/73] recorder - autotranslate more strings --- apps/recorder/ChangeLog | 1 + apps/recorder/app.js | 6 +++--- apps/recorder/metadata.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index 3cf5d8372..a4d0b7e88 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -23,3 +23,4 @@ 0.17: Use default Bangle formatter for booleans 0.18: Improve widget load speed, allow currently recording track to be plotted in openstmap 0.19: Fix track plotting code +0.20: Automatic translation of some more strings. diff --git a/apps/recorder/app.js b/apps/recorder/app.js index 9006d2236..8dcc4c3ed 100644 --- a/apps/recorder/app.js +++ b/apps/recorder/app.js @@ -61,7 +61,7 @@ function showMainMenu() { setTimeout(function() { E.showMenu(); WIDGETS["recorder"].setRecording(v).then(function() { - print("Complete"); + print(/*LANG*/"Complete"); loadSettings(); print(settings.recording); showMainMenu(); @@ -96,7 +96,7 @@ function showMainMenu() { }; var recorders = WIDGETS["recorder"].getRecorders(); Object.keys(recorders).forEach(id=>{ - mainmenu["Log "+recorders[id]().name] = menuRecord(id); + mainmenu[/*LANG*/"Log "+recorders[id]().name] = menuRecord(id); }); delete recorders; return E.showMenu(mainmenu); @@ -404,7 +404,7 @@ function viewTrack(filename, info) { title: title, miny: min, maxy: max, - xlabel : x=>Math.round(x*dur/(60*infn.length))+" min" // minutes + xlabel : x=>Math.round(x*dur/(60*infn.length))+/*LANG*/" min" // minutes }); g.setFont("6x8",2); g.setFontAlign(0,0,3); diff --git a/apps/recorder/metadata.json b/apps/recorder/metadata.json index bbc08e0ef..91ceaf86e 100644 --- a/apps/recorder/metadata.json +++ b/apps/recorder/metadata.json @@ -2,7 +2,7 @@ "id": "recorder", "name": "Recorder", "shortName": "Recorder", - "version": "0.19", + "version": "0.20", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", From fb721b00a72a32a0de2359caa00a689f4f2519fa Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 2 Dec 2022 23:19:35 +0100 Subject: [PATCH 70/73] hrm - autotranslate strings --- apps/hrm/ChangeLog | 1 + apps/hrm/heartrate.js | 6 +++--- apps/hrm/metadata.json | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/hrm/ChangeLog b/apps/hrm/ChangeLog index 62956e8cd..b55ba8930 100644 --- a/apps/hrm/ChangeLog +++ b/apps/hrm/ChangeLog @@ -8,3 +8,4 @@ 0.08: Don't force backlight on/watch unlocked on Bangle 2 0.09: Grey out BPM until confidence is over 50% 0.10: Autoscale raw graph to maximum value seen +0.11: Automatic translation of strings. diff --git a/apps/hrm/heartrate.js b/apps/hrm/heartrate.js index 386341e6d..2e5a720e5 100644 --- a/apps/hrm/heartrate.js +++ b/apps/hrm/heartrate.js @@ -37,7 +37,7 @@ function updateHrm(){ var px = g.getWidth()/2; g.setFontAlign(0,-1); g.clearRect(0,24,g.getWidth(),80); - g.setFont("6x8").drawString("Confidence "+(hrmInfo.confidence || "--")+"%", px, 70); + g.setFont("6x8").drawString(/*LANG*/"Confidence "+(hrmInfo.confidence || "--")+"%", px, 70); updateScale(); @@ -46,7 +46,7 @@ function updateHrm(){ g.setFontVector(40).setColor(hrmInfo.confidence > 50 ? g.theme.fg : "#888").drawString(str,px,45); px += g.stringWidth(str)/2; g.setFont("6x8").setColor(g.theme.fg); - g.drawString("BPM",px+15,45); + g.drawString(/*LANG*/"BPM",px+15,45); } function updateScale(){ @@ -101,7 +101,7 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); g.setColor(g.theme.fg); g.reset().setFont("6x8",2).setFontAlign(0,-1); -g.drawString("Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); +g.drawString(/*LANG*/"Please wait...",g.getWidth()/2,g.getHeight()/2 - 16); countDown(); diff --git a/apps/hrm/metadata.json b/apps/hrm/metadata.json index c5a5f4f4d..f254b5d23 100644 --- a/apps/hrm/metadata.json +++ b/apps/hrm/metadata.json @@ -1,7 +1,7 @@ { "id": "hrm", "name": "Heart Rate Monitor", - "version": "0.10", + "version": "0.11", "description": "Measure your heart rate and see live sensor data", "icon": "heartrate.png", "tags": "health", From ee21d0bb4820aad91baf567d7f1ad54d642f7aae Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Fri, 2 Dec 2022 23:30:08 +0100 Subject: [PATCH 71/73] weather - autotranslate strings --- apps/weather/ChangeLog | 4 +++- apps/weather/app.js | 22 +++++++++++----------- apps/weather/metadata.json | 2 +- 3 files changed, 15 insertions(+), 13 deletions(-) diff --git a/apps/weather/ChangeLog b/apps/weather/ChangeLog index 1b6c1b9b5..359cb8635 100644 --- a/apps/weather/ChangeLog +++ b/apps/weather/ChangeLog @@ -17,4 +17,6 @@ 0.18: Added hasRange to clkinfo. 0.19: Added weather condition to clkinfo. 0.20: Added weather condition with temperature to clkinfo. -0.21: Updated clkinfo icon. \ No newline at end of file +0.21: Updated clkinfo icon. +0.22: Automatic translation of strings, some left untranslated. +>>>>>>> b37fcacd1 (weather - autotranslate strings) diff --git a/apps/weather/app.js b/apps/weather/app.js index f63b226b9..8988c5002 100644 --- a/apps/weather/app.js +++ b/apps/weather/app.js @@ -16,10 +16,10 @@ var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [ {type: "txt", font: "12%", valign: -1, id: "tempUnit", label: "°C"}, ]}, {filly: 1}, - {type: "txt", font: "6x8", pad: 2, halign: 1, label: "Humidity"}, + {type: "txt", font: "6x8", pad: 2, halign: 1, label: /*LANG*/"Humidity"}, {type: "txt", font: "9%", pad: 2, halign: 1, id: "hum", label: "000%"}, {filly: 1}, - {type: "txt", font: "6x8", pad: 2, halign: -1, label: "Wind"}, + {type: "txt", font: "6x8", pad: 2, halign: -1, label: /*LANG*/"Wind"}, {type: "h", halign: -1, c: [ {type: "txt", font: "9%", pad: 2, id: "wind", label: "00"}, {type: "txt", font: "6x8", pad: 2, valign: -1, id: "windUnit", label: "km/h"}, @@ -27,22 +27,22 @@ var layout = new Layout({type:"v", bgCol: g.theme.bg, c: [ ]}, ]}, {filly: 1}, - {type: "txt", font: "9%", wrap: true, height: g.getHeight()*0.18, fillx: 1, id: "cond", label: "Weather condition"}, + {type: "txt", font: "9%", wrap: true, height: g.getHeight()*0.18, fillx: 1, id: "cond", label: /*LANG*/"Weather condition"}, {filly: 1}, {type: "h", c: [ {type: "txt", font: "6x8", pad: 4, id: "loc", label: "Toronto"}, {fillx: 1}, - {type: "txt", font: "6x8", pad: 4, id: "updateTime", label: "15 minutes ago"}, + {type: "txt", font: "6x8", pad: 4, id: "updateTime", label: /*LANG*/"15 minutes ago"}, ]}, {filly: 1}, ]}, {lazy: true}); function formatDuration(millis) { let pluralize = (n, w) => n + " " + w + (n == 1 ? "" : "s"); - if (millis < 60000) return "< 1 minute"; - if (millis < 3600000) return pluralize(Math.floor(millis/60000), "minute"); - if (millis < 86400000) return pluralize(Math.floor(millis/3600000), "hour"); - return pluralize(Math.floor(millis/86400000), "day"); + if (millis < 60000) return /*LANG*/"< 1 minute"; + if (millis < 3600000) return pluralize(Math.floor(millis/60000), /*LANG*/"minute"); + if (millis < 86400000) return pluralize(Math.floor(millis/3600000), /*LANG*/"hour"); + return pluralize(Math.floor(millis/86400000), /*LANG*/"day"); } function draw() { @@ -57,7 +57,7 @@ function draw() { layout.windUnit.label = wind[2] + " " + (current.wrose||'').toUpperCase(); layout.cond.label = current.txt.charAt(0).toUpperCase()+(current.txt||'').slice(1); layout.loc.label = current.loc; - layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`; + layout.updateTime.label = `${formatDuration(Date.now() - current.time)} ago`; // How to autotranslate this and similar? layout.update(); layout.render(); } @@ -77,9 +77,9 @@ function update() { } else { layout.forgetLazyState(); if (NRF.getSecurityStatus().connected) { - E.showMessage("Weather\nunknown\n\nIs Gadgetbridge\nweather\nreporting set\nup on your\nphone?"); + E.showMessage(/*LANG*/"Weather\nunknown\n\nIs Gadgetbridge\nweather\nreporting set\nup on your\nphone?"); } else { - E.showMessage("Weather\nunknown\n\nGadgetbridge\nnot connected"); + E.showMessage(/*LANG*/"Weather\nunknown\n\nGadgetbridge\nnot connected"); NRF.on("connect", update); } } diff --git a/apps/weather/metadata.json b/apps/weather/metadata.json index 500eac012..7fefb7685 100644 --- a/apps/weather/metadata.json +++ b/apps/weather/metadata.json @@ -1,7 +1,7 @@ { "id": "weather", "name": "Weather", - "version": "0.21", + "version": "0.22", "description": "Show Gadgetbridge weather report", "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], From ae6d53ffc397439e24d732c633af01206e2a8008 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 5 Dec 2022 17:09:09 +0000 Subject: [PATCH 72/73] bootloader 0.55: Add toLocalISOString polyfill for pre-2v15 firmwares + Only add boot info comments if settings.bootDebug was set + If settings.bootDebug is set, output timing for each section of .boot0 --- apps/boot/ChangeLog | 3 ++ apps/boot/bootupdate.js | 72 ++++++++++++++++++++++++++--------------- apps/boot/metadata.json | 2 +- 3 files changed, 50 insertions(+), 27 deletions(-) diff --git a/apps/boot/ChangeLog b/apps/boot/ChangeLog index 0eaf517d9..780d9cc7d 100644 --- a/apps/boot/ChangeLog +++ b/apps/boot/ChangeLog @@ -61,3 +61,6 @@ 0.52: Ensure heading patch for pre-2v15.68 firmware applies to getCompass 0.53: Add polyfills for pre-2v15.135 firmware for Bangle.load and Bangle.showClock 0.54: Fix for invalid version comparison in polyfill +0.55: Add toLocalISOString polyfill for pre-2v15 firmwares + Only add boot info comments if settings.bootDebug was set + If settings.bootDebug is set, output timing for each section of .boot0 diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index ad58437ec..112dfeba8 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -1,16 +1,22 @@ /* This rewrites boot0.js based on current settings. If settings changed then it recalculates, but this avoids us doing a whole bunch of reconfiguration most of the time. */ +{ // execute in our own scope so we don't have to free variables... E.showMessage(/*LANG*/"Updating boot0..."); -var s = require('Storage').readJSON('setting.json',1)||{}; -var BANGLEJS2 = process.env.HWVERSION==2; // Is Bangle.js 2 -var FWVERSION = parseFloat(process.env.VERSION.replace("v","").replace(/\.(\d\d)$/,".0$1")); -var boot = "", bootPost = ""; +let s = require('Storage').readJSON('setting.json',1)||{}; +const BANGLEJS2 = process.env.HWVERSION==2; // Is Bangle.js 2 +const FWVERSION = parseFloat(process.env.VERSION.replace("v","").replace(/\.(\d\d)$/,".0$1")); +const DEBUG = s.bootDebug; // we can set this to enable debugging output in boot0 +let boot = "", bootPost = ""; +if (DEBUG) { + boot += "var _tm=Date.now()\n"; + bootPost += "delete _tm;"; +} if (require('Storage').hash) { // new in 2v11 - helps ensure files haven't changed - var CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/)+E.CRC32(process.env.GIT_COMMIT); + let CRC = E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\.boot\.js/)+E.CRC32(process.env.GIT_COMMIT); boot += `if (E.CRC32(require('Storage').read('setting.json'))+require('Storage').hash(/\\.boot\\.js/)+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; } else { - var CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))+E.CRC32(process.env.GIT_COMMIT); + let CRC = E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\.boot\.js/))+E.CRC32(process.env.GIT_COMMIT); boot += `if (E.CRC32(require('Storage').read('setting.json'))+E.CRC32(require('Storage').list(/\\.boot\\.js/))+E.CRC32(process.env.GIT_COMMIT)!=${CRC})`; } boot += ` { eval(require('Storage').read('bootupdate.js')); throw "Storage Updated!"}\n`; @@ -88,14 +94,25 @@ delete Bangle.showClock; if (!Bangle.showClock) boot += `Bangle.showClock = ()=>{load(".bootcde")};\n`; delete Bangle.load; if (!Bangle.load) boot += `Bangle.load = load;\n`; +let date = new Date(); +delete date.toLocalISOString; // toLocalISOString was only introduced in 2v15 +if (!date.toLocalISOString) boot += `Date.prototype.toLocalISOString = function() { + var o = this.getTimezoneOffset(); + var d = new Date(this.getTime() - o*60000); + var sign = o>0?"-":"+"; + o = Math.abs(o); + return d.toISOString().slice(0,-1)+sign+Math.floor(o/60).toString().padStart(2,0)+(o%60).toString().padStart(2,0); +};\n`; +// show timings +if (DEBUG) boot += `print(".boot0",0|(Date.now()-_tm),"ms");_tm=Date.now();\n` // ================================================== BOOT.JS // Append *.boot.js files // These could change bleServices/bleServiceOptions if needed -var bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ - var getPriority = /.*\.(\d+)\.boot\.js$/; - var aPriority = a.match(getPriority); - var bPriority = b.match(getPriority); +let bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ + let getPriority = /.*\.(\d+)\.boot\.js$/; + let aPriority = a.match(getPriority); + let bPriority = b.match(getPriority); if (aPriority && bPriority){ return parseInt(aPriority[1]) - parseInt(bPriority[1]); } else if (aPriority && !bPriority){ @@ -106,14 +123,16 @@ var bootFiles = require('Storage').list(/\.boot\.js$/).sort((a,b)=>{ return a==b ? 0 : (a>b ? 1 : -1); }); // precalculate file size -var fileSize = boot.length + bootPost.length; +let fileSize = boot.length + bootPost.length; bootFiles.forEach(bootFile=>{ // match the size of data we're adding below in bootFiles.forEach - fileSize += 2+bootFile.length+1+require('Storage').read(bootFile).length+2; + if (DEBUG) fileSize += 2+bootFile.length+1; // `//${bootFile}\n` comment + fileSize += require('Storage').read(bootFile).length+2; // boot code plus ";\n" + if (DEBUG) fileSize += 48+E.toJS(bootFile).length; // `print(${E.toJS(bootFile)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n` }); // write file in chunks (so as not to use up all RAM) require('Storage').write('.boot0',boot,0,fileSize); -var fileOffset = boot.length; +let fileOffset = boot.length; bootFiles.forEach(bootFile=>{ // we add a semicolon so if the file is wrapped in (function(){ ... }() // with no semicolon we don't end up with (function(){ ... }()(function(){ ... }() @@ -122,16 +141,18 @@ bootFiles.forEach(bootFile=>{ // "//"+bootFile+"\n"+require('Storage').read(bootFile)+";\n"; // but we need to do this without ever loading everything into RAM as some // boot files seem to be getting pretty big now. - require('Storage').write('.boot0',"//"+bootFile+"\n",fileOffset); - fileOffset+=2+bootFile.length+1; - var bf = require('Storage').read(bootFile); + if (DEBUG) { + require('Storage').write('.boot0',`//${bootFile}\n`,fileOffset); + fileOffset+=2+bootFile.length+1; + } + let bf = require('Storage').read(bootFile); // we can't just write 'bf' in one go because at least in 2v13 and earlier // Espruino wants to read the whole file into RAM first, and on Bangle.js 1 // it can be too big (especially BTHRM). - var bflen = bf.length; - var bfoffset = 0; + let bflen = bf.length; + let bfoffset = 0; while (bflen) { - var bfchunk = Math.min(bflen, 2048); + let bfchunk = Math.min(bflen, 2048); require('Storage').write('.boot0',bf.substr(bfoffset, bfchunk),fileOffset); fileOffset+=bfchunk; bfoffset+=bfchunk; @@ -139,15 +160,14 @@ bootFiles.forEach(bootFile=>{ } require('Storage').write('.boot0',";\n",fileOffset); fileOffset+=2; + if (DEBUG) { + require('Storage').write('.boot0',`print(${E.toJS(bootFile)},0|(Date.now()-_tm),"ms");_tm=Date.now();\n`,fileOffset); + fileOffset += 48+E.toJS(bootFile).length + } }); require('Storage').write('.boot0',bootPost,fileOffset); - -delete boot; -delete bootPost; -delete bootFiles; -delete fileSize; -delete fileOffset; E.showMessage(/*LANG*/"Reloading..."); -eval(require('Storage').read('.boot0')); +} // .bootcde should be run automatically after if required, since // we normally get called automatically from '.boot0' +eval(require('Storage').read('.boot0')); diff --git a/apps/boot/metadata.json b/apps/boot/metadata.json index bd39beb7f..455563a16 100644 --- a/apps/boot/metadata.json +++ b/apps/boot/metadata.json @@ -1,7 +1,7 @@ { "id": "boot", "name": "Bootloader", - "version": "0.54", + "version": "0.55", "description": "This is needed by Bangle.js to automatically load the clock, menu, widgets and settings", "icon": "bootloader.png", "type": "bootloader", From b47725568c7d08636cdef5a3486276568dcb7bde Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 5 Dec 2022 17:09:22 +0000 Subject: [PATCH 73/73] Not sure how, but core got set to earlier commit --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 764197500..3a953179b 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 76419750083a88ee7a569db3975ae1bdd6dc155a +Subproject commit 3a953179b7bb9f574d4e77d5f34b6b7deee1e884