From d71509583736a88ef44f5fbc5881ed56800b837c Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 11 Jan 2025 21:16:23 +0100 Subject: [PATCH 001/135] msgtwscr: new app! Temporarily activate scroll on twist function when a new message triggers the message app. --- apps/msgtwscr/ChangeLog | 1 + apps/msgtwscr/README.md | 19 +++++++++++++++++++ apps/msgtwscr/app.png | Bin 0 -> 1466 bytes apps/msgtwscr/boot.js | 31 +++++++++++++++++++++++++++++++ apps/msgtwscr/metadata.json | 13 +++++++++++++ 5 files changed, 64 insertions(+) create mode 100644 apps/msgtwscr/ChangeLog create mode 100644 apps/msgtwscr/README.md create mode 100644 apps/msgtwscr/app.png create mode 100644 apps/msgtwscr/boot.js create mode 100644 apps/msgtwscr/metadata.json diff --git a/apps/msgtwscr/ChangeLog b/apps/msgtwscr/ChangeLog new file mode 100644 index 0000000000..5560f00bce --- /dev/null +++ b/apps/msgtwscr/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/msgtwscr/README.md b/apps/msgtwscr/README.md new file mode 100644 index 0000000000..e97b8b2f1a --- /dev/null +++ b/apps/msgtwscr/README.md @@ -0,0 +1,19 @@ +# Message Scroll on Twist + +Temporarily activate scroll on twist function when a new message triggers the message app. This way it's possible to scroll through a message in the message scroller hands free. + +## Usage + +This is a bootloader app and only needs to be installed to add the functionality to the watch. + +## Notes + +Tried with [a development version "Message UI" app](https://github.com/espruino/BangleApps/pull/3685) centered around the message scroller. Should work with the standard version as well. + +## Requests + +Mention @thyttan in an issue on the espruino/BangleApps repository. + +## Creator + +thyttan diff --git a/apps/msgtwscr/app.png b/apps/msgtwscr/app.png new file mode 100644 index 0000000000000000000000000000000000000000..83d7e9add5396af12aa2b860375291aea1507a30 GIT binary patch literal 1466 zcmV;r1x5OaP)L8%qoKz;CEPmD*nSzLYFL?6DI{Vw)shTeX#9egKdnMBvO@of#)F*fBPC z9OsiB${20NIg5npF%qT>;%qCk-wISbVFnT=Ai=IN`>l{*GlG1a zvL6G)*;d5a4C2N$#Mm=??X$lNN#n;znmvfIM|OR#sPQPGdJn?v!RpB;%ull$aszSW z@v015Xs#v02}Jc9i0Xl;?g_$;m4`sw>=oZ6*$o*pU9XC5p}8XZ8;IzzMOg2te9#zs z1aaE=Y=9NR*Hy7CG}n^;v?#6vmUJ%>)*PwV-LBceKRr5#1LugJRti6Us%@<6q3h8DGQq8xJvb;vx0;Fui>Ze~%G8FmWxc3$?jG7?m3@Yo;hVjcPg*9Cv=F4srAf!wZB|)e#YnJXoY=e0 zC(NX5=~bi1N|t3K!E%lN3H)hkM$)|g-qM1&VVkJo8Nym~?E)m&pWc*a%a?vc(TfNl zF8z0CAxU``hX>5JC!dhTSJ6ekXzgJZ{EQn{( z{8pJlqxu9NO_iUs>g&=X22ZI|QJwykbkET-0_1@@S#VBH z*-8S63<)UK5NN3Ec#5!Ys;G3HaB*p#vOrOT%&Vs=k}EBM_G-z}I|=7V^OSiJ%&V{L zet?Hf$KFeNAxC;XhY&?2fROyyt_R45cu*~AJ}5#s#bQn5g#e39_VT4wdD49L)kr}= zZmV5@`^<-Ap)p;lG*1aALHzPG9kXTugb)krj<+{q>C%dA{0d-B(Oy$|Apn>UNJt%g zUuh9J$Xr8^j#cvjLWq$1GZIvha;5n>5prKnFem$b_eDA72@+IZM@V)0?PnyY_@x|a zf%^>t1_!NJETQq;P1*n?n-awjWZ*; zLFM@w5ll;}aJ3j}JV-dj6WU$kSG!r0<+SSdE-pUj+1HW20tSK znUXxgjI^cV0K&kWv;}^p8*_?+e<^NjRBuYl3QBK5yL+2a6&!2&z+p^D+*Ok=wep4Y zr9~v*rzK$Ot@=kVVrb$!j9k2ek&9O`Jo!Ba#xKD)G6~P%7+k(#INklQ^>|@*^wwVh z-^e5e#x7xS;<6BAaQrg*M=!uTGy(U(D0=#a;BfoU)$PG~yQ}^Jcm~H_^$kzLH+n%3 zr-4LyvHRVg0oYxA=ybZ#(bc`d)LXfHBmdH+;u#!=cW7K#Hnj7Cymt_eULR~d9%1>M z>vI0X)LV6X25!3ghSBSzj0oa%+0f35@?La0d(mO*!MRSy4@|vPmuujV!`=Ua3R9d^ z+}$rMn@#!i_8y$GI$pH5J3e9Rv20F{-R|{if (Bangle.CLOCK && msg.new) { + setTimeout(()=>{ + if (global.__FILE__=="messagegui.new.js") { + onTwistEmitDrag(); + } + },700) // It feels like there's a more elegant solution than checking the filename after 700 milliseconds. But this at least seems to work w/o sometimes activating when it shouldn't. + }}); + + // twistThreshold How much acceleration to register a twist of the watch strap? Can be negative for opposite direction. default = 800 + // twistMaxY Maximum acceleration in Y to trigger a twist (low Y means watch is facing the right way up). default = -800 + // twistTimeout How little time (in ms) must a twist take from low->high acceleration? default = 1000 + function onTwistEmitDrag() { + Bangle.setOptions({twistThreshold:2500, twistMaxY:-800, twistTimeout:400}); + Bangle.on("twist", ()=>{ + let i = 25; + const int = setInterval(() => { + Bangle.emit("drag", {dy:-3}) + i--; + if (i<1) clearInterval(int); + }, 10); + }); + + } +} diff --git a/apps/msgtwscr/metadata.json b/apps/msgtwscr/metadata.json new file mode 100644 index 0000000000..0bd79e55a5 --- /dev/null +++ b/apps/msgtwscr/metadata.json @@ -0,0 +1,13 @@ +{ "id": "msgtwscr", + "name": "Message Scroll on Twist", + "version":"0.01", + "description": "Temporarily activate scroll on twist function when a new message triggers the message app.", + "icon": "app.png", + "tags": "messages,tweak, scroll", + "type": "bootloader", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"msgtwscr.boot.js","url":"boot.js"} + ] +} From 07ce15dee97638022f3c60b05cba66a1408b51db Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Tue, 21 Jan 2025 21:49:16 +0100 Subject: [PATCH 002/135] msgtwscr: tweak app name. --- apps/msgtwscr/README.md | 2 +- apps/msgtwscr/metadata.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/msgtwscr/README.md b/apps/msgtwscr/README.md index e97b8b2f1a..2fbdda2402 100644 --- a/apps/msgtwscr/README.md +++ b/apps/msgtwscr/README.md @@ -1,4 +1,4 @@ -# Message Scroll on Twist +# Message Twist to Scroll Temporarily activate scroll on twist function when a new message triggers the message app. This way it's possible to scroll through a message in the message scroller hands free. diff --git a/apps/msgtwscr/metadata.json b/apps/msgtwscr/metadata.json index 0bd79e55a5..5bf1e97366 100644 --- a/apps/msgtwscr/metadata.json +++ b/apps/msgtwscr/metadata.json @@ -1,5 +1,5 @@ { "id": "msgtwscr", - "name": "Message Scroll on Twist", + "name": "Message Twist to Scroll", "version":"0.01", "description": "Temporarily activate scroll on twist function when a new message triggers the message app.", "icon": "app.png", From c412f68b7591d901cd854921bd909c0e7a39f363 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sat, 11 Jan 2025 17:45:37 -0600 Subject: [PATCH 003/135] [weatherClock] Add yellow to error icon to show on dark theme --- apps/weatherClock/ChangeLog | 3 ++- apps/weatherClock/app.js | 2 +- .../weatherClock/icons/icons8-error-48-yellow.png | Bin 0 -> 572 bytes apps/weatherClock/metadata.json | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 apps/weatherClock/icons/icons8-error-48-yellow.png diff --git a/apps/weatherClock/ChangeLog b/apps/weatherClock/ChangeLog index f31e15729d..d2c9a9d1f0 100644 --- a/apps/weatherClock/ChangeLog +++ b/apps/weatherClock/ChangeLog @@ -3,4 +3,5 @@ 0.03: Minor layout extra spaces. 0.04: Layout now compatible with Bangle.js 2. 0.05: Use weather condition code for icon selection. -0.06: WeatherClock icons now reflect weather conditions better. Add settings menu to hide elements and to use weather icons of Weather app. Images placed into functions for performance. \ No newline at end of file +0.06: WeatherClock icons now reflect weather conditions better. Add settings menu to hide elements and to use weather icons of Weather app. Images placed into functions for performance. +0.07: Add yellow to error icon to show up on dark theme. \ No newline at end of file diff --git a/apps/weatherClock/app.js b/apps/weatherClock/app.js index 4896a9f496..a7a186b1d9 100644 --- a/apps/weatherClock/app.js +++ b/apps/weatherClock/app.js @@ -26,7 +26,7 @@ function getStorm() { } // err icon - https://icons8.com/icons/set/error function getErr() { - return require("heatshrink").decompress(atob("mEwwkBiIA/AH4AZUAIWUiAXBWqgXXdIYuVGCgXBgICCIyYXCJCQTDC6QrEMCQSEJCQRFC6ApGJCCiDDQSpQFAYXEJBqNGJCA/EC4ZIOEwgXFJBgNEAhKlNAgxIKBgoXEJBjsLC5TsIeRycMBhRrMMBKzQEozjOBxAgHGww+IA6wfSH4hnIC47OMSJqlRIJAXCACIXaGoQARPwwuTAH4A/ABw")); + return require("heatshrink").decompress(atob("mEw4UA///A4PgAYQA/ABkFqALJitUBatVqoKIgILBoALIq2VBZEFrWlJBALLitq1JIIqoLBJBFV1WqBY5GBBYJIHBYOlrQLHIwRIIioLDJAxSBBYJUHIwILBJA4LKKQQLCJAsFBYpIEKQILDKgpGBBYZIFBYQACBYqZCAAZIDdgILGJASlDAAZUDIwQ7DJAgLLIwYLDJAbsBBYxICIwxUDKQ5UDBYIAIBZgvBABBTCBQ7xGAH4AC")); } function getDummy() { return require("heatshrink").decompress(atob("gMBwMAwA")); diff --git a/apps/weatherClock/icons/icons8-error-48-yellow.png b/apps/weatherClock/icons/icons8-error-48-yellow.png new file mode 100644 index 0000000000000000000000000000000000000000..55912f00b376bc6bc218289a061a42a07f288d66 GIT binary patch literal 572 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA3?vioaBc-sjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$1AIbUf%O0XK!RcI;noHq#at5P7Yr1+eu@{UmVvXtBeIx*f$uN~Gak=h zkpdKyC~=J_3C>R|DNig)We7;j%q!9Ja}7~2)icyH`n`vF8&J)*)CkWsPfsld4j_k> zL5h);ff2~^0%B<>8{}dQMrN=$6Oe7l$iyH3q@#d1vz-Mjo&{usKmrhh^uuU0OBsNE zp1{t)0#spOWNg5=0Aeag2kQceNmGDq5MTnD!vt0tWN86pL3J4#fC7)<<<)N%r*7p` z0hz}=T^vI^yq``y$ah$Q$NBQ#|L*?HK{>|*6ZhuYO*!&IldJdoGN)eazXk$=S9_&= z=hrxjyi>dId0xS@6VZpN1Pf(eJDd-1*=*K0QNQEKmQ?i#?&vKU?($WD31+!kb{=L`VFq6rFbH(i@xdS51=^TubhTdlc4!AH*unBlR zQ-U>bPD{1&f}JaQGVXotXV~k1K;@QseopVat;{_FCzyMVb#O;q+J3<3;Q1>3AN Date: Mon, 15 Jan 2024 15:14:37 +0100 Subject: [PATCH 004/135] pushups: new app --- apps/pushups/ChangeLog | 1 + apps/pushups/README.md | 11 ++++++ apps/pushups/app-icon.js | 1 + apps/pushups/app.js | 69 +++++++++++++++++++++++++++++++++++++ apps/pushups/metadata.json | 17 +++++++++ apps/pushups/pushups.png | Bin 0 -> 854 bytes 6 files changed, 99 insertions(+) create mode 100644 apps/pushups/ChangeLog create mode 100644 apps/pushups/README.md create mode 100644 apps/pushups/app-icon.js create mode 100644 apps/pushups/app.js create mode 100644 apps/pushups/metadata.json create mode 100644 apps/pushups/pushups.png diff --git a/apps/pushups/ChangeLog b/apps/pushups/ChangeLog new file mode 100644 index 0000000000..9fa2c81720 --- /dev/null +++ b/apps/pushups/ChangeLog @@ -0,0 +1 @@ +0.01: Initial code diff --git a/apps/pushups/README.md b/apps/pushups/README.md new file mode 100644 index 0000000000..60c0f315e1 --- /dev/null +++ b/apps/pushups/README.md @@ -0,0 +1,11 @@ +# Pushups + +Train for push ups using the accelerometer. It should buzz everytime you go up and down. +Swipe the screen to set the countdown value. + + +## Creator + +Feel free to give me feedback : is it useful for you ? what other features would you like ? + +frederic.wagner@imag.fr diff --git a/apps/pushups/app-icon.js b/apps/pushups/app-icon.js new file mode 100644 index 0000000000..3f98295ada --- /dev/null +++ b/apps/pushups/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AH4A/AH4A/ACcEogXVolEoAuVAAIXYhvdC6vdAAPQL6QuBAAaPRhtNDAgyQDQIXE7qYPC48iMaFM5gWC6kikAXPpvMDAXSC6BIBhoYB5oXBJB4XBOQPc5lCC4IYPC4StBCwUikgvQAAMCC4TlCeZgHFC4YYKFwoADkgXCDBIuHEQgACOpZTKC6oNGiIASC7YA/AH4A/AH4AdA")) diff --git a/apps/pushups/app.js b/apps/pushups/app.js new file mode 100644 index 0000000000..26f490c774 --- /dev/null +++ b/apps/pushups/app.js @@ -0,0 +1,69 @@ + +Bangle.loadWidgets(); + +const UP = 0; +const DOWN = 1; + +let status = UP; + + // to get rid of noise we'll need to count how many measures confirm where we think we are +let counts_in_opposite_status = 0; +let remaining_pushups = 10; + +function display() { + g.clear(); + g.setColor(0, 0, 0); + g.setFont("Vector:80").setFontAlign(0, 0).drawString(""+remaining_pushups, g.getWidth()/2, g.getHeight()/2); + Bangle.drawWidgets(); + g.flip(); +} + +display(); + +Bangle.setPollInterval(80); + + +setWatch( + function () { + load(); + }, + BTN1, + { + repeat: true, + } +); + +Bangle.on('swipe', function(directionLR, directionUD) { + if (directionUD == -1) { + remaining_pushups += 1; + } else if (directionUD == 1) { + remaining_pushups = Math.max(remaining_pushups-1, 1); + } else if (directionLR == -1) { + remaining_pushups += 5; + } else if (directionLR == 1) { + remaining_pushups = Math.max(remaining_pushups-5, 1); + } + display(); +}); + +Bangle.on('accel', function(xyz) { + let new_status = (xyz.y > 0.4)?DOWN:UP; + if (new_status != status) { + counts_in_opposite_status += 1; + + if (counts_in_opposite_status == 6) { + status = 1-status; + counts_in_opposite_status = 0; + if (status == UP) { + remaining_pushups -= 1; + display(); + if (remaining_pushups == 0) { + Bangle.buzz(500); + } + } + Bangle.buzz(100); + } + } else { + counts_in_opposite_status = 0; + } +}); diff --git a/apps/pushups/metadata.json b/apps/pushups/metadata.json new file mode 100644 index 0000000000..64a445067f --- /dev/null +++ b/apps/pushups/metadata.json @@ -0,0 +1,17 @@ +{ + "id": "pushups", + "name": "Pushups", + "shortName": "Pushups", + "version": "0.1", + "description": "Pushups countdown using the accelerometer.", + "allow_emulator":false, + "icon": "pushups.png", + "type": "app", + "tags": "health", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"pushups.app.js","url":"app.js"}, + {"name":"pushups.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/pushups/pushups.png b/apps/pushups/pushups.png new file mode 100644 index 0000000000000000000000000000000000000000..66c5902b6dc5ce8c6f094f7db20647e0d991a039 GIT binary patch literal 854 zcmV-c1F8IpP)~B5)xQb^$|7 zNQjn$gadS@mhMPmNE(dMcrZrgsUbcv_#noEi5}E+RtN~R8caNEjUtMQ6gdd#{$^{p zEl`jM*jDFD{!4ea`+xsGvoj+I91e%W;cz${PTaw;Sf~;-pknd6ic!C6MUs$U$-~TG z1QiI003*m9RRE)BLL#6NaeR&rj2ZU;m5P8${h&xbpz;f#avjvlW+4$e0D$rPf@mh^auI zExpSSczz@qe3m^hWy|}mfJO_Uoj!(U+7GIu*%~te7ulG}FwzW(HwRK+s2~+aN-|)g zVlQZp{HOw6YKKPZ2}GxI|C=e3yg@J#_v8$R`!?D9c;MRJY|Tu%59TGx1nrC&}76mqhY@L+wl3# z?T&M;ZA#~8G=bapW8p;;qfwQhR#u(7b6Jw_t`^f67Kg%H4AIkLH?3Ld^S6kz;JV{N zZ;QhGdh$(l03O*gXRZ9f!nhehmF~*awM&w`-rm6ZAUt%2U3in}PyXwQ&AH)*<5W|J z{e)Nl5JVG*m}8%e-N2&ITN_cGNoGa+mZUINal1;yvnoNK=aj(c?V?}Ah&T~Z{c2%} zd4RXB(kC(_BAeM2hLLyCFJKs*4xAS-IwLGIu3%RfLGM+J-Yw)1;jnegFUf07*qoM6N<$f+pCAS^xk5 literal 0 HcmV?d00001 From ffd78b6a7ebce5b23c0c7b892aac3fb21f03c102 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Mon, 15 Jan 2024 17:38:41 +0100 Subject: [PATCH 005/135] getting ready for more activities --- apps/pushups/ChangeLog | 2 +- apps/pushups/app.js | 51 +++++++++++++++++++++++++++++------------- 2 files changed, 37 insertions(+), 16 deletions(-) diff --git a/apps/pushups/ChangeLog b/apps/pushups/ChangeLog index 9fa2c81720..6d4fa64411 100644 --- a/apps/pushups/ChangeLog +++ b/apps/pushups/ChangeLog @@ -1 +1 @@ -0.01: Initial code +0.1: Initial code diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 26f490c774..cd04acef9c 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -1,19 +1,37 @@ Bangle.loadWidgets(); -const UP = 0; -const DOWN = 1; +const ACTIVITIES = ["pushups", "situps"]; +const POSITIONS = [2, 2]; +const GOALS = [10, 10]; +const DETECTORS = [ + (xyz) => { + return (xyz.y > 0.4)?1:0; + }, + (xyz) => { + if (xyz.x > 0.8 && xyz.z > -0.5) { + return 1; + } else if (xyz.x < 0.8 && xyz.z < -0.5) { + return 0; + } else { + return null; + } + } +]; -let status = UP; +let current_activity = 0; +let current_status = 0; // to get rid of noise we'll need to count how many measures confirm where we think we are let counts_in_opposite_status = 0; -let remaining_pushups = 10; +let remaining = 10; + function display() { g.clear(); g.setColor(0, 0, 0); - g.setFont("Vector:80").setFontAlign(0, 0).drawString(""+remaining_pushups, g.getWidth()/2, g.getHeight()/2); + g.setFont("Vector:80").setFontAlign(0, 0).drawString(""+remaining, g.getWidth()/2, g.getHeight()/2); + g.setFont("6x8:2").setFontAlign(0, 1).drawString(ACTIVITIES[current_activity], g.getWidth()/2, g.getHeight()); Bangle.drawWidgets(); g.flip(); } @@ -35,29 +53,32 @@ setWatch( Bangle.on('swipe', function(directionLR, directionUD) { if (directionUD == -1) { - remaining_pushups += 1; + remaining += 1; } else if (directionUD == 1) { - remaining_pushups = Math.max(remaining_pushups-1, 1); + remaining = Math.max(remaining-1, 1); } else if (directionLR == -1) { - remaining_pushups += 5; + remaining += 5; } else if (directionLR == 1) { - remaining_pushups = Math.max(remaining_pushups-5, 1); + remaining = Math.max(remaining-5, 1); } display(); }); Bangle.on('accel', function(xyz) { - let new_status = (xyz.y > 0.4)?DOWN:UP; - if (new_status != status) { + let new_status = DETECTORS[current_activity](xyz); + if (new_status === null) { + return; + } + if (new_status != current_status) { counts_in_opposite_status += 1; if (counts_in_opposite_status == 6) { - status = 1-status; + current_status = 1-current_status; counts_in_opposite_status = 0; - if (status == UP) { - remaining_pushups -= 1; + if (current_status == 0) { + remaining -= 1; display(); - if (remaining_pushups == 0) { + if (remaining == 0) { Bangle.buzz(500); } } From 3add89837bf79e87c202b4f29e5678b974ec567f Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Wed, 17 Jan 2024 17:10:19 +0100 Subject: [PATCH 006/135] pushups: ready for routines --- apps/pushups/app.js | 50 +++++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index cd04acef9c..df8ff4c32a 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -1,37 +1,47 @@ Bangle.loadWidgets(); -const ACTIVITIES = ["pushups", "situps"]; -const POSITIONS = [2, 2]; -const GOALS = [10, 10]; +const ACTIVITIES = ["pushups", "situps", "squats"]; +let routine = [[0, 10], [1, 10], [2, 10]]; + const DETECTORS = [ (xyz) => { return (xyz.y > 0.4)?1:0; }, (xyz) => { - if (xyz.x > 0.8 && xyz.z > -0.5) { + if (xyz.y > 0.4 && xyz.z > -1) { return 1; - } else if (xyz.x < 0.8 && xyz.z < -0.5) { + } else if (xyz.x < 0.4 && xyz.z < -1) { + return 0; + } else { + return null; + } + }, + (xyz) => { + if (xyz.z > -1) { return 0; + } else if (xyz.z < -1.1) { + return 1; } else { return null; } } ]; -let current_activity = 0; +let routine_step = 0; let current_status = 0; - // to get rid of noise we'll need to count how many measures confirm where we think we are +// to get rid of noise we'll need to count how many measures confirm where we think we are let counts_in_opposite_status = 0; -let remaining = 10; +let remaining = routine[routine_step][1]; function display() { g.clear(); g.setColor(0, 0, 0); g.setFont("Vector:80").setFontAlign(0, 0).drawString(""+remaining, g.getWidth()/2, g.getHeight()/2); - g.setFont("6x8:2").setFontAlign(0, 1).drawString(ACTIVITIES[current_activity], g.getWidth()/2, g.getHeight()); + let activity = ACTIVITIES[routine[routine_step][0]]; + g.setFont("6x8:2").setFontAlign(0, 1).drawString(activity, g.getWidth()/2, g.getHeight()); Bangle.drawWidgets(); g.flip(); } @@ -57,15 +67,22 @@ Bangle.on('swipe', function(directionLR, directionUD) { } else if (directionUD == 1) { remaining = Math.max(remaining-1, 1); } else if (directionLR == -1) { - remaining += 5; + if (routine_step < routine.length -1) { + routine_step += 1; + remaining = routine[routine_step][1]; + } } else if (directionLR == 1) { - remaining = Math.max(remaining-5, 1); + if (routine_step > 0) { + routine_step -= 1; + remaining = routine[routine_step][1]; + } } display(); }); Bangle.on('accel', function(xyz) { - let new_status = DETECTORS[current_activity](xyz); + let activity = routine[routine_step][0]; + let new_status = DETECTORS[activity](xyz); if (new_status === null) { return; } @@ -79,7 +96,14 @@ Bangle.on('accel', function(xyz) { remaining -= 1; display(); if (remaining == 0) { - Bangle.buzz(500); + Bangle.buzz(500).then(() => { + routine_step += 1; + if (routine_step >= routine.length) { + load(); + } + remaining = routine[routine_step][1]; + display(); + }) } } Bangle.buzz(100); From 60dc77d89f004434f7ce98272c5e1ff8aaa26a8d Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Thu, 18 Jan 2024 15:02:04 +0100 Subject: [PATCH 007/135] pushups: better situps detection --- apps/pushups/app.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index df8ff4c32a..23c2f57d46 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -9,13 +9,7 @@ const DETECTORS = [ return (xyz.y > 0.4)?1:0; }, (xyz) => { - if (xyz.y > 0.4 && xyz.z > -1) { - return 1; - } else if (xyz.x < 0.4 && xyz.z < -1) { - return 0; - } else { - return null; - } + return (xyz.x > 0)?1:0; }, (xyz) => { if (xyz.z > -1) { From e01de941c66877171f211826b4a55ebbcc818dc9 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Fri, 19 Jan 2024 15:26:25 +0100 Subject: [PATCH 008/135] pushups: some images, plank, time based activities --- apps/pushups/app.js | 214 +++++++++++++++++++++++++++++++------------- 1 file changed, 153 insertions(+), 61 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 23c2f57d46..f56e136774 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -1,15 +1,37 @@ +let h = require("heatshrink"); Bangle.loadWidgets(); -const ACTIVITIES = ["pushups", "situps", "squats"]; -let routine = [[0, 10], [1, 10], [2, 10]]; +const ACTIVITIES = ["pushups", "situps", "squats", "plank"]; +const IMAGES = [ + h.decompress( + atob( + "mEwwhC/AH4A/AH4A/ACcEogXVolEoAuVAAIXYhvdC6vdAAPQL6QuBAAaPRhtNDAgyQDQIXE7qYPC48iMaFM5gWC6kikAXPpvMDAXSC6BIBhoYB5oXBJB4XBOQPc5lCC4IYPC4StBCwUikgvQAAMCC4TlCeZgHFC4YYKFwoADkgXCDBIuHEQgACOpZTKC6oNGiIASC7YA/AH4A/AH4AdA" + ) + ), + h.decompress( + atob( + "mEwwhC/AH4A/ADlEogWUggXBoAuVAAQXXDKQXGJaAXXO4RhVCYSSWGQTZWFy8wC6c0olDmYXTmdEmYXVAARITC4YwTgYXHkUgC6JICgUiDBxIFCwQwTIoIADC6MyC4hIRCwgwRFggwPC4JFESKRbGJB4uFYSMDLI5IPIA7aQkUwA4hIBE5AASC7IA/AH4A/ACwA=" + ) + ), + h.decompress( + atob( + "mEwwhC/AFUN7vQC6ndAAIuVAAIwTC/53fU7AAugUjmczmRjCPp4VBAAM9C4h+MgYXDloXRCwczCwpHMCoU4u51RIwc3uAXVw4XSLoZGSL35e/AB0IxAADxvdAAIXX6AX8gBfWGAcikgWCC54ADhpGRAAguDC65GWL35eyF4ZGTC7BJCCygA+" + ) + ), + h.decompress( + atob( + "mEwwhC/AH4A/AH4A/AHkEolAC6lEAAIuVAAIwTC6nd7oXTCoIAB6AXPgVNCwYwCO5siCopIEFxUCkUtC44AMkQX/CowACUogXLQAIXHbAgAHV4QXFTwa7IbwdEoQWCEg4sIC4kgHhAtJC4RULAAJQBC4qZKE4oXENwYXPP5KGLFJgA/AH4A/AH4AUA==" + ) + ) +]; const DETECTORS = [ (xyz) => { - return (xyz.y > 0.4)?1:0; + return xyz.y > 0.4 ? 1 : 0; }, (xyz) => { - return (xyz.x > 0)?1:0; + return xyz.x > 0 ? 1 : 0; }, (xyz) => { if (xyz.z > -1) { @@ -19,32 +41,129 @@ const DETECTORS = [ } else { return null; } - } + }, + null ]; -let routine_step = 0; -let current_status = 0; +class FitnessStatus { + constructor() { + this.routine = [ + [0, 10], + [1, 10], + [2, 10], + [3, 30] + ]; + this.routine_step = 0; + this.current_status = 0; + + // to get rid of noise we'll need to count how many measures confirm where we think we are + this.counts_in_opposite_status = 0; + this.remaining = this.routine[this.routine_step][1]; + this.activity_start = getTime(); + } + + display() { + g.clear(); + g.setColor(0, 0, 0); + let activity = this.routine[this.routine_step][0]; + let countdown = this.remaining; + if (DETECTORS[activity] === null) { + countdown = this.remaining - Math.floor(getTime() - this.activity_start); + } + g.setFont("Vector:70") + .setFontAlign(0, 0) + .drawString( + "" + countdown, + (g.getWidth() * 3) / 10, + g.getHeight() / 2 + ); + let activity_name = ACTIVITIES[activity]; + g.drawImage(IMAGES[activity], g.getWidth() / 2, (g.getHeight() * 1) / 5, { + scale: 2, + }); + g.setFont("6x8:2") + .setFontAlign(0, 1) + .drawString(activity_name, g.getWidth() / 2, g.getHeight()); + Bangle.drawWidgets(); + g.flip(); + } + + first_activity() { + return this.routine_step == 0; + } + + last_activity() { + return this.routine_step == this.routine.length - 1; + } -// to get rid of noise we'll need to count how many measures confirm where we think we are -let counts_in_opposite_status = 0; -let remaining = routine[routine_step][1]; + next_activity() { + this.routine_step += 1; + if (this.routine_step >= this.routine.length) { + load(); + } + this.remaining = this.routine[this.routine_step][1]; + // this.display(); + this.activity_start = getTime(); + this.current_status = 0; + this.counts_in_opposite_status = 0; + } + previous_activity() { + this.routine_step -= 1; + this.remaining = this.routine[this.routine_step][1]; + // this.display(); + this.activity_start = getTime(); + this.current_status = 0; + this.counts_in_opposite_status = 0; + } -function display() { - g.clear(); - g.setColor(0, 0, 0); - g.setFont("Vector:80").setFontAlign(0, 0).drawString(""+remaining, g.getWidth()/2, g.getHeight()/2); - let activity = ACTIVITIES[routine[routine_step][0]]; - g.setFont("6x8:2").setFontAlign(0, 1).drawString(activity, g.getWidth()/2, g.getHeight()); - Bangle.drawWidgets(); - g.flip(); + detect(xyz) { + let activity = this.routine[this.routine_step][0]; + let detector = DETECTORS[activity]; + if (detector === null) { + // it's time based + let activity_duration = getTime() - this.activity_start; + if (activity_duration > this.remaining) { + Bangle.buzz(500).then(() => { + status.next_activity(); + }); + } + return; + } + // it's movement based + let new_status = DETECTORS[activity](xyz); + if (new_status === null) { + return; + } + if (new_status != this.current_status) { + this.counts_in_opposite_status += 1; + + // we consider 6 counts to smooth out noise + if (this.counts_in_opposite_status == 6) { + this.current_status = 1 - this.current_status; + this.counts_in_opposite_status = 0; + if (this.current_status == 0) { + this.remaining -= 1; + // this.display(); + if (this.remaining == 0) { + Bangle.buzz(500).then(() => { + status.next_activity(); + }); + } + } + Bangle.buzz(100); + } + } else { + this.counts_in_opposite_status = 0; + } + } } -display(); +let status = new FitnessStatus(); +// status.display(); Bangle.setPollInterval(80); - setWatch( function () { load(); @@ -55,54 +174,27 @@ setWatch( } ); -Bangle.on('swipe', function(directionLR, directionUD) { +Bangle.on("swipe", function (directionLR, directionUD) { if (directionUD == -1) { - remaining += 1; + status.remaining += 1; } else if (directionUD == 1) { - remaining = Math.max(remaining-1, 1); + status.remaining = Math.max(status.remaining - 1, 1); } else if (directionLR == -1) { - if (routine_step < routine.length -1) { - routine_step += 1; - remaining = routine[routine_step][1]; + if (!status.last_activity()) { + status.next_activity(); } } else if (directionLR == 1) { - if (routine_step > 0) { - routine_step -= 1; - remaining = routine[routine_step][1]; + if (!status.first_activity()) { + status.previous_activity(); } } - display(); + // status.display(); }); -Bangle.on('accel', function(xyz) { - let activity = routine[routine_step][0]; - let new_status = DETECTORS[activity](xyz); - if (new_status === null) { - return; - } - if (new_status != current_status) { - counts_in_opposite_status += 1; - - if (counts_in_opposite_status == 6) { - current_status = 1-current_status; - counts_in_opposite_status = 0; - if (current_status == 0) { - remaining -= 1; - display(); - if (remaining == 0) { - Bangle.buzz(500).then(() => { - routine_step += 1; - if (routine_step >= routine.length) { - load(); - } - remaining = routine[routine_step][1]; - display(); - }) - } - } - Bangle.buzz(100); - } - } else { - counts_in_opposite_status = 0; - } +Bangle.on("accel", function (xyz) { + status.detect(xyz); }); + +setInterval(() => { + status.display(); +}, 250); From a43c84147676dde1f0a1dd5fa20f149b124204c3 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Mon, 22 Jan 2024 10:40:21 +0100 Subject: [PATCH 009/135] pushups: loops + jumping jacks + rest --- apps/pushups/app.js | 75 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 63 insertions(+), 12 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index f56e136774..8fc3810c57 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -2,7 +2,9 @@ let h = require("heatshrink"); Bangle.loadWidgets(); -const ACTIVITIES = ["pushups", "situps", "squats", "plank"]; +//TODO: should we force not moving for planks and rests + +const ACTIVITIES = ["pushups", "situps", "squats", "plank", "jacks", "rest"]; const IMAGES = [ h.decompress( atob( @@ -23,6 +25,16 @@ const IMAGES = [ atob( "mEwwhC/AH4A/AH4A/AHkEolAC6lEAAIuVAAIwTC6nd7oXTCoIAB6AXPgVNCwYwCO5siCopIEFxUCkUtC44AMkQX/CowACUogXLQAIXHbAgAHV4QXFTwa7IbwdEoQWCEg4sIC4kgHhAtJC4RULAAJQBC4qZKE4oXENwYXPP5KGLFJgA/AH4A/AH4AUA==" ) + ), + h.decompress( + atob( + "mEwwhC/AFdEogWUggXBoAuVC7BIUC7RHPE4h3GAwKJPIwiVLBYQMHMgZNJBoY+EBBAYKoUikUkSaAXJSRxjBCwIXCeKMEC4UiCyIABC4bvTC/4AGhvdAAQXX6AXRCwYwSFwgwSCwoXQFwfQAgYXSGggwOFIowQCAQoEGB4nHD44XJBwxINEwRQOBo4MIJBouDmYACBQwAKgYWDAAMwa5wXCAoYXRADBIEIyQAGDJoWCCAgHHCxANIDBkDBawA/ADQA==" + ) + ), + h.decompress( + atob( + "mEwwhC/AH4AU1QAGC/4XXAAkKC6wWB0Au/F3KvPFw4XOLpAXOLpaBKRhgMBEZAKKHYYKKK5IjLC5alNC5BSOC5AuLe5guKABQuWd54XYgUiAAUgC7IAPC64ACC4IWUGIIu/F2a/va7QA/AH4AGA=" + ) ) ]; @@ -42,16 +54,28 @@ const DETECTORS = [ return null; } }, + null, + (xyz) => { + if ((xyz.x > 0) && (xyz.y < 0) && xyz.z < -0.25) { + return 0; + } + if ((xyz.x < 0) && (xyz.y > 0) && xyz.z > -0.25) { + return 1; + } + return null; + }, null ]; class FitnessStatus { - constructor() { + constructor(duration) { this.routine = [ [0, 10], [1, 10], [2, 10], - [3, 30] + [3, 30], + [4, 10], + [5, 30], ]; this.routine_step = 0; this.current_status = 0; @@ -60,11 +84,20 @@ class FitnessStatus { this.counts_in_opposite_status = 0; this.remaining = this.routine[this.routine_step][1]; this.activity_start = getTime(); + this.starting_time = this.activity_start; + this.duration = duration; + this.completed = false; } display() { g.clear(); g.setColor(0, 0, 0); + if (this.completed) { + g.setFont("Vector:40") + .setFontAlign(0, 0) + .drawString("Good Job!", g.getWidth()/2, g.getHeight()/2); + return; + } let activity = this.routine[this.routine_step][0]; let countdown = this.remaining; if (DETECTORS[activity] === null) { @@ -72,18 +105,29 @@ class FitnessStatus { } g.setFont("Vector:70") .setFontAlign(0, 0) - .drawString( - "" + countdown, - (g.getWidth() * 3) / 10, - g.getHeight() / 2 - ); + .drawString("" + countdown, (g.getWidth() * 3) / 10, g.getHeight() / 2); let activity_name = ACTIVITIES[activity]; g.drawImage(IMAGES[activity], g.getWidth() / 2, (g.getHeight() * 1) / 5, { scale: 2, }); + let global_countdown = ""; + if (this.duration !== null) { + let elapsed = getTime() - this.starting_time; + let remaining = Math.max(0, this.duration - elapsed); + let seconds = Math.floor(remaining % 60); + let minutes = Math.floor(remaining / 60) % 60; + let hours = Math.floor(remaining / 3600); + if (hours > 0) { + global_countdown = " / " + hours + "h" + minutes +"m" + seconds + "s"; + } else if (minutes > 0) { + global_countdown = " / " + minutes +"m" + seconds + "s"; + } else { + global_countdown = " / " + seconds + "s"; + } + } g.setFont("6x8:2") .setFontAlign(0, 1) - .drawString(activity_name, g.getWidth() / 2, g.getHeight()); + .drawString(activity_name+global_countdown, g.getWidth() / 2, g.getHeight()); Bangle.drawWidgets(); g.flip(); } @@ -98,9 +142,16 @@ class FitnessStatus { next_activity() { this.routine_step += 1; - if (this.routine_step >= this.routine.length) { - load(); + + this.completed = (this.duration===null)?(this.routine_step >= this.routine_length):(getTime() - this.starting_time > this.duration); + + if (this.completed) { + Bangle.buzz(1000).then(() => { + load(); + }); + return; } + this.routine_step = this.routine_step % this.routine.length; this.remaining = this.routine[this.routine_step][1]; // this.display(); this.activity_start = getTime(); @@ -159,7 +210,7 @@ class FitnessStatus { } } -let status = new FitnessStatus(); +let status = new FitnessStatus(10 * 60); // status.display(); Bangle.setPollInterval(80); From f52a21f2b556026f6d7a03e8686669ebe2ca2b5d Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Tue, 23 Jan 2024 16:13:31 +0100 Subject: [PATCH 010/135] pushups: stop detection when buzzing --- apps/pushups/app.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 8fc3810c57..3151bb4ece 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -79,6 +79,7 @@ class FitnessStatus { ]; this.routine_step = 0; this.current_status = 0; + this.buzzing = false; // to get rid of noise we'll need to count how many measures confirm where we think we are this.counts_in_opposite_status = 0; @@ -157,6 +158,7 @@ class FitnessStatus { this.activity_start = getTime(); this.current_status = 0; this.counts_in_opposite_status = 0; + this.buzzing = false; } previous_activity() { @@ -169,12 +171,16 @@ class FitnessStatus { } detect(xyz) { + if (this.buzzing) { + return; + } let activity = this.routine[this.routine_step][0]; let detector = DETECTORS[activity]; if (detector === null) { // it's time based let activity_duration = getTime() - this.activity_start; if (activity_duration > this.remaining) { + this.buzzing = true; Bangle.buzz(500).then(() => { status.next_activity(); }); @@ -197,6 +203,7 @@ class FitnessStatus { this.remaining -= 1; // this.display(); if (this.remaining == 0) { + this.buzzing = true; Bangle.buzz(500).then(() => { status.next_activity(); }); From 99aacb0b226a860bdfdd7a262a8cdeecc29f8281 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Fri, 16 Feb 2024 09:30:20 +0100 Subject: [PATCH 011/135] pushups: working on menu --- apps/pushups/app.js | 131 +++++++++++++++++++++++++++++++++----------- 1 file changed, 98 insertions(+), 33 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 3151bb4ece..1200abbb93 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -1,6 +1,5 @@ let h = require("heatshrink"); -Bangle.loadWidgets(); //TODO: should we force not moving for planks and rests @@ -56,10 +55,10 @@ const DETECTORS = [ }, null, (xyz) => { - if ((xyz.x > 0) && (xyz.y < 0) && xyz.z < -0.25) { + if (xyz.y > 0.2) { return 0; } - if ((xyz.x < 0) && (xyz.y > 0) && xyz.z > -0.25) { + if (xyz.y < 0) { return 1; } return null; @@ -94,7 +93,7 @@ class FitnessStatus { g.clear(); g.setColor(0, 0, 0); if (this.completed) { - g.setFont("Vector:40") + g.setFont("Vector:32") .setFontAlign(0, 0) .drawString("Good Job!", g.getWidth()/2, g.getHeight()/2); return; @@ -220,39 +219,105 @@ class FitnessStatus { let status = new FitnessStatus(10 * 60); // status.display(); -Bangle.setPollInterval(80); +Bangle.setPollInterval(10); -setWatch( - function () { - load(); - }, - BTN1, - { - repeat: true, - } -); -Bangle.on("swipe", function (directionLR, directionUD) { - if (directionUD == -1) { - status.remaining += 1; - } else if (directionUD == 1) { - status.remaining = Math.max(status.remaining - 1, 1); - } else if (directionLR == -1) { - if (!status.last_activity()) { - status.next_activity(); +function start_routine() { + + Bangle.loadWidgets(); + + Bangle.on("swipe", function (directionLR, directionUD) { + if (directionUD == -1) { + status.remaining += 1; + } else if (directionUD == 1) { + status.remaining = Math.max(status.remaining - 1, 1); + } else if (directionLR == -1) { + if (!status.last_activity()) { + status.next_activity(); + } + } else if (directionLR == 1) { + if (!status.first_activity()) { + status.previous_activity(); + } } - } else if (directionLR == 1) { - if (!status.first_activity()) { - status.previous_activity(); + // status.display(); + }); + + Bangle.on("accel", function (xyz) { + status.detect(xyz); + }); + + setInterval(() => { + status.display(); + }, 250); + +} + + +function edit_menu() { + let w = g.getWidth(); + let h = g.getHeight(); + let routine = [ + [0, 10], + [1, 10], + [2, 10], + [3, 30], + [4, 10], + [5, 30] + ]; + + E.showScroller({ + h : 60, + c : routine.length+2, + draw : function(idx, r) { + g.setColor(1).drawRect(r.x, r.y, r.w, r.h); + if (idx == routine.length + 1) { + g.setFont("Vector:28").setFontAlign(0, 0).drawString("Ok", r.x+r.w/2, r.y+r.h/2); + } else if (idx == routine.length) { + g.setFont("Vector:28").setFontAlign(0, 0).drawString("Add", r.x+r.w/2, r.y+r.h/2); + } else { + let activity = routine[idx][0]; + let count = routine[idx][1]; + let activity_name = ACTIVITIES[activity]; + let img = IMAGES[activity]; + g.drawImage(img, r.x + r.w / 5, r.y + 10); + g.setFont("6x8:2").setFontAlign(0, 0).drawString(""+count, r.x+r.w*4/5, r.y+r.h/2); + } + }, + select : function(idx) { + if (idx == routine.length + 1) { + E.showScroller(); + start_routine(); + } else if (idx == routine.length) { + console.log("TODO: add"); + } else { + console.log("TODO: change counter"); } } - // status.display(); -}); + }); +} + +function main_menu() { + let w = g.getWidth(); + let h = g.getHeight(); + g.clear(); + g.setColor(1); + g.drawRect(10, 10, w-10, h/2-10); + g.drawRect(10, h/2+10, w-10, h-10); + g.setFont("Vector:32") + .setFontAlign(0, 0) + .drawString("Start", w/2, h/4); + g.drawString("Edit", w/2, 3*h/4); + Bangle.on("touch", function(button, xy) { + if (xy.y > h/2+10) { + Bangle.removeAllListeners("touch"); + edit_menu(); + } else if (xy.y < h/2-10) { + Bangle.removeAllListeners("touch"); + start_routine(); + } + }) +} -Bangle.on("accel", function (xyz) { - status.detect(xyz); -}); -setInterval(() => { - status.display(); -}, 250); +main_menu(); From 2fcf47746d93e1b7ef79a16d8b45cf66507e6962 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Fri, 1 Mar 2024 14:10:52 +0100 Subject: [PATCH 012/135] pushups: working on menu ; fiddling with accel --- apps/pushups/app.js | 66 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 11 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 1200abbb93..a17231db3e 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -1,6 +1,5 @@ let h = require("heatshrink"); - //TODO: should we force not moving for planks and rests const ACTIVITIES = ["pushups", "situps", "squats", "plank", "jacks", "rest"]; @@ -219,6 +218,9 @@ class FitnessStatus { let status = new FitnessStatus(10 * 60); // status.display(); + Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app + Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter + Bangle.accelWr(0x18,0b11110100); // +-8g Bangle.setPollInterval(10); @@ -249,7 +251,7 @@ function start_routine() { setInterval(() => { status.display(); - }, 250); + }, 350); } @@ -257,14 +259,7 @@ function start_routine() { function edit_menu() { let w = g.getWidth(); let h = g.getHeight(); - let routine = [ - [0, 10], - [1, 10], - [2, 10], - [3, 30], - [4, 10], - [5, 30] - ]; + let routine = status.routine; E.showScroller({ h : 60, @@ -291,12 +286,50 @@ function edit_menu() { } else if (idx == routine.length) { console.log("TODO: add"); } else { - console.log("TODO: change counter"); + E.showScroller(); + set_counter(idx); } } }); } +function set_counter(index) { + let w = g.getWidth(); + let h = g.getHeight(); + let counter = status.routine[index][1]; + g.setFont("Vector:64") + .setFontAlign(0, 0); + g.clear(); + g.drawString(""+counter, w/2, h/2); + Bangle.on("swipe", function (directionLR, directionUD) { + if (directionUD == -1) { + counter += 5; + } else if (directionUD == 1) { + counter -= 5; + } else if (directionLR == -1) { + counter -= 1; + } else if (directionLR == 1) { + counter += 1; + } + if (counter < 0) { + counter = 0; + } + g.clear(); + g.drawString(""+counter, w/2, h/2); + }); + Bangle.on("touch", function(button, xy) { + if (counter == 0) { + status.routine.splice(index, 1); + } else { + status.routine[index][1] = counter; + } + Bangle.removeAllListeners("touch"); + Bangle.removeAllListeners("swipe"); + edit_menu(); + }); + +} + function main_menu() { let w = g.getWidth(); let h = g.getHeight(); @@ -308,11 +341,22 @@ function main_menu() { .setFontAlign(0, 0) .drawString("Start", w/2, h/4); g.drawString("Edit", w/2, 3*h/4); + Bangle.setLocked(false); Bangle.on("touch", function(button, xy) { if (xy.y > h/2+10) { + g.fillRect(10, h/2+10, w-10, h-10); + g.setColor(1, 1, 1) + .setFont("Vector:32") + .setFontAlign(0, 0) + .drawString("Edit", w/2, 3*h/4); Bangle.removeAllListeners("touch"); edit_menu(); } else if (xy.y < h/2-10) { + g.fillRect(10, 10, w-10, h/2-10); + g.setColor(1, 1, 1) + .setFont("Vector:32") + .setFontAlign(0, 0) + .drawString("Start", w/2, h/4); Bangle.removeAllListeners("touch"); start_routine(); } From 83a8a6521775081cf1634df717aad07852b5df98 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Wed, 10 Jul 2024 14:54:47 +0200 Subject: [PATCH 013/135] pushups: activity editor works we also disable jumping jacks detector --- apps/pushups/app.js | 69 +++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 21 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index a17231db3e..a490d95190 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -36,6 +36,17 @@ const IMAGES = [ ) ]; +// number of movements or duration required for each activity +const DEFAULTS = [10, 10, 10, 30, 30, 30]; + +function default_routine() { + let routine = []; + DEFAULTS.forEach((d, i) => { + routine.push([i, d]); + }); + return routine; +} + const DETECTORS = [ (xyz) => { return xyz.y > 0.4 ? 1 : 0; @@ -53,28 +64,25 @@ const DETECTORS = [ } }, null, - (xyz) => { - if (xyz.y > 0.2) { - return 0; - } - if (xyz.y < 0) { - return 1; - } - return null; - }, + null, + // (xyz) => { + // if (xyz.y > 0.2) { + // return 0; + // } + // if (xyz.y < 0) { + // return 1; + // } + // return null; + // }, // TODO: jumping jacks detector does not work null ]; class FitnessStatus { constructor(duration) { - this.routine = [ - [0, 10], - [1, 10], - [2, 10], - [3, 30], - [4, 10], - [5, 30], - ]; + this.routine = require("Storage").readJSON("pushups.cfg", true); + if (this.routine === undefined) { + this.routine = default_routine(); + } this.routine_step = 0; this.current_status = 0; this.buzzing = false; @@ -257,8 +265,6 @@ function start_routine() { function edit_menu() { - let w = g.getWidth(); - let h = g.getHeight(); let routine = status.routine; E.showScroller({ @@ -273,7 +279,6 @@ function edit_menu() { } else { let activity = routine[idx][0]; let count = routine[idx][1]; - let activity_name = ACTIVITIES[activity]; let img = IMAGES[activity]; g.drawImage(img, r.x + r.w / 5, r.y + 10); g.setFont("6x8:2").setFontAlign(0, 0).drawString(""+count, r.x+r.w*4/5, r.y+r.h/2); @@ -282,9 +287,11 @@ function edit_menu() { select : function(idx) { if (idx == routine.length + 1) { E.showScroller(); + require("Storage").writeJSON("pushups.cfg", routine); start_routine(); } else if (idx == routine.length) { - console.log("TODO: add"); + E.showScroller(); + add_activity(); } else { E.showScroller(); set_counter(idx); @@ -293,6 +300,26 @@ function edit_menu() { }); } + +function add_activity() { + E.showScroller({ + h : 60, + c : IMAGES.length, + draw : function(idx, r) { + g.setColor(1).drawRect(r.x, r.y, r.w, r.h); + let img = IMAGES[idx]; + g.drawImage(img, r.x + r.w / 3, r.y + 10); + }, + select : function(idx) { + let new_index = status.routine.length; + status.routine.push([idx, 10]); + E.showScroller(); + set_counter(new_index); + } + }); +} + + function set_counter(index) { let w = g.getWidth(); let h = g.getHeight(); From 8f8b228a12efa6767fbfe601b94235432079794d Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Wed, 24 Jul 2024 16:12:26 +0200 Subject: [PATCH 014/135] pushups: better detections ? --- apps/pushups/app.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index a490d95190..afd88dc853 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -49,10 +49,17 @@ function default_routine() { const DETECTORS = [ (xyz) => { - return xyz.y > 0.4 ? 1 : 0; + return xyz.y > 0.3 ? 1 : 0; }, (xyz) => { - return xyz.x > 0 ? 1 : 0; + if (xyz.x > 0.15) { + return 1; + } else if (xyz.x < -0.15) { + return 0; + } else { + return null; + } + // return xyz.x > 0 ? 1 : 0; }, (xyz) => { if (xyz.z > -1) { From 58319aa95b670fbebb5743114208d97b243bb4a6 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Thu, 25 Jul 2024 13:49:55 +0200 Subject: [PATCH 015/135] pushups: new bounds, better messages --- apps/pushups/app.js | 42 ++++++++++++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index afd88dc853..2f2a741ce4 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -49,7 +49,13 @@ function default_routine() { const DETECTORS = [ (xyz) => { - return xyz.y > 0.3 ? 1 : 0; + if (xyz.y > 0.3) { + return 1; + } else if (xyz.y < 0.2) { + return 0; + } else { + return null; + } }, (xyz) => { if (xyz.x > 0.15) { @@ -62,9 +68,9 @@ const DETECTORS = [ // return xyz.x > 0 ? 1 : 0; }, (xyz) => { - if (xyz.z > -1) { + if (xyz.z > -0.4) { return 0; - } else if (xyz.z < -1.1) { + } else if (xyz.z < -0.6) { return 1; } else { return null; @@ -233,14 +239,15 @@ class FitnessStatus { let status = new FitnessStatus(10 * 60); // status.display(); - Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app - Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter - Bangle.accelWr(0x18,0b11110100); // +-8g + // Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app + // Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter + // Bangle.accelWr(0x18,0b11110100); // +-8g Bangle.setPollInterval(10); function start_routine() { + status.remaining = status.routine[status.routine_step][1]; Bangle.loadWidgets(); Bangle.on("swipe", function (directionLR, directionUD) { @@ -331,10 +338,22 @@ function set_counter(index) { let w = g.getWidth(); let h = g.getHeight(); let counter = status.routine[index][1]; - g.setFont("Vector:64") - .setFontAlign(0, 0); - g.clear(); - g.drawString(""+counter, w/2, h/2); + function display() { + g.clear(); + g.setFont("6x8:2") + .setFontAlign(1, 0) + .drawString("+1", w, h/2); + g.setFontAlign(-1, 0) + .drawString("-1", 0, h/2); + g.setFontAlign(0, -1) + .drawString("+5", w/2, 0); + g.setFontAlign(0, 1) + .drawString("-5", w/2, h); + g.setFont("Vector:64") + .setFontAlign(0, 0) + .drawString(""+counter, w/2, h/2); + } + display(); Bangle.on("swipe", function (directionLR, directionUD) { if (directionUD == -1) { counter += 5; @@ -348,8 +367,7 @@ function set_counter(index) { if (counter < 0) { counter = 0; } - g.clear(); - g.drawString(""+counter, w/2, h/2); + display(); }); Bangle.on("touch", function(button, xy) { if (counter == 0) { From e6776b876165efd86d246b099884aa4cf2eec9c5 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Fri, 26 Jul 2024 07:04:29 +0200 Subject: [PATCH 016/135] pushups: more tuning --- apps/pushups/app.js | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 2f2a741ce4..6861c76570 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -49,18 +49,18 @@ function default_routine() { const DETECTORS = [ (xyz) => { - if (xyz.y > 0.3) { + if (xyz.y > 0.15) { return 1; - } else if (xyz.y < 0.2) { + } else if (xyz.y < 0.1) { return 0; } else { return null; } }, (xyz) => { - if (xyz.x > 0.15) { + if (xyz.x > 0.075) { return 1; - } else if (xyz.x < -0.15) { + } else if (xyz.x < -0.075) { return 0; } else { return null; @@ -167,6 +167,10 @@ class FitnessStatus { if (this.completed) { Bangle.buzz(1000).then(() => { + Bangle.setPollInterval(80); // default poll interval + Bangle.accelWr(0x18, 0b01101100); // off, +-4g + Bangle.accelWr(0x1B, 0x0); // default 12.5hz output + Bangle.accelWr(0x18, 0b11101100); // +-4g load(); }); return; @@ -239,16 +243,28 @@ class FitnessStatus { let status = new FitnessStatus(10 * 60); // status.display(); - // Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app - // Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter - // Bangle.accelWr(0x18,0b11110100); // +-8g -Bangle.setPollInterval(10); - function start_routine() { + Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app + Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter + Bangle.accelWr(0x18,0b11110100); // +-8g + Bangle.setPollInterval(10); + + Bangle.setPollInterval(80); // default poll interval + Bangle.accelWr(0x18, 0b01101100); // off, +-4g + Bangle.accelWr(0x1B, 0x0); // default 12.5hz output + Bangle.accelWr(0x18, 0b11101100); // +-4g status.remaining = status.routine[status.routine_step][1]; + Bangle.setPollInterval(80); // default poll interval + Bangle.accelWr(0x18, 0b01101100); // off, +-4g + Bangle.accelWr(0x1B, 0x0); // default 12.5hz output + Bangle.accelWr(0x18, 0b11101100); // +-4g Bangle.loadWidgets(); + Bangle.setPollInterval(80); // default poll interval + Bangle.accelWr(0x18, 0b01101100); // off, +-4g + Bangle.accelWr(0x1B, 0x0); // default 12.5hz output + Bangle.accelWr(0x18, 0b11101100); // +-4g Bangle.on("swipe", function (directionLR, directionUD) { if (directionUD == -1) { From b6b6a847774f289825b2a2a7e87f1a3621e7807b Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Mon, 29 Jul 2024 10:40:51 +0200 Subject: [PATCH 017/135] pushups: fixing paste error --- apps/pushups/app.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 6861c76570..bf4734702b 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -49,6 +49,7 @@ function default_routine() { const DETECTORS = [ (xyz) => { + "ram" if (xyz.y > 0.15) { return 1; } else if (xyz.y < 0.1) { @@ -58,6 +59,7 @@ const DETECTORS = [ } }, (xyz) => { + "ram" if (xyz.x > 0.075) { return 1; } else if (xyz.x < -0.075) { @@ -68,6 +70,7 @@ const DETECTORS = [ // return xyz.x > 0 ? 1 : 0; }, (xyz) => { + "ram" if (xyz.z > -0.4) { return 0; } else if (xyz.z < -0.6) { @@ -251,20 +254,8 @@ function start_routine() { Bangle.accelWr(0x18,0b11110100); // +-8g Bangle.setPollInterval(10); - Bangle.setPollInterval(80); // default poll interval - Bangle.accelWr(0x18, 0b01101100); // off, +-4g - Bangle.accelWr(0x1B, 0x0); // default 12.5hz output - Bangle.accelWr(0x18, 0b11101100); // +-4g status.remaining = status.routine[status.routine_step][1]; - Bangle.setPollInterval(80); // default poll interval - Bangle.accelWr(0x18, 0b01101100); // off, +-4g - Bangle.accelWr(0x1B, 0x0); // default 12.5hz output - Bangle.accelWr(0x18, 0b11101100); // +-4g Bangle.loadWidgets(); - Bangle.setPollInterval(80); // default poll interval - Bangle.accelWr(0x18, 0b01101100); // off, +-4g - Bangle.accelWr(0x1B, 0x0); // default 12.5hz output - Bangle.accelWr(0x18, 0b11101100); // +-4g Bangle.on("swipe", function (directionLR, directionUD) { if (directionUD == -1) { From 9bbde8e5fb2d8b28de3b2cade7d27b6516e61f46 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Mon, 29 Jul 2024 10:54:46 +0200 Subject: [PATCH 018/135] pushups: jacks detector is back --- apps/pushups/app.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index bf4734702b..3d7ff9b983 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -37,7 +37,7 @@ const IMAGES = [ ]; // number of movements or duration required for each activity -const DEFAULTS = [10, 10, 10, 30, 30, 30]; +const DEFAULTS = [7, 10, 10, 30, 15, 30]; function default_routine() { let routine = []; @@ -80,16 +80,16 @@ const DETECTORS = [ } }, null, - null, - // (xyz) => { - // if (xyz.y > 0.2) { - // return 0; - // } - // if (xyz.y < 0) { - // return 1; - // } - // return null; - // }, // TODO: jumping jacks detector does not work + (xyz) => { + "ram" + if (xyz.x < -0.8) { + return 0; + } + if (xyz.x > 0.3) { + return 1; + } + return null; + }, null ]; From 24a54fef8de3ea97af1ac4e5bd94f18d2a483d76 Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Thu, 9 Jan 2025 20:42:28 +0100 Subject: [PATCH 019/135] pushups: theme colors --- apps/pushups/app.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 3d7ff9b983..11214a32e9 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -113,8 +113,9 @@ class FitnessStatus { } display() { + g.setBgColor(g.theme.bg); g.clear(); - g.setColor(0, 0, 0); + g.setColor(g.theme.fg); if (this.completed) { g.setFont("Vector:32") .setFontAlign(0, 0) @@ -292,7 +293,7 @@ function edit_menu() { h : 60, c : routine.length+2, draw : function(idx, r) { - g.setColor(1).drawRect(r.x, r.y, r.w, r.h); + g.setColor(g.theme.fg).drawRect(r.x, r.y, r.w, r.h); if (idx == routine.length + 1) { g.setFont("Vector:28").setFontAlign(0, 0).drawString("Ok", r.x+r.w/2, r.y+r.h/2); } else if (idx == routine.length) { @@ -327,7 +328,7 @@ function add_activity() { h : 60, c : IMAGES.length, draw : function(idx, r) { - g.setColor(1).drawRect(r.x, r.y, r.w, r.h); + g.setColor(g.theme.fg).drawRect(r.x, r.y, r.w, r.h); let img = IMAGES[idx]; g.drawImage(img, r.x + r.w / 3, r.y + 10); }, @@ -392,8 +393,9 @@ function set_counter(index) { function main_menu() { let w = g.getWidth(); let h = g.getHeight(); + g.setBgColor(g.theme.bg); g.clear(); - g.setColor(1); + g.setColor(g.theme.fg); g.drawRect(10, 10, w-10, h/2-10); g.drawRect(10, h/2+10, w-10, h-10); g.setFont("Vector:32") @@ -403,16 +405,18 @@ function main_menu() { Bangle.setLocked(false); Bangle.on("touch", function(button, xy) { if (xy.y > h/2+10) { + g.setColor(g.theme.fg); g.fillRect(10, h/2+10, w-10, h-10); - g.setColor(1, 1, 1) + g.setColor(g.theme.bg) .setFont("Vector:32") .setFontAlign(0, 0) .drawString("Edit", w/2, 3*h/4); Bangle.removeAllListeners("touch"); edit_menu(); } else if (xy.y < h/2-10) { + g.setColor(g.theme.fg); g.fillRect(10, 10, w-10, h/2-10); - g.setColor(1, 1, 1) + g.setColor(g.theme.bg) .setFont("Vector:32") .setFontAlign(0, 0) .drawString("Start", w/2, h/4); From 2d0193a1db89c4b6c498e23fa8082f233e843c0b Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Fri, 6 Sep 2024 11:00:24 +0200 Subject: [PATCH 020/135] pushups : getting ready for release --- apps/pushups/README.md | 27 +++++++- apps/pushups/app.js | 121 +++++++++++++++++++++++++--------- apps/pushups/metadata.json | 1 + apps/pushups/shot_menu.png | Bin 0 -> 2199 bytes apps/pushups/shot_pushups.png | Bin 0 -> 2887 bytes apps/pushups/shot_squats.png | Bin 0 -> 3020 bytes 6 files changed, 116 insertions(+), 33 deletions(-) create mode 100644 apps/pushups/shot_menu.png create mode 100644 apps/pushups/shot_pushups.png create mode 100644 apps/pushups/shot_squats.png diff --git a/apps/pushups/README.md b/apps/pushups/README.md index 60c0f315e1..df2fe5358f 100644 --- a/apps/pushups/README.md +++ b/apps/pushups/README.md @@ -1,7 +1,30 @@ # Pushups -Train for push ups using the accelerometer. It should buzz everytime you go up and down. -Swipe the screen to set the countdown value. +Pushups is an exercising app with a twist : the accelerometer. + +![Screenshot](shot_pushups.png) + +I initially just wanted a pushups counter but i kind of got out of hand. + +The accelerometer will work on the following exercises : + +- pushups +- situps +- squats +- jumping jacks + +For each of them it will try to detect two positions (for example up and down for pushups) +and buzz on each change. You can set up a target counter for each exercise. + +Precision is not 100% but it's good for me and kind of increases my motivation. + +Other activities are time based like + +- plank +- rest + + +Define your training routine, set a duration and you're ready to go. ## Creator diff --git a/apps/pushups/app.js b/apps/pushups/app.js index 11214a32e9..ee03025fd9 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -39,6 +39,14 @@ const IMAGES = [ // number of movements or duration required for each activity const DEFAULTS = [7, 10, 10, 30, 15, 30]; +// detector sensitivity for each activity +// (less is more reactive but more sensitive to noise) +const COUNTS = [6, 10, 6, 6, 6, 5]; + +function default_config() { + return {duration: 10*60, routine: default_routine()}; +} + function default_routine() { let routine = []; DEFAULTS.forEach((d, i) => { @@ -94,11 +102,8 @@ const DETECTORS = [ ]; class FitnessStatus { - constructor(duration) { - this.routine = require("Storage").readJSON("pushups.cfg", true); - if (this.routine === undefined) { - this.routine = default_routine(); - } + constructor(config) { + this.routine = config.routine; this.routine_step = 0; this.current_status = 0; this.buzzing = false; @@ -108,7 +113,7 @@ class FitnessStatus { this.remaining = this.routine[this.routine_step][1]; this.activity_start = getTime(); this.starting_time = this.activity_start; - this.duration = duration; + this.duration = config.duration; this.completed = false; } @@ -203,6 +208,7 @@ class FitnessStatus { } let activity = this.routine[this.routine_step][0]; let detector = DETECTORS[activity]; + let status = this; if (detector === null) { // it's time based let activity_duration = getTime() - this.activity_start; @@ -222,8 +228,7 @@ class FitnessStatus { if (new_status != this.current_status) { this.counts_in_opposite_status += 1; - // we consider 6 counts to smooth out noise - if (this.counts_in_opposite_status == 6) { + if (this.counts_in_opposite_status == COUNTS[activity]) { this.current_status = 1 - this.current_status; this.counts_in_opposite_status = 0; if (this.current_status == 0) { @@ -244,11 +249,9 @@ class FitnessStatus { } } -let status = new FitnessStatus(10 * 60); -// status.display(); - -function start_routine() { +function start_routine(config) { + let status = new FitnessStatus(config); Bangle.accelWr(0x18,0b01110100); // off, +-8g // NOTE: this code is taken from 'accelrec' app Bangle.accelWr(0x1B,0x03 | 0x40); // 100hz output, ODR/2 filter @@ -286,8 +289,8 @@ function start_routine() { } -function edit_menu() { - let routine = status.routine; +function edit_menu(config) { + let routine = config.routine; E.showScroller({ h : 60, @@ -309,21 +312,20 @@ function edit_menu() { select : function(idx) { if (idx == routine.length + 1) { E.showScroller(); - require("Storage").writeJSON("pushups.cfg", routine); - start_routine(); + set_duration(config); } else if (idx == routine.length) { E.showScroller(); - add_activity(); + add_activity(config); } else { E.showScroller(); - set_counter(idx); + set_counter(config, idx); } } }); } -function add_activity() { +function add_activity(config) { E.showScroller({ h : 60, c : IMAGES.length, @@ -333,19 +335,19 @@ function add_activity() { g.drawImage(img, r.x + r.w / 3, r.y + 10); }, select : function(idx) { - let new_index = status.routine.length; - status.routine.push([idx, 10]); + let new_index = config.routine.length; + config.routine.push([idx, 10]); E.showScroller(); - set_counter(new_index); + set_counter(config, new_index); } }); } -function set_counter(index) { +function set_counter(config, index) { let w = g.getWidth(); let h = g.getHeight(); - let counter = status.routine[index][1]; + let counter = config.routine[index][1]; function display() { g.clear(); g.setFont("6x8:2") @@ -379,18 +381,69 @@ function set_counter(index) { }); Bangle.on("touch", function(button, xy) { if (counter == 0) { - status.routine.splice(index, 1); + config.routine.splice(index, 1); } else { - status.routine[index][1] = counter; + config.routine[index][1] = counter; + } + Bangle.removeAllListeners("touch"); + Bangle.removeAllListeners("swipe"); + edit_menu(config); + }); + +} + + +//TODO: factorize code with set_counter +function set_duration(config) { + let w = g.getWidth(); + let h = g.getHeight(); + let duration = config.duration; + let minutes = Math.floor(duration / 60); + function display() { + g.clear(); + g.setColor(0); + g.setFont("6x8:2") + .setFontAlign(1, 0) + .drawString("+1", w, h/2); + g.setFontAlign(-1, 0) + .drawString("-1", 0, h/2); + g.setFontAlign(0, -1) + .drawString("+5", w/2, 0); + g.setFontAlign(0, 1) + .drawString("-5", w/2, h); + g.drawString("minutes", w/2, h-40); + g.setFont("Vector:64") + .setFontAlign(0, 0) + .drawString(""+minutes, w/2, h/2); + } + display(); + Bangle.on("swipe", function (directionLR, directionUD) { + if (directionUD == -1) { + minutes += 5; + } else if (directionUD == 1) { + minutes -= 5; + } else if (directionLR == -1) { + minutes -= 1; + } else if (directionLR == 1) { + minutes += 1; } + if (minutes < 1) { + minutes = 1; + } + display(); + }); + Bangle.on("touch", function(button, xy) { Bangle.removeAllListeners("touch"); Bangle.removeAllListeners("swipe"); - edit_menu(); + config.duration = minutes * 60; + //TODO: don't write if no change + require("Storage").writeJSON("pushups.cfg", config); + start_routine(config); }); } -function main_menu() { +function main_menu(config) { let w = g.getWidth(); let h = g.getHeight(); g.setBgColor(g.theme.bg); @@ -412,7 +465,7 @@ function main_menu() { .setFontAlign(0, 0) .drawString("Edit", w/2, 3*h/4); Bangle.removeAllListeners("touch"); - edit_menu(); + edit_menu(config); } else if (xy.y < h/2-10) { g.setColor(g.theme.fg); g.fillRect(10, 10, w-10, h/2-10); @@ -421,10 +474,16 @@ function main_menu() { .setFontAlign(0, 0) .drawString("Start", w/2, h/4); Bangle.removeAllListeners("touch"); - start_routine(); + set_duration(config); } }) } -main_menu(); +let config = require("Storage").readJSON("pushups.cfg", true); + +if (config === undefined) { + config = default_config(); +} + +main_menu(config); diff --git a/apps/pushups/metadata.json b/apps/pushups/metadata.json index 64a445067f..dc8dd69897 100644 --- a/apps/pushups/metadata.json +++ b/apps/pushups/metadata.json @@ -9,6 +9,7 @@ "type": "app", "tags": "health", "supports": ["BANGLEJS2"], + "screenshots": [{"url":"shot_pushups.png"}, {"url":"shot_squats.png"}, {"url":"shot_menu.png"}], "readme": "README.md", "storage": [ {"name":"pushups.app.js","url":"app.js"}, diff --git a/apps/pushups/shot_menu.png b/apps/pushups/shot_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..b7f44b6e207294846f4d9ad43c04d04e9c634a46 GIT binary patch literal 2199 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 G-hTkkB8vk6 literal 0 HcmV?d00001 diff --git a/apps/pushups/shot_squats.png b/apps/pushups/shot_squats.png new file mode 100644 index 0000000000000000000000000000000000000000..de3ac7bdd18453fc0e0755f47f29c2361601702e GIT binary patch literal 3020 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 literal 0 HcmV?d00001 From 7a219870ca0852b9503b7946e699177ca7d70d4b Mon Sep 17 00:00:00 2001 From: frederic wagner Date: Thu, 9 Jan 2025 20:47:15 +0100 Subject: [PATCH 021/135] pushups: theme colors --- apps/pushups/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/pushups/app.js b/apps/pushups/app.js index ee03025fd9..102a0a1416 100644 --- a/apps/pushups/app.js +++ b/apps/pushups/app.js @@ -400,8 +400,9 @@ function set_duration(config) { let duration = config.duration; let minutes = Math.floor(duration / 60); function display() { + g.setBgColor(g.theme.bg); g.clear(); - g.setColor(0); + g.setColor(g.theme.fg); g.setFont("6x8:2") .setFontAlign(1, 0) .drawString("+1", w, h/2); From 4970c30d244c7d8ea8705615495daa87f979f179 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sat, 4 Jan 2025 23:47:29 +0100 Subject: [PATCH 022/135] spacer: Integrate with newer sky library --- apps/spacer/spacer.app.js | 152 ++++++++++++++++++++++++++++++-------- 1 file changed, 121 insertions(+), 31 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 13812b2a59..0015c1c767 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -124,13 +124,14 @@ let ui = { let fix = {}; /* Global for sky library */ -/* sky library v0.1.0 */ +/* sky library v0.2.2 */ let sky = { sats: [], snum: 0, sats_used: 0, sky_start: -1, this_usable: 0, + debug: 0, drawGrid: function() { g.setColor(0,0,0); @@ -140,7 +141,8 @@ let sky = { ui.radCircle(1.0); }, - snrLim: 28, + /* 18.. don't get reliable fix in 40s */ + snrLim: 22, drawSat: function(s) { let a = s.azi / 360; let e = ((90 - s.ele) / 90); @@ -172,7 +174,7 @@ let sky = { if (fix && fix.fix && fix.lat) { g.setColor(0, 0, 0) - .setFontAlign(-1, 1); + .setFontAlign(-1, 1); g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); } this.decorate(); @@ -197,13 +199,11 @@ let sky = { msg: {}, tof: function(v) { let i = (1*v); return i.toFixed(0); }, fmtSys: function(sys) { - if (sys && sys.sent !== undefined && sys.d23 !== undefined) - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; - else - return "(no data)\n"; + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; }, display: function() { - if (ui.display != 1) + /* unused on skyspy */ + if (ui.display == 1) return; let m = this.old_msg; let msg = "" + this.tof(m.time) + "\n" + @@ -218,37 +218,122 @@ let sky = { .setFontAlign(-1, -1) .drawString(msg, 0, 0); }, + snrSort: function() { + return this.sats.slice(0, this.snum).sort((a, b) => b.snr - a.snr); + }, + getSatSNR: function(n) { /* Get n-th strongest sat */ + if (n <= 0 || n > this.sats.length) + return -1; + + // Sort the satellites by snr in descending order + let sortedSats = this.snrSort(); + + // Return the SNR of the n-th strongest satellite + return sortedSats[n - 1].snr; + }, + qualest: function() { + // Sort the satellites by snr in descending order + let sortedSats = this.snrSort(); + if (sortedSats[4] && sortedSats[4].snr) { + return "" + sortedSats[4].snr + "dB"; + } + for (i=4; i>=0; i--) { + if (sortedSats[i] && sortedSats[i].snr) + return "S" + (i+1); + } + return "nil"; + }, + satVisibility: [], + trackSatelliteVisibility: function() { + const threshold = this.snrLim; // SNR threshold + const now = getTime(); + let newVisibility = []; + //this.satVisibility = []; + for (let i = 0; i < this.snum; i++) { + let sat = this.sats[i]; + let existingSat = this.satVisibility[sat.id]; + if (sat.snr >= threshold) { + if (!existingSat) { + // New satellite starts visibility + newVisibility[sat.id] = { start: now, visible: true }; + } else + newVisibility[sat.id] = this.satVisibility[sat.id]; + } + } + this.satVisibility = newVisibility; + }, + getnthLowestStartTimeSat: function(n) { + // Collect all satellites from visibility + let satellites = Object.values(this.satVisibility); + + // Ensure we have at least 5 satellites + if (satellites.length < n) + return -1; + + // Sort satellites by start time in ascending order + satellites.sort((a, b) => a.start - b.start); + + // Return the satellite with the 5th lowest start time + return satellites[n-1]; // 0-based index, so 5th is index 4 + }, + goodest: function () { + let s = this.getnthLowestStartTimeSat(5); + if (s==-1) + return "none"; + let t = getTime() - s.start; + return "" + t; + }, + onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */}, + messageEnd: function() { + this.old_msg = this.msg; + this.msg = {}; + this.msg.gp = {}; + this.msg.bd = {}; + this.msg.gl = {}; + this.drawSats(this.sats); + let r = this.qualest(); + let r1 = this.goodest(); + print(r, r1, this.old_msg.hdop, this.old_msg.quality); + if (ui.display == 4) + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + this.trackSatelliteVisibility(); + //print(this.sats); + if (this.sats_used < 5) + this.sky_start = getTime(); + this.snum = 0; + this.sats = []; + this.sats_used = 0; + this.onMessageEnd(); + }, parseRaw: function(msg, lost) { if (lost) print("## data lost"); let s = msg.split(","); + // print(getTime(), s[0]); + //return; let cmd = s[0].slice(3); //print("cmd", cmd); + if (cmd === "TXT") { + this.messageEnd(); + return; + } if (cmd === "GGA") { - this.old_msg = this.msg; - this.msg = {}; this.msg.time = s[1]; this.msg.quality = s[6]; this.msg.in_view = s[7]; this.msg.hdop = s[8]; - this.msg.gp = {}; - this.msg.bd = {}; - this.msg.gl = {}; - print("-----------------------------------------------"); - print("GGA Time", s[1], "fix quality", s[4], "sats in view ", s[5]); - this.drawSats(this.sats); - if (this.sats_used < 5) - this.sky_start = getTime(); - this.snum = 0; - this.sats = []; - this.sats_used = 0; + + if (this.debug > 0) { + print("-----------------------------------------------"); + print("GGA Time", s[1], "fix quality", s[4], "sats in view ", s[5]); + } return; } if (cmd === "GLL") return; /* Position lat/lon */ if (cmd === "GSA") { /* - $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 + $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 0 1 2 15 16 17 18 - */ + */ /* Satelites used, fix type! INTERESTING */ let sys = s[18]; let add = {}; @@ -256,29 +341,34 @@ let sky = { add.pdop = s[15]; add.hdop = s[16]; add.vdop = s[17]; + sys = sys[0]; /* FIXME -- should really add to the sentence */ if (sys == 1) { this.msg.gp = add; } else if (sys == 2) { this.msg.gl = add; } else if (sys == 4) { this.msg.bd = add; } - else print("GSA Unknown system\n"); - - print(msg); + else { + print("GSA Unknown system -- ", sys, "\n"); + print(msg); + } return; } if (s[0] === "$GPGSV") { - print("Have gps sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have gps sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } if (s[0] === "$BDGSV") { - print("Have baidu sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have baidu sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } if (s[0] === "$GLGSV") { - print("Have glonass sentences", s[1], "/", s[2]); + if (this.debug > 0) + print("Have glonass sentences", s[1], "/", s[2]); this.parseSats(s); this.msg.gl.sent = ""+s[2]; return; @@ -304,7 +394,7 @@ let sky = { this.sys += 1; if (this.sys == 4) this.sys = 0; - let val = 7; + val = 7; if (this.sys) val = 1 << (this.sys - 1); this.casic_cmd("$PCAS04,"+val); @@ -323,7 +413,7 @@ function start() { // CASIC_CMD("$PCAS06,0"); /* Query product information */ setTimeout(() => sky.casic_cmd("$PCAS04,7"), 1000); /* Enable gps + beidou + glonass */ -setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1000); /* Enable gps + beidou + glonass */ +setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all messages */ //setTimeout(() => sky.casic_cmd("$PCAS10,2"), 1200); /* 2: cold start, 1 warm start, 0: hot start */ From 6ae311e2d3fb202ee4c855f83a6f38d0a0b8d679 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:48:51 +0100 Subject: [PATCH 023/135] spacer: Make it easier to split modules, got it back to working order. --- apps/spacer/spacer.app.js | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 0015c1c767..817b61ffc0 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -162,8 +162,6 @@ let sky = { // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 decorate: function() {}, drawSats: function(sats) { - if (ui.display != 0) - return; g.reset() .setColor(1, 1, 1) .fillRect(0, ui.wi, ui.w, ui.y2) @@ -201,10 +199,7 @@ let sky = { fmtSys: function(sys) { return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; }, - display: function() { - /* unused on skyspy */ - if (ui.display == 1) - return; + drawRace: function() { let m = this.old_msg; let msg = "" + this.tof(m.time) + "\n" + "q" + m.quality + " " + m.in_view + " " + m.hdop + "\n" + @@ -283,19 +278,31 @@ let sky = { let t = getTime() - s.start; return "" + t; }, - onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */}, + drawEstimates: function() { + let r = this.qualest(); + let r1 = this.goodest(); + print(r, r1, this.old_msg.hdop, this.old_msg.quality); + /* FIXME: -- for skyspy + if (ui.display == 4) + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + */ + }, + onMessageEnd: function() { + /* quality.updateGps(); /* FIXME -- for skyspy */ + if (ui.display == 0) + this.drawSats(this.sats); + if (ui.display == 1) + this.drawRace(); + if (ui.display == 4) + this.drawEstimates(); + }, messageEnd: function() { this.old_msg = this.msg; this.msg = {}; this.msg.gp = {}; this.msg.bd = {}; this.msg.gl = {}; - this.drawSats(this.sats); - let r = this.qualest(); - let r1 = this.goodest(); - print(r, r1, this.old_msg.hdop, this.old_msg.quality); - if (ui.display == 4) - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + this.onMessageEnd(); this.trackSatelliteVisibility(); //print(this.sats); if (this.sats_used < 5) @@ -303,7 +310,6 @@ let sky = { this.snum = 0; this.sats = []; this.sats_used = 0; - this.onMessageEnd(); }, parseRaw: function(msg, lost) { if (lost) print("## data lost"); @@ -312,7 +318,7 @@ let sky = { //return; let cmd = s[0].slice(3); //print("cmd", cmd); - if (cmd === "TXT") { + if (cmd === "TXT") { // FIXME: we want to end on some more common message */ this.messageEnd(); return; } @@ -408,7 +414,6 @@ function start() { setTimeout(function() { Bangle.removeAllListeners('GPS-raw'); }, 1000000); - setInterval(function() { sky.display(); }, 1000); } // CASIC_CMD("$PCAS06,0"); /* Query product information */ From 179c88a341c1d43d1f20583a1d9846a6829c2b39 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:52:30 +0100 Subject: [PATCH 024/135] spacer: Cleanups. --- apps/spacer/spacer.app.js | 28 ++++++++++------------------ 1 file changed, 10 insertions(+), 18 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 817b61ffc0..acfd06a871 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -1,20 +1,6 @@ /* Space race */ /* - -Performance Assessment of GNSS Signals in -terms of Time to First Fix for -Cold, Warm and Hot Start -Matteo Paonni, Marco Anghileri, Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller -Institute of Geodesy and Navigation, University FAF Munich, Germany - -=> 22 to 26 dB -- long time / no fix / ... -=> 26db + -- basically strength no longer matters - -apps/assistedgps/custom.html - -https://github.com/espruino/EspruinoDocs/blob/master/info/Bangle.js2%20Technical.md#gps - gsa mi rika 2d/3d fix, a taky pdop/vdop/hdop CFG-NAVX z CASIC_en -- umoznuje nastavit chodec / auto / letadlo @@ -279,13 +265,19 @@ let sky = { return "" + t; }, drawEstimates: function() { + /* + Performance Assessment of GNSS Signals in terms of Time to + First Fix for Cold, Warm and Hot Start Matteo Paonni, Marco Anghileri, + Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller Institute + of Geodesy and Navigation, University FAF Munich, Germany + + => 22 to 26 dB -- long time / no fix / ... + => 26db + -- basically strength no longer matters + */ let r = this.qualest(); let r1 = this.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); - /* FIXME: -- for skyspy - if (ui.display == 4) - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); - */ + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, onMessageEnd: function() { /* quality.updateGps(); /* FIXME -- for skyspy */ From c570682b13b5b5f7f62246fd9fa2907e91c0ff40 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:53:17 +0100 Subject: [PATCH 025/135] spacer: Fix whitespace. --- apps/spacer/spacer.app.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index acfd06a871..449a3ca7f4 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -1,6 +1,6 @@ /* Space race */ -/* +/* gsa mi rika 2d/3d fix, a taky pdop/vdop/hdop CFG-NAVX z CASIC_en -- umoznuje nastavit chodec / auto / letadlo @@ -54,12 +54,12 @@ let ui = { touchHandler: function(d) { let x = Math.floor(d.x); let y = Math.floor(d.y); - + if (d.b != 1 || this.last_b != 0) { this.last_b = d.b; return; } - + print("touch", x, y, this.h, this.w); if ((x this.sats.length) return -1; - + // Sort the satellites by snr in descending order let sortedSats = this.snrSort(); @@ -237,7 +237,7 @@ let sky = { if (!existingSat) { // New satellite starts visibility newVisibility[sat.id] = { start: now, visible: true }; - } else + } else newVisibility[sat.id] = this.satVisibility[sat.id]; } } @@ -265,7 +265,7 @@ let sky = { return "" + t; }, drawEstimates: function() { - /* + /* Performance Assessment of GNSS Signals in terms of Time to First Fix for Cold, Warm and Hot Start Matteo Paonni, Marco Anghileri, Stefan Wallner, José-Ángel Ávila-Rodríguez, Bernd Eissfeller Institute @@ -330,7 +330,7 @@ let sky = { if (cmd === "GSA") { /* $GNGSA,A,1,,,,,,,,,,,,,25.5,25.5,25.5,4*04 - 0 1 2 15 16 17 18 + 0 1 2 15 16 17 18 */ /* Satelites used, fix type! INTERESTING */ let sys = s[18]; @@ -376,7 +376,7 @@ let sky = { if (cmd === "ZDA") return; /* Time + timezone */ if (cmd === "TXT") { this.msg.finished = 1; - return; /* Misc text? antena open */ + return; /* Misc text? antena open */ } print(msg); From d12ace49b905c5c203aa8a050bbe76b25654e653 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 18:57:05 +0100 Subject: [PATCH 026/135] spacer: More cleanups. --- apps/spacer/spacer.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 449a3ca7f4..60e11d26ab 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -402,7 +402,7 @@ let sky = { function start() { Bangle.setGPSPower(1); - Bangle.on('GPS-raw', function(a, b) { sky.parseRaw(a, b); }); + Bangle.on('GPS-raw', (a, b) => sky.parseRaw(a, b)); setTimeout(function() { Bangle.removeAllListeners('GPS-raw'); }, 1000000); From e626dce2a48fced6714bb0a14ae4b916211bd130 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 19:01:17 +0100 Subject: [PATCH 027/135] spacer: better split into modules --- apps/spacer/spacer.app.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 60e11d26ab..631eb25db5 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -279,15 +279,7 @@ let sky = { print(r, r1, this.old_msg.hdop, this.old_msg.quality); ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, - onMessageEnd: function() { - /* quality.updateGps(); /* FIXME -- for skyspy */ - if (ui.display == 0) - this.drawSats(this.sats); - if (ui.display == 1) - this.drawRace(); - if (ui.display == 4) - this.drawEstimates(); - }, + onMessageEnd: function() {}, messageEnd: function() { this.old_msg = this.msg; this.msg = {}; @@ -408,6 +400,17 @@ function start() { }, 1000000); } +function onMessage() { + /* quality.updateGps(); /* FIXME -- for skyspy + if (ui.display == 4) + sky.drawEstimates(); + */ + if (ui.display == 0) + sky.drawSats(sky.sats); + if (ui.display == 1) + sky.drawRace(); +} + // CASIC_CMD("$PCAS06,0"); /* Query product information */ setTimeout(() => sky.casic_cmd("$PCAS04,7"), 1000); /* Enable gps + beidou + glonass */ setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all messages */ @@ -417,4 +420,5 @@ setTimeout(() => sky.casic_cmd("$PCAS03,1,1,1,1,1,1,1,1"), 1500); /* Enable all ui.init(); ui.topLeft = () => sky.selectSpace(); Bangle.on("drag", (b) => ui.touchHandler(b)); +sky.onMessageEnd = onMessage; start(); From 1d1a3ee5b31de00702f4ff8e0a42d8640fa667b4 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:09:06 +0100 Subject: [PATCH 028/135] spacer: Move satelite set related functions to separate struct. --- apps/spacer/spacer.app.js | 183 ++++++++++++++++++++------------------ 1 file changed, 94 insertions(+), 89 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 631eb25db5..9210eeea4d 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -108,62 +108,16 @@ let ui = { }, }; +/* sky library v0.2.3 + needs ui */ + let fix = {}; /* Global for sky library */ -/* sky library v0.2.2 */ -let sky = { +let skys = { sats: [], snum: 0, sats_used: 0, - sky_start: -1, - this_usable: 0, - debug: 0, - - drawGrid: function() { - g.setColor(0,0,0); - ui.radLine(0, 1, 0.5, 1); - ui.radLine(0.25, 1, 0.75, 1); - ui.radCircle(0.5); - ui.radCircle(1.0); - }, - - /* 18.. don't get reliable fix in 40s */ - snrLim: 22, - drawSat: function(s) { - let a = s.azi / 360; - let e = ((90 - s.ele) / 90); - let x = ui.radX(a, e); - let y = ui.radY(a, e); - - if (s.snr == 0) - g.setColor(1, 0.25, 0.25); - else if (s.snr < this.snrLim) - g.setColor(0.25, 0.5, 0.25); - else - g.setColor(0, 0, 0); - g.drawString(s.id, x, y); - }, - - // Should correspond to view from below. - // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 - decorate: function() {}, - drawSats: function(sats) { - g.reset() - .setColor(1, 1, 1) - .fillRect(0, ui.wi, ui.w, ui.y2) - .setFont("Vector", 20) - .setFontAlign(0, 0); - this.drawGrid(); - sats.forEach(s => this.drawSat(s)); - - if (fix && fix.fix && fix.lat) { - g.setColor(0, 0, 0) - .setFontAlign(-1, 1); - g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); - } - this.decorate(); - }, - + parseSats: function(s) { let view = 1 * s[3]; let k = Math.min(4, view - this.snum); @@ -179,26 +133,6 @@ let sky = { } }, - old_msg: {}, - msg: {}, - tof: function(v) { let i = (1*v); return i.toFixed(0); }, - fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; - }, - drawRace: function() { - let m = this.old_msg; - let msg = "" + this.tof(m.time) + "\n" + - "q" + m.quality + " " + m.in_view + " " + m.hdop + "\n" + - "gp"+ this.fmtSys(m.gp) + - "bd" + this.fmtSys(m.bd) + - "gl" + this.fmtSys(m.gl); - if (this.msg.finished != 1) - msg += "!"; - g.reset().clear().setFont("Vector", 30) - .setColor(0, 0, 0) - .setFontAlign(-1, -1) - .drawString(msg, 0, 0); - }, snrSort: function() { return this.sats.slice(0, this.snum).sort((a, b) => b.snr - a.snr); }, @@ -264,6 +198,79 @@ let sky = { let t = getTime() - s.start; return "" + t; }, +}; + +let sky = { + sky_start: -1, + this_usable: 0, + debug: 0, + all: skys, /* Sattelites from all systems */ + + drawGrid: function() { + g.setColor(0,0,0); + ui.radLine(0, 1, 0.5, 1); + ui.radLine(0.25, 1, 0.75, 1); + ui.radCircle(0.5); + ui.radCircle(1.0); + }, + + /* 18.. don't get reliable fix in 40s */ + snrLim: 22, + drawSat: function(s) { + let a = s.azi / 360; + let e = ((90 - s.ele) / 90); + let x = ui.radX(a, e); + let y = ui.radY(a, e); + + if (s.snr == 0) + g.setColor(1, 0.25, 0.25); + else if (s.snr < this.snrLim) + g.setColor(0.25, 0.5, 0.25); + else + g.setColor(0, 0, 0); + g.drawString(s.id, x, y); + }, + + // Should correspond to view from below. + // https://in-the-sky.org//satmap_radar.php?year=2023&month=10&day=24&skin=1 + decorate: function() {}, + drawSats: function(sats) { + g.reset() + .setColor(1, 1, 1) + .fillRect(0, ui.wi, ui.w, ui.y2) + .setFont("Vector", 20) + .setFontAlign(0, 0); + this.drawGrid(); + sats.forEach(s => this.drawSat(s)); + + if (fix && fix.fix && fix.lat) { + g.setColor(0, 0, 0) + .setFontAlign(-1, 1); + g.drawString(fix.satellites + "/" + fix.hdop, 5, ui.y2); + } + this.decorate(); + }, + + old_msg: {}, + msg: {}, + tof: function(v) { let i = (1*v); return i.toFixed(0); }, + fmtSys: function(sys) { + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; + }, + drawRace: function() { + let m = this.old_msg; + let msg = "gmt " + this.tof(m.time) + "\n" + + "q" + m.quality + " S" + m.in_view + " h" + (1*m.hdop).toFixed(1) + "m\n" + + "gp"+ this.fmtSys(m.gp) + + "bd" + this.fmtSys(m.bd) + + "gl" + this.fmtSys(m.gl); + if (this.msg.finished != 1) + msg += "!"; + g.reset().clear().setFont("Vector", 30) + .setColor(0, 0, 0) + .setFontAlign(-1, -1) + .drawString(msg, 0, 0); + }, drawEstimates: function() { /* Performance Assessment of GNSS Signals in terms of Time to @@ -274,8 +281,8 @@ let sky = { => 22 to 26 dB -- long time / no fix / ... => 26db + -- basically strength no longer matters */ - let r = this.qualest(); - let r1 = this.goodest(); + let r = this.all.qualest(); + let r1 = this.all.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); }, @@ -287,22 +294,24 @@ let sky = { this.msg.bd = {}; this.msg.gl = {}; this.onMessageEnd(); - this.trackSatelliteVisibility(); + this.all.trackSatelliteVisibility(); //print(this.sats); - if (this.sats_used < 5) + if (this.all.sats_used < 5) this.sky_start = getTime(); - this.snum = 0; - this.sats = []; - this.sats_used = 0; + this.all.snum = 0; + this.all.sats = []; + this.all.sats_used = 0; }, parseRaw: function(msg, lost) { + //print(msg); if (lost) print("## data lost"); let s = msg.split(","); // print(getTime(), s[0]); //return; let cmd = s[0].slice(3); //print("cmd", cmd); - if (cmd === "TXT") { // FIXME: we want to end on some more common message */ + if (cmd === "RMC") { + /* Repeat of position/speed/course */ this.messageEnd(); return; } @@ -345,32 +354,28 @@ let sky = { if (s[0] === "$GPGSV") { if (this.debug > 0) print("Have gps sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } if (s[0] === "$BDGSV") { if (this.debug > 0) print("Have baidu sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } if (s[0] === "$GLGSV") { if (this.debug > 0) print("Have glonass sentences", s[1], "/", s[2]); - this.parseSats(s); + this.all.parseSats(s); this.msg.gl.sent = ""+s[2]; return; } - if (cmd === "RMC") return; /* Repeat of position/speed/course */ + if (cmd === "VTG") return; /* Speeds in knots/kph */ if (cmd === "ZDA") return; /* Time + timezone */ - if (cmd === "TXT") { - this.msg.finished = 1; - return; /* Misc text? antena open */ - } - + if (cmd === "TXT") return; /* Misc text? antena open */ print(msg); }, casic_cmd: function (cmd) { @@ -406,7 +411,7 @@ function onMessage() { sky.drawEstimates(); */ if (ui.display == 0) - sky.drawSats(sky.sats); + sky.drawSats(sky.all.sats); if (ui.display == 1) sky.drawRace(); } From 3de7bbcf33b32698537f32cc045b276607f2b51c Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:17:41 +0100 Subject: [PATCH 029/135] spacer: More refactoring. --- apps/spacer/spacer.app.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 9210eeea4d..cc9c019a86 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -117,7 +117,12 @@ let skys = { sats: [], snum: 0, sats_used: 0, - + + reset: function() { + this.snum = 0; + this.sats = []; + this.sats_used = 0; + }, parseSats: function(s) { let view = 1 * s[3]; let k = Math.min(4, view - this.snum); @@ -298,9 +303,7 @@ let sky = { //print(this.sats); if (this.all.sats_used < 5) this.sky_start = getTime(); - this.all.snum = 0; - this.all.sats = []; - this.all.sats_used = 0; + this.all.reset(); }, parseRaw: function(msg, lost) { //print(msg); From ced4223e2ea35ffe778fca277d1c61823517c767 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Sun, 5 Jan 2025 20:26:58 +0100 Subject: [PATCH 030/135] spacer: prepare for printing vdop/pdop --- apps/spacer/spacer.app.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index cc9c019a86..43681264f3 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -258,14 +258,17 @@ let sky = { old_msg: {}, msg: {}, - tof: function(v) { let i = (1*v); return i.toFixed(0); }, + tof: function(v, n) { let i = (1*v); return i.toFixed(n); }, + tof0: function(v) { return this.tof(v, 0); }, + tof1: function(v) { return this.tof(v, 1); }, fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof(sys.vdop) + "\n"; + return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof0(sys.vdop) + "\n"; }, drawRace: function() { let m = this.old_msg; - let msg = "gmt " + this.tof(m.time) + "\n" + - "q" + m.quality + " S" + m.in_view + " h" + (1*m.hdop).toFixed(1) + "m\n" + + let msg = "gmt" + this.tof0(m.time) + "\n" + + "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + +/* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ "gp"+ this.fmtSys(m.gp) + "bd" + this.fmtSys(m.bd) + "gl" + this.fmtSys(m.gl); From 3e38d715b734cc60a3da55c0c4497e6a47fc5903 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 14:22:32 +0100 Subject: [PATCH 031/135] spacer: refactor --- apps/spacer/spacer.app.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 43681264f3..ede98eb6be 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -117,6 +117,7 @@ let skys = { sats: [], snum: 0, sats_used: 0, + sky_start: -1, reset: function() { this.snum = 0; @@ -203,10 +204,14 @@ let skys = { let t = getTime() - s.start; return "" + t; }, + onEnd: function () { + if (this.sats_used < 5) + this.sky_start = getTime(); + this.reset(); + }, }; let sky = { - sky_start: -1, this_usable: 0, debug: 0, all: skys, /* Sattelites from all systems */ @@ -292,7 +297,7 @@ let sky = { let r = this.all.qualest(); let r1 = this.all.goodest(); print(r, r1, this.old_msg.hdop, this.old_msg.quality); - ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.sky_start)); + ui.drawMsg(r + "\n" + r1 + "\n" + this.old_msg.hdop + "-" + this.old_msg.quality + "d\n" + (getTime() - this.all.sky_start)); }, onMessageEnd: function() {}, messageEnd: function() { @@ -304,9 +309,7 @@ let sky = { this.onMessageEnd(); this.all.trackSatelliteVisibility(); //print(this.sats); - if (this.all.sats_used < 5) - this.sky_start = getTime(); - this.all.reset(); + this.all.onEnd(); }, parseRaw: function(msg, lost) { //print(msg); From 0597658b1dc9cff037cb6cdc216e20c505e3fa2c Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 14:28:04 +0100 Subject: [PATCH 032/135] spacer: display fix summary --- apps/spacer/spacer.app.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index ede98eb6be..1b31afb645 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -200,9 +200,15 @@ let skys = { goodest: function () { let s = this.getnthLowestStartTimeSat(5); if (s==-1) - return "none"; + return ""; let t = getTime() - s.start; - return "" + t; + return "" + t + "s"; + }, + summary: function () { + let s = this.goodest(); + if (s != "") + return s; + return this.qualest(); }, onEnd: function () { if (this.sats_used < 5) @@ -273,7 +279,8 @@ let sky = { let m = this.old_msg; let msg = "gmt" + this.tof0(m.time) + "\n" + "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + -/* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ + /* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ + this.all.summary() + "\n" + "gp"+ this.fmtSys(m.gp) + "bd" + this.fmtSys(m.bd) + "gl" + this.fmtSys(m.gl); From 921b2b557ecb675abcc3693508e80098cf17e884 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 6 Jan 2025 17:43:46 +0100 Subject: [PATCH 033/135] spacer: update icon. --- apps/spacer/app-icon.js | 2 +- apps/spacer/app.png | Bin 14889 -> 1976 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/spacer/app-icon.js b/apps/spacer/app-icon.js index 903d14af51..53dbfa31ee 100644 --- a/apps/spacer/app-icon.js +++ b/apps/spacer/app-icon.js @@ -1,2 +1,2 @@ -require("heatshrink").decompress(atob("mEwgIQNgQFEj/gAof+jgECgeAAIIFBgwCBuACBhgCEjAOEAoQ6CmAhCDwItDoEB4AFCsEBFgUEkEDG4XEJYcL8gFCgUP+gxCAoP8DIIFBhfsiEIAoMJAogCBAoYlBiBMBAoUwrA0B////ALECI0QAocgAolgApVADolAHYnAAomAAoqdBAoKVBMoRvCOIQDCRIIFBYwKVBAoKqC4AFBVQVggTRDn0CYgQcBN4LpDV4T7IAooAJA=")) +require("heatshrink").decompress(atob("mEwhHXAH4A/AH4A/AGMAF34v/F34EBAAIvrFwQxnEoIsFGEyNHF9ZgNGrheMF4guJHDAvLEhCdbLyLLdL5ImFfRo6SLpjGOCgw5TdZRhKHwhEPFxjOJCwwOGF6zOJBxpjFAB4TKR6aEJDpgwKd5rzUYBrkVMxwtVF7CYHeBxGRF5LwMR9YvdPiJfjBhYv/F/4v/F/4v/F/4v/F/4v/F/4vfAH4Ad")) diff --git a/apps/spacer/app.png b/apps/spacer/app.png index ce7ac239fd0f72f3a1ab88ccfa91bcd21846caf4..6743d6e59284b3867f46119a9400afa32cecdefa 100644 GIT binary patch literal 1976 zcmd5-c~q0v5>Gxq;bS$C9T9;%8g`J#RyJ8eAZ&u{Vu-RTU;|;5uzVH*NGw{R3I-H# z#ggz?s!$u^Qb9m^(5C@`5+7icB}R4(m45V{_s9F={oi}eotb-Q<~Mido;g!~D1f9S zuPu*4p_F{QJ%bV6y1gM8gmUjqQxJxx2b0`UoFSbL$N{9g`-DKqVnA_aD3t7RA5XWC z9Lhr7aM-xF;?B2QuC<2KD8iNfyteCOEe)$S>1&yH#?`+{T>8BFWl~|wjcNpkgSu}V zju&DMQav^OQ84LVr37N_Xp+;DykEuY!fDh4Xi#^;ziEt=13ra^K}=4D z6sqLgTh*d~%2WH^Vl`#GR1OM<7jRC%6h8@ooVxRiNmQM`0cb?hU!oTZd9}rpm1KjT2F$`xqdV*j&=m}5?-^;tHxOYALHY!lmHySWS4% z+WN8#jJ3Z#NST2cFL&{r<_&LskK9CjiW}2L+)`&k&irv2Cd58o=p?mn{H$`8DM-fH zf6~artas;xh8tJ`;aweZdqHLSAKBexyq38tS!4sT_@W9%iNxDI(L&gTeC7nXS4tL{`#oIcQI0pMDR9UTAqDB<8-XP(&k zw~nm-ZJ0W0`!)aNsZ!1_xVgV?zx@to9mrsh2+J&RT*v6UGY5yNrNw#^J6 zB~1tnB$-+9;Rvnr-N`v!(z09l_39;!#Do(1G9^pP9Ap2ctMN3*L6`GwbROT;qiK#l zR+tA8DTySm`7K485hJwgsEUYB%1$i5I8Iy+v9JOlyXPBcZuv&9r zJ(F43);#5T?w#s4TgM`MDZ@6{hl*J0q7 zcTE0sg2aYc$diY!fa0XE-dZj6*NdKl`93a7-IP><^SXhjbztw#I)b#{eMtpiR+d#) zcq!_ccf)|=B93-@XL7~1>H?uKgWDwAki1DPUXOQuLfm%%{BAelU!*I?%T(Vys&VZW zykztH{nTco4yOt3wit_h+k);`M>ghXET!zxZ?vn2*qSude{=sqsY zPk^%>XV^eS()fiK2U^zLRImMt?rf_3bTfM|5E6g*^@qMn{uXW$9eIKi+)n=~bOUKk zwKeid)lsr7+2X}=dXMj~&@jQx@W|HE3^ceaEe6!N<=Och>9atb*8Ra4P@5TO?l5`IDeQj%^vzV^i*z8F8VV=pJqIi zi@%&MJ>^s7chyFm!sfI2Sl7U0?7C_YkFVr#b-kdZZt3UtG=L6Va*2VW&tB9TDO&ns zDFC-*D@PgI_K~HS`&HLkFH3Fkp7Pc6?8&-wDwkF4mnCd9oJ6bPjBB=sMcIR8o4wCI zCJZ2Pbv`Y1sKbHS8HMrlOXVBNj3?(2`}@lq>HCzCl%UPBBB>86fcN;Z!Tlp6% z9#@RUq?b23F4U70U>>~$}**EcIlv{;Dz~c7*AID8uL3(?XtQ`|TrZ38e7~siq Hr=Ix}GpBEV literal 14889 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

obkzBHHw)%!W~j@Fk!G)!@_9jb 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 oeUItr=y-W~? Date: Tue, 7 Jan 2025 11:44:39 +0100 Subject: [PATCH 034/135] spacer: better docs, compute statistics per-system --- apps/spacer/README.md | 14 +++++++++++- apps/spacer/spacer.app.js | 48 +++++++++++++++++++++++++++++++++++---- 2 files changed, 56 insertions(+), 6 deletions(-) diff --git a/apps/spacer/README.md b/apps/spacer/README.md index 5a8725a966..00d9de4a3b 100644 --- a/apps/spacer/README.md +++ b/apps/spacer/README.md @@ -4,5 +4,17 @@ Compare GPS with Baido and Glonass This turns GNSS receiver into mode with all three systems enabled, and displays debug info from all of them. Click into top left corner to -switch navigation systems. +switch navigation systems. Clicks in bottom half of screen switch info +pages. + +GNSS acquisition has few phases, and this software is assuming you are +not doing a cold start. GNSS fix needs 4 or 5 satellites with +reasonable signal strength, and then holding the same place for 40 or +so seconds. + +nil -- no satellites visible + +S1..S4 -- not enough satellites being decoded (5 needed) + +XXdB -- have enough satellites, but signal is not strong enough diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 1b31afb645..7d4699a7b2 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -217,10 +217,37 @@ let skys = { }, }; +function deepCopy(obj) { + if (obj === null || typeof obj !== "object") { + return obj; // Return primitive values as-is + } + + if (Array.isArray(obj)) { + return obj.map(deepCopy); // Handle arrays recursively + } + + const copy = {}; + for (const key in obj) { + if (obj.hasOwnProperty(key)) { + copy[key] = deepCopy(obj[key]); // Recursively copy properties + } + } + return copy; +} + let sky = { this_usable: 0, debug: 0, all: skys, /* Sattelites from all systems */ + split: 1, + + init: function () { + if (this.split) { + this.s_gp = deepCopy(skys); + this.s_gl = deepCopy(skys); + this.s_bd = deepCopy(skys); + } + }, drawGrid: function() { g.setColor(0,0,0); @@ -272,8 +299,12 @@ let sky = { tof: function(v, n) { let i = (1*v); return i.toFixed(n); }, tof0: function(v) { return this.tof(v, 0); }, tof1: function(v) { return this.tof(v, 1); }, - fmtSys: function(sys) { - return sys.sent + "." + sys.d23 + "D "+ this.tof(sys.pdop) + " " + this.tof0(sys.vdop) + "\n"; + fmtSys: function(sys, sats) { + let r = sys.sent + " "; + // r+= sys.d23 + "D "; + if (sats) + r += sats.sats_used + "/" + sats.snum; + return r + "\n"; }, drawRace: function() { let m = this.old_msg; @@ -281,9 +312,9 @@ let sky = { "q" + m.quality + " S" + m.in_view + " h" + this.tof0(m.hdop) + "m\n" + /* "v" + this.tof0(m.vdop) + "m " + "p" + this.tof0(m.pdop) + "m\n" + */ this.all.summary() + "\n" + - "gp"+ this.fmtSys(m.gp) + - "bd" + this.fmtSys(m.bd) + - "gl" + this.fmtSys(m.gl); + "gp"+ this.fmtSys(m.gp, this.s_gp) + + "bd" + this.fmtSys(m.bd, this.s_bd) + + "gl" + this.fmtSys(m.gl, this.s_gl); if (this.msg.finished != 1) msg += "!"; g.reset().clear().setFont("Vector", 30) @@ -371,6 +402,8 @@ let sky = { if (this.debug > 0) print("Have gps sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_gp.parseSats(s); this.msg.gp.sent = ""+s[2]; return; } @@ -378,6 +411,8 @@ let sky = { if (this.debug > 0) print("Have baidu sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_bd.parseSats(s); this.msg.bd.sent = ""+s[2]; return; } @@ -385,6 +420,8 @@ let sky = { if (this.debug > 0) print("Have glonass sentences", s[1], "/", s[2]); this.all.parseSats(s); + if (this.split) + this.s_gl.parseSats(s); this.msg.gl.sent = ""+s[2]; return; } @@ -442,4 +479,5 @@ ui.init(); ui.topLeft = () => sky.selectSpace(); Bangle.on("drag", (b) => ui.touchHandler(b)); sky.onMessageEnd = onMessage; +sky.init(); start(); From 11903326f6c6b0681f9eee0dccb91b541f0e8dc5 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Tue, 7 Jan 2025 12:34:08 +0100 Subject: [PATCH 035/135] spacer: report details for each system --- apps/spacer/spacer.app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 7d4699a7b2..d66defaf6d 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -162,7 +162,7 @@ let skys = { if (sortedSats[i] && sortedSats[i].snr) return "S" + (i+1); } - return "nil"; + return "U" + this.snum; }, satVisibility: [], trackSatelliteVisibility: function() { @@ -303,7 +303,8 @@ let sky = { let r = sys.sent + " "; // r+= sys.d23 + "D "; if (sats) - r += sats.sats_used + "/" + sats.snum; + // r += sats.sats_used + "/" + sats.snum; + r += sats.summary(); return r + "\n"; }, drawRace: function() { From 520b1848becd0222d40b09ff6db7798383554731 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 11:17:14 +0100 Subject: [PATCH 036/135] spacer: Fix computations on multiple systems --- apps/spacer/spacer.app.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index d66defaf6d..95f2ab4264 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -211,6 +211,7 @@ let skys = { return this.qualest(); }, onEnd: function () { + this.trackSatelliteVisibility(); if (this.sats_used < 5) this.sky_start = getTime(); this.reset(); @@ -346,9 +347,13 @@ let sky = { this.msg.bd = {}; this.msg.gl = {}; this.onMessageEnd(); - this.all.trackSatelliteVisibility(); //print(this.sats); this.all.onEnd(); + if (this.split) { + this.s_gp.onEnd(); + this.s_gl.onEnd(); + this.s_bd.onEnd(); + } }, parseRaw: function(msg, lost) { //print(msg); From ef62d2ef56137d621369c6c29be21f00c64da707 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 11:22:49 +0100 Subject: [PATCH 037/135] spacer: Display systems with no data as "off" --- apps/spacer/spacer.app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 95f2ab4264..2a12d1f501 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -301,6 +301,8 @@ let sky = { tof0: function(v) { return this.tof(v, 0); }, tof1: function(v) { return this.tof(v, 1); }, fmtSys: function(sys, sats) { + if (!sys.sent) + return " off\n"; let r = sys.sent + " "; // r+= sys.d23 + "D "; if (sats) From 36a3695475fbbd5780011a4a04acda618dff7c65 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 20:14:34 +0100 Subject: [PATCH 038/135] spacer: Document current behaviour --- apps/spacer/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/spacer/README.md b/apps/spacer/README.md index 00d9de4a3b..b3fc437ba7 100644 --- a/apps/spacer/README.md +++ b/apps/spacer/README.md @@ -12,9 +12,9 @@ not doing a cold start. GNSS fix needs 4 or 5 satellites with reasonable signal strength, and then holding the same place for 40 or so seconds. -nil -- no satellites visible +Uxx -- satellites are known but not being received S1..S4 -- not enough satellites being decoded (5 needed) -XXdB -- have enough satellites, but signal is not strong enough +XXdB -- this is strength of 5th strongest satellite From 92b6a9f518a1f2034fac1aaf23129afe2a60f58d Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 20:14:47 +0100 Subject: [PATCH 039/135] spacer: version 0.10 --- apps/spacer/ChangeLog | 1 + apps/spacer/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/spacer/ChangeLog b/apps/spacer/ChangeLog index 263d4078d2..88e8a64fc0 100644 --- a/apps/spacer/ChangeLog +++ b/apps/spacer/ChangeLog @@ -1 +1,2 @@ 0.01: attempt to import +0.10: major updates, display satellites, display per-system satellite info diff --git a/apps/spacer/metadata.json b/apps/spacer/metadata.json index 55598f9535..e114d8dd12 100644 --- a/apps/spacer/metadata.json +++ b/apps/spacer/metadata.json @@ -1,6 +1,6 @@ { "id": "spacer", "name": "Space Race", - "version": "0.01", + "version": "0.10", "description": "Compare GPS with Baido and Glonass", "icon": "app.png", "readme": "README.md", From c0cc2378f131f0ba68420d0763985cb537cc46eb Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Fri, 10 Jan 2025 21:21:21 +0100 Subject: [PATCH 040/135] spacer: fix some warnings --- apps/spacer/spacer.app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/spacer/spacer.app.js b/apps/spacer/spacer.app.js index 2a12d1f501..99453e79a8 100644 --- a/apps/spacer/spacer.app.js +++ b/apps/spacer/spacer.app.js @@ -158,7 +158,7 @@ let skys = { if (sortedSats[4] && sortedSats[4].snr) { return "" + sortedSats[4].snr + "dB"; } - for (i=4; i>=0; i--) { + for (let i=4; i>=0; i--) { if (sortedSats[i] && sortedSats[i].snr) return "S" + (i+1); } @@ -450,7 +450,7 @@ let sky = { this.sys += 1; if (this.sys == 4) this.sys = 0; - val = 7; + let val = 7; if (this.sys) val = 1 << (this.sys - 1); this.casic_cmd("$PCAS04,"+val); From e7083fe190650b67eab503f2c048c6cac27eb655 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Jan 2025 10:48:23 +0000 Subject: [PATCH 041/135] add more docs for recorder items --- apps/recorder/README.md | 17 +++++++++++++++++ apps/recorder/widget.js | 16 +++++++++------- 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/apps/recorder/README.md b/apps/recorder/README.md index 6da739b1cd..d04e0342d6 100644 --- a/apps/recorder/README.md +++ b/apps/recorder/README.md @@ -52,6 +52,23 @@ As long as widgets are loaded, you can: * Call `WIDGETS["recorder"].setRecording(true, {force:"new"/"append"/"overwrite")` to start recording (it returns a promise, and will not show a menu) * Call `WIDGETS["recorder"].setRecording(false)` to stop recording +### Recording new items + +You can add new data items to record by creating a JS file on the Bangle named ending in `.recorder.js` that adds a new item +to the supplied `recorders` array. For example `foobar.recorder.js` could contain: + +``` +(function(recorders) { + recorders.foobar = { + name : "Foobar", // Name to appear in UIs + fields : ["foobar"], // Column headings to appear as header in recorded CSV data + getValues : () => [123], // Columns of data (length should match 'fields') + start : () => {}, // Called when recording starts - turn on any hardware/intervals you need + stop : () => {}, // Called when recording stops - turn off any hardware/intervals + draw (x,y) => {} // draw 12x12px status image at x,y on g + } +}) +``` ## Tips diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 74cffb068f..740df922f8 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -145,15 +145,17 @@ } } - /* eg. foobar.recorder.js + /* You can add new data items to record by creating a JS file on the Bangle named ending in `.recorder.js` that adds a new item +to the supplied `recorders` array. For example `foobar.recorder.js` could contain: + (function(recorders) { recorders.foobar = { - name : "Foobar", - fields : ["foobar"], - getValues : () => [123], - start : () => {}, - stop : () => {}, - draw (x,y) => {} // draw 12x12px status image + name : "Foobar", // Name to appear in UIs + fields : ["foobar"], // Column headings to appear as header in recorded CSV data + getValues : () => [123], // Columns of data (length should match 'fields') + start : () => {}, // Called when recording starts - turn on any hardware/intervals you need + stop : () => {}, // Called when recording stops - turn off any hardware/intervals + draw (x,y) => {} // draw 12x12px status image at x,y on g } }) */ From 0eaed9fdb0e58f471b17ac4689bab3aa082f1747 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 20 Jan 2025 10:48:41 +0000 Subject: [PATCH 042/135] lint exemptions --- apps/lint_exemptions.js | 63 ----------------------------------------- 1 file changed, 63 deletions(-) diff --git a/apps/lint_exemptions.js b/apps/lint_exemptions.js index 1b3a3cc11b..70b5bbb388 100644 --- a/apps/lint_exemptions.js +++ b/apps/lint_exemptions.js @@ -79,12 +79,6 @@ module.exports = { "no-undef" ] }, - "apps/podadrem/app.js": { - "hash": "f7392e74974f69553aade2dcc07527b5d3b71a9b84e6dc5e0dd995e78dff8007", - "rules": [ - "no-unused-vars" - ] - }, "apps/openstmap/imagefilter.js": { "hash": "8a71e9a0ecfa94150379c41a5a915cfdac39f8b2e485e5cc1ce4629e85293acd", "rules": [ @@ -148,13 +142,6 @@ module.exports = { "no-unused-vars" ] }, - "apps/waypoints/waypoints.app.js": { - "hash": "ff02639eb8f81784c942093d57d254295e2c78918adb4bcffdf0d0284ebfac55", - "rules": [ - "no-unused-vars", - "no-undef" - ] - }, "apps/timerclk/timer.js": { "hash": "3b70606f1742b34bf4769f6e8703144ff0c3ba401a3a21f97ddcab5432c94db5", "rules": [ @@ -195,12 +182,6 @@ module.exports = { "no-unused-vars" ] }, - "apps/poweroff/settings.js": { - "hash": "c197afe72c612a4b3825a3a12a628d0f4ed83823da3f28885bbf473037a02506", - "rules": [ - "no-unused-vars" - ] - }, "apps/oxofocus/app.js": { "hash": "cd29309373974ef038725e26d8a2ff2634a437c89cdffc3b12defd65a948db75", "rules": [ @@ -208,13 +189,6 @@ module.exports = { "no-undef" ] }, - "apps/orloj/app.js": { - "hash": "fa43f035d759ba94f564392f410c0c6c485bb41a33c062f03d666738d517ccf3", - "rules": [ - "no-unused-vars", - "no-undef" - ] - }, "apps/nixie/m_vatch.js": { "hash": "36a7fa956f99d5815cd6bac570d2b86833d1d37474d7eef0bb21892bdf6723a8", "rules": [ @@ -490,13 +464,6 @@ module.exports = { "no-undef" ] }, - "apps/doztime/app-bangle1.js": { - "hash": "1e9598c201175180ae77d1c3bc47e8138b339b72eb58782b5057fb7aefdc88a1", - "rules": [ - "no-unused-vars", - "no-undef" - ] - }, "apps/carcrazy/app.js": { "hash": "fd9f98f4f9e24c63a8fa02918dceab4503edf88e06537922caf86e85884408f3", "rules": [ @@ -587,12 +554,6 @@ module.exports = { "no-undef" ] }, - "apps/swp2clk/settings.js": { - "hash": "2d9de7ffdf171f6e7b058741046c8a326cf9d5dba651f52fcdb523214b08d626", - "rules": [ - "no-undef" - ] - }, "apps/sunclock/app.js": { "hash": "54f49294816e06907003a71289a8b79641b1cd082044fb22bb4c4b80f6845459", "rules": [ @@ -617,12 +578,6 @@ module.exports = { "no-undef" ] }, - "apps/spotrem/app.js": { - "hash": "35f3ee5371acde28427fd01e191ff58108d3d9e4db1a221dca081b7a7b9c3c77", - "rules": [ - "no-undef" - ] - }, "apps/speedalt/app.js": { "hash": "2c8a2c0d7f60a8c25ee86e943f59df8fb5816ceac00e9e077220227d8885b133", "rules": [ @@ -761,12 +716,6 @@ module.exports = { "no-undef" ] }, - "apps/owmweather/boot.js": { - "hash": "10fe98e871a7df3338fc764d62ac4db65c20c44774aad112f5faf26c7497f78e", - "rules": [ - "no-undef" - ] - }, "apps/openwind/app.js": { "hash": "91bfda771bd5cc3127ede3b52f5f088b733ac9e7fc2d8dff4f1d732e66a8af47", "rules": [ @@ -917,12 +866,6 @@ module.exports = { "no-undef" ] }, - "apps/infoclk/settings.js": { - "hash": "56adc3eff3cbc04dd08238ed7e559416ebbc7736c872070c757d70bf5f31b440", - "rules": [ - "no-undef" - ] - }, "apps/infoclk/app.js": { "hash": "27cc368eb1be14658db7fd482e78c4bc7673e2a1c68bc3a1a5f7c7e29915ca88", "rules": [ @@ -971,12 +914,6 @@ module.exports = { "no-undef" ] }, - "apps/gpssetup/gpssetup.js": { - "hash": "a63f670f4adf04895e6837270fcf19bd56f0a6d049cfb8e3ad8928c283d1bfd3", - "rules": [ - "no-undef" - ] - }, "apps/glbasic/glbasic.app.js": { "hash": "7d12a030d6f0ef69a0e5a9783229fd49c0a6a06bf751e3ac562145d2ce8350e9", "rules": [ From de9a364c9187861daa9f7d71a834db6e37cf6c35 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sat, 25 Jan 2025 18:21:45 +1100 Subject: [PATCH 043/135] Add Dense Clock app --- apps/denseclock/app-icon.js | 1 + apps/denseclock/app.js | 157 ++++++++++++++++++++++++++++++++++ apps/denseclock/app.png | Bin 0 -> 1569 bytes apps/denseclock/metadata.json | 14 +++ 4 files changed, 172 insertions(+) create mode 100644 apps/denseclock/app-icon.js create mode 100644 apps/denseclock/app.js create mode 100644 apps/denseclock/app.png create mode 100644 apps/denseclock/metadata.json diff --git a/apps/denseclock/app-icon.js b/apps/denseclock/app-icon.js new file mode 100644 index 0000000000..380a7b4ff8 --- /dev/null +++ b/apps/denseclock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mElwMBwf/AAeAAomYAomcAov4/E/w/jzngnEPg+AzninGOn+IznnnPOn+cCIIFBh4RBAoPPC4Xn/PP8efAo3jAoWPwAdCC4OB+AjC4BGEAEnH/ADBx/BGoN//0PwPx8E/AoOP/HnAoPPAoPmn0/ApHkn//5+DDoQFBEYPhAoX48YFE4/jAogvBAoWP8QFBFAKDBn0+geBwHwvwFBwYA=")) diff --git a/apps/denseclock/app.js b/apps/denseclock/app.js new file mode 100644 index 0000000000..62a40154e6 --- /dev/null +++ b/apps/denseclock/app.js @@ -0,0 +1,157 @@ +// FONTS + +/* + Share Tech Mono: https://fonts.google.com/specimen/Share+Tech+Mono + Converted with: https://www.espruino.com/Font+Converter +*/ + +Graphics.prototype.setFontShareTechMonoBig = function(scale) { + // Actual height 56 (55 - 0) + this.setFontCustom( + atob('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAAAAAAAB+AAAAAAAAB+AAAAAAAAB+AAAAAAAAB+AAAAAAAAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAAAAAAAHwAAAAAAAA/wAAAAAAAD/wAAAAAAAf/wAAAAAAB//gAAAAAAP/8AAAAAAA//wAAAAAAH/+AAAAAAA//4AAAAAAD//AAAAAAAf/8AAAAAAB//gAAAAAAP/8AAAAAAB//wAAAAAAH/+AAAAAAA//4AAAAAAD//AAAAAAAf/4AAAAAAB//gAAAAAAP/8AAAAAAA//wAAAAAAA/+AAAAAAAA/4AAAAAAAA/AAAAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf///4AAAAD/////AAAAP/////wAAAf/////4AAA//////8AAA//////8AAB/AAB/j+AAB+AAH/B+AAB8AAP8A+AAB8AA/4A+AAB8AB/gA+AAB8AH/AA+AAB8AP8AA+AAB8A/4AA+AAB8B/gAA+AAB+D/AAB+AAA//+AAP8AAA//////8AAAf/////4AAAP/////wAAAH/////gAAAB////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAeAAAfgAAAA+AAAfAAAAA+AAA/AAAAA+AAA+AAAAA+AAA+AAAAA+AAB+AAAAA+AAB8AAAAA+AAB//////+AAB//////+AAB//////+AAB//////+AAB//////+AAB//////+AAAAAAAAA+AAAAAAAAA+AAAAAAAAA+AAAAAAAAA+AAAAAAAAA+AAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAB8AAAAD+AAB8AAAAP+AAB8AAAAf+AAB8AAAB/+AAB8AAAD/+AAB8AAAH/+AAB8AAAf8+AAB8AAA/4+AAB8AAD/w+AAB8AAH/A+AAB+AAf+A+AAB+AA/4A+AAA////wA+AAA////gA+AAAf//+AA+AAAP//8AA+AAAH//wAA+AAAB/+AAA+AAAAAAAAA+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAA+AAB8AAAAA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AD8AA+AAB+AH+AB+AAA////gD+AAA//////8AAAf/////8AAAP//P//4AAAH/+H//wAAAA/4D//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAAAAP/wAAAAAAD//wAAAAAB///wAAAAAf///wAAAAH////wAAAB///+HwAAAB///gHwAAAB//wAHwAAAB/4AAHwAAAB+AAAHwAAABAAAAHwAAAAAAP///+AAAAAf///+AAAAAf///+AAAAAf///+AAAAAf///+AAAAAf///+AAAAAAAHwAAAAAAAAHwAAAAAAAAHwAAAAAAAAHwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB///wAA+AAB///wAA+AAB///wAA+AAB///wAA+AAB///wAA+AAB///wAA+AAB8AHwAA+AAB8AHwAA+AAB8AHwAA+AAB8AD4AA+AAB8AD4AA+AAB8AD4AB+AAB8AD+AD+AAB8AD///8AAB8AB///8AAB8AA///4AAB8AAf//wAAB4AAP//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////AAAAP/////gAAAf/////4AAAf/////4AAA//////8AAA/APgAD+AAB+APgAB+AAB8APgAA+AAB8APgAA+AAB8APgAA+AAB8APgAA+AAB8APgAA+AAB8APgAA+AAB8AHwAA+AAB8AHwAB+AAB8AH+AP8AAB8AH///8AAB8AD///4AAAAAB///wAAAAAA///gAAAAAAP/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAAAB8AAAAAAAAB8AAAAAAAAB8AAAAAAAAB8AAAAAOAAB8AAAAD+AAB8AAAAf+AAB8AAAD/+AAB8AAA//+AAB8AAH//+AAB8AB///gAAB8AP//8AAAB8D///AAAAB8f//4AAAAB////AAAAAB///wAAAAAB//+AAAAAAB//gAAAAAAB/8AAAAAAAB/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//AAAAD/8H//wAAAP//P//4AAAf/////8AAA//////8AAA//////+AAB/AP+AB+AAB8AD8AA+AAB8AD8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AB8AA+AAB8AD8AA+AAB+AH+AA+AAA////AD+AAA//////8AAAf/////8AAAP//P//4AAAH/+H//wAAAA/4D//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//4AAAAAAP//+AAAAAAf///AAAAAAf///AA+AAA////gA+AAB/AAfgA+AAB+AAPgA+AAB8AAPwA+AAB8AAHwA+AAB8AAHwA+AAB8AAHwA+AAB8AAHwA+AAB8AAHwA+AAB8AAHwB+AAB+AAHwB+AAA//////8AAA//////8AAAf/////4AAAP/////wAAAH/////gAAAB////+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB+AAB+AAAAB+AAB+AAAAB+AAB+AAAAB+AAB+AAAAB+AAB+AAAAB+AAB+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'), + 46, + 32, + 60+(scale<<8)+(1<<16) + ); + return this; +}; + +Graphics.prototype.setFontShareTechMono = function(scale) { + // Actual height 38 (37 - 0) + this.setFontCustom( + atob('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAAAAeAAAAAB4AAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABwAAAAAfAAAAAP8AAAAD/gAAAB/4AAAAf+AAAAP/AAAAH/gAAAB/4AAAA/8AAAAP/AAAAH/gAAAD/wAAAA/8AAAAP+AAAAA/gAAAADwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//4AAA///8AAP///8AA////wAHwAfvgAeAH4eABwA/A4AHAHwDgAcB+AOAB4PgB4AHj8AHgAf///+AA////wAB///+AAD///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAOAA8AAA4ADwAADgAeAAAOAB4AAA4AH////gAf///+AB////4AH////gAAAAAOAAAAAA4AAAAADgAAAAAOAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AHAAAfgAcAAD+ABwAA/4AHAAH/gAcAA/OABwAP44AHgB+DgAfAfwOAA//8A4AD//gDgAH/4AOAAH+AA4AAAAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAOABwBwA4AHAHADgAcAcAOABwBwA4AHAHADgAeA+AOAB8H4B4AD////gAP///8AAf+f/gAAPgf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPgAAAAP+AAAAP/4AAAf//gAAf//OAAB//A4AAH+ADgAAcAAOAAAAH//4AAA///gAAD//+AAAP//4AAAAHgAAAAAOAAAAAA4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/+ADgAf/4AOAB//gA4AH/+ADgAcA4AOABwDgA4AHAPADgAcA8AeABwD//4AHAH//AAcAP/4AAAAf/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA///8AAH///4AA////wAH////gAeB4AeABwHgA4AHAeADgAcB4AOABwHgA4AHAeAHgAcA//+ABwD//wAAAH/+AAAAP/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAABwAAAAAHAAAAgAcAAAeABwAAf4AHAAP/gAcAH/+ABwH/+AAHD//AAAf//AAAB//gAAAH/gAAAAfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB/gAAP+f/gAD////AAP///+AB//8B4AHgPgDgAcAcAOABwBwA4AHAHADgAcAcAOAB4D4B4AH////gAP///8AAf/f/wAAfw/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//AAAAH/+AAAA//8A4AH4HwDgAeAHgOABwAeA4AHAB4DgAcAHgOABwAeB4AHgB4HgAf///+AA////wAB///+AAB///gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AHgAAHgAeAAAeAB4AAB4AHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA='), + 46, + 22, + 40+(scale<<8)+(1<<16) + ); + return this; +}; + +Graphics.prototype.setFontShareTechMonoSmall = function(scale) { + // Actual height 23 (22 - 0) + this.setFontCustom( + atob('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/zgP/zgP/zgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPAAAPwAAPwAAAAAAPwAAPwAAPAAAAAAAAAAAAAAAAAAAAAAAAwYAP//gP//gP//gAwYAP//gP//gP//gAwYAAAAAAAAAAAAAAAAAB4AAD+BgH/Bg+HB8+DB8+DB8GD/gGB/AAAcAAAAAAAAAABAAH7AAP7AAMLAAMbAAP7AAHzfAAG/gAGxgAGxgAG/gAGfAAGAAAAAAAAAADz/AH//gP+DgMOBgMMBgMMBgMP/gAP/gAMAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAPwAAPwAAPgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//wP//8/AA+4AAGgAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAC4AAG/AB+P//8D//wAAAAAAAAAAAAAAAAAAAAAAAADAAADuAAB+AAP4AAfwAAP8AAB+AADsAADAAAAAAAAAAAAAAAAAAAADgAADgAADgAAf8AAf8AAf8AADgAADgAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAAD+AAD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAADgAADgAADgAADgAADgAADgAADgAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgAADgAADgAAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAeAAD8AAfwAB+AAP4AA/AAH8AAfgAA8AAAwAAAAAAAAAAAAAAAD/+AH//APB/gMDxgMHBgMeBgP//gH//AD/+AAAAAAAAAAAAAAAAAGAAgGABgOABgOABgP//gP//gAABgAABgAABgAAAAAAAAAAAAAAAAAABgMAHgMAPgMA9gMB5gOHxgH/BgD+BgAABgAAAAAAAAAAAAAAAAAAAAMCBgMGBgMGBgMHBgP/DgH//gD5/AAAAAAAAAAAAAAAAAAAAAAD4AA/4AP/4APwYAMAYAAP/gAP/gAAcAAAYAAAAAAAAAAAAAAAAAAAAAP+BgP+BgMGBgMGBgMHDgMH/gMD/AAAAAAAAAAAAAAAAAAAAAD/+AH//AP//gMMBgMMBgMOBgMP/gMH/AAD+AAAAAAAAAAAAAAAAAMAAAMAAAMADgMAfgMH/AM/4AP/AAPwAAGAAAAAAAAAAAAAAAAAAAD5/AH//gP/DgMHBgMGBgMHBgP/jgH//gD5/AAAAAAAAAAAAAAAAAD+AAH/AgP/hgMBhgMBhgMBhgP//gH//AD/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcDgAcDgAcDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeAcD+AcD4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAHgAAHgAAPwAAMwAAc4AAY4AA4cAA4cABwMAAAAAAAAAAAAAAAAAAMYAAMYAAMYAAMYAAMYAAMYAAMYAAMYAAMYAAAAAAAAAAAAAAAAABwMAA4cAA4cAAY4AAc4AAMwAAPwAAHgAAHgAAAAAAAAAAAAAAAAAAAAAMAAAMABgMDzgMHzgOeAAH8AAD4AAAAAAAAAAAAAAB/8AH//AP//gMHhgMf5gM/9gMwNgM/5gM/8gMAMAP/8AH/8AA/wAAAAAAADgAA/gAP/gD/4AP8YAPAYAP8YAD/4AAP/gAA/gAADgAAAAAAAAAAAAP//gP//gMGBgMGBgMGBgMGBgP/DgH//gD5/AAAAAAAAAAAAAAAAAB/8AH//AP//gOABgMABgMABgMABgMABgMABgAAAAAAAAAAAAAAAAP//gP//gMABgMABgMABgMABgOADgH//gH//AAAAAAAAAAAAAAAAAP//gP//gP//gMGBgMGBgMGBgMGBgMGBgMABgAAAAAAAAAAAAAAAAP//gP//gP//gMHAAMHAAMHAAMHAAMHAAMAAAAAAAAAAAAAAAAAAAD/+AH//AP//gMABgMDBgMDBgMD/gMD/gAD/gAAAAAAAAAAAAAAAAP//gP//gAHAAAHAAAHAAAHAAAHAAP//gP//gAAAAAAAAAAAAAAAAAAAAMABgMABgP//gP//gP//gMABgMABgAAAAAAAAAAAAAAAAAAAAAAAAAABgMABgMABgMABgMAHgP//AP/+AAAAAAAAAAAAAAAAAAAAAP//gP//gAPAAAfgAB/4ADw+APAfgOAHgIABgAAAAAAAAAAAAAAAAAAAAP//gP//gAABgAABgAABgAABgAABgAAAAAAAAAAAAAAAAP//gP//gPgAAP+AAB/gAAHwAB/gAP8AAPgAAP//gP//gAAAAAAAAAAAAP//gP//gPwAAP/AAA/8AAD/gAAPgP//gP//gAAAAAAAAAAAAA/8AH//AH//gOADgMABgMABgMABgOADgH//gH//AA/4AAAAAAAAAAAAAP//gP//gMDgAMDgAMDgAMDgAP/AAH/AAD+AAAAAAAAAAAAAAA/8AH//AH//gOADgMABgMABgMABgOADgH//gH//wA/4wAAAAAAAAH//gP//gP//gMDAAMDAAMDgAOD8AP//AH+PgB4DgAAAgAAAAAAAAAAAAD4AAH+BgP+BgOGBgMHBgMHBgMH/gMD/AAA+AAAAAAAAAAAAAMAAAMAAAMAAAMAAAP//gP//gP//gMAAAMAAAMAAAMAAAAAAAAAAAAAAAP//AP//gAADgAABgAABgAABgAADgP//gP//AAAAAAAAAAAAAMAAAP4AAP/wAA//AAB/gAAHgAD/gB/+AP/AAPwAAIAAAAAAAAAAAP/gAP//gAP/gAAfgAH+AAHwAAD/gAAfgAf/gP//gP8AAAAAAAAAAAAAgOADgPgPgH4+AB/4AAfwAB/4AH4/APgPgOADgAAAgAAAAAAAAMAAAPAAAPwAAD8AAA//gAP/gAf/gD8AAPwAAPAAAIAAAAAAAAAAAAAAAMADgMAPgMA/gMD5gMPhgM+BgP4BgPgBgOABgAAAAAAAAAAAAAAAAAAAAAAAA///+///+wAAGwAAGwAAGAAAAAAAAAAAAAAAAAAAAwAAA+AAAfgAAH8AAA/AAAP4AAB+AAAPwAAD8AAAeAAAGAAAAAAAAAAAAAAAAAAAAwAAGwAAGwAAG///+///+AAAAAAAAAAAAAAAAAAAAAAAAA4AAD4AAPwAAeAAAYAAAeAAAPwAAD4AAAYAAAAAAAAAAAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAGAAAAAAAAAAAAAAAAIAAAMAAAOAAAGAAACAAAAAAAAAAAAAAAAAAAAAAAAAOAAY/gAY/gAZxgAZxgAZxgAZxgAf/gAP/gAABgAAAgAAAAAAAAAAAAP//gP//gAcBgAYBgAYBgAYBgAcDgAf/gAP/AAAAAAAAAAAAAAAAAAAAAAP/AAf/gAYBgAYBgAYBgAYBgAYBgAAAAAAAAAAAAAAAAAAAAAP/AAf/gAcDgAYBgAYBgAYBgAYDgP//gP//gAAAAAAAAAAAAAAAAAP+AAf/gAf/gAYxgAYxgAYxgAfxgAPxgAHwAAAAAAAAAAAAAAAAAAYBgAYBgD//gP//gP//gMYBgMYBgMYBgMQAAAAAAAAAAAAAAAAAAAPwGAf/GAYfGAYfGAYfGAYfGAY7mAf7+Afx8AAAAAAAAAAAAAAAAP//gP//gAcAAAYAAAYAAAYAAAcAAAf/gAP/gAAAAAAAAAAAAAAAAAYAAAYAAAYAAMf/gOf/gMf/gAABgAABgAABgAAAAAAAAAAAAAAAAAAAAAAAGAYAGAYAGAYAGMf/+Of/+Mf/8AAAAAAAAAAAAAAAAAAAAP//gP//gP//gADwAAH8AAefAAcHgAYDgAQAgAAAAAAAAAAAAEAAAMAAAMAAAMAAAP//AP//gAADgAABgAABgAABgAAAgAAAAAAAAAf/gAf/gAYAAAYAAAf/gAf/gAf/gAYAAAYAAAf/gAP/gAAAAAAAAAAAAAf/gAf/gAcAAAYAAAYAAAYAAAcAAAf/gAP/gAAAAAAAAAAAAAAAAAP/AAf/gAcDgAYBgAYBgAYBgAcDgAf/gAP/AAAAAAAAAAAAAAAAAAf/+Af/+AcBgAYBgAYBgAYBgAcDgAf/gAP/AAAAAAAAAAAAAAAAAAP/AAf/gAcDgAYBgAYBgAYBgAYDgAf/+Af/+AAAAAAAAAAAAAAAAAYBgAYBgAf/gAf/gAcBgAYBgAYBgAYAAAYAAAAAAAAAAAAAAAAAAAAAAAPhgAfxgAZxgAYxgAYxgAY/gAYfAAAAAAAAAAAAAAAAAAAAAAYAAAYAAAYAAD//AD//gAYBgAYBgAYBgAYBgAAAAAAAAAAAAAAAAAf+AAf/gAf/gAABgAABgAABgAf/gAf/gAf/gAAAAAAAAAAAAAQAAAeAAAf4AAH/AAAfgAADgAAfgAH/AAf4AAeAAAQAAAAAAAAAAAfAAAf/AAD/gAAPgAD/gAH4AAH/gAAPgAD/gAf+AAfAAAAAAAAAAAAAAAYBgAcHgAfPAAH+AAD4AAH+AAfPgAcDgAQBgAAAAAAAAAAAAAQAAAeAAAfwGAH+GAA/uAAD+AAf8AH/AAf4AAeAAAQAAAAAAAAAAAAAAAABgAYHgAYPgAY/gAZ5gAfxgAfBgAeBgAYAAAAAAAAAAAAAAAAAAAAAAADgAADgAf//8/+/+4AAGwAAGwAAGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf//+///+f//+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAAGwAAG4AAG/+/+f//8ADgAADgAAAAAAAAAAAAAAAAAAAAAADgAADAAADAAADAAADAAADgAABgAADgAADAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'), + 32, + atob("DQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0NDQ0H"), + 24+(scale<<8)+(1<<16) + ); + return this; +}; + +{ + + // VARS + + let FONT_NAME = "ShareTechMono"; + let BIG_FONT_HEIGHT = 60; + //let NORMAL_FONT_HEIGHT = 40; + let SMALL_FONT_HEIGHT = 24; + + let timeDrawTimeout; + let infoDrawTimeout; + let lockState = Bangle.isLocked(); + let pressure; + + + + // LISTENERS + + Bangle.on('lock', function(isLocked) { + lockState = isLocked; + timeDraw(); + infoDraw(); + }); + + + + // DRAW FUNCTIONS + + let timeDraw = function() { + g.reset(); + g.clearRect(Bangle.appRect.x, Bangle.appRect.y, Bangle.appRect.x2, Bangle.appRect.y + BIG_FONT_HEIGHT); + + var date = new Date(); + var timeArray = [date.getHours().toString().padStart(2, "0"), + date.getMinutes().toString().padStart(2, "0")]; + if (!lockState) timeArray.push(date.getSeconds().toString().padStart(2, "0")); + var timeString = timeArray.join(":"); + g.setFontAlign(0, 0).setColor(g.theme.fg).setFont(FONT_NAME + (lockState ? "Big" : "")); + g.drawString(timeString, Bangle.appRect.x2/2, Bangle.appRect.y + BIG_FONT_HEIGHT/2); + + if (timeDrawTimeout) clearTimeout(timeDrawTimeout); + timeDrawTimeout = setTimeout(function() { + timeDrawTimeout = undefined; + timeDraw(); + }, (lockState ? 10000 - (Date.now() % 10000) : 1000 - (Date.now() % 1000))); // if locked, every clock's 10s, otherwise every 1s + }; + + let infoDraw = function() { + g.reset(); + + var date = new Date(); + var dateString = [date.getFullYear().toString().padStart(4,"0"), + (date.getMonth()+1).toString().padStart(2,"0"), + date.getDate().toString().padStart(2,"0")].join("-"); + + var tzOffset = -(date.getTimezoneOffset())/60; + var tzOffsetString = (tzOffset >= 0 ? "+" + tzOffset : tzOffset); + + var batteryString = (Bangle.isCharging() ? "+" : "") + E.getBattery() + "%"; + + var pressureString = (pressure ? pressure + "hPa" : "(hPa)"); + + var powerString = (E.getPowerUsage().total / 1000) + "mA"; + + var stepsString = Bangle.getHealthStatus("day").steps + "ST"; + + var bluetoothStatus = NRF.getSecurityStatus(); + var bluetoothString = (bluetoothStatus.connected ? bluetoothStatus.connected_addr.split(" ")[0].substr(-5) : "N/C"); + + var infoMatrix = [ + [dateString + tzOffsetString ], + [batteryString, pressureString], + [powerString ], + [stepsString, bluetoothString ] + ]; + + g.clearRect(Bangle.appRect.x, Bangle.appRect.y + BIG_FONT_HEIGHT, Bangle.appRect.x2, Bangle.appRect.y2); + g.setFontAlign(0, -1).setColor(g.theme.fg2).setFont(FONT_NAME+"Small"); + + infoMatrix.forEach((lineArray, lineNumber) => { + g.drawString(lineArray.join(" "), Bangle.appRect.x2/2, Bangle.appRect.y + BIG_FONT_HEIGHT + SMALL_FONT_HEIGHT*lineNumber); + }); + + Bangle.getPressure().then(baroValue => { pressure=Math.round(baroValue.pressure); }); + + if (infoDrawTimeout) clearTimeout(infoDrawTimeout); + infoDrawTimeout = setTimeout(function() { + infoDrawTimeout = undefined; + infoDraw(); + }, (lockState ? 60000 : 10000)); // if locked, a minute from now, otherwise in 10s + }; + + + + // DRAW CALLS + + g.clear(); + + Bangle.setUI({ + mode: "clock", + remove: function() { + if (timeDrawTimeout) clearTimeout(timeDrawTimeout); + timeDrawTimeout = undefined; + if (infoDrawTimeout) clearTimeout(infoDrawTimeout); + infoDrawTimeout = undefined; + + delete Graphics.prototype.setFontShareTechMono; + delete Graphics.prototype.setFontShareTechMonoBig; + delete Graphics.prototype.setFontShareTechMonoSmall; + }}); + + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + timeDraw(); + infoDraw(); +} diff --git a/apps/denseclock/app.png b/apps/denseclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e395fcf8dab8c375e49b2d5a3ee61ab18999aa49 GIT binary patch literal 1569 zcmV++2HyFJP)EX>4Tx04R}tkv&MmP!xqv8>J!@K|828WT;MdQ4z;lg(6f4wL+^7CNKSiCJjl7 zi=*ILaPVib>fqw6tAnc`2>yV$3r>nIQsR9{p+$@r9`ED4dk*j22Lu}xrdeHaK+|nA zolJli&xt2Yx*+i**A;ArbawX991=)@`G8A zRnA+SwMvb(?#W*m&g(17T&FdPBo?s*2_h8KP(}qdVzld|SV+@(!pA@2`XzEHZ+(5ySo_p#$NPXOT=xYFDHY6F=4B)#6& zqDMggHgIv>)|5Tqat9cCGGtSBC4pA3PypV~=$mrD;4RR*=FP2jj?)JqL$gZV00)P_ zc#*Q#ecs*EIk$g%TJ!q>9cprf@^f1Q00006VoOIv0RI600RN!9r;`8x010qNS#tmY zE+YT{E+YYWr9XB6000McNliru=>Zu7DgtiJ!V&-g02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00a3+L_t(&-tC!hXx3E}$3H!7uG!L26BCU{39&Xqos1B{ z#_UD2@GlPbLIOpiB1QZM>I*57FvQ3|IHTn&YnAq*cj_of){Ew!LM6n;h*h*~vN`{4 z&wSzc%JK5Mzdg^hIVb+U@bJ68bI6j*I&y+9jq0@w>& z9qvl30{Q~KUx5+BdGaameY1XF>b(@0_aIroZmnygtsBmh&kNA|fF7X0+d?CNw}IKf zIG_VK4txw;7f%)NzRpf3Fa~G`nt&ZZw3_X%8h|svRPoFKW&ppaf03T8 zz-K^O?@d|A&Da7n4Bs@-o-?$H2n&o7ZKR>q7#WSCHN-4jtlU%<7RWd4AGHrp2l^e{ zirz4^BGdj|&&9z1a@*@Y?-(mLmE++r0!9N*4A6;e16tHBmfPM2EYDPKUXFs-8o>_d zav0|iU@}k+JPm9BW&&>j`!bQ6*H4(?LJRu@I0~E`Bv*bzVGF>kQednX+63kL3RLMi zNe2($A3fU)-%8IL-fd@hNZY-!qHRl?=M)w&%1 z27U&11}YNsbXh$szuW*E9)SG0zzX0Q(Pnw!1G?C1Bfh_LU(`q3a%Unc5~~9@;>H{% zKN7eQF;-N3wml$sgR{Wvz)NaR1m0BpE!Bnq9#f3+IB*L1PF5>dK0Fq{#5SqAapwA5rb~1Czkw>R{MV~0 zT3QEb5x2|lOAX)o2tgGpLUo(ciN!3S5SU_Um6G!VaMLWXa~6d; zd=XfwQ|iAE=x>RUYwwOD0iM^gRiFUastMf$E~*q*ID`sxYTRW>GLaxbg8PqKe2H?b Tdy8}$00000NkvXXu0mjfaLv*} literal 0 HcmV?d00001 diff --git a/apps/denseclock/metadata.json b/apps/denseclock/metadata.json new file mode 100644 index 0000000000..fa8c620a29 --- /dev/null +++ b/apps/denseclock/metadata.json @@ -0,0 +1,14 @@ +{ "id": "denseclock", + "name": "Dense Clock", + "shortName":"Dense Clock", + "version":"0.01", + "description": "A clockface dense with text-only information. Switches between showing seconds and minutes when unlocked/locked, in the interest of saving power.", + "icon": "app.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "storage": [ + {"name":"denseclock.app.js","url":"app.js"}, + {"name":"denseclock.img","url":"app-icon.js","evaluate":true} + ] +} From 3425470bcc202d11675bb8f7de49390a900fd0b9 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sat, 25 Jan 2025 18:32:11 +1100 Subject: [PATCH 044/135] denseclock: add screenshots --- apps/denseclock/metadata.json | 4 ++++ apps/denseclock/screenshot_locked.png | Bin 0 -> 3535 bytes apps/denseclock/screenshot_unlocked.png | Bin 0 -> 3590 bytes 3 files changed, 4 insertions(+) create mode 100644 apps/denseclock/screenshot_locked.png create mode 100644 apps/denseclock/screenshot_unlocked.png diff --git a/apps/denseclock/metadata.json b/apps/denseclock/metadata.json index fa8c620a29..d5bcd3cd53 100644 --- a/apps/denseclock/metadata.json +++ b/apps/denseclock/metadata.json @@ -10,5 +10,9 @@ "storage": [ {"name":"denseclock.app.js","url":"app.js"}, {"name":"denseclock.img","url":"app-icon.js","evaluate":true} + ], + "screenshots": [ + {"url":"screenshot_locked.png"}, + {"url":"screenshot_unlocked.png"} ] } diff --git a/apps/denseclock/screenshot_locked.png b/apps/denseclock/screenshot_locked.png new file mode 100644 index 0000000000000000000000000000000000000000..61a05ca446c9a44b1d72c6c66739fa70e1149029 GIT binary patch literal 3535 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 literal 0 HcmV?d00001 diff --git a/apps/denseclock/screenshot_unlocked.png b/apps/denseclock/screenshot_unlocked.png new file mode 100644 index 0000000000000000000000000000000000000000..f1af09cbacbe67306b90ec6c26ff191aa57ff786 GIT binary patch literal 3590 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 H{O$h(BRQD5 literal 0 HcmV?d00001 From 26258e4db92cef7e7314e9c5f1f7f68c20aa02a3 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sat, 25 Jan 2025 18:51:37 +1100 Subject: [PATCH 045/135] denseclock: bump version --- apps/denseclock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/denseclock/metadata.json b/apps/denseclock/metadata.json index d5bcd3cd53..515e4661c2 100644 --- a/apps/denseclock/metadata.json +++ b/apps/denseclock/metadata.json @@ -1,7 +1,7 @@ { "id": "denseclock", "name": "Dense Clock", "shortName":"Dense Clock", - "version":"0.01", + "version":"0.02", "description": "A clockface dense with text-only information. Switches between showing seconds and minutes when unlocked/locked, in the interest of saving power.", "icon": "app.png", "type": "clock", From f6e2eff9da81c0affc73d7f1a948547f0662b119 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sat, 25 Jan 2025 19:22:29 +1100 Subject: [PATCH 046/135] denseclock: (retroactive) changelog --- apps/denseclock/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/denseclock/ChangeLog diff --git a/apps/denseclock/ChangeLog b/apps/denseclock/ChangeLog new file mode 100644 index 0000000000..2e09e5bb28 --- /dev/null +++ b/apps/denseclock/ChangeLog @@ -0,0 +1,2 @@ +0.01: Begin rewrite from old code. +0.02: Changed visuals: uA > mA, info order, battery state indication From a24ce3f83c0ba2f0064d37f7b8fbf9e9ad62c75a Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sat, 25 Jan 2025 21:19:16 +1100 Subject: [PATCH 047/135] denseclock: app icon update blurred inverted background to improve readability note in changelog --- apps/denseclock/ChangeLog | 1 + apps/denseclock/app-icon.js | 2 +- apps/denseclock/app.png | Bin 1569 -> 4198 bytes apps/denseclock/metadata.json | 2 +- 4 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/denseclock/ChangeLog b/apps/denseclock/ChangeLog index 2e09e5bb28..7ae520fa5f 100644 --- a/apps/denseclock/ChangeLog +++ b/apps/denseclock/ChangeLog @@ -1,2 +1,3 @@ 0.01: Begin rewrite from old code. 0.02: Changed visuals: uA > mA, info order, battery state indication +0.03: Update app icon diff --git a/apps/denseclock/app-icon.js b/apps/denseclock/app-icon.js index 380a7b4ff8..b8a0761f89 100644 --- a/apps/denseclock/app-icon.js +++ b/apps/denseclock/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mElwMBwf/AAeAAomYAomcAov4/E/w/jzngnEPg+AzninGOn+IznnnPOn+cCIIFBh4RBAoPPC4Xn/PP8efAo3jAoWPwAdCC4OB+AjC4BGEAEnH/ADBx/BGoN//0PwPx8E/AoOP/HnAoPPAoPmn0/ApHkn//5+DDoQFBEYPhAoX48YFE4/jAogvBAoWP8QFBFAKDBn0+geBwHwvwFBwYA=")) +require("heatshrink").decompress(atob("mEwwcBkmSpIC/AS0nwEHCh5yBggROgP4jgROh1ICKWT4Hkz0AC4NPgFypPgAQIRDyBLBCIMAiVAgECpAGBCInwn4RBg4dBoH/yV4j+ACI0Dz05kARB8gRJgARFgYRBgEB5IRKBwICCI4/8CIdJ/kCGoP+CIMPUIIRBkgRIYop9DgJHCPowDBTwUAyAREiSkBCITCOAX4CuwE5kmT4D1BBYSMByShBhwRCgEkWYQRDUIIRCUIWfEALXBCIsDCIMf+QICvEECIILBBAV5CIUcBAYRFpEEBYIRKnARIgFyHwfk+PAGogREgQIBPQMk+EACI9J/hrCyUHCIMHCJEnwAIByEBCIJrFCI/wWYIROwP5CIShECI7FBgjFDPoTFBgTXGBYICCCI6PDAX4C/ARoA=")) diff --git a/apps/denseclock/app.png b/apps/denseclock/app.png index e395fcf8dab8c375e49b2d5a3ee61ab18999aa49..4f27b473ca189d0d1457b960d08599b436dfa66d 100644 GIT binary patch delta 4103 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 IM6N<$f^!zRApigX diff --git a/apps/denseclock/metadata.json b/apps/denseclock/metadata.json index 515e4661c2..c361313ffd 100644 --- a/apps/denseclock/metadata.json +++ b/apps/denseclock/metadata.json @@ -1,7 +1,7 @@ { "id": "denseclock", "name": "Dense Clock", "shortName":"Dense Clock", - "version":"0.02", + "version":"0.03", "description": "A clockface dense with text-only information. Switches between showing seconds and minutes when unlocked/locked, in the interest of saving power.", "icon": "app.png", "type": "clock", From 25d782e91c405fae98642744c23da93fd0102abe Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Tue, 2 Jul 2024 00:43:29 +0200 Subject: [PATCH 048/135] spotrem: refactor to handle ui all inside setUI and fix lint warnings --- apps/spotrem/ChangeLog | 1 + apps/spotrem/app.js | 15 ++++----------- apps/spotrem/metadata.json | 2 +- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/apps/spotrem/ChangeLog b/apps/spotrem/ChangeLog index 723fbd2d7f..f214545514 100644 --- a/apps/spotrem/ChangeLog +++ b/apps/spotrem/ChangeLog @@ -11,3 +11,4 @@ when fastloading. 0.10: Some refactoring to shorten the code. 0.11: Further refactoring to shorten the code. Fixed search and play that was broken in v0.10. 0.12: Fix some warnings from the linter. +0.13: Move ui-handlers inside setUI-call. diff --git a/apps/spotrem/app.js b/apps/spotrem/app.js index 4abc5392c8..bbe706b935 100644 --- a/apps/spotrem/app.js +++ b/apps/spotrem/app.js @@ -14,7 +14,6 @@ let gfx = function() { widgetUtils.hide(); R = Bangle.appRect; const MARIGIN = 8; - // g.drawString(str, x, y, solid) g.clearRect(R); g.reset(); @@ -100,23 +99,17 @@ let swipeHandler = function(LR, _) { // Navigation input on the main layout let setUI = function() { -// Bangle.setUI code from rigrig's smessages app for volume control: https://git.tubul.net/rigrig/BangleApps/src/branch/personal/apps/smessages/app.js Bangle.setUI( {mode : "updown", - remove : ()=>{ - Bangle.removeListener("touch", touchHandler); - Bangle.removeListener("swipe", swipeHandler); - clearWatch(buttonHandler); - widgetUtils.show(); - } + touch: touchHandler, + swipe: swipeHandler, + btn: ()=>load(), + remove : ()=>widgetUtils.show(), }, ud => { if (ud) Bangle.musicControl(ud>0 ? "volumedown" : "volumeup"); } ); - Bangle.on("touch", touchHandler); - Bangle.on("swipe", swipeHandler); - let buttonHandler = setWatch(()=>{load();}, BTN, {edge:'falling'}); }; // Get back to the main layout diff --git a/apps/spotrem/metadata.json b/apps/spotrem/metadata.json index f25b0e42b3..8ecc0d867c 100644 --- a/apps/spotrem/metadata.json +++ b/apps/spotrem/metadata.json @@ -1,7 +1,7 @@ { "id": "spotrem", "name": "Remote for Spotify", - "version": "0.12", + "version": "0.13", "description": "Control spotify on your android device.", "readme": "README.md", "type": "app", From 70358008fd85ac023348b0c56851a6fedabc1056 Mon Sep 17 00:00:00 2001 From: David Volovskiy Date: Sun, 2 Feb 2025 09:35:49 -0500 Subject: [PATCH 049/135] Added fixed on not reading defaults in counter2 settings --- apps/counter2/ChangeLog | 1 + apps/counter2/metadata.json | 2 +- apps/counter2/settings.js | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/counter2/ChangeLog b/apps/counter2/ChangeLog index 58eacf6132..d952c505b1 100644 --- a/apps/counter2/ChangeLog +++ b/apps/counter2/ChangeLog @@ -2,3 +2,4 @@ 0.02: Added Settings & readme 0.03: Fix lint warnings 0.04: Fix lint warnings +0.05: Fix on not reading counter defaults in Settings diff --git a/apps/counter2/metadata.json b/apps/counter2/metadata.json index 400abf2679..04b00487f1 100644 --- a/apps/counter2/metadata.json +++ b/apps/counter2/metadata.json @@ -1,7 +1,7 @@ { "id": "counter2", "name": "Counter2", - "version": "0.04", + "version": "0.05", "description": "Dual Counter", "readme":"README.md", "icon": "counter2-icon.png", diff --git a/apps/counter2/settings.js b/apps/counter2/settings.js index f97d49ad32..d74d9269fc 100644 --- a/apps/counter2/settings.js +++ b/apps/counter2/settings.js @@ -18,7 +18,7 @@ "": { "title": "Counter2" }, "< Back": () => back(), 'Default C1': { - value: settings[0], + value: settings.max0, min: -99, max: 99, onchange: v => { settings.max0 = v; @@ -26,7 +26,7 @@ } }, 'Default C2': { - value: settings[2], + value: settings.max1, min: -99, max: 99, onchange: v => { settings.max1 = v; From 70d3c0fcb5522bd9d056f579d113d639b870d101 Mon Sep 17 00:00:00 2001 From: Le~Kat Date: Fri, 31 Jan 2025 18:25:02 -0500 Subject: [PATCH 050/135] added a settings page to multidice --- apps/multidice/ChangeLog | 5 ++++ apps/multidice/app.js | 57 ++++++++++++++++++++++++++--------- apps/multidice/metadata.json | 6 ++-- apps/multidice/settings.js | 58 ++++++++++++++++++++++++++++++++++++ 4 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 apps/multidice/settings.js diff --git a/apps/multidice/ChangeLog b/apps/multidice/ChangeLog index cb0cce2aab..ca17e18335 100644 --- a/apps/multidice/ChangeLog +++ b/apps/multidice/ChangeLog @@ -30,3 +30,8 @@ 1.28: increased vibration strength, added some comments, & some QOL 1.29: changed image 1.30: changed image, again +1.40: added various settings for controlling when & how to throw dice +1.41: fixed dumb mistake +1.42: okay maby I should've read the *whole* error log +1.43: playing whackamole with ESLint +1.44: fixed (?) settings app diff --git a/apps/multidice/app.js b/apps/multidice/app.js index 53f67e21e7..fe869626ae 100644 --- a/apps/multidice/app.js +++ b/apps/multidice/app.js @@ -1,12 +1,20 @@ -var menu = true; // default to have the selection menu open +var settings = Object.assign({ + vibrate: true, + shake: true, + screen: false, + shake_timeout: 200, + shake_duration: 100, +}, require('Storage').readJSON("multidice.json", true) || {}); + +var menu = true; // defaults to having the menu open const DICE_ARRAY = [0, 4, 6, 8, 10, 12, 20, 100]; // 0 means nothing selected const SELECTION_ARRAY = [6, 0, 0, 0, 0, 0, 0, 0]; // default to selecting a single d20 // function to draw the selection menu function drawMenu() { - stringArr = new Array ("", "", "", "", "", "", "", ""); - for (i = 0; i < 8; i++) { + var stringArr = new Array ("", "", "", "", "", "", "", ""); + for (var i = 0; i < 8; i++) { if (SELECTION_ARRAY [i] != 0) { @@ -41,6 +49,7 @@ function touchHandler (button, xy) { return; } + var selection; if (xy.x <= 87) { // left if (xy.y <= 43) { // first @@ -84,15 +93,30 @@ function touchHandler (button, xy) { drawMenu(); } +var shaken = false; +var last_shaken = null; function accelHandler (xyz) { + // if the screen should be on *and* it isn't, return + if (settings.screen && ! Bangle.isBacklightOn()) { + + return; + } + if (xyz.diff >= 0.3) { - menu = false; - mutex (rollDice).catch (() => { + shaken = true; + last_shaken = Date.now(); + } else if (shaken && last_shaken !== null) { + + if (Date.now() - last_shaken > settings.shake_timeout) { - return; // not necessary, but prevents spamming the logs - }); + last_shaken = null; + shaken = false; + menu = false; + + mutex (rollDice).catch (() => { return; }); + } } } @@ -123,8 +147,8 @@ function mutex (functionRef) { // function to roll all selected dice, and display them function rollDice() { - resultsArr = new Uint8Array (8); - for (i = 0; i < 8; i++) { + var resultsArr = new Uint8Array (8); + for (var i = 0; i < 8; i++) { if (SELECTION_ARRAY [i] != 0) { @@ -135,7 +159,7 @@ function rollDice() { g.clear(); g.setFont ("Vector", 40); - for (i = 0; i < 4; i++) { + for (var i = 0; i < 4; i++) { if (SELECTION_ARRAY [i] != 0) { @@ -143,7 +167,7 @@ function rollDice() { } } - for (i = 4; i < 8; i++) { + for (var i = 4; i < 8; i++) { if (SELECTION_ARRAY [i] != 0) { @@ -157,14 +181,19 @@ function rollDice() { // triggers the vibration, then pauses before returning function vibrate() { + if (! settings.vibrate) { + + return (Promise.resolve (0)); + } + return new Promise ((resolve, reject) => { - return Bangle.buzz (50, 1).then ((value) => { + return Bangle.buzz (settings.shake_duration, 1).then ((value) => { setTimeout (() => { resolve (value); - }, 200); + }, 2 * settings.shake_duration + settings.shake_timeout); }); }); } @@ -177,7 +206,7 @@ function random (max) { drawMenu(); Bangle.on ('touch', touchHandler); -Bangle.on ('accel', accelHandler); +if (settings.shake) { Bangle.on ('accel', accelHandler); } setWatch (function() { menu = false; diff --git a/apps/multidice/metadata.json b/apps/multidice/metadata.json index 304c789e45..dd69410608 100644 --- a/apps/multidice/metadata.json +++ b/apps/multidice/metadata.json @@ -1,7 +1,7 @@ { "id": "multidice", "name": "multiple dice roller", "shortName":"multidice", - "version":"1.30", + "version":"1.44", "description": "roll anywhere from 1-8 dice at the same time", "icon": "app.png", "tags": "tool,game", @@ -10,6 +10,8 @@ "allow_emulator": true, "storage": [ {"name":"multidice.app.js","url":"app.js"}, + {"name":"multidice.settings.js","url":"settings.js"}, {"name":"multidice.img","url":"app-icon.js","evaluate":true} - ] + ], + "data": [{"name": "multidice.json"}] } diff --git a/apps/multidice/settings.js b/apps/multidice/settings.js new file mode 100644 index 0000000000..446a785e10 --- /dev/null +++ b/apps/multidice/settings.js @@ -0,0 +1,58 @@ +(function(back) { + var settings = Object.assign({ + vibrate: true, + shake: true, + screen: false, + shake_timeout: 200, + shake_duration: 100, + }, require('Storage').readJSON("multidice.json", true) || {}); + + function writeSettings() { + require('Storage').writeJSON("multidice.json", settings); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "multi dice roll" }, + "< Back" : () => back(), + 'vibrate on roll?': { + value: !!settings.vibrate, + onchange: v => { + settings.vibrate = v; + writeSettings(); + } + }, + 'allow shaking?': { + value: !!settings.shake, + onchange: v => { + settings.shake = v; + writeSettings(); + } + }, + 'screen on to shake?': { + value: !!settings.screen, + onchange: v => { + settings.screen = v; + writeSettings(); + } + }, + 'shake timeout': { + value: settings.shake_timeout / 5, + min: 10, max: 40, + format: v => v * 5, + onchange: v => { + settings.shake_timeout = v * 5; + writeSettings(); + } + }, + 'shake duration': { + value: settings.shake_duration / 5, + min: 10, max: 40, + format: v => v * 5, + onchange: v => { + settings.shake_duration = v * 5; + writeSettings(); + } + }, + }); +}) From ab61680ae5d09340751e27c42f99bcc625f1e004 Mon Sep 17 00:00:00 2001 From: Randy Heydon Date: Fri, 31 Jan 2025 21:28:30 -0500 Subject: [PATCH 051/135] bwclk & bwclklite: Support 12-hour time format. This modifies how the time string is generated so it respects the system's locale settings, specifically for 12-hour time. This is done with the locale package, which also simplifies some of the string handling since the package creates a complete time string. Note this does not add any display of AM/PM, but neither do any other clock faces. --- apps/bwclk/ChangeLog | 3 ++- apps/bwclk/app.js | 8 +++----- apps/bwclk/metadata.json | 2 +- apps/bwclklite/ChangeLog | 3 ++- apps/bwclklite/app.js | 8 +++----- apps/bwclklite/metadata.json | 2 +- 6 files changed, 12 insertions(+), 14 deletions(-) diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 191bb51e5b..74b80b73bf 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -32,4 +32,5 @@ clkinfo.addInteractive that would cause ReferenceError. 0.30: Use widget_utils 0.31: Use clock_info module as an app 0.32: Make the border of the clock_info box extend all the way to the right of the screen. -0.33: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749) \ No newline at end of file +0.33: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749) +0.34: Support 12-hour time format diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index fdb82df73f..5053dafbbc 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -239,11 +239,9 @@ let drawTime = function() { var y = y1; var date = new Date(); - var hours = String(date.getHours()); - var minutes = date.getMinutes(); - minutes = minutes < 10 ? String("0") + minutes : minutes; - var colon = settings.hideColon ? "" : ":"; - var timeStr = hours + colon + minutes; + var timeStr = locale.time(date, 1); + if (settings.hideColon) + timeStr = timeStr.replace(":", ""); // Set y coordinates correctly y += parseInt((H - y)/2) + 5; diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index d4091c2fe7..de84ba9473 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclk", "name": "BW Clock", - "version": "0.33", + "version": "0.34", "description": "A very minimalistic clock.", "readme": "README.md", "icon": "app.png", diff --git a/apps/bwclklite/ChangeLog b/apps/bwclklite/ChangeLog index c68c62edcc..bba66928ba 100644 --- a/apps/bwclklite/ChangeLog +++ b/apps/bwclklite/ChangeLog @@ -35,4 +35,5 @@ clkinfo.addInteractive that would cause ReferenceError. Remove invertion of theme as this doesn'twork very well with fastloading. Do an quick inital fillRect on theclock info area. 0.33: Make the border of the clock_info box extend all the way to the right of the screen. -0.34: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749) \ No newline at end of file +0.34: Fix issue rendering ClockInfos with for fg+bg color set to the same (#2749) +0.35: Support 12-hour time format diff --git a/apps/bwclklite/app.js b/apps/bwclklite/app.js index 05f61ec58c..794b39aa9d 100644 --- a/apps/bwclklite/app.js +++ b/apps/bwclklite/app.js @@ -199,11 +199,9 @@ let drawTime = function() { let y = y1; let date = new Date(); - let hours = String(date.getHours()); - let minutes = date.getMinutes(); - minutes = minutes < 10 ? String("0") + minutes : minutes; - let colon = settings.hideColon ? "" : ":"; - let timeStr = hours + colon + minutes; + var timeStr = locale.time(date, 1); + if (settings.hideColon) + timeStr = timeStr.replace(":", ""); // Set y coordinates correctly y += parseInt((H - y)/2) + 5; diff --git a/apps/bwclklite/metadata.json b/apps/bwclklite/metadata.json index f8dffdca92..14af7131c6 100644 --- a/apps/bwclklite/metadata.json +++ b/apps/bwclklite/metadata.json @@ -1,7 +1,7 @@ { "id": "bwclklite", "name": "BW Clock Lite", - "version": "0.34", + "version": "0.35", "description": "A very minimalistic clock. This version of BW Clock is quicker at the cost of the custom font.", "readme": "README.md", "icon": "app.png", From bb5a05a2b11198446f52a3e044891feb9d78d3f6 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 3 Feb 2025 12:17:23 +0000 Subject: [PATCH 052/135] 0.15: Fix error when displaying a category with only one clockinfo (fix #3728) --- apps/clock_info/ChangeLog | 3 ++- apps/clock_info/lib.js | 2 +- apps/clock_info/metadata.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/clock_info/ChangeLog b/apps/clock_info/ChangeLog index 7d20438996..cf7da2fa13 100644 --- a/apps/clock_info/ChangeLog +++ b/apps/clock_info/ChangeLog @@ -12,4 +12,5 @@ 0.11: Prepend swipe listener if possible 0.12: Add drawFilledImage to allow drawing icons with a separately coloured middle 0.13: Cache loaded ClockInfos so if we have clockInfoWidget and a clock, we don't load them twice (saves ~300ms) -0.14: Check for .clkinfocache and use that if exists (from boot 0.64) \ No newline at end of file +0.14: Check for .clkinfocache and use that if exists (from boot 0.64) +0.15: Fix error when displaying a category with only one clockinfo (fix #3728) diff --git a/apps/clock_info/lib.js b/apps/clock_info/lib.js index 0e20ab8555..cb6a19abb3 100644 --- a/apps/clock_info/lib.js +++ b/apps/clock_info/lib.js @@ -283,7 +283,7 @@ exports.addInteractive = function(menu, options) { //in the worst case we come back to 0 } while(menu[options.menuA].items.length==0); // When we change, ensure we don't display the same thing as another clockinfo if we can avoid it - while ((options.menuB < menu[options.menuA].items.length) && + while ((options.menuB < menu[options.menuA].items.length-1) && exports.clockInfos.some(m => (m!=options) && m.menuA==options.menuA && m.menuB==options.menuB)) options.menuB++; } diff --git a/apps/clock_info/metadata.json b/apps/clock_info/metadata.json index 1d9a73ce3a..9e9079c28b 100644 --- a/apps/clock_info/metadata.json +++ b/apps/clock_info/metadata.json @@ -1,7 +1,7 @@ { "id": "clock_info", "name": "Clock Info Module", "shortName": "Clock Info", - "version":"0.14", + "version":"0.15", "description": "A library used by clocks to provide extra information on the clock face (Altitude, BPM, etc)", "icon": "app.png", "type": "module", From 914145d4131e8fe094d2786a7bc92364a12baa4e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 3 Feb 2025 12:17:39 +0000 Subject: [PATCH 053/135] fix generator script --- apps/icons/gen/generate.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/icons/gen/generate.js b/apps/icons/gen/generate.js index b91eedcdcd..fd97a1ce9d 100755 --- a/apps/icons/gen/generate.js +++ b/apps/icons/gen/generate.js @@ -7,7 +7,7 @@ /* eslint-env node */ -var imageconverter = require("../../../webtools/imageconverter.js").imageconverter; +var imageconverter = require("../../../webtools/imageconverter.js"); var icons = JSON.parse(require("fs").readFileSync(__dirname+"/icon_names.json")); const imgOptions = { mode : "1bit", From 24040169517474103f83d804b58ae1ccad746f63 Mon Sep 17 00:00:00 2001 From: Randy Heydon Date: Tue, 28 Jan 2025 20:37:58 -0500 Subject: [PATCH 054/135] calendar: read events synchronized from Gadgetbridge This is a partial fix for feature request #3707. This allows synchronized events (stored in android.calendar.json) to be shown in the app, alongside the manually entered events and alarm events that are already shown. Note only date/time and event title are currently used; other information available in the synchronized events (e.g. duration, description) are ignored. --- apps/calendar/ChangeLog | 1 + apps/calendar/calendar.js | 6 ++++++ apps/calendar/metadata.json | 2 +- 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/apps/calendar/ChangeLog b/apps/calendar/ChangeLog index 9a4f814911..d737ec6d4f 100644 --- a/apps/calendar/ChangeLog +++ b/apps/calendar/ChangeLog @@ -19,3 +19,4 @@ Display Widgets in menus 0.17: Load holidays before events so the latter is not overpainted 0.18: Minor code improvements +0.19: Read events synchronized from Gadgetbridge diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index e140ff5766..da5a00a6ec 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -60,6 +60,12 @@ const loadEvents = () => { date.setSeconds(time.s); return {date: date, msg: a.msg, type: "e"}; })); + // all events synchronized from Gadgetbridge + events = events.concat((require("Storage").readJSON("android.calendar.json",1) || []).map(a => { + // timestamp is in seconds, Date requires milliseconds + const date = new Date(a.timestamp * 1000); + return {date: date, msg: a.title, type: "e"}; + })); }; const loadSettings = () => { diff --git a/apps/calendar/metadata.json b/apps/calendar/metadata.json index 468bceabb8..5f5f21b27a 100644 --- a/apps/calendar/metadata.json +++ b/apps/calendar/metadata.json @@ -1,7 +1,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.18", + "version": "0.19", "description": "Monthly calendar, displays holidays uploaded from the web interface and scheduled events.", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], From 7bfd03702282eb1676cb083282f9e546555e54f8 Mon Sep 17 00:00:00 2001 From: Randy Heydon Date: Wed, 29 Jan 2025 19:30:43 -0500 Subject: [PATCH 055/135] Fix lint warnings. Loop variables had warnings for being undefinied. Added the "let" keyword where they are initialized. --- apps/calendar/calendar.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index da5a00a6ec..ea06b70e85 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -227,8 +227,8 @@ const drawCalendar = function(date) { }, []); let i = 0; g.setFont("8x12", fontSize); - for (y = 0; y < rowN - 1; y++) { - for (x = 0; x < colN; x++) { + for (let y = 0; y < rowN - 1; y++) { + for (let x = 0; x < colN; x++) { i++; const day = days[i]; const curMonth = day < 15 ? month+1 : day < 50 ? month-1 : month; From c900f88908ab487a189204573835b3db9e7d2b02 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Mon, 13 May 2024 22:42:21 +0200 Subject: [PATCH 056/135] mysetup: set up watch to my preference --- apps/mysetup/ChangeLog | 2 + apps/mysetup/README.md | 29 ++++++++++++ apps/mysetup/app-icon.js | 1 + apps/mysetup/app.png | Bin 0 -> 1620 bytes apps/mysetup/autoreset.json | 1 + apps/mysetup/backswipe.json | 1 + apps/mysetup/dtlaunch.json | 1 + apps/mysetup/fastload.json | 1 + apps/mysetup/lightswitch.json | 1 + apps/mysetup/messages.settings.json | 1 + apps/mysetup/metadata.json | 68 ++++++++++++++++++++++++++++ apps/mysetup/quicklaunch.json | 1 + apps/mysetup/recorder.json | 1 + apps/mysetup/setting.json | 1 + apps/mysetup/widbt_notify.json | 1 + 15 files changed, 110 insertions(+) create mode 100644 apps/mysetup/ChangeLog create mode 100644 apps/mysetup/README.md create mode 100644 apps/mysetup/app-icon.js create mode 100644 apps/mysetup/app.png create mode 100644 apps/mysetup/autoreset.json create mode 100644 apps/mysetup/backswipe.json create mode 100644 apps/mysetup/dtlaunch.json create mode 100644 apps/mysetup/fastload.json create mode 100644 apps/mysetup/lightswitch.json create mode 100644 apps/mysetup/messages.settings.json create mode 100644 apps/mysetup/metadata.json create mode 100644 apps/mysetup/quicklaunch.json create mode 100644 apps/mysetup/recorder.json create mode 100644 apps/mysetup/setting.json create mode 100644 apps/mysetup/widbt_notify.json diff --git a/apps/mysetup/ChangeLog b/apps/mysetup/ChangeLog new file mode 100644 index 0000000000..b783a79175 --- /dev/null +++ b/apps/mysetup/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: update to my current preferences. diff --git a/apps/mysetup/README.md b/apps/mysetup/README.md new file mode 100644 index 0000000000..278665743d --- /dev/null +++ b/apps/mysetup/README.md @@ -0,0 +1,29 @@ +# App Name + +Describe the app... + +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Usage + +Before installing this do: + +1. Factory reset the watch. +2. Remove all apps via the "More..." tab in the App Loader. +3. Make sure minification is turned off on the App Loader. + +## Features + +Name the function + +## Controls + +Name the buttons and what they are used for + +## Requests + +Name who should be contacted for support/update requests + +## Creator + +thyttan diff --git a/apps/mysetup/app-icon.js b/apps/mysetup/app-icon.js new file mode 100644 index 0000000000..49232b8386 --- /dev/null +++ b/apps/mysetup/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/mysetup/app.png b/apps/mysetup/app.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 Date: Sat, 6 Jul 2024 13:39:22 +0200 Subject: [PATCH 057/135] mysetup: update app list --- apps/mysetup/ChangeLog | 1 + apps/mysetup/metadata.json | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/mysetup/ChangeLog b/apps/mysetup/ChangeLog index b783a79175..e2cf1d249e 100644 --- a/apps/mysetup/ChangeLog +++ b/apps/mysetup/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: update to my current preferences. +0.03: update app list diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 3a5af4b549..2d12581922 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -1,6 +1,6 @@ { "id": "mysetup", "name": "My Setup", - "version":"0.02", + "version":"0.03", "description": "Setup the Bangle.js watch as I want it.", "icon": "app.png", "type": "settings", @@ -34,15 +34,14 @@ "recorder":"app", "bthrm":"app", "fastload":"app", - "fastreset":"app", "agenda":"app", "edgeclk":"app", - "activityreminder":"app", "twenties":"app", "autoreset":"app", "chargent":"app", "setting":"app", - "boot":"app" + "boot":"app", + "setuichange":"app" }, "readme": "README.md", "storage": [ From 10065ead7b77d4712e27173407b12d80800e6050 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 6 Jul 2024 15:10:05 +0200 Subject: [PATCH 058/135] mysetup: add edgeclk settings --- apps/mysetup/edgeclk.settings.json | 1 + apps/mysetup/metadata.json | 2 ++ 2 files changed, 3 insertions(+) create mode 100644 apps/mysetup/edgeclk.settings.json diff --git a/apps/mysetup/edgeclk.settings.json b/apps/mysetup/edgeclk.settings.json new file mode 100644 index 0000000000..6ff3cbe842 --- /dev/null +++ b/apps/mysetup/edgeclk.settings.json @@ -0,0 +1 @@ +{"buzzOnCharge":true,"monthFirst":true,"twentyFourH":true,"showAmPm":false,"showSeconds":false,"showWeather":false,"stepGoal":10000,"stepBar":true,"weekBar":true,"mondayFirst":true,"dayBar":true} diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 2d12581922..fbe3ff8025 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -61,6 +61,8 @@ "url":"widbt_notify.json"}, {"name":"recorder.json", "url":"recorder.json"}, + {"name":"edgeclk.settings.json", + "url":"edgeclk.settings.json"}, {"name":"setting.json", "url":"setting.json"} ] From 641f0c8f43b32db8a778e0bed9e6477bf35d40bd Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 10 Jul 2024 23:44:01 +0200 Subject: [PATCH 059/135] mysetup: add delaylock app --- apps/mysetup/backswipe.json | 2 +- apps/mysetup/metadata.json | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/mysetup/backswipe.json b/apps/mysetup/backswipe.json index b43cb1cf40..aa66bd5344 100644 --- a/apps/mysetup/backswipe.json +++ b/apps/mysetup/backswipe.json @@ -1 +1 @@ -{"mode":0,"apps":[{"name":"Calculator","src":"calculator.app.js"},{"name":"SleepLog","src":"sleeplog.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js","files":"messagegui.info,messagegui,messagegui.app.js,messagegui.new.js,messagegui.boot.js,messagegui.img"}],"standardNumSwipeHandlers":4,"standardNumDragHandlers":1} \ No newline at end of file +{"mode":0,"apps":[{"name":"Calculator","src":"calculator.app.js"},{"name":"SleepLog","src":"sleeplog.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js"},{"name":"Messages","sortorder":-9,"src":"messagegui.app.js","files":"messagegui.info,messagegui,messagegui.app.js,messagegui.new.js,messagegui.boot.js,messagegui.img"}],"standardNumSwipeHandlers":5,"standardNumDragHandlers":1} diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index fbe3ff8025..206aba80ed 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -6,6 +6,7 @@ "type": "settings", "tags": "system,clkinfo", "supports" : ["BANGLEJS2"], + "readme": "README.md", "dependencies" : { "sched":"app", "kbmulti":"app", @@ -33,17 +34,17 @@ "alarm":"app", "recorder":"app", "bthrm":"app", - "fastload":"app", "agenda":"app", "edgeclk":"app", "twenties":"app", "autoreset":"app", "chargent":"app", "setting":"app", + "fastload":"app", "boot":"app", + "delaylock":"app", "setuichange":"app" }, - "readme": "README.md", "storage": [ {"name":"backswipe.json", "url":"backswipe.json"}, From 5ca54f520735c90a19ac2614f978629201de2d9a Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 10 Jul 2024 23:45:50 +0200 Subject: [PATCH 060/135] =?UTF-8?q?mysetup:=20add=20app=20=C2=B4forge?= =?UTF-8?q?=C2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/mysetup/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 206aba80ed..82c01159d4 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -30,6 +30,7 @@ "runplus":"app", "dtlaunch":"app", "quicklaunch":"app", + "forge":"app", "kineticscroll":"app", "alarm":"app", "recorder":"app", From 1bc249ab63c4ca01fbe9878facde8437dc5975dc Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sun, 10 Nov 2024 09:58:27 +0100 Subject: [PATCH 061/135] mysetup: remove traces of mysetup installation --- apps/mysetup/boot.js | 5 +++++ apps/mysetup/metadata.json | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 apps/mysetup/boot.js diff --git a/apps/mysetup/boot.js b/apps/mysetup/boot.js new file mode 100644 index 0000000000..85f2c4ff0c --- /dev/null +++ b/apps/mysetup/boot.js @@ -0,0 +1,5 @@ +{ +require("Storage").erase("mysetup.info"); +require("Storage").erase("mysetup.boot.js"); +load(); +} diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 82c01159d4..a1ed941b99 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -66,6 +66,8 @@ {"name":"edgeclk.settings.json", "url":"edgeclk.settings.json"}, {"name":"setting.json", - "url":"setting.json"} + "url":"setting.json"}, + {"name":"mysetup.boot.js", + "url":"boot.js"} ] } From 32e81df19f2a5b74d50a4d3aa260a04ea52d3757 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sun, 10 Nov 2024 10:09:07 +0100 Subject: [PATCH 062/135] mysetup: rm setuichange, use kbedgewrite --- apps/mysetup/metadata.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index a1ed941b99..4ed008b190 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -9,7 +9,7 @@ "readme": "README.md", "dependencies" : { "sched":"app", - "kbmulti":"app", + "kbedgewrite":"app", "messageicons":"app", "widmsggrid":"app", "msgwakefup":"app", @@ -43,8 +43,7 @@ "setting":"app", "fastload":"app", "boot":"app", - "delaylock":"app", - "setuichange":"app" + "delaylock":"app" }, "storage": [ {"name":"backswipe.json", From 83952e2598738481a03cbb7ff1edd4cb4ab47408 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 22 Jan 2025 21:12:48 +0100 Subject: [PATCH 063/135] mysetup: add apps, tweak edgeclk settings json --- apps/mysetup/edgeclk.settings.json | 2 +- apps/mysetup/metadata.json | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/mysetup/edgeclk.settings.json b/apps/mysetup/edgeclk.settings.json index 6ff3cbe842..bdf875621c 100644 --- a/apps/mysetup/edgeclk.settings.json +++ b/apps/mysetup/edgeclk.settings.json @@ -1 +1 @@ -{"buzzOnCharge":true,"monthFirst":true,"twentyFourH":true,"showAmPm":false,"showSeconds":false,"showWeather":false,"stepGoal":10000,"stepBar":true,"weekBar":true,"mondayFirst":true,"dayBar":true} +{"buzzOnCharge":true,"monthFirst":true,"twentyFourH":true,"showAmPm":false,"showSeconds":true,"showWeather":false,"stepGoal":10000,"stepBar":true,"weekBar":true,"mondayFirst":true,"dayBar":true,"redrawOnStep":false} diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 4ed008b190..3fdf934762 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -43,6 +43,8 @@ "setting":"app", "fastload":"app", "boot":"app", + "gbdiscon":"app", + "ateatimer":"app", "delaylock":"app" }, "storage": [ From 1a362f5e1b26d6cfea986301695067914142c042 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 21:09:46 +0100 Subject: [PATCH 064/135] mysetup: add msgtwscr app --- apps/mysetup/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/mysetup/metadata.json b/apps/mysetup/metadata.json index 3fdf934762..acf75cdd42 100644 --- a/apps/mysetup/metadata.json +++ b/apps/mysetup/metadata.json @@ -13,6 +13,7 @@ "messageicons":"app", "widmsggrid":"app", "msgwakefup":"app", + "msgtwscr":"app", "notify":"app", "health":"app", "widminbate":"app", From 44809a75e1fe5553f9a96d871f91af0032646e59 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 21:19:26 +0100 Subject: [PATCH 065/135] mysetup: add icon --- apps/mysetup/app-icon.js | 1 - apps/mysetup/app.png | Bin 1620 -> 1789 bytes 2 files changed, 1 deletion(-) delete mode 100644 apps/mysetup/app-icon.js diff --git a/apps/mysetup/app-icon.js b/apps/mysetup/app-icon.js deleted file mode 100644 index 49232b8386..0000000000 --- a/apps/mysetup/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/mysetup/app.png b/apps/mysetup/app.png index 582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0..24ff01b8a4a6588bbfde982ce24cdb50735e51f5 100644 GIT binary patch delta 1773 zcmV8Q}8HClU z^Y4B?*T3^S=h~7qfg#e`-6GAWP2@HIA8XQU8dmRL{i6cz#H0)EZY9&ny4G~-v1B^A zukDkz?~awHC<9cZj8_OgNG1y0_RmSWzkh zbrs#C0gOO!{O56ji0?jhNwGB$QWjOW%*c%eFzyg`f`7^~WIB0FmF4M@BwdVTxt4kG zm+@DYjA`C+J0TYeVyrzxslLUoFxJ``W0za&5m`ozlP~72iyGzCzHZ9Yfr=X6*DcSt zoYTA`2!h#Hv(~g5HFrKN?8-AE(vK9Sakv%$Kw%soYu@(XQR!6k3mvfp({GwzIUt-U z^y7Gs>VE<^m~|9I`M!DQOJP2FO3`(7d8XsHCj`LUs3^yMiJgg(m`|pYqH%MBVIDaq z1mIK))oE_rTMCF99&0uzQ@gP&>)#Hb((H`o_vB;G?6nOr?I*4Mgz(+a1*^}3cr{V9 zdDZ1|ONER)jA=Xf26|&p@3952aC@hibMIE6d4DT=F=oq#YpMX;QWXnjodRfXk|O}v zdlJQ`jyl5 zz{^8fb0M3xn1>v``K_BBw@~vVO@e#q%eDYi2$u(A@jfT!8(;W?`3>ZJQ>I+@?{C0M zJAWECH#i2UT~%|OVsw9Dt%LDo2w@Xtde4GwyKI|Z@OVm;*VgBV=G!t{69C}XbdqiQ z)k3j+*K*PLV1rQ=ySitzg>5d_X$ykc=50-4=^IPMwdHImF!bMRP|lxOIx!2VzTe)_veyp{gLtPHlGPlNn{W2bCdD!Db5uXxjdf z@XeYxgaI^E00eXU2Cv)vTG0SzAf(J^8qN_~;GA~?;He4^g)kl3UsEG8k-1`}*MD~s zL)B<_?sr844DUU3D!oD~MW|5C*FEr*7*^z`j|&w*;PnoHg&`ExM@kz~5hR00X~vi|Ey`w?cz2nd8yVz?0W_LEq=k zy2bwlfT{crk9cW4GujrB+*7yGq1^V<-xp^9EbGX4;vHQH+vd#;gDc>;6Mypu=gbvB zqz;V+P>4RZ03_c&IC;hHBetf}BtL{N29Vl&m%k!s*ZjtcfPn!pDj6JnubmeSU_0Eh zx^@wF_Z^vAXZz0Y4bK*)`QL2N92pm-00 zgg6}B`}6Tx#GzWuS%JhwOCgXkBCmUzhD5fg+4C=V3R|DkABHTl^1+)8h=2iwo#;ck4W=a z!2o^;e>)wMo-iiec0~ags?jRS zcuqW(NtNRNw+WAyU5BS8QknM?sZ2i6(Y5k?`*9S@UjOIi@s7-DJ0JQNYblu(N>Kj^ P00000NkvXXu0mjf)Z}v3 delta 1603 zcmV-J2E6(G4b%*fB!32COGiWi{{a60|De66lK=n)2}wjjRA_4iBBgQZ;76qOQH!eYQP$e z!AKAcJ}AB5-5IcA@d8w#^g@T3&dgpul+x+U-n)CIwK<9WpMUnc?eD+#{x0kLJ~)lj z_;W+1>qV*0;V;<>t_7g#4P@iwmk z1qmdsUbfUStd9Y|TVP;i68~i*#Z&Y~>jipZkI1cLC-XG&6_#ObWSo3TMb<VnloLT~EMt9))wb_t9z`$fds1weiDS%fvYLsiPBH2ZnQDk6uTc5^7mPDSrl!}_vf zTUQ)F+oLxD4{1WMdd9!Hc|m5n$vQyR>+YsqvNZO#t<^15JLgwo1!6$$$ooOkyMm*J z0F*s8gnyK)TljRMmz2LruK4O$zQL{wjY9)Z0kt|Lq(2FsQU|U{&Lnw&nv-iz0UQ(1 z_C;r*+zXKT!Vl?Dy;NHGm#6;#j+0`o?rE&cS33Uzu^t4%0M>8gZsvJekQx2@V+fHo z*5xa0rzlknI`ob)Spqpmmr>I{XwtT=f>`%xcYlkXpJLUDL8`0V*CWqymfo()hTHYJB=sn`2^Q$mRE>02( z+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8 z^nZyH25leAvW+P%&S;$=IlOmqK~5megP0ekG0q%cjYX8Luf59F*IsobYlouaRHM0~ z(;q09t|si8%+WECi^loRmFYCwYI6mr1b@o&75=}a@Lib3Y|Ie4CxKK>Okic}5Rq_U zeN+~H!uVe{{lz}^`kQW`|!xuR17T{A$XG+1=zihuSA zi1p!&kSPh)j$Fxp5Gw{9(I0?wrrO+K-v|fy4|DX;36jHEtgI3$_c6CFMEwO7gd?t7 z-aKL)pd~&(x0thy7QxaE*@Ws7r4mmjvcx<3IQ(NG=PY9s!vkrC2h#ks?>HAOpF`dJ zh_{!DY|1~1bS#dwebHHv-OtHAL4Pqg_G^mIKKhN3WERtBFmGXm+WH8Q3O|NVINqP; zhpz`Xd?0}cEM8H=+`36mP?GrceEI9%2{WYQhDKVxISl-_Sn>l$M(Eo9D?J ziW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQS^k|*9wyt=f4ZOo!+#eiul{gC zVkpfgTMv^?S+&Oz-^QfHN=vA6Mu zqQHxcUJp$bNst%thoZ%hhv~ZHvseduC&kuI$^k?+Ves;_U-A`;(L4gMVKHj9f;MB& zfHIHq{q=E#pRw2n(gD^ETK4Xl>NV?WoW`FWzXM%bGkOQp1Xln6002ovPDHLkV1m{L B8@m7i From 43159826b4785eae4753f0dbeec6ee26e58e8809 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 21:53:35 +0100 Subject: [PATCH 066/135] mysetup: becomes "anotherconf" --- apps/{mysetup => anotherconf}/ChangeLog | 1 + apps/anotherconf/README.md | 26 ++++++++++++++++ apps/{mysetup => anotherconf}/app.png | Bin apps/{mysetup => anotherconf}/autoreset.json | 0 apps/{mysetup => anotherconf}/backswipe.json | 0 apps/anotherconf/boot.js | 5 +++ apps/{mysetup => anotherconf}/dtlaunch.json | 0 .../edgeclk.settings.json | 0 apps/{mysetup => anotherconf}/fastload.json | 0 .../{mysetup => anotherconf}/lightswitch.json | 0 .../messages.settings.json | 0 apps/{mysetup => anotherconf}/metadata.json | 25 +++++++-------- .../{mysetup => anotherconf}/quicklaunch.json | 0 apps/{mysetup => anotherconf}/recorder.json | 0 apps/{mysetup => anotherconf}/setting.json | 0 .../widbt_notify.json | 0 apps/mysetup/README.md | 29 ------------------ apps/mysetup/boot.js | 5 --- 18 files changed, 45 insertions(+), 46 deletions(-) rename apps/{mysetup => anotherconf}/ChangeLog (61%) create mode 100644 apps/anotherconf/README.md rename apps/{mysetup => anotherconf}/app.png (100%) rename apps/{mysetup => anotherconf}/autoreset.json (100%) rename apps/{mysetup => anotherconf}/backswipe.json (100%) create mode 100644 apps/anotherconf/boot.js rename apps/{mysetup => anotherconf}/dtlaunch.json (100%) rename apps/{mysetup => anotherconf}/edgeclk.settings.json (100%) rename apps/{mysetup => anotherconf}/fastload.json (100%) rename apps/{mysetup => anotherconf}/lightswitch.json (100%) rename apps/{mysetup => anotherconf}/messages.settings.json (100%) rename apps/{mysetup => anotherconf}/metadata.json (78%) rename apps/{mysetup => anotherconf}/quicklaunch.json (100%) rename apps/{mysetup => anotherconf}/recorder.json (100%) rename apps/{mysetup => anotherconf}/setting.json (100%) rename apps/{mysetup => anotherconf}/widbt_notify.json (100%) delete mode 100644 apps/mysetup/README.md delete mode 100644 apps/mysetup/boot.js diff --git a/apps/mysetup/ChangeLog b/apps/anotherconf/ChangeLog similarity index 61% rename from apps/mysetup/ChangeLog rename to apps/anotherconf/ChangeLog index e2cf1d249e..6237f5b04e 100644 --- a/apps/mysetup/ChangeLog +++ b/apps/anotherconf/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: update to my current preferences. 0.03: update app list +0.04: change app name "mysetup" -> "anotherconf" diff --git a/apps/anotherconf/README.md b/apps/anotherconf/README.md new file mode 100644 index 0000000000..4fac2feb4f --- /dev/null +++ b/apps/anotherconf/README.md @@ -0,0 +1,26 @@ +# Another Default Config + +A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing. + +## Usage + +Before installing do this: + +1. Backup your current setup (via the "More..." tab of the App Loader) so you can restore it later if you want. +2. Factory reset the watch. +3. Remove all apps via the "More..." tab in the App Loader. +4. Make sure minification is turned off on the App Loader. +5. Then install. +6. Try it out, switch out apps to your favorites and tweak to your liking! + +## Features + +There will not be a trace of a "Another Default Config" app on your watch after installation. Only the apps it installed and the configurations. + +## Requests + +Add to the espruino/BangleApps issue tracker and mention @thyttan for bug reports and suggestions. Or do a pull request! + +## Creator + +thyttan diff --git a/apps/mysetup/app.png b/apps/anotherconf/app.png similarity index 100% rename from apps/mysetup/app.png rename to apps/anotherconf/app.png diff --git a/apps/mysetup/autoreset.json b/apps/anotherconf/autoreset.json similarity index 100% rename from apps/mysetup/autoreset.json rename to apps/anotherconf/autoreset.json diff --git a/apps/mysetup/backswipe.json b/apps/anotherconf/backswipe.json similarity index 100% rename from apps/mysetup/backswipe.json rename to apps/anotherconf/backswipe.json diff --git a/apps/anotherconf/boot.js b/apps/anotherconf/boot.js new file mode 100644 index 0000000000..a04465039a --- /dev/null +++ b/apps/anotherconf/boot.js @@ -0,0 +1,5 @@ +{ +require("Storage").erase("anotherconf.info"); +require("Storage").erase("anotherconf.boot.js"); +load(); +} diff --git a/apps/mysetup/dtlaunch.json b/apps/anotherconf/dtlaunch.json similarity index 100% rename from apps/mysetup/dtlaunch.json rename to apps/anotherconf/dtlaunch.json diff --git a/apps/mysetup/edgeclk.settings.json b/apps/anotherconf/edgeclk.settings.json similarity index 100% rename from apps/mysetup/edgeclk.settings.json rename to apps/anotherconf/edgeclk.settings.json diff --git a/apps/mysetup/fastload.json b/apps/anotherconf/fastload.json similarity index 100% rename from apps/mysetup/fastload.json rename to apps/anotherconf/fastload.json diff --git a/apps/mysetup/lightswitch.json b/apps/anotherconf/lightswitch.json similarity index 100% rename from apps/mysetup/lightswitch.json rename to apps/anotherconf/lightswitch.json diff --git a/apps/mysetup/messages.settings.json b/apps/anotherconf/messages.settings.json similarity index 100% rename from apps/mysetup/messages.settings.json rename to apps/anotherconf/messages.settings.json diff --git a/apps/mysetup/metadata.json b/apps/anotherconf/metadata.json similarity index 78% rename from apps/mysetup/metadata.json rename to apps/anotherconf/metadata.json index acf75cdd42..cbbf972786 100644 --- a/apps/mysetup/metadata.json +++ b/apps/anotherconf/metadata.json @@ -1,19 +1,20 @@ -{ "id": "mysetup", - "name": "My Setup", - "version":"0.03", - "description": "Setup the Bangle.js watch as I want it.", +{ "id": "anotherconf", + "name": "Another Default Config", + "version":"0.04", + "description": "A different default loadout of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.", "icon": "app.png", "type": "settings", - "tags": "system,clkinfo", + "tags": "system, configuration, config", "supports" : ["BANGLEJS2"], "readme": "README.md", "dependencies" : { "sched":"app", - "kbedgewrite":"app", + "kbmulti":"app", "messageicons":"app", "widmsggrid":"app", "msgwakefup":"app", "msgtwscr":"app", + "delaylock":"app", "notify":"app", "health":"app", "widminbate":"app", @@ -31,22 +32,22 @@ "runplus":"app", "dtlaunch":"app", "quicklaunch":"app", - "forge":"app", "kineticscroll":"app", "alarm":"app", "recorder":"app", - "bthrm":"app", "agenda":"app", "edgeclk":"app", - "twenties":"app", "autoreset":"app", "chargent":"app", "setting":"app", "fastload":"app", "boot":"app", - "gbdiscon":"app", "ateatimer":"app", - "delaylock":"app" + "drained":"app", + "forge":"app", + "bthrm":"app", + "twenties":"app", + "gbdiscon":"app" }, "storage": [ {"name":"backswipe.json", @@ -69,7 +70,7 @@ "url":"edgeclk.settings.json"}, {"name":"setting.json", "url":"setting.json"}, - {"name":"mysetup.boot.js", + {"name":"anotherconf.boot.js", "url":"boot.js"} ] } diff --git a/apps/mysetup/quicklaunch.json b/apps/anotherconf/quicklaunch.json similarity index 100% rename from apps/mysetup/quicklaunch.json rename to apps/anotherconf/quicklaunch.json diff --git a/apps/mysetup/recorder.json b/apps/anotherconf/recorder.json similarity index 100% rename from apps/mysetup/recorder.json rename to apps/anotherconf/recorder.json diff --git a/apps/mysetup/setting.json b/apps/anotherconf/setting.json similarity index 100% rename from apps/mysetup/setting.json rename to apps/anotherconf/setting.json diff --git a/apps/mysetup/widbt_notify.json b/apps/anotherconf/widbt_notify.json similarity index 100% rename from apps/mysetup/widbt_notify.json rename to apps/anotherconf/widbt_notify.json diff --git a/apps/mysetup/README.md b/apps/mysetup/README.md deleted file mode 100644 index 278665743d..0000000000 --- a/apps/mysetup/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# App Name - -Describe the app... - -Add screen shots (if possible) to the app folder and link then into this file with ![](.png) - -## Usage - -Before installing this do: - -1. Factory reset the watch. -2. Remove all apps via the "More..." tab in the App Loader. -3. Make sure minification is turned off on the App Loader. - -## Features - -Name the function - -## Controls - -Name the buttons and what they are used for - -## Requests - -Name who should be contacted for support/update requests - -## Creator - -thyttan diff --git a/apps/mysetup/boot.js b/apps/mysetup/boot.js deleted file mode 100644 index 85f2c4ff0c..0000000000 --- a/apps/mysetup/boot.js +++ /dev/null @@ -1,5 +0,0 @@ -{ -require("Storage").erase("mysetup.info"); -require("Storage").erase("mysetup.boot.js"); -load(); -} From 90011268116414aed1cb3635381cbade97473e0b Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 22:07:26 +0100 Subject: [PATCH 067/135] anotherconf: remove some apps not as important as the others --- apps/anotherconf/ChangeLog | 1 + apps/anotherconf/metadata.json | 8 ++------ 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/anotherconf/ChangeLog b/apps/anotherconf/ChangeLog index 6237f5b04e..6c717cad7b 100644 --- a/apps/anotherconf/ChangeLog +++ b/apps/anotherconf/ChangeLog @@ -2,3 +2,4 @@ 0.02: update to my current preferences. 0.03: update app list 0.04: change app name "mysetup" -> "anotherconf" +0.05: remove apps that are not "core" to the experience. diff --git a/apps/anotherconf/metadata.json b/apps/anotherconf/metadata.json index cbbf972786..2a65584db2 100644 --- a/apps/anotherconf/metadata.json +++ b/apps/anotherconf/metadata.json @@ -1,6 +1,6 @@ { "id": "anotherconf", "name": "Another Default Config", - "version":"0.04", + "version":"0.05", "description": "A different default loadout of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.", "icon": "app.png", "type": "settings", @@ -43,11 +43,7 @@ "fastload":"app", "boot":"app", "ateatimer":"app", - "drained":"app", - "forge":"app", - "bthrm":"app", - "twenties":"app", - "gbdiscon":"app" + "drained":"app" }, "storage": [ {"name":"backswipe.json", From de8fd1526e3ecdabd13255b96bf2d9f8ad48d1a3 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 22:24:39 +0100 Subject: [PATCH 068/135] anotherconf: add to readme --- apps/anotherconf/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/apps/anotherconf/README.md b/apps/anotherconf/README.md index 4fac2feb4f..c292bb0a67 100644 --- a/apps/anotherconf/README.md +++ b/apps/anotherconf/README.md @@ -17,6 +17,14 @@ Before installing do this: There will not be a trace of a "Another Default Config" app on your watch after installation. Only the apps it installed and the configurations. +On the clock face: +- Swipe right on the screen to open the launcher (Desktop Launcher) - or press the hardware button. +- Swipe left to open a flashlight app. +- Swipe up to open the messages. +- Swipe down for quick access to music and podcast controls. + - (Do a subsequent left or right swipe to enter the listed apps) +- (Check out the "Quick Launch" app readme for more info) + ## Requests Add to the espruino/BangleApps issue tracker and mention @thyttan for bug reports and suggestions. Or do a pull request! From 5db094bbf02ea3992b9cf27b9a10fc3557f53286 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Wed, 29 Jan 2025 22:32:00 +0100 Subject: [PATCH 069/135] anotherconf: left swipe on clock fires up the torch --- apps/anotherconf/quicklaunch.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/anotherconf/quicklaunch.json b/apps/anotherconf/quicklaunch.json index 56df7d3d23..4edbb083bf 100644 --- a/apps/anotherconf/quicklaunch.json +++ b/apps/anotherconf/quicklaunch.json @@ -1 +1 @@ -{lapp:{name:"Show Launcher",sortorder:-12,src:"no source"},rapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},uapp:{name:"Messages",sortorder:-9,src:"messagegui.app.js"},dapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},tapp:{name:""},dlapp:{name:"PA Remote",src:"podadrem.app.js"},drapp:{name:"Remote for Spotify",src:"spotrem.app.js"},duapp:{name:""},ddapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},dtapp:{name:""},ddlapp:{name:"Alarms",src:"alarm.app.js"},ddrapp:{name:"Run+",src:"runplus.app.js"},dduapp:{name:""},dddapp:{name:"Agenda",src:"agenda.app.js"},ddtapp:{name:""},rlapp:{name:""},rrapp:{name:""},ruapp:{name:""},rdapp:{name:""},rtapp:{name:""},trace:"dr"} \ No newline at end of file +{lapp:{name:"Show Launcher",sortorder:-12,src:"no source"},rapp:{name:"torch",type:"app",sortorder:-11,src:"torch.app.js"},uapp:{name:"Messages",sortorder:-9,src:"messagegui.app.js"},dapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},tapp:{name:""},dlapp:{name:"PA Remote",src:"podadrem.app.js"},drapp:{name:"Remote for Spotify",src:"spotrem.app.js"},duapp:{name:""},ddapp:{name:"Extension",type:"app",sortorder:-11,src:"quicklaunch.app.js"},dtapp:{name:""},ddlapp:{name:"Alarms",src:"alarm.app.js"},ddrapp:{name:"Run+",src:"runplus.app.js"},dduapp:{name:""},dddapp:{name:"Agenda",src:"agenda.app.js"},ddtapp:{name:""},rlapp:{name:""},rrapp:{name:""},ruapp:{name:""},rdapp:{name:""},rtapp:{name:""},trace:"dr"} From ab2d74587213ca2276afc776346e480b591daa32 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Mon, 3 Feb 2025 09:59:02 +0100 Subject: [PATCH 070/135] anotherconf: becomes "confthyttan" + some suggested changes --- apps/anotherconf/boot.js | 5 ----- apps/{anotherconf => confthyttan}/ChangeLog | 1 + apps/{anotherconf => confthyttan}/README.md | 6 +++--- apps/{anotherconf => confthyttan}/app.png | Bin .../autoreset.json | 0 .../backswipe.json | 0 .../{anotherconf => confthyttan}/dtlaunch.json | 0 .../edgeclk.settings.json | 0 .../{anotherconf => confthyttan}/fastload.json | 0 .../lightswitch.json | 0 .../messages.settings.json | 0 .../{anotherconf => confthyttan}/metadata.json | 17 +++++++---------- .../quicklaunch.json | 0 .../{anotherconf => confthyttan}/recorder.json | 0 apps/{anotherconf => confthyttan}/setting.json | 0 .../widbt_notify.json | 0 16 files changed, 11 insertions(+), 18 deletions(-) delete mode 100644 apps/anotherconf/boot.js rename apps/{anotherconf => confthyttan}/ChangeLog (78%) rename apps/{anotherconf => confthyttan}/README.md (82%) rename apps/{anotherconf => confthyttan}/app.png (100%) rename apps/{anotherconf => confthyttan}/autoreset.json (100%) rename apps/{anotherconf => confthyttan}/backswipe.json (100%) rename apps/{anotherconf => confthyttan}/dtlaunch.json (100%) rename apps/{anotherconf => confthyttan}/edgeclk.settings.json (100%) rename apps/{anotherconf => confthyttan}/fastload.json (100%) rename apps/{anotherconf => confthyttan}/lightswitch.json (100%) rename apps/{anotherconf => confthyttan}/messages.settings.json (100%) rename apps/{anotherconf => confthyttan}/metadata.json (77%) rename apps/{anotherconf => confthyttan}/quicklaunch.json (100%) rename apps/{anotherconf => confthyttan}/recorder.json (100%) rename apps/{anotherconf => confthyttan}/setting.json (100%) rename apps/{anotherconf => confthyttan}/widbt_notify.json (100%) diff --git a/apps/anotherconf/boot.js b/apps/anotherconf/boot.js deleted file mode 100644 index a04465039a..0000000000 --- a/apps/anotherconf/boot.js +++ /dev/null @@ -1,5 +0,0 @@ -{ -require("Storage").erase("anotherconf.info"); -require("Storage").erase("anotherconf.boot.js"); -load(); -} diff --git a/apps/anotherconf/ChangeLog b/apps/confthyttan/ChangeLog similarity index 78% rename from apps/anotherconf/ChangeLog rename to apps/confthyttan/ChangeLog index 6c717cad7b..77d527619d 100644 --- a/apps/anotherconf/ChangeLog +++ b/apps/confthyttan/ChangeLog @@ -3,3 +3,4 @@ 0.03: update app list 0.04: change app name "mysetup" -> "anotherconf" 0.05: remove apps that are not "core" to the experience. +0.06: change name "anotherconf" -> "confthyttan" diff --git a/apps/anotherconf/README.md b/apps/confthyttan/README.md similarity index 82% rename from apps/anotherconf/README.md rename to apps/confthyttan/README.md index c292bb0a67..5f78191717 100644 --- a/apps/anotherconf/README.md +++ b/apps/confthyttan/README.md @@ -1,4 +1,4 @@ -# Another Default Config +# Thyttan's Default Config A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing. @@ -15,7 +15,7 @@ Before installing do this: ## Features -There will not be a trace of a "Another Default Config" app on your watch after installation. Only the apps it installed and the configurations. +There will not be a trace of a "Thyttan's Default Config" app on your watch after installation. Only the apps it installed and the configurations. On the clock face: - Swipe right on the screen to open the launcher (Desktop Launcher) - or press the hardware button. @@ -27,7 +27,7 @@ On the clock face: ## Requests -Add to the espruino/BangleApps issue tracker and mention @thyttan for bug reports and suggestions. Or do a pull request! +Add to the espruino/BangleApps issue tracker and mention @thyttan for bug reports and suggestions. ## Creator diff --git a/apps/anotherconf/app.png b/apps/confthyttan/app.png similarity index 100% rename from apps/anotherconf/app.png rename to apps/confthyttan/app.png diff --git a/apps/anotherconf/autoreset.json b/apps/confthyttan/autoreset.json similarity index 100% rename from apps/anotherconf/autoreset.json rename to apps/confthyttan/autoreset.json diff --git a/apps/anotherconf/backswipe.json b/apps/confthyttan/backswipe.json similarity index 100% rename from apps/anotherconf/backswipe.json rename to apps/confthyttan/backswipe.json diff --git a/apps/anotherconf/dtlaunch.json b/apps/confthyttan/dtlaunch.json similarity index 100% rename from apps/anotherconf/dtlaunch.json rename to apps/confthyttan/dtlaunch.json diff --git a/apps/anotherconf/edgeclk.settings.json b/apps/confthyttan/edgeclk.settings.json similarity index 100% rename from apps/anotherconf/edgeclk.settings.json rename to apps/confthyttan/edgeclk.settings.json diff --git a/apps/anotherconf/fastload.json b/apps/confthyttan/fastload.json similarity index 100% rename from apps/anotherconf/fastload.json rename to apps/confthyttan/fastload.json diff --git a/apps/anotherconf/lightswitch.json b/apps/confthyttan/lightswitch.json similarity index 100% rename from apps/anotherconf/lightswitch.json rename to apps/confthyttan/lightswitch.json diff --git a/apps/anotherconf/messages.settings.json b/apps/confthyttan/messages.settings.json similarity index 100% rename from apps/anotherconf/messages.settings.json rename to apps/confthyttan/messages.settings.json diff --git a/apps/anotherconf/metadata.json b/apps/confthyttan/metadata.json similarity index 77% rename from apps/anotherconf/metadata.json rename to apps/confthyttan/metadata.json index 2a65584db2..c706d45f57 100644 --- a/apps/anotherconf/metadata.json +++ b/apps/confthyttan/metadata.json @@ -1,10 +1,10 @@ -{ "id": "anotherconf", - "name": "Another Default Config", - "version":"0.05", - "description": "A different default loadout of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.", +{ "id": "confthyttan", + "name": "Thyttan's Default Config", + "version":"0.06", + "description": "A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.", "icon": "app.png", - "type": "settings", - "tags": "system, configuration, config", + "type": "RAM", + "tags": "system, configuration, config, anotherconfig, thyttan", "supports" : ["BANGLEJS2"], "readme": "README.md", "dependencies" : { @@ -26,7 +26,6 @@ "torch":"app", "calculator":"app", "widbt_notify":"app", - "clock_info":"app", "smpltmr":"app", "clkinfostopw":"app", "runplus":"app", @@ -65,8 +64,6 @@ {"name":"edgeclk.settings.json", "url":"edgeclk.settings.json"}, {"name":"setting.json", - "url":"setting.json"}, - {"name":"anotherconf.boot.js", - "url":"boot.js"} + "url":"setting.json"} ] } diff --git a/apps/anotherconf/quicklaunch.json b/apps/confthyttan/quicklaunch.json similarity index 100% rename from apps/anotherconf/quicklaunch.json rename to apps/confthyttan/quicklaunch.json diff --git a/apps/anotherconf/recorder.json b/apps/confthyttan/recorder.json similarity index 100% rename from apps/anotherconf/recorder.json rename to apps/confthyttan/recorder.json diff --git a/apps/anotherconf/setting.json b/apps/confthyttan/setting.json similarity index 100% rename from apps/anotherconf/setting.json rename to apps/confthyttan/setting.json diff --git a/apps/anotherconf/widbt_notify.json b/apps/confthyttan/widbt_notify.json similarity index 100% rename from apps/anotherconf/widbt_notify.json rename to apps/confthyttan/widbt_notify.json From 2ee884ef5c7fb9abbe5af2661098ca5a6c5fbf72 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 4 Feb 2025 11:44:41 +0000 Subject: [PATCH 071/135] fix broken messagesoverlay metadata file --- apps/messagesoverlay/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/messagesoverlay/metadata.json b/apps/messagesoverlay/metadata.json index 26095eb33a..ba5f005c3c 100644 --- a/apps/messagesoverlay/metadata.json +++ b/apps/messagesoverlay/metadata.json @@ -15,6 +15,6 @@ {"name":"messagesoverlay.settings.js","url":"settings.js"}, {"name":"messagesoverlay.default.json","url":"default.json"} ], - "data": [{"name":"bthrm.json"}], + "data":[{"name":"messagesoverlay.json"}], "screenshots": [{"url":"screen_call.png"} ,{"url":"screen_message.png"} ] } From 90a0baf790f74d6efde42ff04b5b5f0c5f736b1f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 4 Feb 2025 12:23:03 +0000 Subject: [PATCH 072/135] handle 'defaultconfig' app type for default configurations --- README.md | 1 + apps/confthyttan/README.md | 7 ++----- apps/confthyttan/metadata.json | 5 ++--- bin/sanitycheck.js | 11 ++++++++--- core | 2 +- typescript/types/info.d.ts | 2 +- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index ddcf23f259..13da10b0ae 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,7 @@ and which gives information about the app for the Launcher. // 'notify' - provides 'notify' library for showing notifications // 'locale' - provides 'locale' library for language-specific date/distance/etc // (a version of 'locale' is included in the firmware) + // 'defaultconfig' - a set of apps that will can be installed and will wipe out all previously installed apps "tags": "", // comma separated tag list for searching // common types are: // 'clock' - it's a clock diff --git a/apps/confthyttan/README.md b/apps/confthyttan/README.md index 5f78191717..e9b952c822 100644 --- a/apps/confthyttan/README.md +++ b/apps/confthyttan/README.md @@ -7,11 +7,8 @@ A different default set of apps and configurations. Brings many quality of life Before installing do this: 1. Backup your current setup (via the "More..." tab of the App Loader) so you can restore it later if you want. -2. Factory reset the watch. -3. Remove all apps via the "More..." tab in the App Loader. -4. Make sure minification is turned off on the App Loader. -5. Then install. -6. Try it out, switch out apps to your favorites and tweak to your liking! +2. Install this app (you'll be prompted about all data being removed from your Bangle) +3. Try it out, switch out apps to your favorites and tweak to your liking! ## Features diff --git a/apps/confthyttan/metadata.json b/apps/confthyttan/metadata.json index c706d45f57..5fd18c7e90 100644 --- a/apps/confthyttan/metadata.json +++ b/apps/confthyttan/metadata.json @@ -3,8 +3,8 @@ "version":"0.06", "description": "A different default set of apps and configurations. Brings many quality of life improvements. Opinionated based on the creators taste. Read more below before installing.", "icon": "app.png", - "type": "RAM", - "tags": "system, configuration, config, anotherconfig, thyttan", + "type": "defaultconfig", + "tags": "system,configuration,config,anotherconfig,thyttan", "supports" : ["BANGLEJS2"], "readme": "README.md", "dependencies" : { @@ -13,7 +13,6 @@ "messageicons":"app", "widmsggrid":"app", "msgwakefup":"app", - "msgtwscr":"app", "delaylock":"app", "notify":"app", "health":"app", diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 086c2e551d..80f8abe24d 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -169,7 +169,7 @@ const APP_KEYS = [ const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports', 'noOverwrite']; const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate']; const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports' -const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","scheduler","notify","locale","settings","textinput","module","clkinfo"]; // values allowed for "type" field +const METADATA_TYPES = ["app","clock","widget","bootloader","RAM","launch","scheduler","notify","locale","settings","textinput","module","clkinfo","defaultconfig"]; // values allowed for "type" field - listed in README.md const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ]; const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"]; @@ -207,6 +207,10 @@ apps.forEach((app,appIdx) => { if (!app.name) ERROR(`App ${app.id} has no name`, {file:metadataFile}); var isApp = !app.type || app.type=="app"; var appTags = app.tags ? app.tags.split(",") : []; + /*if (appTags.some(tag => tag!=tag.trim())) + WARN(`App ${app.id} 'tag' list contains whitespace ("${app.tags}")`, {file:metadataFile}); + if (appTags.some(tag => tag!=tag.toLowerCase())) + WARN(`App ${app.id} 'tag' list contains uppercase ("${app.tags}")`, {file:metadataFile});*/ if (app.name.length>20 && !app.shortName && isApp) ERROR(`App ${app.id} has a long name, but no shortName`, {file:metadataFile}); if (app.type && !METADATA_TYPES.includes(app.type)) ERROR(`App ${app.id} 'type' is one one of `+METADATA_TYPES, {file:metadataFile}); @@ -296,7 +300,8 @@ apps.forEach((app,appIdx) => { if (INTERNAL_FILES_IN_APP_TYPE[app.type].includes(file.name)) fileInternal = true; } - allFiles.push({app: app.id, file: file.name, internal:fileInternal}); + if (!app.type=="defaultconfig") + allFiles.push({app: app.id, file: file.name, internal:fileInternal}); if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`, {file:metadataFile}); if (!file.url && !file.content && !app.custom) ERROR(`App ${app.id} file ${file.name} has no contents`, {file:metadataFile}); var fileContents = ""; @@ -494,7 +499,7 @@ while(fileA=allFiles.pop()) { if (isGlob(nameA)||isGlob(nameB)) ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`); else if (fileA.app != fileB.app && (!fileA.internal) && (!fileB.internal)) - WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`); + WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`, {file:APPSDIR_RELATIVE+fileB.app+"/metadata.json"}); } }) } diff --git a/core b/core index bf08b48483..3ec8e289a2 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit bf08b484830ef4e811faf67ec663ebf839b5d09b +Subproject commit 3ec8e289a26a545d0d0c50f6945978584fb3d7f8 diff --git a/typescript/types/info.d.ts b/typescript/types/info.d.ts index c305b02612..21014ff8fc 100644 --- a/typescript/types/info.d.ts +++ b/typescript/types/info.d.ts @@ -14,4 +14,4 @@ type AppInfo = { type AppType = "app" | "clock" | "widget" | "module" | "bootloader" | "settings" | "clkinfo" | "RAM" | "launch" | "textinput" | "scheduler" | - "notify" | "locale"; + "notify" | "locale" | "defaultconfig"; From fd3944f5d65c6c4b17b3d4dfaba9c0e57373f823 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 4 Feb 2025 12:38:56 +0000 Subject: [PATCH 073/135] Fix up app metadata - spaces/uppercase in tags meant these apps wouldn't have appeared in some searches --- README.md | 2 +- apps/UI4swatch/metadata.json | 2 +- apps/Uke/metadata.json | 4 ++-- apps/bblobface/metadata.json | 2 +- apps/beeptest/metadata.json | 2 +- apps/bordle/metadata.json | 2 +- apps/calclock/metadata.json | 2 +- apps/cassioWatch/metadata.json | 2 +- apps/chronlog/metadata.json | 2 +- apps/color_catalog/metadata.json | 2 +- apps/delaylock/metadata.json | 2 +- apps/dinoClock/metadata.json | 2 +- apps/followtherecipe/metadata.json | 2 +- apps/gassist/metadata.json | 2 +- apps/gbdiscon/metadata.json | 2 +- apps/golfview/metadata.json | 4 ++-- apps/guitar/metadata.json | 4 ++-- apps/guitarsongs/metadata.json | 2 +- apps/intervalTimer/metadata.json | 2 +- apps/kanagsec/metadata.json | 12 ++++++------ apps/ohmcalc/metadata.json | 2 +- apps/pastel/metadata.json | 2 +- apps/poweroff/metadata.json | 2 +- apps/quicklaunch/metadata.json | 2 +- apps/rescalc/metadata.json | 2 +- apps/scribble/metadata.json | 2 +- apps/sevenmin/metadata.json | 2 +- apps/spaceclock/metadata.json | 4 ++-- apps/swiperclocklaunch/metadata.json | 2 +- apps/tabanchi/metadata.json | 2 +- apps/testuserinput/metadata.json | 2 +- apps/timestamplog/metadata.json | 2 +- apps/tinydraw/metadata.json | 2 +- apps/weatherClock/metadata.json | 2 +- apps/widscrlock/metadata.json | 4 ++-- bin/sanitycheck.js | 4 ++-- 36 files changed, 47 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 13da10b0ae..b9b770b374 100644 --- a/README.md +++ b/README.md @@ -271,7 +271,7 @@ and which gives information about the app for the Launcher. // 'locale' - provides 'locale' library for language-specific date/distance/etc // (a version of 'locale' is included in the firmware) // 'defaultconfig' - a set of apps that will can be installed and will wipe out all previously installed apps - "tags": "", // comma separated tag list for searching + "tags": "", // comma separated tag list for searching (don't include uppercase or spaces) // common types are: // 'clock' - it's a clock // 'widget' - it is (or provides) a widget diff --git a/apps/UI4swatch/metadata.json b/apps/UI4swatch/metadata.json index bcb0e6c51d..5b4abf4061 100644 --- a/apps/UI4swatch/metadata.json +++ b/apps/UI4swatch/metadata.json @@ -5,7 +5,7 @@ "version": "0.02", "description": "A UI/UX for espruino smartwatches, displays dinamically calc. x,y coordinates.", "icon": "app.png", - "tags": "Color,input,buttons,touch,UI", + "tags": "color,input,buttons,touch,ui", "supports": ["BANGLEJS"], "readme": "README.md", "screenshots": [{"url":"UI4swatch_icon.png"},{"url":"UI4swatch_s1.png"}], diff --git a/apps/Uke/metadata.json b/apps/Uke/metadata.json index 5a3f17639f..1185c7202c 100644 --- a/apps/Uke/metadata.json +++ b/apps/Uke/metadata.json @@ -4,8 +4,8 @@ "version": "0.04", "description": "Wrist mounted ukulele chords", "icon": "app.png", - "tags": "uke, chords", - "supports" : ["BANGLEJS2"], + "tags": "uke,chords", + "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"Uke.app.js","url":"app.js"}, diff --git a/apps/bblobface/metadata.json b/apps/bblobface/metadata.json index 6af247c913..8393755b09 100644 --- a/apps/bblobface/metadata.json +++ b/apps/bblobface/metadata.json @@ -6,7 +6,7 @@ "description": "A fully featured watch face with a playable game on the side.", "readme":"README.md", "type": "clock", - "tags": "clock, game", + "tags": "clock,game", "supports" : ["BANGLEJS2"], "storage": [ {"name":"bblobface.app.js","url":"app.js"}, diff --git a/apps/beeptest/metadata.json b/apps/beeptest/metadata.json index a9856bc932..7c25a38488 100644 --- a/apps/beeptest/metadata.json +++ b/apps/beeptest/metadata.json @@ -5,7 +5,7 @@ "version": "0.01", "description": "Aerobic fitness test created by Léger & Lambert", "icon": "beeptest.png", - "tags": "Health", + "tags": "health", "supports": ["BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/bordle/metadata.json b/apps/bordle/metadata.json index f6011f7988..0dbcf09f91 100644 --- a/apps/bordle/metadata.json +++ b/apps/bordle/metadata.json @@ -6,7 +6,7 @@ "description": "Bangle version of a popular word search game", "supports" : ["BANGLEJS2"], "readme": "README.md", - "tags": "game, text", + "tags": "game,text", "storage": [ {"name":"bordle.app.js","url":"bordle.app.js"}, {"name":"wordlencr.txt","url":"wordlencr.txt"}, diff --git a/apps/calclock/metadata.json b/apps/calclock/metadata.json index c339e8ce0e..31dcb88d08 100644 --- a/apps/calclock/metadata.json +++ b/apps/calclock/metadata.json @@ -6,7 +6,7 @@ "description": "Show the current and upcoming events synchronized from Gadgetbridge", "icon": "calclock.png", "type": "clock", - "tags": "clock agenda", + "tags": "clock,agenda", "supports": ["BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/cassioWatch/metadata.json b/apps/cassioWatch/metadata.json index fb7dfd4014..5ec12e751b 100644 --- a/apps/cassioWatch/metadata.json +++ b/apps/cassioWatch/metadata.json @@ -6,7 +6,7 @@ "icon": "app.png", "version": "0.13", "type": "clock", - "tags": "clock, weather, cassio, retro", + "tags": "clock,weather,cassio,retro", "supports": ["BANGLEJS2"], "allow_emulator": true, "readme": "README.md", diff --git a/apps/chronlog/metadata.json b/apps/chronlog/metadata.json index 8ed618b279..50a9166bf4 100644 --- a/apps/chronlog/metadata.json +++ b/apps/chronlog/metadata.json @@ -3,7 +3,7 @@ "version":"0.01", "description": "Record time active on a task, course, work or anything really.", "icon": "app.png", - "tags": "logging, record, work, tasks", + "tags": "logging,record,work,tasks", "supports" : ["BANGLEJS2"], "readme": "README.md", "screenshots" : [ { "url":"dump.png"}, { "url":"dump1.png" }, { "url":"dump2.png" }, { "url":"dump3.png" }, { "url":"dump4.png" }, { "url":"dump5.png" }, { "url":"dump6.png" } ], diff --git a/apps/color_catalog/metadata.json b/apps/color_catalog/metadata.json index 4d49308ef9..e445e31756 100644 --- a/apps/color_catalog/metadata.json +++ b/apps/color_catalog/metadata.json @@ -5,7 +5,7 @@ "version": "0.03", "description": "Displays RGB565 and RGB888 colors, its name and code in screen.", "icon": "app.png", - "tags": "Color,input,buttons,touch,UI", + "tags": "color,input,buttons,touch,ui", "supports": ["BANGLEJS"], "readme": "README.md", "storage": [ diff --git a/apps/delaylock/metadata.json b/apps/delaylock/metadata.json index dff4d92198..7441d822be 100644 --- a/apps/delaylock/metadata.json +++ b/apps/delaylock/metadata.json @@ -3,7 +3,7 @@ "version":"0.01", "description": "Delay the locking of the screen to 5 seconds after the backlight turns off.", "icon": "app.png", - "tags": "settings, configuration, backlight, touchscreen, screen", + "tags": "settings,configuration,backlight,touchscreen,screen", "type": "bootloader", "supports" : ["BANGLEJS2"], "readme": "README.md", diff --git a/apps/dinoClock/metadata.json b/apps/dinoClock/metadata.json index a61ce122b5..1455e84a64 100644 --- a/apps/dinoClock/metadata.json +++ b/apps/dinoClock/metadata.json @@ -6,7 +6,7 @@ "icon": "app.png", "version": "0.01", "type": "clock", - "tags": "clock, weather, dino, trex, chrome", + "tags": "clock,weather,dino,trex,chrome", "supports": ["BANGLEJS2"], "allow_emulator": true, "readme": "README.md", diff --git a/apps/followtherecipe/metadata.json b/apps/followtherecipe/metadata.json index 0c1de08178..59fabc8c5e 100644 --- a/apps/followtherecipe/metadata.json +++ b/apps/followtherecipe/metadata.json @@ -6,7 +6,7 @@ "version": "0.02", "description": "Follow The Recipe (FTR) is a bangle.js app to follow a recipe step by step", "type": "app", - "tags": "tool, tools, cook", + "tags": "tool,tools,cook", "supports": [ "BANGLEJS2" ], diff --git a/apps/gassist/metadata.json b/apps/gassist/metadata.json index 995c44adb8..bd38cdfb8b 100644 --- a/apps/gassist/metadata.json +++ b/apps/gassist/metadata.json @@ -5,7 +5,7 @@ "description": "A simple way to initiate Google Assistant on Android. Intents must be enabled in Gadgetbridge.", "icon": "app.png", "type": "app", - "tags": "tool, voice, tasker", + "tags": "tool,voice,tasker", "supports": ["BANGLEJS","BANGLEJS2"], "allow_emulator": false, "storage": [ diff --git a/apps/gbdiscon/metadata.json b/apps/gbdiscon/metadata.json index ecc92d01cf..904b4c6a22 100644 --- a/apps/gbdiscon/metadata.json +++ b/apps/gbdiscon/metadata.json @@ -4,7 +4,7 @@ "version":"0.01", "description": "Disconnect from your android device by running this app. The app will forward you to your clock face immediately after triggering the command. (Gadgetbridge nightly required until version 82 is released)", "icon": "app.png", - "tags": "android, gadgetbridge, bluetooth, bt", + "tags": "android,gadgetbridge,bluetooth,bt", "supports" : ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"gbdiscon.app.js","url":"app.js"}, diff --git a/apps/golfview/metadata.json b/apps/golfview/metadata.json index bc3a00f901..cf77f3a264 100644 --- a/apps/golfview/metadata.json +++ b/apps/golfview/metadata.json @@ -3,9 +3,9 @@ "version": "0.03", "description": "This app will provide you with on course data to support your golf game!", "icon": "golfview.png", - "tags": "outdoors, gps", + "tags": "outdoors,gps", "allow_emulator": true, - "supports" : ["BANGLEJS2"], + "supports" : ["BANGLEJS2"], "readme": "README.md", "custom": "custom.html", "storage": [ diff --git a/apps/guitar/metadata.json b/apps/guitar/metadata.json index 0dc6893d6d..7b4683c472 100644 --- a/apps/guitar/metadata.json +++ b/apps/guitar/metadata.json @@ -4,8 +4,8 @@ "version": "0.03", "description": "Wrist mounted guitar chords", "icon": "app.png", - "tags": "guitar, chords", - "supports" : ["BANGLEJS2"], + "tags": "guitar,chords", + "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"guitar.app.js","url":"app.js"}, diff --git a/apps/guitarsongs/metadata.json b/apps/guitarsongs/metadata.json index 242850a703..18e1f7146c 100644 --- a/apps/guitarsongs/metadata.json +++ b/apps/guitarsongs/metadata.json @@ -5,7 +5,7 @@ "description": "Songs lyrics and guitar chords", "icon": "app.png", "screenshots": [{"url": "screenshot.png"}], - "tags": "guitar, song, lyrics, chords", + "tags": "guitar,song,lyrics,chords", "supports" : ["BANGLEJS2"], "interface": "manage_songs.html", "readme": "README.md", diff --git a/apps/intervalTimer/metadata.json b/apps/intervalTimer/metadata.json index 2722473c1c..a0489833ce 100644 --- a/apps/intervalTimer/metadata.json +++ b/apps/intervalTimer/metadata.json @@ -5,7 +5,7 @@ "icon": "app.png", "version":"0.01", "description": "Interval Timer for workouts, HIIT, or whatever else.", - "tags": "timer, interval, hiit, workout", + "tags": "timer,interval,hiit,workout", "readme":"README.md", "supports":["BANGLEJS2"], "storage": [ diff --git a/apps/kanagsec/metadata.json b/apps/kanagsec/metadata.json index c00ec9d7ad..2e3376c5b6 100644 --- a/apps/kanagsec/metadata.json +++ b/apps/kanagsec/metadata.json @@ -1,23 +1,23 @@ -{ +{ "id": "kanagsec", "name": "Kanagawa clock", "shortName":"kanagawa", "version": "0.04", "description": "A clock that displays the great wave of kanagawa (image from wikipedia) with seconds in active mode.", "icon": "app.png", - "tags": "clock, kanagawa, wave", + "tags": "clock,kanagawa,wave", "type": "clock", - "supports" : ["BANGLEJS2"], + "supports" : ["BANGLEJS2"], "readme": "README.md", "allow_emulator":true, - "storage": + "storage": [ {"name":"kanagsec.app.js","url":"app.js"}, {"name":"kanagsec.img","url":"app-icon.js","evaluate":true} ], - "screenshots" : + "screenshots" : [ { "url":"screenshot.png" }, - { "url":"screenshot2.png" } + { "url":"screenshot2.png" } ] } \ No newline at end of file diff --git a/apps/ohmcalc/metadata.json b/apps/ohmcalc/metadata.json index c72727a4cc..2ab25947f3 100644 --- a/apps/ohmcalc/metadata.json +++ b/apps/ohmcalc/metadata.json @@ -6,7 +6,7 @@ "description": "A smart and simple calculator for Ohm's Law calculations, designed specifically for Bangle.js 2 smartwatches. Handles voltage, current, resistance, and power calculations with smart logic to prevent invalid inputs.", "icon": "app.png", "type": "app", - "tags": "calculator, utilities, electric", + "tags": "calculator,utilities,electric", "supports": ["BANGLEJS2"], "readme": "README.md", "allow_emulator": true, diff --git a/apps/pastel/metadata.json b/apps/pastel/metadata.json index 532aa8ccc8..5d1f925fe2 100644 --- a/apps/pastel/metadata.json +++ b/apps/pastel/metadata.json @@ -8,7 +8,7 @@ "dependencies": {"mylocation":"app","weather":"app"}, "screenshots": [{"url":"screenshot_pastel.png"}, {"url":"weather_icons.png"}], "type": "clock", - "tags": "clock, weather, tool", + "tags": "clock,weather,tool", "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/poweroff/metadata.json b/apps/poweroff/metadata.json index 218e4b441c..b9a7d60ea0 100644 --- a/apps/poweroff/metadata.json +++ b/apps/poweroff/metadata.json @@ -4,7 +4,7 @@ "version": "0.05", "description": "Simple app to power off your Bangle.js", "icon": "app.png", -"tags": "tool, poweroff, shutdown", +"tags": "tool,poweroff,shutdown", "supports" : ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "allow_emulator": true, diff --git a/apps/quicklaunch/metadata.json b/apps/quicklaunch/metadata.json index 15c40dfdca..95ae0b014a 100644 --- a/apps/quicklaunch/metadata.json +++ b/apps/quicklaunch/metadata.json @@ -5,7 +5,7 @@ "version": "0.16", "description": "Tap or swipe left/right/up/down on your clock face to launch up to five apps of your choice. Configurations can be accessed through Settings->Apps.", "type": "bootloader", - "tags": "tools, system", + "tags": "tools,system", "readme": "README.md", "supports": ["BANGLEJS2"], "storage": [ diff --git a/apps/rescalc/metadata.json b/apps/rescalc/metadata.json index cd2b7ea310..f7f7c5e29b 100644 --- a/apps/rescalc/metadata.json +++ b/apps/rescalc/metadata.json @@ -10,7 +10,7 @@ {"url": "screenshot-2.png"} ], "description": "An intuitive, easy-to-use app that aids in the interpretation of resistor color codes and calculation of resistance values.", - "tags": "app, tool, electricity, ohms, converter", + "tags": "app,tool,electricity,ohms,converter", "supports": ["BANGLEJS2"], "readme": "README.md", "allow_emulator": true, diff --git a/apps/scribble/metadata.json b/apps/scribble/metadata.json index 2c31be931a..19c6c707c8 100644 --- a/apps/scribble/metadata.json +++ b/apps/scribble/metadata.json @@ -6,7 +6,7 @@ "description": "A keyboard on your wrist! Swipe right for space, left for delete.", "icon": "app.png", "allow_emulator": true, - "tags": "tools, keyboard, text, scribble", + "tags": "tools,keyboard,text,scribble", "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/sevenmin/metadata.json b/apps/sevenmin/metadata.json index 5103a5f970..8a1867e4a0 100644 --- a/apps/sevenmin/metadata.json +++ b/apps/sevenmin/metadata.json @@ -5,7 +5,7 @@ "description": "A basic implementation of the famous consice workout", "icon": "icon.png", "type":"app", - "tags": "Training, Workout", + "tags": "training,workout", "supports": ["BANGLEJS2"], "readme": "README.md", "allow_emulator":true, diff --git a/apps/spaceclock/metadata.json b/apps/spaceclock/metadata.json index 1e8bc266fd..cff458d085 100644 --- a/apps/spaceclock/metadata.json +++ b/apps/spaceclock/metadata.json @@ -5,8 +5,8 @@ "description": "Watch face in the style of Casio Prototype Space Resist", "icon": "app-icon.png", "type": "clock", - "tags": "clock, casio, retro", - "supports" : ["BANGLEJS2"], + "tags": "clock,casio,retro", + "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"spaceclock.app.js","url":"app.js"}, diff --git a/apps/swiperclocklaunch/metadata.json b/apps/swiperclocklaunch/metadata.json index d474b38e30..6bb24987ef 100644 --- a/apps/swiperclocklaunch/metadata.json +++ b/apps/swiperclocklaunch/metadata.json @@ -5,7 +5,7 @@ "description": "Navigate between clock and launcher with Swipe action", "icon": "swiperclocklaunch.png", "type": "bootloader", - "tags": "tools, system", + "tags": "tools,system", "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ {"name":"swiperclocklaunch.boot.js","url":"boot.js"}, diff --git a/apps/tabanchi/metadata.json b/apps/tabanchi/metadata.json index db81707b50..43ebc62acc 100644 --- a/apps/tabanchi/metadata.json +++ b/apps/tabanchi/metadata.json @@ -7,7 +7,7 @@ "description": "Tamagotchi WatchApp", "icon": "app.png", "allow_emulator": true, - "tags": "clock, watch, virtual pet", + "tags": "clock,watch,virtualpet", "supports": [ "BANGLEJS2" ], diff --git a/apps/testuserinput/metadata.json b/apps/testuserinput/metadata.json index 4098431986..39fab86af5 100644 --- a/apps/testuserinput/metadata.json +++ b/apps/testuserinput/metadata.json @@ -5,7 +5,7 @@ "version": "0.08", "description": "App to test the bangle.js input interface. It displays the user action in text, circle buttons or on/off switch UI elements.", "icon": "app.png", - "tags": "input,interface,buttons,touch,UI", + "tags": "input,interface,buttons,touch,ui", "supports": ["BANGLEJS"], "readme": "README.md", "storage": [ diff --git a/apps/timestamplog/metadata.json b/apps/timestamplog/metadata.json index e1aa0eb239..6f0126c4a7 100644 --- a/apps/timestamplog/metadata.json +++ b/apps/timestamplog/metadata.json @@ -7,7 +7,7 @@ "description": "Conveniently record a series of date/time stamps", "screenshots": [ {"url": "screenshot.png" } ], "readme": "README.md", - "tags": "timestamp, log", + "tags": "timestamp,log", "supports": ["BANGLEJS2"], "interface": "interface.html", "storage": [ diff --git a/apps/tinydraw/metadata.json b/apps/tinydraw/metadata.json index 21ea1eb89a..61f4129e82 100644 --- a/apps/tinydraw/metadata.json +++ b/apps/tinydraw/metadata.json @@ -6,7 +6,7 @@ "description": "Draw stuff in your wrist", "icon": "app.png", "allow_emulator": true, - "tags": "tools, keyboard, text, scribble", + "tags": "tools,keyboard,text,scribble", "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/apps/weatherClock/metadata.json b/apps/weatherClock/metadata.json index 88057c8dd3..b1b586a211 100644 --- a/apps/weatherClock/metadata.json +++ b/apps/weatherClock/metadata.json @@ -8,7 +8,7 @@ "dependencies": {"weather":"app"}, "screenshots": [{"url":"screens/screen1.png"}], "type": "clock", - "tags": "clock, weather", + "tags": "clock,weather", "supports": ["BANGLEJS","BANGLEJS2"], "allow_emulator": true, "readme": "README.md", diff --git a/apps/widscrlock/metadata.json b/apps/widscrlock/metadata.json index 5110d76c1d..568c61b937 100644 --- a/apps/widscrlock/metadata.json +++ b/apps/widscrlock/metadata.json @@ -3,9 +3,9 @@ "shortName":"Screenlock", "version":"0.03", "description": "Lock a Bangle 2 screen by tapping a widget.", - "icon": "widget.png", + "icon": "widget.png", "type": "widget", - "tags": "widget, screenlock", + "tags": "widget,screenlock", "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 80f8abe24d..5432999eb6 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -207,10 +207,10 @@ apps.forEach((app,appIdx) => { if (!app.name) ERROR(`App ${app.id} has no name`, {file:metadataFile}); var isApp = !app.type || app.type=="app"; var appTags = app.tags ? app.tags.split(",") : []; - /*if (appTags.some(tag => tag!=tag.trim())) + if (appTags.some(tag => tag!=tag.trim())) WARN(`App ${app.id} 'tag' list contains whitespace ("${app.tags}")`, {file:metadataFile}); if (appTags.some(tag => tag!=tag.toLowerCase())) - WARN(`App ${app.id} 'tag' list contains uppercase ("${app.tags}")`, {file:metadataFile});*/ + WARN(`App ${app.id} 'tag' list contains uppercase ("${app.tags}")`, {file:metadataFile}); if (app.name.length>20 && !app.shortName && isApp) ERROR(`App ${app.id} has a long name, but no shortName`, {file:metadataFile}); if (app.type && !METADATA_TYPES.includes(app.type)) ERROR(`App ${app.id} 'type' is one one of `+METADATA_TYPES, {file:metadataFile}); From 9078a7bd014e7f0bccaf90f4fc989cde140d9b8e Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Feb 2025 09:45:07 +0000 Subject: [PATCH 074/135] remove known warnings from list by default so we can see new errors more clearly (fix #3733) --- bin/sanitycheck.js | 48 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 5432999eb6..5366ab2945 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -2,6 +2,31 @@ /* Checks for any obvious problems in apps.json */ +var BASEDIR = __dirname+"/../"; +var APPSDIR_RELATIVE = "apps/"; +var APPSDIR = BASEDIR + APPSDIR_RELATIVE; +var showAllErrors = process.argv.includes("--show-all"); + +if (process.argv.includes("--help")) { + console.log(`BangleApps Sanity Check +------------------------ + +Checks apps in this repository for common issues that might +cause problems. + +USAGE: + +bin/sanitycheck.js + - default, runs all tests (hides known errors) +bin/sanitycheck.js --show-all + - show all warnings/errors (including known ones) +bin/sanitycheck.js --help + - show this message +`); + process.exit(0); +} + + var fs = require("fs"); var vm = require("vm"); var heatshrink = require("../webtools/heatshrink"); @@ -27,9 +52,7 @@ var jsparse = (() => { return str => acorn.parse(str, { ecmaVersion: 2020 }); })(); -var BASEDIR = __dirname+"/../"; -var APPSDIR_RELATIVE = "apps/"; -var APPSDIR = BASEDIR + APPSDIR_RELATIVE; + var knownWarningCount = 0; var knownErrorCount = 0; var warningCount = 0; @@ -38,23 +61,23 @@ function ERROR(msg, opt) { // file=app.js,line=1,col=5,endColumn=7 opt = opt||{}; if (KNOWN_ERRORS.includes(msg)) { - console.log(`Known error : ${msg}`); knownErrorCount++; - } else { - console.log(`::error${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`); - errorCount++; + if (!showAllErrors) return; + msg += " (KNOWN)" } + console.log(`::error${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`); + errorCount++; } function WARN(msg, opt) { // file=app.js,line=1,col=5,endColumn=7 opt = opt||{}; if (KNOWN_WARNINGS.includes(msg)) { - console.log(`Known warning : ${msg}`); knownWarningCount++; - } else { - console.log(`::warning${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`); - warningCount++; + if (!showAllErrors) return; + msg += " (KNOWN)" } + console.log(`::warning${Object.keys(opt).length?" ":""}${Object.keys(opt).map(k=>k+"="+opt[k]).join(",")}::${msg}`); + warningCount++; } /* These are errors that we temporarily allow */ var KNOWN_ERRORS = [ @@ -526,7 +549,8 @@ function sanityCheckLocales(){ promise.then(function() { console.log("=================================="); - console.log(`${errorCount} errors, ${warningCount} warnings (and ${knownErrorCount} known errors, ${knownWarningCount} known warnings)`); + console.log(`${errorCount} errors, ${warningCount} warnings`); + console.log(`${knownErrorCount} known errors, ${knownWarningCount} known warnings${(knownErrorCount||knownWarningCount)?", run with --show-all to see them":""}`); console.log("=================================="); if (errorCount) { process.exit(1); From 4f3933cd16037facf0cd7998b9304d76faa1ad5b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Feb 2025 10:11:55 +0000 Subject: [PATCH 075/135] now check for outdated known warnings/errors --- bin/sanitycheck.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 5366ab2945..e4532b41bd 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -57,9 +57,13 @@ var knownWarningCount = 0; var knownErrorCount = 0; var warningCount = 0; var errorCount = 0; +var warningList = []; +var errorList = []; + function ERROR(msg, opt) { // file=app.js,line=1,col=5,endColumn=7 opt = opt||{}; + errorList.push(msg); if (KNOWN_ERRORS.includes(msg)) { knownErrorCount++; if (!showAllErrors) return; @@ -71,6 +75,7 @@ function ERROR(msg, opt) { function WARN(msg, opt) { // file=app.js,line=1,col=5,endColumn=7 opt = opt||{}; + warningList.push(msg); if (KNOWN_WARNINGS.includes(msg)) { knownWarningCount++; if (!showAllErrors) return; @@ -136,7 +141,6 @@ var KNOWN_ERRORS = [ var KNOWN_WARNINGS = [ "App gpsrec data file wildcard .gpsrc? does not include app ID", "App owmweather data file weather.json is also listed as data file for app weather", - "App messagegui storage file messagegui is also listed as storage file for app messagelist", "App carcrazy has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"carcrazy.settings.json\"}]`)", "App loadingscreen has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"loadingscreen.settings.json\"}]`)", "App trex has a setting file but no corresponding data entry (add `\"data\":[{\"name\":\"trex.settings.json\"}]`)", @@ -548,6 +552,14 @@ function sanityCheckLocales(){ } promise.then(function() { + KNOWN_ERRORS.forEach(msg => { + if (!errorList.includes(msg)) + WARN(`Known error '${msg}' no longer occurs`); + }); + KNOWN_WARNINGS.forEach(msg => { + if (!warningList.includes(msg)) + WARN(`Known warning '${msg}' no longer occurs`); + }); console.log("=================================="); console.log(`${errorCount} errors, ${warningCount} warnings`); console.log(`${knownErrorCount} known errors, ${knownWarningCount} known warnings${(knownErrorCount||knownWarningCount)?", run with --show-all to see them":""}`); From ead737c735cd6281580c9f2fdee11952689132bb Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 5 Feb 2025 10:16:04 +0000 Subject: [PATCH 076/135] Update locales to avoid some sanity check errors based on month/etc length --- apps/locale/locales.js | 18 +++++++++--------- bin/sanitycheck.js | 28 ---------------------------- 2 files changed, 9 insertions(+), 37 deletions(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index c704e0f904..1e30812275 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -261,7 +261,7 @@ var locales = { ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%d %B %Y", "1": "%d/%m/%Y" }, // 1 mars 2020 // 01/03/2020 - abmonth: "janv,févr,mars,avril,mai,juin,juil,août,sept,oct,nov,déc", + abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", @@ -423,7 +423,7 @@ var locales = { ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %B %d %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 - abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", + abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", @@ -452,7 +452,7 @@ var locales = { speed: "kmh", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: { 0: "vorm", 1: " nachm" }, + ampm: { 0: "vorm", 1: "nachm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A, %d. %B %Y", "1": "%d.%m.%Y" }, // Sonntag, 1. März 2020 // 1.3.2020 abmonth: "Jan,Feb,März,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez", @@ -471,7 +471,7 @@ var locales = { ampm: { 0: "AM", 1: "PM" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %d %B %Y", "1": "%d/%m/%y" }, // dimanche 1 mars 2020 // 01/03/20 - abmonth: "janv.,févr.,mars,avril,mai,juin,juil.,août,sept.,oct.,nov.,déc.", + abmonth: "janv,févr,mars,avr,mai,juin,juil,août,sept,oct,nov,déc", month: "janvier,février,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre", abday: "dim,lun,mar,mer,jeu,ven,sam", day: "dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi", @@ -567,7 +567,7 @@ var locales = { ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%A %d %B de %Y", "1": "%d/%m/%Y" }, // dimenge 1 de març de 2020 // 01/03/2020 - abmonth: "gen.,febr.,març,abril,mai,junh,julh,ago.,set.,oct.,nov.,dec.", + abmonth: "gen,febr,març,abril,mai,junh,julh,ago,set,oct,nov,dec", month: "genièr,febrièr,març,abril,mai,junh,julhet,agost,setembre,octòbre,novembre,decembre", abday: "dg,dl,dm,dc,dj,dv,ds", day: "dimenge,diluns,dimars,dimècres,dijòus,divendres,dissabte", @@ -612,10 +612,10 @@ var locales = { speed: "km/h", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: { 0: "dop.", 1: "pop." }, + ampm: { 0: "dop", 1: "pop" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%-d. %b %Y", 1: "%-d.%-m.%Y" }, // "3. jan. 2020" // "3.1.2020"(short) - abmonth: "sij.,velj.,ožu.,tra.,svi,lip.,srp.,kol.,ruj.,lis.,stu.,pro.", + abmonth: "sij,velj,ožu,tra,svi,lip,srp,kol,ruj,lis,stu,pro", month: "siječanj,veljača,ožujak,travanj,svibanj,lipanj,srpanj,kolovoz,rujan,listopad,studeni,prosinac", abday: "ned.,pon.,uto.,sri.,čet.,pet.,sub.", day: "nedjelja,ponedjeljak,utorak,srijeda,četvrtak,petak,subota", @@ -628,7 +628,7 @@ var locales = { speed: "km/h", distance: { 0: "m", 1: "km" }, temperature: "°C", - ampm: { 0: "dop.", 1: "pop." }, + ampm: { 0: "dop", 1: "pop" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%-d. %b %Y", 1: "%-d.%-m.%Y" }, // "3. jan. 2020" // "3.1.2020"(short) abmonth: "jan.,feb.,mar.,apr.,maj,jun.,jul.,avg.,sep.,okt.,nov.,dec.", @@ -728,7 +728,7 @@ var locales = { ampm: { 0: "am", 1: "pm" }, timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, datePattern: { 0: "%d %B %Y", "1": "%d/%m/%y" }, - abmonth: "gen.,febr.,març,abr.,maig,juny,jul.,ag.,set.,oct.,nov.,des.", + abmonth: "gen,febr,març,abr,maig,juny,jul,ag,set,oct,nov,des", month: "gener,febrer,març,abril,maig,juny,juliol,agost,setembre,octubre,novembre,desembre", abday: "dg.,dl.,dt.,dc.,dj.,dv.,ds.", day: "diumenge,dilluns,dimarts,dimecres,dijous,divendres,dissabte", diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index e4532b41bd..75f740d4fa 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -88,7 +88,6 @@ function WARN(msg, opt) { var KNOWN_ERRORS = [ "In locale en_CA, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)", "In locale fr_FR, long date output must be shorter than 15 characters (10 septembre 2024 -> 17)", - "In locale fr_FR, short month must be shorter than 5 characters", "In locale sv_SE, speed must be shorter than 5 characters", "In locale en_SE, long date output must be shorter than 15 characters (September 10 2024 -> 17)", "In locale en_NZ, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)", @@ -97,45 +96,18 @@ var KNOWN_ERRORS = [ "In locale en_IL, long date output must be shorter than 15 characters (Wednesday, September 10, 2024 -> 29)", "In locale es_ES, long date output must be shorter than 15 characters (miércoles, 10 de septiembre de 2024 -> 35)", "In locale fr_BE, long date output must be shorter than 15 characters (dimanche septembre 10 2024 -> 26)", - "In locale fr_BE, short month must be shorter than 5 characters", - "In locale fr_BE, short month must be shorter than 5 characters", - "In locale fr_BE, short month must be shorter than 5 characters", - "In locale fr_BE, short month must be shorter than 5 characters", - "In locale fr_BE, short month must be shorter than 5 characters", "In locale fi_FI, long date output must be shorter than 15 characters (keskiviikkona 10. maaliskuuta 2024 -> 34)", "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", - "In locale fi_FI, short month must be shorter than 5 characters", "In locale de_CH, meridian must be shorter than 4 characters", "In locale de_CH, meridian must be shorter than 4 characters", "In locale de_CH, long date output must be shorter than 15 characters (Donnerstag, 10. September 2024 -> 30)", "In locale fr_CH, long date output must be shorter than 15 characters (dimanche 10 septembre 2024 -> 26)", - "In locale fr_CH, short month must be shorter than 5 characters", - "In locale fr_CH, short month must be shorter than 5 characters", - "In locale fr_CH, short month must be shorter than 5 characters", - "In locale fr_CH, short month must be shorter than 5 characters", - "In locale fr_CH, short month must be shorter than 5 characters", "In locale wae_CH, long date output must be shorter than 15 characters (Sunntag, 10. Herbštmánet 2024 -> 29)", "In locale tr_TR, long date output must be shorter than 15 characters (10 Haziran 2024 Pazartesi -> 25)", "In locale hu_HU, long date output must be shorter than 15 characters (2024 Szep 10, Csütörtök -> 23)", "In locale oc_FR, long date output must be shorter than 15 characters (divendres 10 setembre de 2024 -> 29)", "In locale oc_FR, short month must be shorter than 5 characters", - "In locale oc_FR, short month must be shorter than 5 characters", - "In locale hr_HR, meridian must be shorter than 4 characters", - "In locale hr_HR, meridian must be shorter than 4 characters", - "In locale hr_HR, short month must be shorter than 5 characters", - "In locale sl_SI, meridian must be shorter than 4 characters", - "In locale sl_SI, meridian must be shorter than 4 characters", "In locale ca_ES, long date output must be shorter than 15 characters (10 setembre 2024 -> 16)", - "In locale ca_ES, short month must be shorter than 5 characters", ]; /* These are warnings we know about but don't want in our output */ var KNOWN_WARNINGS = [ From 7c78e870ab91e541068d2fd4d47b3c9172d99ed5 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 5 Feb 2025 23:11:02 +0100 Subject: [PATCH 077/135] sched: fix type re hidden set to false hiding widget --- apps/sched/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/README.md b/apps/sched/README.md index 1216a1a11f..0fa780405e 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -49,7 +49,7 @@ Alarms are stored in an array in `sched.json`, and take the form: // e.g. repeat every 2 months: { interval: "month", num: 2 }. // Supported intervals: day, week, month, year vibrate : "...", // OPTIONAL pattern of '.', '-' and ' ' to use for when buzzing out this alarm (defaults to '..' if not set) - hidden : false, // OPTIONAL if false, the widget should not show an icon for this alarm + hidden : false, // OPTIONAL if true, the widget should not show an icon for this alarm as : false, // auto snooze timer : 5*60*1000, // OPTIONAL - if set, this is a timer and it's the time in ms del : false, // OPTIONAL - if true, delete the timer after expiration From 87d73be447029b4ba77bfd0c3a5063a1f0fe4072 Mon Sep 17 00:00:00 2001 From: Brian Whelan Date: Fri, 7 Feb 2025 21:52:01 +0000 Subject: [PATCH 078/135] New app "Shortcuts" Adds a new app that allows you to pin apps to clockfaces that support clock_info --- apps/clkshortcuts/ChangeLog | 1 + apps/clkshortcuts/README.md | 10 + .../clkshortcuts/add_shortcuts_screenshot.png | Bin 0 -> 471 bytes apps/clkshortcuts/app-icon.js | 1 + apps/clkshortcuts/app.js | 224 ++++++++++++++++++ apps/clkshortcuts/app.png | Bin 0 -> 1131 bytes apps/clkshortcuts/clkinfo.js | 45 ++++ .../example_shortcuts_screenshot.png | Bin 0 -> 622 bytes apps/clkshortcuts/metadata.json | 17 ++ 9 files changed, 298 insertions(+) create mode 100644 apps/clkshortcuts/ChangeLog create mode 100644 apps/clkshortcuts/README.md create mode 100644 apps/clkshortcuts/add_shortcuts_screenshot.png create mode 100644 apps/clkshortcuts/app-icon.js create mode 100644 apps/clkshortcuts/app.js create mode 100644 apps/clkshortcuts/app.png create mode 100644 apps/clkshortcuts/clkinfo.js create mode 100644 apps/clkshortcuts/example_shortcuts_screenshot.png create mode 100644 apps/clkshortcuts/metadata.json diff --git a/apps/clkshortcuts/ChangeLog b/apps/clkshortcuts/ChangeLog new file mode 100644 index 0000000000..759f687774 --- /dev/null +++ b/apps/clkshortcuts/ChangeLog @@ -0,0 +1 @@ +0.01: New app! \ No newline at end of file diff --git a/apps/clkshortcuts/README.md b/apps/clkshortcuts/README.md new file mode 100644 index 0000000000..0d4b72318d --- /dev/null +++ b/apps/clkshortcuts/README.md @@ -0,0 +1,10 @@ +# Shortcuts + +An app that allows you to create custom ClockInfos that act as shortcuts to your favourite apps. + +## Create a Shortcut +After installing the app, you can open the app to add and manage existing shortcuts. If no shortcuts exist, the app will display a ``[+] Shortcuts`` button as a ClockInfo on your Clock (see screenshots), which when clicked will quickly launch into the app so you can add new shortcuts. + +When adding a shortcut, first select the app you wish to use, then select the icon you wish to register to the shortcut. If a keyboard is installed, you'll get the option to rename the shortcut before saving. + +Once created, your shortcut will appear on any Clocks with ClockInfo support, and tapping the shortcut will launch the chosen app \ No newline at end of file diff --git a/apps/clkshortcuts/add_shortcuts_screenshot.png b/apps/clkshortcuts/add_shortcuts_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..ea7c6273b9f3d4ab4ad05105873455f8224660f8 GIT binary patch literal 471 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(a8A!&?{Fw`+7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$O`0h2Ka=yGW=)w|NlRb7uwr89VA%b5n0T@z;_sg8IR|$NCBD>?&;zfl5y|t zbk0f53L>m0dH>vFcvpXdaf-_UR?YuCX}caX{dl7#GF5`1;j+h3(@4{e9ojei=AYE+ zifxUV7%KXFdvg4pIj(zz;@+%3q2%`G^`ocNA3W~NaE)n^%M{{$2&S+btzkmMCh?l3r5-k<)on|_~=Er%&U#wfGL-2oN zg%5M}I`PA`m8WLNZ+h+9A$Z>}C-`#Z$KO4zH@w`^EOVTCeyBZS-6ZGS^FzKn_iC5K zN7Y9;rxaH|ws>ou?)15lccW|1k8_VsJNEq0J_0tFnZd#O*dK=X$!@D#>el%K!=1s? L)z4*}Q$iB}H6zec literal 0 HcmV?d00001 diff --git a/apps/clkshortcuts/app-icon.js b/apps/clkshortcuts/app-icon.js new file mode 100644 index 0000000000..99f51a2e80 --- /dev/null +++ b/apps/clkshortcuts/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UB/4ACBIM889VAHmqAAwKCrQLH0oLCuBoFhoLCtJ1HtILBtYLH9ILBtALHlILQlRFCwALSnWwgECBY8O1gLJgeoBaojLHZfqAQILIFwMDBY8CFwMO2QLGhwuBlWuBY0K4ED1aDHBYJUBlQLGnRUChQLIKgJHHBYJUBZY8KgZUBBZHCKgILHh2CBZMC0fABZC+CBZBSBC5JUB14MDcY2q1YLIDAILGtY4EAAXpBYNpBY9pBYNauAKFhulBYWqAAwLCqoLHBQQA6A=")) \ No newline at end of file diff --git a/apps/clkshortcuts/app.js b/apps/clkshortcuts/app.js new file mode 100644 index 0000000000..197ca70cff --- /dev/null +++ b/apps/clkshortcuts/app.js @@ -0,0 +1,224 @@ +var storage = require("Storage"); +var keyboard = "textinput"; +try { + keyboard = require(keyboard); +} catch (e) { + keyboard = null; +} + +var icons = [ + {name:"agenda", img :"GBiBAAAAAAA8AAB+AA/n8B/n+BgAGBgAGBn/mBn/mBgAGBgAGBn/mBn/+BgD/BgHDhn+Bhn8MxgMIxgMIx/8Ew/+BgAHDgAD/AAA8A=="}, + {name:"alarm", img:"GBiBAAAAAAAAAAYAYA4AcBx+ODn/nAOBwAcA4A4YcAwYMBgYGBgYGBgYGBgYGBgeGBgHGAwBMA4AcAcA4AOBwAH/gAB+AAAAAAAAAA=="}, + {name:"mail", img:"GBiBAAAAAAAAAAAAAAAAAB//+D///DAADDgAHDwAPDcA7DPDzDDnDDA8DDAYDDAADDAADDAADDAADD///B//+AAAAAAAAAAAAAAAAA=="}, + {name:"android", img: "GBiBAAAAAAEAgAD/AAD/AAHDgAGBgAMkwAMAwAP/wBv/2BsA2BsA2BsA2BsA2BsA2BsA2Bv/2AP/wADnAADnAADnAADnAADnAAAAAA=="}, + {name:"add", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgYGBgYGBgYGBgYGBn/mBn/mBgYGBgYGBgYGBgYGBgAGBgAGB//+A//8AAAAAAAAAAAAA=="}, + {name:"bangle", img:"GBiBAAD+AAH+AAH+AAH+AAH/AAOHAAYBgAwAwBgwYBgwYBgwIBAwOBAwOBgYIBgMYBgAYAwAwAYBgAOHAAH/AAH+AAH+AAH+AAD+AA=="}, + {name:"bike", img:"GBiBAAAAAAAAAAAAAAAD+AAD/AADjAABjAfhnAfjyAMDwAcGwB4O+H8M/GGZ5sD7c8fzM8fjM8DDA2GBhn8B/h4AeAAAAAAAAAAAAA=="}, + {name:"map", img:"GBiBAAAAAAAAAAAAAADgGAf8+B//+BjHGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjDGBjjGB//+B8/4BgHAAAAAAAAAAAAAA=="}, + {name:"play", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBjAGBjwGBj8GBjeGBjHmBjB2BjB2BjHmBjeGBj8GBjwGBjAGBgAGB//+A//8AAAAAAAAAAAAA=="}, + {name:"fast forward", img:"GBiBAAAAAAAAAAAAAH///v///8AAA8YYA8eeA8f/g8b7w8Y488YYO8YYO8Y488b7w8f/g8eeA8YYA8AAA////3///gAAAAAAAAAAAA=="}, + {name:"rewind", img:"GBiBAAAAAAAAAAAAAH///v///8AAA8AYY8B548H/48PfY88cY9wYY9wYY88cY8PfY8H/48B548AYY8AAA////3///gAAAAAAAAAAAA=="}, + {name:"timer", img:"GBiBAAAAAAB+AAB+AAAAMAB+OAH/nAOByAcA4A4YcAwYMBgYGBgYGBgYGBgYGBgAGBgAGAwAMA4AcAcA4AOBwAH/gAB+AAAAAAAAAA=="}, + {name:"connected", img:"GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBngGBn4GBgcGBgOGBnHGBnzGBgxmBgZmBmZmBmZmBgAGBgAGB//+A//8AAAAAAAAAAAAA=="}, + {name:"lock", img:"GBiBAAAAAAA8AAD/AAHDgAGBgAMAwAMAwAMAwAf/4A//8AwAMAwAMAwAMAwYMAw8MAw8MAwYMAwAMAwAMAwAMA//8Af/4AAAAAAAAA=="}, + {name:"battery", img:"GBiBAAAAAAAAAAB+AAB+AAHngAPnwAMAwAMAwAMIwAMIwAMYwAM4wAM+wAN8wAMcwAMYwAMQwAMQwAMAwAMAwAP/wAH/gAAAAAAAAA=="}, + {name:"game", img:"GBiBAAAAAAAAAAAAAAA8AAB+AABmAABmAAB+AAA8AAAYAAAYAAAYAAMYAA//8B//+BgAGBgAGBgAGBgAGB//+A//8AAAAAAAAAAAAA=="}, + {name:"dice", img:"GBiBAAAAAB//8D//+HAAPGMDHmeHnmeHnmMDHmAAHmMDHmeHnmeHnmMDHmAAHmMDHmeHnmeHnmMDHnAAPn///j///h///g///AAAAA=="}, + {name:"gear", img:"GBiBAAAAAAAAAAA8AAB+AABmAA3nsA/D8B8A+Dg8HBx+OAznMAzDMAzDMAznMBx+ODg8HB8A+A/D8A3nsABmAAB+AAA8AAAAAAAAAA=="}, + {name:"wrench", img:"GBiBAAAAAAAAAAAAAAAHgAAfwAA7gAAzEABjOABj+ABh+ABgGADgMAHAcAOP4AcfgA44AB9wADHgADHAADGAAB8AAA4AAAAAAAAAAA=="}, + {name:"calendar", img:"FhgBDADAMAMP/////////////////////8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAPAAA8AADwAAP///////"}, + {name:"power", img:"GBiBAAAAAAAAAAB+AAH/gAeBwA4YcAwYMBjbGBnbmDGZjDMYzDMYzDMAzDMAzDGBjBnDmBj/GAw8MA4AcAeB4AH/gAB+AAAAAAAAAA=="}, + {name:"terminal", img:"GBiBAAAAAAAAAAAAAA//8B//+B//+B//+B//+BgAGBgAGBgAGBmAGBjAGBhgGBhgGBjAGBmPmBgAGBgAGB//+A//8AAAAAAAAAAAAA=="}, + {name:"camera", img:"GBiBAAAAAAAAAAD/AAH/gAMAwD8A/H8A/mA8BmD/BmHDhmGBhmMAxmMAxmMAxmMAxmGBhmHDhmD/BmA8BmAABn///j///AAAAAAAAA=="}, + {name:"phone", img:"GBiBAAAAAAAAAAOAAA/AABzgADBgADBgADBgABjgABjAABzAAAxgAA5wAAc58AMf+AGHHADgDABwDAA8GAAfGAAH8AAA4AAAAAAAAA=="}, + {name:"two prong plug", img:"GBiBAAABgAADwAAHwAAPgACfAAHOAAPkBgHwDwP4Hwf8Pg/+fB//OD//kD//wD//4D//8D//4B//QB/+AD/8AH/4APnwAHAAACAAAA=="}, + {name:"steps", img:"GBiBAAcAAA+AAA/AAA/AAB/AAB/gAA/g4A/h8A/j8A/D8A/D+AfH+AAH8AHn8APj8APj8AHj4AHg4AADAAAHwAAHwAAHgAAHgAADAA=="}, + {name:"graph", img:"GBiBAAAAAAAAAAAAAAAAAAAAAADAAADAAAHAAAHjAAHjgAPngH9n/n82/gA+AAA8AAA8AAAcAAAYAAAYAAAAAAAAAAAAAAAAAAAAAA=="}, + {name:"hills", img:"GBiBAAAAAAAAAAAAAAAAAAAAAAACAAAGAAAPAAEZgAOwwAPwQAZgYAwAMBgAGBAACDAADGAABv///////wAAAAAAAAAAAAAAAAAAAA=="}, + {name:"sun", img:"GBiBAAAYAAAYAAAYAAgAEBwAOAx+MAD/AAHDgAMAwAcA4AYAYOYAZ+YAZwYAYAcA4AMAwAHDgAD/AAx+MBwAOAgAEAAYAAAYAAAYAA=="}, + {name:"home", img:"GBiBAAAAAAAAAAAAAAH/gAP/wAdg4A5wYA44MBwf+DgP/BgAGBgAGBgAGBnnmBnnmBnnmBnnmBngGBngGB//+B//+AAAAAAAAAAAAA=="}, + {name:"bell", img:"GBiBAAAAAAAAAAAfgAB/2ADw+AHAMAOAGAcAGD4ADHgADDgADBwADA4AHAcAGAOAOAHAcAPg4ANxwAM5gAP/AAHvAAAHAAACAAAAAA=="}, + {name:"bin", img:"GBiBAAAAAAAAAAB+AB//+B//+AwAMAwAMAxmMAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYANmwAMAwAMAwAP/wAH/gAAAAAAAAA=="}, +]; + +let storedApps; +var showMainMenu = () => { + storedApps = storage.readJSON("clkshortcuts.json", 1) || {}; + + var mainMenu = { + "": { + title: "Shortcuts", + }, + "< Back": () => { + load(); + }, + "New": () => { + // Select the app + getSelectedApp().then((app) => { + getSelectedIcon().then((icon) => { + promptForRename(app.name).then((name) => { + E.showMessage("Saving..."); + storedApps[app.src] = { + name: name, src: app.src, icon: icon + }; + storage.writeJSON("clkshortcuts.json", storedApps); + showMainMenu(); + }).catch(() => { + E.showMessage("Saving..."); + storedApps[app.src] = { + name: app.name, src: app.src, icon: icon + }; + storage.writeJSON("clkshortcuts.json", storedApps); + showMainMenu(); + } ); + }).catch(() => {showMainMenu();}); + }).catch(() => {showMainMenu();}); + }, + }; + getStoredAppsArray(storedApps).forEach((app) => { + mainMenu[app.name] = { + onchange: () => { + showEditMenu(app).then((dirty) => { + if (dirty) { + E.showMessage("Saving..."); + storage.writeJSON("clkshortcuts.json", storedApps); + } + showMainMenu(); + }); + }, + format: v=>"\0" + atob(app.icon) + }; + }); + E.showMenu(mainMenu); +}; + +var showEditMenu = (app) => { + return new Promise((resolve, reject) => { + var editMenu = { + "": { + title: "Edit " + app.name, + }, + "< Back": () => { + resolve(false); + }, + "Name":{ + onchange: () => { + promptForRename(app.name).then((name) => { + storedApps[app.src].name = name; + resolve(true); + }).catch(); + }, + format: v=>app.name.substring(0, 7) + }, + "Icon": { + onchange: () => { + getSelectedIcon().then((icon) => { + storedApps[app.src].icon = icon; + resolve(true); + }).catch(() => resolve(false)); + }, + format: v=>"\0" + atob(app.icon) + }, + "Delete": { + onchange: () => { + delete storedApps[app.src] + resolve(true); + }, + format: v=>"\0" + atob("GBiBAAAAAAAAAAB+AB//+B//+AwAMAwAMAxmMAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYAZmYANmwAMAwAMAwAP/wAH/gAAAAAAAAA==") + } + }; + E.showMenu(editMenu); + }); +}; + +var promptForRename = (name) => { + return new Promise((resolve, reject) => { + if (!keyboard) { reject("No textinput is available"); } + else { + return require("textinput").input({text:name}).then((result) => resolve(result)); + } + }); +}; + +var getStoredAppsArray = (apps) => { + var appList = Object.keys(apps); + var storedAppArray = []; + for (var i = 0; i < appList.length; i++) { + var app = "" + appList[i]; + storedAppArray.push( + apps[app] + ); + } + return storedAppArray; +}; + +var getSelectedIcon = () => { + return new Promise((resolve, reject) => { + var iconMenu = { + "": { + title: "Select Icon", + }, + "< Back": () => { + reject("The user cancelled the operation"); + }, + }; + + icons.forEach((icon) => { + iconMenu["\0" + atob(icon.img) + " " + icon.name] = () => { + resolve(icon.img); + }; + }); + + E.showMenu(iconMenu); + }); +}; + +var getAppList = () => { + var appList = storage + .list(/\.info$/) + .map((appInfoFileName) => { + var appInfo = storage.readJSON(appInfoFileName, 1); + return ( + appInfo && { + name: appInfo.name, + sortorder: appInfo.sortorder, + src: appInfo.src, + } + ); + }) + .filter((app) => app && !!app.src); + appList.sort((a, b) => { + var n = (0 | a.sortorder) - (0 | b.sortorder); + if (n) return n; + if (a.name < b.name) return -1; + if (a.name > b.name) return 1; + return 0; + }); + + return appList; +}; + +var getSelectedApp = () => { + return new Promise((resolve, reject) => { + E.showMessage("Loading apps..."); + var selectAppMenu = { + "": { + title: "Select App", + }, + "< Back": () => { + reject("The user cancelled the operation"); + }, + }; + + var appList = getAppList(); + appList.forEach((app) => { + selectAppMenu[app.name] = () => { + resolve(app); + }; + }); + + E.showMenu(selectAppMenu); + }); +}; + +showMainMenu(); \ No newline at end of file diff --git a/apps/clkshortcuts/app.png b/apps/clkshortcuts/app.png new file mode 100644 index 0000000000000000000000000000000000000000..66e28fde79af1045cfc8f2a1ea3ebbd8b2a7c204 GIT binary patch literal 1131 zcmV-x1eE)UP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGf6951U69E94oEQKA1OQ1yK~!i%?U_9+ zWKk5yuSoLP7`%QAk95G{ml+M4}=jqFd8Q6tgO|LZwuRPPZFE6lla(XoUER zkHqW_cH-mgIcM*keTV#aGm8f#V?$Dk5m)$?+HJ%gMM-$xa-dvLKPa)6BpT&_5w6wJFC`F@&h6Wua zIvnZ1?d`4Ji=3sUCB5e?eBnqrKR<`6sw(y=D=XtAP=d4_V}}wW3T%ZsQC(fle$hbZB_v3+R zWUTD(??Y*6Df^X_l)&EJo~{Xvv>juI5+e$1*xA{EoSYo?sjI7li;D|g6CPFkY`0Iy*b9 zNkCp+9_;S!29E8p_=>R&+||{^Hg30DmjpvMGjm^{(Vv)@fTpG35iSF)h=C(4h z@Z~ z%nWY_1_o3?K>_c-H&H*0_Vo1dc5G}+;i|;@xNP#awY8PE@g(dNB4{Z!Z()OjgIq>; z*r};0czSx`W2Z3rpv2gAfLL8!#{r$bJaTb#gN{pxj#N6B*q^72_eN9ab zEH5wX8s{+ipu~tfKrAjULUD0%pdorP9UmWum6a7ZJ39k>Gt-vQVdA31utOx!(mFCS z61W4ul*{FU(a}+D9T}E5K{)nKOiQcB<57o)hiZCyTJ`q!DtwSr+1c3&lh;|puCir6#A4+PQyA*+`t^7`n*m*6Ud2va12X6QaKH^iEUHzQT^Z`=(i3z xegsAQi^)K}rc=j1JYuXj|Kv-MAi;-6soz#qUFcx}E6o4^002ovPDHLkV1iM-87BY$ literal 0 HcmV?d00001 diff --git a/apps/clkshortcuts/clkinfo.js b/apps/clkshortcuts/clkinfo.js new file mode 100644 index 0000000000..842ae2747c --- /dev/null +++ b/apps/clkshortcuts/clkinfo.js @@ -0,0 +1,45 @@ +(function() { + var storage = require("Storage"); + var storedApps = storage.readJSON("clkshortcuts.json", 1) || {}; + var items = []; + if (Object.keys(storedApps).length !== 0) { + for (var key in storedApps) { + var source = { + name: storedApps[key].name, + img: storedApps[key].icon, + src: storedApps[key].src, + get : function() { + return { + text : this.name, + img : atob(this.img) + } + }, + run: function() { load(this.src);}, + show : function() {}, + hide : function() {}, + } + items.push(source); + } + } + else { + var source = { + name: "Shortcuts", + img: "GBiBAAAAAAAAAAAAAA//8B//+BgAGBgAGBgYGBgYGBgYGBgYGBn/mBn/mBgYGBgYGBgYGBgYGBgAGBgAGB//+A//8AAAAAAAAAAAAA==", + src: "clkshortcuts.app.js", + get : function() { + return { + text : this.name, + img : atob(this.img) + } + }, + run: function() { load(this.src);}, + show : function() {}, + hide : function() {}, + }; + items = [source]; + } + return { + name: "Shortcuts", + items: items + }; +}) \ No newline at end of file diff --git a/apps/clkshortcuts/example_shortcuts_screenshot.png b/apps/clkshortcuts/example_shortcuts_screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..b60a57f5743622691d2ac5c937c4d36887896d39 GIT binary patch literal 622 zcmV-!0+IcRP)Px#1ZP1_K>z@;j|==^1poj52~bQ_MF9T*|Ns900032ug_i&T010qNS#tmY4#NNd z4#NS*Z>VGd00HhvL_t(&-tCtSmV+P+gy9B;8-)8Ga`|+f}a^bTVkCEW*qifr9 z+@k9sY6HP`%WZ)ZO&B}mp+@U@C8q`k@fdjSfOF4ootIj?yjRva_GZ z!@$zq11quq^e2cKQ&p9jC^ExpsbE1?Sc z-PPuN75x{=Q+gioeE&=#2!d`9Ew1^6YSDhFs&`iRI+9;9dU1P&y8!EJV5)-2@4!O1N{5h|ohVD5ok z+eE;G4%b6L?i7m_V6zW}kJmM@t%IXCrc1n|6pGOCnPhko>6XmD;27l;qyo$%!9|ua z9i|%zu&Jk8+-?Ue(k^#4Gr5@k^(n2K$v3}N==xd_xBI~m1T|y_3E-K*G)Mpg`~cYG z#7@6A=`Ig3 Date: Sun, 9 Feb 2025 22:30:13 -0500 Subject: [PATCH 079/135] Add v0.1 of daymoon clock --- apps/daymoon/ChangeLog | 0 apps/daymoon/README.md | 3 + apps/daymoon/app-icon.js | Bin 0 -> 1027 bytes apps/daymoon/app.js | 162 ++++++++++++++++++++++++++++++++++++ apps/daymoon/icon.png | Bin 0 -> 1660 bytes apps/daymoon/metadata.json | 18 ++++ apps/daymoon/screenshot.png | Bin 0 -> 4446 bytes 7 files changed, 183 insertions(+) create mode 100644 apps/daymoon/ChangeLog create mode 100644 apps/daymoon/README.md create mode 100644 apps/daymoon/app-icon.js create mode 100644 apps/daymoon/app.js create mode 100644 apps/daymoon/icon.png create mode 100644 apps/daymoon/metadata.json create mode 100644 apps/daymoon/screenshot.png diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog new file mode 100644 index 0000000000..e69de29bb2 diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md new file mode 100644 index 0000000000..ffb33ef69f --- /dev/null +++ b/apps/daymoon/README.md @@ -0,0 +1,3 @@ +# FairBangle +This started out with a goal to recreate the Fair Circadian watchface from Pebble for the Bangle.js2. +It ended up with me making a mostly new watchface that has the moon phase more prominent, but keeps the single dial 24 hour clock with daylight and sunset highlighted. diff --git a/apps/daymoon/app-icon.js b/apps/daymoon/app-icon.js new file mode 100644 index 0000000000000000000000000000000000000000..47663be0c38d52ffb95e7be2445bcac124bfab0b GIT binary patch literal 1027 zcmV+e1pNDnP)Px&y-7qtRA@u(S?zM{AP7y~|Dkh75rqQ??(Us!XWBoVRHFjt1JnDuuICaz&!Zl% z`@ZGy_2b6>0{C`?etiWV0QDy@-@Aq;qxascYh)PJ}e)sqiSeD`{j*;R?L`A z6ZlpDX{N_1DF|B$`Th$2O!Zz2;2H2>n80r(yzTVCJotNi?YIIbB&Lk*Gdah{!sYpr zGn|02-CQm1}qIZo)?cLG@e zgv){9$ux^;-s+^)SW?@beN1w|S@<}B%u!d6q)t?FsaC979o+;Bp)TruyT11Tqd=;Z211?>c)BlDz*8HoKCf{=`$X*63PKpbkmAXDe5NXRsFr_R z+K~A`#E+==D)_)63^grF!iJCuoktFw`2cc&pOqS!u2u_&@qwOkqm^C|>+s75IP+_T zQx4$a)lvGg5CD?6zW_HWx*z)Hr6I)*{5l7aYaKG;JWg))hpjnbS)Y1G5?E(r!ACmt zDF>uX%Ve^grAEeDOB;_qG3s5M-shwj@;Jch^!K+Ns%a%6Rgl=Ub0qdq=n1pZS6!=B5`~K7f_CNSIuyTxh%l=uBAk;SWP69EdJFQ3ARq#ZK&TAXB5) zeZW;8;Gh>^`dw&;S;V6^w^D)V3X1Ew0p#7NtwfCj!?#PAr@0vic#aHgbD`Py`t~a6 z*J@XR4D;TKsSjWi#kU|&m+=5zW!Aky-v=s~#}44A0&;`Qon@v>hEDzg61e|%{hEws zy1X3n+8R#B2jt+I+#o!Lc1>1,32); + //this gives r/2 pts on the way down and up, capped at 64 total for polyfill + let a=[],b=[],s1=1,s2=0; + // scale s1 is 1 or -1 for fixed edge of the shadow; defined via case switches below + // scale s2 factor for the moving edge of the shadow + // need to do some computation to simplify for new/full moon if k 'close enough' to 0 or 1/-1 + // + let isWaxing=(mp.phase<0.5); + s1 = isWaxing ? -1 : 1; + s2 = isWaxing ? 1-2*k : 2*k-1; + let tr =(pos.r+0.5); + for (var i=0;i{ + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 10000); //was 1000 + draw(); // draw immediately + } +}); +/* Show launcher when middle button pressed +This should be done *before* Bangle.loadWidgets so that +widgets know if they're being loaded into a clock app or not */ +Bangle.setUI("clock"); +// Load widgets +Bangle.loadWidgets(); +Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/daymoon/icon.png b/apps/daymoon/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..f9cd8417826f35b096abdcbfbab4e22b622d163f GIT binary patch literal 1660 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 literal 0 HcmV?d00001 From d6f62fd80f9a91f57097b73428b4f570b4afe6e5 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Sun, 9 Feb 2025 23:00:50 -0500 Subject: [PATCH 080/135] Fix missing comma, update name in storage --- apps/daymoon/metadata.json | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index f7ebdb8f03..813de8d93b 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,8 +1,7 @@ -{ - "id": "daymoon", +{ "id": "daymoon", "name": "Circadian Moon Clock", "version": "0.1", - "dependencies": {"mylocation":"app"}, + "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}], @@ -10,9 +9,9 @@ "tags": "clock,moon,lunar", "supports": ["BANGLEJS2"], "allow_emulator": true, - "readme":"README.md" + "readme":"README.md", "storage": [ - {"name":"fairbangle.app.js","url":"app.js"}, - {"name":"fairbangle.img","url":"app-icon.js","evaluate":true} + {"name":"daymoon.app.js","url":"app.js"}, + {"name":"daymoon.img","url":"app-icon.js","evaluate":true} ] } \ No newline at end of file From d688a0dd71a16e971988ab85d10fe86acf8ec4f7 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Sun, 9 Feb 2025 23:08:59 -0500 Subject: [PATCH 081/135] Fix icon url --- apps/daymoon/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index 813de8d93b..04214ab4d1 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -3,7 +3,7 @@ "version": "0.1", "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up", - "icon": "app.png", + "icon": "icon.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", "tags": "clock,moon,lunar", From 50bf9c30e8fcd2a14c89578f2880307c96f69135 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Mon, 10 Feb 2025 00:11:27 -0500 Subject: [PATCH 082/135] Fix app icon to be image string, not PNG binary --- apps/daymoon/app-icon.js | Bin 1027 -> 1094 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/daymoon/app-icon.js b/apps/daymoon/app-icon.js index 47663be0c38d52ffb95e7be2445bcac124bfab0b..a87dd3ee2b1281ba88913a91aeeddf07a39eb5ac 100644 GIT binary patch literal 1094 zcmWlXO_QoR7=-`Jtmc$e7lEL#xQiqZ%s6~G7sc6)h~Y~z5J=Qte{sR9M+ zLn?rY1U&6o4jQSXU;IKWZ11-h25Az)JLTrEz#<@u?$D}|_j7@!yX(ow8(>Wa&LsI} zF{^XKaE<$I;|;>qq79kJC6obFNtiP#kl{GU>r1b{I?n_8TfZuNU5#Lce*o#msR8or zXv;FhpINZ1n}ga%s8EIB{F=xcqDj+p8wm?v++~s!+s%Mu^ z7#vKrz8MKfBganc4vrctE&R4@wmQS=+eYSU#3~gd*V75zuIMr7j@yS83K)Dk=Eul|-`wT6xS>f(z<_r!`yD_^{Gv8&fdZUd z#nBoA9YZuMs2sa)?Sm~ZO;k1W<;M1Fgdv4K%P^|v(n_{t@^D479Rx_@QR-+}5%~HU z&t6(nTQt3_T`7LfH1i4Q7-Y$66o>ZurMb4>dwuV53v?kfNDofew0-5UOgBod)1yKd NF=%MNf8YN6`5#tnWGw&y literal 1027 zcmV+e1pNDnP)Px&y-7qtRA@u(S?zM{AP7y~|Dkh75rqQ??(Us!XWBoVRHFjt1JnDuuICaz&!Zl% z`@ZGy_2b6>0{C`?etiWV0QDy@-@Aq;qxascYh)PJ}e)sqiSeD`{j*;R?L`A z6ZlpDX{N_1DF|B$`Th$2O!Zz2;2H2>n80r(yzTVCJotNi?YIIbB&Lk*Gdah{!sYpr zGn|02-CQm1}qIZo)?cLG@e zgv){9$ux^;-s+^)SW?@beN1w|S@<}B%u!d6q)t?FsaC979o+;Bp)TruyT11Tqd=;Z211?>c)BlDz*8HoKCf{=`$X*63PKpbkmAXDe5NXRsFr_R z+K~A`#E+==D)_)63^grF!iJCuoktFw`2cc&pOqS!u2u_&@qwOkqm^C|>+s75IP+_T zQx4$a)lvGg5CD?6zW_HWx*z)Hr6I)*{5l7aYaKG;JWg))hpjnbS)Y1G5?E(r!ACmt zDF>uX%Ve^grAEeDOB;_qG3s5M-shwj@;Jch^!K+Ns%a%6Rgl=Ub0qdq=n1pZS6!=B5`~K7f_CNSIuyTxh%l=uBAk;SWP69EdJFQ3ARq#ZK&TAXB5) zeZW;8;Gh>^`dw&;S;V6^w^D)V3X1Ew0p#7NtwfCj!?#PAr@0vic#aHgbD`Py`t~a6 z*J@XR4D;TKsSjWi#kU|&m+=5zW!Aky-v=s~#}44A0&;`Qon@v>hEDzg61e|%{hEws zy1X3n+8R#B2jt+I+#o!Lc1 Date: Mon, 10 Feb 2025 13:37:30 -0500 Subject: [PATCH 083/135] 0.1 Release Add changelog, update app icon, lay out development path. --- apps/daymoon/ChangeLog | 1 + apps/daymoon/README.md | 16 ++++++++++++++-- apps/daymoon/{icon.png => daymoon.png} | Bin apps/daymoon/metadata.json | 6 +++--- 4 files changed, 18 insertions(+), 5 deletions(-) rename apps/daymoon/{icon.png => daymoon.png} (100%) diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index e69de29bb2..1e5e620fe4 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -0,0 +1 @@ +0.1 First functional release \ No newline at end of file diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index ffb33ef69f..cef8435697 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -1,3 +1,15 @@ -# FairBangle -This started out with a goal to recreate the Fair Circadian watchface from Pebble for the Bangle.js2. +# DayMoon Circadian +This started out with a goal to recreate the Pebble [Fair Circadian watchface](https://setpebble.com/app/fair-circadian) by Matthew Clark for the Bangle.js2. It ended up with me making a mostly new watchface that has the moon phase more prominent, but keeps the single dial 24 hour clock with daylight and sunset highlighted. + +## Future Development +Feature roadmap: +0.1.1 fix the layout so that the widget bar is clear; + put sunrise/sunset at angle on sides +0.2 add Day of week and month display +1.0 Seconds display +1.1 Color Themes (and settings/options) +1.2 Moon display angle represents how it looks in the sky +1.3 custom/bigger/fitted time digits + +2.0 clockinfo support? diff --git a/apps/daymoon/icon.png b/apps/daymoon/daymoon.png similarity index 100% rename from apps/daymoon/icon.png rename to apps/daymoon/daymoon.png diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index 04214ab4d1..2d94300433 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,9 +1,9 @@ { "id": "daymoon", - "name": "Circadian Moon Clock", + "name": "DayMoon Circadian Clock", "version": "0.1", - "dependencies": {"mylocation":"app"}, + "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up", - "icon": "icon.png", + "icon": "daymoon.png", "screenshots": [{"url":"screenshot.png"}], "type": "clock", "tags": "clock,moon,lunar", From 1456d6dc93ce3b6a5de2dc19e121e9c7f92dc859 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Tue, 11 Feb 2025 13:44:30 -0500 Subject: [PATCH 084/135] Release DayMoon clock v 0.1.2 --- apps/daymoon/ChangeLog | 3 +- apps/daymoon/README.md | 19 ++--- apps/daymoon/app.js | 143 +++++++++++++++++++++++------------- apps/daymoon/metadata.json | 4 +- apps/daymoon/screenshot.png | Bin 4446 -> 4538 bytes 5 files changed, 104 insertions(+), 65 deletions(-) diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index 1e5e620fe4..d3b376af01 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -1 +1,2 @@ -0.1 First functional release \ No newline at end of file +0.1 First functional release +0.1.1 move moon down, rotate sunrise/sunset, shift Hours/minutes to corners \ No newline at end of file diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index cef8435697..803eb16960 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -2,14 +2,15 @@ This started out with a goal to recreate the Pebble [Fair Circadian watchface](https://setpebble.com/app/fair-circadian) by Matthew Clark for the Bangle.js2. It ended up with me making a mostly new watchface that has the moon phase more prominent, but keeps the single dial 24 hour clock with daylight and sunset highlighted. +This uses the myLocation app to get your latitude and longitude for proper daylight calculations. If your location isn't set in that app, it will default to Nashua, NH. If your sunrise/sunset times aren't making sense, check that first! + ## Future Development Feature roadmap: -0.1.1 fix the layout so that the widget bar is clear; - put sunrise/sunset at angle on sides -0.2 add Day of week and month display -1.0 Seconds display -1.1 Color Themes (and settings/options) -1.2 Moon display angle represents how it looks in the sky -1.3 custom/bigger/fitted time digits - -2.0 clockinfo support? + - [x]0.1.1 Fix blocking widgets + - [x]0.1.2 Day and Night different color markers + - [ ]0.2 add Day of week and month display + - [ ]1.0 Seconds display + - [ ]1.1 Color Themes (and settings/options) + - [ ]1.2 Moon display angle represents how it looks in the sky + - [ ]1.3 custom/bigger/fitted time digits + - [ ]2.0 clockinfo support? diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index b3f16ec27c..1f770869f3 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -3,19 +3,36 @@ let location; var Utils = require("graphics_utils"); var SunCalc = require("suncalc"); - -const TAU = 2.0*Math.PI,MX=g.getWidth()/2,MY=g.getHeight()/2-20,R=40,X=MX+55,Y=MY+98; -const DAY_MILLIS = 86400000, DIAL=0.05; -const dR1=R+2,dR2=R+23,dR3=R+26; -var shadeCol=8196; -const M_POS = {x:MX,y:MY,r:R}; -const moon_texture = { - width : 80, height : 80, bpp : 1,transparent:0, - buffer : require("heatshrink").decompress(atob("ABsRqAJHkEiBA0VqtVqgIEgIIBqNVBIkCkQACDg4ABGYku1Wu1GICYgSDqsVBIf71U73WigQ6FAAdABIMD/2K1YpBwATCgoTFHgUf/e7/ej1eiJw5vEn/+///9WqxAoCutVq4UEBIP//YTB3Uj0UgJw5QCgYRBE4Uq1BOCE4N3CZWq3e6UIJiGMgUPJwX/9wpBE4MXutXJ4oTBCQW71f/8R2C6onGqgTD/3v//oE4RNFKoNQl//3+//4nB/UikBOHE4ZQB/2vCYOq9FXEIImDAoNUE4O61e73e/ZQP6E5FVO4O+xxQDCYInDPAIFDE4IlCKQWj+QnJCYJPC1wTB/BPBO4TyCAoUrd4JMB1U/MgM6J5SeBJgOoPAPu1QkCAARPBKYMjE4LGB0UrFgJ3JqkLEwPv1WIwXqeIIjCd4tUkW7HgOqkUj0W/1EVE5EA1Z3B1WAwXo/+ICZWv/YnCgE6ncgCZFQgEv9wnCwGu12gCZMCUAP/0UikE63eggoTHoEAwYnB9GAgEq1GAgITJPAM70ECkEiKQITIgEAhRNBAgMAhADCBwRTDioJBlRMBAgMCCQUACANURIaKBBwImDAAhkBqMRCYNRRQITBJIInGKAxiBAAMoJ448BE4Y6CEYgCBKYQ8DYogAMHggMHKQYUGJoYAJA=")) +var RADII = { + moon: 40, + arcMin: 48, + arcMax: 63, + dots: 55, + needle: 54, +}; +var COL ={ + moon: 65535, // + txture:33792, // 0.5 ,0.5,0 + shadow: 8196, // .125,0, .125 + day: 40159, //0.6, 0.6,1 + night: 6, // 0, 0, 0.2 + ndots: 2047, // 0, 1, 1 cyan + ddots: 0, + needle:63488, // 1, 0, 0 red + stime: 2047 }; -const dial = { width: 23, height: 9, bpp:1, transparent:0, - buffer: atob("///B///gAADgAADgAADgAAOAAA5///j//8A=") +const TAU = 2.0*Math.PI; +const MX=g.getWidth()/2,MY=24+3+RADII.arcMax; +const DAY_MILLIS = 86400000; +const M_POS = {x:MX,y:MY,r:RADII.moon}; +// images +const moon_texture = { width : 80, height : 80, bpp : 1,transparent:0, + buffer : require("heatshrink").decompress(atob("ABsRqAJHkEiBA0N0uq1AIEgNVqtRqoJEgUiAAQJEioTBAAIzEl2q12oxATECQdVioJD/eqne60UCHQoADoAJBgf+xWrFIOACYUFCYo8Cj/73f70er0ROHAANUBIM//3///q1WIFAV1qtXCggJB//7CYO6keikBOHKAUDCIInClSgCgonBu4TK1W73ShBMQxkCh5OC//uFIInBi91q5PFCYISC3er//iOwXVE41UCYf+9//9AnCJopVBqEv/+/3//E4P6kUgJw4nDKAP+14TB1Xoq4hBEwYFBqgnB3Wr3e737KB/QnIqp3B32OKAYTBE4Z4BAoYnBEoRSC0fyE5ITBJ4WuCYP4J4J3CeQQFClbvBJgOqn5kBnRPKTwJMB1B4B92qEgQACJ4JTBkYnBYwOilYsBO5NUhYmB9+qxGC9TxBEYTvFqki3Y8B1Uikei3+oionIgGrO4OqwGC9H/xATK1/7E4UAnU7kATIqEAl/uE4WA12u0ATJgSgB/+ikUgnW70EFCY9AgGDE4PowEAlWowEBCZJ4BneggUgkRSBCZEAgEKJoIEBgEIAYQOCKYcVBIMqJgIEBgQSCgAQBqiJDRQIOBEwYAEMgNRiITBqKKBCYJJBE4xQGMQIABlBPHHgInDHQQjEAQJTCHgbFEABg8EBg5SDCgxNDABI=")) +}; +const needle = { width: 23, height: 11, bpp:1, transparent:0, + buffer: atob("///B///D///AAAPAAAHAAAHAAAcAADz///H//8P//wA=") }; + /* now use SunCalc.getMoonIllumination() previously used these: @@ -26,58 +43,78 @@ const dial = { width: 23, height: 9, bpp:1, transparent:0, // requires the myLocation app function loadLocation() { - location = require("Storage").readJSON(LOCATION_FILE,1)||{"lat":51.5072,"lon":0.1276,"location":"London"}; + location = require("Storage").readJSON(LOCATION_FILE,1)||{"lat":45,"lon":-71.3,"location":"Nashua"};//{"lat":51.5072,"lon":0.1276,"location":"London"}; } -function drawMoon(shape){ - g.setColor(0,0,0).fillCircle(MX,MY,R+30); - g.setColor(1,1,1).fillCircle(MX,MY,R-1); - g.setColor(1,1,0).drawImage(moon_texture,MX,MY,{rotate:0}); +function drawMoon(shadowShape){ + g.setColor(0,0,0).fillCircle(MX,MY,RADII.arcMax+3); + g.setColor(COL.moon).fillCircle(MX,MY,RADII.moon); + g.setColor(COL.txture).drawImage(moon_texture,MX,MY,{rotate:0}); //later can set the rotation here to the parallacticAngle from getMoonPosition - g.setColor(shadeCol).fillPoly(shape); - //later set rotation of the fillPoly? parallactic-mp.angle I think. use g.transformVertices + g.setColor(COL.shadow).fillPoly(shadowShape); + //later set rotation of the fillPoly? parallactic-mp.angle I think. + //Use g.transformVertices to do the rotation } -function drawSunTime(times){ +function drawDayRing(times){ + let r_ = RADII.arcMin; + let rm = RADII.arcMax; + let rd = RADII.dots; radT=[tToRad(times[0]),tToRad(times[1])]; hhmm=[require("locale").time(times[0],1),require("locale").time(times[1],1)]; - g.setColor(0.6,0.6,1); - Utils.fillArc(g,MX,MY,R+9,R+26,radT[0],radT[1]); - g.setColor(0,0,0.2); - Utils.fillArc(g,MX,MY,R+9,R+26,radT[1]-TAU,radT[0]); - g.setFont('6x8').setColor(0,1,1); - g.setFontAlign(-1,1,0).drawString(hhmm[0],MX-(R+26),MY+R+26); - g.setFontAlign(1,1,0).drawString(hhmm[1],MX+(R+26),MY+R+26); -} - -function drawDial() { - let r=56; - let labels=['6P','12A','6A','12P']; - let offx=[-11,2,12,2]; - let offy=[1,-11,1,14]; - g.setFont('4x6').setFontAlign(0,0,0).setColor(0,1,1); - //draw dots & labels - let j =0; + g.setColor(COL.day); + Utils.fillArc(g,MX,MY,r_,rm,radT[0],radT[1]); + g.setColor(COL.night); + Utils.fillArc(g,MX,MY,r_,rm,radT[1]-TAU,radT[0]); + //write sunrise/sunset times + g.setFont('6x8').setColor(COL.stime); + g.setFontAlign(0,1,3).drawString(hhmm[0],MX-rm-2,MY); + g.setFontAlign(0,1,1).drawString(hhmm[1],MX+rm+2,MY); + //draw dots + let edges=[]; + var isday=true; + let flag = false; + if (radT[1]>TAU){ + edges=[radT[1]-TAU,radT[0]]; + g.setColor(COL.ddots); + isDay=true; + } else { + edges=[radT[0],radT[1]]; + g.setColor(COL.ndots); + isDay=false; + } for (var i=0;i<24;i++) { let a=i*TAU/24; - let ds = (i%3 == 0) ? 2 : 1; - let pX = MX+Math.cos(a)*r; - let pY = MY+Math.sin(a)*r; - g.fillCircle(pX,pY,ds); - if (i%6==0) { - //console.log(i,j); - g.drawString(labels[j],pX+offx[j],pY+offy[j]); - j++; - } + if (!flag && a>edges[0]){ + //first cross + if (isDay){g.setColor(COL.ndots);}else{g.setColor(COL.ddots);} + flag = true; + } else if (flag && a>edges[1]){ + //second cross + if (isDay){g.setColor(COL.ddots);}else{g.setColor(COL.ndots);} + flag = false; + } + let dotSize = (i%3 == 0) ? 2 : 1; + let pX = MX+Math.cos(a)*rd; + let pY = MY+Math.sin(a)*rd; + g.fillCircle(pX,pY,dotSize); + } + let labels=['6P','12A','6A','12P']; + let qX=[rd-9,2,11-rd,2]; + let qY=[1,rd-10,1,12-rd]; + g.setFont('4x6').setFontAlign(0,0,0).setColor(COL.ndots); + for (var j=0;j<4;j++){ + g.drawString(labels[j],MX+qX[j],MY+qY[j]); } } + function drawHHMM(d) { var HM=require("locale").time(d, 1 /*omit seconds*/).split(":"); //write digital time - g.setBgColor(0,0,0).setColor(1,1,1).setFontVector(46); - g.setFontAlign(1,1,0).drawString(" "+HM[0],MX,g.getHeight()+7,true); - g.setFontAlign(-1,1,0).drawString(HM[1]+" ",MX+10,g.getHeight()+7,true); + g.setBgColor(0,0,0).setColor(1,1,1).setFontVector(45); + g.setFontAlign(1,1,0).drawString(" "+HM[0],MX-20,g.getHeight()+3); + g.setFontAlign(-1,1,0).drawString(HM[1]+" ",MX+30,g.getHeight()+3); var meridian = require("locale").meridian(d); } @@ -99,7 +136,6 @@ function moonShade(pos,mp) { s2 = isWaxing ? 1-2*k : 2*k-1; let tr =(pos.r+0.5); for (var i=0;i?_7a2)b*&`QOH>KhV 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 B&Nu)7 delta 4438 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 cVrm5b13TQ}T9ZA~Gynhq07*qoM6N<$g4 Date: Tue, 4 Feb 2025 18:56:20 +0100 Subject: [PATCH 085/135] New app! --- apps/txtreader/ChangeLog | 1 + apps/txtreader/README.md | 20 ++++++ apps/txtreader/app-icon.js | 1 + apps/txtreader/app.js | 88 +++++++++++++++++++++++ apps/txtreader/metadata.json | 16 +++++ apps/txtreader/screenshot_txtreader.png | Bin 0 -> 7168 bytes apps/txtreader/txtreader.png | Bin 0 -> 1549 bytes apps/txtreader/txtreader_transparent.png | Bin 0 -> 1549 bytes 8 files changed, 126 insertions(+) create mode 100644 apps/txtreader/ChangeLog create mode 100644 apps/txtreader/README.md create mode 100644 apps/txtreader/app-icon.js create mode 100644 apps/txtreader/app.js create mode 100644 apps/txtreader/metadata.json create mode 100644 apps/txtreader/screenshot_txtreader.png create mode 100644 apps/txtreader/txtreader.png create mode 100644 apps/txtreader/txtreader_transparent.png diff --git a/apps/txtreader/ChangeLog b/apps/txtreader/ChangeLog new file mode 100644 index 0000000000..5560f00bce --- /dev/null +++ b/apps/txtreader/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/txtreader/README.md b/apps/txtreader/README.md new file mode 100644 index 0000000000..1cede764ce --- /dev/null +++ b/apps/txtreader/README.md @@ -0,0 +1,20 @@ +# txtreader + +Very basic text reader with an integrated file selector. + +## Features + +- select files from storage (.txt) +- display their contents +- browse pages + +## Controls + +Bangle.js 2 +- tap the right side of the screen to flip to the next page +- tap the left side of the screen to flip to the previous page +- exit by pressing the physical button + +## Creator + + diff --git a/apps/txtreader/app-icon.js b/apps/txtreader/app-icon.js new file mode 100644 index 0000000000..a8c210baf5 --- /dev/null +++ b/apps/txtreader/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkCkQA/AH4A/AAcosd2m9jw04AQlyC5WL1e63YCG3lUC5WPj/x/8f+H/h4CBj/3jYXLv/3/4CCt4FC/IXM/4AI/YXk/WZzOfCgWfAoIXN/F3u9/C4V/AoIvUI6H3F4p3oC6/73e734XTR4wXQ/vd7vfC6f85gAG55HQAAppBC5n5xAAGz4vmzIAGF/33F49/C5v6F4+vC5rrFd6JHCv4XTI4WfF6lms1vF6mq1WvC6Z3WxfdABHVugXKlFUogAHoVCC5QA/AH4A6A")) \ No newline at end of file diff --git a/apps/txtreader/app.js b/apps/txtreader/app.js new file mode 100644 index 0000000000..890b4254c4 --- /dev/null +++ b/apps/txtreader/app.js @@ -0,0 +1,88 @@ +function showFileSelector() { + let files = require("Storage").list().filter(f => f.endsWith('.txt')); + + let menuItems = {}; + files.forEach(file => { + menuItems[file] = () => { + E.showPrompt(`Select ${file}?`).then(confirm => { + if (confirm) { + onFileSelected(file); + } else { + showFileSelector(); + } + }); + }; + }); + + menuItems['< Back'] = () => { load(); }; // Go back to the launcher or previous screen + E.showMenu(menuItems); +} + +function onFileSelected(file) { + + var text = require("Storage").read(file); + + function displayText(text, startLine, pageNumber) { + g.clear(); + g.setFont("6x8", 1); + g.setColor(1); + g.drawString("Page " + pageNumber, 10, 2); + g.drawString(file, g.getWidth()-file.length*6, 2); + + var lines = text.split("\n"); + var y = 15; // Text start, top row reserved for page number + var currentLine = startLine || 0; + var linesDisplayed = 0; //Per page + + for (var i = currentLine; i < lines.length; i++) { + var wrappedLines = g.wrapString(lines[i], g.getWidth() - 20); + for (var j = 0; j < wrappedLines.length; j++) { + g.drawString(wrappedLines[j], 10, y); + y += 10; // Move down for the next line + linesDisplayed++; + if (y >= g.getHeight() - 10) { + // If we run out of space, stop drawing + return { nextStartLine: i , linesDisplayed: linesDisplayed }; + } + } + } + return null; // No more lines to display + } + + var currentStartLine = 0; + var currentPage = 1; + var history = []; // Track the start line and lines displayed for each page + + // Initial display + var result = displayText(text, currentStartLine, currentPage); + history.push({ startLine: currentStartLine, linesDisplayed: result.linesDisplayed }); + + // Handle touch events + Bangle.on('touch', function(button) { + if (button === 2) { // Right side of the screen (next page) + var nextStartLine = displayText(text, currentStartLine, currentPage + 1); + if (nextStartLine !== null) { + currentStartLine = nextStartLine.nextStartLine; + currentPage++; + history.push({ startLine: currentStartLine, linesDisplayed: nextStartLine.linesDisplayed }); + displayText(text, currentStartLine, currentPage); + } else { + currentStartLine = 0; + currentPage = 1; + history = [{ startLine: currentStartLine, linesDisplayed: result.linesDisplayed }]; + displayText(text, currentStartLine, currentPage); + } + } else if (button === 1) { // Left side of the screen (previous page) + if (currentPage > 1) { + // Go back to the previous page + history.pop(); // Remove the current page from history + var previousPage = history[history.length - 1]; + currentStartLine = previousPage.startLine; + currentPage--; + displayText(text, currentStartLine, currentPage); + } + } + }); +} + +showFileSelector(); \ No newline at end of file diff --git a/apps/txtreader/metadata.json b/apps/txtreader/metadata.json new file mode 100644 index 0000000000..985b8e5ea6 --- /dev/null +++ b/apps/txtreader/metadata.json @@ -0,0 +1,16 @@ +{ + "id": "txtreader", + "name": "txtreader", + "shortName": "txtreader", + "version": "0.01", + "description": "Basic text reader with pages and a file selector.", + "icon": "txtreader.png", + "screenshots": [{"url":"screenshot_txtreader.png"}], + "tags": "app,tool", + "supports": ["BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"txtreader.app.js","url":"app.js"}, + {"name":"txtreader.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/txtreader/screenshot_txtreader.png b/apps/txtreader/screenshot_txtreader.png new file mode 100644 index 0000000000000000000000000000000000000000..1b565024aa69b1dde87b3fe1fb703fdb8c007583 GIT binary patch literal 7168 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 SR1MzD^O+i&8{{8yIsZS{p3)Tn literal 0 HcmV?d00001 diff --git a/apps/txtreader/txtreader.png b/apps/txtreader/txtreader.png new file mode 100644 index 0000000000000000000000000000000000000000..a60ee864722a913e9f359abe54bdce504f32634e GIT binary patch literal 1549 zcmYLJdpMM76o0>Q8RRl9VOx!H7d@I}_mPbmX2eL->?D+F4ZEx)j8r0Kh^=?RMA{;jen*bkbv}O14oGWy0-e^4&Ip+wR%5bohJMtD;B1+D2h zmxuL=UghRr8nQZgJgR_wsL%d2;Y`BILr<34t(~3M$T!O?XlAw()nVyV_oh zDa&$-YmfQHzm|VlS&_?qHrM@@*|iI?5o2N{mv3iGlRitUcL_>o^8cijt#oj_9%f2h zB=H_k7HUTtcJPKbB}OGH8%>EzwA6Z`Z!Yi6f#HAd2&>XsNA-y_K_P)1XS3XLA`MeW zR}vnn<%O{mdnT&ubNjG_ZF?&dc*iO1a_Wl-uPOWonQUlN$#MoL98YR+WsRnwQ_)WJ z-+d5(RmSij;DW#$jw+e9-4{ECQ8RI0yT}rc1E9W^M)eL#c`3WlBNT<1h>MTVjuyL` zP?nLezAsExAe~_|W^C&pt!@0|B*(2D;?AHFzF|4FD{aQ8Zff|8=YmK{f1lJW=46PM zAD2coHT}%J)cE{$+5w=edHeyJXs)X{8zYJD=eVsoz4eNg9y9_;+_x8d?0G6T_^l(d zHWaAb2pcM!)|4&yTydckMn&_U#-K(pK9}0^1GeS`YSSwlnp#*==E~mQ4i@&uHZtc` z3amFpQz7R1C)(cN$o2(YKe_U#)_MN6F%2X-FBE!le~l%3l<2cXESKVK;4;I}LP}D<7V7L@_kIu+)J|`p3Cs5E^{h=W#TLs9QOVP@b#5V4!4lXPakD%|e zZ@rQoZmyhEfwzKKt{O)<*z;4pEYL;}E7(n<X=M2fqV`2qLCf%8U88EU^vm;LLUoYSy7=By;v>)Qdz&QSydARLNLt3mtfP^HWal( zI+wY3B^wN8QI>BO*A*y5Xo*+Kdo4bYB@&@Z@evs+fq?ObPLO9gHWj=Zipc0ELrlGD zxQz=*OR8}XohZ*G6im)S*+eGbwA3-+Jgmr&b@Kg|mx-89un3lH+cx3wX;0@o+H&6* zqZbyG-7_10vxQvAM2U_)dW4g%2&-!`-^R7;gTz-lra^xC+||7y1FxE9fk4d#2PvAK zGfq1&DaNq0YwxxROPjSBFy08%?ra%c9)qI&-@2`DU3n){$)W`re?0>6(pKd{PSy*$ zW!%Mft_ZY0RR^_m_XqExV-oiFu2@#oK*R$iK0uQ)t5}v<@fw_fMIMGPEK8fBS{`-? zG>!f!Lkyh3ZjQB%%R*X2dCe^9ZhSqJuZE`sRYNyPzqjG1yZB9pHP}HKfJ-2(#SU%< zb$_1`6##TojZUGd^U=jUugD0Wv~=d7dl=(3Fp#~n-&c24A~NGdxN%ZS0}xhhLWuE0 z467AxG+mH>Yy6C-`>o}aCPSAM}`!ssj7DX9r`gZE(z&eROhhh oS5&jfmUOGcM&0}W@3vo|vF~W8IN-EfJo@hdG+#RPh7UXIU&u?`tN;K2 literal 0 HcmV?d00001 diff --git a/apps/txtreader/txtreader_transparent.png b/apps/txtreader/txtreader_transparent.png new file mode 100644 index 0000000000000000000000000000000000000000..a60ee864722a913e9f359abe54bdce504f32634e GIT binary patch literal 1549 zcmYLJdpMM76o0>Q8RRl9VOx!H7d@I}_mPbmX2eL->?D+F4ZEx)j8r0Kh^=?RMA{;jen*bkbv}O14oGWy0-e^4&Ip+wR%5bohJMtD;B1+D2h zmxuL=UghRr8nQZgJgR_wsL%d2;Y`BILr<34t(~3M$T!O?XlAw()nVyV_oh zDa&$-YmfQHzm|VlS&_?qHrM@@*|iI?5o2N{mv3iGlRitUcL_>o^8cijt#oj_9%f2h zB=H_k7HUTtcJPKbB}OGH8%>EzwA6Z`Z!Yi6f#HAd2&>XsNA-y_K_P)1XS3XLA`MeW zR}vnn<%O{mdnT&ubNjG_ZF?&dc*iO1a_Wl-uPOWonQUlN$#MoL98YR+WsRnwQ_)WJ z-+d5(RmSij;DW#$jw+e9-4{ECQ8RI0yT}rc1E9W^M)eL#c`3WlBNT<1h>MTVjuyL` zP?nLezAsExAe~_|W^C&pt!@0|B*(2D;?AHFzF|4FD{aQ8Zff|8=YmK{f1lJW=46PM zAD2coHT}%J)cE{$+5w=edHeyJXs)X{8zYJD=eVsoz4eNg9y9_;+_x8d?0G6T_^l(d zHWaAb2pcM!)|4&yTydckMn&_U#-K(pK9}0^1GeS`YSSwlnp#*==E~mQ4i@&uHZtc` z3amFpQz7R1C)(cN$o2(YKe_U#)_MN6F%2X-FBE!le~l%3l<2cXESKVK;4;I}LP}D<7V7L@_kIu+)J|`p3Cs5E^{h=W#TLs9QOVP@b#5V4!4lXPakD%|e zZ@rQoZmyhEfwzKKt{O)<*z;4pEYL;}E7(n<X=M2fqV`2qLCf%8U88EU^vm;LLUoYSy7=By;v>)Qdz&QSydARLNLt3mtfP^HWal( zI+wY3B^wN8QI>BO*A*y5Xo*+Kdo4bYB@&@Z@evs+fq?ObPLO9gHWj=Zipc0ELrlGD zxQz=*OR8}XohZ*G6im)S*+eGbwA3-+Jgmr&b@Kg|mx-89un3lH+cx3wX;0@o+H&6* zqZbyG-7_10vxQvAM2U_)dW4g%2&-!`-^R7;gTz-lra^xC+||7y1FxE9fk4d#2PvAK zGfq1&DaNq0YwxxROPjSBFy08%?ra%c9)qI&-@2`DU3n){$)W`re?0>6(pKd{PSy*$ zW!%Mft_ZY0RR^_m_XqExV-oiFu2@#oK*R$iK0uQ)t5}v<@fw_fMIMGPEK8fBS{`-? zG>!f!Lkyh3ZjQB%%R*X2dCe^9ZhSqJuZE`sRYNyPzqjG1yZB9pHP}HKfJ-2(#SU%< zb$_1`6##TojZUGd^U=jUugD0Wv~=d7dl=(3Fp#~n-&c24A~NGdxN%ZS0}xhhLWuE0 z467AxG+mH>Yy6C-`>o}aCPSAM}`!ssj7DX9r`gZE(z&eROhhh oS5&jfmUOGcM&0}W@3vo|vF~W8IN-EfJo@hdG+#RPh7UXIU&u?`tN;K2 literal 0 HcmV?d00001 From 7a8b410d402e78ff6017f37de164358984a37589 Mon Sep 17 00:00:00 2001 From: tonykakuuu Date: Thu, 6 Feb 2025 22:28:36 +0100 Subject: [PATCH 086/135] Implemented offsets, support larger files & general performance increase --- apps/txtreader/app.js | 55 ++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/apps/txtreader/app.js b/apps/txtreader/app.js index 890b4254c4..bc6bec7084 100644 --- a/apps/txtreader/app.js +++ b/apps/txtreader/app.js @@ -14,72 +14,73 @@ function showFileSelector() { }; }); - menuItems['< Back'] = () => { load(); }; // Go back to the launcher or previous screen + menuItems['< Back'] = () => { load(); }; E.showMenu(menuItems); } function onFileSelected(file) { + const fileSize = require("Storage").read(file, 0, 0).length; + const chunkSize = 1024; + let currentOffset = 0; + let currentPage = 1; + let history = []; - var text = require("Storage").read(file); - - function displayText(text, startLine, pageNumber) { + function displayText(offset, pageNumber) { g.clear(); g.setFont("6x8", 1); g.setColor(1); g.drawString("Page " + pageNumber, 10, 2); - g.drawString(file, g.getWidth()-file.length*6, 2); + //g.drawString("Offset " + offset, 60, 2); + g.drawString(file, g.getWidth() - file.length * 6, 2); + var text = require("Storage").read(file, offset, chunkSize); var lines = text.split("\n"); var y = 15; // Text start, top row reserved for page number - var currentLine = startLine || 0; - var linesDisplayed = 0; //Per page + var linesDisplayed = 0; // Lines per page + var totalCharsDisplayed = 0; // Total characters per page - for (var i = currentLine; i < lines.length; i++) { + for (var i = 0; i < lines.length; i++) { var wrappedLines = g.wrapString(lines[i], g.getWidth() - 20); for (var j = 0; j < wrappedLines.length; j++) { g.drawString(wrappedLines[j], 10, y); y += 10; // Move down for the next line linesDisplayed++; + totalCharsDisplayed += wrappedLines[j].length + (j < wrappedLines.length - 1 ? 0 : 1); // Add newline character for the last wrapped line if (y >= g.getHeight() - 10) { // If we run out of space, stop drawing - return { nextStartLine: i , linesDisplayed: linesDisplayed }; + return { nextOffset: offset + totalCharsDisplayed, linesDisplayed: linesDisplayed }; } } } return null; // No more lines to display } - var currentStartLine = 0; - var currentPage = 1; - var history = []; // Track the start line and lines displayed for each page - // Initial display - var result = displayText(text, currentStartLine, currentPage); - history.push({ startLine: currentStartLine, linesDisplayed: result.linesDisplayed }); + var result = displayText(currentOffset, currentPage); + history.push({ offset: currentOffset, linesDisplayed: result.linesDisplayed }); // Handle touch events Bangle.on('touch', function(button) { if (button === 2) { // Right side of the screen (next page) - var nextStartLine = displayText(text, currentStartLine, currentPage + 1); - if (nextStartLine !== null) { - currentStartLine = nextStartLine.nextStartLine; + var nextOffset = displayText(currentOffset, currentPage + 1); + if (nextOffset !== null) { + currentOffset = nextOffset.nextOffset; currentPage++; - history.push({ startLine: currentStartLine, linesDisplayed: nextStartLine.linesDisplayed }); - displayText(text, currentStartLine, currentPage); + history.push({ offset: currentOffset, linesDisplayed: nextOffset.linesDisplayed }); + displayText(currentOffset, currentPage); } else { - currentStartLine = 0; + currentOffset = 0; currentPage = 1; - history = [{ startLine: currentStartLine, linesDisplayed: result.linesDisplayed }]; - displayText(text, currentStartLine, currentPage); + history = [{ offset: currentOffset, linesDisplayed: result.linesDisplayed }]; + displayText(currentOffset, currentPage); } } else if (button === 1) { // Left side of the screen (previous page) if (currentPage > 1) { - // Go back to the previous page - history.pop(); // Remove the current page from history + history.pop(); // Remove current page from history var previousPage = history[history.length - 1]; - currentStartLine = previousPage.startLine; + currentOffset = previousPage.offset; currentPage--; - displayText(text, currentStartLine, currentPage); + displayText(currentOffset, currentPage); } } }); From d6ae8505255ba67a608f0b2779f8381d06917873 Mon Sep 17 00:00:00 2001 From: tonykakuuu Date: Thu, 6 Feb 2025 22:31:09 +0100 Subject: [PATCH 087/135] Unused variable --- apps/txtreader/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/txtreader/app.js b/apps/txtreader/app.js index bc6bec7084..df61a2783b 100644 --- a/apps/txtreader/app.js +++ b/apps/txtreader/app.js @@ -19,7 +19,6 @@ function showFileSelector() { } function onFileSelected(file) { - const fileSize = require("Storage").read(file, 0, 0).length; const chunkSize = 1024; let currentOffset = 0; let currentPage = 1; From afd91e33986efd2a67de068f1a9083b87f063fd4 Mon Sep 17 00:00:00 2001 From: tonykakuuu Date: Sun, 9 Feb 2025 11:05:20 +0100 Subject: [PATCH 088/135] Set font color to g.theme.fg --- apps/txtreader/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/txtreader/app.js b/apps/txtreader/app.js index df61a2783b..1e4fd30e96 100644 --- a/apps/txtreader/app.js +++ b/apps/txtreader/app.js @@ -27,7 +27,7 @@ function onFileSelected(file) { function displayText(offset, pageNumber) { g.clear(); g.setFont("6x8", 1); - g.setColor(1); + g.setColor(g.theme.fg); g.drawString("Page " + pageNumber, 10, 2); //g.drawString("Offset " + offset, 60, 2); g.drawString(file, g.getWidth() - file.length * 6, 2); From cdf984a0e85e5c5823cd2d632977fe08808c3cec Mon Sep 17 00:00:00 2001 From: Rob Pilling Date: Tue, 11 Feb 2025 07:15:45 +0000 Subject: [PATCH 089/135] drained: redisplay immediately when charge status changes --- apps/drained/ChangeLog | 1 + apps/drained/app.js | 1 + apps/drained/app.ts | 1 + apps/drained/metadata.json | 2 +- 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps/drained/ChangeLog b/apps/drained/ChangeLog index 0667d8ff61..af1ee299b9 100644 --- a/apps/drained/ChangeLog +++ b/apps/drained/ChangeLog @@ -6,3 +6,4 @@ 0.05: Enhance menu: permit toggling bluetooth 0.06: Display clock in green when charging, with "charging" text 0.07: Correctly restore full power when the charged threshold is reached +0.08: Redisplay immediately on changes to charging status diff --git a/apps/drained/app.js b/apps/drained/app.js index cefddbcc7d..9f8f6988f9 100644 --- a/apps/drained/app.js +++ b/apps/drained/app.js @@ -118,6 +118,7 @@ Bangle.on("charging", function (charging) { drainedInterval = clearInterval(drainedInterval); if (charging) drainedInterval = setInterval(checkCharge, interval * 60 * 1000); + draw(); }); if (!keepStartup) { var storage = require("Storage"); diff --git a/apps/drained/app.ts b/apps/drained/app.ts index bd79ebcab9..57c71e727d 100644 --- a/apps/drained/app.ts +++ b/apps/drained/app.ts @@ -151,6 +151,7 @@ Bangle.on("charging", charging => { drainedInterval = clearInterval(drainedInterval) as undefined; if(charging) drainedInterval = setInterval(checkCharge, interval * 60 * 1000); + draw(); // redraw to update charging status on screen }); if(!keepStartup){ diff --git a/apps/drained/metadata.json b/apps/drained/metadata.json index eff9a331b1..84addc8039 100644 --- a/apps/drained/metadata.json +++ b/apps/drained/metadata.json @@ -1,7 +1,7 @@ { "id": "drained", "name": "Drained", - "version": "0.07", + "version": "0.08", "description": "Switches to displaying a simple clock when the battery percentage is low, and disables some peripherals", "readme": "README.md", "icon": "icon.png", From 8c13f585d92bbb8c78d8dc8deadfcb094dac9509 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Tue, 11 Feb 2025 15:18:25 -0500 Subject: [PATCH 090/135] Update ChangeLog --- apps/daymoon/ChangeLog | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index d3b376af01..c0502fc82f 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -1,2 +1,3 @@ -0.1 First functional release -0.1.1 move moon down, rotate sunrise/sunset, shift Hours/minutes to corners \ No newline at end of file +0.1 : First functional release +0.1.1 : move moon down, rotate sunrise/sunset, shift Hours/minutes to corners +0.1.2 : Change day and night to have different dots \ No newline at end of file From 57eed5eabda1656759249ab48c5978ace4b4d927 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Tue, 11 Feb 2025 15:52:33 -0500 Subject: [PATCH 091/135] Version 0.04 Fix theme and versioning --- apps/daymoon/ChangeLog | 7 ++++--- apps/daymoon/README.md | 16 ++++++++-------- apps/daymoon/app.js | 1 + apps/daymoon/metadata.json | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index c0502fc82f..8e650db841 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -1,3 +1,4 @@ -0.1 : First functional release -0.1.1 : move moon down, rotate sunrise/sunset, shift Hours/minutes to corners -0.1.2 : Change day and night to have different dots \ No newline at end of file +0.01: First functional release +0.02: move moon down, rotate sunrise/sunset, shift Hours/minutes to corners +0.03: Change day and night to have different dots +0.04: Update ChangeLog, coerce dark theme \ No newline at end of file diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index 803eb16960..2c7e0e6adf 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -6,11 +6,11 @@ This uses the myLocation app to get your latitude and longitude for proper dayli ## Future Development Feature roadmap: - - [x]0.1.1 Fix blocking widgets - - [x]0.1.2 Day and Night different color markers - - [ ]0.2 add Day of week and month display - - [ ]1.0 Seconds display - - [ ]1.1 Color Themes (and settings/options) - - [ ]1.2 Moon display angle represents how it looks in the sky - - [ ]1.3 custom/bigger/fitted time digits - - [ ]2.0 clockinfo support? + - [x]0.01 Fix blocking widgets + - [x]0.03 Day and Night different color markers + - [ ]0.05 add Day of week and month display + - [ ]0.06 Seconds display + - [ ]0.07 Color Themes (and settings/options) + - [ ]0.08 Moon display angle represents how it looks in the sky + - [ ]0.10 custom/bigger/fitted time digits + - [ ]0.20 clockinfo support? diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index 1f770869f3..53d6fd640f 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -196,4 +196,5 @@ widgets know if they're being loaded into a clock app or not */ Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); +g.setTheme({bg:"#000"}); Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index 900985de2b..fd2c2c4d02 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,6 +1,6 @@ { "id": "daymoon", "name": "DayMoon Circadian Clock", - "version": "0.1.2", + "version": "0.4", "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up inspired by Matthew Clark's *Fair Circadian* Pebble watchface", "icon": "daymoon.png", From 1e6a9c8d752f81a402483b796e4f8a7643c017d2 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Tue, 11 Feb 2025 16:10:36 -0500 Subject: [PATCH 092/135] Fix metadata to agree with ChangeLog Last time had it as 0.4 when it should have been 0.04 --- apps/daymoon/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index fd2c2c4d02..e2cbf2a8fc 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,6 +1,6 @@ { "id": "daymoon", "name": "DayMoon Circadian Clock", - "version": "0.4", + "version": "0.04", "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up inspired by Matthew Clark's *Fair Circadian* Pebble watchface", "icon": "daymoon.png", From 7c4e455706bb9e4b83d54af26b168f0fb98869d2 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Tue, 11 Feb 2025 20:10:16 -0500 Subject: [PATCH 093/135] Fix sanity check tabs, defines --- apps/daymoon/app.js | 69 +++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index 53d6fd640f..352395ba88 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -4,22 +4,22 @@ let location; var Utils = require("graphics_utils"); var SunCalc = require("suncalc"); var RADII = { - moon: 40, - arcMin: 48, - arcMax: 63, - dots: 55, - needle: 54, + moon: 40, + arcMin: 48, + arcMax: 63, + dots: 55, + needle: 54, }; var COL ={ - moon: 65535, // - txture:33792, // 0.5 ,0.5,0 - shadow: 8196, // .125,0, .125 - day: 40159, //0.6, 0.6,1 - night: 6, // 0, 0, 0.2 - ndots: 2047, // 0, 1, 1 cyan - ddots: 0, - needle:63488, // 1, 0, 0 red - stime: 2047 + moon: 65535, // + txture:33792, // 0.5 ,0.5,0 + shadow: 8196, // .125,0, .125 + day: 40159, //0.6, 0.6,1 + night: 6, // 0, 0, 0.2 + ndots: 2047, // 0, 1, 1 cyan + ddots: 0, + needle:63488, // 1, 0, 0 red + stime: 2047 }; const TAU = 2.0*Math.PI; const MX=g.getWidth()/2,MY=24+3+RADII.arcMax; @@ -60,8 +60,8 @@ function drawDayRing(times){ let r_ = RADII.arcMin; let rm = RADII.arcMax; let rd = RADII.dots; - radT=[tToRad(times[0]),tToRad(times[1])]; - hhmm=[require("locale").time(times[0],1),require("locale").time(times[1],1)]; + let radT=[tToRad(times[0]),tToRad(times[1])]; + let hhmm=[require("locale").time(times[0],1),require("locale").time(times[1],1)]; g.setColor(COL.day); Utils.fillArc(g,MX,MY,r_,rm,radT[0],radT[1]); g.setColor(COL.night); @@ -72,28 +72,28 @@ function drawDayRing(times){ g.setFontAlign(0,1,1).drawString(hhmm[1],MX+rm+2,MY); //draw dots let edges=[]; - var isday=true; + boolean isDay; let flag = false; if (radT[1]>TAU){ - edges=[radT[1]-TAU,radT[0]]; - g.setColor(COL.ddots); - isDay=true; + edges=[radT[1]-TAU,radT[0]]; + g.setColor(COL.ddots); + isDay=true; } else { - edges=[radT[0],radT[1]]; - g.setColor(COL.ndots); - isDay=false; + edges=[radT[0],radT[1]]; + g.setColor(COL.ndots); + isDay=false; } for (var i=0;i<24;i++) { let a=i*TAU/24; - if (!flag && a>edges[0]){ - //first cross - if (isDay){g.setColor(COL.ndots);}else{g.setColor(COL.ddots);} - flag = true; - } else if (flag && a>edges[1]){ - //second cross - if (isDay){g.setColor(COL.ddots);}else{g.setColor(COL.ndots);} - flag = false; - } + if (!flag && a>edges[0]){ + //first cross + if (isDay){g.setColor(COL.ndots);}else{g.setColor(COL.ddots);} + flag = true; + } else if (flag && a>edges[1]){ + //second cross + if (isDay){g.setColor(COL.ddots);}else{g.setColor(COL.ndots);} + flag = false; + } let dotSize = (i%3 == 0) ? 2 : 1; let pX = MX+Math.cos(a)*rd; let pY = MY+Math.sin(a)*rd; @@ -104,7 +104,7 @@ function drawDayRing(times){ let qY=[1,rd-10,1,12-rd]; g.setFont('4x6').setFontAlign(0,0,0).setColor(COL.ndots); for (var j=0;j<4;j++){ - g.drawString(labels[j],MX+qX[j],MY+qY[j]); + g.drawString(labels[j],MX+qX[j],MY+qY[j]); } } @@ -115,7 +115,8 @@ function drawHHMM(d) { g.setBgColor(0,0,0).setColor(1,1,1).setFontVector(45); g.setFontAlign(1,1,0).drawString(" "+HM[0],MX-20,g.getHeight()+3); g.setFontAlign(-1,1,0).drawString(HM[1]+" ",MX+30,g.getHeight()+3); - var meridian = require("locale").meridian(d); + // TODO: use the meridian text AM/PM or blank for 24 hr. + // var meridian = require("locale").meridian(d); } function moonShade(pos,mp) { From 9de98a0d181ae44b19861f75c7d7f69ae34e5f0a Mon Sep 17 00:00:00 2001 From: MomentumV Date: Wed, 12 Feb 2025 09:38:25 -0500 Subject: [PATCH 094/135] Prettify and validate JS --- apps/daymoon/app.js | 285 +++++++++++++++++++++++--------------------- 1 file changed, 149 insertions(+), 136 deletions(-) diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index 352395ba88..25664eceae 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -10,28 +10,37 @@ var RADII = { dots: 55, needle: 54, }; -var COL ={ - moon: 65535, // - txture:33792, // 0.5 ,0.5,0 - shadow: 8196, // .125,0, .125 - day: 40159, //0.6, 0.6,1 - night: 6, // 0, 0, 0.2 - ndots: 2047, // 0, 1, 1 cyan - ddots: 0, - needle:63488, // 1, 0, 0 red - stime: 2047 +var COL = { + moon: 65535, // + txture: 33792, // 0.5 ,0.5,0 + shadow: 8196, // .125,0, .125 + day: 40159, //0.6, 0.6,1 + night: 6, // 0, 0, 0.2 + ndots: 2047, // 0, 1, 1 cyan + ddots: 0, + needle: 63488, // 1, 0, 0 red + stime: 2047 }; -const TAU = 2.0*Math.PI; -const MX=g.getWidth()/2,MY=24+3+RADII.arcMax; +const TAU = 2.0 * Math.PI; +const MX = g.getWidth() / 2, + MY = 24 + 3 + RADII.arcMax; const DAY_MILLIS = 86400000; -const M_POS = {x:MX,y:MY,r:RADII.moon}; +const M_POS = { x: MX, y: MY, r: RADII.moon }; // images -const moon_texture = { width : 80, height : 80, bpp : 1,transparent:0, - buffer : require("heatshrink").decompress(atob("ABsRqAJHkEiBA0N0uq1AIEgNVqtRqoJEgUiAAQJEioTBAAIzEl2q12oxATECQdVioJD/eqne60UCHQoADoAJBgf+xWrFIOACYUFCYo8Cj/73f70er0ROHAANUBIM//3///q1WIFAV1qtXCggJB//7CYO6keikBOHKAUDCIInClSgCgonBu4TK1W73ShBMQxkCh5OC//uFIInBi91q5PFCYISC3er//iOwXVE41UCYf+9//9AnCJopVBqEv/+/3//E4P6kUgJw4nDKAP+14TB1Xoq4hBEwYFBqgnB3Wr3e737KB/QnIqp3B32OKAYTBE4Z4BAoYnBEoRSC0fyE5ITBJ4WuCYP4J4J3CeQQFClbvBJgOqn5kBnRPKTwJMB1B4B92qEgQACJ4JTBkYnBYwOilYsBO5NUhYmB9+qxGC9TxBEYTvFqki3Y8B1Uikei3+oionIgGrO4OqwGC9H/xATK1/7E4UAnU7kATIqEAl/uE4WA12u0ATJgSgB/+ikUgnW70EFCY9AgGDE4PowEAlWowEBCZJ4BneggUgkRSBCZEAgEKJoIEBgEIAYQOCKYcVBIMqJgIEBgQSCgAQBqiJDRQIOBEwYAEMgNRiITBqKKBCYJJBE4xQGMQIABlBPHHgInDHQQjEAQJTCHgbFEABg8EBg5SDCgxNDABI=")) +const moon_texture = { + width: 80, + height: 80, + bpp: 1, + transparent: 0, + buffer: require("heatshrink").decompress(atob("ABsRqAJHkEiBA0N0uq1AIEgNVqtRqoJEgUiAAQJEioTBAAIzEl2q12oxATECQdVioJD/eqne60UCHQoADoAJBgf+xWrFIOACYUFCYo8Cj/73f70er0ROHAANUBIM//3///q1WIFAV1qtXCggJB//7CYO6keikBOHKAUDCIInClSgCgonBu4TK1W73ShBMQxkCh5OC//uFIInBi91q5PFCYISC3er//iOwXVE41UCYf+9//9AnCJopVBqEv/+/3//E4P6kUgJw4nDKAP+14TB1Xoq4hBEwYFBqgnB3Wr3e737KB/QnIqp3B32OKAYTBE4Z4BAoYnBEoRSC0fyE5ITBJ4WuCYP4J4J3CeQQFClbvBJgOqn5kBnRPKTwJMB1B4B92qEgQACJ4JTBkYnBYwOilYsBO5NUhYmB9+qxGC9TxBEYTvFqki3Y8B1Uikei3+oionIgGrO4OqwGC9H/xATK1/7E4UAnU7kATIqEAl/uE4WA12u0ATJgSgB/+ikUgnW70EFCY9AgGDE4PowEAlWowEBCZJ4BneggUgkRSBCZEAgEKJoIEBgEIAYQOCKYcVBIMqJgIEBgQSCgAQBqiJDRQIOBEwYAEMgNRiITBqKKBCYJJBE4xQGMQIABlBPHHgInDHQQjEAQJTCHgbFEABg8EBg5SDCgxNDABI=")) +}; +const needle = { + width: 23, + height: 11, + bpp: 1, + transparent: 0, + buffer: atob("///B///D///AAAPAAAHAAAHAAAcAADz///H//8P//wA=") }; -const needle = { width: 23, height: 11, bpp:1, transparent:0, - buffer: atob("///B///D///AAAPAAAHAAAHAAAcAADz///H//8P//wA=") - }; /* now use SunCalc.getMoonIllumination() @@ -43,132 +52,136 @@ const needle = { width: 23, height: 11, bpp:1, transparent:0, // requires the myLocation app function loadLocation() { - location = require("Storage").readJSON(LOCATION_FILE,1)||{"lat":45,"lon":-71.3,"location":"Nashua"};//{"lat":51.5072,"lon":0.1276,"location":"London"}; + location = require("Storage").readJSON(LOCATION_FILE, 1) || { "lat": 45, "lon": -71.3, "location": "Nashua" }; //{"lat":51.5072,"lon":0.1276,"location":"London"}; } -function drawMoon(shadowShape){ - g.setColor(0,0,0).fillCircle(MX,MY,RADII.arcMax+3); - g.setColor(COL.moon).fillCircle(MX,MY,RADII.moon); - g.setColor(COL.txture).drawImage(moon_texture,MX,MY,{rotate:0}); - //later can set the rotation here to the parallacticAngle from getMoonPosition - g.setColor(COL.shadow).fillPoly(shadowShape); - //later set rotation of the fillPoly? parallactic-mp.angle I think. - //Use g.transformVertices to do the rotation +function drawMoon(shadowShape) { + g.setColor(0, 0, 0).fillCircle(MX, MY, RADII.arcMax + 3); + g.setColor(COL.moon).fillCircle(MX, MY, RADII.moon); + g.setColor(COL.txture).drawImage(moon_texture, MX, MY, { rotate: 0 }); + // TODO: can set the rotation here to the parallacticAngle from getMoonPosition + g.setColor(COL.shadow).fillPoly(shadowShape); + // TODO: set rotation of the fillPoly? parallactic-mp.angle I think. + // Use g.transformVertices to do the rotation } -function drawDayRing(times){ - let r_ = RADII.arcMin; - let rm = RADII.arcMax; - let rd = RADII.dots; - let radT=[tToRad(times[0]),tToRad(times[1])]; - let hhmm=[require("locale").time(times[0],1),require("locale").time(times[1],1)]; - g.setColor(COL.day); - Utils.fillArc(g,MX,MY,r_,rm,radT[0],radT[1]); - g.setColor(COL.night); - Utils.fillArc(g,MX,MY,r_,rm,radT[1]-TAU,radT[0]); - //write sunrise/sunset times - g.setFont('6x8').setColor(COL.stime); - g.setFontAlign(0,1,3).drawString(hhmm[0],MX-rm-2,MY); - g.setFontAlign(0,1,1).drawString(hhmm[1],MX+rm+2,MY); - //draw dots - let edges=[]; - boolean isDay; - let flag = false; - if (radT[1]>TAU){ - edges=[radT[1]-TAU,radT[0]]; - g.setColor(COL.ddots); - isDay=true; - } else { - edges=[radT[0],radT[1]]; - g.setColor(COL.ndots); - isDay=false; - } - for (var i=0;i<24;i++) { - let a=i*TAU/24; - if (!flag && a>edges[0]){ - //first cross - if (isDay){g.setColor(COL.ndots);}else{g.setColor(COL.ddots);} - flag = true; - } else if (flag && a>edges[1]){ - //second cross - if (isDay){g.setColor(COL.ddots);}else{g.setColor(COL.ndots);} - flag = false; +function drawDayRing(times) { + let r_ = RADII.arcMin; + let rm = RADII.arcMax; + let rd = RADII.dots; + let radT = [tToRad(times[0]), tToRad(times[1])]; + let hhmm = [require("locale").time(times[0], 1), require("locale").time(times[1], 1)]; + g.setColor(COL.day); + Utils.fillArc(g, MX, MY, r_, rm, radT[0], radT[1]); + g.setColor(COL.night); + Utils.fillArc(g, MX, MY, r_, rm, radT[1] - TAU, radT[0]); + // write sunrise/sunset times + g.setFont('6x8').setColor(COL.stime); + g.setFontAlign(0, 1, 3).drawString(hhmm[0], MX - rm - 2, MY); + g.setFontAlign(0, 1, 1).drawString(hhmm[1], MX + rm + 2, MY); + // draw dots + let edges = []; + let isDay = false; + let flag = false; + if (radT[1] > TAU) { + edges = [radT[1] - TAU, radT[0]]; + g.setColor(COL.ddots); + isDay = true; + } else { + edges = [radT[0], radT[1]]; + g.setColor(COL.ndots); + isDay = false; + } + for (var i = 0; i < 24; i++) { + let a = i * TAU / 24; + if (!flag && a > edges[0]) { + //first cross + if (isDay) { g.setColor(COL.ndots); } else { g.setColor(COL.ddots); } + flag = true; + } else if (flag && a > edges[1]) { + //second cross + if (isDay) { g.setColor(COL.ddots); } else { g.setColor(COL.ndots); } + flag = false; + } + let dotSize = (i % 3 == 0) ? 2 : 1; + let pX = MX + Math.cos(a) * rd; + let pY = MY + Math.sin(a) * rd; + g.fillCircle(pX, pY, dotSize); + } + let labels = ['6P', '12A', '6A', '12P']; + let qX = [rd - 9, 2, 11 - rd, 2]; + let qY = [1, rd - 10, 1, 12 - rd]; + g.setFont('4x6').setFontAlign(0, 0, 0).setColor(COL.ndots); + for (var j = 0; j < 4; j++) { + g.drawString(labels[j], MX + qX[j], MY + qY[j]); } - let dotSize = (i%3 == 0) ? 2 : 1; - let pX = MX+Math.cos(a)*rd; - let pY = MY+Math.sin(a)*rd; - g.fillCircle(pX,pY,dotSize); - } - let labels=['6P','12A','6A','12P']; - let qX=[rd-9,2,11-rd,2]; - let qY=[1,rd-10,1,12-rd]; - g.setFont('4x6').setFontAlign(0,0,0).setColor(COL.ndots); - for (var j=0;j<4;j++){ - g.drawString(labels[j],MX+qX[j],MY+qY[j]); - } } function drawHHMM(d) { - var HM=require("locale").time(d, 1 /*omit seconds*/).split(":"); - //write digital time - g.setBgColor(0,0,0).setColor(1,1,1).setFontVector(45); - g.setFontAlign(1,1,0).drawString(" "+HM[0],MX-20,g.getHeight()+3); - g.setFontAlign(-1,1,0).drawString(HM[1]+" ",MX+30,g.getHeight()+3); - // TODO: use the meridian text AM/PM or blank for 24 hr. - // var meridian = require("locale").meridian(d); + var HM = require("locale").time(d, 1 /*omit seconds*/ ).split(":"); + // write digital time + g.setBgColor(0, 0, 0).setColor(1, 1, 1).setFontVector(45); + g.setFontAlign(1, 1, 0).drawString(" " + HM[0], MX - 20, g.getHeight() + 3); + g.setFontAlign(-1, 1, 0).drawString(HM[1] + " ", MX + 30, g.getHeight() + 3); + // TODO: use the meridian text AM/PM or blank for 24 hr. + // var meridian = require("locale").meridian(d); } -function moonShade(pos,mp) { - pos = pos !== undefined ? pos : M_POS; - mp = mp !== undefined ? mp : SunCalc.getMoonIllumination(new Date()); - //position has x,y, r for the drawing, mp is from SunCalc Moon Illumination - let k=mp.fraction; - //k is the percent along the equator of the terminator - const pts = Math.min(pos.r>>1,32); - //this gives r/2 pts on the way down and up, capped at 64 total for polyfill - let a=[],b=[],s1=1,s2=0; - // scale s1 is 1 or -1 for fixed edge of the shadow; defined via case switches below - // scale s2 factor for the moving edge of the shadow - // need to do some computation to simplify for new/full moon if k 'close enough' to 0 or 1/-1 - // - let isWaxing=(mp.phase<0.5); - s1 = isWaxing ? -1 : 1; - s2 = isWaxing ? 1-2*k : 2*k-1; - let tr =(pos.r+0.5); - for (var i=0;i> 1, 32); + // this gives r/2 pts on the way down and up, capped at 64 total for polyfill + let a = [], + b = [], + s1 = 1, + s2 = 0; + // scale s1 is 1 or -1 for fixed edge of the shadow; defined via case switches below + // scale s2 factor for the moving edge of the shadow + // need to do some computation to simplify for new/full moon if k 'close enough' to 0 or 1/-1 + // + let isWaxing = (mp.phase < 0.5); + s1 = isWaxing ? -1 : 1; + s2 = isWaxing ? 1 - 2 * k : 2 * k - 1; + let tr = (pos.r + 0.5); + for (var i = 0; i < pts; i++) { + // down stroke on the outer shadow + var t = i * Math.PI / (pts + 1); //pts+1 so we leave the last point for the starting of going up + let cirX = Math.sin(t) * tr; + let cirY = Math.cos(t) * tr; + a.push(pos.x + s1 * cirX); //x + a.push(pos.y + cirY); //y + b.push(pos.x + s2 * cirX); //x for shadow edge + b.push(pos.y - cirY); //y going up for shadow edge + } + return a.concat(b); } function tToRad(date) { - date = (date !== undefined) ? new Date(date.getTime()) : new Date(); - let milli = date - new Date(date.setHours(0,0,0,0)); - return (milli/DAY_MILLIS +0.25)*TAU; + date = (date !== undefined) ? new Date(date.getTime()) : new Date(); + let milli = date - new Date(date.setHours(0, 0, 0, 0)); + return (milli / DAY_MILLIS + 0.25) * TAU; } function draw() { - // work out how to display the current time - var d = new Date(), a=tToRad(d); - var shape = moonShade(M_POS,SunCalc.getMoonIllumination(d)); - var sTimes = SunCalc.getTimes(d,location.lat,location.lon); - var daylight = [sTimes.sunrise,sTimes.sunset]; - //clear time area - g.setColor(0).fillRect(0,176-45,176,176); - drawMoon(shape); - drawDayRing(daylight); - drawHHMM(d); - //draw pointer - //Maybe later make this an overlay that can be removed?? -avoid drawing so much every minute/second - g.setColor(COL.needle).drawImage(needle,MX+RADII.needle*Math.cos(a),MY+RADII.needle*Math.sin(a),{rotate:a}); + // work out how to display the current time + var d = new Date(), + a = tToRad(d); + var shape = moonShade(M_POS, SunCalc.getMoonIllumination(d)); + var sTimes = SunCalc.getTimes(d, location.lat, location.lon); + var daylight = [sTimes.sunrise, sTimes.sunset]; + //clear time area + g.setColor(0).fillRect(0, 176 - 45, 176, 176); + drawMoon(shape); + drawDayRing(daylight); + drawHHMM(d); + // draw pointer + // TODO: Maybe later make this an overlay that can be removed?? -avoid drawing so much every minute/second + g.setColor(COL.needle).drawImage(needle, MX + RADII.needle * Math.cos(a), MY + RADII.needle * Math.sin(a), { rotate: a }); } @@ -176,20 +189,20 @@ function draw() { g.reset(); // requires the myLocation app loadLocation(); -g.setBgColor(0,0,0).clear(); +g.setBgColor(0, 0, 0).clear(); // draw immediately at first draw(); // now draw every second // eventually maybe update the moon just every hour?? var secondInterval = setInterval(draw, 10000); //was 1000 // Stop updates when LCD is off, restart when on -Bangle.on('lcdPower',on=>{ - if (secondInterval) clearInterval(secondInterval); - secondInterval = undefined; - if (on) { - secondInterval = setInterval(draw, 10000); //was 1000 - draw(); // draw immediately - } +Bangle.on('lcdPower', on => { + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 10000); //was 1000 + draw(); // draw immediately + } }); /* Show launcher when middle button pressed This should be done *before* Bangle.loadWidgets so that @@ -197,5 +210,5 @@ widgets know if they're being loaded into a clock app or not */ Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); -g.setTheme({bg:"#000"}); +g.setTheme({ bg: "#000" }); Bangle.drawWidgets(); \ No newline at end of file From 3a124f5343722217a4ba8073fcf67fe2cb38e204 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Wed, 12 Feb 2025 09:56:02 -0500 Subject: [PATCH 095/135] Update README.md --- apps/daymoon/README.md | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index 2c7e0e6adf..5cd46f07e6 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -6,11 +6,13 @@ This uses the myLocation app to get your latitude and longitude for proper dayli ## Future Development Feature roadmap: - - [x]0.01 Fix blocking widgets - - [x]0.03 Day and Night different color markers - - [ ]0.05 add Day of week and month display - - [ ]0.06 Seconds display - - [ ]0.07 Color Themes (and settings/options) - - [ ]0.08 Moon display angle represents how it looks in the sky - - [ ]0.10 custom/bigger/fitted time digits - - [ ]0.20 clockinfo support? + - [x] 0.01 Fix blocking widgets + - [x] 0.03 Day and Night different color markers + - [ ] 0.05 add Day of week and month display + - [ ] 0.06 Seconds display + - [ ] 0.07 Color Themes (and settings/options) + - [ ] 0.08 Moon display angle represents how it looks in the sky + - [ ] 0.10 custom/bigger/fitted time digits + - [ ] 0.20 clockinfo support? + - [ ] 0.30 Tap/swipe actions? + From 6ca244a4ad52eae6d62c2bf89b26ab5f1fc7c5c3 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 14:43:18 +1100 Subject: [PATCH 096/135] grandfather-clock: add initial metadata --- apps/grandfather-clock/ChangeLog | 1 + apps/grandfather-clock/README.md | 15 +++++++++++++++ apps/grandfather-clock/icon.png | Bin 0 -> 1620 bytes apps/grandfather-clock/metadata.json | 14 ++++++++++++++ apps/grandfather-clock/widget.js | 5 +++++ 5 files changed, 35 insertions(+) create mode 100644 apps/grandfather-clock/ChangeLog create mode 100644 apps/grandfather-clock/README.md create mode 100644 apps/grandfather-clock/icon.png create mode 100644 apps/grandfather-clock/metadata.json create mode 100644 apps/grandfather-clock/widget.js diff --git a/apps/grandfather-clock/ChangeLog b/apps/grandfather-clock/ChangeLog new file mode 100644 index 0000000000..4c21f3ace3 --- /dev/null +++ b/apps/grandfather-clock/ChangeLog @@ -0,0 +1 @@ +0.01: New Widget! diff --git a/apps/grandfather-clock/README.md b/apps/grandfather-clock/README.md new file mode 100644 index 0000000000..12ce92f9e1 --- /dev/null +++ b/apps/grandfather-clock/README.md @@ -0,0 +1,15 @@ +# Grandfather Clock + +A widget that runs in the background and chimes every 15mins (similar to Chimer), and counts out the fractions of an hour and the o'clock hour. + +## Usage + +Once installed, see the App Settings page for options. + +## Requests + +Drop me a message at @yogsoy on Discord if you need help / discover a bug that I can squash for you. + +## Creator + +Written by June B (yogsoy), inspired by aaronrolls' Chimer. diff --git a/apps/grandfather-clock/icon.png b/apps/grandfather-clock/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0 GIT binary patch literal 1620 zcmV-a2CMmrP)1gXjloC|3_d8m;N2OpV(|i0q4YwBna<2! zK9thw%-*|urnNbV{Gax^?eD+#{x0kLJ~)lj_;W+1>qV*k8akT^^dvctZccUyj4}H~#M%Wwee_v` zHMv7o%BM8@dBrLshn{wGD9BDl?^eV5vSM3T96;NnHvtc6La=(qzq)xrX1d8bK-TN- zrd_f$_O`9nEmS+_S7HTXK<&u;LDIW|qlN&KJvM}tt6TVVqL-AvNv`B*{NzNpBfSQwQP5~Sf(Dp@Vq1+3Q`N9wBQN2`J_?M^u0FIMlt?p^8 z%U3%80kIwg!T{E9<8J18S&$k1`eO)@HP+=TZKo(z3_A3VFYJB=sn`2^Q$mRE>02(+W)np;)L1!GUvU2{O{<&F_nE6Qe#D~Xf|dD z+?d3-D1(IUiL`C2;PPv4CKw8H)v7h8^obJ&Z6D0CjVUe8Xq_NAymxUyPAMU^CCrIu z%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FmS*)xQD)%wBE=2tW6@(+MTi!fk9H1pWKew2(jTXVu4%vk26QvSQCbGmk`Z)Y! zBIhh)6vG2)h6mF8wC^|l$M(Eo9D?JiW}=_T2jUA>LC80foTera{^p)Wi`>}Gf;(|ZwEZQ zS^k|*9wyt=f4ZOo!xty7{%}HKD9tBZ50g$=%v&&vMa!#@Nsf>EkEEDA*ST6fiC+An zsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0WahgmHV6yeLWqoYkSl4pzFQ(_Vp&I ztO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J?{Xmin45#=3l9BmL6Bp<*MZej zrsWN7oRPUr7IvrHoIHOjS=gPTCw>d)^LQK+B|=f2qbGjrWaOd5D<<9Dv>MTW0X3z> zyPy}9`<>1~?NCx@m8G$_@rRTy5zH12YM&P)=tU+L^fgY z^0Z&_6^qdVuwgN3wt_Ze(10?J@%{C2grBk42hsu74qEo^nd&v`X`IHN9lrxzS~GeF S(*#!l0000 { + + + +})() From bda1d247dd243b99df7bce236e401b726da4ae4f Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 16:30:54 +1100 Subject: [PATCH 097/135] grandfather-clock: initial code commit --- apps/grandfather-clock/widget.js | 62 ++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/apps/grandfather-clock/widget.js b/apps/grandfather-clock/widget.js index 4a3b50f45e..33fb3059f4 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfather-clock/widget.js @@ -1,5 +1,67 @@ (() => { + // todo: all of these configurable through app settings menu. + const twelve_hour = true; + const swap_meridian = false; + const hour_attention_buzz_ms = 1000; + const hour_count_buzz_ms = 250; + const fraction_count_buzz_ms = 250; + const fractions_of_hour = 4; // 4 = 15min intervals + const wait_ms = 500; + const meridian_buzz_ms = 100; + const meridian_buzz_wait_ms = 50; + let date; + let fractionMs = 3600000 / fractions_of_hour + let chime = function () { + date = new Date(); + let hourFrac = Math.floor(date.getMinutes() / (60 / fractions_of_hour)); + + if (hourFrac == 0) { // if it's an o'clock hour + let chimeHour = (twelve_hour ? date.getHours() % 12 : date.getHours()); + if (chimeHour == 0) (twelve_hour ? chimeHour += 12 : chimeHour += 24); + + Bangle.buzz(hour_attention_buzz_ms).then(() => { // initial buzz + setTimeout(hourChime, wait_ms, chimeHour); // wait a period before doing the first chime + }); + } else { // if it's a fraction of an hour + fractionChime(hourFrac); + } + + queueNextChime(); + }; + + let hourChime = function (hoursLeftToChime) { + hoursLeftToChime--; + Bangle.buzz(hour_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + if (hoursLeftToChime > 0) { + setTimeout(hourChime, wait_ms, hoursLeftToChime); + } else if (twelve_hour) { // once finished with the hour count + setTimeout(meridianChime, wait_ms, (date.getHours() >= 12)); // if in twelve hour mode, queue up the meridian chime. + } + }); + }; + + let fractionChime = function (fractionsLeftToChime) { + fractionsLeftToChime--; + Bangle.buzz(fraction_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + if (fractionsLeftToChime > 0) setTimeout(fractionChime, wait_ms, fractionsLeftToChime); + }); + }; + + let meridianChime = function (meridian) { + if ((swap_meridian ? !meridian : meridian)) { // default: if PM + Bangle.buzz(meridian_buzz_ms).then(setTimeout(Bangle.buzz, meridian_buzz_wait_ms, meridian_buzz_ms)); // buzz once, wait, buzz again. + } else { // default: if AM + Bangle.buzz(meridian_buzz_ms); // buzz once. + } + }; + + let queueNextChime = function () { + let msUntilNextFraction = fractionMs - (Date.now() % fractionMs); + setTimeout(chime, msUntilNextFraction); + }; + + queueNextChime(); })() From eb3819b6246cb28ef59664260322affd79b5b199 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 16:38:06 +1100 Subject: [PATCH 098/135] grandfather-clock: metadata & documentation updates --- apps/grandfather-clock/README.md | 15 +++++++++++++-- apps/grandfather-clock/metadata.json | 2 +- apps/grandfather-clock/widget.js | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/apps/grandfather-clock/README.md b/apps/grandfather-clock/README.md index 12ce92f9e1..34b0d28925 100644 --- a/apps/grandfather-clock/README.md +++ b/apps/grandfather-clock/README.md @@ -1,10 +1,21 @@ # Grandfather Clock -A widget that runs in the background and chimes every 15mins (similar to Chimer), and counts out the fractions of an hour and the o'clock hour. +A widget that runs in the background and chimes on every (configurable) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. ## Usage -Once installed, see the App Settings page for options. +Once installed, see the App Settings page for options. ** This is not implemented yet. Await v0.02 + +Defaults: +- Twelve hour mode is ENABLED. +- Swap meridian is DISABLED. (in the AM, there will be a single buzz after counting the hours. in the PM, there will be two buzzes after counting the hours) +- The attention buzz for the hour chime is 1000ms long. +- The buzz for each hour count is 250ms long. +- The buzz for each fraction count is 250ms long. +- The widget will count out 4 fractions of an hour (15 min interval). +- The time between count buzzes is 500ms. +- The meridian buzzes are 100ms long. +- The time between meridian buzzes is 50ms long. ## Requests diff --git a/apps/grandfather-clock/metadata.json b/apps/grandfather-clock/metadata.json index f8fa524891..133ba3859d 100644 --- a/apps/grandfather-clock/metadata.json +++ b/apps/grandfather-clock/metadata.json @@ -2,7 +2,7 @@ "name": "Grandfather Clock Bell Widget", "shortName":"Grandfather Clock", "version":"0.01", - "description": "A widget that chimes every 15mins (similar to Chimer), and counts out the fractions of an hour and the o'clock hour.", + "description": "A widget that chimes every fraction of an hour (similar to Chimer), and counts out the fractions and the o'clock hour.", "icon": "icon.png", "type": "widget", "tags": "widget", diff --git a/apps/grandfather-clock/widget.js b/apps/grandfather-clock/widget.js index 33fb3059f4..3cdf66af35 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfather-clock/widget.js @@ -6,7 +6,7 @@ const hour_attention_buzz_ms = 1000; const hour_count_buzz_ms = 250; const fraction_count_buzz_ms = 250; - const fractions_of_hour = 4; // 4 = 15min intervals + const fractions_of_hour = 4; // 4 = 15min intervals, 6 = 10min intervals const wait_ms = 500; const meridian_buzz_ms = 100; const meridian_buzz_wait_ms = 50; From 4209dbbd6dc99f112bc896963e02894b4c9e6989 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 16:38:42 +1100 Subject: [PATCH 099/135] =?UTF-8?q?grandfather-clock:=20missing=20semi=20?= =?UTF-8?q?=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/grandfather-clock/widget.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grandfather-clock/widget.js b/apps/grandfather-clock/widget.js index 3cdf66af35..4b07104da0 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfather-clock/widget.js @@ -12,7 +12,7 @@ const meridian_buzz_wait_ms = 50; let date; - let fractionMs = 3600000 / fractions_of_hour + let fractionMs = 3600000 / fractions_of_hour; let chime = function () { date = new Date(); From 76e22f6829accfd3fe6911c683bbf330d88d8329 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 22:08:37 +1100 Subject: [PATCH 100/135] grandfather-clock: adjust default meridian timings --- apps/grandfather-clock/README.md | 6 +++--- apps/grandfather-clock/widget.js | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/grandfather-clock/README.md b/apps/grandfather-clock/README.md index 34b0d28925..f0e628cda7 100644 --- a/apps/grandfather-clock/README.md +++ b/apps/grandfather-clock/README.md @@ -12,10 +12,10 @@ Defaults: - The attention buzz for the hour chime is 1000ms long. - The buzz for each hour count is 250ms long. - The buzz for each fraction count is 250ms long. -- The widget will count out 4 fractions of an hour (15 min interval). +- The widget will count out 4 fractions of an hour (a 15 min interval). - The time between count buzzes is 500ms. -- The meridian buzzes are 100ms long. -- The time between meridian buzzes is 50ms long. +- The meridian buzzes are 50ms long. +- The time between meridian buzzes is 300ms. ## Requests diff --git a/apps/grandfather-clock/widget.js b/apps/grandfather-clock/widget.js index 4b07104da0..86b134c15f 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfather-clock/widget.js @@ -8,8 +8,8 @@ const fraction_count_buzz_ms = 250; const fractions_of_hour = 4; // 4 = 15min intervals, 6 = 10min intervals const wait_ms = 500; - const meridian_buzz_ms = 100; - const meridian_buzz_wait_ms = 50; + const meridian_buzz_ms = 50; + const meridian_buzz_wait_ms = 300; let date; let fractionMs = 3600000 / fractions_of_hour; From d5f805f2ee5144f2a5933e2878d087cb456faa86 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 22:08:55 +1100 Subject: [PATCH 101/135] grandfather-clock: remove "bell" from app name --- apps/grandfather-clock/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grandfather-clock/metadata.json b/apps/grandfather-clock/metadata.json index 133ba3859d..2bd092e23c 100644 --- a/apps/grandfather-clock/metadata.json +++ b/apps/grandfather-clock/metadata.json @@ -1,5 +1,5 @@ { "id": "grandfather-clock", - "name": "Grandfather Clock Bell Widget", + "name": "Grandfather Clock Widget", "shortName":"Grandfather Clock", "version":"0.01", "description": "A widget that chimes every fraction of an hour (similar to Chimer), and counts out the fractions and the o'clock hour.", From fa4d7dcd64d2afa9a6845866ae980a229e754fb8 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 22:19:55 +1100 Subject: [PATCH 102/135] grandfather-clock: add icon --- apps/grandfather-clock/icon.png | Bin 1620 -> 4971 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/grandfather-clock/icon.png b/apps/grandfather-clock/icon.png index 582cb2e0853a5a2899a3afbd7eb19cde2ee7f6a0..b7ca0872f2cafac763afc700a2e1916ae524b2f1 100644 GIT binary patch literal 4971 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 delta 1590 zcmV-62FdyBCe#d&B$E^n5q|~=NklVsi@II zDWLJF<-tS+MbQVNMvWngMiMVMF($}~PbV60iJqKGq6sl-z#5IgNDvG@D81m_8L(pU z0#u>&LWh~o%w9f}(&^0JyL+a!If?wA_PXuwzxMtv>-#=9jnnvZLw~00MXDHdHZ-F~ zE6@xyAk0IFoNQ?rJ z?=L3MHi1NI%W6w_1%Iftvl|hOhaVrR!sN{2xw@hkSSKy zk8akT^^R7(Pu73-SLjz9%wK^oEKM9^v2d+uZBzb_ElWR@^923y?MQ5Sh3y}H359v|8 zR9g6#r~d$slVYvzX{^gvI{yK&9t6Sw)^Fo(=6P9=8U6ZW2$40`DO|&}2{l-??t>KM^xP{PQp9J>sMDt1wG0P7(^*|FxpxgxUNu=e>XY z@94oXm34@@sD<7z%UMsx_zdi4z8GAI!3iDJ{-u zogg{9cYkp~PAMU^CCrIu%1M71EC`5o2if_~7E&h??0jeQ1Y3N6p?}G72FSn>E+sATQ)Q)70!M+WViTAl9FdlI z^_bw)g$_FC{~s`6^Y4_v-WecL8bso`qEiB0GeD&@Sajx!_6dmf;f#FXiqAg!jge#)(`PVmVSj|$`UsHZGo<5&Mq0i(4E(oP@&iXk=-U1(Bgrgt{}SSg8|!FVQpN1*ApW3% zX$qBd0$g%sHPPlXP=%gv2Ryu4{+&-ACfn41x}XBX7bma&a6)1z%_mzAlTKO8TYoT% zMa!#@Nsf>EkEEDA*ST6fiC+AnsNK1#>!x0obq@j$QqYU-ad3ZvbjqUU+%iw(0Wahg zmHV6yeLWqoYkSl4pzFQ(_Vp&ItO{WI-48rGLwQb?#vgVvduyd9_6W)rFRoQJq3I(J z?{Xmin45#=3l9BmL6Bp<*MZejrhnxPZJd$0O%`^i+?+grDp}Z_q9=X}=<|3S6D2}X zo}(vz>ty7i#49G<-Lx9fe*rb6#JivumHVB}LG4gdXO*R~xABLfz>ADt4^0(GkQeZW zqQ#Jh>AK{zSO Date: Thu, 30 Jan 2025 22:20:29 +1100 Subject: [PATCH 103/135] grandfather-clock: update readme --- apps/grandfather-clock/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/apps/grandfather-clock/README.md b/apps/grandfather-clock/README.md index f0e628cda7..637ab50c46 100644 --- a/apps/grandfather-clock/README.md +++ b/apps/grandfather-clock/README.md @@ -1,10 +1,10 @@ # Grandfather Clock -A widget that runs in the background and chimes on every (configurable) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. +A widget that runs in the background and chimes on every (configurable*) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. ## Usage -Once installed, see the App Settings page for options. ** This is not implemented yet. Await v0.02 +Once installed, see the App Settings page for options. Defaults: - Twelve hour mode is ENABLED. @@ -24,3 +24,7 @@ Drop me a message at @yogsoy on Discord if you need help / discover a bug that I ## Creator Written by June B (yogsoy), inspired by aaronrolls' Chimer. + +## Notes + +\* This is not implemented yet, sorry! Await v0.02. From b45b8546d9bfff67fb7a5df790541da6f798a7e6 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 22:41:09 +1100 Subject: [PATCH 104/135] grandfather-clock: show icon for widget once settings are implemented, this will be disabled by default --- apps/grandfather-clock/widget.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/apps/grandfather-clock/widget.js b/apps/grandfather-clock/widget.js index 86b134c15f..86294e0879 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfather-clock/widget.js @@ -1,5 +1,14 @@ (() => { + WIDGETS["grandfather-clock"] = { + area: "tr", + width: 24, + draw: function() { + g.reset(); + g.drawImage(atob("GBiBAAAYAAA8AAA8AAD/AAH/gAP/wAf/4Afn4Afn4Afn4Afn4Afn4Af/4Af/4Afn4Afn4A/n8A//8B//+D///AAAAAAAAAA8AAAYAA=="), this.x, this.y); + } + }; + // todo: all of these configurable through app settings menu. const twelve_hour = true; const swap_meridian = false; From bb9acbd6874c09b4ea1c7078f4c31b3212f1d249 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Thu, 30 Jan 2025 23:06:11 +1100 Subject: [PATCH 105/135] grandfather-clock: more edits to readme, todo --- apps/grandfather-clock/README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/grandfather-clock/README.md b/apps/grandfather-clock/README.md index 637ab50c46..fdf98dd86f 100644 --- a/apps/grandfather-clock/README.md +++ b/apps/grandfather-clock/README.md @@ -4,7 +4,7 @@ A widget that runs in the background and chimes on every (configurable*) fractio ## Usage -Once installed, see the App Settings page for options. +Once installed, see the App Settings page for options. * Defaults: - Twelve hour mode is ENABLED. @@ -25,6 +25,8 @@ Drop me a message at @yogsoy on Discord if you need help / discover a bug that I Written by June B (yogsoy), inspired by aaronrolls' Chimer. -## Notes +## Todo -\* This is not implemented yet, sorry! Await v0.02. +\* App settings are not implemented yet, sorry! Await v0.02. + +A better icon would be nice. A 1-bit simplified grandfather clock. From 51925c1284e12d9df295bdb22f02d959bc4382d3 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sun, 9 Feb 2025 23:47:36 +1100 Subject: [PATCH 106/135] grandfatherclock: rename app to grandfatherclock --- .../ChangeLog | 0 .../README.md | 0 .../icon.png | Bin .../metadata.json | 4 ++-- .../widget.js | 2 +- 5 files changed, 3 insertions(+), 3 deletions(-) rename apps/{grandfather-clock => grandfatherclock}/ChangeLog (100%) rename apps/{grandfather-clock => grandfatherclock}/README.md (100%) rename apps/{grandfather-clock => grandfatherclock}/icon.png (100%) rename apps/{grandfather-clock => grandfatherclock}/metadata.json (80%) rename apps/{grandfather-clock => grandfatherclock}/widget.js (98%) diff --git a/apps/grandfather-clock/ChangeLog b/apps/grandfatherclock/ChangeLog similarity index 100% rename from apps/grandfather-clock/ChangeLog rename to apps/grandfatherclock/ChangeLog diff --git a/apps/grandfather-clock/README.md b/apps/grandfatherclock/README.md similarity index 100% rename from apps/grandfather-clock/README.md rename to apps/grandfatherclock/README.md diff --git a/apps/grandfather-clock/icon.png b/apps/grandfatherclock/icon.png similarity index 100% rename from apps/grandfather-clock/icon.png rename to apps/grandfatherclock/icon.png diff --git a/apps/grandfather-clock/metadata.json b/apps/grandfatherclock/metadata.json similarity index 80% rename from apps/grandfather-clock/metadata.json rename to apps/grandfatherclock/metadata.json index 2bd092e23c..4d388d0b7d 100644 --- a/apps/grandfather-clock/metadata.json +++ b/apps/grandfatherclock/metadata.json @@ -1,4 +1,4 @@ -{ "id": "grandfather-clock", +{ "id": "grandfatherclock", "name": "Grandfather Clock Widget", "shortName":"Grandfather Clock", "version":"0.01", @@ -9,6 +9,6 @@ "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ - {"name":"grandfather-clock.wid.js","url":"widget.js"} + {"name":"grandfatherclock.wid.js","url":"widget.js"} ] } diff --git a/apps/grandfather-clock/widget.js b/apps/grandfatherclock/widget.js similarity index 98% rename from apps/grandfather-clock/widget.js rename to apps/grandfatherclock/widget.js index 86294e0879..fbbc260dcf 100644 --- a/apps/grandfather-clock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -1,6 +1,6 @@ (() => { - WIDGETS["grandfather-clock"] = { + WIDGETS["grandfatherclock"] = { area: "tr", width: 24, draw: function() { From 2327dbed90244d77d6f3672306270d289ddf8c3c Mon Sep 17 00:00:00 2001 From: June Bennison Date: Sun, 9 Feb 2025 23:57:07 +1100 Subject: [PATCH 107/135] grandfatherclock: update icon from https://icons8.com/icon/D2sDn8Iefcjx/old-fashioned-clock --- apps/grandfatherclock/icon.png | Bin 4971 -> 979 bytes apps/grandfatherclock/widget.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/grandfatherclock/icon.png b/apps/grandfatherclock/icon.png index b7ca0872f2cafac763afc700a2e1916ae524b2f1..8dc851c0432813ed8664031aa7433ce6fbc76eb2 100644 GIT binary patch delta 957 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 diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index fbbc260dcf..af2d910f9c 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -5,7 +5,7 @@ width: 24, draw: function() { g.reset(); - g.drawImage(atob("GBiBAAAYAAA8AAA8AAD/AAH/gAP/wAf/4Afn4Afn4Afn4Afn4Afn4Af/4Af/4Afn4Afn4A/n8A//8B//+D///AAAAAAAAAA8AAAYAA=="), this.x, this.y); + g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); } }; From 19605aceb8fa2d99b933078cf56aeb1786c70925 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 00:47:16 +1100 Subject: [PATCH 108/135] grandfatherclock: remove unused widget icon space --- apps/grandfatherclock/widget.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index af2d910f9c..66e63830b8 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -2,7 +2,6 @@ WIDGETS["grandfatherclock"] = { area: "tr", - width: 24, draw: function() { g.reset(); g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); From e51c1c084a5ab5a42d8a1061a78e83e7b4a35ea0 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 00:47:37 +1100 Subject: [PATCH 109/135] grandfatherclock: implement settings menu --- apps/grandfatherclock/settings.js | 83 +++++++++++++++++++++++++++++++ apps/grandfatherclock/widget.js | 53 ++++++++++---------- 2 files changed, 111 insertions(+), 25 deletions(-) create mode 100644 apps/grandfatherclock/settings.js diff --git a/apps/grandfatherclock/settings.js b/apps/grandfatherclock/settings.js new file mode 100644 index 0000000000..6ab3b43b35 --- /dev/null +++ b/apps/grandfatherclock/settings.js @@ -0,0 +1,83 @@ +(function(back) { + + const configFile = "grandfatherclock.json"; + + let config = Object.assign({ + twelve_hour: true, + swap_meridian: false, + hour_attention_buzz_ms: 1000, + hour_count_buzz_ms: 250, + fraction_count_buzz_ms: 250, + fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals + wait_ms: 500, + meridian_buzz_ms: 50, + meridian_buzz_wait_ms: 300 + }, require('Storage').readJSON("grandfatherclock.json", true) || {}); + + let writeConfig = function() { + require('Storage').writeJSON(configFile, config); + }; + + E.showMenu({ + "": {"title" : "Grandfather Clock"}, + "< Back": () => back(), + "12 / 24 hour": { + value: config.twelve_hour, + format: v => v ? "12" : "24", + onchange: v => { + config.twelve_hour = v; + writeConfig(); + } + },"Swap meridian": { + value: config.swap_meridian, + format: v => v ? "Yes" : "No", + onchange: v => { + config.swap_meridian = v; + writeConfig(); + } + },"Hr attn. buzz length (ms)": { + value: config.hour_attention_buzz_ms, + onchange: v => { + config.hour_attention_buzz_ms = v; + writeConfig(); + } + },"Hr count buzz (ms)": { + value: config.hour_count_buzz_ms, + onchange: v => { + config.hour_count_buzz_ms = v; + writeConfig(); + } + },"Frac. count buzz (ms)": { + value: config.fraction_count_buzz_ms, + onchange: v => { + config.fraction_count_buzz_ms = v; + writeConfig(); + } + },"Fracs. of hour": { + value: config.fractions_of_hour, + onchange: v => { + config.fractions_of_hour = v; + writeConfig(); + } + },"Count wait (ms)": { + value: config.wait_ms, + onchange: v => { + config.wait_ms = v; + writeConfig(); + } + },"Meridian buzz (ms)": { + value: config.meridian_buzz_ms, + onchange: v => { + config.meridian_buzz_ms = v; + writeConfig(); + } + },"Meridian wait (ms)": { + value: config.meridian_buzz_wait_ms, + onchange: v => { + config.meridian_buzz_wait_ms = v; + writeConfig(); + } + } + }); + +}) diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index 66e63830b8..32162186a7 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -2,36 +2,39 @@ WIDGETS["grandfatherclock"] = { area: "tr", + width: 16, draw: function() { g.reset(); g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); } }; - // todo: all of these configurable through app settings menu. - const twelve_hour = true; - const swap_meridian = false; - const hour_attention_buzz_ms = 1000; - const hour_count_buzz_ms = 250; - const fraction_count_buzz_ms = 250; - const fractions_of_hour = 4; // 4 = 15min intervals, 6 = 10min intervals - const wait_ms = 500; - const meridian_buzz_ms = 50; - const meridian_buzz_wait_ms = 300; + // sensible defaults + let config = Object.assign({ + twelve_hour: true, + swap_meridian: false, + hour_attention_buzz_ms: 1000, + hour_count_buzz_ms: 250, + fraction_count_buzz_ms: 250, + fractions_of_hour: 4, // 4 = 15min intervals, 6 = 10min intervals + wait_ms: 500, + meridian_buzz_ms: 50, + meridian_buzz_wait_ms: 300 + }, require('Storage').readJSON("grandfatherclock.json", true) || {}); // or, load the app settings file. let date; - let fractionMs = 3600000 / fractions_of_hour; + let fractionMs = 3600000 / config.fractions_of_hour; let chime = function () { date = new Date(); - let hourFrac = Math.floor(date.getMinutes() / (60 / fractions_of_hour)); + let hourFrac = Math.floor(date.getMinutes() / (60 / config.fractions_of_hour)); if (hourFrac == 0) { // if it's an o'clock hour - let chimeHour = (twelve_hour ? date.getHours() % 12 : date.getHours()); - if (chimeHour == 0) (twelve_hour ? chimeHour += 12 : chimeHour += 24); + let chimeHour = (config.twelve_hour ? date.getHours() % 12 : date.getHours()); + if (chimeHour == 0) (config.twelve_hour ? chimeHour += 12 : chimeHour += 24); - Bangle.buzz(hour_attention_buzz_ms).then(() => { // initial buzz - setTimeout(hourChime, wait_ms, chimeHour); // wait a period before doing the first chime + Bangle.buzz(config.hour_attention_buzz_ms).then(() => { // initial buzz + setTimeout(hourChime, config.wait_ms, chimeHour); // wait a period before doing the first chime }); } else { // if it's a fraction of an hour fractionChime(hourFrac); @@ -42,27 +45,27 @@ let hourChime = function (hoursLeftToChime) { hoursLeftToChime--; - Bangle.buzz(hour_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + Bangle.buzz(config.hour_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. if (hoursLeftToChime > 0) { - setTimeout(hourChime, wait_ms, hoursLeftToChime); - } else if (twelve_hour) { // once finished with the hour count - setTimeout(meridianChime, wait_ms, (date.getHours() >= 12)); // if in twelve hour mode, queue up the meridian chime. + setTimeout(hourChime, config.wait_ms, hoursLeftToChime); + } else if (config.twelve_hour) { // once finished with the hour count + setTimeout(meridianChime, config.wait_ms, (date.getHours() >= 12)); // if in twelve hour mode, queue up the meridian chime. } }); }; let fractionChime = function (fractionsLeftToChime) { fractionsLeftToChime--; - Bangle.buzz(fraction_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. - if (fractionsLeftToChime > 0) setTimeout(fractionChime, wait_ms, fractionsLeftToChime); + Bangle.buzz(config.fraction_count_buzz_ms).then(() => { // recursive. buzz and wait to do the next buzz. + if (fractionsLeftToChime > 0) setTimeout(fractionChime, config.wait_ms, fractionsLeftToChime); }); }; let meridianChime = function (meridian) { - if ((swap_meridian ? !meridian : meridian)) { // default: if PM - Bangle.buzz(meridian_buzz_ms).then(setTimeout(Bangle.buzz, meridian_buzz_wait_ms, meridian_buzz_ms)); // buzz once, wait, buzz again. + if ((config.swap_meridian ? !meridian : meridian)) { // default: if PM + Bangle.buzz(config.meridian_buzz_ms).then(setTimeout(Bangle.buzz, config.meridian_buzz_wait_ms, config.meridian_buzz_ms)); // buzz once, wait, buzz again. } else { // default: if AM - Bangle.buzz(meridian_buzz_ms); // buzz once. + Bangle.buzz(config.meridian_buzz_ms); // buzz once. } }; From 98db3426e78506b7588505529c30a543c6fd0b69 Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 00:52:36 +1100 Subject: [PATCH 110/135] grandfatherclock: update metadata for settings --- apps/grandfatherclock/metadata.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/grandfatherclock/metadata.json b/apps/grandfatherclock/metadata.json index 4d388d0b7d..bd1166b3d3 100644 --- a/apps/grandfatherclock/metadata.json +++ b/apps/grandfatherclock/metadata.json @@ -9,6 +9,10 @@ "supports" : ["BANGLEJS2"], "readme": "README.md", "storage": [ - {"name":"grandfatherclock.wid.js","url":"widget.js"} + {"name":"grandfatherclock.wid.js","url":"widget.js"}, + {"name":"grandfatherclock.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"grandfatherclock.json"} ] } From d6023b4c03cd0f50b475270f0f8b45a2fa27375f Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 01:00:05 +1100 Subject: [PATCH 111/135] grandfatherclock: clean settings --- apps/grandfatherclock/settings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/grandfatherclock/settings.js b/apps/grandfatherclock/settings.js index 6ab3b43b35..e59e969bfb 100644 --- a/apps/grandfatherclock/settings.js +++ b/apps/grandfatherclock/settings.js @@ -21,16 +21,14 @@ E.showMenu({ "": {"title" : "Grandfather Clock"}, "< Back": () => back(), - "12 / 24 hour": { + "12 hour": { value: config.twelve_hour, - format: v => v ? "12" : "24", onchange: v => { config.twelve_hour = v; writeConfig(); } },"Swap meridian": { value: config.swap_meridian, - format: v => v ? "Yes" : "No", onchange: v => { config.swap_meridian = v; writeConfig(); From 31ccb2a494395773522725d27c1503c4d8b0939c Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 01:06:21 +1100 Subject: [PATCH 112/135] grandfatherclock: draw widget option --- apps/grandfatherclock/settings.js | 8 ++++++++ apps/grandfatherclock/widget.js | 21 ++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/apps/grandfatherclock/settings.js b/apps/grandfatherclock/settings.js index e59e969bfb..6401dffa5e 100644 --- a/apps/grandfatherclock/settings.js +++ b/apps/grandfatherclock/settings.js @@ -3,6 +3,7 @@ const configFile = "grandfatherclock.json"; let config = Object.assign({ + draw_widget: true, twelve_hour: true, swap_meridian: false, hour_attention_buzz_ms: 1000, @@ -21,6 +22,13 @@ E.showMenu({ "": {"title" : "Grandfather Clock"}, "< Back": () => back(), + "Draw widget": { + value: config.draw_widget, + onchange: v => { + config.draw_widget = v; + writeConfig(); + } + }, "12 hour": { value: config.twelve_hour, onchange: v => { diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index 32162186a7..b7014d5955 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -1,16 +1,8 @@ (() => { - WIDGETS["grandfatherclock"] = { - area: "tr", - width: 16, - draw: function() { - g.reset(); - g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); - } - }; - // sensible defaults let config = Object.assign({ + draw_widget: true, twelve_hour: true, swap_meridian: false, hour_attention_buzz_ms: 1000, @@ -22,6 +14,17 @@ meridian_buzz_wait_ms: 300 }, require('Storage').readJSON("grandfatherclock.json", true) || {}); // or, load the app settings file. + WIDGETS["grandfatherclock"] = { + area: "tr", + width: config.draw_widget ? 16, + draw: function() { + if (config.draw_widget) { + g.reset(); + g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); + } + } + }; + let date; let fractionMs = 3600000 / config.fractions_of_hour; From b4b8bebfda03d8436f98c8ef54389cc79da6994f Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 01:11:07 +1100 Subject: [PATCH 113/135] grandfatherclock: undefine widget width & draw ifn't --- apps/grandfatherclock/widget.js | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index b7014d5955..bb9d9406f7 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -16,13 +16,11 @@ WIDGETS["grandfatherclock"] = { area: "tr", - width: config.draw_widget ? 16, - draw: function() { - if (config.draw_widget) { - g.reset(); - g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); - } - } + width: config.draw_widget ? 16 : undefined, + draw: config.draw_widget ? function() { + g.reset(); + g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); + } : undefined }; let date; From 38596a55e8d3a14d9936b844ff775ba830bff0da Mon Sep 17 00:00:00 2001 From: June Bennison Date: Mon, 10 Feb 2025 01:59:42 +1100 Subject: [PATCH 114/135] grandfatherclock: metadata & changelog --- apps/grandfatherclock/ChangeLog | 1 + apps/grandfatherclock/README.md | 10 ++-------- apps/grandfatherclock/metadata.json | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/apps/grandfatherclock/ChangeLog b/apps/grandfatherclock/ChangeLog index 4c21f3ace3..a21dc397db 100644 --- a/apps/grandfatherclock/ChangeLog +++ b/apps/grandfatherclock/ChangeLog @@ -1 +1,2 @@ 0.01: New Widget! +0.02: rename, new icon, settings menu! diff --git a/apps/grandfatherclock/README.md b/apps/grandfatherclock/README.md index fdf98dd86f..b701164cc7 100644 --- a/apps/grandfatherclock/README.md +++ b/apps/grandfatherclock/README.md @@ -1,10 +1,10 @@ # Grandfather Clock -A widget that runs in the background and chimes on every (configurable*) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. +A widget that runs in the background and chimes on every (configurable) fraction of an hour, similar to Chimer, and counts out the fractions and the o'clock hour. ## Usage -Once installed, see the App Settings page for options. * +Once installed, see the App Settings page for options. Defaults: - Twelve hour mode is ENABLED. @@ -24,9 +24,3 @@ Drop me a message at @yogsoy on Discord if you need help / discover a bug that I ## Creator Written by June B (yogsoy), inspired by aaronrolls' Chimer. - -## Todo - -\* App settings are not implemented yet, sorry! Await v0.02. - -A better icon would be nice. A 1-bit simplified grandfather clock. diff --git a/apps/grandfatherclock/metadata.json b/apps/grandfatherclock/metadata.json index bd1166b3d3..053e384d6b 100644 --- a/apps/grandfatherclock/metadata.json +++ b/apps/grandfatherclock/metadata.json @@ -1,7 +1,7 @@ { "id": "grandfatherclock", "name": "Grandfather Clock Widget", "shortName":"Grandfather Clock", - "version":"0.01", + "version":"0.02", "description": "A widget that chimes every fraction of an hour (similar to Chimer), and counts out the fractions and the o'clock hour.", "icon": "icon.png", "type": "widget", From 58f6dd71c6e5714156b016408ea7a874bd82f08f Mon Sep 17 00:00:00 2001 From: June Bennison Date: Wed, 12 Feb 2025 19:43:04 +1100 Subject: [PATCH 115/135] grandfatherclock: show/hide functionality change sets width to 0 and checks inside the draw function rather than leaving them undefined --- apps/grandfatherclock/widget.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/grandfatherclock/widget.js b/apps/grandfatherclock/widget.js index bb9d9406f7..96e121e631 100644 --- a/apps/grandfatherclock/widget.js +++ b/apps/grandfatherclock/widget.js @@ -16,11 +16,13 @@ WIDGETS["grandfatherclock"] = { area: "tr", - width: config.draw_widget ? 16 : undefined, - draw: config.draw_widget ? function() { - g.reset(); - g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); - } : undefined + width: config.draw_widget ? 16 : 0, + draw: function() { + if (config.draw_widget) { + g.reset(); + g.drawImage(atob("EBiDASSTJJISSSSZJJJCSSTJ///ISSZP///5CTJ/////ITJ/////ITJ/+B//ITJ/+B//ITJ//+P/ITJ/////ISZP///5CSRJ///ICSQJJJJACSYBJJIBCSYABgABCSYABgABCSYAJAABCSYANgABCSYBtgABCSYNtsABCSYBtgABCSYAMAABCSYAAAABCSZJJJJJCQ=="), this.x, this.y); + } + } }; let date; From daf1c06b4d110a3df1251af9cdcda5cff98ebaf3 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Wed, 12 Feb 2025 17:18:02 +0100 Subject: [PATCH 116/135] daymoon: set all dark theme info --- apps/daymoon/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index 25664eceae..9ed5c53540 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -210,5 +210,5 @@ widgets know if they're being loaded into a clock app or not */ Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); -g.setTheme({ bg: "#000" }); +g.setTheme({fg:"#fff", bg:"#000", fg2:"#fff", bg2:"#004", fgH:"#fff", bgH:"#00f", dark:true }); Bangle.drawWidgets(); \ No newline at end of file From 2ad8f637a4fed3fb9bba9404c0d3caa6c9868a4d Mon Sep 17 00:00:00 2001 From: MomentumV Date: Thu, 13 Feb 2025 12:51:13 -0500 Subject: [PATCH 117/135] 0.04.1 release Fixes a bug in the dot coloring and adds more screenshots --- apps/daymoon/ChangeLog | 3 +- apps/daymoon/README.md | 3 +- apps/daymoon/app.js | 331 ++++++++++++++++++++---------------- apps/daymoon/metadata.json | 4 +- apps/daymoon/s1.png | Bin 0 -> 4005 bytes apps/daymoon/s2.png | Bin 0 -> 4429 bytes apps/daymoon/s3.png | Bin 0 -> 3632 bytes apps/daymoon/s4.png | Bin 0 -> 3527 bytes apps/daymoon/screenshot.png | Bin 4538 -> 0 bytes 9 files changed, 195 insertions(+), 146 deletions(-) create mode 100644 apps/daymoon/s1.png create mode 100644 apps/daymoon/s2.png create mode 100644 apps/daymoon/s3.png create mode 100644 apps/daymoon/s4.png delete mode 100644 apps/daymoon/screenshot.png diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index 8e650db841..a793d20176 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -1,4 +1,5 @@ 0.01: First functional release 0.02: move moon down, rotate sunrise/sunset, shift Hours/minutes to corners 0.03: Change day and night to have different dots -0.04: Update ChangeLog, coerce dark theme \ No newline at end of file +0.04: Update ChangeLog, coerce dark theme +0.04.1: Add more screenshots, fix bug in dot colors diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index 5cd46f07e6..2162bf8088 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -8,6 +8,7 @@ This uses the myLocation app to get your latitude and longitude for proper dayli Feature roadmap: - [x] 0.01 Fix blocking widgets - [x] 0.03 Day and Night different color markers + - [x] 0.04 Add to App Loader - [ ] 0.05 add Day of week and month display - [ ] 0.06 Seconds display - [ ] 0.07 Color Themes (and settings/options) @@ -15,4 +16,4 @@ Feature roadmap: - [ ] 0.10 custom/bigger/fitted time digits - [ ] 0.20 clockinfo support? - [ ] 0.30 Tap/swipe actions? - + \ No newline at end of file diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index 9ed5c53540..cb560ae9f7 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -4,42 +4,46 @@ let location; var Utils = require("graphics_utils"); var SunCalc = require("suncalc"); var RADII = { - moon: 40, - arcMin: 48, - arcMax: 63, - dots: 55, - needle: 54, + moon: 40, + arcMin: 48, + arcMax: 63, + dots: 55, + needle: 54, }; var COL = { - moon: 65535, // - txture: 33792, // 0.5 ,0.5,0 - shadow: 8196, // .125,0, .125 - day: 40159, //0.6, 0.6,1 - night: 6, // 0, 0, 0.2 - ndots: 2047, // 0, 1, 1 cyan - ddots: 0, - needle: 63488, // 1, 0, 0 red - stime: 2047 + moon: 65535, // + txture: 33792, // 0.5 ,0.5,0 + shadow: 8196, // .125,0, .125 + day: 40159, //0.6, 0.6,1 + night: 6, // 0, 0, 0.2 + ndots: 2047, // 0, 1, 1 cyan + ddots: 0, + needle: 63488, // 1, 0, 0 red + stime: 2047 }; const TAU = 2.0 * Math.PI; const MX = g.getWidth() / 2, - MY = 24 + 3 + RADII.arcMax; + MY = 24 + 3 + RADII.arcMax; const DAY_MILLIS = 86400000; -const M_POS = { x: MX, y: MY, r: RADII.moon }; +const M_POS = { + x: MX, + y: MY, + r: RADII.moon +}; // images const moon_texture = { - width: 80, - height: 80, - bpp: 1, - transparent: 0, - buffer: require("heatshrink").decompress(atob("ABsRqAJHkEiBA0N0uq1AIEgNVqtRqoJEgUiAAQJEioTBAAIzEl2q12oxATECQdVioJD/eqne60UCHQoADoAJBgf+xWrFIOACYUFCYo8Cj/73f70er0ROHAANUBIM//3///q1WIFAV1qtXCggJB//7CYO6keikBOHKAUDCIInClSgCgonBu4TK1W73ShBMQxkCh5OC//uFIInBi91q5PFCYISC3er//iOwXVE41UCYf+9//9AnCJopVBqEv/+/3//E4P6kUgJw4nDKAP+14TB1Xoq4hBEwYFBqgnB3Wr3e737KB/QnIqp3B32OKAYTBE4Z4BAoYnBEoRSC0fyE5ITBJ4WuCYP4J4J3CeQQFClbvBJgOqn5kBnRPKTwJMB1B4B92qEgQACJ4JTBkYnBYwOilYsBO5NUhYmB9+qxGC9TxBEYTvFqki3Y8B1Uikei3+oionIgGrO4OqwGC9H/xATK1/7E4UAnU7kATIqEAl/uE4WA12u0ATJgSgB/+ikUgnW70EFCY9AgGDE4PowEAlWowEBCZJ4BneggUgkRSBCZEAgEKJoIEBgEIAYQOCKYcVBIMqJgIEBgQSCgAQBqiJDRQIOBEwYAEMgNRiITBqKKBCYJJBE4xQGMQIABlBPHHgInDHQQjEAQJTCHgbFEABg8EBg5SDCgxNDABI=")) + width: 80, + height: 80, + bpp: 1, + transparent: 0, + buffer: require("heatshrink").decompress(atob("ABsRqAJHkEiBA0N0uq1AIEgNVqtRqoJEgUiAAQJEioTBAAIzEl2q12oxATECQdVioJD/eqne60UCHQoADoAJBgf+xWrFIOACYUFCYo8Cj/73f70er0ROHAANUBIM//3///q1WIFAV1qtXCggJB//7CYO6keikBOHKAUDCIInClSgCgonBu4TK1W73ShBMQxkCh5OC//uFIInBi91q5PFCYISC3er//iOwXVE41UCYf+9//9AnCJopVBqEv/+/3//E4P6kUgJw4nDKAP+14TB1Xoq4hBEwYFBqgnB3Wr3e737KB/QnIqp3B32OKAYTBE4Z4BAoYnBEoRSC0fyE5ITBJ4WuCYP4J4J3CeQQFClbvBJgOqn5kBnRPKTwJMB1B4B92qEgQACJ4JTBkYnBYwOilYsBO5NUhYmB9+qxGC9TxBEYTvFqki3Y8B1Uikei3+oionIgGrO4OqwGC9H/xATK1/7E4UAnU7kATIqEAl/uE4WA12u0ATJgSgB/+ikUgnW70EFCY9AgGDE4PowEAlWowEBCZJ4BneggUgkRSBCZEAgEKJoIEBgEIAYQOCKYcVBIMqJgIEBgQSCgAQBqiJDRQIOBEwYAEMgNRiITBqKKBCYJJBE4xQGMQIABlBPHHgInDHQQjEAQJTCHgbFEABg8EBg5SDCgxNDABI=")) }; const needle = { - width: 23, - height: 11, - bpp: 1, - transparent: 0, - buffer: atob("///B///D///AAAPAAAHAAAHAAAcAADz///H//8P//wA=") + width: 23, + height: 10, + bpp: 1, + transparent: 0, + buffer: atob("//+B///D///AAAHgAADgAAHAAA9///j//+H//gA=") }; /* @@ -52,137 +56,172 @@ const needle = { // requires the myLocation app function loadLocation() { - location = require("Storage").readJSON(LOCATION_FILE, 1) || { "lat": 45, "lon": -71.3, "location": "Nashua" }; //{"lat":51.5072,"lon":0.1276,"location":"London"}; + location = require("Storage").readJSON(LOCATION_FILE, 1) || { + "lat": 45, + "lon": -71.3, + "location": "Nashua" + }; //{"lat":51.5072,"lon":0.1276,"location":"London"}; } function drawMoon(shadowShape) { - g.setColor(0, 0, 0).fillCircle(MX, MY, RADII.arcMax + 3); - g.setColor(COL.moon).fillCircle(MX, MY, RADII.moon); - g.setColor(COL.txture).drawImage(moon_texture, MX, MY, { rotate: 0 }); - // TODO: can set the rotation here to the parallacticAngle from getMoonPosition - g.setColor(COL.shadow).fillPoly(shadowShape); - // TODO: set rotation of the fillPoly? parallactic-mp.angle I think. - // Use g.transformVertices to do the rotation + g.setColor(0, 0, 0).fillCircle(MX, MY, RADII.arcMax + 3); + g.setColor(COL.moon).fillCircle(MX, MY, RADII.moon - 1); + g.setColor(COL.txture).drawImage(moon_texture, MX, MY, { + rotate: 0 + }); + // TODO: can set the rotation here to the parallacticAngle from getMoonPosition + g.setColor(COL.shadow).fillPoly(shadowShape); + // TODO: set rotation of the fillPoly? parallactic-mp.angle I think. + // Use g.transformVertices to do the rotation } function drawDayRing(times) { - let r_ = RADII.arcMin; - let rm = RADII.arcMax; - let rd = RADII.dots; - let radT = [tToRad(times[0]), tToRad(times[1])]; - let hhmm = [require("locale").time(times[0], 1), require("locale").time(times[1], 1)]; - g.setColor(COL.day); - Utils.fillArc(g, MX, MY, r_, rm, radT[0], radT[1]); - g.setColor(COL.night); - Utils.fillArc(g, MX, MY, r_, rm, radT[1] - TAU, radT[0]); - // write sunrise/sunset times - g.setFont('6x8').setColor(COL.stime); - g.setFontAlign(0, 1, 3).drawString(hhmm[0], MX - rm - 2, MY); - g.setFontAlign(0, 1, 1).drawString(hhmm[1], MX + rm + 2, MY); - // draw dots - let edges = []; - let isDay = false; - let flag = false; - if (radT[1] > TAU) { - edges = [radT[1] - TAU, radT[0]]; + let r_ = RADII.arcMin; + let rm = RADII.arcMax; + let rd = RADII.dots; + let radT = [tToRad(times[0]), tToRad(times[1])]; + let hhmm = [require("locale").time(times[0], 1), require("locale").time(times[1], 1)]; + g.setColor(COL.day); + Utils.fillArc(g, MX, MY, r_, rm, radT[0], radT[1]); + g.setColor(COL.night); + Utils.fillArc(g, MX, MY, r_, rm, radT[1] - TAU, radT[0]); + // write sunrise/sunset times + g.setFont('6x8').setColor(COL.stime); + g.setFontAlign(0, 1, 3).drawString(hhmm[0], MX - rm - 2, MY); + g.setFontAlign(0, 1, 1).drawString(hhmm[1], MX + rm + 2, MY); + // draw dots + let edges = []; + let isDay = false; + let flag = false; + if (radT[1] > TAU) { + edges = [radT[1] - TAU, radT[0]]; + g.setColor(COL.ddots); + isDay = true; + } else { + edges = [radT[0], radT[1]]; + g.setColor(COL.ndots); + isDay = false; + } + for (var i = 0; i < 24; i++) { + let a = i * TAU / 24; + if (!flag && a > edges[0] && a < edges[1]) { + //first cross + if (isDay) { + g.setColor(COL.ndots); + } else { + g.setColor(COL.ddots); + } + flag = true; + } else if (flag && a > edges[1]) { + //second cross + if (isDay) { g.setColor(COL.ddots); - isDay = true; - } else { - edges = [radT[0], radT[1]]; + } else { g.setColor(COL.ndots); - isDay = false; - } - for (var i = 0; i < 24; i++) { - let a = i * TAU / 24; - if (!flag && a > edges[0]) { - //first cross - if (isDay) { g.setColor(COL.ndots); } else { g.setColor(COL.ddots); } - flag = true; - } else if (flag && a > edges[1]) { - //second cross - if (isDay) { g.setColor(COL.ddots); } else { g.setColor(COL.ndots); } - flag = false; - } - let dotSize = (i % 3 == 0) ? 2 : 1; - let pX = MX + Math.cos(a) * rd; - let pY = MY + Math.sin(a) * rd; - g.fillCircle(pX, pY, dotSize); - } - let labels = ['6P', '12A', '6A', '12P']; - let qX = [rd - 9, 2, 11 - rd, 2]; - let qY = [1, rd - 10, 1, 12 - rd]; - g.setFont('4x6').setFontAlign(0, 0, 0).setColor(COL.ndots); - for (var j = 0; j < 4; j++) { - g.drawString(labels[j], MX + qX[j], MY + qY[j]); + } + flag = false; } + let dotSize = (i % 3 == 0) ? 2 : 1; + let pX = MX + Math.cos(a) * rd; + let pY = MY + Math.sin(a) * rd; + g.fillCircle(pX, pY, dotSize); + } + let labels = ['6P', '12A', '6A', '12P']; + let qX = [rd - 9, 2, 11 - rd, 2]; + let qY = [1, rd - 10, 1, 12 - rd]; + g.setFont('4x6').setFontAlign(0, 0, 0).setColor(COL.ndots); + for (var j = 0; j < 4; j++) { + g.drawString(labels[j], MX + qX[j], MY + qY[j]); + } } function drawHHMM(d) { - var HM = require("locale").time(d, 1 /*omit seconds*/ ).split(":"); - // write digital time - g.setBgColor(0, 0, 0).setColor(1, 1, 1).setFontVector(45); - g.setFontAlign(1, 1, 0).drawString(" " + HM[0], MX - 20, g.getHeight() + 3); - g.setFontAlign(-1, 1, 0).drawString(HM[1] + " ", MX + 30, g.getHeight() + 3); - // TODO: use the meridian text AM/PM or blank for 24 hr. - // var meridian = require("locale").meridian(d); + var HM = require("locale").time(d, 1 /*omit seconds*/ ).split(":"); + // write digital time + g.setBgColor(0, 0, 0).setColor(1, 1, 1).setFontVector(45); + g.setFontAlign(1, 1, 0).drawString(" " + HM[0], MX - 20, g.getHeight() + 3); + g.setFontAlign(-1, 1, 0).drawString(HM[1] + " ", MX + 30, g.getHeight() + 3); + // TODO: use the meridian text AM/PM or blank for 24 hr. + // var meridian = require("locale").meridian(d); } function moonShade(pos, mp) { - pos = pos !== undefined ? pos : M_POS; - mp = mp !== undefined ? mp : SunCalc.getMoonIllumination(new Date()); - // pos has x,y, r for the drawing, mp is from SunCalc Moon Illumination - let k = mp.fraction; - // k is the percent along the equator of the terminator - const pts = Math.min(pos.r >> 1, 32); - // this gives r/2 pts on the way down and up, capped at 64 total for polyfill - let a = [], - b = [], - s1 = 1, - s2 = 0; - // scale s1 is 1 or -1 for fixed edge of the shadow; defined via case switches below - // scale s2 factor for the moving edge of the shadow - // need to do some computation to simplify for new/full moon if k 'close enough' to 0 or 1/-1 - // - let isWaxing = (mp.phase < 0.5); - s1 = isWaxing ? -1 : 1; - s2 = isWaxing ? 1 - 2 * k : 2 * k - 1; - let tr = (pos.r + 0.5); - for (var i = 0; i < pts; i++) { - // down stroke on the outer shadow - var t = i * Math.PI / (pts + 1); //pts+1 so we leave the last point for the starting of going up - let cirX = Math.sin(t) * tr; - let cirY = Math.cos(t) * tr; - a.push(pos.x + s1 * cirX); //x - a.push(pos.y + cirY); //y - b.push(pos.x + s2 * cirX); //x for shadow edge - b.push(pos.y - cirY); //y going up for shadow edge - } - return a.concat(b); + pos = pos !== undefined ? pos : M_POS; + mp = mp !== undefined ? mp : SunCalc.getMoonIllumination(new Date()); + // pos has x,y, r for the drawing, mp is from SunCalc Moon Illumination + let k = mp.fraction; + // k is the percent along the equator of the terminator + const pts = Math.min(pos.r >> 1, 32); + // this gives r/2 pts on the way down and up, capped at 64 total for polyfill + let a = [], + b = [], + s1 = 1, + s2 = 0; + // scale s1 is 1 or -1 for fixed edge of the shadow; defined via case switches below + // scale s2 factor for the moving edge of the shadow + // need to do some computation to simplify for new/full moon if k 'close enough' to 0 or 1/-1 + // + let isWaxing = (mp.phase < 0.5); + s1 = isWaxing ? -1 : 1; + s2 = isWaxing ? 1 - 2 * k : 2 * k - 1; + let tr = (pos.r + 1); + for (var i = 0; i < pts; i++) { + // down stroke on the outer shadow + var t = i * Math.PI / (pts + 1); //pts+1 so we leave the last point for the starting of going up + let cirX = Math.sin(t) * tr; + let cirY = Math.cos(t) * tr; + a.push(pos.x + s1 * cirX); //x + a.push(pos.y + cirY); //y + b.push(pos.x + s2 * cirX); //x for shadow edge + b.push(pos.y - cirY); //y going up for shadow edge + } + return a.concat(b); } function tToRad(date) { - date = (date !== undefined) ? new Date(date.getTime()) : new Date(); - let milli = date - new Date(date.setHours(0, 0, 0, 0)); - return (milli / DAY_MILLIS + 0.25) * TAU; + date = (date !== undefined) ? new Date(date.getTime()) : new Date(); + let milli = date - new Date(date.setHours(0, 0, 0, 0)); + return (milli / DAY_MILLIS + 0.25) * TAU; } -function draw() { - // work out how to display the current time - var d = new Date(), - a = tToRad(d); - var shape = moonShade(M_POS, SunCalc.getMoonIllumination(d)); - var sTimes = SunCalc.getTimes(d, location.lat, location.lon); - var daylight = [sTimes.sunrise, sTimes.sunset]; - //clear time area - g.setColor(0).fillRect(0, 176 - 45, 176, 176); - drawMoon(shape); - drawDayRing(daylight); - drawHHMM(d); - // draw pointer - // TODO: Maybe later make this an overlay that can be removed?? -avoid drawing so much every minute/second - g.setColor(COL.needle).drawImage(needle, MX + RADII.needle * Math.cos(a), MY + RADII.needle * Math.sin(a), { rotate: a }); +function draw(date) { + d = date !== undefined ? date : new Date(); + //var d = new Date(), + var a = tToRad(d), + shape = moonShade(M_POS, SunCalc.getMoonIllumination(d)), + sTimes = SunCalc.getTimes(d, location.lat, location.lon), + daylight = [sTimes.sunrise, sTimes.sunset]; + //clear time area + g.clearRect(Bangle.appRect); //g.setColor(0).fillRect(0, 176 - 45, 176, 176); + drawMoon(shape); + drawDayRing(daylight); + drawHHMM(d); + // draw pointer + // TODO: Maybe later make this an overlay that can be removed?? -avoid drawing so much every minute/second + g.setColor(COL.needle).drawImage(needle, MX + RADII.needle * Math.cos(a), MY + RADII.needle * Math.sin(a), { + rotate: a + }); + +} +const shotTimes = [1720626960000, 1729184400000, 1738298880000, 1717575420000]; +/*first quarter -2 days moon at 10:20 in the summer + jun 10 2024 10:56 +full moon at 12 noon near fall equinox + Sep 17 2024 12:00 +new moon at 11pm in winter + dec 30 2024 23:48 +3rd quarter moon at 03:17 am + May 5 2024 03:17*/ + +function screenshots(times) { + let d = new Date(); + for (let t of times) { + d.setTime(t); + draw(d); + g.dump(); + } } // Clear the screen once, at startup @@ -197,12 +236,12 @@ draw(); var secondInterval = setInterval(draw, 10000); //was 1000 // Stop updates when LCD is off, restart when on Bangle.on('lcdPower', on => { - if (secondInterval) clearInterval(secondInterval); - secondInterval = undefined; - if (on) { - secondInterval = setInterval(draw, 10000); //was 1000 - draw(); // draw immediately - } + if (secondInterval) clearInterval(secondInterval); + secondInterval = undefined; + if (on) { + secondInterval = setInterval(draw, 10000); //was 1000 + draw(); // draw immediately + } }); /* Show launcher when middle button pressed This should be done *before* Bangle.loadWidgets so that @@ -210,5 +249,13 @@ widgets know if they're being loaded into a clock app or not */ Bangle.setUI("clock"); // Load widgets Bangle.loadWidgets(); -g.setTheme({fg:"#fff", bg:"#000", fg2:"#fff", bg2:"#004", fgH:"#fff", bgH:"#00f", dark:true }); +g.setTheme({ + fg: "#fff", + bg: "#000", + fg2: "#fff", + bg2: "#004", + fgH: "#fff", + bgH: "#00f", + dark: true +}); Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index e2cbf2a8fc..49e4b9df8c 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,10 +1,10 @@ { "id": "daymoon", "name": "DayMoon Circadian Clock", - "version": "0.04", + "version": "0.04.1", "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up inspired by Matthew Clark's *Fair Circadian* Pebble watchface", "icon": "daymoon.png", - "screenshots": [{"url":"screenshot.png"}], + "screenshots": [{"url":"s1.png"},{"url":"s2.png"},{"url":"s3.png"},{"url":"s4.png"}], "type": "clock", "tags": "clock,moon,lunar", "supports": ["BANGLEJS2"], diff --git a/apps/daymoon/s1.png b/apps/daymoon/s1.png new file mode 100644 index 0000000000000000000000000000000000000000..cb64c2f0128317c212e28b95182c84e63844ba98 GIT binary patch literal 4005 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 Nn|h|YRodvd{{fO=i^u=~ literal 0 HcmV?d00001 diff --git a/apps/daymoon/s3.png b/apps/daymoon/s3.png new file mode 100644 index 0000000000000000000000000000000000000000..463be5d2160eaee50a0d89ddc07a7baaea249701 GIT binary patch literal 3632 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 D?gy^@ literal 0 HcmV?d00001 diff --git a/apps/daymoon/screenshot.png b/apps/daymoon/screenshot.png deleted file mode 100644 index 937ab01a9d201702e6c08fa6a5f4beeeca408d06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4538 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 B&Nu)7 From 14b03fb50ec767ec921c502916d5cc1873c4e483 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Thu, 13 Feb 2025 13:28:09 -0500 Subject: [PATCH 118/135] Fix versioning I didn't realize it would choke on further dots in the versioning. --- apps/daymoon/ChangeLog | 2 +- apps/daymoon/README.md | 9 +++++---- apps/daymoon/metadata.json | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/daymoon/ChangeLog b/apps/daymoon/ChangeLog index a793d20176..a00fe79829 100644 --- a/apps/daymoon/ChangeLog +++ b/apps/daymoon/ChangeLog @@ -2,4 +2,4 @@ 0.02: move moon down, rotate sunrise/sunset, shift Hours/minutes to corners 0.03: Change day and night to have different dots 0.04: Update ChangeLog, coerce dark theme -0.04.1: Add more screenshots, fix bug in dot colors +0.05: Add more screenshots, fix bug in dot colors diff --git a/apps/daymoon/README.md b/apps/daymoon/README.md index 2162bf8088..4b43b75aa3 100644 --- a/apps/daymoon/README.md +++ b/apps/daymoon/README.md @@ -9,10 +9,11 @@ Feature roadmap: - [x] 0.01 Fix blocking widgets - [x] 0.03 Day and Night different color markers - [x] 0.04 Add to App Loader - - [ ] 0.05 add Day of week and month display - - [ ] 0.06 Seconds display - - [ ] 0.07 Color Themes (and settings/options) - - [ ] 0.08 Moon display angle represents how it looks in the sky + - [x] 0.05 Add more screenshots with different moon phases + - [ ] 0.06 add Day of week and month display + - [ ] 0.07 Seconds display + - [ ] 0.08 Color Themes (and settings/options) + - [ ] 0.09 Moon display angle represents how it looks in the sky - [ ] 0.10 custom/bigger/fitted time digits - [ ] 0.20 clockinfo support? - [ ] 0.30 Tap/swipe actions? diff --git a/apps/daymoon/metadata.json b/apps/daymoon/metadata.json index 49e4b9df8c..f06e216bc7 100644 --- a/apps/daymoon/metadata.json +++ b/apps/daymoon/metadata.json @@ -1,6 +1,6 @@ { "id": "daymoon", "name": "DayMoon Circadian Clock", - "version": "0.04.1", + "version": "0.05", "dependencies": {"mylocation":"app"}, "description": "A 24 hour clockface showing the Moon Phase and portion of the day that the Sun is up inspired by Matthew Clark's *Fair Circadian* Pebble watchface", "icon": "daymoon.png", From 70dc27691e52bba41bfcc594af911da082e61955 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sat, 8 Feb 2025 14:27:01 -0600 Subject: [PATCH 119/135] [gbmusic] fix #3737; fix autostart saved state; pass playpause to gb instead of play; allow widget clicks --- apps/gbmusic/ChangeLog | 1 + apps/gbmusic/app.js | 16 +++++++++++----- apps/gbmusic/boot.js | 4 ++-- apps/gbmusic/metadata.json | 2 +- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/apps/gbmusic/ChangeLog b/apps/gbmusic/ChangeLog index 0275542fb6..433c583689 100644 --- a/apps/gbmusic/ChangeLog +++ b/apps/gbmusic/ChangeLog @@ -12,3 +12,4 @@ 0.11: Use default Bangle formatter for booleans 0.12: Issue newline before GB commands (solves issue with console.log and ignored commands) 0.13: Upgrade to new translation system +0.14: Fix auto-start saved state; fix clearing track number; allow widget clicks diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 7f5aad8f37..8cf813fb94 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -91,8 +91,8 @@ function rScroller(l) { const w = g.stringWidth(l.label)+40, y = l.y+l.h/2; l.offset = l.offset%w; - g.setClipRect(l.x, l.y, l.x+l.w-1, l.y+l.h-1) - .setColor(l.col).setBgColor(l.bgCol) // need to set colors: iScroll calls this function outside Layout + //g.setClipRect(l.x, l.y, l.x+l.w-1, l.y+l.h-1) + g.setColor(l.col).setBgColor(l.bgCol) // need to set colors: iScroll calls this function outside Layout .setFontAlign(-1, 0) // left center .clearRect(l.x, l.y, l.x+l.w-1, l.y+l.h-1) .drawString(l.label, l.x-l.offset+40, y) @@ -433,15 +433,21 @@ function sendCommand(command) { drawControls(); } +function handleTouch(btn, pos) { + if (pos === undefined || pos.y >= Bangle.appRect.y) { + togglePlay(); + } +} + function togglePlay() { - sendCommand(stat==="play" ? "pause" : "play"); + sendCommand(stat==="play" ? "pause" : "playpause"); } /** * Setup touch+swipe for Bangle.js 1 */ function touch1() { - Bangle.on("touch", togglePlay); + Bangle.on("touch", handleTouch); Bangle.on("swipe", dir => { sendCommand(dir===1 ? "previous" : "next"); }); @@ -450,7 +456,7 @@ function touch1() { * Setup touch+swipe for Bangle.js 2 */ function touch2() { - Bangle.on("touch", togglePlay); + Bangle.on("touch", handleTouch); // swiping let drag; Bangle.on("drag", e => { diff --git a/apps/gbmusic/boot.js b/apps/gbmusic/boot.js index 154f85c2b4..6cd544a217 100644 --- a/apps/gbmusic/boot.js +++ b/apps/gbmusic/boot.js @@ -10,7 +10,7 @@ setTimeout( // make other boot code run first, so we override e.g. android.boot. * Only runs while other apps are loaded */ function check() { - if (s!=="play" || !i || !a || !Bangle.CLOCK) return; // only launch app if we know which song we are playing, and autoLoad is enabled + if ((!s || s.state!=="play") || !i || !a || !Bangle.CLOCK) return; // only launch app if we know which song we are playing, and autoLoad is enabled delete (i.t); // store info and launch music app require("Storage").writeJSON("gbmusic.load.json", { @@ -27,7 +27,7 @@ setTimeout( // make other boot code run first, so we override e.g. android.boot. i = e; return APP ? info(e) : check(); case "musicstate": - s = e.state; + s = e; return APP ? state(e) : check(); default: // pass on other events diff --git a/apps/gbmusic/metadata.json b/apps/gbmusic/metadata.json index 0024a1708d..a463e6ea01 100644 --- a/apps/gbmusic/metadata.json +++ b/apps/gbmusic/metadata.json @@ -2,7 +2,7 @@ "id": "gbmusic", "name": "Gadgetbridge Music Controls", "shortName": "Music Controls", - "version": "0.13", + "version": "0.14", "description": "Control the music on your Gadgetbridge-connected phone", "icon": "icon.png", "screenshots": [{"url":"screenshot_v1_d.png"},{"url":"screenshot_v1_l.png"}, From 16e7ea4c6fb1696b2a35f466c38d1daa8ce10033 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Sat, 8 Feb 2025 16:01:18 -0600 Subject: [PATCH 120/135] [gbmusic] fix lint warnings --- apps/gbmusic/app.js | 109 ++++++++++++++++++++++--------------------- apps/gbmusic/boot.js | 11 +++-- 2 files changed, 62 insertions(+), 58 deletions(-) diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 8cf813fb94..1f6f6c6200 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -128,57 +128,60 @@ function rInfo(l) { .setFontAlign(0, -1) // center top .drawString(l.label, l.x+l.w/2, l.y); } -/** - * Render icon - * @param l - */ -function rIcon(l) { - const x2 = l.x+l.w-1, - y2 = l.y+l.h-1; - switch(l.icon) { - case "pause": { - const w13 = l.w/3; - g.drawRect(l.x, l.y, l.x+w13, y2); - g.drawRect(l.x+l.w-w13, l.y, x2, y2); - break; - } - case "play": { - g.drawPoly([ - l.x, l.y, - x2, l.y+l.h/2, - l.x, y2, - ], true); - break; - } - case "previous": { - const w15 = l.w*1/5; - g.drawPoly([ - x2, l.y, - l.x+w15, l.y+l.h/2, - x2, y2, - ], true); - g.drawRect(l.x, l.y, l.x+w15, y2); - break; - } - case "next": { - const w45 = l.w*4/5; - g.drawPoly([ - l.x, l.y, - l.x+w45, l.y+l.h/2, - l.x, y2, - ], true); - g.drawRect(l.x+w45, l.y, x2, y2); - break; - } - default: { // red X - console.log(`Unknown icon: ${l.icon}`); - g.setColor("#f00") - .drawRect(l.x, l.y, x2, y2) - .drawLine(l.x, l.y, x2, y2) - .drawLine(l.x, y2, x2, l.y); - } - } -} + +// *** Unused Function *** +// // /** +// // * Render icon +// // * @param l +// // */ +// // function rIcon(l) { +// // const x2 = l.x+l.w-1, +// // y2 = l.y+l.h-1; +// // switch(l.icon) { +// // case "pause": { +// // const w13 = l.w/3; +// // g.drawRect(l.x, l.y, l.x+w13, y2); +// // g.drawRect(l.x+l.w-w13, l.y, x2, y2); +// // break; +// // } +// // case "play": { +// // g.drawPoly([ +// // l.x, l.y, +// // x2, l.y+l.h/2, +// // l.x, y2, +// // ], true); +// // break; +// // } +// // case "previous": { +// // const w15 = l.w*1/5; +// // g.drawPoly([ +// // x2, l.y, +// // l.x+w15, l.y+l.h/2, +// // x2, y2, +// // ], true); +// // g.drawRect(l.x, l.y, l.x+w15, y2); +// // break; +// // } +// // case "next": { +// // const w45 = l.w*4/5; +// // g.drawPoly([ +// // l.x, l.y, +// // l.x+w45, l.y+l.h/2, +// // l.x, y2, +// // ], true); +// // g.drawRect(l.x+w45, l.y, x2, y2); +// // break; +// // } +// // default: { // red X +// // console.log(`Unknown icon: ${l.icon}`); +// // g.setColor("#f00") +// // .drawRect(l.x, l.y, x2, y2) +// // .drawLine(l.x, l.y, x2, y2) +// // .drawLine(l.x, y2, x2, l.y); +// // } +// // } +// // } + let layout; function makeUI() { Bangle.loadWidgets(); @@ -489,10 +492,10 @@ function startLCDWatch() { Bangle.on("lcdPower", (on) => { if (on) { // redraw and resume scrolling - tick(); + //tick(); // Not sure what this function was; currently undefined layout.render(); fadeOut(); - if (offset.offset!==null) { + if (layout.title.offset!==null) { // Making an assumption about what offset.offset was supposed to be if (!iScroll) { iScroll = setInterval(scroll, 200); } diff --git a/apps/gbmusic/boot.js b/apps/gbmusic/boot.js index 6cd544a217..2f1c09d8ad 100644 --- a/apps/gbmusic/boot.js +++ b/apps/gbmusic/boot.js @@ -1,6 +1,6 @@ setTimeout( // make other boot code run first, so we override e.g. android.boot.js GB () => { - const APP = global.__FILE__==="gbmusic.app.js", + const APP = globalThis.__FILE__==="gbmusic.app.js", a = !!(require("Storage").readJSON("gbmusic.json", 1) || {}).autoStart; let s, i; // state, info @@ -20,18 +20,19 @@ setTimeout( // make other boot code run first, so we override e.g. android.boot. load("gbmusic.app.js"); } - global.GB = (_GB => e => { + + globalThis.GB = (_GB => e => { // we eat music events! switch(e.t) { case "musicinfo": i = e; - return APP ? info(e) : check(); + return APP ? globalThis.info(e) : check(); case "musicstate": s = e; - return APP ? state(e) : check(); + return APP ? globalThis.state(e) : check(); default: // pass on other events if (_GB) setTimeout(_GB, 0, e); } - })(global.GB); + })(globalThis.GB); }, 1); From aa4367090bf25cbf34b494c3c572c5edb33c46e6 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Wed, 12 Feb 2025 11:17:54 -0600 Subject: [PATCH 121/135] [gbmusic] delete commented out code --- apps/gbmusic/app.js | 54 --------------------------------------------- 1 file changed, 54 deletions(-) diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 1f6f6c6200..50e7cf500b 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -91,7 +91,6 @@ function rScroller(l) { const w = g.stringWidth(l.label)+40, y = l.y+l.h/2; l.offset = l.offset%w; - //g.setClipRect(l.x, l.y, l.x+l.w-1, l.y+l.h-1) g.setColor(l.col).setBgColor(l.bgCol) // need to set colors: iScroll calls this function outside Layout .setFontAlign(-1, 0) // left center .clearRect(l.x, l.y, l.x+l.w-1, l.y+l.h-1) @@ -129,58 +128,6 @@ function rInfo(l) { .drawString(l.label, l.x+l.w/2, l.y); } -// *** Unused Function *** -// // /** -// // * Render icon -// // * @param l -// // */ -// // function rIcon(l) { -// // const x2 = l.x+l.w-1, -// // y2 = l.y+l.h-1; -// // switch(l.icon) { -// // case "pause": { -// // const w13 = l.w/3; -// // g.drawRect(l.x, l.y, l.x+w13, y2); -// // g.drawRect(l.x+l.w-w13, l.y, x2, y2); -// // break; -// // } -// // case "play": { -// // g.drawPoly([ -// // l.x, l.y, -// // x2, l.y+l.h/2, -// // l.x, y2, -// // ], true); -// // break; -// // } -// // case "previous": { -// // const w15 = l.w*1/5; -// // g.drawPoly([ -// // x2, l.y, -// // l.x+w15, l.y+l.h/2, -// // x2, y2, -// // ], true); -// // g.drawRect(l.x, l.y, l.x+w15, y2); -// // break; -// // } -// // case "next": { -// // const w45 = l.w*4/5; -// // g.drawPoly([ -// // l.x, l.y, -// // l.x+w45, l.y+l.h/2, -// // l.x, y2, -// // ], true); -// // g.drawRect(l.x+w45, l.y, x2, y2); -// // break; -// // } -// // default: { // red X -// // console.log(`Unknown icon: ${l.icon}`); -// // g.setColor("#f00") -// // .drawRect(l.x, l.y, x2, y2) -// // .drawLine(l.x, l.y, x2, y2) -// // .drawLine(l.x, y2, x2, l.y); -// // } -// // } -// // } let layout; function makeUI() { @@ -492,7 +439,6 @@ function startLCDWatch() { Bangle.on("lcdPower", (on) => { if (on) { // redraw and resume scrolling - //tick(); // Not sure what this function was; currently undefined layout.render(); fadeOut(); if (layout.title.offset!==null) { // Making an assumption about what offset.offset was supposed to be From bea0e5eccfeb92dccfe874e8ab89e1238edcd63c Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:29:00 -0600 Subject: [PATCH 122/135] [gbmusic] update sendCommand parameter jsdoc --- apps/gbmusic/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 50e7cf500b..b09d772ff0 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -367,7 +367,7 @@ function handleButton2Press() { let tCommand = {}; /** * Send command and highlight corresponding control - * @param {string} command - "play"/"pause"/"next"/"previous"/"volumeup"/"volumedown" + * @param {"play"|"pause"|"playpause"|"next"|"previous"|"volumeup"|"volumedown"} command */ function sendCommand(command) { Bluetooth.println(""); From 31377c92d3b445c0a72f8aeb69450083043e0666 Mon Sep 17 00:00:00 2001 From: Logan B <3870583+thinkpoop@users.noreply.github.com> Date: Wed, 12 Feb 2025 18:31:39 -0600 Subject: [PATCH 123/135] [gbmusic] always send playpause when toggling play/pause --- apps/gbmusic/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index b09d772ff0..31e56ec396 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -390,7 +390,7 @@ function handleTouch(btn, pos) { } function togglePlay() { - sendCommand(stat==="play" ? "pause" : "playpause"); + sendCommand("playpause"); } /** From 45d4693f45be0e2c5c95475ef7f79a1063f1e8f6 Mon Sep 17 00:00:00 2001 From: Randy Heydon Date: Thu, 6 Feb 2025 06:55:38 -0500 Subject: [PATCH 124/135] calendar: properly display synced all-day events. Discovered that, in the events synchronized from Gadgetbridge, all-day events have timestamps that disregard local timezones. Specifically, all-day events always start at midnight UTC, which caused calendar to display them starting at a different time depending on time zone offset (e.g. for my offset of -5, I see all-day events start at 19:00 the day before). Borrowed logic from the agenda app to correct this. This logic shifts an all-day event's start time to start at midnight in the current time zone. Also specify all-day events as type "o" (other) so the full day is highlighted and the start time is not displayed. Note that this does nothing to handle all-day events that span more than one day (only the first day is highlighted in the calendar). Also note that I'm not sure how this will handle time zone changes, like shifting to/from daylight savings time. --- apps/calendar/ChangeLog | 1 + apps/calendar/calendar.js | 8 +++++--- apps/calendar/metadata.json | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/calendar/ChangeLog b/apps/calendar/ChangeLog index d737ec6d4f..b5a5fbe2f8 100644 --- a/apps/calendar/ChangeLog +++ b/apps/calendar/ChangeLog @@ -20,3 +20,4 @@ 0.17: Load holidays before events so the latter is not overpainted 0.18: Minor code improvements 0.19: Read events synchronized from Gadgetbridge +0.20: Correct start time of all-day events synchronized from Gadgetbridge diff --git a/apps/calendar/calendar.js b/apps/calendar/calendar.js index ea06b70e85..d6eefce391 100644 --- a/apps/calendar/calendar.js +++ b/apps/calendar/calendar.js @@ -62,9 +62,11 @@ const loadEvents = () => { })); // all events synchronized from Gadgetbridge events = events.concat((require("Storage").readJSON("android.calendar.json",1) || []).map(a => { - // timestamp is in seconds, Date requires milliseconds - const date = new Date(a.timestamp * 1000); - return {date: date, msg: a.title, type: "e"}; + // All-day events always start at 00:00:00 UTC, so we need to "undo" the + // timezone offsetting to make sure that the day is correct. + const offset = a.allDay ? new Date().getTimezoneOffset() * 60 : 0 + const date = new Date((a.timestamp+offset) * 1000); + return {date: date, msg: a.title, type: a.allDay ? "o" : "e"}; })); }; diff --git a/apps/calendar/metadata.json b/apps/calendar/metadata.json index 5f5f21b27a..36713a487e 100644 --- a/apps/calendar/metadata.json +++ b/apps/calendar/metadata.json @@ -1,7 +1,7 @@ { "id": "calendar", "name": "Calendar", - "version": "0.19", + "version": "0.20", "description": "Monthly calendar, displays holidays uploaded from the web interface and scheduled events.", "icon": "calendar.png", "screenshots": [{"url":"screenshot_calendar.png"}], From 1bdd65dc8e4d46b963c675a4f3a5afcca1b9bacd Mon Sep 17 00:00:00 2001 From: smulrine Date: Tue, 11 Feb 2025 21:42:10 +0000 Subject: [PATCH 125/135] Create app.js --- apps/pacer/app.js | 845 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 845 insertions(+) create mode 100644 apps/pacer/app.js diff --git a/apps/pacer/app.js b/apps/pacer/app.js new file mode 100644 index 0000000000..1422f78107 --- /dev/null +++ b/apps/pacer/app.js @@ -0,0 +1,845 @@ +Bangle.loadWidgets(); +g.clear(); +Bangle.drawWidgets(); + +var cfg; +try { + cfg = require("Storage").readJSON("pacer.json",true)||{}; +} +catch(err) { + cfg = {}; +} +if (process.env.BOARD == 'BANGLEJS2') + var bangle2 = true; +else + var bangle2 = false; + +var laps = ["Off","0.25","0.5","1","2","5","10"]; +var fg = 1; +var fixed = false; +var started = false; +var startHidden = false; +var recording = false; +var invID = 0; +var intID = 0; +var startID = 0; +var cadID = 0; +var finID = 0; +var lapID = 0; +var steps = 0; +var sats = 0; +var ctr = 0; +var elapsed_ms = 0; +var finish_ms = 0; +var lap_start_ms = 0; +var lap_ms; +var gps = {fix:0,satellites:0}; +var fp; +var start_time; +var current_time; +var paused_time = 0; +var last_time = 0; +var begin_pause; +var next_lap = 0.0; +var skip_ctr = 0; +var skip_max = 0; +var force_write = true; +var show_lap = false; +var lcd_on = true; +var dist = 0.0; +var pdist = 0.0; +var oldDist = 0.0; +var oldLat = -1; +var oldLon = -1; +var oldTime = -1; +var cadence = 0; +var pace = 0; +var ppace = 0; +var R = 6371; +var stepTimes = []; +var dists = []; + +function pace_str(pval) { + var psecs = 295 + 5 * pval; + return ''+Math.floor(psecs/60)+':'+('0'+psecs%60).substr(-2); +} + +function defaults() { + if (typeof(cfg.record) != 'boolean') + cfg.record = true; + if (typeof(cfg.metric) != 'boolean') + cfg.metric = false; + if (typeof(cfg.lap_idx) != 'number') + cfg.lap_idx = 3; + if (typeof(cfg.dark) != 'boolean') + cfg.dark = true; + if (typeof(cfg.eco) != 'boolean') + cfg.eco = false; + if (typeof(cfg.storage) != 'boolean') + cfg.storage = false; + if (typeof(cfg.show_steps) != 'boolean') + cfg.show_steps = false; + if (typeof(cfg.pacer) != 'number') + cfg.pacer = 0; + fg = cfg.dark?1:0; +} + +function genFilename() { + var today=new Date(); + return ('.pacer'+today.getFullYear()+('0'+(today.getMonth()+1)).substr(-2)+('0'+today.getDate()).substr(-2)+('0'+today.getHours()).substr(-2)+('0'+today.getMinutes()).substr(-2)+('0'+today.getSeconds()).substr(-2)+'.csv'); +} + +function doCadence() { + if (steps > 0) + clearInterval(cadID); + cadID = setTimeout(function() { + cadence = 0; + }, 2000); + if (recording) { + steps++; + stepTimes.push(Date.now()); + stepTimes = stepTimes.slice(-20); + const elapsed = stepTimes[stepTimes.length - 1] - stepTimes[0]; + cadence = elapsed ? Math.round(60000 * (stepTimes.length - 1) / elapsed) : 0; + } else + stepTimes = []; +} + +function doPace(thistime,thisdist) { + dists.push([thistime,thisdist]); + dists = dists.slice(-30); + const thiselapsed = dists[dists.length - 1][0] - dists[0][0]; + const thisdistance = dists[dists.length - 1][1] - dists[0][1]; + pace = thisdistance ? ((thiselapsed) / thisdistance) / 1000 : 0; +} + +function countStep() { + if (recording) + steps++; +} + +function calcCrow(lat1, lon1, lat2, lon2) +{ + var dLat = toRad(lat2-lat1); + var dLon = toRad(lon2-lon1); + var lat1r = toRad(lat1); + var lat2r = toRad(lat2); + + var a = Math.sin(dLat/2) * Math.sin(dLat/2) + Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1r) * Math.cos(lat2r); + var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); + var d = R * c; + if (isNaN(d)) + return 0; + else + return d; +} + +function toRad(Value) +{ + return Value * Math.PI / 180; +} + +function saveGPS(fix) { + var newLat, newLon, newTime, newDist; + + try { + newTime = fix.time.getTime(); + } + catch(err) { + newTime = NaN; + } + newLat = fix.lat; + newLon = fix.lon; + gps = fix; + if (!cfg.storage) { + if (gps.satellites >= 8) + skip_max = 0; + else if (gps.satellites < 4) + skip_max = 5; + else + skip_max = 8 - gps.satellites; + } + if (recording && cfg.pacer > 0 && skip_ctr >= (cfg.storage ? 9 : skip_max)) + pdist = (elapsed_ms / 1000) / ppace; + if (isNaN(newLat) || isNaN(newLon) || isNaN(newTime)) { + skip_ctr = 0; + skip_max = 0; + force_write = true; + } else { + if (oldLat != -1 && recording) { + skip_ctr++; + if (skip_ctr > (cfg.storage ? 9 : skip_max)) { + skip_ctr = 0; + oldDist = dist; + newDist = calcCrow(oldLat, oldLon, newLat, newLon); + dist += newDist; + doPace(newTime,dist); + oldLat = newLat; + oldLon = newLon; + oldTime = newTime; + } + } else { + oldLat = newLat; + oldLon = newLon; + oldTime = newTime; + } + if (recording && cfg.record && (force_write || skip_ctr == 0)) { + fp.write([gps.time.getTime(),gps.lat.toFixed(5),gps.lon.toFixed(5),gps.alt].join(",")+"\n"); + last_time = gps.time; + if (force_write) { + skip_ctr = 0; + force_write = false; + } + } + } +} + +function drawInvert() { + // not applicable to bangle2 + g.drawImage(atob("DQ0BD4HjHwT4L8D+B/A/gfwL4J8EeMD4AA=="),225,26); +} + +function drawSatIcon() { + if (bangle2) + g.drawImage(atob("CQkBIDo7i+Pj6O4uAgA="),3,53); + else + g.drawImage(atob("DAwBEAOAcQ84T8D4HwPyHPCOAcAI"),4,66); +} + +function drawStepsIcon() { + if (bangle2) + g.drawimage(atob("CQkBBhudzudzgBzsMAA="),3,139); + else + g.drawImage(atob("DAwBAMAcMeOeeeeeeAecAcOYOAGA"),4,197); +} + +function drawCadenceIcon() { + if (bangle2) + g.drawImage(atob("CQkBCB4SEBgMBCQ8CAA="),3,139); + else + g.drawImage(atob("DAwBBAAwP4YxxDwDwDwjjGH8DAAg"),4,197); +} + +function hideStart() { + g.clearRect(bangle2?162:226,bangle2?81:113,bangle2?174:238,bangle2?93:125); +} + +function drawStart() { + hideStart(); + g.fillPoly([bangle2?162:226,bangle2?81:113,bangle2?162:226,bangle2?93:125,bangle2?174:238,bangle2?87:119,bangle2?162:226,bangle2?81:113]); +} + +function drawPause() { + hideStart(); + g.fillRect(bangle2?165:227,bangle2?82:113,bangle2?167:230,bangle2?92:125); + g.fillRect(bangle2?171:234,bangle2?82:113,bangle2?173:237,bangle2?92:125); +} + +function drawStop() { + // not applicable to bangle2 + g.fillRect(226,202,237,213); +} + +function drawExit() { + if (bangle2) + g.drawImage(atob("CQkBwfHdx8HB8d3HwQg="),165,82); + else + g.drawImage(atob("DAwBwD4HcOOcH4DwDwH4OccO4HwD"),226,202); +} + +function setColours() { + g.setBgColor(1-fg,1-fg,1-fg); + g.setColor(fg,fg,fg); +} + +function setScreenMode() { + g.reset(); + setColours(); + g.clearRect(0,24,bangle2?175:239,bangle2?151:215); +} + +function doLayout() { + setColours(); + if (!bangle2) + drawInvert(); + drawSatIcon(); + drawDist(); + drawTime(); + if (cfg.pacer == 0) + drawPace(); + else { + drawPacer(); + drawSmallPace(); + } + g.setFont("6x8",bangle2?2:3); + if (cfg.show_steps) { + drawStepsIcon(); + g.drawString(steps.toString(),bangle2?15:20,bangle2?134:190,true); + } else { + drawCadenceIcon(); + g.drawString(cadence.toString()+" ",bangle2?15:20,bangle2?134:190,true); + } + drawStart(); + if (!bangle2) + drawStop(); +} + +function drawDist() { + g.setFont("6x8",bangle2?4:5); // 3:5? + var dStr = dist.toString(); + if (dStr.indexOf('.') == -1) + dStr += '.0'; + g.drawString(((' '+(dStr.split('.'))[0])).substr(-2),bangle2?33:53,bangle2?26:35,true); + g.fillRect(bangle2?80:112,bangle2?51:66,bangle2?82:115,bangle2?53:69); + g.drawString(((dStr.split('.'))[1]+'0').substr(0,2),bangle2?86:120,bangle2?26:35,true); + g.setFont("6x8",2); + g.drawString(cfg.metric?"K":"M",bangle2?134:180,bangle2?40:56,true); +} + +function drawPacer() { + g.setFont("6x8",bangle2?3:5); + var pstr=(pdist>dist?'-':'+')+(Math.floor(Math.abs(dist-pdist)))%100; + g.drawString(pstr,bangle2?(49-(pstr.length>2?18:0)):(53-(pstr.length>2?30:0)),bangle2?107:145,true); + g.fillRect(bangle2?84:112,bangle2?126:176,bangle2?85:115,bangle2?127:179); + g.drawString(('0'+Math.floor(Math.abs(((dist-pdist)*100)%100))).substr(-2),bangle2?89:120,bangle2?107:145,true); + g.setFont("6x8",bangle2?1:2); + g.drawString(cfg.metric?"K":"M",bangle2?125:180,bangle2?121:166,true); +} + +function drawPace() { + g.setFont("6x8",bangle2?3:5); + if (pace > 0 && pace < 6000) + g.drawString((' '+Math.floor(pace/60)).substr(-2),bangle2?49:53,bangle2?107:145,true); + else + g.drawString("--",bangle2?49:53,bangle2?107:145,true); + g.fillRect(bangle2?84:112,bangle2?117:160,bangle2?85:115,bangle2?118:163); + g.fillRect(bangle2?84:112,bangle2?120:166,bangle2?85:115,bangle2?121:169); + if (pace > 0 && pace < 6000) + g.drawString(('0'+Math.floor(pace%60)).substr(-2),bangle2?89:120,bangle2?107:145,true); + else + g.drawString("--",bangle2?89:120,bangle2?107:145,true); + g.setFont("6x8",bangle2?1:2); + g.drawString(cfg.metric?"/K":"/M",bangle2?124:178,bangle2?121:166,true); +} + +function drawSmallPace() { + g.setFont("6x8",bangle2?2:3); + if (pace > 0 && pace < 6000) + g.drawString((' '+Math.floor(pace/60)).substr(-2),bangle2?113:136,bangle2?134:190,true); + else + g.drawString("--",bangle2?113:136,bangle2?134:190,true); + if (bangle2) { + g.setPixel(136,140); + g.setPixel(136,142); + } else { + g.fillRect(172,199,173,200); + g.fillRect(172,203,173,204); + } + if (pace > 0 && pace < 6000) + g.drawString(('0'+Math.floor(pace%60)).substr(-2),bangle2?138:176,bangle2?134:190,true); + else + g.drawString("--",bangle2?138:176,bangle2?134:190,true); + g.setFont("6x8",1); + g.drawString(cfg.metric?"/K":"/M",bangle2?164:212,bangle2?141:204,true); +} + +function drawTime() { + var seconds; + var minutes; + var hours; + + setColours(); + g.setFont("6x8",bangle2?5:7); + seconds = parseInt(elapsed_ms/1000) % 60; + minutes = parseInt(elapsed_ms/60000) % 60; + hours = parseInt(elapsed_ms/3600000) % 10; + g.drawString(hours.toString(),bangle2?6:5,bangle2?63:82,true); + g.fillRect(bangle2?34:44,bangle2?79:103,bangle2?36:48,bangle2?81:107); + g.fillRect(bangle2?34:44,bangle2?84:112,bangle2?36:48,bangle2?86:116); + g.drawString(('0'+minutes).substr(-2),bangle2?40:53,bangle2?63:82,true); + g.fillRect(bangle2?98:134,bangle2?79:103,bangle2?100:138,bangle2?81:107); + g.fillRect(bangle2?98:134,bangle2?84:112,bangle2?100:138,bangle2?86:116); + g.drawString(('0'+seconds).substr(-2),bangle2?104:143,bangle2?63:82,true); +} + +function drawGPSBox() { + g.drawRect(2,26,bangle2?12:17,bangle2?51:63); +} + +function drawGPS() { + g.clearRect(3,27,bangle2?11:16,bangle2?50:62); + if (gps.satellites > 0) { + if (!gps.fix) + g.setColor("#FF0000"); + else if (gps.satellites < 4) + g.setColor("#FF5500"); + else if (gps.satellites < 6) + g.setColor("#FF8800"); + else if (gps.satellites < 8) + g.setColor("#FFCC00"); + else + g.setColor("#00FF00"); + g.fillRect(3,bangle2?50:62,bangle2?11:16,(bangle2?50:62)-(gps.satellites>12?12:gps.satellites)*(bangle2?2:3)+1); + g.setColor(fg,fg,fg); + } +} + +function hideLap() { + show_lap = false; + g.reset(); + setColours(); + g.clearRect(bangle2?6:5,bangle2?63:82,bangle2?162:224,bangle2?129:182); + if (recording) { + current_time = Date.now(); + elapsed_ms = current_time - (start_time + paused_time); + } else + elapsed_ms = begin_pause - (start_time + paused_time); + drawTime(); + if (cfg.pacer == 0) + drawPace(); + else { + drawPacer(); + drawSmallPace(); + } +} + +function showLap() { + g.clearRect(bangle2?6:5,bangle2?63:82,bangle2?162:224,bangle2?129:182); + g.drawRect(bangle2?21:28,bangle2?68:90,bangle2?147:201,bangle2?124:174); + g.drawRect(bangle2?23:30,bangle2?70:92,bangle2?145:199,bangle2?122:172); + g.setFont("6x8",bangle2?1:2); + g.drawString("Last lap",bangle2?61:68,bangle2?77:102,true); + g.setFont("6x8",bangle2?3:5); + if (lap_ms < 600000) { + g.drawString((''+Math.floor(lap_ms/60000)),bangle2?57:69,bangle2?89:122,true); + g.fillRect(bangle2?74:98,bangle2?99:137,bangle2?75:101,bangle2?100:140); + g.fillRect(bangle2?74:98,bangle2?102:143,bangle2?75:101,bangle2?103:146); + g.drawString(('0'+Math.floor((lap_ms%60000)/1000)).substr(-2),bangle2?78:106,bangle2?89:122,true); + } else if (lap_ms < 3600000) { + g.drawString((''+Math.floor(lap_ms/60000)),bangle2?48:54,bangle2?89:122,true); + g.fillRect(bangle2?83:113,bangle2?99:137,bangle2?84:116,bangle2?100:140); + g.fillRect(bangle2?83:113,bangle2?102:143,bangle2?84:116,bangle2?103:146); + g.drawString(('0'+Math.floor((lap_ms%60000)/1000)).substr(-2),bangle2?87:121,bangle2?89:122,true); + } else { + g.drawString((''+Math.floor(lap_ms/3600000)).substr(-1),bangle2?37:35,bangle2?89:122,true); + g.fillRect(bangle2?54:64,bangle2?99:137,bangle2?55:67,bangle2?100:140); + g.fillRect(bangle2?54:64,bangle2?102:143,bangle2?55:67,bangle2?103:146); + g.drawString(('0'+Math.floor((lap_ms%3600000)/60000)).substr(-2),bangle2?58:72,bangle2?89:122,true); + g.fillRect(bangle2?93:131,bangle2?99:137,bangle2?94:134,bangle2?100:140); + g.fillRect(bangle2?93:131,bangle2?102:143,bangle2?94:134,bangle2?103:146); + g.drawString(('0'+Math.floor((lap_ms%60000)/1000)).substr(-2),bangle2?97:139,bangle2?89:122,true); + } + Bangle.setLCDPower(true); +} + +function mainLoop() { + g.reset(); + setColours(); + current_time = Date.now(); + if (started) { + elapsed_ms = current_time - (start_time + paused_time); + if (oldDist != dist) { + drawDist(); + if (cfg.lap_idx > 0 && dist >= next_lap ) { + show_lap = true; + next_lap += parseFloat(laps[cfg.lap_idx]); + lap_ms = elapsed_ms - lap_start_ms; + lap_start_ms = elapsed_ms; + Bangle.buzz(); + lapID = setTimeout(hideLap,5000); + showLap(); + } + } + } else + elapsed_ms = 0; + drawSats = false; + if (recording) { + if (!show_lap) + drawTime(); + g.setFont("6x8",bangle2?2:3); + if (cfg.show_steps) + g.drawString(steps.toString(),bangle2?15:20,bangle2?134:190,true); + else + g.drawString(cadence.toString()+" ",bangle2?15:20,bangle2?134:190,true); + } /* else + g.setFont("6x8",3); */ + if (!show_lap) + if (cfg.pacer == 0) + drawPace(); + else { + drawPacer(); + drawSmallPace(); + } + if (gps.fix) { + if (!started && startHidden) { + startHidden = false; + if (!bangle2) + startID = setWatch(start, BTN2); + else + startID = setWatch(start, BTN1, {edge: 'falling'}); + drawStart(); + } + if (!fixed) { + fixed = true; + drawSats = true; + } + } else { + if (!started && !startHidden) { + startHidden = true; + clearWatch(startID); + hideStart(); + } + if (fixed) { + fixed = false; + drawSats = true; + } + } + if (gps.satellites != sats) { + sats = gps.satellites; + drawSats = true; + } + if (drawSats) + drawGPS(); + if (ctr++%10 == 0) { + g.reset(); + Bangle.drawWidgets(); + } +} + +function restart(e) { + if (bangle2 && (e.time - e.lastTime > 0.5)) { + finish(); + } + g.reset(); + setColours(); + paused_time += (Date.now() - begin_pause); + pace = 0; + drawPause(); + oldDist = dist; + skip_ctr = 0; + force_write = true; + recording = true; + Bangle.buzz(); + if (!bangle2) + setWatch(pause, BTN2); + else + setWatch(pause, BTN1, { edge: 'falling' }); +} + +function pause(e) { + if (bangle2 && (e.time - e.lastTime > 0.5)) { + finish(); + } + g.reset(); + setColours(); + begin_pause = Date.now(); + elapsed_ms = begin_pause - (start_time + paused_time); + finish_ms = elapsed_ms; + drawDist(); + recording = false; + if (!show_lap) + drawTime(); + drawStart(); + oldTime = -1; + if (!isNaN(gps.time) && !isNaN(gps.lat) && !isNaN(gps.lon) && !isNaN(gps.alt) && cfg.record && (last_time != gps.time)) + fp.write([gps.time.getTime(),gps.lat.toFixed(5),gps.lon.toFixed(5),gps.alt].join(",")+"\n"); + Bangle.buzz(); + dists = []; + if (!bangle2) + setWatch(restart, BTN2); + else + setWatch(restart, BTN1, { edge: 'falling' }); +} + +function start() { + g.reset(); + setColours(); + if (cfg.eco){ + Bangle.setLCDPower(true); + Bangle.setLCDTimeout(10); + } + if (cfg.record) + fp = require("Storage").open(genFilename(),"w"); + start_time = Date.now(); + drawPause(); + Bangle.buzz(); + started = true; + recording = true; + if (!bangle2) + setWatch(pause, BTN2); + else + setWatch(pause, BTN1, { edge: 'falling' }); + if (cfg.show_steps) + Bangle.on('step',countStep); + else + Bangle.on('step',doCadence); + clearInterval(intID); + intID = setInterval(mainLoop,200); + if (cfg.lap_idx > 0) + next_lap = parseFloat(laps[cfg.lap_idx]); +} + +function endScreen() { + fg = 1-fg; + setScreenMode(); + if (!bangle2) + drawInvert(); + drawExit(); + g.setFont("6x8",bangle2?1:2); + var dStr = dist.toString(); + if (dStr.indexOf('.') == -1) + dStr += '.00'; + dStr = dStr.slice(0, (dStr.indexOf('.'))+3); + if (bangle2) + g.drawString('Distance: '+dStr+(cfg.metric?'K':'M'),38,43); + else { + //g.drawString('Distance: '+dist.toFixed(2),19,53); + g.drawString('Distance: '+dStr,19,53); + g.setFont("6x8",1); + //g.drawString(cfg.metric?'K':'M',139+12*(dist.toFixed(2).length),60); + g.drawString(cfg.metric?'K':'M',139+12*(dStr.length),60); + g.setFont("6x8",2); + } + g.drawString('Time: '+parseInt(finish_ms/3600000)%10+':'+('0'+parseInt(finish_ms/60000)%60).substr(-2)+':'+('0'+parseInt(finish_ms/1000)%60).substr(-2),bangle2?62:67,bangle2?63:83); + var avgPace = dist?((finish_ms/dist)/1000):0; + var paceStr = 'Avg Pace: '+parseInt(avgPace/60)+':'+('0'+parseInt(avgPace%60)).substr(-2); + if (bangle2) + g.drawString(paceStr+(cfg.metric?'/K':'/M'),38,83); + else { + g.drawString(paceStr,19,113); + g.setFont("6x8",1); + g.drawString(cfg.metric?'/K':'/M',19+12*(paceStr.length),120); + g.setFont("6x8",2); + } + g.drawString("Steps: "+steps,bangle2?56:55,bangle2?103:143); + var avgCadence = steps?(60*steps/(finish_ms/1000)):0; + g.drawString("Cadence: "+parseInt(avgCadence),bangle2?44:31,bangle2?123:173); + g.reset(); + Bangle.drawWidgets(); +} + +function finish() { + if (recording) { + finish_ms = elapsed_ms; + if (!isNaN(gps.time) && !isNaN(gps.lat) && !isNaN(gps.lon) && !isNaN(gps.alt) && cfg.record && (last_time != gps.time)) + fp.write([gps.time.getTime(),gps.lat.toFixed(5),gps.lon.toFixed(5),gps.alt].join(",")+"\n"); + } + recording = false; + Bangle.setGPSPower(0); + Bangle.on('step',function(){}); + Bangle.on('GPS',function(){}); + clearInterval(lapID); + clearInterval(intID); + if (!bangle2) { + clearWatch(finID); + clearWatch(invID); + } + if (!bangle2) { + setWatch(function() {if (lcd_on) endScreen();}, BTN1, {repeat:true}); + setWatch(function() {load();},BTN3); + } else + setWatch(function() {load();},BTN1); + fg = 1-fg; + endScreen(); +} + +function startScreen() { + clearInterval(intID); + if (!bangle2) { + clearWatch(invID); + } + clearWatch(finID); + setScreenMode(); + doLayout(); + drawGPSBox(); + Bangle.buzz(); + if (!bangle2) { + invID = setWatch(invertRunning, BTN1, {repeat:true}); + startID = setWatch(start, BTN2); + finID = setWatch(finish, BTN3); + } else + startID = setWatch(start, BTN1, {edge: 'falling'}); + fixed = false; + intID = setInterval(mainLoop,1000); +} + +function invertRunning() { + // not applicable to bangle2 + if (!lcd_on) + return; + fg = 1-fg; + setScreenMode(); + if (started) + if (recording) { + current_time = Date.now(); + elapsed_ms = current_time - (start_time + paused_time); + } else + elapsed_ms = begin_pause - (start_time + paused_time); + else + elapsed_ms = 0; + drawInvert(); + drawSatIcon(); + drawGPSBox(); + drawGPS(); + drawDist(); + if (show_lap) + showLap(); + else { + drawTime(); + if (cfg.pacer == 0) + drawPace(); + else { + drawPacer(); + drawSmallPace(); + } + } + g.setFont("6x8",3); + if (cfg.show_steps) { + drawStepsIcon(); + g.drawString(steps.toString(),20,190,true); + } else { + drawCadenceIcon(); + g.drawString(cadence.toString()+" ",20,190,true); + } + if (recording) + drawPause(); + else if (started || gps.fix) + drawStart(); + drawStop(); + g.reset(); + Bangle.drawWidgets(); +} + +function drawDots() { + if (ctr % 4 == 0) + g.drawString(" ",bangle2?116:176,bangle2?90:108,true); + else if (ctr % 4 == 1) + g.drawString(".",bangle2?116:176,bangle2?90:108); + else if (ctr % 4 == 2) + g.drawString("..",bangle2?116:176,bangle2?90:108); + else + g.drawString("...",bangle2?116:176,bangle2?90:108); +} + +function invertWaiting() { + /* not applicable to bangle2 */ + fg = 1-fg; + setScreenMode(); + drawInvert(); + drawExit(); + g.setFont("6x8",2); + g.drawString("Locating",68,88); + g.drawString("Satellites",56,108); + ctr--; + drawDots(); + g.reset(); + Bangle.drawWidgets(); + ctr++; +} + +function awaitGPSLoop() { + g.reset(); + setColours(); + g.setFont("6x8",bangle2?1:2); + drawDots(); + if (gps.fix) + startScreen(); + if (ctr % 10 == 0) { + g.reset(); + Bangle.drawWidgets(); + } + ctr++; +} + +function awaitGPS() { + Bangle.setOptions({wakeOnTwist:false}); + Bangle.setGPSPower(1); + Bangle.on('GPS', saveGPS); + Bangle.setLCDPower(true); + Bangle.setLCDTimeout(0); + g.reset(); + setColours(); + if (!bangle2) { + drawInvert(); + invID = setWatch(invertWaiting, BTN1, {repeat:true}); + } + drawExit(); + g.setFont("6x8",bangle2?1:2); + // g.drawString("Locating",bangle2?36:68,bangle2?72:88); + // g.drawString("Satellites",bangle2?24:56,bangle2?92:108); + g.drawString("Locating",bangle2?62:68,bangle2?78:88); + g.drawString("Satellites",56,bangle2?90:108); + intID = setInterval(awaitGPSLoop,1000); + if (bangle2) + finID = setWatch(function(){load();},BTN1); + else + finID = setWatch(function(){load();},BTN3); +} + +function main() { + require("Storage").write("pacer.json", cfg); + E.showMenu(); + if (cfg.eco) + Bangle.on('lcdPower', function(on) {setTimeout(function(){lcd_on = on;}, 500);}); + fg = cfg.dark?1:0; + R = cfg.metric?6371:3959; + ppace = 295 + 5 * cfg.pacer; + setScreenMode(); + awaitGPS(); +} + +defaults(); + +var main_menu = { + "" : { "title" : "Pacer"}, + "Start": function() { main(); }, + "Recording" : { + value : cfg.record, + format : v => v?"On":"Off", + onchange : v => { cfg.record = v; }, + }, + "Units" : { + value : cfg.metric, + format : v => v?"Metric":"Imperial", + onchange : v => { cfg.metric = v; }, + }, + "Lap" : { + value : cfg.lap_idx, + format : v => laps[v], + min : 0, max : 6, + onchange : v => { cfg.lap_idx = v; } + }, + "Dark mode" : { + value : cfg.dark, + format : v => v?"On":"Off", + onchange : v => { cfg.dark = v; }, + }, + "Eco battery" : { + value : cfg.eco, + format : v => v?"On":"Off", + onchange : v => { cfg.eco = v; }, + }, + "Eco storage" : { + value : cfg.storage, + format : v => v?"On":"Off", + onchange : v => { cfg.storage = v; }, + }, + "Steps" : { + value : cfg.show_steps, + format : v => v?"Count":"Cadence", + onchange : v => { cfg.show_steps = v; }, + }, + "Pacer" : { + value : cfg.pacer, + format : v => v==0?"Off":pace_str(v), + min : 0, max : 121, + onchange : v => { cfg.pacer = v; } + }, +}; + +if (!bangle2) { + Bangle.setLCDMode(); +} +Bangle.setLCDBrightness(1); +setScreenMode(); +E.showMenu(main_menu); From 0eb45edd1e721c84db3a3599c2035b3ad2a6d05f Mon Sep 17 00:00:00 2001 From: smulrine Date: Tue, 11 Feb 2025 21:44:04 +0000 Subject: [PATCH 126/135] Add files via upload --- apps/pacer/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/pacer/app-icon.js diff --git a/apps/pacer/app-icon.js b/apps/pacer/app-icon.js new file mode 100644 index 0000000000..33eeed26bc --- /dev/null +++ b/apps/pacer/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4cA///un/+2Eqee1nV+X26NjtfNGLsf+AQOg+kzAROnskyfACJs5CINACJshCKAjMgfJBoPwgpHLiGSpMk3kHyneO5OECIMl23Aj+AO5QRD7ZSJgPpknZkmNCIJFJhFJk1wgFtCIN4CJFCpMwAgIRCt5HIoVN8B/BCIVmEZFyt6RCCIb7Ih5SCmYRCkjoM7YRB78k6ARO++kzwQKhgRC4GEzARKswRD8mT///Lg8DtmbCILvEEw8DkmzCIUcCIWTN40bkmWUoUCCIWbCJGSrIpC5YoB5x7HCINLRZcAg3bsgwBsARNtgRBlgRLmyNBCIMlwAQJgLkBtuyMwIRHvJUBpP2GoMGCIOwCI1SBQOSr3bA4PJSQKtGSoWSpXYBAMZAwKcGoQRCpoLCZAOSoARFh5HCk4IDtmpnikMAAMOpO8CJ0KpKQKAAlyfoQANqVMCByGBt4ROgWSfhgACjmTvAROimTCB0A8mbYgwAIwmYEZ/07wRPj/wCJ4AI")) From 0505234c4fd3ef46ed9f10acd5d80900f709d120 Mon Sep 17 00:00:00 2001 From: smulrine Date: Tue, 11 Feb 2025 21:45:29 +0000 Subject: [PATCH 127/135] Add files via upload --- apps/pacer/README.md | 56 +++++++++++ apps/pacer/interface.html | 198 ++++++++++++++++++++++++++++++++++++++ apps/pacer/metadata.json | 19 ++++ 3 files changed, 273 insertions(+) create mode 100644 apps/pacer/README.md create mode 100644 apps/pacer/interface.html create mode 100644 apps/pacer/metadata.json diff --git a/apps/pacer/README.md b/apps/pacer/README.md new file mode 100644 index 0000000000..0824bc7f4d --- /dev/null +++ b/apps/pacer/README.md @@ -0,0 +1,56 @@ +## Pacer + +![icon](app.png) + +Run with a virtual partner at your chosen pace, and export the GPX data +from the Bangle.js App Store. + +## Usage + +Pacer starts up with a menu. + +* **Recording** - whether to record the run +* **Units** - imperial or metric +* **Lap** - the multiple of a mile or kilometer to use for splits +* **Dark mode** - use black or white background +* **Eco battery** - display will turn off after 10 seconds +* **Eco storage** - only record GPS position every 10 seconds +* **Steps** - display step count or cadence +* **Pacer** - pace of virtual partner + +On selecting **Start**, GPS position will be detected. A run cannot be +started without a GPS fix. The watch touchscreen is disabled while the +app is running. + +The app will run on Bangle.js 1 and 2, although use on Bangle.js 2 is not +recommended due to poor GPS accuracy. + +On a Bangle.js 1, the top button reverses the screen colours, the middle +button starts, pauses or resumes a run, and the bottom button ends the run. + +On a Bangle.js 2, a short press of the button starts, pauses or resumes a +run, and a long press (over 0.5 seconds, but under 2!) ends the run. Note +that holding the button for 2 seconds will exit back to the default clock +app. + +## Downloading + +GPX tracks can be downloaded using the +[App Loader](https://banglejs.com/apps/?id=pacer). Connect the +Bangle.js and click on the Pacer app's disk icon to see the tracks +available for downloading. + +## Tips + +For best results, only start a run when the satellite signal strength bar is +green. + +Use the [Assisted GPS Updater](https://banglejs.com/apps/#AGPS) to improve +the time taken to get a GPS fix. + +## Bugs + +The eco settings are unlikely to be useful. + +GPS track smoothing is accomplished simply by reducing the frequency with +which readings are taken, depending on signal strength. diff --git a/apps/pacer/interface.html b/apps/pacer/interface.html new file mode 100644 index 0000000000..71e8842d44 --- /dev/null +++ b/apps/pacer/interface.html @@ -0,0 +1,198 @@ + + + + + +

+
+ + + + + + + diff --git a/apps/pacer/metadata.json b/apps/pacer/metadata.json new file mode 100644 index 0000000000..1fb5fcdcd8 --- /dev/null +++ b/apps/pacer/metadata.json @@ -0,0 +1,19 @@ +{ + "id": "pacer", + "name": "Pacer", + "version": "0.01", + "description": "Run with a virtual partner", + "icon": "app.png", + "tags": "run,running,fitness,outdoors,gps", + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "interface": "interface.html", + "storage": [ + {"name":"pacer.app.js","url":"app.js"}, + {"name":"pacer.img","url":"app-icon.js","evaluate":true} + ], + "data": [ + {"name":"pacer.json"}, + {"wildcard":".pacer*.csv","storageFile":true} + ] +} From 37eccc26e7841b27daaed49c066c79e2bef413c2 Mon Sep 17 00:00:00 2001 From: smulrine Date: Tue, 11 Feb 2025 22:22:09 +0000 Subject: [PATCH 128/135] Add files via upload --- apps/pacer/app.png | Bin 0 -> 2263 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/pacer/app.png diff --git a/apps/pacer/app.png b/apps/pacer/app.png new file mode 100644 index 0000000000000000000000000000000000000000..92148056878e20aa72bc542fb374db0203226a15 GIT binary patch literal 2263 zcmV;|2q^c7P)+aIooC0iiNvOPJ!q`T*Q=ljmRXYbt$@Etd7Fq2nSmQebjP)3rX1sG0Xp&)N& zJg%~*R-H1(i!o>dPVAW{RV(Q;Lr0Gvt<`5q0007hAKdu&g(kPh_1w&5pPr5f2k&2+ zu}!TM?-)7$$#G%w003fI3ge1qapTRId@#IhVHHr{mwUvwBOwZ2wW&RVRbdQ5NS>Fy{GdM_T30PX1f@%Kt z4I6&3YiISod6Q*Q*($(LN-z|xX4-uF=DzfKAYL8`3HWU9PZb(DeQfBc@kN@9OzGqN zU49 zhoxh)K%r7ks`_Y-w%-J#L3=}+)zTK^c>n-tZ8CeVT|8ffETJchSAW?Q?Z55g)f-5q zHd88&x#0ri^T8Mm4Jt7S#$h82Dq6m!w*q?A1E>EqH&?1s?#6La&2jAEX^W4&+mqj( zJteBUiUM2SkODD=#YlkwtgS8Z%2XqeM5oVx&Yix6J-9wyqtQqklnTn=>hgxv;tIg)OSQ44lAYFCBk?1I+7a+PHl0rvL!8 ze_3>u^ZShyO#=XcA%B>rwXxyoh04WuqGJ(4Z7k>AK5O}jD@hmd){YIYH@9V{id+Qn zIYH1CkkC^LSX(VYCEHOP{_pj9UTbQ&Ra7uyj1~YuL{U&Q`)5V~Fhh$1ilfmtp00g{3grA#XK+biX+x)`bht(}!S#{lR zwcJI5&O8>N zZTACwgZt^|c+SsNv^JaLIt#I0MgRdlytU}_5_;#&-%h{n)Xm25PLknegX1`)YBIpj z_@M5r0~AA8qzSpUmYMeZqcNs0J9f0Tk|_1KoKvK7r7HS)*tme7d2qk^j>FAvO^N`M z$%MBBiQ_>5$1oHGmhpm2sfh5QrBV>n5^$NVn2Jz#BM$)3`SDV@uzlsh?P>`N z*tzwk@%7%^OI#?DEhQF%CPNPd*?lVr1w#;Y)VoQ}mu51Vf{EttY6&;7J*26QCJz9> z1p@HEVgW9|c8eiM0tlr+NlD>CqItVvCK6O$UUsO-t(n-$hz(nM^n#CF*!dUV%uWj1Ykk0Bbk%TI}}Nb(`M5nG^vvpDcWF*ywTF zbeRS^p1?z=7^u1S?Mp=};)4d2b>;f?6$iWeZ7qNO5+ll)K+97jLhy7u2LLFYB?E)5bD~tV-=9OZ7DbZ>0N7mi+C&9!KJ9baBJO!`k_23p ztE6ODpZejUfKY%x(tM}R8E>G7z+mANE|96{Xd9}s8rQx0_N7?9o63G)oQlkcSy!uo z5C9So@T>>OkOvepYQz^G&7YL0fQV_WIa0DlOi{}TLKOQj|9?Y*z;T@atOY|`N=uK1 z;z?Ff@yd2vApPYmt(cfLhJw*~B=7-0TseQ{@RUVImLwt|qFJZ^{OE1~*qsPaJmz*& zzneee((K7IXO9RUIRXI|2`JQ(DCU6PPR}T~zC5pRxUuUo+gx|E(d+Eko+##k2|x%i zT0(C~HyCB%F`vf`UbpM)Q)^B=NECO#1k@aQc12G9@Vu_oufKWi9^-Uv>I?3G2 Date: Wed, 12 Feb 2025 00:11:22 +0000 Subject: [PATCH 129/135] minor code fixes --- apps/pacer/app.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/apps/pacer/app.js b/apps/pacer/app.js index 1422f78107..d12a13b017 100644 --- a/apps/pacer/app.js +++ b/apps/pacer/app.js @@ -46,12 +46,12 @@ var skip_max = 0; var force_write = true; var show_lap = false; var lcd_on = true; +var drawSats = false; var dist = 0.0; var pdist = 0.0; var oldDist = 0.0; var oldLat = -1; var oldLon = -1; -var oldTime = -1; var cadence = 0; var pace = 0; var ppace = 0; @@ -176,12 +176,10 @@ function saveGPS(fix) { doPace(newTime,dist); oldLat = newLat; oldLon = newLon; - oldTime = newTime; } } else { oldLat = newLat; oldLon = newLon; - oldTime = newTime; } if (recording && cfg.record && (force_write || skip_ctr == 0)) { fp.write([gps.time.getTime(),gps.lat.toFixed(5),gps.lon.toFixed(5),gps.alt].join(",")+"\n"); @@ -540,7 +538,6 @@ function pause(e) { if (!show_lap) drawTime(); drawStart(); - oldTime = -1; if (!isNaN(gps.time) && !isNaN(gps.lat) && !isNaN(gps.lon) && !isNaN(gps.alt) && cfg.record && (last_time != gps.time)) fp.write([gps.time.getTime(),gps.lat.toFixed(5),gps.lon.toFixed(5),gps.alt].join(",")+"\n"); Bangle.buzz(); From 88807d5735224afbd2863e7a312105e31408381f Mon Sep 17 00:00:00 2001 From: smulrine Date: Wed, 12 Feb 2025 23:18:36 +0000 Subject: [PATCH 130/135] Add files via upload --- apps/pacer/screenshot.png | Bin 0 -> 2592 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/pacer/screenshot.png diff --git a/apps/pacer/screenshot.png b/apps/pacer/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..d97f04d7d9c7619d8b802b15905a92869e412f23 GIT binary patch literal 2592 zcmb7``8(8o7so%}8Dq>COK6yssfc7ZNLjN?m@;T`yRB0~Su(QUwjm`?gu+imA39r`$@M}S6AXsz)^|B_alH1y=VR<8_*VMs_D$EpNkg|2> zE6!UqH#M)DX2iN92jJqb1ICn9H9xhDmYxm3(O~nnRnKGLeQBX7XO%b`$WfA<9sB?lBDt<15d)@H^<_AF;DFkPylIqCz5g&11p)9XX`95k6 zuHe(1x2KU5yx9(Wt!hK6ZIdB13ch*_uY|hmSM$EI^~gg;Dg+b$ZUU;P-L&Ofrb*M@ zpHF^y3n&C_=i18HauVaKY;zE?ULwnG&uZDIGRhqT!Qb9pm*Zm!^69Ud(NsSbPknMh zm%9km;wBm_#8IS&qINOet|!OH58h4-vKLw5R;0W^*9KM0V6aL2`_d|`;cmsazG85M zFL#hD+$eL!qKm?`8a~Fo2HL{4gTbJI|7*l)|7oOZ){4{R@`or07#(R#;s++WqEe$=gGy#iY z2NeMv+z>Dop=F8wrz#8Nxe9sxM!rHDHMvSxG&IKQ0?(afYnaGvNgJ+^L%>74CX+!i| z9Nwq%Nhcn(Zxrzr)2LRP#1~7GUjAHbeSD}OjOhe*S+cd#K#J*xz54LP_4KJA91L(U zsrOwq)vkHu4+HI8``oF`KAHDyx9^%Mvyad%Zhb8SRDUTjl5$%Ko}(UXBi@OOGJ%-d z;&q$F3x3lgoi87D!v9iH!{9X;grLldP8j4lw^>e49&xFS|K5uyNHK~0>e?KSv<7!f znsi_?-k@58kcErPjh!C97^6pBM>d_|zekFzDYp@?`SAJblRn!YH+2GfC_)qK^JAPox+0aIC71Ocw2v1@-TicM|$qY2_ zbgv*2lFBFNCMY^&y}O8~H*sAFzyE!U$a*z8{d~ieAmLyKUF3JYaYeWJ7SCwRvkLSq zK=gIrS}6kX-#0raEXFL59#Z@ho}{4t zkJc)$SGC-&?y8^Df8^krB0wn72<**=2z9`LUuoDiErRac)-!nHgk?xYtZCk>h@LYF z;JSWC)kAtCa)iE9&v{d2fb#FGB1cxw5^`NIp*&KjB4UEqbFB8QsvDmrhv1JNm7<>qct7F zcK#F4f&DOSpuiBOFJRCx&_4!?)m=mr47})_N3X{d2V~EWP4%ZEat??8N29@Q{Xw0C z+}N2{p!AgB<}Y!3uKY7!dP=IUn$*43XSnu8eyl?>(&9cQ@}lv2jiSJtMnxd`Sck&D z#w(s~6ou45`F=ouMcWi=j{m;MI-uKUYRj+lNrZHqUJ5|2W#SPL6c{lL-qyMRm_5a9 zsR;^pl&`F9KGerPIJhm?I#Dc2qbg4BPz%-zhQAxZO z=d5ty#{o&}%;Rfr>)-s9 z8tp@rp|#g2xJ=+XqOGek#?&%7p4< zU4NcOs)Nn4XYL{?z@hp{!F%;hy#>czqm}YdOB?SNS!(NfBxiw@m>y>=q@OoTN#Kod zS3)O@BfxYLmhaunl(8GU!VZk74^`Bn#@XuyB+}Mh&mu!TYY`03eZzah&FP|^fsYH0_$BA872-t~ z(wu#MbIQERV|=AOKidNs%2W*#HLD1hrA%UVP%J6I@mYC0iId&Db-Zho9a}<3MM^Lg^?}sNvaF&=y06d5L}v1;Q3MAN4^iJiuFi10P$%!R^?R{eWH4ny?OVNQx4G wDG4HTkQ9HWJz%ngiM>d5-2YVe|7pw-nGNqLH6zQY@J>EpX>M&+X+n?tFVEPW{r~^~ literal 0 HcmV?d00001 From 4d8acef7a722c2f6e7ab1eb5b9a7b497e663ea1f Mon Sep 17 00:00:00 2001 From: smulrine Date: Wed, 12 Feb 2025 23:20:06 +0000 Subject: [PATCH 131/135] added screenshot --- apps/pacer/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/pacer/metadata.json b/apps/pacer/metadata.json index 1fb5fcdcd8..87d5fb1cec 100644 --- a/apps/pacer/metadata.json +++ b/apps/pacer/metadata.json @@ -8,6 +8,7 @@ "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "interface": "interface.html", + "screenshots": [{"url":"screenshot.png"}], "storage": [ {"name":"pacer.app.js","url":"app.js"}, {"name":"pacer.img","url":"app-icon.js","evaluate":true} From 69bf06f8b2e0e379769dbd35ec41815b77ae0595 Mon Sep 17 00:00:00 2001 From: smulrine Date: Wed, 12 Feb 2025 23:21:51 +0000 Subject: [PATCH 132/135] fixed Bangle.js2 exit icon --- apps/pacer/app.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/apps/pacer/app.js b/apps/pacer/app.js index d12a13b017..6b2b9efcef 100644 --- a/apps/pacer/app.js +++ b/apps/pacer/app.js @@ -46,7 +46,7 @@ var skip_max = 0; var force_write = true; var show_lap = false; var lcd_on = true; -var drawSats = false; +var drawSats = true; var dist = 0.0; var pdist = 0.0; var oldDist = 0.0; @@ -507,21 +507,22 @@ function mainLoop() { function restart(e) { if (bangle2 && (e.time - e.lastTime > 0.5)) { finish(); + } else { + g.reset(); + setColours(); + paused_time += (Date.now() - begin_pause); + pace = 0; + drawPause(); + oldDist = dist; + skip_ctr = 0; + force_write = true; + recording = true; + Bangle.buzz(); + if (!bangle2) + setWatch(pause, BTN2); + else + setWatch(pause, BTN1, { edge: 'falling' }); } - g.reset(); - setColours(); - paused_time += (Date.now() - begin_pause); - pace = 0; - drawPause(); - oldDist = dist; - skip_ctr = 0; - force_write = true; - recording = true; - Bangle.buzz(); - if (!bangle2) - setWatch(pause, BTN2); - else - setWatch(pause, BTN1, { edge: 'falling' }); } function pause(e) { From 9e99d0643ad3504ba77b9bc323fad2e57aeea756 Mon Sep 17 00:00:00 2001 From: MomentumV Date: Thu, 13 Feb 2025 13:43:35 -0500 Subject: [PATCH 133/135] Fix linter complaints Commented out the utility functions and variables used to make documentation. Seems like there should be a better approach, maybe an extra dev.js? --- apps/daymoon/app.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/apps/daymoon/app.js b/apps/daymoon/app.js index cb560ae9f7..ce403fdfeb 100644 --- a/apps/daymoon/app.js +++ b/apps/daymoon/app.js @@ -186,9 +186,7 @@ function tToRad(date) { } function draw(date) { - d = date !== undefined ? date : new Date(); - - //var d = new Date(), + var d = date !== undefined ? date : new Date(); var a = tToRad(d), shape = moonShade(M_POS, SunCalc.getMoonIllumination(d)), sTimes = SunCalc.getTimes(d, location.lat, location.lon), @@ -205,15 +203,16 @@ function draw(date) { }); } +/* const shotTimes = [1720626960000, 1729184400000, 1738298880000, 1717575420000]; -/*first quarter -2 days moon at 10:20 in the summer +let desc =`first quarter -2 days moon at 10:20 in the summer jun 10 2024 10:56 full moon at 12 noon near fall equinox Sep 17 2024 12:00 new moon at 11pm in winter dec 30 2024 23:48 3rd quarter moon at 03:17 am - May 5 2024 03:17*/ + May 5 2024 03:17` function screenshots(times) { let d = new Date(); @@ -223,7 +222,7 @@ function screenshots(times) { g.dump(); } } - +*/ // Clear the screen once, at startup g.reset(); // requires the myLocation app From ba590dba1c996abd02e11a81eb73f225c04fc772 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 15 Feb 2025 03:25:46 +0100 Subject: [PATCH 134/135] msgtwscr: fix formatting of metadata tags --- apps/msgtwscr/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/msgtwscr/metadata.json b/apps/msgtwscr/metadata.json index 5bf1e97366..6f267ea011 100644 --- a/apps/msgtwscr/metadata.json +++ b/apps/msgtwscr/metadata.json @@ -3,7 +3,7 @@ "version":"0.01", "description": "Temporarily activate scroll on twist function when a new message triggers the message app.", "icon": "app.png", - "tags": "messages,tweak, scroll", + "tags": "messages,tweak,scroll", "type": "bootloader", "supports" : ["BANGLEJS2"], "readme": "README.md", From d18ddceb33a78f803c80d065aba2299cdeefce1b Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com⁩> Date: Sat, 15 Feb 2025 03:42:00 +0100 Subject: [PATCH 135/135] msgtwscr: unlock the watch on twist as well Maybe implement this in a separate app instead. --- apps/msgtwscr/boot.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/msgtwscr/boot.js b/apps/msgtwscr/boot.js index 821561bdc8..22bc03bccf 100644 --- a/apps/msgtwscr/boot.js +++ b/apps/msgtwscr/boot.js @@ -19,6 +19,8 @@ function onTwistEmitDrag() { Bangle.setOptions({twistThreshold:2500, twistMaxY:-800, twistTimeout:400}); Bangle.on("twist", ()=>{ + Bangle.setLocked(false); + Bangle.setLCDPower(true); let i = 25; const int = setInterval(() => { Bangle.emit("drag", {dy:-3})