From ac3d0acedcce80c31527e4502a54a16045a5de60 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Thu, 14 Apr 2022 22:35:38 +0200 Subject: [PATCH 01/78] dragboard app added --- apps/dragboard/ChangeLog | 2 + apps/dragboard/README.md | 23 +++ apps/dragboard/app.png | Bin 0 -> 1514 bytes apps/dragboard/lib.js | 346 ++++++++++++++++++++++++++++++++++ apps/dragboard/metadata.json | 14 ++ apps/dragboard/screenshot.png | Bin 0 -> 2215 bytes 6 files changed, 385 insertions(+) create mode 100644 apps/dragboard/ChangeLog create mode 100644 apps/dragboard/README.md create mode 100644 apps/dragboard/app.png create mode 100644 apps/dragboard/lib.js create mode 100644 apps/dragboard/metadata.json create mode 100644 apps/dragboard/screenshot.png diff --git a/apps/dragboard/ChangeLog b/apps/dragboard/ChangeLog new file mode 100644 index 000000000..b12304571 --- /dev/null +++ b/apps/dragboard/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Added some missing code. diff --git a/apps/dragboard/README.md b/apps/dragboard/README.md new file mode 100644 index 000000000..13f89bbcb --- /dev/null +++ b/apps/dragboard/README.md @@ -0,0 +1,23 @@ +Swipe along the red field and release to select a letter. + +Do the same for green field to select number or punctuation. + +Release on left or right part of black field for backspace or space. + +Swiping between the different fields is possible! + +The drag in Dragboard is a nod to the javascript 'drag' event, which is used to select the characters. Also, you can't help but feel somewhat glamorous and risque when this is your keyboard! + +Known bugs: +- Initially developed for use with dark theme set on Bangle.js 2 - looks aweful with other themes. +- Keyboard is not exited correctly when trying to close the keyboard. +- Text is drawn over system back button. +- Text does not wrap. + +To do: +- Make keyboard theme agnostic. +- Keep number/punctuation color one color. +- Handle system back button in some way. +- Make text wrap and/or scroll up/sideways once available space runs out. +- Optimize code. Further split it up in functions. Add 'ram' keyword where suitable. +- Possibly provide a dragboard.settings.js file diff --git a/apps/dragboard/app.png b/apps/dragboard/app.png new file mode 100644 index 0000000000000000000000000000000000000000..26e7518960bb859db3c3aa7802bd20406e7d1604 GIT binary patch literal 1514 zcmVXTO*^&uvR#&ToY#3)6v z8Mwoqa|wv|A%Q*!KG~*^MIwseQwVaIJ0~-7DvcpcFqn$?RYcG>HVs(Ol4|_OEr^Z@ zGjsOp!<;KObLaD%$<2#@81|mE)?Rz9S!?atA3_%dL9oU-cU(j+7K_DuyUC_SKA(TX zIk&W4uRl?_t7Logk#p3yHV=}D--}g_%3IN9H_4;{hZP$rKF11J!`M6he>iVEt1Z;AOZlD zO6BVy2!0taqZ|6kMS#i4$(tID#xo+aJtn;pMbYEsa`{}ZvGZ#0L(lWJ&CJYv)oToN zsezf9nXf$0+or1TiO9u%jE|z|0}=TRusr_kGRAx`F)?vtukj*sQB~g?#CYhCLP=n) zeF=C3H~~yWQ6$Eg1Hk>jpTaQA4r{LY7|JRX<5vL2n8(5}{BOBjJ{LvNRLtAnWn3x@ z(}CrH77B&W<_Pn0|JotWa~X!|z*WJI4qR>g=)iywhPZS?hkxQL0c-7XU~4?*Dd34P z3{R)kyOz^l*Lt4!Y+9v@=75OoEffl~ zg+gK0Ikz{aZJT40ur?N>22KKQ{?@o$E`J`M@|Ig`PXOaUMnq25>-FCrK79D&ewC++ z!1(xhW@>6`q?=3_hC9MA+}TCseqbq(QPl@Bnauk^5NznzhC~st)@}lx2DVhIRn6z~ z@APr1YztLAqNo2M!HvIs64U)><2JcQl{R zA6>U@UDfyfsdxJ0$~GzP0vCU`-T7HTtto~(ANnsJLgsd*Tw%ED^+!0t5A|6 zo(0xkx^!s;@a-J2SS&u6*wi*K#_SEl@B%;(1dluC9;Ue!xeNn4psN2Ak+r~P;6JG? zU5J+fH~(a3j5+U|16b86Jg@^I@(v4BuHk&nR4C@ynvNCSdM<8CS&jQzsjEvlq-n`z3 zqUaU?RsE!umvqfO3gCI(f_%La5Rp6L?%!K^i5zgw9RX0)U5k`Px5w>*6I>z(N~O}@ zfRBJ1ec!)gw{Fnf57B(;!t=c0H~=VcFz)Z^CYToM*RS79^VaX9c9*`1_btx37l118 zptbh4Uh*lh9Y9rIX~#_LK&e!^psELHz6AX~sh(a?)g5trvK>Fw&M}k8><6lolNRm ziP6!~{UY))a7VRT{aspp^P#Gfaa-slliGm;2M&A>Oac+`q_uV^%W4n=x6(|XZ)&yL z(N1zhxfd!Hi*KvyQ-A?x;&XFiWV2a6ilQgtuP;_Am5y(8L%SEM*X#Ry-`@!A@I3Ed zy= ( g.getHeight() - 12 )) { + // Translate x-position to character + if (event.x < abcPadding) { charHL = 0; } + else if (event.x >= 176-abcPadding) { charHL = 25; } + else { charHL = Math.floor((event.x-abcPadding)/6); } + + // Datastream for development purposes + //print(event.x, event.y, event.b, abc.charAt(charHL), abc.charAt(charHLPrev)); + + // Unmark previous character and mark the current one... + // Handling switching between letters and numbers/punctuation + if (typePrev != 'abc') { + // Small character in list + g.setColor(0,1,0); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + // Large character + g.setColor(0,0,0); + g.setFont('6x8:3'); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + } + + if (charHL != charHLPrev) { + // unmark in the list + g.setColor(1,0,0); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + // hide previous large character + g.setColor(0,0,0); + g.fillRect(0,g.getHeight()/3,176,g.getHeight()/3+24); + g.setColor([0,0,0]); + g.setFont('6x8:3'); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + // mark in the list + g.setColor(1,1,1); + g.setFont('6x8'); + g.drawString(abc.charAt(charHL), abcPadding + charHL*6, g.getHeight()/2); + // show new large character + //g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString(abc.charAt(charHL), abcPadding + charHL*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + } + // Print string at top of screen + if (event.b == 0) { + text = text + abc.charAt(charHL); + updateTopString(); + + // Autoswitching letter case + if (abc.charAt(charHL) == abc.charAt(charHL).toUpperCase()) { + g.setColor(0,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + abc = abc.toLowerCase(); + g.setColor(1,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + letterCase = 0 + } + //print(text); + } + // Update previous character to current one + charHLPrev = charHL; + typePrev = 'abc'; + } + + // 12345678901234567890 + // Choose number or puctuation by draging on green rectangle + else if ((event.y < ( g.getHeight() - 12 )) && (event.y > ( g.getHeight() - 52 ))) { + // Translate x-position to character + if (event.x < numPunctPadding) { numPunctHL = 0; } + else if (event.x > 176-numPunctPadding) { numPunctHL = numPunct.length-1; } + else { numPunctHL = Math.floor((event.x-numPunctPadding)/6); } + + // Datastream for development purposes + //print(event.x, event.y, event.b, numPunct.charAt(numPunctHL), numPunct.charAt(numPunctHLPrev)); + + // Unmark previous character and mark the current one... + // Handling switching between letters and numbers/punctuation + if (typePrev != 'numPunct') { + // Small character in list + g.setColor(1,0,0); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + // Large character + g.setColor(0,0,0); + g.setFont('6x8:3'); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + } + if (numPunctHL != numPunctHLPrev) { + // unmark in the list + g.setColor(0,1,0); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + // hide previous large character + g.setColor(0,0,0); + g.fillRect(0,g.getHeight()/3,176,g.getHeight()/3+24); + g.setColor(0,0,0); + g.setFont('6x8:3'); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + // mark in the list + g.setColor(1,1,1); + g.setFont('6x8'); + g.drawString(numPunct.charAt(numPunctHL), numPunctPadding + numPunctHL*6, g.getHeight()/4); + // show new large character + //g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString(numPunct.charAt(numPunctHL), numPunctPadding + numPunctHL*6 -largeCharOffset, g.getHeight()/3); + g.setFont('6x8'); + } + // Print string at top of screen + if (event.b == 0) { + g.setColor(1,1,1); + // Backspace if releasing before list of numbers/punctuation + if (event.x < numPunctPadding) { + // show delete sign + g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString('del', g.getWidth()/2 -27, g.getHeight()/3); + g.setFont('6x8'); + delLast = 1; + + text = text.slice(0, -1); + updateTopString(); + //print(text); + } + // Append space if releasing after list of numbers/punctuation + else if (event.x > g.getWidth()-numPunctPadding) { + //show space sign + g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString('space', g.getWidth()/2 -6*3*5/2, g.getHeight()/3); + g.setFont('6x8'); + spaceLast = 1; + + text = text + ' '; + updateTopString(); + //print(text); + } + // Append selected number/punctuation + else { + text = text + numPunctHidden.charAt(numPunctHL); + updateTopString(); + + // Autoswitching letter case + if ((text.charAt(text.length-1) == '.') || (text.charAt(text.length-1) == '!')) { + g.setColor(0,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + abc = abc.toUpperCase(); + g.setColor(1,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + letterCase = 1; + + } + //print(text); + } + } + // Update previous character to current one + numPunctHLPrev = numPunctHL; + typePrev = 'numPunct'; + } + // Make a space or backspace by swiping right or left on screen above green rectangle + else { + if (event.b == 0) { + g.setColor(1,1,1); + if (event.x < g.getWidth()/2) { + // unmark character in the list + g.setColor(1,0,0); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + + // unmark number/punctuation in the list + g.setColor(0,1,0); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + + // hide previous large character + g.setColor([0,0,0]); + g.setFont('6x8:3'); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + + // hide previous large character + g.setColor(0,0,0); + g.setFont('6x8:3'); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); + + // show delete sign + g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString('del', g.getWidth()/2 -27, g.getHeight()/3); + g.setFont('6x8'); + delLast = 1; + + // Backspace and draw string upper right corner + text = text.slice(0, -1); + updateTopString(); + if (text.length==0) { + g.setColor(0,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + abc = abc.toUpperCase(); + g.setColor(1,0,0); + g.drawString(abc, abcPadding, g.getHeight()/2); + letterCase = 1; + } + //print(text, 'undid'); + } + else { + // unmark character in the list + g.setColor(1,0,0); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + + // unmark number/punctuation in the list + g.setColor(0,1,0); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + + // hide previous large character + g.setColor([0,0,0]); + g.setFont('6x8:3'); + g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + + // hide previous large character + g.setColor(0,0,0); + g.setFont('6x8:3'); + g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); + + //show space sign + g.setColor(1,1,1); + g.setFont('6x8:3'); + g.drawString('space', g.getWidth()/2 -6*3*5/2, g.getHeight()/3); + g.setFont('6x8'); + spaceLast = 1; + + // Append space and draw string upper right corner + text = text + numPunctHidden.charAt(0); + updateTopString(); + //print(text, 'made space'); + } + } + } + }); + + return new Promise((resolve,reject) => { + Bangle.setUI({mode:"custom", back:()=>{ + Bangle.setUI(); + g.clearRect(Bangle.appRect); + resolve(text); + }}); + }); + +}; diff --git a/apps/dragboard/metadata.json b/apps/dragboard/metadata.json new file mode 100644 index 000000000..f8f1f6c85 --- /dev/null +++ b/apps/dragboard/metadata.json @@ -0,0 +1,14 @@ +{ "id": "dragboard", + "name": "Dragboard", + "version":"0.02", + "description": "A library for text input via swiping keyboard", + "icon": "app.png", + "type":"textinput", + "tags": "keyboard", + "supports" : ["BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"textinput","url":"lib.js"} + ] +} diff --git a/apps/dragboard/screenshot.png b/apps/dragboard/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..a9451d1a43161be0d33b1686743d9564663a15a9 GIT binary patch literal 2215 zcmds3Ygm$J82-R-iZvZ9%``BR%x!tdv@!%dgo2uq);vThO^dQ(nu-THeXX*oQ`9_V zV42z~@@%99l9hCXg@&a@PR&X@rY3kC+rR$q$98Q$-sf;#_x)VY_1w?-nPS0>_q`NXgYwrgLF6)2;1aj)wzt?M zumx%ZNl<12>#e6s*4Z0#`}Ihxq_E{Uo;fu$r^#qFvVSmS#<2YA5vLcQcmZp%_{c+b zGP)hBIRcDA9me)_z?=);na!31A45 z(I4&vy_++mu6@>I+t&n^<3@uS`x{Fp<83Qa>f1L}nv>1Ki}DR;V@=NNH`s|wofs!j zS{rU~heq_0A9pm=vM@^2YK8b7zSHG#^@XTmn?v()bOux}-4-T@D`Dx!%nEA^g*7_) z7esk3T&v%F=J`RQweo#N@P_?~h38(ijg zBJs4d{iiaF`bcs*06DI^)S$X7crYmM^pR&Xj^_}A8MK2XLJ9@ zp|Oi*JJNbDA9*GaG==Bz>|v83%}SH-h}=UGudzv8KfSk8M_!ENy(_adts9@Fc1f+H z>$&YIA(LS&&&NR%$~O{=dXAizC`>EQ?IVn+Xu<>g7k>!q_@uEsW;`|NH`b9fXZ?}r zn;#`e_TJ)M+W16KV%{{>GBC&o>8guH za@x{nrD)jb8KH{uhBXkH#mDcJ7%VIH?aoTH?NTnk5q2e4@jz%rF5H~mkgLXo3)jx{ zGwUjq{9hR^8{m4YMmqziPiJTNoV%{Gu;G<+aVv;aJ9+4it~w#+O%%>J!9e0K92j2T zqRRScKT)eA6&ndq;fO)+;s&br4z(go#W?_+EoTh>MQv8;I?pe@fghH;qIYdPnwo`j zjxI!o*c-xC>0Oq{5OSs%hZP_|#dBb|u z32kvpxVA0vgWU#v6Fn&2i-|(;FO%uqEE)(`y+?&GNF+KOfxhKjTE4`M&PAaheT(Ss z9?p4xK#L}Ut51lbw9QdC7^pBsp$Y)Fo}J;<4)7*XAbnF3D&uq!FAtf zh`aCctcMfv}%uDT5iEB@W z;%eJMRhmxjPWG<-ai<0E_QBq)IqxJjhReEOH23a_4F)L|PQA!M> zKTl{m>Z8Yum7l5=5gRYsBxTsKZq$aFHK#ih-1+Fb3|wQxB)W>oFn-kq)vt+ptB4S; zuUr&c9v#SJ*l+Q}KT%_u9qJvDAtBMM_I~?_qgR5@P;+%EO?F^FjD;A?-It}SUz?ZG z=AU9NJ?w(#^8~yfLrb29bt{tCPcAq9lzEC1;wu=;RexfZ=y$M%!3ozN_8T6=aBdZ^ zw1^)lE+j~85a=sQBWv6M$mC)S1+A6ozn40EajZa8VQctc;oF?s6MpeTB=ThnTN#Ra zxzz<%1 Date: Tue, 19 Apr 2022 23:03:59 +0200 Subject: [PATCH 02/78] dragboard v0.03 --- apps/dragboard/ChangeLog | 1 + apps/dragboard/README.md | 9 +- apps/dragboard/lib.js | 480 ++++++++++++++-------------------- apps/dragboard/metadata.json | 2 +- apps/dragboard/screenshot.png | Bin 2215 -> 2487 bytes 5 files changed, 204 insertions(+), 288 deletions(-) diff --git a/apps/dragboard/ChangeLog b/apps/dragboard/ChangeLog index b12304571..415ffbb09 100644 --- a/apps/dragboard/ChangeLog +++ b/apps/dragboard/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Added some missing code. +0.03: Made the code shorter and somewhat more readable by writing some functions. Also made it work as a library where it returns the text once finished. The keyboard is now made to exit correctly when the 'back' event is called. The keyboard now uses theme colors correctly, although it still looks best with dark theme. The numbers row is now solidly green - except for highlights. diff --git a/apps/dragboard/README.md b/apps/dragboard/README.md index 13f89bbcb..56feaf6a4 100644 --- a/apps/dragboard/README.md +++ b/apps/dragboard/README.md @@ -9,15 +9,10 @@ Swiping between the different fields is possible! The drag in Dragboard is a nod to the javascript 'drag' event, which is used to select the characters. Also, you can't help but feel somewhat glamorous and risque when this is your keyboard! Known bugs: -- Initially developed for use with dark theme set on Bangle.js 2 - looks aweful with other themes. -- Keyboard is not exited correctly when trying to close the keyboard. -- Text is drawn over system back button. +- Initially developed for use with dark theme set on Bangle.js 2 - that is still the preferred way to view it although it now works with other themes. - Text does not wrap. To do: -- Make keyboard theme agnostic. -- Keep number/punctuation color one color. -- Handle system back button in some way. - Make text wrap and/or scroll up/sideways once available space runs out. -- Optimize code. Further split it up in functions. Add 'ram' keyword where suitable. +- Optimize code. Further split it up in functions. - Possibly provide a dragboard.settings.js file diff --git a/apps/dragboard/lib.js b/apps/dragboard/lib.js index 693dbc418..31fac8998 100644 --- a/apps/dragboard/lib.js +++ b/apps/dragboard/lib.js @@ -7,340 +7,260 @@ exports.input = function(options) { var text = options.text; if ("string"!=typeof text) text=""; - //Draw the alphabet on the screen + var BGCOLOR = g.theme.bg; + var HLCOLOR = g.theme.fg; + var ABCCOLOR = g.toColor(1,0,0);//'#FF0000'; + var NUMCOLOR = g.toColor(0,1,0);//'#00FF00'; + var BIGFONT = '6x8:3'; + var BIGFONTWIDTH = parseInt(BIGFONT.charAt(0)*parseInt(BIGFONT.charAt(-1))); + var SMALLFONT = '6x8:1'; + var SMALLFONTWIDTH = parseInt(SMALLFONT.charAt(0)*parseInt(SMALLFONT.charAt(-1))); - var abc = 'abcdefghijklmnopqrstuvwxyz'.toUpperCase(); - var fontSize = "6x8"; - //var xStep = 6; - var abcPadding = (g.getWidth()-6*abc.length)/2; + var ABC = 'abcdefghijklmnopqrstuvwxyz'.toUpperCase(); + var ABCPADDING = (g.getWidth()-6*ABC.length)/2; - var numPunct = ' 1234567890!?,.- '; - var numPunctHidden = ' 1234567890!?,.- '; - var numPunctPadding = (g.getWidth()-6*numPunct.length)/2; + var NUM = ' 1234567890!?,.- '; + var NUMHIDDEN = ' 1234567890!?,.- '; + var NUMPADDING = (g.getWidth()-6*NUM.length)/2; var rectHeight = 40; - var bgColor = [0,0,0]; - var HLColor = [1,1,1]; - var abcColor = [1,0,0]; - var numPunctColor = [0,1,0]; - var delLast; - var spaceLast; - function drawABC() { + var delSpaceLast; + + function drawAbcRow() { g.clear(); - g.setFont(fontSize); - g.setColor(1,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); + g.setFont(SMALLFONT); + g.setColor(ABCCOLOR); + g.drawString(ABC, ABCPADDING, g.getHeight()/2); g.fillRect(0, g.getHeight()-26, g.getWidth(), g.getHeight()); } - function drawNumPunct() { - g.setFont(fontSize); - g.setColor(0,1,1); - g.drawString(numPunct, numPunctPadding, g.getHeight()/4); + function drawNumRow() { + g.setFont(SMALLFONT); + g.setColor(NUMCOLOR); + g.drawString(NUM, NUMPADDING, g.getHeight()/4); - g.fillRect(numPunctPadding, g.getHeight()-rectHeight*4/3, g.getWidth()-numPunctPadding, g.getHeight()-rectHeight*2/3); + g.fillRect(NUMPADDING, g.getHeight()-rectHeight*4/3, g.getWidth()-NUMPADDING, g.getHeight()-rectHeight*2/3); } function initMarker() { g.setColor(0.5,0,0); - g.fillRect(5,5,11,13); - g.setColor(1,1,1); + g.fillRect(3,4+20,11,13+20); + g.setColor(HLCOLOR); } function updateTopString() { - g.setColor(0,0,0); - g.fillRect(0,5,176,13); + "ram" + g.setColor(BGCOLOR); + g.fillRect(0,4+20,176,13+20); g.setColor(0.2,0,0); - g.fillRect(5,5,5+text.length*6,13); + g.fillRect(3,4+20,5+text.length*6,13+20); g.setColor(0.7,0,0); - g.fillRect(text.length*6+5,5,10+text.length*6,13); + g.fillRect(text.length*6+5,4+20,10+text.length*6,13+20); g.setColor(1,1,1); - g.drawString(text, 5, 5); + g.drawString(text, 5, 5+20); } - drawABC(); - drawNumPunct(); + drawAbcRow(); + drawNumRow(); initMarker(); - var charHL; - var charHLPrev = -10; - var numPunctHL; - var numPunctHLPrev = -10; + var abcHL; + var abcHLPrev = -10; + var numHL; + var numHLPrev = -10; var type = ''; var typePrev = ''; var largeCharOffset = 6; - var letterCase = 1; - + + function resetChars(char, HLPrev, typePadding, heightDivisor, rowColor) { + "ram" + // Small character in list + g.setColor(rowColor); + g.setFont(SMALLFONT); + g.drawString(char, typePadding + HLPrev*6, g.getHeight()/heightDivisor); + // Large character + g.setColor(BGCOLOR); + g.fillRect(0,g.getHeight()/3,176,g.getHeight()/3+24); + //g.drawString(charSet.charAt(HLPrev), typePadding + HLPrev*6 -largeCharOffset, g.getHeight()/3);; //Old implementation where I find the shape and place of letter to remove instead of just a rectangle. + // mark in the list + } + function showChars(char, HL, typePadding, heightDivisor) { + "ram" + // mark in the list + g.setColor(HLCOLOR); + g.setFont(SMALLFONT); + if (char != 'del' && char != 'space') g.drawString(char, typePadding + HL*6, g.getHeight()/heightDivisor); + // show new large character + g.setFont(BIGFONT); + g.drawString(char, typePadding + HL*6 -largeCharOffset, g.getHeight()/3); + g.setFont(SMALLFONT); + } + + function changeCase(abcHL) { + g.setColor(BGCOLOR); + g.drawString(ABC, ABCPADDING, g.getHeight()/2); + if (ABC.charAt(abcHL) == ABC.charAt(abcHL).toUpperCase()) ABC = ABC.toLowerCase(); + else ABC = ABC.toUpperCase(); + g.setColor(ABCCOLOR); + g.drawString(ABC, ABCPADDING, g.getHeight()/2); + } + return new Promise((resolve,reject) => { // Interpret touch input - Bangle.on('drag', function(event) { - g.setFont('6x8'); + Bangle.setUI({ + mode: 'custom', + back: ()=>{ + Bangle.setUI(); + g.clearRect(Bangle.appRect); + resolve(text); + }, + drag: function(event) { - // hide delete sign - if (delLast == 1) { - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString('del', g.getWidth()/2 -27, g.getHeight()/3); - g.setFont('6x8'); - delLast = 0; - } + // ABCDEFGHIJKLMNOPQRSTUVWXYZ + // Choose character by draging along red rectangle at bottom of screen + if (event.y >= ( g.getHeight() - 12 )) { + // Translate x-position to character + if (event.x < ABCPADDING) { abcHL = 0; } + else if (event.x >= 176-ABCPADDING) { abcHL = 25; } + else { abcHL = Math.floor((event.x-ABCPADDING)/6); } - //hide space sign - if (spaceLast == 1) { - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString('space', g.getWidth()/2 -6*3*5/2, g.getHeight()/3); - g.setFont('6x8'); - spaceLast = 0; - } + // Datastream for development purposes + //print(event.x, event.y, event.b, ABC.charAt(abcHL), ABC.charAt(abcHLPrev)); + // Unmark previous character and mark the current one... + // Handling switching between letters and numbers/punctuation + if (typePrev != 'abc') resetChars(NUM.charAt(numHLPrev), numHLPrev, NUMPADDING, 4, NUMCOLOR); - // ABCDEFGHIJKLMNOPQRSTUVWXYZ - // Choose character by draging along red rectangle at bottom of screen - if (event.y >= ( g.getHeight() - 12 )) { - // Translate x-position to character - if (event.x < abcPadding) { charHL = 0; } - else if (event.x >= 176-abcPadding) { charHL = 25; } - else { charHL = Math.floor((event.x-abcPadding)/6); } - - // Datastream for development purposes - //print(event.x, event.y, event.b, abc.charAt(charHL), abc.charAt(charHLPrev)); - - // Unmark previous character and mark the current one... - // Handling switching between letters and numbers/punctuation - if (typePrev != 'abc') { - // Small character in list - g.setColor(0,1,0); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); - // Large character - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - } - - if (charHL != charHLPrev) { - // unmark in the list - g.setColor(1,0,0); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); - // hide previous large character - g.setColor(0,0,0); - g.fillRect(0,g.getHeight()/3,176,g.getHeight()/3+24); - g.setColor([0,0,0]); - g.setFont('6x8:3'); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - // mark in the list - g.setColor(1,1,1); - g.setFont('6x8'); - g.drawString(abc.charAt(charHL), abcPadding + charHL*6, g.getHeight()/2); - // show new large character - //g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString(abc.charAt(charHL), abcPadding + charHL*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - } - // Print string at top of screen - if (event.b == 0) { - text = text + abc.charAt(charHL); - updateTopString(); - - // Autoswitching letter case - if (abc.charAt(charHL) == abc.charAt(charHL).toUpperCase()) { - g.setColor(0,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - abc = abc.toLowerCase(); - g.setColor(1,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - letterCase = 0 - } - //print(text); - } - // Update previous character to current one - charHLPrev = charHL; - typePrev = 'abc'; - } - - // 12345678901234567890 - // Choose number or puctuation by draging on green rectangle - else if ((event.y < ( g.getHeight() - 12 )) && (event.y > ( g.getHeight() - 52 ))) { - // Translate x-position to character - if (event.x < numPunctPadding) { numPunctHL = 0; } - else if (event.x > 176-numPunctPadding) { numPunctHL = numPunct.length-1; } - else { numPunctHL = Math.floor((event.x-numPunctPadding)/6); } - - // Datastream for development purposes - //print(event.x, event.y, event.b, numPunct.charAt(numPunctHL), numPunct.charAt(numPunctHLPrev)); - - // Unmark previous character and mark the current one... - // Handling switching between letters and numbers/punctuation - if (typePrev != 'numPunct') { - // Small character in list - g.setColor(1,0,0); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); - // Large character - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - } - if (numPunctHL != numPunctHLPrev) { - // unmark in the list - g.setColor(0,1,0); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); - // hide previous large character - g.setColor(0,0,0); - g.fillRect(0,g.getHeight()/3,176,g.getHeight()/3+24); - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - // mark in the list - g.setColor(1,1,1); - g.setFont('6x8'); - g.drawString(numPunct.charAt(numPunctHL), numPunctPadding + numPunctHL*6, g.getHeight()/4); - // show new large character - //g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString(numPunct.charAt(numPunctHL), numPunctPadding + numPunctHL*6 -largeCharOffset, g.getHeight()/3); - g.setFont('6x8'); - } - // Print string at top of screen - if (event.b == 0) { - g.setColor(1,1,1); - // Backspace if releasing before list of numbers/punctuation - if (event.x < numPunctPadding) { - // show delete sign - g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString('del', g.getWidth()/2 -27, g.getHeight()/3); - g.setFont('6x8'); - delLast = 1; - - text = text.slice(0, -1); - updateTopString(); - //print(text); - } - // Append space if releasing after list of numbers/punctuation - else if (event.x > g.getWidth()-numPunctPadding) { - //show space sign - g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString('space', g.getWidth()/2 -6*3*5/2, g.getHeight()/3); - g.setFont('6x8'); - spaceLast = 1; - - text = text + ' '; - updateTopString(); - //print(text); - } - // Append selected number/punctuation - else { - text = text + numPunctHidden.charAt(numPunctHL); + if (abcHL != abcHLPrev) { + resetChars(ABC.charAt(abcHLPrev), abcHLPrev, ABCPADDING, 2, ABCCOLOR); + showChars(ABC.charAt(abcHL), abcHL, ABCPADDING, 2); + } + // Print string at top of screen + if (event.b == 0) { + text = text + ABC.charAt(abcHL); updateTopString(); // Autoswitching letter case - if ((text.charAt(text.length-1) == '.') || (text.charAt(text.length-1) == '!')) { - g.setColor(0,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - abc = abc.toUpperCase(); - g.setColor(1,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - letterCase = 1; - - } - //print(text); + if (ABC.charAt(abcHL) == ABC.charAt(abcHL).toUpperCase()) changeCase(abcHL); } + // Update previous character to current one + abcHLPrev = abcHL; + typePrev = 'abc'; } - // Update previous character to current one - numPunctHLPrev = numPunctHL; - typePrev = 'numPunct'; - } - // Make a space or backspace by swiping right or left on screen above green rectangle - else { - if (event.b == 0) { - g.setColor(1,1,1); - if (event.x < g.getWidth()/2) { - // unmark character in the list - g.setColor(1,0,0); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + + + + + + + + - // unmark number/punctuation in the list - g.setColor(0,1,0); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + // 12345678901234567890 + // Choose number or puctuation by draging on green rectangle + else if ((event.y < ( g.getHeight() - 12 )) && (event.y > ( g.getHeight() - 52 ))) { + // Translate x-position to character + if (event.x < NUMPADDING) { numHL = 0; } + else if (event.x > 176-NUMPADDING) { numHL = NUM.length-1; } + else { numHL = Math.floor((event.x-NUMPADDING)/6); } - // hide previous large character - g.setColor([0,0,0]); - g.setFont('6x8:3'); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + // Datastream for development purposes + //print(event.x, event.y, event.b, NUM.charAt(numHL), NUM.charAt(numHLPrev)); - // hide previous large character - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); - - // show delete sign - g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString('del', g.getWidth()/2 -27, g.getHeight()/3); - g.setFont('6x8'); - delLast = 1; - - // Backspace and draw string upper right corner - text = text.slice(0, -1); - updateTopString(); - if (text.length==0) { - g.setColor(0,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - abc = abc.toUpperCase(); - g.setColor(1,0,0); - g.drawString(abc, abcPadding, g.getHeight()/2); - letterCase = 1; + // Unmark previous character and mark the current one... + // Handling switching between letters and numbers/punctuation + if (typePrev != 'num') resetChars(ABC.charAt(abcHLPrev), abcHLPrev, ABCPADDING, 2, ABCCOLOR); + + if (numHL != numHLPrev) { + resetChars(NUM.charAt(numHLPrev), numHLPrev, NUMPADDING, 4, NUMCOLOR); + showChars(NUM.charAt(numHL), numHL, NUMPADDING, 4); + } + // Print string at top of screen + if (event.b == 0) { + g.setColor(HLCOLOR); + // Backspace if releasing before list of numbers/punctuation + if (event.x < NUMPADDING) { + // show delete sign + showChars('del', 0, g.getWidth()/2 +6 -27 , 4); + delSpaceLast = 1; + text = text.slice(0, -1); + updateTopString(); + //print(text); + } + // Append space if releasing after list of numbers/punctuation + else if (event.x > g.getWidth()-NUMPADDING) { + //show space sign + showChars('space', 0, g.getWidth()/2 +6 -6*3*5/2 , 4); + delSpaceLast = 1; + text = text + ' '; + updateTopString(); + //print(text); + } + // Append selected number/punctuation + else { + text = text + NUMHIDDEN.charAt(numHL); + updateTopString(); + + // Autoswitching letter case + if ((text.charAt(text.length-1) == '.') || (text.charAt(text.length-1) == '!')) changeCase(); } - //print(text, 'undid'); } - else { - // unmark character in the list - g.setColor(1,0,0); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6, g.getHeight()/2); + // Update previous character to current one + numHLPrev = numHL; + typePrev = 'num'; + } + + + + + + + + + // Make a space or backspace by swiping right or left on screen above green rectangle + else { + if (event.b == 0) { + g.setColor(HLCOLOR); + if (event.x < g.getWidth()/2) { + resetChars(ABC.charAt(abcHLPrev), abcHLPrev, ABCPADDING, 2, ABCCOLOR); + resetChars(NUM.charAt(numHLPrev), numHLPrev, NUMPADDING, 4, NUMCOLOR); - // unmark number/punctuation in the list - g.setColor(0,1,0); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6, g.getHeight()/4); + // show delete sign + showChars('del', 0, g.getWidth()/2 +6 -27 , 4); + delSpaceLast = 1; - // hide previous large character - g.setColor([0,0,0]); - g.setFont('6x8:3'); - g.drawString(abc.charAt(charHLPrev), abcPadding + charHLPrev*6 -largeCharOffset, g.getHeight()/3); + // Backspace and draw string upper right corner + text = text.slice(0, -1); + updateTopString(); + if (text.length==0) changeCase(abcHL); + //print(text, 'undid'); + } + else { + resetChars(ABC.charAt(abcHLPrev), abcHLPrev, ABCPADDING, 2, ABCCOLOR); + resetChars(NUM.charAt(numHLPrev), numHLPrev, NUMPADDING, 4, NUMCOLOR); - // hide previous large character - g.setColor(0,0,0); - g.setFont('6x8:3'); - g.drawString(numPunct.charAt(numPunctHLPrev), numPunctPadding + numPunctHLPrev*6 -largeCharOffset, g.getHeight()/3); + //show space sign + showChars('space', 0, g.getWidth()/2 +6 -6*3*5/2 , 4); + delSpaceLast = 1; - //show space sign - g.setColor(1,1,1); - g.setFont('6x8:3'); - g.drawString('space', g.getWidth()/2 -6*3*5/2, g.getHeight()/3); - g.setFont('6x8'); - spaceLast = 1; - - // Append space and draw string upper right corner - text = text + numPunctHidden.charAt(0); - updateTopString(); - //print(text, 'made space'); + // Append space and draw string upper right corner + text = text + NUMHIDDEN.charAt(0); + updateTopString(); + //print(text, 'made space'); + } } } } - }); - - return new Promise((resolve,reject) => { + }); +}); +/* return new Promise((resolve,reject) => { Bangle.setUI({mode:"custom", back:()=>{ Bangle.setUI(); g.clearRect(Bangle.appRect); + Bangle.setUI(); resolve(text); }}); - }); + }); */ }; diff --git a/apps/dragboard/metadata.json b/apps/dragboard/metadata.json index f8f1f6c85..65ac6fb2e 100644 --- a/apps/dragboard/metadata.json +++ b/apps/dragboard/metadata.json @@ -1,6 +1,6 @@ { "id": "dragboard", "name": "Dragboard", - "version":"0.02", + "version":"0.03", "description": "A library for text input via swiping keyboard", "icon": "app.png", "type":"textinput", diff --git a/apps/dragboard/screenshot.png b/apps/dragboard/screenshot.png index a9451d1a43161be0d33b1686743d9564663a15a9..dbe27f4080e2e1281ffcbccf8536228fc3517d20 100644 GIT binary patch literal 2487 zcmdUxdpOkV7RP@xe)h~z3{tsIB)4RXkg%u7B_iXN+eB&$Wl*j|{Mb(Js3wMCjH6`#&j089bI$qa{PDi)dERGz*ILi|yzhG6^fQh&JH_P1 z007u&XKO`(ZPPy&`WJX_?D#~44dN=n<^=F)K=BIzV8ZRJj=RPX7t1E2bhLJeE^cps z?u(e`q+(9o3B~7)#FnO0cHh^mU#VVPm|fY3OWP)JT(UHFAX_k0A45_1e(TTUEUW98 zcsD<{4~Ml>)h2?Gzk%J_ByGiX552!nEAuQlPx-`~8(c1TCEh}Xow&Wu|CO9e_vSdm z$74GA-}iBrpi1z1B(dd*hJy6S6`74CdIr@_UA?_VTy2?0Xl*Nx4&0mwW)n@qL=Q>2 zsJm}!Ag6uVw47;2PCdW7Np+bRL8(1}@!=MGFiCTlL-#GcsuzooBq(-hKt4uo3gl*E z(VvH>(p|a&bKXw4$Hd0SU2&3XbQdgu-C`ND>-&Fo;RrKD#tV+NW65!0m)*QEK9kJ4 zMtl>>g8j@pm87w(lup~?=@JyF>X5GJfI4vkVoBn9e$G2Tu72{c77LwA5vD!FUXF8@ z(bubppVUh@FA^)ec2D0x)Mz^0TRUvAIfrn`J`9v7a*;Fpl${m*-9vlVd56LLk|}q* zlviy^o&X#%)_dg2{zk9dUwpf&E7i8<7p*U{`xOmtXw%JFEI z2zh$SWs2m?U3_v;nV4EK9}qqBNaDx#oWjeeQWsIz%ZMT5S^j#Cd6>L#R;Tt|5H;WC zD?K}|TdNthRID`v5K-OuGKqM^M3p6jCSkTIn8;rB40%?MEjW0ks#>Hma3Dt@If6d9a2x_uMi;npVNKk8mPsCf zl>Ec4P5^7nuUaeGavUIX&t7#zeZtv&gBN|*@8&cnjQe%&4a%B`rqRxmN!vmUU1j=I zz?_^W6Z3FD=E=g-QL5gVhnS!QRh!PWvCXdy<&!$A-&c-aCJ{ACjB6P!V7ry3|H$qQ z*#ed)%PorIWvsjU>0@W#xv1;*W(%vO{oFBkhW98Y#M-4IAZ?6pipN4YTI@lrqTZR&x!t1zai}KbK8=N-@b&K&rI+ z6@Iq^ApMz3NOb%f-`NZ~OCJKU8=vPYV?YK}3HNJ=WwV0L60w0hS$QjWMk*!%#U~*t zTc_q2)p|NRpN zLl-qwqXS8F1wD!Ce}LGrK&xH`%x(6izvMSPiGP(WEiD_an~`Z5WPt$J<)j|#BfzPc zaLs=BZdm-AVD}8~0&uLfu@d?fi1+hBS{zjvV442-R%2x1^}Bn7@;p&qZ=!N#!Thy9 z=;n0td2jK#xs|19&*Xv-z0N3j$|bj{l=nUL-`u8pdon+~zH54);52@e63)6!>sgg2 zG!UGo`bRe+8u%U3=Y+!LhAkgrex(ub=E@PR(O=%Ghm{+i#+Rir_5vOf+y4&4}(VZ2fbR z>@BD6z;{z8tR0&@IIq0OOy$SKxf1^F`yFRz_BAB~$i|Aky~AkSvSI6f;&A}-IP-f} z5X@TMOS%!4MAy+YU>L&hdZ%u>2NutfEtCt8M}XyjEAG{SHDYhF^s@n^lcoKPEUXc| z$SAP}pqhK?D`H4AHTiIWgIW@O_-%fSC;}uNFV%k_h35oavZMYl($dS3tZBAUws^WO z(xc}^h_o|U4z9m{aMI5|=nEZLRe=R})76>)Elm&-T}B_oi-{fgLzp4O^O8?s&jPvs z&n_2?p&n()YnTYgpC=Qex}1=9Ar0lJm3cvrPA_B|_7-nPS0>_q`NXgYwrgLF6)2;1aj)wzt?M zumx%ZNl<12>#e6s*4Z0#`}Ihxq_E{Uo;fu$r^#qFvVSmS#<2YA5vLcQcmZp%_{c+b zGP)hBIRcDA9me)_z?=);na!31A45 z(I4&vy_++mu6@>I+t&n^<3@uS`x{Fp<83Qa>f1L}nv>1Ki}DR;V@=NNH`s|wofs!j zS{rU~heq_0A9pm=vM@^2YK8b7zSHG#^@XTmn?v()bOux}-4-T@D`Dx!%nEA^g*7_) z7esk3T&v%F=J`RQweo#N@P_?~h38(ijg zBJs4d{iiaF`bcs*06DI^)S$X7crYmM^pR&Xj^_}A8MK2XLJ9@ zp|Oi*JJNbDA9*GaG==Bz>|v83%}SH-h}=UGudzv8KfSk8M_!ENy(_adts9@Fc1f+H z>$&YIA(LS&&&NR%$~O{=dXAizC`>EQ?IVn+Xu<>g7k>!q_@uEsW;`|NH`b9fXZ?}r zn;#`e_TJ)M+W16KV%{{>GBC&o>8guH za@x{nrD)jb8KH{uhBXkH#mDcJ7%VIH?aoTH?NTnk5q2e4@jz%rF5H~mkgLXo3)jx{ zGwUjq{9hR^8{m4YMmqziPiJTNoV%{Gu;G<+aVv;aJ9+4it~w#+O%%>J!9e0K92j2T zqRRScKT)eA6&ndq;fO)+;s&br4z(go#W?_+EoTh>MQv8;I?pe@fghH;qIYdPnwo`j zjxI!o*c-xC>0Oq{5OSs%hZP_|#dBb|u z32kvpxVA0vgWU#v6Fn&2i-|(;FO%uqEE)(`y+?&GNF+KOfxhKjTE4`M&PAaheT(Ss z9?p4xK#L}Ut51lbw9QdC7^pBsp$Y)Fo}J;<4)7*XAbnF3D&uq!FAtf zh`aCctcMfv}%uDT5iEB@W z;%eJMRhmxjPWG<-ai<0E_QBq)IqxJjhReEOH23a_4F)L|PQA!M> zKTl{m>Z8Yum7l5=5gRYsBxTsKZq$aFHK#ih-1+Fb3|wQxB)W>oFn-kq)vt+ptB4S; zuUr&c9v#SJ*l+Q}KT%_u9qJvDAtBMM_I~?_qgR5@P;+%EO?F^FjD;A?-It}SUz?ZG z=AU9NJ?w(#^8~yfLrb29bt{tCPcAq9lzEC1;wu=;RexfZ=y$M%!3ozN_8T6=aBdZ^ zw1^)lE+j~85a=sQBWv6M$mC)S1+A6ozn40EajZa8VQctc;oF?s6MpeTB=ThnTN#Ra zxzz<%1 Date: Tue, 19 Apr 2022 23:33:09 +0200 Subject: [PATCH 03/78] dragboard v0.04 --- apps/dragboard/ChangeLog | 1 + apps/dragboard/lib.js | 8 +------- apps/dragboard/metadata.json | 2 +- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/apps/dragboard/ChangeLog b/apps/dragboard/ChangeLog index 415ffbb09..67bc62a4b 100644 --- a/apps/dragboard/ChangeLog +++ b/apps/dragboard/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Added some missing code. 0.03: Made the code shorter and somewhat more readable by writing some functions. Also made it work as a library where it returns the text once finished. The keyboard is now made to exit correctly when the 'back' event is called. The keyboard now uses theme colors correctly, although it still looks best with dark theme. The numbers row is now solidly green - except for highlights. +0.04: Now displays the opened text string at launch. diff --git a/apps/dragboard/lib.js b/apps/dragboard/lib.js index 31fac8998..d846055c1 100644 --- a/apps/dragboard/lib.js +++ b/apps/dragboard/lib.js @@ -44,12 +44,6 @@ exports.input = function(options) { g.fillRect(NUMPADDING, g.getHeight()-rectHeight*4/3, g.getWidth()-NUMPADDING, g.getHeight()-rectHeight*2/3); } - function initMarker() { - g.setColor(0.5,0,0); - g.fillRect(3,4+20,11,13+20); - g.setColor(HLCOLOR); - } - function updateTopString() { "ram" g.setColor(BGCOLOR); @@ -64,7 +58,7 @@ exports.input = function(options) { drawAbcRow(); drawNumRow(); - initMarker(); + updateTopString(); var abcHL; var abcHLPrev = -10; diff --git a/apps/dragboard/metadata.json b/apps/dragboard/metadata.json index 65ac6fb2e..f852a12f5 100644 --- a/apps/dragboard/metadata.json +++ b/apps/dragboard/metadata.json @@ -1,6 +1,6 @@ { "id": "dragboard", "name": "Dragboard", - "version":"0.03", + "version":"0.04", "description": "A library for text input via swiping keyboard", "icon": "app.png", "type":"textinput", From 6c77b7bc64b269f6a529649d76b4c48b69d0ad84 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 22:01:54 +0100 Subject: [PATCH 04/78] Fuzzyw translation (#3) * Update metadata.json * Update ChangeLog * Update fuzzyw.app.js * Update de_DE.json * Update de_DE.json --- apps/fuzzyw/ChangeLog | 1 + apps/fuzzyw/fuzzyw.app.js | 59 ++++++++++++++++++++++++--------------- apps/fuzzyw/metadata.json | 5 ++-- lang/de_DE.json | 31 ++++++++++++++++++-- 4 files changed, 68 insertions(+), 28 deletions(-) diff --git a/apps/fuzzyw/ChangeLog b/apps/fuzzyw/ChangeLog index 7b83706bf..63a0d60f0 100644 --- a/apps/fuzzyw/ChangeLog +++ b/apps/fuzzyw/ChangeLog @@ -1 +1,2 @@ 0.01: First release +0.02: Move translations to locale module diff --git a/apps/fuzzyw/fuzzyw.app.js b/apps/fuzzyw/fuzzyw.app.js index 07b5c4068..debcb3c4d 100644 --- a/apps/fuzzyw/fuzzyw.app.js +++ b/apps/fuzzyw/fuzzyw.app.js @@ -1,15 +1,37 @@ // adapted from https://github.com/hallettj/Fuzzy-Text-International/ -const fuzzy_strings = require("Storage").readJSON("fuzzy_strings.json"); -const SETTINGS_FILE = "fuzzyw.settings.json"; -let settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'language': 'System', 'alignment':'Centre'}; - -if (settings.language == 'System') { - settings.language = require('locale').name; -} - -let fuzzy_string = fuzzy_strings[settings.language]; +let fuzzy_string = { + "hours":[ + /*LANG*/"twelve", + /*LANG*/"one", + /*LANG*/"two", + /*LANG*/"three", + /*LANG*/"four", + /*LANG*/"five", + /*LANG*/"six", + /*LANG*/"seven", + /*LANG*/"eight", + /*LANG*/"nine", + /*LANG*/"ten", + /*LANG*/"eleven" + ], + "minutes":[ + /*LANG*/"*$1 o'clock", + /*LANG*/"five past *$1", + /*LANG*/"ten past *$1", + /*LANG*/"quarter past *$1", + /*LANG*/"twenty past *$1", + /*LANG*/"twenty five past *$1", + /*LANG*/"half past *$1", + /*LANG*/"twenty five to *$2", + /*LANG*/"twenty to *$2", + /*LANG*/"quarter to *$2", + /*LANG*/"ten to *$2", + /*LANG*/"five to *$2" + ] +}; +let text_scale = 3.5; let timeout = 2.5*60; let drawTimeout; @@ -24,24 +46,15 @@ function queueDraw(seconds) { const h = g.getHeight(); const w = g.getWidth(); -let align_mode = 0; -let align_pos = w/2; -if (settings.alignment =='Left') { - align_mode = -1; - align_pos = 0; -} else if (settings.alignment == 'Right') { - align_mode = 1; - align_pos = w; -} function getTimeString(date) { let segment = Math.round((date.getMinutes()*60 + date.getSeconds() + 1)/300); let hour = date.getHours() + Math.floor(segment/12); f_string = fuzzy_string.minutes[segment % 12]; if (f_string.includes('$1')) { - f_string = f_string.replace('$1', fuzzy_string.hours[(hour) % 24]); + f_string = f_string.replace('$1', fuzzy_string.hours[(hour) % 12]); } else { - f_string = f_string.replace('$2', fuzzy_string.hours[(hour + 1) % 24]); + f_string = f_string.replace('$2', fuzzy_string.hours[(hour + 1) % 12]); } return f_string; } @@ -49,11 +62,11 @@ function getTimeString(date) { function draw() { let time_string = getTimeString(new Date()).replace('*', ''); // print(time_string); - g.setFont('Vector', (h-24*2)/fuzzy_string.text_scale); - g.setFontAlign(align_mode, 0); + g.setFont('Vector', (h-24*2)/text_scale); + g.setFontAlign(0, 0); g.clearRect(0, 24, w, h-24); g.setColor(g.theme.fg); - g.drawString(g.wrapString(time_string, w).join("\n"), align_pos, h/2); + g.drawString(g.wrapString(time_string, w).join("\n"), w/2, h/2); queueDraw(timeout); } diff --git a/apps/fuzzyw/metadata.json b/apps/fuzzyw/metadata.json index ebd20e49f..a5edf4962 100644 --- a/apps/fuzzyw/metadata.json +++ b/apps/fuzzyw/metadata.json @@ -2,7 +2,7 @@ "id":"fuzzyw", "name":"Fuzzy Text Clock", "shortName": "Fuzzy Text", - "version": "0.01", + "version": "0.02", "description": "An imprecise clock for when you're not in a rush", "readme": "README.md", "icon":"fuzzyw.png", @@ -14,7 +14,6 @@ "storage": [ {"name":"fuzzyw.app.js","url":"fuzzyw.app.js"}, {"name":"fuzzyw.settings.js","url":"fuzzyw.settings.js"}, - {"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true}, - {"name":"fuzzy_strings.json","url":"fuzzy_strings.json"} + {"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true} ] } diff --git a/lang/de_DE.json b/lang/de_DE.json index 8c893e6ad..e0deef7fb 100644 --- a/lang/de_DE.json +++ b/lang/de_DE.json @@ -164,10 +164,37 @@ "Music": "Musik", "color": "Farbe", "off": "aus", - "Theme": "Thema" + "Theme": "Thema", + "one": "eins", + "two": "zwei", + "three": "drei", + "four": "vier", + "five": "fünf", + "six": "sechs", + "seven": "sieben", + "eight": "acht", + "nine": "neun", + "ten": "zehn", + "eleven": "elf", + "twelve": "zwölf" }, "alarm": { "//": "App-specific overrides", "rpt": "Wdh." + }, + "fuzzyw": { + "//": "App-specific overrides", + "*$1 o'clock": "*$1 uhr", + "five past *$1": "fünf nach *$1", + "ten past *$1": "zehn nach *$1", + "quarter past *$1": "viertel nach *$1", + "twenty past *$1": "zwanzig nach *$1", + "twenty five past *$1": "fünf for halb *$2", + "half past *$1": "halb *$2", + "twenty five to *$2": "fünf nach halb *$2", + "twenty to *$2": "zwanzig vor *$2", + "quarter to *$2": "viertel vor *$2", + "ten to *$2": "zehn vor *$2", + "five to *$2": "fünf vor *$2" } -} \ No newline at end of file +} From ca91e7876a2b639afa42a2053b13fb7c326f2c6f Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:32:36 -0700 Subject: [PATCH 05/78] Create app-icon.js --- apps/mtnclock/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/mtnclock/app-icon.js diff --git a/apps/mtnclock/app-icon.js b/apps/mtnclock/app-icon.js new file mode 100644 index 000000000..5723602c7 --- /dev/null +++ b/apps/mtnclock/app-icon.js @@ -0,0 +1 @@ +atob("MDCEBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVQAzAFVVVVVVVVVVVVVVVVVVVVVVVVVVVQLzIFVVVVVVAFVVVVVVVVVVVVVVVVVVUB//MQVVVVVQAQVVVVVVVVVVVVVVVVVVAB8RMQBVVVVQIwBVVVVVVVVVVVVVVVVQAQAAABAFVVUB8zAFVVVVVVVVVVVVVVVQExAiAYEFVVAD/zIFVVVVVVVVVVVVVVUBMzgzg4gQVQAvMvMAVVVVVVVVVVVVVVAIMzMzM4iABQACABAABVVVVVVVVVVVVQAjMzMzMziCABgQAQAiAFVVVVVVVVVVVQEzMzMzMzOIECMyIyKIEFVVVVVVVVVVUBMzMzMzMzM4gQIzMzM4gQVVVVVVVVVVAIMzMzMzMzM4iACDMzM4iABVVVVVVVVQAjMzMzMzMzMziCATMzMziCAFVVVVVVVQEzMzMzMzMzMzOIECMzMzOIEFVVVVVVUBMzMzMzMzMzMzM4gQIzMzM4gQVVVVVVAIMiMzMzMzMzMiM4iACDMzMiiABVVVVQAjIAIzMzMzMzIAIziCATMzIAKCAFVVVQE4AACDMzMzM4AACDOIECM4AACIEFVVUAERAiARERERERAiAREREAERAiAREAVVUAAAEyEAAAAAAAEyEAAAAAAAEyEAAAVVVVUBMzIQVVVVUBMzIQVVVVUBMzIQVVVVVVABEREQBVVVABEREQBVVVABEREQBVVVVVAAAAAABVVVAAAAAABVVVAAAAAABVVVVVUGIiJgVVVVUGIiJgVVVVUGIiJgVVVVVVACIiIgBVVVACIiIgBVVVACIiIgBVVVVQAiIiInAFVQAiIiInAFVQAiIiInAFVVVQEiIiInYFVQEiIiInYFVQEiIiInYFVVUAAAAAAAAAUAAAAAAAAAUAAAAAAAAAVVVVAHd3dwBVVVAHd3dwBVVVAHd3dwBVVVVQB3d3d3AFVQB3d3d3AFVQB3d3d3AFVVVQYiIiInYFVQYiIiInYFVQYiIiInYFVVUAIiIiIicAUAIiIiIicAUAIiIiIicAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAARAAAAUAAAARAAAAUAAAARAAAAVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEAFVVVVVVBEBVVVVVVQBEBVVVVVVVVVAAAAAAAAVVBEBVUAAAAAAABVVVVVVVUAASM/MyIQAAAAAAABIjPzMhAAVVVVVVABP///////MyIiIjP///////MQBVVVVQE////////////////////////zEFVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==") From 8aeab136bc5d7ffa8101f1316c86c5a9f1a2ab0b Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:32:55 -0700 Subject: [PATCH 06/78] Add files via upload --- apps/mtnclock/README.md | 19 ++ apps/mtnclock/app.js | 350 ++++++++++++++++++++++++++++++++++ apps/mtnclock/app.png | Bin 0 -> 2212 bytes apps/mtnclock/metadata.json | 25 +++ apps/mtnclock/screenshot1.png | Bin 0 -> 4350 bytes apps/mtnclock/screenshot2.png | Bin 0 -> 3856 bytes apps/mtnclock/screenshot3.png | Bin 0 -> 3602 bytes apps/mtnclock/screenshot4.png | Bin 0 -> 3623 bytes apps/mtnclock/screenshot5.png | Bin 0 -> 3427 bytes 9 files changed, 394 insertions(+) create mode 100644 apps/mtnclock/README.md create mode 100644 apps/mtnclock/app.js create mode 100644 apps/mtnclock/app.png create mode 100644 apps/mtnclock/metadata.json create mode 100644 apps/mtnclock/screenshot1.png create mode 100644 apps/mtnclock/screenshot2.png create mode 100644 apps/mtnclock/screenshot3.png create mode 100644 apps/mtnclock/screenshot4.png create mode 100644 apps/mtnclock/screenshot5.png diff --git a/apps/mtnclock/README.md b/apps/mtnclock/README.md new file mode 100644 index 000000000..a88c847cb --- /dev/null +++ b/apps/mtnclock/README.md @@ -0,0 +1,19 @@ +# Mountain Pass Clock + +Mountain Pass Clock changes depending on time (day/night) and weather conditions. + +This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification). To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. + +If you choose not to set up weather, this clock will default to clear weather, and the scenery will still change from night to day. + +## WARNING + +This app has not been tested on the original Bangle JS. + +## Images + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) +![](screenshot4.png) +![](screenshot5.png) \ No newline at end of file diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js new file mode 100644 index 000000000..cc1d541d8 --- /dev/null +++ b/apps/mtnclock/app.js @@ -0,0 +1,350 @@ +var data = require("Storage").readJSON("mtnclock.json", 1) || {}; + +//seeded RNG to generate stars, snow, etc +function sfc32(a, b, c, d) { + return function() { + a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; + var t = (a + b) | 0; + a = b ^ b >>> 9; + b = c + (c << 3) | 0; + c = (c << 21 | c >>> 11); + d = d + 1 | 0; + t = t + d | 0; + c = c + t | 0; + return (t >>> 0) / 4294967296; + }; +} + +//scale x, y coords to screen +function px(x) { + return x*g.getWidth()/100; +} + +function py(y) { + return y*g.getHeight()/100; +} + +function drawMtn(color, coord, dimen) { + //scale mountains to different sizes + g.setColor(color.mtn1).fillPoly([ + coord.x,coord.y, + coord.x,coord.y+dimen.h, + coord.x-dimen.w/2,coord.y+dimen.h + ]); + g.setColor(color.mtn2).fillPoly([ + coord.x,coord.y, + coord.x,coord.y+dimen.h, + coord.x+dimen.w/2,coord.y+dimen.h + ]); +} + +function drawTree(color, coord, dimen) { + //scale trees to different sizes + g.setColor(color.tree1).fillPoly([ + coord.x,coord.y, + coord.x-dimen.w/5,coord.y+dimen.h/4, + coord.x-dimen.w/12,coord.y+dimen.h/4, + coord.x-dimen.w/2.8,coord.y+1.95*dimen.h/4, + coord.x-dimen.w/8,coord.y+1.95*dimen.h/4, + coord.x-dimen.w/2,coord.y+3*dimen.h/4, + coord.x,coord.y+3*dimen.h/4 + ]); + g.setColor(color.tree2).fillPoly([ + coord.x,coord.y, + coord.x+dimen.w/5,coord.y+dimen.h/4, + coord.x+dimen.w/12,coord.y+dimen.h/4, + coord.x+dimen.w/2.8,coord.y+1.95*dimen.h/4, + coord.x+dimen.w/8,coord.y+1.95*dimen.h/4, + coord.x+dimen.w/2,coord.y+3*dimen.h/4, + coord.x,coord.y+3*dimen.h/4 + ]); + g.setColor(color.tree3).fillRect( + coord.x-dimen.w/12,coord.y+3*dimen.h/4, + coord.x+dimen.w/12,coord.y+dimen.h + ); +} + +function drawSnow(color, coord, size) { + g.setColor(color).drawLine(coord.x-px(size),coord.y-py(size),coord.x+px(size),coord.y+py(size)); + g.drawLine(coord.x-px(size),coord.y+py(size),coord.x+px(size),coord.y-py(size)); + g.drawLine(coord.x,coord.y+py(size),coord.x,coord.y-py(size)); + g.drawLine(coord.x-px(size),coord.y,coord.x+px(size),coord.y); +} + +function draw(color) { + +var seed; +var rand; + +g.clear(); +//background + g.setColor(color.bg1).fillRect( + px(0),py(0), + px(100),py(45) + ); + g.setColor(color.bg2).fillRect( + px(0),py(45), + px(100),py(100) + ); + //lightning + if (color.ltn) { + g.setColor(color.ltn).fillPoly([ + px(70),py(20), + px(60),py(28), + px(71),py(29), + px(63),py(40), + px(75),py(28), + px(64),py(27) + ]); + g.fillPoly([ + px(40),py(20), + px(30),py(28), + px(41),py(29), + px(33),py(40), + px(45),py(28), + px(34),py(27) + ]); + } + //stars + if (color.star) { + seed = 4; + rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); + for (let i = 0; i < 40; i++) { + g.setColor(color.star).drawCircle(Math.floor(rand() * px(100)),Math.floor(rand() * py(33)),Math.floor(rand() * 2)); + } + } + //birds + if (color.bird) { + g.setColor(color.bird).fillCircle(px(17),py(12),px(5)).fillCircle(px(23),py(10),px(5)); + g.setColor(color.bg1).fillCircle(px(18),py(15),px(6)).fillCircle(px(24),py(13),px(6)); + g.setColor(color.bird).fillCircle(px(28),py(19),px(4)).fillCircle(px(33),py(19),px(4)); + g.setColor(color.bg1).fillCircle(px(28),py(21),px(5)).fillCircle(px(34),py(21),px(5)); + } + //sun/moon + if (color.sun) g.setColor(color.sun).fillCircle(px(65), py(22), py(20)); + //path + g.setColor(color.path).fillPoly([ + px(60),py(44), + px(39),py(55), + px(72),py(57), + px(30),py(100), + px(70),py(100), + px(78),py(55), + px(46),py(53) + ]); + //fog + if (color.fog) { + g.setColor(color.fog); + for (let i = 1; i <= 47; i = i+2) { + g.drawLine(px(0),py(i),px(100),py(i)); + } + } + //rain + if (color.rain1) { + g.setColor(color.rain1); + for (let i = 0; i <= 6; i++) { + g.drawLine(px(6+i*20),py(20),px(-14+i*20),py(45)); + } + if (color.rain2) { + for (let i = 0; i <= 6; i++) { + g.drawLine(px(16+i*20),py(20),px(-4+i*20),py(45)); + } + } + } + //snow + if (color.snow) { + seed = 11; + rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); + for (let i = 0; i < 30; i++) { + drawSnow(color.snow, {x:Math.floor(rand() * px(100)), y:(Math.floor(rand() * py(25))+py(20))}, Math.floor(rand() * 3)); + } + } + //mountains + drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(35), y:py(30)}, {w:px(38), h:py(17)}); + drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(10), y:py(20)}, {w:px(50), h:py(30)}); + drawMtn({mtn1:color.mtn1, mtn2:color.mtn2}, {x:px(90), y:py(20)}, {w:px(70), h:py(30)}); + //lake + g.setColor(color.lake).fillEllipse(px(-15), py(52), px(30), py(57)); + //trees + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(12),y:py(52)}, {w:px(13),h:py(13)}); + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(48),y:py(52)}, {w:px(13),h:py(13)}); + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(34),y:py(46)}, {w:px(6),h:py(6)}); + drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(70),y:py(46)}, {w:px(6),h:py(6)}); + drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(90),y:py(52)}, {w:px(13),h:py(13)}); + //clouds + if (color.cloud1) { + g.setColor(color.cloud1); + if (color.cloud2) g.fillRect(0, 0, px(100), py(10)); + g.fillCircle(px(3), py(12), py(4)); + g.fillCircle(px(10), py(12), py(5)); + g.fillCircle(px(16), py(11), py(6)); + g.fillCircle(px(24), py(10), py(8)); + g.fillCircle(px(30), py(11), py(6)); + g.fillCircle(px(35), py(12), py(5)); + g.fillCircle(px(40), py(12), py(6)); + g.fillCircle(px(48), py(13), py(5)); + g.fillCircle(px(55), py(14), py(5)); + g.fillCircle(px(60), py(12), py(5)); + g.fillCircle(px(65), py(11), py(6)); + g.fillCircle(px(75), py(10), py(8)); + g.fillCircle(px(85), py(11), py(6)); + g.fillCircle(px(90), py(12), py(5)); + g.fillCircle(px(97), py(13), py(4)); + } + + //clock text + (color.clock == undefined) ? g.setColor(0xFFFF) : g.setColor(color.clock); + g.setFont("Vector", py(20)).setFontAlign(-1, -1).drawString((require("locale").time(new Date(), 1).replace(" ", "")), px(2), py(67)); + g.setFont("Vector", py(10)).drawString(require('locale').dow(new Date(), 1)+" "+new Date().getDate()+" "+require('locale').month(new Date(), 1)+((data.temp == undefined) ? "" : " | "+require('locale').temp(Math.round(data.temp-273.15)).replace(".0", "")), px(2), py(87)); +} + +var i = 0; + +function setWeather() { + var a = {}; + //clear day/night is default weather + if ((data.code >= 800 && data.code <=802) || data.code == undefined) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-clear + a = { + bg1:0x4FFF, bg2:0x03E0, + sun:0xFD20, + path:0x8200, + mtn1:0x045f, mtn2:0x000F, + lake:0x000F, + tree1:0x07E0, tree2:0, tree3:0x7BE0, + bird:0xFFFF + }; + //day-cloudy + if (data.code == 801 || data.code == 802) a.cloud1 = 0xFFFF; + } + else { + //night-clear + a = { + bg1:0, bg2:0x0005, + sun:0xC618, + path:0, + mtn1:0x0210, mtn2:0x0010, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + star:0xFFFF + }; + //night-cloudy + if (data.code == 801 || data.code == 802) a.cloud1 = 0x4208; + } + } + else if (((data.code >= 300) && (data.code < 600)) || ((data.code >= 200) && (data.code < 300)) || data.code == 803 || data.code == 804) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-overcast + a = { + bg1:0xC618, bg2:0x0200, + path:0x3000, + mtn1:0x3B38, mtn2:0x0005, + lake:0x000F, + tree1:0x03E0, tree2:0, tree3:0x59E0, + cloud1:0x7BEF, cloud2:1 + }; + //day-lightning + if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; + //day-drizzle + if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xFFFF; + //day-rain + if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) a.rain2 = 1; + } + else { + //night-overcast + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + cloud1:0x4208, cloud2:1 + }; + //night-lightning + if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; + //night-drizzle + if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xC618; + //night-rain + if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) rain2 = 1; + } + } + else if ((data.code >= 700) && (data.code < 800)) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-fog + a = { + bg1:0xC618, bg2:0x0200, + path:0x3000, + mtn1:0x3B38, mtn2:0x0005, + lake:0x000F, + tree1:0x03E0, tree2:0, tree3:0x59E0, + fog:0xFFFF + }; + } + else { + //night-fog + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + fog:0x7BEF + }; + } + } + else if ((data.code >= 600) && (data.code < 700)) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-snow + a = { + bg1:0, bg2:0x7BEF, + path:0xC618, + mtn1:0xFFFF, mtn2:0x7BEF, + lake:0x07FF, + tree1:0xC618, tree2:0xC618, tree3:0x59E0, + cloud1:0x7BEF, cloud2:1, + snow:0xFFFF, + clock: 0 + }; + } + else { + //night-snow + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x39E7, tree2:0x39E7, tree3:0x59E0, + cloud1:0x4208, cloud2:1, + snow:0xFFFF + }; + } + } + draw(a); +} + +const _GB = global.GB; +global.GB = (event) => { + if (event.t==="weather") { + data = event; + require("Storage").write('mtnclock.json', event); + setWeather(); + } + if (_GB) setTimeout(_GB, 0, event); +}; + +var drawTimeout; + +//update watchface in next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + setWeather(); + queueDraw(); + }, 60000 - (Date.now() % 60000)); +} + +queueDraw(); +setWeather(); +Bangle.setUI("clock"); \ No newline at end of file diff --git a/apps/mtnclock/app.png b/apps/mtnclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..08330429484759d65cf2e89d392799b7be063064 GIT binary patch literal 2212 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 literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot2.png b/apps/mtnclock/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..730edbab5a618d7d98524656b7445cc56dbcb645 GIT binary patch literal 3856 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 Y0dz>%728&#g8%>k07*qoM6N<$f(O|K)&Kwi literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot4.png b/apps/mtnclock/screenshot4.png new file mode 100644 index 0000000000000000000000000000000000000000..8f2e1de907117a4378c87de973aa09711961a6ef GIT binary patch literal 3623 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 literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot5.png b/apps/mtnclock/screenshot5.png new file mode 100644 index 0000000000000000000000000000000000000000..b34a3111ca81395be3b6644ab7f576222029c98f GIT binary patch literal 3427 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 FV1hRXwUz(? literal 0 HcmV?d00001 From baa2313649b2dafdc720a52a6e7ae1c1dfc58d37 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Wed, 20 Apr 2022 21:44:50 -0700 Subject: [PATCH 07/78] Delete apps/mtnclock directory --- apps/mtnclock/README.md | 19 -- apps/mtnclock/app-icon.js | 1 - apps/mtnclock/app.js | 350 ---------------------------------- apps/mtnclock/app.png | Bin 2212 -> 0 bytes apps/mtnclock/metadata.json | 25 --- apps/mtnclock/screenshot1.png | Bin 4350 -> 0 bytes apps/mtnclock/screenshot2.png | Bin 3856 -> 0 bytes apps/mtnclock/screenshot3.png | Bin 3602 -> 0 bytes apps/mtnclock/screenshot4.png | Bin 3623 -> 0 bytes apps/mtnclock/screenshot5.png | Bin 3427 -> 0 bytes 10 files changed, 395 deletions(-) delete mode 100644 apps/mtnclock/README.md delete mode 100644 apps/mtnclock/app-icon.js delete mode 100644 apps/mtnclock/app.js delete mode 100644 apps/mtnclock/app.png delete mode 100644 apps/mtnclock/metadata.json delete mode 100644 apps/mtnclock/screenshot1.png delete mode 100644 apps/mtnclock/screenshot2.png delete mode 100644 apps/mtnclock/screenshot3.png delete mode 100644 apps/mtnclock/screenshot4.png delete mode 100644 apps/mtnclock/screenshot5.png diff --git a/apps/mtnclock/README.md b/apps/mtnclock/README.md deleted file mode 100644 index a88c847cb..000000000 --- a/apps/mtnclock/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Mountain Pass Clock - -Mountain Pass Clock changes depending on time (day/night) and weather conditions. - -This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification). To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. - -If you choose not to set up weather, this clock will default to clear weather, and the scenery will still change from night to day. - -## WARNING - -This app has not been tested on the original Bangle JS. - -## Images - -![](screenshot1.png) -![](screenshot2.png) -![](screenshot3.png) -![](screenshot4.png) -![](screenshot5.png) \ No newline at end of file diff --git a/apps/mtnclock/app-icon.js b/apps/mtnclock/app-icon.js deleted file mode 100644 index 5723602c7..000000000 --- a/apps/mtnclock/app-icon.js +++ /dev/null @@ -1 +0,0 @@ -atob("MDCEBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVQAzAFVVVVVVVVVVVVVVVVVVVVVVVVVVVQLzIFVVVVVVAFVVVVVVVVVVVVVVVVVVUB//MQVVVVVQAQVVVVVVVVVVVVVVVVVVAB8RMQBVVVVQIwBVVVVVVVVVVVVVVVVQAQAAABAFVVUB8zAFVVVVVVVVVVVVVVVQExAiAYEFVVAD/zIFVVVVVVVVVVVVVVUBMzgzg4gQVQAvMvMAVVVVVVVVVVVVVVAIMzMzM4iABQACABAABVVVVVVVVVVVVQAjMzMzMziCABgQAQAiAFVVVVVVVVVVVQEzMzMzMzOIECMyIyKIEFVVVVVVVVVVUBMzMzMzMzM4gQIzMzM4gQVVVVVVVVVVAIMzMzMzMzM4iACDMzM4iABVVVVVVVVQAjMzMzMzMzMziCATMzMziCAFVVVVVVVQEzMzMzMzMzMzOIECMzMzOIEFVVVVVVUBMzMzMzMzMzMzM4gQIzMzM4gQVVVVVVAIMiMzMzMzMzMiM4iACDMzMiiABVVVVQAjIAIzMzMzMzIAIziCATMzIAKCAFVVVQE4AACDMzMzM4AACDOIECM4AACIEFVVUAERAiARERERERAiAREREAERAiAREAVVUAAAEyEAAAAAAAEyEAAAAAAAEyEAAAVVVVUBMzIQVVVVUBMzIQVVVVUBMzIQVVVVVVABEREQBVVVABEREQBVVVABEREQBVVVVVAAAAAABVVVAAAAAABVVVAAAAAABVVVVVUGIiJgVVVVUGIiJgVVVVUGIiJgVVVVVVACIiIgBVVVACIiIgBVVVACIiIgBVVVVQAiIiInAFVQAiIiInAFVQAiIiInAFVVVQEiIiInYFVQEiIiInYFVQEiIiInYFVVUAAAAAAAAAUAAAAAAAAAUAAAAAAAAAVVVVAHd3dwBVVVAHd3dwBVVVAHd3dwBVVVVQB3d3d3AFVQB3d3d3AFVQB3d3d3AFVVVQYiIiInYFVQYiIiInYFVQYiIiInYFVVUAIiIiIicAUAIiIiIicAUAIiIiIicAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAARAAAAUAAAARAAAAUAAAARAAAAVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEAFVVVVVVBEBVVVVVVQBEBVVVVVVVVVAAAAAAAAVVBEBVUAAAAAAABVVVVVVVUAASM/MyIQAAAAAAABIjPzMhAAVVVVVVABP///////MyIiIjP///////MQBVVVVQE////////////////////////zEFVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==") diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js deleted file mode 100644 index cc1d541d8..000000000 --- a/apps/mtnclock/app.js +++ /dev/null @@ -1,350 +0,0 @@ -var data = require("Storage").readJSON("mtnclock.json", 1) || {}; - -//seeded RNG to generate stars, snow, etc -function sfc32(a, b, c, d) { - return function() { - a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; - var t = (a + b) | 0; - a = b ^ b >>> 9; - b = c + (c << 3) | 0; - c = (c << 21 | c >>> 11); - d = d + 1 | 0; - t = t + d | 0; - c = c + t | 0; - return (t >>> 0) / 4294967296; - }; -} - -//scale x, y coords to screen -function px(x) { - return x*g.getWidth()/100; -} - -function py(y) { - return y*g.getHeight()/100; -} - -function drawMtn(color, coord, dimen) { - //scale mountains to different sizes - g.setColor(color.mtn1).fillPoly([ - coord.x,coord.y, - coord.x,coord.y+dimen.h, - coord.x-dimen.w/2,coord.y+dimen.h - ]); - g.setColor(color.mtn2).fillPoly([ - coord.x,coord.y, - coord.x,coord.y+dimen.h, - coord.x+dimen.w/2,coord.y+dimen.h - ]); -} - -function drawTree(color, coord, dimen) { - //scale trees to different sizes - g.setColor(color.tree1).fillPoly([ - coord.x,coord.y, - coord.x-dimen.w/5,coord.y+dimen.h/4, - coord.x-dimen.w/12,coord.y+dimen.h/4, - coord.x-dimen.w/2.8,coord.y+1.95*dimen.h/4, - coord.x-dimen.w/8,coord.y+1.95*dimen.h/4, - coord.x-dimen.w/2,coord.y+3*dimen.h/4, - coord.x,coord.y+3*dimen.h/4 - ]); - g.setColor(color.tree2).fillPoly([ - coord.x,coord.y, - coord.x+dimen.w/5,coord.y+dimen.h/4, - coord.x+dimen.w/12,coord.y+dimen.h/4, - coord.x+dimen.w/2.8,coord.y+1.95*dimen.h/4, - coord.x+dimen.w/8,coord.y+1.95*dimen.h/4, - coord.x+dimen.w/2,coord.y+3*dimen.h/4, - coord.x,coord.y+3*dimen.h/4 - ]); - g.setColor(color.tree3).fillRect( - coord.x-dimen.w/12,coord.y+3*dimen.h/4, - coord.x+dimen.w/12,coord.y+dimen.h - ); -} - -function drawSnow(color, coord, size) { - g.setColor(color).drawLine(coord.x-px(size),coord.y-py(size),coord.x+px(size),coord.y+py(size)); - g.drawLine(coord.x-px(size),coord.y+py(size),coord.x+px(size),coord.y-py(size)); - g.drawLine(coord.x,coord.y+py(size),coord.x,coord.y-py(size)); - g.drawLine(coord.x-px(size),coord.y,coord.x+px(size),coord.y); -} - -function draw(color) { - -var seed; -var rand; - -g.clear(); -//background - g.setColor(color.bg1).fillRect( - px(0),py(0), - px(100),py(45) - ); - g.setColor(color.bg2).fillRect( - px(0),py(45), - px(100),py(100) - ); - //lightning - if (color.ltn) { - g.setColor(color.ltn).fillPoly([ - px(70),py(20), - px(60),py(28), - px(71),py(29), - px(63),py(40), - px(75),py(28), - px(64),py(27) - ]); - g.fillPoly([ - px(40),py(20), - px(30),py(28), - px(41),py(29), - px(33),py(40), - px(45),py(28), - px(34),py(27) - ]); - } - //stars - if (color.star) { - seed = 4; - rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); - for (let i = 0; i < 40; i++) { - g.setColor(color.star).drawCircle(Math.floor(rand() * px(100)),Math.floor(rand() * py(33)),Math.floor(rand() * 2)); - } - } - //birds - if (color.bird) { - g.setColor(color.bird).fillCircle(px(17),py(12),px(5)).fillCircle(px(23),py(10),px(5)); - g.setColor(color.bg1).fillCircle(px(18),py(15),px(6)).fillCircle(px(24),py(13),px(6)); - g.setColor(color.bird).fillCircle(px(28),py(19),px(4)).fillCircle(px(33),py(19),px(4)); - g.setColor(color.bg1).fillCircle(px(28),py(21),px(5)).fillCircle(px(34),py(21),px(5)); - } - //sun/moon - if (color.sun) g.setColor(color.sun).fillCircle(px(65), py(22), py(20)); - //path - g.setColor(color.path).fillPoly([ - px(60),py(44), - px(39),py(55), - px(72),py(57), - px(30),py(100), - px(70),py(100), - px(78),py(55), - px(46),py(53) - ]); - //fog - if (color.fog) { - g.setColor(color.fog); - for (let i = 1; i <= 47; i = i+2) { - g.drawLine(px(0),py(i),px(100),py(i)); - } - } - //rain - if (color.rain1) { - g.setColor(color.rain1); - for (let i = 0; i <= 6; i++) { - g.drawLine(px(6+i*20),py(20),px(-14+i*20),py(45)); - } - if (color.rain2) { - for (let i = 0; i <= 6; i++) { - g.drawLine(px(16+i*20),py(20),px(-4+i*20),py(45)); - } - } - } - //snow - if (color.snow) { - seed = 11; - rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); - for (let i = 0; i < 30; i++) { - drawSnow(color.snow, {x:Math.floor(rand() * px(100)), y:(Math.floor(rand() * py(25))+py(20))}, Math.floor(rand() * 3)); - } - } - //mountains - drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(35), y:py(30)}, {w:px(38), h:py(17)}); - drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(10), y:py(20)}, {w:px(50), h:py(30)}); - drawMtn({mtn1:color.mtn1, mtn2:color.mtn2}, {x:px(90), y:py(20)}, {w:px(70), h:py(30)}); - //lake - g.setColor(color.lake).fillEllipse(px(-15), py(52), px(30), py(57)); - //trees - drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(12),y:py(52)}, {w:px(13),h:py(13)}); - drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(48),y:py(52)}, {w:px(13),h:py(13)}); - drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(34),y:py(46)}, {w:px(6),h:py(6)}); - drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(70),y:py(46)}, {w:px(6),h:py(6)}); - drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(90),y:py(52)}, {w:px(13),h:py(13)}); - //clouds - if (color.cloud1) { - g.setColor(color.cloud1); - if (color.cloud2) g.fillRect(0, 0, px(100), py(10)); - g.fillCircle(px(3), py(12), py(4)); - g.fillCircle(px(10), py(12), py(5)); - g.fillCircle(px(16), py(11), py(6)); - g.fillCircle(px(24), py(10), py(8)); - g.fillCircle(px(30), py(11), py(6)); - g.fillCircle(px(35), py(12), py(5)); - g.fillCircle(px(40), py(12), py(6)); - g.fillCircle(px(48), py(13), py(5)); - g.fillCircle(px(55), py(14), py(5)); - g.fillCircle(px(60), py(12), py(5)); - g.fillCircle(px(65), py(11), py(6)); - g.fillCircle(px(75), py(10), py(8)); - g.fillCircle(px(85), py(11), py(6)); - g.fillCircle(px(90), py(12), py(5)); - g.fillCircle(px(97), py(13), py(4)); - } - - //clock text - (color.clock == undefined) ? g.setColor(0xFFFF) : g.setColor(color.clock); - g.setFont("Vector", py(20)).setFontAlign(-1, -1).drawString((require("locale").time(new Date(), 1).replace(" ", "")), px(2), py(67)); - g.setFont("Vector", py(10)).drawString(require('locale').dow(new Date(), 1)+" "+new Date().getDate()+" "+require('locale').month(new Date(), 1)+((data.temp == undefined) ? "" : " | "+require('locale').temp(Math.round(data.temp-273.15)).replace(".0", "")), px(2), py(87)); -} - -var i = 0; - -function setWeather() { - var a = {}; - //clear day/night is default weather - if ((data.code >= 800 && data.code <=802) || data.code == undefined) { - if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { - //day-clear - a = { - bg1:0x4FFF, bg2:0x03E0, - sun:0xFD20, - path:0x8200, - mtn1:0x045f, mtn2:0x000F, - lake:0x000F, - tree1:0x07E0, tree2:0, tree3:0x7BE0, - bird:0xFFFF - }; - //day-cloudy - if (data.code == 801 || data.code == 802) a.cloud1 = 0xFFFF; - } - else { - //night-clear - a = { - bg1:0, bg2:0x0005, - sun:0xC618, - path:0, - mtn1:0x0210, mtn2:0x0010, - lake:0x000F, - tree1:0x0200, tree2:0, tree3:0x59E0, - star:0xFFFF - }; - //night-cloudy - if (data.code == 801 || data.code == 802) a.cloud1 = 0x4208; - } - } - else if (((data.code >= 300) && (data.code < 600)) || ((data.code >= 200) && (data.code < 300)) || data.code == 803 || data.code == 804) { - if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { - //day-overcast - a = { - bg1:0xC618, bg2:0x0200, - path:0x3000, - mtn1:0x3B38, mtn2:0x0005, - lake:0x000F, - tree1:0x03E0, tree2:0, tree3:0x59E0, - cloud1:0x7BEF, cloud2:1 - }; - //day-lightning - if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; - //day-drizzle - if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xFFFF; - //day-rain - if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) a.rain2 = 1; - } - else { - //night-overcast - a = { - bg1:0, bg2:0x0005, - path:0, - mtn1:0x0010, mtn2:0x000F, - lake:0x000F, - tree1:0x0200, tree2:0, tree3:0x59E0, - cloud1:0x4208, cloud2:1 - }; - //night-lightning - if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; - //night-drizzle - if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xC618; - //night-rain - if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) rain2 = 1; - } - } - else if ((data.code >= 700) && (data.code < 800)) { - if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { - //day-fog - a = { - bg1:0xC618, bg2:0x0200, - path:0x3000, - mtn1:0x3B38, mtn2:0x0005, - lake:0x000F, - tree1:0x03E0, tree2:0, tree3:0x59E0, - fog:0xFFFF - }; - } - else { - //night-fog - a = { - bg1:0, bg2:0x0005, - path:0, - mtn1:0x0010, mtn2:0x000F, - lake:0x000F, - tree1:0x0200, tree2:0, tree3:0x59E0, - fog:0x7BEF - }; - } - } - else if ((data.code >= 600) && (data.code < 700)) { - if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { - //day-snow - a = { - bg1:0, bg2:0x7BEF, - path:0xC618, - mtn1:0xFFFF, mtn2:0x7BEF, - lake:0x07FF, - tree1:0xC618, tree2:0xC618, tree3:0x59E0, - cloud1:0x7BEF, cloud2:1, - snow:0xFFFF, - clock: 0 - }; - } - else { - //night-snow - a = { - bg1:0, bg2:0x0005, - path:0, - mtn1:0x0010, mtn2:0x000F, - lake:0x000F, - tree1:0x39E7, tree2:0x39E7, tree3:0x59E0, - cloud1:0x4208, cloud2:1, - snow:0xFFFF - }; - } - } - draw(a); -} - -const _GB = global.GB; -global.GB = (event) => { - if (event.t==="weather") { - data = event; - require("Storage").write('mtnclock.json', event); - setWeather(); - } - if (_GB) setTimeout(_GB, 0, event); -}; - -var drawTimeout; - -//update watchface in next minute -function queueDraw() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - setWeather(); - queueDraw(); - }, 60000 - (Date.now() % 60000)); -} - -queueDraw(); -setWeather(); -Bangle.setUI("clock"); \ No newline at end of file diff --git a/apps/mtnclock/app.png b/apps/mtnclock/app.png deleted file mode 100644 index 08330429484759d65cf2e89d392799b7be063064..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2212 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 diff --git a/apps/mtnclock/screenshot2.png b/apps/mtnclock/screenshot2.png deleted file mode 100644 index 730edbab5a618d7d98524656b7445cc56dbcb645..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3856 zcmV+r5AX1aP)Px@%1J~)RCr$Po#~dOAPj}O-~XX!j#Z^?At5&#i>Cg}B7_jgM+~UHKR-YJ{{8#+ z^ZWa|{U!fQJFGPiw%MDLH=TD?c>N}UbMme_d0%=bfirAcc?C`aXUw}+%v+9E5;zH* z1kUV5W^YEVWJ%y8a1uBPoCHn+Cka<3;iyzxW+6tABir@Keq;=sA2;LHP$T2Yd~N#G=K5;zH*1WppJOv20qkMiJb*C!h=%8nTWC;3+< zf98Qlkt5snA^+>me##%^xurPH!}s!BIqmgm`C7fS_0axM!>Vm}uO}T}v^}ZZt$Y$V zN$5kuQFgQtSP5>p8t1vNAh2L`dz}38I;gg}7^j!Hfj|LC;8Enrc74b{Gl2sgH$~sX z0!iQ`p$`d1*)a)x6BIqP8!iOiZP#Nv5ltbXHzr)Ur(N%9Uzd5~LEyhZ-o6;~P!wdh zVGI2JzURp{Z+?FMndS^jV8kO2&EHy8V=6>W4}yCU)vG_V$?>vJOU`HZUMBo`{9(IT z2)ujHwjc6tJP8bA=z#_Q$ooy;&wiSU#3X?c52(1%i@>{wop-5wcynH2HXDjzI!Y^hVnFt{49GP3((}{ z34C7JTNV)!m^G~f%c;X)S_g{J7*1Y0Kd=R+hk+4+>0-v)I9LXZdFoJYke|uk#v@c9vA%UAD<_OG@ zS3=;-PQWNws-T>_cnnk@dyoRT8+I zcE{K1srgvT_trdu$^&zrxfEtn*^33Z@#U{yvsu*qqDb7#LWsuQ>fc$H=?JVLuZ6%#Vl^s;RP>y?=kvfw9+--azX)u$ih{u9=`|_AG=yp9 z6`gmydi1B3-`3cLlH*R^h!_~n_j+a_M(ot>{mk>rIIjH3Ys&+liM>bBcyC%II}%t! zn2YL#zIWKE)7Yguc|8gI@rBFjGD$v8n+NW7dM(c{%lH&WT>V*yW(+LrUZb>;z)|^O zQe%hHb6&)g#>$c9&DjNX9ymRnklHKewa6JpT;RPB(lMMm z3xUSM67p&YjOrmZ{;2Zf$@@?Omn1Y#03m@rNvw@oZ$aLt#lSTJKIQC&*-1|V<{|IH z3G6ngN&?S7VhO>giFuzM1D^@m)29Bg+R!lC9x-gXWO|$?ACj(*4wksyR`{yy_*BUb82w) z82Eb*;xSbufqRp9J@O`j+wUhpNgPaIO_oAJUUAIXslTvZ=r}dXEuV$Z-re>fa5Rb6 zC2tZKdqWK8;hl+OiHXm#GEBJ6{S)iOjSq1BrUd3ayeEPGNV%E2zJa(;ZtD8}|6}w< z-*qM}hu^a-^;ELhleJliQG^1>QY|t{->7!AcDQdA;z|H2KRlXbKmUHK8=yO&ze)W5 zp78oH??c`T;XYcFr;nZ$D1qGc+{2eiyaDb1^Rf^X5);JZV$SI6b>i+vQ~bz#5dSq9 z{N&nvD`Q~Uy1IMvF>4$U5GleoJ1TcnNnrBS+US^)8|!z#X+Cr(eP!IGe4DubPWP+#KVT1jYzlQnE~CMN(8FoAXBT^&)k5tVDxjVU2ByIycV)pHHieA@Idlnt5Pp z9u+O01a|P1iA2m!U~f~c67wti{kz?eIy{hJjt#@__KVdrsy&prQSH+^ec#bm@AjkG z^L-*i;Xzp?Enu;LTMTSQFcBMidG6(jZm0GrFu8_*5V%BuGpRUnmx29M;Oc3wk0PFXyT)kKnZU&`KApghq;VnNXdwalcSiyflegC- z)}oB5hl-^Ld^|~EdXt+u$72SkSpb=?Vdf1p0E-fMG)kEE14uJ@k7epPu1xa~7)9Nz z<;o#+*3(&>7^vb3sKQ3O#qPvCl|<-rDdX1qr32=J{VW7!R@4JmFSmIAQS)~rurMpp zm%xs(&(t{LX2sOXJ1W<~4t4@llaf>ZZr6>mTo~a9J4?+Urk{|wr5=3=?C9K6i^>?d zK0Fx%2kbgaQG^bHRc=sysn{^`a^WPXXkP+zN>7bdfpVPj1)`QN+QAO`7?`sxr~Ind zxqcgCx+vml%^juB<@BC1n-fc5bTH9Lv06E9)~wbaRNs#M))SbzyY2MsSvVQEK`5@1 z?-vxx@$Q$kd3Sw?C;7GQ^dT_nxmhkPAhbXd*ovr6{n-fY)Gha8aNc%G0t-Dpi_c|& zB(M{zyvd@C37xw0mn3i&=xwJY@LWJiZG;wZC$N?rS zOR6Zj95J|dt291;TS7sa+6uF^V>$e<6L*QQIJ)Sw}-Jr6)F9O$$zLU1RCLwT? zTof6t_DdO(vQ+yV?IpHD`}ovyO#+`uahbq^EJW)r+#(ktFgYO`9&gDSaFbUW11rH~ z4pGelIw@WyaE%Zi1ooDTP)DP;rVf>L*!padhxGBuWiAA!vI`bczCVOSe4V{WGikFM z6frb%}+2X2wY!}Be4Lh2%AxHuSzSx3kD9%Heh3}`2AgQtdM zniy3=V1#TMy%D)3x?1f>noCP7M+v8737JCNo^IM4I(3~+UPiewOS6iCEQ86|`%q<4|MxrUTw|3JDFH1h%+;)*WtvB(Tuqg~hu7 zZr|y9y~av-#zI^{+CXr5=>5RnJ5yG--FLPqy&`wo&a!8*3uh0?-pCGNOE!AS&pO_% z`WFJX2H$cvz{AtMPM>M|ae(A>vP?s~2q38lOnf8cIFR*G^q9cKX+Rbdg147)=c!xQ z$+Hk=x@bMz)AKyM-P#X?Se|`GWl8%*ts*r!t^eEgtGz?I*XmR~jiw=#2Vq;Dwi$BQ zYbUW(Pffknsj}Aq{=QBOM|Zy|UrOL}c~0??z?aD%v7`tL3cnw?q=D31&+o~#dZ&~) z<(XV<`{#C%*pTZpDvu+v)E>2VkI;c>Y_@vlvEXuB7% zl(Fyr?+Ss-^S|e%mL>YIeih&V3O;6yOM@VVQWiYH>EUhmsPsRHbElR3e?4==+w0~52L=H-7 zO+PesSOTBl!g!8_S0OO9f?VFP-q^vSV%jf*pJL%E5pPD|GG81O<8pG@Jg_x>Lun-O zK7J7&w`>v;}TY;3V(Q(%-<~NSp*-nm?)hZ3&#@{U+~j4~}T7UH=cR86YRN SMk|N_0000Px?%t=H+RCr$Po#}epIt)aU_kZa2^P*UmNMf*Yk*0s{ZB2n7Fg%1H#rggD`T6(n z-@l*V-`~go@V|`1S~_^Bm*VB-T@_xxBrwIhs(7D%lfW#SRz87AVAi~A)x5`ik-#J{ z3C!*VyEmgwG7^{sCV@#{5|{)g30EfJs8$@i5TnS!d1JaCtbs}XmB~*6lY}uO92G|r zm;@$)*@a*if&?ZBS0*955TkZ5=Vc8{a`2T*5||`hn}nnC$1VhG@0Cwb_JK!{gY(9m zI3zF$OaikH%s%j_6NLmOfk|Kzm;@$)Ny3#$$Ug9>9n5)Sx&fo&$QqdBUzz;RKJd@` zPwg1kK9|OgIz~8edlOzdZ+ihBh1&YNB$`VH?f0?oUw@=HjQ%_eK3cm{ylPsLp!!8% zjes-8dXsJSNjqnMF*nFE_e7X?@jHNop z8EGyoFp`z}=h^n{p4qP)u_k%Wqh9PHZVFg-M> zu?s?z=xkrKt0?)it*7^fj1#X;H%0-Y;?+5W9*x>W*EYuX??~AYF=w`o>xdWE%}KyA zWwheOo#`cDOQPktWXtnoe-J3rF%Y@NRs@q9>7iC{;;k6_>%NN@UzG=5#Pw$#HpS+lUz%GPW zy!JA}n&{((INCw#UW!*6{V1K_t=X@ymMXg&?Np;cDb`ZjARa2QcZ+QQuU8XqZ~Ere zyr|w@85IbO8q zr6gc%O}%v?&sPwze9@=!*e;LwFBbf)Q8S4*^Hj2k_vO$2oC$Tavo3dV);3ir;`yl>zxTaIQu8h z(h=*I?aKnii|6OqK=^%xFQ=3cWvE>r^_#kq;4muPGAW1{`@w!@RQyO4MHKJcu4;8Eg4=bcBq*uxNXU2Bb7tOlMf zxR{7D%Z59PchMSnEfG_^x%nc2|9&jc^CDB3#M$DN`JXEu`+MJUel74ME^e{8&+PlY zVMg)3bU^}#5ICmACW{gsvC5|R`$+;PeD6iix7iBZPx>AYzt}QPKoU5Vz%l(|l(Tmi zFS`(_;_X#d%t^*xH+UrQ(jvaMcuC+c;>{v4#mg>4!VO&eM#Wy;eqTxP@?D7T;-%== zg}999tR&_pSm>vc@0zU9uZpe}_nUPgW)lZW;wVwgwtoM*?)N0_uPNXUUQA8bNmQq1 z$Smvk`EgSMqvRVs&X?Tt!-P(orQ^NIjR^cs-sx#?v`8d-gG59Ed)}9olA8VbXp(B@ zkB&!e{^)u7+arO~kGrFI`X~8Wt6!VIT0(Fki`nOZi$oxhz=wzof9D`-vlug7C5_SE@XMU>tX+Oumu{X#2|PTTbYPMQkigm+ zt~x&Z1RAXv9T}@nI>nPoHxHl0jn)O{cSRt8z?J!{HIHtG<-M~I<;UvlNA=^37hD7D zx)LNXnm>-4G6Devt~5L^(}h6EQ>lT&YHZXGbevX?s9j-PP9Ipi7>;KI=7>N5fmg2q zy<}N!{aWF9<5PJ8CqAjf=4B16%_qlC6#)l_&XDDfvFPzSW*!2C&OyVu5`-_9pv ze_bPK{UU*}ZUhNz%`2~)A_5Kqm$%qe-~5;Q(Z_Xff0wSy|J=s1zU-u&|V zp%EZ~gKE)eviQjyr7MiAsK3#1B7vjwOglp&KmuQmz|lG)fukczdyK$e1i}f7)!=4rV@1W4eZ8hG4^lBJSZQf9@61kTDo?RJR(MBqp7uJq^k@pX?5 zf@Rr7es{&c%H+=_Ievp@mfiZV3&_&R1qfVA#xZ0sA>)6t>>?gy&7EZzS<{`z6bW1- zV=GVyxw7mc#6$(QUn6qDWZA8sY`x^VFo7*ec^k?Db1QY%Pz7ejwyUQr8OZR z0oUGAs}#~e77!A)YH6J^(8$3{w-SUS6-WGAn~l26a`g4TTQCvhWbh0KkN zIZDNH4I;NJyU5&E9pfUfrM5+OB5D^Q+AIXdYv$2Xy8(ggk4t^^uhuR?G-OOPfst0E zwWc2}@7d;86S$Qe>F!=rOCwLjW+gDvA3k?$W|78)2`r1(mV_+34{v59FzIX4N$Dzx zz!Fic79F$fM%1$wYPZzGr*J`gt6-){;1)@w zCv?_#6FhcHHTDPsBYwOn?7QjBk;MfFEZs$01D|DALqEj#XaaBkW!cRU@)}lE?*m(F z-Hk{iegb0_0zXcqa@S-wp)5{dZ7&uLf0kWoehc+1*GPU?J0ghPJC8XL7=L1<+o@T0 zr6+sZdC~FcxXr)$Z{&3Ol;Ym&^RIUyvM8Bl7bOoW9<85QcF}cl9PmD{Hc06Ez!`RH zH9FFlt@)Gp6B)C0ATCT`jo3V&8kA zCA_pL#t4%He#RXkr6oa#T~rtnHBmd#Q@`WqR=bvX-Q^nSU5J_9!0&Z;YoBLT>0E%o ztA?I_-!}pzu;aVkzE7srMMMIxogl8ZYe#?t zHWPU5#DBaefv=KDu4BOnkicpJ&zI%x!Hn%e$ps0V^*(G=>ZOEbJ!yORzqf4@OjHzh zMZo)6w$>jc&#hRaZ{x+U_+t@zA9x$?{fP|k6Fua6AWA>^P=2JVCC|&sRRrAHL+v$^g`~Aw z4*hLF$HXB5F4x{|qCcae{Jsc}fa|4M`*)p0e}9LyMm{}>s}<+RplS)cB_?7ATM}lu zW-q|w^{sW(#C{YfI!+>zXKmWL-ZPi94$J3aAGlWYXbHUEu@-{vcc}Jy-S~1CYa6>n zOzq~@64!eZ_wJ`uy9%v)3;jtJTk{@C4ZREDNeFtaX7_0+pdDWmNXb=hYx_ zia0?vxt7L?1m5>mrT!pt7hAKZsev>^t(_p6-v-p8@3EEi_&d635y40atj#B1cP1ke zS3I7%6@;2785#*Y_O;Bq-q&#asuhzg) z;!1bup5s(XoE)(87ll|7tGz*L(M;0^me$|;+_O$io;5V~tVeS#R0Dh8VVLuJO_+3J zJ%ZBB^croOuTPDtC8~Bj)P=AF_0HGW1Z9s{@A>SW#$S0u0>=kYTXsZyU=uJ29GwT+ zV+7O@xDkQXvAOsKB=E%(%;l{Rfg2Ebg*5c^@fzgi_d@j44ChLVz=a8%7PG|-UyH#1 Y0dz>%728&#g8%>k07*qoM6N<$f(O|K)&Kwi diff --git a/apps/mtnclock/screenshot4.png b/apps/mtnclock/screenshot4.png deleted file mode 100644 index 8f2e1de907117a4378c87de973aa09711961a6ef..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3623 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 diff --git a/apps/mtnclock/screenshot5.png b/apps/mtnclock/screenshot5.png deleted file mode 100644 index b34a3111ca81395be3b6644ab7f576222029c98f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3427 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 FV1hRXwUz(? From bdcd253e6c66c75741efa7bfedb1be251fedec43 Mon Sep 17 00:00:00 2001 From: sir-indy Date: Thu, 21 Apr 2022 16:35:54 +0100 Subject: [PATCH 08/78] remove fuzzyw.settings.js --- apps/fuzzyw/fuzzyw.settings.js | 46 ---------------------------------- apps/fuzzyw/metadata.json | 1 - 2 files changed, 47 deletions(-) delete mode 100644 apps/fuzzyw/fuzzyw.settings.js diff --git a/apps/fuzzyw/fuzzyw.settings.js b/apps/fuzzyw/fuzzyw.settings.js deleted file mode 100644 index 00219accf..000000000 --- a/apps/fuzzyw/fuzzyw.settings.js +++ /dev/null @@ -1,46 +0,0 @@ -(function(back) { - const SETTINGS_FILE = "fuzzyw.settings.json"; - - var align_options = ['Left','Centre','Right']; - var language_options = ['System', 'en_GB', 'en_US', 'es_ES', 'fr_FR', 'no_NO', 'sv_SE', 'de_DE']; - - // initialize with default settings... - let s = {'language': 'System', 'alignment': 'Centre'}; - - // ...and overwrite them with any saved values - // This way saved values are preserved if a new version adds more settings - const storage = require('Storage') - let settings = storage.readJSON(SETTINGS_FILE, 1) || s; - const saved = settings || {} - for (const key in saved) { - s[key] = saved[key] - } - - function save() { - settings = s - storage.write(SETTINGS_FILE, settings) - } - - E.showMenu({ - '': { 'title': 'Fuzzy Text Clock' }, - '< Back': back, - 'Language': { - value: 0 | language_options.indexOf(s.language), - min: 0, max: language_options.length - 1, - format: v => language_options[v], - onchange: v => { - s.language = language_options[v]; - save(); - } - }, - 'Alignment': { - value: 0 | align_options.indexOf(s.alignment), - min: 0, max: align_options.length - 1, - format: v => align_options[v], - onchange: v => { - s.alignment = align_options[v]; - save(); - } - }, - }); -}) diff --git a/apps/fuzzyw/metadata.json b/apps/fuzzyw/metadata.json index a5edf4962..5d3045edb 100644 --- a/apps/fuzzyw/metadata.json +++ b/apps/fuzzyw/metadata.json @@ -13,7 +13,6 @@ "allow_emulator": true, "storage": [ {"name":"fuzzyw.app.js","url":"fuzzyw.app.js"}, - {"name":"fuzzyw.settings.js","url":"fuzzyw.settings.js"}, {"name":"fuzzyw.img","url":"fuzzyw.icon.js","evaluate":true} ] } From 9c2e1987e2b13ebbf2bfd72ca441e408508de33a Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Thu, 21 Apr 2022 17:06:32 +0100 Subject: [PATCH 09/78] remove fuzzy strings, add translations to lang files --- apps/fuzzyw/fuzzy_strings.json | 186 --------------------------------- lang/es_ES.json | 29 ++++- lang/fr_FR.json | 29 ++++- lang/nn_NO.json | 29 ++++- lang/sv_SE.json | 29 ++++- 5 files changed, 112 insertions(+), 190 deletions(-) delete mode 100644 apps/fuzzyw/fuzzy_strings.json diff --git a/apps/fuzzyw/fuzzy_strings.json b/apps/fuzzyw/fuzzy_strings.json deleted file mode 100644 index 55f443813..000000000 --- a/apps/fuzzyw/fuzzy_strings.json +++ /dev/null @@ -1,186 +0,0 @@ -{ - "en_GB":{ - "hours":[ - "midnight", "one", "two", "three", "four", "five", - "six", "seven", "eight", "nine", "ten", "eleven", - "twelve", "one", "two", "three", "four", "five", - "six", "seven", "eight", "nine", "ten", "eleven" - ], - "minutes":[ - "*$1 o'clock", - "five past *$1", - "ten past *$1", - "quarter past *$1", - "twenty past *$1", - "twenty five past *$1", - "half past *$1", - "twenty five to *$2", - "twenty to *$2", - "quarter to *$2", - "ten to *$2", - "five to *$2" - ], - "text_scale":3.5 - }, - "en_US":{ - "hours":[ - "midnight", "one", "two", "three", "four", "five", - "six", "seven", "eight", "nine", "ten", "eleven", - "twelve", "one", "two", "three", "four", "five", - "six", "seven", "eight", "nine", "ten", "eleven" - ], - "minutes":[ - "*$1 o'clock", - "five after *$1", - "ten after *$1", - "quarter after *$1", - "twenty after *$1", - "twenty five after *$1", - "half past *$1", - "twenty five to *$2", - "twenty to *$2", - "quarter to *$2", - "ten to *$2", - "five to *$2" - ], - "text_scale":3.5 - }, - "es_ES":{ - "hours":[ - "doce", "una", "dos", "tres", "cuatro", "cinco", - "seis", "siete", "ocho", "nueve", "diez", "once", - "doce", "una", "dos", "tres", "cuatro", "cinco", - "seis", "siete", "ocho", "nueve", "diez", "once" - ], - "minutes":[ - "*$1 en punto", - "*$1 y cinco", - "*$1 y diez", - "*$1 y cuarto", - "*$1 y veinte", - "*$1 y veinti- cinco", - "*$1 y media", - "*$2 menos veinti- cinco", - "*$2 menos veinte", - "*$2 menos cuarto", - "*$2 menos diez", - "*$2 menos cinco" - ], - "text_scale":3.5 - }, - "fr_FR":{ - "hours":[ - "douze", "une", "deux", "trois", "quatre", "cinq", - "six", "sept", "huit", "neuf", "dix", "onze", - "douze", "une", "deux", "trois", "quatre", "cinq", - "six", "sept", "huit", "neuf", "dix", "onze" - ], - "minutes":[ - "*$1 heures", - "*$1 heures cinq", - "*$1 heures dix", - "*$1 heures et quart", - "*$1 heures vingt", - "*$1 heures vingt- cinq", - "*$1 heures et demie", - "*$2 moins vingt- cinq", - "*$2 heures moins vingt", - "*$2 moins le quart", - "*$2 heures moins dix", - "*$2 heures moins cinq" - ], - "text_scale":3.5 - }, - "no_NB":{ - "hours":[ - "tolv", "ett", "to", "tre", "fire", "fem", - "seks", "sju", "åtte", "ni", "ti", "elleve", - "tolv", "ett", "to", "tre", "fire", "fem", - "seks", "sju", "åtte", "ni", "ti", "elleve" - ], - "minutes":[ - "klokka er *$1", - "fem over *$1", - "ti over *$1", - "kvart over *$1", - "ti på halv *$2", - "fem på halv *$2", - "halv *$2", - "fem over halv *$2", - "ti over halv *$2", - "kvart på *$2", - "ti på *$2", - "fem på *$2" - ], - "text_scale":3.5 - }, - "nn_NO":{ - "hours":[ - "tolv", "eitt", "to", "tre", "fire", "fem", - "seks", "sju", "åtte", "ni", "ti", "elleve", - "tolv", "eitt", "to", "tre", "fire", "fem", - "seks", "sju", "åtte", "ni", "ti", "elleve" - ], - "minutes":[ - "klokka er *$1", - "fem over *$1", - "ti over *$1", - "kvart over *$1", - "ti på halv *$2", - "fem på halv *$2", - "halv *$2", - "fem over halv *$2", - "ti over halv *$2", - "kvart på *$2", - "ti på *$2", - "fem på *$2" - ], - "text_scale":3.5 - }, - "sv_SE":{ - "hours":[ - "tolv", "ett", "två", "tre", "fyra", "fem", - "sex", "sju", "åtta", "nio", "tio", "elva", - "tolv", "ett", "två", "tre", "fyra", "fem", - "sex", "sju", "åtta", "nio", "tio", "elva" - ], - "minutes":[ - "*$1", - "fem över *$1", - "tio över *$1", - "kvart över *$1", - "tjugo över *$1", - "fem i halv *$2", - "halv *$2", - "fem över halv *$2", - "tjugo i *$2", - "kvart i *$2", - "tio i *$2", - "fem i *$2" - ], - "text_scale":3.5 - }, - "de_DE":{ - "hours":[ - "zwölf", "eins", "zwei", "drei", "vier", "fünf", - "sechs", "sieben", "acht", "neun", "zehn", "elf", - "zwölf", "eins", "zwei", "drei", "vier", "fünf", - "sechs", "sieben", "acht", "neun", "zehn", "elf" - ], - "minutes":[ - "*$1 uhr", - "fünf nach *$1", - "zehn nach *$1", - "viertel nach *$1", - "zwanzig nach *$1", - "fünf for halb *$2", - "halb *$2", - "fünf nach halb *$2", - "zwanzig vor *$2", - "viertel vor *$2", - "zehn vor *$2", - "fünf vor *$2" - ], - "text_scale":3.5 - } -} diff --git a/lang/es_ES.json b/lang/es_ES.json index d381582e3..41dd377ab 100644 --- a/lang/es_ES.json +++ b/lang/es_ES.json @@ -164,10 +164,37 @@ "Music": "Música", "color": "color", "off": "fuera de", - "Theme": "Tema" + "Theme": "Tema", + "one": "una", + "two": "dos", + "three": "tres", + "four": "cuatro", + "five": "cinco", + "six": "seis", + "seven": "siete", + "eight": "ocho", + "nine": "nueve", + "ten": "diez", + "eleven": "once", + "twelve": "doce" }, "alarm": { "//": "App-specific overrides", "rpt": "rep." + }, + "fuzzyw": { + "//": "App-specific overrides", + "*$1 o'clock": "*$1 en punto", + "five past *$1": "*$1 y cincq", + "ten past *$1": "*$1 y diez", + "quarter past *$1": "*$1 y cuarto", + "twenty past *$1": "*$1 y veinte", + "twenty five past *$1": "*$1 y veinti- cinco", + "half past *$1": "*$1 y media", + "twenty five to *$2": "*$2 menos veinti- cinco", + "twenty to *$2": "*$2 menos veinte", + "quarter to *$2": "*$2 menos cuarto", + "ten to *$2": "*$2 menos diez", + "five to *$2": "*$2 menos cinco" } } \ No newline at end of file diff --git a/lang/fr_FR.json b/lang/fr_FR.json index ad0f03b0c..ac3785e9d 100644 --- a/lang/fr_FR.json +++ b/lang/fr_FR.json @@ -164,10 +164,37 @@ "color": "couleur", "Off": "Off", "off": "off", - "Theme": "Thème" + "Theme": "Thème", + "one": "une", + "two": "deux", + "three": "trois", + "four": "quatre", + "five": "cinq", + "six": "six", + "seven": "sept", + "eight": "huit", + "nine": "neuf", + "ten": "dix", + "eleven": "onze", + "twelve": "douze" }, "alarm": { "//": "App-specific overrides", "rpt": "rép." + }, + "fuzzyw": { + "//": "App-specific overrides", + "*$1 o'clock": "*$1 heures", + "five past *$1": "*$1 heures cinq", + "ten past *$1": "*$1 heures dix", + "quarter past *$1": "*$1 heures et quart", + "twenty past *$1": "*$1 heures vingt", + "twenty five past *$1": "*$1 heures vingt- cinq", + "half past *$1": "*$1 heures et demie", + "twenty five to *$2": "*$2 moins vingt- cinq", + "twenty to *$2": "*$2 heures moins vingt", + "quarter to *$2": "*$2 moins le quart", + "ten to *$2": "*$2 heures moins dix", + "five to *$2": "*$2 heures moins cinq" } } \ No newline at end of file diff --git a/lang/nn_NO.json b/lang/nn_NO.json index 176d82b48..c85855acc 100644 --- a/lang/nn_NO.json +++ b/lang/nn_NO.json @@ -239,6 +239,33 @@ "Su color": "Su farge", "filled": "fylt", "Mrk.Color": "Mrk.Farge", - "Mrk.Size": "Mrk.Storleik" + "Mrk.Size": "Mrk.Storleik", + "one": "eitt", + "two": "to", + "three": "tre", + "four": "fire", + "five": "fem", + "six": "seks", + "seven": "sju", + "eight": "åtte", + "nine": "ni", + "ten": "ti", + "eleven": "elleve", + "twelve": "tolv" + }, + "fuzzyw": { + "//": "App-specific overrides", + "*$1 o'clock": "klokka er *$1", + "five past *$1": "fem over *$1", + "ten past *$1": "ti over *$1", + "quarter past *$1": "kvart over *$1", + "twenty past *$1": "ti på halv *$2", + "twenty five past *$1": "fem på halv *$2", + "half past *$1": "halv *$2", + "twenty five to *$2": "fem over halv *$2", + "twenty to *$2": "ti over halv *$2", + "quarter to *$2": "kvart på *$2", + "ten to *$2": "ti på *$2", + "five to *$2": "fem på *$2" } } diff --git a/lang/sv_SE.json b/lang/sv_SE.json index 6b35f5cdf..6e0f30fa4 100644 --- a/lang/sv_SE.json +++ b/lang/sv_SE.json @@ -164,10 +164,37 @@ "color": "färg", "off": "off", "Off": "Av", - "Theme": "Tema" + "Theme": "Tema", + "one": "ett", + "two": "två", + "three": "tre", + "four": "fyra", + "five": "fem", + "six": "sex", + "seven": "sju", + "eight": "åtta", + "nine": "nio", + "ten": "tio", + "eleven": "elva", + "twelve": "tolv" }, "alarm": { "//": "App-specific overrides", "rpt": "uppr." + }, + "fuzzyw": { + "//": "App-specific overrides", + "*$1 o'clock": "*$1", + "five past *$1": "fem över *$1", + "ten past *$1": "tio över *$1", + "quarter past *$1": "kvart över *$1", + "twenty past *$1": "tjugo över *$1", + "twenty five past *$1": "fem i halv *$2", + "half past *$1": "halv *$2", + "twenty five to *$2": "fem över halv *$2", + "twenty to *$2": "tjugo i *$2", + "quarter to *$2": "kvart i *$2", + "ten to *$2": "tio i *$2", + "five to *$2": "fem i *$2" } } \ No newline at end of file From 9133345ec7046207dedb1cb0dab24500d4d8e283 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Thu, 21 Apr 2022 17:14:16 +0100 Subject: [PATCH 10/78] Updated Readme --- apps/fuzzyw/ChangeLog | 2 +- apps/fuzzyw/README.md | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/apps/fuzzyw/ChangeLog b/apps/fuzzyw/ChangeLog index 63a0d60f0..0e5b66949 100644 --- a/apps/fuzzyw/ChangeLog +++ b/apps/fuzzyw/ChangeLog @@ -1,2 +1,2 @@ 0.01: First release -0.02: Move translations to locale module +0.02: Move translations to locale module (removed watch settings, now pick language in Bangle App Loader, More..., Settings) diff --git a/apps/fuzzyw/README.md b/apps/fuzzyw/README.md index 906eb167b..49d0fe0d5 100644 --- a/apps/fuzzyw/README.md +++ b/apps/fuzzyw/README.md @@ -4,12 +4,11 @@ An imprecise clock for when you're not in a rush. This clock is a remake of one of my favourite Pebble watchfaces, Fuzzy Text International. I use this watch for weekends and holidays, when 'within 5 minutes of the actual time' is close enough! -By default it will use the language set on the watch, go to settings to pick: -* en_GB - English -* en_US - American +Translations are supported to get the time in the language of your choice! To choose language, in the Bangle App Loader, navigate to the 'More...' tab and pick language under 'Settings'. Currently supported languages are below, but if you want to contribution a translation please feel free!: +* en_GB - English (Default) * es_ES - Spanish * fr_FR - French -* no_NO - Norwegian +* nn_NO - Norwegian Nynorsk (thank you zerodogg) * sv_SE - Swedish * de_DE - German From a6991560c370b33070ff225d155f04e0e3262026 Mon Sep 17 00:00:00 2001 From: Rarder44 Date: Thu, 21 Apr 2022 22:00:24 +0200 Subject: [PATCH 11/78] fix get font size --- apps/gbmusic/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/gbmusic/app.js b/apps/gbmusic/app.js index 5252ac0ac..49f54dac9 100644 --- a/apps/gbmusic/app.js +++ b/apps/gbmusic/app.js @@ -86,7 +86,8 @@ function infoColor(name) { * @param l */ function rScroller(l) { - g.setFont("Vector", Math.round(g.getHeight()*l.fsz.slice(0, -1)/100)); + var size=l.font.split(":")[1].slice(0,-1); + g.setFont("Vector", Math.round(g.getHeight()*size/100)); const w = g.stringWidth(l.label)+40, y = l.y+l.h/2; l.offset = l.offset%w; From 662581bff00a8cc145e4c07ea25be92cfeedc013 Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 21 Apr 2022 22:05:12 +0200 Subject: [PATCH 12/78] [sched] Update lib.js Correct `decodeTime(t)` to return a more likely expected time: - before: `require("sched").decodeTime(60*60*1000-1)` returns: `{ hrs: 0, mins: 60 }` - after: `require("sched").decodeTime(60*60*1000-1)` returns: `{ hrs: 1, mins: 0 }` --- apps/sched/lib.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 58ba5daf0..6211f4837 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -110,9 +110,9 @@ exports.setSettings = function(settings) { // time in ms -> { hrs, mins } exports.decodeTime = function(t) { - t = 0 | t; // sanitise - let hrs = 0 | (t / 3600000); - return { hrs: hrs, mins: Math.round((t - hrs * 3600000) / 60000) }; + t = Math.ceil(t / 60000); // sanitise to full minutes + let hrs = 0 | (t / 60); + return { hrs: hrs, mins: t - hrs * 60; } // time in { hrs, mins } -> ms From 052c1694d262381e09889a7a4b87fa20d7c7c7ac Mon Sep 17 00:00:00 2001 From: storm64 Date: Thu, 21 Apr 2022 23:01:39 +0200 Subject: [PATCH 13/78] [Sched] Correct `decodeTime(t)` rounding Correct `decodeTime(t)` to return a more likely expected time: - before: `require("sched").decodeTime(60*60*1000-1)` returns: `{ hrs: 0, mins: 60 }` - after: `require("sched").decodeTime(60*60*1000-1)` returns: `{ hrs: 1, mins: 0 }` --- apps/sched/ChangeLog | 1 + apps/sched/lib.js | 2 +- apps/sched/metadata.json | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 7372f9c4a..d944e7eed 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -4,3 +4,4 @@ 0.04: Fix `getTimeToAlarm` to check for next dow if alarm.t lower currentTime. 0.05: Export new functions (`newDefaultAlarm/Timer`), add Settings page 0.06: Refactor some methods to library +0.07: Correct `decodeTime(t)` to return a more likely expected time diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 6211f4837..0eeea68e3 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -112,7 +112,7 @@ exports.setSettings = function(settings) { exports.decodeTime = function(t) { t = Math.ceil(t / 60000); // sanitise to full minutes let hrs = 0 | (t / 60); - return { hrs: hrs, mins: t - hrs * 60; + return { hrs: hrs, mins: t - hrs * 60 }; } // time in { hrs, mins } -> ms diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 5f61d7d04..c41e5b5b3 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.06", + "version": "0.07", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", From 51c1e86d492fc35d258502c1d24e68226fafe7e5 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 22 Apr 2022 00:34:04 +0100 Subject: [PATCH 14/78] dtlaunch, make left to right swipe exit optional --- apps/dtlaunch/ChangeLog | 1 + apps/dtlaunch/app-b2.js | 9 +++++---- apps/dtlaunch/metadata.json | 2 +- apps/dtlaunch/settings-b2.js | 11 ++++++++++- 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index 66fda2f29..95952b9fe 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -10,3 +10,4 @@ 0.10: added "one click exit" setting for Bangle 2 0.11: Fix bangle.js 1 white icons not displaying 0.12: On Bangle 2 change to swiping up/down to move between pages as to match page indicator. Swiping from left to right now loads the clock. +0.13: Added swipeExit setting so that left-right to exit is an option diff --git a/apps/dtlaunch/app-b2.js b/apps/dtlaunch/app-b2.js index 7202e4f33..8466a7414 100644 --- a/apps/dtlaunch/app-b2.js +++ b/apps/dtlaunch/app-b2.js @@ -6,7 +6,8 @@ var settings = Object.assign({ showClocks: true, showLaunchers: true, direct: false, - oneClickExit:false + oneClickExit:false, + swipeExit: false }, require('Storage').readJSON("dtlaunch.json", true) || {}); if( settings.oneClickExit) @@ -88,14 +89,14 @@ function drawPage(p){ Bangle.on("swipe",(dirLeftRight, dirUpDown)=>{ selected = 0; oldselected=-1; - if (dirUpDown==-1){ + if(settings.swipeExit && dirLeftRight==1) showClock(); + if (dirUpDown==-1||dirLeftRight==-1){ ++page; if (page>maxPage) page=0; drawPage(page); - } else if (dirUpDown==1){ + } else if (dirUpDown==1||dirLeftRight==1){ --page; if (page<0) page=maxPage; drawPage(page); } - if (dirLeftRight==1) showClock(); }); function showClock(){ diff --git a/apps/dtlaunch/metadata.json b/apps/dtlaunch/metadata.json index a5391cef0..7784972ca 100644 --- a/apps/dtlaunch/metadata.json +++ b/apps/dtlaunch/metadata.json @@ -1,7 +1,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", - "version": "0.12", + "version": "0.13", "description": "Desktop style App Launcher with six (four for Bangle 2) apps per page - fast access if you have lots of apps installed.", "screenshots": [{"url":"shot1.png"},{"url":"shot2.png"},{"url":"shot3.png"}], "icon": "icon.png", diff --git a/apps/dtlaunch/settings-b2.js b/apps/dtlaunch/settings-b2.js index 8eca46a7e..7ead63be0 100644 --- a/apps/dtlaunch/settings-b2.js +++ b/apps/dtlaunch/settings-b2.js @@ -5,7 +5,8 @@ showClocks: true, showLaunchers: true, direct: false, - oneClickExit:false + oneClickExit:false, + swipeExit: false }, require('Storage').readJSON(FILE, true) || {}); function writeSettings() { @@ -39,6 +40,14 @@ writeSettings(); } }, + 'Swipe Exit': { + value: settings.swipeExit, + format: v => v?"On":"Off", + onchange: v => { + settings.swipeExit = v; + writeSettings(); + } + }, 'One click exit': { value: settings.oneClickExit, format: v => v?"On":"Off", From 34f02fd1dadae445282c8551c5b6a3a81ea5a026 Mon Sep 17 00:00:00 2001 From: Michael Salaverry Date: Wed, 9 Feb 2022 23:11:02 +0200 Subject: [PATCH 15/78] feat: use customizer to more accurately generate calendar data file feat: brand new UI to display upcoming/current calendar events feat: add holidays, shabbat torah readings, and time display to clock --- apps/hebrew_calendar/ChangeLog | 4 +- .../HebrewCalendar-Screenshot.png | Bin 0 -> 3110 bytes apps/hebrew_calendar/README.md | 15 +- apps/hebrew_calendar/app.js | 199 +++++++++-- apps/hebrew_calendar/customizer.html | 46 +++ apps/hebrew_calendar/customizer.mjs | 329 ++++++++++++++++++ apps/hebrew_calendar/hebrewDate.js | 311 ----------------- apps/hebrew_calendar/metadata.json | 16 +- 8 files changed, 569 insertions(+), 351 deletions(-) create mode 100644 apps/hebrew_calendar/HebrewCalendar-Screenshot.png create mode 100644 apps/hebrew_calendar/customizer.html create mode 100644 apps/hebrew_calendar/customizer.mjs delete mode 100644 apps/hebrew_calendar/hebrewDate.js diff --git a/apps/hebrew_calendar/ChangeLog b/apps/hebrew_calendar/ChangeLog index fdd29db66..1fb04080d 100644 --- a/apps/hebrew_calendar/ChangeLog +++ b/apps/hebrew_calendar/ChangeLog @@ -1,4 +1,6 @@ 0.01: New App! 0.02: using TS and rollup to bundle 0.03: bug fixes and support bangle 1 -0.04: removing TS \ No newline at end of file +0.04: removing TS +0.05: major overhaul; now you customize your calendar based on your location for candle lighting times +0.06: bug fixes and improvements \ No newline at end of file diff --git a/apps/hebrew_calendar/HebrewCalendar-Screenshot.png b/apps/hebrew_calendar/HebrewCalendar-Screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..f60314c997b65cbb99a8049aec51d3d17d25e162 GIT binary patch literal 3110 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.png) +Displays the current hebrew calendar date and upcoming holidays alongside a clock + +![](./HebrewCalendar-Screenshot.png) ## Usage -Open the app, and it shows a menu with the date components +Set it up as your clock in the settings ## Features -Shows the hebrew date, month, and year; alongside the gregorian date +- Shows the hebrew date, month, and year; alongside the gregorian date +- Shows when upcoming holidays start +- Shows the gregorian day of week, date, and current time ## Controls -Name the buttons and what they are used for +N/A ## Requests @@ -22,5 +25,5 @@ Michael Salaverry (github.com/barakplasma) ## Creator Michael Salaverry -with help from https://github.com/IonicaBizau/hebrew-date (MIT license) +with help from https://github.com/hebcal/hebcal-es6 (MIT license) which is used to calculate the calendar

\ No newline at end of file diff --git a/apps/hebrew_calendar/app.js b/apps/hebrew_calendar/app.js index 399d124f3..3d098c60a 100644 --- a/apps/hebrew_calendar/app.js +++ b/apps/hebrew_calendar/app.js @@ -1,26 +1,181 @@ -g.clear(); +const dayInMS = 86400000; -let now = new Date(); +const DateProvider = { now: () => Date.now() }; -let today = require('hebrewDate').hebrewDate(now); +const Layout = require("Layout"); +const Locale = require("locale"); -var mainmenu = { - "": { - "title": "Hebrew Date" - }, - greg: { - // @ts-ignore - value: require('locale').date(now, 1), - }, - date: { - value: today.date, - }, - month: { - value: today.month_name, - }, - year: { - value: today.year, +let nextEndingEvent; + +function getCurrentEvents() { + const now = DateProvider.now(); + + const current = hebrewCalendar.filter( + (x) => x.startEvent <= now && x.endEvent >= now + ); + + nextEndingEvent = current.reduce((acc, ev) => { + return Math.min(acc, ev.endEvent); + }, Infinity); + + return current.map((event, i) => { + return { + type: "txt", + font: "12x20", + id: "currentEvents" + i, + label: event.desc, + pad: 2, + bgCol: g.theme.bg, + }; + }); +} + +function getUpcomingEvents() { + const now = DateProvider.now(); + + const futureEvents = hebrewCalendar.filter( + (x) => x.startEvent >= now && x.startEvent <= now + dayInMS + ); + + let warning; + let eventsLeft = hebrewCalendar.filter( + (x) => x.startEvent >= now && x.startEvent <= now + dayInMS * 14 + ).length; + + if (eventsLeft < 14) { + warning = { + startEvent: 0, + type: "txt", + font: "4x6", + id: "warning", + label: "only " + eventsLeft + " events left in calendar; update soon", + pad: 2, + bgCol: g.theme.bg, + }; } -}; -// @ts-ignore -E.showMenu(mainmenu); \ No newline at end of file + + return futureEvents + .slice(0, 2) + .map((event, i) => { + return { + startEvent: event.startEvent, + type: "txt", + font: "6x8", + id: "upcomingEvents" + 1, + label: event.desc + " at " + Locale.time(new Date(event.startEvent), 1), + pad: 2, + bgCol: g.theme.bg, + }; + }) + .concat(warning) + .sort(function (a, b) { + return a.startEvent - b.startEvent; + }); +} + +function dateTime() { + return ( + Locale.dow(new Date(), 1) + + " " + + Locale.date(new Date(), 1) + + " " + + Locale.time(new Date(), 1) + ); +} + +function makeLayout() { + return new Layout( + { + type: "v", + c: [ + { + type: "txt", + font: "6x8", + id: "title", + label: "-- Hebrew Calendar Events --", + pad: 2, + bgCol: g.theme.bg2, + }, + { + type: "txt", + font: "6x8", + id: "currently", + label: "Currently", + pad: 2, + bgCol: g.theme.bgH, + }, + ] + .concat(getCurrentEvents()) + .concat([ + { + type: "txt", + font: "6x8", + label: "Upcoming", + id: "upcoming", + pad: 2, + bgCol: g.theme.bgH, + }, + ]) + .concat(getUpcomingEvents()) + .concat([ + { + type: "txt", + font: "Vector14", + id: "time", + label: dateTime(), + pad: 2, + bgCol: undefined, + }, + ]), + }, + { lazy: true } + ); +} +let layout = makeLayout(); +// see also https://www.espruino.com/Bangle.js+Layout#updating-the-screen + +// timeout used to update every minute +let drawTimeout; + +function draw() { + layout.time.label = dateTime(); + layout.render(); + + // schedule a draw for the next minute + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function () { + drawTimeout = undefined; + draw(); + }, 60000 - (DateProvider.now() % 60000)); + console.log("updated time"); +} + +// update time and draw +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +draw(); + +function findNextEvent() { + return hebrewCalendar.find((ev) => { + return ev.startEvent > DateProvider.now(); + }); +} + +function updateCalendar() { + layout.clear(); + layout = makeLayout(); + layout.forgetLazyState(); + layout.render(); + + let nextChange = Math.min( + findNextEvent().startEvent - DateProvider.now() + 5000, + nextEndingEvent - DateProvider.now() + 5000 + ); + setTimeout(updateCalendar, nextChange); + console.log("updated events"); +} + +updateCalendar(); + +Bangle.setUI("clock"); \ No newline at end of file diff --git a/apps/hebrew_calendar/customizer.html b/apps/hebrew_calendar/customizer.html new file mode 100644 index 000000000..bea860e53 --- /dev/null +++ b/apps/hebrew_calendar/customizer.html @@ -0,0 +1,46 @@ + + + + + + + + Hebrew Calendar Customizer + + + + +
+
+
+
Hebrew Calendar Loader
+
+
+
Your location
+
+
+ + + + +
get your latitude and longitude from plus.codes or:
+ + + +
+
+
+ +
+ + +
+ + + \ No newline at end of file diff --git a/apps/hebrew_calendar/customizer.mjs b/apps/hebrew_calendar/customizer.mjs new file mode 100644 index 000000000..06716a63b --- /dev/null +++ b/apps/hebrew_calendar/customizer.mjs @@ -0,0 +1,329 @@ +import { + HebrewCalendar, + HDate, + Location, + Zmanim, +} from "https://cdn.skypack.dev/@hebcal/core@^3?min"; + +function onload(event) { + event.preventDefault(); + const latLon = getLatLonFromForm(); + const events = generateHebCal(latLon); + const calendar = serializeEvents(events); + console.debug(calendar); + globalThis["cal"] = calendar; + loadWatch(calendar); +} + +function loadWatch(json) { + sendCustomizedApp({ + id: "hebrew_calendar", + + storage: [ + { + name: "hebrew_calendar.app.js", + url: "app.js", + // content below is same as app.js except for the first line which customizes the hebrewCalendar object used + content: ` +let hebrewCalendar = ${json}; + +const dayInMS = 86400000; + +const DateProvider = { now: () => Date.now() }; + +const Layout = require("Layout"); +const Locale = require("locale"); + +let nextEndingEvent; + +function getCurrentEvents() { + const now = DateProvider.now(); + + const current = hebrewCalendar.filter( + (x) => x.startEvent <= now && x.endEvent >= now + ); + + nextEndingEvent = current.reduce((acc, ev) => { + return Math.min(acc, ev.endEvent); + }, Infinity); + + return current.map((event, i) => { + return { + type: "txt", + font: "12x20", + id: "currentEvents" + i, + label: event.desc, + pad: 2, + bgCol: g.theme.bg, + }; + }); +} + +function getUpcomingEvents() { + const now = DateProvider.now(); + + const futureEvents = hebrewCalendar.filter( + (x) => x.startEvent >= now && x.startEvent <= now + dayInMS + ); + + let warning; + let eventsLeft = hebrewCalendar.filter( + (x) => x.startEvent >= now && x.startEvent <= now + dayInMS * 14 + ).length; + + if (eventsLeft < 14) { + warning = { + startEvent: 0, + type: "txt", + font: "4x6", + id: "warning", + label: "only " + eventsLeft + " events left in calendar; update soon", + pad: 2, + bgCol: g.theme.bg, + }; + } + + return futureEvents + .slice(0, 2) + .map((event, i) => { + return { + startEvent: event.startEvent, + type: "txt", + font: "6x8", + id: "upcomingEvents" + 1, + label: event.desc + " at " + Locale.time(new Date(event.startEvent), 1), + pad: 2, + bgCol: g.theme.bg, + }; + }) + .concat(warning) + .sort(function (a, b) { + return a.startEvent - b.startEvent; + }); +} + +function dateTime() { + return ( + Locale.dow(new Date(), 1) + + " " + + Locale.date(new Date(), 1) + + " " + + Locale.time(new Date(), 1) + ); +} + +function makeLayout() { + return new Layout( + { + type: "v", + c: [ + { + type: "txt", + font: "6x8", + id: "title", + label: "-- Hebrew Calendar Events --", + pad: 2, + bgCol: g.theme.bg2, + }, + { + type: "txt", + font: "6x8", + id: "currently", + label: "Currently", + pad: 2, + bgCol: g.theme.bgH, + }, + ] + .concat(getCurrentEvents()) + .concat([ + { + type: "txt", + font: "6x8", + label: "Upcoming", + id: "upcoming", + pad: 2, + bgCol: g.theme.bgH, + }, + ]) + .concat(getUpcomingEvents()) + .concat([ + { + type: "txt", + font: "Vector14", + id: "time", + label: dateTime(), + pad: 2, + bgCol: undefined, + }, + ]), + }, + { lazy: true } + ); +} +let layout = makeLayout(); +// see also https://www.espruino.com/Bangle.js+Layout#updating-the-screen + +// timeout used to update every minute +let drawTimeout; + +function draw() { + layout.time.label = dateTime(); + layout.render(); + + // schedule a draw for the next minute + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function () { + drawTimeout = undefined; + draw(); + }, 60000 - (DateProvider.now() % 60000)); + console.log("updated time"); +} + +// update time and draw +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); +draw(); + +function findNextEvent() { + return hebrewCalendar.find((ev) => { + return ev.startEvent > DateProvider.now(); + }); +} + +function updateCalendar() { + layout.clear(); + layout = makeLayout(); + layout.forgetLazyState(); + layout.render(); + + let nextChange = Math.min( + findNextEvent().startEvent - DateProvider.now() + 5000, + nextEndingEvent - DateProvider.now() + 5000 + ); + setTimeout(updateCalendar, nextChange); + console.log("updated events"); +} + +updateCalendar(); + +Bangle.setUI("clock"); + `, + }, + ], + }); +} + +document + .querySelector("button[type=submit]") + .addEventListener("click", onload, false); + +document.querySelector("#geoloc")?.addEventListener("click", (event) => { + event.preventDefault(); + navigator.geolocation.getCurrentPosition( + (pos) => { + const { + coords: { latitude, longitude }, + } = pos; + locationElements[0].value = latitude; + locationElements[1].value = longitude; + console.debug(pos); + }, + (err) => { + if (err.PERMISSION_DENIED) { + alert("permission required to use geolocation api; enter manually"); + } + if (err.POSITION_UNAVAILABLE) { + alert("position unavailable; enter manually"); + } + }, + { enableHighAccuracy: false } + ); +}); + +document.querySelector( + "#hDate" +).innerText = `Today is ${new Date().toLocaleDateString()} & ${new HDate().toString()}`; + +const locationElements = [ + document.querySelector("#lat"), + document.querySelector("#lon"), +]; + +function getLatLonFromForm() { + const latLon = locationElements.map((el) => el.value); + if (locationElements.every((x) => x.checkValidity())) { + return latLon; + } else { + console.debug("lat lon invalid error"); + return [0, 0]; + } +} + +function groupBy(arr, fn) { + return arr + .map(typeof fn === "function" ? fn : (val) => val[fn]) + .reduce((acc, val, i) => { + acc[val] = (acc[val] || []).concat(arr[i]); + return acc; + }, {}); +} + +function generateHebCal(latLon) { + const location = new Location( + ...latLon, + document.querySelector("#inIL").checked + ); + + const now = new Date(); + + const options = { + year: now.getFullYear(), + isHebrewYear: false, + candlelighting: true, + location, + addHebrewDates: true, + addHebrewDatesForEvents: true, + sedrot: true, + start: now, + end: new Date(now.getFullYear(), now.getMonth() + 3), + }; + + const events = HebrewCalendar.calendar(options).map((ev) => { + const { desc, eventTime, startEvent, endEvent } = ev; + + const zman = new Zmanim(ev.date, ...latLon.map(Number)); + + let output = { + desc, + startEvent: startEvent?.eventTime?.getTime() || zman.gregEve().getTime(), + endEvent: endEvent?.eventTime?.getTime() || zman.shkiah().getTime(), + }; + + if (eventTime) { + delete output.startEvent; + delete output.endEvent; + output.startEvent = eventTime.getTime(); + output.endEvent = eventTime.getTime() + 60000 * 15; + } + + return output; + }); + + // console.table(events) + + return events.sort((a, b) => { + return a.startEvent - b.startEvent; + }); +} + +function enc(data) { + return btoa(heatshrink.compress(new TextEncoder().encode(data))); +} + +function serializeEvents(events) { + // const splitByGregorianMonth = groupBy(events, (evt) => { + // return new Date(evt.startEvent).getMonth(); + // }); + return JSON.stringify(events); +} diff --git a/apps/hebrew_calendar/hebrewDate.js b/apps/hebrew_calendar/hebrewDate.js deleted file mode 100644 index da0c9cf50..000000000 --- a/apps/hebrew_calendar/hebrewDate.js +++ /dev/null @@ -1,311 +0,0 @@ -/*! - * This script was taked from this page http://www.shamash.org/help/javadate.shtml and ported to Node.js by Ionică Bizău in https://github.com/IonicaBizau/hebrew-date - * - * This script was adapted from C sources written by - * Scott E. Lee, which contain the following copyright notice: - * - * Copyright 1993-1995, Scott E. Lee, all rights reserved. - * Permission granted to use, copy, modify, distribute and sell so long as - * the above copyright and this permission statement are retained in all - * copies. THERE IS NO WARRANTY - USE AT YOUR OWN RISK. - * - * Bill Hastings - * RBI Software Systems - * bhastings@rbi.com - */ -var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; -var GREG_SDN_OFFSET = 32045, DAYS_PER_5_MONTHS = 153, DAYS_PER_4_YEARS = 1461, DAYS_PER_400_YEARS = 146097; -var HALAKIM_PER_HOUR = 1080, HALAKIM_PER_DAY = 25920, HALAKIM_PER_LUNAR_CYCLE = 29 * HALAKIM_PER_DAY + 13753, HALAKIM_PER_METONIC_CYCLE = HALAKIM_PER_LUNAR_CYCLE * (12 * 19 + 7); -var HEB_SDN_OFFSET = 347997, NEW_MOON_OF_CREATION = 31524, NOON = 18 * HALAKIM_PER_HOUR, AM3_11_20 = 9 * HALAKIM_PER_HOUR + 204, AM9_32_43 = 15 * HALAKIM_PER_HOUR + 589; -var SUN = 0, MON = 1, TUES = 2, WED = 3, THUR = 4, FRI = 5, SAT = 6; -function weekdayarr(d0, d1, d2, d3, d4, d5, d6) { - this[0] = d0; - this[1] = d1; - this[2] = d2; - this[3] = d3; - this[4] = d4; - this[5] = d5; - this[6] = d6; -} -function gregmontharr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11) { - this[0] = m0; - this[1] = m1; - this[2] = m2; - this[3] = m3; - this[4] = m4; - this[5] = m5; - this[6] = m6; - this[7] = m7; - this[8] = m8; - this[9] = m9; - this[10] = m10; - this[11] = m11; -} -function hebrewmontharr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13) { - this[0] = m0; - this[1] = m1; - this[2] = m2; - this[3] = m3; - this[4] = m4; - this[5] = m5; - this[6] = m6; - this[7] = m7; - this[8] = m8; - this[9] = m9; - this[10] = m10; - this[11] = m11; - this[12] = m12; - this[13] = m13; -} -function monthsperyeararr(m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16, m17, m18) { - this[0] = m0; - this[1] = m1; - this[2] = m2; - this[3] = m3; - this[4] = m4; - this[5] = m5; - this[6] = m6; - this[7] = m7; - this[8] = m8; - this[9] = m9; - this[10] = m10; - this[11] = m11; - this[12] = m12; - this[13] = m13; - this[14] = m14; - this[15] = m15; - this[16] = m16; - this[17] = m17; - this[18] = m18; -} -var gWeekday = new weekdayarr("Sun", "Mon", "Tues", "Wednes", "Thurs", "Fri", "Satur"), gMonth = new gregmontharr("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"), hMonth = new hebrewmontharr("Tishri", "Heshvan", "Kislev", "Tevet", "Shevat", "AdarI", "AdarII", "Nisan", "Iyyar", "Sivan", "Tammuz", "Av", "Elul"), mpy = new monthsperyeararr(12, 12, 13, 12, 12, 13, 12, 13, 12, 12, 13, 12, 12, 13, 12, 12, 13, 12, 13); -/** - * hebrewDate - * Convert the Gregorian dates into Hebrew calendar dates. - * - * @name hebrewDate - * @function - * @param {Date|Number} inputDate The date object (representing the Gregorian date) or the year. - * @return {Object} An object containing: - * - * - `year`: The Hebrew year. - * - `month`: The Hebrew month. - * - `month_name`: The Hebrew month name. - * - `date`: The Hebrew date. - */ -function hebrewDate(inputDateOrYear) { - var inputMonth, inputDate; - var hebrewMonth = 0, hebrewDate = 0, hebrewYear = 0, metonicCycle = 0, metonicYear = 0, moladDay = 0, moladHalakim = 0; - function GregorianToSdn(inputYear, inputMonth, inputDay) { - var year = 0, month = 0, sdn = void 0; - // Make year a positive number - if (inputYear < 0) { - year = inputYear + 4801; - } - else { - year = inputYear + 4800; - } - // Adjust the start of the year - if (inputMonth > 2) { - month = inputMonth - 3; - } - else { - month = inputMonth + 9; - year--; - } - sdn = Math.floor(Math.floor(year / 100) * DAYS_PER_400_YEARS / 4); - sdn += Math.floor(year % 100 * DAYS_PER_4_YEARS / 4); - sdn += Math.floor((month * DAYS_PER_5_MONTHS + 2) / 5); - sdn += inputDay - GREG_SDN_OFFSET; - return sdn; - } - function SdnToHebrew(sdn) { - var tishri1 = 0, tishri1After = 0, yearLength = 0, inputDay = sdn - HEB_SDN_OFFSET; - FindTishriMolad(inputDay); - tishri1 = Tishri1(metonicYear, moladDay, moladHalakim); - if (inputDay >= tishri1) { - // It found Tishri 1 at the start of the year. - hebrewYear = metonicCycle * 19 + metonicYear + 1; - if (inputDay < tishri1 + 59) { - if (inputDay < tishri1 + 30) { - hebrewMonth = 1; - hebrewDate = inputDay - tishri1 + 1; - } - else { - hebrewMonth = 2; - hebrewDate = inputDay - tishri1 - 29; - } - return; - } - // We need the length of the year to figure this out,so find Tishri 1 of the next year. - moladHalakim += HALAKIM_PER_LUNAR_CYCLE * mpy[metonicYear]; - moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY); - moladHalakim = moladHalakim % HALAKIM_PER_DAY; - tishri1After = Tishri1((metonicYear + 1) % 19, moladDay, moladHalakim); - } - else { - // It found Tishri 1 at the end of the year. - hebrewYear = metonicCycle * 19 + metonicYear; - if (inputDay >= tishri1 - 177) { - // It is one of the last 6 months of the year. - if (inputDay > tishri1 - 30) { - hebrewMonth = 13; - hebrewDate = inputDay - tishri1 + 30; - } - else if (inputDay > tishri1 - 60) { - hebrewMonth = 12; - hebrewDate = inputDay - tishri1 + 60; - } - else if (inputDay > tishri1 - 89) { - hebrewMonth = 11; - hebrewDate = inputDay - tishri1 + 89; - } - else if (inputDay > tishri1 - 119) { - hebrewMonth = 10; - hebrewDate = inputDay - tishri1 + 119; - } - else if (inputDay > tishri1 - 148) { - hebrewMonth = 9; - hebrewDate = inputDay - tishri1 + 148; - } - else { - hebrewMonth = 8; - hebrewDate = inputDay - tishri1 + 178; - } - return; - } - else { - if (mpy[(hebrewYear - 1) % 19] == 13) { - hebrewMonth = 7; - hebrewDate = inputDay - tishri1 + 207; - if (hebrewDate > 0) - return; - hebrewMonth--; - hebrewDate += 30; - if (hebrewDate > 0) - return; - hebrewMonth--; - hebrewDate += 30; - } - else { - hebrewMonth = 6; - hebrewDate = inputDay - tishri1 + 207; - if (hebrewDate > 0) - return; - hebrewMonth--; - hebrewDate += 30; - } - if (hebrewDate > 0) - return; - hebrewMonth--; - hebrewDate += 29; - if (hebrewDate > 0) - return; - // We need the length of the year to figure this out,so find Tishri 1 of this year. - tishri1After = tishri1; - FindTishriMolad(moladDay - 365); - tishri1 = Tishri1(metonicYear, moladDay, moladHalakim); - } - } - yearLength = tishri1After - tishri1; - moladDay = inputDay - tishri1 - 29; - if (yearLength == 355 || yearLength == 385) { - // Heshvan has 30 days - if (moladDay <= 30) { - hebrewMonth = 2; - hebrewDate = moladDay; - return; - } - moladDay -= 30; - } - else { - // Heshvan has 29 days - if (moladDay <= 29) { - hebrewMonth = 2; - hebrewDate = moladDay; - return; - } - moladDay -= 29; - } - // It has to be Kislev. - hebrewMonth = 3; - hebrewDate = moladDay; - } - function FindTishriMolad(inputDay) { - // Estimate the metonic cycle number. Note that this may be an under - // estimate because there are 6939.6896 days in a metonic cycle not - // 6940,but it will never be an over estimate. The loop below will - // correct for any error in this estimate. - metonicCycle = Math.floor((inputDay + 310) / 6940); - // Calculate the time of the starting molad for this metonic cycle. - MoladOfMetonicCycle(); - // If the above was an under estimate,increment the cycle number until - // the correct one is found. For modern dates this loop is about 98.6% - // likely to not execute,even once,because the above estimate is - // really quite close. - while (moladDay < inputDay - 6940 + 310) { - metonicCycle++; - moladHalakim += HALAKIM_PER_METONIC_CYCLE; - moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY); - moladHalakim = moladHalakim % HALAKIM_PER_DAY; - } - // Find the molad of Tishri closest to this date. - for (metonicYear = 0; metonicYear < 18; metonicYear++) { - if (moladDay > inputDay - 74) - break; - moladHalakim += HALAKIM_PER_LUNAR_CYCLE * mpy[metonicYear]; - moladDay += Math.floor(moladHalakim / HALAKIM_PER_DAY); - moladHalakim = moladHalakim % HALAKIM_PER_DAY; - } - } - function MoladOfMetonicCycle() { - var r1 = void 0, r2 = void 0, d1 = void 0, d2 = void 0; - // Start with the time of the first molad after creation. - r1 = NEW_MOON_OF_CREATION; - // Calculate gMetonicCycle * HALAKIM_PER_METONIC_CYCLE. The upper 32 - // bits of the result will be in r2 and the lower 16 bits will be in r1. - r1 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE & 0xFFFF); - r2 = r1 >> 16; - r2 += metonicCycle * (HALAKIM_PER_METONIC_CYCLE >> 16 & 0xFFFF); - // Calculate r2r1 / HALAKIM_PER_DAY. The remainder will be in r1,the - // upper 16 bits of the quotient will be in d2 and the lower 16 bits - // will be in d1. - d2 = Math.floor(r2 / HALAKIM_PER_DAY); - r2 -= d2 * HALAKIM_PER_DAY; - r1 = r2 << 16 | r1 & 0xFFFF; - d1 = Math.floor(r1 / HALAKIM_PER_DAY); - r1 -= d1 * HALAKIM_PER_DAY; - moladDay = d2 << 16 | d1; - moladHalakim = r1; - } - function Tishri1(metonicYear, moladDay, moladHalakim) { - var tishri1 = moladDay, dow = tishri1 % 7, leapYear = metonicYear == 2 || metonicYear == 5 || metonicYear == 7 || metonicYear == 10 || metonicYear == 13 || metonicYear == 16 || metonicYear == 18, lastWasLeapYear = metonicYear == 3 || metonicYear == 6 || metonicYear == 8 || metonicYear == 11 || metonicYear == 14 || metonicYear == 17 || metonicYear == 0; - // Apply rules 2,3 and 4 - if (moladHalakim >= NOON || !leapYear && dow == TUES && moladHalakim >= AM3_11_20 || lastWasLeapYear && dow == MON && moladHalakim >= AM9_32_43) { - tishri1++; - dow++; - if (dow == 7) - dow = 0; - } - // Apply rule 1 after the others because it can cause an additional delay of one day. - if (dow == WED || dow == FRI || dow == SUN) { - tishri1++; - } - return tishri1; - } - var inputYear = inputDateOrYear; - if ((typeof inputYear === "undefined" ? "undefined" : _typeof(inputYear)) === "object") { - inputMonth = inputDateOrYear.getMonth() + 1; - inputDate = inputDateOrYear.getDate(); - inputYear = inputDateOrYear.getFullYear(); - } - SdnToHebrew(GregorianToSdn(inputYear, inputMonth, inputDate)); - return { - year: hebrewYear, - month: hebrewMonth, - date: hebrewDate, - month_name: hMonth[hebrewMonth - 1] - }; -} - -exports.hebrewDate = hebrewDate; diff --git a/apps/hebrew_calendar/metadata.json b/apps/hebrew_calendar/metadata.json index a2b7932b6..dc10a99f2 100644 --- a/apps/hebrew_calendar/metadata.json +++ b/apps/hebrew_calendar/metadata.json @@ -2,25 +2,19 @@ "id": "hebrew_calendar", "name": "Hebrew Calendar", "shortName": "HebCal", - "version": "0.04", - "description": "lists the date according to the hebrew calendar", + "version": "0.06", + "description": "lists the date & holidays according to the hebrew calendar", "icon": "app.png", "allow_emulator": false, - "tags": "tool,locale", + "tags": "clocks,tools", + "custom": "customizer.html", "supports": [ "BANGLEJS", "BANGLEJS2" ], + "type": "clock", "readme": "README.md", "storage": [ - { - "name": "hebrew_calendar.app.js", - "url": "app.js" - }, - { - "name": "hebrewDate", - "url": "hebrewDate.js" - }, { "name": "hebrew_calendar.img", "url": "app-icon.js", From 7e7ccc3085e314630b5caac3c879ba27d4f09177 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 22 Apr 2022 09:34:23 +0100 Subject: [PATCH 16/78] bump suggested fw version --- loader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader.js b/loader.js index c4553940b..ee7b584a2 100644 --- a/loader.js +++ b/loader.js @@ -16,7 +16,7 @@ if (window.location.host=="banglejs.com") { 'This is not the official Bangle.js App Loader - you can try the Official Version here.'; } -var RECOMMENDED_VERSION = "2v12"; +var RECOMMENDED_VERSION = "2v13"; // could check http://www.espruino.com/json/BANGLEJS.json for this // We're only interested in Bangles From 0239503983f32cde7e1d22b9eb7c212a862f8205 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 22 Apr 2022 21:21:52 +0100 Subject: [PATCH 17/78] Mylocation fixed back button --- apps/mylocation/ChangeLog | 1 + apps/mylocation/metadata.json | 2 +- apps/mylocation/mylocation.app.js | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/mylocation/ChangeLog b/apps/mylocation/ChangeLog index ab8af7620..146e7e277 100644 --- a/apps/mylocation/ChangeLog +++ b/apps/mylocation/ChangeLog @@ -2,3 +2,4 @@ 0.02: Enhanced icon, make it bolder 0.03: Fixed issue with defaulting back to London 0.04: Fixed issue selecting Frankfurt not saved +0.05: Fixed issue with back option diff --git a/apps/mylocation/metadata.json b/apps/mylocation/metadata.json index 9182ba160..e8dc6bb26 100644 --- a/apps/mylocation/metadata.json +++ b/apps/mylocation/metadata.json @@ -4,7 +4,7 @@ "icon": "mylocation.png", "type": "app", "screenshots": [{"url":"screenshot_1.png"}], - "version":"0.04", + "version":"0.05", "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", "readme": "README.md", "tags": "tool,utility", diff --git a/apps/mylocation/mylocation.app.js b/apps/mylocation/mylocation.app.js index b9451e0fb..fd5c9cc6d 100644 --- a/apps/mylocation/mylocation.app.js +++ b/apps/mylocation/mylocation.app.js @@ -55,7 +55,7 @@ function showMainMenu() { //console.log("showMainMenu"); const mainmenu = { '': { 'title': 'My Location' }, - '{ load(); }, + '< Back': ()=>{ load(); }, 'City': { value: 0 | locations.indexOf(s.location), min: 0, max: locations.length - 1, From 21243f5f76abef49a8a32915407beebcd81e970c Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 22 Apr 2022 21:38:11 +0100 Subject: [PATCH 18/78] Flipper fixed dark theme color --- apps/flipper/ChangeLog | 1 + apps/flipper/{flipper.app.js => app.js} | 2 +- apps/flipper/{flipper.png => app.png} | Bin apps/flipper/{flipper.icon.js => icon.js} | 0 apps/flipper/metadata.json | 10 +++++----- 5 files changed, 7 insertions(+), 6 deletions(-) rename apps/flipper/{flipper.app.js => app.js} (95%) rename apps/flipper/{flipper.png => app.png} (100%) rename apps/flipper/{flipper.icon.js => icon.js} (100%) diff --git a/apps/flipper/ChangeLog b/apps/flipper/ChangeLog index 9db0e26c5..2e94a2286 100644 --- a/apps/flipper/ChangeLog +++ b/apps/flipper/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: updated dark theme bg2 color value diff --git a/apps/flipper/flipper.app.js b/apps/flipper/app.js similarity index 95% rename from apps/flipper/flipper.app.js rename to apps/flipper/app.js index 7171306b1..ad5aa383c 100644 --- a/apps/flipper/flipper.app.js +++ b/apps/flipper/app.js @@ -18,7 +18,7 @@ function flipTheme() { if (!g.theme.dark) { upd({ fg:cl("#fff"), bg:cl("#000"), - fg2:cl("#0ff"), bg2:cl("#000"), + fg2:cl("#fff"), bg2:cl("#004"), fgH:cl("#fff"), bgH:cl("#00f"), dark:true }); diff --git a/apps/flipper/flipper.png b/apps/flipper/app.png similarity index 100% rename from apps/flipper/flipper.png rename to apps/flipper/app.png diff --git a/apps/flipper/flipper.icon.js b/apps/flipper/icon.js similarity index 100% rename from apps/flipper/flipper.icon.js rename to apps/flipper/icon.js diff --git a/apps/flipper/metadata.json b/apps/flipper/metadata.json index aac4f1643..45ecf00cc 100644 --- a/apps/flipper/metadata.json +++ b/apps/flipper/metadata.json @@ -2,17 +2,17 @@ { "id": "flipper", "name": "flipper", - "version": "0.01", + "version": "0.02", "description": "Switch between dark and light theme and vice versa, combine with pattern launcher and swipe to flip.", "readme":"README.md", - "screenshots": [{"url":"flipper.png"}], - "icon": "flipper.png", + "screenshots": [{"url":"app.png"}], + "icon": "app.png", "type": "app", "tags": "game", "supports": ["BANGLEJS2"], "allow_emulator": true, "storage": [ - {"name":"flipper.app.js","url":"flipper.app.js"}, - {"name":"flipper.img","url":"flipper.icon.js","evaluate":true} + {"name":"flipper.app.js","url":"app.js"}, + {"name":"flipper.img","url":"icon.js","evaluate":true} ] } From 4d5cc23d44eb23a525179c881a5d72ae0f5b29fd Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 22 Apr 2022 21:59:13 +0100 Subject: [PATCH 19/78] Mylocation - renamed source files to preferred standard --- apps/mylocation/{mylocation.app.js => app.js} | 0 apps/mylocation/{mylocation.png => app.png} | Bin apps/mylocation/{mylocation.icon.js => icon.js} | 0 apps/mylocation/metadata.json | 6 +++--- 4 files changed, 3 insertions(+), 3 deletions(-) rename apps/mylocation/{mylocation.app.js => app.js} (100%) rename apps/mylocation/{mylocation.png => app.png} (100%) rename apps/mylocation/{mylocation.icon.js => icon.js} (100%) diff --git a/apps/mylocation/mylocation.app.js b/apps/mylocation/app.js similarity index 100% rename from apps/mylocation/mylocation.app.js rename to apps/mylocation/app.js diff --git a/apps/mylocation/mylocation.png b/apps/mylocation/app.png similarity index 100% rename from apps/mylocation/mylocation.png rename to apps/mylocation/app.png diff --git a/apps/mylocation/mylocation.icon.js b/apps/mylocation/icon.js similarity index 100% rename from apps/mylocation/mylocation.icon.js rename to apps/mylocation/icon.js diff --git a/apps/mylocation/metadata.json b/apps/mylocation/metadata.json index e8dc6bb26..c2c38b549 100644 --- a/apps/mylocation/metadata.json +++ b/apps/mylocation/metadata.json @@ -1,7 +1,7 @@ { "id": "mylocation", "name": "My Location", "shortName":"My Location", - "icon": "mylocation.png", + "icon": "app.png", "type": "app", "screenshots": [{"url":"screenshot_1.png"}], "version":"0.05", @@ -10,8 +10,8 @@ "tags": "tool,utility", "supports": ["BANGLEJS", "BANGLEJS2"], "storage": [ - {"name":"mylocation.app.js","url":"mylocation.app.js"}, - {"name":"mylocation.img","url":"mylocation.icon.js","evaluate": true } + {"name":"mylocation.app.js","url":"app.js"}, + {"name":"mylocation.img","url":"icon.js","evaluate": true } ], "data": [ {"name":"mylocation.json"} From a1baaceb91588863833e5269684b2cf6974cc958 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Fri, 22 Apr 2022 22:05:29 +0100 Subject: [PATCH 20/78] Mylocation - renamed source files to preferred standard --- apps/mylocation/ChangeLog | 1 + apps/mylocation/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/mylocation/ChangeLog b/apps/mylocation/ChangeLog index 146e7e277..1239554f0 100644 --- a/apps/mylocation/ChangeLog +++ b/apps/mylocation/ChangeLog @@ -3,3 +3,4 @@ 0.03: Fixed issue with defaulting back to London 0.04: Fixed issue selecting Frankfurt not saved 0.05: Fixed issue with back option +0.06: renamed source files to match standard diff --git a/apps/mylocation/metadata.json b/apps/mylocation/metadata.json index c2c38b549..16549b2ba 100644 --- a/apps/mylocation/metadata.json +++ b/apps/mylocation/metadata.json @@ -4,7 +4,7 @@ "icon": "app.png", "type": "app", "screenshots": [{"url":"screenshot_1.png"}], - "version":"0.05", + "version":"0.06", "description": "Sets and stores the lat and long of your preferred City or it can be set from the GPS. mylocation.json can be used by other apps that need your main location lat and lon. See README", "readme": "README.md", "tags": "tool,utility", From 5525d467fcd0ec2bd85582b6e8b957c2a5255cad Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 22 Apr 2022 22:09:47 +0200 Subject: [PATCH 21/78] [Health Tracking] Add LANG placeholder, minor tweaks - Update getSettings() function - Fix some labels - The increment in the daily step goal now is 250 instead of 100 --- apps/health/ChangeLog | 1 + apps/health/app.js | 97 ++++++++++++++++++++++----------------- apps/health/metadata.json | 2 +- 3 files changed, 57 insertions(+), 43 deletions(-) diff --git a/apps/health/ChangeLog b/apps/health/ChangeLog index 7dbb9c458..b5c42b3f6 100644 --- a/apps/health/ChangeLog +++ b/apps/health/ChangeLog @@ -11,3 +11,4 @@ 0.10: Adds additional 3 minute setting for HRM 0.11: Pre-minified boot&lib - folds constants and saves RAM 0.12: Add setting for Daily Step Goal +0.13: Add support for internationalization diff --git a/apps/health/app.js b/apps/health/app.js index e39590e2d..0f372df90 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -1,42 +1,54 @@ function getSettings() { - return require("Storage").readJSON("health.json",1)||{}; + return Object.assign({ + hrm: 0, + stepGoal: 10000 + }, require("Storage").readJSON("health.json", true) || {}); } -function setSettings(healthSettings) { - require("Storage").writeJSON("health.json",healthSettings); +function setSettings(settings) { + require("Storage").writeJSON("health.json", settings); } function menuMain() { swipe_enabled = false; clearButton(); E.showMenu({ - "":{title:"Health Tracking"}, - "< Back":()=>load(), - "Step Counting":()=>menuStepCount(), - "Movement":()=>menuMovement(), - "Heart Rate":()=>menuHRM(), - "Settings":()=>menuSettings() + "": { title: /*LANG*/"Health Tracking" }, + /*LANG*/"< Back": () => load(), + /*LANG*/"Step Counting": () => menuStepCount(), + /*LANG*/"Movement": () => menuMovement(), + /*LANG*/"Heart Rate": () => menuHRM(), + /*LANG*/"Settings": () => menuSettings() }); } function menuSettings() { swipe_enabled = false; clearButton(); - var healthSettings=getSettings(); - //print(healthSettings); + let settings = getSettings(); + E.showMenu({ - "":{title:"Health Tracking"}, - "< Back":()=>menuMain(), - "Heart Rt":{ - value : 0|healthSettings.hrm, - min : 0, max : 3, - format : v=>["Off","3 mins","10 mins","Always"][v], - onchange : v => { healthSettings.hrm=v;setSettings(healthSettings); } + "": { title:/*LANG*/"Health Tracking" }, + /*LANG*/"< Back": () => menuMain(), + /*LANG*/"HRM Interval": { + value: settings.hrm, + min: 0, + max: 3, + format: v => [ /*LANG*/"Off", /*LANG*/"3 min", /*LANG*/"10 min", /*LANG*/"Always"][v], + onchange: v => { + settings.hrm = v; + setSettings(settings); + } }, - "Daily Step Goal":{ - value : (healthSettings.stepGoal ? healthSettings.stepGoal : 10000), - min : 0, max : 20000, step : 100, - onchange : v => { healthSettings.stepGoal=v;setSettings(healthSettings); } + /*LANG*/"Daily Step Goal": { + value: settings.stepGoal, + min: 0, + max: 20000, + step: 250, + onchange: v => { + settings.stepGoal = v; + setSettings(settings); + } } }); } @@ -45,10 +57,10 @@ function menuStepCount() { swipe_enabled = false; clearButton(); E.showMenu({ - "":{title:"Step Counting"}, - "< Back":()=>menuMain(), - "per hour":()=>stepsPerHour(), - "per day":()=>stepsPerDay() + "": { title:/*LANG*/"Steps" }, + /*LANG*/"< Back": () => menuMain(), + /*LANG*/"per hour": () => stepsPerHour(), + /*LANG*/"per day": () => stepsPerDay() }); } @@ -56,10 +68,10 @@ function menuMovement() { swipe_enabled = false; clearButton(); E.showMenu({ - "":{title:"Movement"}, - "< Back":()=>menuMain(), - "per hour":()=>movementPerHour(), - "per day":()=>movementPerDay(), + "": { title:/*LANG*/"Movement" }, + /*LANG*/"< Back": () => menuMain(), + /*LANG*/"per hour": () => movementPerHour(), + /*LANG*/"per day": () => movementPerDay(), }); } @@ -67,17 +79,17 @@ function menuHRM() { swipe_enabled = false; clearButton(); E.showMenu({ - "":{title:"Heart Rate"}, - "< Back":()=>menuMain(), - "per hour":()=>hrmPerHour(), - "per day":()=>hrmPerDay(), + "": { title:/*LANG*/"Heart Rate" }, + /*LANG*/"< Back": () => menuMain(), + /*LANG*/"per hour": () => hrmPerHour(), + /*LANG*/"per day": () => hrmPerDay(), }); } function stepsPerHour() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(24); + let data = new Uint16Array(24); require("health").readDay(new Date(), h=>data[h.hr]+=h.steps); g.clear(1); Bangle.drawWidgets(); @@ -88,7 +100,7 @@ function stepsPerHour() { function stepsPerDay() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(31); + let data = new Uint16Array(31); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps); g.clear(1); Bangle.drawWidgets(); @@ -99,8 +111,8 @@ function stepsPerDay() { function hrmPerHour() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(24); - var cnt = new Uint8Array(23); + let data = new Uint16Array(24); + let cnt = new Uint8Array(23); require("health").readDay(new Date(), h=>{ data[h.hr]+=h.bpm; if (h.bpm) cnt[h.hr]++; @@ -115,8 +127,8 @@ function hrmPerHour() { function hrmPerDay() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(31); - var cnt = new Uint8Array(31); + let data = new Uint16Array(31); + let cnt = new Uint8Array(31); require("health").readDailySummaries(new Date(), h=>{ data[h.day]+=h.bpm; if (h.bpm) cnt[h.day]++; @@ -131,7 +143,7 @@ function hrmPerDay() { function movementPerHour() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(24); + let data = new Uint16Array(24); require("health").readDay(new Date(), h=>data[h.hr]+=h.movement); g.clear(1); Bangle.drawWidgets(); @@ -142,7 +154,7 @@ function movementPerHour() { function movementPerDay() { E.showMessage(/*LANG*/"Loading..."); - var data = new Uint16Array(31); + let data = new Uint16Array(31); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement); g.clear(1); Bangle.drawWidgets(); @@ -260,4 +272,5 @@ function clearButton() { Bangle.loadWidgets(); Bangle.drawWidgets(); + menuMain(); diff --git a/apps/health/metadata.json b/apps/health/metadata.json index 5d096dc07..a452436bb 100644 --- a/apps/health/metadata.json +++ b/apps/health/metadata.json @@ -1,7 +1,7 @@ { "id": "health", "name": "Health Tracking", - "version": "0.12", + "version": "0.13", "description": "Logs health data and provides an app to view it", "icon": "app.png", "tags": "tool,system,health", From 78ec6d34b4fb4f26917e75186b0b16780c07fd39 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Sat, 23 Apr 2022 15:22:01 +0200 Subject: [PATCH 22/78] dragboard v0.05 --- apps/dragboard/ChangeLog | 1 + apps/dragboard/ChangeLog~ | 4 ++++ apps/dragboard/lib.js | 9 +++++---- apps/dragboard/metadata.json | 2 +- apps/dragboard/metadata.json~ | 14 ++++++++++++++ 5 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 apps/dragboard/ChangeLog~ create mode 100644 apps/dragboard/metadata.json~ diff --git a/apps/dragboard/ChangeLog b/apps/dragboard/ChangeLog index 67bc62a4b..48a1ffb03 100644 --- a/apps/dragboard/ChangeLog +++ b/apps/dragboard/ChangeLog @@ -2,3 +2,4 @@ 0.02: Added some missing code. 0.03: Made the code shorter and somewhat more readable by writing some functions. Also made it work as a library where it returns the text once finished. The keyboard is now made to exit correctly when the 'back' event is called. The keyboard now uses theme colors correctly, although it still looks best with dark theme. The numbers row is now solidly green - except for highlights. 0.04: Now displays the opened text string at launch. +0.05: Now scrolls text when string gets longer than screen width. diff --git a/apps/dragboard/ChangeLog~ b/apps/dragboard/ChangeLog~ new file mode 100644 index 000000000..67bc62a4b --- /dev/null +++ b/apps/dragboard/ChangeLog~ @@ -0,0 +1,4 @@ +0.01: New App! +0.02: Added some missing code. +0.03: Made the code shorter and somewhat more readable by writing some functions. Also made it work as a library where it returns the text once finished. The keyboard is now made to exit correctly when the 'back' event is called. The keyboard now uses theme colors correctly, although it still looks best with dark theme. The numbers row is now solidly green - except for highlights. +0.04: Now displays the opened text string at launch. diff --git a/apps/dragboard/lib.js b/apps/dragboard/lib.js index d846055c1..b9b19f982 100644 --- a/apps/dragboard/lib.js +++ b/apps/dragboard/lib.js @@ -49,11 +49,12 @@ exports.input = function(options) { g.setColor(BGCOLOR); g.fillRect(0,4+20,176,13+20); g.setColor(0.2,0,0); - g.fillRect(3,4+20,5+text.length*6,13+20); + var rectLen = text.length<27? text.length*6:27*6; + g.fillRect(3,4+20,5+rectLen,13+20); g.setColor(0.7,0,0); - g.fillRect(text.length*6+5,4+20,10+text.length*6,13+20); + g.fillRect(rectLen+5,4+20,rectLen+10,13+20); g.setColor(1,1,1); - g.drawString(text, 5, 5+20); + g.drawString(text.length<=27? text.substr(-27, 27) : '<- '+text.substr(-24,24), 5, 5+20); } drawAbcRow(); @@ -213,7 +214,7 @@ exports.input = function(options) { // Make a space or backspace by swiping right or left on screen above green rectangle - else { + else if (event.y > 20+4) { if (event.b == 0) { g.setColor(HLCOLOR); if (event.x < g.getWidth()/2) { diff --git a/apps/dragboard/metadata.json b/apps/dragboard/metadata.json index f852a12f5..f9c73ddde 100644 --- a/apps/dragboard/metadata.json +++ b/apps/dragboard/metadata.json @@ -1,6 +1,6 @@ { "id": "dragboard", "name": "Dragboard", - "version":"0.04", + "version":"0.05", "description": "A library for text input via swiping keyboard", "icon": "app.png", "type":"textinput", diff --git a/apps/dragboard/metadata.json~ b/apps/dragboard/metadata.json~ new file mode 100644 index 000000000..f852a12f5 --- /dev/null +++ b/apps/dragboard/metadata.json~ @@ -0,0 +1,14 @@ +{ "id": "dragboard", + "name": "Dragboard", + "version":"0.04", + "description": "A library for text input via swiping keyboard", + "icon": "app.png", + "type":"textinput", + "tags": "keyboard", + "supports" : ["BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"textinput","url":"lib.js"} + ] +} From 37204e9446c109e950786852cfb306cd3d16497f Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Sat, 23 Apr 2022 15:24:08 +0200 Subject: [PATCH 23/78] remove some files --- apps/dragboard/ChangeLog~ | 4 ---- apps/dragboard/metadata.json~ | 14 -------------- 2 files changed, 18 deletions(-) delete mode 100644 apps/dragboard/ChangeLog~ delete mode 100644 apps/dragboard/metadata.json~ diff --git a/apps/dragboard/ChangeLog~ b/apps/dragboard/ChangeLog~ deleted file mode 100644 index 67bc62a4b..000000000 --- a/apps/dragboard/ChangeLog~ +++ /dev/null @@ -1,4 +0,0 @@ -0.01: New App! -0.02: Added some missing code. -0.03: Made the code shorter and somewhat more readable by writing some functions. Also made it work as a library where it returns the text once finished. The keyboard is now made to exit correctly when the 'back' event is called. The keyboard now uses theme colors correctly, although it still looks best with dark theme. The numbers row is now solidly green - except for highlights. -0.04: Now displays the opened text string at launch. diff --git a/apps/dragboard/metadata.json~ b/apps/dragboard/metadata.json~ deleted file mode 100644 index f852a12f5..000000000 --- a/apps/dragboard/metadata.json~ +++ /dev/null @@ -1,14 +0,0 @@ -{ "id": "dragboard", - "name": "Dragboard", - "version":"0.04", - "description": "A library for text input via swiping keyboard", - "icon": "app.png", - "type":"textinput", - "tags": "keyboard", - "supports" : ["BANGLEJS2"], - "screenshots": [{"url":"screenshot.png"}], - "readme": "README.md", - "storage": [ - {"name":"textinput","url":"lib.js"} - ] -} From d55280b94037bcd5f92490c2602fb74d2beb838e Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Sat, 23 Apr 2022 15:28:41 +0200 Subject: [PATCH 24/78] update README.md after v0.05 fixes --- apps/dragboard/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/dragboard/README.md b/apps/dragboard/README.md index 56feaf6a4..91f429a0c 100644 --- a/apps/dragboard/README.md +++ b/apps/dragboard/README.md @@ -10,9 +10,7 @@ The drag in Dragboard is a nod to the javascript 'drag' event, which is used to Known bugs: - Initially developed for use with dark theme set on Bangle.js 2 - that is still the preferred way to view it although it now works with other themes. -- Text does not wrap. +- When doing 'del' on a empty text-string, the letter case is changed. To do: -- Make text wrap and/or scroll up/sideways once available space runs out. -- Optimize code. Further split it up in functions. - Possibly provide a dragboard.settings.js file From e7450f6bc6762bb938c500d309981943c5401402 Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Sat, 23 Apr 2022 15:41:07 +0200 Subject: [PATCH 25/78] adjusted README.md --- apps/dragboard/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dragboard/README.md b/apps/dragboard/README.md index 91f429a0c..8960e5749 100644 --- a/apps/dragboard/README.md +++ b/apps/dragboard/README.md @@ -10,7 +10,7 @@ The drag in Dragboard is a nod to the javascript 'drag' event, which is used to Known bugs: - Initially developed for use with dark theme set on Bangle.js 2 - that is still the preferred way to view it although it now works with other themes. -- When doing 'del' on a empty text-string, the letter case is changed. +- When repeatedly doing 'del' on an empty text-string, the letter case is changed back and forth between upper and lower case. To do: - Possibly provide a dragboard.settings.js file From 8c537c6f7eaef63b8888a570cd52f45b6f00efe5 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sat, 23 Apr 2022 18:42:06 +0200 Subject: [PATCH 26/78] Consider widget field for marker positioning --- apps/kbswipe/ChangeLog | 1 + apps/kbswipe/lib.js | 12 ++++++------ apps/kbswipe/metadata.json | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/kbswipe/ChangeLog b/apps/kbswipe/ChangeLog index 87fb43d3d..533409acc 100644 --- a/apps/kbswipe/ChangeLog +++ b/apps/kbswipe/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Now keeps user input trace intact by changing how the screen is updated. +0.03: Positioning of marker now takes the height of the widget field into account. diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index 7837a6984..48fc8a818 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -54,18 +54,18 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); if (strArr.length == 0) { Rx1 = 4; Rx2 = 6*4; - Ry1 = 8*4; - Ry2 = 8*4 + 3; + Ry1 = 8*4 + R.y; + Ry2 = 8*4 + 3 + R.y; } else if (strArr.length <= 4) { Rx1 = (strArr[strArr.length-1].length)%7*6*4 + 4 ; Rx2 = (strArr[strArr.length-1].length)%7*6*4 + 6*4; - Ry1 = (strArr.length)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4); - Ry2 = (strArr.length)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + 3; + Ry1 = (strArr.length)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + R.y; + Ry2 = (strArr.length)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + 3 + R.y; } else { Rx1 = (strArr[strArr.length-1].length)%7*6*4 + 4 ; Rx2 = (strArr[strArr.length-1].length)%7*6*4 + 6*4; - Ry1 = (4)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4); - Ry2 = (4)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + 3; + Ry1 = (4)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + R.y; + Ry2 = (4)*(8*4) + Math.floor((strArr[strArr.length-1].length)/7)*(8*4) + 3 + R.y; } //print(Rx1,Rx2,Ry1, Ry2); return {x:Rx1,y:Ry1,x2:Rx2,y2:Ry2}; diff --git a/apps/kbswipe/metadata.json b/apps/kbswipe/metadata.json index f1e7cf7d6..c44cde58b 100644 --- a/apps/kbswipe/metadata.json +++ b/apps/kbswipe/metadata.json @@ -1,6 +1,6 @@ { "id": "kbswipe", "name": "Swipe keyboard", - "version":"0.02", + "version":"0.03", "description": "A library for text input via PalmOS style swipe gestures (beta!)", "icon": "app.png", "type":"textinput", From 98f199105ef1442d5a75ea4f88cad8df78107e8a Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:24:43 -0700 Subject: [PATCH 27/78] Update boot.js --- apps/android/boot.js | 52 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/apps/android/boot.js b/apps/android/boot.js index eb3d26c6e..a0d538a4a 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -4,7 +4,33 @@ Bluetooth.println(JSON.stringify(message)); } + function getCurrentTime() { + var time = new Date(); + return ( + time.getHours() * 3600000 + + time.getMinutes() * 60000 + + time.getSeconds() * 1000 + ); + } + + //convert GB DOW format to sched DOW format + function convDow(x) { + //if no DOW selected, set alarm to all DOW + if (x == 0) x = 127; + x = x.toString(2); + for (var i = 0; x.length < 7; i++) { + x = "0"+x; + } + x = x.slice(1, 7) + x.slice(0, 1); + return "0b"+x; + } + var settings = require("Storage").readJSON("android.settings.json",1)||{}; + //default alarm settings + if (settings.rp == undefined) settings.rp = true; + if (settings.as == undefined) settings.as = true; + if (settings.vibrate == undefined) settings.vibrate = ".."; + require('Storage').writeJSON("android.settings.json", settings); var _GB = global.GB; global.GB = (event) => { // feed a copy to other handlers if there were any @@ -44,6 +70,32 @@ title:event.name||"Call", body:"Incoming call\n"+event.number}); require("messages").pushMessage(event); }, + "alarm" : function() { + //wipe existing GB alarms + var gbalarms = require("sched").getAlarms().filter(a=>a.appid=="gbalarms"); + for (i = 0; i < gbalarms.length; i++) { + require("sched").setAlarm(gbalarms[i].id, undefined); + } + var alarms = require("sched").getAlarms(); + for (j = 0; j < event.d.length; j++) { + //prevents all alarms from going off at once?? + var last = (event.d[j].h * 3600000 + event.d[j].m * 60000 < getCurrentTime()) ? (new Date()).getDate() : 0; + var a = { + id : "gb"+j, + appid : "gbalarms", + on : true, + t : event.d[j].h * 3600000 + event.d[j].m * 60000, + dow : convDow(event.d[j].rep), + last : last, + rp : settings.rp, + as : settings.as, + vibrate : settings.vibrate + }; + alarms.push(a); + } + require("sched").setAlarms(alarms); + require("sched").reload(); + }, }; var h = HANDLERS[event.t]; if (h) h(); else console.log("GB Unknown",event); From 9df3354a49fcbe47d2591317b7ffbbaa07fea8df Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:25:03 -0700 Subject: [PATCH 28/78] Update settings.js --- apps/android/settings.js | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/apps/android/settings.js b/apps/android/settings.js index 7c46a1fc0..bfb1cd096 100644 --- a/apps/android/settings.js +++ b/apps/android/settings.js @@ -24,7 +24,28 @@ updateSettings(); } }, - /*LANG*/"Messages" : ()=>load("messages.app.js") + /*LANG*/"Messages" : ()=>load("messages.app.js"), + /*LANG*/"Alarms" : () => E.showMenu({ + "" : { "title" : "Find Phone" }, + "< Back" : ()=>E.showMenu(mainmenu), + /*LANG*/"Vibrate": require("buzz_menu").pattern(settings.vibrate, v => {settings.vibrate = v; updateSettings();}), + /*LANG*/"Repeat": { + value: settings.rp, + format : v=>v?/*LANG*/"Yes":/*LANG*/"No", + onchange: v => { + settings.rp = v; + updateSettings(); + } + }, + /*LANG*/"Auto snooze": { + value: settings.as, + format : v=>v?/*LANG*/"Yes":/*LANG*/"No", + onchange: v => { + settings.as = v; + updateSettings(); + } + }, + }) }; E.showMenu(mainmenu); }) From 6c5ab23c9db980f3c83f05d4e821fb63398ea87e Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:25:20 -0700 Subject: [PATCH 29/78] Update ChangeLog --- apps/android/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index 59cb23a46..96b50c3a0 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -6,3 +6,4 @@ 0.05: Fix handling of message actions 0.06: Option to keep messages after a disconnect (default false) (fix #1186) 0.07: Include charging state in battery updates to phone +0.08: Handling of alarms From bbd90e08698f4e6da5d38dc919b5b16b07223675 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:25:39 -0700 Subject: [PATCH 30/78] Update metadata.json --- apps/android/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/android/metadata.json b/apps/android/metadata.json index d126b869a..203cd18b1 100644 --- a/apps/android/metadata.json +++ b/apps/android/metadata.json @@ -2,7 +2,7 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.07", + "version": "0.08", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications,gadgetbridge", From d5489c7fef847ba2fb7bf34c6b9c27ade6303342 Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:26:39 -0700 Subject: [PATCH 31/78] Update README.md --- apps/android/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/android/README.md b/apps/android/README.md index c10718aac..580eeec9a 100644 --- a/apps/android/README.md +++ b/apps/android/README.md @@ -21,6 +21,7 @@ of Gadgetbridge - making your phone make noise so you can find it. * `Keep Msgs` - default is `Off`. When Gadgetbridge disconnects, should Bangle.js keep any messages it has received, or should it delete them? * `Messages` - launches the messages app, showing a list of messages +* `Alarms` - opens a submenu where you can set default settings for alarms such as vibration pattern, repeat, and auto snooze ## How it works From d41284222074ef7fcf4b86f838453d8ee3d32dad Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:46:21 -0700 Subject: [PATCH 32/78] Create lib.js --- apps/tapkb/lib.js | 168 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) create mode 100644 apps/tapkb/lib.js diff --git a/apps/tapkb/lib.js b/apps/tapkb/lib.js new file mode 100644 index 000000000..24c52154f --- /dev/null +++ b/apps/tapkb/lib.js @@ -0,0 +1,168 @@ +exports.input = function(options) { + options = options||{}; + var text = options.text; + if ("string"!=typeof text) text=""; + +var layer = 0; +var caps = 0; + +class keyPad { + constructor(x1, y1, x2, y2, func) { + this.x1 = x1; + this.y1 = y1; + this.x2 = x2; + this.y2 = y2; + this.func = !func ? "" : func; + } + get funcName() { + this.func = func; + } + set funcName(a) { + this.func = a; + } + + draw() { + g.setColor(g.theme.fg).drawRect(this.x1, this.y1, this.x2, this.y2).clearRect(this.x1+1, this.y1+1, this.x2-1, this.y2-1).setFont("6x8",2).setFontAlign(0, 0, 0).drawString(this.func, (((this.x2-this.x1)/2)+this.x1), (((this.y2-this.y1)/2)+this.y1)); + } + + onTouch(xy) { + if (this.func == "space") text += " "; + else if (this.func == "<-") text = text.slice(0, -1); + else if (this.func == "new\nline") text += String.fromCharCode(182); + else if (this.func == "caps") { + caps = 1; + renderKeys(); + } + else if (this.func == "Caps") { + caps = 2; + renderKeys(); + } + else if (this.func == "CAPS") { + caps = 0; + renderKeys(); + } + else { + text += this.func; + if (caps == 1) caps = 0; + } + g.clearRect(25, 0, g.getWidth(), 25).setFontAlign(-1, -1).drawString(text.substring(text.length-12, text.length)+"_", 25, 7); + } +} + +function renderKeys() { + var a; + var i; + if (layer == 0) { + if (caps == 0) { + a = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "caps", "space", "<-"]; + } + else a = ["A", "B", "C", "D", "E", "F", "G", "H", "I", "Caps", "space", "<-"]; + if (caps == 2) a[9] = "CAPS"; + for (i = 0; i < a.length; i++) { + pad[i].funcName = a[i]; + } + } + else if (layer == 1) { + if (caps == 0) { + a = ["j", "k", "l", "m", "n", "o", "p", "q", "r", "caps", "space", "<-"]; + } + else a = ["J", "K", "L", "M", "N", "O", "P", "Q", "R", "Caps", "space", "<-"]; + if (caps == 2) a[9] = "CAPS"; + for (i = 0; i < a.length; i++) { + pad[i].funcName = a[i]; + } + } + else if (layer == 2) { + if (caps == 0) { + a = ["s", "t", "u", "v", "w", "x", "y", "z", "0", "caps", "space", "<-"]; + } + else a = ["S", "T", "U", "V", "W", "X", "Y", "Z", "0", "Caps", "space", "<-"]; + if (caps == 2) a[9] = "CAPS"; + for (i = 0; i < a.length; i++) { + pad[i].funcName = a[i]; + } + } + else if (layer == 3) { + if (caps == 0) { + a = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "caps", "space", "<-"]; + } + else a = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "Caps", "space", "<-"]; + if (caps == 2) a[9] = "CAPS"; + for (i = 0; i < a.length; i++) { + pad[i].funcName = a[i]; + } + } + else if (layer == 4) { + if (caps == 0) { + a = [".", ",", "?", "!", "(", ")", "-", "\'", "new\nline", "caps", "space", "<-"]; + } + else a = ["-", "+", "/", "*", ":", "#", "$", "%", "new\nline", "Caps", "space", "<-"]; + if (caps == 2) a[9] = "CAPS"; + for (i = 0; i < a.length; i++) { + pad[i].funcName = a[i]; + } + } + + for (var j = 0; j < pad.length; j++) { + pad[j].draw(); + } +} + +var pad = []; +pad[0] = new keyPad(0, 29, 57, 64); +pad[1] = new keyPad(59, 29, 116, 64); +pad[2] = new keyPad(118, 29, 175, 64); +pad[3] = new keyPad(0, 66, 57, 101); +pad[4] = new keyPad(59, 66, 116, 101); +pad[5] = new keyPad(118, 66, 175, 101); +pad[6] = new keyPad(0, 103, 57, 138); +pad[7] = new keyPad(59, 103, 116, 138); +pad[8] = new keyPad(118, 103, 175, 138); +pad[9] = new keyPad(0, 140, 57, 175); +pad[10] = new keyPad(59, 140, 116, 175); +pad[11] = new keyPad(118, 140, 175, 175); +g.clear(); +renderKeys(); + +var drag; +var e; + +return new Promise((resolve,reject) => { + + Bangle.setUI({mode:"custom", drag:e=>{ + if (!drag) { // start dragging + drag = {x: e.x, y: e.y}; + } + else if (!e.b) { // released + const dx = e.x-drag.x, dy = e.y-drag.y; + drag = null; + //horizontal swipes + if (Math.abs(dx)>Math.abs(dy)+10) { + //swipe left + if (dx<0) layer == 4 ? layer = 0 : layer++; + //swipe right + if (dx>0) layer == 0 ? layer = 4 : layer--; + } + } + renderKeys(); + },touch:(button, xy)=>{ + for (var i = 0; i < pad.length; i++) { + if ((xy.x >= pad[i].x1) && (xy.x <= pad[i].x2) && (xy.y >= pad[i].y1) && (xy.y <= pad[i].y2)) { + pad[i].onTouch(xy); + i = pad.length; + } + } + },back:()=>{ + Bangle.setUI(); + g.clear(); + resolve(text.replace(new RegExp(String.fromCharCode(182), 'g'), '\n')); + }}); + g.clearRect(25, 0, g.getWidth(), 25).setColor(g.theme.fg).setFont("6x8", 2); + if (text == "") g.setFontAlign(0, -1).drawString("<-Swipe->", g.getWidth()/2, 7); + else { + text = text.replace(/\n/g, String.fromCharCode(182)); + g.setFontAlign(-1, -1).drawString(text.substring(text.length-12, text.length)+"_", 25, 7); + } +}); + +}; From 7a0d47b4d8ce83f467dcd8d21c26ee52f1d71c2a Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:46:44 -0700 Subject: [PATCH 33/78] Add files via upload --- apps/tapkb/ChangeLog | 1 + apps/tapkb/README.md | 4 ++++ apps/tapkb/app-icon.js | 1 + apps/tapkb/app.png | Bin 0 -> 678 bytes apps/tapkb/metadata.json | 15 +++++++++++++++ apps/tapkb/screenshot.png | Bin 0 -> 2589 bytes 6 files changed, 21 insertions(+) create mode 100644 apps/tapkb/ChangeLog create mode 100644 apps/tapkb/README.md create mode 100644 apps/tapkb/app-icon.js create mode 100644 apps/tapkb/app.png create mode 100644 apps/tapkb/metadata.json create mode 100644 apps/tapkb/screenshot.png diff --git a/apps/tapkb/ChangeLog b/apps/tapkb/ChangeLog new file mode 100644 index 000000000..624f1b0fb --- /dev/null +++ b/apps/tapkb/ChangeLog @@ -0,0 +1 @@ +0.01: Initial version \ No newline at end of file diff --git a/apps/tapkb/README.md b/apps/tapkb/README.md new file mode 100644 index 000000000..8fc7cece0 --- /dev/null +++ b/apps/tapkb/README.md @@ -0,0 +1,4 @@ +# Usage + +* Swipe left or right to cycle between the alphabet, numerals, and symbols. +* "New line" is represented by paragraph symbols (¶). When you hit the back button, these symbols will be converted into newline. \ No newline at end of file diff --git a/apps/tapkb/app-icon.js b/apps/tapkb/app-icon.js new file mode 100644 index 000000000..c2b495917 --- /dev/null +++ b/apps/tapkb/app-icon.js @@ -0,0 +1 @@ +atob("MDCBAf////////////////AAAAAAD8AAAAAAA4AAAAAAAYAAAAAAAQf/////4A//////8A//////8A//////8A//////8A//////8A///8P/8A///8P/8A///8P/8A///8P/8A///8P/8A///8P/8A///8P//w///8P//w///8MP/w///8MP/w///8MMPw///8MMPw///8AMMA///8AAMA///8AAAA///8AAAA///8OAAA///8P+AA//wcP/8Af/AEP/8IA+AAP/8IA+AAP/8MA+DAP/8PA+BgP/8P//B4P/8P//g8P/8P//wfP/8P//4Pv/8P//8H//8P//8D//8P//+D//8P///B//4P///gAAAf///wAAAf///4AAA////8AADw==") \ No newline at end of file diff --git a/apps/tapkb/app.png b/apps/tapkb/app.png new file mode 100644 index 0000000000000000000000000000000000000000..2b01ad28042e192524bee3c2cddf89ef958086bd GIT binary patch literal 678 zcmV;X0$KfuP)Dw!Y7&dt$lmS}_w#N8_rP$=?CkSC&&=%1 z&U=i|E*!&s^sv;j(!)I*%@RI=J1r2Ix7?02|HEn$A2)$8ZH6tTY?&s^`FQ0E?8lh) zU<^~3)vxs~%qJ?RhNCeT4(Qj~gM~z8n|eNpG5uN>I?+WOok6QAh(5jDVX3GKtKPu) z0An>WRagB8j0_ALBLl<6AXlNf(6@SxMxX{%+8;(E&>(V+%xDBEU>>hZJeM4q)H$;$ zBpP_FJ-j58QoitD;XvmHBb~?>Fo9r&c@mt#@iYL*J^;U?!QcsF6jR& zXcMm26u5Q+gw5wmg7_EaFrR+>;63Z#8gcVjDgrg8je=tSQMkiH8Z!CzX}1fJ4$> zsCAc_CJn%u2E{+e+NKQc;OdTmS$7 M07*qoM6N<$f}npf`2YX_ literal 0 HcmV?d00001 diff --git a/apps/tapkb/metadata.json b/apps/tapkb/metadata.json new file mode 100644 index 000000000..c450f3d47 --- /dev/null +++ b/apps/tapkb/metadata.json @@ -0,0 +1,15 @@ +{ + "id": "tapkb", + "name": "Tap keyboard", + "version":"0.01", + "description": "An onscreen tap keyboard.", + "icon": "app.png", + "type":"textinput", + "tags": "keyboard", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "screenshots": [{"url":"screenshot.png"}], + "storage": [ + {"name":"textinput","url":"lib.js"} + ] +} \ No newline at end of file diff --git a/apps/tapkb/screenshot.png b/apps/tapkb/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..bd1caed380d80e350f8ec523e85adebf0355864e GIT binary patch literal 2589 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 literal 0 HcmV?d00001 From 033a2a4f6e24cc81c4f36a29b5619f4250292c3b Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:47:55 -0700 Subject: [PATCH 34/78] Update README.md --- apps/tapkb/README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/tapkb/README.md b/apps/tapkb/README.md index 8fc7cece0..4f49b1494 100644 --- a/apps/tapkb/README.md +++ b/apps/tapkb/README.md @@ -1,4 +1,7 @@ -# Usage +# Tap Keyboard +This was originally designed for the Noteify app. With the new keyboard system in place, it has become its own keyboard app. +## Usage * Swipe left or right to cycle between the alphabet, numerals, and symbols. -* "New line" is represented by paragraph symbols (¶). When you hit the back button, these symbols will be converted into newline. \ No newline at end of file +* Hitting "caps" once will capitalize one character only. Hitting "caps" twice activates caps lock, and all subsequent characters will be capitalized until you hit "caps" again. +* "New line" is represented by a pilcrow (¶). When you hit the back button, these symbols will be converted into newline. From 9cbe9ed4ccd1784eda62b10fdd7167f1d509128b Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:57:51 -0700 Subject: [PATCH 35/78] Create app.js --- apps/mtnclock/app.js | 350 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 350 insertions(+) create mode 100644 apps/mtnclock/app.js diff --git a/apps/mtnclock/app.js b/apps/mtnclock/app.js new file mode 100644 index 000000000..28ba25882 --- /dev/null +++ b/apps/mtnclock/app.js @@ -0,0 +1,350 @@ +var data = require("Storage").readJSON("mtnclock.json", 1) || {}; + +//seeded RNG to generate stars, snow, etc +function sfc32(a, b, c, d) { + return function() { + a >>>= 0; b >>>= 0; c >>>= 0; d >>>= 0; + var t = (a + b) | 0; + a = b ^ b >>> 9; + b = c + (c << 3) | 0; + c = (c << 21 | c >>> 11); + d = d + 1 | 0; + t = t + d | 0; + c = c + t | 0; + return (t >>> 0) / 4294967296; + }; +} + +//scale x, y coords to screen +function px(x) { + return x*g.getWidth()/100; +} + +function py(y) { + return y*g.getHeight()/100; +} + +function drawMtn(color, coord, dimen) { + //scale mountains to different sizes + g.setColor(color.mtn1).fillPoly([ + coord.x,coord.y, + coord.x,coord.y+dimen.h, + coord.x-dimen.w/2,coord.y+dimen.h + ]); + g.setColor(color.mtn2).fillPoly([ + coord.x,coord.y, + coord.x,coord.y+dimen.h, + coord.x+dimen.w/2,coord.y+dimen.h + ]); +} + +function drawTree(color, coord, dimen) { + //scale trees to different sizes + g.setColor(color.tree1).fillPoly([ + coord.x,coord.y, + coord.x-dimen.w/5,coord.y+dimen.h/4, + coord.x-dimen.w/12,coord.y+dimen.h/4, + coord.x-dimen.w/2.8,coord.y+1.95*dimen.h/4, + coord.x-dimen.w/8,coord.y+1.95*dimen.h/4, + coord.x-dimen.w/2,coord.y+3*dimen.h/4, + coord.x,coord.y+3*dimen.h/4 + ]); + g.setColor(color.tree2).fillPoly([ + coord.x,coord.y, + coord.x+dimen.w/5,coord.y+dimen.h/4, + coord.x+dimen.w/12,coord.y+dimen.h/4, + coord.x+dimen.w/2.8,coord.y+1.95*dimen.h/4, + coord.x+dimen.w/8,coord.y+1.95*dimen.h/4, + coord.x+dimen.w/2,coord.y+3*dimen.h/4, + coord.x,coord.y+3*dimen.h/4 + ]); + g.setColor(color.tree3).fillRect( + coord.x-dimen.w/12,coord.y+3*dimen.h/4, + coord.x+dimen.w/12,coord.y+dimen.h + ); +} + +function drawSnow(color, coord, size) { + g.setColor(color).drawLine(coord.x-px(size),coord.y-py(size),coord.x+px(size),coord.y+py(size)); + g.drawLine(coord.x-px(size),coord.y+py(size),coord.x+px(size),coord.y-py(size)); + g.drawLine(coord.x,coord.y+py(size),coord.x,coord.y-py(size)); + g.drawLine(coord.x-px(size),coord.y,coord.x+px(size),coord.y); +} + +function draw(color) { + +var seed; +var rand; + +g.clear(); +//background + g.setColor(color.bg1).fillRect( + px(0),py(0), + px(100),py(45) + ); + g.setColor(color.bg2).fillRect( + px(0),py(45), + px(100),py(100) + ); + //lightning + if (color.ltn) { + g.setColor(color.ltn).fillPoly([ + px(70),py(20), + px(60),py(28), + px(71),py(29), + px(63),py(40), + px(75),py(28), + px(64),py(27) + ]); + g.fillPoly([ + px(40),py(20), + px(30),py(28), + px(41),py(29), + px(33),py(40), + px(45),py(28), + px(34),py(27) + ]); + } + //stars + if (color.star) { + seed = 4; + rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); + for (let i = 0; i < 40; i++) { + g.setColor(color.star).drawCircle(Math.floor(rand() * px(100)),Math.floor(rand() * py(33)),Math.floor(rand() * 2)); + } + } + //birds + if (color.bird) { + g.setColor(color.bird).fillCircle(px(17),py(12),px(5)).fillCircle(px(23),py(10),px(5)); + g.setColor(color.bg1).fillCircle(px(18),py(15),px(6)).fillCircle(px(24),py(13),px(6)); + g.setColor(color.bird).fillCircle(px(28),py(19),px(4)).fillCircle(px(33),py(19),px(4)); + g.setColor(color.bg1).fillCircle(px(28),py(21),px(5)).fillCircle(px(34),py(21),px(5)); + } + //sun/moon + if (color.sun) g.setColor(color.sun).fillCircle(px(65), py(22), py(20)); + //path + g.setColor(color.path).fillPoly([ + px(60),py(44), + px(39),py(55), + px(72),py(57), + px(30),py(100), + px(70),py(100), + px(78),py(55), + px(46),py(53) + ]); + //fog + if (color.fog) { + g.setColor(color.fog); + for (let i = 1; i <= 47; i = i+2) { + g.drawLine(px(0),py(i),px(100),py(i)); + } + } + //rain + if (color.rain1) { + g.setColor(color.rain1); + for (let i = 0; i <= 6; i++) { + g.drawLine(px(6+i*20),py(20),px(-14+i*20),py(45)); + } + if (color.rain2) { + for (let i = 0; i <= 6; i++) { + g.drawLine(px(16+i*20),py(20),px(-4+i*20),py(45)); + } + } + } + //snow + if (color.snow) { + seed = 11; + rand = sfc32(0x9E3779B9, 0x243F6A88, 0xB7E15162, seed); + for (let i = 0; i < 30; i++) { + drawSnow(color.snow, {x:Math.floor(rand() * px(100)), y:(Math.floor(rand() * py(25))+py(20))}, Math.floor(rand() * 3)); + } + } + //mountains + drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(35), y:py(30)}, {w:px(38), h:py(17)}); + drawMtn({mtn1:color.mtn2, mtn2:color.mtn1}, {x:px(10), y:py(20)}, {w:px(50), h:py(30)}); + drawMtn({mtn1:color.mtn1, mtn2:color.mtn2}, {x:px(90), y:py(20)}, {w:px(70), h:py(30)}); + //lake + g.setColor(color.lake).fillEllipse(px(-15), py(52), px(30), py(57)); + //trees + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(12),y:py(52)}, {w:px(13),h:py(13)}); + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(48),y:py(52)}, {w:px(13),h:py(13)}); + drawTree({tree1:color.tree2, tree2:color.tree1, tree3:color.tree3}, {x:px(34),y:py(46)}, {w:px(6),h:py(6)}); + drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(70),y:py(46)}, {w:px(6),h:py(6)}); + drawTree({tree1:color.tree1, tree2:color.tree2, tree3:color.tree3}, {x:px(90),y:py(52)}, {w:px(13),h:py(13)}); + //clouds + if (color.cloud1) { + g.setColor(color.cloud1); + if (color.cloud2) g.fillRect(0, 0, px(100), py(10)); + g.fillCircle(px(3), py(12), py(4)); + g.fillCircle(px(10), py(12), py(5)); + g.fillCircle(px(16), py(11), py(6)); + g.fillCircle(px(24), py(10), py(8)); + g.fillCircle(px(30), py(11), py(6)); + g.fillCircle(px(35), py(12), py(5)); + g.fillCircle(px(40), py(12), py(6)); + g.fillCircle(px(48), py(13), py(5)); + g.fillCircle(px(55), py(14), py(5)); + g.fillCircle(px(60), py(12), py(5)); + g.fillCircle(px(65), py(11), py(6)); + g.fillCircle(px(75), py(10), py(8)); + g.fillCircle(px(85), py(11), py(6)); + g.fillCircle(px(90), py(12), py(5)); + g.fillCircle(px(97), py(13), py(4)); + } + + //clock text + (color.clock == undefined) ? g.setColor(0xFFFF) : g.setColor(color.clock); + g.setFont("Vector", py(20)).setFontAlign(-1, -1).drawString((require("locale").time(new Date(), 1).replace(" ", "")), px(2), py(67)); + g.setFont("Vector", py(10)).drawString(require('locale').dow(new Date(), 1)+" "+new Date().getDate()+" "+require('locale').month(new Date(), 1)+((data.temp == undefined) ? "" : " | "+require('locale').temp(Math.round(data.temp-273.15)).replace(".0", "")), px(2), py(87)); +} + +var i = 0; + +function setWeather() { + var a = {}; + //clear day/night is default weather + if ((data.code >= 800 && data.code <=802) || data.code == undefined) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-clear + a = { + bg1:0x4FFF, bg2:0x03E0, + sun:0xFD20, + path:0x8200, + mtn1:0x045f, mtn2:0x000F, + lake:0x000F, + tree1:0x07E0, tree2:0, tree3:0x7BE0, + bird:0xFFFF + }; + //day-cloudy + if (data.code == 801 || data.code == 802) a.cloud1 = 0xFFFF; + } + else { + //night-clear + a = { + bg1:0, bg2:0x0005, + sun:0xC618, + path:0, + mtn1:0x0210, mtn2:0x0010, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + star:0xFFFF + }; + //night-cloudy + if (data.code == 801 || data.code == 802) a.cloud1 = 0x4208; + } + } + else if (((data.code >= 300) && (data.code < 600)) || ((data.code >= 200) && (data.code < 300)) || data.code == 803 || data.code == 804) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-overcast + a = { + bg1:0xC618, bg2:0x0200, + path:0x3000, + mtn1:0x3B38, mtn2:0x0005, + lake:0x000F, + tree1:0x03E0, tree2:0, tree3:0x59E0, + cloud1:0x7BEF, cloud2:1 + }; + //day-lightning + if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; + //day-drizzle + if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xFFFF; + //day-rain + if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) a.rain2 = 1; + } + else { + //night-overcast + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + cloud1:0x4208, cloud2:1 + }; + //night-lightning + if (data.code >= 200 && data.code < 300) a.ltn = 0xFFFF; + //night-drizzle + if ((data.code >= 300 && data.code < 600) || (data.code >= 200 && data.code <= 202) || (data.code >= 230 && data.code <= 232)) a.rain1 = 0xC618; + //night-rain + if ((data.code >= 500 && data.code < 600) || (data.code >= 200 && data.code <= 202)) rain2 = 1; + } + } + else if ((data.code >= 700) && (data.code < 800)) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-fog + a = { + bg1:0xC618, bg2:0x0200, + path:0x3000, + mtn1:0x3B38, mtn2:0x0005, + lake:0x000F, + tree1:0x03E0, tree2:0, tree3:0x59E0, + fog:0xFFFF + }; + } + else { + //night-fog + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x0200, tree2:0, tree3:0x59E0, + fog:0x7BEF + }; + } + } + else if ((data.code >= 600) && (data.code < 700)) { + if (new Date().getHours() >= 7 && new Date().getHours() <= 19) { + //day-snow + a = { + bg1:0, bg2:0x7BEF, + path:0xC618, + mtn1:0xFFFF, mtn2:0x7BEF, + lake:0x07FF, + tree1:0xC618, tree2:0xC618, tree3:0x59E0, + cloud1:0x7BEF, cloud2:1, + snow:0xFFFF, + clock: 0 + }; + } + else { + //night-snow + a = { + bg1:0, bg2:0x0005, + path:0, + mtn1:0x0010, mtn2:0x000F, + lake:0x000F, + tree1:0x39E7, tree2:0x39E7, tree3:0x59E0, + cloud1:0x4208, cloud2:1, + snow:0xFFFF + }; + } + } + draw(a); +} + +const _GB = global.GB; +global.GB = (event) => { + if (event.t==="weather") { + data = event; + require("Storage").write('mtnclock.json', event); + setWeather(); + } + if (_GB) setTimeout(_GB, 0, event); +}; + +var drawTimeout; + +//update watchface in next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + setWeather(); + queueDraw(); + }, 60000 - (Date.now() % 60000)); +} + +queueDraw(); +setWeather(); +Bangle.setUI("clock"); From 4fb46cb3670bc091487c3ce4ec5335b59e90e7bd Mon Sep 17 00:00:00 2001 From: frigis1 <63980066+frigis1@users.noreply.github.com> Date: Sun, 24 Apr 2022 00:58:14 -0700 Subject: [PATCH 36/78] Add files via upload --- apps/mtnclock/README.md | 21 +++++++++++++++++++++ apps/mtnclock/app-icon.js | 1 + apps/mtnclock/app.png | Bin 0 -> 2212 bytes apps/mtnclock/metadata.json | 25 +++++++++++++++++++++++++ apps/mtnclock/screenshot1.png | Bin 0 -> 4350 bytes apps/mtnclock/screenshot2.png | Bin 0 -> 3856 bytes apps/mtnclock/screenshot3.png | Bin 0 -> 3602 bytes apps/mtnclock/screenshot4.png | Bin 0 -> 3623 bytes apps/mtnclock/screenshot5.png | Bin 0 -> 3427 bytes 9 files changed, 47 insertions(+) create mode 100644 apps/mtnclock/README.md create mode 100644 apps/mtnclock/app-icon.js create mode 100644 apps/mtnclock/app.png create mode 100644 apps/mtnclock/metadata.json create mode 100644 apps/mtnclock/screenshot1.png create mode 100644 apps/mtnclock/screenshot2.png create mode 100644 apps/mtnclock/screenshot3.png create mode 100644 apps/mtnclock/screenshot4.png create mode 100644 apps/mtnclock/screenshot5.png diff --git a/apps/mtnclock/README.md b/apps/mtnclock/README.md new file mode 100644 index 000000000..58538509d --- /dev/null +++ b/apps/mtnclock/README.md @@ -0,0 +1,21 @@ +# Mountain Pass Clock + +Based on the Pebble watchface Weather Land. + +Mountain Pass Clock changes depending on time (day/night) and weather conditions. + +This clock requires Gadgetbridge and an app that Gadgetbridge can use to get the current weather from OpenWeatherMap (e.g. Weather Notification). To set up Gadgetbridge and weather, see https://codeberg.org/Freeyourgadget/Gadgetbridge/wiki/Weather. + +The scene will change according to the following OpenWeatherMap conditions: clear, cloudy, overcast, lightning, drizzle, rain, fog and snow. Each weather condition has night/day scenes. + +If you choose not to set up weather (or are not connected to Gadgetbridge, for that matter), this clock will default to clear weather, and the scenery will still change from night to day. + +Special thanks to Serj for testing this on the original Bangle. + +## Images + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) +![](screenshot4.png) +![](screenshot5.png) diff --git a/apps/mtnclock/app-icon.js b/apps/mtnclock/app-icon.js new file mode 100644 index 000000000..8324c248a --- /dev/null +++ b/apps/mtnclock/app-icon.js @@ -0,0 +1 @@ +atob("MDCEBVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVUAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVAABVVVVVVVVVVVVVVVVVVVVVVVVVVVVQAzAFVVVVVVVVVVVVVVVVVVVVVVVVVVVQLzIFVVVVVVAFVVVVVVVVVVVVVVVVVVUB//MQVVVVVQAQVVVVVVVVVVVVVVVVVVAB8RMQBVVVVQIwBVVVVVVVVVVVVVVVVQAQAAABAFVVUB8zAFVVVVVVVVVVVVVVVQExAiAYEFVVAD/zIFVVVVVVVVVVVVVVUBMzgzg4gQVQAvMvMAVVVVVVVVVVVVVVAIMzMzM4iABQACABAABVVVVVVVVVVVVQAjMzMzMziCABgQAQAiAFVVVVVVVVVVVQEzMzMzMzOIECMyIyKIEFVVVVVVVVVVUBMzMzMzMzM4gQIzMzM4gQVVVVVVVVVVAIMzMzMzMzM4iACDMzM4iABVVVVVVVVQAjMzMzMzMzMziCATMzMziCAFVVVVVVVQEzMzMzMzMzMzOIECMzMzOIEFVVVVVVUBMzMzMzMzMzMzM4gQIzMzM4gQVVVVVVAIMiMzMzMzMzMiM4iACDMzMiiABVVVVQAjIAIzMzMzMzIAIziCATMzIAKCAFVVVQE4AACDMzMzM4AACDOIECM4AACIEFVVUAERAiARERERERAiAREREAERAiAREAVVUAAAEyEAAAAAAAEyEAAAAAAAEyEAAAVVVVUBMzIQVVVVUBMzIQVVVVUBMzIQVVVVVVABEREQBVVVABEREQBVVVABEREQBVVVVVAAAAAABVVVAAAAAABVVVAAAAAABVVVVVUGIiJgVVVVUGIiJgVVVVUGIiJgVVVVVVACIiIgBVVVACIiIgBVVVACIiIgBVVVVQAiIiInAFVQAiIiInAFVQAiIiInAFVVVQEiIiInYFVQEiIiInYFVQEiIiInYFVVUAAAAAAAAAUAAAAAAAAAUAAAAAAAAAVVVVAHd3dwBVVVAHd3dwBVVVAHd3dwBVVVVQB3d3d3AFVQB3d3d3AFVQB3d3d3AFVVVQYiIiInYFVQYiIiInYFVQYiIiInYFVVUAIiIiIicAUAIiIiIicAUAIiIiIicAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAARAAAAUAAAARAAAAUAAAARAAAAVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEBVVVVVVVBEBVVVVVVVBEBVVVVVVVVVBEAFVVVVVVBEBVVVVVVQBEBVVVVVVVVVAAAAAAAAVVBEBVUAAAAAAABVVVVVVVUAASM/MyIQAAAAAAABIjPzMhAAVVVVVVABP///////MyIiIjP///////MQBVVVVQE////////////////////////zEFVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVQ==") \ No newline at end of file diff --git a/apps/mtnclock/app.png b/apps/mtnclock/app.png new file mode 100644 index 0000000000000000000000000000000000000000..08330429484759d65cf2e89d392799b7be063064 GIT binary patch literal 2212 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 literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot2.png b/apps/mtnclock/screenshot2.png new file mode 100644 index 0000000000000000000000000000000000000000..730edbab5a618d7d98524656b7445cc56dbcb645 GIT binary patch literal 3856 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 Y0dz>%728&#g8%>k07*qoM6N<$f(O|K)&Kwi literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot4.png b/apps/mtnclock/screenshot4.png new file mode 100644 index 0000000000000000000000000000000000000000..8f2e1de907117a4378c87de973aa09711961a6ef GIT binary patch literal 3623 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 literal 0 HcmV?d00001 diff --git a/apps/mtnclock/screenshot5.png b/apps/mtnclock/screenshot5.png new file mode 100644 index 0000000000000000000000000000000000000000..b34a3111ca81395be3b6644ab7f576222029c98f GIT binary patch literal 3427 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 FV1hRXwUz(? literal 0 HcmV?d00001 From 1eab970caabb0921520b6e41734868f2ea6eed62 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sun, 24 Apr 2022 16:25:36 +0200 Subject: [PATCH 37/78] [Scheduler] Add "Default Repeat" to settings --- apps/sched/ChangeLog | 1 + apps/sched/README.md | 3 ++- apps/sched/lib.js | 5 +++-- apps/sched/metadata.json | 2 +- apps/sched/settings.js | 9 +++++++++ 5 files changed, 16 insertions(+), 4 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 7372f9c4a..ec157cb1c 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -4,3 +4,4 @@ 0.04: Fix `getTimeToAlarm` to check for next dow if alarm.t lower currentTime. 0.05: Export new functions (`newDefaultAlarm/Timer`), add Settings page 0.06: Refactor some methods to library +0.07: Update settings diff --git a/apps/sched/README.md b/apps/sched/README.md index 47507fc14..57acdc0b7 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -16,6 +16,7 @@ Global Settings - `Unlock at Buzz` - If `Yes` the alarm/timer will unlock the watch - `Default Auto Snooze` - Default _Auto Snooze_ value for newly created alarms (_Alarms_ only) - `Default Snooze` - Default _Snooze_ value for newly created alarms/timers +- `Default Repeat` - Default _Repeat_ value for newly created alarms (_Alarms_ only) - `Buzz Count` - The number of buzzes before the watch goes silent - `Buzz Interval` - The interval between one buzz and the next - `Default Alarm/Timer Pattern` - Default vibration pattern for newly created alarms/timers @@ -38,7 +39,7 @@ Alarms are stored in an array in `sched.json`, and take the form: // WED = 8 // THU = 16 // FRI = 32 - // SAT = 64 + // SAT = 64 date : "2022-04-04", // OPTIONAL date for the alarm, in YYYY-MM-DD format // eg (new Date()).toISOString().substr(0,10) diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 58ba5daf0..32aa099f8 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -59,8 +59,8 @@ exports.newDefaultAlarm = function () { let alarm = { t: 12 * 3600000, // Default to 12:00 on: true, - rp: false, // repeat not the default - as: settings.defaultAutoSnooze || false, + rp: settings.defaultRepeat, + as: settings.defaultAutoSnooze, dow: 0b1111111, last: 0, vibrate: settings.defaultAlarmPattern, @@ -95,6 +95,7 @@ exports.getSettings = function () { unlockAtBuzz: false, defaultSnoozeMillis: 600000, // 10 minutes defaultAutoSnooze: false, + defaultRepeat: false, buzzCount: 10, buzzIntervalMillis: 3000, // 3 seconds defaultAlarmPattern: "..", diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 5f61d7d04..c41e5b5b3 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.06", + "version": "0.07", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", diff --git a/apps/sched/settings.js b/apps/sched/settings.js index 642e43b43..5ddb4dab2 100644 --- a/apps/sched/settings.js +++ b/apps/sched/settings.js @@ -36,6 +36,15 @@ } }, + /*LANG*/"Default Repeat": { + value: settings.defaultRepeat, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => { + settings.defaultRepeat = v; + require("sched").setSettings(settings); + } + }, + /*LANG*/"Buzz Count": { value: settings.buzzCount, min: 5, From ad4a99a04c620283ec5add763cba4267cedef16b Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 18:50:29 +0200 Subject: [PATCH 38/78] First commit for the next version of ActivityReminder: tweaking some values --- apps/activityreminder/ChangeLog | 1 + apps/activityreminder/app.js | 2 +- apps/activityreminder/lib.js | 8 ++++---- apps/activityreminder/metadata.json | 4 ++-- apps/activityreminder/settings.js | 2 +- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/activityreminder/ChangeLog b/apps/activityreminder/ChangeLog index 5560f00bc..53e29a66d 100644 --- a/apps/activityreminder/ChangeLog +++ b/apps/activityreminder/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Fix the settings bug and some tweaking diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 9fb52e9ac..310dc10b0 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -15,7 +15,7 @@ function drawAlert(){ }); Bangle.buzz(400); - setTimeout(load, 10000); + setTimeout(load, 20000); } function run(){ diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index fee30e4c3..712842fba 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -6,17 +6,17 @@ exports.loadSettings = function() { maxInnactivityMin: 30, dismissDelayMin: 15, minSteps: 50 - }, require("Storage").readJSON("ar.settings.json", true) || {}); + }, require("Storage").readJSON("activityreminder.s.json", true) || {}); }; exports.writeSettings = function(settings){ - require("Storage").writeJSON("ar.settings.json", settings); + require("Storage").writeJSON("activityreminder.s.json", settings); }; exports.saveStepsArray = function(stepsArray) { - require("Storage").writeJSON("ar.stepsarray.json", stepsArray); + require("Storage").writeJSON("activityreminder.sa.json", stepsArray); }; exports.loadStepsArray = function(){ - return require("Storage").readJSON("ar.stepsarray.json") || []; + return require("Storage").readJSON("activityreminder.sa.json") || []; }; \ No newline at end of file diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index bc31776d6..260baafba 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -3,7 +3,7 @@ "name": "Activity Reminder", "shortName":"Activity Reminder", "description": "A reminder to take short walks for the ones with a sedentary lifestyle", - "version":"0.01", + "version":"0.02", "icon": "app.png", "type": "app", "tags": "tool,activity", @@ -17,6 +17,6 @@ {"name": "activityreminder.img", "url": "app-icon.js", "evaluate": true} ], "data": [ - {"name": "ar.settings.json", "name": "ar.stepsarray.json"} + {"name": "activityreminder.s.json", "name": "activityreminder.sa.json"} ] } diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 65a19feb2..0b8f0542e 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -32,7 +32,7 @@ }, 'Max innactivity': { value: 30|settings.maxInnactivityMin, - min: 15, max: 60, + min: 15, max: 120, onchange: v => { settings.maxInnactivityMin = v; require("activityreminder").writeSettings(settings); From a9d8d52beb8bcd38ecc3237a7c347af058191763 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 19:15:57 +0200 Subject: [PATCH 39/78] add logs for debug --- apps/activityreminder/settings.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 0b8f0542e..6e25bc6d6 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -2,6 +2,9 @@ // Load settings var settings = require("activityreminder").loadSettings(); + console.log('In settings') + console.log(settings); + // Show the menu E.showMenu({ "" : { "title" : "Activity Reminder" }, From 2f67e5c0ed60ae87d13329a494fffc6a849de1b1 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 19:25:11 +0200 Subject: [PATCH 40/78] Try to fix the settings issue --- apps/activityreminder/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 6e25bc6d6..f26753820 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -34,7 +34,7 @@ } }, 'Max innactivity': { - value: 30|settings.maxInnactivityMin, + value: settings.maxInnactivityMin, min: 15, max: 120, onchange: v => { settings.maxInnactivityMin = v; From d63eb7e003608630801ce58a40a4904c9c05d095 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 19:35:50 +0200 Subject: [PATCH 41/78] Fix settings issue --- apps/activityreminder/settings.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index f26753820..249af0c54 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -10,7 +10,7 @@ "" : { "title" : "Activity Reminder" }, "< Back" : () => back(), 'Enable': { - value: !!settings.enabled, + value: settings.enabled, format: v => v?"Yes":"No", onchange: v => { settings.enabled = v; @@ -18,7 +18,7 @@ } }, 'Start hour': { - value: 9|settings.startHour, + value: settings.startHour, min: 0, max: 24, onchange: v => { settings.startHour = v; @@ -26,7 +26,7 @@ } }, 'End hour': { - value: 20|settings.endHour, + value: settings.endHour, min: 0, max: 24, onchange: v => { settings.endHour = v; @@ -42,7 +42,7 @@ } }, 'Dismiss delay': { - value: 10|settings.dismissDelayMin, + value: settings.dismissDelayMin, min: 5, max: 15, onchange: v => { settings.dismissDelayMin = v; @@ -50,7 +50,7 @@ } }, 'Min steps': { - value: 50|settings.minSteps, + value: settings.minSteps, min: 10, max: 500, onchange: v => { settings.minSteps = v; From cbbab7c04c690bbd60a5a121f785f749269ff77f Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 19:42:35 +0200 Subject: [PATCH 42/78] Fix settings bug --- apps/terminalclock/ChangeLog | 1 + apps/terminalclock/metadata.json | 2 +- apps/terminalclock/settings.js | 10 +++++----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/terminalclock/ChangeLog b/apps/terminalclock/ChangeLog index 14159bc19..4e53f6f8b 100644 --- a/apps/terminalclock/ChangeLog +++ b/apps/terminalclock/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Rename "Activity" in "Motion" and display the true values for it 0.03: Add Banglejs 1 compatibility +0.04: Fix settings bug diff --git a/apps/terminalclock/metadata.json b/apps/terminalclock/metadata.json index de369bf10..a34602913 100644 --- a/apps/terminalclock/metadata.json +++ b/apps/terminalclock/metadata.json @@ -3,7 +3,7 @@ "name": "Terminal Clock", "shortName":"Terminal Clock", "description": "A terminal cli like clock displaying multiple sensor data", - "version":"0.03", + "version":"0.04", "icon": "app.png", "type": "clock", "tags": "clock", diff --git a/apps/terminalclock/settings.js b/apps/terminalclock/settings.js index 77df69b12..6b686058b 100644 --- a/apps/terminalclock/settings.js +++ b/apps/terminalclock/settings.js @@ -18,7 +18,7 @@ "" : { "title" : "Terminal Clock" }, "< Back" : () => back(), 'HR confidence': { - value: 50|settings.HRMinConfidence, // 0| converts undefined to 0 + value: settings.HRMinConfidence, min: 0, max: 100, onchange: v => { settings.HRMinConfidence = v; @@ -26,7 +26,7 @@ } }, 'Show date': { - value: !!settings.showDate, + value: settings.showDate, format: v => v?"Yes":"No", onchange: v => { settings.showDate = v; @@ -34,7 +34,7 @@ } }, 'Show HRM': { - value: !!settings.showHRM, + value: settings.showHRM, format: v => v?"Yes":"No", onchange: v => { settings.showHRM = v; @@ -42,7 +42,7 @@ } }, 'Show Activity': { - value: !!settings.showActivity, + value: settings.showActivity, format: v => v?"Yes":"No", onchange: v => { settings.showActivity = v; @@ -50,7 +50,7 @@ } }, 'Show Steps': { - value: !!settings.showStepCount, + value: settings.showStepCount, format: v => v?"Yes":"No", onchange: v => { settings.showStepCount = v; From 3a7e67d56b27193a6492b98e538e4f067de52b3a Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Sun, 24 Apr 2022 19:57:18 +0200 Subject: [PATCH 43/78] remove debug logs --- apps/activityreminder/settings.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 249af0c54..bdd105781 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -2,9 +2,6 @@ // Load settings var settings = require("activityreminder").loadSettings(); - console.log('In settings') - console.log(settings); - // Show the menu E.showMenu({ "" : { "title" : "Activity Reminder" }, From 65f8e20575f1614a07057c5c4fcb24690befb90c Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sun, 24 Apr 2022 21:36:17 +0200 Subject: [PATCH 44/78] [Alarms & Timers] Add missing require("sched") --- apps/alarm/ChangeLog | 3 ++- apps/alarm/app.js | 2 +- apps/alarm/metadata.json | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index e3b69e76e..bb59a63d5 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -20,4 +20,5 @@ 0.19: Ensure rescheduled alarms that already fired have 'last' reset 0.20: Use the new 'sched' factories to initialize new alarms/timers 0.21: Fix time reset after a day of week change (#1676) -0.22: Refactor some methods to scheduling library \ No newline at end of file +0.22: Refactor some methods to scheduling library +0.23: Fix regression with Days of Week (#1735) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 15a4c3774..5d230c98c 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -104,7 +104,7 @@ function editAlarm(alarmIndex, alarm) { value: "SMTWTFS".split("").map((d,n)=>a.dow&(1< editDOW(a.dow, d => { a.dow = d; - a.t = encodeTime(t); + a.t = require("sched").encodeTime(t); editAlarm(alarmIndex, a); }) }, diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index 906df810f..cd1f1f699 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.22", + "version": "0.23", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From 39598a2d1f178a6ba08bcb4f768ea7336465b309 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 25 Apr 2022 11:45:06 +0100 Subject: [PATCH 45/78] Add Bluetooth multimeter support --- apps/btmultimeter/ChangeLog | 1 + apps/btmultimeter/README.md | 32 ++++++++++ apps/btmultimeter/app-icon.js | 1 + apps/btmultimeter/app.js | 105 +++++++++++++++++++++++++++++++ apps/btmultimeter/app.png | Bin 0 -> 13454 bytes apps/btmultimeter/metadata.json | 15 +++++ apps/btmultimeter/screenshot.png | Bin 0 -> 2696 bytes 7 files changed, 154 insertions(+) create mode 100644 apps/btmultimeter/ChangeLog create mode 100644 apps/btmultimeter/README.md create mode 100644 apps/btmultimeter/app-icon.js create mode 100644 apps/btmultimeter/app.js create mode 100644 apps/btmultimeter/app.png create mode 100644 apps/btmultimeter/metadata.json create mode 100644 apps/btmultimeter/screenshot.png diff --git a/apps/btmultimeter/ChangeLog b/apps/btmultimeter/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/btmultimeter/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/btmultimeter/README.md b/apps/btmultimeter/README.md new file mode 100644 index 000000000..80fcdcf50 --- /dev/null +++ b/apps/btmultimeter/README.md @@ -0,0 +1,32 @@ +# Bluetooth Multimeter + +Connect to compatible a Bluetooth Multimeters and display the result on your wrist! + +## Compatible Bluetooth meters + +Only the OWON is supported right now - feel free to add support for more! + +### OWON OW18E + +Available [on Amazon](https://www.amazon.co.uk/Bluetooth-Multimeter-Multimeters-Voltmeter-Resistance/dp/B08NJT38SF/ref=sr_1_1) + +Turn the meter on, and long-press the Hz/Duty/Delta/Bluetooth button on the right hand side. Now run the app. + +## Usage + +The app currently only displays the current reading from the volt meter. + +If the app fails to connect you'll need to reload it to reconnect. + +To exit the app, long-press the button. + + +## Future functionality... + +* Logging +* Graphs +* More than one meter + +## Creator + +Gordon Williams (please file issues via GitHub) diff --git a/apps/btmultimeter/app-icon.js b/apps/btmultimeter/app-icon.js new file mode 100644 index 000000000..d1e10b1ce --- /dev/null +++ b/apps/btmultimeter/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4kA///z3vy067fWlP7/t1r3f33vrU07tdxHKn1mnUEv92DgO75xUwmcziIAIiAWJgYXLiIuLC5dwC6xIJCwP/swAHsIXM5GZAA/HC4kCC42I7oAG3OXC4sgC4/e9v+939AQP7C40iC429C4Pu/wCC9YXHGAYXCzoXC3wCCC5AwDC4WZC4M+909AQM7C5AwCC4ef/tfn/dAQQXIDAQXDAA4XHJIYXBzNVAA9XC4K8CR4QwCC4Mzi93AA1xC4JBCC4QwCC4URABIXBCgaqDC5MWC4YRCI4hfC1VEmMX93u8MR/Pd6J3CCQJ3DR4YXF84XBR4ilDbAYXFagM3iP1R4YQBCwbXER4KHBRYaWBR4TWFYoQXCsKPKCIQuEC452BC6MxiPju8xiYZEI5gXBiLDHO5k+FgKSBCYM+C4inJAAMWmlEolDi8TC4jXJAAQWBAANBUoIXCCQQCBDgQXCn0z+gXDokRjwXCCIQXCDoQuHAAJlBC4ZBBC4kiC4ekC4lBI4ioDYQYXD1QXJXIR3DL4fjn4XBGIdBbQQXFYAYvE0gXEF5DXGC4IYBC4WhC5IFCC4dKC4QDB+KPDC4guCX4n6GAIXCmK/CuAXEAgQvEPAIXC14JDmAXDFwYXEeAKpCBAgXECwYXFeQVDC5AAFC400AwoXQAAwXJgYXWGBoWJAF4A==") diff --git a/apps/btmultimeter/app.js b/apps/btmultimeter/app.js new file mode 100644 index 000000000..11bcca9fb --- /dev/null +++ b/apps/btmultimeter/app.js @@ -0,0 +1,105 @@ +var decoded; +var gatt; + + +function decode(d) { + var value = d.getUint16(4,1); + if (value&32768) + value = -(value&32767); + var flags = d.getUint8(0); + var flags2 = d.getUint8(1); + // mv dc 27,240 "11xxx" + // mv ac 95,240 "1011xxx" + // v dc 36,240 "100xxx" 36(2dp) 35(20dp) + // v ac 100,240 "1100xxx" 100(2dp) 99(20dp) 97(2000dp) + // ohms 55,241 "110xxx" + // beep 231,242 "11100xxx" + // diode 167,242 "10100xxx" + // capac 76,241 "1001xxx" + // hz 162,241 "10100xxx" + // temp 33,242 "100xxx" + // ncv 96,243 "1100xxx" + // uA 146,240 "10010xxx" + // ma 155,240 "10011xxx" + // A 163,240 "10100xxx" + var dp = flags&7; + var range = (flags>>3)&7; + value *= Math.pow(10, -dp); + var isAC = !!(flags&64); + var mode = "?", units = ""; + if (flags2==240) { + if (flags&128) { + mode = "current"; + units = ["","nA","uA","mA","A","kA","MA",""][range]; + } else { + mode = "voltage"; + units = ["","nV","uV","mV","V","kV","MV",""][range] + " " + (isAC?"AC":"DC"); + } + } else if (flags2==241) { + if (isAC) { + mode = "capacitance"; + units = ["","nF","uF","mF","F","kF","MF",""][range]; + } else if (flags&128) { + mode = "frequency"; + units = "Hz"; + } else { + mode = "resistance"; + units = ["","nOhm","uOhm","mOhm","Ohm","kOhm","MOhm",""][range]; + } + } else if (flags2==242) { + if (flags&128) mode = isAC ? "continuity" : "diode"; + else { + mode = "temperature"; + units = isAC ? "F" : "C"; + } + } else if (flags2==243) mode = "ncv"; + //console.log(mode+" "+value+" "+units,new Uint8Array(d.buffer).slice()); + decoded = { + value : value, + mode : mode, // current/voltage/capacitance/frequency/resistance/temperature + units : units, // eg 'mA' + raw : new Uint8Array(d.buffer).slice(), + }; + updateDisplay(decoded); +} + +function updateDisplay(d) { + var mode = d.mode; + mode = mode.substr(0,1).toUpperCase()+mode.substr(1); + var s = d.value.toString(); + + var R = Bangle.appRect; + g.reset().clearRect(R); + g.setFont("12x20").setFontAlign(-1,-1).drawString(mode, R.x, R.y); + g.setFont("12x20").setFontAlign(1,1).drawString(d.units, R.x+R.w-1, R.y+R.h-1); + var fontSize = 80; + g.setFont("Vector",fontSize).setFontAlign(0,0); + while (g.stringWidth(s) > R.w-20) { + fontSize -= 2; + g.setFont("Vector", fontSize); + } + g.drawString(s, R.x+R.w/2, R.y+R.h/2); +} + +Bangle.loadWidgets(); +Bangle.drawWidgets(); +E.showMessage(/*LANG*/"Connecting..."); + +NRF.requestDevice({ filters: [{ name: 'BDM' }] }).then(function(device) { + return device.gatt.connect(); +}).then(function(g) { + gatt = g; + return gatt.getPrimaryService(0xFFF0); +}).then(function(service) { + return service.getCharacteristic(0xFFF4); +}).then(function(c) { + c.on('characteristicvaluechanged', function(event) { + d = event.target.value; + decode(d); + }); + return c.startNotifications(); +}).then(function() { + E.showMessage(/*LANG*/"Connected."); +}).catch(function(e) { + E.showMessage(e.toString()); +}); diff --git a/apps/btmultimeter/app.png b/apps/btmultimeter/app.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e75c76e04b58368611ba309134a776eec81fd4 GIT binary patch literal 13454 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 literal 0 HcmV?d00001 diff --git a/apps/btmultimeter/metadata.json b/apps/btmultimeter/metadata.json new file mode 100644 index 000000000..3a9a72063 --- /dev/null +++ b/apps/btmultimeter/metadata.json @@ -0,0 +1,15 @@ +{ "id": "btmultimeter", + "name": "Bluetooth Multimeter", + "shortName":"BT Meter", + "version":"0.01", + "description": "Connect to compatible a Bluetooth Multimeters and display the result on your wrist!", + "icon": "app.png", + "tags": "bluetooth,tool", + "screenshots" : [ { "url":"screenshot.png" } ], + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"btmultimeter.app.js","url":"app.js"}, + {"name":"btmultimeter.img","url":"app-icon.js","evaluate":true} + ] +} diff --git a/apps/btmultimeter/screenshot.png b/apps/btmultimeter/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..dfd64eabf95a4730ab1d00f6c4f522671b6ddc64 GIT binary patch literal 2696 zcmdT`_g9k%7EL~bkOZWJG6NA|DI+F`NI<&6fFV>tAVC<&fD(vQ5lE!O4+}zcGE`9n zDIyL86FM0wkveom1R;nS+K3b>N<{nV^WM4V-S^WyH|3l&UJ9X%fIuKp z1UnnIedPY9Bo6L(PW_DUK0u?~@Yay$1L%1O1Yu3Ev2v&RF69Ygicd&Fa=(B7xJVF$ z=+ss)FM;HZNc}3DGWtO9HqG+!p!A+q!BJ2gP+CF>gD_wO(_}anZI!$v7(%~ITnj&vAW(Sde!}A zyMnKgBATAG2+wP|-@pSzo+KC9Sfz-%y<lmK6P2v=_0H zy?uyy?(ZY>7QpY#fBUStUOP1WN`)!(?cEa4=f+uu)kNKVSEz(g`50TPu&~ zBwU)tEjdkW@IDW2xQjPnRz@dh7Ybv;S$!%dhi4wRQc$$v_1$W6Z$QmtuVl($z~Sa0 zOJ7^z&wdx}Fzl;4LRG(O-}ZlhSdf4cB~sNB0xD|lrHSNj$vPRi!mVivJ>he=hCi~h zMSZb3rP>mCc9L#lC~H0yG(&T0j?Ct4uX|TeX^O z1#_m~&W^{R0nTzn#12LRyA(?KeO1HO;ES;+0+5KOA??VwA;93P>4`RYW1{8kdbIZ! zmtPk}VXs%Ef5HQ$YFtO*WBd`n(`~o-r5{DJ>1Tw!wO@S2)K{9mCGe<>Ci~@tlwa0o zHzth=zaGS2tK;Q`lM9#vlZHZAN`O(YL2FWe4omc}N?4F@TC zEyLALIA>}{AVIGL2QyR0JvV^0(XtrK(OE5lH3u@EQEedLYB3H9JO17>9ZyCdb%KBn z^{g4$AH?lZXM{sb8gy7EI0TbvxVmkp3Pu+E@2Oi_fZyMuFP?v>A9I-xXWIB3b8X?6 zxRa4Lp8-WLJU3Le3ry6C?6^4 z7PPvf276*~lj#CEkf?z6$T=7@tBm7$lc-a{In*xFm7j%&Ko2J-)tM7H-l$6t3ZRN* zb$VSvD$$}VT|1I5pQPYQEE|@*XM=&&_2qiq zz!90Y?z-8=llinkg9^UuT60F$!z#e1Ls`?gY0i7oHfj|SY%!?GHEalsH)>E=uecLD zwx-7Itg#L7JjHmtk-FvCJ{)h~03%*) zg&;Qa7lshVqt#%zF+L;q@z3~pK1u(dH2vba>?u2?OwsCl_Qzy67Fx+xRg`cm##YvB zyI*#6_$|A#*!)Q%=`!t}-`h4nK|Q4t`{I)p33EP`x>;ty&2nI z=>zX5jk1JRwYQa1ona675B+P%fiTl6gQcPG`i_}KJ>NJxTy>55EsV!~GN~s^I^UkQ zc7b>pKGlaX#|Rg(5dzEvcd4m{kv}*rm$egRvD3>8S2v*2lyfKU$y>LVOX^ptAAw{n~WLXPV zhf`N6@I1ND-?#U)Q*ab%=Aw&de4_J6)aY<^_6p{&%h1xSd|jJdYNoUffY(}32>D8% z%p2H=&+0p6KOGy$J+F9Q0N(-7Z`o{Z`r`m^z5G-kN5DZUBR_6{L2kGC z{nIO)Z)#e{zwAxtTSrDR`n7z7KXfz~(T-Tz!i~=}wUZxgK4ei{4k<$^Ya27T9avRk ziuW%QmaedDj}#x!u$=qoH4O$Z)>DEe%8)1jBzVP<`^zjfRuISQ-&?bNLOpRk>+Ql0ZfImmdVRIn>1x0B-2S}h(Gst86=W>nLZ|x_FbB|!X z+SmDG?GN-aAwcq!Ch7k`vhiK~=N9SF?cAuLRU&WbL(b)n<-F=6On%4B9%rJQyJ@om zP4m+RNiT5WyR5O`j{iC#$-YYq6m^x*wx=b09G@*-t+1|Lt8VAs-Oc>|r-aj@nlpceX{A#HcgYk51H@aNdLbw+0x%OPOwKyfjX z|G10D>Y||g4Il)2SWNBB3@l9Moi($vRFlhSD)&mDr$zR7P8#UInkgUjJZftm*EatZ zl-N>O-7@z==Dyo}j(;F*`BGo~>)+ Date: Mon, 25 Apr 2022 11:45:17 +0100 Subject: [PATCH 46/78] minor tweaks --- README.md | 2 +- core | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a6c449cc7..78dd1b492 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ try and keep filenames short to avoid overflowing the buffer. ### Screenshots -In the app `metadata.json` file you can add a list of screenshots with a line like: `"screenshots" : [ { url:"screenshot.png" } ],` +In the app `metadata.json` file you can add a list of screenshots with a line like: `"screenshots" : [ { "url":"screenshot.png" } ],` To get a screenshot you can: diff --git a/core b/core index 89049a5c7..24730dc0b 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 89049a5c7c80d2b56dc235d135fc63b80789db96 +Subproject commit 24730dc0bac75ea9eff0e2632e530a6ff7652b19 From acdbdd81dc85cb3492a49fe9dd6654225e5a485c Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Mon, 25 Apr 2022 11:45:45 +0100 Subject: [PATCH 47/78] oops --- apps/btmultimeter/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/btmultimeter/app-icon.js b/apps/btmultimeter/app-icon.js index d1e10b1ce..815929fd1 100644 --- a/apps/btmultimeter/app-icon.js +++ b/apps/btmultimeter/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEw4kA///z3vy067fWlP7/t1r3f33vrU07tdxHKn1mnUEv92DgO75xUwmcziIAIiAWJgYXLiIuLC5dwC6xIJCwP/swAHsIXM5GZAA/HC4kCC42I7oAG3OXC4sgC4/e9v+939AQP7C40iC429C4Pu/wCC9YXHGAYXCzoXC3wCCC5AwDC4WZC4M+909AQM7C5AwCC4ef/tfn/dAQQXIDAQXDAA4XHJIYXBzNVAA9XC4K8CR4QwCC4Mzi93AA1xC4JBCC4QwCC4URABIXBCgaqDC5MWC4YRCI4hfC1VEmMX93u8MR/Pd6J3CCQJ3DR4YXF84XBR4ilDbAYXFagM3iP1R4YQBCwbXER4KHBRYaWBR4TWFYoQXCsKPKCIQuEC452BC6MxiPju8xiYZEI5gXBiLDHO5k+FgKSBCYM+C4inJAAMWmlEolDi8TC4jXJAAQWBAANBUoIXCCQQCBDgQXCn0z+gXDokRjwXCCIQXCDoQuHAAJlBC4ZBBC4kiC4ekC4lBI4ioDYQYXD1QXJXIR3DL4fjn4XBGIdBbQQXFYAYvE0gXEF5DXGC4IYBC4WhC5IFCC4dKC4QDB+KPDC4guCX4n6GAIXCmK/CuAXEAgQvEPAIXC14JDmAXDFwYXEeAKpCBAgXECwYXFeQVDC5AAFC400AwoXQAAwXJgYXWGBoWJAF4A==") +require("heatshrink").decompress(atob("mEw4kA///z3vy067fWlP7/t1r3f33vrU07tdxHKn1mnUEv92DgO75xUwmcziIAIiAWJgYXLiIuLC5dwC6xIJCwP/swAHsIXM5GZAA/HC4kCC42I7oAG3OXC4sgC4/e9v+939AQP7C40iC429C4Pu/wCC9YXHGAYXCzoXC3wCCC5AwDC4WZC4M+909AQM7C5AwCC4ef/tfn/dAQQXIDAQXDAA4XHJIYXBzNVAA9XC4K8CR4QwCC4Mzi93AA1xC4JBCC4QwCC4URABIXBCgaqDC5MWC4YRCI4hfC1VEmMX93u8MR/Pd6J3CCQJ3DR4YXF84XBR4ilDbAYXFagM3iP1R4YQBCwbXER4KHBRYaWBR4TWFYoQXCsKPKCIQuEC452BC6MxiPju8xiYZEI5gXBiLDHO5k+FgKSBCYM+C4inJAAMWmlEolDi8TC4jXJAAQWBAANBUoIXCCQQCBDgQXCn0z+gXDokRjwXCCIQXCDoQuHAAJlBC4ZBBC4kiC4ekC4lBI4ioDYQYXD1QXJXIR3DL4fjn4XBGIdBbQQXFYAYvE0gXEF5DXGC4IYBC4WhC5IFCC4dKC4QDB+KPDC4guCX4n6GAIXCmK/CuAXEAgQvEPAIXC14JDmAXDFwYXEeAKpCBAgXECwYXFeQVDC5AAFC400AwoXQAAwXJgYXWGBoWJAF4A==")) From 499ec22dd82d74ebd76cb027dccadf04479ad1be Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Sat, 23 Apr 2022 22:49:06 +0200 Subject: [PATCH 48/78] [AppLoader] Add new chips --- index.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/index.html b/index.html index 7a94f684a..a3f358bc2 100644 --- a/index.html +++ b/index.html @@ -75,11 +75,14 @@

+ + +