From 7c98f4a1c7a8857a256ffc081b0fe67717328d6b Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 21 Dec 2021 01:22:19 +0100 Subject: [PATCH 001/312] Update core 0.15: Fix: Dims of notification icon (v0.12) are retrieved from icon header (no more hardcoded width=64px) --- apps/messages/ChangeLog | 1 + apps/messages/widget.js | 13 +++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 94848a26c..2b400fcd3 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -21,3 +21,4 @@ Add 'Delete All' option to message options Now update correctly when 'require("messages").clearAll()' is called 0.14: Hide widget when all unread notifications are dismissed from phone +0.15: Fix: Dims of notification icon (v0.12) are retrieved from icon header (no more hardcoded width=64px) diff --git a/apps/messages/widget.js b/apps/messages/widget.js index f01d22ec7..05622b162 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,9 +1,10 @@ -WIDGETS["messages"]={area:"tl",width:0,draw:function() { +WIDGETS["messages"]={area:"tl", width:0, ICONS:[atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA=="),atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA==")], //icons should be equal size or first larger +draw:function() { Bangle.removeListener('touch', this.touch); if (!this.width) return; var c = (Date.now()-this.t)/1000; - g.reset().clearRect(this.x,this.y,this.x+this.width,this.y+23); - g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y); + g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.ICONS[0].charCodeAt(1)); + g.drawImage(this.ICONS[c&1], this.x, this.y); //if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.repeat===undefined) settings.repeat = 4; @@ -17,7 +18,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { WIDGETS["messages"].t=Date.now(); // first time WIDGETS["messages"].l=Date.now()-10000; // last buzz if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing - WIDGETS["messages"].width=64; + WIDGETS["messages"].width=this.ICONS[0].charCodeAt(0); Bangle.drawWidgets(); Bangle.setLCDPower(1);// turns screen on },hide:function() { @@ -36,7 +37,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { b(); },touch:function(b,c) { var w=WIDGETS["messages"]; - if (!w||!w.width||c.xw.x+w.width||c.yw.y+23) return; + if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.ICONS[0].charCodeAt(1)) return; load("messages.app.js"); }}; /* We might have returned here if we were in the Messages app for a @@ -45,4 +46,4 @@ want to buzz but should still show that there are unread messages. */ if (global.MESSAGES===undefined) (function() { var messages = require("Storage").readJSON("messages.json",1)||[]; if (messages.some(m=>m.new)) WIDGETS["messages"].show(true); -})(); +})(); \ No newline at end of file From 39aff0e7ed9239438b6ee959cfc15f918c61ba24 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 21 Dec 2021 02:01:39 +0100 Subject: [PATCH 002/312] messages app v0.15 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e5e9f8f02..e37bfd908 100644 --- a/apps.json +++ b/apps.json @@ -77,7 +77,7 @@ { "id": "messages", "name": "Messages", - "version": "0.14", + "version": "0.15", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", From c72b6fcc0981086d7a87e14367dceb21df9410cf Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:12:26 +0100 Subject: [PATCH 003/312] Nifty-A Clock with iso week number * code changed to show iso week number * settings file created * screenshot updated * settings screenshot created * readme adjusted * and app.json increased to v0.02 --- apps.json | 2 +- apps/ffcniftya/ChangeLog | 1 + apps/ffcniftya/README.md | 5 +++ apps/ffcniftya/app.js | 37 +++++++++++++------ apps/ffcniftya/ffcniftya.settings.js | 25 +++++++++++++ apps/ffcniftya/screenshot_nifty.png | Bin 3487 -> 52362 bytes apps/ffcniftya/screenshot_settings_nifty.png | Bin 0 -> 46504 bytes 7 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 apps/ffcniftya/ffcniftya.settings.js create mode 100644 apps/ffcniftya/screenshot_settings_nifty.png diff --git a/apps.json b/apps.json index e5e9f8f02..2139cd8eb 100644 --- a/apps.json +++ b/apps.json @@ -4316,7 +4316,7 @@ { "id": "ffcniftya", "name": "Nifty-A Clock", - "version": "0.01", + "version": "0.02", "description": "A nifty clock with time and date", "icon": "app.png", "screenshots": [{"url":"screenshot_nifty.png"}], diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index 18bc264a3..bf70a213b 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1 +1,2 @@ 0.01: New Clock Nifty A +0.02: Shows the current week number, can be disabled via settings "" diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index f1fee9b1f..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,4 +1,9 @@ # Nifty-A Clock +##This is the clock ![](screenshot_nifty.png) +##And the week number can be turned On/Off via settings +![](screenshot_settings_nifty.png) +default is "On" + diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 31742f64a..c7e08cf9c 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -16,6 +16,18 @@ const center = { y: Math.round(((viewport.height - widget) / 2) + widget), } +function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + function d02(value) { return ('0' + value).substr(-2); } @@ -29,23 +41,26 @@ function draw() { const minutes = d02(now.getMinutes()); const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); - const year = now.getFullYear(); - - const month2 = locale.month(now, 3); - const day2 = locale.dow(now, 3); + const year = now.getFullYear(now); + const weekNum = d02(ISO8601_week_no(now)); + const monthName = locale.month(now, 3); + const dayName = locale.dow(now, 3); + const centerTimeScaleX = center.x + 32 * scale; g.setFontAlign(1, 0).setFont("Vector", 90 * scale); - g.drawString(hour, center.x + 32 * scale, center.y - 31 * scale); - g.drawString(minutes, center.x + 32 * scale, center.y + 46 * scale); + g.drawString(hour, centerTimeScaleX, center.y - 31 * scale); + g.drawString(minutes, centerTimeScaleX, center.y + 46 * scale); g.fillRect(center.x + 30 * scale, center.y - 72 * scale, center.x + 32 * scale, center.y + 74 * scale); + const centerDatesScaleX = center.x + 40 * scale; g.setFontAlign(-1, 0).setFont("Vector", 16 * scale); - g.drawString(year, center.x + 40 * scale, center.y - 62 * scale); - g.drawString(month, center.x + 40 * scale, center.y - 44 * scale); - g.drawString(day, center.x + 40 * scale, center.y - 26 * scale); - g.drawString(month2, center.x + 40 * scale, center.y + 48 * scale); - g.drawString(day2, center.x + 40 * scale, center.y + 66 * scale); + g.drawString(year, centerDatesScaleX, center.y - 62 * scale); + g.drawString(month, centerDatesScaleX, center.y - 44 * scale); + g.drawString(day, centerDatesScaleX, center.y - 26 * scale); + g.drawString(weekNum, centerDatesScaleX, center.y + 15 * scale); + g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); + g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js new file mode 100644 index 000000000..d9a1c9fca --- /dev/null +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -0,0 +1,25 @@ +(function(back) { + var FILE = "\ffcniftya.json"; + // Load settings + var cfg = Object.assign({ + showWeekNum: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, cfg); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "Nifty-A Clock" }, + "< Back" : () => back(), + 'week number?': { + value: cfg.showWeekNum, + format: v => v?"On":"Off", + onchange: v => { + cfg.showWeekNum = v; + writeSettings(); + } + } + }); +}) \ No newline at end of file diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index 0df056223c087638f940b2095330944c87df9906..3e394dced2b1a7907ff52ce3006ea83bed111d22 100644 GIT binary patch literal 52362 zcmZ^~Ra6^H7cPtyinqlbURt2I6?bp(;!s?Ih2ZY)P_!-X6t@H@?pE9r+$A^!33B@V z|IN8M7c;YF?>(~i$lCL)XJRze6!CE=aZpfD@INcbef?L~{V%=7{Fm1@@0k26P~E;N z%AnLtP#^xQU;w05rBP7olW-r+U;V3NJ1ZHup`Z}-|1Y7Yvk_4J6B4@1>$_`#JX|fU zQM6P!6oo%=D=_`|iu|V{{r^=q?q24u)+qmGSi5+n zWYly@BlL;?MD+h_BRlh*b&sd~a{H_=IdNvehUQGQkmA%5rkR_=|Qyc~Nl2?+^} zwL5!JQQ||6=Fm?~z}!95W3KiU)>{qVvz#}EuRk$Jy?dv0cCv>+ytFTh9Q#ak44$36 z_;myxw<1p=2&hAK2LkGs=azdlCkA$0jV969ez6}{NZYC{9aK;z%rFD zz$dx;v_VJ+t2;WfKh7pQ5b0v2(lrKhV1#lV^^~cf0my&PL24!$ZcawXZU#HbI)(YAQFKEpocjRif@A`QPDd`HY6MS2g1 zG)-%{v<^Ur#=!Z-xU!HC)Jn3a%}oZXb*RV-=#nIMB~TOeKc^DQ7(#+NDC=N_x>W2R6I*Z*-%=_R7*~oL5)TS0EbAlOod|v zpn1f82Ta{y1sxb|mq;9Dc}|h1WaA%bi7<+PRc^g}m=n8)LqjXM$&;+%&#D-S3l4L>%5%_X6+2WOUT>`9+*H z0$V$VdI=XaT<7F@c6+@y6NDZ z!uJ!Yc57K!a9no?;|d_V$y{fcOKeL_F|uIs2?O?Zb?7N$19sTeKn z%Ii+|5oznP~@+VU-yNAicP%y4?Q}m=2_4mbQIzpY;Ag7Q&k(h!k?LNlxgRfgypj-Eb@3;FOC`BEiaunO|DNq!6ihWz? z^CfRi*fLYTEDA2b(35JKqUZu9)*c2K;pKgRR#c`Wa%hS*)k#<9vzCKHii<$`H>>_! zJZ-j+qX4j0`Jz>5(sPIeg>%Od228hKASh|2Y#F+*nX(0k&yK!$~PqTdhZ!9=u1%)iIla5+)n)ebO`5KDH<2GcqV&Mbr*;%B5O2?zwk^$kvntxAkk}bj!7D zu7u+3=SLO5w*^f{zqHp)q2N2y)3Mo8Co#*uORLE$*njA2cH^oXtZ~+P5D)S^iR-Yp z$=gYv#kk8|Dd2O1l%f_7-dSRSp~EA#O)CmPQ+iZ+@MNm`$PAk{(54#{I%l+>dm`Xw z7)9eZ=Qv+qfoEi?TqNFVRT*#(>a=;ei@1W<5fRRZ;{2F%`Koj& zv@W3=xdq58}`Gz;l50h z4tiP>fbiF?tgV@MJ>HLdKAmyZSAvlB^G%;36f>F^J@o=LXj*3zY1_@alcOro6ov{~ zP-cF4N&J{&CP=>5wkhuD4PgKJ6_c)r;Q%1nzbnBer3an{AyB)OBjJn4kE1BV1-1yY zP2ul8?nd#E9ZqwKxoWAThh}kszqxMYsdhVb?;8l(RWPRnmq23zXJ40q)#KxwpG+2R zi)4y~OW#CQRy=+VOUX9|lX7a zar_=45+HYnIucANp&8KiqvR5CXOL;_$>9+s0Vc3qI!*;VUI0QoR~3vp{S&GU!PB}m z-$0cnEBV)$euumGM?sCi)p}L)DBx=6ssL!!!f4KBsKyx5+%~jOwdzPE-~?8MLHw3l zd@6ykKdYW6(37Y+X`t3YW`Ji<*X4|5qdVirx8;S3lKnl-oG@~J8NCjQyZZQ&3ptK{RMoMp-AP z5nRjSUTc6nH!nqyAX=bRHE1!s>c3GitMrN@7B{ddX4G zG%!wo8dZ5Md1ReyQpoFBMRb3KZ|AdLb)``8qD%T0qyZMuHMx)@aOilUOn*M z@%U)1n&&s)yuO=p5lz6|1+->()>8JN$*T#*737n(>T#Ivd3dwl2!-fQvl67!w}f60 zr^G9Z2D2@pw~{}yk6kYb$$TI5*rj+y;Bx;@4qoJM|+F*RVo>F066P zR9CIcm(%BW7iJCdfiu`;mcZy~X3X>GIH@s)2%4kN1$hTAI;0D1dB>yA$5I3bTTj+P z#Qj81#sPUYpn!cUILDdD{2C%xa2dAd^M{5%C|B$f)2PF@2!C-TEb-cKT`3QLjIg80 zH;W^{rn=g=V^#ok*6^_BdopAl?HENBS=ITOVAzYWrGDyrcr1lMFb#bwdX(eXLgI#~_PouY!+z?!s_^ZDpbHJL$90-P1!4uqp(6#{9^qiiGXVpc(gFDP!OJUs%&_-9*I6}&W=ShA@g7YO;he+_T?YqBfS##K=Bnp* zUrP1DU;-5v=@PX6=BVX8bCDHMk*hPxobF_aPzhC&AjsBs?zvghB@C*e{07xi#apIj z;2B(feTl-_E_J{o)xRq}<~}F?(~m@u{ivwju-4-HKD5klm0deeO?g*3Gq8visbt9} zyPV&ilf=Svf52A|ua^;#eDhNcg=^a}H94TnoLT!k);IraZFB&zt38U&3S%Rf>1vvm zT#UxEUsNFuuPI%9j`=P!dY$+q6R0Vv!=bCRy|mJYJ>(U~%HN->v8xJf*iDX zmUuQ4w8`xpm;Y-Sx=8h>w34DF7Irl6_qNGdU9Gdt!&;N3NPCTZSGlF>`sveL8-&~B zQ=K_Y^xj0aS*`GehEd~h7%3Ob>6ZQ5?|_TR^K?_i#(u z=Pf9=5eX#poaO;LXNvhga!{et&K4Z>GWZIiZu%JWR6F_9-FaVfHab$MkF6heX^Yor zzww_Cs=A1`#I4XbSiJqG9G_>bNYI58T0)N2oK_IjD(}OvMu1uRn;LxQ_g{CEzrSW>#DT{jDP0 z#W+}^`k<90QHS?uta#7ormy*H?6QRRgS_WKd2MSWlaYg8-252J1C}B@ISg=QrbKjZ z5juSISc(xq*tn_@+UD`iB1;5Vm~;EH5&mO4v965HXCybsKDFA{GppLiDQd<6xH@{W z0Gr>wYdSkTt-lT2Q4vLE3y!9Gj$9#>^Pp!HTC~jPfdh@Ej0=DtBflOr;^V)4FRuiq z{4tczY772F?ZWX#Xd0IXOORny_T!r>*1nrVJ2m)!{aR%x z<0lm)`e~nM&~4W2Nc?RmP}IK9v_wm)=BAC^zfXwDIQE+C-kHIA{PH*VFV-@)&JO!k zL+y`;dh1|6(N|7HZu@`FE-E`6+tc$qAAMqawJiHBSX#n@%E$)sruLIBp{RG&%dGTy z%YPDJz{%5&1!!?<7lAGpyD6i8b)+Ljtd5MfyV6&U086)`T8z0_P(ax7-_~to)8^H? zV2+j(m$oNpgy-=m!e!thdy}Y>@6>G>^#Wuu#5bkzR}sxSmG2L>vRJ?5n?4P>Va;MDyXm&-m2-#KT8 zlW!imGWAfXC0>nlKTHcvy+^UMi!c0eUWJDF-h)N9joUVJnL--#Xyl4cxNoXsg;`TN z>=LbTJ)SY`-c_SdNwiR1LpL%_GNeak6{Xl%ZBxj^Wn+wV&d+B$T=wnY9*pREK+)Pk z;1u$Tkh8IsZ*ciSQ4O+~<6c*7&^%7-pP4i0XH~1b4A~nlUCIQ&p2r>c{kZ;bql3vy=K`ezT#ZplLC+}C$ zv-^-X+oUS*SFZ#(F$Edj9ATKQS!vW|T2HY3cm14V3A!ed@eNlJaC**C4bNW4poMo6|mnVjQ z%7m#~<0eK{i`GUHV*@J`Q&7T~^TuLT9-#`oAq&HcA!O`b=AdOshFbOCIt}Ou7 z#hay(#!R2m3PIj>X}3kzkm2eYWlV z4!#oO5?ja3gw8N||0SV!CSryu(1m0r^S>^#(jI=`O&hzV;7xq7)cF~D zoJcPp3$TE`SzKH&$RUPLggx<;d{|>CD{*ZYs8Bm3M7QixGH?_xq+T(E$U+5UTQY%b zYj%?zbqh9d$sRS4XL^UKqG~*CBGAJesp#$}MX2(z7mP8fcD_dgsU=8#!;}9cOh>^% zlwA1+L+mG?~?#E}=Q@&R~hM+NZ}IATK_^fk2oQ3#nh>5rR=bTW}Ds6`JX zR&b*71F~S!-z~Ca=$T<^HtY$GnNkw6!g(#0uuO)lU4#zHrQL96X2#oj`vDD&7`>=l z;>lhRsJvcpBBv%Kk-6TL`dtdyzOqkzw8`ir{>AlA%%38N(ZsTjJ!w9shXfpR154TJ zjw2E`xXuu5xk!BSarZC&Eo*(``EM-|$D`{*&)M-fs~@Y+`tMVt6hB}sH`}|;kEILF zHydafXMy<>8rM3)JkMy7mSt}xt>eff9OCFqYzWypE+ghW=XkChU+hw=oRp~co(6FazSsFQ$rn-PV!kIHHJQ1ISAt4aELQ&F{RP4EP+PbyB=-b8xQvZ*Mg& zKcCFLI7!}J08Y+R37b!AOpcG^0N&bx?Ff&39MDM}VTmifWHX)qLR-zrDr0 zk%L>D>Mx-+CeRG+>57$JnSol2bBuS+ zTY#;t&Emgz-#qota(yRwRYX5fvx3HouCYT@w{Q5-XiHwYV844d=xJA~V66%(MdHST z+~hmwZI%>;Nes4B9&0oX7RmX388MULjvc!AkOsUmPNE8BS$*M*O;wC^)Y_WTAeTQl zV0z@Cfy`43N0@j-o7SjpOxN*bZo@@}(BFBMFOK)a+MvgOtM{}9MkLhOi>}NSCvUa> z0eKjz(e#^l2i>!y-nAk^tJMK)VSV#aPi0N8%A_o|+?FOmE7fsT#9e9@JS*?1G~fU< z(PU}r)zr>GShD!=j)40oC65zRw!S3@j!^Cr#( zW?7UmG52jZ_61_`<_hl_(Ilt>5yv>Fw>#vtP;{14J7FlmvIpQfL?DmHB0ZXJ*ZqO9R^hIFo zpHUo*LgPJa$2_T4PCF(m8g2-1D+3nat5;5`y>TAC7;I(G9+*@O?Nr>I(h(P8Uyk6h zqGCb=N?EMK@~^FcREfVN)=E{W_ZRgK%l<0<%rn0Mn@v;t?foP>@nEL0AL_EejHr)_ zgb)Nxa=`3go=m$myI2=>e|^Zy`sneOm||;#I}(q}ogbb#xDkWB@3kZs2Oz}+>+OpA zbOeYm{KvJnq;cl4x+?B8b$J7=bo*fq>+vSV(&Hel!c2fVT{|Foe-|uv-d5Hc&K6@I z)%|M^U{T6!T$$jZ33Dqb7_Pgece z-Nz$lcAEV$y5SnOSXmwZ~<@^CnTv8Z2x*ub$Vcy za&tT0rLi|$@bu&`t~$xN+@XANP5)7$$k_z_34Ng|y`~%0J>%_pSF%dJU z?|dIK;w>ZhCAw;lWs0X;XJ))iI8+KMYJlP9=_0=((I$>;f)j z=(_=oV;rorT{awjsYX=5=jUxO3DrgIfmG#R!ep1_=-+_PW$WI~xxBTc+ScY@QQu+_ z_ORYeUC~D5xijJm5t@)SQR}?8I=mI0Pk(TGkpBk+vnC14?mm&_%&`X^4HSw77gL6y zvQVYJLjTUrlC1gPY;N(klBn$ai-}!`b$-HmyRZtG$_MQS_WWLcJ2XC?cP27EP9&kM zEk%b+^#<}OuU7?bs2%X%3^x6Ic zo&*o}G}wCrYbbiHwjs$Vid>@ZRP>f@cG#{V=h4rfe_2pMv8Pc#zHX3vUnFmUs!4jU za#k7t{Fsvb%uDyu1VH5dPpLVKTE7Ez7o* zF-4SNP+?qq5oVyT{51g+QW~WAC%>M{*YX%;Mv5YHX{Z%rUSLj7ue$zZ?698yT}9LL zx-2EA<~10PUs>8y&3s9kcU!ZhKvt8^+Ipqj3so!wKutg$UXbnHUnEO0ID>w!u;YK0 zV0NDUIR&&VeE1x^ri|=ZkPi|A%DGD0XEr`mu(D=lcSj z(Yx0(7z6?swMCM)Z@#$m)=aTpZloc}VP2Sn85)uKM0eQBw8IeWke5uJy4vfd23H>p z*Qq3lY;_$rs#o-yKk!4?(MLUshbHR2h+1?imf1{key^ND8?~cHR#5tZO`nL${#u^JE!nML ztnVd@r_uLOFC7KtZey6i5oUGheGD;H)EF{87$RJY-zUhooZ3G`d*)vHgKMqus9(+w zUxLCJ#|3rR^2JO=F1+Z7jS@o3rEu83N+I(6%f43fV!U5ly2R*eFHt|}Q&!ki_?G^5 z_#qzKIsk3gcZ(gJmr!F*=!@RiyxOIsep?^JY1!#S1U&gmw6AMgS<>?GZPE!H%PqQ< zxE@)%`n=wl!j++uC`1gFX71>-Q|Xc>%{DXoaU4f;QYW!cds;t|H^)b24_hkZkZviq z_zm_54H2h|TMrcG$}G>5%WIr-9yOuy3*gFGB*y5IO+Gtvgg@B@K@mwi z@zLsac7M^?P82WVY}c0_$zE1)7NF-{oZb0OP!{cxIBI`Dy>{-09*H#IGymA2Oa}5@ zb#d2{y3KziEH&V=Tzw}8leHuCzhx$oE0S|(XuEq^$bG5T653~86;LKy$w_;PTR6`+%?_V+7PnFfSFfRX1z%4?GE-xZ zD4!Fbt)AMnKmpVLL`Qw;L)V``Z7tE6czZ=IiGV(7(B zaKzm#R|PvOwoWPf?-gz;^guhjy}2ar$3o<+dNqX1R3CtQYV62W4Lw+kB-Pkncz^Qb zS&UIc7jADWg<|t*&9OhxZR(jzT+?NDRJ0jBD9;bHVEN8+x;Vi#ZrLn*#}mK zmAve~%Mt`M1R#-l;8N^rlI@SpnxIn^0T9&MK^Nq_4Rmy>V@%900xG6TUZi)^G>Nw% z;rG^+Rh!ZRt@l^F(TVzGAvD{(b%)_zz|5 zgC~^H02&E$IYFNcXjMEK(3~H~@?J@*8Q{1)Ym;gIRb%}ggHGdt&50f$95_q_ETUFA z8$|x0r2OSrgn74Ivf>-C?9_E5EvROagyDO+rF-xq7ne3VO@kW1?Tm-hSWq9>pXf92 z&F^@*w*C-HrJmw)l)OcwBY+}>Ia5<(vn_gTV^Wb{U^zWg(kAm|Z&Dy=f*6@Z7dY{Y z8Pe*)8=(Nsq^1&tH&NBJPU?!a_1>>F_*8c60?U@LBz!YI4gc_Qua}-EZ*Cr}>4baw znQdAGP1#(PR(sC9#aafuY(5F-uzgVn(W%5DMcVceLno6#f2M!^qI@*Jj@dSZ=XD{P z1%QaTErZy%4o>!sWx3z%x}N6KA$CtTSxaJ8WF{Ak$MV>W!Y&G96o)K;-CE>MndFOV zt-CpzFhhijnZ}b-^h^M{4I!uhLax6f*x0)VAJJcEEigAJYSFq%PPWkFRm&(+%%^7f zY#g+Y39jg588Qa0H4V|~pN9kWn|1h&68w-_r7H2L@05#70%b%IuZ!ggQzjtJk%x;8 zGIs&e=Wmivre8JdHao!_2*oekt&Gjd9uf9NB_ySqw1a1>V=VWPGQ%Vd)^I+OL7oQAnfQBxXGpahSO*t##%ELC3ZsPrp*4w;dE6gKOm{onSbyf?G5W2`B})9fn+UO0G4Awc zM~p1DnVOa^nA@SJ?T4sF^^P$enhN4o z0joFA(45=vUdx+`lMPsBL4yd#RjV_R+i`(lR5IQSk9{${okae1v6w#fX?iN1H|ddb znGjsTZ@2lzF3V_b2VR1(`OFoYr;hgDCGsklb3yJX`Pc9k6{5R1)Q^8Q`#;klEiyzh z0Ei*6n#H*#8@5~{P}kjsHR71g)Vwm!h>eRhm+<+#9s@=3FKHO_)=pIc+Ts$UqxZhP+sz|ZHRf<}}_RKOD`KE!9t1_l}>R_MpX^o29h`9(2}5g(r%-aMVx zxo@?{a-lq<+;NOyClByWcT&}j>3df?D#2@+Dr)N|R{K0x=W%yE&K4ruCZJHm0rJc) zi#C+IZq^(c8;_n+y=!4nGey?1VbG?BG)`C6{8Z^F}a=Hk+2nMtuu2@rzCtCov$L}MDH zB9PzQ2D?3$n!|eE;SE#sM{m`vJg7MlpE>*Fx!!RL+wb!4q}%Pv%TL;~b{`m`?J zxUqh3a3pgNjiK(YN2jnOE)a;Ic|CR;9hf&Ro{pAjHV2^5V{f`J{o~ld;cNT*)0K`x zaS2VxbASNm#$o=?095PFU~Z;gi%YTTM({NlT|G7j(POI)qH=gotnl!;u@YKzTQ$kWqtG^=c68zn2Di1nPT9iZb?TEZ6wEW-@Q( z_W-=;y#=&k$T{|EK0_E+{O!L34kDDS8}7VIPg?$5*3sL=)4Q?p^Wxy*TsXi59D(o$ zmro|FBf0JhYU&FHNY}dh1FxT6EQdO_oROo8k~Y9pqm|$%9u#j)XIcgOCs$^oU;YM= z`g>QnQS%$x=`ebGXAMg8+f$l_Ziyphkw%X1ypee2s~}@y{td z^;HtyYy7qP&dUR>&PABa8JW@_flA0e%JCyWuA$wShrQF*NDze1k)l0wgRu2K<4@gq z!gsrm=Sn#p=PQ^r3Ymiq6Ql!&I@UxDqZPDiVkd_`emE3LQO1w`USjsqBn{Y`|M^-? z_Q$;=x`@4_-MoF>xUSe3cyG>N3Z?z!oyNAj5QcU6?cyi-f-8ItwS2mVZAUF;#kv5a zJmWi<1NbaxuJaMBzWljXbmjrmr#UP>Q#oZy+s{^HB-BD|(WpwpRpdPS^v)+7dFngZ zd3%z#?4agb@-(|B>9oxR85D@%!7y!6tBf`>0;7G7(kNXki`~Mrz9(Wmi$ICa5tOof zJUU$s@SOFyb?Azl@$uxhF?r{110I-Sed8y=6ZM@C-yx5G=}dj|mhk$4SMK2C@i2j8WfWvUVU>euq5ZXOD-+UVX1IH}4DfcX|b9PbNHN1gF z;KItGfX5NBq?jWN(w83V`sQz5T!i51b=r?ba^$D&)+-N-++IDE(6Zp{RR-Ml9=?;; zxd5s8aI(eu1wq*AC8^g+)0Bt^bOoK%SXdi5U^Mh~J^w|kOr@zWQDk^eIYSt0ysq`i z21=c?0hr9SX|z#oJe*~Qt%TV?;lg}ysq}F%vr_epRZ&l*6##|JzlSjGFpjtX`{R>e z8?c5zM9Y0kv1U$ON@NJv%mBfAm~=cpDgIpL(Il{R2*|Cf&P4Rf&mO4f*TdRN#yIcu zU?-8L}`qNzLHY7yxa$NnztX2fUf*ci`Xoe7&d?7!}lybU#oZ<0v)18Ve)ivF0 z^8_|}b-r*o`JL~tyD}LcNcP-M*4@SIGGy?Q*GUE^>dlw{7Ec4)&O@^tH#^4MD;zQ9 zm3{mdS)*fx6!0u9Z1kyIY3l-KjnwM+*6%5gf6Q^pVSZMwB-%gW^d>^I@bZ>ilzMw` z26CBpE_dGMku5#UXE|=kQG76NDIxte1gKzVQm+0qPq2J!;`Jlo!hsIV=_BsUmZWh+ zG)|8eQ}JK)$SfBo`1)QIk!AV~lx4cMwdiQ47!Z2POu$2OKro{9H&1YN?P6^fey5eF z-Q3PW4Gp(%yWWy$-WkV?RH$lfoD6(v%Q`7Q=GBn~?#OvG$t&iYx9n^Ov@kBPogq&7 zOzr6IAN?GaEWdV=;HKgKn8$z||1yMMN{ZVqns_IS=SoaGUja;;A_+`vX)ePs(sgP2 zLFx5RccNYO3xD4JkA`B?xUYWo`3TEhwGKT!j~7_+Pz`1#<7j543xX0z9&w+5vK((J zZakOiY8#UBf)YEfR(ZFF8y-7q z#ofLWwiIM2RfRLurDMcrn_AYiY(7NoG?p7QB2c?-G5$zPp4(!!(8@j|Ay^W=8DgF# z=96tY(Q|zH`86Zn4}(l z!oC4Vt;uu!$_Htn_#O@aJd>*8;16PK>sE^_dD9z+3i7@rE)$yeBm$okqygb`_$!ky z7v;bjrUacWIO2eM-BAd&p)3}lNEgqhPfJGY{)HXK z*^73`_TaN^DI)&Ev08x*sg7+1pHX@eAu-YJ1U%KYKbU@=_X5aGuV-5-U0_`zLf4e! zkszBY6~iTq5>onrNp*18&^RG6Epan&3tQ_vHA}F^!ehj9sk$hwul4@N5qTWSgk|81 z`b$PJ$ZI*zYeI;eI!5<~lP8c_g3B(8J^TETBxFq7P5hWbiNx|WXWUI4Yw+3_*e zBY*H#Tt?maW*pBBwJ2}@B<0C2r7?BJiFyt&28eWTl(pvn6+Vx`GkOolU57R4N~O z)3Pf+9Y{0tfb?@jtb9bQ5q3@|3I_(Z^L#_3Tu*(Qp<7komSDJVgp3F<=Q9l%WvYewr=*BsK5SggI`x)&ACL$2(c?s&~xkzJ7qyuIi zigs%Z1zGv0%QW!9)bJH;*uu)7k+XfZW~H2QDs`+U&9B-2#=|#9-&O8LgOe(o1vcje zhi!M;mtv>UQo?>6NODF19|Pz2aX)hWnpx&cQ5Ojm6ML8!ygq_Z0&u)=T4$qn|Lbkow>Ba)zRwHC zeq?yj=!^XyIS^}Z>s8C2$}f)?{ZKHea~aYx!!LH%BC%36*@5Tp0__x2YV=!&0D=tqVA(RIvGbVRRNYfY3&KuVO+0fajme;<$B|w6@b--e{ey2sw zYS7u&6TYYw+b11G*8Lt5%!pbyH(8Y0m6dNGW`{1nnU9Kgp@^6l?))?``_)o|CePC` zU1T>ENWk%+QPRXYOT2wU)8V6)6&0$}o7vGK{~USvR$}AJ-33{-oxifVZI9`ouz*wsbM3DC9_lE{=%`(=e`|nLEBlt? zzC*>OwM6oyVr@5SHm8eKM?%yQ>3_*6HsYL}B_;9^({^a#R|{-dycvWqI)gK)=)O`j zuzwtPJHhwT>(3Wv2?XZwpvU0L%)x)xY;Sh=SYcl;Mnf)w*HEX2I@7S_RLDuD zaq&ZtnqpA#6PtX~yp-4J2^i}%=x;=1%|u&GehXhzk2Ly+DfRyC!HYGH%?5w_WryjM zh4PXKdtb0R%~Y{=c`BLB$Mo#$1hTLQ-uEDiVE(ngM1E^O3DJg!wX^t3rt=u`bB(H; zT4E{qnJCe;AiyCLzq`(X=P_xS@+qvz`ZU0RH0tp9Pc(@~uLR}x*Qej~N@B zpH9y>Ky^=Fi1JF{reJ59hFME0kV^15_Hkl>A7WLDyQ`6G+>jRT;ufOekJp&A?H}_ULOs!!P>Rz%P|LQ#>ZUT#v9T5dtYpuux85BU1|}ipjU`X>MuoVl?E<>pLP9l8L834>#YsDoZ43X`(*qM zLI726>Y15(yTMuBOJxpc|JarL6n-10A3XQRlc0MZu&M&9ek9t1$8wsd%5=EXk*#U6 z$6C!sQTBw$y39c>+RxH9c<~DNEXBLgLpTb{wk9nZEY-*MYv$OS+}r@}r5)!p? z{o1cg2o$Wh>hOa%QC}ywJ+ZP+Ft1i1N5DVvzaDNtA?4T$T);JQ9GStk}Nz}CFz6i z1QCE@N6)gZiuSPIa%_dYt?U7aUt2<$eSN2;N{A>eusUkvFkM0^D#zo*(c~q;-ofeJ~0bRVz!;`8MyWb zR?~6nl+|L|7Vt9kVzrLkl!SKqUtK}m0JTrgWqQz2fL@Hr`JulMXo_4MLfxK*-4Kdn z8j7R#nRBM~31x8WWuQ-tma)W)ofkDbV8EIsQ}1{<^I@yVoqEcG?nFmM&q2>ZPd%Z% zS6rYxAe$?qb4TaC-_z$Iq4IV6q2J)&rw(zHM6R|YNhamtuuW8R5mZpdmUy~`*+ z_HTc*s3axP$i-X2x#dt~2K3jwgVm1#k{_X%(JCgBBX3%bC7*&RE?$k&e+}8e+1`El z9o-U$X+3elkv3b4iI2baMSN9aW%a-Hz`$gm&A_x;*zwq@N zYBK>Pd}{{Qf@PDk%}pOK%N%zvGf#SubT{Jsb5C|M>xFW3BQ(^FFA-d$KdXLIU0VMf z?sF?8;&KUfS_+mW72?^92WmSV2$cwp4aq>_q}`{B$ zU1GM~ABk2MB{U~A^6QEd^MuJGJ5NnSAJ4ijlqFasrQQ=K6++?6`uuj(3W`meJ5ag2Zn+h7FWrhzO zmN!{9ZY}x`_Or2`aXOjXwSQk{$}*QuYt*tDUebDh#0tnulF$%uRF`XIr?Ot83^~gF z;tdu$9@F62z))&*{}2yM4(FTTl_{OIZRn)FikDw;k&))^rx6GbF_6gt!j?f~k9!Jj zNJLb12RI>eAXvwzhwI*J)=CeHmU})iVBQ~xEg%zlOYlYPeXT*>eV45sniy%a&@$$o zgWZ8u&T+*okMfr)aY?W1)0VTw^n=Cbp{t13`t3_Y?Ka zNPT)zz`IhU{sEWlj2qL7XpokJBj1hl@1?1dfKbtVPUCtt|_L`d|I$;$Gsd z;!_%uEo?pfCt#DgWh<65eA9ZPUpmq61Rr9fT=ujDSX@H)61Ulg4c((+$-6}t1iYFH zr=k#}c0btUga7+Xw3XSL?b%~=IpTUS>6+$k5$sA&L`Od6C7gHnwtbkv<+Zip@`Utm zCqEk;PTfFNV``=Me8E)h$@n}G@0e-ydUE!gCP+Pr#(y{jQOc+8$;KinV#v?tEGtRQ z;Pv*Y^tCQyv14jeYV)JcSEesFziW@I`x@}BBQ6N==a)%>{)}-xp5&eU!{?g=4j!8g zj2pA#yOwt`x~GG7IT0?;e$l zV-@Es^A$|&o)9L;lUfjjnT)fZ6d#RO`^V6*FbdB5lryZ4xneHaH15NAJ~s!FE zH`r7il6W3NlZx|{Ns_H~oK@1bB11xmFmsZXsmnDd?cWg&Y+$eA+W%*#+3Zl`+g5<=!x;ny zNlet$+osKZ_N$*|Q=;)7>lga)<8d*$(mXzzQfe=}m#0Z33z z`yjxA0zYgXW2Sm|fk%}oF^W%se2I*M?}y<>b$ks!ZUE4h3Bu(hc#ox@n*=gnFYE8G zvn&7nkX>`>9d5j=E`ZMqV(*`G0kVpgK6?60#(TS6anY6b`7eFK&Uyc7 z8mD67i5}Crtg7gv;E6!rinFX7kClNuMb5vghU_p2 zm+OEmOUOJ5aWAG>B>lKo;^e)4bC>=4=hxbz`<}42<`x}ZxPifmykJ~Fo;Ey_ix=g5 zbHI#AcI44>wDj>lE%gEa!bhPA^jjUUqz9%xK{_TBE{pU&_^!62kI;{X*}eYS4ZH24 zi|({*uUcp~UH_O}d-X$h<8_Pd`fDHc^!3{3lE3SYrS?C+x!o?m@J4@XF2C{pKK zntWVZV;9}r*krs)%C{imWykIwyYTn7*q<-F%HIFMciOw&`$oyY1Slq|UqPw%Q|^y6 z9Q!3SV*gjw?Y`vEpCHDmS{}S-owv=W(FhLcfM(elNJU4$*v|HqAKOL=f2Na|a+3Zl zo3-_}>ZPsr%b#9jOCDctwN)1)Sv_>wfN!TI31r`kCmd$aYHuK$*y z%tP|z^gJrc75Gg#Zt?ms25!s zL*A5tMoUv`ffIcBBrRwo6P12Qs;`mpG+KXmubpuGT>Jc2KWO!BJdhqdrA!GGxx_9L zxv{y;{&>kkyY+vrvU#&7*}wnjAFQr}=YeD8p`Yyk#TPf*iWk=VzWJ#qUa&{*yvI&| z%NuOYp$7_Q$PPPdjvaFNLH7KL?e>+=eB0^=`t9V`zS534?ojb5L)Q%BVXjHjJM6Hd z5AnN-WxWHQCsvuKB?o#;KFatmiy+D)uI8)w8GH{6cta4PeFeO{hza12Y9mOZIp9Fz z5XZyom`tPxWQb2JS!35+`H21gzi+l>iB+(fVxTy(UKP z8d$y@%JZ>J{zjjcW}efC_Q_8rrc43jb)YX5XnSl&9y8aP`8tpnSKDML19keRa`El7 z@Wk3$6^0)|SM`GD+#}C=)Ae`T4cFXZyS8n$V~#)8US7M&?!My@yZz?-Z10{f-LKqv$4&3CUOX?NGv_3Lp=!KGB4l z^}%b{R+X*`6OU8U$O%zi>7&%yKA_rpwUe>sp4Z2}Q9-rJ2bEsBY?EE^i)-zr=i?1K z?Je5#DjxFd!csQIs=cGP7oGg30%;CJ%^KKq&Uw9^^N~0Dw_%H}MnUoeBrl^NWjLb=rr|kmIK+Ag%4e(X3cq@`$?-kp_I(hRZp4ys5e{|KSJX;5jBAO`v zN>m%PhSvCwA5i9xG<~KszyYPapauKE5BaQ1xzau}kBt6bdAAI&P$L@h0m0J+F+xH) z4J6UTBcEwdV{ggcm(zHQJ@MoQ`^68huyrr4x7PL+Ywysq%KpifqV`TcXle)M59=U& z9EwCq!c5!o2JShZ< zlJT~kI^So<#Bn@*5GV$b&?@IB-aG z^R*aDeYv=^$=VZeQl$?Zs% zX`%3R6<=$r7hin2@dF=ziyeEy5!T(sS8L_I-!-@W;-DB z#12@LCMJg#H$1NkJZSpmC|5G=s=6#gdO>J}Q;Yt%F3Y4m;>fx7>XTpL{FPxWZ<&UU zIH$zNk((uKZ&=xQ_r^ZuAtR%UM@D(pf;3kl;2%B)MNS4AUPazo5|Hf}*dNCXPpXc$(Wb;K}H_8`QBu>h0I zdq!T?z89AF!0Y&5FOv=i`s?kXh0E<1Ke@uTZ`o<% zI@7^zPkU8(HwP6ZN)9GjCULxF$a}8P%{T*j z&IrT)q*+Xc6)V=+V-G#AW*A8D0-pCT$aYDqns#>LA%Dq|*K@;T1*D8jE5AAfC=VXj zg#AWOp%JI8Pw*O|gI5lK_f5hXh`!3a!4&oGG@N4an*d%yw#z^tWn7?A=M_pon1XB! zkdA=Re@OsH!anOLlfrtm^4xXLv-ao97TWKBbG_~D?D6l{@zfZAa=afh1zGe!Ik$(g z{sG>gJve9w%$#5!`}o;*#4F~=X!-tymapQ@5>So_$q%KjEb)VJc)qCdt0JVz_+#iL zWWI_Q1LmuQ>NptT<=le`hcw@?paXP)M{J& z&=P-HAAJ$BJ#m(mfojV9ryS&Y2UyyR2>?{u@TXYZyPg;TuAs23tFPnkU`)OtRmz`h ze7V&uM6O}i$BX=+@1&%Y;Huz{LUM|ePdwI0E%L{95hG3mRY(Z-2&q^UG`Osz2Roy$KPg$9W&RTZyg-!cSDHlupvBn) zHQ9!Zd+h2f@3-r(UT8O7_n>Xt+8Oi&ersAEwk18?8sD29vHS0Q%I>&jk*!*>(N_&7 zAWu~k9eF$NhuA~t&F}W9+^>7XEOp8gQtwq=S0T&B*4He4as|yjLuENGBUa1&zw!k! zef%9-8qS`+VY}s~$L+F9ZnwccekPxb`@s~z)_}CPQ#m1*2T=H~7Y}V8e&ifG?_+1U z5s&b?YCLkGY!txVpS*MCiYfR^x}##pp|7e8zUNe)ItH=ILzUJ(LG^G!pN=mNwfwoQ zcIyrI8E(_0xgASTz|L~;`TF0ag|9TQPWx6_t{5LX|KDkWo z>#Vnjr_ToM>;L)*|1A@KUSO;qT`vAB>)KZxc0k5u6(0CNWz6;w17*C7YaV;@g)AQh z`zlO=K@|TZ9MS6BGhh!r_^j>N-f!1kbB~t)L2ViMHgVA4WXnOq7fg+0nE?RB@}d-O zT^|3c!|dFTon~|APxI3=TN9o)h=XAvkSHNMAX8RZl~(W;cnOtumGS6YkuYbh9gn1yg8fZnHmMzQ}I;pR4S^sV(-cpM1fZC$wvO z6W$jdLFLZf`gJ?(#%u4jSG?i~d(CT)Q@z>Jr(X1TmCczm**^N|_t?Z~6K(IFUc33G z2W>#B!TIOE*ALNKHt)7y|MU{88R)SOe(X#;?3IUTGKqjDlyjthe4KK{)Q4v;yu9F} z3|UsL+gDk+uI^KxEPf+n9{^%G05oDySe>|!-q|(m_xvyY;~m@}yoTE`Z7 zVfc@~?8aqE8@f6L6Y&(5du3JDYrtQ5>@54-m)>We|L5~;=0Q`mmyEB> z`0_3~`6wi1l?PfVkqgP~fd3|j(&hJPC3u>0wZe<}@5U9?;3htC!oJE9%H>3UO;iIM z*HhyfsRxzekpd_7w%qADaAvFh{TJV-ZNUk?#tMka zk{HV=Hzj!Anv8U)*IsqPeEZwazSqW0)gDbl#(ULhlR^NQ&Xa%A_nQPL$#nn7Yxx+s3`Sa|UR~{xDyefRh*z)~D8>zQz{(O)9^!vZEcfap!JLhlS zt_eF>b%vg(>VXxrk`@ip8Nx0`*Jpk#ZseoPzpX-nL_`*cGGcgys9;yaVz_N*k6nDx zUG~eLUTxQ2aj!MhHEPzzb;j!c45s8c)!z5MbX3Ib8@Z!)(g{b{o6kJaKJw|eTl;=3 zQVw@>hWy}y81!Eb`E_i-mk!Z~H|qXkV2C9o_}M1@OSX&)Ie}4a1?BQg17p*PUxu-C zMzv9K=8<>S^cMTf-@nUVd&bHBV>;1a;J5=&@G`AhFTb?W7T*1&96`vQ{ebTinY3c} zz`~EqRa}-E^c7DC71}`X7-{s$R$}|sF8kGgUtzc2a-V(iE9cu=-|<@inE@tOYR2y+A_2`@oa-4Lh&&eT+am3YcK_d2fFPI zrygaW`||tjBcFJiPPt9;#vIlhwJ@|)a8;NPEy^=QK0@MA&Sf@n;DU0^*V9q$+XuBS zwT~Dm)5th=km(Hj0&t)a6F(qn0#NmvH-$Nj$Wu<5P;2LZ`ki*b>{(#|0wx`X$a5eV zCys#|Kx^0Hg&zxpa=KyYPFXS|G3oG>Y>B0JCc5*F9Mo5Nce(W8r)78U?6cqf;!1mH z!Nc~AfBkzq{cR^&Z-0-|@~(v2z$#nYVAouJzy10bf3WwTC*%Fhd$p6}rH*lD6nbf~ zDLVE{@U+VWKShBc(`Ef9UIkxlv%-Q&K#hLwoL*=j-zW&eNeDn$T;P6r?KZpMx3}0W zH#}q=tsP!g{k8$^g9+$~k{fTMaGG^Or!xfPrO*6E@ZWy!-PYKlLN-RK^uH48LG)Bt`B#o>aTc42a6Tgg`2A*{ZocewLE%4Pr zXyA6V@*sJvVonnWpgl7@tCh;+O{J@yyY|{0w>;o?E}Xl0l5p!9>*S5=?6N=HZT}s4H-i?fKZ50m`{73L=PXic7rlE^R1}IDUfNVc{ zfZe-Uz88~||&e2Wl0 z=N?>tojpT#(S>))fUmU=p7$R6(8tcQ_=yDJvOSdD$dsL~%kC3NGL!exfYfh7MMo;4 z1$EwDE-SA@PcQp8RfAosbO}+CkGku zpLZ1k`eNy;Zy2^Wz4ev$)o*;%KK6I-um+xO)n-2x>WrwZ=hTkF6@fg#(+Y_f4o7<* z1=4(*qSlQ#%Godou}WVw;Y~y6d}Ub~#^!-gU~GNL0myRbmdnXk4Mp6P^b&O}?aG5* zgqZl^+OJr|86xgd6(D{4n|y?f5x2Brz;PIMQsw^r15I=+bHYogD(VUF%UH*F^Hri% zD>vHWN1n3rC2MJJw#_?w?dBWqFy5WKa@9-z zgXg#F0RO<XfKJj$Qs#Og2$29j?1p^k5}ql; zaY0vlcPXh-8N!8PS!SrHDxHH9PeX0l+-0}lxWMG^FBIdqWnD)h3u%9V zMty;h^s;RL^1v4lmh(J_0Q3SXctwok;5%)i`--GCJd2Ie6v+cn7vu)*z zFWDV;F0{Mvc*yR$Wue`9^L@5){g!B_{rVxonRn=H>+0&Ut1iFAZoE#0e#NbJ$^Tqs z&n#XVUnJEB^NgN@x8OZOxeNe5(%AwY!v^)II#zoeM(`X^=tj+I7C-fZwz;ZAsRhw6 zGVN})?^*WTdb{?j$L-;J9=DEheCwbzAO&zp<9ksJ%x(oPr*w2Q*jvsz(cb&P(^bT8 zqg5H8AJS!k68ySuk;h=GH3G`Lo($Y`3eEjd&<(U`RjX|VMetjxQ^1UwoGj>ZyBjYj zeq8h65rW5P=g%gn46wF&gqiwAicYGj~7lZLELhQ;CAFKw!X zOKr8yn&{MvCkzu2(IqBG9;oO5Dk{qI1lpH%81hB%as|elc8pui;~21r0(1rtd0P9R zyY70ye)64*by}WK2wpJgibw@&)@k$0kFLPl_;LKi|10d>A2?NqlM(CZ$uh7C#4~{?%UL0!3c8SYAj4co4Wg4V;w&IB=R@kalo2{vt{USdwuH{_x zxuxx|sFI=@)c*tx{wq&7#9BM}En}@#1rNzLF(GBia<8L587~6{myW{?7?pFX-`hK4 z*IeyjI2~xyLh1a%0OeWFq|UO)3R?+ePM|#Ufs5j}X+^SD6VDAe5M%Gjvc?irQ(t4x zF5hfdUG}g&yJ&@9C&Yje5@xdvKp9UYH9%Ef;>~Y9&OY{;cS^{C;*w4%dMpIvQI|11 z5QFXXX$M|3aR^$J$lwZv^7V10qD=ufvs%+Byx=?Qh}l4J`u@&${>N4Sa`49;$e*Te#8zsjH9IGd*C} z{`qzpXoLJkz4HM0>LVH=#3rnh_{UxZPuBq8BzVs2hO$Iz| zzh?WdUwp+H$2C_BIQh=FoKE-)9I*v2?rP4quAR66&oPa4NdmanqBtDeNPmRLyi%s2njxW^fz%r zv-U~TRlr@f>N3aRmg5X%pbm!E_d*$(q&;?wsxUP5%S&p3r)6qIb?Tcd5F&xB`K3of=Ib@OhaEoM8rykx zBKk<0KqXHs_vpVj9V0wOCw9V z)ikt3lTnhM_!J!}&;Lj#I6taSzI>(f1j-jK%Yr|2EykXF`Xzhn(G}L-!oC+mQU+Z5 zj)vJopmot6+FFKBe(f>#nl~J0z5V@BrVcawHAselGH#ZKuxtmaG%9%TD}U;|6?j0j zm9WajL+uKZmi?UXc^$Xk&in9LcEpkM{h3?n^L_*#fsB_zhfY|+`7v;wmA&})w_Deq ze3N7-GyC*df9No|Dk_{m28kO&JN69OpD(`8Zn^Rddd{@91Ghy zK44);wDCY$VH4ze@(-x?1r79+x+?lqjJ`cVL_dX|%aGeb=BUOjgiziK-Ky)G?1kqy z+k)E{`K2?z4ksbhmvHEgC0UL62SJv&fgzhdZIaDDOkSdyn;h~SDhKF40%cW(h}|Oz zk8;OX6@ykTC+`pRD9|){CJhVV#jWa40&+wjC=@RpN{&i#FXd9t?@~;hP;Up$ohq3n zgUV@}0iYcZ0P!%l{@cCxJfV~K0^7S=o>(XNkSBNo*q8FH60VK%gMsX;{bvv~lXxC@ z*WMAk?9zL*=e=JBD!JG;(5}=kw2+0)R_OuNl)Mzga(<+A*Ld{ab_(Z=|o;AQy6W(+F!87a~?|ZBNf~qRQFkN?W#)`*hHOX*~8Hyi4g;&8CZy* ztQHyYvB%G|Q(kwBGtNWkv~`cJfg#`9*YA($xdDm}<#<7iFTF0FgC9{GC@$=?9C9tT zryGwKzu(4fSNFD}&68K`A9>z()~rc3_mBgfuY^zlgACt=qKmeE{aeKt*ROtgo85N( z13Iv2vK93Sr1Nr-D*f^jzkz)0@rT&FgXdBNWtV}zxj7MoBoB*cr&h+iV&w*{Y7dFv zuvWH4^EVLb!(T%5qXC64_S%CzcIG=yu=oG%Sw240C2!@i0LbHgYb4KQmp^Q`|M3Q! zF{RbM{iDxW^L`zuA!I4F+gBQhJpBA+AFc+KV{DXWI}UI@`2~LErAPx{Fli}aoPp8x zbe8=_+oYRul;QlaJGIc@`Bexi=olko=3H^*BX-qA_sJ-wWboAwIPrsoq{Rq^?P*T# zF<=9Iy*@krju-fNMA2i}3xiX!+Bg%^w2PxZ-{+wWF_d(fR2VMbA46atSP{TLViwCd zRL1s(H`%n-58KB-dA7ar>{G0-*z>^~At4k)e{2_6S=5i{)oJo=-&Jcr{@$N$$>Jsc z;7s6F+X9s`wd2V-F17g~O)R^Y(`vQ^Dp8ocimu}RrbA(b)!N@pWq?d-~pYK{+0VG zL-sv3P6(X|uQI97kIPyfEFr3M$0g&Pgu;k(_EZOej!1h0g-{-Yb0*ss& zWmAVxc;PbLa-YcqaV4mw&a5_Zy0#CJoi~nSM1DRf+9qy-^8uYA=iI1};1B2f_CXop zHcA?3mikS7QdUX(|ALEhxyCQw8ks;E9#XE< zMU>%$g5S}21+K`Da=DdIt@l@^p?`iT^DU3~;gA-^)joj=egWix#H-d9o#x)R2$YR_ zoDzT`UIohUO}N)82xVa3nc($!RrK+>!9B_$6J^x3)RzR}M4;2Ab!=6+5)zg!Ad1y_)1kLi@4 zGzN?D_@yhhRYe}~L#@*O+aAJqJ<$v0TIvUNpslrjJMQ>7_U5yX7awQp;1>Jo1p1?G zLdsFOtmRfE1CoAN5ulIv^_Q=>6hQ;Xwn@)pjMsAkSy!tLG!0xHz{}N^TgPc5m2xP! z@v6Mk7a{uwvJFr!2g-H+g;~BR%N|>Fs~{bMmxO&8lG3~PcKOL3<&Ch67xf-!raXbc z;I2>7$W9Zll2$0!B~;2t6OX|QFA!<(OEH&*0ACVmMH@{bJVF@tm_bp1e_CPGl&3*O zA65SNw#4L)TKn*Muea~~;B)qY553tAoIMpxe+mpn!38SxiHkCE=p8bV{1PCOn<7Vv z<<4IfTi^pDI#={}b(xN#1yt!V+1vwHKu8!ubF&UZT1K5&<(a#38$q~GXc_^tgYuZ|Re|Xynelci zFZWf>d%a@%O9kbYB+}unJkKA((?acC5#BnUGfuh$r&P*=MI6Nui>T90ez~;O&@gNh zCz-wbeXp_a{_qR-o)5p-X3X8+pB(G$?f2CwX`(M@N|8@4_$TWG72E-^gtJ=7xY$;x zob5?p?_M1~>ul~^8SdLpw(tJz^Y;Fao?$~ZqA$Jj90}ljsh^CKck+xwm4Ef6D(uIf zK~Y&{D+q5YiLd&X^*~_iDFL1+IliDe#_GqZRohXPV+CZJ^5x0|(wQ$ij|A!{PuU2d z$3z${a{_HBs~E6%q7R;$G7swiZsCwk(ID13%uc27oxWH_;(|IDWxT^rl)UIC?P zNgbD)I5^eU4_SL_zrFXIlkGqM>(lnG_n&G99XiwBYmAPVFwhW5Z%YiYiurfn_){Sd zC=sg@r#+s8EmrZBice~y5`1kc}L zMw&Wec^Yn3#Jgkz2O7Nno8W^by4-Oh&>ngi2-jKrysv)uD3p2sDkt67)9dwo|BF}Y z^L2ffx&Q<%D~H(AD4?jT#DHQqHpk&+jCj-JsFO#W&|&uWvrn+^e*ZJ}-VdB^GY*(y z4f4qS+Bf(0ce{-J1HIa65X%(BR}b$&L(W0TGKkCrI$zY;K?hH^cb)TE`|gkb!OnW` z>ujig!1u6dpGloO6Ea=lQ9!=x2yg;1nFEIrM3lHb@0Z_-w$KkC_7cj zz}^?fofDtF6A}j^x&0_eI3%A5*$+_eDg^x4i!Z#( z9)CE#Lc~RRzs4)@hs{wC`09fI>2MK(1yxl!W@SWl5LX16wFk#=wU5)@mRq^d65C!+ySVmRV=aw!HrUf?A3pzVJNXT- zbmLA%rLd_ipqzFklyJRHu`6En#6csrH@p*}uMZxZ?T%X>v72wW)35t7@wnCtKRn!D zuN{@x^nl?&hnI}J{q3jPo8Ec?k6NQKpCsN<3CcYC7HJH>K)K9$SHJWGt=i@myX>+> zcGHDd+Wr$8?YlquqP6WmUS6FZUA%&h=R6G!r=xVG4{BAW&7@C~#7mw=yOTKgAZ&=|2ApO^%T$kzOpKU-;kYj0Tvr8|1&~Crv zdYd|_(Z2ot&)T?|lQe;No(0}ZZTHb1Wyuf!>-kq|1611)vpuOAcDem1T18#8ZGgAM zUi5J>T(Q6~30_Yg zT<|=Wq14rLwsr6a@zIZr({ELiSGiBv0w-20C>Fewpe$oK&0u9Zp~^!kR+GS~vHIp# zyZDa_?as??wn^h^?7Khuyp2C#vTxVQFt*R^Bg+%~TNXu8;#Pq+F&WF{WqSL9#4XeF zZ&{Npnk9{DeU*Od#s4Q#G>AcrJu2IWxS-E~;GM}cC_HSFX_5AJ{+goV27r5VZ41%} z;}u4HLxVc@!t&zU9zY}0nWvuilm|c2-qTtJ!RhZWXee;tiS+0J0_Zy@ndcSUV-l+j znaOiz$7}jFN#)dIaDI~;-6&27MY2_pp5V74Lu|K@8)NZjC7_886ySR-KUKX~^FZbS z(ur5b9Sh!)1DQVT#VJ5WE-(7ZQi5_nNi)mFLNVn>0r;$_xosHRw#+k->CBg9a9WH4 z^?XWgfU&%h&N3Nr6)A`YV^OYrfr!!paB={uA(q5)Czy$<3ZO&k2zX&9s}Sw8-DsK- zvfnZeK)y&iP@Xtr=>={TnOV!;j*>jIad_tWT`mTCebOKxujc|PveW;2A+r8!%el;i#(x{!)VJs~m`^dNqiSI*Kg21P3HD8W_ zeex(soN~Ve)K+fK0W|AVr)5Z*G^;c$BYI<(Jo4EfI~<*l8JKjkjAcIaVbJtdow0;+ zpMh760n$mAcr<>LWj&DigrqaJ-pf_yH#Vp%LV2?IKEJdbNsh|2_SH|;SNbU+@v=VS zeLQ=yslzossfX5mhjjq&t!0($Tnm9FVh9GF9K---~3L<@*K~^0WzKK z3BcGm@g2C!#@0bq<+kY%6L+6&1zH_Jswy`d@wIPct{LH=m5fK6#1bkB6=XdjnTYyw z$4+q+ZU%rh7%Fi>)&W^Z*}m|~dD7*d$ z_BE={eE@avHx_?iJda8%#N{)k)h*YZy`5_6+DDy76)5Y1bU7r9O7jt^)MvR4AfJ5_{u)%>nX4q2rZHcW&$~9DaWF|pg4yZV zPDm1{&w(Hv0R_6+D{cOt>5Wd8@yFsO4S;g`A3JEt697J203d1k-Z%=1ufkO82xB43 z%JsNF3|Z&x_*0xZDbvbHQZ6f}%TO`kay*)P*9Fmg(|PrGJt-9Ry=r=<;2t_WSgu{$o7d}Zj%sYw5#HjX=Oek^U*Hy8GH{+Wn2!c zG6uN9ivGPjh^UM^GZcsf)B-_}9r%|Og~zKs{YHpC7*ywmQGIAV9(V^&J-UbEhDRut z-eQJkNZJ`Ek5TVQPnV6l9I_13QKm`BH;w&3$qkcwN#i$7MI)~9I)l{vH%;I-wo!fq zW&}f|TC z3_dZnEoEbt{ZwgIfwFS@edAys8pFj;F4KVv``s0;!Gf3DR}31MiE9lLy?U<9VP zyT@$f#y#GSU*VxX23&N6fB|!{itEh&PTV2Yb2mUI(Yo4Un>~A~D<7WyK0bYv_z%HQ zX5>jzmie*5BU36WqyuVgcUP~iUb)4;Ma*&<-=L_q!Q$Hw@eolA?x2=nZV~g21^R&| z%QG6mh`GMY>!|YC39f^4w+?XcEj<51Y9S9w#DM!`T-@d4&fPHA&UNtOrF@j3ANt90 z;5r{_YHh8txd$KMWPIyGmC`aPkLiIo^IUVyV!QF8YptWD#{TQ4U$l;C@k zbP7E-MuxGF^?(n!E562db`IJ1{^L^Hw0?)=8}w%xFeEOY>CXq3b_5JJZtM*B^A427 z3#o-Da?oW0^YFXB9!lMz8|rwN$;(J%2yW2ws7)CDfIr=b5%4l_^aXHfPvmH#J|w?F zV^h5~X)NZ=pJM;|z0dl?KlBT@@rq99Q@qK5FS&G~-F?L!HlfYzKY#dn8#irYA(Nvh zz(uWX-?7)WZ`tFWp<}>TMbWO;j2S<^(WcCpD*wV`0d@XezZEOi!Wj2%MfuWHw-hveul4X%qps7jAYvYI=Fl(~CL< zv4ZrZwtP$ZYv1{l9ExxutUvdTu&GrHRW!=T{_ux;?cS^JvPm8F_HW<$q)j?-ioc+x zLRB8AUQT1lk}dYlfBN6@!f|J@4u_+OsGQ{Mv-f}Cbor(rdFaO#u{PlG<)T_Z5gq8-MZ~ih<)DYA6!%JN( zS$P1`DZy&-WQZ%=UU}xddxz}BmD}xSKf26*_QR{~(T85N4KgxD2#m6^g-(U2E3cb(}g502@s z+a9w&U2?7c+qb@I`|m%)2736qRq&AgSLmzH91kF`dQ|XAX#k$HY-}A6d2k{hHc%LF z7RJ}j1N;SZ8fAnA5s%xTz0dZYy|!k3k6m;1V*C0(|IYsOhuf@smrl9*G&b_S-Qrym z8W!_w8i@-jfhj&5V8!3?|tyRg}h4a&jTM%#&Q@CxP;^@+Y=l^`6#RM!Pp@fdD;-N zJu%=kr0YZvdeKm56}sq*khJmC?4#MfBo3|6Cn@sq;)W{yvv=h=<;qnQ9T;nd)Q1A? z=#vS-wrK9W88&C$el~N~IIVo`Hf?5$%{X9!O`JH+>2BS+%kIAWe*4-tK4nK7J4;)j zMr|SZ0e5JJT;Ta#HQ$Mco{$?z*%PvyHkl^Qbb@O|MX?n@PoewN37QBDLF_XNWAKvb zfM*4^Z11tP>w4_^s~)p|{>NX~^;a&i?%jRbGUPq>qaXaqe*UAY?3u?`iF>?cu%7J*LD!>ExUI+IhVABpWx~L1{H-P5^2%)yo+5m>ap^9+i2wJz=`vKlAh0U=z6^-7Q91? z$>-aS#3}fWJu&)>Rno64=`V~ra4Mj@e+t^0H|?;;7p=6V&#bZMpI>h~w(s?J`5@N> zZKgl_g}GsbJB?DbWqZ-AR6K?8aC{#y1!gsfhNZVI`p^<(%Eq@F4|qMhP&qSWO? zAf`;KoC*qJ(Xc8kdm{W&olel#U-z(m<%_?tTdrSZ{daue{eDdGJ~F$z?0}4Jgy1 zi=+p*RLZAEWAO1}Q4@8!zb+ec@|bjhR3K%JFC3?$f8yL@r$;;W1tcDE*{cSO9$d=H zx``Te7wymqJ;Eb6U`a*lS$&XJU~AOXwb%EfLppQx_VStpP292}D}qj+wgEb_*d-TV zV_*AU-?uM+@q6}Hhh`NN-Tehi<6K@cS!VCa=!a7^CW`}Lv)MH({`^B_OR|d`AjHQD@j6v?=yG((2c@B}EdgtBaDE9Fp@H6hBV5Bw}E(*oSK{GTe)0K>B}KQ%)K%&xfNUR!wY6MhPf!6-as z!3;)G>N`52KnjAQGb#ZQvCIJN#||#_9!3oZI|)~+!&pH zLBrd7GRqX4oya>M;>)jPMiU=g`9uwH6ve7k^|+qTCOI`Xe9p3gTS_g$z}X zo9!KxR9TFs)7!29HwJyMIV?S<)FGuMPMu7X%X`;kBT1svQpxGT_^>|Rp94- zk3MRqU3$fj?Gu0hZksh{f*mls-A+5>So`un{k=W<$kTSywYSDf>mspw$#^xYzKs#N z9D7j}?EvSE!UEtS^Er8ejI%!Lvb;RG%k;`PZn0je5J(73V7ArTrj4DpbK9V`V7yv( znQ^q`=7V2N@F!?dD1#0;%}g+lDt>wJp2HCav+SlBvIsujuF3^n=$h z_7PvI*@BSwcETs!-KS-pmn?c8G4RA53U5VV%K%X~0@np5CLKsXbi+s?GhgdJVD z;-(y`_=~zSWIxn7Rc5Tmsz7;xpitXjmtA^?J+pY3HEIvUce>yMTZOKMOxpr^QKjn@ z*YXab8Y#MWkM(qKv)-O<+KX+oJ)N6v&z>#T-MLl!DwXZos=7TM_Uzs+#S!nZuI`?~ zW>B^aOP%4N2`~$9*uszwaqBniv6tnA`?}+YtpVprvf!=3jj}>H%DQ|`J8m9u9hBPK z8~QU4`czgT1!QZKqyt?$Y-F%g{q3}&fju(tUN!8|9&(p;c5V|--I8OM_4V!XFf`C* zU7g!)uj&XxLtW~#Q-6Fma9w#y?3|km)qMs7{t5acym+Uz4Ne95+bO0V^); z{w0*#0X0uP`J5)HI#2_*egOthCx$m{?zNx&@H$()a+CI;GGH+QyKWRoNNuUZAo%M2 zkoDNP?|+jWd;Fm;5C(%6<_cX~M@!K;{ovJ9sD5B&+tx1o@elrFoqKxY*FcM{0m||I z3P3>aI&lV@H*cbS^3!MA)am2hGlG^&dj>TC&_FN0a6=?bukHba^YX^M_T7KK*m`z$ z`$`h{#U2w}$>pnz$_|<}$FxeM~sI4IrR9QMtxWv z`U?*&vQC%t12-=?-J^y${6>40V>~}!!N>5RmEWo$&+qItwbWVb`1rj(mJ4W>2bBL! zt?hQ=vU4bNxVw%I$9ZJ9X^$V?Uw@&D?F8c5T9kO|Um>?c_$PSx7(Z2d`=Uel**6<|yIF4x29Xll7 z$BG9gUJM3~0N$k_Wmx{1LeS)TI(;%p&}$ARJ;n;b>Vw0G?G^_zFBNazMur%#83=ia zGfjDOYlr>MAMUY-bP#KhC;!e5|K6s|p6R?-`-)WwIlA`_+k*?9w%`5c5}%ZNIy>!{ zV-B^if8+0L%GB}JJJ74uvc^9D+3(u+t-Cd@>Zhm6np?~|#%X;T9I;skOtK&R_cvp= zSn%fklz2;sI?BNf{sTxCDV68A14$>-fUnF?ax2-DA_c2F-q}!VTekGr&%S@Hz4YQ% ze;^vOh9KJwu_Hw?SUi|B%ndag&@%YpkDY0!pLM*|web5BEbY-*F6TfnOp1L|T-OBr zzw(bSUT?qr*;UrLOG{cyv-j!yOhNci@gV}VZBfT_=S;NoKXbOtn7yC8i1w$d=P&TX zctc#g4t0`Mo^`{fUi-JNUSR!uw5RlaG*uWRa)lShh%{B~$U~>vSN`>H;x`}!C@wAu zR+S0e%7GHRKy?V26EFS|A&0LB6sg(|kD&3OLjl<~+h-mp0y2FjP$wc<)SB(8s~6eL z7vEr-bM_zK|BOw-0~g~^rUx(0P0fA>bi>;1?){-Vc}knjm^s036GL`jV8m9f+$uZ4 z4z&6x@casngcYK_t=;m#(n88cdmr#m)=qB4{Oxvs{UCV5NSTI*1o*ePoQ`OjL5x+l$=j$`DGN94fl83M?dx!d-JNAy;HGWF>eo>6_s&_*IuP|O$l8k{R+)wf7Nw_G@JsETg+I%Q*?@1>L zl!rS4Ga&Zbfd>%NAE4fXmh%;!HhCHw(?7=U2Pu^Sl*2P~99lRK=UX2hsT8)?mzVee zdElNNdF>IKf7pI@_>t4>=woNtl>OVZD)t6l(P(b0v15;$X(ya8+m3(LEIU@=$YW+| zt2ozAIQdXJ_=wrkDc{0I#-Q!|6hIkud7e>;hd@bQqD{zOHQq8*`Hr--C&CmK<-Iyx zKmWoidvWD@+qGwh?be}d*RG8^sBE#lyEa*u4j8+4Y}7%F!`NmU>fd9Z_~bk6jQ5=E z7Q?S{M#l_D#N_jh?sP>ynaebR2{EF*)G@D^X`lYwIoi53>JZrFbvby@09-&B*si_( zcHPx?+n()v-6H^gZ5v$L6u5($AmowNe^bNx!XP!Eii4km=jg(X34`S-053a)dFMc7 zZhUIvJQ2KEGz?phi4gU{e?qp)Kp&Mn^-`6yBVfSG^|U1*57?BYZiszl)b@m}7n6^} zod5hmflE11;awKbqoTZ)i>Kq*>T#gs{cRG`CrKzCL^4&Uccj=JFyQI6j zd9{|DRzcUXMcXHO3L@ZOh9d~488}&AmLVbdEAtvqF4q=f>B!I^2qGX_yLNZmQ%^2e zb&Gplf5W;jrMPSjggh<=;OUxS8CjFfnYX{ch#7ASK%Uu#Md#Zq)t%>IkSt6jBMeX| zpX(Y7Cf&%Ki*>t zuDjb>8;9&$-~Eium^Z`nw?hIL&oCHh0BS891b z;kEPam{-rXqfR)`jy>@pn}6g1{MJV0Fp`}?uzV>5hVTwlBM^|dLHVUhSdf5qK=I@>HD< zQt;#|gb{Bq~Hl!m?nr^^qh;WhjfuJFX5eKpOZk6hadRLTU zuVa5HNG75aW>6@Be9{Amvn=reqN0f)4j)XESpF#z0)vks_`pXo^pL^d49VWGsK|ck zBMebODvzQ09YK{b5Cm{y(BP|3hJf~5=5tS6;??_9KGWF`Kssrn8|ne_(Js=i{^961 z+rT0?7nM#uz`7TWgKYO`6#8pt)a$)1>6mr}wMCN1ep5>mME*pf7%1 zG<2Lc5Oo0UNA;^TWm%qeDSwoOLm^$3Wo(;FXI<6Iz>@p5tj_Q{Om8heErQ>*5`dFHy-GZ! zu>eV%NlQ6tCK`J7K2;A*FLxTz#)CdNVQT6b8y>hqc6f?8f7v!}p@%$9NRVx5N1XhX+n4D?+knI+BtLGza367X5Ii5v zD#(;kPfUQBR5GC=2%bgFDWg8yBwn@$%JgUx*G46vyeZEZGx&Mp_v_9z@i0;7gPx+? zZ*aJ=F%t5c7_Zs@USA9*06l-2V&pLBls!eCr1H437R-FX*4|4l+mO zhn*M7&=dT){HjC)lqdg$`1K>{u%8Ei20hP@l=FpA7YkXSqq_2V;g#bnPk*_m1&>2? z@&J_U0n(g>GR@d~JMJ44?XnGhWIq5pcOHr{NW7HSd(l6-PC0?(rDoA%PmMr?pB3QB zViW^3jpczoVS!&E0F*mRg8m|BmLbYDK+(P`EO?OzpAhYxIUg7eo0Qqp+h9NW(N*^B zlP|glpp9P{&?g2^O2@N_#Lz&mz3ZG)?2LE4+Gjn+i%h;9p$Db?(wo}*Q(E$rOP||n z-~W$GZMbK^Cy3(}e7c8M58U!K(LUvrdG_gl{Gi%#aFv1X?YCXK`|Qr!9=B(ndd>%* zNy3kux3tDv==~iIBF7+d{ZzIj4_#w#J@aHc{=|c1#PQAtb>_PA!4f`iz4rm8ttJ>N zha02HQg;}#X`$V5)y+1(rPjXj&5zpw^JlnWyNsekXY7}g z2Ia0F^+OtiL@vtYrX7d0=f^;n6VM&oIOrxW^wLm+|IwG=e5?e{o1mP}Nr|b@KKY{% zJlRBAI$ke2h)!UFwBuGF85x@w0s8V&y0Wyzvf#;i z7EbUd+Tx$*3fu=s&Yr#j8SbF1+th0pU$Vfy`|V5Y_M0BE&Fgm9`j@uY)(yLD_qM&Z zdF^)FvX-*Vwr0&HTlext+q`+FZQQWK)~?xRS6+6HeeXMewEOQ{V!b_hLf%~#51{h{ z;`GgfQSQCuB;gl5W5lEhh{BeF%VRF5Lf%MVQt+l^17H3GXp@0DSFqB-V3bwr)lE&Eyn)r*=4~VP z-#@+Ho_uJTwY9d4QY3BC6ZvFQmsG#`t*^5E_V4gZf7~djS6w{@t~5`sMPE)v9fgtd zMMoZ=bnWm~oS9v+q!K1hCaLCg4^wT-@4Ei-1(U8*}Bu8h-1GSTO8?5 z^!$AhFeYh4(dy*w*+=qZ8OF7J=U#hx^-jCyst4`c-@MRnyZH&*xt$-h;pe?{s8mz* zBi8*Kkb1&f5~utC#tD<~T+s_Wpi7KZ9H4jh`{=?ClcLRCc}eM>ADXCux~l9Y0}_4G zgw&D#Ic|();KEYgX#+3mU?bEsF}$sS^58YLOiWIIbkHg$g#vkKUqn+^D!`)EwFq+#J(!7v_X5fdS#E%A>JuwfdrxCy{__-=L zc*8n-an(-y*$*$bM;};bTh?#W&J-Fk*oj-!2~B86J_e$KrYxG4f};YGor@06XunIU;6W-JIf z#^s6Wd@Jamb3h#cF0!#Dqs;quLRzxqj$FasP(TaeO8M4#fbey$M z>hPN$C@^_rz(I+4q z2k798gdawSeT=q|&~xxX3?A)C6Ow1}QjX-g3RT>49Xj9;4N#_uia*gnNzr~+s>BGy z%Z;<+Oas(Weybfs=7{u@4Aq1$O#=~tiiAR6k9^Z z9vzDoIMC_SJ{sj=mAP-IQ)F(Y++7aMK1*6&^Lwa$F^NwN4 z3r%A1ax%HB-ic&lR^@4&{a<#T1QL=l0A^4K%Hr*g0CkizdZe@C6w=%1(Bk$`TW_n^ zb=j}~`(}ILnKk}mI{=&%j)(z4p6nNcX>J_0H=cg1H8j^)XIHnjBC#xjn}eOa;=#BM z>jN!5cry-<5c*{|KEm<-Mud-vDxZC+XB*~@pc@@HRX&2g_;V~lQAgiSlTwU`D%Djk z2YNn?gB}o)6{n`A$vQg+ZT+26emUW}W1$n_c?WnkMU;4BAPq1XAci0i zA;@BAvFVFN}z*CS@KH%KD+6aZf|eK6srLduY=BP?pXXJL@Pmkan6cs+0n;c@I1uzj6UAt@ zzqGE?{&3O#_M`7!W^0yjv^MTmsU3I-5)iz2zr{d6gWoKhI;q88d&-g4&=Pm)P$tF+ zjZ`$e@>5*U;9+?Vb0~rd5X!7hjEtd0zvL^j7cv0wl5wWt7yjI^P&9{O+KEr6fu%~( zJk93639UMxC~U5yTQ5V0A%7e+nYb%fZm{dFyxqMp{joi3s&AA5HTmRAK9CzD;7|-7 z7@q4vDd zX?p_wxO+Bit!y9Oa*{t}!z`vh_HhVL|3a0*@HD{>GVryT7-$)Y`hmar20<7q^R`f< z^MTR<{^OlsBxMKC6aDt~c3W5XUTtGKt-H4;ekWP05noX!?Af*3_I7u99na&UXK!Cv zfq(r7{fSoP{k_gltqzV|wr0&v>*?z8gDy>ZpIg`7F3B54L%=AwLX*p_A5t}uFi0Nq z@0BsSZ0JR)98YkO({&;J``b9R@NgTOyM-K<&<%Pf=B@91QJ_yU(kAz!RT|YR7ReiZ z5d+j^V9X0I=(Gvo1^+Q=;F7HmuODze)Q+*sHngt$#3w%WO@>Z(<^(XxL?{Os1VX`5 z0_0U5b`}E;9)KdT2s|1d8Asng&|q7(4%h|1zQtB9TkABK{dl9wr8GbhU9e=w;Ym1* zv^v6r)sOVqX>UH(jyP_fE0Te4l%f$FBW5Yh<;V|H&abvPg%aVDWt4ZlJ$Ta5gj(o*zJNVE8?4U!Y+rbATTWH&EiXRM8Yo%LS6j%#E8zK9}O;(uyfa54Q7uWe&j*a z1Oni?iRCs2-JOqAStEz>?6URt^75DDvCUrdx>wlvN#jBn3h111$uj|u&~gV80|5o6 z!yY-dO)>WTZnpO!1Pq$(2rmT$Lf5e`PeZ1!nfivq0R~^3yUnBk+WyEK{;{U-}l?L69~o)1#m}s_o344po|ggd*s?>XX)PTUrq~`JR4jkYZvS|! zI{r)1tu3{7+_7`*xZ`KpIUjn1wRFVK0?-a2Ib`%pDa0vodKdECRAU>{$CniKK|vcg zb=$)aEcIt!837-RV9DDd6CN#IP*@!x==SyQwl}@$IQzgy-fR;m^X1cS)k$aa{3tPB zYwB;afgrRr;O*^o*0Eo^?b+RHYhGOM%e!|jEc!&I&%zmtS~Up0n0oqw~U)nNwpGg1)*0m%FB`HK{JS_!fKk z!6$9OeNWl__djln9$Dggoi+CWQ42jo-^ZVE5)EI4ykiA;RYZN_WvJpO4L35+Q=d?+ zk23lPQZ7aDY>Hx5E6TaFR}5Knj%2Qc65#|0csa(VJcaq=`X(BKJf7~tge}F z(Q>#5AsIkU|P&>FMD$RN+Cut8YLFVRWH5gkd`o1`Q5NoGVN+L2Hmp zRfBzY_Sq-Nc+aqo39Wue!Xw6EDfV&h+0cjD^vi>G^>q2+u33}%q~qq;2R`_EJO0&2 z%kbkX>*xdTh#4@xt|S3pVdsgu-JLzQapO*RK)$t*Y)mNjsO*2;dn!+$Z~AR&ZgE`a zTPqV^zC;$rh%FX-Y_=$U12wkbo=0uPbE`C=bU18i7B3BU#h>rAJ8yYZdc;|TCxn)d zkMl>KJ90X66m^s*PTCP^#);rIBVZh;2f{c5A311~6FD!P5x~i+VOY&AL zz%P{vvL0N#AD3gGPZ@j@J5wqP#f1VHY(*ZkY*HUr7ydvF|02W97y1Oa*q>Q_?eJsf>!6nhPxL1}i=OX2WzbGS zw3+BDS8cNEuf5YJ6@0-H?b_PfDif25+|$?X``4kNxN*aS{_X8;E`QKuYZrT6f6SD( z42{&<>8BoVU;X;|_QfxK*xq;UTW!{?*>?4nci0`bKH`UHzsezY*gYaIhiCStOai}j zr!v0+!!|{EpG?vTyupWWQ^XfGz@&p;AjUilJ>^JXwL?bAXct#l!b!2kTAT)^T?BdtPV#!*TZvVE}kep;BmZR4EJN3_bzhk1Ac3 zb@!gV8U!hlmO6D~z%2W2WZG)@9Vbl~wg-c~J=QSNZ)d#aXnWrWPqPX8b;wYPA9N8g zcz(UP=mY6QuF^j|wYIg&h~&)%V`3e8*#7pBkG{zcJ#vnFZ{L0hsDp-5VWb#^^s{@< zpuMzehls@(`J@$YdSGIn{pD(ldX~|4I6WogzNi)O^;Q z@%G`5y~E}oGT&~#ZlT?F!~Jf6?&Z~vtw?iQyUsb#fR`9YUd5{nEZPVI507fcJJ+xj zwk#MoW5!q#;K}W%;18JyIgSLt(;^R!kE1?Jz`9R-GWNjn*glj<@&! z%^U5oqi0*4yaoN|#DZQLV)EfeBSn@C+y`0p4DJAODF*z?i0bz4?zZmEoi=CAWZQ4Q zCYw2Zg6%)O!w#G^(WcGluxZmeY`V&(@84llC$-u!N6xSheC$kX8{evBx45W|j`Tri za1wh(WX7V=n>@M#9u)k5;FTxg#*J&T*#{kHJG3X>v~jCD0@`!X^zD`CGRe^mr|zBG zI&Gl4%MLkWw%-fN8v#J*MP=%zQ3mtEi(Bp4$Cv5AJYuJx@hTfPc|yftyp8&2i?V%3 zzdd-*!*=AMGemd3zv}^SJz*k0F>s*Wamz#2pab`-PB~hWmhBQxgmu_0H$7~RJiN@- zuUl{P=N;g8L0v}ifK9ZvwA&MlSK0#$p0sD5U1`(ypKRkh+Psc2!H9F4m;C2tIrz+# z6nB99Ohn|%@%MVgH4iU((tlM9?_RBxc z7Umm$fx|Ug9%c0Bh($MfMVA<-ds)$BIYy7@p-0_r*;;G={?9)X4fKmFQY}2k1!(cX zB}XiF$PSp+Xy5wZpRr->;Th=EMaIa%uM}Nz%@cOpWw%;K(~y1jU(d7IhtJivjEDDm z@(_c-!8F*i<-6<$|MnC6;5o0ccYWwAzs3yTT&d~msc@2UO-1l zpho-Jf#G_4bkQ2S{;I`x_jQk2_pUx`XpY;AkYeUQl>t#>-#f9V;MQy!b$?%vmc3zl zzIJ=l+m5x@zvWf_6@EW4t6Ta)SOP)@ud)0fJoV0xXd^5EJnEPj)X7?95Heh~<*pMS zZe5Rz$a?rub1A;AfyrV1Fi~yokd{ngiN`wXctk_Cj)y=8ZoKM`iO+tMzIZsC<+7Lk zsjBHWcwmy@iFsCoiCXOYMWkPCn;T__yh_!T9Y!rpDblc^YxNVxDLtsVNh=bQfyu)4 zZveia2_6qAv1;vy8a(vMzZUr(zT%e>(cH-6wx@)WdMTAQ3B_nPXXv9Z!lU%`X#cCp3=T60t~ zeSTCSLL9PqJ*{7bfgiCM*TlVh(T=fk-Ki0WHnte-NyFpEa|6WCrw*fJ6`{R9O6mQ? z?O>MPxYb`6e6x&HW8;??HDTGOV--AHlUpLL;Bb)d)Lwn*vX^b^=ACx?Z42z$tM0Jp zpI*cDkJ+tP zKW4i&cY+oQ29;(o=mzSe;T~DztqKjk>ghr$o6u2j=YHfgJLOGBsZjVr;;_bZ3k(SS zAS45X(F5si0EBjfQcM{*GaGbtTU{bMLC?&)KafeQ|FV+k#8kE-4WLxzSd=u9cE_rqbq zllx|M8kgx9aQ2Ha!Jr8a$UM2`Pv5Ceev1yL!$eCxK?5V=&LtxIPpHXYTRCjW_~EI$ zYuIkR=^@*;ZHrBwJTX=S4sZj*wrTTbdv@vbwq(f?o4j9x&I%pYKCZF&^&$>v!`7)o zGPLNcrMbb{+8b@sqzQhx6FyT%jBlpPdQKb;_rBkSZz-PZ_O2sz0#6KZ8ZRI6NeBck zv(cbQ%Sm^CgWY%Ua=Yr%hwP@S9<**9KG>W2p@o(*1lnWFNz-Sg7y(5Kg^kEd@i5M$ z{c7wzA9%f;_`1V=iHhe}V~?B0o5B!cz{0~O?W~W!g9mtr2BB;;lry@}rW~)1a@|PO zlz<%IgF}DNAnyuOU;a%C%|N_b{*WVvg9qn!xc|l@OSL>R0mH%bJ&zf^R%hpFf-w{NpWikd<{j_n!LT5b)M)6QBiMV!HAt*p%iK zs>5rDZ~e!o z>_5N%Is49!|Iz;SyI;16llJoo+|pd9G{0yxD33eIUS6}!7T))y-G1x6wqfH2mk%8z zkj^p!vY>l-VQp3CMe!^FRK{Z-Rh%A-E%J5D=bCm%DBa?4F)lyXBT=?AB`^ zway)T)fg8qr75N(g3Kp~yYf}x8I~~RRnJ#jX6@f*?>grsJNKh+vAOf6NO7@O#SoJY zZ8126A@74DAf1ARK?cx1>qv)kqW_@9(w<(Na)ifw;Q_+arb4oBzwRlTVMvmpm;@^F zf#e|PhAn_URww`*yr1h)?GguCOc=h?g;B$!s5#G_JtKDiJx_BWaa?F*zr^IZ%c$9J zGpCQY*Sz6a8&;lYD(D+tUH3A0_+%UL%+iha@(V9ntM=HZyzU5_FhyR}<%$XA&ojul zH*W2+h4(z-Bez3mn3XSXvd0!ZXLsJQz>Yue5c`KOo$F8i@fLcv9Y-B`sBPP_!?thR zWg9ncwoMz>+pO8VR1pqz7SI?Ue)t^g+}opr{T5rlZkOGA*J4|6?*sOV;|{eWjy}u} zk>~^Y5=f&nLh1~_Svamf#7xE!H3KI;f+XZhR|Sf8W;C#*JNrlMnrk1kdv1En28&+? z%F8>boOYyxPSprKsC=NmPsIba|I}uC?|HAclTSO!I>t3fkzo|cG=qxgNN+(o5PXCo zGvMXHC19My(1Hf|97fVRt7#=o9PMlUMI+E*3lNhf42^p7^aV}lMLemMKh4FHRKpr5 z?y@BgPtWoEfNv307qS$}Czd1NQljIrXq!9h>t zgIDfa;mx&V>mU`Y36lZ7nb7bN2VH3A_sUwD>uu%%6K&(Bjdt5DciT!Uu`#DcaK)&NBqSp63Gw9txZ~O>IUpXA9=Uh z)Y|2LzTQ@^US;q9z&qs4U+FxjZc?|z8GNNG* z40hXRKJzX+>i9YSBvX1J=#&SH_83$eHTB@JbR<5(yLoTUuHipZ3rRLkijm z?ce^Dd;s{AXCHWH48|v?>XJ9oX^`MBRW+<`FqDHwJGKZc>F~m39=-++ZJ~yY!p+A* z`6B9|jC$?HKKqw1|JL7hFC?KvzYaPZ&>K71#<~%kKexmF>D!;MK7SOHiJo^KwVlyn zs$U1khNfn_{-$Mi%VoFOxW*y-+BZIEvyYhLk5w{xm^6M3S-cGNYmAGnN<8cyle|%$ zTkLxtiGjGL9S7pR9_doN*VhkPQ%e{fjw8-S2-r!_HV3U1Pg;5BRgYBfVmZ*-M9k?zeA! zIYq%zjMJh65R~Q;*^HST_R+t6lYQq0pSDAeo?+eEFQPm=VA(Jdc=b|v;23ZOLoo=$ zpn{v*ffO>086eHITIhx+j%5jfvMq;14nEMJ4r9d_5;&3L!J&~j83WF)0+ZKYVI^L< zn$X`j=w4k4@Fki3 zo^GDUfNqSXPg0lDjjb}y%fR4wou-c+7rvbGE#KK~3m?!E&zLP!^0?55JH2A4jJa{eJG09CCdgqcAfDTxjh2o9^j+?YZ z75`q&1*7>7+c9??wsiShchNnKG+zmzey09ReOdV#)uE2X&7 zCJ4b(47|z%RJN;g&=xORrKu5zgHRaWf#p~P3g!3*?F#S`Tu4~4``9F$SCS3EHJYJXfV$!otT0nZi+ z%m9F&%E>hSr;-pZ1dn>sq3r6V8Q+_${N?qV?b@3jvbz^7w}%$JYzrTG(e7Kg!tQ?$*ZIkOoQyi&t`i1;9Q21FiUW^bo?>7bcswJ((uyHrtbRZd z9tXF!_Ersy*)vbA_Q?^~v8T^& zy?LqKchl2q6tf8iVKh6-G>YH^igu<F%?~pWSBHUiE-A@gfzNABjl{4tKA(i^h-6 z%$>czo&D|;Y~H*neuaVkv*Q#48Bz$~9k&Oc(kUJj1A!(VKO{S!nh4s1cJN{=1w23m}pap#lf<9PkxmMkvJ@Cbs zJZkq`$M3}Lwg3F?M{U~tnXVJR0wP^t40vBw7k+uOUvl>K_KCNce2sh;N&WZo?6vyl zMhCa9nTY(rOG5JNGCJdtW@!CtiFg7Se+-x_DfI1+S4u~@0-(ce&-e#_=t{O#ud&wH z_&EYw3N%mq=#C6U=ivdE!8NvH$AB%o^J$;G0LoH@dk;EDV}=NV!U50uPTa4~W*pcq z57Xy+F>nS4tIxcqAttlYZ}b7UFv3fZiLx=4#G!qr84z%iZg`V8yphj9d%PiD9bWOm zlO}X%P)2O?CSJ_9$KOx3b9;~N*wSU&Hh0;^^}B8BmLA)^r`DcZw$X06{s~*LVvCmh zHus{b1Hku(Y=@)-?i6vb?P9@QQ5cpEg|CiIswh zFB?%QPsK%j+%s^!iH9xQyKULBwYF*97B@)dNUHh>0b@s#qMg`9RhQPq6NT52Uxn29!fBA$aEk<75UZrlbZA@O(dt>QGAIk8A z@B$veUpgq1O`Epa?=HB`o_zX6KNHl-(01+}w9EhWkS(}tv2R6Mwe{;5H_5KQ{vrGG zr8jA>98au4559@%Blr-B-{s3EMh0z^0u5J?_=5kv8q^n8Zr7IM5nK5Jo+CUt5K0dv<1uQu zpj*hHE`4%9tFfuU_V(4;wYM*|dv04~Lp{Z>gwmJr;4^v00Ju)8BJ1nvw(;#lHg00O ze`Oz9q2r)SJ0=iDiFb7+N>~0EfM{?91u6XcYwAFgl)es}JN_7X#KhXZ}6YrDJb5P-75}mGFT8fiA2O6FFb+Y&O4G4z=15Z}9 zwQ;ZuTngM;|U*oaqpr8gT>y6>z?%C*I(gFyt*vn8`%Ja$1o|+LmXQp zZZgc9qgCVlx2sOxONzuWFdQ#XVEJWYH;U(0_1|W#&O0*k zI#_uu?J4;d0*5}{G|5#BwjR5?hwb*emfL+dKW+n^y^ae{SQk#fpMMs=lzB16s{x;V z;3WIP|2ogFgs>DxeJrEMi#&`B%d20elWg$gS3D$lZ!d4?jERpy;f?XMj2kcAKH`XZ zws_I=_Tc@`Sbbx&t$umC?d|Tjm)7mEr=MDB+qLB1b=yPMuSq_4?o|I>I_Ffnq#wq$ zU1Pu%9G-4VzQTFML>{j?4#MLnjJM{d7U#FiuM4ZbBomNref(tQJc>%-Ix_75pM=7f z-eL)KBb6K2xM8Tq+WHN>wq@&}y}Wj>ZP?hWdf{y7mZJ99nss~aMa8QW)^G0fuxayvLZ5K77u^DW zx2;ur)7Amox^2K|ty$A)FR!8f9(z&Vm;n!TZ*dBXggFW-?W?QpX{3)#SxX+fqxYJ&I zN%BbUm)CUJDy3hRocG+b%C5cQKI_@jCHmEsjedMjDkCP1F~g^S%X(NV+kV3~ZRTW6 z*jSlx2Pz-xWI^g%TX&s?~~z<*dKp?n;#rE zZrp3P-1wk%v~}3tJv_Iq{x#0&ywr=;N{{PwhIoF(Hosbf;##$G)0eM6>IPl!+1qC; zG%=ofZiBtBe7)bw=E?%En+3NF$tUu0mVzcujmwQpzN!r3;Qob=jqpwgTz-$j<4K)qn#C zFVTPi`zw|YyhH38V>Y5}1_~kZU@o8(;Tw7hMc+JQ0ZsqDzbF;N|w77AA zOB=Qd9MsTDJocxA$}y(@UsdMW7YLvzbDNBv!SY`rNegbY_S22 zI;qY-tT=7$3x=sVXBtYa_(T?*?e4RV_8u#!o6PAt*WGXV&R)x9`z_biYn|;m#Z|r5 zqx&8W4zuKS+`&<+Mqr^ z^gX`1+!iismWL3rcn9H@lrJ%clxT3}5)r5YZyt1N;JW$wH$99=;YMO4=Ttvf!bo2N zQb>Vkf}TPSnuSYVbc@dZ-XVXM&-Q6BEV|@%c`Fy+p5OzMGb!OjY!6=8_+TM#jgw03 zG6`8yaDh=C4@|t6lo@Y`qe%D;YOuIx?@4=a$NN^HG5Glx&b8{=YL7F0s!es65pZ}C z`nd6xcILcuY}eivt8bWWFTePXjgdv7G-GSVT3ubO?cM#pePhjX|C9hT6Gdw8=&^!~ z{w2F`@h5HhiqA{IyFApGHl^Ms)Kv-3Qfrf}Uf%qU_>q@^Tp{Ka+h5+;ZW%d(*)!{G z&e=^6;CSP)N$4W?!6)$or=h$wCHIj$^{+Tacb@MIAok?vr>IC{APaLjQW-pQnqCtt zG%{8IE{}~8=DG^%BBi)eP6XK9*6lA)79`}nx{-ont9YSO<#Y^4(Bx;^DVMXZuB_m( z>cy-A!Y@cMsNd^*4e~vLp{_2k0gxYpN4bhjd^-%H@z^kc13JMy<%Ocam|zq=!mvER zv?-N#`<<)AlhJ895{%-Wy6_4(C;(obSr0bLGeBX^lhV!0XVTR1_U=Dg?2(5zScMdi&G70_Z0F8H_S2s{qcEe$W;Rb% zTV?Wz;)Cel^2#ndDu-90F~ER&L79h7zdrek7p(QjDJxSb@!^4Xdvn|0Y}Sm4Hn(ZK zExr6xcH_<0OAlhX+xa?zJJX`zPx^=!A)e;llN`9_IcHyqgILat#C7r|PY0quUxQa+ z4lhgBDxi2FyfQ!$CeH|X01850LUr6rjFjh@!ySR;_d2sFCJ@5f=#oR!cWLyIGgf0GsQ>DNhm=bpPiul9cfz^j+2^I3ZC!`S}V%N$|wt# z&1tN12Dl zIZzDhf>w#}&vvz`H_Ta+y7tGP`mT<33I$HH&TQ6sGDhPKbfiSRGKoFWU2X05&D*ZC z`@Vmpt^e^Y_SoZh*aJVhU4zbv8YEYUmJU04vejpbDyu5J$2y_0K)K-Hap?_6TqD;s z-3sm`@-S9pMS^eSp;w_>Qm)8|*Ehl=j0zl&fX7WjaA7I5pkc~zxK|bo-FO+ULs66k zB7TjJ#Dm8(%A_{94sR5Bh#5SjqC_a_28E*wER>Pt(_t8r!&NsUuZ7{^y%0(&%g0L6 zd@c91kzgb|JYVn|8fxs~CCzrv{VQzc>Lu1UoVCu*R#zaOHyxoNXn{|GJNGCBZF7c( zZ~~)(h-(ho!>cI6KX546qBNIlxAwL}HnXY59{%CYcFS#FwED^QK5-9y;2O$K3h(4s zYM+?cjbEtHF1y>DMWyyeNKvh z&iom6#j?xoKl=|`%dxC&f49Y6dVZUF3gItukXwr9(SeWem7yK3OUA_B49Y++*C35v zDuf7zlY!#;6p4uUZ}d8gLP?Pu$_zI|PkQ3dU>bl!n30m;JONvO{#;B27S~B>N&heC zXu!Ypq6`prCoUL_@^OY(5^cj^uLIty7fYIaR&ul-f@ z5Bs1Y-#=*YynEO-KE2)gH0Tm!k%>_7P%7-#;c=;4Ru;>t%9ccg#84nYwZvRfQkHa3 z0rJwlgHU$zUQs5LJk%Qn4P^*L4)~;EF{;G+ZSmq}TfXuF2{J+m2qocRlA>`Yu{c2) zU^qi0bOwflQmEqM*tUqr8Y5w6vjzKb-+!&GwO~*E>J^n!te8QGV!#NDwDl9la!*?@ zn|q8Ay2y*)rNhuogVQeYD`)2}Y_>};JKq{k&sgKsNv?1R)%QLK77E9JE7}>wJGDoi zf5vviU@%}SDYM`Fc86`<@VZqD=WX4C*V(i=lcfx4`5oRyeNpUu;kr))>OH#;SWRV# z&73>ka`{2qwex@!cgQ}mpvh$}=8TMs6pEmt!=<)Q{ApLHz~^tzm@(e!C)T;Q4_#1W zMdki+!UG472>`zTfd_GdanxDRaf3}lIM;={+mWE#Y3 z>0U|H5h$GlUMOe~3M?{`FhDpZx3p?cMSUU*}gPwN7uu#+KMe&|4U={fCa*vEx0q>AAP8?L>#~Bj&w6 z>H`}ZlF&HEHQ>1CJZ$-%ZtKZ)*rlIaWapnZOWv(cq00n46zN`8yp-1kZt6W)-Uk=1 zng8SrjkLo+h_OoW3t6bG(u{5T<9oL8iOqIe#h@$j^f}Wk$3__7=}!=;;&4+q$eR=- zVrYH~4rQaqiZ@3TH>(`0g?JJ810KxVmOOKRc5?uqPgS z(SM5qM47Z^EuJ}I1_C12l?S)ZyG~5A;n83Suhj%s=$_)2fKZT7a@NnoD1?(dS)WhY zK@7q`5ew=jeA5d^D>QIL)g6l*2nK{rRUjv#f`IPPqT@qk8@?BJrX@kco^jhM+6C;qQLRw z8b$NNd5V1G97H1vGpgo!C7CLFZsWgf^RKsBby?o-zHfy!&uexVC8yV~ zHCQ3pAR_&lc#24pB3^^gOGz}A3R@@A!u-bA$H zl!OC`x;&#!^1wWElOb$Yd0-=FQqiAY-#&~2QYn}3v(AoQ38&zV;LTvDPkO5&!UqxG zl&ohN#bbEi}q0l5IA7$_F>&=o=l4DoAe zfHTYKWl#}=9)Wa^!8M+T>;A!F+r8(2M%eA53&R!-u0+%qA);B9=kQQ0LQjcZvF%i= zuN|)&kmL>GvCdO?NAH4Ra-9)KHh{$8J*;5FN~e6D@}fJB_?vQrl4nxjl;l#}c!}{T zgTgyPDhGTV1$9V?uY_#QM-*3*=UZ-3g8zfAG;J1jBaGs{f1pozVGx0z^Wvo~Z+kHW z$wC2wb3{}To)8+aE)H{0a__dKpdm~U1KCh=ya4J*NI~OHyvos#GhD>eSeeQrGywS0 ztlEIFAWl8z4DmipLt$||2S*s4M&iJbO8GT<pUFVaZTJiLlwgnYJ(#lEWJ*Qz4~b zx(Pw?IJ}Jv4(6*HP34DuAFuF%x&h`hrIdO`9iYM!dKSvWIfMs1+Gf$g4M*s*jE?6C zrIpes54g@BhbF#b`Dy_;T%|VrUX8+gdL!B=FNIt_C97PSkI&D~&p-a36}YJa9|riQ&N=P30tWaOgYfb3fAOu);E!X#CK}Z?3kG-- zb5^8r=CcN|0bb#XW5No&0Dghn>cj`Ys~?lD@^A-+?S9_C1K@x6Ub3>CxHZ77kB`=B zWXB&kup+VJpNCyuMQ4C(5SLni{Q08%>mOkz<@r|YzQ#G&=b!&CNFA63k{xe=L;F() z)I03=2e@*~Edh=?+>fHZs*XBydA$Ta+GnxjQ{8{aWIqA@2QadQ_|bvUZxD{o8+GL3 zy3~OU@Iz>AlyQFsm3@f21;Az9Xy-$>5WO8dT42w{FQ>ZN@$S_z+VSZK?}1yL_W1W@ zM{acJvICdZzw!!CAq;R1G`r0bodMS#o^AXe?gBVUJ?gO0^{@F; zIz{UvHV9zqWghfYq1?;Xo)pjj4t+tS++#;bM(4=U{ZGH1`bEZH(;KR_&WE4yO`HMV zXQ{|vCEo$yePnhfqZD}b%RHk*^St{gzj>@?mPvevtV?)H!EZ6A#PSu zjOpT??PB7E3mTy26$(8oLi`X0S+bdfSnaEz&pF++(HEma43-n z?5uzR-r1dw+|FmXPkv9t0CzyL^Q{Ir!JVFOa_-PIcCOC=cL3aDY#DY(knd0*3$Xgz z$LP-~9DX9>6t7da5ShmA2=blkV*p0q{T@AT8Nh!djoks{JJyE+Tzk{2cJIh>(a+ef zHUnK9c&4!{K)!Q*D8MZ^(BD3y@YUu+f7zZ6@JeIP#V8*+$kzS|_4NRZcHsBRG{BE+ zqg;?VnhQ<&PYmp0@T;g15I>>52%4z#mfE%;i{L}@h~`M`z&n{c0^q0Ahk#RpadnRZ zFq(hEuLd|9;@tpN>qFr=Adbef07vtk7tb_+cQjWuxc0I1r1}(quC!zTW@4lJ=#)M1 zt_Ej8{G|F&h}d!GXO7yv=zP;VuxhUIkfp>@;?zV$PAPg%LT1#5f)wS_0=A_AIv+YN z@&i5xjsn&K^+4r#KNV&490Bn8~e8s|OK=g-eM&BL;Hris*sXXMn%dTxqV-iBW@ zj4*j(`eCT-`V4R=`P>272G7ktj+R}Y0gg4FIwITPsmTMuvgEeC3To*~)Px#0I#RyrlbA0er-L z|3?Ea-tDbjV-`u0Oh2Z%1;C8CqmH^p8BpthQ7ok6p>Vy%A-{}h!F>gNR7b}3?EyBt z-)%R(?{HokVTE zk><|GKZ-HBJ_8&%Fz~u!?wz{tjQR}lKtQjio?-5y(%xZb)n|YgxU8DHy8HIzjmpgK zF=qg*#6ass$8B>8(E|Z%E-DT>t|xaShEg92SCl*ZiwvZm%rVOWjs!%CRSbVd=0(S3 z)NmC`sc!_pwJng68>%ZZZYjVS#;+EzXJ3mLq}GQ5jO4KMm}LNGz`J_ydl;KlOAQnQ ze7$_81Dt8LYHoH%$*k#|TTgxNz}YT$93f?PrU7NiM`K7XD#QjDQI{B#)umKJiB##K zS+!*@R0B-gSid3D+#TT^{Sber?(+?B0>Hlk-lqUudev$c=(q%Ypecqu#AU&|Yu7!i zn^kM(SuoRqTltsTqvIg*k_M#%oN4AA;8lE3G-96`|zVo2sw_bkCO9kU4e)mjWq`BbMGcwN5m&`w z^h7ip*?|v@&=?~%l>lbMcGt!1V>I0bVCG>DQ-L3~3}D0rzMT8su@k_x&Wawl&31qW zm=XH7pE59JGP)v*pZR}yZ^eG(7a5GurGbd>jOkAr%jk;e$N+ra3LKg~@~dPVfHS&^fUqTa+a?`LX5 z;9+uOVx#buTY~JInfgYLHNe6zMY4ck;WfZNmjeW_A~YlR=v9A;%+J=?3o#py)ze#u zlk1Autl$V_BgZH;st_x&SUnB!7cDcy9tkEhw^Az$u@ZxY*L&cE?#qCaJ(h*)h_Awx zoqugUwkCJr&JH}o)K(1E?DIT3LafwdfDQ10ulLHGEGq<|uz4%V(eTm5dtz`*Jpqg7Y5#w zZSail&d8Bnp8;mnpD;GtU;{kCv02|=yDb**k zoab@cjAVcf@NEHR;AM}xn7K!;_3S*nh1j6$vd3I3yzKl2coQg2X>9!v$8@EmCKfU# z20MQ@V|R8Q?!b)t1I99js_?o44=`@>lv{RS1zu(QV1OsnHXz(~0MCTi01qH)@|05m zR-t6HQ1_>7ZfcyXT1MpHJupL0FqSol4c!YBn_q9dbA4=VbgN{5S&A;kD<(1Fdx28& z>y627U(R|Uu?;Xo(83Okn2D4!8)79MbJ~AmfDzZhF+FBQAyxv6ew>#z^y-1sY=9$j zi0i$EwL&3A5@}Muj9})?9*fj%fD=_81+dxyTcwT6Gf__H@4+bm*XlZkypwPb(h zFu)zoW&+%Eywy*M2n3CUOWWy&dpnw-*!M~bB`tgHHue3`|8 z)W`zd0=o}xZPXPyovgXNEP9uM}5(aoQ znc)0801T$O)i49Ri5&)5Gr|CCx~1P`fHg@Cu%=u3T?SZ_Gz2(XSS3v+ht_#!D=srP z^6<1veab_elKbj=LV(M2!YJWvlNrERcy~DA7*(GEK9M>~wf^%>y8<om zGB5L};`gjr^xnuMWS%G0r*>c#U?fgW*9^aCfO|S50+2c;ON=Mghk$=o`&efHM!;+} zg)Gmg4*Vp8TZ?7KF07c%0F3zBdi}HZK6A8}R<>SEznCpVxnk9hnR%aLZWMnfh}HUL z0bJAa>fvwc9@qd!=;vQIz}K46TZo+?R?S5)+o22h)YsF2ueJrXeRH%OL*_#~sh%7u zTZr>SD~#?jmKEx*^|5~dpZCG&`ETukuhe(Dhq!39v4Ak+XM&3w!Q>x}&8%+*z~#eV zD}Us)BGM-HA?_;Jh>n$MtSZ#Vt<#A56o7lRS#iI-2ab}>0C|M5QQqkF-Rm>JsFT4s z#ps>E&DdJZsLuc=0qkkkC}4os=vX$ AM*si- diff --git a/apps/ffcniftya/screenshot_settings_nifty.png b/apps/ffcniftya/screenshot_settings_nifty.png new file mode 100644 index 0000000000000000000000000000000000000000..a13f6c16f0c70ab52566343e9ce842b57422ce3a GIT binary patch literal 46504 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 literal 0 HcmV?d00001 From c21b6b560b9d42e2122abae9408e091a555a6c9f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:23:28 +0100 Subject: [PATCH 004/312] Update README.md missing spaces :-( --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 410eb7b8e3f1602ce138954ad1e006358acd32ff Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:15 +0100 Subject: [PATCH 005/312] Revert "Update README.md" This reverts commit c21b6b560b9d42e2122abae9408e091a555a6c9f. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 0d28e3bd98aea0a62f447123fb780750b91fccaa Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:21 +0100 Subject: [PATCH 006/312] Revert "Revert "Update README.md"" This reverts commit 410eb7b8e3f1602ce138954ad1e006358acd32ff. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 2d7a22f473e1f6b6ae7256d130296df6d217ee95 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:24 +0100 Subject: [PATCH 007/312] Revert "Revert "Revert "Update README.md""" This reverts commit 0d28e3bd98aea0a62f447123fb780750b91fccaa. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 599e492a832c183c0a6e31838a29eeb0d7f81a84 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:28 +0100 Subject: [PATCH 008/312] Revert "Revert "Revert "Revert "Update README.md"""" This reverts commit 2d7a22f473e1f6b6ae7256d130296df6d217ee95. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From c053c591f8ff2d6039d8434f20d1332aaf13c256 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:30 +0100 Subject: [PATCH 009/312] Revert "Revert "Revert "Revert "Revert "Update README.md""""" This reverts commit 599e492a832c183c0a6e31838a29eeb0d7f81a84. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 4a333b718c3d78de6ff8976e181055aa7117871d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:33 +0100 Subject: [PATCH 010/312] Revert "Revert "Revert "Revert "Revert "Revert "Update README.md"""""" This reverts commit c053c591f8ff2d6039d8434f20d1332aaf13c256. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 762a6b055ad8577568a311a40cd03af379e4338c Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:36 +0100 Subject: [PATCH 011/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md""""""" This reverts commit 4a333b718c3d78de6ff8976e181055aa7117871d. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From cf5377cbed6540ef9092c66caf1866f6549e78bf Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:38 +0100 Subject: [PATCH 012/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md"""""""" This reverts commit 762a6b055ad8577568a311a40cd03af379e4338c. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 272bf2f813cf80cd562eb2adbec56de90991ed62 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:41 +0100 Subject: [PATCH 013/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md""""""""" This reverts commit cf5377cbed6540ef9092c66caf1866f6549e78bf. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From cc4ab8ff74ce274634b347bfc1698f7ee99363e7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:17:31 +0100 Subject: [PATCH 014/312] Update app.js --- apps/ffcniftya/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 1cda0bc18..5f23599a0 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,6 +1,6 @@ const locale = require("locale"); const is12Hour = (require("Storage").readJSON("setting.json", 1) || {})["12hour"]; -const CFG = require('Storage').readJSON("ffcniftya.json", true) || {showWeek: true}; +const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeek: true}; /* Clock *********************************************/ const scale = g.getWidth() / 176; From a6d87816bb9c14623eefc2b91d3b73c6247480c6 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:12:26 +0100 Subject: [PATCH 015/312] Nifty-A Clock with iso week number * code changed to show iso week number * settings file created * screenshot updated * settings screenshot created * readme adjusted * and app.json increased to v0.02 --- apps.json | 2 +- apps/ffcniftya/ChangeLog | 1 + apps/ffcniftya/README.md | 5 +++ apps/ffcniftya/app.js | 37 +++++++++++++------ apps/ffcniftya/ffcniftya.settings.js | 25 +++++++++++++ apps/ffcniftya/screenshot_nifty.png | Bin 3487 -> 52362 bytes apps/ffcniftya/screenshot_settings_nifty.png | Bin 0 -> 46504 bytes 7 files changed, 58 insertions(+), 12 deletions(-) create mode 100644 apps/ffcniftya/ffcniftya.settings.js create mode 100644 apps/ffcniftya/screenshot_settings_nifty.png diff --git a/apps.json b/apps.json index 89c5f7b70..507a70e76 100644 --- a/apps.json +++ b/apps.json @@ -4316,7 +4316,7 @@ { "id": "ffcniftya", "name": "Nifty-A Clock", - "version": "0.01", + "version": "0.02", "description": "A nifty clock with time and date", "icon": "app.png", "screenshots": [{"url":"screenshot_nifty.png"}], diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index 18bc264a3..bf70a213b 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1 +1,2 @@ 0.01: New Clock Nifty A +0.02: Shows the current week number, can be disabled via settings "" diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index f1fee9b1f..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,4 +1,9 @@ # Nifty-A Clock +##This is the clock ![](screenshot_nifty.png) +##And the week number can be turned On/Off via settings +![](screenshot_settings_nifty.png) +default is "On" + diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 31742f64a..c7e08cf9c 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -16,6 +16,18 @@ const center = { y: Math.round(((viewport.height - widget) / 2) + widget), } +function ISO8601_week_no(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + var tdt = new Date(date.valueOf()); + var dayn = (date.getDay() + 6) % 7; + tdt.setDate(tdt.getDate() - dayn + 3); + var firstThursday = tdt.valueOf(); + tdt.setMonth(0, 1); + if (tdt.getDay() !== 4) { + tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); + } + return 1 + Math.ceil((firstThursday - tdt) / 604800000); +} + function d02(value) { return ('0' + value).substr(-2); } @@ -29,23 +41,26 @@ function draw() { const minutes = d02(now.getMinutes()); const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); - const year = now.getFullYear(); - - const month2 = locale.month(now, 3); - const day2 = locale.dow(now, 3); + const year = now.getFullYear(now); + const weekNum = d02(ISO8601_week_no(now)); + const monthName = locale.month(now, 3); + const dayName = locale.dow(now, 3); + const centerTimeScaleX = center.x + 32 * scale; g.setFontAlign(1, 0).setFont("Vector", 90 * scale); - g.drawString(hour, center.x + 32 * scale, center.y - 31 * scale); - g.drawString(minutes, center.x + 32 * scale, center.y + 46 * scale); + g.drawString(hour, centerTimeScaleX, center.y - 31 * scale); + g.drawString(minutes, centerTimeScaleX, center.y + 46 * scale); g.fillRect(center.x + 30 * scale, center.y - 72 * scale, center.x + 32 * scale, center.y + 74 * scale); + const centerDatesScaleX = center.x + 40 * scale; g.setFontAlign(-1, 0).setFont("Vector", 16 * scale); - g.drawString(year, center.x + 40 * scale, center.y - 62 * scale); - g.drawString(month, center.x + 40 * scale, center.y - 44 * scale); - g.drawString(day, center.x + 40 * scale, center.y - 26 * scale); - g.drawString(month2, center.x + 40 * scale, center.y + 48 * scale); - g.drawString(day2, center.x + 40 * scale, center.y + 66 * scale); + g.drawString(year, centerDatesScaleX, center.y - 62 * scale); + g.drawString(month, centerDatesScaleX, center.y - 44 * scale); + g.drawString(day, centerDatesScaleX, center.y - 26 * scale); + g.drawString(weekNum, centerDatesScaleX, center.y + 15 * scale); + g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); + g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js new file mode 100644 index 000000000..d9a1c9fca --- /dev/null +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -0,0 +1,25 @@ +(function(back) { + var FILE = "\ffcniftya.json"; + // Load settings + var cfg = Object.assign({ + showWeekNum: true, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, cfg); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "Nifty-A Clock" }, + "< Back" : () => back(), + 'week number?': { + value: cfg.showWeekNum, + format: v => v?"On":"Off", + onchange: v => { + cfg.showWeekNum = v; + writeSettings(); + } + } + }); +}) \ No newline at end of file diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index 0df056223c087638f940b2095330944c87df9906..3e394dced2b1a7907ff52ce3006ea83bed111d22 100644 GIT binary patch literal 52362 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 AM*si- diff --git a/apps/ffcniftya/screenshot_settings_nifty.png b/apps/ffcniftya/screenshot_settings_nifty.png new file mode 100644 index 0000000000000000000000000000000000000000..a13f6c16f0c70ab52566343e9ce842b57422ce3a GIT binary patch literal 46504 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 literal 0 HcmV?d00001 From 36283ebdf48379c26ec168f9b10ee4f4bd59d998 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 21 Dec 2021 01:22:19 +0100 Subject: [PATCH 016/312] Update core 0.15: Fix: Dims of notification icon (v0.12) are retrieved from icon header (no more hardcoded width=64px) --- apps/messages/ChangeLog | 2 +- apps/messages/widget.js | 13 +++++++------ core | 2 +- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index fe46ba97a..97a136780 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -22,4 +22,4 @@ Now update correctly when 'require("messages").clearAll()' is called 0.14: Hide widget when all unread notifications are dismissed from phone 0.15: Don't buzz when Quiet Mode is active -0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147) +0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147) \ No newline at end of file diff --git a/apps/messages/widget.js b/apps/messages/widget.js index e831e5b68..def222758 100644 --- a/apps/messages/widget.js +++ b/apps/messages/widget.js @@ -1,9 +1,10 @@ -WIDGETS["messages"]={area:"tl",width:0,draw:function() { +WIDGETS["messages"]={area:"tl", width:0, ICONS:[atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA=="),atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA==")], //icons should be equal size or first larger +draw:function() { Bangle.removeListener('touch', this.touch); if (!this.width) return; var c = (Date.now()-this.t)/1000; - g.reset().clearRect(this.x,this.y,this.x+this.width,this.y+23); - g.drawImage((c&1) ? atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+DAADDAADDAADDwAPD8A/DOBzDDn/DA//DAHvDAPvjAPvjAPvjAPvh///gf/vAAD+AAB8AAAAA==") : atob("GBiBAAAAAAAAAAAAAAAAAAAAAB//+D///D///A//8CP/xDj/HD48DD+B8D/D+D/3vD/vvj/vvj/vvj/vvh/v/gfnvAAD+AAB8AAAAA=="), this.x, this.y); + g.reset().clearRect(this.x, this.y, this.x+this.width, this.y+this.ICONS[0].charCodeAt(1)); + g.drawImage(this.ICONS[c&1], this.x, this.y); //if (c<60) Bangle.setLCDPower(1); // keep LCD on for 1 minute let settings = require('Storage').readJSON("messages.settings.json", true) || {}; if (settings.repeat===undefined) settings.repeat = 4; @@ -17,7 +18,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { WIDGETS["messages"].t=Date.now(); // first time WIDGETS["messages"].l=Date.now()-10000; // last buzz if (quiet) WIDGETS["messages"].t -= 500000; // if quiet, set last time in the past so there is no buzzing - WIDGETS["messages"].width=64; + WIDGETS["messages"].width=this.ICONS[0].charCodeAt(0); Bangle.drawWidgets(); Bangle.setLCDPower(1);// turns screen on },hide:function() { @@ -37,7 +38,7 @@ WIDGETS["messages"]={area:"tl",width:0,draw:function() { b(); },touch:function(b,c) { var w=WIDGETS["messages"]; - if (!w||!w.width||c.xw.x+w.width||c.yw.y+23) return; + if (!w||!w.width||c.xw.x+w.width||c.yw.y+w.ICONS[0].charCodeAt(1)) return; load("messages.app.js"); }}; /* We might have returned here if we were in the Messages app for a @@ -46,4 +47,4 @@ want to buzz but should still show that there are unread messages. */ if (global.MESSAGES===undefined) (function() { var messages = require("Storage").readJSON("messages.json",1)||[]; if (messages.some(m=>m.new)) WIDGETS["messages"].show(true); -})(); +})(); \ No newline at end of file diff --git a/core b/core index 5a5957714..2a8e872ec 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf +Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3 From 757f463420122e557405d663a7c70d96d5834ba9 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 00:23:28 +0100 Subject: [PATCH 017/312] Update README.md missing spaces :-( --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 2887798bab1f9c4cce569cc982427e44518d2f2e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:15 +0100 Subject: [PATCH 018/312] Revert "Update README.md" This reverts commit c21b6b560b9d42e2122abae9408e091a555a6c9f. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From d2ce046f6215ee7fb9bed195b748add72b4501c6 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:21 +0100 Subject: [PATCH 019/312] Revert "Revert "Update README.md"" This reverts commit 410eb7b8e3f1602ce138954ad1e006358acd32ff. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 3349a5386314dd765e1d05f913859f6b115aaa0f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:24 +0100 Subject: [PATCH 020/312] Revert "Revert "Revert "Update README.md""" This reverts commit 0d28e3bd98aea0a62f447123fb780750b91fccaa. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 8425d8d64e50f28001e0e5ecce3cc008ff0f299f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:28 +0100 Subject: [PATCH 021/312] Revert "Revert "Revert "Revert "Update README.md"""" This reverts commit 2d7a22f473e1f6b6ae7256d130296df6d217ee95. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 3c52401998ee2e14f561afc9c0c3158139b96433 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:30 +0100 Subject: [PATCH 022/312] Revert "Revert "Revert "Revert "Revert "Update README.md""""" This reverts commit 599e492a832c183c0a6e31838a29eeb0d7f81a84. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 3a769087ed080e55edbd056596c55d9e73550637 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:33 +0100 Subject: [PATCH 023/312] Revert "Revert "Revert "Revert "Revert "Revert "Update README.md"""""" This reverts commit c053c591f8ff2d6039d8434f20d1332aaf13c256. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From cd88e61dd819bada01bb586d33d78c22c4fb19fd Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:36 +0100 Subject: [PATCH 024/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md""""""" This reverts commit 4a333b718c3d78de6ff8976e181055aa7117871d. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From bccd692ec2c33bdd3228ce640a66775ef28a62c8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:38 +0100 Subject: [PATCH 025/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md"""""""" This reverts commit 762a6b055ad8577568a311a40cd03af379e4338c. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index e84335297..5ec8ab681 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -##This is the clock +## This is the clock ![](screenshot_nifty.png) -##And the week number can be turned On/Off via settings +## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From 4f70dd568ea1201a246eba182a54ac4f13789df2 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 23 Dec 2021 01:38:41 +0100 Subject: [PATCH 026/312] Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Revert "Update README.md""""""""" This reverts commit cf5377cbed6540ef9092c66caf1866f6549e78bf. --- apps/ffcniftya/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..e84335297 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,9 @@ # Nifty-A Clock -## This is the clock +##This is the clock ![](screenshot_nifty.png) -## The week number can be turned On/Off via settings +##And the week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) default is "On" From b3fe124e19a688e7706fdcdf503ca6434e2e6b90 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:04:59 +0100 Subject: [PATCH 027/312] fix settings + added screenshots and changed README --- apps/ffcniftya/ffcniftya.settings.js | 2 +- apps/ffcniftya/photo_nifty.png | Bin 0 -> 52362 bytes apps/ffcniftya/photo_settings_nifty.png | Bin 0 -> 46504 bytes apps/ffcniftya/screenshot_nifty.png | Bin 52362 -> 2379 bytes apps/ffcniftya/screenshot_settings_nifty.png | Bin 46504 -> 1431 bytes 5 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 apps/ffcniftya/photo_nifty.png create mode 100644 apps/ffcniftya/photo_settings_nifty.png diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index d9a1c9fca..f4112c9d7 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -}) \ No newline at end of file +})(load); \ No newline at end of file diff --git a/apps/ffcniftya/photo_nifty.png b/apps/ffcniftya/photo_nifty.png new file mode 100644 index 0000000000000000000000000000000000000000..3e394dced2b1a7907ff52ce3006ea83bed111d22 GIT binary patch literal 52362 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 literal 0 HcmV?d00001 diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index 3e394dced2b1a7907ff52ce3006ea83bed111d22..de6ba651d3a25034c1fc4006efb5e3ca4dfdc860 100644 GIT binary patch literal 2379 zcmds(c~lbU7QnG`Dod+zQZvX(6C0Pt9Z)gN#L^&jGM6+7l@wQy+_lou!f=Ul($XfE za>HD(QA{*b5ETX;#l$sKEHm82{n0<~yno(*@2_{x@7{avIrpA>zVF`qo$tYABtl+J zRSp0E$X~Ftagy2rsci1qA=Ov^)>1>%y!7xSIcEXKsLW zLC}YRrJ9h4g+X%&(w@9J3s;-0qHWs*|DB78Kb$=j`skRN$p2uTdZ*eK8cp;|a8IUC zbZRP`_vGgzSk*TEkg%`Df5khioSuBTbX`jksgs*?W~HTG?YH{RZ~x3Rr{Im~Ue-D~9)nmvZ0dDLD1)o0n1^)mfEJF?v!b1H zIj{JV64z zO5ZaWAKUy?LRd1iUT43o#rmY}5wOm{RpwR{%;Ijx2SYaGkXAe|(KkcdoBX8NTWUe? zwnGHVwL`|I@v&aes-eC*k_I!mwSf%REi8A87g1PqQN`7$sC!mp8HD4^EEq#0AG#t_&j7kR5Vm((sylDTC;%HY={&uU&Qv+I}RU?T{h<{)T z*2@H*a_wt<*+ASeE-}ZDw0|6f2ALCt+mL^?4ycR728Ppdcg|CQy)&P4*5zL?$;)EkmiEcxf;jxuy85S$*23#i)a9D4%)@^@8Cx zl5j|n8%7Cx)ilN>-&S@eN9gUe;2N_bVM)?SFM|$Ot1Mb}XbC@F73Gyh=&b>!;mt7N z_+y$Uk(?p)xemJ^C)7aD+kp9;_Qs&-To4#KK%7u9c34(dT=)ml&f}b5vLK(*Q0<%2 zIJ0-auq5D&WcZLZ>%X9oppDt^9q5fsclj8hSi=45q3@xDhBvt+1&>-JsW}ije7W;5 zGp&VOOCNq3pg&5=RifXF^^6V;bDn^Fw`ts}ktl`ed1#bk)GKbx%O!4zWV;><+2XJs zZ(^Wme#f5O?P)@MXBchU#rA7ZE1cAZK6>CL)E!3Ibb5_ACV%ehXES#kv4;CoVlNO={kw$S@ihwmL5qgb-uK35t0fft&qS_E2d zX>$$@bbayc9;o%dNfCf?9m;ymDS3LjuiL;lWrb4AUxQEgl1h%1H5s_W7P_Bc2p(N# z!+|MQoB|8xR&lgxvDrvlWu*};dMiKGk8<~%`yDnISFAOoj`m+H%)}I2F5r~juyTjO zsU_#1+D71^a2n*EDDG=<##>mUQ4*^=QnnQs;#KJS3o&wQ9fVTezpgKKi^)D$rs@@~ zr1Xz-FjTdIhRj&0QK1kvfNi~CYNx1cAYS%7mFPi2&zhz(R*42O$v_;IC6SQ)P62CY zSXuWa>^IMc>3+AJcV96Oynn_g ziG%1CMSCsTHJ93n{1cBvTKO}tJHKbFV&rn}PIEpVt1c%8=$c4?4(Q0$BA&;7KM&AR ze8ZYt!HG-h9lb^FAe_hkxbzfCJ7enfaT}|JaaWpA_p731hPdA{|LN^-+#B4vNu{2q zNcrb5=}K34_698aXDB%qPIuMUu{acwqMlvV5Us$8{PbSI*!+Z-gir^vAqcHf2C zG0~lr2W@c4LeWY+rxp(j;90sC7z9j`8R{;EAOFcZA$LM#)%_ V>F&$)YUu|EaN#`ChHCA7_g`((~i$lCL)XJRze6!CE=aZpfD@INcbef?L~{V%=7{Fm1@@0k26P~E;N z%AnLtP#^xQU;w05rBP7olW-r+U;V3NJ1ZHup`Z}-|1Y7Yvk_4J6B4@1>$_`#JX|fU zQM6P!6oo%=D=_`|iu|V{{r^=q?q24u)+qmGSi5+n zWYly@BlL;?MD+h_BRlh*b&sd~a{H_=IdNvehUQGQkmA%5rkR_=|Qyc~Nl2?+^} zwL5!JQQ||6=Fm?~z}!95W3KiU)>{qVvz#}EuRk$Jy?dv0cCv>+ytFTh9Q#ak44$36 z_;myxw<1p=2&hAK2LkGs=azdlCkA$0jV969ez6}{NZYC{9aK;z%rFD zz$dx;v_VJ+t2;WfKh7pQ5b0v2(lrKhV1#lV^^~cf0my&PL24!$ZcawXZU#HbI)(YAQFKEpocjRif@A`QPDd`HY6MS2g1 zG)-%{v<^Ur#=!Z-xU!HC)Jn3a%}oZXb*RV-=#nIMB~TOeKc^DQ7(#+NDC=N_x>W2R6I*Z*-%=_R7*~oL5)TS0EbAlOod|v zpn1f82Ta{y1sxb|mq;9Dc}|h1WaA%bi7<+PRc^g}m=n8)LqjXM$&;+%&#D-S3l4L>%5%_X6+2WOUT>`9+*H z0$V$VdI=XaT<7F@c6+@y6NDZ z!uJ!Yc57K!a9no?;|d_V$y{fcOKeL_F|uIs2?O?Zb?7N$19sTeKn z%Ii+|5oznP~@+VU-yNAicP%y4?Q}m=2_4mbQIzpY;Ag7Q&k(h!k?LNlxgRfgypj-Eb@3;FOC`BEiaunO|DNq!6ihWz? z^CfRi*fLYTEDA2b(35JKqUZu9)*c2K;pKgRR#c`Wa%hS*)k#<9vzCKHii<$`H>>_! zJZ-j+qX4j0`Jz>5(sPIeg>%Od228hKASh|2Y#F+*nX(0k&yK!$~PqTdhZ!9=u1%)iIla5+)n)ebO`5KDH<2GcqV&Mbr*;%B5O2?zwk^$kvntxAkk}bj!7D zu7u+3=SLO5w*^f{zqHp)q2N2y)3Mo8Co#*uORLE$*njA2cH^oXtZ~+P5D)S^iR-Yp z$=gYv#kk8|Dd2O1l%f_7-dSRSp~EA#O)CmPQ+iZ+@MNm`$PAk{(54#{I%l+>dm`Xw z7)9eZ=Qv+qfoEi?TqNFVRT*#(>a=;ei@1W<5fRRZ;{2F%`Koj& zv@W3=xdq58}`Gz;l50h z4tiP>fbiF?tgV@MJ>HLdKAmyZSAvlB^G%;36f>F^J@o=LXj*3zY1_@alcOro6ov{~ zP-cF4N&J{&CP=>5wkhuD4PgKJ6_c)r;Q%1nzbnBer3an{AyB)OBjJn4kE1BV1-1yY zP2ul8?nd#E9ZqwKxoWAThh}kszqxMYsdhVb?;8l(RWPRnmq23zXJ40q)#KxwpG+2R zi)4y~OW#CQRy=+VOUX9|lX7a zar_=45+HYnIucANp&8KiqvR5CXOL;_$>9+s0Vc3qI!*;VUI0QoR~3vp{S&GU!PB}m z-$0cnEBV)$euumGM?sCi)p}L)DBx=6ssL!!!f4KBsKyx5+%~jOwdzPE-~?8MLHw3l zd@6ykKdYW6(37Y+X`t3YW`Ji<*X4|5qdVirx8;S3lKnl-oG@~J8NCjQyZZQ&3ptK{RMoMp-AP z5nRjSUTc6nH!nqyAX=bRHE1!s>c3GitMrN@7B{ddX4G zG%!wo8dZ5Md1ReyQpoFBMRb3KZ|AdLb)``8qD%T0qyZMuHMx)@aOilUOn*M z@%U)1n&&s)yuO=p5lz6|1+->()>8JN$*T#*737n(>T#Ivd3dwl2!-fQvl67!w}f60 zr^G9Z2D2@pw~{}yk6kYb$$TI5*rj+y;Bx;@4qoJM|+F*RVo>F066P zR9CIcm(%BW7iJCdfiu`;mcZy~X3X>GIH@s)2%4kN1$hTAI;0D1dB>yA$5I3bTTj+P z#Qj81#sPUYpn!cUILDdD{2C%xa2dAd^M{5%C|B$f)2PF@2!C-TEb-cKT`3QLjIg80 zH;W^{rn=g=V^#ok*6^_BdopAl?HENBS=ITOVAzYWrGDyrcr1lMFb#bwdX(eXLgI#~_PouY!+z?!s_^ZDpbHJL$90-P1!4uqp(6#{9^qiiGXVpc(gFDP!OJUs%&_-9*I6}&W=ShA@g7YO;he+_T?YqBfS##K=Bnp* zUrP1DU;-5v=@PX6=BVX8bCDHMk*hPxobF_aPzhC&AjsBs?zvghB@C*e{07xi#apIj z;2B(feTl-_E_J{o)xRq}<~}F?(~m@u{ivwju-4-HKD5klm0deeO?g*3Gq8visbt9} zyPV&ilf=Svf52A|ua^;#eDhNcg=^a}H94TnoLT!k);IraZFB&zt38U&3S%Rf>1vvm zT#UxEUsNFuuPI%9j`=P!dY$+q6R0Vv!=bCRy|mJYJ>(U~%HN->v8xJf*iDX zmUuQ4w8`xpm;Y-Sx=8h>w34DF7Irl6_qNGdU9Gdt!&;N3NPCTZSGlF>`sveL8-&~B zQ=K_Y^xj0aS*`GehEd~h7%3Ob>6ZQ5?|_TR^K?_i#(u z=Pf9=5eX#poaO;LXNvhga!{et&K4Z>GWZIiZu%JWR6F_9-FaVfHab$MkF6heX^Yor zzww_Cs=A1`#I4XbSiJqG9G_>bNYI58T0)N2oK_IjD(}OvMu1uRn;LxQ_g{CEzrSW>#DT{jDP0 z#W+}^`k<90QHS?uta#7ormy*H?6QRRgS_WKd2MSWlaYg8-252J1C}B@ISg=QrbKjZ z5juSISc(xq*tn_@+UD`iB1;5Vm~;EH5&mO4v965HXCybsKDFA{GppLiDQd<6xH@{W z0Gr>wYdSkTt-lT2Q4vLE3y!9Gj$9#>^Pp!HTC~jPfdh@Ej0=DtBflOr;^V)4FRuiq z{4tczY772F?ZWX#Xd0IXOORny_T!r>*1nrVJ2m)!{aR%x z<0lm)`e~nM&~4W2Nc?RmP}IK9v_wm)=BAC^zfXwDIQE+C-kHIA{PH*VFV-@)&JO!k zL+y`;dh1|6(N|7HZu@`FE-E`6+tc$qAAMqawJiHBSX#n@%E$)sruLIBp{RG&%dGTy z%YPDJz{%5&1!!?<7lAGpyD6i8b)+Ljtd5MfyV6&U086)`T8z0_P(ax7-_~to)8^H? zV2+j(m$oNpgy-=m!e!thdy}Y>@6>G>^#Wuu#5bkzR}sxSmG2L>vRJ?5n?4P>Va;MDyXm&-m2-#KT8 zlW!imGWAfXC0>nlKTHcvy+^UMi!c0eUWJDF-h)N9joUVJnL--#Xyl4cxNoXsg;`TN z>=LbTJ)SY`-c_SdNwiR1LpL%_GNeak6{Xl%ZBxj^Wn+wV&d+B$T=wnY9*pREK+)Pk z;1u$Tkh8IsZ*ciSQ4O+~<6c*7&^%7-pP4i0XH~1b4A~nlUCIQ&p2r>c{kZ;bql3vy=K`ezT#ZplLC+}C$ zv-^-X+oUS*SFZ#(F$Edj9ATKQS!vW|T2HY3cm14V3A!ed@eNlJaC**C4bNW4poMo6|mnVjQ z%7m#~<0eK{i`GUHV*@J`Q&7T~^TuLT9-#`oAq&HcA!O`b=AdOshFbOCIt}Ou7 z#hay(#!R2m3PIj>X}3kzkm2eYWlV z4!#oO5?ja3gw8N||0SV!CSryu(1m0r^S>^#(jI=`O&hzV;7xq7)cF~D zoJcPp3$TE`SzKH&$RUPLggx<;d{|>CD{*ZYs8Bm3M7QixGH?_xq+T(E$U+5UTQY%b zYj%?zbqh9d$sRS4XL^UKqG~*CBGAJesp#$}MX2(z7mP8fcD_dgsU=8#!;}9cOh>^% zlwA1+L+mG?~?#E}=Q@&R~hM+NZ}IATK_^fk2oQ3#nh>5rR=bTW}Ds6`JX zR&b*71F~S!-z~Ca=$T<^HtY$GnNkw6!g(#0uuO)lU4#zHrQL96X2#oj`vDD&7`>=l z;>lhRsJvcpBBv%Kk-6TL`dtdyzOqkzw8`ir{>AlA%%38N(ZsTjJ!w9shXfpR154TJ zjw2E`xXuu5xk!BSarZC&Eo*(``EM-|$D`{*&)M-fs~@Y+`tMVt6hB}sH`}|;kEILF zHydafXMy<>8rM3)JkMy7mSt}xt>eff9OCFqYzWypE+ghW=XkChU+hw=oRp~co(6FazSsFQ$rn-PV!kIHHJQ1ISAt4aELQ&F{RP4EP+PbyB=-b8xQvZ*Mg& zKcCFLI7!}J08Y+R37b!AOpcG^0N&bx?Ff&39MDM}VTmifWHX)qLR-zrDr0 zk%L>D>Mx-+CeRG+>57$JnSol2bBuS+ zTY#;t&Emgz-#qota(yRwRYX5fvx3HouCYT@w{Q5-XiHwYV844d=xJA~V66%(MdHST z+~hmwZI%>;Nes4B9&0oX7RmX388MULjvc!AkOsUmPNE8BS$*M*O;wC^)Y_WTAeTQl zV0z@Cfy`43N0@j-o7SjpOxN*bZo@@}(BFBMFOK)a+MvgOtM{}9MkLhOi>}NSCvUa> z0eKjz(e#^l2i>!y-nAk^tJMK)VSV#aPi0N8%A_o|+?FOmE7fsT#9e9@JS*?1G~fU< z(PU}r)zr>GShD!=j)40oC65zRw!S3@j!^Cr#( zW?7UmG52jZ_61_`<_hl_(Ilt>5yv>Fw>#vtP;{14J7FlmvIpQfL?DmHB0ZXJ*ZqO9R^hIFo zpHUo*LgPJa$2_T4PCF(m8g2-1D+3nat5;5`y>TAC7;I(G9+*@O?Nr>I(h(P8Uyk6h zqGCb=N?EMK@~^FcREfVN)=E{W_ZRgK%l<0<%rn0Mn@v;t?foP>@nEL0AL_EejHr)_ zgb)Nxa=`3go=m$myI2=>e|^Zy`sneOm||;#I}(q}ogbb#xDkWB@3kZs2Oz}+>+OpA zbOeYm{KvJnq;cl4x+?B8b$J7=bo*fq>+vSV(&Hel!c2fVT{|Foe-|uv-d5Hc&K6@I z)%|M^U{T6!T$$jZ33Dqb7_Pgece z-Nz$lcAEV$y5SnOSXmwZ~<@^CnTv8Z2x*ub$Vcy za&tT0rLi|$@bu&`t~$xN+@XANP5)7$$k_z_34Ng|y`~%0J>%_pSF%dJU z?|dIK;w>ZhCAw;lWs0X;XJ))iI8+KMYJlP9=_0=((I$>;f)j z=(_=oV;rorT{awjsYX=5=jUxO3DrgIfmG#R!ep1_=-+_PW$WI~xxBTc+ScY@QQu+_ z_ORYeUC~D5xijJm5t@)SQR}?8I=mI0Pk(TGkpBk+vnC14?mm&_%&`X^4HSw77gL6y zvQVYJLjTUrlC1gPY;N(klBn$ai-}!`b$-HmyRZtG$_MQS_WWLcJ2XC?cP27EP9&kM zEk%b+^#<}OuU7?bs2%X%3^x6Ic zo&*o}G}wCrYbbiHwjs$Vid>@ZRP>f@cG#{V=h4rfe_2pMv8Pc#zHX3vUnFmUs!4jU za#k7t{Fsvb%uDyu1VH5dPpLVKTE7Ez7o* zF-4SNP+?qq5oVyT{51g+QW~WAC%>M{*YX%;Mv5YHX{Z%rUSLj7ue$zZ?698yT}9LL zx-2EA<~10PUs>8y&3s9kcU!ZhKvt8^+Ipqj3so!wKutg$UXbnHUnEO0ID>w!u;YK0 zV0NDUIR&&VeE1x^ri|=ZkPi|A%DGD0XEr`mu(D=lcSj z(Yx0(7z6?swMCM)Z@#$m)=aTpZloc}VP2Sn85)uKM0eQBw8IeWke5uJy4vfd23H>p z*Qq3lY;_$rs#o-yKk!4?(MLUshbHR2h+1?imf1{key^ND8?~cHR#5tZO`nL${#u^JE!nML ztnVd@r_uLOFC7KtZey6i5oUGheGD;H)EF{87$RJY-zUhooZ3G`d*)vHgKMqus9(+w zUxLCJ#|3rR^2JO=F1+Z7jS@o3rEu83N+I(6%f43fV!U5ly2R*eFHt|}Q&!ki_?G^5 z_#qzKIsk3gcZ(gJmr!F*=!@RiyxOIsep?^JY1!#S1U&gmw6AMgS<>?GZPE!H%PqQ< zxE@)%`n=wl!j++uC`1gFX71>-Q|Xc>%{DXoaU4f;QYW!cds;t|H^)b24_hkZkZviq z_zm_54H2h|TMrcG$}G>5%WIr-9yOuy3*gFGB*y5IO+Gtvgg@B@K@mwi z@zLsac7M^?P82WVY}c0_$zE1)7NF-{oZb0OP!{cxIBI`Dy>{-09*H#IGymA2Oa}5@ zb#d2{y3KziEH&V=Tzw}8leHuCzhx$oE0S|(XuEq^$bG5T653~86;LKy$w_;PTR6`+%?_V+7PnFfSFfRX1z%4?GE-xZ zD4!Fbt)AMnKmpVLL`Qw;L)V``Z7tE6czZ=IiGV(7(B zaKzm#R|PvOwoWPf?-gz;^guhjy}2ar$3o<+dNqX1R3CtQYV62W4Lw+kB-Pkncz^Qb zS&UIc7jADWg<|t*&9OhxZR(jzT+?NDRJ0jBD9;bHVEN8+x;Vi#ZrLn*#}mK zmAve~%Mt`M1R#-l;8N^rlI@SpnxIn^0T9&MK^Nq_4Rmy>V@%900xG6TUZi)^G>Nw% z;rG^+Rh!ZRt@l^F(TVzGAvD{(b%)_zz|5 zgC~^H02&E$IYFNcXjMEK(3~H~@?J@*8Q{1)Ym;gIRb%}ggHGdt&50f$95_q_ETUFA z8$|x0r2OSrgn74Ivf>-C?9_E5EvROagyDO+rF-xq7ne3VO@kW1?Tm-hSWq9>pXf92 z&F^@*w*C-HrJmw)l)OcwBY+}>Ia5<(vn_gTV^Wb{U^zWg(kAm|Z&Dy=f*6@Z7dY{Y z8Pe*)8=(Nsq^1&tH&NBJPU?!a_1>>F_*8c60?U@LBz!YI4gc_Qua}-EZ*Cr}>4baw znQdAGP1#(PR(sC9#aafuY(5F-uzgVn(W%5DMcVceLno6#f2M!^qI@*Jj@dSZ=XD{P z1%QaTErZy%4o>!sWx3z%x}N6KA$CtTSxaJ8WF{Ak$MV>W!Y&G96o)K;-CE>MndFOV zt-CpzFhhijnZ}b-^h^M{4I!uhLax6f*x0)VAJJcEEigAJYSFq%PPWkFRm&(+%%^7f zY#g+Y39jg588Qa0H4V|~pN9kWn|1h&68w-_r7H2L@05#70%b%IuZ!ggQzjtJk%x;8 zGIs&e=Wmivre8JdHao!_2*oekt&Gjd9uf9NB_ySqw1a1>V=VWPGQ%Vd)^I+OL7oQAnfQBxXGpahSO*t##%ELC3ZsPrp*4w;dE6gKOm{onSbyf?G5W2`B})9fn+UO0G4Awc zM~p1DnVOa^nA@SJ?T4sF^^P$enhN4o z0joFA(45=vUdx+`lMPsBL4yd#RjV_R+i`(lR5IQSk9{${okae1v6w#fX?iN1H|ddb znGjsTZ@2lzF3V_b2VR1(`OFoYr;hgDCGsklb3yJX`Pc9k6{5R1)Q^8Q`#;klEiyzh z0Ei*6n#H*#8@5~{P}kjsHR71g)Vwm!h>eRhm+<+#9s@=3FKHO_)=pIc+Ts$UqxZhP+sz|ZHRf<}}_RKOD`KE!9t1_l}>R_MpX^o29h`9(2}5g(r%-aMVx zxo@?{a-lq<+;NOyClByWcT&}j>3df?D#2@+Dr)N|R{K0x=W%yE&K4ruCZJHm0rJc) zi#C+IZq^(c8;_n+y=!4nGey?1VbG?BG)`C6{8Z^F}a=Hk+2nMtuu2@rzCtCov$L}MDH zB9PzQ2D?3$n!|eE;SE#sM{m`vJg7MlpE>*Fx!!RL+wb!4q}%Pv%TL;~b{`m`?J zxUqh3a3pgNjiK(YN2jnOE)a;Ic|CR;9hf&Ro{pAjHV2^5V{f`J{o~ld;cNT*)0K`x zaS2VxbASNm#$o=?095PFU~Z;gi%YTTM({NlT|G7j(POI)qH=gotnl!;u@YKzTQ$kWqtG^=c68zn2Di1nPT9iZb?TEZ6wEW-@Q( z_W-=;y#=&k$T{|EK0_E+{O!L34kDDS8}7VIPg?$5*3sL=)4Q?p^Wxy*TsXi59D(o$ zmro|FBf0JhYU&FHNY}dh1FxT6EQdO_oROo8k~Y9pqm|$%9u#j)XIcgOCs$^oU;YM= z`g>QnQS%$x=`ebGXAMg8+f$l_Ziyphkw%X1ypee2s~}@y{td z^;HtyYy7qP&dUR>&PABa8JW@_flA0e%JCyWuA$wShrQF*NDze1k)l0wgRu2K<4@gq z!gsrm=Sn#p=PQ^r3Ymiq6Ql!&I@UxDqZPDiVkd_`emE3LQO1w`USjsqBn{Y`|M^-? z_Q$;=x`@4_-MoF>xUSe3cyG>N3Z?z!oyNAj5QcU6?cyi-f-8ItwS2mVZAUF;#kv5a zJmWi<1NbaxuJaMBzWljXbmjrmr#UP>Q#oZy+s{^HB-BD|(WpwpRpdPS^v)+7dFngZ zd3%z#?4agb@-(|B>9oxR85D@%!7y!6tBf`>0;7G7(kNXki`~Mrz9(Wmi$ICa5tOof zJUU$s@SOFyb?Azl@$uxhF?r{110I-Sed8y=6ZM@C-yx5G=}dj|mhk$4SMK2C@i2j8WfWvUVU>euq5ZXOD-+UVX1IH}4DfcX|b9PbNHN1gF z;KItGfX5NBq?jWN(w83V`sQz5T!i51b=r?ba^$D&)+-N-++IDE(6Zp{RR-Ml9=?;; zxd5s8aI(eu1wq*AC8^g+)0Bt^bOoK%SXdi5U^Mh~J^w|kOr@zWQDk^eIYSt0ysq`i z21=c?0hr9SX|z#oJe*~Qt%TV?;lg}ysq}F%vr_epRZ&l*6##|JzlSjGFpjtX`{R>e z8?c5zM9Y0kv1U$ON@NJv%mBfAm~=cpDgIpL(Il{R2*|Cf&P4Rf&mO4f*TdRN#yIcu zU?-8L}`qNzLHY7yxa$NnztX2fUf*ci`Xoe7&d?7!}lybU#oZ<0v)18Ve)ivF0 z^8_|}b-r*o`JL~tyD}LcNcP-M*4@SIGGy?Q*GUE^>dlw{7Ec4)&O@^tH#^4MD;zQ9 zm3{mdS)*fx6!0u9Z1kyIY3l-KjnwM+*6%5gf6Q^pVSZMwB-%gW^d>^I@bZ>ilzMw` z26CBpE_dGMku5#UXE|=kQG76NDIxte1gKzVQm+0qPq2J!;`Jlo!hsIV=_BsUmZWh+ zG)|8eQ}JK)$SfBo`1)QIk!AV~lx4cMwdiQ47!Z2POu$2OKro{9H&1YN?P6^fey5eF z-Q3PW4Gp(%yWWy$-WkV?RH$lfoD6(v%Q`7Q=GBn~?#OvG$t&iYx9n^Ov@kBPogq&7 zOzr6IAN?GaEWdV=;HKgKn8$z||1yMMN{ZVqns_IS=SoaGUja;;A_+`vX)ePs(sgP2 zLFx5RccNYO3xD4JkA`B?xUYWo`3TEhwGKT!j~7_+Pz`1#<7j543xX0z9&w+5vK((J zZakOiY8#UBf)YEfR(ZFF8y-7q z#ofLWwiIM2RfRLurDMcrn_AYiY(7NoG?p7QB2c?-G5$zPp4(!!(8@j|Ay^W=8DgF# z=96tY(Q|zH`86Zn4}(l z!oC4Vt;uu!$_Htn_#O@aJd>*8;16PK>sE^_dD9z+3i7@rE)$yeBm$okqygb`_$!ky z7v;bjrUacWIO2eM-BAd&p)3}lNEgqhPfJGY{)HXK z*^73`_TaN^DI)&Ev08x*sg7+1pHX@eAu-YJ1U%KYKbU@=_X5aGuV-5-U0_`zLf4e! zkszBY6~iTq5>onrNp*18&^RG6Epan&3tQ_vHA}F^!ehj9sk$hwul4@N5qTWSgk|81 z`b$PJ$ZI*zYeI;eI!5<~lP8c_g3B(8J^TETBxFq7P5hWbiNx|WXWUI4Yw+3_*e zBY*H#Tt?maW*pBBwJ2}@B<0C2r7?BJiFyt&28eWTl(pvn6+Vx`GkOolU57R4N~O z)3Pf+9Y{0tfb?@jtb9bQ5q3@|3I_(Z^L#_3Tu*(Qp<7komSDJVgp3F<=Q9l%WvYewr=*BsK5SggI`x)&ACL$2(c?s&~xkzJ7qyuIi zigs%Z1zGv0%QW!9)bJH;*uu)7k+XfZW~H2QDs`+U&9B-2#=|#9-&O8LgOe(o1vcje zhi!M;mtv>UQo?>6NODF19|Pz2aX)hWnpx&cQ5Ojm6ML8!ygq_Z0&u)=T4$qn|Lbkow>Ba)zRwHC zeq?yj=!^XyIS^}Z>s8C2$}f)?{ZKHea~aYx!!LH%BC%36*@5Tp0__x2YV=!&0D=tqVA(RIvGbVRRNYfY3&KuVO+0fajme;<$B|w6@b--e{ey2sw zYS7u&6TYYw+b11G*8Lt5%!pbyH(8Y0m6dNGW`{1nnU9Kgp@^6l?))?``_)o|CePC` zU1T>ENWk%+QPRXYOT2wU)8V6)6&0$}o7vGK{~USvR$}AJ-33{-oxifVZI9`ouz*wsbM3DC9_lE{=%`(=e`|nLEBlt? zzC*>OwM6oyVr@5SHm8eKM?%yQ>3_*6HsYL}B_;9^({^a#R|{-dycvWqI)gK)=)O`j zuzwtPJHhwT>(3Wv2?XZwpvU0L%)x)xY;Sh=SYcl;Mnf)w*HEX2I@7S_RLDuD zaq&ZtnqpA#6PtX~yp-4J2^i}%=x;=1%|u&GehXhzk2Ly+DfRyC!HYGH%?5w_WryjM zh4PXKdtb0R%~Y{=c`BLB$Mo#$1hTLQ-uEDiVE(ngM1E^O3DJg!wX^t3rt=u`bB(H; zT4E{qnJCe;AiyCLzq`(X=P_xS@+qvz`ZU0RH0tp9Pc(@~uLR}x*Qej~N@B zpH9y>Ky^=Fi1JF{reJ59hFME0kV^15_Hkl>A7WLDyQ`6G+>jRT;ufOekJp&A?H}_ULOs!!P>Rz%P|LQ#>ZUT#v9T5dtYpuux85BU1|}ipjU`X>MuoVl?E<>pLP9l8L834>#YsDoZ43X`(*qM zLI726>Y15(yTMuBOJxpc|JarL6n-10A3XQRlc0MZu&M&9ek9t1$8wsd%5=EXk*#U6 z$6C!sQTBw$y39c>+RxH9c<~DNEXBLgLpTb{wk9nZEY-*MYv$OS+}r@}r5)!p? z{o1cg2o$Wh>hOa%QC}ywJ+ZP+Ft1i1N5DVvzaDNtA?4T$T);JQ9GStk}Nz}CFz6i z1QCE@N6)gZiuSPIa%_dYt?U7aUt2<$eSN2;N{A>eusUkvFkM0^D#zo*(c~q;-ofeJ~0bRVz!;`8MyWb zR?~6nl+|L|7Vt9kVzrLkl!SKqUtK}m0JTrgWqQz2fL@Hr`JulMXo_4MLfxK*-4Kdn z8j7R#nRBM~31x8WWuQ-tma)W)ofkDbV8EIsQ}1{<^I@yVoqEcG?nFmM&q2>ZPd%Z% zS6rYxAe$?qb4TaC-_z$Iq4IV6q2J)&rw(zHM6R|YNhamtuuW8R5mZpdmUy~`*+ z_HTc*s3axP$i-X2x#dt~2K3jwgVm1#k{_X%(JCgBBX3%bC7*&RE?$k&e+}8e+1`El z9o-U$X+3elkv3b4iI2baMSN9aW%a-Hz`$gm&A_x;*zwq@N zYBK>Pd}{{Qf@PDk%}pOK%N%zvGf#SubT{Jsb5C|M>xFW3BQ(^FFA-d$KdXLIU0VMf z?sF?8;&KUfS_+mW72?^92WmSV2$cwp4aq>_q}`{B$ zU1GM~ABk2MB{U~A^6QEd^MuJGJ5NnSAJ4ijlqFasrQQ=K6++?6`uuj(3W`meJ5ag2Zn+h7FWrhzO zmN!{9ZY}x`_Or2`aXOjXwSQk{$}*QuYt*tDUebDh#0tnulF$%uRF`XIr?Ot83^~gF z;tdu$9@F62z))&*{}2yM4(FTTl_{OIZRn)FikDw;k&))^rx6GbF_6gt!j?f~k9!Jj zNJLb12RI>eAXvwzhwI*J)=CeHmU})iVBQ~xEg%zlOYlYPeXT*>eV45sniy%a&@$$o zgWZ8u&T+*okMfr)aY?W1)0VTw^n=Cbp{t13`t3_Y?Ka zNPT)zz`IhU{sEWlj2qL7XpokJBj1hl@1?1dfKbtVPUCtt|_L`d|I$;$Gsd z;!_%uEo?pfCt#DgWh<65eA9ZPUpmq61Rr9fT=ujDSX@H)61Ulg4c((+$-6}t1iYFH zr=k#}c0btUga7+Xw3XSL?b%~=IpTUS>6+$k5$sA&L`Od6C7gHnwtbkv<+Zip@`Utm zCqEk;PTfFNV``=Me8E)h$@n}G@0e-ydUE!gCP+Pr#(y{jQOc+8$;KinV#v?tEGtRQ z;Pv*Y^tCQyv14jeYV)JcSEesFziW@I`x@}BBQ6N==a)%>{)}-xp5&eU!{?g=4j!8g zj2pA#yOwt`x~GG7IT0?;e$l zV-@Es^A$|&o)9L;lUfjjnT)fZ6d#RO`^V6*FbdB5lryZ4xneHaH15NAJ~s!FE zH`r7il6W3NlZx|{Ns_H~oK@1bB11xmFmsZXsmnDd?cWg&Y+$eA+W%*#+3Zl`+g5<=!x;ny zNlet$+osKZ_N$*|Q=;)7>lga)<8d*$(mXzzQfe=}m#0Z33z z`yjxA0zYgXW2Sm|fk%}oF^W%se2I*M?}y<>b$ks!ZUE4h3Bu(hc#ox@n*=gnFYE8G zvn&7nkX>`>9d5j=E`ZMqV(*`G0kVpgK6?60#(TS6anY6b`7eFK&Uyc7 z8mD67i5}Crtg7gv;E6!rinFX7kClNuMb5vghU_p2 zm+OEmOUOJ5aWAG>B>lKo;^e)4bC>=4=hxbz`<}42<`x}ZxPifmykJ~Fo;Ey_ix=g5 zbHI#AcI44>wDj>lE%gEa!bhPA^jjUUqz9%xK{_TBE{pU&_^!62kI;{X*}eYS4ZH24 zi|({*uUcp~UH_O}d-X$h<8_Pd`fDHc^!3{3lE3SYrS?C+x!o?m@J4@XF2C{pKK zntWVZV;9}r*krs)%C{imWykIwyYTn7*q<-F%HIFMciOw&`$oyY1Slq|UqPw%Q|^y6 z9Q!3SV*gjw?Y`vEpCHDmS{}S-owv=W(FhLcfM(elNJU4$*v|HqAKOL=f2Na|a+3Zl zo3-_}>ZPsr%b#9jOCDctwN)1)Sv_>wfN!TI31r`kCmd$aYHuK$*y z%tP|z^gJrc75Gg#Zt?ms25!s zL*A5tMoUv`ffIcBBrRwo6P12Qs;`mpG+KXmubpuGT>Jc2KWO!BJdhqdrA!GGxx_9L zxv{y;{&>kkyY+vrvU#&7*}wnjAFQr}=YeD8p`Yyk#TPf*iWk=VzWJ#qUa&{*yvI&| z%NuOYp$7_Q$PPPdjvaFNLH7KL?e>+=eB0^=`t9V`zS534?ojb5L)Q%BVXjHjJM6Hd z5AnN-WxWHQCsvuKB?o#;KFatmiy+D)uI8)w8GH{6cta4PeFeO{hza12Y9mOZIp9Fz z5XZyom`tPxWQb2JS!35+`H21gzi+l>iB+(fVxTy(UKP z8d$y@%JZ>J{zjjcW}efC_Q_8rrc43jb)YX5XnSl&9y8aP`8tpnSKDML19keRa`El7 z@Wk3$6^0)|SM`GD+#}C=)Ae`T4cFXZyS8n$V~#)8US7M&?!My@yZz?-Z10{f-LKqv$4&3CUOX?NGv_3Lp=!KGB4l z^}%b{R+X*`6OU8U$O%zi>7&%yKA_rpwUe>sp4Z2}Q9-rJ2bEsBY?EE^i)-zr=i?1K z?Je5#DjxFd!csQIs=cGP7oGg30%;CJ%^KKq&Uw9^^N~0Dw_%H}MnUoeBrl^NWjLb=rr|kmIK+Ag%4e(X3cq@`$?-kp_I(hRZp4ys5e{|KSJX;5jBAO`v zN>m%PhSvCwA5i9xG<~KszyYPapauKE5BaQ1xzau}kBt6bdAAI&P$L@h0m0J+F+xH) z4J6UTBcEwdV{ggcm(zHQJ@MoQ`^68huyrr4x7PL+Ywysq%KpifqV`TcXle)M59=U& z9EwCq!c5!o2JShZ< zlJT~kI^So<#Bn@*5GV$b&?@IB-aG z^R*aDeYv=^$=VZeQl$?Zs% zX`%3R6<=$r7hin2@dF=ziyeEy5!T(sS8L_I-!-@W;-DB z#12@LCMJg#H$1NkJZSpmC|5G=s=6#gdO>J}Q;Yt%F3Y4m;>fx7>XTpL{FPxWZ<&UU zIH$zNk((uKZ&=xQ_r^ZuAtR%UM@D(pf;3kl;2%B)MNS4AUPazo5|Hf}*dNCXPpXc$(Wb;K}H_8`QBu>h0I zdq!T?z89AF!0Y&5FOv=i`s?kXh0E<1Ke@uTZ`o<% zI@7^zPkU8(HwP6ZN)9GjCULxF$a}8P%{T*j z&IrT)q*+Xc6)V=+V-G#AW*A8D0-pCT$aYDqns#>LA%Dq|*K@;T1*D8jE5AAfC=VXj zg#AWOp%JI8Pw*O|gI5lK_f5hXh`!3a!4&oGG@N4an*d%yw#z^tWn7?A=M_pon1XB! zkdA=Re@OsH!anOLlfrtm^4xXLv-ao97TWKBbG_~D?D6l{@zfZAa=afh1zGe!Ik$(g z{sG>gJve9w%$#5!`}o;*#4F~=X!-tymapQ@5>So_$q%KjEb)VJc)qCdt0JVz_+#iL zWWI_Q1LmuQ>NptT<=le`hcw@?paXP)M{J& z&=P-HAAJ$BJ#m(mfojV9ryS&Y2UyyR2>?{u@TXYZyPg;TuAs23tFPnkU`)OtRmz`h ze7V&uM6O}i$BX=+@1&%Y;Huz{LUM|ePdwI0E%L{95hG3mRY(Z-2&q^UG`Osz2Roy$KPg$9W&RTZyg-!cSDHlupvBn) zHQ9!Zd+h2f@3-r(UT8O7_n>Xt+8Oi&ersAEwk18?8sD29vHS0Q%I>&jk*!*>(N_&7 zAWu~k9eF$NhuA~t&F}W9+^>7XEOp8gQtwq=S0T&B*4He4as|yjLuENGBUa1&zw!k! zef%9-8qS`+VY}s~$L+F9ZnwccekPxb`@s~z)_}CPQ#m1*2T=H~7Y}V8e&ifG?_+1U z5s&b?YCLkGY!txVpS*MCiYfR^x}##pp|7e8zUNe)ItH=ILzUJ(LG^G!pN=mNwfwoQ zcIyrI8E(_0xgASTz|L~;`TF0ag|9TQPWx6_t{5LX|KDkWo z>#Vnjr_ToM>;L)*|1A@KUSO;qT`vAB>)KZxc0k5u6(0CNWz6;w17*C7YaV;@g)AQh z`zlO=K@|TZ9MS6BGhh!r_^j>N-f!1kbB~t)L2ViMHgVA4WXnOq7fg+0nE?RB@}d-O zT^|3c!|dFTon~|APxI3=TN9o)h=XAvkSHNMAX8RZl~(W;cnOtumGS6YkuYbh9gn1yg8fZnHmMzQ}I;pR4S^sV(-cpM1fZC$wvO z6W$jdLFLZf`gJ?(#%u4jSG?i~d(CT)Q@z>Jr(X1TmCczm**^N|_t?Z~6K(IFUc33G z2W>#B!TIOE*ALNKHt)7y|MU{88R)SOe(X#;?3IUTGKqjDlyjthe4KK{)Q4v;yu9F} z3|UsL+gDk+uI^KxEPf+n9{^%G05oDySe>|!-q|(m_xvyY;~m@}yoTE`Z7 zVfc@~?8aqE8@f6L6Y&(5du3JDYrtQ5>@54-m)>We|L5~;=0Q`mmyEB> z`0_3~`6wi1l?PfVkqgP~fd3|j(&hJPC3u>0wZe<}@5U9?;3htC!oJE9%H>3UO;iIM z*HhyfsRxzekpd_7w%qADaAvFh{TJV-ZNUk?#tMka zk{HV=Hzj!Anv8U)*IsqPeEZwazSqW0)gDbl#(ULhlR^NQ&Xa%A_nQPL$#nn7Yxx+s3`Sa|UR~{xDyefRh*z)~D8>zQz{(O)9^!vZEcfap!JLhlS zt_eF>b%vg(>VXxrk`@ip8Nx0`*Jpk#ZseoPzpX-nL_`*cGGcgys9;yaVz_N*k6nDx zUG~eLUTxQ2aj!MhHEPzzb;j!c45s8c)!z5MbX3Ib8@Z!)(g{b{o6kJaKJw|eTl;=3 zQVw@>hWy}y81!Eb`E_i-mk!Z~H|qXkV2C9o_}M1@OSX&)Ie}4a1?BQg17p*PUxu-C zMzv9K=8<>S^cMTf-@nUVd&bHBV>;1a;J5=&@G`AhFTb?W7T*1&96`vQ{ebTinY3c} zz`~EqRa}-E^c7DC71}`X7-{s$R$}|sF8kGgUtzc2a-V(iE9cu=-|<@inE@tOYR2y+A_2`@oa-4Lh&&eT+am3YcK_d2fFPI zrygaW`||tjBcFJiPPt9;#vIlhwJ@|)a8;NPEy^=QK0@MA&Sf@n;DU0^*V9q$+XuBS zwT~Dm)5th=km(Hj0&t)a6F(qn0#NmvH-$Nj$Wu<5P;2LZ`ki*b>{(#|0wx`X$a5eV zCys#|Kx^0Hg&zxpa=KyYPFXS|G3oG>Y>B0JCc5*F9Mo5Nce(W8r)78U?6cqf;!1mH z!Nc~AfBkzq{cR^&Z-0-|@~(v2z$#nYVAouJzy10bf3WwTC*%Fhd$p6}rH*lD6nbf~ zDLVE{@U+VWKShBc(`Ef9UIkxlv%-Q&K#hLwoL*=j-zW&eNeDn$T;P6r?KZpMx3}0W zH#}q=tsP!g{k8$^g9+$~k{fTMaGG^Or!xfPrO*6E@ZWy!-PYKlLN-RK^uH48LG)Bt`B#o>aTc42a6Tgg`2A*{ZocewLE%4Pr zXyA6V@*sJvVonnWpgl7@tCh;+O{J@yyY|{0w>;o?E}Xl0l5p!9>*S5=?6N=HZT}s4H-i?fKZ50m`{73L=PXic7rlE^R1}IDUfNVc{ zfZe-Uz88~||&e2Wl0 z=N?>tojpT#(S>))fUmU=p7$R6(8tcQ_=yDJvOSdD$dsL~%kC3NGL!exfYfh7MMo;4 z1$EwDE-SA@PcQp8RfAosbO}+CkGku zpLZ1k`eNy;Zy2^Wz4ev$)o*;%KK6I-um+xO)n-2x>WrwZ=hTkF6@fg#(+Y_f4o7<* z1=4(*qSlQ#%Godou}WVw;Y~y6d}Ub~#^!-gU~GNL0myRbmdnXk4Mp6P^b&O}?aG5* zgqZl^+OJr|86xgd6(D{4n|y?f5x2Brz;PIMQsw^r15I=+bHYogD(VUF%UH*F^Hri% zD>vHWN1n3rC2MJJw#_?w?dBWqFy5WKa@9-z zgXg#F0RO<XfKJj$Qs#Og2$29j?1p^k5}ql; zaY0vlcPXh-8N!8PS!SrHDxHH9PeX0l+-0}lxWMG^FBIdqWnD)h3u%9V zMty;h^s;RL^1v4lmh(J_0Q3SXctwok;5%)i`--GCJd2Ie6v+cn7vu)*z zFWDV;F0{Mvc*yR$Wue`9^L@5){g!B_{rVxonRn=H>+0&Ut1iFAZoE#0e#NbJ$^Tqs z&n#XVUnJEB^NgN@x8OZOxeNe5(%AwY!v^)II#zoeM(`X^=tj+I7C-fZwz;ZAsRhw6 zGVN})?^*WTdb{?j$L-;J9=DEheCwbzAO&zp<9ksJ%x(oPr*w2Q*jvsz(cb&P(^bT8 zqg5H8AJS!k68ySuk;h=GH3G`Lo($Y`3eEjd&<(U`RjX|VMetjxQ^1UwoGj>ZyBjYj zeq8h65rW5P=g%gn46wF&gqiwAicYGj~7lZLELhQ;CAFKw!X zOKr8yn&{MvCkzu2(IqBG9;oO5Dk{qI1lpH%81hB%as|elc8pui;~21r0(1rtd0P9R zyY70ye)64*by}WK2wpJgibw@&)@k$0kFLPl_;LKi|10d>A2?NqlM(CZ$uh7C#4~{?%UL0!3c8SYAj4co4Wg4V;w&IB=R@kalo2{vt{USdwuH{_x zxuxx|sFI=@)c*tx{wq&7#9BM}En}@#1rNzLF(GBia<8L587~6{myW{?7?pFX-`hK4 z*IeyjI2~xyLh1a%0OeWFq|UO)3R?+ePM|#Ufs5j}X+^SD6VDAe5M%Gjvc?irQ(t4x zF5hfdUG}g&yJ&@9C&Yje5@xdvKp9UYH9%Ef;>~Y9&OY{;cS^{C;*w4%dMpIvQI|11 z5QFXXX$M|3aR^$J$lwZv^7V10qD=ufvs%+Byx=?Qh}l4J`u@&${>N4Sa`49;$e*Te#8zsjH9IGd*C} z{`qzpXoLJkz4HM0>LVH=#3rnh_{UxZPuBq8BzVs2hO$Iz| zzh?WdUwp+H$2C_BIQh=FoKE-)9I*v2?rP4quAR66&oPa4NdmanqBtDeNPmRLyi%s2njxW^fz%r zv-U~TRlr@f>N3aRmg5X%pbm!E_d*$(q&;?wsxUP5%S&p3r)6qIb?Tcd5F&xB`K3of=Ib@OhaEoM8rykx zBKk<0KqXHs_vpVj9V0wOCw9V z)ikt3lTnhM_!J!}&;Lj#I6taSzI>(f1j-jK%Yr|2EykXF`Xzhn(G}L-!oC+mQU+Z5 zj)vJopmot6+FFKBe(f>#nl~J0z5V@BrVcawHAselGH#ZKuxtmaG%9%TD}U;|6?j0j zm9WajL+uKZmi?UXc^$Xk&in9LcEpkM{h3?n^L_*#fsB_zhfY|+`7v;wmA&})w_Deq ze3N7-GyC*df9No|Dk_{m28kO&JN69OpD(`8Zn^Rddd{@91Ghy zK44);wDCY$VH4ze@(-x?1r79+x+?lqjJ`cVL_dX|%aGeb=BUOjgiziK-Ky)G?1kqy z+k)E{`K2?z4ksbhmvHEgC0UL62SJv&fgzhdZIaDDOkSdyn;h~SDhKF40%cW(h}|Oz zk8;OX6@ykTC+`pRD9|){CJhVV#jWa40&+wjC=@RpN{&i#FXd9t?@~;hP;Up$ohq3n zgUV@}0iYcZ0P!%l{@cCxJfV~K0^7S=o>(XNkSBNo*q8FH60VK%gMsX;{bvv~lXxC@ z*WMAk?9zL*=e=JBD!JG;(5}=kw2+0)R_OuNl)Mzga(<+A*Ld{ab_(Z=|o;AQy6W(+F!87a~?|ZBNf~qRQFkN?W#)`*hHOX*~8Hyi4g;&8CZy* ztQHyYvB%G|Q(kwBGtNWkv~`cJfg#`9*YA($xdDm}<#<7iFTF0FgC9{GC@$=?9C9tT zryGwKzu(4fSNFD}&68K`A9>z()~rc3_mBgfuY^zlgACt=qKmeE{aeKt*ROtgo85N( z13Iv2vK93Sr1Nr-D*f^jzkz)0@rT&FgXdBNWtV}zxj7MoBoB*cr&h+iV&w*{Y7dFv zuvWH4^EVLb!(T%5qXC64_S%CzcIG=yu=oG%Sw240C2!@i0LbHgYb4KQmp^Q`|M3Q! zF{RbM{iDxW^L`zuA!I4F+gBQhJpBA+AFc+KV{DXWI}UI@`2~LErAPx{Fli}aoPp8x zbe8=_+oYRul;QlaJGIc@`Bexi=olko=3H^*BX-qA_sJ-wWboAwIPrsoq{Rq^?P*T# zF<=9Iy*@krju-fNMA2i}3xiX!+Bg%^w2PxZ-{+wWF_d(fR2VMbA46atSP{TLViwCd zRL1s(H`%n-58KB-dA7ar>{G0-*z>^~At4k)e{2_6S=5i{)oJo=-&Jcr{@$N$$>Jsc z;7s6F+X9s`wd2V-F17g~O)R^Y(`vQ^Dp8ocimu}RrbA(b)!N@pWq?d-~pYK{+0VG zL-sv3P6(X|uQI97kIPyfEFr3M$0g&Pgu;k(_EZOej!1h0g-{-Yb0*ss& zWmAVxc;PbLa-YcqaV4mw&a5_Zy0#CJoi~nSM1DRf+9qy-^8uYA=iI1};1B2f_CXop zHcA?3mikS7QdUX(|ALEhxyCQw8ks;E9#XE< zMU>%$g5S}21+K`Da=DdIt@l@^p?`iT^DU3~;gA-^)joj=egWix#H-d9o#x)R2$YR_ zoDzT`UIohUO}N)82xVa3nc($!RrK+>!9B_$6J^x3)RzR}M4;2Ab!=6+5)zg!Ad1y_)1kLi@4 zGzN?D_@yhhRYe}~L#@*O+aAJqJ<$v0TIvUNpslrjJMQ>7_U5yX7awQp;1>Jo1p1?G zLdsFOtmRfE1CoAN5ulIv^_Q=>6hQ;Xwn@)pjMsAkSy!tLG!0xHz{}N^TgPc5m2xP! z@v6Mk7a{uwvJFr!2g-H+g;~BR%N|>Fs~{bMmxO&8lG3~PcKOL3<&Ch67xf-!raXbc z;I2>7$W9Zll2$0!B~;2t6OX|QFA!<(OEH&*0ACVmMH@{bJVF@tm_bp1e_CPGl&3*O zA65SNw#4L)TKn*Muea~~;B)qY553tAoIMpxe+mpn!38SxiHkCE=p8bV{1PCOn<7Vv z<<4IfTi^pDI#={}b(xN#1yt!V+1vwHKu8!ubF&UZT1K5&<(a#38$q~GXc_^tgYuZ|Re|Xynelci zFZWf>d%a@%O9kbYB+}unJkKA((?acC5#BnUGfuh$r&P*=MI6Nui>T90ez~;O&@gNh zCz-wbeXp_a{_qR-o)5p-X3X8+pB(G$?f2CwX`(M@N|8@4_$TWG72E-^gtJ=7xY$;x zob5?p?_M1~>ul~^8SdLpw(tJz^Y;Fao?$~ZqA$Jj90}ljsh^CKck+xwm4Ef6D(uIf zK~Y&{D+q5YiLd&X^*~_iDFL1+IliDe#_GqZRohXPV+CZJ^5x0|(wQ$ij|A!{PuU2d z$3z${a{_HBs~E6%q7R;$G7swiZsCwk(ID13%uc27oxWH_;(|IDWxT^rl)UIC?P zNgbD)I5^eU4_SL_zrFXIlkGqM>(lnG_n&G99XiwBYmAPVFwhW5Z%YiYiurfn_){Sd zC=sg@r#+s8EmrZBice~y5`1kc}L zMw&Wec^Yn3#Jgkz2O7Nno8W^by4-Oh&>ngi2-jKrysv)uD3p2sDkt67)9dwo|BF}Y z^L2ffx&Q<%D~H(AD4?jT#DHQqHpk&+jCj-JsFO#W&|&uWvrn+^e*ZJ}-VdB^GY*(y z4f4qS+Bf(0ce{-J1HIa65X%(BR}b$&L(W0TGKkCrI$zY;K?hH^cb)TE`|gkb!OnW` z>ujig!1u6dpGloO6Ea=lQ9!=x2yg;1nFEIrM3lHb@0Z_-w$KkC_7cj zz}^?fofDtF6A}j^x&0_eI3%A5*$+_eDg^x4i!Z#( z9)CE#Lc~RRzs4)@hs{wC`09fI>2MK(1yxl!W@SWl5LX16wFk#=wU5)@mRq^d65C!+ySVmRV=aw!HrUf?A3pzVJNXT- zbmLA%rLd_ipqzFklyJRHu`6En#6csrH@p*}uMZxZ?T%X>v72wW)35t7@wnCtKRn!D zuN{@x^nl?&hnI}J{q3jPo8Ec?k6NQKpCsN<3CcYC7HJH>K)K9$SHJWGt=i@myX>+> zcGHDd+Wr$8?YlquqP6WmUS6FZUA%&h=R6G!r=xVG4{BAW&7@C~#7mw=yOTKgAZ&=|2ApO^%T$kzOpKU-;kYj0Tvr8|1&~Crv zdYd|_(Z2ot&)T?|lQe;No(0}ZZTHb1Wyuf!>-kq|1611)vpuOAcDem1T18#8ZGgAM zUi5J>T(Q6~30_Yg zT<|=Wq14rLwsr6a@zIZr({ELiSGiBv0w-20C>Fewpe$oK&0u9Zp~^!kR+GS~vHIp# zyZDa_?as??wn^h^?7Khuyp2C#vTxVQFt*R^Bg+%~TNXu8;#Pq+F&WF{WqSL9#4XeF zZ&{Npnk9{DeU*Od#s4Q#G>AcrJu2IWxS-E~;GM}cC_HSFX_5AJ{+goV27r5VZ41%} z;}u4HLxVc@!t&zU9zY}0nWvuilm|c2-qTtJ!RhZWXee;tiS+0J0_Zy@ndcSUV-l+j znaOiz$7}jFN#)dIaDI~;-6&27MY2_pp5V74Lu|K@8)NZjC7_886ySR-KUKX~^FZbS z(ur5b9Sh!)1DQVT#VJ5WE-(7ZQi5_nNi)mFLNVn>0r;$_xosHRw#+k->CBg9a9WH4 z^?XWgfU&%h&N3Nr6)A`YV^OYrfr!!paB={uA(q5)Czy$<3ZO&k2zX&9s}Sw8-DsK- zvfnZeK)y&iP@Xtr=>={TnOV!;j*>jIad_tWT`mTCebOKxujc|PveW;2A+r8!%el;i#(x{!)VJs~m`^dNqiSI*Kg21P3HD8W_ zeex(soN~Ve)K+fK0W|AVr)5Z*G^;c$BYI<(Jo4EfI~<*l8JKjkjAcIaVbJtdow0;+ zpMh760n$mAcr<>LWj&DigrqaJ-pf_yH#Vp%LV2?IKEJdbNsh|2_SH|;SNbU+@v=VS zeLQ=yslzossfX5mhjjq&t!0($Tnm9FVh9GF9K---~3L<@*K~^0WzKK z3BcGm@g2C!#@0bq<+kY%6L+6&1zH_Jswy`d@wIPct{LH=m5fK6#1bkB6=XdjnTYyw z$4+q+ZU%rh7%Fi>)&W^Z*}m|~dD7*d$ z_BE={eE@avHx_?iJda8%#N{)k)h*YZy`5_6+DDy76)5Y1bU7r9O7jt^)MvR4AfJ5_{u)%>nX4q2rZHcW&$~9DaWF|pg4yZV zPDm1{&w(Hv0R_6+D{cOt>5Wd8@yFsO4S;g`A3JEt697J203d1k-Z%=1ufkO82xB43 z%JsNF3|Z&x_*0xZDbvbHQZ6f}%TO`kay*)P*9Fmg(|PrGJt-9Ry=r=<;2t_WSgu{$o7d}Zj%sYw5#HjX=Oek^U*Hy8GH{+Wn2!c zG6uN9ivGPjh^UM^GZcsf)B-_}9r%|Og~zKs{YHpC7*ywmQGIAV9(V^&J-UbEhDRut z-eQJkNZJ`Ek5TVQPnV6l9I_13QKm`BH;w&3$qkcwN#i$7MI)~9I)l{vH%;I-wo!fq zW&}f|TC z3_dZnEoEbt{ZwgIfwFS@edAys8pFj;F4KVv``s0;!Gf3DR}31MiE9lLy?U<9VP zyT@$f#y#GSU*VxX23&N6fB|!{itEh&PTV2Yb2mUI(Yo4Un>~A~D<7WyK0bYv_z%HQ zX5>jzmie*5BU36WqyuVgcUP~iUb)4;Ma*&<-=L_q!Q$Hw@eolA?x2=nZV~g21^R&| z%QG6mh`GMY>!|YC39f^4w+?XcEj<51Y9S9w#DM!`T-@d4&fPHA&UNtOrF@j3ANt90 z;5r{_YHh8txd$KMWPIyGmC`aPkLiIo^IUVyV!QF8YptWD#{TQ4U$l;C@k zbP7E-MuxGF^?(n!E562db`IJ1{^L^Hw0?)=8}w%xFeEOY>CXq3b_5JJZtM*B^A427 z3#o-Da?oW0^YFXB9!lMz8|rwN$;(J%2yW2ws7)CDfIr=b5%4l_^aXHfPvmH#J|w?F zV^h5~X)NZ=pJM;|z0dl?KlBT@@rq99Q@qK5FS&G~-F?L!HlfYzKY#dn8#irYA(Nvh zz(uWX-?7)WZ`tFWp<}>TMbWO;j2S<^(WcCpD*wV`0d@XezZEOi!Wj2%MfuWHw-hveul4X%qps7jAYvYI=Fl(~CL< zv4ZrZwtP$ZYv1{l9ExxutUvdTu&GrHRW!=T{_ux;?cS^JvPm8F_HW<$q)j?-ioc+x zLRB8AUQT1lk}dYlfBN6@!f|J@4u_+OsGQ{Mv-f}Cbor(rdFaO#u{PlG<)T_Z5gq8-MZ~ih<)DYA6!%JN( zS$P1`DZy&-WQZ%=UU}xddxz}BmD}xSKf26*_QR{~(T85N4KgxD2#m6^g-(U2E3cb(}g502@s z+a9w&U2?7c+qb@I`|m%)2736qRq&AgSLmzH91kF`dQ|XAX#k$HY-}A6d2k{hHc%LF z7RJ}j1N;SZ8fAnA5s%xTz0dZYy|!k3k6m;1V*C0(|IYsOhuf@smrl9*G&b_S-Qrym z8W!_w8i@-jfhj&5V8!3?|tyRg}h4a&jTM%#&Q@CxP;^@+Y=l^`6#RM!Pp@fdD;-N zJu%=kr0YZvdeKm56}sq*khJmC?4#MfBo3|6Cn@sq;)W{yvv=h=<;qnQ9T;nd)Q1A? z=#vS-wrK9W88&C$el~N~IIVo`Hf?5$%{X9!O`JH+>2BS+%kIAWe*4-tK4nK7J4;)j zMr|SZ0e5JJT;Ta#HQ$Mco{$?z*%PvyHkl^Qbb@O|MX?n@PoewN37QBDLF_XNWAKvb zfM*4^Z11tP>w4_^s~)p|{>NX~^;a&i?%jRbGUPq>qaXaqe*UAY?3u?`iF>?cu%7J*LD!>ExUI+IhVABpWx~L1{H-P5^2%)yo+5m>ap^9+i2wJz=`vKlAh0U=z6^-7Q91? z$>-aS#3}fWJu&)>Rno64=`V~ra4Mj@e+t^0H|?;;7p=6V&#bZMpI>h~w(s?J`5@N> zZKgl_g}GsbJB?DbWqZ-AR6K?8aC{#y1!gsfhNZVI`p^<(%Eq@F4|qMhP&qSWO? zAf`;KoC*qJ(Xc8kdm{W&olel#U-z(m<%_?tTdrSZ{daue{eDdGJ~F$z?0}4Jgy1 zi=+p*RLZAEWAO1}Q4@8!zb+ec@|bjhR3K%JFC3?$f8yL@r$;;W1tcDE*{cSO9$d=H zx``Te7wymqJ;Eb6U`a*lS$&XJU~AOXwb%EfLppQx_VStpP292}D}qj+wgEb_*d-TV zV_*AU-?uM+@q6}Hhh`NN-Tehi<6K@cS!VCa=!a7^CW`}Lv)MH({`^B_OR|d`AjHQD@j6v?=yG((2c@B}EdgtBaDE9Fp@H6hBV5Bw}E(*oSK{GTe)0K>B}KQ%)K%&xfNUR!wY6MhPf!6-as z!3;)G>N`52KnjAQGb#ZQvCIJN#||#_9!3oZI|)~+!&pH zLBrd7GRqX4oya>M;>)jPMiU=g`9uwH6ve7k^|+qTCOI`Xe9p3gTS_g$z}X zo9!KxR9TFs)7!29HwJyMIV?S<)FGuMPMu7X%X`;kBT1svQpxGT_^>|Rp94- zk3MRqU3$fj?Gu0hZksh{f*mls-A+5>So`un{k=W<$kTSywYSDf>mspw$#^xYzKs#N z9D7j}?EvSE!UEtS^Er8ejI%!Lvb;RG%k;`PZn0je5J(73V7ArTrj4DpbK9V`V7yv( znQ^q`=7V2N@F!?dD1#0;%}g+lDt>wJp2HCav+SlBvIsujuF3^n=$h z_7PvI*@BSwcETs!-KS-pmn?c8G4RA53U5VV%K%X~0@np5CLKsXbi+s?GhgdJVD z;-(y`_=~zSWIxn7Rc5Tmsz7;xpitXjmtA^?J+pY3HEIvUce>yMTZOKMOxpr^QKjn@ z*YXab8Y#MWkM(qKv)-O<+KX+oJ)N6v&z>#T-MLl!DwXZos=7TM_Uzs+#S!nZuI`?~ zW>B^aOP%4N2`~$9*uszwaqBniv6tnA`?}+YtpVprvf!=3jj}>H%DQ|`J8m9u9hBPK z8~QU4`czgT1!QZKqyt?$Y-F%g{q3}&fju(tUN!8|9&(p;c5V|--I8OM_4V!XFf`C* zU7g!)uj&XxLtW~#Q-6Fma9w#y?3|km)qMs7{t5acym+Uz4Ne95+bO0V^); z{w0*#0X0uP`J5)HI#2_*egOthCx$m{?zNx&@H$()a+CI;GGH+QyKWRoNNuUZAo%M2 zkoDNP?|+jWd;Fm;5C(%6<_cX~M@!K;{ovJ9sD5B&+tx1o@elrFoqKxY*FcM{0m||I z3P3>aI&lV@H*cbS^3!MA)am2hGlG^&dj>TC&_FN0a6=?bukHba^YX^M_T7KK*m`z$ z`$`h{#U2w}$>pnz$_|<}$FxeM~sI4IrR9QMtxWv z`U?*&vQC%t12-=?-J^y${6>40V>~}!!N>5RmEWo$&+qItwbWVb`1rj(mJ4W>2bBL! zt?hQ=vU4bNxVw%I$9ZJ9X^$V?Uw@&D?F8c5T9kO|Um>?c_$PSx7(Z2d`=Uel**6<|yIF4x29Xll7 z$BG9gUJM3~0N$k_Wmx{1LeS)TI(;%p&}$ARJ;n;b>Vw0G?G^_zFBNazMur%#83=ia zGfjDOYlr>MAMUY-bP#KhC;!e5|K6s|p6R?-`-)WwIlA`_+k*?9w%`5c5}%ZNIy>!{ zV-B^if8+0L%GB}JJJ74uvc^9D+3(u+t-Cd@>Zhm6np?~|#%X;T9I;skOtK&R_cvp= zSn%fklz2;sI?BNf{sTxCDV68A14$>-fUnF?ax2-DA_c2F-q}!VTekGr&%S@Hz4YQ% ze;^vOh9KJwu_Hw?SUi|B%ndag&@%YpkDY0!pLM*|web5BEbY-*F6TfnOp1L|T-OBr zzw(bSUT?qr*;UrLOG{cyv-j!yOhNci@gV}VZBfT_=S;NoKXbOtn7yC8i1w$d=P&TX zctc#g4t0`Mo^`{fUi-JNUSR!uw5RlaG*uWRa)lShh%{B~$U~>vSN`>H;x`}!C@wAu zR+S0e%7GHRKy?V26EFS|A&0LB6sg(|kD&3OLjl<~+h-mp0y2FjP$wc<)SB(8s~6eL z7vEr-bM_zK|BOw-0~g~^rUx(0P0fA>bi>;1?){-Vc}knjm^s036GL`jV8m9f+$uZ4 z4z&6x@casngcYK_t=;m#(n88cdmr#m)=qB4{Oxvs{UCV5NSTI*1o*ePoQ`OjL5x+l$=j$`DGN94fl83M?dx!d-JNAy;HGWF>eo>6_s&_*IuP|O$l8k{R+)wf7Nw_G@JsETg+I%Q*?@1>L zl!rS4Ga&Zbfd>%NAE4fXmh%;!HhCHw(?7=U2Pu^Sl*2P~99lRK=UX2hsT8)?mzVee zdElNNdF>IKf7pI@_>t4>=woNtl>OVZD)t6l(P(b0v15;$X(ya8+m3(LEIU@=$YW+| zt2ozAIQdXJ_=wrkDc{0I#-Q!|6hIkud7e>;hd@bQqD{zOHQq8*`Hr--C&CmK<-Iyx zKmWoidvWD@+qGwh?be}d*RG8^sBE#lyEa*u4j8+4Y}7%F!`NmU>fd9Z_~bk6jQ5=E z7Q?S{M#l_D#N_jh?sP>ynaebR2{EF*)G@D^X`lYwIoi53>JZrFbvby@09-&B*si_( zcHPx?+n()v-6H^gZ5v$L6u5($AmowNe^bNx!XP!Eii4km=jg(X34`S-053a)dFMc7 zZhUIvJQ2KEGz?phi4gU{e?qp)Kp&Mn^-`6yBVfSG^|U1*57?BYZiszl)b@m}7n6^} zod5hmflE11;awKbqoTZ)i>Kq*>T#gs{cRG`CrKzCL^4&Uccj=JFyQI6j zd9{|DRzcUXMcXHO3L@ZOh9d~488}&AmLVbdEAtvqF4q=f>B!I^2qGX_yLNZmQ%^2e zb&Gplf5W;jrMPSjggh<=;OUxS8CjFfnYX{ch#7ASK%Uu#Md#Zq)t%>IkSt6jBMeX| zpX(Y7Cf&%Ki*>t zuDjb>8;9&$-~Eium^Z`nw?hIL&oCHh0BS891b z;kEPam{-rXqfR)`jy>@pn}6g1{MJV0Fp`}?uzV>5hVTwlBM^|dLHVUhSdf5qK=I@>HD< zQt;#|gb{Bq~Hl!m?nr^^qh;WhjfuJFX5eKpOZk6hadRLTU zuVa5HNG75aW>6@Be9{Amvn=reqN0f)4j)XESpF#z0)vks_`pXo^pL^d49VWGsK|ck zBMebODvzQ09YK{b5Cm{y(BP|3hJf~5=5tS6;??_9KGWF`Kssrn8|ne_(Js=i{^961 z+rT0?7nM#uz`7TWgKYO`6#8pt)a$)1>6mr}wMCN1ep5>mME*pf7%1 zG<2Lc5Oo0UNA;^TWm%qeDSwoOLm^$3Wo(;FXI<6Iz>@p5tj_Q{Om8heErQ>*5`dFHy-GZ! zu>eV%NlQ6tCK`J7K2;A*FLxTz#)CdNVQT6b8y>hqc6f?8f7v!}p@%$9NRVx5N1XhX+n4D?+knI+BtLGza367X5Ii5v zD#(;kPfUQBR5GC=2%bgFDWg8yBwn@$%JgUx*G46vyeZEZGx&Mp_v_9z@i0;7gPx+? zZ*aJ=F%t5c7_Zs@USA9*06l-2V&pLBls!eCr1H437R-FX*4|4l+mO zhn*M7&=dT){HjC)lqdg$`1K>{u%8Ei20hP@l=FpA7YkXSqq_2V;g#bnPk*_m1&>2? z@&J_U0n(g>GR@d~JMJ44?XnGhWIq5pcOHr{NW7HSd(l6-PC0?(rDoA%PmMr?pB3QB zViW^3jpczoVS!&E0F*mRg8m|BmLbYDK+(P`EO?OzpAhYxIUg7eo0Qqp+h9NW(N*^B zlP|glpp9P{&?g2^O2@N_#Lz&mz3ZG)?2LE4+Gjn+i%h;9p$Db?(wo}*Q(E$rOP||n z-~W$GZMbK^Cy3(}e7c8M58U!K(LUvrdG_gl{Gi%#aFv1X?YCXK`|Qr!9=B(ndd>%* zNy3kux3tDv==~iIBF7+d{ZzIj4_#w#J@aHc{=|c1#PQAtb>_PA!4f`iz4rm8ttJ>N zha02HQg;}#X`$V5)y+1(rPjXj&5zpw^JlnWyNsekXY7}g z2Ia0F^+OtiL@vtYrX7d0=f^;n6VM&oIOrxW^wLm+|IwG=e5?e{o1mP}Nr|b@KKY{% zJlRBAI$ke2h)!UFwBuGF85x@w0s8V&y0Wyzvf#;i z7EbUd+Tx$*3fu=s&Yr#j8SbF1+th0pU$Vfy`|V5Y_M0BE&Fgm9`j@uY)(yLD_qM&Z zdF^)FvX-*Vwr0&HTlext+q`+FZQQWK)~?xRS6+6HeeXMewEOQ{V!b_hLf%~#51{h{ z;`GgfQSQCuB;gl5W5lEhh{BeF%VRF5Lf%MVQt+l^17H3GXp@0DSFqB-V3bwr)lE&Eyn)r*=4~VP z-#@+Ho_uJTwY9d4QY3BC6ZvFQmsG#`t*^5E_V4gZf7~djS6w{@t~5`sMPE)v9fgtd zMMoZ=bnWm~oS9v+q!K1hCaLCg4^wT-@4Ei-1(U8*}Bu8h-1GSTO8?5 z^!$AhFeYh4(dy*w*+=qZ8OF7J=U#hx^-jCyst4`c-@MRnyZH&*xt$-h;pe?{s8mz* zBi8*Kkb1&f5~utC#tD<~T+s_Wpi7KZ9H4jh`{=?ClcLRCc}eM>ADXCux~l9Y0}_4G zgw&D#Ic|();KEYgX#+3mU?bEsF}$sS^58YLOiWIIbkHg$g#vkKUqn+^D!`)EwFq+#J(!7v_X5fdS#E%A>JuwfdrxCy{__-=L zc*8n-an(-y*$*$bM;};bTh?#W&J-Fk*oj-!2~B86J_e$KrYxG4f};YGor@06XunIU;6W-JIf z#^s6Wd@Jamb3h#cF0!#Dqs;quLRzxqj$FasP(TaeO8M4#fbey$M z>hPN$C@^_rz(I+4q z2k798gdawSeT=q|&~xxX3?A)C6Ow1}QjX-g3RT>49Xj9;4N#_uia*gnNzr~+s>BGy z%Z;<+Oas(Weybfs=7{u@4Aq1$O#=~tiiAR6k9^Z z9vzDoIMC_SJ{sj=mAP-IQ)F(Y++7aMK1*6&^Lwa$F^NwN4 z3r%A1ax%HB-ic&lR^@4&{a<#T1QL=l0A^4K%Hr*g0CkizdZe@C6w=%1(Bk$`TW_n^ zb=j}~`(}ILnKk}mI{=&%j)(z4p6nNcX>J_0H=cg1H8j^)XIHnjBC#xjn}eOa;=#BM z>jN!5cry-<5c*{|KEm<-Mud-vDxZC+XB*~@pc@@HRX&2g_;V~lQAgiSlTwU`D%Djk z2YNn?gB}o)6{n`A$vQg+ZT+26emUW}W1$n_c?WnkMU;4BAPq1XAci0i zA;@BAvFVFN}z*CS@KH%KD+6aZf|eK6srLduY=BP?pXXJL@Pmkan6cs+0n;c@I1uzj6UAt@ zzqGE?{&3O#_M`7!W^0yjv^MTmsU3I-5)iz2zr{d6gWoKhI;q88d&-g4&=Pm)P$tF+ zjZ`$e@>5*U;9+?Vb0~rd5X!7hjEtd0zvL^j7cv0wl5wWt7yjI^P&9{O+KEr6fu%~( zJk93639UMxC~U5yTQ5V0A%7e+nYb%fZm{dFyxqMp{joi3s&AA5HTmRAK9CzD;7|-7 z7@q4vDd zX?p_wxO+Bit!y9Oa*{t}!z`vh_HhVL|3a0*@HD{>GVryT7-$)Y`hmar20<7q^R`f< z^MTR<{^OlsBxMKC6aDt~c3W5XUTtGKt-H4;ekWP05noX!?Af*3_I7u99na&UXK!Cv zfq(r7{fSoP{k_gltqzV|wr0&v>*?z8gDy>ZpIg`7F3B54L%=AwLX*p_A5t}uFi0Nq z@0BsSZ0JR)98YkO({&;J``b9R@NgTOyM-K<&<%Pf=B@91QJ_yU(kAz!RT|YR7ReiZ z5d+j^V9X0I=(Gvo1^+Q=;F7HmuODze)Q+*sHngt$#3w%WO@>Z(<^(XxL?{Os1VX`5 z0_0U5b`}E;9)KdT2s|1d8Asng&|q7(4%h|1zQtB9TkABK{dl9wr8GbhU9e=w;Ym1* zv^v6r)sOVqX>UH(jyP_fE0Te4l%f$FBW5Yh<;V|H&abvPg%aVDWt4ZlJ$Ta5gj(o*zJNVE8?4U!Y+rbATTWH&EiXRM8Yo%LS6j%#E8zK9}O;(uyfa54Q7uWe&j*a z1Oni?iRCs2-JOqAStEz>?6URt^75DDvCUrdx>wlvN#jBn3h111$uj|u&~gV80|5o6 z!yY-dO)>WTZnpO!1Pq$(2rmT$Lf5e`PeZ1!nfivq0R~^3yUnBk+WyEK{;{U-}l?L69~o)1#m}s_o344po|ggd*s?>XX)PTUrq~`JR4jkYZvS|! zI{r)1tu3{7+_7`*xZ`KpIUjn1wRFVK0?-a2Ib`%pDa0vodKdECRAU>{$CniKK|vcg zb=$)aEcIt!837-RV9DDd6CN#IP*@!x==SyQwl}@$IQzgy-fR;m^X1cS)k$aa{3tPB zYwB;afgrRr;O*^o*0Eo^?b+RHYhGOM%e!|jEc!&I&%zmtS~Up0n0oqw~U)nNwpGg1)*0m%FB`HK{JS_!fKk z!6$9OeNWl__djln9$Dggoi+CWQ42jo-^ZVE5)EI4ykiA;RYZN_WvJpO4L35+Q=d?+ zk23lPQZ7aDY>Hx5E6TaFR}5Knj%2Qc65#|0csa(VJcaq=`X(BKJf7~tge}F z(Q>#5AsIkU|P&>FMD$RN+Cut8YLFVRWH5gkd`o1`Q5NoGVN+L2Hmp zRfBzY_Sq-Nc+aqo39Wue!Xw6EDfV&h+0cjD^vi>G^>q2+u33}%q~qq;2R`_EJO0&2 z%kbkX>*xdTh#4@xt|S3pVdsgu-JLzQapO*RK)$t*Y)mNjsO*2;dn!+$Z~AR&ZgE`a zTPqV^zC;$rh%FX-Y_=$U12wkbo=0uPbE`C=bU18i7B3BU#h>rAJ8yYZdc;|TCxn)d zkMl>KJ90X66m^s*PTCP^#);rIBVZh;2f{c5A311~6FD!P5x~i+VOY&AL zz%P{vvL0N#AD3gGPZ@j@J5wqP#f1VHY(*ZkY*HUr7ydvF|02W97y1Oa*q>Q_?eJsf>!6nhPxL1}i=OX2WzbGS zw3+BDS8cNEuf5YJ6@0-H?b_PfDif25+|$?X``4kNxN*aS{_X8;E`QKuYZrT6f6SD( z42{&<>8BoVU;X;|_QfxK*xq;UTW!{?*>?4nci0`bKH`UHzsezY*gYaIhiCStOai}j zr!v0+!!|{EpG?vTyupWWQ^XfGz@&p;AjUilJ>^JXwL?bAXct#l!b!2kTAT)^T?BdtPV#!*TZvVE}kep;BmZR4EJN3_bzhk1Ac3 zb@!gV8U!hlmO6D~z%2W2WZG)@9Vbl~wg-c~J=QSNZ)d#aXnWrWPqPX8b;wYPA9N8g zcz(UP=mY6QuF^j|wYIg&h~&)%V`3e8*#7pBkG{zcJ#vnFZ{L0hsDp-5VWb#^^s{@< zpuMzehls@(`J@$YdSGIn{pD(ldX~|4I6WogzNi)O^;Q z@%G`5y~E}oGT&~#ZlT?F!~Jf6?&Z~vtw?iQyUsb#fR`9YUd5{nEZPVI507fcJJ+xj zwk#MoW5!q#;K}W%;18JyIgSLt(;^R!kE1?Jz`9R-GWNjn*glj<@&! z%^U5oqi0*4yaoN|#DZQLV)EfeBSn@C+y`0p4DJAODF*z?i0bz4?zZmEoi=CAWZQ4Q zCYw2Zg6%)O!w#G^(WcGluxZmeY`V&(@84llC$-u!N6xSheC$kX8{evBx45W|j`Tri za1wh(WX7V=n>@M#9u)k5;FTxg#*J&T*#{kHJG3X>v~jCD0@`!X^zD`CGRe^mr|zBG zI&Gl4%MLkWw%-fN8v#J*MP=%zQ3mtEi(Bp4$Cv5AJYuJx@hTfPc|yftyp8&2i?V%3 zzdd-*!*=AMGemd3zv}^SJz*k0F>s*Wamz#2pab`-PB~hWmhBQxgmu_0H$7~RJiN@- zuUl{P=N;g8L0v}ifK9ZvwA&MlSK0#$p0sD5U1`(ypKRkh+Psc2!H9F4m;C2tIrz+# z6nB99Ohn|%@%MVgH4iU((tlM9?_RBxc z7Umm$fx|Ug9%c0Bh($MfMVA<-ds)$BIYy7@p-0_r*;;G={?9)X4fKmFQY}2k1!(cX zB}XiF$PSp+Xy5wZpRr->;Th=EMaIa%uM}Nz%@cOpWw%;K(~y1jU(d7IhtJivjEDDm z@(_c-!8F*i<-6<$|MnC6;5o0ccYWwAzs3yTT&d~msc@2UO-1l zpho-Jf#G_4bkQ2S{;I`x_jQk2_pUx`XpY;AkYeUQl>t#>-#f9V;MQy!b$?%vmc3zl zzIJ=l+m5x@zvWf_6@EW4t6Ta)SOP)@ud)0fJoV0xXd^5EJnEPj)X7?95Heh~<*pMS zZe5Rz$a?rub1A;AfyrV1Fi~yokd{ngiN`wXctk_Cj)y=8ZoKM`iO+tMzIZsC<+7Lk zsjBHWcwmy@iFsCoiCXOYMWkPCn;T__yh_!T9Y!rpDblc^YxNVxDLtsVNh=bQfyu)4 zZveia2_6qAv1;vy8a(vMzZUr(zT%e>(cH-6wx@)WdMTAQ3B_nPXXv9Z!lU%`X#cCp3=T60t~ zeSTCSLL9PqJ*{7bfgiCM*TlVh(T=fk-Ki0WHnte-NyFpEa|6WCrw*fJ6`{R9O6mQ? z?O>MPxYb`6e6x&HW8;??HDTGOV--AHlUpLL;Bb)d)Lwn*vX^b^=ACx?Z42z$tM0Jp zpI*cDkJ+tP zKW4i&cY+oQ29;(o=mzSe;T~DztqKjk>ghr$o6u2j=YHfgJLOGBsZjVr;;_bZ3k(SS zAS45X(F5si0EBjfQcM{*GaGbtTU{bMLC?&)KafeQ|FV+k#8kE-4WLxzSd=u9cE_rqbq zllx|M8kgx9aQ2Ha!Jr8a$UM2`Pv5Ceev1yL!$eCxK?5V=&LtxIPpHXYTRCjW_~EI$ zYuIkR=^@*;ZHrBwJTX=S4sZj*wrTTbdv@vbwq(f?o4j9x&I%pYKCZF&^&$>v!`7)o zGPLNcrMbb{+8b@sqzQhx6FyT%jBlpPdQKb;_rBkSZz-PZ_O2sz0#6KZ8ZRI6NeBck zv(cbQ%Sm^CgWY%Ua=Yr%hwP@S9<**9KG>W2p@o(*1lnWFNz-Sg7y(5Kg^kEd@i5M$ z{c7wzA9%f;_`1V=iHhe}V~?B0o5B!cz{0~O?W~W!g9mtr2BB;;lry@}rW~)1a@|PO zlz<%IgF}DNAnyuOU;a%C%|N_b{*WVvg9qn!xc|l@OSL>R0mH%bJ&zf^R%hpFf-w{NpWikd<{j_n!LT5b)M)6QBiMV!HAt*p%iK zs>5rDZ~e!o z>_5N%Is49!|Iz;SyI;16llJoo+|pd9G{0yxD33eIUS6}!7T))y-G1x6wqfH2mk%8z zkj^p!vY>l-VQp3CMe!^FRK{Z-Rh%A-E%J5D=bCm%DBa?4F)lyXBT=?AB`^ zway)T)fg8qr75N(g3Kp~yYf}x8I~~RRnJ#jX6@f*?>grsJNKh+vAOf6NO7@O#SoJY zZ8126A@74DAf1ARK?cx1>qv)kqW_@9(w<(Na)ifw;Q_+arb4oBzwRlTVMvmpm;@^F zf#e|PhAn_URww`*yr1h)?GguCOc=h?g;B$!s5#G_JtKDiJx_BWaa?F*zr^IZ%c$9J zGpCQY*Sz6a8&;lYD(D+tUH3A0_+%UL%+iha@(V9ntM=HZyzU5_FhyR}<%$XA&ojul zH*W2+h4(z-Bez3mn3XSXvd0!ZXLsJQz>Yue5c`KOo$F8i@fLcv9Y-B`sBPP_!?thR zWg9ncwoMz>+pO8VR1pqz7SI?Ue)t^g+}opr{T5rlZkOGA*J4|6?*sOV;|{eWjy}u} zk>~^Y5=f&nLh1~_Svamf#7xE!H3KI;f+XZhR|Sf8W;C#*JNrlMnrk1kdv1En28&+? z%F8>boOYyxPSprKsC=NmPsIba|I}uC?|HAclTSO!I>t3fkzo|cG=qxgNN+(o5PXCo zGvMXHC19My(1Hf|97fVRt7#=o9PMlUMI+E*3lNhf42^p7^aV}lMLemMKh4FHRKpr5 z?y@BgPtWoEfNv307qS$}Czd1NQljIrXq!9h>t zgIDfa;mx&V>mU`Y36lZ7nb7bN2VH3A_sUwD>uu%%6K&(Bjdt5DciT!Uu`#DcaK)&NBqSp63Gw9txZ~O>IUpXA9=Uh z)Y|2LzTQ@^US;q9z&qs4U+FxjZc?|z8GNNG* z40hXRKJzX+>i9YSBvX1J=#&SH_83$eHTB@JbR<5(yLoTUuHipZ3rRLkijm z?ce^Dd;s{AXCHWH48|v?>XJ9oX^`MBRW+<`FqDHwJGKZc>F~m39=-++ZJ~yY!p+A* z`6B9|jC$?HKKqw1|JL7hFC?KvzYaPZ&>K71#<~%kKexmF>D!;MK7SOHiJo^KwVlyn zs$U1khNfn_{-$Mi%VoFOxW*y-+BZIEvyYhLk5w{xm^6M3S-cGNYmAGnN<8cyle|%$ zTkLxtiGjGL9S7pR9_doN*VhkPQ%e{fjw8-S2-r!_HV3U1Pg;5BRgYBfVmZ*-M9k?zeA! zIYq%zjMJh65R~Q;*^HST_R+t6lYQq0pSDAeo?+eEFQPm=VA(Jdc=b|v;23ZOLoo=$ zpn{v*ffO>086eHITIhx+j%5jfvMq;14nEMJ4r9d_5;&3L!J&~j83WF)0+ZKYVI^L< zn$X`j=w4k4@Fki3 zo^GDUfNqSXPg0lDjjb}y%fR4wou-c+7rvbGE#KK~3m?!E&zLP!^0?55JH2A4jJa{eJG09CCdgqcAfDTxjh2o9^j+?YZ z75`q&1*7>7+c9??wsiShchNnKG+zmzey09ReOdV#)uE2X&7 zCJ4b(47|z%RJN;g&=xORrKu5zgHRaWf#p~P3g!3*?F#S`Tu4~4``9F$SCS3EHJYJXfV$!otT0nZi+ z%m9F&%E>hSr;-pZ1dn>sq3r6V8Q+_${N?qV?b@3jvbz^7w}%$JYzrTG(e7Kg!tQ?$*ZIkOoQyi&t`i1;9Q21FiUW^bo?>7bcswJ((uyHrtbRZd z9tXF!_Ersy*)vbA_Q?^~v8T^& zy?LqKchl2q6tf8iVKh6-G>YH^igu<F%?~pWSBHUiE-A@gfzNABjl{4tKA(i^h-6 z%$>czo&D|;Y~H*neuaVkv*Q#48Bz$~9k&Oc(kUJj1A!(VKO{S!nh4s1cJN{=1w23m}pap#lf<9PkxmMkvJ@Cbs zJZkq`$M3}Lwg3F?M{U~tnXVJR0wP^t40vBw7k+uOUvl>K_KCNce2sh;N&WZo?6vyl zMhCa9nTY(rOG5JNGCJdtW@!CtiFg7Se+-x_DfI1+S4u~@0-(ce&-e#_=t{O#ud&wH z_&EYw3N%mq=#C6U=ivdE!8NvH$AB%o^J$;G0LoH@dk;EDV}=NV!U50uPTa4~W*pcq z57Xy+F>nS4tIxcqAttlYZ}b7UFv3fZiLx=4#G!qr84z%iZg`V8yphj9d%PiD9bWOm zlO}X%P)2O?CSJ_9$KOx3b9;~N*wSU&Hh0;^^}B8BmLA)^r`DcZw$X06{s~*LVvCmh zHus{b1Hku(Y=@)-?i6vb?P9@QQ5cpEg|CiIswh zFB?%QPsK%j+%s^!iH9xQyKULBwYF*97B@)dNUHh>0b@s#qMg`9RhQPq6NT52Uxn29!fBA$aEk<75UZrlbZA@O(dt>QGAIk8A z@B$veUpgq1O`Epa?=HB`o_zX6KNHl-(01+}w9EhWkS(}tv2R6Mwe{;5H_5KQ{vrGG zr8jA>98au4559@%Blr-B-{s3EMh0z^0u5J?_=5kv8q^n8Zr7IM5nK5Jo+CUt5K0dv<1uQu zpj*hHE`4%9tFfuU_V(4;wYM*|dv04~Lp{Z>gwmJr;4^v00Ju)8BJ1nvw(;#lHg00O ze`Oz9q2r)SJ0=iDiFb7+N>~0EfM{?91u6XcYwAFgl)es}JN_7X#KhXZ}6YrDJb5P-75}mGFT8fiA2O6FFb+Y&O4G4z=15Z}9 zwQ;ZuTngM;|U*oaqpr8gT>y6>z?%C*I(gFyt*vn8`%Ja$1o|+LmXQp zZZgc9qgCVlx2sOxONzuWFdQ#XVEJWYH;U(0_1|W#&O0*k zI#_uu?J4;d0*5}{G|5#BwjR5?hwb*emfL+dKW+n^y^ae{SQk#fpMMs=lzB16s{x;V z;3WIP|2ogFgs>DxeJrEMi#&`B%d20elWg$gS3D$lZ!d4?jERpy;f?XMj2kcAKH`XZ zws_I=_Tc@`Sbbx&t$umC?d|Tjm)7mEr=MDB+qLB1b=yPMuSq_4?o|I>I_Ffnq#wq$ zU1Pu%9G-4VzQTFML>{j?4#MLnjJM{d7U#FiuM4ZbBomNref(tQJc>%-Ix_75pM=7f z-eL)KBb6K2xM8Tq+WHN>wq@&}y}Wj>ZP?hWdf{y7mZJ99nss~aMa8QW)^G0fuxayvLZ5K77u^DW zx2;ur)7Amox^2K|ty$A)FR!8f9(z&Vm;n!TZ*dBXggFW-?W?QpX{3)#SxX+fqxYJ&I zN%BbUm)CUJDy3hRocG+b%C5cQKI_@jCHmEsjedMjDkCP1F~g^S%X(NV+kV3~ZRTW6 z*jSlx2Pz-xWI^g%TX&s?~~z<*dKp?n;#rE zZrp3P-1wk%v~}3tJv_Iq{x#0&ywr=;N{{PwhIoF(Hosbf;##$G)0eM6>IPl!+1qC; zG%=ofZiBtBe7)bw=E?%En+3NF$tUu0mVzcujmwQpzN!r3;Qob=jqpwgTz-$j<4K)qn#C zFVTPi`zw|YyhH38V>Y5}1_~kZU@o8(;Tw7hMc+JQ0ZsqDzbF;N|w77AA zOB=Qd9MsTDJocxA$}y(@UsdMW7YLvzbDNBv!SY`rNegbY_S22 zI;qY-tT=7$3x=sVXBtYa_(T?*?e4RV_8u#!o6PAt*WGXV&R)x9`z_biYn|;m#Z|r5 zqx&8W4zuKS+`&<+Mqr^ z^gX`1+!iismWL3rcn9H@lrJ%clxT3}5)r5YZyt1N;JW$wH$99=;YMO4=Ttvf!bo2N zQb>Vkf}TPSnuSYVbc@dZ-XVXM&-Q6BEV|@%c`Fy+p5OzMGb!OjY!6=8_+TM#jgw03 zG6`8yaDh=C4@|t6lo@Y`qe%D;YOuIx?@4=a$NN^HG5Glx&b8{=YL7F0s!es65pZ}C z`nd6xcILcuY}eivt8bWWFTePXjgdv7G-GSVT3ubO?cM#pePhjX|C9hT6Gdw8=&^!~ z{w2F`@h5HhiqA{IyFApGHl^Ms)Kv-3Qfrf}Uf%qU_>q@^Tp{Ka+h5+;ZW%d(*)!{G z&e=^6;CSP)N$4W?!6)$or=h$wCHIj$^{+Tacb@MIAok?vr>IC{APaLjQW-pQnqCtt zG%{8IE{}~8=DG^%BBi)eP6XK9*6lA)79`}nx{-ont9YSO<#Y^4(Bx;^DVMXZuB_m( z>cy-A!Y@cMsNd^*4e~vLp{_2k0gxYpN4bhjd^-%H@z^kc13JMy<%Ocam|zq=!mvER zv?-N#`<<)AlhJ895{%-Wy6_4(C;(obSr0bLGeBX^lhV!0XVTR1_U=Dg?2(5zScMdi&G70_Z0F8H_S2s{qcEe$W;Rb% zTV?Wz;)Cel^2#ndDu-90F~ER&L79h7zdrek7p(QjDJxSb@!^4Xdvn|0Y}Sm4Hn(ZK zExr6xcH_<0OAlhX+xa?zJJX`zPx^=!A)e;llN`9_IcHyqgILat#C7r|PY0quUxQa+ z4lhgBDxi2FyfQ!$CeH|X01850LUr6rjFjh@!ySR;_d2sFCJ@5f=#oR!cWLyIGgf0GsQ>DNhm=bpPiul9cfz^j+2^I3ZC!`S}V%N$|wt# z&1tN12Dl zIZzDhf>w#}&vvz`H_Ta+y7tGP`mT<33I$HH&TQ6sGDhPKbfiSRGKoFWU2X05&D*ZC z`@Vmpt^e^Y_SoZh*aJVhU4zbv8YEYUmJU04vejpbDyu5J$2y_0K)K-Hap?_6TqD;s z-3sm`@-S9pMS^eSp;w_>Qm)8|*Ehl=j0zl&fX7WjaA7I5pkc~zxK|bo-FO+ULs66k zB7TjJ#Dm8(%A_{94sR5Bh#5SjqC_a_28E*wER>Pt(_t8r!&NsUuZ7{^y%0(&%g0L6 zd@c91kzgb|JYVn|8fxs~CCzrv{VQzc>Lu1UoVCu*R#zaOHyxoNXn{|GJNGCBZF7c( zZ~~)(h-(ho!>cI6KX546qBNIlxAwL}HnXY59{%CYcFS#FwED^QK5-9y;2O$K3h(4s zYM+?cjbEtHF1y>DMWyyeNKvh z&iom6#j?xoKl=|`%dxC&f49Y6dVZUF3gItukXwr9(SeWem7yK3OUA_B49Y++*C35v zDuf7zlY!#;6p4uUZ}d8gLP?Pu$_zI|PkQ3dU>bl!n30m;JONvO{#;B27S~B>N&heC zXu!Ypq6`prCoUL_@^OY(5^cj^uLIty7fYIaR&ul-f@ z5Bs1Y-#=*YynEO-KE2)gH0Tm!k%>_7P%7-#;c=;4Ru;>t%9ccg#84nYwZvRfQkHa3 z0rJwlgHU$zUQs5LJk%Qn4P^*L4)~;EF{;G+ZSmq}TfXuF2{J+m2qocRlA>`Yu{c2) zU^qi0bOwflQmEqM*tUqr8Y5w6vjzKb-+!&GwO~*E>J^n!te8QGV!#NDwDl9la!*?@ zn|q8Ay2y*)rNhuogVQeYD`)2}Y_>};JKq{k&sgKsNv?1R)%QLK77E9JE7}>wJGDoi zf5vviU@%}SDYM`Fc86`<@VZqD=WX4C*V(i=lcfx4`5oRyeNpUu;kr))>OH#;SWRV# z&73>ka`{2qwex@!cgQ}mpvh$}=8TMs6pEmt!=<)Q{ApLHz~^tzm@(e!C)T;Q4_#1W zMdki+!UG472>`zTfd_GdanxDRaf3}lIM;={+mWE#Y3 z>0U|H5h$GlUMOe~3M?{`FhDpZx3p?cMSUU*}gPwN7uu#+KMe&|4U={fCa*vEx0q>AAP8?L>#~Bj&w6 z>H`}ZlF&HEHQ>1CJZ$-%ZtKZ)*rlIaWapnZOWv(cq00n46zN`8yp-1kZt6W)-Uk=1 zng8SrjkLo+h_OoW3t6bG(u{5T<9oL8iOqIe#h@$j^f}Wk$3__7=}!=;;&4+q$eR=- zVrYH~4rQaqiZ@3TH>(`0g?JJ810KxVmOOKRc5?uqPgS z(SM5qM47Z^EuJ}I1_C12l?S)ZyG~5A;n83Suhj%s=$_)2fKZT7a@NnoD1?(dS)WhY zK@7q`5ew=jeA5d^D>QIL)g6l*2nK{rRUjv#f`IPPqT@qk8@?BJrX@kco^jhM+6C;qQLRw z8b$NNd5V1G97H1vGpgo!C7CLFZsWgf^RKsBby?o-zHfy!&uexVC8yV~ zHCQ3pAR_&lc#24pB3^^gOGz}A3R@@A!u-bA$H zl!OC`x;&#!^1wWElOb$Yd0-=FQqiAY-#&~2QYn}3v(AoQ38&zV;LTvDPkO5&!UqxG zl&ohN#bbEi}q0l5IA7$_F>&=o=l4DoAe zfHTYKWl#}=9)Wa^!8M+T>;A!F+r8(2M%eA53&R!-u0+%qA);B9=kQQ0LQjcZvF%i= zuN|)&kmL>GvCdO?NAH4Ra-9)KHh{$8J*;5FN~e6D@}fJB_?vQrl4nxjl;l#}c!}{T zgTgyPDhGTV1$9V?uY_#QM-*3*=UZ-3g8zfAG;J1jBaGs{f1pozVGx0z^Wvo~Z+kHW z$wC2wb3{}To)8+aE)H{0a__dKpdm~U1KCh=ya4J*NI~OHyvos#GhD>eSeeQrGywS0 ztlEIFAWl8z4DmipLt$||2S*s4M&iJbO8GT<pUFVaZTJiLlwgnYJ(#lEWJ*Qz4~b zx(Pw?IJ}Jv4(6*HP34DuAFuF%x&h`hrIdO`9iYM!dKSvWIfMs1+Gf$g4M*s*jE?6C zrIpes54g@BhbF#b`Dy_;T%|VrUX8+gdL!B=FNIt_2^|xPM zym-n!DOtT*^r&i4^rWT2$$D36{{Q(?!{}c>?LQO$;dcV}@8AEn^NntH{!~eOkxR4A zMed*8n;pjfYR)7%DT{|IwI}R4C99-oQSm$HYT@a>eqa4Nr_KKLB42Xj)_<3No(@yv zn^UBp&VJ~cUbJt_sR!vClS?J?SAO9YFHM0Tc1NbPd(D4+TKw|(Nu62aFhhI&8{eOk{Ay?W^0fS%<8wpJ_wI57YvE$%#`smwaNxJ!@O7(|NJWS6`4Sd7t8wZWqnB z^J?+xuaS@S_db+AaVBEf`GdwRM|QI|-DWlrs!!nt@>m)h6a)lVn3^0M1UNXD7#$T9 zIN*Yhes{;`DISz%T2$NqVgLKpa$lX7Hk!{q_hQD%!uA`RrEj$&r>3`pN_Y~KuUt5;ei(Iy0 z-k7~}?~W~1RXvxa)`ebJbv&a#y(9T_?$?*?AM5IrcX>^06SieCOtC)g_vZDR#|-w} zCUc(t3_do&XGxOs<^H`MhhI*Tx30b0o|1IMjc<<7wu}Gy3lH)t2tU8%Fyne&LvJ*n zubN*7%ORQD4C}uahgYuhy zXKy)<*;~$6Pm0z#rT2ac+vdl7A3M4t_-u67c0N5YdHWr0-a5sVPY=w#CCG96#Hyzs zwlV##S#SE)TSK?q+`8=A&vSKcA6zScf4^C~_rbzX#>OAt&ps=wR~f7j6)hpYGit)m zS~az$r>wu6`yO|NJ9POg{l6E=PUl-khtDVrUwbnmU~WwMv9->T)uk@UteL4_U!U7~ zI-LLNrcJj)cX#z`E|)sI)lL8QPiDyuaU16crx3{wYg!yhf-3v={bPDH;m4F$Yo*hG Pg(-ultDnm{r-UW|MyW+1 literal 46504 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 From b024319de41a2ce4ae039b2df6e9c9b3547709da Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:13:55 +0100 Subject: [PATCH 028/312] fix settings, missing in apps.json --- apps.json | 4 +++- apps/ffcniftya/ffcniftya.settings.js | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 507a70e76..aa3b49884 100644 --- a/apps.json +++ b/apps.json @@ -4328,7 +4328,9 @@ "storage": [ {"name":"ffcniftya.app.js","url":"app.js"}, {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} - ] + {"name":"ffcniftya.settings.js","url":"settings.js"}, + ], + "data": [{"name":"ffcniftya.json"}] }, { "id": "ffcniftyb", diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index f4112c9d7..03d9f76f9 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -})(load); \ No newline at end of file +}); \ No newline at end of file From 07e6eb409086dd6e401839e823bb307b51c85deb Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:18:14 +0100 Subject: [PATCH 029/312] settings and apps.json --- apps.json | 4 ++-- apps/ffcniftya/ffcniftya.settings.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index aa3b49884..b5b6e66cf 100644 --- a/apps.json +++ b/apps.json @@ -4327,8 +4327,8 @@ "allow_emulator": true, "storage": [ {"name":"ffcniftya.app.js","url":"app.js"}, - {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true} - {"name":"ffcniftya.settings.js","url":"settings.js"}, + {"name":"ffcniftya.img","url":"app-icon.js","evaluate":true}, + {"name":"ffcniftya.settings.js","url":"settings.js"} ], "data": [{"name":"ffcniftya.json"}] }, diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/ffcniftya.settings.js index 03d9f76f9..d9a1c9fca 100644 --- a/apps/ffcniftya/ffcniftya.settings.js +++ b/apps/ffcniftya/ffcniftya.settings.js @@ -22,4 +22,4 @@ } } }); -}); \ No newline at end of file +}) \ No newline at end of file From df2cfd7015a03485e6d8c9ae5a7fabff6a535979 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:27:13 +0100 Subject: [PATCH 030/312] fix settings filename --- apps/ffcniftya/{ffcniftya.settings.js => settings.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename apps/ffcniftya/{ffcniftya.settings.js => settings.js} (100%) diff --git a/apps/ffcniftya/ffcniftya.settings.js b/apps/ffcniftya/settings.js similarity index 100% rename from apps/ffcniftya/ffcniftya.settings.js rename to apps/ffcniftya/settings.js From 036d2c55c08475f31f12713c6fed5c934146108e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 02:47:01 +0100 Subject: [PATCH 031/312] Update screenshot_nifty.png --- apps/ffcniftya/screenshot_nifty.png | Bin 2379 -> 2159 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/ffcniftya/screenshot_nifty.png b/apps/ffcniftya/screenshot_nifty.png index de6ba651d3a25034c1fc4006efb5e3ca4dfdc860..bbee9e27cc3554f596fd9478068376001cc1740e 100644 GIT binary patch literal 2159 zcmcJRdpHyNAIC={VN54oFdCJ_{7Q4%a+ym+NUk$t$1t~Y*EZxDr!r1GE=Mlw2=AWJqfPp zWB@?z*^iLZJnoha04M>^IiY;7URs<|@tLwxy^dYj*%`&0=Y`!$)_-w3gS9nWJ#IAe z+;bHTZQyV0*!IaKtO<8^HaL{NYh91P1+P zq4XQIjpF?}N*^cfUdHcH$)0vS9wgAm#lN?68Jmt9dCsklU2Uwju#0~BuDD@xBL>5= zKu>oI`wSBn@e?;2#+R3d2v(U{bZ#%5Hxumy@kqV{yKKKqpbO6=X3cfLhHjiPg^Y-Y z)^%NeI#@g=+)e61tpukYZ7B&rW@ZKEMZ2t=sHznZ+cuj<)w9S~`_)^>6gfF1E!zf{ zSKEY!$)(Gf3YfJ}#W(9>Bmp$2uLCSL5XY-$6 zr@Dd&wimA!3tmgg7%MuKxCOjDAXgE1_#blJO9YFMJkXy~v(tdXcb)!fzI~RhYr6aB zcQi(dizvF!zgJAL35HbNm#&rdQB$@I4e;OQ{0iNk1Y{j{WPf%%qO#*`Ih)A?7BM_tqhdS!zt|u5k1;2WeDYNd%p5IwXN}=C%+ce-sba`hc?wdBZ z@MQ_Ps~m<1^3qsZSe2l_aO%?GH>Ba|H(RR`ENC7w(s|HEneM=m1mvgA!GO8jYAW z%HeM$8Z>(EZcs9qM*l4QN8$f%!{3z6uT$l07jfde?e?5Xitl4Ey{@+uP>cdE{Y33> z%S*GYAco4f4AzGi`r^u=?q|rNh>FCvBFY}8d~Djx#q^lW&NJO#V@nP2{~10m9nT>Z zl!`QH*EMfs`VUa&J()vbT7h$6D|}_rP#<5`v_DW<+wv(me?$$1sZQ_U&AN$0!*x)` z?YV<0D1Nq3zLXrISEsm5bgUM8MUf=F8GigSw*HO{ zkBj27T$!?sd|P~T`Y&)>#GwT|*+l-VC2~*$h3N=qKfjZuE^$+FE%i(qs*baU(2V8Bn|#G zZskbN6-WRldGJgV4sGQv=u`1{HPN_6YL)P|+`0)`8$D#hXw6bCxgbDs`9#L;_*&T& zKx?{%WFy^p4n&);8R>N^$8*!_oBmk(Mg$EmLAw&n(^%Ew_*&i0d@?sogEn44uijN) zs|RT{)9Unnz0V>BI0BX%)XeoiD2mKirS|ST*?_Go+9TEC+5W0%>k3WA2D}H-Dm+%4 zl5d=^YIyQm3QhH{O9H37Eme{O`|*FRF8(xyjzlY?dySyXRdrEH+Ov?2B#hy#!AhOO!+oz#}Z7!j`j4A4WQ64 zs}YNxWZl(SP9p5bP+eb8n$bq>k_W>Fruh8Oc5pSfu7uGk`y>F)IeR*_IfUi@7n-mH AkpKVy literal 2379 zcmds(c~lbU7QnG`Dod+zQZvX(6C0Pt9Z)gN#L^&jGM6+7l@wQy+_lou!f=Ul($XfE za>HD(QA{*b5ETX;#l$sKEHm82{n0<~yno(*@2_{x@7{avIrpA>zVF`qo$tYABtl+J zRSp0E$X~Ftagy2rsci1qA=Ov^)>1>%y!7xSIcEXKsLW zLC}YRrJ9h4g+X%&(w@9J3s;-0qHWs*|DB78Kb$=j`skRN$p2uTdZ*eK8cp;|a8IUC zbZRP`_vGgzSk*TEkg%`Df5khioSuBTbX`jksgs*?W~HTG?YH{RZ~x3Rr{Im~Ue-D~9)nmvZ0dDLD1)o0n1^)mfEJF?v!b1H zIj{JV64z zO5ZaWAKUy?LRd1iUT43o#rmY}5wOm{RpwR{%;Ijx2SYaGkXAe|(KkcdoBX8NTWUe? zwnGHVwL`|I@v&aes-eC*k_I!mwSf%REi8A87g1PqQN`7$sC!mp8HD4^EEq#0AG#t_&j7kR5Vm((sylDTC;%HY={&uU&Qv+I}RU?T{h<{)T z*2@H*a_wt<*+ASeE-}ZDw0|6f2ALCt+mL^?4ycR728Ppdcg|CQy)&P4*5zL?$;)EkmiEcxf;jxuy85S$*23#i)a9D4%)@^@8Cx zl5j|n8%7Cx)ilN>-&S@eN9gUe;2N_bVM)?SFM|$Ot1Mb}XbC@F73Gyh=&b>!;mt7N z_+y$Uk(?p)xemJ^C)7aD+kp9;_Qs&-To4#KK%7u9c34(dT=)ml&f}b5vLK(*Q0<%2 zIJ0-auq5D&WcZLZ>%X9oppDt^9q5fsclj8hSi=45q3@xDhBvt+1&>-JsW}ije7W;5 zGp&VOOCNq3pg&5=RifXF^^6V;bDn^Fw`ts}ktl`ed1#bk)GKbx%O!4zWV;><+2XJs zZ(^Wme#f5O?P)@MXBchU#rA7ZE1cAZK6>CL)E!3Ibb5_ACV%ehXES#kv4;CoVlNO={kw$S@ihwmL5qgb-uK35t0fft&qS_E2d zX>$$@bbayc9;o%dNfCf?9m;ymDS3LjuiL;lWrb4AUxQEgl1h%1H5s_W7P_Bc2p(N# z!+|MQoB|8xR&lgxvDrvlWu*};dMiKGk8<~%`yDnISFAOoj`m+H%)}I2F5r~juyTjO zsU_#1+D71^a2n*EDDG=<##>mUQ4*^=QnnQs;#KJS3o&wQ9fVTezpgKKi^)D$rs@@~ zr1Xz-FjTdIhRj&0QK1kvfNi~CYNx1cAYS%7mFPi2&zhz(R*42O$v_;IC6SQ)P62CY zSXuWa>^IMc>3+AJcV96Oynn_g ziG%1CMSCsTHJ93n{1cBvTKO}tJHKbFV&rn}PIEpVt1c%8=$c4?4(Q0$BA&;7KM&AR ze8ZYt!HG-h9lb^FAe_hkxbzfCJ7enfaT}|JaaWpA_p731hPdA{|LN^-+#B4vNu{2q zNcrb5=}K34_698aXDB%qPIuMUu{acwqMlvV5Us$8{PbSI*!+Z-gir^vAqcHf2C zG0~lr2W@c4LeWY+rxp(j;90sC7z9j`8R{;EAOFcZA$LM#)%_ V>F&$)YUu|EaN#`ChHCA7_g`( Date: Sun, 26 Dec 2021 03:38:26 +0100 Subject: [PATCH 032/312] Update settings.js --- apps/ffcniftya/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index d9a1c9fca..3e69f08dc 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -3,7 +3,7 @@ // Load settings var cfg = Object.assign({ showWeekNum: true, - }, require('Storage').readJSON(FILE, true) || {}); + }, require('Storage').readJSON(FILE, 1) || {}); function writeSettings() { require('Storage').writeJSON(FILE, cfg); From d7f324e9c857e3b55b550f8ef1e1c987ffab93a3 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:04:51 +0100 Subject: [PATCH 033/312] Update settings.js --- apps/ffcniftya/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index 3e69f08dc..65b6486b1 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -1,5 +1,5 @@ (function(back) { - var FILE = "\ffcniftya.json"; + var FILE = "ffcniftya.json"; // Load settings var cfg = Object.assign({ showWeekNum: true, From fa4f3bfebe5c44675e5634ef54a74451922497de Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 16:17:42 +0100 Subject: [PATCH 034/312] settings name typo --- apps/ffcniftya/settings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/apps/ffcniftya/settings.js b/apps/ffcniftya/settings.js index 65b6486b1..46e4ef5aa 100644 --- a/apps/ffcniftya/settings.js +++ b/apps/ffcniftya/settings.js @@ -1,9 +1,7 @@ (function(back) { var FILE = "ffcniftya.json"; // Load settings - var cfg = Object.assign({ - showWeekNum: true, - }, require('Storage').readJSON(FILE, 1) || {}); + var cfg = require('Storage').readJSON(FILE, 1) || { showWeekNum: true }; function writeSettings() { require('Storage').writeJSON(FILE, cfg); From 73eeea7651c637136ed21d246ff5b805ba2fe574 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 5 Jan 2022 00:58:27 +0100 Subject: [PATCH 035/312] Update core --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 2a8e872ec..5a5957714 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 2a8e872ecb143a10e53273b4d3473164e104e1d3 +Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf From a5664a70bdf9d34d60f0bb006c0b3df16da7be2a Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 5 Jan 2022 22:46:58 +0100 Subject: [PATCH 036/312] Update core --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index b05af96b2..5a5957714 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit b05af96b2522a7a7225a56d804faf9383f8a8f97 +Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf From 8d4820bd0ab7aab5488705c98c57c59ce1d282e5 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 21:14:40 +0100 Subject: [PATCH 037/312] Added missing menu 'back' in timer --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 1 + 2 files changed, 2 insertions(+) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index d129e9f9f..5c92a60c0 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -13,3 +13,4 @@ Widgets now shown on Alarm screen 0.13: Alarm widget state now updates when setting/resetting an alarm 0.14: Order of 'back' menu item +0.15: Added missing menu 'back' in timer \ No newline at end of file diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 17062d44a..068098155 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -137,6 +137,7 @@ function editTimer(alarmIndex) { } const menu = { '': { 'title': /*LANG*/'Timer' }, + /*LANG*/'< Back' : showMainMenu, /*LANG*/'Hours': { value: hrs, onchange: function(v){if (v<0)v=23;if (v>23)v=0;hrs=v;this.value=v;} // no arrow fn -> preserve 'this' From bef16014f0aebe0334bef5f9073fd21c1d957d75 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 21:18:31 +0100 Subject: [PATCH 038/312] apps alarm v0.15 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..1c0d60eba 100644 --- a/apps.json +++ b/apps.json @@ -201,7 +201,7 @@ "id": "alarm", "name": "Default Alarm & Timer", "shortName": "Alarms", - "version": "0.14", + "version": "0.15", "description": "Set and respond to alarms and timers", "icon": "app.png", "tags": "tool,alarm,widget", From b667b8b00fb6c10e827f65459c61854ef0cc8263 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 21:37:48 +0100 Subject: [PATCH 039/312] adopt to banglejs2 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 3fc0616da..e90c43aaa 100644 --- a/apps.json +++ b/apps.json @@ -2783,7 +2783,7 @@ "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "storage": [ {"name":"sleepphasealarm.app.js","url":"app.js"}, {"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true} From b80071447f081f5d3cd4c2c98b232ebc0c5daacb Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 21:42:48 +0100 Subject: [PATCH 040/312] v0.03 --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e90c43aaa..b440a01a7 100644 --- a/apps.json +++ b/apps.json @@ -2779,7 +2779,7 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.02", + "version": "0.03", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", From f6d5c25f5ffbf556c737ab207864cb52eb348200 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 21:44:12 +0100 Subject: [PATCH 041/312] changelog v0.03 --- apps/sleepphasealarm/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index 47448167e..f633abee0 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Respect Quiet Mode +0.03: available for BangleJS2 \ No newline at end of file From 5622c2de2921f47a084aa81ef6661f7b49e463ae Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 22:59:46 +0100 Subject: [PATCH 042/312] added qalarm --- apps/sleepphasealarm/ChangeLog | 3 ++- apps/sleepphasealarm/app.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index f633abee0..0f0e4a20b 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Respect Quiet Mode -0.03: available for BangleJS2 \ No newline at end of file +0.03: available for BangleJS2 + added support for qalarms \ No newline at end of file diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 0de0b9afc..ed5077b02 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -1,4 +1,4 @@ -const alarms = require("Storage").readJSON("alarm.json",1)||[]; +const alarms = require("Storage").readJSON("alarm.json",1)||require("Storage").readJSON("qalarm.json",1)||[]; const active = alarms.filter(a=>a.on); // Sleep/Wake detection with Estimation of Stationary Sleep-segments (ESS): From 5697d1bab46224d72cb47e3a69a6af88c7a59e7d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 13 Jan 2022 01:19:18 +0100 Subject: [PATCH 043/312] former core update (non master) --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index 5a5957714..b05af96b2 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit 5a5957714d4aa04413329f57c03e6de0cfb74caf +Subproject commit b05af96b2522a7a7225a56d804faf9383f8a8f97 From 430490a69870d1e306f71afea43b1b38411d7014 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sat, 15 Jan 2022 22:37:44 +0100 Subject: [PATCH 044/312] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 28 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 21 +++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 000000000..5f49e72ef --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,28 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] + title" +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..50186e142 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,21 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] + title" +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 7e60a50e0785949b32623c68e857df8c285ad96f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sat, 15 Jan 2022 22:45:01 +0100 Subject: [PATCH 045/312] Update issue templates --- .github/ISSUE_TEMPLATE/bangle-bug-report.md | 28 +++++++++++++++++++ .../ISSUE_TEMPLATE/bangle-feature-request.md | 21 ++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bangle-bug-report.md create mode 100644 .github/ISSUE_TEMPLATE/bangle-feature-request.md diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report.md b/.github/ISSUE_TEMPLATE/bangle-bug-report.md new file mode 100644 index 000000000..5d84c7d83 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report.md @@ -0,0 +1,28 @@ +--- +name: Bangle Bug report +about: 'Bangle: Create a report to help us improve' +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] + title" +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md new file mode 100644 index 000000000..89baefa2f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -0,0 +1,21 @@ +--- +name: Bangle Feature request +about: 'Bangle: Suggest an idea for this project' +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] + title" +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 4d0ac31c4374571344a648127407b7e7f1310fe7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sat, 15 Jan 2022 22:54:23 +0100 Subject: [PATCH 046/312] removed default templates --- .github/ISSUE_TEMPLATE/bug_report.md | 28 ----------------------- .github/ISSUE_TEMPLATE/feature_request.md | 21 ----------------- 2 files changed, 49 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bug_report.md delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index 5f49e72ef..000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] - title" -labels: bug -assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md deleted file mode 100644 index 50186e142..000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -name: Feature request -about: Suggest an idea for this project -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] - title" -labels: enhancement -assignees: '' - ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. From c3cd24484ee6d8b9348afd2fc966d15f2026d9ff Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:43:16 +0100 Subject: [PATCH 047/312] test bug template as form --- .github/ISSUE_TEMPLATE/bangle-bug-report.md | 62 +++++++++++++-------- 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report.md b/.github/ISSUE_TEMPLATE/bangle-bug-report.md index 5d84c7d83..d333cfac8 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report.md +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report.md @@ -1,28 +1,46 @@ --- name: Bangle Bug report -about: 'Bangle: Create a report to help us improve' +about: 'Bangle: Create a report to help us improve!' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" labels: bug assignees: '' - ---- - -**Describe the bug** -A clear and concise description of what the bug is. - -**To Reproduce** -Steps to reproduce the behavior: -1. Go to '...' -2. Click on '....' -3. Scroll down to '....' -4. See error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, add screenshots to help explain your problem. - -**Additional context** -Add any other context about the problem here. +body: + - type: markdown + attributes: + value: | + ### If you have a question then + ### ** Ask it in the [forum](http://forum.espruino.com/microcosms/1424/), please! ** + - type: dropdown + id: bangle + attributes: + label: version + description: Bangle version? + options: + - Bangle 1 + - Bangle 2 + - type: textarea + id: report + attributes: + label: Bug description + description: and please mention expected behaviour + placeholder: | + **Describe the bug** + A clear and concise description of what the bug is. + + **Expected behavior** + A clear and concise description of what you expected to happen. + - type: textarea + id: log_screens + attributes: + label: Log file or log outp or screenshots + placeholder: | + logfile, logoutout or screen + - type: textarea + id: addional + attributes: + label: Additional context + description: for further helpfull information + placeholder: | + for further helpfull information +--- \ No newline at end of file From cc08ecf33c497472d2f6b21826c358691901a5be Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:50:41 +0100 Subject: [PATCH 048/312] testing custom bug form --- .../bangle-bug-report-custom-form.md | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md new file mode 100644 index 000000000..d333cfac8 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md @@ -0,0 +1,46 @@ +--- +name: Bangle Bug report +about: 'Bangle: Create a report to help us improve!' +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] + title" +labels: bug +assignees: '' +body: + - type: markdown + attributes: + value: | + ### If you have a question then + ### ** Ask it in the [forum](http://forum.espruino.com/microcosms/1424/), please! ** + - type: dropdown + id: bangle + attributes: + label: version + description: Bangle version? + options: + - Bangle 1 + - Bangle 2 + - type: textarea + id: report + attributes: + label: Bug description + description: and please mention expected behaviour + placeholder: | + **Describe the bug** + A clear and concise description of what the bug is. + + **Expected behavior** + A clear and concise description of what you expected to happen. + - type: textarea + id: log_screens + attributes: + label: Log file or log outp or screenshots + placeholder: | + logfile, logoutout or screen + - type: textarea + id: addional + attributes: + label: Additional context + description: for further helpfull information + placeholder: | + for further helpfull information +--- \ No newline at end of file From 9a7b57ca373a74709332a653e1db59ec396e3be7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:51:58 +0100 Subject: [PATCH 049/312] template name unique --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md index d333cfac8..d233aee67 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md @@ -1,5 +1,5 @@ --- -name: Bangle Bug report +name: Bangle Bug custom form about: 'Bangle: Create a report to help us improve!' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" From 3abe7b57e58e93706fb833fa5ff49cb8086407d7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:54:14 +0100 Subject: [PATCH 050/312] type changed to yaml --- ...g-report-custom-form.md => bangle-bug-report-custom-form.yaml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .github/ISSUE_TEMPLATE/{bangle-bug-report-custom-form.md => bangle-bug-report-custom-form.yaml} (100%) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml similarity index 100% rename from .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.md rename to .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml From 33792391acc62bba9f38ee88412d80327f8ab02a Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:55:39 +0100 Subject: [PATCH 051/312] removed md syntax --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index d233aee67..6993c1316 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,4 +1,3 @@ ---- name: Bangle Bug custom form about: 'Bangle: Create a report to help us improve!' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] @@ -42,5 +41,4 @@ body: label: Additional context description: for further helpfull information placeholder: | - for further helpfull information ---- \ No newline at end of file + for further helpfull information \ No newline at end of file From e92dd3d8305df7e037552f926eb70d4733233c07 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 13:59:59 +0100 Subject: [PATCH 052/312] cfg from github docu --- .../ISSUE_TEMPLATE/example-github-cfg.yaml | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/example-github-cfg.yaml diff --git a/.github/ISSUE_TEMPLATE/example-github-cfg.yaml b/.github/ISSUE_TEMPLATE/example-github-cfg.yaml new file mode 100644 index 000000000..9d0d058c0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/example-github-cfg.yaml @@ -0,0 +1,62 @@ +name: Bug Report +description: File a bug report +title: "[Bug]: " +labels: ["bug", "triage"] +assignees: + - octocat +body: + - type: markdown + attributes: + value: | + Thanks for taking the time to fill out this bug report! + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you if we need more info? + placeholder: ex. email@example.com + validations: + required: false + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "A bug happened!" + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - 1.0.2 (Default) + - 1.0.3 (Edge) + validations: + required: true + - type: dropdown + id: browsers + attributes: + label: What browsers are you seeing the problem on? + multiple: true + options: + - Firefox + - Chrome + - Safari + - Microsoft Edge + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com) + options: + - label: I agree to follow this project's Code of Conduct + required: true \ No newline at end of file From 35b41f2eed4f7e64291ecaf2438c9bf1d577ab18 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:42:03 +0100 Subject: [PATCH 053/312] bug custom form fix --- .../bangle-bug-report-custom-form.yaml | 22 ++++++--- .github/ISSUE_TEMPLATE/bangle-bug-report.md | 46 ------------------- 2 files changed, 15 insertions(+), 53 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bangle-bug-report.md diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 6993c1316..cc57df8ff 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,20 +1,28 @@ -name: Bangle Bug custom form -about: 'Bangle: Create a report to help us improve!' +name: Bangle Bug report +description: Bangle: Create a report to help us improve! title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: bug -assignees: '' +labels: ["bug"] +assignees: [] body: - type: markdown attributes: value: | ### If you have a question then ### ** Ask it in the [forum](http://forum.espruino.com/microcosms/1424/), please! ** - - type: dropdown + - type: checkboxes + id: searched + attributes: + label: agree searched + description: + options: + label: I confirm that I have searched the forum and also for similiar bugs. + required: true + - type: checkboxes id: bangle attributes: - label: version - description: Bangle version? + label: hwversion + description: Which Bangle hw version is affected? options: - Bangle 1 - Bangle 2 diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report.md b/.github/ISSUE_TEMPLATE/bangle-bug-report.md deleted file mode 100644 index d333cfac8..000000000 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -name: Bangle Bug report -about: 'Bangle: Create a report to help us improve!' -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] - title" -labels: bug -assignees: '' -body: - - type: markdown - attributes: - value: | - ### If you have a question then - ### ** Ask it in the [forum](http://forum.espruino.com/microcosms/1424/), please! ** - - type: dropdown - id: bangle - attributes: - label: version - description: Bangle version? - options: - - Bangle 1 - - Bangle 2 - - type: textarea - id: report - attributes: - label: Bug description - description: and please mention expected behaviour - placeholder: | - **Describe the bug** - A clear and concise description of what the bug is. - - **Expected behavior** - A clear and concise description of what you expected to happen. - - type: textarea - id: log_screens - attributes: - label: Log file or log outp or screenshots - placeholder: | - logfile, logoutout or screen - - type: textarea - id: addional - attributes: - label: Additional context - description: for further helpfull information - placeholder: | - for further helpfull information ---- \ No newline at end of file From f3a6351b55fc66b2539291f12163bcf948b52e1f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:44:29 +0100 Subject: [PATCH 054/312] retry --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index cc57df8ff..f9d069acd 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,7 +1,7 @@ name: Bangle Bug report description: Bangle: Create a report to help us improve! -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] - title" +title: "[Bug]: " +#title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" labels: ["bug"] assignees: [] body: @@ -37,6 +37,8 @@ body: **Expected behavior** A clear and concise description of what you expected to happen. + validations: + required: true - type: textarea id: log_screens attributes: From eb287c290a18e8695112418e5592e0848e22c00a Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:47:51 +0100 Subject: [PATCH 055/312] simplified --- .../bangle-bug-report-custom-form.yaml | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index f9d069acd..b33fdeee0 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -14,18 +14,18 @@ body: id: searched attributes: label: agree searched - description: + description: abc options: label: I confirm that I have searched the forum and also for similiar bugs. required: true - - type: checkboxes - id: bangle - attributes: - label: hwversion - description: Which Bangle hw version is affected? - options: - - Bangle 1 - - Bangle 2 +# - type: checkboxes +# id: bangle +# attributes: +# label: hwversion +# description: Which Bangle hw version is affected? +# options: +# - Bangle 1 +# - Bangle 2 - type: textarea id: report attributes: @@ -39,16 +39,16 @@ body: A clear and concise description of what you expected to happen. validations: required: true - - type: textarea - id: log_screens - attributes: - label: Log file or log outp or screenshots - placeholder: | - logfile, logoutout or screen - - type: textarea - id: addional - attributes: - label: Additional context - description: for further helpfull information - placeholder: | - for further helpfull information \ No newline at end of file +# - type: textarea +# id: log_screens +# attributes: +# label: Log file or log outp or screenshots +# placeholder: | +# logfile, logoutout or screen +# - type: textarea +# id: addional +# attributes: +# label: Additional context +# description: for further helpfull information +# placeholder: | +# for further helpfull information \ No newline at end of file From ef4e6a9a2f8e98187b6353fb0ed3da8f0e4ad966 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 14:54:54 +0100 Subject: [PATCH 056/312] fixed title : --- .../bangle-bug-report-custom-form.yaml | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index b33fdeee0..9f3b50601 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,7 +1,6 @@ name: Bangle Bug report -description: Bangle: Create a report to help us improve! -title: "[Bug]: " -#title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" +description: "Bangle: Create a report to help us improve!" +title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" labels: ["bug"] assignees: [] body: @@ -18,14 +17,23 @@ body: options: label: I confirm that I have searched the forum and also for similiar bugs. required: true -# - type: checkboxes -# id: bangle -# attributes: -# label: hwversion -# description: Which Bangle hw version is affected? -# options: -# - Bangle 1 -# - Bangle 2 + - type: input + id: devobject + attributes: + label: development object + description: | + the foldername in 'BangleApps' + for generall issues create a generic issue, please. + validations: + required: true + - type: checkboxes + id: bangle + attributes: + label: hwversion + description: Which Bangle hw version is affected? + options: + - Bangle 1 + - Bangle 2 - type: textarea id: report attributes: From 72d8a8b8726aa1dc13a4ca58c71399a11b5a20b3 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:37:35 +0100 Subject: [PATCH 057/312] and onther try ;) --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 9f3b50601..7de4dc553 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -15,7 +15,7 @@ body: label: agree searched description: abc options: - label: I confirm that I have searched the forum and also for similiar bugs. + - label: I confirm that I have searched the forum and also for similiar bugs. required: true - type: input id: devobject From 00f10333213a3ddcb0ff01e056be0f8ca6e14bc7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:42:18 +0100 Subject: [PATCH 058/312] custom form --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 7de4dc553..53c4db93b 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -16,7 +16,7 @@ body: description: abc options: - label: I confirm that I have searched the forum and also for similiar bugs. - required: true + required: true - type: input id: devobject attributes: From 7f51ff79bc7ab01ab3d5dd41aec829fb5561570c Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:50:48 +0100 Subject: [PATCH 059/312] try #4 --- .../bangle-bug-report-custom-form.yaml | 58 ++++++++++++------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 53c4db93b..a1f02b9df 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -12,15 +12,15 @@ body: - type: checkboxes id: searched attributes: - label: agree searched - description: abc + label: Agree searched + description: Please search for (closed) issues options: - label: I confirm that I have searched the forum and also for similiar bugs. required: true - type: input id: devobject attributes: - label: development object + label: Development object description: | the foldername in 'BangleApps' for generall issues create a generic issue, please. @@ -29,16 +29,16 @@ body: - type: checkboxes id: bangle attributes: - label: hwversion + label: Hardware version description: Which Bangle hw version is affected? options: - - Bangle 1 - - Bangle 2 + - label: Bangle 1 + - label: Bangle 2 - type: textarea id: report attributes: label: Bug description - description: and please mention expected behaviour + description: please also mention the expected behaviour. placeholder: | **Describe the bug** A clear and concise description of what the bug is. @@ -47,16 +47,34 @@ body: A clear and concise description of what you expected to happen. validations: required: true -# - type: textarea -# id: log_screens -# attributes: -# label: Log file or log outp or screenshots -# placeholder: | -# logfile, logoutout or screen -# - type: textarea -# id: addional -# attributes: -# label: Additional context -# description: for further helpfull information -# placeholder: | -# for further helpfull information \ No newline at end of file + - type: textarea + id: reproduce + attributes: + label: + description: Can be added here to make it more clear. + placeholder: | + 1. start app xy + 2. choose abc + 3. bug occurs + value: | + 1. + 2. + 3. + ... + - type: textarea + id: log_screens + attributes: + label: Log file / outpout / screenshots + description: Can be added here to make it more clear. + placeholder: | + logfile, logoutput or screendump. + + Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. + Please avoid upload of sensitive data. + - type: textarea + id: addional + attributes: + label: Additional context + description: For further helpfull information. + placeholder: | + for further helpfull information \ No newline at end of file From ae12f6cf0619341ac4de9caeb5c67ad2ad0002a8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 17 Jan 2022 18:53:58 +0100 Subject: [PATCH 060/312] bug template xth try --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index a1f02b9df..e5a200496 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -38,7 +38,7 @@ body: id: report attributes: label: Bug description - description: please also mention the expected behaviour. + description: Please also mention the expected behaviour. placeholder: | **Describe the bug** A clear and concise description of what the bug is. @@ -50,8 +50,8 @@ body: - type: textarea id: reproduce attributes: - label: - description: Can be added here to make it more clear. + label: Steps to reproduce + description: Please provide the steps until bug occurs. placeholder: | 1. start app xy 2. choose abc From 19e4408963a602959d8c48516f99e29dc801cce4 Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Tue, 18 Jan 2022 00:16:11 +0100 Subject: [PATCH 061/312] labels: feature request, widet --- .github/ISSUE_TEMPLATE/bangle-feature-request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md index 89baefa2f..93af81dbd 100644 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -3,7 +3,7 @@ name: Bangle Feature request about: 'Bangle: Suggest an idea for this project' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: enhancement +labels: feature request, widet assignees: '' --- From 6e757747b4d46aa7a3e5d7137b98b85cf3b4649e Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Tue, 18 Jan 2022 00:18:10 +0100 Subject: [PATCH 062/312] labels: [feature request, widet] --- .github/ISSUE_TEMPLATE/bangle-feature-request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md index 93af81dbd..59af567e8 100644 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -3,7 +3,7 @@ name: Bangle Feature request about: 'Bangle: Suggest an idea for this project' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: feature request, widet +labels: [feature request, widet] assignees: '' --- From f5cf11f784fe8944c301c42b89a0dcd7328951a0 Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Tue, 18 Jan 2022 00:19:36 +0100 Subject: [PATCH 063/312] labels --- .github/ISSUE_TEMPLATE/bangle-feature-request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md index 59af567e8..fcd319f25 100644 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -3,7 +3,7 @@ name: Bangle Feature request about: 'Bangle: Suggest an idea for this project' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: [feature request, widet] +labels: ["feature request", "widet"] assignees: '' --- From 76ded3ce6424f742202fa6e494a20ac5a403ae6b Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Tue, 18 Jan 2022 00:20:56 +0100 Subject: [PATCH 064/312] label next try --- .github/ISSUE_TEMPLATE/bangle-feature-request.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md index fcd319f25..14ea0a0ae 100644 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -3,7 +3,7 @@ name: Bangle Feature request about: 'Bangle: Suggest an idea for this project' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: ["feature request", "widet"] +labels: "feature request", "widet" assignees: '' --- From eff442026e22edb7a4036ed34a9f02e4b53a43c2 Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Tue, 18 Jan 2022 00:22:01 +0100 Subject: [PATCH 065/312] and another try --- .github/ISSUE_TEMPLATE/bangle-feature-request.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md index 14ea0a0ae..de230e3c3 100644 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ b/.github/ISSUE_TEMPLATE/bangle-feature-request.md @@ -3,9 +3,10 @@ name: Bangle Feature request about: 'Bangle: Suggest an idea for this project' title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" -labels: "feature request", "widet" +labels: + - widget + - feature request assignees: '' - --- **Is your feature request related to a problem? Please describe.** From a9804987aa42c60efa162eadaf1d383531e1a5e6 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 20 Jan 2022 00:41:47 +0100 Subject: [PATCH 066/312] timecal 0.02 --- apps/timecal/ChangeLog | 7 + apps/timecal/README.md | 16 + apps/timecal/timecal.app.js | 326 +++++++++++++----- apps/timecal/timecal.app.test.js | 566 +++++++++++++++++++++++++++++++ apps/timecal/timecal.settings.js | 31 ++ 5 files changed, 862 insertions(+), 84 deletions(-) create mode 100644 apps/timecal/ChangeLog create mode 100644 apps/timecal/README.md create mode 100644 apps/timecal/timecal.app.test.js create mode 100644 apps/timecal/timecal.settings.js diff --git a/apps/timecal/ChangeLog b/apps/timecal/ChangeLog new file mode 100644 index 000000000..58da864d3 --- /dev/null +++ b/apps/timecal/ChangeLog @@ -0,0 +1,7 @@ +0.01: Initial creation of the clock face time and calendar +0.02: Feature Request #1154 and some findings... + -> get rendered time from optimisations + -> *BATT SAFE* only update once a minute instead of once a second + -> *RAM optimized* clean code, corrected minute update (timout, no intervall) + -> locale: weekday name (first two characters) from locale + -> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default]) \ No newline at end of file diff --git a/apps/timecal/README.md b/apps/timecal/README.md new file mode 100644 index 000000000..345b117f3 --- /dev/null +++ b/apps/timecal/README.md @@ -0,0 +1,16 @@ +# Calendar Clock + +## Features +Shows the +* Date +* Time (hh:mm) - respecting 12/24 (uses locale string) +* 3 weeks calendar view (last,current and next week) + +### The settings menu +Calendar View can be customized +* Cal.Start Day: Set day of week start. Values: 0=Sunday ... 6=Saturday or -1 Relative to today (default 1: Monday) +* Date Type: Choose how the date is display. Values: none, locale (default), MMM YYYY #WW +* Sunday Color: Set Sundays color. Values: none (default), red, green or blue +* today Color: Set today color. Values: none, red (default), green or blue +* today Marker: Outline today graphically. Values: none (default), rect(angle) or circle +* today MColor: Color for Outline. Values: none (default), red, green or blue diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index b28326c46..090464be1 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -1,94 +1,252 @@ -var center = g.getWidth() / 2; -var lastDayDraw; -var lastTimeDraw; - -var fontColor = g.theme.fg; -var accentColor = "#FF0000"; -var locale = require("locale"); - -function loop() { - var d = new Date(); - var cleared = false; - if(lastDayDraw != d.getDate()){ - lastDayDraw = d.getDate(); - drawDate(d); - drawCal(d); - } +//Clock renders date, time and pre,current,next week calender view +class TimeCalClock{ + DATE_FONT_SIZE(){ return 20; } + TIME_FONT_SIZE(){ return 40; } - if(lastTimeDraw != d.getMinutes() || cleared){ - lastTimeDraw = d.getMinutes(); - drawTime(d); - } -} -function drawTime(d){ - var hour = ("0" + d.getHours()).slice(-2); - var min = ("0" + d.getMinutes()).slice(-2); - g.setFontAlign(0,-1,0); - g.setFont("Vector",40); - g.setColor(fontColor); - g.clearRect(0,50,g.getWidth(),90); - g.drawString(hour + ":" + min,center,50); -} -function drawDate(d){ - var day = ("0" + d.getDate()).slice(-2); - var month = ("0" + d.getMonth()).slice(-2); - var dateStr = locale.date(d,1); - g.clearRect(0,24,g.getWidth(),44); - g.setFont("Vector",20); - g.setColor(fontColor); - g.setFontAlign(0,-1,0); - g.drawString(dateStr,center,24); -} + /** + * @param{Date} date optional the date (e.g. for testing) + * @param{Settings} settings optional settings to use e.g. for testing + */ + constructor(date, settings){ + if (date) + this.date=date; -function drawCal(d){ - var calStart = 101; - var cellSize = g.getWidth() / 7; - var halfSize = cellSize / 2; - g.clearRect(0,calStart,g.getWidth(),g.getHeight()); - g.drawLine(0,calStart,g.getWidth(),calStart); - var days = ["Mo","Tu","We","Th","Fr","Sa","Su"]; - g.setFont("Vector",10); - g.setColor(fontColor); - g.setFontAlign(-1,-1,0); - for(var i = 0; i < days.length;i++){ - g.drawString(days[i],i*cellSize+5,calStart -11); - if(i!=0){ - g.drawLine(i*cellSize,calStart,i*cellSize,g.getHeight()); - } + if (settings) + this._settings = settings; + else + this._settings = require("Storage").readJSON("timecal.settings.json", 1) || {}; + + const defaults = { + showDate:"l", //(n)one, (l)ocale, (m)onth short(y)ear(w)eek + + wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, + + todayNumClr:"#00E", + todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed + todayMrkClr:"#0E0", + todayMrkMrkPxl:3, + + suColor:"#E00", //sunday + phColor:"#E00", //public holiday + + calBorder:true + }; + for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings + for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults + + g.clear(); + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + this.center_x = Bangle.appRect.w/2; } - var cellHeight = (g.getHeight() -calStart ) / 3; - for(var i = 0;i < 3;i++){ - var starty = calStart + i * cellHeight; - g.drawLine(0,starty,g.getWidth(),starty); + + /** + * @returns {Object} current settings object + */ + settings(){ + return this._settings; + } + + + /* + * Run forest run + **/ + draw(){ + this.drawTime(); + } + + /** + * draw given or current time from date + * overwatch timezone changes + * schedules itself to update + */ + drawTime(){ + d=this.date ? this.date : new Date(); + console.log("drawTime", d); + const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; + + d=d?d :new Date(); + + g.setFontAlign(0, -1); + g.setFont("Vector", this.TIME_FONT_SIZE()); + g.setColor(g.theme.fg); + g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option + + setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + this.TZOffset=d.getTimezoneOffset(); + } + + /** + * draws given date and cal + * @param{Date} d provide date or uses today + */ + drawDateAndCal(){ + d=this.date ? this.date : new Date(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); + + this.drawDate(); + this.drawCal(); + this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); } - g.setFont("Vector",15); - - var dayOfWeek = d.getDay(); - var dayRem = d.getDay() - 1; - if(dayRem <0){ - dayRem = 0; - } - - var start = new Date(); - start.setDate(start.getDate()-(7+dayRem)); - g.setFontAlign(0,-1,0); - for (var y = 0;y < 3; y++){ - for(var x = 0;x < 7; x++){ - if(start.getDate() === d.getDate()){ - g.setColor(accentColor); - }else{ - g.setColor(fontColor); + /** + * draws given date as defiend in settings + */ + drawDate(){ + d=this.date ? this.date : new Date(); + + const FONT_SIZE=20; + const Y=Bangle.appRect.y; + var render=false; + var dateStr = ""; + console.log(">"+this.settings().showDate+"<"); + if (!(this.settings().showDate==="n")) + for (let c of this.settings().showDate) { //add part as configured + switch (c){ + case "l":{ //locale + render=true; + dateStr+=require("locale").date(d,1); + break; + } + case "m":{ //month e.g. Jan. + render=true; + dateStr+=require("locale").month(d,1); + break; + } + case "y":{ //year e.g. 2022 + render=true; + dateStr+=d.getFullYear(); + break; + } + case "w":{ //week e.g. #02 + dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); + break; + } + default: //append c + dateStr+=c; + render=dateStr.length>0; + break; //noop + } } - g.drawString(start.getDate(),x*cellSize +(cellSize / 2) + 2,calStart+(cellHeight*y) + 5); - start.setDate(start.getDate()+1); + if (render){ + g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); + g.setFont("Vector", FONT_SIZE); + g.setColor(g.theme.fg); + g.setFontAlign(0, -1); + g.drawString(dateStr,this.center_x,Y); + } + //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option + } + + /** + * draws calender week view (-1,0,1) for given date + */ + drawCal(){ + d=this.date ? this.date : new Date(); + + const DAY_NAME_FONT_SIZE=10; + const CAL_Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10+this.TIME_FONT_SIZE()+3; + const CAL_AREA_H=Bangle.appRect.h-CAL_Y-24; //0,24,48 no,1,2 widget lines + const CELL_W=Bangle.appRect.w/7; //cell width + const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth + const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 + + g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); + + var dNames=[]; + if (require("locale") && require("locale").abday) + dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars + else + dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback + + g.setFont("Vector", DAY_NAME_FONT_SIZE); + g.setColor(g.theme.fg); + g.setFontAlign(-1, -1); + + //draw grid & Headline + for(var dNo=0; dNo0) + g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); + } + + var nextY=CAL_Y+DAY_NAME_FONT_SIZE; + + for(i=0; i<3; i++){ + const y=nextY+i*CELL_H; + g.drawLine(Bangle.appRect.x, y, Bangle.appRect.x2, y); + } + + g.setFont("Vector", DAY_NUM_FONT_SIZE); + + //write days + const todayDate=d.getDate(); + const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + var rD=new Date(); + rD.setDate(rD.getDate()-days); + var rDate=rD.getDate(); + for(var y=0; y<3; y++){ + for(var x=0; xSu, 1->Mo, ... //Issue #1154: weekstart So/Mo, + + todayNumClr:"#00E", + todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed + todayMrkClr:"#0E0", + todayMrkMrkPxl:3, + + suColor:"#E00", //sunday + phColor:"#E00", //public holiday + + calBorder:true + }; + for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings + for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults + + g.clear(); + Bangle.setUI("clock"); + Bangle.loadWidgets(); + Bangle.drawWidgets(); + + this.center_x = Bangle.appRect.w/2; + } + + /** + * @returns {Object} current settings object + */ + settings(){ + return this._settings; + } + + + /* + * Run forest run + **/ + draw(){ + this.drawTime(); + } + + /** + * draw given or current time from date + * overwatch timezone changes + * schedules itself to update + */ + drawTime(){ + d=this.date ? this.date : new Date(); + console.log("drawTime", d); + const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; + + d=d?d :new Date(); + + g.setFontAlign(0, -1); + g.setFont("Vector", this.TIME_FONT_SIZE()); + g.setColor(g.theme.fg); + g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option + + setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + this.TZOffset=d.getTimezoneOffset(); + } + + /** + * draws given date and cal + * @param{Date} d provide date or uses today + */ + drawDateAndCal(){ + d=this.date ? this.date : new Date(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); + + this.drawDate(); + this.drawCal(); + this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); + } + + /** + * draws given date as defiend in settings + */ + drawDate(){ + d=this.date ? this.date : new Date(); + + const FONT_SIZE=20; + const Y=Bangle.appRect.y; + var render=false; + var dateStr = ""; + console.log(this.settings().showDate); + if (this.settings().showDate!=="n"); + for (let c of this.settings().showDate) { //add part as configured + switch (c){ + case "l":{ //locale + render=true; + dateStr+=require("locale").date(d,1); + break; + } + case "m":{ //month e.g. Jan. + render=true; + dateStr+=require("locale").month(d,1); + break; + } + case "y":{ //year e.g. 2022 + render=true; + dateStr+=d.getFullYear(); + break; + } + case "w":{ //week e.g. #02 + dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); + break; + } + default: //append c + dateStr+=c; + render=dateStr.length>0; + break; //noop + } + } + if (render){ + g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); + g.setFont("Vector", FONT_SIZE); + g.setColor(g.theme.fg); + g.setFontAlign(0, -1); + g.drawString(dateStr,this.center_x,Y); + } + //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option + } + + /** + * draws calender week view (-1,0,1) for given date + */ + drawCal(){ + d=this.date ? this.date : new Date(); + + const DAY_NAME_FONT_SIZE=10; + const CAL_Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10+this.TIME_FONT_SIZE()+3; + const CAL_AREA_H=Bangle.appRect.h-CAL_Y-24; //0,24,48 no,1,2 widget lines + const CELL_W=Bangle.appRect.w/7; //cell width + const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth + const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 + + g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); + + var dNames=[]; + if (require("locale") && require("locale").abday) + dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars + else + dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback + + g.setFont("Vector", DAY_NAME_FONT_SIZE); + g.setColor(g.theme.fg); + g.setFontAlign(-1, -1); + + //draw grid & Headline + for(var dNo=0; dNo0) + g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); + } + + var nextY=CAL_Y+DAY_NAME_FONT_SIZE; + + for(i=0; i<3; i++){ + const y=nextY+i*CELL_H; + g.drawLine(Bangle.appRect.x, y, Bangle.appRect.x2, y); + } + + g.setFont("Vector", DAY_NUM_FONT_SIZE); + + //write days + const todayDate=d.getDate(); + const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + var rD=new Date(); + rD.setDate(rD.getDate()-days); + var rDate=rD.getDate(); + for(var y=0; y<3; y++){ + for(var x=0; x", + functionNames: ["required, ", "..."], + cases: [ + { + value: "required,", + beforeTxt: "optional,", + beforeExpression: "optional,", + afterText: "optional,", + afterExpression: "optional," + } + ] + } + } + + constructor(data){ + + this._validate(data); + + this.setting = data.setting; + this.methodNames = data.functionNames; + this.cases = data.cases.map((entry) => { + return { + value: entry.value, + beforeTxt: entry.beforeTxt||"", + beforeExpression: entry.beforeExpression||true, + afterTxt: entry.afterTxt||"", + afterExpression: entry.afterExpression||true + }; + }); + } + + /** + * validates the given data config + */ + _validate(data){ + //validate given config + if (!data.setting) throw new EmptyMandatoryError("setting", data, this.TEST_SETTING_SAMPLE()); + if (!data.cases instanceof Array || data.cases.length==0) throw new EmptyMandatoryError("cases", data, this.TEST_SETTING_SAMPLE()); + if (!data.functionNames instanceof Array || data.functionNames==0) throw new EmptyMandatoryError("functionNames", data, this.TEST_SETTING_SAMPLE()); + + data.cases.forEach((entry,idx) => { + if (!entry.value) throw new EmptyMandatoryError("cases["+idx+"].value", entry, this.TEST_SETTING_SAMPLE()); + }); + } +} + +/*************************************************************************/ + +/** + * Testing a Bangle object + */ +class BangleTestRunner{ + /** + * create for ObjClass + * @param {Class} objClass + * @param {LogSeverity} minSeverity to Log + */ + constructor(objClass, minSeverity){ + this.TESTCASE_MSG_BEFORE_TIMEOUT = 1000; //5s + this.TESTCASE_RUN_TIMEOUT = 1000; //5s + this.TESTCASE_MSG_AFTER_TIMEOUT = 1000; //5s + + this.oClass = objClass; + this.minSvrty = minSeverity; + this.tests = []; + + this.currentCaseNum = this.currentTestNum = this.currentTest = this.currentCase = undefined; + } + + /** + * add a Setting Test, return instance for chaining + * @param {TestSetting} + */ + addSetting(test) { + this.tests.push(test); + return this; + } + + /** + * Test execution of all tests + */ + execute() { + this._init(); + while (this._nextTest()) { + this._beforeTest(); + while (this._nextCase()) { + this._beforeCase(); + this._runCase(); + this._afterCase(); + } + this._afterTest(); + }; + } + + /** + * global prepare + */ + _init() { + console.log(new Date(),">>init"); + this.currentTestNum=-1; + this.currentCaseNum=-1; + } + + /** + * before each test + */ + _beforeTest() { + console.log(new Date(),">>test #" + this.currentTestNum); + } + + /** + * befor each testcase + */ + _beforeCase() { + console.log(new Date(),">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); + if (this.currentTest instanceof TestSetting) { + console.log( + this.currentTest.setting + "="+this.currentCase.value+"\n"+ + this.currentCase.beforeTxt ? "testcase: " + this.currentCase.beforeTxt : "" + ); + } + } + + _runCase() { + console.log(new Date(), ">>running..."); + var returns = []; + this.currentTest.methodNames.forEach((methodName) => { + var instance = eval("new " + this.oClass + ""); + console.log(instance); + const method = instance[methodName]; + //console.log(">>"+this.oClass+"["+methodName+"]()"); + //if (typeof method !== "function") + // throw new InvalidMethodName(this.oClass, methodName); + let settings={}; settings[this.currentTest.setting] = this.currentCase.value; + returns.push(new TimeCalClock(new Date(), settings).drawDate()); + //returns.push(method()); + console.log("<<"+this.oClass+"["+methodName+"]()"); + g.dump() + }); + + //this._delay(1).then((result) => console.log(new Date(), "finished")); + //g.dump(); + /*var testCaseNum=0; + test.cases.forEach(testcase => { //execute test + testcase.dates.forEach(date => { //spawn with each date + testCaseNum++; + E.showMessage( + "="+testcase.value+"\n" + +"expected: "+testcase.descr, + "#"+testCaseNum+": "+test.setting + ); + this._delay(TESTCASE_MSG_TIMEOUT).then((r,e) => { + const objUnderTest = new Object.create(this.ObjClass)(date, new Object()[test.setting]=test.value ); + objUnderTest.draw(); + this._delay(TESTCASE_RUN_TIMEOUT).then((r,e) => { + }); + }); + }); + });*/ + console.log(new Date(), "<<...running"); + } + + _afterCase() { + if (this.currentTest instanceof TestSetting) { + if (this.currentCase.afterTxt.length>0) { + console.log( + "--EXPECTED: " + this.currentCase.afterTxt + ); + } + } + console.log(new Date(), "< setTimeout(resolve, sec)); + } + + _waits(sec) { + this._delay(1).then(); + } + + _log() { + + } + + _nextTest() { + if (this.currentTestNum>=-1 && (this.currentTestNum+1)=-1 && (this.currentCaseNum+1) back(), + "Cal.Start Day": { + value: settings.wdStrt === undefined ? 1 : settings.wdStrt, //def: 1: mon + min: -1, max: 6, + //render dow from locale or LANG"today" + format: v => (v>=0 ? (require("locale") && require("locale").abday && require("locale").abday[v] ? : && require("locale").abday[v] : DOW_abbr_FB[v]) : /*LANG*/"today"), + onchange: v => { + settings.weekDay = v; + writeSettings(); + } + } +}; \ No newline at end of file From fd60061c538e32a82787ab2d12fe0fedeb3f35c1 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 20 Jan 2022 00:54:10 +0100 Subject: [PATCH 067/312] apps.json v 0.02 --- apps.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 07d267991..f9c5b34fb 100644 --- a/apps.json +++ b/apps.json @@ -4655,13 +4655,15 @@ "name": "TimeCal", "shortName":"TimeCal", "icon": "icon.png", - "version":"0.01", + "version":"0.02", "description": "TimeCal shows the Time along with a 3 week calendar", "tags": "clock", + "readme":"README.md", "type": "clock", "supports":["BANGLEJS2"], "storage": [ - {"name":"timecal.app.js","url":"timecal.app.js"} + {"name":"timecal.app.js","url":"timecal.app.js"}, + {"name":"timecal.settings.js","url":"timecal.settings.js"} ] }, { From 757cb521b13825dd2ab71a69b4a0b1ec00010f8e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 24 Jan 2022 23:54:56 +0100 Subject: [PATCH 068/312] bug report with hw,fw and textarea #1 --- .../bangle-bug-report-custom-form.yaml | 83 +++++++------------ 1 file changed, 28 insertions(+), 55 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index e5a200496..9d092ef90 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,39 +1,36 @@ name: Bangle Bug report -description: "Bangle: Create a report to help us improve!" -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] title" +description: "Bangle: Create a issue to help us improve!" +title: "Please give it a short description and provide the affected app/widget." labels: ["bug"] assignees: [] body: - type: markdown attributes: value: | - ### If you have a question then - ### ** Ask it in the [forum](http://forum.espruino.com/microcosms/1424/), please! ** - - type: checkboxes - id: searched + ### If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! + - type: dropdown + id: hwversion attributes: - label: Agree searched - description: Please search for (closed) issues - options: - - label: I confirm that I have searched the forum and also for similiar bugs. - required: true - - type: input - id: devobject - attributes: - label: Development object - description: | - the foldername in 'BangleApps' - for generall issues create a generic issue, please. - validations: - required: true - - type: checkboxes - id: bangle - attributes: - label: Hardware version - description: Which Bangle hw version is affected? + label: Affected hardware version + description: | + Which Bangle hardware version(s) is/are affected? + Hint: You can select both with ctrl key. options: - label: Bangle 1 - label: Bangle 2 + multiple: true + - type: input + id: fwversion + attributes: + label: Your firmware version + description: | + Please use the latest released firmware and check if the bug still occurs. + If it occurs only in "Cutting Edge build" please mention this. + Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) + Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) + placeholder: e.g. 2v11 + validations: + required: true - type: textarea id: report attributes: @@ -45,36 +42,12 @@ body: **Expected behavior** A clear and concise description of what you expected to happen. - validations: - required: true - - type: textarea - id: reproduce - attributes: - label: Steps to reproduce - description: Please provide the steps until bug occurs. - placeholder: | - 1. start app xy + + **Steps to reproduce + 1. Start app xy 2. choose abc 3. bug occurs - value: | - 1. - 2. - 3. - ... - - type: textarea - id: log_screens - attributes: - label: Log file / outpout / screenshots - description: Can be added here to make it more clear. - placeholder: | - logfile, logoutput or screendump. - Tip: You can attach images or log files by clicking this area to highlight it and then dragging files in. - Please avoid upload of sensitive data. - - type: textarea - id: addional - attributes: - label: Additional context - description: For further helpfull information. - placeholder: | - for further helpfull information \ No newline at end of file + It could be helpfull for us to provide + validations: + required: true \ No newline at end of file From 6fae64a2f5b2c0f86a7b4ce6740591568fdc46fd Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:00:32 +0100 Subject: [PATCH 069/312] bug report with hw,fw and textarea (2) --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 9d092ef90..2c91d545c 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -7,7 +7,7 @@ body: - type: markdown attributes: value: | - ### If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! + ** If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! ** - type: dropdown id: hwversion attributes: @@ -19,7 +19,7 @@ body: - label: Bangle 1 - label: Bangle 2 multiple: true - - type: input + - type: input id: fwversion attributes: label: Your firmware version From 63a8fc95cf7c89f87a3cb812e01d2afb903caf90 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:10:00 +0100 Subject: [PATCH 070/312] bug report with hw,fw and textarea (3) --- .../bangle-bug-report-custom-form.yaml | 17 ++--- .../ISSUE_TEMPLATE/bangle-feature-request.md | 22 ------- .../ISSUE_TEMPLATE/example-github-cfg.yaml | 62 ------------------- 3 files changed, 10 insertions(+), 91 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/bangle-feature-request.md delete mode 100644 .github/ISSUE_TEMPLATE/example-github-cfg.yaml diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 2c91d545c..a7be5d375 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -1,24 +1,26 @@ -name: Bangle Bug report +name: Bangle bug report description: "Bangle: Create a issue to help us improve!" -title: "Please give it a short description and provide the affected app/widget." +title: "Short description and provide the affected app/widget" labels: ["bug"] assignees: [] body: - type: markdown attributes: value: | - ** If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! ** + ### If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! - type: dropdown id: hwversion attributes: label: Affected hardware version description: | Which Bangle hardware version(s) is/are affected? - Hint: You can select both with ctrl key. + Hint: You can select multiple entries. options: - - label: Bangle 1 - - label: Bangle 2 + - Bangle 1 + - Bangle 2 multiple: true + validations: + required: true - type: input id: fwversion attributes: @@ -26,8 +28,9 @@ body: description: | Please use the latest released firmware and check if the bug still occurs. If it occurs only in "Cutting Edge build" please mention this. + Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead. Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) - Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) + Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) placeholder: e.g. 2v11 validations: required: true diff --git a/.github/ISSUE_TEMPLATE/bangle-feature-request.md b/.github/ISSUE_TEMPLATE/bangle-feature-request.md deleted file mode 100644 index de230e3c3..000000000 --- a/.github/ISSUE_TEMPLATE/bangle-feature-request.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -name: Bangle Feature request -about: 'Bangle: Suggest an idea for this project' -title: "[general/app/widget/clock e.g. clock] [development object e.g. antonclock] - title" -labels: - - widget - - feature request -assignees: '' ---- - -**Is your feature request related to a problem? Please describe.** -A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] - -**Describe the solution you'd like** -A clear and concise description of what you want to happen. - -**Describe alternatives you've considered** -A clear and concise description of any alternative solutions or features you've considered. - -**Additional context** -Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/example-github-cfg.yaml b/.github/ISSUE_TEMPLATE/example-github-cfg.yaml deleted file mode 100644 index 9d0d058c0..000000000 --- a/.github/ISSUE_TEMPLATE/example-github-cfg.yaml +++ /dev/null @@ -1,62 +0,0 @@ -name: Bug Report -description: File a bug report -title: "[Bug]: " -labels: ["bug", "triage"] -assignees: - - octocat -body: - - type: markdown - attributes: - value: | - Thanks for taking the time to fill out this bug report! - - type: input - id: contact - attributes: - label: Contact Details - description: How can we get in touch with you if we need more info? - placeholder: ex. email@example.com - validations: - required: false - - type: textarea - id: what-happened - attributes: - label: What happened? - description: Also tell us, what did you expect to happen? - placeholder: Tell us what you see! - value: "A bug happened!" - validations: - required: true - - type: dropdown - id: version - attributes: - label: Version - description: What version of our software are you running? - options: - - 1.0.2 (Default) - - 1.0.3 (Edge) - validations: - required: true - - type: dropdown - id: browsers - attributes: - label: What browsers are you seeing the problem on? - multiple: true - options: - - Firefox - - Chrome - - Safari - - Microsoft Edge - - type: textarea - id: logs - attributes: - label: Relevant log output - description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. - render: shell - - type: checkboxes - id: terms - attributes: - label: Code of Conduct - description: By submitting this issue, you agree to follow our [Code of Conduct](https://example.com) - options: - - label: I agree to follow this project's Code of Conduct - required: true \ No newline at end of file From b054ed9ffebea7ec8d13c4661525c0896819f7a3 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:18:54 +0100 Subject: [PATCH 071/312] bug report with hw,fw and textarea (4) --- .../bangle-bug-report-custom-form.yaml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index a7be5d375..bf9c1d610 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -26,19 +26,20 @@ body: attributes: label: Your firmware version description: | - Please use the latest released firmware and check if the bug still occurs. + * Please make sure you installed the latest released firmware! * If it occurs only in "Cutting Edge build" please mention this. + Update instructions: + * Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) * + * Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) * Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead. - Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) - Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) placeholder: e.g. 2v11 validations: required: true - type: textarea id: report attributes: - label: Bug description - description: Please also mention the expected behaviour. + label: The bug + description: * Please also mention the expected behaviour and steps to reproduce* placeholder: | **Describe the bug** A clear and concise description of what the bug is. @@ -46,11 +47,11 @@ body: **Expected behavior** A clear and concise description of what you expected to happen. - **Steps to reproduce + **Steps to reproduce** 1. Start app xy 2. choose abc 3. bug occurs - It could be helpfull for us to provide + It could be helpfull for us to provide the devopment folder in 'bangle apps' folder validations: required: true \ No newline at end of file From 568c6cdfad4dc418b6e8f34e7abfe60038213690 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:19:29 +0100 Subject: [PATCH 072/312] bug report with hw,fw and textarea (5) --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index bf9c1d610..b3b3266ff 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -39,7 +39,7 @@ body: id: report attributes: label: The bug - description: * Please also mention the expected behaviour and steps to reproduce* + description: * Please also mention the expected behaviour and steps to reproduce * placeholder: | **Describe the bug** A clear and concise description of what the bug is. From 8b6d289bc9338f81f608d7b2324721effcc37286 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:24:25 +0100 Subject: [PATCH 073/312] bug report with hw,fw and textarea (6) --- .../bangle-bug-report-custom-form.yaml | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index b3b3266ff..57645f800 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -7,14 +7,14 @@ body: - type: markdown attributes: value: | - ### If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! + # Attention: If you have a question then ask it at the [bangle forum](http://forum.espruino.com/microcosms/1424/), please! - type: dropdown id: hwversion attributes: label: Affected hardware version description: | Which Bangle hardware version(s) is/are affected? - Hint: You can select multiple entries. + _Hint: You can select multiple entries._ options: - Bangle 1 - Bangle 2 @@ -26,12 +26,12 @@ body: attributes: label: Your firmware version description: | - * Please make sure you installed the latest released firmware! * + ## Please make sure you installed the latest released firmware! If it occurs only in "Cutting Edge build" please mention this. Update instructions: - * Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates) * - * Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates) * - Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead. + **Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates)** + **Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates)** + _Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead._ placeholder: e.g. 2v11 validations: required: true @@ -39,15 +39,16 @@ body: id: report attributes: label: The bug - description: * Please also mention the expected behaviour and steps to reproduce * + description: | + ** Please also mention the expected behaviour and steps to reproduce ** placeholder: | - **Describe the bug** + ###Describe the bug A clear and concise description of what the bug is. - **Expected behavior** + ###Expected behavior A clear and concise description of what you expected to happen. - **Steps to reproduce** + ###Steps to reproduce 1. Start app xy 2. choose abc 3. bug occurs From aec48abda66e150e3592c6275df4d8a955ec6ddf Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 25 Jan 2022 00:26:01 +0100 Subject: [PATCH 074/312] bug report with hw,fw and textarea (7) --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 57645f800..28021246f 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -26,7 +26,7 @@ body: attributes: label: Your firmware version description: | - ## Please make sure you installed the latest released firmware! + ## Please make sure you installed the latest (released) firmware! If it occurs only in "Cutting Edge build" please mention this. Update instructions: **Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates)** @@ -40,7 +40,7 @@ body: attributes: label: The bug description: | - ** Please also mention the expected behaviour and steps to reproduce ** + ## Please also mention the expected behaviour and steps to reproduce placeholder: | ###Describe the bug A clear and concise description of what the bug is. From ad7b0df2a15c7a0573129b60d9f7687ef691f6ab Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 28 Jan 2022 11:23:43 +0100 Subject: [PATCH 075/312] settings fixed, first version BangleTestRunner --- apps/timecal/timecal.app.js | 90 +++++++------ apps/timecal/timecal.app.test.js | 216 ++++++++++++++++--------------- apps/timecal/timecal.settings.js | 148 +++++++++++++++++---- 3 files changed, 290 insertions(+), 164 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 090464be1..17daf127a 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -17,19 +17,19 @@ class TimeCalClock{ this._settings = require("Storage").readJSON("timecal.settings.json", 1) || {}; const defaults = { - showDate:"l", //(n)one, (l)ocale, (m)onth short(y)ear(w)eek - - wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, + shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week + + wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - todayNumClr:"#00E", - todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed - todayMrkClr:"#0E0", - todayMrkMrkPxl:3, + tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:3, //px - suColor:"#E00", //sunday - phColor:"#E00", //public holiday + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday - calBorder:true + calBrdr:false }; for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults @@ -39,7 +39,9 @@ class TimeCalClock{ Bangle.loadWidgets(); Bangle.drawWidgets(); - this.center_x = Bangle.appRect.w/2; + this.centerX = Bangle.appRect.w/2; + this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b + this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -64,7 +66,6 @@ class TimeCalClock{ */ drawTime(){ d=this.date ? this.date : new Date(); - console.log("drawTime", d); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; d=d?d :new Date(); @@ -73,7 +74,7 @@ class TimeCalClock{ g.setFont("Vector", this.TIME_FONT_SIZE()); g.setColor(g.theme.fg); g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -107,9 +108,9 @@ class TimeCalClock{ const Y=Bangle.appRect.y; var render=false; var dateStr = ""; - console.log(">"+this.settings().showDate+"<"); - if (!(this.settings().showDate==="n")) - for (let c of this.settings().showDate) { //add part as configured + if (this.settings().shwDate>0) { //skip if exactly -none + const dateSttngs = ["","l","M","m.Y #W"]; + for (let c of dateSttngs[this.settings().shwDate]) { //add part as configured switch (c){ case "l":{ //locale render=true; @@ -121,12 +122,26 @@ class TimeCalClock{ dateStr+=require("locale").month(d,1); break; } - case "y":{ //year e.g. 2022 + case "M":{ //month e.g. January + render=true; + dateStr+=require("locale").month(d,0); + break; + } + case "y":{ //year e.g. 22 + render=true; + dateStr+=d.getFullYear().slice(-2); + break; + } + case "Y":{ //year e.g. 2022 render=true; dateStr+=d.getFullYear(); break; } - case "w":{ //week e.g. #02 + case "w":{ //week e.g. #2 + dateStr+=(this.ISO8601calWeek(d)); + break; + } + case "W":{ //week e.g. #02 dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); break; } @@ -136,12 +151,13 @@ class TimeCalClock{ break; //noop } } + } if (render){ g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); g.setFont("Vector", FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(0, -1); - g.drawString(dateStr,this.center_x,Y); + g.drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -161,19 +177,18 @@ class TimeCalClock{ g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - var dNames=[]; - if (require("locale") && require("locale").abday) - dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars - else - dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback - g.setFont("Vector", DAY_NAME_FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(-1, -1); + + const tdyDate=d.getDate(); + const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); + //draw grid & Headline + const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -189,31 +204,30 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const todayDate=d.getDate(); - const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) var rD=new Date(); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ for(var x=0; xSu, 1->Mo, ... //Issue #1154: weekstart So/Mo, + shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week + + wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - todayNumClr:"#00E", - todayMrker:"r", //(n)one, (c)ircle, (r)ect, (f)illed - todayMrkClr:"#0E0", - todayMrkMrkPxl:3, + tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:3, //px - suColor:"#E00", //sunday - phColor:"#E00", //public holiday + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday - calBorder:true + calBrdr:false }; for (const k in this._settings) if (!defaults.hasOwnProperty(k)) delete this._settings[k]; //remove invalid settings for (const k in defaults) if(!this._settings.hasOwnProperty(k)) this._settings[k] = defaults[k]; //assign missing defaults @@ -39,7 +39,9 @@ class TimeCalClock{ Bangle.loadWidgets(); Bangle.drawWidgets(); - this.center_x = Bangle.appRect.w/2; + this.centerX = Bangle.appRect.w/2; + this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b + this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -64,7 +66,6 @@ class TimeCalClock{ */ drawTime(){ d=this.date ? this.date : new Date(); - console.log("drawTime", d); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; d=d?d :new Date(); @@ -73,7 +74,7 @@ class TimeCalClock{ g.setFont("Vector", this.TIME_FONT_SIZE()); g.setColor(g.theme.fg); g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.center_x, Y); + g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -107,9 +108,9 @@ class TimeCalClock{ const Y=Bangle.appRect.y; var render=false; var dateStr = ""; - console.log(this.settings().showDate); - if (this.settings().showDate!=="n"); - for (let c of this.settings().showDate) { //add part as configured + if (this.settings().shwDate>0) { //skip if exactly -none + const dateSttngs = ["","l","M","m.Y #W"]; + for (let c of dateSttngs[this.settings().shwDate]) { //add part as configured switch (c){ case "l":{ //locale render=true; @@ -121,12 +122,26 @@ class TimeCalClock{ dateStr+=require("locale").month(d,1); break; } - case "y":{ //year e.g. 2022 + case "M":{ //month e.g. January + render=true; + dateStr+=require("locale").month(d,0); + break; + } + case "y":{ //year e.g. 22 + render=true; + dateStr+=d.getFullYear().slice(-2); + break; + } + case "Y":{ //year e.g. 2022 render=true; dateStr+=d.getFullYear(); break; } - case "w":{ //week e.g. #02 + case "w":{ //week e.g. #2 + dateStr+=(this.ISO8601calWeek(d)); + break; + } + case "W":{ //week e.g. #02 dateStr+=("0"+this.ISO8601calWeek(d)).slice(-2); break; } @@ -136,12 +151,13 @@ class TimeCalClock{ break; //noop } } + } if (render){ g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); g.setFont("Vector", FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(0, -1); - g.drawString(dateStr,this.center_x,Y); + g.drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -161,19 +177,18 @@ class TimeCalClock{ g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - var dNames=[]; - if (require("locale") && require("locale").abday) - dNames=require("locale").abday.map((a) => a.length>2 ? a.substr(0, 2) : a ); //retrieve from locale and force max 2 chars - else - dNames=["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]; //fallback - g.setFont("Vector", DAY_NAME_FONT_SIZE); g.setColor(g.theme.fg); g.setFontAlign(-1, -1); + + const tdyDate=d.getDate(); + const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); + //draw grid & Headline + const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -189,31 +204,30 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const todayDate=d.getDate(); - const days=7+(7+d.getDay()-this.settings().wdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) + const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) var rD=new Date(); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ for(var x=0; x", - functionNames: ["required, ", "..."], cases: [ { value: "required,", @@ -335,7 +354,10 @@ class TestSetting extends Test{ afterText: "optional,", afterExpression: "optional," } - ] + ], + constructorParams: ["optional: ","|TEST_SETTINGS|","..."], //TEST_SETTINGS will be replcaed with each current {setting: case} + functionNames: ["required, ", "..."], + functionParams: ["optional: ","|TEST_SETTINGS|","..."] } } @@ -344,7 +366,6 @@ class TestSetting extends Test{ this._validate(data); this.setting = data.setting; - this.methodNames = data.functionNames; this.cases = data.cases.map((entry) => { return { value: entry.value, @@ -354,6 +375,9 @@ class TestSetting extends Test{ afterExpression: entry.afterExpression||true }; }); + this.constructorParams = data.constructorParams, + this.functionNames = data.functionNames; + this.functionParams = data.functionParams; } /** @@ -362,11 +386,11 @@ class TestSetting extends Test{ _validate(data){ //validate given config if (!data.setting) throw new EmptyMandatoryError("setting", data, this.TEST_SETTING_SAMPLE()); - if (!data.cases instanceof Array || data.cases.length==0) throw new EmptyMandatoryError("cases", data, this.TEST_SETTING_SAMPLE()); - if (!data.functionNames instanceof Array || data.functionNames==0) throw new EmptyMandatoryError("functionNames", data, this.TEST_SETTING_SAMPLE()); + if (!(data.cases instanceof Array) || data.cases.length==0) throw new EmptyMandatoryError("cases", data, this.TEST_SETTING_SAMPLE()); + if (!(data.functionNames instanceof Array) || data.functionNames==0) throw new EmptyMandatoryError("functionNames", data, this.TEST_SETTING_SAMPLE()); data.cases.forEach((entry,idx) => { - if (!entry.value) throw new EmptyMandatoryError("cases["+idx+"].value", entry, this.TEST_SETTING_SAMPLE()); + if (entry.value === undefined) throw new EmptyMandatoryError("cases["+idx+"].value", entry, this.TEST_SETTING_SAMPLE()); }); } } @@ -398,8 +422,8 @@ class BangleTestRunner{ * add a Setting Test, return instance for chaining * @param {TestSetting} */ - addSetting(test) { - this.tests.push(test); + addTestSettings(sttngs) { + this.tests.push(new TestSetting(sttngs)); return this; } @@ -416,14 +440,14 @@ class BangleTestRunner{ this._afterCase(); } this._afterTest(); - }; + } } /** - * global prepare + * global prepare - before all test */ _init() { - console.log(new Date(),">>init"); + console.log(new Date().getTime(),">>init"); this.currentTestNum=-1; this.currentCaseNum=-1; } @@ -448,45 +472,33 @@ class BangleTestRunner{ } } + /** + * testcase runner + */ _runCase() { console.log(new Date(), ">>running..."); var returns = []; - this.currentTest.methodNames.forEach((methodName) => { - var instance = eval("new " + this.oClass + ""); - console.log(instance); - const method = instance[methodName]; - //console.log(">>"+this.oClass+"["+methodName+"]()"); - //if (typeof method !== "function") - // throw new InvalidMethodName(this.oClass, methodName); - let settings={}; settings[this.currentTest.setting] = this.currentCase.value; - returns.push(new TimeCalClock(new Date(), settings).drawDate()); - //returns.push(method()); - console.log("<<"+this.oClass+"["+methodName+"]()"); - g.dump() + this.currentTest.functionNames.forEach((fName) => { + var settings={}; settings[this.currentTest.setting] = this.currentCase.value; + var cParams = this.currentTest.constructorParams||[]; + cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + var fParams = this.currentTest.functionParams||[]; + fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + + var creatorFunc = new Function("return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] + let instance = creatorFunc.call(this.oClass, cParams[0], cParams[1], cParams[2], cParams[3], cParams[4], cParams[5], cParams[6], cParams[7], cParams[8], cParams[9]); //spwan + + console.log(">>"+this.oClass+"["+fName+"]()"); + returns.push(instance[fName](fParams[0], fParams[1], fParams[2], fParams[3], fParams[4], fParams[5], fParams[6], fParams[7], fParams[8], fParams[9])); //run method and store result + console.log("<<"+this.oClass+"["+fName+"]()"); + g.dump(); }); - - //this._delay(1).then((result) => console.log(new Date(), "finished")); - //g.dump(); - /*var testCaseNum=0; - test.cases.forEach(testcase => { //execute test - testcase.dates.forEach(date => { //spawn with each date - testCaseNum++; - E.showMessage( - "="+testcase.value+"\n" - +"expected: "+testcase.descr, - "#"+testCaseNum+": "+test.setting - ); - this._delay(TESTCASE_MSG_TIMEOUT).then((r,e) => { - const objUnderTest = new Object.create(this.ObjClass)(date, new Object()[test.setting]=test.value ); - objUnderTest.draw(); - this._delay(TESTCASE_RUN_TIMEOUT).then((r,e) => { - }); - }); - }); - });*/ console.log(new Date(), "<<...running"); } + /** + * after each testcase + */ _afterCase() { if (this.currentTest instanceof TestSetting) { if (this.currentCase.afterTxt.length>0) { @@ -498,10 +510,16 @@ class BangleTestRunner{ console.log(new Date(), "<Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for always focus/center today - function writeSettings() { + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:2, //px + + suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday + + calBrdr:false + }, + require('Storage').readJSON(FILE, true) || {} + ); + + const SETTINGS_AT_START = Object.assign(settings); //hardcopy of current and defaults + + var saveSettings = () => { require('Storage').writeJSON(FILE, settings); }; -}); -var mainmenu = { - "": { - "title": "Time calendar clock" - }, - "< Back": () => back(), - "Cal.Start Day": { - value: settings.wdStrt === undefined ? 1 : settings.wdStrt, //def: 1: mon - min: -1, max: 6, - //render dow from locale or LANG"today" - format: v => (v>=0 ? (require("locale") && require("locale").abday && require("locale").abday[v] ? : && require("locale").abday[v] : DOW_abbr_FB[v]) : /*LANG*/"today"), - onchange: v => { - settings.weekDay = v; - writeSettings(); - } - } -}; \ No newline at end of file + var restoreAndExitSettings = () => { + require('Storage').writeJSON(FILE, SETTINGS_AT_START); + E.showMenu(); + }; + + var showMainMenu = () => { + E.showMenu({ + "": { + "title": /*LANG*/"Time cal clock" + }, + /*LANG*/"< Save": () => save(), + /*LANG*/"Show date": { + value: settings.shwDate, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"locale", /*LANG*/"M", /*LANG*/"m.Y #W"][v], + onchange: v => { + settings.shwDate = v; + saveSettings(); + } + }, + /*LANG*/"Start wday": { + value: settings.wdStrt, + min: -1, max: 6, + format: v => v>=0 ? ABR_DAY[v] : /*LANG*/"today", + onchange: v => { + settings.wdStrt = v; + saveSettings(); + } + }, + /*LANG*/"Su color": { + value: settings.suClr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.suClr = v; + saveSettings(); + } + }, + /*LANG*/"Border": { + value: settings.calBrdr, + format: v => v ? "show" : "none", + onchange: v => { + settings.calBrdr = v; + saveSettings(); + } + }, + /*LANG*/"Today settings": () => { + showTodayMenu(); + }, + /*LANG*/"< Cancel": () => restoreAndExitSettings() + }); + }; + + var showTodayMenu = () => { + E.showMenu({ + "": { + "title": /*LANG*/"Today settings" + }, + "< Back": () => showMainMenu(), + /*LANG*/"Color": { + value: settings.tdyNumClr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.tdyNumClr = v; + saveSettings(); + } + }, + /*LANG*/"Marker": { + value: settings.tdyMrkr, + min: 0, max: 3, + format: v => [/*LANG*/"none", /*LANG*/"circle", /*LANG*/"rectangle", /*LANG*/"filled"][v], + onchange: v => { + settings.tdyMrkr = v; + saveSettings(); + } + }, + /*LANG*/"Mrk.Color": { + value: settings.tdyMrkClr, + min: 0, max: 2, + format: v => [/*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + onchange: v => { + settings.tdyMrkClr = v; + saveSettings(); + } + }, + /*LANG*/"Mrk.Size": { + value: settings.tdyMrkPxl, + min: 0, max: 10, + format: v => v+"px", + onchange: v => { + settings.tdyMrkPxl = v; + saveSettings(); + } + }, + /*LANG*/"< Cancel": () => restoreAndExitSettings() + }); + }; + + showMainMenu(); +}); From 6e054468abe36c60d876d128966fdce0a7f0aaa8 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 1 Feb 2022 23:44:59 +0100 Subject: [PATCH 076/312] 0.03-settings fixed, app 90% automated tested --- apps.json | 2 +- apps/timecal/timecal.app.js | 59 ++++-- apps/timecal/timecal.app.test.js | 347 +++++++++++++++++++++++++------ apps/timecal/timecal.settings.js | 4 +- 4 files changed, 325 insertions(+), 87 deletions(-) diff --git a/apps.json b/apps.json index f9c5b34fb..79bd0b046 100644 --- a/apps.json +++ b/apps.json @@ -4655,7 +4655,7 @@ "name": "TimeCal", "shortName":"TimeCal", "icon": "icon.png", - "version":"0.02", + "version":"0.03", "description": "TimeCal shows the Time along with a 3 week calendar", "tags": "clock", "readme":"README.md", diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 17daf127a..97cd596c8 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -19,14 +19,14 @@ class TimeCalClock{ const defaults = { shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week - wdStrt:1, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today + wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkPxl:3, //px - suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E //phColor:"#E00", //public holiday calBrdr:false @@ -41,7 +41,19 @@ class TimeCalClock{ this.centerX = Bangle.appRect.w/2; this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b - this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + + this.ABR_DAY=[]; + if (require("locale") && require("locale").dow) + for (let d=0; d<=6; d++) { + var refDay=new Date(); + refDay.setFullYear(1972); + refDay.setMonth(0); + refDay.setDate(2+d); + this.ABR_DAY.push(require("locale").dow(refDay)); + + } + else + this.ABR_DAY=["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -57,7 +69,10 @@ class TimeCalClock{ **/ draw(){ this.drawTime(); - } + + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + } /** * draw given or current time from date @@ -77,10 +92,7 @@ class TimeCalClock{ g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option - setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); - if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) - this.drawDateAndCal(); - this.TZOffset=d.getTimezoneOffset(); + setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); } /** @@ -90,11 +102,12 @@ class TimeCalClock{ drawDateAndCal(){ d=this.date ? this.date : new Date(); - if (this.tOutD) //abort exisiting - clearTimeout(this.tOutD); - + this.TZOffset=d.getTimezoneOffset(); this.drawDate(); this.drawCal(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); } @@ -182,13 +195,15 @@ class TimeCalClock{ g.setFontAlign(-1, -1); - const tdyDate=d.getDate(); - const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); - //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; + const dName=dNames[dIdx]; + if (dIdx==0) //sunday colorize txt + g.setColor(this.nrgb[this.settings().suClr]); + else + g.setColor(g.theme.fg); g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -204,8 +219,9 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) - var rD=new Date(); + const tdyDate=d.getDate(); + const days=this.settings().wdStrt>=0 ? 7+((7+d.getDay()-this.settings().wdStrt)%7) : 10;//start day (week before=7 days + days in this week realtive to week start) or fixed 7+3 days + var rD=new Date(d.getTime()); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ @@ -215,7 +231,7 @@ class TimeCalClock{ switch(this.settings().tdyMrkr){ //0:none, 1:circle, 2:rectangle, 3:filled case 1: for(m=1; m<=this.settings().tdyMrkPxl&&mSu, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today + wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - tdyNumClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E tdyMrkPxl:3, //px - suClr:0, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E //phColor:"#E00", //public holiday calBrdr:false @@ -41,7 +41,19 @@ class TimeCalClock{ this.centerX = Bangle.appRect.w/2; this.nrgb = [g.theme.fg, "#E00", "#0E0", "#00E"]; //fg, r ,g , b - this.ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + + this.ABR_DAY=[]; + if (require("locale") && require("locale").dow) + for (let d=0; d<=6; d++) { + var refDay=new Date(); + refDay.setFullYear(1972); + refDay.setMonth(0); + refDay.setDate(2+d); + this.ABR_DAY.push(require("locale").dow(refDay)); + + } + else + this.ABR_DAY=["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; } /** @@ -57,7 +69,10 @@ class TimeCalClock{ **/ draw(){ this.drawTime(); - } + + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + this.drawDateAndCal(); + } /** * draw given or current time from date @@ -77,10 +92,7 @@ class TimeCalClock{ g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option - setTimeout(this.drawTime.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); - if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) - this.drawDateAndCal(); - this.TZOffset=d.getTimezoneOffset(); + setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); } /** @@ -90,11 +102,12 @@ class TimeCalClock{ drawDateAndCal(){ d=this.date ? this.date : new Date(); - if (this.tOutD) //abort exisiting - clearTimeout(this.tOutD); - + this.TZOffset=d.getTimezoneOffset(); this.drawDate(); this.drawCal(); + + if (this.tOutD) //abort exisiting + clearTimeout(this.tOutD); this.tOutD=setTimeout(this.drawDateAndCal.bind(this), 86400000-(d.getHours()*24*60*1000)-(d.getMinutes()*60*1000)-d.getSeconds()-d.getMilliseconds()); } @@ -182,13 +195,15 @@ class TimeCalClock{ g.setFontAlign(-1, -1); - const tdyDate=d.getDate(); - const sttngsWdStrt=this.settings().wdStrt>=0 ? this.settings().wdStrt : tdyDate.getDay(); - //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; + const dName=dNames[dIdx]; + if (dIdx==0) //sunday colorize txt + g.setColor(this.nrgb[this.settings().suClr]); + else + g.setColor(g.theme.fg); g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); @@ -204,8 +219,9 @@ class TimeCalClock{ g.setFont("Vector", DAY_NUM_FONT_SIZE); //write days - const days=7+(7+d.getDay()-sttngsWdStrt)%7;//start day (week before=7 days + days in this week realtive to week start) - var rD=new Date(); + const tdyDate=d.getDate(); + const days=this.settings().wdStrt>=0 ? 7+((7+d.getDay()-this.settings().wdStrt)%7) : 10;//start day (week before=7 days + days in this week realtive to week start) or fixed 7+3 days + var rD=new Date(d.getTime()); rD.setDate(rD.getDate()-days); var rDate=rD.getDate(); for(var y=0; y<3; y++){ @@ -215,7 +231,7 @@ class TimeCalClock{ switch(this.settings().tdyMrkr){ //0:none, 1:circle, 2:rectangle, 3:filled case 1: for(m=1; m<=this.settings().tdyMrkPxl&&m","|TEST_SETTINGS|","..."], //TEST_SETTINGS will be replcaed with each current {setting: case} functionNames: ["required, ", "..."], functionParams: ["optional: ","|TEST_SETTINGS|","..."] - } + }; } constructor(data){ @@ -375,7 +390,7 @@ class TestSetting extends Test{ afterExpression: entry.afterExpression||true }; }); - this.constructorParams = data.constructorParams, + this.constructorParams = data.constructorParams; this.functionNames = data.functionNames; this.functionParams = data.functionParams; } @@ -440,14 +455,16 @@ class BangleTestRunner{ this._afterCase(); } this._afterTest(); + this._firstCase(); } + this._exit(); } /** * global prepare - before all test */ _init() { - console.log(new Date().getTime(),">>init"); + console.log(this._nowTime(), ">>init"); this.currentTestNum=-1; this.currentCaseNum=-1; } @@ -456,72 +473,69 @@ class BangleTestRunner{ * before each test */ _beforeTest() { - console.log(new Date(),">>test #" + this.currentTestNum); + console.log(this._nowTime(), ">>test #" + this.currentTestNum); } /** * befor each testcase */ _beforeCase() { - console.log(new Date(),">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); - if (this.currentTest instanceof TestSetting) { - console.log( - this.currentTest.setting + "="+this.currentCase.value+"\n"+ - this.currentCase.beforeTxt ? "testcase: " + this.currentCase.beforeTxt : "" + console.log(this._nowTime(), ">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); + if (this.currentTest instanceof TestSetting) + console.log(this.currentTest.setting+"="+this.currentCase.value+"\n" + +this.currentCase.beforeTxt ? "testcase:"+this.currentCase.beforeTxt : "" ); - } } /** * testcase runner */ _runCase() { - console.log(new Date(), ">>running..."); + console.log(this._nowTime(), ">>running..."); var returns = []; this.currentTest.functionNames.forEach((fName) => { var settings={}; settings[this.currentTest.setting] = this.currentCase.value; var cParams = this.currentTest.constructorParams||[]; - cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + cParams = cParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v);//replace settings in call params var fParams = this.currentTest.functionParams||[]; - fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v)//replace settings in call params + fParams = fParams.map((v) => (v && v instanceof String && v==="|TEST_SETTINGS|") ? settings : v);//replace settings in call params - var creatorFunc = new Function("return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] + var creatorFunc = new Function("console.log('Constructor params:', arguments); return new " + this.oClass + "(arguments[0],arguments[1],arguments[2],arguments[3],arguments[4],arguments[5],arguments[6],arguments[7],arguments[8],arguments[9])"); //prepare spwan arguments[0],arguments[1] let instance = creatorFunc.call(this.oClass, cParams[0], cParams[1], cParams[2], cParams[3], cParams[4], cParams[5], cParams[6], cParams[7], cParams[8], cParams[9]); //spwan console.log(">>"+this.oClass+"["+fName+"]()"); + + console.log('Instance:', instance); + console.log('Function params:', fParams); returns.push(instance[fName](fParams[0], fParams[1], fParams[2], fParams[3], fParams[4], fParams[5], fParams[6], fParams[7], fParams[8], fParams[9])); //run method and store result - console.log("<<"+this.oClass+"["+fName+"]()"); g.dump(); + console.log("<<"+this.oClass+"["+fName+"]()"); }); - console.log(new Date(), "<<...running"); + console.log(this._nowTime(), "<<...running"); } /** * after each testcase */ _afterCase() { - if (this.currentTest instanceof TestSetting) { - if (this.currentCase.afterTxt.length>0) { - console.log( - "--EXPECTED: " + this.currentCase.afterTxt - ); - } - } - console.log(new Date(), "<0) + console.log("++EXPECTED:" + this.currentCase.afterTxt + "EXPECTED++"); + console.log(this._nowTime(), "<=-1 && (this.currentTestNum+1)=-1 && (this.currentCaseNum+1) Date: Tue, 1 Feb 2022 23:46:53 +0100 Subject: [PATCH 077/312] changelog v0.03 --- apps/timecal/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/timecal/ChangeLog b/apps/timecal/ChangeLog index 58da864d3..499ac9afa 100644 --- a/apps/timecal/ChangeLog +++ b/apps/timecal/ChangeLog @@ -4,4 +4,5 @@ -> *BATT SAFE* only update once a minute instead of once a second -> *RAM optimized* clean code, corrected minute update (timout, no intervall) -> locale: weekday name (first two characters) from locale - -> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default]) \ No newline at end of file + -> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default]) +0.03: a lot of more settings for outline, colors and highlights \ No newline at end of file From 1a13b81ccfab65457650bd118f7e01057819a61e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Tue, 1 Feb 2022 23:59:48 +0100 Subject: [PATCH 078/312] updated generated metadata.json --- apps/timecal/metadata.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/timecal/metadata.json b/apps/timecal/metadata.json index 3237dd08a..472a4a817 100644 --- a/apps/timecal/metadata.json +++ b/apps/timecal/metadata.json @@ -8,6 +8,7 @@ "type": "clock", "supports":["BANGLEJS2"], "storage": [ - {"name":"timecal.app.js","url":"timecal.app.js"} + {"name":"timecal.app.js","url":"timecal.app.js"}, + {"name":"timecal.settings.js","url":"timecal.settings.js"} ] } From d63d2fd3302bce45b31aa44dc37e4d67f5f01c39 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:00:11 +0100 Subject: [PATCH 079/312] app v 0.03 --- apps/timecal/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/timecal/metadata.json b/apps/timecal/metadata.json index 472a4a817..a1cf31a93 100644 --- a/apps/timecal/metadata.json +++ b/apps/timecal/metadata.json @@ -2,7 +2,7 @@ "name": "TimeCal", "shortName":"TimeCal", "icon": "icon.png", - "version":"0.01", + "version":"0.03", "description": "TimeCal shows the Time along with a 3 week calendar", "tags": "clock", "type": "clock", From 7cd333db57a7ce0956a6c8ecc22397707dcc8322 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:35:49 +0100 Subject: [PATCH 080/312] fixed copy issue; force 1 widget line --- apps/timecal/timecal.app.js | 4 ++-- apps/timecal/timecal.app.test.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 97cd596c8..79ef649c6 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -183,7 +183,7 @@ class TimeCalClock{ const DAY_NAME_FONT_SIZE=10; const CAL_Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10+this.TIME_FONT_SIZE()+3; - const CAL_AREA_H=Bangle.appRect.h-CAL_Y-24; //0,24,48 no,1,2 widget lines + const CAL_AREA_H=Bangle.appRect.h-CAL_Y+24; //+24: top widegtes only const CELL_W=Bangle.appRect.w/7; //cell width const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 @@ -276,6 +276,6 @@ class TimeCalClock{ } return Number(1 + Math.ceil((firstThursday - tdt) / 604800000)); } - +} timeCalClock = new TimeCalClock(); timeCalClock.draw(); \ No newline at end of file diff --git a/apps/timecal/timecal.app.test.js b/apps/timecal/timecal.app.test.js index 97cfd5d57..6a7a8220f 100644 --- a/apps/timecal/timecal.app.test.js +++ b/apps/timecal/timecal.app.test.js @@ -183,7 +183,7 @@ class TimeCalClock{ const DAY_NAME_FONT_SIZE=10; const CAL_Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10+this.TIME_FONT_SIZE()+3; - const CAL_AREA_H=Bangle.appRect.h-CAL_Y-24; //0,24,48 no,1,2 widget lines + const CAL_AREA_H=Bangle.appRect.h-CAL_Y;//+24; //+24: top widegtes only const CELL_W=Bangle.appRect.w/7; //cell width const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 @@ -276,7 +276,7 @@ class TimeCalClock{ } return Number(1 + Math.ceil((firstThursday - tdt) / 604800000)); } - } +} //************************************************************************************* //************************************************************************************* From 5f8a3317a9ad2df18d915b3690ef79a4d279069b Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:43:12 +0100 Subject: [PATCH 081/312] fixed SuClr drawlines --- apps/timecal/timecal.app.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 79ef649c6..4dc111312 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -198,15 +198,17 @@ class TimeCalClock{ //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; const dName=dNames[dIdx]; + g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names + if(dNo>0) + g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); + if (dIdx==0) //sunday colorize txt g.setColor(this.nrgb[this.settings().suClr]); else g.setColor(g.theme.fg); - g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names - if(dNo>0) - g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; From 8ee18f1eedc0c8a13072385e165a7dc92e88cca9 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:53:53 +0100 Subject: [PATCH 082/312] colorize only sunday --- apps/timecal/timecal.app.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 4dc111312..50a171e26 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -198,17 +198,17 @@ class TimeCalClock{ //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; const dName=dNames[dIdx]; - g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); - if (dIdx==0) //sunday colorize txt + if (dIdx==0) { + //sunday colorize txt g.setColor(this.nrgb[this.settings().suClr]); - else + g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names g.setColor(g.theme.fg); + } } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; From 243538ac4ceafde6714dc4ca5dc649422fdab180 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 00:57:39 +0100 Subject: [PATCH 083/312] no red pls ;) --- apps/timecal/timecal.app.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 50a171e26..b5f212666 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -198,6 +198,7 @@ class TimeCalClock{ //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; const dName=dNames[dIdx]; if(dNo>0) @@ -206,13 +207,13 @@ class TimeCalClock{ if (dIdx==0) { //sunday colorize txt g.setColor(this.nrgb[this.settings().suClr]); - g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names - g.setColor(g.theme.fg); } + g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; + g.setColor(g.theme.fg); for(i=0; i<3; i++){ const y=nextY+i*CELL_H; g.drawLine(Bangle.appRect.x, y, Bangle.appRect.x2, y); From 7ef30431f1aace4f8b1cd7f0a9e259bdd2d04b4f Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 01:05:49 +0100 Subject: [PATCH 084/312] su colored lines... --- apps/timecal/timecal.app.js | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index b5f212666..9d78f7d08 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -198,22 +198,18 @@ class TimeCalClock{ //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; const dName=dNames[dIdx]; if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); - if (dIdx==0) { - //sunday colorize txt - g.setColor(this.nrgb[this.settings().suClr]); - } + if (dIdx==0) g.setColor(this.nrgb[this.settings().suClr]); //sunday maybe colorize txt g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names + g.setColor(g.theme.fg); } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; - g.setColor(g.theme.fg); for(i=0; i<3; i++){ const y=nextY+i*CELL_H; g.drawLine(Bangle.appRect.x, y, Bangle.appRect.x2, y); From ac05df0964579cc869627dfcc25c17f614374ffd Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 2 Feb 2022 22:16:44 +0100 Subject: [PATCH 085/312] codeoptimze and metadata emulator --- apps/timecal/metadata.json | 6 ++-- .../timecal/{ => testing}/timecal.app.test.js | 34 ++++++------------- apps/timecal/timecal.app.js | 27 ++++----------- 3 files changed, 21 insertions(+), 46 deletions(-) rename apps/timecal/{ => testing}/timecal.app.test.js (96%) diff --git a/apps/timecal/metadata.json b/apps/timecal/metadata.json index a1cf31a93..70ea98842 100644 --- a/apps/timecal/metadata.json +++ b/apps/timecal/metadata.json @@ -1,12 +1,14 @@ { "id": "timecal", "name": "TimeCal", "shortName":"TimeCal", - "icon": "icon.png", "version":"0.03", "description": "TimeCal shows the Time along with a 3 week calendar", - "tags": "clock", + "icon": "icon.png", "type": "clock", + "tags": "clock,calendar", "supports":["BANGLEJS2"], + "readme": "README.md", + "allow_emulator":true, "storage": [ {"name":"timecal.app.js","url":"timecal.app.js"}, {"name":"timecal.settings.js","url":"timecal.settings.js"} diff --git a/apps/timecal/timecal.app.test.js b/apps/timecal/testing/timecal.app.test.js similarity index 96% rename from apps/timecal/timecal.app.test.js rename to apps/timecal/testing/timecal.app.test.js index 6a7a8220f..8da4e26b5 100644 --- a/apps/timecal/timecal.app.test.js +++ b/apps/timecal/testing/timecal.app.test.js @@ -85,11 +85,9 @@ class TimeCalClock{ d=d?d :new Date(); - g.setFontAlign(0, -1); - g.setFont("Vector", this.TIME_FONT_SIZE()); - g.setColor(g.theme.fg); - g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); + g.setFontAlign(0, -1).setFont("Vector", this.TIME_FONT_SIZE()).setColor(g.theme.fg) + .clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7) + .drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y, true); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -166,11 +164,7 @@ class TimeCalClock{ } } if (render){ - g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); - g.setFont("Vector", FONT_SIZE); - g.setColor(g.theme.fg); - g.setFontAlign(0, -1); - g.drawString(dateStr,this.centerX,Y); + g.setFont("Vector", FONT_SIZE).setColor(g.theme.fg).setFontAlign(0, -1).clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3).drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -183,30 +177,23 @@ class TimeCalClock{ const DAY_NAME_FONT_SIZE=10; const CAL_Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10+this.TIME_FONT_SIZE()+3; - const CAL_AREA_H=Bangle.appRect.h-CAL_Y;//+24; //+24: top widegtes only + const CAL_AREA_H=Bangle.appRect.h-CAL_Y+24; //+24: top widegtes only const CELL_W=Bangle.appRect.w/7; //cell width const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 - g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - - g.setFont("Vector", DAY_NAME_FONT_SIZE); - g.setColor(g.theme.fg); - g.setFontAlign(-1, -1); - + g.setFont("Vector", DAY_NAME_FONT_SIZE).setColor(g.theme.fg).setFontAlign(-1, -1).clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 for(var dNo=0; dNo=0 ? (dNo+this.settings().wdStrt)%7 : (dNo+d.getDay()+4)%7; const dName=dNames[dIdx]; - if (dIdx==0) //sunday colorize txt - g.setColor(this.nrgb[this.settings().suClr]); - else - g.setColor(g.theme.fg); - g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names if(dNo>0) g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); + + if (dIdx==0) g.setColor(this.nrgb[this.settings().suClr]); //sunday maybe colorize txt + g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1).setColor(g.theme.fg); } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; @@ -255,8 +242,7 @@ class TimeCalClock{ } } if (this.settings().calBorder) { - g.setColor(g.theme.fg); - g.drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); + g.setColor(g.theme.fg).drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); } } diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 9d78f7d08..4c2f719e9 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -85,11 +85,9 @@ class TimeCalClock{ d=d?d :new Date(); - g.setFontAlign(0, -1); - g.setFont("Vector", this.TIME_FONT_SIZE()); - g.setColor(g.theme.fg); - g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); - g.drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y); + g.setFontAlign(0, -1).setFont("Vector", this.TIME_FONT_SIZE()).setColor(g.theme.fg) + .clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7) + .drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y, true); //.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7); //DEV-Option setTimeout(this.draw.bind(this), 60000-(d.getSeconds()*1000)-d.getMilliseconds()); @@ -166,11 +164,7 @@ class TimeCalClock{ } } if (render){ - g.clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); - g.setFont("Vector", FONT_SIZE); - g.setColor(g.theme.fg); - g.setFontAlign(0, -1); - g.drawString(dateStr,this.centerX,Y); + g.setFont("Vector", FONT_SIZE).setColor(g.theme.fg).setFontAlign(0, -1).clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3).drawString(dateStr,this.centerX,Y); } //g.drawRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+FONT_SIZE-3); //DEV-Option } @@ -188,12 +182,7 @@ class TimeCalClock{ const CELL_H=(CAL_AREA_H-DAY_NAME_FONT_SIZE)/3; //cell heigth const DAY_NUM_FONT_SIZE=Math.min(CELL_H-1,15); //size down, max 15 - g.clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); - - g.setFont("Vector", DAY_NAME_FONT_SIZE); - g.setColor(g.theme.fg); - g.setFontAlign(-1, -1); - + g.setFont("Vector", DAY_NAME_FONT_SIZE).setColor(g.theme.fg).setFontAlign(-1, -1).clearRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H); //draw grid & Headline const dNames = this.ABR_DAY.map((a) => a.length<=2 ? a : a.substr(0, 2)); //force shrt 2 @@ -204,8 +193,7 @@ class TimeCalClock{ g.drawLine(dNo*CELL_W, CAL_Y, dNo*CELL_W, CAL_Y+CAL_AREA_H-1); if (dIdx==0) g.setColor(this.nrgb[this.settings().suClr]); //sunday maybe colorize txt - g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1); //center Names - g.setColor(g.theme.fg); + g.drawString(dName, dNo*CELL_W+(CELL_W-g.stringWidth(dName))/2+2, CAL_Y+1).setColor(g.theme.fg); } var nextY=CAL_Y+DAY_NAME_FONT_SIZE; @@ -254,8 +242,7 @@ class TimeCalClock{ } } if (this.settings().calBorder) { - g.setColor(g.theme.fg); - g.drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); + g.setColor(g.theme.fg).drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); } } From c3832472d935206ac33f98179bcf3493e962b826 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:45:40 +0100 Subject: [PATCH 086/312] issue template first draft --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index 28021246f..a96b6e87c 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -27,8 +27,10 @@ body: label: Your firmware version description: | ## Please make sure you installed the latest (released) firmware! - If it occurs only in "Cutting Edge build" please mention this. - Update instructions: + How to see FW version? Within the AppLoader at "More..."-page: Device info; via the "about"-app or the "firmware"-widget. + If the issue will occur in "Cutting Edge build" only, please mention this. + + FW Update instructions: **Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates)** **Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates)** _Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead._ From 7b590a1408f5074d455982fa1481974681c49a72 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:52:22 +0100 Subject: [PATCH 087/312] fw placeholder 2v12 --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index a96b6e87c..51a896546 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -34,7 +34,7 @@ body: **Bangle 2: [firmware update instructions](https://www.espruino.com/Bangle.js2#firmware-updates)** **Bangle 1: [firmware update instructions](https://www.espruino.com/Bangle.js#firmware-updates)** _Hint: The links will open inplace hold e.g. ctrl/cmd-key and click to open in a new tab instead._ - placeholder: e.g. 2v11 + placeholder: e.g. 2v12 validations: required: true - type: textarea From c459820105371d70ec7c07dbc4aef75b5cdf1387 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 4 Feb 2022 00:59:53 +0100 Subject: [PATCH 088/312] allow a forced draw on settime --- apps/timecal/timecal.app.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 4c2f719e9..492d69503 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -67,10 +67,10 @@ class TimeCalClock{ /* * Run forest run **/ - draw(){ + draw(force){ this.drawTime(); - if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + if (force || this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) this.drawDateAndCal(); } @@ -83,8 +83,6 @@ class TimeCalClock{ d=this.date ? this.date : new Date(); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; - d=d?d :new Date(); - g.setFontAlign(0, -1).setFont("Vector", this.TIME_FONT_SIZE()).setColor(g.theme.fg) .clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7) .drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y, true); @@ -264,4 +262,11 @@ class TimeCalClock{ } } -timeCalClock = new TimeCalClock(); timeCalClock.draw(); \ No newline at end of file +timeCalClock = new TimeCalClock(); timeCalClock.draw(); + +//hook on settime to redraw immediatly +var _setTime = setTime; +var setTime = function(t) { + _setTime(t); + timeCalClock.draw(true); +}; \ No newline at end of file From 8c5af4aabbe56037281d400086fb4a1d54d53db2 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 17 Feb 2022 02:11:23 +0100 Subject: [PATCH 089/312] fixed app, test, settings and changelog/readme --- apps/timecal/ChangeLog | 3 +- apps/timecal/README.md | 18 ++-- apps/timecal/metadata.json | 4 +- apps/timecal/testing/timecal.app.test.js | 25 +++-- apps/timecal/timecal.app.js | 8 +- apps/timecal/timecal.settings.js | 116 +++++++++-------------- 6 files changed, 86 insertions(+), 88 deletions(-) diff --git a/apps/timecal/ChangeLog b/apps/timecal/ChangeLog index 499ac9afa..43bff461d 100644 --- a/apps/timecal/ChangeLog +++ b/apps/timecal/ChangeLog @@ -5,4 +5,5 @@ -> *RAM optimized* clean code, corrected minute update (timout, no intervall) -> locale: weekday name (first two characters) from locale -> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default]) -0.03: a lot of more settings for outline, colors and highlights \ No newline at end of file +0.03: a lot of more settings for outline, colors and highlights +0.04: finalized README, fixed settings cancel, fixed border-setting \ No newline at end of file diff --git a/apps/timecal/README.md b/apps/timecal/README.md index 345b117f3..d26f9ba4d 100644 --- a/apps/timecal/README.md +++ b/apps/timecal/README.md @@ -8,9 +8,15 @@ Shows the ### The settings menu Calendar View can be customized -* Cal.Start Day: Set day of week start. Values: 0=Sunday ... 6=Saturday or -1 Relative to today (default 1: Monday) -* Date Type: Choose how the date is display. Values: none, locale (default), MMM YYYY #WW -* Sunday Color: Set Sundays color. Values: none (default), red, green or blue -* today Color: Set today color. Values: none, red (default), green or blue -* today Marker: Outline today graphically. Values: none (default), rect(angle) or circle -* today MColor: Color for Outline. Values: none (default), red, green or blue +* < Save: Exist and save the current settings +* Show date: Choose if and how the date is displayed: none, locale (default), monthfull or monthshort.yearshort #weeknum with 0 prefixed +* Start wday: Set day of week start. Values: 0=Sunday, 1=Monday,...,6=Saturday or -1=Relative to today (default 0: Sunday) +* Su color: Set Sundays color. Values: none (default), red, green or blue +* Border: show or none (default) +* Submenu Today settings - choose how today is highlighted + * < Back: + * Color: none, red (default), green or blue + * Marker: Outline today graphically. Values: none (default), circle, rect(angle) + * Mrk.Color: Circle/rectangle color: red (default), green or blue + * Mrk.Size: Circle/rectangle thickness in pixel: min:1, max: 10, default:3 +* < Cancel: Exit and no change. Nevertheless missing default settings and superflous settings will be removed and saved. diff --git a/apps/timecal/metadata.json b/apps/timecal/metadata.json index 70ea98842..4dd8a8ca0 100644 --- a/apps/timecal/metadata.json +++ b/apps/timecal/metadata.json @@ -1,8 +1,8 @@ { "id": "timecal", "name": "TimeCal", "shortName":"TimeCal", - "version":"0.03", - "description": "TimeCal shows the Time along with a 3 week calendar", + "version":"0.04", + "description": "TimeCal shows the date/time along with a 3 week calendar", "icon": "icon.png", "type": "clock", "tags": "clock,calendar", diff --git a/apps/timecal/testing/timecal.app.test.js b/apps/timecal/testing/timecal.app.test.js index 8da4e26b5..e41f3d848 100644 --- a/apps/timecal/testing/timecal.app.test.js +++ b/apps/timecal/testing/timecal.app.test.js @@ -241,7 +241,7 @@ class TimeCalClock{ rDate=rD.getDate(); } } - if (this.settings().calBorder) { + if (this.settings().calBrdr) { g.setColor(g.theme.fg).drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); } } @@ -267,7 +267,7 @@ class TimeCalClock{ //************************************************************************************* //************************************************************************************* //************************************************************************************* -//Copy ABOVE the src code of clock-app and load via espruino WEB IDE +//Copy ABOVE the src code of clock-app class and load via espruino WEB IDE //************************************************************************************* //************************************************************************************* //************************************************************************************* @@ -466,11 +466,10 @@ class BangleTestRunner{ * befor each testcase */ _beforeCase() { + console.log(this.currentTest); console.log(this._nowTime(), ">>case #" + this.currentTestNum + "." + this.currentCaseNum + "/" + (this.currentTest.cases.length-1)); if (this.currentTest instanceof TestSetting) - console.log(this.currentTest.setting+"="+this.currentCase.value+"\n" - +this.currentCase.beforeTxt ? "testcase:"+this.currentCase.beforeTxt : "" - ); + console.log(this.currentTest.setting+"="+this.currentCase.value+"/n"+(this.currentCase.beforeTxt ? "#"+this.currentCase.beforeTxt : "")); } /** @@ -562,13 +561,12 @@ class BangleTestRunner{ _nowTime() { d = new Date(); - return(("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2) + ":" + ("0" + d.getSeconds()).slice(-2) + "." + ("00" + d.getMilliseconds()).slice(-3)) + return(("0" + d.getHours()).slice(-2) + ":" + ("0" + d.getMinutes()).slice(-2) + ":" + ("0" + d.getSeconds()).slice(-2) + "." + ("00" + d.getMilliseconds()).slice(-3)); } } /** * TEST all Settings */ -const SUNDAY = new BangleTestRunner("TimeCalClock", LogSeverity.INFO) /* .addTestSettings({ @@ -784,4 +782,17 @@ new BangleTestRunner("TimeCalClock", LogSeverity.INFO) functionParams: [], }) */ + + /* + .addTestSettings({ + setting: "calBrdr", + cases: [ + { value: false, beforeTxt:"Calendar without border?" , afterTxt: "No outer border." }, + { value: true, beforeTxt:"Calendar with border?" , afterTxt: "Outer border." }, + ], + constructorParams: [new Date(),"|TEST_SETTINGS|"], + functionNames: ["drawCal"], + functionParams: [], + }) + */ .execute(); \ No newline at end of file diff --git a/apps/timecal/timecal.app.js b/apps/timecal/timecal.app.js index 492d69503..c4baef486 100644 --- a/apps/timecal/timecal.app.js +++ b/apps/timecal/timecal.app.js @@ -67,10 +67,10 @@ class TimeCalClock{ /* * Run forest run **/ - draw(force){ + draw(){ this.drawTime(); - if (force || this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) + if (this.TZOffset===undefined || this.TZOffset!==d.getTimezoneOffset()) this.drawDateAndCal(); } @@ -83,6 +83,8 @@ class TimeCalClock{ d=this.date ? this.date : new Date(); const Y=Bangle.appRect.y+this.DATE_FONT_SIZE()+10; + d=d?d :new Date(); + g.setFontAlign(0, -1).setFont("Vector", this.TIME_FONT_SIZE()).setColor(g.theme.fg) .clearRect(Bangle.appRect.x, Y, Bangle.appRect.x2, Y+this.TIME_FONT_SIZE()-7) .drawString(("0" + require("locale").time(d, 1)).slice(-5), this.centerX, Y, true); @@ -239,7 +241,7 @@ class TimeCalClock{ rDate=rD.getDate(); } } - if (this.settings().calBorder) { + if (this.settings().calBrdr) { g.setColor(g.theme.fg).drawRect(Bangle.appRect.x, CAL_Y, Bangle.appRect.x2, CAL_Y+CAL_AREA_H-1); } } diff --git a/apps/timecal/timecal.settings.js b/apps/timecal/timecal.settings.js index 642f9a236..38c87903b 100644 --- a/apps/timecal/timecal.settings.js +++ b/apps/timecal/timecal.settings.js @@ -1,83 +1,73 @@ // Settings menu for Time calendar clock -(function(save) { +(function(exit) { ABR_DAY = require("locale") && require("locale").abday ? require("locale").abday : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - var FILE = "timecal.settings.json"; - var settings = Object.assign( // Load settings and use defaults - { - shwDate:1, //0:none, 1:locale, 2:month short, 3:month shortyear week - - wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for always focus/center today + var FILE = "timecal.validSttngs.json"; - tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E - tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled - tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E - tdyMrkPxl:3, //px + const DEFAULTS = { + shwDate:1, //0:none, 1:locale, 2:month, 3:monthshort.year #week + + wdStrt:0, //identical to getDay() 0->Su, 1->Mo, ... //Issue #1154: weekstart So/Mo, -1 for use today - suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E - //phColor:"#E00", //public holiday + tdyNumClr:3, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkr:0, //0:none, 1:circle, 2:rectangle, 3:filled + tdyMrkClr:2, //1:red=#E00, 2:green=#0E0, 3:blue=#00E + tdyMrkPxl:3, //px - calBrdr:false - }, - require('Storage').readJSON(FILE, true) || {} - ); + suClr:1, //0:fg, 1:red=#E00, 2:green=#0E0, 3:blue=#00E + //phColor:"#E00", //public holiday - const SETTINGS_AT_START = Object.assign(settings); //hardcopy of current and defaults + calBrdr:false + }; + validSttngs = require("Storage").readJSON("timecal.validSttngs.json", 1) || {}; + for (const k in validSttngs) if (!DEFAULTS.hasOwnProperty(k)) delete this.validSttngs[k]; //remove invalid settings + for (const k in DEFAULTS) if(!validSttngs.hasOwnProperty(k)) validSttngs[k] = validSttngs[k]; //assign missing defaults - var saveSettings = () => { - require('Storage').writeJSON(FILE, settings); + var changedSttngs = Object.assign({}, validSttngs); + + var saveExitSettings = () => { + require('Storage').writeJSON(FILE, changedSttngs); + exit(); }; - var restoreAndExitSettings = () => { - require('Storage').writeJSON(FILE, SETTINGS_AT_START); - E.showMenu(); + var cancelExitSettings = () => { + require('Storage').writeJSON(FILE, validSttngs); + exit(); }; var showMainMenu = () => { E.showMenu({ "": { - "title": /*LANG*/"Time cal clock" + "title": "TimeCal "+ /*LANG*/"settings" }, - /*LANG*/"< Save": () => save(), + /*LANG*/"< Save": () => saveExitSettings(), /*LANG*/"Show date": { - value: settings.shwDate, + value: validSttngs.shwDate, min: 0, max: 3, format: v => [/*LANG*/"none", /*LANG*/"locale", /*LANG*/"M", /*LANG*/"m.Y #W"][v], - onchange: v => { - settings.shwDate = v; - saveSettings(); - } + onchange: v => validSttngs.shwDate = v }, /*LANG*/"Start wday": { - value: settings.wdStrt, + value: validSttngs.wdStrt, min: -1, max: 6, format: v => v>=0 ? ABR_DAY[v] : /*LANG*/"today", - onchange: v => { - settings.wdStrt = v; - saveSettings(); - } + onchange: v => validSttngs.wdStrt = v }, /*LANG*/"Su color": { - value: settings.suClr, + value: validSttngs.suClr, min: 0, max: 3, format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], - onchange: v => { - settings.suClr = v; - saveSettings(); - } + onchange: v => validSttngs.suClr = v }, /*LANG*/"Border": { - value: settings.calBrdr, - format: v => v ? "show" : "none", - onchange: v => { - settings.calBrdr = v; - saveSettings(); - } + value: validSttngs.calBrdr, + format: v => v ? /*LANG*/"show" : /*LANG*/"none", + onchange: v => validSttngs.calBrdr = v }, /*LANG*/"Today settings": () => { showTodayMenu(); }, - /*LANG*/"< Cancel": () => restoreAndExitSettings() + /*LANG*/"< Cancel": () => cancelExitSettings() }); }; @@ -88,42 +78,30 @@ }, "< Back": () => showMainMenu(), /*LANG*/"Color": { - value: settings.tdyNumClr, + value: validSttngs.tdyNumClr, min: 0, max: 3, format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], - onchange: v => { - settings.tdyNumClr = v; - saveSettings(); - } + onchange: v => validSttngs.tdyNumClr = v }, /*LANG*/"Marker": { - value: settings.tdyMrkr, + value: validSttngs.tdyMrkr, min: 0, max: 3, format: v => [/*LANG*/"none", /*LANG*/"circle", /*LANG*/"rectangle", /*LANG*/"filled"][v], - onchange: v => { - settings.tdyMrkr = v; - saveSettings(); - } + onchange: v => validSttngs.tdyMrkr = v }, /*LANG*/"Mrk.Color": { - value: settings.tdyMrkClr, + value: validSttngs.tdyMrkClr, min: 0, max: 2, format: v => [/*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], - onchange: v => { - settings.tdyMrkClr = v; - saveSettings(); - } + onchange: v => validSttngs.tdyMrkClr = v }, /*LANG*/"Mrk.Size": { - value: settings.tdyMrkPxl, - min: 0, max: 10, + value: validSttngs.tdyMrkPxl, + min: 1, max: 10, format: v => v+"px", - onchange: v => { - settings.tdyMrkPxl = v; - saveSettings(); - } + onchange: v => validSttngs.tdyMrkPxl = v }, - /*LANG*/"< Cancel": () => restoreAndExitSettings() + /*LANG*/"< Cancel": () => cancelExitSettings() }); }; From e3cc8717e6933cfcddc9174e0570e6941460e01e Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sat, 2 Apr 2022 22:23:48 -0700 Subject: [PATCH 090/312] emulator mvp course parsed and displayed! --- apps/golfview/ChangeLog | 1 + apps/golfview/README.md | 21 ++++++ apps/golfview/golfview-icon.js | 1 + apps/golfview/golfview.js | 51 +++++++++++++++ apps/golfview/golfview.png | Bin 0 -> 22517 bytes apps/golfview/index.html | 114 +++++++++++++++++++++++++++++++++ apps/golfview/maptools.js | 59 +++++++++++++++++ apps/golfview/metadata.json | 14 ++++ 8 files changed, 261 insertions(+) create mode 100644 apps/golfview/ChangeLog create mode 100644 apps/golfview/README.md create mode 100644 apps/golfview/golfview-icon.js create mode 100644 apps/golfview/golfview.js create mode 100644 apps/golfview/golfview.png create mode 100644 apps/golfview/index.html create mode 100644 apps/golfview/maptools.js create mode 100644 apps/golfview/metadata.json diff --git a/apps/golfview/ChangeLog b/apps/golfview/ChangeLog new file mode 100644 index 000000000..b243db101 --- /dev/null +++ b/apps/golfview/ChangeLog @@ -0,0 +1 @@ +0.01: New App! Very limited course support. diff --git a/apps/golfview/README.md b/apps/golfview/README.md new file mode 100644 index 000000000..56d90782d --- /dev/null +++ b/apps/golfview/README.md @@ -0,0 +1,21 @@ +# App Name + +Describe the app... + +Add screen shots (if possible) to the app folder and link then into this file with ![](.png) + +## Usage + +Select your course of interest upon loading this app. + +## Contributions + +The performance of this app depends on the accuracy and consistency of user-submitted maps. Please contribute to Open Street Map using these guidelines and provide input in ways to support this application. + +## Controls + +Swipe to change holes and tap to see a green closeup. + +## Requests/Creator + +[Jason Dekarske](https://github.com/jdekarske) \ No newline at end of file diff --git a/apps/golfview/golfview-icon.js b/apps/golfview/golfview-icon.js new file mode 100644 index 000000000..83b180e4c --- /dev/null +++ b/apps/golfview/golfview-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("AAkCpMkyQCBwANGggLCAQYOOpAONpMgBwgLFHxAOJyVABwt/8QRGBwsv/mREAwOEkv/K4IOFyBZE3/ypMiHwwODy/+AYOJPowFD//Jkh9HAodf/IsGAQMSAoVL/4FD7dtBwWCCgd/6QOE2wjGl/6AoVbBwJDBBwh6BGQYOB7ZBG3/pAoUtBwNkBwuX/ojDBwNsZw3/0gFCBwJcDPQn0AoYOB2QOFpf+AoZcCNYx6ELgRrGAQoOB7IONPQUJBxB6CAoNBBxB6CRINIBYdJlIOIggODkiJFU4UABwmSAoWWU4cAfwQOCpSJDBwcCBAOJHQRNDBwUggAIByIKCJoYCCBwJ6CLAYOHgIFBogKCLgYCCgEAAoNIA4WUBw56CkRrFAQWAB4J6FqQOEyAOBPQRrCPQYCCBwJ6CNYYOFoAPBAoQOIpAOBPQRcCRIwOBPQRcCTBB6CFIoOGeoYCIBwJ6DARCJCNYQOIRIRrDARAOCLgckydtAQaJDLgttcwICCRIRNFpu0AQYOEJpQODVQYOLTZKYCHw4OKHw4NFAAS8ELIgABA==")) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js new file mode 100644 index 000000000..93d70e31c --- /dev/null +++ b/apps/golfview/golfview.js @@ -0,0 +1,51 @@ +let course = require("Storage").readJSON("course_data_hole1.json"); + +console.log(Object.keys(course)); + +g.clear(); + +for (var feature of course.features) { + //console.log(Object.keys(feature)); + if (feature.type === "fairway"){ + g.setColor(0,0,1); + } else if ( feature.type === "tee"){ + g.setColor(1,0,0); + } else if (feature.type === "green"){ + g.setColor(0,1,0); + } else if (feature.type === "bunker"){ + g.setColor(1,1,0); + } else { + continue; + } + + var nodelist = []; + feature.nodesXY.forEach(function (node) { + nodelist.push(node.x); + nodelist.push(node.y); + }); + newnodelist = g.transformVertices(nodelist,{ + x: 150, // x offset (default 0) + y: 150, // y offset (default 0) + scale: 0.45, // scale factor (default 1) + rotate: course.angle - 1.57, // angle in radians (default 0) + }); + + g.fillPoly(newnodelist, true); + console.log(feature.type); + console.log(nodelist); +} + +var nodelist = []; +course.nodesXY.forEach(function (node) { + nodelist.push(node.x); + nodelist.push(node.y); +}); + +newnodelist = g.transformVertices(nodelist,{ + x: 150, // x offset (default 0) + y: 150, // y offset (default 0) + scale: 0.45, // scale factor (default 1) + rotate: course.angle - 1.57, // angle in radians (default 0) +}); +g.setColor(0,1,1); +g.drawPoly(newnodelist); \ No newline at end of file diff --git a/apps/golfview/golfview.png b/apps/golfview/golfview.png new file mode 100644 index 0000000000000000000000000000000000000000..2bb61628218690fdd21aeb651f6275a78ca9318d GIT binary patch literal 22517 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 E2Tt6HqyPW_ literal 0 HcmV?d00001 diff --git a/apps/golfview/index.html b/apps/golfview/index.html new file mode 100644 index 000000000..24016ccbd --- /dev/null +++ b/apps/golfview/index.html @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apps/golfview/maptools.js b/apps/golfview/maptools.js new file mode 100644 index 000000000..af05343c8 --- /dev/null +++ b/apps/golfview/maptools.js @@ -0,0 +1,59 @@ +const EARTHRADIUS = 6371000; //km + +function radians(a) { + return a * Math.PI / 180; +} + +function degrees(a) { + let d = a * 180 / Math.PI; + return (d + 360) % 360; +} + +function toXY(a, origin) { + let pt = { + x: 0, + y: 0 + }; + + pt.x = EARTHRADIUS * radians(a.lon - origin.lon) * Math.cos(radians((a.lat + origin.lat) / 2)); + pt.y = EARTHRADIUS * radians(origin.lat - a.lat); + return pt; +} + +function arraytoXY(array, origin) { + let out = []; + for (var j in array) { + let newpt = toXY(array[j], origin); + out.push(newpt); + } + return out; +} + +function angle(a, b) { + let x = b.x - a.x; + let y = b.y - a.y; + return Math.atan2(-y, x); +} + +function rotateVec(a, theta) { + let pt = { + x: 0, + y: 0 + }; + c = Math.cos(theta); + s = Math.sin(theta); + pt.x = c * a.x - s * a.y; + pt.y = s * a.x + c * a.y; + return pt; +} + +// https://stackoverflow.com/questions/19721439/download-json-object-as-a-file-from-browser +function downloadObjectAsJSON(exportObj, exportName) { + var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); + var downloadAnchorNode = document.createElement('a'); + downloadAnchorNode.setAttribute("href", dataStr); + downloadAnchorNode.setAttribute("download", exportName + ".json"); + document.body.appendChild(downloadAnchorNode); // required for firefox + downloadAnchorNode.click(); + downloadAnchorNode.remove(); +} \ No newline at end of file diff --git a/apps/golfview/metadata.json b/apps/golfview/metadata.json new file mode 100644 index 000000000..bbb221b64 --- /dev/null +++ b/apps/golfview/metadata.json @@ -0,0 +1,14 @@ +{ "id": "glfview", + "name": "Golf View", + "version":"0.01", + "description": "This app will provide you with on course data to support your golf game! All information comes from OpenStreetMap. Please contribute by drawing your course using these guidelines: [guidelines](guidelines.com)", + "icon": "golfview.png", + "tags": "", + "supports" : ["BANGLEJS2"], + "readme": "README.md", + "custom": "index.html", + "storage": [ + {"name":"glfview.app.js","url":"golfview.js"}, + {"name":"glfview.img","url":"golfview-icon.js","evaluate":true} + ] +} From e3fb656ff84db1786a13eea12dfd17c8df8035b5 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sat, 2 Apr 2022 22:52:47 -0700 Subject: [PATCH 091/312] simplify the course geometry --- apps/golfview/golfview.js | 3 ++- apps/golfview/index.html | 6 ++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 93d70e31c..0ec55f28c 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,7 +1,8 @@ -let course = require("Storage").readJSON("course_data_hole1.json"); +let course = require("Storage").readJSON("course_data(3).json"); console.log(Object.keys(course)); +g.setBgColor(0,0,0); g.clear(); for (var feature of course.features) { diff --git a/apps/golfview/index.html b/apps/golfview/index.html index 24016ccbd..c018756ed 100644 --- a/apps/golfview/index.html +++ b/apps/golfview/index.html @@ -2,6 +2,7 @@ + @@ -75,13 +76,14 @@ return course_processed; } - function preprocessCoords(course_input) { + function preprocessCoords(course_input) { //todo posibly remove other coordinates for ~0.5 size reduction // first do the high-level way for (var hole in course_input.holes) { course_input.holes[hole].nodesXY = arraytoXY(course_input.holes[hole].nodes, course_input.holes[hole].nodes[0]) // then do the shapes in the features for (var feature in course_input.holes[hole].features) { - course_input.holes[hole].features[feature].nodesXY = arraytoXY(course_input.holes[hole].features[feature].nodes, course_input.holes[hole].nodes[0]); + many_points = arraytoXY(course_input.holes[hole].features[feature].nodes, course_input.holes[hole].nodes[0]); + course_input.holes[hole].features[feature].nodesXY = simplify(many_points,3,true); // from simplify-js } // find out how the hole is angled From 4458280fbe5171ad141a933fb376396d0470bca9 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sat, 2 Apr 2022 22:55:59 -0700 Subject: [PATCH 092/312] add license --- apps/golfview/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/golfview/LICENSE diff --git a/apps/golfview/LICENSE b/apps/golfview/LICENSE new file mode 100644 index 000000000..18c8d5fc3 --- /dev/null +++ b/apps/golfview/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Jason Dekarske + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file From 6d4f02734671c0f2157362ab6aa4f20d57cac75c Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sun, 3 Apr 2022 12:58:49 -0700 Subject: [PATCH 093/312] shrink output file a bunch --- apps/golfview/index.html | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/golfview/index.html b/apps/golfview/index.html index c018756ed..6c942fb18 100644 --- a/apps/golfview/index.html +++ b/apps/golfview/index.html @@ -8,8 +8,8 @@ - - +

No course

+ @@ -83,7 +83,12 @@ // then do the shapes in the features for (var feature in course_input.holes[hole].features) { many_points = arraytoXY(course_input.holes[hole].features[feature].nodes, course_input.holes[hole].nodes[0]); - course_input.holes[hole].features[feature].nodesXY = simplify(many_points,3,true); // from simplify-js + less_points = simplify(many_points, 3, true); // from simplify-js + // convert to int to save some memory + course_input.holes[hole].features[feature].nodesXY = less_points.map(function (pt) { + return { x: Math.round(pt.x), y: Math.round(pt.y) } + }); + delete course_input.holes[hole].features[feature].nodes; // delete coords because they take up a lot of memory } // find out how the hole is angled @@ -100,11 +105,13 @@ out = preprocessCoords(out); console.log(course_input); console.log(out); + $('#status').text("Course retrieved!"); + $('#upload').attr("disabled", false); }) // When the 'upload' button is clicked... document.getElementById("upload").addEventListener("click", function () { - downloadObjectAsJSON(out.holes["1"], "course_data"); + downloadObjectAsJSON(out.holes, "course_data"); sendCustomizedApp({ storage: courses }); From c9d70e386366e3054628fd122e45ddacc02bf565 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sun, 3 Apr 2022 14:57:02 -0700 Subject: [PATCH 094/312] format, use pi --- apps/golfview/golfview.js | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 0ec55f28c..7b31201d2 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -2,38 +2,38 @@ let course = require("Storage").readJSON("course_data(3).json"); console.log(Object.keys(course)); -g.setBgColor(0,0,0); +g.setBgColor(0, 0, 0); g.clear(); for (var feature of course.features) { //console.log(Object.keys(feature)); - if (feature.type === "fairway"){ - g.setColor(0,0,1); - } else if ( feature.type === "tee"){ - g.setColor(1,0,0); - } else if (feature.type === "green"){ - g.setColor(0,1,0); - } else if (feature.type === "bunker"){ - g.setColor(1,1,0); + if (feature.type === "fairway") { + g.setColor(0, 0, 1); + } else if (feature.type === "tee") { + g.setColor(1, 0, 0); + } else if (feature.type === "green") { + g.setColor(0, 1, 0); + } else if (feature.type === "bunker") { + g.setColor(1, 1, 0); } else { continue; } - + var nodelist = []; feature.nodesXY.forEach(function (node) { nodelist.push(node.x); nodelist.push(node.y); }); - newnodelist = g.transformVertices(nodelist,{ + newnodelist = g.transformVertices(nodelist, { x: 150, // x offset (default 0) y: 150, // y offset (default 0) scale: 0.45, // scale factor (default 1) - rotate: course.angle - 1.57, // angle in radians (default 0) + rotate: course.angle - Math.PI / 2.0, // angle in radians (default 0) }); - + g.fillPoly(newnodelist, true); console.log(feature.type); - console.log(nodelist); + console.log(newnodelist); } var nodelist = []; @@ -42,11 +42,11 @@ course.nodesXY.forEach(function (node) { nodelist.push(node.y); }); -newnodelist = g.transformVertices(nodelist,{ +newnodelist = g.transformVertices(nodelist, { x: 150, // x offset (default 0) y: 150, // y offset (default 0) scale: 0.45, // scale factor (default 1) - rotate: course.angle - 1.57, // angle in radians (default 0) + rotate: course.angle - Math.PI / 2.0, // angle in radians (default 0) }); -g.setColor(0,1,1); +g.setColor(0, 1, 1); g.drawPoly(newnodelist); \ No newline at end of file From 394ffeb37889e2be53a262afaacd62d15719e4d8 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sun, 3 Apr 2022 16:43:19 -0700 Subject: [PATCH 095/312] put the hole in a layout --- apps/golfview/golfview.js | 125 ++++++++++++++++++++++++-------------- apps/golfview/maptools.js | 4 ++ 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 7b31201d2..75103f7b5 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,52 +1,83 @@ let course = require("Storage").readJSON("course_data(3).json"); - -console.log(Object.keys(course)); - -g.setBgColor(0, 0, 0); -g.clear(); - -for (var feature of course.features) { - //console.log(Object.keys(feature)); - if (feature.type === "fairway") { - g.setColor(0, 0, 1); - } else if (feature.type === "tee") { - g.setColor(1, 0, 0); - } else if (feature.type === "green") { - g.setColor(0, 1, 0); - } else if (feature.type === "bunker") { - g.setColor(1, 1, 0); - } else { - continue; - } - - var nodelist = []; - feature.nodesXY.forEach(function (node) { - nodelist.push(node.x); - nodelist.push(node.y); - }); - newnodelist = g.transformVertices(nodelist, { - x: 150, // x offset (default 0) - y: 150, // y offset (default 0) - scale: 0.45, // scale factor (default 1) - rotate: course.angle - Math.PI / 2.0, // angle in radians (default 0) - }); - - g.fillPoly(newnodelist, true); - console.log(feature.type); - console.log(newnodelist); +let hole = course; +function distance(a, b) { + return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)) } -var nodelist = []; -course.nodesXY.forEach(function (node) { - nodelist.push(node.x); - nodelist.push(node.y); +function drawHole(l) { + + console.log(l); + let hole_straight_distance = distance( + hole.nodesXY[0], + hole.nodesXY[hole.nodesXY.length - 1] + ); + + let scale = 0.9 * l.h / hole_straight_distance; + + let transform = { + x: l.x + l.w / 2, // x offset (default 0) + y: l.h * 0.95, // y offset (default 0) + scale: scale, // scale factor (default 1) + rotate: hole.angle - Math.PI / 2.0, // angle in radians (default 0) + } + + for (var feature of hole.features) { + //console.log(Object.keys(feature)); + if (feature.type === "fairway") { + g.setColor(0, 0, 1); + } else if (feature.type === "tee") { + g.setColor(1, 0, 0); + } else if (feature.type === "green") { + g.setColor(0, 1, 0); + } else if (feature.type === "bunker") { + g.setColor(1, 1, 0); + } else { + continue; + } + + var nodelist = []; + feature.nodesXY.forEach(function (node) { + nodelist.push(node.x); + nodelist.push(node.y); + }); + newnodelist = g.transformVertices(nodelist, transform); + + g.fillPoly(newnodelist, true); + //console.log(feature.type); + //console.log(newnodelist); + } + + var waynodelist = []; + hole.nodesXY.forEach(function (node) { + waynodelist.push(node.x); + waynodelist.push(node.y); + }); + + newnodelist = g.transformVertices(waynodelist, transform); + g.setColor(0, 1, 1); + g.drawPoly(newnodelist); +} + +// The layout, referencing the custom renderer +var Layout = require("Layout"); +var layout = new Layout({ + type: "h", c: [ + { + type: "v", c: [ + { type: "txt", font: "10%", label: "Hole 1" }, + { type: "txt", font: "10%", label: "Par 4" }, + { type: "txt", font: "10%", label: "Hcp 15" }, + { type: "txt", font: "35%", label: "420" }, + { type: "txt", font: "20%", label: "69" }, + ] + }, + { type: "custom", render: drawHole, id: "graph", bgCol: g.theme.bg, fillx: 1, filly: 1 } + ] }); -newnodelist = g.transformVertices(nodelist, { - x: 150, // x offset (default 0) - y: 150, // y offset (default 0) - scale: 0.45, // scale factor (default 1) - rotate: course.angle - Math.PI / 2.0, // angle in radians (default 0) -}); -g.setColor(0, 1, 1); -g.drawPoly(newnodelist); \ No newline at end of file +console.log(g.getWidth()); +console.log(g.getHeight()); + +g.clear(); +layout.render(); +layout.debug(); \ No newline at end of file diff --git a/apps/golfview/maptools.js b/apps/golfview/maptools.js index af05343c8..fffd57ca0 100644 --- a/apps/golfview/maptools.js +++ b/apps/golfview/maptools.js @@ -47,6 +47,10 @@ function rotateVec(a, theta) { return pt; } +function distance(a,b) { + return Math.sqrt(Math.pow(a.x-b.x,2) + Math.pow(a.y-b.y,2)) +} + // https://stackoverflow.com/questions/19721439/download-json-object-as-a-file-from-browser function downloadObjectAsJSON(exportObj, exportName) { var dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(exportObj)); From 29c3a5e62fe5dcc0fac2a3a774f55103fe870e90 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sun, 3 Apr 2022 18:00:50 -0700 Subject: [PATCH 096/312] swiping and hole stats --- apps/golfview/golfview.js | 64 ++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 21 deletions(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 75103f7b5..250507774 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,12 +1,14 @@ let course = require("Storage").readJSON("course_data(3).json"); -let hole = course; +let current_hole = 1; +let hole = course[current_hole.toString()]; + function distance(a, b) { - return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)) + return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2)); } function drawHole(l) { - console.log(l); + //console.log(l); let hole_straight_distance = distance( hole.nodesXY[0], hole.nodesXY[hole.nodesXY.length - 1] @@ -15,22 +17,24 @@ function drawHole(l) { let scale = 0.9 * l.h / hole_straight_distance; let transform = { - x: l.x + l.w / 2, // x offset (default 0) - y: l.h * 0.95, // y offset (default 0) + x: l.x + l.w / 2, // center in the box + y: l.h * 0.95, // pad it just a bit scale: scale, // scale factor (default 1) rotate: hole.angle - Math.PI / 2.0, // angle in radians (default 0) - } + }; for (var feature of hole.features) { //console.log(Object.keys(feature)); if (feature.type === "fairway") { - g.setColor(0, 0, 1); + g.setColor(1, 0, 1); // magenta } else if (feature.type === "tee") { - g.setColor(1, 0, 0); + g.setColor(1, 0, 0); // red } else if (feature.type === "green") { - g.setColor(0, 1, 0); + g.setColor(0, 1, 0); // green } else if (feature.type === "bunker") { - g.setColor(1, 1, 0); + g.setColor(1, 1, 0); // yellow + } else if (feature.type === "water_hazard") { + g.setColor(0, 0, 1); // blue } else { continue; } @@ -54,7 +58,7 @@ function drawHole(l) { }); newnodelist = g.transformVertices(waynodelist, transform); - g.setColor(0, 1, 1); + g.setColor(0, 1, 1); // cyan g.drawPoly(newnodelist); } @@ -64,20 +68,38 @@ var layout = new Layout({ type: "h", c: [ { type: "v", c: [ - { type: "txt", font: "10%", label: "Hole 1" }, - { type: "txt", font: "10%", label: "Par 4" }, - { type: "txt", font: "10%", label: "Hcp 15" }, - { type: "txt", font: "35%", label: "420" }, - { type: "txt", font: "20%", label: "69" }, + { type: "txt", font: "10%", id: "hole", label: "Hole 1" }, + { type: "txt", font: "10%", id: "par", label: "Par 4" }, + { type: "txt", font: "10%", id: "hcp", label: "Hcp 15" }, + { type: "txt", font: "35%", id: "postyardage", label: "420" }, + { type: "txt", font: "20%", id: "measyardage", label: "69" }, ] }, { type: "custom", render: drawHole, id: "graph", bgCol: g.theme.bg, fillx: 1, filly: 1 } - ] + ], + lazy: true }); -console.log(g.getWidth()); -console.log(g.getHeight()); - g.clear(); layout.render(); -layout.debug(); \ No newline at end of file +//layout.debug(); + +Bangle.on('swipe', function (direction) { + if (direction > 0) { + current_hole--; + } else { + current_hole++; + } + + if (current_hole > 18) { current_hole = 1; } + if (current_hole < 1) { current_hole = 18; } + hole = course[current_hole.toString()]; + + layout.hole.label = "Hole " + current_hole; + layout.par.label = "Par " + course[current_hole.toString()].par; + layout.hcp.label = "Hcp " + course[current_hole.toString()].handicap; + layout.postyardage.label = 420; //TODO + + g.clear(); + layout.render(); +}); \ No newline at end of file From 789fc3d467fa1bf7d2209d8a3f946b425ad87482 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Sun, 3 Apr 2022 20:58:44 -0700 Subject: [PATCH 097/312] fix the mixed up hole ways --- apps/golfview/golfview.js | 2 +- apps/golfview/index.html | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 250507774..e19c08c29 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,4 +1,4 @@ -let course = require("Storage").readJSON("course_data(3).json"); +let course = require("Storage").readJSON("course_data.json"); let current_hole = 1; let hole = course[current_hole.toString()]; diff --git a/apps/golfview/index.html b/apps/golfview/index.html index 6c942fb18..45ca60555 100644 --- a/apps/golfview/index.html +++ b/apps/golfview/index.html @@ -16,7 +16,7 @@ @@ -57,7 +60,7 @@ } // if we find a feature add it to the corresponding hole - if (/(green)|(bunker)|(tee)|(teebox)|(fairway)|(water_hazard)/.test(element.tags.golf)) { //TODO missing cartpath + if (/(green)|(bunker)|(tee)|(teebox)|(fairway)|(water_hazard)/.test(element.tags.golf)) { let nodes = [] for (const node_id of element.nodes) { nodes.push(findNodeCoordinates(course_verbose, node_id)); @@ -75,14 +78,14 @@ return course_processed; } - function preprocessCoords(course_input) { //todo posibly remove other coordinates for ~0.5 size reduction + function preprocessCoords(course_input) { // first do the high-level way for (var hole in course_input.holes) { course_input.holes[hole].nodesXY = arraytoXY(course_input.holes[hole].nodes, course_input.holes[hole].nodes[0]) // then do the shapes in the features for (var feature in course_input.holes[hole].features) { many_points = arraytoXY(course_input.holes[hole].features[feature].nodes, course_input.holes[hole].nodes[0]); - less_points = simplify(many_points, 3, true); // from simplify-js + less_points = simplify(many_points, 2, true); // from simplify-js // convert to int to save some memory course_input.holes[hole].features[feature].nodesXY = less_points.map(function (pt) { return { x: Math.round(pt.x), y: Math.round(pt.y) } @@ -90,12 +93,21 @@ delete course_input.holes[hole].features[feature].nodes; // delete coords because they take up a lot of memory } - // find out how the hole is angled course_input.holes[hole].angle = angle(course_input.holes[hole].nodesXY[0], course_input.holes[hole].nodesXY[course_input.holes[hole].nodesXY.length - 1]) } return course_input; } + $("#upload").click(function () { + sendCustomizedApp({ + storage: courses + }); + }); + + $("#download").click(function () { + downloadObjectAsJSON(out.holes, "course_data"); + }); + var out = {}; // download info from the course $.post(url, query, function (result) { @@ -106,16 +118,9 @@ console.log(out); $('#status').text("Course retrieved!"); $('#upload').attr("disabled", false); + $('#download').attr("disabled", false); }) - // When the 'upload' button is clicked... - document.getElementById("upload").addEventListener("click", function () { - downloadObjectAsJSON(out.holes, "course_data"); - sendCustomizedApp({ - storage: courses - }); - }); - From ac1a7e13a8c691112d30504c1ded06bb52432740 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 11:28:40 -0700 Subject: [PATCH 104/312] battling custom page on apploader --- apps/golfview/app-icon.js | 1 + apps/golfview/{index.html => custom.html} | 0 apps/golfview/metadata.json | 4 ++-- 3 files changed, 3 insertions(+), 2 deletions(-) create mode 100644 apps/golfview/app-icon.js rename apps/golfview/{index.html => custom.html} (100%) diff --git a/apps/golfview/app-icon.js b/apps/golfview/app-icon.js new file mode 100644 index 000000000..49232b838 --- /dev/null +++ b/apps/golfview/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwJC/AH4A/AH4AgA==")) diff --git a/apps/golfview/index.html b/apps/golfview/custom.html similarity index 100% rename from apps/golfview/index.html rename to apps/golfview/custom.html diff --git a/apps/golfview/metadata.json b/apps/golfview/metadata.json index 9a17894f4..8988c6bc7 100644 --- a/apps/golfview/metadata.json +++ b/apps/golfview/metadata.json @@ -3,11 +3,11 @@ "version":"0.01", "description": "This app will provide you with on course data to support your golf game! All information comes from OpenStreetMap. Please contribute by drawing your course using these guidelines: [guidelines](guidelines.com)", "icon": "golfview.png", - "tags": "outdoors", + "tags": "outdoors, gps", "allow_emulator": true, "supports" : ["BANGLEJS2"], "readme": "README.md", - "interface": "index.html", + "custom": "custom.html", "storage": [ {"name":"golfview.app.js","url":"golfview.js"}, {"name":"golfview.img","url":"app-icon.js","evaluate":true} From 8d86dc48a31e147e242018f836fed5b04cf08805 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 11:40:29 -0700 Subject: [PATCH 105/312] fix undefined reference --- apps/golfview/custom.html | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index 425c87c0d..2120b9fb4 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -98,6 +98,7 @@ return course_input; } + let courses = {}; $("#upload").click(function () { sendCustomizedApp({ storage: courses @@ -105,10 +106,9 @@ }); $("#download").click(function () { - downloadObjectAsJSON(out.holes, "course_data"); + downloadObjectAsJSON(courses, "courses"); }); - var out = {}; // download info from the course $.post(url, query, function (result) { course_input = result; @@ -116,6 +116,7 @@ out = processFeatures(course_input.elements); out = preprocessCoords(out); console.log(out); + courses = JSON.parse(JSON.stringify(out)); // deep copy $('#status').text("Course retrieved!"); $('#upload').attr("disabled", false); $('#download').attr("disabled", false); From 877d9eb6432ba1d425082ea6f75094f499d52b2e Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 11:43:31 -0700 Subject: [PATCH 106/312] update example obj --- apps/golfview/golfview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index e19c08c29..bd35508fe 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,4 +1,4 @@ -let course = require("Storage").readJSON("course_data.json"); +let course = require("Storage").readJSON("courses.json").holes; let current_hole = 1; let hole = course[current_hole.toString()]; From b1a2e81e438137b8fa2413575d543f329a273010 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 11:46:44 -0700 Subject: [PATCH 107/312] js scope is confusing --- apps/golfview/custom.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index 2120b9fb4..54204ac94 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -98,7 +98,7 @@ return course_input; } - let courses = {}; + var courses = {}; $("#upload").click(function () { sendCustomizedApp({ storage: courses From 6221bfd1e827d17698e09c3e7b3995125f17e56e Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 12:12:57 -0700 Subject: [PATCH 108/312] does it have to be an array? --- apps/golfview/custom.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index 54204ac94..b619251cb 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -98,7 +98,7 @@ return course_input; } - var courses = {}; + var courses = []; $("#upload").click(function () { sendCustomizedApp({ storage: courses @@ -116,7 +116,7 @@ out = processFeatures(course_input.elements); out = preprocessCoords(out); console.log(out); - courses = JSON.parse(JSON.stringify(out)); // deep copy + courses.push(JSON.parse(JSON.stringify(out))); // deep copy $('#status').text("Course retrieved!"); $('#upload').attr("disabled", false); $('#download').attr("disabled", false); From d13ca46cc5fa963fef06deaf56020808a0c40aa0 Mon Sep 17 00:00:00 2001 From: Kevin Whitaker Date: Tue, 5 Apr 2022 15:32:49 -0400 Subject: [PATCH 109/312] fix issue where game over didn't prevent player from continuing. --- apps/red7game/red7.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/red7game/red7.js b/apps/red7game/red7.js index 901bc186f..38afb775e 100644 --- a/apps/red7game/red7.js +++ b/apps/red7game/red7.js @@ -703,8 +703,8 @@ function drawScreenHelp() { } function drawGameOver(win) { + startedGame = false; E.showAlert(win ? "AI has given up. You Win!" : "You cannot play. AI wins.").then(function(){ - startedGame = false; undoStack = []; drawMainMenu(); }); From d1c06b94fc26592529cd6bf4362c729a155036b1 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 12:33:59 -0700 Subject: [PATCH 110/312] last little fix for debug --- apps/golfview/golfview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index bd35508fe..74feb7c63 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,4 +1,4 @@ -let course = require("Storage").readJSON("courses.json").holes; +let course = require("Storage").readJSON("courses.json")[0].holes; let current_hole = 1; let hole = course[current_hole.toString()]; From 15c5ae9f73814427ecfcfc2cff31c1e1713c807d Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 12:59:09 -0700 Subject: [PATCH 111/312] I think I got it --- apps/golfview/custom.html | 14 +++++++++----- apps/golfview/golfview.js | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index b619251cb..e71332212 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -78,7 +78,7 @@ return course_processed; } - function preprocessCoords(course_input) { + function preprocessCoords(course_input) { // first do the high-level way for (var hole in course_input.holes) { course_input.holes[hole].nodesXY = arraytoXY(course_input.holes[hole].nodes, course_input.holes[hole].nodes[0]) @@ -98,15 +98,16 @@ return course_input; } - var courses = []; + var course = {}; + var course_name = "Davis"; $("#upload").click(function () { sendCustomizedApp({ - storage: courses + storage: course }); }); $("#download").click(function () { - downloadObjectAsJSON(courses, "courses"); + downloadObjectAsJSON(course, "golfcourse-" + course_name); }); // download info from the course @@ -116,7 +117,10 @@ out = processFeatures(course_input.elements); out = preprocessCoords(out); console.log(out); - courses.push(JSON.parse(JSON.stringify(out))); // deep copy + course = { + name: "golfcourse-" + course_name + ".json", + content: JSON.parse(JSON.stringify(out)) // deep copy + }; $('#status').text("Course retrieved!"); $('#upload').attr("disabled", false); $('#download').attr("disabled", false); diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index 74feb7c63..2cf394375 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -1,4 +1,4 @@ -let course = require("Storage").readJSON("courses.json")[0].holes; +let course = require("Storage").readJSON("golfcourse-Davis.json").holes;//TODO use the course ID let current_hole = 1; let hole = course[current_hole.toString()]; From 477ca4832117e619a854763d6d6879e8bec671ed Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Tue, 5 Apr 2022 13:31:24 -0700 Subject: [PATCH 112/312] this workflow... --- apps/golfview/custom.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index e71332212..92b6c20ba 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -98,11 +98,11 @@ return course_input; } - var course = {}; + var courses = []; var course_name = "Davis"; $("#upload").click(function () { sendCustomizedApp({ - storage: course + storage: courses }); }); @@ -117,10 +117,10 @@ out = processFeatures(course_input.elements); out = preprocessCoords(out); console.log(out); - course = { + courses.push({ name: "golfcourse-" + course_name + ".json", content: JSON.parse(JSON.stringify(out)) // deep copy - }; + }); $('#status').text("Course retrieved!"); $('#upload').attr("disabled", false); $('#download').attr("disabled", false); From 28c2298d8b75b85e9ee24dc35d9df78b0a25130f Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 13:56:47 +0200 Subject: [PATCH 113/312] add the icon for Activity Reminder --- apps/activityreminder/app-icon.js | 1 + apps/activityreminder/app.png | Bin 0 -> 1509 bytes apps/activityreminder/metadata.json | 5 +++-- 3 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 apps/activityreminder/app-icon.js create mode 100644 apps/activityreminder/app.png diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js new file mode 100644 index 000000000..0b17c16ca --- /dev/null +++ b/apps/activityreminder/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("AKBQMDAf+AEfxHwOL4IOBxcAJBhgCBhP9AcBfwOJD/gBxP5H/xPwOZPwCCRhAOCSBAOeHxwOQNxyeCBxP9B/AVxTeN+IAfxfgDxvABwQ+JwL/wCeJgQiDDwOHA1gKPgRCEIAicD//DgAgEzQvDwCCEXAvB8AOF4L5f/AwgR8EdQfh/+CPgvABwZ+BwoHwAODAOGPgsABwiWC3QYABxP5DAOGRwf9AIRP/xPCeFAIwBwVOHgJwzxSODHxWCBwvD+IeBxPv+BoChwzwCZAcOtxf/gwOIaAS8CBwzcIiAhwD4WOIOAfAxxAOCkAV+FAfxB/gvw4H8IH+AOEHQsGcAxaDgOD/AOHP4BwDwH/I5A2eCBw04D8KABwlADHzSCmAwID+DiCBwyEEBwz4D/EuH/+eIgQ8GADgA==")) diff --git a/apps/activityreminder/app.png b/apps/activityreminder/app.png new file mode 100644 index 0000000000000000000000000000000000000000..3c5df499bbac84664799d6dfad70bbd8a432a8bd GIT binary patch literal 1509 zcmVg(8VH5XGX1_O|t5&e7XF zv*+$PXZQBr$UoVKp1U(UGdr_8yR(I(__?E{vLlZ-)d4Dd456*t=}5p6@`SfG#W%EzrQ;t>oJLox@}0aqyBe*&Hd zo&(+n_5vM1o6+w~pdDEk8V;9`oY5iRHlRi6-vZno^{J#8iFh>}OxG_1iyY_{1H%UG zdx2yOhG`^c|G^CO50mtQX`W>aisg(|;BVlh4D{_0O(l=zo@E4JLI|e7xyIjHfL}7u z9{{#i;pqjT3}9|udvoykz6wt-2xR~hc@mmd?@}lTWq_}Zzh~v(VYKT z1N}t`eM98}&Adp2%1~JqN@!n~q9tGh$>VMrcnCP?z@r9;5uM1kANXz zoB1+ubp}4G6du}+aK10WeZaQh4FOkX^v|<8$DIg7PGg zMfnN9RI=?fZy9_aGk#xzWR9*zxHiMsRgp#cImr2a6zB)0IF7N_;JwMxuLCKyJ&7bs zHUoIeB(o^L3^;7`yW4Rbb1U5ANY{bn36->e;VA@Mm2UWLI}AnsHNp4swH=CbX*o zw5>2t^Wy&3D~wI$my(S4A_jouR+y)4bR8`1R`@LC+ZVtah<7{!JWKM5YcNtGFLo;5 z29QdTD>f7u|6iPgR_^@%>;f z63=&GKYw39_4VQj+(JSNh5ZDGbDvm^+oIWzEMC>HM4?^nU22aokF@V7-{LliD42#O zlC{FR^#U#aS0X#a9oW;{YPG)}g{CgOK#TvgD}JAk{#It3|}n@0G7^oz~9_JYaC?l8hw0oPmle?U^1cy~xcU3x(mGJBdrE0q3INgAp$ z6uMHzsw*#;jLeu#nXTw`{hKZQT|%L5c7%D@XMG5{!YWy4P50MQ?6go=r1Y<;7qlV& z;h`zN1IZRO%mm(5XjVpauA$Hbe8M<-fp%|KM(*ddS#JaGC;9X>_Lh?oqnSBES}2UG z7c>E%k(@E@8QWE)Ka*Kk(RYpVyDbztku1{mf?(w^6V+yH2D-b)?I2PEsJufcA?2*J zQ0N4nK|D_5>vFd625rWk!tU;|LQeyyT6o$FdmibEk0Mv)HS++F0);taX>B`ju>)Vt zuxYJ~81*ziYGuQ0?6V!W-;vUoZCf-^BDpJQZ5X+F8@Fq+7-=)M5jZ^u&osl`00000 LNkvXXu0mjfwhzTf literal 0 HcmV?d00001 diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index e16876e5e..31aa97288 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -4,13 +4,14 @@ "shortName":"Activity Reminder", "description": "A reminder to take short walks for the ones with a sedentary lifestyle", "version":"0.01", - "type": "bootloader", + "type": "app", "tags": "tool", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ {"name": "activityreminder.boot.js","url": "boot.js"}, - {"name": "activityreminder.settings.js","url": "settings.js"} + {"name": "activityreminder.settings.js","url": "settings.js"}, + {"name": "activityreminder.img","url": "app-icon.js","evaluate": true} ], "data": [ {"name": "activityreminder.json"} From 44df89561fbdf80420b1859cdb0f1c7274f32994 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:03:58 +0200 Subject: [PATCH 114/312] change app-icon for Activity Reminder --- apps/activityreminder/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index 0b17c16ca..a3ecc9637 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("AKBQMDAf+AEfxHwOL4IOBxcAJBhgCBhP9AcBfwOJD/gBxP5H/xPwOZPwCCRhAOCSBAOeHxwOQNxyeCBxP9B/AVxTeN+IAfxfgDxvABwQ+JwL/wCeJgQiDDwOHA1gKPgRCEIAicD//DgAgEzQvDwCCEXAvB8AOF4L5f/AwgR8EdQfh/+CPgvABwZ+BwoHwAODAOGPgsABwiWC3QYABxP5DAOGRwf9AIRP/xPCeFAIwBwVOHgJwzxSODHxWCBwvD+IeBxPv+BoChwzwCZAcOtxf/gwOIaAS8CBwzcIiAhwD4WOIOAfAxxAOCkAV+FAfxB/gvw4H8IH+AOEHQsGcAxaDgOD/AOHP4BwDwH/I5A2eCBw04D8KABwlADHzSCmAwID+DiCBwyEEBwz4D/EuH/+eIgQ8GADgA==")) +require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA") From 68cc3d6adab46621916703378a5ec50c1c629d1f Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:09:45 +0200 Subject: [PATCH 115/312] Change icon to try to understand what cause the issue --- apps/activityreminder/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index a3ecc9637..5e57a4b7c 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA") +require("heatshrink").decompress(atob("mEwghC/AHsHu93uAX/C+wACsAaTC/4Xiu1mswXRCYNnDQQxTgwX/C8QABuAaTg4X/C7Z3Xa/4Xds1ms4XUCgV2DYIXUsBdTC/4AEg4VCC61wIiYX/C74A/AGIA==")) From 84318bd7bcb9c8ee7bd08d845d1f3ccfa201ebbe Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:13:44 +0200 Subject: [PATCH 116/312] Hopefully fix the broken build because of no icon --- apps/activityreminder/app-icon.js | 2 +- apps/activityreminder/metadata.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index 5e57a4b7c..a3ecc9637 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwghC/AHsHu93uAX/C+wACsAaTC/4Xiu1mswXRCYNnDQQxTgwX/C8QABuAaTg4X/C7Z3Xa/4Xds1ms4XUCgV2DYIXUsBdTC/4AEg4VCC61wIiYX/C74A/AGIA==")) +require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA") diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 31aa97288..3dfb88419 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -4,6 +4,7 @@ "shortName":"Activity Reminder", "description": "A reminder to take short walks for the ones with a sedentary lifestyle", "version":"0.01", + "icon": "app.png", "type": "app", "tags": "tool", "supports": ["BANGLEJS", "BANGLEJS2"], From 172654594ae008b27f43dce5ddc1a22d2520feac Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:20:49 +0200 Subject: [PATCH 117/312] close the open parenthesis for on the app-icon of Activity Reminder --- apps/activityreminder/app-icon.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index a3ecc9637..676b73c9c 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA") +require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA")) From b4ea88281e1a204b97d81adb1bd97e4f312e58ff Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:24:16 +0200 Subject: [PATCH 118/312] fix Activity Reminder icon size --- apps/activityreminder/app-icon.js | 2 +- apps/activityreminder/app.png | Bin 1509 -> 1135 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index 676b73c9c..df66b1e93 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("oFAwMB/4AR/EfA4vgg4HFwAkGGAIGE/0BwF/A4kP+AHE/kf/E/A5k/AIJGEA4JIEA54fHA5A3HJ4IHE/0H8BXFN434gB/F+APG8AHBD4nAv/AJ4mBCIMPA4cDWAo+BEIQgCJwP/8OACATNC8PAIIRcC8HwA4Xgvl/8DCBHwR1B+H/4I+C8AHBn4HCgfAA4MA4Y+CwAHCJYLdBgAHE/kMA4ZHB/0AhE//E8J4UAjAHBU4eAnDPFI4MfFYIHC8P4h4HE+/4GgKHDPAJkBw63F/+DA4hoBLwIHDNwiICHAPhY4g4B8DHEA4KQBX4UB/EH+C/Dgfwgf4A4QdCwZwDFoOA4P8A4c/gHAPAf8jkDZ4IHDTgPwoAHCUAMfNIKYDAgP4OIIHDIQQHDPgP8S4f/54iBDwYAOA")) +require("heatshrink").decompress(atob("mEwwMB/4AM+EPAofgg4FD4EDAoeD4IFDx/xAocP+AFDj/4Ap4XFEYuH8IFDwA7EgAFD/0AMYf8NoIFC/F/4F/MgRaBj4FBE4PGDAXDAIMACQOH3/j4E/IwMf8f8v/+jkf8AFB/k4AoIXB/FwAoQ0BsAFEgMf+BgB/kHAoJSCh8PJIJ8Cgf8GgIMBgIFEgH+KYX+mF+Aoc8n7GC/k8j4FC+F8j+HaAX4h4FC4Pww5uBN4PA44FDwPDwboD8CiCegPweAXwn/wHYTPBLIYAKA=")) diff --git a/apps/activityreminder/app.png b/apps/activityreminder/app.png index 3c5df499bbac84664799d6dfad70bbd8a432a8bd..5a2a5b2a4fae93c8f957123dcdb55a9f02459c70 100644 GIT binary patch delta 1132 zcmV-y1e5#a3-1UaiBL{Q4GJ0x0000DNk~Le0000m0000m2nGNE09OL}hmj!^e*`2+ zL_t(&fz{bftX)$S2k_r3Du}jdoBC*4qZ-si(T7Nd#J~V)N-GqpsE7&ikrf}1dXH}!3#KhVCp8oGW?=dc-nr& zRRhvkiA!-e|3oO+j1R;J@7=zwh`_Q_wAK@NbRyKTP)J(MPXB|;Yq(croSc7m-_^B&Q-!?F zMg4}G63!4-3AIqp8_jG7j>Y&$Yss(|Te7w{8T%X83_@&*Vf=35`X_DA3_@&*B|>4= zsrUxQu>mJdRz$bwfnmIhe;L{Dal9&&%w?E`n@jq)3m?DzUFzrx>B=7yYMeUER2_|< zab3T}rWjV-N!k&g4(yf46HM;E&?W8egj- zKi^hxhJ*!)C)>dCUW-3b*vHeAT2kZh;)pknZPUe@GvADsglm`8_V|JSTKGfvXi4XH(Wc9T#FH9v60`?YN;E@j0GV zzA9si^?p2deH(r^DK11`%j$FzUkfXhV|FtBm$0YT;dI3V&}i1zH#~tq@D|QU#+ECO z(i@tUY8ld0TGw02?PH_z2{eSQ@S+;q%@OyI;%&v0VRs~Ae=~L|PT~met+1UV2+z6e z`zg(8VH5XGX1_O|t5&e7XF zv*+$PXZQBr$UoVKp1U(UGdr_8yR(I(__?E{vLlZ-)d4Dd456*t=}5p6@`SfG#W%EzrQ;t>oJLox@}0aqyBe*&Hd zo&(+n_5vM1o6+w~pdDEk8V;9`oY5iRHlRi6-vZno^{J#8iFh>}OxG_1iyY_{1H%UG zdx2yOhG`^c|G^CO50mtQX`W>aisg(|;BVlh4D{_0O(l=zo@E4JLI|e7xyIjHfL}7u z9{{#i;pqjT3}9|udvoykz6wt-2xR~hc@mmd?@}lTWq_}Zzh~v(VYKT z1N}t`eM98}&Adp2%1~JqN@!n~q9tGh$>VMrcnCP?z@r9;5uM1kANXz zoB1+ubp}4G6du}+aK10WeZaQh4FOkX^v|<8$DIg7PGg zMfnN9RI=?fZy9_aGk#xzWR9*zxHiMsRgp#cImr2a6zB)0IF7N_;JwMxuLCKyJ&7bs zHUoIeB(o^L3^;7`yW4Rbb1U5ANY{bn36->e;VA@Mm2UWLI}AnsHNp4swH=CbX*o zw5>2t^Wy&3D~wI$my(S4A_jouR+y)4bR8`1R`@LC+ZVtah<7{!JWKM5YcNtGFLo;5 z29QdTD>f7u|6iPgR_^@%>;f z63=&GKYw39_4VQj+(JSNh5ZDGbDvm^+oIWzEMC>HM4?^nU22aokF@V7-{LliD42#O zlC{FR^#U#aS0X#a9oW;{YPG)}g{CgOK#TvgD}JAk{#It3|}n@0G7^oz~9_JYaC?l8hw0oPmle?U^1cy~xcU3x(mGJBdrE0q3INgAp$ z6uMHzsw*#;jLeu#nXTw`{hKZQT|%L5c7%D@XMG5{!YWy4P50MQ?6go=r1Y<;7qlV& z;h`zN1IZRO%mm(5XjVpauA$Hbe8M<-fp%|KM(*ddS#JaGC;9X>_Lh?oqnSBES}2UG z7c>E%k(@E@8QWE)Ka*Kk(RYpVyDbztku1{mf?(w^6V+yH2D-b)?I2PEsJufcA?2*J zQ0N4nK|D_5>vFd625rWk!tU;|LQeyyT6o$FdmibEk0Mv)HS++F0);taX>B`ju>)Vt zuxYJ~81*ziYGuQ0?6V!W-;vUoZCf-^BDpJQZ5X+F8@Fq+7-=)M5jZ^u&osl`00000 LNkvXXu0mjfwhzTf From 8862a9c279917918e6f24b575ff2ef8f6496ead6 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:40:48 +0200 Subject: [PATCH 119/312] Add the app.js file for Activity Reminder app --- apps/activityreminder/app.js | 3 +++ apps/activityreminder/metadata.json | 3 ++- 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 apps/activityreminder/app.js diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js new file mode 100644 index 000000000..4a82e33b6 --- /dev/null +++ b/apps/activityreminder/app.js @@ -0,0 +1,3 @@ +Bangle.loadWidgets(); +Bangle.drawWidgets(); +eval(require("Storage").read("activityreminder.settings.js"))(()=>load()); diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 3dfb88419..182585f10 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -6,10 +6,11 @@ "version":"0.01", "icon": "app.png", "type": "app", - "tags": "tool", + "tags": "tool,activity", "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ + {"name": "activityreminder.app.js","url":"app.js"}, {"name": "activityreminder.boot.js","url": "boot.js"}, {"name": "activityreminder.settings.js","url": "settings.js"}, {"name": "activityreminder.img","url": "app-icon.js","evaluate": true} From 9164e6a55a7134d7a9550c4ed874261a00bae6ed Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 14:56:27 +0200 Subject: [PATCH 120/312] changing Activity Reminder icon color --- apps/activityreminder/app-icon.js | 2 +- apps/activityreminder/app.png | Bin 1135 -> 10183 bytes 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app-icon.js b/apps/activityreminder/app-icon.js index df66b1e93..418657961 100644 --- a/apps/activityreminder/app-icon.js +++ b/apps/activityreminder/app-icon.js @@ -1 +1 @@ -require("heatshrink").decompress(atob("mEwwMB/4AM+EPAofgg4FD4EDAoeD4IFDx/xAocP+AFDj/4Ap4XFEYuH8IFDwA7EgAFD/0AMYf8NoIFC/F/4F/MgRaBj4FBE4PGDAXDAIMACQOH3/j4E/IwMf8f8v/+jkf8AFB/k4AoIXB/FwAoQ0BsAFEgMf+BgB/kHAoJSCh8PJIJ8Cgf8GgIMBgIFEgH+KYX+mF+Aoc8n7GC/k8j4FC+F8j+HaAX4h4FC4Pww5uBN4PA44FDwPDwboD8CiCegPweAXwn/wHYTPBLIYAKA=")) +require("heatshrink").decompress(atob("mEwwYda7dtwAQNmwRB2wQMgO2CIXACJcNCIfYCJYOCCgQRNJQYRM2ADBgwR/CKprRWAKPQWZ0DCIjXLjYREGpYODAQVgCBB3Btj+EAoQAGO4IdCgImDCAwLCAoo4IF4J3DCIPDCIQ4FO4VtwARCAoIRGRgQCBa4IRCKAQRERgOwIIIRDAoOACIoIBwwRHLIqMCFgIRCGQQRIWAYRLYQoREWwTmHO4IRCFgLXHPoi/CbogAFEAIRCWwTpKEwZBCHwK5BCJZEBCJZcCGQTLDCJK/BAQIRKMoaSDOIYAFeQYRMcYRWBXIUAWYPACIq8DagfACJQLCCIYsBU4QRF7B9CAogRGI4QLCAoprIMoZKER5C/DAoShMAo4AGfAQFIACQ=")) diff --git a/apps/activityreminder/app.png b/apps/activityreminder/app.png index 5a2a5b2a4fae93c8f957123dcdb55a9f02459c70..758f3a249a5d6b3a0c651856829db773d69b36f8 100644 GIT binary patch literal 10183 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 WaCh$IzQQn%r68jsT`u|L+5Z5j{h-eP delta 1115 zcmV-h1f=`NPwxnjBYyw}VoOIv0RI600RN!9r;`8x1SCmBK~!jg)!9v~T~ibX@ZT#c zh_+~(`e<6C8q`G5he(CQzyN7VD-@}yhzaqL7?_AeT0~k&8xvoN3SriGJ{l5@N~wWP zDxrBLicpl-s-o{2>~nJW+4r3D?!E8cck7?*L$Q4{GwHO+J41V1JYQDOL16H=)c&5FSF-( z>@Y4Fh|&^F7ewabj^Rn16>(-`T{f2U_Tc0xRa$}7imSW2hI>cCy{+%++Q3##L0jA4 zzuh6f@Ay$u(0?s$@NbRyKTP)J(E zM9(+2!H+q+d+`2AW36UR|AWhGxL0JHoPT%U)wO|Bg}ly1{f3(o&Jb1!wNTC*&1?sb z#rQ~T$*>n&vbHxF`y1B`LTrj*{BGjmJdRz$bwfnmIh z8QJe~yegE;WtfGVOZvA9AHV%w>gWpT${!PIoI1=@9gUxHUBASp7*^a#+7X}Qr^xPm zttqu7^R=+IlAD-}c=$N7eFTpxeiPz0ikC9~=Nu2>;pNEw`K<3se5X3Sda~tCB!01Q zfLS(ypMS?9A0I^hvv42YR7|tDJ>4(yw`(5YkK)W4U#lWN-&SyjgawHw+raW(i$77= z$J3QsQseL9h&PUH*ob?CREj5mSHvB|DV>U6S|ffAJ}ePG(FE$Y()fV04PQlluXQSZ z1`bq+Um{#mRSBq@0M$8O*E&w0g+hpP2m5iZVt>BpZKT5qyr1yj5pE}{w$p>UNFR7A zadaU0Jud7#Cv-T0s}&b#Q`SEn7h)wI7j~rWxS<>IIi6L%Dr1WEemr)48-6z_E<|6; z>U0uc3oDglb~65#u&3AIbj1VEXx7&^Jb^#(7S2e+3dQ50#C}yTCjj#mQ(>ppbjd5%wOX(4Q~Mni!W+U}(E@!yeAG+ZI8NDb!UExstnM16 h4hu8;DHnd+;XlT7ITkV1H=h6i002ovPDHLkV1iFuEeHSr From efe25635dceae934d653d1a198077aefd4934567 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 15:06:24 +0200 Subject: [PATCH 121/312] Change the logo color slightly to be less visually agressive --- apps/activityreminder/app.png | Bin 10183 -> 10269 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/activityreminder/app.png b/apps/activityreminder/app.png index 758f3a249a5d6b3a0c651856829db773d69b36f8..91073c4440664fb9cb976bb7a8911c310e5c2c84 100644 GIT binary patch delta 6507 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 R*8l(j07*qoM6N;tV1g+bYz_bb delta 6615 zcmV;|87StRP{&V@BLWsxktHF2BP)=F|Feo-LNdd07|-b)^z!=)ASHP!+f~mlTe74~ zAclKy1e6;8_rFv94_`^^OF17?$RS*Ox$LqjJW1F7D(knt-1@z~?0Jj7-@L9KZx~*( z&rhasK7YTiA2-+!g=hZdMyZ`Q>f1N6JNHlTZgd8+G9$y2er}Y{jjY*!Z|HM_vX^y* zoZ{;e>e!F{UP;#$dBh1aeZgL6H(pp zTEE&=`EELEgS)17y6d8u$9inKF-2#FGWg0E(~Mm&CVZDov)g}s>uI9Rw%ddk8*aC} zY94dZYuJ1>wMI*f+%+FHnwx2fi{E~$-(E1Mqyp)l9=2j$#)z?hnTB{ye)BOrqUSNH zUk1Lv-+zf;Egtk@Wl52YVe7s{_4c%=#@qqT;bS7z>wE^EGBSUjZ)a#?h8(vnt4w&HyZ-b5aCfkCuob$v_ zbcq-$-g@V~4?g;T%s;}M{rEPd%&ywa+ti;sJ*3*9x-U5R>x ztY?r5mod8-Go-q0>BX_8<~GBR-2c1BT2x`~5o+{a!X;M{(c@R2SG-tF!sOl)xpiH! zn#}Zn18;Cev*g||rITS*t2%OsX_z#6E@APmu104UWmPk$PWB)(>%NX~;+_>?;IeE; z_F&;sTTvrDqpC)`B1lI>cjy$ZD3O3b0%VL4ZTHEzf$!q11a%?fZ3t^&Gq~AWQ_FH~ z#1=cV?mjjaJeuZ%Hp~!>^Tt=xNac|l&u~_M#7iUuFkp&z2|6cfT^g0k(2Tt5~;wE-L?~`y=;{@yWEU^Eh1FnXY$ZoeIP=v`iTgC z3Kw5%hUp3|T`$f`f>BRr#c;hks}s%!q`i*WRJbrzmO`Q@0CHA4St5y2LU5!*X#sTS>sBZy3eMxC6Rm-=W&V7 zBW7_c^DJ@XwtVcR;`-)Mee;2c$Y1M*J@(4?y7~LLZn1+3^UFx8KIth-$O*g4vYMae zSON|dTRbeG{%i^Yco_rE5_4F8v4*~wg}4S#b7bCFF|I&e#6x@^@#4EP(d*h%h3`Iu z{d2+UEo4( z6`fY?h+%=kqESFWFczKXg+{Y>*UEeZiM zg+X$1?UHX{VDKb?M@z6}|BzXFY?^@V&OHJa685JWvHlQkpSXUtHojMwDlUZHyfwLqE3 z@#BOJ1ll(dsy@vryif5IQ$~Qxj3_l_Mm)%ba7HuEjUv!pDl>u{l_-!M+2Y`J<+4zW zc#bQ#g^bigepx8n-qws+dmOeDSw?4RfM*kpXha^sp9WV2)cTNrk1isFL1wwqp9xO= zfC(`ne1G%;3Qd&OfWDCnOQ8iwUn?OeA^mFxzp4NU19UY?yUHR5qLV~MmtuU~t9?eI z6(xfJo|a)$yiWMEL;iJgOK1ziiKcPMk`*{Je-%0!pWdq%O98 zU$5#^C3kCJF7{a#?#TZcc7lKIHP7NV<8nKFE)FwJAAyJHZDMmtYnWYLr0YS$T zkd0r}m)X#%`XKZ&Q0rF6Cf>%cnmQ)hX)>#eBB;0PlfR_qX@0vtno4rm0!=4n$lgkh zPpJoi7YUhvb=^`~3*@o$7Fj7d>30y-mm#Q4%u7e>VX9De1BOYOD9Pv<0CSOJ7z%W* zJ^Gqcf1$(lU^6cm3cYlxFjbTiL&DA6C1%*;t`gG&K8IQ$Il+K^-P7~t(2ClQFW0H; z^hSU>f|ts8CcB8xnB<{}4(x*JsZt3^&s4a|Mu-o8%Kb;2eK%QzvmcDTm+<85y##K_l@(fzIAwbMhO`l*57NHoYmef! zMX?)y6hc{FHYn5=9f}7$w`D|cGW7K{;>Z4k`n*B$zR&P|n?e1o&+vVlLH(@H@O_&> z{jAUMeMzW3uL+%0Y#>TpHNCW8;b`oYsi@8HOCC|lq4V)}fLo?o1$JDZx30q~lnT-c z;JP$?8hUjCOuj1Bd>%u{2ksfjc~RXN>LJH}6lHl!l>w+Np)k@HN{VIF2bcd$3aa;7 z@NcD{dang$TROt$ZY{}{4-sfzLM`A7LJens zbc{H|G+g6@bcC$W00PEBvEa}hX~S3;!6-@hfrvrjqAoD8p9@Gp0+gm8!UMVwa5Lov z-30mqZ>9l@sX%s#9-tN@)4P`v@=&Y8p=NcQo~-jF>8M|_&X=U4{OVkDgGZ zcXXr+ciy&V!wJxi(r^mCs?~8qKWK1&u0&tR)1@CGATXWlcj-5;n(f_!Mt80jblENF zR8h4Q3!;W^$*h`mwbCM%k+$OZ#t>z521Vf2-_2=z4X8J;^A%3ftv>1>FK} zKt52{7AoqMh@kk9Vdmu%_CXy!az%`; zlI;FrZ|TlgBjD;q`mDXKUPQ>B*8eW8o)AfC^@@>d3rJBk55_60-Z%L4cIoxeq3=^c z{V*4>_MaQEs!D4Q4->WIA6NnVfK4(5?Pcr1=a=3brB*c`T5M93sPFmVXY`=H=ZBxs zgZhjgq`cI-{(4rIU$Vo0ZZoJ4eTL<33J2>D~K1_ukk6@`CdW1Hu}U5 z7~6B92ZC{%T`4ZrjUe>Ok!Q*6B}Z1xt#;9EtN?rPQp+BUcCxVox`n+jtC7_*06z@i zYkb$2SHEq{OBPA*7DK=3-m1?#^Q2h(-Nu;Oob$3V2F((k7%gjm*$rXxq%AUd{dCz5 z`BZhQpYFt*+#*V{f6>s8Xj>v$Z53_HUCevIT&f;Percmdfpi`z-&RW!)I&^=nv2&L z0!#m?sv|Luz>o&ik{AdKsoNs@8yLpI(^aY4yjeJ^BdTn5FN=x7PX)>jmZa%p7rBoS zemj7=N1$AfMcyobr7rM;l}DKib52%ES^JXJl(kFpT&o~fl0}=Oq%pD^DyLm^8Y*|Y zXg5^SY8SOfR;S}Wb=QRYO~jvl$+dGTMKr{1rBf>9w)vR`NO}~jh)W6z3s_QT-)q=`n*9IbdJM58E7xj6yXxev8P3ukAhF8X zRd~j&d-bk6&FUbS(;jRaA(YgE-(tiU5K-GiCFq2$h8i3Q-KTYwAz}`6{j(ZJ0#78{>1TfZsJ?pRNSTK)MasMi zQ=(|?jD;IHR9Vz0At?%K?e$VpUVBS=Mf~iD91t()kk?6z0U+Wmf@7&xG%g{m;H_f& zHJ*xpc?o9O4Eb3{{4~VX>4=Z`9gBH1r9&Rn98MQ8RidgFFEY9)AExNTt=dPjF#T5z z;y?C>kNba{>mO5H{UX<8M>rv~5Wk}2B!8rlgWf0w7|C;tDV?0vo+{hu+7a&3v57~{ zZsZhU5+fqSgIm?q)1yx%5i$Y1g zR7$Ck@!qEHz&y;QSJs__OhHacO%pcGO`9V6@1>Yf|GbTL>IU`C+gN88Oa1dU*4f2U zKi+a09nwH0cMz=LL8PXA0HdVDhDJ$=c~U~aF`;;O_v~Tjvo#=Q-g^UTZ4MNB zJNKLhB#31*glfG+OP~kJwq3@Jt9KE9D*S%dj|_mCs+(9hR3l} z35n+3Z|A75_IW;r*4bs>DEGu@1RyTpN6+zOxZ5H8ZM#n1mxt~kL z?&TF}nh=*gTDVX$j7TiK_ld>3{D%U>*!+_YP_IJZy$+BJ3D0$r*>Bc=1$wMlT&EvY zl2|;AZ%Y1NMS1G;m0tCcNL0}WfY*Ep zVIE#1Slafa6UmfB-7fEcecOoQm7Iz+qrG&xS&j~CzbbUuuM%vQ{i;Q+%_t({f>lwp zzzF<0ij_^?ajVFmc7fF0+!eA}od710PrH3Oy=P%}A5$W!PW1Q6FgSQcI1OgZ*Tj{lnS*r^fx{Fq3*+*;j{|&cT?|zL8TUb{~vc?HhbXcBr$Nu)^ob zrG(E5m9D)^#H#cZpRJ6sS{ZjIgL0jD->nSMw{E^1UHW)l?W@N(=h!6jk1o5LEw?T^ z1=yBlW))!9vyW7NN>L=|Dy8n~RZhRZRIfu}y`JmOTGk(A{cjql>YL8#vvIo51L3**JdoYzf#B%%KcU2R(n!zGM*1xg??(DL zYqTQq(od#D#t~|`Pt=~mf1tu8=M8;G>v$0CFUN+h6v)Sad4rlE{joc${v)Iv>OVqS zisQdT+V}aU?$d++ns3W%f0b`Vb^y!ce5euu_i4HTM4zeGuf(f*s)oFF+@XA_8p}B$ zhZ2#p(XF3VHl{7mZsV=ZPlH#aRbGd4FZI5RRiEj2kYI5T80H)AqlGn1ki zs|YYQHa0jkH8-)5(OG&8>>zSA-Bo1XGB~%rfRADFxs0b&mjF@8Uem|JStULv9yRHL#E)E8JbvR`bXnk;Q8SaCCyo+}#ST_Fn3YV8 zc#=4#YC7c$S&voDTb#8@jkWH{Ul_^jE6ZG`IfNt@u>=Vs6x2{g1vcWe>ZDjm(|*Fo zKj``;aw+60gOOtaRcMf1KlmT~?$#w3Vu2MI^!67hGr0jK{cXxO8_V1Zie?Nx7a<42{IH~{u00v@9M??Vs0RI60pp$wg zB!3Jx8X5XsEdT%kTS-JgRA}DqnavWzAP9s5llOmRdrA)-LlAaRJ8`C`Ht}2e5$JJj zzJ&7D)>?lzk+lWfffI#DIXqZ|Oo0cA5Gwoy==n`>ot)J01LYACTuO&0XCXZ{U$1~y zz;XhtOtVE6>VdY_81VdyZ26mbGJH+|%6}!2LS!mDK!m{HEeMa`pa`MEN31p=MoQp` z0k0+S*=G&$nufnFsmKWfQmLllvu+|H-w(7Sv)~bFwD*oc=XOqk2gaI~!4ulav1*ig z@=yV!lL}kr;rsaYe;061KvwWVUC1*Y>A^%?E#aOzY(8(@Q#7IGH#B#^AXnl~C49)) ztF9yKoi4x%SPNJ+%`#I7PjHTm)00-vmHc^LDUoSTys<&)$a=2h*&Jxect7j)d2%eo zv(UAnw`Q`QPgq2#0gSd1Z7!54ACidycMpsddce*N_cv>{$}AZz_D(UfarXItS|5(f V_AkWlq@w@;002ovPDHLkV1j(L?Tr8c From 0fee4bd8c4ea6b278edbe23b291d1bbea5419bb6 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 17:30:55 +0200 Subject: [PATCH 122/312] try to fix the issue with the watchface drawing over the Activity Reminder --- apps/activityreminder/boot.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 170ece135..97d0d1d52 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -39,6 +39,9 @@ if (global.activityreminder) { }, showAlert: function(){ + g.clear(); + Bangle.loadWidgets(); + Bangle.drawWidgets(); E.showPrompt("Innactivity detected",{ title:"Activity reminder", buttons : {"Ok": true,"Dismiss": false} @@ -52,11 +55,11 @@ if (global.activityreminder) { load(); }); Bangle.buzz(); - + setTimeout(load, 10000); }, } ); - setInterval(global.activityreminder.run, 60000); + setInterval(global.activityreminder.run, 2000); } From 513d2f7002a992da6ed5cc4a44d8cafe9d40a0e4 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 18:16:51 +0200 Subject: [PATCH 123/312] Try a new structure to avoid bugs --- apps/activityreminder/app.js | 23 +++++++++++++++++++- apps/activityreminder/boot.js | 41 +++++++++-------------------------- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 4a82e33b6..1668e0dc9 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,3 +1,24 @@ +g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -eval(require("Storage").read("activityreminder.settings.js"))(()=>load()); + + +/* draw the alert */ +E.showPrompt("Innactivity detected",{ + title:"Activity reminder", + buttons : {"Ok": true,"Dismiss": false} +}).then(function(v) { + console.log(stepsArray); + if(v == true){ + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); + } + if(v == false){ + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); + } + load(); +}); + + +Bangle.buzz(); +setTimeout(load, 10000); + diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 97d0d1d52..4504e4d09 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -7,6 +7,7 @@ global.activityreminder = Object.assign({ minSteps: 50, }, require("Storage").readJSON("activityreminder.json", true) || {}); +var stepsArray = []; if (global.activityreminder) { @@ -14,52 +15,30 @@ if (global.activityreminder) { activityreminder = Object.assign(activityreminder, { - stepsArray: [], run: function(){ var now = new Date(); var h = now.getHours(); + console.log(stepsArray); if(h >= activityreminder.startHour && h < activityreminder.endHour) { var health = Bangle.getHealthStatus("day"); - activityreminder.stepsArray.unshift(health.steps); - activityreminder.stepsArray = activityreminder.stepsArray.slice(0, activityreminder.maxInnactivityMin); + stepsArray.unshift(health.steps); + stepsArray = activityreminder.stepsArray.slice(0, activityreminder.maxInnactivityMin); } else{ - activityreminder.stepsArray = []; + stepsArray = []; } - if(activityreminder.stepsArray.length == activityreminder.maxInnactivityMin){ - if (activityreminder.stepsArray[0] - activityreminder.stepsArray[activityreminder.stepsArray.length-1] < activityreminder.minSteps) + if(stepsArray.length == activityreminder.maxInnactivityMin){ + if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) { - activityreminder.showAlert(); + load('authentiwatch.app.js'); } } - - - }, - - showAlert: function(){ - g.clear(); - Bangle.loadWidgets(); - Bangle.drawWidgets(); - E.showPrompt("Innactivity detected",{ - title:"Activity reminder", - buttons : {"Ok": true,"Dismiss": false} - }).then(function(v) { - if(v == true){ - activityreminder.stepsArray = activityreminder.stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); - } - if(v == false){ - activityreminder.stepsArray = activityreminder.stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); - } - load(); - }); - Bangle.buzz(); - setTimeout(load, 10000); - }, - } + } ); + setInterval(global.activityreminder.run, 2000); } From 47f9e581a3dea25b11b64732cec27fb6ddfc5bc4 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 18:21:43 +0200 Subject: [PATCH 124/312] bug fixes --- apps/activityreminder/boot.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 4504e4d09..0a3d94793 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -24,7 +24,7 @@ if (global.activityreminder) { { var health = Bangle.getHealthStatus("day"); stepsArray.unshift(health.steps); - stepsArray = activityreminder.stepsArray.slice(0, activityreminder.maxInnactivityMin); + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); } else{ stepsArray = []; @@ -36,8 +36,7 @@ if (global.activityreminder) { } } } - ); - + }); setInterval(global.activityreminder.run, 2000); } From 269b5732095696d88e8d7ece6d586c58bafbd158 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 18:29:12 +0200 Subject: [PATCH 125/312] launch the right app for the alert and try to preserve stepsArray --- apps/activityreminder/app.js | 6 +++--- apps/activityreminder/boot.js | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 1668e0dc9..45d9247bb 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -8,12 +8,12 @@ E.showPrompt("Innactivity detected",{ title:"Activity reminder", buttons : {"Ok": true,"Dismiss": false} }).then(function(v) { - console.log(stepsArray); + console.log(global.stepsArray); if(v == true){ - stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); + global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); } if(v == false){ - stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); + global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); } load(); }); diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 0a3d94793..b69237251 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -32,7 +32,7 @@ if (global.activityreminder) { if(stepsArray.length == activityreminder.maxInnactivityMin){ if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) { - load('authentiwatch.app.js'); + load('activityreminder.app.js'); } } } From 919175671dea80321c5d68ab710a582681965914 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 18:31:11 +0200 Subject: [PATCH 126/312] Try to preserve stepsArray --- apps/activityreminder/boot.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index b69237251..3b4c12205 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -7,7 +7,7 @@ global.activityreminder = Object.assign({ minSteps: 50, }, require("Storage").readJSON("activityreminder.json", true) || {}); -var stepsArray = []; +global.stepsArray = []; if (global.activityreminder) { @@ -19,18 +19,18 @@ if (global.activityreminder) { run: function(){ var now = new Date(); var h = now.getHours(); - console.log(stepsArray); + console.log(global.stepsArray); if(h >= activityreminder.startHour && h < activityreminder.endHour) { var health = Bangle.getHealthStatus("day"); - stepsArray.unshift(health.steps); - stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); + global.stepsArray.unshift(health.steps); + global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin); } else{ - stepsArray = []; + global.stepsArray = []; } - if(stepsArray.length == activityreminder.maxInnactivityMin){ - if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) + if(global.stepsArray.length == activityreminder.maxInnactivityMin){ + if (global.stepsArray[0] - global.stepsArray[stepsArray.length-1] < activityreminder.minSteps) { load('activityreminder.app.js'); } From e9f3a0ff3a54cd3009af1152b69f613e238e3d27 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Thu, 7 Apr 2022 19:19:42 +0200 Subject: [PATCH 127/312] Refactor, untested --- apps/activityreminder/app.js | 72 +++++++++++++++++++++++++---------- apps/activityreminder/boot.js | 24 ++++++++---- 2 files changed, 67 insertions(+), 29 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 45d9247bb..5fefbc97a 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,24 +1,54 @@ +global.activityreminder = Object.assign({ + enabled: true, + startHour: 9, + endHour: 20, + maxInnactivityMin: 30, + dismissDelayMin: 15, + minSteps: 50 +}, require("Storage").readJSON("activityreminder.json", true) || {}); + +var stepsArray = []; // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it + + +function drawAlert(){ + E.showPrompt("Innactivity detected",{ + title:"Activity reminder", + buttons : {"Ok": true,"Dismiss": false} + }).then(function(v) { + console.log(global.stepsArray); + if(v == true){ + stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); + // todo save stepsArray + } + if(v == false){ + stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); + // todo save stepsArray + } + load(); + }); + + Bangle.buzz(); + setTimeout(load, 10000); + +} + +function run() +{ + if(stepsArray.length == activityreminder.maxInnactivityMin){ + if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) + { + drawAlert(); + } + }else{ + // todo find something else to do when there is no alert to show, showing the setting is a placeholder for now + eval(require("Storage").read("android.settings.js"))(()=>load()); + } + + +} + + g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); - - -/* draw the alert */ -E.showPrompt("Innactivity detected",{ - title:"Activity reminder", - buttons : {"Ok": true,"Dismiss": false} -}).then(function(v) { - console.log(global.stepsArray); - if(v == true){ - global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); - } - if(v == false){ - global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); - } - load(); -}); - - -Bangle.buzz(); -setTimeout(load, 10000); - +run(); diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 3b4c12205..7b33b35ff 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -4,12 +4,14 @@ global.activityreminder = Object.assign({ endHour: 20, maxInnactivityMin: 30, dismissDelayMin: 15, - minSteps: 50, + minSteps: 50 }, require("Storage").readJSON("activityreminder.json", true) || {}); -global.stepsArray = []; +var stepsArray = []; // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it +// todo put it in sequential to see if it work still + if (global.activityreminder) { activityreminder = @@ -23,14 +25,20 @@ if (global.activityreminder) { if(h >= activityreminder.startHour && h < activityreminder.endHour) { var health = Bangle.getHealthStatus("day"); - global.stepsArray.unshift(health.steps); - global.stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin); + stepsArray.unshift(health.steps); + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); + // todo save stepsArray } else{ - global.stepsArray = []; + if(stepsArray != []) + { + stepsArray = []; + // todo save stepsArray + } + } - if(global.stepsArray.length == activityreminder.maxInnactivityMin){ - if (global.stepsArray[0] - global.stepsArray[stepsArray.length-1] < activityreminder.minSteps) + if(stepsArray.length == activityreminder.maxInnactivityMin){ + if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) { load('activityreminder.app.js'); } @@ -38,6 +46,6 @@ if (global.activityreminder) { } }); - setInterval(global.activityreminder.run, 2000); + setInterval(global.activityreminder.run, 60000); } From 3ac987c1e2a5d612c02e1b3bf14d28761b126e3e Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Thu, 7 Apr 2022 12:56:53 -0700 Subject: [PATCH 128/312] use more efficient overpass query --- apps/golfview/custom.html | 79 ++++++++++++++++++--------------------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index 92b6c20ba..3b4485267 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -19,7 +19,7 @@ @@ -19,10 +37,15 @@ diff --git a/apps/golfview/screenshot.png b/apps/golfview/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..983b19ececf7104759f01563d5a87f440d73ecca GIT binary patch literal 3355 zcmV+$4dn8PP)Px>)k#D_RCr$Po!PddIt)Zl{{N$MS4haEiEWi84^aKs0a-3>3Soxxcs`%cKmMZv z6$KuDk8o|Ce{sk?2yl3PE)y^V-d&t1hzamzaEqNtCcKdl6X4joUnW`)fL~&HotOY$ z2D#XY5a3un8LhJdy#V&QFdeuv7^@6NfLEy$^DHVrfC%g5wx0KaZf=x=;@ zRwCE~lhwc$f&dez2^6ro?|VH#>%boOeT_&5o&cEHQXs&GiaZ|go~ZWB5c>PE$ktfL z82h*_c&yJk9b;Q#jD(s12LLPqRsush7_tFw<-8Ke1lS4i8HBy~wg2CTvj7|gR?T%a zIgNDP+SodnFW3W11uXrJ?sINUr2R?`90hO-K22UTLi{xdafyro{~`TjgxmFms^?g} z4uG;V6W}kvk~3PIdxQfc2V^hkGRFBAWF5fI$Me1N=J=Psj3!--?YW=(++F~ew3Eh` z^e)ZW8&evy`|q#Cr4xMb^(OgF+y?H}|M{~fzy%Gxu-yXS0;@+uEwvb5aKEm#5Wwi# zE!r=#h42?YB*MXPH-JwD{CGazZ(W>?Ilz6lV<`KjP6^2K??}(ci?|T<;(~nOECE~{ zY~+B9BS{;n(8y{-9Jb%0$t`e5@4F8>odcf% zZs{q(-MTsDl9BE^OkaOn~FG zTrd&}Fa|OKUJ!xxQ`SOUw@?DSJ`D@bzyfgDkzs%X+lXN;MC~F9S-L{jRz2|%3XvR; zICE@ch4|lQmH;2B*#a4XM_Oe-4wMpH>n)X`hlmAY0$jb*h622ujSAoBmhOyM0FJnY zjp8(BJ1xWnSOwp!sOXbkt=r0)Th1s*88OkZW4A*g{(Y8G^(;hCA3VGV*0|>p;Maau zNHbu|h#3o}CK>|q0bt9+JOucEfJ<$J6>d$L_id4$+!A-}J`%(qfQ82?n{x=bp)s8U zqfeqqZ*WLGaIJSnp+Q?2G~S%s)gb4o(C4^<%D=Rz_kgYtpx&VX$;Fn+%e8Q z0B+z{V4DDc^pf7*K%nor+;z|{9T;^&XE|SOOf3zqG1mU4^(q3xV{P8h|%55kC7Wl^;2%q!`Qm4!~=^h}%UlE~gFaftM-X z-4g}jCBSzFWybj{;3dE_7VyqFDdBYkZ0v>ELfjeB+T0EBUK(KOf(iZos5kmilZbU$ z%>|og+bNG7BfJC{_>9!K;72&6J9QS2HP1U-Vtv>FF9ALQdkc^OSAWb3&F6ujsg7sq%~TM#|=FtA4fY=!sH;q$7< zO@rD^h_j=$3Y!TL0mcrgp0|?suXlA>h0r>%w0%iV0*pb{+-igaE8X|}&Bv|)OA*>m{Jh{qu@>r zu+(?HfU4bzLxIOi@^Kd7gVoX+v}QF$lUL}rJ$vAa`)c8RyM9K+Ps&Q}*jfjcisZTQ zLoNzi+n{#>J4h_aB>z4bU<z>khne;@>MKgz}G0nPk065ZpVSv#hL>B-Z z*Icm1j^4R=a`%pH)*}+�$6M{KRJ=G=+#3UNg42Xq6qUbBWB^nuALV2gKitxDKs@ z*aKS%5iPhS2Uqb9J8S2XnX5Jzmj+1yN4E}5fUU)d7TTJJtAL-KHFL?%Q0>ijE2_!O^Xtm4v1I z_T7*?kyuC^RNLluR|B~8<^usP|KahoE*j{jf%qx_x88iXJHT16NpUp?gxQS~0gi4X zsx3rKsGjeBO;Jo^```g>_`FvJSQ4H9zlqL-EHgIb%E5vfrZ&HfK~Jgr%ug* zfXJh9B5B*#c#-)@<9Wu)jE(62?vdavzZ+^CII4{hpGG@RV>Sntik-PyB8_cS162v{dxmt5GkJ|}gZyP}e?$}CLVd@UA zcNJovXoog}0H3Jxz>?v_o_wqa%(kD`ffa3p$AvEgFj8m)FeFY53?#l5Do;MzvHsbf z0K4RSn*ex;swpxOQxk8WB@)-Fh$SEESl|6309Lp#Sn8i?E$_gV;!3b(#Pk4V$;UHZ zSPP*5*xE)c4X~%Mkq}F<+%N^-28Z(L?7)`<7!umJkpvxja7b}B6FU3_dr$w2#4*b8 zyIT~%$u2y#1BVr(5J&RBjPnFDVwyxGz$V$c?c@c; zyMJqGa<{2O@JEohIJMb>Vm7*;K$xJYgx9oS$8elIJ^Gnw9jrGjcfk>Y6p zkz$R^O)kB#1pv>_5}@?Ak`vm9eca{pPfg~zBG^Z7Eb7_(Vuo7a)yWsBwyTqvM ztbqk_I&Y4ee2!zyoSRvbNdT5ym;fItOn?t!5McS(*8-F2blO~guE3>poh(On3vX_w zp)&ziwh=8CUdDm5PTA3LL>^?(xv4-Vz_MK40(oHZjxEh@=G>&*x8Jh?R=RNQ1h=FE zdrsfk;I5Qg6XeMNuC)>Bbztb|BeVde*o?P zF##sP1X!m4w_aKSI`GovWAX%;3@ojH7U1MQc)A{V>EhlYc>;WgDqnbx1o*Ll(#G4vyA?^ZQ%2zU2+Z>sQ>|vRFko~D?os|OU?l!6(GQoYBE-L z1qg6=$vI%80t7fxO~&f300HhUIR}hXfB;9T$yh@akX|V|CdE5(LrTO!TM7_h^0Bl6 z1bFH4F?kKZFSU}|2tLe16m1F+V4H5-YZ3(r@Fay`8a4$8uuV7aHHiWQc#=Xe4Vwau zSBr`Pc@byRnR_KEK!B5kW!QcSXdtEo_p1v>0u>;@pitawP6Y_?oONMVpaKLK6pEY8 lsQ>| Date: Fri, 8 Apr 2022 17:36:13 -0700 Subject: [PATCH 157/312] clean up readme --- apps/golfview/README.md | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/apps/golfview/README.md b/apps/golfview/README.md index 99c977f80..7afd87206 100644 --- a/apps/golfview/README.md +++ b/apps/golfview/README.md @@ -6,24 +6,20 @@ This app leverages open source map data to give you a birds eye view of your gol ## Usage -Select your course of interest upon loading this app. +Swipe left and right to select your hole. Use the GPS assist app to get a faster GPS fix. ## Contributions -The performance of this app depends on the accuracy and consistency of user-submitted maps. -
- Example Course +The performance of this app depends on the accuracy and consistency of user-submitted maps. + +- See official mapping guidelines [here](https://wiki.openstreetmap.org/wiki/Tag:leisure%3Dgolf_course). +- All holes and features must be within the target course's area. +- Supported features are greens, fairways, tees, bunkers, water hazards and holes. +- All features for a given hole should have the "ref" tag with the hole number as value. Shared features should list ref values separated by ';'. [example](https://www.openstreetmap.org/way/36896320). +- here must be 18 holes and they must have the following tags: handicap, par, ref, dist. +- For any mapping assistance or issues, please file in the official repo. + +[Example Course](https://www.openstreetmap.org/way/25447898) ## Controls Swipe to change holes and tap to see a green closeup. From e3a56172774e6dd4b0d3058413adc3588449006c Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Fri, 8 Apr 2022 17:36:54 -0700 Subject: [PATCH 158/312] app name :P --- apps/golfview/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/README.md b/apps/golfview/README.md index 7afd87206..481a7a3c6 100644 --- a/apps/golfview/README.md +++ b/apps/golfview/README.md @@ -1,4 +1,4 @@ -# App Name +# Golf View This app leverages open source map data to give you a birds eye view of your golf game! See a preview of any hole as well as your realtime distance to the green and position on the hole. From 65679f0f3baf60d9bda32bc2a75808784db1a99c Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Fri, 8 Apr 2022 17:53:36 -0700 Subject: [PATCH 159/312] typo --- apps/golfview/golfview.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/golfview.js b/apps/golfview/golfview.js index ba4e3de49..62d6f4096 100644 --- a/apps/golfview/golfview.js +++ b/apps/golfview/golfview.js @@ -4,7 +4,7 @@ const EARTHRADIUS = 6371000; //km function radians(a) { return a * Math.PI / 180; } -position + function degrees(a) { let d = a * 180 / Math.PI; return (d + 360) % 360; From 06356f0304a56685f9e9c2f44b0ac886051712ce Mon Sep 17 00:00:00 2001 From: marko Date: Fri, 8 Apr 2022 20:58:40 -0400 Subject: [PATCH 160/312] Better support for themes. --- apps/2047pp/2047pp.app.js | 2 +- apps/openwind/app.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/2047pp/2047pp.app.js b/apps/2047pp/2047pp.app.js index 58738d04a..9163aaf3a 100644 --- a/apps/2047pp/2047pp.app.js +++ b/apps/2047pp/2047pp.app.js @@ -17,7 +17,7 @@ class TwoK { bh = Math.floor(h/4); bw = Math.floor(w/4); g.clearRect(0, 0, g.getWidth()-1, yo).setFontAlign(0, 0, 0); - g.setFont("Vector", 16).setColor("#fff").drawString("Score:"+this.score.toString(), g.getWidth()/2, 8); + g.setFont("Vector", 16).setColor(g.theme.fg).drawString("Score:"+this.score.toString(), g.getWidth()/2, 8); this.drawBRect(xo-3, yo-3, xo+w+2, yo+h+2, 4, "#a88", "#caa", false); for (y=0; y<4; ++y) for (x=0; x<4; ++x) { diff --git a/apps/openwind/app.js b/apps/openwind/app.js index 210b747d9..b1c8fea4b 100644 --- a/apps/openwind/app.js +++ b/apps/openwind/app.js @@ -48,7 +48,7 @@ function draw_compass(awa, aws, twa, tws) { g.clearRect(0, 24, g.getWidth()-1, g.getHeight()-1); fh = w*0.15; g.setColor(0, 0, 1).fillPoly(hullpoly); - g.setFontVector(fh).setColor(1, 1, 1); + g.setFontVector(fh).setColor(g.theme.fg); g.setFontAlign(0, 0, 0).drawString("0", cx, 24+fh/2); g.setFontAlign(0, 0, 1).drawString("90", g.getWidth()-12-fh, cy); g.setFontAlign(0, 0, 2).drawString("180", cx, g.getHeight()-fh/2); @@ -64,7 +64,7 @@ function draw_compass(awa, aws, twa, tws) { if (tws>0) g.setColor(1, 0, 0).drawString(tws.toFixed(1), cx, cy+0.32*w); if (settings.truewind && typeof gps_course.spd!=='undefined') { spd = gps_course.spd/1.852; - g.setColor(1, 1, 1).setFont("7x11Numeric7Seg", w*0.03).setFontAlign(-1, 1, 0).drawString(spd.toFixed(1), 1, g.getHeight()-1); + g.setColor(g.theme.fg).setFont("7x11Numeric7Seg", w*0.03).setFontAlign(-1, 1, 0).drawString(spd.toFixed(1), 1, g.getHeight()-1); } } From 8613b6662fb7f78d08f9c4347a5f86da218f1d17 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Fri, 8 Apr 2022 18:20:49 -0700 Subject: [PATCH 161/312] osm attribution --- apps/golfview/README.md | 6 +++++- apps/golfview/custom.html | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/golfview/README.md b/apps/golfview/README.md index 481a7a3c6..41aae02a0 100644 --- a/apps/golfview/README.md +++ b/apps/golfview/README.md @@ -26,4 +26,8 @@ Swipe to change holes and tap to see a green closeup. ## Requests/Creator -[Jason Dekarske](https://github.com/jdekarske) \ No newline at end of file +[Jason Dekarske](https://github.com/jdekarske) + +## Attribution + +[© OpenStreetMap contributors](https://www.openstreetmap.org/copyright) diff --git a/apps/golfview/custom.html b/apps/golfview/custom.html index d9b89f336..94bc551c0 100644 --- a/apps/golfview/custom.html +++ b/apps/golfview/custom.html @@ -30,6 +30,7 @@ repo Example Course + © OpenStreetMap contributors

From 0eb1c5fe0c9e60b3ddd47f5561a9b4865a9fb812 Mon Sep 17 00:00:00 2001 From: Jason Dekarske Date: Fri, 8 Apr 2022 18:25:15 -0700 Subject: [PATCH 162/312] fix description --- apps/golfview/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/golfview/metadata.json b/apps/golfview/metadata.json index be1a6d75a..961d24e4d 100644 --- a/apps/golfview/metadata.json +++ b/apps/golfview/metadata.json @@ -1,7 +1,7 @@ { "id": "golfview", "name": "Golf View", "version":"0.01", - "description": "This app will provide you with on course data to support your golf game! All information comes from OpenStreetMap. Please contribute by drawing your course using these guidelines: [guidelines](guidelines.com)", + "description": "This app will provide you with on course data to support your golf game!", "icon": "golfview.png", "tags": "outdoors, gps", "allow_emulator": true, From 83fbed1f59ba3f801bb5da3b1126d2145f80b163 Mon Sep 17 00:00:00 2001 From: marko Date: Fri, 8 Apr 2022 21:26:31 -0400 Subject: [PATCH 163/312] Bump version, add Changelog --- apps/2047pp/ChangeLog | 2 ++ apps/2047pp/metadata.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 apps/2047pp/ChangeLog diff --git a/apps/2047pp/ChangeLog b/apps/2047pp/ChangeLog new file mode 100644 index 000000000..a1f88e5ec --- /dev/null +++ b/apps/2047pp/ChangeLog @@ -0,0 +1,2 @@ +0.01: New app! +0.02: Better support for watch themes diff --git a/apps/2047pp/metadata.json b/apps/2047pp/metadata.json index f0fd6c1e3..033354ac6 100644 --- a/apps/2047pp/metadata.json +++ b/apps/2047pp/metadata.json @@ -2,7 +2,7 @@ "name": "2047pp", "shortName":"2047pp", "icon": "app.png", - "version":"0.01", + "version":"0.02", "description": "Bangle version of a tile shifting game", "supports" : ["BANGLEJS","BANGLEJS2"], "allow_emulator": true, From 614d73adda0a912f0d6e566c506e303bada82416 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Sat, 9 Apr 2022 11:22:51 +0200 Subject: [PATCH 164/312] sleepphasealarm - Read alarms from new scheduling library - account for higher acceleration sensor noise on Bangle.js 2 --- apps/sleepphasealarm/ChangeLog | 1 + apps/sleepphasealarm/app.js | 21 ++++++++++++++------- apps/sleepphasealarm/metadata.json | 2 +- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index dbc3a0b82..b07c5b9f7 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,3 +1,4 @@ 0.01: New App! 0.02: Respect Quiet Mode 0.03: Add compatibility for Bangle.js 2 and new firmware, added "Alarm at " for the alarm time +0.04: Read alarms from new scheduling library, account for higher acceleration sensor noise on Bangle.js 2 diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index e963f2c40..3f0f7d2b5 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -1,5 +1,5 @@ const BANGLEJS2 = process.env.HWVERSION == 2; //# check for bangle 2 -const alarms = require("Storage").readJSON("alarm.json",1)||[]; +const alarms = require("Storage").readJSON("sched.json",1)||[]; const active = alarms.filter(a=>a.on); // Sleep/Wake detection with Estimation of Stationary Sleep-segments (ESS): @@ -9,12 +9,12 @@ const active = alarms.filter(a=>a.on); // Function needs to be called for every measurement but returns a value at maximum once a second (see winwidth) // start of sleep marker is delayed by sleepthresh due to continous data reading const winwidth=13; -const nomothresh=0.006; +const nomothresh=0.03; // 0.006 was working on Bangle1, but Bangle2 has higher noise. const sleepthresh=600; var ess_values = []; var slsnds = 0; -function calc_ess(val) { - ess_values.push(val); +function calc_ess(acc_magn) { + ess_values.push(acc_magn); if (ess_values.length == winwidth) { // calculate standard deviation over ~1s @@ -38,13 +38,20 @@ function calc_ess(val) { } } +// copied from alarm app +// time in ms -> { hrs, mins } +function decodeTime(t) { + t = 0|t; // sanitise + var hrs = 0|(t/3600000); + return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) }; +} + // locate next alarm var nextAlarm; active.forEach(alarm => { const now = new Date(); - const alarmHour = alarm.hr/1; - const alarmMinute = Math.round((alarm.hr%1)*60); - var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), alarmHour, alarmMinute); + const t = decodeTime(alarm.t); + var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), t.hrs, t.mins); if (dateAlarm < now) { // dateAlarm in the past, add 24h dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); } diff --git a/apps/sleepphasealarm/metadata.json b/apps/sleepphasealarm/metadata.json index ed0f21028..bc75027c2 100644 --- a/apps/sleepphasealarm/metadata.json +++ b/apps/sleepphasealarm/metadata.json @@ -2,7 +2,7 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.03", + "version": "0.04", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", From c4b7c798d24f74cab1d935678b9a02938d2465fd Mon Sep 17 00:00:00 2001 From: storm64 Date: Sat, 9 Apr 2022 14:46:08 +0200 Subject: [PATCH 165/312] sched: Ensure dow wrap, Sa(6)+1 = Su(0) --- apps/sched/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 1189fa275..48094c86f 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -38,7 +38,7 @@ exports.getTimeToAlarm = function(alarm, time) { if (!alarm) return undefined; if (!time) time = new Date(); var currentTime = (time.getHours()*3600000)+(time.getMinutes()*60000)+(time.getSeconds()*1000); - var active = alarm.on && (alarm.dow>>(time.getDay()+(alarm.t>((time.getDay()+(alarm.t Date: Sat, 9 Apr 2022 14:49:52 +0200 Subject: [PATCH 166/312] Version 0.06 of BW Clock --- apps/bwclk/ChangeLog | 3 ++- apps/bwclk/README.md | 2 +- apps/bwclk/app.js | 4 ++-- apps/bwclk/metadata.json | 6 +++--- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 05a22774f..75f973f52 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -2,4 +2,5 @@ 0.02: Use build in function for steps and other improvements. 0.03: Adapt colors based on the theme of the user. 0.04: Steps can be hidden now such that the time is even larger. -0.05: Included icons for information. \ No newline at end of file +0.05: Included icons for information. +0.06: Design improvements. \ No newline at end of file diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index a5b66df71..45bed6216 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -1,4 +1,4 @@ -# Black & White clock +# BW Clock ![](screenshot.png) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index d4e6c50ab..5968d0d85 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -250,7 +250,7 @@ function draw() { g.fillRect(0,y,W,H); // Draw date - y -= settings.fullscreen ? 5 : 0; + y -= settings.fullscreen ? 10 : 0; var date = new Date(); g.setColor(g.theme.fg); g.setFontAlign(1,1); @@ -268,7 +268,7 @@ function draw() { g.setColor(g.theme.bg); g.setFontAlign(0,-1); var timeStr = locale.time(date,1); - y += settings.fullscreen ? 20 : 10; + y += settings.fullscreen ? 25 : 10; if(showInfo == 0){ y += 8; diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index babaa37bf..4e69a3b0d 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -1,8 +1,8 @@ { "id": "bwclk", - "name": "BlackWhite Clock", - "version": "0.05", - "description": "Black and white clock.", + "name": "BW Clock", + "version": "0.06", + "description": "BW Clock.", "readme": "README.md", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}], From e6f49639be2101a96d1806bf64abe160a52a370a Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sat, 9 Apr 2022 19:49:16 +0200 Subject: [PATCH 167/312] Update lib.js to not clear the trace of user input Change the way the display is updated as to keep user input trace intact until they lift their finger from the screen. Now only the marker is updated every second as opposed to the whole screen. To achieve this the marker is reimplemented outside the wrapString-method with g.fillRect() and g.clearRect() as well as a newly introduced function findMarker(). --- apps/kbswipe/lib.js | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/apps/kbswipe/lib.js b/apps/kbswipe/lib.js index 51f92f510..7837a6984 100644 --- a/apps/kbswipe/lib.js +++ b/apps/kbswipe/lib.js @@ -45,11 +45,39 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); var flashToggle = false; const R = Bangle.appRect; + var Rx1; + var Rx2; + var Ry1; + var Ry2; + + function findMarker(strArr) { + if (strArr.length == 0) { + Rx1 = 4; + Rx2 = 6*4; + Ry1 = 8*4; + Ry2 = 8*4 + 3; + } 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; + } 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; + } + //print(Rx1,Rx2,Ry1, Ry2); + return {x:Rx1,y:Ry1,x2:Rx2,y2:Ry2}; + } function draw(noclear) { g.reset(); - if (!noclear) g.clearRect(R); - var l = g.setFont("6x8:4").wrapString(text+(flashToggle?"_":" "), R.w-8); + var l = g.setFont("6x8:4").wrapString(text+' ', R.w-8); + if (!l) l = []; + //print(text+':'); + //print(l); + if (!noclear) (flashToggle?(g.fillRect(findMarker(l))):(g.clearRect(findMarker(l)))); if (l.length>4) l=l.slice(-4); g.drawString(l.join("\n"),R.x+4,R.y+4); } @@ -80,6 +108,7 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); var ch = o.stroke; if (ch=="\b") text = text.slice(0,-1); else text += ch; + g.clearRect(R); } flashToggle = true; draw(); @@ -87,7 +116,7 @@ exports.getStrokes( (id,s) => Bangle.strokes[id] = Unistroke.new(s) ); Bangle.on('stroke',strokeHandler); g.reset().clearRect(R); show(); - draw(true); + draw(false); var flashInterval; return new Promise((resolve,reject) => { From 0514c7dbd1245093a96880abd56090d26ff8af90 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sat, 9 Apr 2022 20:11:59 +0200 Subject: [PATCH 168/312] Added app name for Pushover --- apps/ios/boot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ios/boot.js b/apps/ios/boot.js index 50286c4a6..0659fd105 100644 --- a/apps/ios/boot.js +++ b/apps/ios/boot.js @@ -105,6 +105,7 @@ E.on('notify',msg=>{ "io.robbie.HomeAssistant": "Home Assistant", "net.weks.prowl": "Prowl", "net.whatsapp.WhatsApp": "WhatsApp", + "net.superblock.Pushover": "Pushover", "nl.ah.Appie": "Albert Heijn", "nl.postnl.TrackNTrace": "PostNL", "ph.telegra.Telegraph": "Telegram", From 1307ce9fc9fb2bc153be27be2ea06ec7cab6bd1a Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sun, 10 Apr 2022 12:00:52 +0200 Subject: [PATCH 169/312] Corrected translation for "timer" --- lang/nn_NO.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lang/nn_NO.json b/lang/nn_NO.json index 51d81c7a0..5da8ea851 100644 --- a/lang/nn_NO.json +++ b/lang/nn_NO.json @@ -32,7 +32,7 @@ "circle count": "antall sirklar", "minimum": "minimum", "maximum": "maksimum", - "New Timer": "Ny tidtaking", + "New Timer": "Ny nedteljing", "battery warn": "batteriåtvaring", "heartrate": "puls", "circle 2": "sirkel 2", @@ -48,7 +48,7 @@ "Are you sure": "Er du sikker", "Delete all messages": "Slett alle meldingar", "Record Run": "Rekordlaup", - "Unread timer": "Ulest tidtaking", + "Unread timer": "Ulest nedteljing", "Vibration": "Vibrering", "Utils": "Verkty", "Quiet Mode": "Stille modus", @@ -142,7 +142,7 @@ "Set Time": "Still tid", "Factory Reset": "Nullstill til fabrikkinnstillingar", "Messages": "Meldingar", - "Timer": "Timar", + "Timer": "Nedteljing", "BACK": "TILLBAKE", "Error in settings": "Feil i innstillingar", "Whitelist": "Tillatelsesliste", From aaefe390b0c9887ddabe6683b170e1bcfe85c8db Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sun, 10 Apr 2022 12:17:14 +0200 Subject: [PATCH 170/312] Added basic command-line parameter handling --- bin/language_scan.js | 69 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 64 insertions(+), 5 deletions(-) diff --git a/bin/language_scan.js b/bin/language_scan.js index 26ee77024..8e1fab381 100755 --- a/bin/language_scan.js +++ b/bin/language_scan.js @@ -1,13 +1,72 @@ -#!/usr/bin/nodejs +#!/usr/bin/env node /* Scans for strings that may be in English in each app, and outputs a list of strings that have been found. See https://github.com/espruino/BangleApps/issues/1311 - -If you want to auto-add new string (with *only english text*), set the -environment variable AUTOREFRESH. */ +let refresh = false; + +function handleCliParameters () +{ + let usage = "USAGE: language_scan.js [options]"; + let die = function (message) { + console.log(usage); + console.log(message); + process.exit(3); + }; + let hadTURL = false, + hadDEEPL = false; + for(let i = 2; i < process.argv.length; i++) + { + const param = process.argv[i]; + switch(param) + { + case '-r': + case '--refresh': + refresh = true; + break; + case '--deepl': + i++; + let KEY = process.argv[i]; + if(KEY === '' || KEY === null || KEY === undefined) + { + die('--deepl requires a parameter: the API key to use'); + } + process.env.DEEPL = KEY; + hadDEEPL = true; + break; + case '--turl': + i++; + let URL = process.argv[i]; + if(URL === '' || URL === null || URL === undefined) + { + die('--turl requires a parameter: the URL to use'); + } + process.env.TURL = URL; + hadTURL = true; + break; + case '-h': + case '--help': + console.log(usage+"\n"); + console.log("Parameters:"); + console.log(" -h, --help Output this help text and exit"); + console.log(" -r, --refresh Auto-add new strings into lang/*.json"); + console.log(' --deepl KEY Enable DEEPL as auto-translation engine and'); + console.log(' use KEY as its API key. You also need to provide --turl'); + console.log(' --turl URL In combination with --deepl, use URL as the API base URL'); + process.exit(0); + default: + die("Unknown parameter: "+param); + } + } + if((hadTURL !== false || hadDEEPL !== false) && hadTURL !== hadDEEPL) + { + die("Use of deepl requires both a --deepl API key and --turl URL"); + } +} +handleCliParameters(); + let translate = false; if (process.env.DEEPL) { // Requires translate @@ -237,7 +296,7 @@ for (let language of languages) { translations.GLOBAL[translationItem.str] = translation; resolve() })) - } else if(process.env.AUTOREFRESH && !translate) { + } else if(refresh && !translate) { translationPromises.push(new Promise(async (resolve) => { translations.GLOBAL[translationItem.str] = translationItem.str; resolve() From 8a86f2e9a24bf8fe14f4f506f0885996018d7d94 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 12:52:07 +0200 Subject: [PATCH 171/312] [dtlaunch, b2] Change swipe direction to UpDown Change swipe directions to move between pages from LeftRight to UpDown, as to match the page indicators. Implemented like 'natural scrolling'. Also added function showClock() which is called on 'left-to-right' swipe. Here I imagine the clock to be to the left of the launcher, if you do that then this also follows the natural scrolling principle. --- apps/dtlaunch/app-b2.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/apps/dtlaunch/app-b2.js b/apps/dtlaunch/app-b2.js index e0f7f825f..7202e4f33 100644 --- a/apps/dtlaunch/app-b2.js +++ b/apps/dtlaunch/app-b2.js @@ -85,18 +85,25 @@ function drawPage(p){ g.flip(); } -Bangle.on("swipe",(dir)=>{ +Bangle.on("swipe",(dirLeftRight, dirUpDown)=>{ selected = 0; oldselected=-1; - if (dir<0){ + if (dirUpDown==-1){ ++page; if (page>maxPage) page=0; drawPage(page); - } else { + } else if (dirUpDown==1){ --page; if (page<0) page=maxPage; drawPage(page); - } + } + if (dirLeftRight==1) showClock(); }); +function showClock(){ + var app = require("Storage").readJSON('setting.json', 1).clock; + if (app) load(app); + else E.showMessage("clock\nnot found"); +} + function isTouched(p,n){ if (n<0 || n>3) return false; var x1 = (n%2)*72+XOFF; var y1 = n>1?72+YOFF:YOFF; From f160a44c50a7eef177ef559b04fbe3ad28beb1b7 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 10 Apr 2022 13:54:51 +0200 Subject: [PATCH 172/312] Minor changes --- apps/bwclk/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 5968d0d85..9bb1ed4cd 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -250,7 +250,7 @@ function draw() { g.fillRect(0,y,W,H); // Draw date - y -= settings.fullscreen ? 10 : 0; + y -= settings.fullscreen ? 8 : 0; var date = new Date(); g.setColor(g.theme.fg); g.setFontAlign(1,1); @@ -268,7 +268,7 @@ function draw() { g.setColor(g.theme.bg); g.setFontAlign(0,-1); var timeStr = locale.time(date,1); - y += settings.fullscreen ? 25 : 10; + y += settings.fullscreen ? 23 : 10; if(showInfo == 0){ y += 8; From c10bd83c9ffc1d433a25c7d48d1b8a0f6c98e7cb Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sun, 10 Apr 2022 16:04:31 +0200 Subject: [PATCH 173/312] Autogenerate apps.json if needed --- bin/language_scan.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/bin/language_scan.js b/bin/language_scan.js index 8e1fab381..464d8f998 100755 --- a/bin/language_scan.js +++ b/bin/language_scan.js @@ -5,6 +5,8 @@ outputs a list of strings that have been found. See https://github.com/espruino/BangleApps/issues/1311 */ +var childProcess = require('child_process'); + let refresh = false; function handleCliParameters () @@ -126,6 +128,14 @@ try { } catch (e) { ERROR("apps.json not found"); } +if (appsFile.indexOf("---") === 0 && fs.existsSync(BASEDIR+"bin/create_apps_json.sh")) +{ + console.log("apps.json has not been generated, running bin/create_apps_json.sh to build it..."); + childProcess.execFileSync(BASEDIR+'bin/create_apps_json.sh',[],{ + stdio: 'inherit' + }); + appsFile = fs.readFileSync(BASEDIR+"apps.json").toString(); +} try{ apps = JSON.parse(appsFile); } catch (e) { From e94ff288d05e60d3f12d3abb165982e8ef648a64 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sun, 10 Apr 2022 16:18:58 +0200 Subject: [PATCH 174/312] lang/nn: additional translations --- lang/nn_NO.json | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lang/nn_NO.json b/lang/nn_NO.json index 5da8ea851..176d82b48 100644 --- a/lang/nn_NO.json +++ b/lang/nn_NO.json @@ -52,7 +52,7 @@ "Vibration": "Vibrering", "Utils": "Verkty", "Quiet Mode": "Stille modus", - "Passkey BETA": "Passkey BETA", + "Passkey BETA": "Passord BETA", "Dark BW": "Mørk BW", "BTNs 1:startlap 2:exit 3:reset": "BTN 1:start 2:avslutt 3:nullstill", "start&lap/reset, BTN1: EXIT": "start&runde/nullstill, BTN1: AVSLUTT", @@ -62,7 +62,7 @@ "Vector font size": "Storleik for vektorskrifttype", "Font": "Skrifttype", "Yes\ndefinitely": "Ja\ndefinitivt", - "App Source\nNot found": "App-kilde\nikkje funnet", + "App Source\nNot found": "App-kjelde\nikkje funnet", "Make Connectable": "Gjer mogleg å kople til", "HID": "HID", "Bluetooth": "Bluetooth", @@ -78,21 +78,21 @@ "Highlight FG": "Marker FG", "Background 2": "Bakgrunn 2", "LCD Brightness": "Lyusstyrke på LCD-skjermen", - "Add Device": "Legg till enhet", + "Add Device": "Legg til eining", "Wake on BTN1": "Vakne ved KNAPP1", "Wake on BTN2": "Vakne ved KNAPP2", "Twist Timeout": "Tidsavbrot for vridning", "Wake on Touch": "Vakne ved berøring", "LCD Timeout": "LCD tidsavbrot", "Foreground": "Forgrunn", - "Connect device\nto add to\nwhitelist": "Kople til eining\nfor å leggje til\ntillatelsesliste", + "Connect device\nto add to\nwhitelist": "Kople til eining\nfor å leggje til\ni lista", "Wake on FaceUp": "Vakne på FaceUp", "Twist Threshold": "Terskel for vridning", "Wake on BTN3": "Vakne på BTN3", "Clock Style": "Klokkestil", "Time Zone": "Tidssone", "Twist Max Y": "Vridning Max Y", - "Stay Connectable": "Behald høve til tilkopling", + "Stay Connectable": "Opne for tilkopling", "This will remove everything": "Dette vil fjerne alt", "Turn Off": "Slå av", "Connectable": "Kan koplast til", @@ -201,7 +201,7 @@ "Delete Track": "Slett spor", "Drawing": "Teikning", "Altitude (m)": "Høgd (m)", - "Speed (m/s)": "Hastighet (m/s)", + "Speed (m/s)": "Hastigheit (m/s)", "Notifications": "Varsel", "Snooze": "Slumre", "settings": "innstillingar", @@ -226,6 +226,19 @@ "green": "grøn", "blue": "blå", "Track": "Spor", - "none": "inga" + "none": "inga", + "Plot Map": "Plott Kart", + "Plot OpenStMap": "Plott OpenStMap", + "Plot Alt": "Plott Høgde", + "Plot Speed": "Plott Hastigheit", + "Dist Pattern": "Avstandsmønster", + "Step Pattern": "Stegmønster", + "Time Pattern": "Tidsmønster", + "Boxes": "Bokstar", + "Start wday": "Start vdag", + "Su color": "Su farge", + "filled": "fylt", + "Mrk.Color": "Mrk.Farge", + "Mrk.Size": "Mrk.Storleik" } } From 44810118b472e336cd308e25e33e196a597af3b7 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 10 Apr 2022 16:41:19 +0200 Subject: [PATCH 175/312] buzz_menu: fix duplicate "Off" option --- modules/buzz_menu.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/buzz_menu.js b/modules/buzz_menu.js index 64b225343..0b399355c 100644 --- a/modules/buzz_menu.js +++ b/modules/buzz_menu.js @@ -4,7 +4,7 @@ exports.pattern = function(value, callback) { var vibPatterns = ["", ".", "..", "-", "--", "-.-", "---"]; return { value: Math.max(0,vibPatterns.indexOf(value)), - min: 0, max: vibPatterns.length, + min: 0, max: vibPatterns.length-1, format: v => vibPatterns[v]||/*LANG*/"Off", onchange: v => { callback(vibPatterns[v]); From 0b9d8b16a664072b442ac62ff1338e74335d5f18 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Sun, 10 Apr 2022 17:01:28 +0200 Subject: [PATCH 176/312] buzz_menu: give a demonstration after selecting a pattern --- modules/buzz_menu.js | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/buzz_menu.js b/modules/buzz_menu.js index 64b225343..b821d5021 100644 --- a/modules/buzz_menu.js +++ b/modules/buzz_menu.js @@ -7,6 +7,7 @@ exports.pattern = function(value, callback) { min: 0, max: vibPatterns.length, format: v => vibPatterns[v]||/*LANG*/"Off", onchange: v => { + require("buzz").pattern(vibPatterns[v]); callback(vibPatterns[v]); } }; From 78e135b80d236f0c7277361ac733ad647d03a099 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Sun, 10 Apr 2022 21:35:46 +0200 Subject: [PATCH 177/312] Tagging bootloader messages, and all "Loading..." messages --- apps/accellog/app.js | 2 +- apps/boot/bootupdate.js | 4 ++-- apps/dane_tcr/app.js | 2 +- apps/gpsinfo/gps-info.js | 2 +- apps/gpsrec/app.js | 2 +- apps/gpstime/gpstime.js | 2 +- apps/health/app.js | 12 ++++++------ apps/ltherm/app.js | 2 +- apps/thermomF/app.js | 2 +- apps/toucher/app.js | 2 +- apps/viewstl/viewstl.app.js | 2 +- apps/viewstl/viewstl.min.js | 2 +- 12 files changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/accellog/app.js b/apps/accellog/app.js index c54c5002b..4bead361e 100644 --- a/apps/accellog/app.js +++ b/apps/accellog/app.js @@ -29,7 +29,7 @@ function showMenu() { } function viewLog(n) { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var f = require("Storage").open(getFileName(n), "r"); var records = 0, l = "", ll=""; while ((l=f.readLine())!==undefined) {records++;ll=l;} diff --git a/apps/boot/bootupdate.js b/apps/boot/bootupdate.js index 46391d874..119cd2c2c 100644 --- a/apps/boot/bootupdate.js +++ b/apps/boot/bootupdate.js @@ -1,7 +1,7 @@ /* This rewrites boot0.js based on current settings. If settings changed then it recalculates, but this avoids us doing a whole bunch of reconfiguration most of the time. */ -E.showMessage("Updating boot0..."); +E.showMessage(/*LANG*/"Updating boot0..."); var s = require('Storage').readJSON('setting.json',1)||{}; var BANGLEJS2 = process.env.HWVERSION==2; // Is Bangle.js 2 var boot = "", bootPost = ""; @@ -209,7 +209,7 @@ delete bootPost; delete bootFiles; delete fileSize; delete fileOffset; -E.showMessage("Reloading..."); +E.showMessage(/*LANG*/"Reloading..."); eval(require('Storage').read('.boot0')); // .bootcde should be run automatically after if required, since // we normally get called automatically from '.boot0' diff --git a/apps/dane_tcr/app.js b/apps/dane_tcr/app.js index aa25379d3..ce75c55cb 100644 --- a/apps/dane_tcr/app.js +++ b/apps/dane_tcr/app.js @@ -244,7 +244,7 @@ function run(){ Bangle.setLCDMode(); g.clear(); g.flip(); - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); load(app.src); } diff --git a/apps/gpsinfo/gps-info.js b/apps/gpsinfo/gps-info.js index 0eca2ccf5..a6e21af0d 100644 --- a/apps/gpsinfo/gps-info.js +++ b/apps/gpsinfo/gps-info.js @@ -5,7 +5,7 @@ function satelliteImage() { var Layout = require("Layout"); var layout; //Bangle.setGPSPower(1, "app"); -E.showMessage("Loading..."); // avoid showing rubbish on screen +E.showMessage(/*LANG*/"Loading..."); // avoid showing rubbish on screen var lastFix = { fix: -1, diff --git a/apps/gpsrec/app.js b/apps/gpsrec/app.js index 527eb780d..4595f616d 100644 --- a/apps/gpsrec/app.js +++ b/apps/gpsrec/app.js @@ -126,7 +126,7 @@ function asTime(v){ function viewTrack(n, info) { if (!info) { - E.showMessage("Loading...","GPS Track "+n); + E.showMessage(/*LANG*/"Loading...","GPS Track "+n); info = getTrackInfo(n); } const menu = { diff --git a/apps/gpstime/gpstime.js b/apps/gpstime/gpstime.js index 8c80953fa..6a01821ba 100644 --- a/apps/gpstime/gpstime.js +++ b/apps/gpstime/gpstime.js @@ -10,7 +10,7 @@ var Layout = require("Layout"); Bangle.setGPSPower(1, "app"); Bangle.loadWidgets(); Bangle.drawWidgets(); -E.showMessage("Loading..."); // avoid showing rubbish on screen +E.showMessage(/*LANG*/"Loading..."); // avoid showing rubbish on screen function setGPSTime() { if (fix.time!==undefined) { diff --git a/apps/health/app.js b/apps/health/app.js index 7a55eec27..64640603e 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -70,7 +70,7 @@ function menuHRM() { function stepsPerHour() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(24); require("health").readDay(new Date(), h=>data[h.hr]+=h.steps); g.clear(1); @@ -81,7 +81,7 @@ function stepsPerHour() { } function stepsPerDay() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(31); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.steps); g.clear(1); @@ -92,7 +92,7 @@ function stepsPerDay() { } function hrmPerHour() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(24); var cnt = new Uint8Array(23); require("health").readDay(new Date(), h=>{ @@ -108,7 +108,7 @@ function hrmPerHour() { } function hrmPerDay() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(31); var cnt = new Uint8Array(31); require("health").readDailySummaries(new Date(), h=>{ @@ -124,7 +124,7 @@ function hrmPerDay() { } function movementPerHour() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(24); require("health").readDay(new Date(), h=>data[h.hr]+=h.movement); g.clear(1); @@ -135,7 +135,7 @@ function movementPerHour() { } function movementPerDay() { - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); var data = new Uint16Array(31); require("health").readDailySummaries(new Date(), h=>data[h.day]+=h.movement); g.clear(1); diff --git a/apps/ltherm/app.js b/apps/ltherm/app.js index 7accae2ed..2cbf26e5f 100644 --- a/apps/ltherm/app.js +++ b/apps/ltherm/app.js @@ -20,6 +20,6 @@ const avg = []; setInterval(function() { drawTemperature(); }, 2000); -E.showMessage("Loading..."); +E.showMessage(/*LANG*/"Loading..."); Bangle.loadWidgets(); Bangle.drawWidgets(); diff --git a/apps/thermomF/app.js b/apps/thermomF/app.js index 2961e1efc..ac754d448 100644 --- a/apps/thermomF/app.js +++ b/apps/thermomF/app.js @@ -23,6 +23,6 @@ setInterval(function() { drawTemperature(); }, 20000); drawTemperature(); -E.showMessage("Loading..."); +E.showMessage(/*LANG*/"Loading..."); Bangle.loadWidgets(); Bangle.drawWidgets(); \ No newline at end of file diff --git a/apps/toucher/app.js b/apps/toucher/app.js index aab50fbda..19310592e 100644 --- a/apps/toucher/app.js +++ b/apps/toucher/app.js @@ -255,7 +255,7 @@ function run(){ if (process.env.HWVERSION == 1) Bangle.setLCDMode(); g.clear(); g.flip(); - E.showMessage("Loading..."); + E.showMessage(/*LANG*/"Loading..."); load(app.src); } diff --git a/apps/viewstl/viewstl.app.js b/apps/viewstl/viewstl.app.js index 0b2512176..34d018705 100644 --- a/apps/viewstl/viewstl.app.js +++ b/apps/viewstl/viewstl.app.js @@ -354,7 +354,7 @@ function loadFile(fn) { Bangle.setLCDMode("direct"); g.clear(); E.showMenu(); - E.showMessage("Loading...", fn); + E.showMessage(/*LANG*/"Loading...", fn); readSTL(fn); zDist = 5*largestExtent(points); g.clear(); diff --git a/apps/viewstl/viewstl.min.js b/apps/viewstl/viewstl.min.js index 77469042c..82975bbf9 100644 --- a/apps/viewstl/viewstl.min.js +++ b/apps/viewstl/viewstl.min.js @@ -216,7 +216,7 @@ function loadFile(fn) { Bangle.setLCDMode("direct"); g.clear(); E.showMenu(); - E.showMessage("Loading...", fn); + E.showMessage(/*LANG*/"Loading...", fn); readSTL(fn); zDist = 5*largestExtent(points); g.clear(); From d1bd45f30023e4a3151ad557cdaf136a937cc753 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:35:51 +0200 Subject: [PATCH 178/312] Update metadata.json --- apps/kbswipe/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/kbswipe/metadata.json b/apps/kbswipe/metadata.json index 635841e62..f1e7cf7d6 100644 --- a/apps/kbswipe/metadata.json +++ b/apps/kbswipe/metadata.json @@ -1,6 +1,6 @@ { "id": "kbswipe", "name": "Swipe keyboard", - "version":"0.01", + "version":"0.02", "description": "A library for text input via PalmOS style swipe gestures (beta!)", "icon": "app.png", "type":"textinput", From 0a2605f9c19d18c3fcb1251f96077d5a3fec1aa8 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:37:41 +0200 Subject: [PATCH 179/312] Update ChangeLog --- apps/kbswipe/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/kbswipe/ChangeLog b/apps/kbswipe/ChangeLog index 5560f00bc..87fb43d3d 100644 --- a/apps/kbswipe/ChangeLog +++ b/apps/kbswipe/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Now keeps user input trace intact by changing how the screen is updated. From d801605eaa572d11780fc1cc96d8faf070aac378 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:43:54 +0200 Subject: [PATCH 180/312] Update ChangeLog --- apps/dtlaunch/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index da07af798..f0ea9dbd7 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -9,3 +9,4 @@ 0.09: fix the trasparent widget bar if there are no widgets for Bangle 2 0.10: added "one click exit" setting for Bangle 2 0.11: Fix bangle.js 1 white icons not displaying +0.12: Change to swiping up/down to move between pages. Swiping left-to-right now loads the clock. From 8cfd1ec887eae4913b282819d7a28e102d5b1a16 Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:45:59 +0200 Subject: [PATCH 181/312] Update ChangeLog --- apps/dtlaunch/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index f0ea9dbd7..cd69dbf6e 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -9,4 +9,4 @@ 0.09: fix the trasparent widget bar if there are no widgets for Bangle 2 0.10: added "one click exit" setting for Bangle 2 0.11: Fix bangle.js 1 white icons not displaying -0.12: Change to swiping up/down to move between pages. Swiping left-to-right now loads the clock. +0.12: Change to swiping up/down to move between pages to match page indicator. Swiping from left to right now loads the clock. From 772ab88a0e961dfb3f543f120237595c594bda8d Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:46:43 +0200 Subject: [PATCH 182/312] Update ChangeLog --- apps/dtlaunch/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index cd69dbf6e..1b7fe0539 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -9,4 +9,4 @@ 0.09: fix the trasparent widget bar if there are no widgets for Bangle 2 0.10: added "one click exit" setting for Bangle 2 0.11: Fix bangle.js 1 white icons not displaying -0.12: Change to swiping up/down to move between pages to match page indicator. Swiping from left to right now loads the clock. +0.12: Change to swiping up/down to move between pages as to match page indicator. Swiping from left to right now loads the clock. From 33baed5d2b4af927f02d0d9cfef6f7b3197e27eb Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:48:13 +0200 Subject: [PATCH 183/312] Update ChangeLog --- apps/dtlaunch/ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/ChangeLog b/apps/dtlaunch/ChangeLog index 1b7fe0539..66fda2f29 100644 --- a/apps/dtlaunch/ChangeLog +++ b/apps/dtlaunch/ChangeLog @@ -9,4 +9,4 @@ 0.09: fix the trasparent widget bar if there are no widgets for Bangle 2 0.10: added "one click exit" setting for Bangle 2 0.11: Fix bangle.js 1 white icons not displaying -0.12: Change to swiping up/down to move between pages as to match page indicator. Swiping from left to right now loads the clock. +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. From 78a1c14564431ae8a5d63ae95a69851987b38d9a Mon Sep 17 00:00:00 2001 From: thyttan <97237430+thyttan@users.noreply.github.com> Date: Sun, 10 Apr 2022 22:48:50 +0200 Subject: [PATCH 184/312] Update metadata.json --- apps/dtlaunch/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dtlaunch/metadata.json b/apps/dtlaunch/metadata.json index b3f94442f..a5391cef0 100644 --- a/apps/dtlaunch/metadata.json +++ b/apps/dtlaunch/metadata.json @@ -1,7 +1,7 @@ { "id": "dtlaunch", "name": "Desktop Launcher", - "version": "0.11", + "version": "0.12", "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", From eee8e231db69611672c1fb60776a2538119ff72b Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Mon, 11 Apr 2022 12:58:09 +0200 Subject: [PATCH 185/312] apps/locale: nn_NO: mkh->kmt --- apps/locale/locales.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/locale/locales.js b/apps/locale/locales.js index 06e959954..7a2665170 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -662,7 +662,7 @@ var locales = { thousands_sep: " ", currency_symbol: "kr", int_curr_symbol: "NOK", - speed: "kmh", + speed: "kmt", distance: { 0: "m", 1: "km" }, temperature: "°C", ampm: { 0: "", 1: "" }, From 94c62ae74cd4f930c194eded9d3836211c828229 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:10:53 -0700 Subject: [PATCH 186/312] Update metadata.json --- apps/mtgwatchface/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mtgwatchface/metadata.json b/apps/mtgwatchface/metadata.json index fd81ce10f..ac5fe9287 100644 --- a/apps/mtgwatchface/metadata.json +++ b/apps/mtgwatchface/metadata.json @@ -2,7 +2,7 @@ "id": "mtgwatchface", "name": "MTG Watchface", "shortName": "Magic the Gathering Watch Face", - "version": "1v03", + "version": "0.02", "description": "Magic the Gathering themed watch face. Embrace the inner wizzard. Dispay any of the different types of mana on your watch. Which color are you devoted to today? ", "icon": "icon.png", "screenshots": [ From b3b4c4b1dfeb4fa917d82085bc37a1fd8af7fbbd Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:11:21 -0700 Subject: [PATCH 187/312] Create ChangeLog --- apps/mtgwatchface/ChangeLog | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/mtgwatchface/ChangeLog diff --git a/apps/mtgwatchface/ChangeLog b/apps/mtgwatchface/ChangeLog new file mode 100644 index 000000000..32a3cd454 --- /dev/null +++ b/apps/mtgwatchface/ChangeLog @@ -0,0 +1,2 @@ +0.01: New App! +0.02: Support Dark Theme. From 9ef1c15372b299b7e2d1da83593169c7e7ced852 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:24:27 -0700 Subject: [PATCH 188/312] Update app.js --- apps/mtgwatchface/app.js | 46 +++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/apps/mtgwatchface/app.js b/apps/mtgwatchface/app.js index d54247033..55fb98e78 100644 --- a/apps/mtgwatchface/app.js +++ b/apps/mtgwatchface/app.js @@ -1,35 +1,41 @@ +//g.setTheme({fg : 0xFFFF,bg : 0,fg2 : 0xFFFF,bg2 : 0x0007,fgH : 0xFFFF,bgH : 0x02F7,dark : true}); var blueImg = { width : 93, height : 145, bpp : 2, transparent : 1, palette : new Uint16Array([31,65535,65535,59167]), buffer : require("heatshrink").decompress(atob("qoAlgoWVgIWVKqwWXioWVOasAOarJWgEMLikAhZcUgEK4IWToEK2AWV1hcToEO1ZcTCwOqLiYWCLiYWCLiZbCLiYWClRcSCwS5TCwUCLiQWCgBcSCwZcSqECCwJcSCwZcSCwZcSCwOqCwJcRqEDCwRcRCwhcRCwXALiVUCwhcQCwpcQqkACwZcQCwpcQCwPqwAWCLh4WGLiAWFLiAWB2AWCLiBWBCwhcPCwxcPgE60AWDLh9ACwpcBgIWO1gWElWACxsKCwsO0BFMoEOCwsD1CiMqEO1AWEX4JcMCxE6LhlQgWrCwpcNqkDCwxcNCwOqCwpcNCxM6f5dUgGq4AWFf5o8BCwz/NCwOACwz/MBoOwCwyiMoBqBCwyiBIpQWB0AWGG4PACxUKCxAJBaJNQh2sCw7wBIpIWB1AWHRYR0IqkC1YWIHAIuIfoIWJeIMAFw79CCxKVBFxAWBfo50DFxD9BCxLyCUY9AP4IWJP4T9QAAfqFw9QcxKjDFw7mKFxbPBcxIuKZ5guKCx0OHgK4GCxgOBwDSEoDPLAAUK1kBXArPKAAeq4AuDXALPLAAU6Fwi4OAAMD1R0DXBwuDUYa4PAAMCaQhjBCx0AlQuDUJ7SDOgShQaQSjCUKDSDIoNUUJ8CUYiKBUJ+gUYRFBgChPlYwBOgSKQFYJ0COYKKPUAJ0B0EFRQJMBABhxB4D6BgNUgSKOIQInBlWAipzQnQQBhxFBOYLOP1RtBIoJzQgWqIocQOZ8A1SLBIoMEOaL9BIoRzQlWqaIMq4FAAQJzPH4JZChQcBc5pcCgYCBLh4WBLgS2CLhyhBXIS2CLh86OYSiBLiEDaARcSgEPCARcCMQQAQLgQCCACD/CL4QAQLgMBL4QARLgL/QLgsQUR5cGgRFSCYMBUoYAQ1cAqE6IqRwBqjoQOYewipFTOYMFIqZBBgJFBRaMDOYNVIoLRR1QWBqDRSFIMVqkDIqPqwEVIqcq2EFIoMOXSCdBCwNUMIQWP0EBqtVoC6QnS4BCwNQgSnBCx6hBAAJ5CCyZ0BUZwWFOgIuOlQWEOgMKFxvqCwqjCFxnq0AWEOgMKRhcD1SxBCwlQFwK7KhwWHFwIKB4CIJBYQWFFwPqIxPqCxAuDPwJDHEIL8CFww6B3hwFFgIgBCw67BHYWvCof61RxCgoWHXYKXBAAO//4ECMoUVCw4uCh4SCAAarCCxJ1BC4xKCLRBGEAAJDC/4GCLRCNFAA4VLC5IsMC5BZLO5AVLoAA==")) -} +}; var redImg = { width : 130, height : 144, bpp : 1, transparent : 1, palette : new Uint16Array([63488,65535]), buffer : require("heatshrink").decompress(atob("/4AD8EAh4HEAA38C4UHB5QeBAAQhKwA5Ev4PI/APEgYxK+AQDj5SOgJjLEIYgH/hbDKgQgHJ4JbCKgYgGBQKNDIJIaCII0/Lg4pC/y1IBISMD4CkIc4owDYoprCHIQPDKIopCDAS0EKIjwCIAT2EKIhwCFAQlCCQRwGB4JlCAgJ5C/ZwEBQIkCGgIgBgf+OYRgBF4QEBB4IZCv/PHQZPCYwgJBh/zLQZ4DwAPCCgMBGATRF/ydDGAWPMAbqFGAnhCoXAZIowE/gLBwHweITsHv43B8F8bIowF4LLBv+HaAQcBOwTWBgP4v/8n/jFQUHFgLfBLYV+FgM//AqDK4KCCfgWDDgRgC/EPBYP+VgY+BBgPfRgYLBn+fIAMALo4OBFYPjIAUPK4SMFFYJcBAgXgTwwKBIAMPEoV4TwzoBIAODIAUeGBMPVYIEBg+AVowKC/EOGoTPHGAMB/8BwAPBniYCAAZsCOoY1BCwIAFDYLRCAAIjBZIJRGv7VBAAVgUQxRBUwkAjBxGAAYwDgwnBB5AwEwBxGKgoACOIwwHRAQAIQoQACOIwwIOI7XFAAJxKa4QACB5RREIBQgEOJTUFB5RiEWRJiFWRP9cohAJ/gqBUgRAJ/0f+LlDIBH+g/4v5RCIBH+gP4n/gIBcAv0PMIRAJFQMDeoZAIFQPAWYbCIFQPwv6BCh57DAgYKBvEfKAUDBQQWBMwQKBjxyBGATJFv6MCg+BSIZACbIYaCgfgv7SFB4YAD/EfaQoPHn0H+CRECoQAEj+BKAoPHSIN+KAh2CAAkD+EfKAg1CAAv8g5KCKAI1DAAl/gKhEa4ZQF4EgKAaWDAAkPHIjyBB48HFIhQBSA6LBEoiAIHQIJDMAJwIv4JDEoJwIn5AEMBJKBMBpKFYIJgHB4JADAoLRHLQJADYJIJBHQbBJBII6DOAJQHB4Q6DAoKhGDIQ6DOAJQHB4I6DOAPIWA46ESwPGUBBQDQAPhSIxwCJQQFB8FAMBChCAoPwmBQIMARmB+EMIBBgDCgMDYJl//EBSJH+EoY0BuAgGn4PDh4PBnjCHB4cHB4MPB40AgQUDB4MHIAwAFQgMBQ4QAMM4YALn4POj/gB5pzCABh4EABSpBwAQN/5AOagJwO/4PPWRiAB/6yNB4JxNB4JxNv4PBOJaPBAALjLh4PCOJQOEOJQ9CAASiIHoYwLgYPGMI4PHGA4PHGA4/HGBBfFSRJ/FAATDHB470HII70Kn6zOB4qzIgEfWZoPHQQ4vGKJKTHEA6CHEAzTIEAxOGMQ7iIaosHBhA")) -} +}; var greenImg = { width : 142, height : 145, bpp : 1, transparent : 1, palette : new Uint16Array([2016,65535]), buffer : require("heatshrink").decompress(atob("/4AF/kAv4JGAA4aBn4QN+ARQHwQRNEQRHOwARPNAJ0JAAvgCAUBK58AgYQL/ARDg4RL4ARDgkAh40NEpg0EAAQjJGggRMCA0Aj6/Gg40HbA3+Q4KeDAAjGFBwMDaYYAEIZrGIIZCOIPA58JCBRqFGhZqFGhZqFCBcDCAf8CJZYEVpDVIVpBYHaYJYP+ARMEYZ7MEYgQMCIZ7MfIhGNfIZGNUAaNMfIaNNLAf4LCDUMLAhGQRppGDGhsDGiCNCPZ0fPZ4RDYRpqDCBsAv40PPgQQOYYIiGh6OJRgyCC+DVFYI0DFQMDCIsfAwoZBZIMPBQs/Gg0PSgM/bwrBHnx1CDgkBGg0AvBGBDgsHYI0BIwSGFj7OKIwosBAAccXghjFC4kHF4cDTAsDC4iTERo0OfwpeDTA04dgoMDZoxGERAkDNIpGFgJYDh7MGRpMwAwt8CJJXFahAAIg5NFABUfFQoAK/4QPQ4gAMZIwAFXok/ZwcAhAvFDol+BYl4MgodECwl/AokDdgkBCwYKBDgl/MgkGUgn/UocB/4pEKQgRBfAYpBZBQjEg46ECI7JPh63RIwbJZVZQRMLBMQAws+Aws/DAVgBQrnGSoUDFo1ASgrdChxMLCAKnCvhdLCIQnBQwcPCAr4BAAK5Bv7fDv6LFh4RC/4nBBgQbBCIoQDG4YbDCIhoCAAbxDv4RFK4YAC/gJBgZyDGhJqCDYQQDDAQRHHQppFAAR8BBIX4cYgRG4CWDUoZGHEYJoBFAZ7IAAxqDPYylJSgQAKSYTlEABJYDIxpYDPY5YJCBixDYQ4AFWIbCHI35G/I0oQCgF/Gh8BERnALBxoDAAMHEJxqMIgY1NVwYRMEQw2KEQyQJ/gQICI6/DAAyLLAAi0GK5CiI+ARJfY3we4oACj7VOERB+KYhPwgcAhDWN4EcgF4fRuA/EDOAP8RgxYEg/gj/gGRRYCj/Av4TBCJaQBEAITBCJfn/xTB4IQLGwQgMAAf5DRAA=")) -} +}; var whiteImg = { width : 153, height : 145, bpp : 2, transparent : 0, palette : new Uint16Array([65535,65535,65504,65505]), buffer : require("heatshrink").decompress(atob("ACWqAAOgEsmoEkECEs3///qEsEK1XVqt6wAlg1dV/taEsEq1dX1VeckEq1te2+XX0AlC6v11Qlg2t66tttQlf1W1vdVvLkgEodfrS+fEoPtqtW6wlgyolBqrkY1WqRYolE8vqErD+FlQlDcgK+WlQlBMwglErbkXhW//xzElS9Cqtery+WgWlqt6DQcKEodX6y+X1IbBTIcK0olCqu19RXDgWqKSGqrWtJgcK1ttEoV7rxMCEgIACUB0q63e64aD1t5EoVXJgL2EEyCQByvltQSC1d7EoVVvNa0BKD/4mPIgPlr7aD1VfEodXK4Mq1Wv6oIBfILIN1N9WgK/CPIIbCAANtvRFB+oIDrzCN1Vbqt9vReBhW3yocEDoOvqtf9Wq/tVvxMMIgVW6wRBPIQlDqv19Wtq/q3///QrB9SZLXwQaCM4J5CX4l61Ne3oHCr+trxMLIgdbrTUCryYEK4IIGr+19S+MvLaCEoW19pME8vqywlEqt7rRyLXwQaB9////rIYpXB2u1EolXyxyLXwReBbwZMFq/W1tlEohVCXx1Xytf//VJg3l9aCBAAlZvRyKXwdVt6XB1dW2ttDgteEotWr2gXxpuB/pPB2pMBcouXXwt/y6YL1SVDagde257BAAS9BXwlX9WlTBa+DCwm18p7CAAN9tq+Er29qqYLXwL6Fqt5rt9DwlZXwl6HYKYLXwL6Gq/VvYGEy6CE9YnB1SYL1b6GqttrYGE8tWQQetq73B1SYLfQxhBJYjGBq7FDvNeEoSYLfQxlDOQmqVAdW62qSxSYC0v1EoyQEEwQPE2pvLAAWpbYgAEvxlB36lH9QlNTBBsCAAWvBYtbvSVKTAe3Vwa/EEoeq1oLEq1eS5iYB1tlEo161W9J4P6XogHBy+oORurrYlG9WrAof6AolV+q+OlWW6olGJQIGEOYlttQlNgWlfYi8CNYgHCGod5P4OqYBmpvIdKT4ZMDr9aEoKaMlXeCAJOCEpBzBBAVeeIbnLhW1////YlDEgwhBJgVX67xBFAKYLMIflEpRMDq+XLQXqOZeqJYP1r4bBEpJMD2oqB/o4BYBUKQQXVcAKODJg4CB+oDB9+1vRMKgQlC1t9EpdaGYPltdXEgPVJhYkBq/qr1VtQlJq+rEoN7EoNV9teJgkKFYhMBC4P3yt6yolIqoLB9tbq4PBr3V9QgDD4IFFq5HB8pmCABFW1ogBqxbCJgxsB0AlE1X1vNe0olJX4QgBEoRPBJgkqEwYlCBoP/q7/CX5Ve7ynDHYJMDhW+cAWCEoVV/VV1IlKGQTzEJgsC1tfEwQlDMoZyMVYQACvtaSQUAeYNX9QlGvQWEOQ7xGYYOqTAffBIP+EorkLOQYAFtt6JgUK2+rZYg2DchdV9YHGr3XJgSYB9/q/olFq6+LP4JyGqvtvS/C1d5bwOr/4SEHw6QFLI9eq2oTAXeBANf/wlEXxlVLJH19RMBhW1WhFeXxdVtQIHrdeX4KYBOQLXPAAlaTA60BX4Wq65oITCtVvq/ChWl9rXITCtW66/C1deTD1V8q/ClW1+qBHHxBZETAda1f/MANfX4eprY+RLI9W//61QoB2q/ClXXNI7XIeRIRCv/61N6JgMK1t7DBi+M8oYFX4Wq65DH9YlL9QEDttqTIaLBX4MK0t9OSd6DoVVvt61QABFAPeOQJMBqwQDCIKsBORdaVwd5rQlCAAa/C2ttMQgWBMojkH0t63/V9te0EqEohMBgWrJgntYoI/EAAxYBr/+1Wtry4CIwIlBAwRMF9tX2tXbAjxG1I7C+olEFAa/BJgIgBEoV9rbMBUIgAFCgLMCvQlGFIm1NoIoBvQWBry/KUgPl9X//QlKJgWtEoXXHgK/K9XVrbhDNQJMJVQOqEola0olKq/XbohMJ1XVr/1tWXToNX1YlKqttv2v++qEpJMBDoXq2rDCvQDCEoxZBr3VuoQBORUA1Wv//q0vlDYNX1QlKe4NVr/WX5UAhSCC1ttDgV6cw4lDr2/HQPqEpRzBEoOpvIcCJgKPBAAYHFv2tdAK/KEwerrYeDvTAFrwtHy5yLE4fWDAnq14sEEo1VspyMTYW3RQRFDEwVfLIKfGrLlMAAMCcgZGEAAbFHq1eTBgAB1N9DAv6Eoe1Eo1VTCC+EEwqcETCkqyyxGbIP9EhCYQhW1MxAAKTB8K1tlcYmlYgqYWlWtvJtD3/5Dgl7eIqYQfoN7Cof1rwcEvIGFBASYMhQlBcgl9quVDgguBEoteTBj+B2pLEr9dTwdVrddGYiCCyyYKJQOr6olEq/XDwjbB67yG8uqEpMCOANV9YVE+uX6osDy6mFPYVqOJfVq4nBTAllbwnlvXXUAiCBrS+KhW1vxiFr9bXIIACvdW0ttqt/1JVC6y+KgWttZpDCofWAwm1tVeaIP+CYW1XxUAlVeQ4qYB2pUErde2v/AoPtAQNt9QlKOQLUH9N9A4m1ZodfAQNZvSYKgWpR4g7CvRVFvde3///Q6Cr1eTBRyB65MFvt6KotXyqXB1WtHQNXy6YLhWlvS/E9ta1pyFFwImC6wTB+olLgGqqvqMYP//2tbYJyFNQIlC0q/BttqEpcq1tV/wWB1fVDgLIGNQerGIK+MX4Oq+ocENALIGsvqHQQxBXxoRB1X9Wofq1DIBUIhEDgS/Bq3WTBiZBAAuoZANtTApECX4PXchhzDAAgbB1dX3olCIgIlCGIPv2uqEpgSBEohnBRoN7PYfXIga/B+qfCABpOBDIcCJgKZCAYJEDGINV9TkLZBbaBEoZEDX4IlYDQNlEogeDQYgAV1N5XoQlFVgQlX1dbEoNeEopMCEq8q6y+BEo8oEaxmCy+VEpAAZhWl+olCNTDkItolB64lfXwLkBEsWqr9VrdXEsDkCvYlhhW1yolCEjy+B0vlvdWEsOpvWrrwlgcgNf/olilVVqolj3///2oEsEK1QABEsMCEvw")) -} +}; var blackImg = { width : 152, height : 144, bpp : 1, transparent : 1, palette : new Uint16Array([0,65535]), buffer : require("heatshrink").decompress(atob("/4AGwAKBg4LHAAoeEh4RL8AyNEhAABj4RJ/ASGgYSJ4BsPG5AABn4RH/gSIJhHwCRCaIQQxfLXIQAGgJwQORISvJY/4OJISH8CERwASJVQ3+gC9JjwmF/EAuASImByFEYN4JRB7Bv7hFCREHAQM/cIs8VRMAj4SDAwISLh5wEM4ISKOQYSCj4SKX4f8FgROBfBiWBNAL3JAAKFCXQUDXxISEcAZPCABCYCCQZyLTARHLTAwSPg7PDCSAROXwYSPXwJ/LCS7RBCSN/eoQShn/4CUcfCSXwCUcPCSXgCSEHCWZHDgfAC4bfMCQn//wRGgf//4SFg4IBDAY3DBIYSDn4IBTowJCJgMBwA3CAAJCCAAYJCDgISCgIICIQQACBIf4CQZTCAAIsCKggvCCQQIDL4pdCCQoIDKoQACj4ICR4ISCBAYSFOASiFCQiFEv5oHDYYSFBAYSJPYISUUAiOECSRUECQazECRLkDCVbaDCRDsECSo6BCRwQBCQyEDCRKqICQoHBHQMPew4SE/zEBCQLHEM4YSEFwISCEwigDCQngCQgTCJQarEPIUBCoIAPgYSSNQYADgUAsASHIooABgwSIg7JDCRyaBCR5/BCRFwBI0fW4gSMeYJyGhwSKL4wSJaoQSHvAIFgLoECQqhGfgY5FCRBwBAARzECRF/CQYmEjwSGVAIAEJoYSGGwgADwASHNwYSOGwwSGgISDXIISQCJASDnwSDJRISEgYSCgYSMn4SDZgYSKw4SR/4SQbQISVLxt4OKIABnASRAAQS/CRb2NCX4S/CTkACRsMCR9ACQUCCRtgCQUGCX4SGuASChwSN+ASVjwSPEYM+CRv4CQV+CSP+CSEHCR38gEP/4SggIOBCSUfCRvAgP/gE/CRvgCQOAAwUAAwIAI/EDAwgSL/4SFwAGFAAvnKQsHAwgA==")) +}; +if(g.theme.dark){ + var backgrounds = [blueImg, greenImg, whiteImg]; + var manaColors = ["#0000ff","#00ff00","#ffff00"]; +}else{ + var backgrounds = [blackImg, blueImg, redImg, greenImg, whiteImg]; + var manaColors = ["#000000","#0000ff","#ff0000","#00ff00","#ffff00"]; } -var backgrounds = [blackImg, blueImg, redImg, greenImg, whiteImg] -var manaColors = ["#000000","#0000ff","#ff0000","#00ff00","#ffff00"] var bgIndex = 0; g.width = g.getWidth(); g.height = g.getHeight(); @@ -43,24 +49,24 @@ Graphics.prototype.setFontTreasurehuntDOYwE_20 = function(scale) { // Actual height 20 (19 - 0) this.setFontCustom(atob("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C////4AP////gA/7/q+ADwB8A8APQLwDwAvS/APAC//8A4AP//0DAAv/f0sAAvg//gAAED/8AAAAL/gAAAAL4AAAAAEAAAAAAAAAAC//8AAAv//8AAL///8AA//7/wAH4AF/AAtAAB9ADwAAD4APAAALgA8AAAtADwAAC0APQAAPAAvAAA0AA8AALAADgAA0AAEAAAAAAAAAAAAHgAFbwAv///+AD////4AP////wA/v+q/AD8EAH8APwAAfgA+AAB+AD8AAD4APwAAPgA/gAA8AC/QAHgAP/kB9AAv/+/wAA///9AAB///QAAAf/0AAAAEQAAAAAAAAAAAH/4AAAD//8AAAv//8AAH///4AA/r//wAH0fB/AAsB4B+ADwHQD8APAcALwA8BwAeADwDACwAPAcAPAA+BwA8AD8LQHQALwtA8AAOBgCQAAQAAAAAHVURWQAv///+AC////4AP////gA//+q+AD4BwC8APQDADgA8AMANADwAwAAAPQHQAAA/AcAAAD8AQAAAPwAAAAA8AAAAABgAAAAAAAAAAAAAf//QAAD///QAAv///AAH/qv+AAvAAL8ADwAAPwANAAAvAB0BQA8ALQPADwAtA8APAC0DwA4ALwOAHgAPw9A8AA/D//gAC0P/8AABAr5AAAAAAAAAH/r5rgAf///9AB////0AL+///gAYAOQeAAAA0AUAAADQAAAAANAAAAAA4AAAKADwAQA+7/rvAD////4AL////gAv+v6+ACgAAAsAAAAAAQAAAAAAAB1BUAoAH//+/gAf///+AC////4APqv+vgAQAAAKAAAAAAEAAAAAAAKQAAAAP/AAAAb3//v+v+P/////w/////9D/+v/5AFAAEAAAAAAAAAAPVaVSgA////+AC////4AP////QA////+ACUf9V4AAD/4DgAAv/0EAAH9/wAAB/i/0AAP4D/wAD+AL/gAPgAL/AA8AAL+ACAAAH8AAAAAL4AAAAAPwAAAAAfAAAAAAsAAAAAAwAAAAADAAAAAAIAAAAAAADgFBQYAP7///wA////+AD////4APuvv/wAUAQAfAAAAAA4AAAAADgAAAAAOAAAAAA9AAAAAD8AAAAAeQAAAACwAAAAAFAAL///0AA/+lbwAP/AALQA/wAAIAD9AAAAAPwAAAAA/AAAAAD9AAAAAH9AAAAAD+AAAAAH/UBQAAH///gAB////AAf///4AD//6vQAv+oAEAD/QAAAAP8AAAAAvQAAAAC0AAAAAPgAABAAfgAAsAA/QALwAB/Qb/AAB///8AAB///gAAB//8AAABqUAAAAAAAAD+pZuq/v/////k/////kD/+AAAAO/8AAAAS/8AAAAD/wAAAAH/wAAAAP/AAAAAv9AAAABv4AAAQA/0AADAD/wAANAH/AAA0AL9AADkVf9AAP///9AA////8AD5ABWQAEAAAAAAAAAAAAAAH//8AAA///4AAP+r/wAB9AH/AALgAH8AB4AAH0ALAAALgA8AAAfADwAAA8APQAADgA/QAAMAC/QAGwAL/lC9AAf//vwAA///9AAB//+QAAB//wAAAAWQAAAAAAAAAIAAAAAH1WpVVB7//////P/////4/+///+DVRfVUAMAA8AAAwADwAADQAPAAAPAA4AAA/gHAAAD/74AAAP//AAAAf/8AAAAb+AAAAAFQAAAAAAAAAAAAD//8AAA///4AAL///wAA9QL/AALgAH9AB8AAH0ALQAALgAsAAAfADwAEA8APAA8DgA/AD4NAC/AL2wAH/UP9AAf//v0AA////wAB////AAB//x8AAAagA0AAAAADQAAAAAJAAAAAAACwAAAPAPVWqr4Av////AC////0AH///8AAf/7/AAB9QAQAAHAAAAAAcABgAAB8APAAAH4B/QAAf5v/QAA////AAD//f+gAD/0v/wAHpAv/wAAAAL/0AAAAL/gAAAAH/AAAAAH8AAAAALwAAAAAPAAAAAAcAAAAAA0AAAAABQAAAAAAAP/AHwAC/+AvQAP/8C9AC2/0D0APA/gPgA8C/AvADwL8B8APA/wHgA8D/QtADwP/rwAPgv//AAvA//wAB0D/+AAAAH/QAAAABUAAAAAAAAALgAAAAA8AAAAADwAAAAAPAAAAAA8AAAAADwAAAAAPQAARQA//7//AD////8AP////gA////+AD1WQD8APAAAHwA8AAAOADwAAAQAPAAAAAA+AAAAAD8AAAAAPwAAAAA9AAAAADgAAAAAEAAAAAA4L/5AAD2//8AAP///+AA////8AD/mv/wAPkAH/AAsAAH8AAAAAL4AAAAAPwAAAAA/AAAAAD8AAAAALQAAAAAtADAAADwAOQAJPAA////8AD////4AP////0A//v//w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"), 32, atob("BgYHDQsQEwQKCAgLBgkGDA4GCwoPCwwMCwwGBgwJCwoNGREQExEQEREICBcOHRUTERUaEBYXFh0TERIKCwcKCgYSDg0PDQ0NDgcGEg0XERAPEhINExERFw4ODwYFBgoK"), 20+(scale<<8)+(2<<16)); return this; -} +}; Graphics.prototype.setFontTreasurehuntDOYwE_40_N = function(scale) { // Actual height 40 (39 - 0) this.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHAAAAAA8AAAAABwAAAAAHAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAAB4AAAAAfwAAAAB/AAAAA/4AAAAH+AAAAB/gAAAAf4AAAAH+AAAAB/gAAAA/4AAAAP+AAAAB/wAAAA/8AAAAf/AAAAD/gAAAAf4AAAAA+AAAAADwAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAB/AAAAAP/wAAAB//wAAAf//wAAD///AAAf8H+AAB+AH8AAPgAHwAB4AAPgAHAAAeAA4AAB4ADgAAHgAOAAAOAA4AAB4ADgAAHgAPAAAeAA+AADwAD8AAeAAH4AD4AAf4APgAA/8H8AAD///gAAD//8AAAH//gAAAH/4AAAAAYAAAAAAAAAAAAAAAAAAAAAAAAYAABAADgAAeAAf///4AD////gAP///+AA////4ABwAADgAAAAAGAAAAAAAAAAAAAAABwAAGAAPgAA4AB8AAHgAHwAA8AA8AAHwADgAA/AAMAAP8AB4AB/4AHgAf3gAPAH8eAA8B/B4AD4P4HgAP/+AeAA//wB4AB/8AHgAD/AAPAAPgAB8AAAAAPwAAAAB+AAAAAHgAAAAAAAAAAAAAAAAAAAAABgAAPwAOAMA/AB4DwAcAHAeAA4AOD4ADgA4/AAMADn8AAwAP/wADAA/3AAcAD8cADwAPh4AeAB4HgH4AHAfB/gAAA//8AAAB//gAAAD/8AAAAH/AAAAAEAAAAAAAAAAAAAAAAAAA4AAAAADgAAAAAeAAAAAD4AAAAAPgAAAAB+AAAAAP4AAAAB/gAAAAHOAAAAA44AAAAHjgAAAA8OAGAAPg4AYAD8Dh/gAP///+AB////wAH////gAP///+AA4BwA4AAAHAAgAAAMAAAAAB4AAAAAHgAAAAAeAAAAAB4AAAAAPAAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAADwAAAcAPAAADwAMAAA+AAwAAP4ADAAD/AAOAA/8AA4AD/wADAAP3AAMAA8cABwADhwAfAAOHgD4AA4fAfgADh//8AAfD//gAB8P/8AAHwf/gAAeB/4AABwD/AAAAAAAAAAAAAAAAAAAf/AAAAH//AAAA//+AAAP//4AAB/5/gAAP8A/AAB/wB8AAf3ADwAD8cAPAAfDwA4AB4PADgAPA8AeAB4DwDwAPAHgPAB4Afj4APAB//AB4AD/8APgAH/AA8AAP4ADgAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAPAAAAAB4AADgAPAAA+AB8AAP4AHwAD/gAfAAf4AB8AH+AADwA/gAAPAP4AAA8D+AAADw/wAAAPP8AAAA9/AAAAD/4AAAAP+AAAAA/gAAAAD4AAAAAfAAAAAAwAAAAACAAAAAAAAAAAAAAAAAAAAAAH8AAAAA/4AAAAP/wAADh//AAA/Pw+AAH+8B4AA//AHgAH/8AeAAcHgA4ADgeADgAOB4AOAB4HwB4AHg/gPgAfn/x8AB/9//gAD/3/8AAP+P/gAAPwf4AAAAAfgAAAAAAAAAAAAAAAAAAAAAAAAAAACAAfgAAcAH/gADwA//AAeAD/8ADwAf/4AeADwHgDwAeAeAfABwA4D4APADgfAA4AOD4ADgA4/AAPADn4AA+AN/AAD4A/4AAP8f+AAA///wAAB//8AAAH//gAAAH/4AAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAAHAeAAAA+D4AAAB4PwAAAHg/AAAAcB4AAAAAAAAAAAAAA"), 46, atob("CxgcCxcUHhUXFxYXCw=="), 40+(scale<<8)+(1<<16)); return this; -} +}; //Bluetooth on var btOnImg = { width : 15, height : 22, bpp : 3, transparent : 2, buffer : E.toArrayBuffer(atob("/////H//////A/////4A/////4BH////4JI////4JJH///4J5I///4BP5I///BJ/5A//BJPP5A/4JJ5P5H4J/PL/JHBJf/5JI4JJ/7JJIBP75/ZJAJZPJ/JIBJJ5/JJHBJP/JJA4JJ/JJI/4JPJJI//4BJJA////AAH//A==")) -} +}; var btOffImg = { width : 15, height : 22, bpp : 1, buffer : E.toArrayBuffer(atob("AAAAwAcAGgBEAQgEEBgQIDCAIQAiACgAUABgAMABgAKACQARAEGDAPgA")) -} +}; //Charging symbol var chrgOn = { @@ -68,7 +74,7 @@ var chrgOn = { transparent : 0, palette : new Uint16Array([65535,65504,63488,64928]), buffer : E.toArrayBuffer(atob("qterVKlcrVClcLVAlVfVVA1cDVANQA3ADQAPAAwA")) -} +}; function draw() { g.clear(); @@ -80,21 +86,21 @@ function draw() { drawBatteryStatus(); } function drawDate() { - days = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"] - months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"] + days = ["Sun", "Mon", "Tues", "Wed", "Thurs", "Fri", "Sat"]; + months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; var d = new Date(); var dateString = `${days[d.getDay()]} ${months[d.getMonth()]} ${d.getDate()}`; g.setFontTreasurehuntDOYwE_20(1); var sm = g.stringMetrics(dateString); - g.setColor(0,0,0).drawString(dateString, (g.width - sm.width) / 2, g.height - sm.height - 3); + g.setColor(g.theme.fg).drawString(dateString, (g.width - sm.width) / 2, g.height - sm.height - 3); } function drawTime(){ - var top = 100; pad = 6; bh=48; bw=62; linew=3 + var top = 100; pad = 6; bh=48; bw=62; linew=3; var boxH = {x:pad,y:top,x2:pad+bw,y2:top+bh}; var boxM = {x:g.width-pad-bw,y:top,x2:g.width-pad,y2:top+bh}; - var innerH = {x:boxH.x+linew, y:boxH.y+linew, x2:boxH.x2-linew, y2:boxH.y2-linew} - var innerM = {x:boxM.x+linew, y:boxM.y+linew, x2:boxM.x2-linew, y2:boxM.y2-linew} + var innerH = {x:boxH.x+linew, y:boxH.y+linew, x2:boxH.x2-linew, y2:boxH.y2-linew}; + var innerM = {x:boxM.x+linew, y:boxM.y+linew, x2:boxM.x2-linew, y2:boxM.y2-linew}; g.setColor(manaColors[bgIndex]).fillRect(boxH).fillRect(boxM).clearRect(innerH).clearRect(innerM); //Draw the hour and minute @@ -111,14 +117,14 @@ function drawTime(){ console.log `Hours: ${h}, x: ${xH}, y:${yH}`; var xM = (bw - mM.width)/2 + boxM.x+xOffset; var yM = (bh - mM.height)/2 +boxM.y+yOffset; - g.setColor(0,0,0).drawString (h, xH, yH).drawString(m, xM, yM); + g.setColor(g.theme.fg).drawString (h, xH, yH).drawString(m, xM, yM); } function drawBattery(){ var pad = 6; top=pad; bh=10; bw=40; linew=1; var box = {x:g.width-pad-bw,y:top,x2:g.width-pad,y2:top+bh}; - var innerB = {x:box.x+linew, y:box.y+linew, x2:box.x2-linew, y2:box.y2-linew} - var batteryFill={x:box.x+linew, y:box.y+linew, x2:(box.x-linew)+bw*E.getBattery()/100, y2:box.y2-linew} + var innerB = {x:box.x+linew, y:box.y+linew, x2:box.x2-linew, y2:box.y2-linew}; + var batteryFill={x:box.x+linew, y:box.y+linew, x2:(box.x-linew)+bw*E.getBattery()/100, y2:box.y2-linew}; g.setColor(manaColors[bgIndex]).fillRect(box).clearRect(innerB).setColor(0,1,0).fillRect(batteryFill); } From c722398c76443ba6169225f7b517f720ed169028 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:25:03 -0700 Subject: [PATCH 189/312] Update README.md --- apps/mtgwatchface/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/mtgwatchface/README.md b/apps/mtgwatchface/README.md index 36c0c9efb..9f0a6deb9 100644 --- a/apps/mtgwatchface/README.md +++ b/apps/mtgwatchface/README.md @@ -1,5 +1,5 @@ ## Magic the Gathering Watch Face Magic the Gathering themed watch face. Embrace the inner wizzard. Dispay any of the different types of mana on your watch. Which color are you devoted to today? - +It supports both light and dark mode. ### Touch Enabled Simply touch the screen on the sides to switch the mana colors From 267ec35f73f31debf7e06bd726fe8900051f6b82 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:25:49 -0700 Subject: [PATCH 190/312] Update app.js --- apps/mtgwatchface/app.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/mtgwatchface/app.js b/apps/mtgwatchface/app.js index 55fb98e78..044845fcc 100644 --- a/apps/mtgwatchface/app.js +++ b/apps/mtgwatchface/app.js @@ -1,4 +1,3 @@ -//g.setTheme({fg : 0xFFFF,bg : 0,fg2 : 0xFFFF,bg2 : 0x0007,fgH : 0xFFFF,bgH : 0x02F7,dark : true}); var blueImg = { width : 93, height : 145, bpp : 2, transparent : 1, From 56baf7bdc9887f6cf83c155a391c4c0ec9788e29 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:31:58 -0700 Subject: [PATCH 191/312] Update metadata.json --- apps/lcars/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/lcars/metadata.json b/apps/lcars/metadata.json index 7155442f8..5f3eaa971 100644 --- a/apps/lcars/metadata.json +++ b/apps/lcars/metadata.json @@ -3,7 +3,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.20", + "version":"0.21", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", From d50e525f7ff77975128041af2311193dabe1047d Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:32:32 -0700 Subject: [PATCH 192/312] Update ChangeLog --- apps/lcars/ChangeLog | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 4935fe714..9c17376bb 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -17,4 +17,5 @@ 0.17: Settings for mph/kph and other minor improvements. 0.18: Fullscreen mode can now be enabled or disabled in the settings. 0.19: Alarms can not go bigger than 100. -0.20: Use alarm for alarm functionality instead of own implementation. \ No newline at end of file +0.20: Use alarm for alarm functionality instead of own implementation. +0.21: Add custom theming. From 4e9c59646edf06c4f647531527675337a0c624a9 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:33:11 -0700 Subject: [PATCH 193/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 804 ++++++---------------------------------- 1 file changed, 106 insertions(+), 698 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 577955d2e..f714c3a7a 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,705 +1,113 @@ -const TIMER_IDX = "lcars"; -const SETTINGS_FILE = "lcars.setting.json"; -const locale = require('locale'); -const storage = require('Storage'); -let settings = { - alarm: -1, - dataRow1: "Steps", - dataRow2: "Temp", - dataRow3: "Battery", - speed: "kph", - fullscreen: false, -}; -let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; -for (const key in saved_settings) { - settings[key] = saved_settings[key] -} +(function(back) { + const SETTINGS_FILE = "lcars.setting.json"; -/* - * Colors to use - */ -let cBlue = "#0094FF"; -let cOrange = "#FF9900"; -let cPurple = "#FF00DC"; -let cWhite = "#FFFFFF"; -let cBlack = "#000000"; -let cGrey = "#424242"; - -/* - * Global lcars variables - */ -let lcarsViewPos = 0; -// let hrmValue = 0; -var plotMonth = false; - - -/* - * Requirements and globals - */ - - -var bgLeftFullscreen = { - width : 27, height : 176, bpp : 3, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A==")) -}; - -var bgLeftNotFullscreen = { - width : 27, height : 152, bpp : 3, - transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=")) -}; - -var bgRightFullscreen = { - width : 27, height : 176, bpp : 3, - transparent : 0, - buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAnUP7y/KH4yGeVYAJrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgAA=")) -}; - -var bgRightNotFullscreen = { - width : 27, height : 152, bpp : 3, - transparent : 0, - buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAxrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgA=")) -}; - -var bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen; -var bgRight= settings.fullscreen ? bgRightFullscreen : bgRightNotFullscreen; - -var iconEarth = { - width : 50, height : 50, bpp : 3, - buffer : require("heatshrink").decompress(atob("AFtx48ECBsDwU5k/yhARLjgjBjlzAQMQEZcIkOP/fn31IEZgCBnlz58cEpM4geugEgwU/8+WNZJHDuHHvgmBCQ8goEOnVgJoMnyV58mACItHI4X8uAFBuVHnnz4BuGxk4////Egz3IkmWvPgNw8f/prB//BghTC+AjE7848eMjNnzySBwUJkmf/BuGuPDAQIjBiPHhhTCSQnjMo0ITANJn44Dg8MuFBggCCiFBcAJ0Bv5xEh+ITo2OhHkyf/OIQdBWwVHhgjBNwUE+fP/5EEgePMoYLBhMgyVJk/+BQQdC688I4XxOIc8v//NAvr+QEBj/5NwKVBy1/QYUciPBhk1EAJrC+KeC489QYaMBgU/8BNB9+ChEjz1Jkn/QYMBDQIgCcYTCCiP/nlzJQmenMAgV4//uy/9wRaB/1J8iVCcAfHjt9TYYICnhKCgRKBw159/v//r927OIeeoASBDQccvv3791KYVDBYPLJQeCnPnz//AAP6ocEjEkXgMgJQtz79fLAP8KYkccAcJ8Gf/f/xu/cAMQ4eP5MlyQRCMolx40YsOGBAPfnnzU4KVDpKMBvz8Dh0/8me7IICgkxJQXPIgZTD58sEgcJk+eNoONnFBhk4/5uB/pcDg5KD+4mEv4CBXISVDhEn31/8/+mH7x//JQK5CAAMB4JBCnnxJQf/+fJEgkAa4L+CAQOOjMn/1bXIRxDJQXx58f//Hhlz/88EgsChMgz/Zs/+nfkyV/8huDOI6SD498NwoACi1Z8+S/Plz17/+QCI7jC+ZxBmfPnojIAAMDcYWSp//2wRJEwq2GABECjMgNYwAmA=")) -}; - -var iconSaturn = { - width : 50, height : 50, bpp : 3, - transparent : 1, - buffer : require("heatshrink").decompress(atob("AH4A/AEkQuPHCJ0ChEAwARNjAjBjgjOhs06Q2OEYVx4ARMhEggUMkANIDoIgBoEEgEBNxJEC6ZrBAAMwNxAjDNYcHNxIjB7dtEwIHBwRoKj158+cuPEjlwCRAjC23bpu0wRNDAAsHEYWeEwaSJ6YjCAQUNSRQjEzxQBWZMNEYlsmg2JWAIjCz95SoJuJggjDtuw6dMG5JKCz998wFBJRVNEYW0yaVBJRNhJQN9+4pCzhKJmBKC4YpB/fINxIgCzFxSoQ3J4ENm3CAQPb98wbpEcAQMYWwKYBNxMDXgc2/fv3g2IEAOAgAjBjy5CEhEMfYICBgfPnjdLjj+CgMHiC3JknDhhoINw4jCAB0IJQIANR4QjPAH4A/AFA")) -}; - -var iconMoon = { - width : 50, height : 50, bpp : 3, - transparent : 1, - buffer : require("heatshrink").decompress(atob("AH4AQjlx44CCCZsg8eOkHDwAQKEYgmPhEgEQM48AOIgMHEYoCB4ATI8UAmH/x04JoRuJsImHuBKLn37EwZuIgEQOI8cEpXj/yYBhE8+YNGgkYoJxITBUPnAaC///nC+FjBuIOJZEB8YeCh/8AoYACoMEEAnEjhQDPQJKJ/DCDAoi5DoLdHAoMQgLjFWYPOnngh02IwXzwDjEgPGEYS8BI4MBYoSVG4fP/nghkAgZrDkngJQqSG4gvBg4sBQgkImHihEAWwP8ZBMBEYl5/+cSoVAGQIUFh04weJn///0gj/OEw5KEz45BzhuCTYQAEgePB4IACAoJuBnAQEa4XHjxKB//xFgWHJQsCRgMDEonipwjENwUBDQNx8+evvn/hTDLw3igE+EgZxB8UOXIvEJQUfEYOfv53DEQkgga5BJQvzx84cAj+CDoNh8/eEYJKDuCSEcocnEon+/7xEgFBIIcfB4Mf/IICXI2DgDdBAAn758gCIq5Dv4zBvJuIOIfjEgvP/ARHgwdCB4P3AoTdFAAk4EYk8SQgAFTALaDSQwAGh08//vnDmBABYmEEZYAzA==")) -}; - -var iconMars = { - width : 50, height : 50, bpp : 3, - transparent : 1, - buffer : require("heatshrink").decompress(atob("AH4ATjlwCJ+Dh0wwAQMg0cuPHjFhCZkDps0yVJkmQCBMEjFx42atOmzQmLhMkEYQCCCREQoOGEYmmzB0IEY4CBkARGoJKBEYQCEzgSGkGSpAjDyYCCphuGiFhJQgCD8ASFgRHGAQKbB6BuHJRGeOIsINxEk6dNmARDgMEjQjHAQPnVQojIyZKB6YSDNwK5FAQt54BuDXJIjBEwK5EgxKKXgq5BJRdgXIojJAQJKMcAM0EwM2JUApDoCVFExa7FkGCgAmIkAREEwUEjAmHCIgABhEggQmFpACBCIojBEwRQCzVhwkQU4YADgQmBwQCCI4IFBCAojFAQojGJQQjDAQgRGEZICBEo4gFyUIkilFJQUYEAZrBAQMYNw5KDSQSbCNwwABgOGEwgCBsPACQ5xGwdNnARJcAVh48evvnCJK8Chs+/fv33gCRcB48cuPHCBYA/ADAA==")) -}; - -var iconSatellite = { - width : 50, height : 50, bpp : 3, - transparent : 2, - buffer : require("heatshrink").decompress(atob("pMkyQC/ATGXhIRPyNl0gmPjlwCJ9ly1aCJ1c+fHJR1Hy1ZJR1I+fPnlx6QRLpe+/JKBr5KMuYjBJQMdCJce/fvJQW0CJUlEYQCBSpvvJQbXJjl0NwnzNxGQwEOnHhgF78+WqQyIrFx48cAQXz4ShJgAABh0+8cP//9LJEhg4jDuP3//0LhGQgYlBgeAn///5cIy8MuAmDCIP/9I4HkmCEYMOgHfCQWkCI0cuBuDgF/CIP+CI1Ny1IkeAgHANwIAB/QRFrj7BhkxEwQRC/4RFpbXDgSVBg4RCSorXDI4MJAQMfCIP8cwImDn37fwN58+kwHgLgSVFub7CI4NyBAJKDLgkuEYX78+evKtCLg0jEYRKC58JMoRcFkwjDJQTFDl65EkojEAQMdcwn/+gFC3YjEJQLXEpYRDWwQmEdI6SHAQO0CJUkx4jDF4gCIJQgRMXIjCEARIjCCJ2XEYPKCJqJBJQIROcAUpCJ0kybaDARtdCKAC2kAA=")) -}; - -var iconCharging = { - width : 50, height : 50, bpp : 3, - transparent : 5, - buffer : require("heatshrink").decompress(atob("23btugAwUBtoICARG0h048eODQYCJ6P/AAUCCJfbo4SDxYRLtEcuPHjlwgoRJ7RnIloUHoYjDAQfAExEAwUIkACEkSAIEYwCBhZKH6EIJI0CJRFHEY0BJRWBSgf//0AJRYSE4BKLj4SE8BKLv4RD/hK/JS2AXY0gXwRKG4cMmACCJQMAg8csEFJQsBAwfasEAm379u0gFbcBfHzgFBz1xMQZKBjY/D0E2+BOChu26yVEEYdww+cgAFCg+cgIfB6RKF4HbgEIkGChEAthfCJQ0eEAIjBBAMxk6GCJQtgtyVBwRKBAQMbHAJKGXIIFCgACBhl54qVG2E+EAJKBJoWAm0WJQ6SCXgdxFgMLJQvYjeAEAUwFIUitEtJQ14NwUHgEwKYZKGwOwNYX7XgWCg3CJQ5rB4MevPnAoPDJRJrCgEG/ECAoNsJRUwoEesIIBiJKI3CVDti/CJRKVDiJHBSo0YsOGjED8AjBcAcIgdhcAXAPIUAcAYIBcA4dBAQUG8BrBgBuCgOwcBEeXIK2BBAIFBgRqBGoYAChq8CcYUE4FbUYOACQsHzgjDgwFBCIImBAQsDtwYD7cAloRI22B86YBw5QBgoRJ7dAgYEDCJaeBJoMcsARMAQNoJIIRE6A")) -}; - -var iconNoBattery = { - text: "NO BAT", - width : 50, height : 50, bpp : 3, - transparent : 1, - buffer : require("heatshrink").decompress(atob("kmSpIC/AWMyoQIFsmECJFJhMmA4QXByVICIwODAQ4RRFIQGD5JVLkIGDzJqMyAGDph8MiRKGyApEAoZKFyYIDQwMkSQNkQZABBhIIOOJRuEL5gRIAUKACVQMhmUSNYNDQYJTBBwYFByGTkOE5FJWYNMknCAQKYCiaSCpmGochDoSYBhMwTAZrChILBhmEzKPBF4ImBTAREBDoMmEwJVDoYjBycJFgWEJQRuLJQ1kmQCCjJlCBYbjCagaDBwyDBmBuBF4TjJAUQKINBChCDQxZBcZIIQF4NIgEAgKSDiQmEVQKMBoARBAAMCSQLLBVoxqKL4gaCChVCNwoRKOIo4CJIgABBoSMHpIRFgDdJOIJUBCAUJRgJuEAQb+DIIgRIAX4C/ASOQA")) -}; - -// Font to use: -// -Graphics.prototype.setFontAntonioMedium = function(scale) { - // Actual height 20 (19 - 0) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAA//mP/5gAAAAAAAAAAAAA/gAMAAAAAA/gAPAAAEIIBP+H/8D+IYBP+H/8D+IABCAAwIAfnwP8+PHh448eP3+B4fAAAAAAAH/AD/4AwGAMBgD/4Af8GAAPgAPgAfgAfAAfAA+AAOP/AH/4BgGAYBgH/4A/8AAAAAAAAAQAA/B+f4/+GMPhjv/4/h8Dg/gAcYwAAPwADgAAAAAAAAB//8///sAAaAACAAAMAAb//+f//AAAAAAAbAAGwAA4AA/wADgABsAAbAAAAAAAgAAMAAPwAD8AAMAADAAAAAAAAAAHAAB/AAOAAAAAAAAMAADAAAwAAMAACAAAAAAAAAABgAAYAAAAAAAAA4AD+AP+A/4A/gAOAAAAAAAAAH//j//8wADMAAz//8f/+AAAAAAAMAADAABgAA//+P//gAAAAAAAAAAAAAfgfP4fzAfswfDP/gx/gMAAAHgPj4D8wMDMHAz//8f3+AAEAAAAADwAH8APzA/AwP//j//4AAwAAAD/Hw/x+MwBjOAYz/+Mf/AAAAAAAH//j//8wYDMGAz9/8fP+AAcDAAAwAAMAfjB/4z/wP+AD4AAwAAAAOB/f4///MHAzBwM///H9/gAAAAAAH/Pj/78wGDMBgz//8f/+AAAAAAADhwA4cAAAAAAAAAAAAAADh/A4fgAAAAOAAHwABsAA7gAccAGDAAAAANgADYAA2AANgADYAA2AAAAAAAABgwAccADuAAbAAHwAA4AAAAHwAD8c4/POMHAD/wAfwAAAAAAAAD/wD//B4B4Y/HMf8zMBMyATMwczP+M4BzHwcgf+AA+AAAAAAD4A/+P/8D+DA/4wH/+AB/4AAeAAAAAAA//+P//jBgYwYGP//j//4PH4AAAAAAAf/+P//zgAcwADP4fz+P4Ph8AAAAAAA//+P//jAAYwAGPADj//4P/4AAAAAAA//+P//jBgYwYGMGBgAAAAAAP//j//4wYAMGADBgAAAAAAAA//w///PAHzAQM4MHP7/x+/8AAAAAAD//4//+AGAABgAAYAP//j//4AAAAAAAAAA//+P//gAAAAAAAAAAAHwAB+AABgAAY//+P//AAAAAAAAAAD//4//+APgAf+Afj8PgPjAAYAAAAAAD//4//+AABgAAYAAGAAAAAAA//+P//j/gAD/wAB/gAP4B/4P/AD//4//+AAAAAAAAAAP//j//4P4AAfwAA/g//+P//gAAAAAAAAAA//g//+PAHjAAY4AOP//h//wAAAAAAD//4//+MDADAwA4cAP/AB/gAAAAAAAA//g//+PAHjAAc4APv//5//yAAAAAAD//4//+MGADBgA48AP//h+f4AAAAAAB+Pw/z+MOBjBwY/P+Hx/AAHgwAAMAAD//4//+MAADAAAAAAP//D//4AAOAABgAA4//+P//AAAAwAAP8AD//AA/+AAfgP/4//gPwAAAAA+AAP/4Af/4AD+A//j/wA/wAD/+AA/4B/+P/+D+AAAAAMADj8P4P/4A/4B//w+A+MABgAAA4AAPwAB/gAB/+A//j/gA+AAMAAAAAYwB+MH/jf+Y/8GPwBjAAAAAAP//7//+wABsAAYAAAAAAPAAD/gAH/gAD/gAD4AACAAADAAGwABv//7//+AAAA=="), 32, atob("BQUHCAgVCQQFBQkHBQcFBwgICAgICAgICAgFBQcHBwgPCQkJCQcHCQoFCQkHDQoJCQkJCAYJCQ0ICAcGBwY="), 20+(scale<<8)+(1<<16)); -}; - -Graphics.prototype.setFontAntonioLarge = function(scale) { - // Actual height 39 (39 - 1) - g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAPgAAAAAB8AAAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAD8AAAAAH/gAAAAP/8AAAAf//gAAA///AAAB//+AAAD//8AAAH//4AAAP//wAAAB//gAAAAP/AAAAAB+AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH///AAAf////8AP/////4B//////Af/////8D8AAAAfgeAAAAA8DwAAAAHgeAAAAA8D//////gf/////8B//////AP/////wAf////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAHgAAAAAA8AAAAAAPgAAAAAB4AAAAAAf/////gP/////8B//////gP/////8B//////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAD/+AAP8A//wAP/gP/+AH/8D//wD//gfgAA//8DwAAf+HgeAAP/A8DwAH/gHgfgP/wA8D///4AHgP//+AA8A///AAHgB//AAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AA/gAD/AAH/gA/4AA/+AP/AAH/4D/4AA//gfgA4AB8DwAPAAHgeAB4AA8DwAPgAHgfAD+AB8D//////gP/////4B//5//+AD/+H//gAH/AH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAAAP/AAAAAP/4AAAAP//AAAAP/x4AAAf/wPAAAf/gB4AAf/AAPAAP/AAB4AB//////gP/////8B//////gP/////8AAAAAPAAAAAAB4AAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//wD/AB///Af+AP//4D/4B///Af/gP//4B/8B4D4AAPgPAeAAA8B4DwAAHgPAfAAB8B4D////gPAf///4B4B////APAD///gAAAD//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB///AAAP////4AH/////wB//////Af/////8D8APAA/geADwAB8DwAeAAHgeADwAA8D4AeAAPgf/j+AH8B/8f///gP/h///4Af8H//+AAPgP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAPAAAAAAB4AAAABgPAAAA/8B4AAB//gPAAD//8B4AH///gPAH///8B4P//+AAPH//wAAB///gAAAP//AAAAB/+AAAAAP+AAAAAB+AAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4A/+AAf/w//+AP//v//4B//////Af/////8D4AfwAPgeAB8AA8DwAHAAHgeAB8AA8D4Af4APgf/////8B//////AP//v//4A//4//8AA/4A/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/+AAAAD//+D/gB///4f+AP///j/4D///8f/gfAAHgB8DwAA8AHgeAAHgA8DwAA8AHgfgAHgB8D//////gP/////4A/////+AD/////gAD////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAfgAAB+AD8AAAPwAfgAAB+AD8AAAPwAfgAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DBATExMTExMTExMTCw=="), 45+(scale<<8)+(1<<16)); -}; - - -/* - * Draw watch face - */ -var drawTimeout; -function queueDraw() { - - // Faster updates during alarm to ensure that it is - // shown correctly... - var timeout = isAlarmEnabled() ? 10000 : 60000; - - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, timeout - (Date.now() % timeout)); -} - -/** - * This function plots a data row in LCARS style. - * Note: It can be called async and therefore, the text alignment and - * font is set each time the function is called. - */ -function printRow(text, value, y, c){ - g.setFontAntonioMedium(); - g.setFontAlign(-1,-1,0); - - // Print background - g.setColor(c); - g.setFontAlign(-1,-1,0); - g.fillRect(80, y-2, 165 ,y+18); - g.fillCircle(163, y+8, 10); - g.setColor(cBlack); - g.drawString(text, 135, y); - - // Plot text - width = g.stringWidth(value); - g.setColor(cBlack); - g.fillRect(130-width-8, y-2, 130, y+18); - g.setColor(c); - g.setFontAlign(1,-1,0); - g.drawString(value, 126, y); -} - - -function drawData(key, y, c){ - try{ - _drawData(key, y, c); - } catch(ex){ - // Show last error - next try hopefully works. - } -} - - -function _drawData(key, y, c){ - key = key.toUpperCase() - var text = key; - var value = "ERR"; - var should_print= true; - - if(key == "STEPS"){ - text = "STEP"; - value = getSteps(); - - } else if(key == "BATTERY"){ - text = "BAT"; - value = E.getBattery() + "%"; - - } else if (key == "VREF"){ - value = E.getAnalogVRef().toFixed(2) + "V"; - - } else if(key == "HRM"){ - value = Math.round(Bangle.getHealthStatus("day").bpm); - - } else if (key == "TEMP"){ - var weather = getWeather(); - value = weather.temp; - - } else if (key == "HUMIDITY"){ - text = "HUM"; - var weather = getWeather(); - value = weather.hum; - - } else if (key == "WIND"){ - text = "WND"; - var weather = getWeather(); - value = weather.wind; - - } else if (key == "ALTITUDE"){ - should_print= false; - text = "ALT"; - - // Immediately print something - avoid that its empty - printRow(text, "", y, c); - Bangle.getPressure().then(function(data){ - if(data && data.altitude){ - value = Math.round(data.altitude); - printRow(text, value, y, c); - } - }) - - } else if(key == "CORET"){ - value = locale.temp(parseInt(E.getTemperature())); + // initialize with default settings... + const storage = require('Storage') + let settings = { + alarm: -1, + dataRow1: "Battery", + dataRow2: "Steps", + dataRow3: "Temp", + speed: "kph", + fullscreen: false, + themeColor1: "Orange", + themeColor1BG: "#FF9900", + themeColor2: "Purple", + themeColor2BG: "#FF00DC", + themeColor3: "Cyan", + themeColor3BG: "#0094FF", + }; + let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; + for (const key in saved_settings) { + settings[key] = saved_settings[key] } - // Print for all datapoints that are not async - if(should_print){ - printRow(text, value, y, c); - } -} - -function drawHorizontalBgLine(color, x1, x2, y, h){ - g.setColor(color); - - for(var i=0; i{ - data[h.day]+=h.bpm; - if (h.bpm) cnt[h.day]++; - }); - require("graph").drawBar(g, data, { - axes : true, - minx: 1, - gridx : 5, - gridy : 100, - width : 140, - height : 50, - x: 5, - y: 25 - }); - - // Plot step graph - var data = new Uint16Array(32); - health.readDailySummaries(new Date(), h=>data[h.day]+=h.steps/1000); - var gridY = parseInt(Math.max.apply(Math, data)/2); - gridY = gridY <= 0 ? 1 : gridY; - require("graph").drawBar(g, data, { - axes : true, - minx: 1, - gridx : 5, - gridy : gridY, - width : 140, - height : 50, - x: 5, - y: 115 - }); - - g.setFontAlign(1, 1, 0); - g.setFontAntonioMedium(); - g.setColor(cWhite); - - if(settings.fullscreen){ - g.drawString("M-HRM", 154, 27); - g.drawString("M-STEPS [K]", 154, 115); - } else { - g.drawString("MONTH", 154, 115); + E.showMenu({ + '': { 'title': 'LCARS Clock' }, + '< Back': back, + 'Row 1': { + value: 0 | dataOptions.indexOf(settings.dataRow1), + min: 0, max: 8, + format: v => dataOptions[v], + onchange: v => { + settings.dataRow1 = dataOptions[v]; + save(); + }, + }, + 'Row 2': { + value: 0 | dataOptions.indexOf(settings.dataRow2), + min: 0, max: 8, + format: v => dataOptions[v], + onchange: v => { + settings.dataRow2 = dataOptions[v]; + save(); + }, + }, + 'Row 3': { + value: 0 | dataOptions.indexOf(settings.dataRow3), + min: 0, max: 8, + format: v => dataOptions[v], + onchange: v => { + settings.dataRow3 = dataOptions[v]; + save(); + }, + }, + 'Full Screen': { + value: settings.fullscreen, + format: () => (settings.fullscreen ? 'Yes' : 'No'), + onchange: () => { + settings.fullscreen = !settings.fullscreen; + save(); + }, + }, + 'Speed': { + value: 0 | speedOptions.indexOf(settings.speed), + min: 0, max: 1, + format: v => speedOptions[v], + onchange: v => { + settings.speed = speedOptions[v]; + save(); + }, + }, + 'Theme Color 1': { + value: 0 | color_options.indexOf(settings.themeColor1), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor1 = color_options[v]; + settings.themeColor1BG = bg_code[v]; + save(); + }, + }, + 'Theme Color 2': { + value: 0 | color_options.indexOf(settings.themeColor2), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor2 = color_options[v]; + settings.themeColor2BG = bg_code[v]; + save(); + }, + }, + 'Theme Color 3': { + value: 0 | color_options.indexOf(settings.themeColor3), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor3 = color_options[v]; + settings.themeColor3BG = bg_code[v]; + save(); + }, } - - // Plot day - } else { - var data = new Uint16Array(24); - var cnt = new Uint8Array(24); - health.readDay(new Date(), h=>{ - data[h.hr]+=h.bpm; - if (h.bpm) cnt[h.hr]++; - }); - require("graph").drawBar(g, data, { - axes : true, - minx: 1, - gridx : 4, - gridy : 100, - width : 140, - height : 50, - x: 5, - y: 25 - }); - - // Plot step graph - var data = new Uint16Array(24); - health.readDay(new Date(), h=>data[h.hr]+=h.steps); - var gridY = parseInt(Math.max.apply(Math, data)/1000)*1000; - gridY = gridY <= 0 ? 1000 : gridY; - require("graph").drawBar(g, data, { - axes : true, - minx: 1, - gridx : 4, - gridy : gridY, - width : 140, - height : 50, - x: 5, - y: 115 - }); - - g.setFontAlign(1, 1, 0); - g.setFontAntonioMedium(); - g.setColor(cWhite); - - if(settings.fullscreen){ - g.drawString("D-HRM", 154, 27); - g.drawString("D-STEPS", 154, 115); - } else { - g.drawString("DAY", 154, 115); - } - } -} - -function draw(){ - // Queue draw first to ensure that its called in one minute again. - queueDraw(); - - // Next draw the watch face - g.reset(); - g.clearRect(0, 0, g.getWidth(), g.getHeight()); - - // Draw current lcars position - if(lcarsViewPos == 0){ - drawPosition0(); - } else if (lcarsViewPos == 1) { - drawPosition1(); - } - - // After drawing the watch face, we can draw the widgets - if(settings.fullscreen){ - for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} - } else { - Bangle.drawWidgets(); - } -} - - -/* - * Step counter via widget - */ -function getSteps() { - try{ - if (WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); - } else if (WIDGETS.activepedom !== undefined) { - return WIDGETS.activepedom.getSteps(); - } - } catch(ex) { - // In case we failed, we can only show 0 steps. - } - - return 0; -} - - -function getWeather(){ - var weatherJson; - - try { - weatherJson = storage.readJSON('weather.json'); - } catch(ex) { - // Return default - } - - if(weatherJson === undefined){ - return { - temp: "-", - hum: "-", - txt: "-", - wind: "-", - wdir: "-", - wrose: "-" - }; - } - - var weather = weatherJson.weather; - - // Temperature - weather.temp = locale.temp(weather.temp-273.15); - - // Humidity - weather.hum = weather.hum + "%"; - - // Wind - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - var speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934; - weather.wind = Math.round(wind[1] * speedFactor); - - return weather -} - - -/* - * Handle alarm - */ -function isAlarmEnabled(){ - try{ - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(TIMER_IDX); - if(alarmObj===undefined || !alarmObj.on){ - return false; - } - - return true; - - } catch(ex){ } - return false; -} - -function getAlarmMinutes(){ - if(!isAlarmEnabled()){ - return -1; - } - - var alarm = require('sched'); - var alarmObj = alarm.getAlarm(TIMER_IDX); - return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); -} - -function increaseAlarm(){ - try{ - var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; - var alarm = require('sched') - alarm.setAlarm(TIMER_IDX, { - timer : (minutes+5)*60*1000, - }); - alarm.reload(); - } catch(ex){ } -} - -function decreaseAlarm(){ - try{ - var minutes = getAlarmMinutes(); - minutes -= 5; - - var alarm = require('sched') - alarm.setAlarm(TIMER_IDX, undefined); - - if(minutes > 0){ - alarm.setAlarm(TIMER_IDX, { - timer : minutes*60*1000, - }); - } - - alarm.reload(); - } catch(ex){ } -} - - -/* - * Listeners - */ -Bangle.on('lcdPower',on=>{ - if (on) { - // Whenever we connect to Gadgetbridge, reading data from - // health failed. Therefore, we update only partially... - drawInfo(); - drawState(); - } else { // stop draw timer - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = undefined; - } -}); - -Bangle.on('lock', function(isLocked) { - drawInfo(); -}); - -Bangle.on('charging',function(charging) { - drawState(); -}); - - -function feedback(){ - Bangle.buzz(40, 0.3); -} - -// Touch gestures to control clock. We don't use swipe to be compatible with the bangle ecosystem -Bangle.on('touch', function(btn, e){ - var left = parseInt(g.getWidth() * 0.2); - var right = g.getWidth() - left; - var upper = parseInt(g.getHeight() * 0.2); - var lower = g.getHeight() - upper; - - var is_left = e.x < left; - var is_right = e.x > right; - var is_upper = e.y < upper; - var is_lower = e.y > lower; - - if(is_left && lcarsViewPos == 1){ - feedback(); - lcarsViewPos = 0; - draw(); - return; - - } else if(is_right && lcarsViewPos == 0){ - feedback(); - lcarsViewPos = 1; - draw(); - return; - } - - if(lcarsViewPos == 0){ - if(is_upper){ - feedback(); - increaseAlarm(); - drawState(); - return; - } if(is_lower){ - feedback(); - decreaseAlarm(); - drawState(); - return; - } - } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotMonth != is_lower){ - feedback(); - plotMonth = is_lower; - draw(); - return; - } -}); - - -/* - * Lets start widgets, listen for btn etc. - */ -// Show launcher when middle button pressed -Bangle.setUI("clock"); -Bangle.loadWidgets(); - -// Clear the screen once, at startup and draw clock -g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); -draw(); + }); +}) From c5509992b9cfd533d9bdcbf6e8657b26994f3a1c Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:34:03 -0700 Subject: [PATCH 194/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 811 ++++++++++++++++++++++++++++++++++------ 1 file changed, 706 insertions(+), 105 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index f714c3a7a..7cdd6749e 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,113 +1,714 @@ -(function(back) { - const SETTINGS_FILE = "lcars.setting.json"; +const SETTINGS_FILE = "lcars.setting.json"; +const locale = require('locale'); +const storage = require('Storage') +let settings = { + alarm: -1, + dataRow1: "Steps", + dataRow2: "Temp", + dataRow3: "Battery", + speed: "kph", + fullscreen: false, + themeColor1: "Orange", + themeColor1BG: "#FF9900", + themeColor2: "Purple", + themeColor2BG: "#FF00DC", + themeColor3: "Cyan", + themeColor3BG: "#0094FF", +}; +let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; +for (const key in saved_settings) { + settings[key] = saved_settings[key] +} - // initialize with default settings... - const storage = require('Storage') - let settings = { - alarm: -1, - dataRow1: "Battery", - dataRow2: "Steps", - dataRow3: "Temp", - speed: "kph", - fullscreen: false, - themeColor1: "Orange", - themeColor1BG: "#FF9900", - themeColor2: "Purple", - themeColor2BG: "#FF00DC", - themeColor3: "Cyan", - themeColor3BG: "#0094FF", - }; - let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; - for (const key in saved_settings) { - settings[key] = saved_settings[key] +/* + * Colors to use + */ +let cBlue = settings.themeColor1BG; +let cOrange = settings.themeColor2BG; +let cPurple = settings.themeColor3BG; +let cWhite = "#FFFFFF"; +let cBlack = "#000000"; +let cGrey = "#424242"; + +/* + * Global lcars variables + */ +let lcarsViewPos = 0; +// let hrmValue = 0; +var plotMonth = false; + + +/* + * Requirements and globals + */ + + +var bgLeftFullscreen = { + width : 27, height : 176, bpp : 3, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A==")) +}; + +var bgLeftNotFullscreen = { + width : 27, height : 152, bpp : 3, + transparent : 0, + buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=")) +}; + +var bgRightFullscreen = { + width : 27, height : 176, bpp : 3, + transparent : 0, + buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAnUP7y/KH4yGeVYAJrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgAA=")) +}; + +var bgRightNotFullscreen = { + width : 27, height : 152, bpp : 3, + transparent : 0, + buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAxrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgA=")) +}; + +var bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen; +var bgRight= settings.fullscreen ? bgRightFullscreen : bgRightNotFullscreen; + +var iconEarth = { + width : 50, height : 50, bpp : 3, + buffer : require("heatshrink").decompress(atob("AFtx48ECBsDwU5k/yhARLjgjBjlzAQMQEZcIkOP/fn31IEZgCBnlz58cEpM4geugEgwU/8+WNZJHDuHHvgmBCQ8goEOnVgJoMnyV58mACItHI4X8uAFBuVHnnz4BuGxk4////Egz3IkmWvPgNw8f/prB//BghTC+AjE7848eMjNnzySBwUJkmf/BuGuPDAQIjBiPHhhTCSQnjMo0ITANJn44Dg8MuFBggCCiFBcAJ0Bv5xEh+ITo2OhHkyf/OIQdBWwVHhgjBNwUE+fP/5EEgePMoYLBhMgyVJk/+BQQdC688I4XxOIc8v//NAvr+QEBj/5NwKVBy1/QYUciPBhk1EAJrC+KeC489QYaMBgU/8BNB9+ChEjz1Jkn/QYMBDQIgCcYTCCiP/nlzJQmenMAgV4//uy/9wRaB/1J8iVCcAfHjt9TYYICnhKCgRKBw159/v//r927OIeeoASBDQccvv3791KYVDBYPLJQeCnPnz//AAP6ocEjEkXgMgJQtz79fLAP8KYkccAcJ8Gf/f/xu/cAMQ4eP5MlyQRCMolx40YsOGBAPfnnzU4KVDpKMBvz8Dh0/8me7IICgkxJQXPIgZTD58sEgcJk+eNoONnFBhk4/5uB/pcDg5KD+4mEv4CBXISVDhEn31/8/+mH7x//JQK5CAAMB4JBCnnxJQf/+fJEgkAa4L+CAQOOjMn/1bXIRxDJQXx58f//Hhlz/88EgsChMgz/Zs/+nfkyV/8huDOI6SD498NwoACi1Z8+S/Plz17/+QCI7jC+ZxBmfPnojIAAMDcYWSp//2wRJEwq2GABECjMgNYwAmA=")) +}; + +var iconSaturn = { + width : 50, height : 50, bpp : 3, + transparent : 1, + buffer : require("heatshrink").decompress(atob("AH4A/AEkQuPHCJ0ChEAwARNjAjBjgjOhs06Q2OEYVx4ARMhEggUMkANIDoIgBoEEgEBNxJEC6ZrBAAMwNxAjDNYcHNxIjB7dtEwIHBwRoKj158+cuPEjlwCRAjC23bpu0wRNDAAsHEYWeEwaSJ6YjCAQUNSRQjEzxQBWZMNEYlsmg2JWAIjCz95SoJuJggjDtuw6dMG5JKCz998wFBJRVNEYW0yaVBJRNhJQN9+4pCzhKJmBKC4YpB/fINxIgCzFxSoQ3J4ENm3CAQPb98wbpEcAQMYWwKYBNxMDXgc2/fv3g2IEAOAgAjBjy5CEhEMfYICBgfPnjdLjj+CgMHiC3JknDhhoINw4jCAB0IJQIANR4QjPAH4A/AFA")) +}; + +var iconMoon = { + width : 50, height : 50, bpp : 3, + transparent : 1, + buffer : require("heatshrink").decompress(atob("AH4AQjlx44CCCZsg8eOkHDwAQKEYgmPhEgEQM48AOIgMHEYoCB4ATI8UAmH/x04JoRuJsImHuBKLn37EwZuIgEQOI8cEpXj/yYBhE8+YNGgkYoJxITBUPnAaC///nC+FjBuIOJZEB8YeCh/8AoYACoMEEAnEjhQDPQJKJ/DCDAoi5DoLdHAoMQgLjFWYPOnngh02IwXzwDjEgPGEYS8BI4MBYoSVG4fP/nghkAgZrDkngJQqSG4gvBg4sBQgkImHihEAWwP8ZBMBEYl5/+cSoVAGQIUFh04weJn///0gj/OEw5KEz45BzhuCTYQAEgePB4IACAoJuBnAQEa4XHjxKB//xFgWHJQsCRgMDEonipwjENwUBDQNx8+evvn/hTDLw3igE+EgZxB8UOXIvEJQUfEYOfv53DEQkgga5BJQvzx84cAj+CDoNh8/eEYJKDuCSEcocnEon+/7xEgFBIIcfB4Mf/IICXI2DgDdBAAn758gCIq5Dv4zBvJuIOIfjEgvP/ARHgwdCB4P3AoTdFAAk4EYk8SQgAFTALaDSQwAGh08//vnDmBABYmEEZYAzA==")) +}; + +var iconMars = { + width : 50, height : 50, bpp : 3, + transparent : 1, + buffer : require("heatshrink").decompress(atob("AH4ATjlwCJ+Dh0wwAQMg0cuPHjFhCZkDps0yVJkmQCBMEjFx42atOmzQmLhMkEYQCCCREQoOGEYmmzB0IEY4CBkARGoJKBEYQCEzgSGkGSpAjDyYCCphuGiFhJQgCD8ASFgRHGAQKbB6BuHJRGeOIsINxEk6dNmARDgMEjQjHAQPnVQojIyZKB6YSDNwK5FAQt54BuDXJIjBEwK5EgxKKXgq5BJRdgXIojJAQJKMcAM0EwM2JUApDoCVFExa7FkGCgAmIkAREEwUEjAmHCIgABhEggQmFpACBCIojBEwRQCzVhwkQU4YADgQmBwQCCI4IFBCAojFAQojGJQQjDAQgRGEZICBEo4gFyUIkilFJQUYEAZrBAQMYNw5KDSQSbCNwwABgOGEwgCBsPACQ5xGwdNnARJcAVh48evvnCJK8Chs+/fv33gCRcB48cuPHCBYA/ADAA==")) +}; + +var iconSatellite = { + width : 50, height : 50, bpp : 3, + transparent : 2, + buffer : require("heatshrink").decompress(atob("pMkyQC/ATGXhIRPyNl0gmPjlwCJ9ly1aCJ1c+fHJR1Hy1ZJR1I+fPnlx6QRLpe+/JKBr5KMuYjBJQMdCJce/fvJQW0CJUlEYQCBSpvvJQbXJjl0NwnzNxGQwEOnHhgF78+WqQyIrFx48cAQXz4ShJgAABh0+8cP//9LJEhg4jDuP3//0LhGQgYlBgeAn///5cIy8MuAmDCIP/9I4HkmCEYMOgHfCQWkCI0cuBuDgF/CIP+CI1Ny1IkeAgHANwIAB/QRFrj7BhkxEwQRC/4RFpbXDgSVBg4RCSorXDI4MJAQMfCIP8cwImDn37fwN58+kwHgLgSVFub7CI4NyBAJKDLgkuEYX78+evKtCLg0jEYRKC58JMoRcFkwjDJQTFDl65EkojEAQMdcwn/+gFC3YjEJQLXEpYRDWwQmEdI6SHAQO0CJUkx4jDF4gCIJQgRMXIjCEARIjCCJ2XEYPKCJqJBJQIROcAUpCJ0kybaDARtdCKAC2kAA=")) +}; + +var iconCharging = { + width : 50, height : 50, bpp : 3, + transparent : 5, + buffer : require("heatshrink").decompress(atob("23btugAwUBtoICARG0h048eODQYCJ6P/AAUCCJfbo4SDxYRLtEcuPHjlwgoRJ7RnIloUHoYjDAQfAExEAwUIkACEkSAIEYwCBhZKH6EIJI0CJRFHEY0BJRWBSgf//0AJRYSE4BKLj4SE8BKLv4RD/hK/JS2AXY0gXwRKG4cMmACCJQMAg8csEFJQsBAwfasEAm379u0gFbcBfHzgFBz1xMQZKBjY/D0E2+BOChu26yVEEYdww+cgAFCg+cgIfB6RKF4HbgEIkGChEAthfCJQ0eEAIjBBAMxk6GCJQtgtyVBwRKBAQMbHAJKGXIIFCgACBhl54qVG2E+EAJKBJoWAm0WJQ6SCXgdxFgMLJQvYjeAEAUwFIUitEtJQ14NwUHgEwKYZKGwOwNYX7XgWCg3CJQ5rB4MevPnAoPDJRJrCgEG/ECAoNsJRUwoEesIIBiJKI3CVDti/CJRKVDiJHBSo0YsOGjED8AjBcAcIgdhcAXAPIUAcAYIBcA4dBAQUG8BrBgBuCgOwcBEeXIK2BBAIFBgRqBGoYAChq8CcYUE4FbUYOACQsHzgjDgwFBCIImBAQsDtwYD7cAloRI22B86YBw5QBgoRJ7dAgYEDCJaeBJoMcsARMAQNoJIIRE6A")) +}; + +var iconNoBattery = { + text: "NO BAT", + width : 50, height : 50, bpp : 3, + transparent : 1, + buffer : require("heatshrink").decompress(atob("kmSpIC/AWMyoQIFsmECJFJhMmA4QXByVICIwODAQ4RRFIQGD5JVLkIGDzJqMyAGDph8MiRKGyApEAoZKFyYIDQwMkSQNkQZABBhIIOOJRuEL5gRIAUKACVQMhmUSNYNDQYJTBBwYFByGTkOE5FJWYNMknCAQKYCiaSCpmGochDoSYBhMwTAZrChILBhmEzKPBF4ImBTAREBDoMmEwJVDoYjBycJFgWEJQRuLJQ1kmQCCjJlCBYbjCagaDBwyDBmBuBF4TjJAUQKINBChCDQxZBcZIIQF4NIgEAgKSDiQmEVQKMBoARBAAMCSQLLBVoxqKL4gaCChVCNwoRKOIo4CJIgABBoSMHpIRFgDdJOIJUBCAUJRgJuEAQb+DIIgRIAX4C/ASOQA")) +}; + +// Font to use: +// +Graphics.prototype.setFontAntonioMedium = function(scale) { + // Actual height 20 (19 - 0) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAA//mP/5gAAAAAAAAAAAAA/gAMAAAAAA/gAPAAAEIIBP+H/8D+IYBP+H/8D+IABCAAwIAfnwP8+PHh448eP3+B4fAAAAAAAH/AD/4AwGAMBgD/4Af8GAAPgAPgAfgAfAAfAA+AAOP/AH/4BgGAYBgH/4A/8AAAAAAAAAQAA/B+f4/+GMPhjv/4/h8Dg/gAcYwAAPwADgAAAAAAAAB//8///sAAaAACAAAMAAb//+f//AAAAAAAbAAGwAA4AA/wADgABsAAbAAAAAAAgAAMAAPwAD8AAMAADAAAAAAAAAAHAAB/AAOAAAAAAAAMAADAAAwAAMAACAAAAAAAAAABgAAYAAAAAAAAA4AD+AP+A/4A/gAOAAAAAAAAAH//j//8wADMAAz//8f/+AAAAAAAMAADAABgAA//+P//gAAAAAAAAAAAAAfgfP4fzAfswfDP/gx/gMAAAHgPj4D8wMDMHAz//8f3+AAEAAAAADwAH8APzA/AwP//j//4AAwAAAD/Hw/x+MwBjOAYz/+Mf/AAAAAAAH//j//8wYDMGAz9/8fP+AAcDAAAwAAMAfjB/4z/wP+AD4AAwAAAAOB/f4///MHAzBwM///H9/gAAAAAAH/Pj/78wGDMBgz//8f/+AAAAAAADhwA4cAAAAAAAAAAAAAADh/A4fgAAAAOAAHwABsAA7gAccAGDAAAAANgADYAA2AANgADYAA2AAAAAAAABgwAccADuAAbAAHwAA4AAAAHwAD8c4/POMHAD/wAfwAAAAAAAAD/wD//B4B4Y/HMf8zMBMyATMwczP+M4BzHwcgf+AA+AAAAAAD4A/+P/8D+DA/4wH/+AB/4AAeAAAAAAA//+P//jBgYwYGP//j//4PH4AAAAAAAf/+P//zgAcwADP4fz+P4Ph8AAAAAAA//+P//jAAYwAGPADj//4P/4AAAAAAA//+P//jBgYwYGMGBgAAAAAAP//j//4wYAMGADBgAAAAAAAA//w///PAHzAQM4MHP7/x+/8AAAAAAD//4//+AGAABgAAYAP//j//4AAAAAAAAAA//+P//gAAAAAAAAAAAHwAB+AABgAAY//+P//AAAAAAAAAAD//4//+APgAf+Afj8PgPjAAYAAAAAAD//4//+AABgAAYAAGAAAAAAA//+P//j/gAD/wAB/gAP4B/4P/AD//4//+AAAAAAAAAAP//j//4P4AAfwAA/g//+P//gAAAAAAAAAA//g//+PAHjAAY4AOP//h//wAAAAAAD//4//+MDADAwA4cAP/AB/gAAAAAAAA//g//+PAHjAAc4APv//5//yAAAAAAD//4//+MGADBgA48AP//h+f4AAAAAAB+Pw/z+MOBjBwY/P+Hx/AAHgwAAMAAD//4//+MAADAAAAAAP//D//4AAOAABgAA4//+P//AAAAwAAP8AD//AA/+AAfgP/4//gPwAAAAA+AAP/4Af/4AD+A//j/wA/wAD/+AA/4B/+P/+D+AAAAAMADj8P4P/4A/4B//w+A+MABgAAA4AAPwAB/gAB/+A//j/gA+AAMAAAAAYwB+MH/jf+Y/8GPwBjAAAAAAP//7//+wABsAAYAAAAAAPAAD/gAH/gAD/gAD4AACAAADAAGwABv//7//+AAAA=="), 32, atob("BQUHCAgVCQQFBQkHBQcFBwgICAgICAgICAgFBQcHBwgPCQkJCQcHCQoFCQkHDQoJCQkJCAYJCQ0ICAcGBwY="), 20+(scale<<8)+(1<<16)); +}; + +Graphics.prototype.setFontAntonioLarge = function(scale) { + // Actual height 39 (39 - 1) + g.setFontCustom(atob("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8AAAAAAPgAAAAAB8AAAAAAHgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgAAAAAD8AAAAAH/gAAAAP/8AAAAf//gAAA///AAAB//+AAAD//8AAAH//4AAAP//wAAAB//gAAAAP/AAAAAB+AAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH///AAAf////8AP/////4B//////Af/////8D8AAAAfgeAAAAA8DwAAAAHgeAAAAA8D//////gf/////8B//////AP/////wAf////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8AAAAAAHgAAAAAA8AAAAAAPgAAAAAB4AAAAAAf/////gP/////8B//////gP/////8B//////gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/wAAAAD/+AAP8A//wAP/gP/+AH/8D//wD//gfgAA//8DwAAf+HgeAAP/A8DwAH/gHgfgP/wA8D///4AHgP//+AA8A///AAHgB//AAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4AA/gAD/AAH/gA/4AA/+AP/AAH/4D/4AA//gfgA4AB8DwAPAAHgeAB4AA8DwAPgAHgfAD+AB8D//////gP/////4B//5//+AD/+H//gAH/AH/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP4AAAAAP/AAAAAP/4AAAAP//AAAAP/x4AAAf/wPAAAf/gB4AAf/AAPAAP/AAB4AB//////gP/////8B//////gP/////8AAAAAPAAAAAAB4AAAAAAPAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//wD/AB///Af+AP//4D/4B///Af/gP//4B/8B4D4AAPgPAeAAA8B4DwAAHgPAfAAB8B4D////gPAf///4B4B////APAD///gAAAD//gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB///AAAP////4AH/////wB//////Af/////8D8APAA/geADwAB8DwAeAAHgeADwAA8D4AeAAPgf/j+AH8B/8f///gP/h///4Af8H//+AAPgP//AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4AAAAAAPAAAAAAB4AAAABgPAAAA/8B4AAB//gPAAD//8B4AH///gPAH///8B4P//+AAPH//wAAB///gAAAP//AAAAB/+AAAAAP+AAAAAB+AAAAAAOAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/4A/+AAf/w//+AP//v//4B//////Af/////8D4AfwAPgeAB8AA8DwAHAAHgeAB8AA8D4Af4APgf/////8B//////AP//v//4A//4//8AA/4A/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH/+AAAAD//+D/gB///4f+AP///j/4D///8f/gfAAHgB8DwAA8AHgeAAHgA8DwAA8AHgfgAHgB8D//////gP/////4A/////+AD/////gAD////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPwAfgAAB+AD8AAAPwAfgAAB+AD8AAAPwAfgAAAAAAAAAAAAAAAAAAAAAAAA=="), 46, atob("DBATExMTExMTExMTCw=="), 45+(scale<<8)+(1<<16)); +}; + + +/* + * Draw watch face + */ +var drawTimeout; +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); +} + +/** + * This function plots a data row in LCARS style. + * Note: It can be called async and therefore, the text alignment and + * font is set each time the function is called. + */ +function printRow(text, value, y, c){ + g.setFontAntonioMedium(); + g.setFontAlign(-1,-1,0); + + // Print background + g.setColor(c); + g.setFontAlign(-1,-1,0); + g.fillRect(80, y-2, 165 ,y+18); + g.fillCircle(163, y+8, 10); + g.setColor(cBlack); + g.drawString(text, 135, y); + + // Plot text + width = g.stringWidth(value); + g.setColor(cBlack); + g.fillRect(130-width-8, y-2, 130, y+18); + g.setColor(c); + g.setFontAlign(1,-1,0); + g.drawString(value, 126, y); +} + + +function drawData(key, y, c){ + try{ + _drawData(key, y, c); + } catch(ex){ + // Show last error - next try hopefully works. + } +} + + +function _drawData(key, y, c){ + key = key.toUpperCase() + var text = key; + var value = "ERR"; + var should_print= true; + + if(key == "STEPS"){ + text = "STEP"; + value = getSteps(); + + } else if(key == "BATTERY"){ + text = "BAT"; + value = E.getBattery() + "%"; + + } else if (key == "VREF"){ + value = E.getAnalogVRef().toFixed(2) + "V"; + + } else if(key == "HRM"){ + value = Math.round(Bangle.getHealthStatus("day").bpm); + + } else if (key == "TEMP"){ + var weather = getWeather(); + value = weather.temp; + + } else if (key == "HUMIDITY"){ + text = "HUM"; + var weather = getWeather(); + value = weather.hum; + + } else if (key == "WIND"){ + text = "WND"; + var weather = getWeather(); + value = weather.wind; + + } else if (key == "ALTITUDE"){ + should_print= false; + text = "ALT"; + + // Immediately print something - avoid that its empty + printRow(text, "", y, c); + Bangle.getPressure().then(function(data){ + if(data && data.altitude){ + value = Math.round(data.altitude); + printRow(text, value, y, c); + } + }) + + } else if(key == "CORET"){ + value = locale.temp(parseInt(E.getTemperature())); } - function save() { - storage.write(SETTINGS_FILE, settings) + // Print for all datapoints that are not async + if(should_print){ + printRow(text, value, y, c); + } +} + +function drawHorizontalBgLine(color, x1, x2, y, h){ + g.setColor(color); + + for(var i=0; i dataOptions[v], - onchange: v => { - settings.dataRow1 = dataOptions[v]; - save(); - }, - }, - 'Row 2': { - value: 0 | dataOptions.indexOf(settings.dataRow2), - min: 0, max: 8, - format: v => dataOptions[v], - onchange: v => { - settings.dataRow2 = dataOptions[v]; - save(); - }, - }, - 'Row 3': { - value: 0 | dataOptions.indexOf(settings.dataRow3), - min: 0, max: 8, - format: v => dataOptions[v], - onchange: v => { - settings.dataRow3 = dataOptions[v]; - save(); - }, - }, - 'Full Screen': { - value: settings.fullscreen, - format: () => (settings.fullscreen ? 'Yes' : 'No'), - onchange: () => { - settings.fullscreen = !settings.fullscreen; - save(); - }, - }, - 'Speed': { - value: 0 | speedOptions.indexOf(settings.speed), - min: 0, max: 1, - format: v => speedOptions[v], - onchange: v => { - settings.speed = speedOptions[v]; - save(); - }, - }, - 'Theme Color 1': { - value: 0 | color_options.indexOf(settings.themeColor1), - min: 0, max: 7, - format: v => color_options[v], - onchange: v => { - settings.themeColor1 = color_options[v]; - settings.themeColor1BG = bg_code[v]; - save(); - }, - }, - 'Theme Color 2': { - value: 0 | color_options.indexOf(settings.themeColor2), - min: 0, max: 7, - format: v => color_options[v], - onchange: v => { - settings.themeColor2 = color_options[v]; - settings.themeColor2BG = bg_code[v]; - save(); - }, - }, - 'Theme Color 3': { - value: 0 | color_options.indexOf(settings.themeColor3), - min: 0, max: 7, - format: v => color_options[v], - onchange: v => { - settings.themeColor3 = color_options[v]; - settings.themeColor3BG = bg_code[v]; - save(); - }, + if(NRF.getSecurityStatus().connected){ + g.drawString("CONN", 128, 33); + } else { + g.drawString("NOCON", 128, 33); + } + if(Bangle.isLocked()){ + g.setColor(cPurple); + g.drawString("LOCK", 128, 53); + } +} + +function drawState(){ + if(lcarsViewPos != 0){ + return; + } + + g.clearRect(20, 93, 75, 170); + g.setFontAlign(0, 0, 0); + g.setFontAntonioMedium(); + + if(!isAlarmEnabled()){ + var bat = E.getBattery(); + var current = new Date(); + var hours = current.getHours(); + var iconImg = + Bangle.isCharging() ? iconCharging : + bat < 30 ? iconNoBattery : + Bangle.isGPSOn() ? iconSatellite : + hours % 4 == 0 ? iconSaturn : + hours % 4 == 1 ? iconMars : + hours % 4 == 2 ? iconMoon : + iconEarth; + g.drawImage(iconImg, 23, 118); + g.setColor(cWhite); + g.drawString("STATUS", 23+26, 108); + } else { + // Alarm within symbol + g.setColor(cOrange); + g.drawString("ALARM", 23+26, 108); + g.setColor(cWhite); + g.setFontAntonioLarge(); + g.drawString(getAlarmMinutes(), 23+26, 108+35); + } + + g.setFontAlign(-1, -1, 0); +} + + +function drawPosition0(){ + // Draw background image + var offset = settings.fullscreen ? 0 : 24; + g.drawImage(bgLeft, 0, offset); + drawHorizontalBgLine(cBlue, 25, 120, offset, 4); + drawHorizontalBgLine(cBlue, 130, 176, offset, 4); + drawHorizontalBgLine(cPurple, 20, 70, 80, 4); + drawHorizontalBgLine(cPurple, 80, 176, 80, 4); + drawHorizontalBgLine(cOrange, 35, 110, 87, 4); + drawHorizontalBgLine(cOrange, 120, 176, 87, 4); + + // The last line is a battery indicator too + var bat = E.getBattery() / 100.0; + var batStart = 19; + var batWidth = 172 - batStart; + var batX2 = parseInt(batWidth * bat + batStart); + drawHorizontalBgLine(cOrange, batStart, batX2, 171, 5); + drawHorizontalBgLine(cGrey, batX2, 172, 171, 5); + for(var i=0; i+batStart<=172; i+=parseInt(batWidth/4)){ + drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8) + } + + // Draw Infos + drawInfo(); + + // Write time + g.setFontAlign(-1, -1, 0); + g.setColor(cWhite); + var currentDate = new Date(); + var timeStr = locale.time(currentDate,1); + g.setFontAntonioLarge(); + if(settings.fullscreen){ + g.drawString(timeStr, 27, 10); + } else { + g.drawString(timeStr, 27, 33); + } + + // Write date + g.setColor(cWhite); + g.setFontAntonioMedium(); + if(settings.fullscreen){ + var dayStr = locale.dow(currentDate, true).toUpperCase(); + dayStr += " " + currentDate.getDate(); + dayStr += " " + locale.month(currentDate, 1).toUpperCase(); + g.drawString(dayStr, 30, 56); + } else { + var dayStr = locale.dow(currentDate, true).toUpperCase(); + var date = currentDate.getDate(); + g.drawString(dayStr, 128, 35); + g.drawString(date, 128, 55); + } + + // Draw data + g.setFontAlign(-1, -1, 0); + g.setColor(cWhite); + drawData(settings.dataRow1, 97, cOrange); + drawData(settings.dataRow2, 122, cPurple); + drawData(settings.dataRow3, 147, cBlue); + + // Draw state + drawState(); +} + +function drawPosition1(){ + // Draw background image + var offset = settings.fullscreen ? 0 : 24; + g.drawImage(bgRight, 149, offset); + if(settings.fullscreen){ + drawHorizontalBgLine(cBlue, 0, 140, offset, 4); + } + drawHorizontalBgLine(cPurple, 0, 80, 80, 4); + drawHorizontalBgLine(cPurple, 90, 150, 80, 4); + drawHorizontalBgLine(cOrange, 0, 50, 87, 4); + drawHorizontalBgLine(cOrange, 60, 140, 87, 4); + drawHorizontalBgLine(cOrange, 0, 150, 171, 5); + + // Draw steps bars + g.setColor(cWhite); + let health; + + try { + health = require("health"); + } catch(ex) { + g.setFontAntonioMedium(); + g.drawString("MODULE HEALTH", 20, 110); + g.drawString("REQUIRED.", 20, 130); + g.drawString("MODULE HEALTH", 20, 20); + g.drawString("REQUIRED.", 20, 40); + return; + } + + // Plot HRM graph + if(plotMonth){ + var data = new Uint16Array(32); + var cnt = new Uint8Array(32); + health.readDailySummaries(new Date(), h=>{ + data[h.day]+=h.bpm; + if (h.bpm) cnt[h.day]++; + }); + require("graph").drawBar(g, data, { + axes : true, + minx: 1, + gridx : 5, + gridy : 100, + width : 140, + height : 50, + x: 5, + y: 25 + }); + + // Plot step graph + var data = new Uint16Array(32); + health.readDailySummaries(new Date(), h=>data[h.day]+=h.steps/1000); + var gridY = parseInt(Math.max.apply(Math, data)/2); + gridY = gridY <= 0 ? 1 : gridY; + require("graph").drawBar(g, data, { + axes : true, + minx: 1, + gridx : 5, + gridy : gridY, + width : 140, + height : 50, + x: 5, + y: 115 + }); + + g.setFontAlign(1, 1, 0); + g.setFontAntonioMedium(); + g.setColor(cWhite); + + if(settings.fullscreen){ + g.drawString("M-HRM", 154, 27); + g.drawString("M-STEPS [K]", 154, 115); + } else { + g.drawString("MONTH", 154, 115); } + + // Plot day + } else { + var data = new Uint16Array(24); + var cnt = new Uint8Array(24); + health.readDay(new Date(), h=>{ + data[h.hr]+=h.bpm; + if (h.bpm) cnt[h.hr]++; + }); + require("graph").drawBar(g, data, { + axes : true, + minx: 1, + gridx : 4, + gridy : 100, + width : 140, + height : 50, + x: 5, + y: 25 + }); + + // Plot step graph + var data = new Uint16Array(24); + health.readDay(new Date(), h=>data[h.hr]+=h.steps); + var gridY = parseInt(Math.max.apply(Math, data)/1000)*1000; + gridY = gridY <= 0 ? 1000 : gridY; + require("graph").drawBar(g, data, { + axes : true, + minx: 1, + gridx : 4, + gridy : gridY, + width : 140, + height : 50, + x: 5, + y: 115 + }); + + g.setFontAlign(1, 1, 0); + g.setFontAntonioMedium(); + g.setColor(cWhite); + + if(settings.fullscreen){ + g.drawString("D-HRM", 154, 27); + g.drawString("D-STEPS", 154, 115); + } else { + g.drawString("DAY", 154, 115); + } + } +} + +function draw(){ + // Queue draw first to ensure that its called in one minute again. + queueDraw(); + + // First handle alarm to show this correctly afterwards + handleAlarm(); + + // Next draw the watch face + g.reset(); + g.clearRect(0, 0, g.getWidth(), g.getHeight()); + + // Draw current lcars position + if(lcarsViewPos == 0){ + drawPosition0(); + } else if (lcarsViewPos == 1) { + drawPosition1(); + } + + // After drawing the watch face, we can draw the widgets + if(settings.fullscreen){ + for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} + } else { + Bangle.drawWidgets(); + } +} + + +/* + * Step counter via widget + */ +function getSteps() { + try{ + if (WIDGETS.wpedom !== undefined) { + return WIDGETS.wpedom.getSteps(); + } else if (WIDGETS.activepedom !== undefined) { + return WIDGETS.activepedom.getSteps(); + } + } catch(ex) { + // In case we failed, we can only show 0 steps. + } + + return 0; +} + + +function getWeather(){ + var weatherJson; + + try { + weatherJson = storage.readJSON('weather.json'); + } catch(ex) { + // Return default + } + + if(weatherJson === undefined){ + return { + temp: "-", + hum: "-", + txt: "-", + wind: "-", + wdir: "-", + wrose: "-" + }; + } + + var weather = weatherJson.weather; + + // Temperature + weather.temp = locale.temp(weather.temp-273.15); + + // Humidity + weather.hum = weather.hum + "%"; + + // Wind + const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + var speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934; + weather.wind = Math.round(wind[1] * speedFactor); + + return weather +} + + +/* + * Handle alarm + */ +function getCurrentTimeInMinutes(){ + return Math.floor(Date.now() / (1000*60)); +} + +function isAlarmEnabled(){ + return settings.alarm >= 0; +} + +function getAlarmMinutes(){ + var currentTime = getCurrentTimeInMinutes(); + return settings.alarm - currentTime; +} + +function handleAlarm(){ + if(!isAlarmEnabled()){ + return; + } + + if(getAlarmMinutes() > 0){ + return; + } + + // Alarm + var t = 300; + Bangle.buzz(t, 1) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, t))) + .then(() => Bangle.buzz(t, 1)) + .then(() => new Promise(resolve => setTimeout(resolve, 5E3))) + .then(() => { + // Update alarm state to disabled + settings.alarm = -1; + storage.writeJSON(SETTINGS_FILE, settings); }); -}) +} + + +/* + * Listeners + */ +Bangle.on('lcdPower',on=>{ + if (on) { + // Whenever we connect to Gadgetbridge, reading data from + // health failed. Therefore, we update only partially... + drawInfo(); + drawState(); + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +Bangle.on('lock', function(isLocked) { + drawInfo(); +}); + +Bangle.on('charging',function(charging) { + drawState(); +}); + + +function increaseAlarm(){ + if(isAlarmEnabled() && getAlarmMinutes() < 95){ + settings.alarm += 5; + } else { + settings.alarm = getCurrentTimeInMinutes() + 5; + } + + storage.writeJSON(SETTINGS_FILE, settings); +} + + +function decreaseAlarm(){ + if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){ + settings.alarm -= 5; + } else { + settings.alarm = -1; + } + + storage.writeJSON(SETTINGS_FILE, settings); +} + +function feedback(){ + Bangle.buzz(40, 0.3); +} + +// Touch gestures to control clock. We don't use swipe to be compatible with the bangle ecosystem +Bangle.on('touch', function(btn, e){ + var left = parseInt(g.getWidth() * 0.2); + var right = g.getWidth() - left; + var upper = parseInt(g.getHeight() * 0.2); + var lower = g.getHeight() - upper; + + var is_left = e.x < left; + var is_right = e.x > right; + var is_upper = e.y < upper; + var is_lower = e.y > lower; + + if(is_left && lcarsViewPos == 1){ + feedback(); + lcarsViewPos = 0; + draw(); + return; + + } else if(is_right && lcarsViewPos == 0){ + feedback(); + lcarsViewPos = 1; + draw(); + return; + } + + if(lcarsViewPos == 0){ + if(is_upper){ + feedback(); + increaseAlarm(); + drawState(); + return; + } if(is_lower){ + feedback(); + decreaseAlarm(); + drawState(); + return; + } + } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotMonth != is_lower){ + feedback(); + plotMonth = is_lower; + draw(); + return; + } +}); + + +/* + * Lets start widgets, listen for btn etc. + */ +// Show launcher when middle button pressed +Bangle.setUI("clock"); +Bangle.loadWidgets(); + +// Clear the screen once, at startup and draw clock +g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); +draw(); From b364c4f26653bb109d317c56708f21ee631393a3 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:34:14 -0700 Subject: [PATCH 195/312] Update lcars.settings.js --- apps/lcars/lcars.settings.js | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 75add1ece..f714c3a7a 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -10,6 +10,12 @@ dataRow3: "Temp", speed: "kph", fullscreen: false, + themeColor1: "Orange", + themeColor1BG: "#FF9900", + themeColor2: "Purple", + themeColor2BG: "#FF00DC", + themeColor3: "Cyan", + themeColor3BG: "#0094FF", }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; for (const key in saved_settings) { @@ -20,8 +26,11 @@ storage.write(SETTINGS_FILE, settings) } + var dataOptions = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"]; var speedOptions = ["kph", "mph"]; + var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White']; + var bg_code = ['#0f0','#FF9900','#0094FF','#FF00DC','#f00','#00f','#ffef00','#FFFFFF']; E.showMenu({ '': { 'title': 'LCARS Clock' }, @@ -69,6 +78,36 @@ settings.speed = speedOptions[v]; save(); }, + }, + 'Theme Color 1': { + value: 0 | color_options.indexOf(settings.themeColor1), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor1 = color_options[v]; + settings.themeColor1BG = bg_code[v]; + save(); + }, + }, + 'Theme Color 2': { + value: 0 | color_options.indexOf(settings.themeColor2), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor2 = color_options[v]; + settings.themeColor2BG = bg_code[v]; + save(); + }, + }, + 'Theme Color 3': { + value: 0 | color_options.indexOf(settings.themeColor3), + min: 0, max: 7, + format: v => color_options[v], + onchange: v => { + settings.themeColor3 = color_options[v]; + settings.themeColor3BG = bg_code[v]; + save(); + }, } }); }) From 3eea59ac5ac5b12cb8fa7a66ecec6fd3e1641954 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Mon, 11 Apr 2022 07:35:45 -0700 Subject: [PATCH 196/312] Update README.md --- apps/lcars/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 7024e8edf..65e31b3cc 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -19,6 +19,7 @@ the "sched" app must be installed on your device. * Tap on top/bottom of screen 1 to activate an alarm. Depends on widtmr. * The lower orange line indicates the battery level. * Display graphs (day or month) for steps + hrm on the second screen. + * Customizable theming colors in the settings menu of the app. ## Data that can be configured * Steps - Steps loaded via the wpedom app. @@ -43,3 +44,4 @@ Access different screens via tap on the left/ right side of the screen ## Contributors - [Adam Schmalhofer](https://github.com/adamschmalhofer) - [Jon Warrington](https://github.com/BartokW) +- [Ronin Stegner](https://github.com/Ronin0000) From c3a5f79be163aa2d6c00d00cdb8320b034c854c5 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Mon, 11 Apr 2022 16:37:16 +0200 Subject: [PATCH 197/312] Added app name for Signal --- apps/ios/boot.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/ios/boot.js b/apps/ios/boot.js index 0659fd105..a3b23a79d 100644 --- a/apps/ios/boot.js +++ b/apps/ios/boot.js @@ -108,6 +108,7 @@ E.on('notify',msg=>{ "net.superblock.Pushover": "Pushover", "nl.ah.Appie": "Albert Heijn", "nl.postnl.TrackNTrace": "PostNL", + "org.whispersystems.signal": "Signal", "ph.telegra.Telegraph": "Telegram", "tv.twitch": "Twitch", From f9838cd101c7b30cc88af7048a52bf8628597d91 Mon Sep 17 00:00:00 2001 From: Kevin Whitaker Date: Mon, 11 Apr 2022 13:10:12 -0400 Subject: [PATCH 198/312] update drawing code to use rounded rectangles on newer firmware. --- apps/red7game/red7.js | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/apps/red7game/red7.js b/apps/red7game/red7.js index 38afb775e..2b22488b9 100644 --- a/apps/red7game/red7.js +++ b/apps/red7game/red7.js @@ -35,19 +35,27 @@ class Card { get clipRect() { return this.clippedRect; } + fillRect(x,y,x2,y2,r) { + //This function allows using new rounded corners on newer firmware + if(process.env.VERSION === "2v12" || process.env.VERSION === "2v11" || process.env.VERSION === "2v10") { + g.fillRect(x,y,x2,y2); + } else { + g.fillRect({x:x,y:y,x2:x2,y2:y2,r:r}); + } + } draw(x,y,outlined) { this.rect = {x1: x, x2: x+80, y1: y, y2: y+100}; this.clippedRect = {x1: x, x2: x+24, y1: y, y2: y+100}; var colorIndex = colors.indexOf(this.cardColor); var colorArr = colorsHex[colorIndex]; var colorRule = colorsRules[colorIndex]; - g.setColor(colorArr); - g.setBgColor(colorArr); - g.fillRect(x,y,x+80,y+100); if(outlined) { g.setColor(0,0,0); - g.drawRect(x,y,x+80,y+100); + this.fillRect(x-1,y-1,x+81,y+101,6); } + g.setColor(colorArr); + g.setBgColor(colorArr); + this.fillRect(x,y,x+80,y+100,6); g.setColor(255,255,255); g.setFont("Vector:40"); g.setFontAlign(0,0,0); @@ -61,21 +69,23 @@ class Card { drawBack(x,y,flipped) { this.rect = {x1: x, x2: x+80, y1: y, y2: y-100}; this.clippedRect = {x1: x, x2: x+24, y1: y, y2: y-100}; - g.setColor(255,255,255); g.setBgColor(0,0,0); if(flipped) { - g.fillRect(x,y,x+80,-100); g.setColor(0,0,0); - g.drawRect(x,y,x+80,-100); + this.fillRect(x-1,y+1,x+81,y-101,6); + g.setColor(255,255,255); + this.fillRect(x,y,x+80,y-100,6); g.setFontAlign(0,0,2); g.setColor(255,0,0); g.setBgColor(255,255,255); g.setFont("Vector:40"); //g.drawString(7,x+40,y-40,true); } else { - g.fillRect(x,y,x+80,y+100); g.setColor(0,0,0); - g.drawRect(x,y,x+80,y+100); + this.fillRect(x-1,y-1,x+81,y+101,6); + g.setColor(255,255,255); + this.fillRect(x,y,x+80,y+100,6); + g.setColor(0,0,0); g.setFontAlign(0,0,0); g.setColor(255,0,0); g.setBgColor(255,255,255); @@ -91,7 +101,7 @@ class Card { var colorRule = colorsRules[colorIndex]; g.setColor(colorArr); g.setBgColor(colorArr); - g.fillRect(x,y,x+110,y+45); + this.fillRect(x,y,x+110,y+45,6); g.setColor(255,255,255); g.setFontAlign(0,0,0); g.setFont("6x8:2"); @@ -104,7 +114,7 @@ class Card { var colorArr = colorsHex[colorIndex]; g.setColor(colorArr); g.setBgColor(colorArr); - g.fillRect(x,y,x+20,y+20); + this.fillRect(x,y,x+20,y+20,2); g.setFontAlign(0,0,0); g.setFont("6x8:2"); g.setColor(255,255,255); From ee6825d371b4d23fcc28b7d2242c3819a5c88a8f Mon Sep 17 00:00:00 2001 From: Kevin Whitaker Date: Mon, 11 Apr 2022 13:13:34 -0400 Subject: [PATCH 199/312] update red7 app for release --- apps/red7game/ChangeLog | 7 ++++--- apps/red7game/metadata.json | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/red7game/ChangeLog b/apps/red7game/ChangeLog index 25dd4828d..360b1a305 100644 --- a/apps/red7game/ChangeLog +++ b/apps/red7game/ChangeLog @@ -1,3 +1,4 @@ -1.0: Initial version of game -1.0.1: Fix mistake preventing game from ending in some cases. -1.0.2: Update help screen with more details. +0.01: Initial version of game +0.02: Fix mistake preventing game from ending in some cases. +0.03: Update help screen with more details. +0.04: Update cards to draw rounded on newer firmware. Make sure in-game menu can't be pulled up during end of game. diff --git a/apps/red7game/metadata.json b/apps/red7game/metadata.json index c3c788608..15fec4d21 100644 --- a/apps/red7game/metadata.json +++ b/apps/red7game/metadata.json @@ -2,7 +2,7 @@ "name": "Red 7 Card Game", "shortName" : "Red 7", "icon": "icon.png", - "version":"1.0.2", + "version":"0.04", "description": "An implementation of the card game Red 7 for your watch. Play against the AI and be the last player still in the game to win!", "tags": "game", "supports":["BANGLEJS2"], From 05e390dea2caa5e492fae2b26e44786617444dc1 Mon Sep 17 00:00:00 2001 From: David Peer Date: Mon, 11 Apr 2022 20:05:48 +0200 Subject: [PATCH 200/312] Center date correctly --- apps/bwclk/app.js | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 9bb1ed4cd..97f3a14af 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -252,17 +252,26 @@ function draw() { // Draw date y -= settings.fullscreen ? 8 : 0; var date = new Date(); - g.setColor(g.theme.fg); - g.setFontAlign(1,1); - g.setMediumFont(); var dateStr = date.getDate(); dateStr = ("0" + dateStr).substr(-2); - g.drawString(dateStr, W/2-1, y+4); + g.setMediumFont(); // Needed to compute the width correctly + var dateW = g.stringWidth(dateStr); g.setSmallFont(); + var dayStr = locale.dow(date, true); + var monthStr = locale.month(date, 1); + var dayW = Math.max(g.stringWidth(dayStr), g.stringWidth(monthStr)); + var fullDateW = dateW + 10 + dayW; + g.setFontAlign(-1,1); - g.drawString(locale.dow(date, true), W/2 + 10, y-23); - g.drawString(locale.month(date, 1), W/2 + 10, y+1); + g.setMediumFont(); + g.setColor(g.theme.fg); + g.drawString(dateStr, W/2 - fullDateW / 2, y+4); + + g.setSmallFont(); + g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+4); + g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-23); + // Draw time g.setColor(g.theme.bg); From 544cebf8d084be36de60fe9736b7005be8d17f1b Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 08:36:49 -0700 Subject: [PATCH 201/312] Create appb2.js --- apps/choozi/appb2.js | 209 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 209 insertions(+) create mode 100644 apps/choozi/appb2.js diff --git a/apps/choozi/appb2.js b/apps/choozi/appb2.js new file mode 100644 index 000000000..d5c542be3 --- /dev/null +++ b/apps/choozi/appb2.js @@ -0,0 +1,209 @@ +//g.setTheme({fg : 0xFFFF, fg2 : 0xFFFF,bg2 : 0x0007,fgH : 0xFFFF,bgH : 0x02F7,dark : true}); + + +/* Choozi - Choose people or things at random using Bangle.js. + * Inspired by the "Chwazi" Android app + * + * James Stanley 2021 + */ + +var colours = ['#ff0000', '#ff8080', '#00ff00', '#80ff80', '#0000ff', '#8080ff', '#ffff00', '#00ffff', '#ff00ff', '#ff8000', '#ff0080', '#8000ff', '#0080ff']; + +var stepAngle = 0.18; // radians - resolution of polygon +var gapAngle = 0.035; // radians - gap between segments +var perimMin = 80; // px - min. radius of perimeter +var perimMax = 87; // px - max. radius of perimeter + +var segmentMax = 70; // px - max radius of filled-in segment +var segmentStep = 5; // px - step size of segment fill animation +var circleStep = 4; // px - step size of circle fill animation + +// rolling ball animation: +var maxSpeed = 0.08; // rad/sec +var minSpeed = 0.001; // rad/sec +var animStartSteps = 300; // how many steps before it can start slowing? +var accel = 0.0002; // rad/sec/sec - acc-/deceleration rate +var ballSize = 3; // px - ball radius +var ballTrack = 75; // px - radius of ball path + +var centreX = 88; // px - centre of screen +var centreY = 88; // px - centre of screen + +var fontSize = 50; // px + +var radians = 2*Math.PI; // radians per circle + +var defaultN = 3; // default value for N +var minN = 2; +var maxN = colours.length; +var N; +var arclen; + +// https://www.frankmitchell.org/2015/01/fisher-yates/ +function shuffle (array) { + var i = 0 + , j = 0 + , temp = null; + + for (i = array.length - 1; i > 0; i -= 1) { + j = Math.floor(Math.random() * (i + 1)); + temp = array[i]; + array[i] = array[j]; + array[j] = temp; + } +} + +// draw an arc between radii minR and maxR, and between +// angles minAngle and maxAngle +function arc(minR, maxR, minAngle, maxAngle) { + var step = stepAngle; + var angle = minAngle; + var inside = []; + var outside = []; + var c, s; + while (angle < maxAngle) { + c = Math.cos(angle); + s = Math.sin(angle); + inside.push(centreX+c*minR); // x + inside.push(centreY+s*minR); // y + // outside coordinates are built up in reverse order + outside.unshift(centreY+s*maxR); // y + outside.unshift(centreX+c*maxR); // x + angle += step; + } + c = Math.cos(maxAngle); + s = Math.sin(maxAngle); + inside.push(centreX+c*minR); + inside.push(centreY+s*minR); + outside.unshift(centreY+s*maxR); + outside.unshift(centreX+c*maxR); + + var vertices = inside.concat(outside); + g.fillPoly(vertices, true); +} + +// draw the arc segments around the perimeter +function drawPerimeter() { + g.clear(); + for (var i = 0; i < N; i++) { + g.setColor(colours[i%colours.length]); + var minAngle = (i/N)*radians; + arc(perimMin,perimMax,minAngle,minAngle+arclen); + } +} + +// animate a ball rolling around and settling at "target" radians +function animateChoice(target) { + var angle = 0; + var speed = 0; + var oldx = -10; + var oldy = -10; + var decelFromAngle = -1; + var allowDecel = false; + for (var i = 0; true; i++) { + angle = angle + speed; + if (angle > radians) angle -= radians; + if (i < animStartSteps || (speed < maxSpeed && !allowDecel)) { + speed = speed + accel; + if (speed > maxSpeed) { + speed = maxSpeed; + /* when we reach max speed, we know how long it takes + * to accelerate, and therefore how long to decelerate, so + * we can work out what angle to start decelerating from */ + if (decelFromAngle < 0) { + decelFromAngle = target-angle; + while (decelFromAngle < 0) decelFromAngle += radians; + while (decelFromAngle > radians) decelFromAngle -= radians; + } + } + } else { + if (!allowDecel && (angle < decelFromAngle) && (angle+speed >= decelFromAngle)) allowDecel = true; + if (allowDecel) speed = speed - accel; + if (speed < minSpeed) speed = minSpeed; + if (speed == minSpeed && angle < target && angle+speed >= target) return; + } + + var r = i/2; + if (r > ballTrack) r = ballTrack; + var x = centreX+Math.cos(angle)*r; + var y = centreY+Math.sin(angle)*r; + g.setColor('#000000'); + g.fillCircle(oldx,oldy,ballSize+1); + g.setColor('#ffffff'); + g.fillCircle(x, y, ballSize); + oldx=x; + oldy=y; + } +} + +// choose a winning segment and animate its selection +function choose() { + var chosen = Math.floor(Math.random()*N); + var minAngle = (chosen/N)*radians; + var maxAngle = minAngle + arclen; + animateChoice((minAngle+maxAngle)/2); + g.setColor(colours[chosen%colours.length]); + for (var i = segmentMax-segmentStep; i >= 0; i -= segmentStep) + arc(i, perimMax, minAngle, maxAngle); + arc(0, perimMax, minAngle, maxAngle); + for (var r = 1; r < segmentMax; r += circleStep) + g.fillCircle(centreX,centreY,r); + g.fillCircle(centreX,centreY,segmentMax); +} + +// draw the current value of N in the middle of the screen, with +// up/down arrows +function drawN() { + g.setColor('#000000'); + g.setFont("Vector",fontSize); + g.drawString(N,centreX-g.stringWidth(N)/2+4,centreY-fontSize/2); + if (N < maxN) + g.fillPoly([centreX-6,centreY-fontSize/2-7, centreX+6,centreY-fontSize/2-7, centreX, centreY-fontSize/2-14]); + if (N > minN) + g.fillPoly([centreX-6,centreY+fontSize/2+5, centreX+6,centreY+fontSize/2+5, centreX, centreY+fontSize/2+12]); +} + +// update number of segments, with min/max limit, "arclen" update, +// and screen reset +function setN(n) { + N = n; + if (N < minN) N = minN; + if (N > maxN) N = maxN; + arclen = radians/N - gapAngle; + drawPerimeter(); +} + +// save N to choozi.txt +function writeN() { + var file = require("Storage").open("choozi.txt","w"); + file.write(N); +} + +// load N from choozi.txt +function readN() { + var file = require("Storage").open("choozi.txt","r"); + var n = file.readLine(); + if (n !== undefined) setN(parseInt(n)); + else setN(defaultN); +} + +shuffle(colours); // is this really best? +Bangle.setLCDTimeout(0); // keep screen on +readN(); +drawN(); + +setWatch(() => { + writeN(); + drawPerimeter(); + choose(); +}, BTN1, {repeat:true}); + +Bangle.on('touch', function(zone,e) { + if(e.x>+88){ + setN(N-1); + drawN(); + }else{ + setN(N+1); + drawN(); + } +}); From e82d02df425ff8dcee44d78e2b13773167b09caa Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 08:41:03 -0700 Subject: [PATCH 202/312] Update metadata.json --- apps/choozi/metadata.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/choozi/metadata.json b/apps/choozi/metadata.json index b75ef062a..a10448ed5 100644 --- a/apps/choozi/metadata.json +++ b/apps/choozi/metadata.json @@ -1,16 +1,17 @@ { "id": "choozi", "name": "Choozi", - "version": "0.01", + "version": "0.02", "description": "Choose people or things at random using Bangle.js.", "icon": "app.png", "tags": "tool", - "supports": ["BANGLEJS"], + "supports": ["BANGLEJS","BANGLEJS2"], "readme": "README.md", "allow_emulator": true, "screenshots": [{"url":"bangle1-choozi-screenshot1.png"},{"url":"bangle1-choozi-screenshot2.png"}], "storage": [ - {"name":"choozi.app.js","url":"app.js"}, + {"name":"choozi.app.js","url":"app.js","supports": ["BANGLEJS"]}, + {"name":"choozi.app.js","url":"appb2.js","supports": ["BANGLEJS2"]}, {"name":"choozi.img","url":"app-icon.js","evaluate":true} ] } From 75d68269b99ce0fe8b4d35158f1fb9ee9ad911f5 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 08:41:27 -0700 Subject: [PATCH 203/312] Update ChangeLog --- apps/choozi/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/choozi/ChangeLog b/apps/choozi/ChangeLog index 5560f00bc..7aabe5c89 100644 --- a/apps/choozi/ChangeLog +++ b/apps/choozi/ChangeLog @@ -1 +1,2 @@ 0.01: New App! +0.02: Support Bangle.js 2 From e2e9b69b24a6ba97ad0c9ffe8d7c6f2031c17303 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Wed, 13 Apr 2022 19:16:08 +0200 Subject: [PATCH 204/312] Allow quiet mode to optionally override message auto-open --- apps/messages/lib.js | 11 +++++++++-- apps/messages/settings.js | 5 +++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/apps/messages/lib.js b/apps/messages/lib.js index 7d49d4c64..f584c9e93 100644 --- a/apps/messages/lib.js +++ b/apps/messages/lib.js @@ -56,9 +56,16 @@ exports.pushMessage = function(event) { } // otherwise load messages/show widget var loadMessages = Bangle.CLOCK || event.important; - // first, buzz var quiet = (require('Storage').readJSON('setting.json',1)||{}).quiet; - var unlockWatch = (require('Storage').readJSON('messages.settings.json',1)||{}).unlockWatch; + var appSettings = require('Storage').readJSON('messages.settings.json',1)||{}; + var unlockWatch = appSettings.unlockWatch; + var quietNoAutOpn = appSettings.quietNoAutOpn; + delete appSettings; + // don't auto-open messages in quiet mode if quietNoAutOpn is true + if(quiet && quietNoAutOpn) { + loadMessages = false; + } + // first, buzz if (!quiet && loadMessages && global.WIDGETS && WIDGETS.messages){ WIDGETS.messages.buzz(); if(unlockWatch != false){ diff --git a/apps/messages/settings.js b/apps/messages/settings.js index cc0030ec5..adea36f12 100644 --- a/apps/messages/settings.js +++ b/apps/messages/settings.js @@ -53,6 +53,11 @@ format: v => v?/*LANG*/'Yes':/*LANG*/'No', onchange: v => updateSetting("flash", v) }, + /*LANG*/'Quiet mode disables auto-open': { + value: !!settings().quietNoAutOpn, + format: v => v?/*LANG*/'Yes':/*LANG*/'No', + onchange: v => updateSetting("quietNoAutOpn", v) + }, }; E.showMenu(mainmenu); }) From 3b67746ccda5ca6b42be37b1c13f710cc2a12b8c Mon Sep 17 00:00:00 2001 From: thyttan <6uuxstm66@mozmail.com> Date: Wed, 13 Apr 2022 19:56:48 +0200 Subject: [PATCH 205/312] messagesmusic added. --- apps/messagesmusic/ChangeLog | 1 + apps/messagesmusic/README.md | 15 +++++++++++++++ apps/messagesmusic/app-icon.js | 1 + apps/messagesmusic/app.js | 15 +++++++++++++++ apps/messagesmusic/app.js~ | 15 +++++++++++++++ apps/messagesmusic/app.png | Bin 0 -> 1190 bytes apps/messagesmusic/metadata.json | 18 ++++++++++++++++++ apps/messagesmusic/screenshot.png | Bin 0 -> 2365 bytes 8 files changed, 65 insertions(+) create mode 100644 apps/messagesmusic/ChangeLog create mode 100644 apps/messagesmusic/README.md create mode 100644 apps/messagesmusic/app-icon.js create mode 100644 apps/messagesmusic/app.js create mode 100644 apps/messagesmusic/app.js~ create mode 100644 apps/messagesmusic/app.png create mode 100644 apps/messagesmusic/metadata.json create mode 100644 apps/messagesmusic/screenshot.png diff --git a/apps/messagesmusic/ChangeLog b/apps/messagesmusic/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/messagesmusic/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/messagesmusic/README.md b/apps/messagesmusic/README.md new file mode 100644 index 000000000..7aa9209df --- /dev/null +++ b/apps/messagesmusic/README.md @@ -0,0 +1,15 @@ +Hacky app that uses Messages app and it's library to push a message that triggers the music controls. It's nearly not an app, and yet it moves. + +This app require Messages setting 'Auto-open Music' to be 'Yes'. If it isn't, the app will change it to 'Yes' and let it stay that way. + +Making the music controls accessible this way lets one start a music stream on the phone in some situations even though the message app didn't receive a music message from gadgetbridge to begin with. (I think.) + +It is suggested to use Messages Music along side the app Quick Launch. + +Messages Music v0.01 has been verified to work with Messages v0.31 on Bangle.js 2 fw2v13. + +Music Messages should work with forks of the original Messages app. At least as long as functions pushMessage() in the library and showMusicMessage() in app.js hasn't been changed too much. + +Messages app is created by Gordon Williams with contributions from [Jeroen Peters](https://github.com/jeroenpeters1986). + +The icon used for this app is from [https://icons8.com](https://icons8.com). diff --git a/apps/messagesmusic/app-icon.js b/apps/messagesmusic/app-icon.js new file mode 100644 index 000000000..5252570b6 --- /dev/null +++ b/apps/messagesmusic/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwhC/AFXdAAQVVDKQWHDB0NC5PQCyoYMCxZJKFxgwKCxowJC6xGOJBALE6YwRBQnf+YXPIwvf/4YKJAgXHDBQXNDBIXO/89C5YKFC4gYIC54YHC6AYGC6IYFC9JHWO6ynLa64XJ+YWGC5wWIC5oWJC4p4F74WKOwgXG6YWKC4xIFABRGFYI4uPC7JIOIw4wPCxAwNFxIYMCxZJLCxgYJCxwZGCqIA/AC4=")) diff --git a/apps/messagesmusic/app.js b/apps/messagesmusic/app.js new file mode 100644 index 000000000..a6f7e075e --- /dev/null +++ b/apps/messagesmusic/app.js @@ -0,0 +1,15 @@ +let showMusic = () => { + Bangle.CLOCK = 1; // To pass condition in messages library + require('messages').pushMessage({"t":"add","artist":" ","album":" ","track":" ","dur":0,"c":-1,"n":-1,"id":"music","title":"Music","state":"play","new":true}); + Bangle.CLOCK = undefined; +}; + +var settings = require('Storage').readJSON('messages.settings.json', true) || {}; //read settings if they exist else set to empty dict +if (!settings.openMusic) { + settings.openMusic = true; // This app/hack works as intended only if this setting is true + require('Storage').writeJSON('messages.settings.json', settings); + E.showMessage("First run:\n\nMessages setting\n\n 'Auto-Open Music'\n\n set to 'Yes'"); + setTimeout(()=>{showMusic();}, 5000); +} else { + showMusic(); +} diff --git a/apps/messagesmusic/app.js~ b/apps/messagesmusic/app.js~ new file mode 100644 index 000000000..a02c7704f --- /dev/null +++ b/apps/messagesmusic/app.js~ @@ -0,0 +1,15 @@ +let showMusic = () => { + Bangle.CLOCK = 1; // To pass condition in messages library + require('messages').pushMessage({"t":"add","artist":" ","album":" ","track":" ","dur":0,"c":-1,"n":-1,"id":"music","title":"Music","state":"play","new":true}); + Bangle.CLOCK = undefined; +}; + +var settings = require('Storage').readJSON('messages.settings.json', true) || {}; //read settings if they exist else set to empty dict +if (!settings.openMusic) { + settings.openMusic = true; // This app/hack works as intended only if this setting is true + require('Storage').writeJSON('messages.settings.json', settings); + E.showMessage("First run:\n\nMessages setting\n\n 'Auto-Open Music'\n\n set to 'Yes'"); + setTimeout(()=>{showMusic();}, 5000); +} else { + showMusic(); +}; diff --git a/apps/messagesmusic/app.png b/apps/messagesmusic/app.png new file mode 100644 index 0000000000000000000000000000000000000000..9d2967bba575ae9c0f01c29129533c495d8bb12c GIT binary patch literal 1190 zcmV;X1X=ruP)~5>1;DHp>#2`&L=|Tw!B+{Y=j0qen z2xv5EOh_S7FUEsOjYgv}F-qG&YS3WO0vb_7L((>l9B|vNXTcD)R5?hC%CgIDJM%n1 zFqxh0{4E^l=lFiV_ultq=J$T{`wh%7$DNJD5ky;C&En+mO$r-O$*5=}!V;9)8(H!w ze~QXkL~|lCm|T|~mJaNwxg!-&cx?4D+m?2eT|h%X_i7>;vCvpX^sfO1C z&17nBsdxZo^VLG)Yi(WWxxPFL$S*XzZ>jj3=*Ilz^aozEW_*S6Evt8e^u{MDIErqs z8yGoKZM)m@vJEG&!lZxE2_2Fs;`isZ{bt?f_L{}Jg_{ZK2PdRGx2)0 zLDwfxcx25|+tl;;+@#X|Sx}ql{!^5DI?>6%`;ixAQ>^95{@j>z!1W2(3Ee}`9aany zk8UFM>6grFYe!P)a8liwXW5C}ZUYqsXa@$$&d{mmFQ8`ovm`%0O5%wvV0bnuUC|Xzo7)Oo z5>}sYLN9cw(B|e@8%>>mLM-$;ry-^ucl$`V*z&}G+HyrFE>S+z!}RyxfbHvif5mBV zE8rrtT|ns?Q(qlr>a$PK!qotddeLdAC_v$yz{*GhtLBgPy(Gw4r>&v@14b3LhLl(p z>!)GL2R_6;|4Zl?s*E~q6$OaMpsI#W;=~^NjdD*X)|u0hV~OaX(^k=ilIya=z=f#E zbm9`F_ur=2_H-=bfw9#3k(|?5xf6F_qjETOn$k6<`VLWi{wbzU9{1Z_e4vNjt|HyK z5Qa^cZSpcf&IGf2peY%e=yDry-N;fy*>M#P`i*Xl{z&nKU6kJGm<{oW(32WG^M~tL zHK%_bUt4cZTW7ibhx!TIvKj*)>hC^vW>S&8v!}}+s_dTW(s#yhp}K)=pTdFoW%)zU zuDZeDV>8Y1{Ftk)zpq{4czm*ab24S6U-X*f|8loz9z)q2U6(JuO{c7Fv0Ux~$cbDb zec9Tg!v5&mJaVC3X)CqWkNE5J19GKh^)^8|iMu-~e<`$kz4J~2A86_ZMvmCfC`dO@ z3hM7dNrXE^P9B;qxi$BRkk6` zqLR6Odms(`f4#H2?qr07*qoM6N<$ Eg5c~?^#A|> literal 0 HcmV?d00001 diff --git a/apps/messagesmusic/metadata.json b/apps/messagesmusic/metadata.json new file mode 100644 index 000000000..edc6835ed --- /dev/null +++ b/apps/messagesmusic/metadata.json @@ -0,0 +1,18 @@ +{ + "id": "messagesmusic", + "name":"Messages Music", + "version":"0.01", + "description": "Uses Messages library to push a music message which in turn displays Messages app music controls", + "icon":"app.png", + "type": "app", + "tags":"tool,music", + "screenshots": [{"url":"screenshot.png"}], + "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"messagesmusic.app.js","url":"app.js"}, + {"name":"messagesmusic.img","url":"app-icon.js","evaluate":true} + ], + "dependencies": {"messages":"app"} + +} diff --git a/apps/messagesmusic/screenshot.png b/apps/messagesmusic/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..986b869f862e9d315d3888c5f71569170184094e GIT binary patch literal 2365 zcmeHJdpOezAK#6QjvW$nS&NX0ic{F;bvRnNgq&6`VM|_d5St!m&1LJ}A(vB>B6V_9 zgvo8W%ui@E=9RhB*5*=Mtl1bUNw4$%{r>;{^ZxPue4g(g-_P@TKF{-cp6}Jb053gV zGhGk}r03&JII_;{zXzecj3rjq80tW5aZ`I4R=A1(Y+OL zOEAp-!l76moM3{vNvR=V~04q>wO)PduujaU>#5OJoAjCE|m zocA~mh+@*30@EhYk9 zVdoqcTJ@)&M#@|)*oNxYE)K^9my;L`HSciDy#j_#iebkiz_GEdf#_TLrQawD`oq;Fsi7A&`OC<{b5|d_s zgAg5#v{0fk{S#$tmV(AQ$Wr4WScg`0v*djzD@p181GkqIHd0Z&64~)3^Q$rvPMRBU z9Pd1Vf;_Bl*-)1$C1-z&LVwN_jK>9cD}kXH8{ZN$_zPAQR^4|eXyAfX?ltH%u)~Xn zqX;vaXO~+XkqOI}C(T-Dma|vK*M#QC9B43gBAQ-%Ab~o3FwE)N}PcamQN z`&+Y`b*M;50>03QlYmWk*4Gg9c;NZGkg$V;?CLzbN|sf;IXpLT`qoa`ly7M)!!|Dh z5hpsrOPmD^K1FXa`Q&ExuX61GxBaYj`w=*{+_^sbJ1s*#IE)!IyX@fvU(R;Pg4gg| zvHMZI(1dZ#5$~d&5QEgKd=cd3%$bVD2`cs-lZ^jy*ai{$iReUe;MZCSl^RkRr79b zLavbeEWV<)qhRQ|Xlb8uIGYS1XIVwPIlz|W2OjQQ@Yfrufm2n}tEg zM+=Z9`JSiz22y#^^aIUKeTtYhM&T1m0*ITuyOnLZv!}P15=j7em9A+(sp%S1R&cm*1V>Y>02#_qp-qtMo)#dR2AS!O9p8e8# zQFb!$>AC97?`^L^!$K29BQK@J^++OA{zpFQCuB)fn*9l~UdgOgVcBHdMEJ(#dz1-u zy-?nW{@hCVEPx}^J*3kwhHmdn?om}6wJWWnD%&?ihT1DuCji^-8^Mi?y6&1$cUQZw zdwbq4vvy5=Rn?bbsyTDZS9Dyr8eiG`Z3Kz#8$Rqx zfgzBqugSaK$GFwM<7z@Qn%KUv2JPKis>k^cJpN2oZ$>_LDjQ?V0q)ZchM*J+v#Y=9qQ7wnqb{HBM#=QRZR}-)H z(VSz>Rd^aI9#5Z1kIS*KKQVZ0WphyS+R3@&yd(DIn7GMTbR!*(i|y`<1*mza7__WV z;8({)8I0jeZ*&g{-;^2r)zsnpA^}%Kzp9ns137JR&mypgWdya_2D69hvoCHu-D1OJ zw)*Qq>-9YVW8a3EA`oQG+3AOVPY^h4`%py~1i=vr9UL}*VF~vMcM^3hCK8EVz<)hv zIrGoE&%&vY{a+vN*Jp1pMTEdo4UNIsSgR8TAuzGFJtVP5Q&fMH5HFUz z7(SS|#P|ge5noBART|y?J7!7gNeorm+?z}jaC3mZ4Z(a05z=i6&IXbV#{Q#W3OA-6 s1h%rV6m$0Ct4koH_|o3?D~MI-HAF%8 Date: Wed, 13 Apr 2022 15:07:38 -0700 Subject: [PATCH 206/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 7cdd6749e..2704ea09d 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -23,9 +23,9 @@ for (const key in saved_settings) { /* * Colors to use */ -let cBlue = settings.themeColor1BG; -let cOrange = settings.themeColor2BG; -let cPurple = settings.themeColor3BG; +let cBlue = settings.themeColor3BG; +let cOrange = settings.themeColor1BG; +let cPurple = settings.themeColor2BG; let cWhite = "#FFFFFF"; let cBlack = "#000000"; let cGrey = "#424242"; @@ -38,6 +38,24 @@ let lcarsViewPos = 0; var plotMonth = false; +function convert24to16(input) +{ + let RGB888 = parseInt(input.replace(/^#/, ''), 16); + let r = (RGB888 & 0xFF0000) >> 16; + let g = (RGB888 & 0xFF00) >> 8; + let b = RGB888 & 0xFF; + + r = (r * 249 + 1014) >> 11; + g = (g * 253 + 505) >> 10; + b = (b * 249 + 1014) >> 11; + let RGB565 = 0; + RGB565 = RGB565 | (r << 11); + RGB565 = RGB565 | (g << 5); + RGB565 = RGB565 | b; + + return "0x"+RGB565.toString(16); +} + /* * Requirements and globals */ @@ -46,13 +64,17 @@ var plotMonth = false; var bgLeftFullscreen = { width : 27, height : 176, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A==")) + buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A==")), +// pallet: }; +var gray = convert24to16(cBlue); +var palette1 = new Uint16Array([0x0000,gray,0x0000,gray,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000],0,1); var bgLeftNotFullscreen = { width : 27, height : 152, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=")) + buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=")), + palette: palette1 }; var bgRightFullscreen = { @@ -712,3 +734,4 @@ Bangle.loadWidgets(); // Clear the screen once, at startup and draw clock g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); draw(); +console.log(bgLeftNotFullscreen); From bfa81d976613251edee2d0a2e5015e57e98d5456 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:34:50 -0700 Subject: [PATCH 207/312] Delete bg_right_small.png --- apps/lcars/bg_right_small.png | Bin 769 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/lcars/bg_right_small.png diff --git a/apps/lcars/bg_right_small.png b/apps/lcars/bg_right_small.png deleted file mode 100644 index df9d32b3853d8b2cabc83ef116f4179bfd5a48b0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 769 zcmV+c1OEJpP)1^@s674VWH00004b3#c}2nYxW zdp7D}Ov?G*@oL+#TtdH7YQ(oT@B{0l-qvSc}))HbDiNVgNw(Jp^o?AdE4_7-Nhv#@JrMI2_Yh zHmMSe+@vzb7-Nhv#@MdJ`uk-iC1%33ubeq|Z^XGU}=XYQ>hyq?BSPDUa9z z0f3<1a3Kh=`IzNHwqdEqzVbgIa_qrfpYQ(sGm&hN`+CytMdY}k(FXL9;x&B=KDlhHczsoxTe zf1D15E=z+SdGgBgqw9(%psK%bAZ^prigLB7Nqt5IzRBFFsv8*iW{BlNS@El>PS@!~ zV%_}DlMobP2-69oYh9P9Fuk+$uqjrxw)TPw^EW5nTVI+W+?Bhhm1B%C#u#Iau|0xu zIHs{|<+O148i0zDVB9w{#u#IaF~%5UjO|ve+-iWXb)7?5ndLan{~60(KNE>KH-sR$ zInE~*j4{R-V~jDz*iNvtqBK)M>6!5Lf}L(A5^**(4o*^Gj@8wthLz2BbhsND2iK_} zZT6P`SSt11)`w33K-ZO)fT~UbJ2Ur-%-ms_?C({;riREM^_B27N^XJ^87 zA`B5w)ot%$lT@aqLpOdnolj2n^<{zKg5!PxC40_mtXBDF00000NkvXXu0mjfJ_~X1 From ec3291f3cf97a108d2b22729eae28f49d97cb5d4 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:34:56 -0700 Subject: [PATCH 208/312] Delete bg_left.png --- apps/lcars/bg_left.png | Bin 795 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/lcars/bg_left.png diff --git a/apps/lcars/bg_left.png b/apps/lcars/bg_left.png deleted file mode 100644 index 91c2bb6f7b7f83376ff41b83632819f239358246..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 795 zcmV+$1LXXPP)Lu@Z};XF?e>1+Kn$_>ce=9Pi+wv|?prf!_UgoA*PqAR;0Q5z%b*wr#QIW|?7DXB`WO z%tr&|L5E%C#LQ2Gh*GsW#jLp5NE($b9rB=*a#ddue-I}cpM(`96HM6pf*hi&({4!# zMnqIzE`A7dh_+UHE+@9(jS&b)WnUrf;lz`gzuxi#RaLe{Ro#&k>|I5LbwO22-LBT& z%>Wz1-c(obJ#qa0$E^Y@ldu~lk?60fImZnV#jPx=>v@_Mp5#Unu#tv_i~{G~Z(NOI zG5vxo9PUoQUio}kCq3`sdd!7sTDWhhu5Onh=IrWPhzwpU;R25w4SpG{tjt-f_GcQ3>bghM!iN9H z!jV;@SAT8oA$M`hSV}M=qNuKCYg%|ZCD?KX{QiPtC83d&V9R;k*r;0O<}SKjtq-?~ Z{RF94z^`^=I%EI<002ovPDHLkV1n^vZ1eyC From c4f6ca38248d1eb9ea5e8a4eb9de29d712df6bbc Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:35:02 -0700 Subject: [PATCH 209/312] Delete bg_left_small.png --- apps/lcars/bg_left_small.png | Bin 772 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/lcars/bg_left_small.png diff --git a/apps/lcars/bg_left_small.png b/apps/lcars/bg_left_small.png deleted file mode 100644 index bfdb110d972360313d426b22ac78a7ee9a82b403..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 772 zcmV+f1N;1mP)1^@s674VWH00004b3#c}2nYxW zdOiP_0cN8)Um%OM2;H5eOAQ356ie zyf-x;e2riP67(p=WOt^~qbu;C5L(bnl(~OBh{2f5-U3V12Bnt29%?bS-Rsh`HQ{{U zwsSe3{qFsZoy%nmHc8U+s?uaU^KG-^3JFsy%-jvuHtuzO#z0iD5BJ8ajv6j5VV`Wlc`pTn2b^O;$;F9g)9sc?wK^&WH<{{J2_S1X7CVFyMi^m)5k^=! zV-$*J7>5MfkjlV9Ln>i}5k?qcgq1BeILIrs>ZoG@fc9vhdo*emFfr{90sy62oldK` z)o@7gp;3OAbH1T3%RUGb%}&mWiV5ayeFhd57&Gfjf&l=uwz8iLENs|suEoR(-WVPa z*BxkpeVBMr^Uqs8+RSF1n(0J@0VeFzJRgsz|0s_SgdkvS}^a%t&>R-KjV6awtzQI0Ue2qTOz z!u}IRp=gGMWceymuQi9y_e2w;xsfo!2qTOz!U!X5r(*g@L^_AkX?^_%z%WWHO8JDn z>+MB(AZOrw#p?B@G%>odAdE1=2qTOz!v0|4sC*5pSy+;snwYS#@DvLZMP+ijr)Q5U zW(@>ZL$Mn+Eb!QI@7Gv+driLD-)Sf;NlsBzRR33tkqx8QRCo6gN7K-3NiYC_uq0KB zqOw>LES;z<*PpQY;w8b-dDGu7=u@f74!i&HcClY%5W35joUtAN0000 Date: Wed, 13 Apr 2022 15:35:07 -0700 Subject: [PATCH 210/312] Delete bg_right.png --- apps/lcars/bg_right.png | Bin 791 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 apps/lcars/bg_right.png diff --git a/apps/lcars/bg_right.png b/apps/lcars/bg_right.png deleted file mode 100644 index 6e23a5d6ebc0687268a27c368507b63ed435d2b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 791 zcmV+y1L*vTP)u=77?@_KC=}5|wjz5wZD`KUTKmqT@jSO- z-kr~UXW!lZ&hG38gr$UnEH1q+^tPY>YBwfF1q1-z;&TavrJU^?Epi-7rrce>jIfk% z@4qZ$}v#kR_%l%g*pk2wJWfKa{RR1o0sbG8+742wST<^BmN#~wcL6$zAz#zwJe zwO;f;mWML|KF(pKyFDn@PMq5hF&77_q&I<)#~8 z8Z8%)laqEF^M597uOAPETpL0t`Ei^l7Q~1VBSwrEvE5)XO;h$~j@VT2X39=C9tycC zDtpIOVTCIz&nzpOZff#WRQ9f`f{f|bsuR)ZcSkQi0RYp~>ioJs0qo+$B9j<1cYHN^ z-}~gUW0+}bo*KPx+pTq!PyOksV3`O)_;r29J$#f@X2b%wez;su&vbPqfc})@egR7% V)8R{}8ms^S002ovPDHLkV1jhMZOi}w From e67f2fe6c3a071f991897b1c3e3a40e1b2f3bee2 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:43:14 -0700 Subject: [PATCH 211/312] Add files via upload --- apps/lcars/bg_left.png | Bin 0 -> 789 bytes apps/lcars/bg_left_small.png | Bin 0 -> 760 bytes apps/lcars/bg_right.png | Bin 0 -> 771 bytes apps/lcars/bg_right_small.png | Bin 0 -> 742 bytes 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/lcars/bg_left.png create mode 100644 apps/lcars/bg_left_small.png create mode 100644 apps/lcars/bg_right.png create mode 100644 apps/lcars/bg_right_small.png diff --git a/apps/lcars/bg_left.png b/apps/lcars/bg_left.png new file mode 100644 index 0000000000000000000000000000000000000000..3bae5e458ab84a8aa5164c058f8e1afd52a53ef7 GIT binary patch literal 789 zcmeAS@N?(olHy`uVBq!ia0vp^(m=d{gAGXj;}@*}QY^(zo*^7SP{WbZ0pv3l2e~^j ztUD+35+s@K=Eakt5%+dZboOlr z0k`t-qSWcj#4|oif130E|Gh_cTl7@=Ilnl0ZtT?WT6^2;ZfLv7rY%LXwL&Im7$3?e zmYCd{IK%bWCW8*KE*U^J> zy4vH%diAI0_GuV<=Uoe!cu#HFCLg})*=LMnJ>nFr8LF5HfGRPW&*(@xeYp6yZPfH~lz1$t`b3e#?iF)Jt1dY+$l1 z(U@nrKi2D(w(=r%2Tkd%2eumky&%M&eSuT3`7=B78iNA^Zc3< zMk`)?yZn5w~jYrJq<*R}e_x7$K- zu`}P$~a79e4YP;~i&vpO)ED!s2FC|D#_U@lWwidt$E~tv~ lDxK8z^EdyN?c7d(*lg4KH%vAt^#vwf22WQ%mvv4FO#o=+UcdkV literal 0 HcmV?d00001 diff --git a/apps/lcars/bg_left_small.png b/apps/lcars/bg_left_small.png new file mode 100644 index 0000000000000000000000000000000000000000..8223a1898641255ebc932f777f5bc9871e74990b GIT binary patch literal 760 zcmeAS@N?(olHy`uVBq!ia0vp^(m*_egAGWEewd^Tq*#ibJVQ8upoSx*1ITAA4sv&5 zSa(k5B}g*e(btiIVPik{pF~z5pR>RtvY3H^?+6GpPSxfE8pl-Y>Eakt5%+d>boOlr z0k`t-qSWcj#4|oif130E|Gh_cTl7@=Ik&VX={qfFsn}Te`CkH_HGJq3 zu#$S~aYjj}xch~|^_dfd`xn(|{92p%ZKXiaA(y_Ww8%xRTxueTnyF&{qxjW|Y|@rp zpZMYaxvsg+fhp7Orkc)bnzAu=`4Bk<4XZJ|#l=s8M# zKYn)|U)21~iV2b|(;N|m#f{g>4=tMw@)~c5iH0e(`yDN2YfKf0fD!*&3{5f^Z;4s# z@>{+|a;JFL+i@StU3(aca~{>qN5)hn9V` zoct}%DpRES`KOn2N+0%h33JUmxuW~v;?%0$TO;j0|C+OgTiEsIuTPie-Ie^6yLRT% z*}WAXpP9N!yt%}W1SC{-< z{d40CjlA5NDZg#%|Nmug{rhoQqrq-jSJ9Z?Z#mYl%gKN8Yw^QvLF?u9rzib-XzN;$ z#m&9>KKK8p2KA5DP2FccTh!Cte19f?-?isD7Ph)e)I5)VdaQoyHoM|Kh8L+VdrbTH RtN^A?22WQ%mvv4FO#lJHRD%Ej literal 0 HcmV?d00001 diff --git a/apps/lcars/bg_right.png b/apps/lcars/bg_right.png new file mode 100644 index 0000000000000000000000000000000000000000..a87cf31d1f4e62fdc874d11f9f924dfcb81f9540 GIT binary patch literal 771 zcmeAS@N?(olHy`uVBq!ia0vp^(m=d{gAGXj;}@*}QY^(zo*^7SP{WbZ0pv3l2e~^j ztUD+35+s@K=B8H*3G@3oKm!k3(zvPRq|i5ox}wOw`wl&&Xia*{l{P5>zER zJEL{;nRyz|yt(>*eZ8T)vUIll&J(Y?Ihx9uPpy0ZYU6~isw)e;xIg_`*!gCn>(1J< zdo&h&Iey0FTgQR>^KKfiniFWT`j}Y+TVtvKg4k6pps*)RU`Kw-0V58bW*E_~>Ro^C z>N}Ug8Bk6o-KXvL-$%Y#@#T25M&fZ(LQRC^iGZ!K~ORFc|{M#%& z(aok`X5+sPe%IH`Y!{APdTK%Lp#_^%Vm-IjUecb{dH0{rtCj4PskU!RjWsq|{8OJ9 z@RDWm#Ll?hb7$UloIjT`bH&#e4rjOhW0#4naer8mv&i?s()-p@murkN&oa)tX|=QJ zEq9x<@X9m)&ir{bqxN5t-c8}YHkIx}F4kW1KSX&%Pq+N3+yD5iu*Q{Xb6Jh%*O)3- zZ+cl$o>sMQZ^7r|rDi4jVicEOdigt2c$#B^Bny14`r!y*WUU2)AHmhqlvP6x*H23Sc8^ohGxgJ+&Cc3jTDGF%>@>lj-U26-jx39 zRtvY3H^?+6GpPSxfE8po9F>Eakt5%+dhbp9;| z0k`zpgKkWh+BN?FzrQ7G>6R~wr-GHXPF=Od@j=XoySHPjXE!7}-}>7VVBKzUYa^@r zX6vR%8O6>k{kBH>o)vwayKdHgHl!&-`6nC{1+S< zIg7DlZZ6{{)eAB?Qr$t{(%a5?tvcR)=AC?-VCIp_8470cbr(#tpBr|p2}-?Snivo{ z$!yZT{3_QuH{PCanpib4{Muzl^Jb;)Mf)dlPVFO7iZq|y?Ep_tuw0McE!zW z{s$(ymOnY4rgn=h?$_eUl53xRJ}2{FX6~fb-|g~^3@4s?Q~7Lm^3RWxcc%2)&z+#d zCHz*S_JOX1)}xj?26sL`k4t^hda2Icm=OA%VW85K$@FFr}=;pj3}_#bo_O;@uu{T|D5aj7fH*S^Z2CrPZhsA zbLwl;kS{-;YICmtx1DkB&4S~HuTGt}N9yW|my-`q__Jr}gD+QHR_V%kg{?_0I-V?S zdcfO$=g+|ZKXWItDebQP-FHf7z3Rc6Gc9koy%4{>srfPI{N4ayT4eBa^>bP0l+XkK D%gRdO literal 0 HcmV?d00001 From 1a74b211637b566f50b7acd541ed5d896d28c026 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:44:21 -0700 Subject: [PATCH 212/312] Update lcars.settings.js --- apps/lcars/lcars.settings.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index f714c3a7a..1873bb103 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -10,11 +10,8 @@ dataRow3: "Temp", speed: "kph", fullscreen: false, - themeColor1: "Orange", themeColor1BG: "#FF9900", - themeColor2: "Purple", themeColor2BG: "#FF00DC", - themeColor3: "Cyan", themeColor3BG: "#0094FF", }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; @@ -84,7 +81,6 @@ min: 0, max: 7, format: v => color_options[v], onchange: v => { - settings.themeColor1 = color_options[v]; settings.themeColor1BG = bg_code[v]; save(); }, @@ -94,7 +90,6 @@ min: 0, max: 7, format: v => color_options[v], onchange: v => { - settings.themeColor2 = color_options[v]; settings.themeColor2BG = bg_code[v]; save(); }, @@ -104,7 +99,6 @@ min: 0, max: 7, format: v => color_options[v], onchange: v => { - settings.themeColor3 = color_options[v]; settings.themeColor3BG = bg_code[v]; save(); }, From 8396d96e9a5591e48adf51e0f384c7e80d3d0cb2 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 15:56:25 -0700 Subject: [PATCH 213/312] Update lcars.settings.js --- apps/lcars/lcars.settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 1873bb103..830907fc5 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -77,7 +77,7 @@ }, }, 'Theme Color 1': { - value: 0 | color_options.indexOf(settings.themeColor1), + value: 0 | bg_code.indexOf(settings.themeColor1BG), min: 0, max: 7, format: v => color_options[v], onchange: v => { @@ -86,7 +86,7 @@ }, }, 'Theme Color 2': { - value: 0 | color_options.indexOf(settings.themeColor2), + value: 0 | bg_code.indexOf(settings.themeColor2BG), min: 0, max: 7, format: v => color_options[v], onchange: v => { @@ -95,7 +95,7 @@ }, }, 'Theme Color 3': { - value: 0 | color_options.indexOf(settings.themeColor3), + value: 0 | bg_code.indexOf(settings.themeColor3BG), min: 0, max: 7, format: v => color_options[v], onchange: v => { From 2192e9ff40565345249f4b0d7128e5cbb5dfaedf Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:06:42 -0700 Subject: [PATCH 214/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 91 +++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 36 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 2704ea09d..a3a3b452b 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -8,11 +8,8 @@ let settings = { dataRow3: "Battery", speed: "kph", fullscreen: false, - themeColor1: "Orange", themeColor1BG: "#FF9900", - themeColor2: "Purple", themeColor2BG: "#FF00DC", - themeColor3: "Cyan", themeColor3BG: "#0094FF", }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; @@ -23,9 +20,9 @@ for (const key in saved_settings) { /* * Colors to use */ -let cBlue = settings.themeColor3BG; -let cOrange = settings.themeColor1BG; -let cPurple = settings.themeColor2BG; +let color1 = settings.themeColor3BG; +let color2 = settings.themeColor1BG; +let color3 = settings.themeColor2BG; let cWhite = "#FFFFFF"; let cBlack = "#000000"; let cGrey = "#424242"; @@ -56,37 +53,59 @@ function convert24to16(input) return "0x"+RGB565.toString(16); } -/* - * Requirements and globals - */ +var color1C = convert24to16(color1); +var color2C = convert24to16(color2); +var color3C = convert24to16(color3); +/* +* Requirements and globals +*/ + +var colorPalette = new Uint16Array([ + 0x0000, // not used + color2C, // second + color3C, // third + 0x0000, // not used + color1C, // first + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000, // not used + 0x0000 // not used +],0,1); var bgLeftFullscreen = { width : 27, height : 176, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAFCh/eX5Q/KAwdCAGVbtu27YCCoAJBkuWrNlAQRGCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A==")), -// pallet: + buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAoUP7y/KH5QGDoQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyDCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4"))), + palette: colorPalette }; -var gray = convert24to16(cBlue); -var palette1 = new Uint16Array([0x0000,gray,0x0000,gray,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000],0,1); var bgLeftNotFullscreen = { width : 27, height : 152, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("AAUM2XLlgCCwAJBBAuy4EAmQIF5cggAIGlmwgYIG2XIF42wF4ImGF4ImHJoQmGJoQdJhZNHNY47CgRNGBIJZHHgRiGBIRQ/KH5QCAGVbtu27YCCoAJBkuWrNlAQRkCiwRDAQPQBIMJCIYCBsAJBgomEtu0WoQmEy1YBIMBHYttIwQ7FyxQ/KHFlFAQ7F2weCHYplKChRTCCg5TCHw5TMAD0GzVp0wCCBBGaBIMaBAtpwECBA2mwEJBAugDgMmCIwJBF5EABAtoeQQvGCYQdPJoI7LMQzTCLJKAGzAJBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=")), - palette: palette1 + buffer : require("heatshrink").decompress((atob("/4AB+VJkmSAQV///+BAtJn//5IIFkmf/4IGyVP/gIGpMnF41PHIImGF4ImHJoQmGJoIdK8hNHNY47C/JNGBIJZGyYJBQA5GCKH5Q/KAQAy0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5Q1GShlJChQLCCg5TCHw5TMAD35FAoIIkgJB8hGGv/8Mg8/+QIFp4cB5IRGBIIvI/4IFybyCF4wTCDp5NBHZZiGz4JBLJKAGk4JBO4xQ/KGQA8UP7y/KH5QnAHih/eX5Q/GQ4JCGRJlKCgxTDBAwgCCg5TCHwxTCNA4A=="))), + palette: colorPalette }; var bgRightFullscreen = { width : 27, height : 176, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAnUP7y/KH4yGeVYAJrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgAA=")) + buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAnUP7y/KH4yGeVYAJ0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkp4CS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A=="))), + palette: colorPalette }; var bgRightNotFullscreen = { width : 27, height : 152, bpp : 3, transparent : 0, - buffer : require("heatshrink").decompress(atob("lmy5YCDBIUyBAmy5AJBhYUG2EAhgIFAQMAgQIGCgQABCg4ABEAwUNFI2AKZHAKZEgGRZTGOIUDQxJxGKH5Q/agwAxrdt23bAQVABIMly1ZsoCCMgUWCIYCB6AJBhIRDAQNgBIMFEwlt2i1CEwmWrAJBgI7FtpGCHYuWKH5QxEwpQDlo7F0A7IqBZBEwo7BCIwCBJo53CJoxiCJpIAdgOmzVpAQR/CgAIEAQJ2CBAoCBBIMmCg1oD4QLGFQUCCjQ+CKYw+CKY4JCKYwoCGRMaGREJDoroCgwdFzBlLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJox/CgA=")) + buffer : require("heatshrink").decompress((atob("yVJkgCCyf/AAPJBAYCBk4JB8gUFyVP//yBAoCB//5BAwUCAAIUHAAIgGChopGv5TIn5TIz4yLKYxxC/iGI/xxGKH5Q/agwAx0hGF34JB6RGFr4JB9JkFl4JB+gdFy4JB/QdFpYJB/odFkqrCS4xGCWoyhCKH5QuDoxQCDpI7GDoJZGHYIRGLIQvGO4QvGMQRNJADv+GIqTC/5PGz4JBJ41JBIPJCg2TD4QLGn4JB/gUaHwRTGHwRTHBIRTGNAQyJ8gyI+QdFp4JB/IdFk5lLKH5QvAHih/eX5Q/KE4A8UP7y/KH5QGDpg7HJoxZCCIx3CJowmCF4yACJoyJC/4A="))), + palette: colorPalette }; var bgLeft = settings.fullscreen ? bgLeftFullscreen : bgLeftNotFullscreen; @@ -267,7 +286,7 @@ function drawInfo(){ } g.setFontAntonioMedium(); - g.setColor(cOrange); + g.setColor(color2); g.clearRect(120, 10, g.getWidth(), 75); g.drawString("LCARS", 128, 13); @@ -277,7 +296,7 @@ function drawInfo(){ g.drawString("NOCON", 128, 33); } if(Bangle.isLocked()){ - g.setColor(cPurple); + g.setColor(color3); g.drawString("LOCK", 128, 53); } } @@ -308,7 +327,7 @@ function drawState(){ g.drawString("STATUS", 23+26, 108); } else { // Alarm within symbol - g.setColor(cOrange); + g.setColor(color2); g.drawString("ALARM", 23+26, 108); g.setColor(cWhite); g.setFontAntonioLarge(); @@ -323,19 +342,19 @@ function drawPosition0(){ // Draw background image var offset = settings.fullscreen ? 0 : 24; g.drawImage(bgLeft, 0, offset); - drawHorizontalBgLine(cBlue, 25, 120, offset, 4); - drawHorizontalBgLine(cBlue, 130, 176, offset, 4); - drawHorizontalBgLine(cPurple, 20, 70, 80, 4); - drawHorizontalBgLine(cPurple, 80, 176, 80, 4); - drawHorizontalBgLine(cOrange, 35, 110, 87, 4); - drawHorizontalBgLine(cOrange, 120, 176, 87, 4); + drawHorizontalBgLine(color1, 25, 120, offset, 4); + drawHorizontalBgLine(color1, 130, 176, offset, 4); + drawHorizontalBgLine(color3, 20, 70, 80, 4); + drawHorizontalBgLine(color3, 80, 176, 80, 4); + drawHorizontalBgLine(color2, 35, 110, 87, 4); + drawHorizontalBgLine(color2, 120, 176, 87, 4); // The last line is a battery indicator too var bat = E.getBattery() / 100.0; var batStart = 19; var batWidth = 172 - batStart; var batX2 = parseInt(batWidth * bat + batStart); - drawHorizontalBgLine(cOrange, batStart, batX2, 171, 5); + drawHorizontalBgLine(color2, batStart, batX2, 171, 5); drawHorizontalBgLine(cGrey, batX2, 172, 171, 5); for(var i=0; i+batStart<=172; i+=parseInt(batWidth/4)){ drawHorizontalBgLine(cBlack, batStart+i, batStart+i+3, 168, 8) @@ -374,9 +393,9 @@ function drawPosition0(){ // Draw data g.setFontAlign(-1, -1, 0); g.setColor(cWhite); - drawData(settings.dataRow1, 97, cOrange); - drawData(settings.dataRow2, 122, cPurple); - drawData(settings.dataRow3, 147, cBlue); + drawData(settings.dataRow1, 97, color2); + drawData(settings.dataRow2, 122, color3); + drawData(settings.dataRow3, 147, color1); // Draw state drawState(); @@ -387,13 +406,13 @@ function drawPosition1(){ var offset = settings.fullscreen ? 0 : 24; g.drawImage(bgRight, 149, offset); if(settings.fullscreen){ - drawHorizontalBgLine(cBlue, 0, 140, offset, 4); + drawHorizontalBgLine(color1, 0, 140, offset, 4); } - drawHorizontalBgLine(cPurple, 0, 80, 80, 4); - drawHorizontalBgLine(cPurple, 90, 150, 80, 4); - drawHorizontalBgLine(cOrange, 0, 50, 87, 4); - drawHorizontalBgLine(cOrange, 60, 140, 87, 4); - drawHorizontalBgLine(cOrange, 0, 150, 171, 5); + drawHorizontalBgLine(color3, 0, 80, 80, 4); + drawHorizontalBgLine(color3, 90, 150, 80, 4); + drawHorizontalBgLine(color2, 0, 50, 87, 4); + drawHorizontalBgLine(color2, 60, 140, 87, 4); + drawHorizontalBgLine(color2, 0, 150, 171, 5); // Draw steps bars g.setColor(cWhite); From e272e718419ee5a60918edcfab0303759c2d1873 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:12:17 -0700 Subject: [PATCH 215/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 80 ++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 49 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index a3a3b452b..c1b17d0d1 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -612,39 +612,44 @@ function getCurrentTimeInMinutes(){ return Math.floor(Date.now() / (1000*60)); } -function isAlarmEnabled(){ - return settings.alarm >= 0; -} - function getAlarmMinutes(){ - var currentTime = getCurrentTimeInMinutes(); - return settings.alarm - currentTime; + if(!isAlarmEnabled()){ + return -1; + } + + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + return Math.round(alarm.getTimeToAlarm(alarmObj)/(60*1000)); } -function handleAlarm(){ - if(!isAlarmEnabled()){ - return; +function increaseAlarm(){ + try{ + var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, { + timer : (minutes+5)*60*1000, + }); + alarm.reload(); + } catch(ex){ } +} + +function decreaseAlarm(){ + try{ + var minutes = getAlarmMinutes(); + minutes -= 5; + + var alarm = require('sched') + alarm.setAlarm(TIMER_IDX, undefined); } - if(getAlarmMinutes() > 0){ - return; + if(minutes > 0){ + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); } - // Alarm - var t = 300; - Bangle.buzz(t, 1) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, t))) - .then(() => Bangle.buzz(t, 1)) - .then(() => new Promise(resolve => setTimeout(resolve, 5E3))) - .then(() => { - // Update alarm state to disabled - settings.alarm = -1; - storage.writeJSON(SETTINGS_FILE, settings); - }); + alarm.reload(); + } catch(ex){ } } @@ -671,28 +676,6 @@ Bangle.on('charging',function(charging) { drawState(); }); - -function increaseAlarm(){ - if(isAlarmEnabled() && getAlarmMinutes() < 95){ - settings.alarm += 5; - } else { - settings.alarm = getCurrentTimeInMinutes() + 5; - } - - storage.writeJSON(SETTINGS_FILE, settings); -} - - -function decreaseAlarm(){ - if(isAlarmEnabled() && (settings.alarm-5 > getCurrentTimeInMinutes())){ - settings.alarm -= 5; - } else { - settings.alarm = -1; - } - - storage.writeJSON(SETTINGS_FILE, settings); -} - function feedback(){ Bangle.buzz(40, 0.3); } @@ -753,4 +736,3 @@ Bangle.loadWidgets(); // Clear the screen once, at startup and draw clock g.setTheme({bg:"#000",fg:"#fff",dark:true}).clear(); draw(); -console.log(bgLeftNotFullscreen); From 69496ba1a5c5347a25c3ac339634fd6f3b63fd27 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:15:49 -0700 Subject: [PATCH 216/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index c1b17d0d1..63b10a922 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -171,11 +171,16 @@ Graphics.prototype.setFontAntonioLarge = function(scale) { */ var drawTimeout; function queueDraw() { + + // Faster updates during alarm to ensure that it is + // shown correctly... + var timeout = isAlarmEnabled() ? 10000 : 60000; + if (drawTimeout) clearTimeout(drawTimeout); drawTimeout = setTimeout(function() { drawTimeout = undefined; draw(); - }, 60000 - (Date.now() % 60000)); + }, timeout - (Date.now() % timeout)); } /** @@ -527,9 +532,6 @@ function draw(){ // Queue draw first to ensure that its called in one minute again. queueDraw(); - // First handle alarm to show this correctly afterwards - handleAlarm(); - // Next draw the watch face g.reset(); g.clearRect(0, 0, g.getWidth(), g.getHeight()); @@ -608,8 +610,18 @@ function getWeather(){ /* * Handle alarm */ -function getCurrentTimeInMinutes(){ - return Math.floor(Date.now() / (1000*60)); +function isAlarmEnabled(){ + try{ + var alarm = require('sched'); + var alarmObj = alarm.getAlarm(TIMER_IDX); + if(alarmObj===undefined || !alarmObj.on){ + return false; + } + + return true; + + } catch(ex){ } + return false; } function getAlarmMinutes(){ @@ -640,13 +652,13 @@ function decreaseAlarm(){ var alarm = require('sched') alarm.setAlarm(TIMER_IDX, undefined); - } + - if(minutes > 0){ - alarm.setAlarm(TIMER_IDX, { - timer : minutes*60*1000, - }); - } + if(minutes > 0){ + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); + } alarm.reload(); } catch(ex){ } From 3e7e1c19e548cb54a1bfc4aab27f29bd93b8d2ab Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Wed, 13 Apr 2022 16:17:46 -0700 Subject: [PATCH 217/312] Update lcars.app.js --- apps/lcars/lcars.app.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 63b10a922..3210d6832 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -652,13 +652,12 @@ function decreaseAlarm(){ var alarm = require('sched') alarm.setAlarm(TIMER_IDX, undefined); - - if(minutes > 0){ + if(minutes > 0){ alarm.setAlarm(TIMER_IDX, { timer : minutes*60*1000, }); - } + } alarm.reload(); } catch(ex){ } From 4750a50cb8855fdc5d212a8ccc1d5306db284625 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Thu, 14 Apr 2022 09:57:44 +0100 Subject: [PATCH 218/312] Create README.md --- apps/mosaic/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 apps/mosaic/README.md diff --git a/apps/mosaic/README.md b/apps/mosaic/README.md new file mode 100644 index 000000000..bf3ca671b --- /dev/null +++ b/apps/mosaic/README.md @@ -0,0 +1,13 @@ +# Mosaic Clock + +A fabulously colourful clock! + +* Clearly shows the time on a colourful background that changes every minute. +* Dark and Light theme compatible, with a setting to override the digit colour scheme. +* Show or hide widgets with a setting (default shows widgets). + +![](mosaic_scr1.png) +![](mosaic_scr2.png) +![](mosaic_scr3.png) + +Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From 995d72c7547ce58b0d72c48ca587be89ea50e893 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Thu, 14 Apr 2022 09:58:40 +0100 Subject: [PATCH 219/312] Add files via upload --- apps/mosaic/ChangeLog | 1 + apps/mosaic/metadata.json | 19 ++++++ apps/mosaic/mosaic.app.js | 103 +++++++++++++++++++++++++++++++++ apps/mosaic/mosaic.icon.js | 1 + apps/mosaic/mosaic.png | Bin 0 -> 649 bytes apps/mosaic/mosaic.settings.js | 44 ++++++++++++++ apps/mosaic/pixel digits.xcf | Bin 0 -> 1480 bytes 7 files changed, 168 insertions(+) create mode 100644 apps/mosaic/ChangeLog create mode 100644 apps/mosaic/metadata.json create mode 100644 apps/mosaic/mosaic.app.js create mode 100644 apps/mosaic/mosaic.icon.js create mode 100644 apps/mosaic/mosaic.png create mode 100644 apps/mosaic/mosaic.settings.js create mode 100644 apps/mosaic/pixel digits.xcf diff --git a/apps/mosaic/ChangeLog b/apps/mosaic/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/mosaic/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/mosaic/metadata.json b/apps/mosaic/metadata.json new file mode 100644 index 000000000..267c0de55 --- /dev/null +++ b/apps/mosaic/metadata.json @@ -0,0 +1,19 @@ +{ + "id":"mosaic", + "name":"Mosaic Clock", + "shortName": "Mosaic Clock", + "version": "0.01", + "description": "A fabulously colourful clock", + "readme": "README.md", + "icon":"mosaic.png", + "screenshots": [{"url":"mosaic-scr1.png"},{"url":"mosaic-scr2.png"}], + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS", "BANGLEJS2"], + "allow_emulator": true, + "storage": [ + {"name":"mosaic.app.js","url":"mosaic.app.js"}, + {"name":"mosaic.settings.js","url":"mosaic.settings.js"}, + {"name":"mosaic.img","url":"mosaic.icon.js","evaluate":true} + ] + } diff --git a/apps/mosaic/mosaic.app.js b/apps/mosaic/mosaic.app.js new file mode 100644 index 000000000..8b008b848 --- /dev/null +++ b/apps/mosaic/mosaic.app.js @@ -0,0 +1,103 @@ +Array.prototype.sample = function(){ + return this[Math.floor(Math.random()*this.length)]; +}; + +const SETTINGS_FILE = "mosaic.settings.json"; +let settings; +let theme; +let timeout = 60; +let drawTimeout; +let colours = [ + '#f00', '#00f', '#0f0', '#ff0', '#f0f', '#0ff', + '#8f0', '#f08', '#f80', '#80f', '#0f8', '#08f', +]; +let digits = [ + E.toArrayBuffer(atob("BQcB/Gtax+A=")), + E.toArrayBuffer(atob("BQeCAX9c1zXNc1zX9A==")), + E.toArrayBuffer(atob("BQcB/Hsbx+A=")), + E.toArrayBuffer(atob("BQcB/Hsex+A=")), + E.toArrayBuffer(atob("BQeCAf/zPM8D/Nc1/A==")), + E.toArrayBuffer(atob("BQcB/G8ex+A=")), + E.toArrayBuffer(atob("BQcB/G8ax+A=")), + E.toArrayBuffer(atob("BQeCAf/wP81zXNc1/A==")), + E.toArrayBuffer(atob("BQcB/Gsax+A=")), + E.toArrayBuffer(atob("BQcB/Gsex+A=")) +]; + +function loadSettings() { + settings = require("Storage").readJSON(SETTINGS_FILE,1)|| {'showWidgets': false, 'theme':'System'}; +} + +function loadThemeColors() { + theme = {fg: g.theme.fg, bg: g.theme.bg}; + if (settings.theme === "Dark") { + theme.fg = g.toColor(1,1,1); + theme.bg = g.toColor(0,0,0); + } + else if (settings.theme === "Light") { + theme.fg = g.toColor(0,0,0); + theme.bg = g.toColor(1,1,1); + } +} + +function queueDraw(seconds) { + let millisecs = seconds * 1000; + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, millisecs - (Date.now() % millisecs)); +} + +function draw() { + // draw colourful grid + for (let i_x = 0; i_x < num_squares_w; i_x++) { + for (let i_y = 0; i_y < num_squares_h; i_y++) { + g.setColor(colours.sample()).fillRect( + o_w+i_x*s, o_h+i_y*s, o_w+i_x*s+s, o_h+i_y*s+s + ); + } + } + let t = new Date(); + g.setBgColor(theme.fg); + g.setColor(theme.bg); + g.drawImage(digits[Math.floor(t.getHours()/10)], (mid_x-5)*s+o_w, (mid_y-7)*s+o_h, {scale:s}); + g.drawImage(digits[t.getHours() % 10], (mid_x+1)*s+o_w, (mid_y-7)*s+o_h, {scale:s}); + g.drawImage(digits[Math.floor(t.getMinutes()/10)], (mid_x-5)*s+o_w, (mid_y+1)*s+o_h, {scale:s}); + g.drawImage(digits[t.getMinutes() % 10], (mid_x+1)*s+o_w, (mid_y+1)*s+o_h, {scale:s}); + + queueDraw(timeout); +} + +g.clear(); +loadSettings(); +loadThemeColors(); + +offset_widgets = settings.showWidgets ? 24 : 0; +let available_height = g.getHeight() - offset_widgets; + +// Calculate grid size and offsets +let s = Math.floor(available_height/17); +let num_squares_w = Math.round(g.getWidth()/s) - 1; +let num_squares_h = Math.round(available_height/s) - 1; +let o_w = Math.floor((g.getWidth() - num_squares_w * s)/2); +let o_h = Math.floor((g.getHeight() - num_squares_h * s+offset_widgets)/2); +let mid_x = Math.floor(num_squares_w/2); +let mid_y = Math.floor((num_squares_h-1)/2); + +draw(); + +Bangle.on('lcdPower',on=>{ + if (on) { + draw(); // draw immediately, queue redraw + } else { // stop draw timer + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = undefined; + } +}); + +Bangle.setUI('clock'); +if (settings.showWidgets) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} diff --git a/apps/mosaic/mosaic.icon.js b/apps/mosaic/mosaic.icon.js new file mode 100644 index 000000000..4d781cf68 --- /dev/null +++ b/apps/mosaic/mosaic.icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwcAtu27dt3MkyVJkgHC23UA4WSCP4R/CP4RFBAfSA4VJA4QCFCP4R/CP4RJ7oaMCP4R/CP4RFbge9BoYID3IQCkgR/CP4R/CIoA==")) diff --git a/apps/mosaic/mosaic.png b/apps/mosaic/mosaic.png new file mode 100644 index 0000000000000000000000000000000000000000..f0c814d3b9d3c66f00f2189dc7bdefa9234a240e GIT binary patch literal 649 zcmV;40(Sk0P)EX>4Tx04R}tkv&MmKpe$i(`rR4B6bjQ$WV2$AS&W0RV;#q(pG5I!Q|2}Xws0R zxHt-~1qVMCs}3&Cx;nTDg5U>;qmz@OixgR!iP@updVurGxb<e&d{Pu)s5eMk+B+93&R=Z7jDjD;O&AG;v5#HOd## z4lA6uIIE=!Yu=N;Fp$+&l3b@bj3|~6LmVPxR8T|-7Q(b@q?kz1e#FH;)bPj2C6lWN zMveuPp+ai-!T;cQw`Oi?(n$(LfQ}d2{ulxLyFk5a+uz5wT|WW5&%l+|@|SDC>?i5f zmKHh!`nG|K>y{?(0hc?#;FB&HQbY366mmJ>{fxdT0}R{(-D^&7&3&9c04eHf`35*R z1V;0ez3%evuJ+#kJ=5&(2Ty5onfX|w6951J32;bRa{vG?BLDy{BLR4&KXw2B00(qQ zO+^Rh1O^Ku9SzuDdH?_b8FWQhbVF}#ZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b z0CGu0K~z}7?bpExz%UF$QLA+4dW3Xpbp-j4LJnW&5FYp-q*|^Nw<;(9Bj (settings.showWidgets ? 'Yes' : 'No'), + onchange: () => { + settings.showWidgets = !settings.showWidgets; + save(); + } + }, + 'Theme': { + value: 0 | theme_options.indexOf(s.theme), + min: 0, max: theme_options.length - 1, + format: v => theme_options[v], + onchange: v => { + s.theme = theme_options[v]; + save(); + } + }, + }); +}) diff --git a/apps/mosaic/pixel digits.xcf b/apps/mosaic/pixel digits.xcf new file mode 100644 index 0000000000000000000000000000000000000000..f2c05891c971874a0ead8743a4211ae9a6d5bb2d GIT binary patch literal 1480 zcmd^7TW-@p6dgPCkv35&FY(cjDYQ~5HBy`n@X-&11X8x(I*#iqi7VTE2<M=bpK9=Z=$fb|G(~iM$#Ffq<<68ziugz%Jl<7#;(g zCs-n2Pk;wN7kE~2>Yf7MfNp}+{V1Ew;&};QF!<;skHaz^%j>i}lds>r8!_@wOVe4H z#Qh{s$6TZOQ?Do&(^wYSG#wvp^(IM_O|x9~^wiIj(@+ld7aSpcx*{A%{V{w~T!c|N zPh>EFw`h2k)4!ajrA+71SzK^OHklN0DYf3=hBn2l*)i|jaV#Bzu(!NhcN7+E#M^KY z=M?xHVCw+;s(^j+SMM>R_W;+qxm|Hg;)TQa9KPjn>F{lbcO1@lWPaKXu&I>#tUXgS zW6XaDSlt0RbgcEI!|lIebqLY?YcuQ7Hlxz`A6CS;=hm*{AmIZ&<%^#R{lVu8PvbY8 z+Ow;ie;6S~?rqW6JIR$;Q(tPI8EWy0TsX6F%J-!hc}%{R`f9UiEryo*gQdGAH Date: Thu, 14 Apr 2022 10:07:21 +0100 Subject: [PATCH 220/312] Add mosaic clock screenshots --- apps/mosaic/mosaic-scr1.png | Bin 0 -> 3518 bytes apps/mosaic/mosaic-scr2.png | Bin 0 -> 29149 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/mosaic/mosaic-scr1.png create mode 100644 apps/mosaic/mosaic-scr2.png diff --git a/apps/mosaic/mosaic-scr1.png b/apps/mosaic/mosaic-scr1.png new file mode 100644 index 0000000000000000000000000000000000000000..2c429a9d2d5f7d1ab852ff71af684801751f9fcb GIT binary patch literal 3518 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 literal 0 HcmV?d00001 diff --git a/apps/mosaic/mosaic-scr2.png b/apps/mosaic/mosaic-scr2.png new file mode 100644 index 0000000000000000000000000000000000000000..5a172bb346dc992c0870ede3e6fff59cf4787db4 GIT binary patch literal 29149 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 hY Date: Fri, 15 Apr 2022 09:55:06 +0200 Subject: [PATCH 221/312] [pebble] Use the "locale" module, add /*LANG*/ placeholders - Use the "locale" module to retrieve the date info instead of splitting the value of the toString() - Add some /*LANG*/ here and there - Some code clean up --- apps/pebble/ChangeLog | 11 ++++---- apps/pebble/README.md | 4 +-- apps/pebble/metadata.json | 2 +- apps/pebble/pebble.app.js | 47 +++++++++++++++++----------------- apps/pebble/pebble.settings.js | 24 +++++++++-------- 5 files changed, 46 insertions(+), 42 deletions(-) diff --git a/apps/pebble/ChangeLog b/apps/pebble/ChangeLog index 01f653f48..02fe751e8 100644 --- a/apps/pebble/ChangeLog +++ b/apps/pebble/ChangeLog @@ -1,8 +1,9 @@ -0.01: first release -0.02: included deployment of pebble.settings.js in apps.json +0.01: First release +0.02: Included deployment of pebble.settings.js in apps.json 0.03: Changed time+calendar font to LECO1976Regular, changed to slanting boot 0.04: Fix widget hiding code (fix #1046) 0.05: Fix typo in settings - Purple -0.06: Added dependancy on Pedometer Widget -0.07: Fixed icon and ong file to 48x48 -0.08: Added theme options and optional lock symbol +0.06: Add dependancy on Pedometer Widget +0.07: Fix icon and ong file to 48x48 +0.08: Add theme options and optional lock symbol +0.09: Add support for internationalization (LANG placeholders + "locale" module) diff --git a/apps/pebble/README.md b/apps/pebble/README.md index 953db0ba7..ea76298e0 100644 --- a/apps/pebble/README.md +++ b/apps/pebble/README.md @@ -1,9 +1,9 @@ # Pebble - *a Pebble style clock with configurable background color, to keep the revolution going* +*A Pebble style clock with configurable background color, to keep the revolution going* * Designed specifically for Bangle 2 -* A choice of 6 different background colous through its setting menu. Goto Settings, App/Widget settings, Pebble. +* A choice of 6 different background colous through its settings menu. Goto *Settings* → *Apps* → *Pebble*. * Supports the Light and Dark themes (or set theme independently) * Uses pedometer widget to get latest step count * Dependant apps are installed when Pebble installs diff --git a/apps/pebble/metadata.json b/apps/pebble/metadata.json index eb049e78e..fd29dc4dc 100644 --- a/apps/pebble/metadata.json +++ b/apps/pebble/metadata.json @@ -2,7 +2,7 @@ "id": "pebble", "name": "Pebble Clock", "shortName": "Pebble", - "version": "0.08", + "version": "0.09", "description": "A pebble style clock to keep the rebellion going", "dependencies": {"widpedom":"app"}, "readme": "README.md", diff --git a/apps/pebble/pebble.app.js b/apps/pebble/pebble.app.js index 062592e47..4b8ff28bc 100644 --- a/apps/pebble/pebble.app.js +++ b/apps/pebble/pebble.app.js @@ -27,18 +27,20 @@ const h3 = 7*h/8; let batteryWarning = false; function draw() { + let locale = require("locale"); let date = new Date(); - let da = date.toString().split(" "); - let timeStr = da[4].substr(0,5); + let dayOfWeek = locale.dow(date, 1).toUpperCase(); + let dayOfMonth = date.getDate(); + let time = locale.time(date, 1); const t = 6; - // turn the warning on once we have dipped below 30% - if (E.getBattery() < 30) + if (E.getBattery() < 30) { + // turn the warning on once we have dipped below 30% batteryWarning = true; - - // turn the warning off once we have dipped above 40% - if (E.getBattery() > 40) + } else if (E.getBattery() > 40) { + // turn the warning off once we have dipped above 40% batteryWarning = false; + } g.reset(); g.setColor(settings.bg); @@ -49,14 +51,10 @@ function draw() { g.fillRect(0, h2 - t, w, h2); // day and steps - //if (settings.color == 'Blue' || settings.color == 'Red') - // g.setColor('#fff'); // white on blue or red best contrast - //else - // g.setColor('#000'); // otherwise black regardless of theme g.setColor(theme.day); g.setFontLECO1976Regular22(); g.setFontAlign(0, -1); - g.drawString(da[0].toUpperCase(), w/4, ha); // day of week + g.drawString(dayOfWeek, w/4, ha); g.drawString(getSteps(), 3*w/4, ha); // time @@ -67,7 +65,7 @@ function draw() { g.setFontLECO1976Regular42(); g.setFontAlign(0, -1); g.setColor(!batteryWarning ? theme.fg : '#fff'); - g.drawString(timeStr, w/2, h2 + 8); + g.drawString(time, w/2, h2 + 8); // contrast bar g.setColor(theme.fg); @@ -79,8 +77,8 @@ function draw() { g.setColor(settings.bg); g.drawImage(img, w/2 + ((w/2) - 64)/2, 1, { scale: 1 }); - drawCalendar(((w/2) - 42)/2, 14, 42, 4, da[2]); - + drawCalendar(((w/2) - 42)/2, 14, 42, 4, dayOfMonth); + drawLock(); } @@ -115,8 +113,7 @@ function loadThemeColors() { if (settings.theme === "Dark") { theme.fg = g.toColor(1,1,1); theme.bg = g.toColor(0,0,0); - } - else if (settings.theme === "Light") { + } else if (settings.theme === "Light") { theme.fg = g.toColor(0,0,0); theme.bg = g.toColor(1,1,1); } @@ -144,14 +141,18 @@ Bangle.on('lock', function(on) { g.clear(); Bangle.loadWidgets(); -/* - * we are not drawing the widgets as we are taking over the whole screen - * so we will blank out the draw() functions of each widget and change the - * area to the top bar doesn't get cleared. - */ -for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} + +// We are not drawing the widgets as we are taking over the whole screen +// so we will blank out the draw() functions of each widget and change the +// area to the top bar doesn't get cleared. +for (let wd of WIDGETS) { + wd.draw=()=>{}; + wd.area=""; +} + loadSettings(); loadThemeColors(); setInterval(draw, 15000); // refresh every 15s draw(); + Bangle.setUI("clock"); diff --git a/apps/pebble/pebble.settings.js b/apps/pebble/pebble.settings.js index 8a5fba63b..f1c065db4 100644 --- a/apps/pebble/pebble.settings.js +++ b/apps/pebble/pebble.settings.js @@ -1,21 +1,23 @@ (function(back) { const SETTINGS_FILE = "pebble.json"; - // initialize with default settings... + // TODO Only the color/theme indices should be written in the settings file so the labels can be translated + + // Initialize with default settings... let s = {'bg': '#0f0', 'color': 'Green', 'theme':'System', 'showlock':false} // ...and overwrite them with any saved values // This way saved values are preserved if a new version adds more settings - const storage = require('Storage') + const storage = require('Storage'); let settings = storage.readJSON(SETTINGS_FILE, 1) || s; - const saved = settings || {} + const saved = settings || {}; for (const key in saved) { s[key] = saved[key] } function save() { - settings = s - storage.write(SETTINGS_FILE, settings) + settings = s; + storage.write(SETTINGS_FILE, settings); } var color_options = ['Green','Orange','Cyan','Purple','Red','Blue']; @@ -24,8 +26,8 @@ E.showMenu({ '': { 'title': 'Pebble Clock' }, - '< Back': back, - 'Colour': { + /*LANG*/'< Back': back, + /*LANG*/'Colour': { value: 0 | color_options.indexOf(s.color), min: 0, max: 5, format: v => color_options[v], @@ -35,7 +37,7 @@ save(); } }, - 'Theme': { + /*LANG*/'Theme': { value: 0 | theme_options.indexOf(s.theme), min: 0, max: theme_options.length - 1, format: v => theme_options[v], @@ -44,13 +46,13 @@ save(); } }, - 'Show Lock': { + /*LANG*/'Show Lock': { value: settings.showlock, - format: () => (settings.showlock ? 'Yes' : 'No'), + format: () => (settings.showlock ? /*LANG*/'Yes' : /*LANG*/'No'), onchange: () => { settings.showlock = !settings.showlock; save(); } }, }); -}) +}); From bf6d37be92259b178d26486adaa4a5de4b64f974 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Fri, 15 Apr 2022 10:14:12 +0200 Subject: [PATCH 222/312] [pebble] Get steps from built-in step counter instead of pedometer widget See #1697 --- apps/pebble/ChangeLog | 3 ++- apps/pebble/README.md | 2 -- apps/pebble/metadata.json | 1 - apps/pebble/pebble.app.js | 10 ++-------- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/apps/pebble/ChangeLog b/apps/pebble/ChangeLog index 02fe751e8..94ae15c8c 100644 --- a/apps/pebble/ChangeLog +++ b/apps/pebble/ChangeLog @@ -6,4 +6,5 @@ 0.06: Add dependancy on Pedometer Widget 0.07: Fix icon and ong file to 48x48 0.08: Add theme options and optional lock symbol -0.09: Add support for internationalization (LANG placeholders + "locale" module) +0.09 (1): Add support for internationalization (LANG placeholders + "locale" module) +0.09 (2): Get steps from built-in step counter (widpedom no more needed, fix #1697) diff --git a/apps/pebble/README.md b/apps/pebble/README.md index ea76298e0..051f46e37 100644 --- a/apps/pebble/README.md +++ b/apps/pebble/README.md @@ -5,8 +5,6 @@ * Designed specifically for Bangle 2 * A choice of 6 different background colous through its settings menu. Goto *Settings* → *Apps* → *Pebble*. * Supports the Light and Dark themes (or set theme independently) -* Uses pedometer widget to get latest step count -* Dependant apps are installed when Pebble installs * Uses the whole screen, widgets are made invisible but still run in the background * When battery is less than 30% main screen goes Red * Optionally show a lock symbol when screen is locked (default off, enable in Settings) diff --git a/apps/pebble/metadata.json b/apps/pebble/metadata.json index fd29dc4dc..f3c1fcc12 100644 --- a/apps/pebble/metadata.json +++ b/apps/pebble/metadata.json @@ -4,7 +4,6 @@ "shortName": "Pebble", "version": "0.09", "description": "A pebble style clock to keep the rebellion going", - "dependencies": {"widpedom":"app"}, "readme": "README.md", "icon": "pebble.png", "screenshots": [{"url":"pebble_screenshot.png"}], diff --git a/apps/pebble/pebble.app.js b/apps/pebble/pebble.app.js index 4b8ff28bc..774b24c3f 100644 --- a/apps/pebble/pebble.app.js +++ b/apps/pebble/pebble.app.js @@ -32,6 +32,7 @@ function draw() { let dayOfWeek = locale.dow(date, 1).toUpperCase(); let dayOfMonth = date.getDate(); let time = locale.time(date, 1); + let steps = Bangle.getHealthStatus("day").steps; const t = 6; if (E.getBattery() < 30) { @@ -55,7 +56,7 @@ function draw() { g.setFontLECO1976Regular22(); g.setFontAlign(0, -1); g.drawString(dayOfWeek, w/4, ha); - g.drawString(getSteps(), 3*w/4, ha); + g.drawString(steps, 3*w/4, ha); // time // white on red for battery warning @@ -101,13 +102,6 @@ function drawCalendar(x,y,wi,th,str) { g.drawString(str, x + wi/2, y + wi/2 + th); } -function getSteps() { - if (WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); - } - return '????'; -} - function loadThemeColors() { theme = {fg: g.theme.fg, bg: g.theme.bg, day: g.toColor(0,0,0)}; if (settings.theme === "Dark") { From a77990b402e8d004aa3aa4e83d4595569e489758 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 15 Apr 2022 15:26:57 +0200 Subject: [PATCH 223/312] Save settings if killed --- apps/bwclk/ChangeLog | 2 +- apps/bwclk/app.js | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/bwclk/ChangeLog b/apps/bwclk/ChangeLog index 75f973f52..11569af0c 100644 --- a/apps/bwclk/ChangeLog +++ b/apps/bwclk/ChangeLog @@ -3,4 +3,4 @@ 0.03: Adapt colors based on the theme of the user. 0.04: Steps can be hidden now such that the time is even larger. 0.05: Included icons for information. -0.06: Design improvements. \ No newline at end of file +0.06: Design and usability improvements. \ No newline at end of file diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 97f3a14af..20edddf7e 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -403,7 +403,6 @@ Bangle.on('touch', function(btn, e){ if(is_right){ Bangle.buzz(40, 0.6); settings.showInfo = (settings.showInfo+1) % maxInfo; - storage.write(SETTINGS_FILE, settings); draw(); } @@ -411,11 +410,15 @@ Bangle.on('touch', function(btn, e){ Bangle.buzz(40, 0.6); settings.showInfo = settings.showInfo-1; settings.showInfo = settings.showInfo < 0 ? maxInfo-1 : settings.showInfo; - storage.write(SETTINGS_FILE, settings); draw(); } }); +E.on("kill", function(){ + storage.write(SETTINGS_FILE, settings); +}); + + // Show launcher when middle button pressed Bangle.setUI("clock"); From 63ef4e8bca0dd9e456879abb02c97eb912c196e7 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 15 Apr 2022 15:50:16 +0200 Subject: [PATCH 224/312] Performance Improvements --- apps/bwclk/app.js | 109 +++++++++++++++++++++++++++------------------- 1 file changed, 63 insertions(+), 46 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 20edddf7e..f97eb4c09 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -223,13 +223,43 @@ function decreaseAlarm(){ } catch(ex){ } } +function drawDate(){ + // Draw background + var y = H/5*2 + (settings.fullscreen ? 0 : 8); + g.reset().clearRect(0,0,W,W); -/* - * D R A W - */ -function draw() { - // queue draw in one minute - queueDraw(); + // Draw date + y -= settings.fullscreen ? 8 : 0; + var date = new Date(); + var dateStr = date.getDate(); + dateStr = ("0" + dateStr).substr(-2); + g.setMediumFont(); // Needed to compute the width correctly + var dateW = g.stringWidth(dateStr); + + g.setSmallFont(); + var dayStr = locale.dow(date, true); + var monthStr = locale.month(date, 1); + var dayW = Math.max(g.stringWidth(dayStr), g.stringWidth(monthStr)); + var fullDateW = dateW + 10 + dayW; + + g.setFontAlign(-1,1); + g.setMediumFont(); + g.setColor(g.theme.fg); + g.drawString(dateStr, W/2 - fullDateW / 2, y+4); + + g.setSmallFont(); + g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+4); + g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-23); +} + + +function drawTime(){ + // Draw background + var y = H/5*2 + (settings.fullscreen ? 0 : 8); + g.setColor(g.theme.fg); + g.fillRect(0,y,W,H); + + var date = new Date(); // Set info var showInfo = settings.showInfo; @@ -241,46 +271,14 @@ function draw() { showInfo = 101; } - - // Draw background - var yOffset = settings.fullscreen ? 0 : 10; - var y = H/5*2 + yOffset; - g.reset().clearRect(0,0,W,W); - g.setColor(g.theme.fg); - g.fillRect(0,y,W,H); - - // Draw date - y -= settings.fullscreen ? 8 : 0; - var date = new Date(); - var dateStr = date.getDate(); - dateStr = ("0" + dateStr).substr(-2); - g.setMediumFont(); // Needed to compute the width correctly - var dateW = g.stringWidth(dateStr); - - g.setSmallFont(); - var dayStr = locale.dow(date, true); - var monthStr = locale.month(date, 1); - var dayW = Math.max(g.stringWidth(dayStr), g.stringWidth(monthStr)); - var fullDateW = dateW + 10 + dayW; - - g.setFontAlign(-1,1); - g.setMediumFont(); - g.setColor(g.theme.fg); - g.drawString(dateStr, W/2 - fullDateW / 2, y+4); - - g.setSmallFont(); - g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+4); - g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-23); - - // Draw time g.setColor(g.theme.bg); g.setFontAlign(0,-1); var timeStr = locale.time(date,1); - y += settings.fullscreen ? 23 : 10; + y += settings.fullscreen ? 12 : 10; if(showInfo == 0){ - y += 8; + y += 10; g.setLargeFont(); } else { g.setMediumFont(); @@ -331,14 +329,18 @@ function draw() { } g.drawString(infoStr, W/2 + imgWidth/2, y+3); } +} - // Draw lock + +function drawLock(){ if(settings.showLock && Bangle.isLocked()){ g.setColor(g.theme.fg); g.drawImage(imgLock, W-16, 2); } +} - // Draw widgets if not fullscreen + +function drawWidgets(){ if(settings.fullscreen){ for (let wd of WIDGETS) {wd.draw=()=>{};wd.area="";} } else { @@ -346,6 +348,21 @@ function draw() { } } + +/* + * D R A W + */ +function draw() { + // Queue draw again + queueDraw(); + + // Draw clock + drawDate(); + drawTime(); + drawLock(); + drawWidgets(); +} + Bangle.loadWidgets(); // Clear the screen once, at startup and set the correct theme. @@ -390,27 +407,27 @@ Bangle.on('touch', function(btn, e){ if(is_upper){ Bangle.buzz(40, 0.6); increaseAlarm(); - draw(); + drawTime(); } if(is_lower){ Bangle.buzz(40, 0.6); decreaseAlarm(); - draw(); + drawTime(); } var maxInfo = 6; if(is_right){ Bangle.buzz(40, 0.6); settings.showInfo = (settings.showInfo+1) % maxInfo; - draw(); + drawTime(); } if(is_left){ Bangle.buzz(40, 0.6); settings.showInfo = settings.showInfo-1; settings.showInfo = settings.showInfo < 0 ? maxInfo-1 : settings.showInfo; - draw(); + drawTime(); } }); From 74ac267841a7e7a6a92c056bf1416c4e317498e6 Mon Sep 17 00:00:00 2001 From: David Peer Date: Fri, 15 Apr 2022 16:05:04 +0200 Subject: [PATCH 225/312] Minor changes --- apps/bwclk/README.md | 2 +- apps/bwclk/app.js | 6 +++--- apps/bwclk/metadata.json | 2 +- apps/bwclk/screenshot_3.png | Bin 0 -> 2953 bytes 4 files changed, 5 insertions(+), 5 deletions(-) create mode 100644 apps/bwclk/screenshot_3.png diff --git a/apps/bwclk/README.md b/apps/bwclk/README.md index 45bed6216..f282bd187 100644 --- a/apps/bwclk/README.md +++ b/apps/bwclk/README.md @@ -4,10 +4,10 @@ ## Features - Fullscreen on/off -- The design is adapted to the theme of your bangle. - Tab left/right of screen to show steps, temperature etc. - Enable / disable lock icon in the settings. - If the "sched" app is installed tab top / bottom of the screen to set the timer. +- The design is adapted to the theme of your bangle. ## Thanks to Icons created by Flaticon diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index f97eb4c09..ca5205df8 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -245,10 +245,10 @@ function drawDate(){ g.setFontAlign(-1,1); g.setMediumFont(); g.setColor(g.theme.fg); - g.drawString(dateStr, W/2 - fullDateW / 2, y+4); + g.drawString(dateStr, W/2 - fullDateW / 2, y+5); g.setSmallFont(); - g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+4); + g.drawString(monthStr, W/2 - fullDateW/2 + 10 + dateW, y+3); g.drawString(dayStr, W/2 - fullDateW/2 + 10 + dateW, y-23); } @@ -275,7 +275,7 @@ function drawTime(){ g.setColor(g.theme.bg); g.setFontAlign(0,-1); var timeStr = locale.time(date,1); - y += settings.fullscreen ? 12 : 10; + y += settings.fullscreen ? 14 : 10; if(showInfo == 0){ y += 10; diff --git a/apps/bwclk/metadata.json b/apps/bwclk/metadata.json index 4e69a3b0d..8b13cd256 100644 --- a/apps/bwclk/metadata.json +++ b/apps/bwclk/metadata.json @@ -5,7 +5,7 @@ "description": "BW Clock.", "readme": "README.md", "icon": "app.png", - "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}], + "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot_2.png"}, {"url":"screenshot_3.png"}], "type": "clock", "tags": "clock", "supports": ["BANGLEJS2"], diff --git a/apps/bwclk/screenshot_3.png b/apps/bwclk/screenshot_3.png new file mode 100644 index 0000000000000000000000000000000000000000..1f76b807000d6d2e69a8e3bf64469ee93b39dc82 GIT binary patch literal 2953 zcmV;43wHF0P)Px=LrFwIRCr$Po#AriI0%F<@Bh$yHL3NM~94Gus~Q^0Rg;p`4qeW76VHwAb^)HpMn>_Vqj?n1n|=3Q}6;< z3@ojH0A9L$3SIz;fw`o*TZyaZSqW~Yr z9drD|7WIwhe}`RrfDzcd;2=ID#qh>a1@M_)0UW7latsQZ7aY{DH+*j#0@$nYZ~K-V z*bA5!9It;=W^Wvo0H4L8BLrH>gk1zKFF27okd(Y}SOAaaJkE7?<~@!Vz(^GnHc_y= z;6&%~02P(N6Wcy-1Wv>z8uwk}S{)%g#oG(U0@&-PqG%os1aPxI>bxr6Rw(N^3KYu^ zI-kcb+9i>3h>a)K4z}$(@Ku+2LkITk2nd{rO$R7FF|-BPdW&WQ?19B2u-7&U88QyB z@y2_%eJg-JVthotf{C^DpZO8MccU1aza7A%G#CIge8i;2Mn$_MG7ho9qU>WOfdAG) z9k>sao=60+0QT_G&Q<`Q0BqgGR(9*?Hjj)$Y}yfO1SEhH6{`R_3K=pEu}R2r%TNKF zl)VDtWJs?XE`Ukp7RV$aoo)oMQ?M&@0ZbCo=|%t#1hc+_aU3d$o%9jR1@J*c3&J~Z zCPN^$Ej0i2M3#utNT%#o1b_MrkeQG#l?j-Q-8@sqTK{NFGi4(eAaOyXV;kkTQ670UvOLS31D)kMLSdEZ8-B{ zk{Rof2mCt;gCLY!@xiEw@mwK^R#m$gXFd_=pnju1#ih&G)8X25G5 zajv8kz(mL@U9kX;g5m)vszam$A8!wi`B{rgM~G;(oa2}PvyKxM9L^NsPueU<(KGPq z#sl@?&5>#Ux?6}d@giN14Xy>G756b7>niSS7aIAf$d>`~QUEg&9{E5(t}JAv<00EW zqFeSHjm%MDBY-PZ4f+(oe&GbLU$c@C5qL+(j-$WG`$IIQ5`iw93gDS)Pn>H7_!x2s zV1|kfeF)%&MNvq&0sj%LU|cI%N`c!H z&^6j^(raRd0s@$!qI}$@fB?QtdQHqwKmapTl#kmK82rn`x5cE1r2wpe0EVTKVMhf7 zaL1}BCRhOh3`-@$jtU6ij#W`iumS=YmP&>l6%fE3tD=}-1q3iGl?*#7Ab>koMKQq& z2w+$$8Fo}a0C%j4VuBSAz_3&@?5KbM?pPJY1S=qbVX0);Q2_zmu_}rQRzLv5QpvER z0*?pS`rX`)MH$7k&jstpET5gO*Rr{M^kn$3mRYy%OFu$btJ8XJ3AjCH3Ay>P zU`OMM+OhLFi-VCPE6%7+r+L|H7oYAdLF8vXz2bHh5?ATBC2L_@o!G1MKGLq5mmML_ z#9|bxtB_HE+4->jv3I?wPFLfo0B;@OYNb~KoaruXQ9b?`njGh2`>a|N9-XEEJPL{- zEW-ywIF^r!eAqq(@ZV}Pgk|_(!N>4Zkq^^nXL#wi5LQ7M!ZLhVaeAI-*ga*v6Rf zWr_ucYnm|@HM0X}G^xnN67W$+2yf@i6w4A8eO^)YjL(cFnR!vYe(ki(uTxq_R@Xs%%mCQ4C^HMe(t}X`e=bmMkvW%p ziDN))70V-Vhec`S<5>g|B=fX}}7FazSupYL3i3;7Pm==%?ET*!|E z`1>>RulTCAMk1g^=12Sr;GfkIz!t5C=N`zs5PN)|EmC!0XEESh6IJ&(@YdEC++*y>o`4rmn$1q8LT=G&g5i-J8b8sD9EO9T87&fA4EMMlS>c1Yn- zc#m4l-W`x!Dr{Z_aQ4Px8*g=X7Qh~Oy#QM|RKQl@^ECj^{Ch11z+QMQfEh7W0GRdp zSb&cmW+i~V$D*^d@;?8_V#tCuYy9g0KD&;}h|hv0@`8HSWm)lLG^rfBJiu2ka-$A( z6qI!yWWw_C%&>hFz*i7e7j_oB zo)@(}JggmN29Vx49s{s-MOO6^Hxpg~{2OlpocPkuY1G*bZqJX3AWMOQ!o(dTDu*)_5Wq9l)?9Q21TbAvIh?700G_F~ z=AtVgfa#LT;Y Date: Fri, 15 Apr 2022 18:20:02 +0200 Subject: [PATCH 226/312] Minor changes --- apps/bwclk/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/settings.js b/apps/bwclk/settings.js index 82d1cad0b..0fdaf1a28 100644 --- a/apps/bwclk/settings.js +++ b/apps/bwclk/settings.js @@ -18,7 +18,7 @@ E.showMenu({ - '': { 'title': 'BlackWhite Clock' }, + '': { 'title': 'BW Clock' }, '< Back': back, 'Fullscreen': { value: settings.fullscreen, From ca74fdf50136ea31e69d6833688dab05886efeae Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Fri, 15 Apr 2022 20:45:48 +0200 Subject: [PATCH 227/312] sleepphasealarm replace setInterval with .on('accel') --- apps/sleepphasealarm/app.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index 3f0f7d2b5..dcd176617 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -125,9 +125,9 @@ if (nextAlarm !== undefined) { // minimum alert 30 minutes early minAlarm.setTime(nextAlarm.getTime() - (30*60*1000)); - setInterval(function() { + Bangle.on('accel', (accelData) => { // 12.5Hz const now = new Date(); - const acc = Bangle.getAccel().mag; + const acc = accelData.mag; const swest = calc_ess(acc); if (swest !== undefined) { @@ -143,7 +143,7 @@ if (nextAlarm !== undefined) { buzz(); measure = false; } - }, 80); // 12.5Hz + }); drawApp(); } else { E.showMessage('No Alarm'); From 13bebf09b6159b8634d421322f8e711d5e0ac673 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sat, 16 Apr 2022 18:47:57 +0200 Subject: [PATCH 228/312] Include bangle logo option. --- apps/bwclk/app.js | 24 +++++++++++++++++++----- apps/bwclk/screenshot.png | Bin 2946 -> 3186 bytes apps/bwclk/screenshot_2.png | Bin 2874 -> 2898 bytes apps/bwclk/screenshot_3.png | Bin 2953 -> 3310 bytes 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index ca5205df8..37ae90102 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -11,6 +11,7 @@ const SETTINGS_FILE = "bwclk.setting.json"; const TIMER_IDX = "bwclk"; const W = g.getWidth(); const H = g.getHeight(); +const NUM_INFO=7; /* * Settings @@ -99,6 +100,11 @@ var imgCharging = { buffer : require("heatshrink").decompress(atob("//+v///k///4AQPwBANgBoMxBoMb/P+h/w/kH8H4gfB+EBwfggHH4EAt4CBn4CBj4CBh4FCCIO/8EB//Agf/wEH/8Gh//x////fAQIA=")) }; +var imgWatch = { + width : 24, height : 24, bpp : 1, + transparent : 1, + buffer : require("heatshrink").decompress(atob("/8B//+ARANB/l4//5/1/+f/n/n5+fAQnf9/P44CC8/n7/n+YOB/+fDQQgCEwQsCHBBEC")) +}; /* @@ -294,6 +300,7 @@ function drawTime(){ var infoStr = ""; var infoImg; + var printImgLeft = true; if(showInfo == 100){ infoStr = getAlarmMinutes() + " min."; infoImg = imgTimer; @@ -319,15 +326,23 @@ function drawTime(){ var weather = getWeather(); infoStr = weather.wind; infoImg = imgWind; + } else if (showInfo == NUM_INFO-1){ + infoStr = "Bangle"; + infoImg = imgWatch; + printImgLeft = false; } var imgWidth = 0; if(infoImg !== undefined){ imgWidth = infoImg.width; var strWidth = g.stringWidth(infoStr); - g.drawImage(infoImg, W/2 - strWidth/2 - infoImg.width/2 - 5, y - infoImg.height/2); + g.drawImage( + infoImg, + W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - infoImg.width/2, + y - infoImg.height/2 + ); } - g.drawString(infoStr, W/2 + imgWidth/2, y+3); + g.drawString(infoStr, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); } } @@ -416,17 +431,16 @@ Bangle.on('touch', function(btn, e){ drawTime(); } - var maxInfo = 6; if(is_right){ Bangle.buzz(40, 0.6); - settings.showInfo = (settings.showInfo+1) % maxInfo; + settings.showInfo = (settings.showInfo+1) % NUM_INFO; drawTime(); } if(is_left){ Bangle.buzz(40, 0.6); settings.showInfo = settings.showInfo-1; - settings.showInfo = settings.showInfo < 0 ? maxInfo-1 : settings.showInfo; + settings.showInfo = settings.showInfo < 0 ? NUM_INFO-1 : settings.showInfo; drawTime(); } }); diff --git a/apps/bwclk/screenshot.png b/apps/bwclk/screenshot.png index 02ef7a7048ba756eed6e4b0374b438c5d6cc330e..b30ba4166c6401c2e7fc94170e0f2082504f71b0 100644 GIT binary patch literal 3186 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 literal 2946 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

l8wwa@4(4?{rBP2N_|LvfjPubsU zRq6>+(8SCvsC5la)+DapK(KP*-D%yd^(V`!)ICSz4l{ujp4Lh~d974Ju>5=}D;p6Y zE=W&&Y*Rq@m-3U!(``U93@TkT`n0K2XfAoYF+jERq{qNzQlc76kwsW6ZYI*V5zy_E zQ>1J2o%OZ$wklWZyj$H#M)c4a^$QXLx4;6KV_CLp`3r~N+RCv;rU>%^pTma(RJshQ z)4YGFjz$8zw+TZpBSh(nrqb4ww3b!i>WT6EA&5zj%xwoa&v2R*cr-^vVl%CdqtUZM?dscY;^!+xPy2#IFr1cotdc~q z+AyG$JlE^g{2gfm&P|lGg4Oz*eQ#=OT>fmA?4415tUD_fVqEUqvhSnS!WhsyqFk(N z28^jOkv@B)OFLu1d!O8B#kN3~*ACL&;E?a3GWE-%Ba7cHX@5HFgekodIrlr1Fwu6= zbm2t3ZX(!beXw)ONDtb=KRTYQqDXyNOM$_9DOdL4fP!mNBH5k#)`SO5C4)q7Wbkam tyhH~gz7+zJ67T2lp+?sH@5ut)cMN9vMdsl((UT0g9rZlYb}0P%e*oXzP(%O# literal 2874 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 QZObrl+WH*24uwzpA1k?5N&o-= diff --git a/apps/bwclk/screenshot_3.png b/apps/bwclk/screenshot_3.png index 1f76b807000d6d2e69a8e3bf64469ee93b39dc82..fb5b153b88180e4dfabc26b058bc1e48bb48952c 100644 GIT binary patch literal 3310 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 g0Zf-v4reOxKfG*@A6xCkZ2$lO07*qoM6N<$f Date: Sat, 16 Apr 2022 20:58:29 +0200 Subject: [PATCH 229/312] lang: added Croatian locale --- apps/locale/locales.js | 18 +++++ lang/hr_HR.json | 162 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+) create mode 100644 lang/hr_HR.json diff --git a/apps/locale/locales.js b/apps/locale/locales.js index 06e959954..750b14132 100644 --- a/apps/locale/locales.js +++ b/apps/locale/locales.js @@ -583,6 +583,24 @@ var locales = { abday: "ne,po,út,st,čt,pá,so", day: "neděle,pondělí,úterý,středa,čtvrtek,pátek,sobota", trans: { yes: "ano", Yes: "Ano", no: "ne", No: "Ne", ok: "ok", on: "zap", off: "vyp" } + }, + "hr_HR": { + lang: "hr_HR", + decimal_point: ",", + thousands_sep: ".", + currency_symbol: "€", + int_curr_symbol: "EUR", + speed: "km/h", + distance: { 0: "m", 1: "km" }, + temperature: "°C", + ampm: { 0: "dop.", 1: "pop." }, + timePattern: { 0: "%HH:%MM:%SS", 1: "%HH:%MM" }, + datePattern: { 0: "%-d. %b %Y", 1: "%-d.%-m.%Y" }, // "3. jan. 2020" // "3.1.2020"(short) + abmonth: "sij.,velj.,ožu.,tra.,svi,lip.,srp.,kol.,ruj.,lis.,stu.,pro.", + month: "siječanj,veljača,ožujak,travanj,svibanj,lipanj,srpanj,kolovoz,rujan,listopad,studeni,prosinac", + abday: "ned.,pon.,uto.,sri.,čet.,pet.,sub.", + day: "nedjelja,ponedjeljak,utorak,srijeda,četvrtak,petak,subota", + trans: { yes: "da", Yes: "Da", no: "ne", No: "Ne", ok: "ok", on: "Uklj.", off: "Isklj.", "< Back": "< Natrag" } }, "sl_SI": { lang: "sl_SI", diff --git a/lang/hr_HR.json b/lang/hr_HR.json new file mode 100644 index 000000000..1103a09a3 --- /dev/null +++ b/lang/hr_HR.json @@ -0,0 +1,162 @@ +{ + "//": "Croatian language translations", + "GLOBAL": { + "//": "Translations that apply for all apps", + "Alarm": "Alarm", + "(repeat)": "(ponovi)", + "New Timer": "Novi mjerač vremena", + "New Alarm": "Novi alarm", + "Timer": "Sat", + "Save": "Spremi", + "Connected": "Povezano", + "Keep Msgs": "Zadrži poruke", + "circle 4": "krug 4", + "circle 3": "krug 3", + "circle 1": "krug 1", + "week": "tjedan", + "circle 2": "krug 2", + "Sleep": "Spavanje", + "circle count": "broj krugova", + "steps": "koraci", + "show widgets": "prikaži widgete", + "heartrate": "brzina otkucaja srca", + "valid period": "valjano razdoblje", + "maximum": "maksimalan", + "battery warn": "upozorenje o bateriji", + "weather circle": "vremenski krug", + "data": "podaci", + "goal": "cilj", + "step length": "dužina koraka", + "minimum": "minimum", + "min. confidence": "min. samouvjerenost", + "Heartrate": "Brzina otkucaja srca", + "distance goal": "ciljna udaljenost", + "Steps": "Koraci", + "color": "boja", + "colorize icon": "bojanje ikone", + "App Source\nNot found": "Kod aplikacije\nNije pronađen", + "Show clocks": "Prikaži satove", + "TAP right top/bottom": "TAP desno gore/dolje", + "View Message": "Pogledaj poruku", + "Circle": "Krug", + "Launcher Settings": "Postavke pokretača", + "Vector font size": "Veličina vektorskog fonta", + "Font": "Font", + "Loading": "Učitavanje", + "Delete all messages": "Obriši sve poruke", + "No Messages": "Nema poruka", + "BTNs 1:startlap 2:exit 3:reset": "BTNs 1:startlap 2:exit 3:reset", + "Are you sure": "Jeste li sigurni", + "start&lap/reset, BTN1: EXIT": "start&lap/reset, BTN1: EXIT", + "Mark Unread": "Označi nepročitano", + "Utils": "Utils", + "Record Run": "Snimi trčanje", + "Delete All Messages": "Brisanje svih poruka", + "Unread timer": "Nepročitani timer", + "Music": "Glazba", + "LCD": "LCD", + "Apps": "Aplikacije", + "Bluetooth": "Bluetooth", + "Dark BW": "Tamna BW", + "Vibration": "Vibracija", + "Quiet Mode": "Tihi način", + "Beep": "Beep", + "Passkey BETA": "Passkey BETA", + "Piezo": "Piezo", + "HID": "HID", + "Make Connectable": "Povežite se", + "BLE": "BLE", + "Programmable": "Programabilno", + "Light BW": "Svjetla CB", + "Background": "Pozadina", + "Customize": "Prilagodite", + "Background 2": "Pozadina 2", + "LCD Brightness": "Svjetlost LCD-a", + "Wake on BTN1": "Probudi se na BTN1", + "Wake on BTN2": "Probudi se na BTN2", + "Wake on BTN3": "Probudi se na BTN3", + "LCD Timeout": "LCD timeout", + "Twist Max Y": "Twist Max Y", + "Wake on Twist": "Probudi se na Twist", + "Twist Threshold": "Prag Twista", + "Foreground 2": "Prvi plan 2", + "Foreground": "Prvi plan", + "Remove": "Odstranite", + "Time Zone": "Vremenska zona", + "Highlight FG": "Naznači FG", + "Wake on Touch": "Probudi se na dodir", + "Clock Style": "Stil sata", + "Highlight BG": "Naznači BG", + "Add Device": "Dodaj uređaj", + "Connect device\nto add to\nwhitelist": "Spojite uređaj\nza dodavanje\nna sigurnu listu", + "Utilities": "Usluge", + "Wake on FaceUp": "Prebudi se na FaceUp", + "Compact Storage": "Kompaktna pohrana", + "Log": "Zapis", + "Debug Info": "Debug informacije", + "Turn Off": "Ugasite", + "Flatten Battery": "Prazna baterija", + "Reset to Defaults": "Postavite na početne postavke", + "Reset Settings": "Poništite postavke", + "Twist Timeout": "Twist Timeout", + "This will remove everything": "Ovo će obrisati sve", + "Rewrite Settings": "Ponovno napiši postavke", + "Storage": "Pohrana", + "Compacting...\nTakes approx\n1 minute": "Komprimiranje...\nPribližno\n1 minuta", + "No Clocks Found": "Satovi nisu pronađeni", + "Stay Connectable": "Ostanite povezani", + "Minute": "Minuta", + "Connectable": "Povezivost", + "Hour": "sat", + "Flattening battery - this can take hours.\nLong-press button to cancel": "Pražnjenje baterije - može potrajati satima.\nDugi pritisak da odustanete", + "Second": "Drugi", + "Month": "Mjesec", + "Date": "Datum", + "ALARM": "ALARM", + "Reset all widgets": "Poništite sve widgete", + "Reset All": "Poništite sve widgete", + "TIMER": "TIMER", + "Widgets": "widgeti", + "Hours": "Sati", + "Minutes": "Minute", + "Year": "Godina", + "No app has settings": "Nema aplikacije s postavkama", + "App Settings": "Postavke aplikacije", + "Repeat": "Ponovite", + "Invalid settings": "Neispravna postavka", + "Enabled": "Omogućeno", + "Reset": "Resetiraj", + "off": "Isključeno", + "Side": "Strana", + "Sort Order": "Poredak", + "Left": "Lijevo", + "Right": "Desno", + "on": "uključeno", + "Theme": "Tema", + "Locale": "Lokacija", + "Alerts": "Upozorenja", + "Select Clock": "Odaberite sat", + "System": "Sustav", + "Settings": "Postavke", + "Set Time": "Postavi vrijeme", + "Whitelist": "Sigurna lista", + "Message": "Poruka", + "Vibrate": "Vibriranje", + "Delete": "Izbriši", + "Error in settings": "Pogreška u postavkama", + "Messages": "Poruke", + "Disable": "Onemogućite", + "Show": "Prikaži", + "Ok": "Ok", + "On": "Uključeno", + "Hide": "Sakrij", + "Factory Reset": "Postavljanje na tvorničke postavke", + "Yes": "Da", + "No": "Ne", + "Off": "Isključeno", + "Back": "Natrag" + }, + "alarm": { + "//": "App-specific overrides" + } +} \ No newline at end of file From 1f445f69df924f9bcd10cb8dd95dec8ea48b1757 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 17 Apr 2022 09:43:44 +0200 Subject: [PATCH 230/312] Refactored info into array for easier maintainability. Use "last" bpm rather than day. --- apps/bwclk/app.js | 171 ++++++++++++++++++++++------------------------ 1 file changed, 83 insertions(+), 88 deletions(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 37ae90102..56607135f 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -11,7 +11,6 @@ const SETTINGS_FILE = "bwclk.setting.json"; const TIMER_IDX = "bwclk"; const W = g.getWidth(); const H = g.getHeight(); -const NUM_INFO=7; /* * Settings @@ -108,18 +107,28 @@ var imgWatch = { /* - * Draw timeout + * INFO ENTRIES */ -// timeout used to update every minute -var drawTimeout; +var infoArray = [ + function(){ return [ null, null, "left" ] }, + function(){ return [ E.getBattery() + "%", imgBattery, "left" ] }, + function(){ return [ getSteps(), imgSteps, "left" ] }, + function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm, "left"] }, + function(){ return [ getWeather().temp, imgTemperature, "left" ] }, + function(){ return [ getWeather().wind, imgWind, "left" ] }, + function(){ return [ "Bangle", imgWatch, "right" ] } +]; +const NUM_INFO=infoArray.length; -// schedule a draw for the next minute -function queueDraw() { - if (drawTimeout) clearTimeout(drawTimeout); - drawTimeout = setTimeout(function() { - drawTimeout = undefined; - draw(); - }, 60000 - (Date.now() % 60000)); + +function getInfoEntry(){ + if(isAlarmEnabled()){ + return [getAlarmMinutes() + " min.", imgTimer, "left"] + } else if(Bangle.isCharging()){ + return [E.getBattery() + "%", imgCharging, "left"] + } else{ + return infoArray[settings.showInfo](); + } } @@ -127,19 +136,21 @@ function queueDraw() { * Helper */ function getSteps() { + var steps = 0; try{ if (WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); + steps = WIDGETS.wpedom.getSteps(); } else if (WIDGETS.activepedom !== undefined) { - return WIDGETS.activepedom.getSteps(); + steps = WIDGETS.activepedom.getSteps(); } else { - return Bangle.getHealthStatus("day").steps; + steps = Bangle.getHealthStatus("day").steps; } } catch(ex) { // In case we failed, we can only show 0 steps. } - return 0; + steps = Math.round(steps/100) / 10; // This ensures that we do not show e.g. 15.0k and 15k instead + return steps + "k"; } @@ -229,6 +240,23 @@ function decreaseAlarm(){ } catch(ex){ } } + +/* + * DRAW functions + */ + +function draw() { + // Queue draw again + queueDraw(); + + // Draw clock + drawDate(); + drawTime(); + drawLock(); + drawWidgets(); +} + + function drawDate(){ // Draw background var y = H/5*2 + (settings.fullscreen ? 0 : 8); @@ -264,86 +292,47 @@ function drawTime(){ var y = H/5*2 + (settings.fullscreen ? 0 : 8); g.setColor(g.theme.fg); g.fillRect(0,y,W,H); - var date = new Date(); - // Set info - var showInfo = settings.showInfo; - if(isAlarmEnabled()){ - showInfo = 100; - } - - if(Bangle.isCharging()){ - showInfo = 101; - } - // Draw time g.setColor(g.theme.bg); g.setFontAlign(0,-1); var timeStr = locale.time(date,1); y += settings.fullscreen ? 14 : 10; - if(showInfo == 0){ + var infoEntry = getInfoEntry(); + var infoStr = infoEntry[0]; + var infoImg = infoEntry[1]; + var printImgLeft = infoEntry[2] == "left"; + + // Show large or small time depending on info entry + if(infoStr == null){ y += 10; g.setLargeFont(); } else { g.setMediumFont(); } - g.drawString(timeStr, W/2, y); - // Draw info or timer + // Draw info if set + if(infoStr == null){ + return; + } + y += H/5*2-5; g.setFontAlign(0,0); - if(showInfo > 0){ - g.setSmallFont(); - - var infoStr = ""; - var infoImg; - var printImgLeft = true; - if(showInfo == 100){ - infoStr = getAlarmMinutes() + " min."; - infoImg = imgTimer; - } else if(showInfo == 101){ - infoStr = E.getBattery() + "%"; - infoImg = imgCharging; - } else if (showInfo == 1){ - infoStr = E.getBattery() + "%"; - infoImg = imgBattery; - } else if (showInfo == 2){ - infoStr = getSteps() - infoStr = Math.round(infoStr/100) / 10; // This ensures that we do not show e.g. 15.0k and 15k instead - infoStr = infoStr + "k"; - infoImg = imgSteps; - } else if (showInfo == 3){ - infoStr = Math.round(Bangle.getHealthStatus("day").bpm) + " bpm"; - infoImg = imgBpm; - } else if (showInfo == 4){ - var weather = getWeather(); - infoStr = weather.temp; - infoImg = imgTemperature; - } else if (showInfo == 5){ - var weather = getWeather(); - infoStr = weather.wind; - infoImg = imgWind; - } else if (showInfo == NUM_INFO-1){ - infoStr = "Bangle"; - infoImg = imgWatch; - printImgLeft = false; - } - - var imgWidth = 0; - if(infoImg !== undefined){ - imgWidth = infoImg.width; - var strWidth = g.stringWidth(infoStr); - g.drawImage( - infoImg, - W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - infoImg.width/2, - y - infoImg.height/2 - ); - } - g.drawString(infoStr, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); + g.setSmallFont(); + var imgWidth = 0; + if(infoImg !== undefined){ + imgWidth = infoImg.width; + var strWidth = g.stringWidth(infoStr); + g.drawImage( + infoImg, + W/2 + (printImgLeft ? -strWidth/2-2 : strWidth/2+2) - infoImg.width/2, + y - infoImg.height/2 + ); } + g.drawString(infoStr, printImgLeft ? W/2 + imgWidth/2 + 2 : W/2 - imgWidth/2 - 2, y+3); } @@ -364,20 +353,26 @@ function drawWidgets(){ } -/* - * D R A W - */ -function draw() { - // Queue draw again - queueDraw(); - // Draw clock - drawDate(); - drawTime(); - drawLock(); - drawWidgets(); +/* + * Draw timeout + */ +// timeout used to update every minute +var drawTimeout; + +// schedule a draw for the next minute +function queueDraw() { + if (drawTimeout) clearTimeout(drawTimeout); + drawTimeout = setTimeout(function() { + drawTimeout = undefined; + draw(); + }, 60000 - (Date.now() % 60000)); } + +/* + * Load clock, widgets and listen for events + */ Bangle.loadWidgets(); // Clear the screen once, at startup and set the correct theme. From 177656f1fe86f74dbd62114eb7738af92de20700 Mon Sep 17 00:00:00 2001 From: David Peer Date: Sun, 17 Apr 2022 09:45:01 +0200 Subject: [PATCH 231/312] Logo is now the first info entry. --- apps/bwclk/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/bwclk/app.js b/apps/bwclk/app.js index 56607135f..5240e69ec 100644 --- a/apps/bwclk/app.js +++ b/apps/bwclk/app.js @@ -111,12 +111,12 @@ var imgWatch = { */ var infoArray = [ function(){ return [ null, null, "left" ] }, + function(){ return [ "Bangle", imgWatch, "right" ] }, function(){ return [ E.getBattery() + "%", imgBattery, "left" ] }, function(){ return [ getSteps(), imgSteps, "left" ] }, function(){ return [ Math.round(Bangle.getHealthStatus("last").bpm) + " bpm", imgBpm, "left"] }, function(){ return [ getWeather().temp, imgTemperature, "left" ] }, function(){ return [ getWeather().wind, imgWind, "left" ] }, - function(){ return [ "Bangle", imgWatch, "right" ] } ]; const NUM_INFO=infoArray.length; From 8a84dc31f739ab0e68bfbe117a63cc8b93755ab1 Mon Sep 17 00:00:00 2001 From: Anthony Zhang Date: Mon, 18 Apr 2022 04:32:13 -0400 Subject: [PATCH 232/312] Add HeartZone app --- apps/heartzone/ChangeLog | 1 + apps/heartzone/README.md | 35 ++++++++++ apps/heartzone/app-icon.js | 2 + apps/heartzone/app.js | 87 +++++++++++++++++++++++++ apps/heartzone/icon.png | Bin 0 -> 4926 bytes apps/heartzone/metadata.json | 20 ++++++ apps/heartzone/screenshots/paused.png | Bin 0 -> 3325 bytes apps/heartzone/screenshots/running.png | Bin 0 -> 3510 bytes apps/heartzone/screenshots/start.png | Bin 0 -> 3405 bytes apps/heartzone/settings.js | 27 ++++++++ 10 files changed, 172 insertions(+) create mode 100644 apps/heartzone/ChangeLog create mode 100644 apps/heartzone/README.md create mode 100644 apps/heartzone/app-icon.js create mode 100644 apps/heartzone/app.js create mode 100644 apps/heartzone/icon.png create mode 100644 apps/heartzone/metadata.json create mode 100644 apps/heartzone/screenshots/paused.png create mode 100644 apps/heartzone/screenshots/running.png create mode 100644 apps/heartzone/screenshots/start.png create mode 100644 apps/heartzone/settings.js diff --git a/apps/heartzone/ChangeLog b/apps/heartzone/ChangeLog new file mode 100644 index 000000000..cc2219306 --- /dev/null +++ b/apps/heartzone/ChangeLog @@ -0,0 +1 @@ +1.0: Initial release. diff --git a/apps/heartzone/README.md b/apps/heartzone/README.md new file mode 100644 index 000000000..4de60355d --- /dev/null +++ b/apps/heartzone/README.md @@ -0,0 +1,35 @@ +# HeartZone + +HeartZone continuously monitors your heart rate. If your heart rate is outside of your configured limits, you get a configurable buzz. + +Inspired by [Workout HRM](https://github.com/espruino/BangleApps/tree/master/apps/wohrm), but I wanted the following features: + +* Larger text, more contrast, and color-coding for better readability while exercising. +* Configurable buzz interval, instead of at every heart rate reading (which was too distracting). +* Pause for a rest and resume afterwards without having to restart the heart rate sensor (which takes several seconds each time to stabilize). +* Configure the minimum heart rate confidence threshold (bad readings cause buzzes that have to be ignored). + +However, compared to Workout HRM, HeartZone doesn't support: + +* In-app configuration of the heart rate thresholds - you can only do it in the Settings app. +* Bangle.js 1 - this only supports Bangle.js 2. + +## Usage + +When you first start the app, it will begin displaying your heart rate after a few seconds. Until the heart rate confidence is above your configured minimum confidence, the background will be colored red: + +![Start screen](screenshots/start.png) + +After the heart rate confidence is at an acceptable level, the background will be colored white, and you will receive buzzes on your wrist while your heart rate is out of the configured range. By default, the BPM-too-low buzz is 200ms, while the BPM-too-high buzz is 1000ms: + +![Screen while we are monitoring](screenshots/running.png) + +If you're taking a break, swipe down to turn off the buzzes while continuing to measure and display your heart rate (swipe up again to end your break): + +![Screen while we are paused](screenshots/paused.png) + +When you're done, simply press the side button to exit the app. + +## Creator + +[Uberi](https://github.com/Uberi) diff --git a/apps/heartzone/app-icon.js b/apps/heartzone/app-icon.js new file mode 100644 index 000000000..07c8be0b8 --- /dev/null +++ b/apps/heartzone/app-icon.js @@ -0,0 +1,2 @@ +// generated by http://www.espruino.com/Image+Converter from icon.png +require("heatshrink").decompress(atob("mEwwkBiIA/AHqFCAxQWJ5gABCIQGGABEQB4QABgIGGC5MMCAnAAwwuOABAwIC64/FABBIIC68ADBnAVJEP+AXLBoJ2H/4XN/54GBAIXOGAouBBAMAABQXBGAoHCAB4wDFwQARGAYvWL7CPDbBXAR46/DiAXJgK/Id4URGBHABobwHEAIwIBQQuHAAcYGA3AwIUKC4eAC4sIC5+IGAnAxAXQkAXDgQXRkQwC4EiC6QwCgQXTl0M4HiC6nghwXV93uC9MRC44WOGAIXFFx4ABC4oWQiMSC4chC6MRC4YWSiMeC4PhC6cRC4IWUGAIuVAH4AVA=")) \ No newline at end of file diff --git a/apps/heartzone/app.js b/apps/heartzone/app.js new file mode 100644 index 000000000..9ec3f005d --- /dev/null +++ b/apps/heartzone/app.js @@ -0,0 +1,87 @@ +// clear screen and draw widgets +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +var statusRect = {x: Bangle.appRect.x, y: Bangle.appRect.y, w: Bangle.appRect.w, h: 32}; +var settingsRect = {x: Bangle.appRect.x, y: Bangle.appRect.y2 - 16, w: Bangle.appRect.w, h: 16}; +var hrmRect = {x: Bangle.appRect.x, y: statusRect.y + statusRect.h, w: Bangle.appRect.w, h: Bangle.appRect.h - statusRect.h - settingsRect.h}; + +var isPaused = false; +var settings = Object.assign({ + minBpm: 120, + maxBpm: 160, + minConfidence: 60, + minBuzzIntervalSeconds: 5, + tooLowBuzzDurationMillis: 200, + tooHighBuzzDurationMillis: 1000, +}, require('Storage').readJSON("heartzone.settings.json", true) || {}); + +// draw current settings at the bottom +g.setFont6x15(1).setFontAlign(0, -1, 0); +g.drawString(settings.minBpm + "=" + settings.minConfidence + "% conf.", settingsRect.x + (settingsRect.w / 2), settingsRect.y + 4); + +function drawStatus(status) { // draw status bar at the top + g.setBgColor(g.theme.bg).setColor(g.theme.fg); + g.clearRect(statusRect); + + g.setFontVector(statusRect.h - 4).setFontAlign(0, -1, 0); + g.drawString(status, statusRect.x + (statusRect.w / 2), statusRect.y + 2); +} + +function drawHRM(hrmInfo) { // draw HRM info display + g.setBgColor(hrmInfo.confidence > settings.minConfidence ? '#fff' : '#f00').setColor(hrmInfo.confidence > settings.minConfidence ? '#000' : '#fff'); + g.setFontAlign(-1, -1, 0); + g.clearRect(hrmRect); + + var px = hrmRect.x + 10, py = hrmRect.y + 10; + g.setFontVector((hrmRect.h / 2) - 20); + g.drawString(hrmInfo.bpm, px, py); + g.setFontVector(16); + g.drawString('BPM', px + g.stringWidth(hrmInfo.bpm.toString()) + 32, py); + py += hrmRect.h / 2; + + g.setFontVector((hrmRect.h / 2) - 20); + g.drawString(hrmInfo.confidence, px, py); + g.setFontVector(16); + g.drawString('% conf.', px + g.stringWidth(hrmInfo.confidence.toString()) + 32, py); +} + +drawHRM({bpm: '?', confidence: '?'}); +drawStatus('RUNNING'); + +var lastBuzz = getTime(); +Bangle.on('HRM', function(hrmInfo) { + if (!isPaused) { + var currentTime; + if (hrmInfo.confidence > settings.minConfidence) { + if (hrmInfo.bpm < settings.minBpm) { + currentTime = getTime(); + if (currentTime - lastBuzz > settings.minBuzzIntervalSeconds) { + lastBuzz = currentTime; + Bangle.buzz(settings.tooLowBuzzDurationMillis); + } + } else if (hrmInfo.bpm > settings.maxBpm) { + currentTime = getTime(); + if (currentTime - lastBuzz > minBuzzIntervalSeconds) { + lastBuzz = currentTime; + Bangle.buzz(settings.tooHighBuzzDurationMillis); + } + } + } + } + drawHRM(hrmInfo); +}); + +Bangle.setUI('updown', function(action) { + if (action == -1) { // up + isPaused = false; + drawStatus("RUNNING"); + } else if (action == 1) { // down + isPaused = true; + drawStatus("PAUSED"); + } +}); +setWatch(function() { Bangle.setHRMPower(false, "heartzone"); load(); }, BTN1); + +Bangle.setHRMPower(true, "heartzone"); diff --git a/apps/heartzone/icon.png b/apps/heartzone/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..60ece4b32311242bf1e9d3a1f165ce94742d1bc5 GIT binary patch literal 4926 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 literal 0 HcmV?d00001 diff --git a/apps/heartzone/metadata.json b/apps/heartzone/metadata.json new file mode 100644 index 000000000..04297d76c --- /dev/null +++ b/apps/heartzone/metadata.json @@ -0,0 +1,20 @@ +{ + "id": "heartzone", + "name": "HeartZone", + "version": "1.0", + "description": "Exercise app for keeping your heart rate in the aerobic zone. Buzzes the watch at configurable intervals when your heart rate is outside of configured limits.", + "screenshots": [ + {"url": "screenshots/start.png"}, + {"url": "screenshots/running.png"}, + {"url": "screenshots/paused.png"} + ], + "icon": "icon.png", + "tags": "health", + "supports": ["BANGLEJS2"], + "storage": [ + {"name":"heartzone.app.js","url":"app.js"}, + {"name":"heartzone.settings.js","url":"settings.js"}, + {"name":"heartzone.img","url":"app-icon.js","evaluate":true} + ], + "data": [{"name":"heartzone.settings.json"}] +} diff --git a/apps/heartzone/screenshots/paused.png b/apps/heartzone/screenshots/paused.png new file mode 100644 index 0000000000000000000000000000000000000000..5f89ed07601e1e47fe20c6b54c61604d961e19d3 GIT binary patch literal 3325 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 literal 0 HcmV?d00001 diff --git a/apps/heartzone/screenshots/start.png b/apps/heartzone/screenshots/start.png new file mode 100644 index 0000000000000000000000000000000000000000..195957fa0448dde63a66c3231b97a85c8a950b79 GIT binary patch literal 3405 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 Dr7cj6 literal 0 HcmV?d00001 diff --git a/apps/heartzone/settings.js b/apps/heartzone/settings.js new file mode 100644 index 000000000..64030b0a3 --- /dev/null +++ b/apps/heartzone/settings.js @@ -0,0 +1,27 @@ +(function(back) { + var FILE = "heartzone.settings.json"; + var settings = Object.assign({ + minBpm: 120, + maxBpm: 160, + minConfidence: 60, + minBuzzIntervalSeconds: 5, + tooLowBuzzDurationMillis: 200, + tooHighBuzzDurationMillis: 1000, + }, require('Storage').readJSON(FILE, true) || {}); + + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + + // Show the menu + E.showMenu({ + "" : { "title" : "HeartZone" }, + "< Save & Return" : () => { writeSettings(); back(); }, + 'Min BPM': {value: 0 | settings.minBpm, min: 80, max: 200, step: 10, onchange: v => { settings.minBpm = v; }}, + 'Max BPM': {value: 0 | settings.maxBpm, min: 80, max: 200, step: 10, onchange: v => { settings.maxBpm = v; }}, + 'Min % conf.': {value: 0 | settings.minConfidence, min: 30, max: 100, step: 5, onchange: v => { settings.minConfidence = v; }}, + 'Min buzz int. (sec)': {value: 0 | settings.minBuzzIntervalSeconds, min: 1, max: 30, onchange: v => { settings.minBuzzIntervalSeconds = v; }}, + 'BPM too low buzz (ms)': {value: 0 | settings.tooLowBuzzDurationMillis, min: 0, max: 3000, step: 100, onchange: v => { settings.tooLowBuzzDurationMillis = v; }}, + 'BPM too high buzz (ms)': {value: 0 | settings.tooHighBuzzDurationMillis, min: 0, max: 3000, step: 100, onchange: v => { settings.tooHighBuzzDurationMillis = v; }}, + }); +}) From 50ca27875e7d0425296c5ddef7fe53b05e3479d7 Mon Sep 17 00:00:00 2001 From: Anthony Zhang Date: Mon, 18 Apr 2022 04:45:50 -0400 Subject: [PATCH 233/312] Add README --- apps/heartzone/metadata.json | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/heartzone/metadata.json b/apps/heartzone/metadata.json index 04297d76c..e243063a2 100644 --- a/apps/heartzone/metadata.json +++ b/apps/heartzone/metadata.json @@ -3,6 +3,7 @@ "name": "HeartZone", "version": "1.0", "description": "Exercise app for keeping your heart rate in the aerobic zone. Buzzes the watch at configurable intervals when your heart rate is outside of configured limits.", + "readme":"README.md", "screenshots": [ {"url": "screenshots/start.png"}, {"url": "screenshots/running.png"}, From 43dedbf7093699ea3ca49887e529fa4fdb71e169 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 15:05:41 +0200 Subject: [PATCH 234/312] add a lib.js for common operations --- apps/activityreminder/app.js | 26 +++++++++----------------- apps/activityreminder/boot.js | 22 +++++----------------- apps/activityreminder/lib.js | 18 ++++++++++++++++++ apps/activityreminder/metadata.json | 11 ++++++----- 4 files changed, 38 insertions(+), 39 deletions(-) create mode 100644 apps/activityreminder/lib.js diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 5fefbc97a..e146232b2 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,11 +1,3 @@ -global.activityreminder = Object.assign({ - enabled: true, - startHour: 9, - endHour: 20, - maxInnactivityMin: 30, - dismissDelayMin: 15, - minSteps: 50 -}, require("Storage").readJSON("activityreminder.json", true) || {}); var stepsArray = []; // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it @@ -15,14 +7,14 @@ function drawAlert(){ title:"Activity reminder", buttons : {"Ok": true,"Dismiss": false} }).then(function(v) { - console.log(global.stepsArray); + console.log(stepsArray); // todo remove if(v == true){ - stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); - // todo save stepsArray + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); + require("activityreminder").saveStepsArray(stepsArray); } if(v == false){ - stepsArray = global.stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); - // todo save stepsArray + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - activityreminder.dismissDelayMin); + require("activityreminder").saveStepsArray(stepsArray); } load(); }); @@ -41,14 +33,14 @@ function run() } }else{ // todo find something else to do when there is no alert to show, showing the setting is a placeholder for now - eval(require("Storage").read("android.settings.js"))(()=>load()); + eval(require("Storage").read("activityreminder.settings.js"))(()=>load()); } - - } g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -run(); +global.activityreminder = require("activityreminder").loadSettings(); +stepsArray = require("activityreminder").loadStepsArray(); +run() diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 7b33b35ff..02f571124 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -1,23 +1,10 @@ -global.activityreminder = Object.assign({ - enabled: true, - startHour: 9, - endHour: 20, - maxInnactivityMin: 30, - dismissDelayMin: 15, - minSteps: 50 -}, require("Storage").readJSON("activityreminder.json", true) || {}); - -var stepsArray = []; // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it - - -// todo put it in sequential to see if it work still +global.activityreminder = require("activityreminder").loadSettings(); if (global.activityreminder) { activityreminder = Object.assign(activityreminder, { - run: function(){ var now = new Date(); var h = now.getHours(); @@ -27,13 +14,13 @@ if (global.activityreminder) { var health = Bangle.getHealthStatus("day"); stepsArray.unshift(health.steps); stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); - // todo save stepsArray + require("activityreminder").saveStepsArray(stepsArray); } else{ if(stepsArray != []) { stepsArray = []; - // todo save stepsArray + require("activityreminder").saveStepsArray(stepsArray); } } @@ -46,6 +33,7 @@ if (global.activityreminder) { } }); - setInterval(global.activityreminder.run, 60000); + stepsArray = require("activityreminder").loadStepsArray(); // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it + setInterval(global.activityreminder.run, 1000); // todo change back to 60000 } diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js new file mode 100644 index 000000000..ef4e58712 --- /dev/null +++ b/apps/activityreminder/lib.js @@ -0,0 +1,18 @@ +export.loadSettings = function() { + return Object.assign({ + enabled: true, + startHour: 9, + endHour: 20, + maxInnactivityMin: 30, + dismissDelayMin: 15, + minSteps: 50 + }, require("Storage").readJSON("activityreminder.settings.json", true) || {}); +} + +exports.saveStepsArray = function(stepsArray) { + require("Storage").writeJSON("activityreminder.stepsarray.json", stepsArray); +} + +exports.loadStepsArray = function(){ + return require("Storage").readJSON("activityreminder.stepsarray.json") || []; +} \ No newline at end of file diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 182585f10..0b7633144 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -10,12 +10,13 @@ "supports": ["BANGLEJS", "BANGLEJS2"], "readme": "README.md", "storage": [ - {"name": "activityreminder.app.js","url":"app.js"}, - {"name": "activityreminder.boot.js","url": "boot.js"}, - {"name": "activityreminder.settings.js","url": "settings.js"}, - {"name": "activityreminder.img","url": "app-icon.js","evaluate": true} + {"name": "activityreminder.app.js", "url":"app.js"}, + {"name": "activityreminder.boot.js", "url": "boot.js"}, + {"name": "activityreminder.settings.js", "url": "settings.js"}, + {"name": "activityreminder", "url": "lib.js"}, + {"name": "activityreminder.img", "url": "app-icon.js", "evaluate": true} ], "data": [ - {"name": "activityreminder.json"} + {"name": "activityreminder.settings.json", "name": "activityreminder.stepsarray.json"} ] } From a3682c51f0ea172c786b49a60446735eaf004f0b Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 15:07:38 +0200 Subject: [PATCH 235/312] Fix loadSettings --- apps/activityreminder/app.js | 4 ---- apps/activityreminder/lib.js | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index e146232b2..664249d03 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,7 +1,3 @@ - -var stepsArray = []; // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it - - function drawAlert(){ E.showPrompt("Innactivity detected",{ title:"Activity reminder", diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index ef4e58712..1cddfcc40 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -1,4 +1,4 @@ -export.loadSettings = function() { +exports.loadSettings = function() { return Object.assign({ enabled: true, startHour: 9, From 1a42e8dcb424d3eb0055f2ab2741d36e2349fd36 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 18 Apr 2022 15:13:25 +0200 Subject: [PATCH 236/312] Mrk.Color doesn't reflect the color selected #1706 --- apps/timecal/ChangeLog | 3 ++- apps/timecal/README.md | 20 ++++++++++---------- apps/timecal/metadata.json | 2 +- apps/timecal/timecal.settings.js | 18 ++++++++---------- 4 files changed, 21 insertions(+), 22 deletions(-) diff --git a/apps/timecal/ChangeLog b/apps/timecal/ChangeLog index e48145b4b..57e7a1758 100644 --- a/apps/timecal/ChangeLog +++ b/apps/timecal/ChangeLog @@ -7,4 +7,5 @@ -> added settings to render cal view begin day (-1: today, 0:sunday, 1:monday [default]) 0.03: a lot of more settings for outline, colors and highlights 0.04: finalized README, fixed settings cancel, fixed border-setting -0.05: bugfix: default settings \ No newline at end of file +0.05: bugfix: default settings +0.06: bugfix: Mrk.Color doesn't reflect the color selected, fixes #1706 diff --git a/apps/timecal/README.md b/apps/timecal/README.md index d26f9ba4d..8c5d619ad 100644 --- a/apps/timecal/README.md +++ b/apps/timecal/README.md @@ -8,15 +8,15 @@ Shows the ### The settings menu Calendar View can be customized -* < Save: Exist and save the current settings -* Show date: Choose if and how the date is displayed: none, locale (default), monthfull or monthshort.yearshort #weeknum with 0 prefixed -* Start wday: Set day of week start. Values: 0=Sunday, 1=Monday,...,6=Saturday or -1=Relative to today (default 0: Sunday) -* Su color: Set Sundays color. Values: none (default), red, green or blue -* Border: show or none (default) +* < Save: Exit and save the current settings +* Show date: Choose if and how the date is displayed: none, locale [default], monthfull or monthshort.yearshort #weeknum with 0 prefixed +* Start wday: Set day of week start. Values: 0=Sunday, 1=Monday,...,6=Saturday or -1=Relative to today [default 0: Sunday] +* Su color: Set Sundays color. Values: none [default], red, green or blue +* Border: show or none [default] * Submenu Today settings - choose how today is highlighted * < Back: - * Color: none, red (default), green or blue - * Marker: Outline today graphically. Values: none (default), circle, rect(angle) - * Mrk.Color: Circle/rectangle color: red (default), green or blue - * Mrk.Size: Circle/rectangle thickness in pixel: min:1, max: 10, default:3 -* < Cancel: Exit and no change. Nevertheless missing default settings and superflous settings will be removed and saved. + * Color: none, red [default], green or blue + * Marker: Highlight today graphically. Values: none [default], circle, rectangle or filled + * Mrk.Color: Circle/rectangle color: red, green [default] or blue + * Mrk.Size: Circle/rectangle thickness in pixel: min: 1 to 10:max [default:3] +* < Cancel: Exit and no change. (Nevertheless missing default settings will be added and superflous settings will be removed.) diff --git a/apps/timecal/metadata.json b/apps/timecal/metadata.json index f439f4e9c..287dce0ae 100644 --- a/apps/timecal/metadata.json +++ b/apps/timecal/metadata.json @@ -1,7 +1,7 @@ { "id": "timecal", "name": "TimeCal", "shortName":"TimeCal", - "version":"0.05", + "version":"0.06", "description": "TimeCal shows the date/time along with a 3 week calendar", "icon": "icon.png", "type": "clock", diff --git a/apps/timecal/timecal.settings.js b/apps/timecal/timecal.settings.js index e86f3d8b8..8a7867c0d 100644 --- a/apps/timecal/timecal.settings.js +++ b/apps/timecal/timecal.settings.js @@ -64,9 +64,7 @@ format: v => v ? /*LANG*/"show" : /*LANG*/"none", onchange: v => chngdSttngs.calBrdr = v }, - /*LANG*/"Today settings": () => { - showTodayMenu(); - }, + /*LANG*/"Today settings": () => showTodayMenu(), /*LANG*/"< Cancel": () => cancelExitSettings() }); }; @@ -75,9 +73,9 @@ E.showMenu({ "": { "title": /*LANG*/"Today settings" - }, - "< Back": () => showMainMenu(), - /*LANG*/"Color": { + }, + "< Back": () => showMainMenu(), + /*LANG*/"Color": { value: chngdSttngs.tdyNumClr, min: 0, max: 3, format: v => [/*LANG*/"none", /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], @@ -91,8 +89,8 @@ }, /*LANG*/"Mrk.Color": { value: chngdSttngs.tdyMrkClr, - min: 0, max: 2, - format: v => [/*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], + min: 1, max: 3, + format: v => [undefined, /*LANG*/"red", /*LANG*/"green", /*LANG*/"blue"][v], onchange: v => chngdSttngs.tdyMrkClr = v }, /*LANG*/"Mrk.Size": { @@ -101,8 +99,8 @@ format: v => v+"px", onchange: v => chngdSttngs.tdyMrkPxl = v }, - /*LANG*/"< Cancel": () => cancelExitSettings() - }); + /*LANG*/"< Cancel": () => cancelExitSettings() + }); }; showMainMenu(); From 6517b926eab4a91a3e4c5607ad6e0dcf21e1e9c1 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 15:40:13 +0200 Subject: [PATCH 237/312] increase the step time a bit to test a bit easier --- apps/activityreminder/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 02f571124..cf9c2eadf 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -34,6 +34,6 @@ if (global.activityreminder) { }); stepsArray = require("activityreminder").loadStepsArray(); // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it - setInterval(global.activityreminder.run, 1000); // todo change back to 60000 + setInterval(global.activityreminder.run, 10000); // todo change back to 60000 } From 08c0964527c7320db8f8b9c8a58733ec66443336 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 15:46:44 +0200 Subject: [PATCH 238/312] Increase the step count delay to one min --- apps/activityreminder/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index cf9c2eadf..b3df062cd 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -34,6 +34,6 @@ if (global.activityreminder) { }); stepsArray = require("activityreminder").loadStepsArray(); // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it - setInterval(global.activityreminder.run, 10000); // todo change back to 60000 + setInterval(global.activityreminder.run, 60000); // todo change back to 60000 } From 09c09303c3f63910a52379de54d1fdc70d6b0f17 Mon Sep 17 00:00:00 2001 From: Danny Falss Date: Mon, 18 Apr 2022 15:48:34 +0200 Subject: [PATCH 239/312] Update bangle-bug-report-custom-form.yaml --- .github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml index c32feaf85..484b3ba85 100644 --- a/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml +++ b/.github/ISSUE_TEMPLATE/bangle-bug-report-custom-form.yaml @@ -8,6 +8,7 @@ body: attributes: value: | **:fire: Attention: If you have a question then please ask on the [Bangle.js forum](http://forum.espruino.com/microcosms/1424/) :fire:** + ----------------------------------------------------- - type: dropdown id: hwversion attributes: From 202dcdd7819c1df4c761fe5fe338c519a625650b Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Mon, 18 Apr 2022 15:49:21 +0200 Subject: [PATCH 240/312] removed in progress work on sleepphase --- apps/sleepphasealarm/ChangeLog | 1 - apps/sleepphasealarm/app.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index b78459a11..dbc3a0b82 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -1,4 +1,3 @@ 0.01: New App! 0.02: Respect Quiet Mode 0.03: Add compatibility for Bangle.js 2 and new firmware, added "Alarm at " for the alarm time -0.04: added support for qalarms diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index c5515d3fb..e963f2c40 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -1,5 +1,5 @@ -const alarms = require("Storage").readJSON("alarm.json",1)||require("Storage").readJSON("qalarm.json",1)||[]; const BANGLEJS2 = process.env.HWVERSION == 2; //# check for bangle 2 +const alarms = require("Storage").readJSON("alarm.json",1)||[]; const active = alarms.filter(a=>a.on); // Sleep/Wake detection with Estimation of Stationary Sleep-segments (ESS): From 4f17ed02d6bc2f25225c27029decfadc0432c319 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Mon, 18 Apr 2022 16:26:01 +0200 Subject: [PATCH 241/312] widcal: fix memory leak Repeated redrawing would create multiple redraw-timeouts --- apps/widcal/ChangeLog | 3 ++- apps/widcal/metadata.json | 2 +- apps/widcal/widget.js | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/widcal/ChangeLog b/apps/widcal/ChangeLog index a4bc24d1a..07b8f7424 100644 --- a/apps/widcal/ChangeLog +++ b/apps/widcal/ChangeLog @@ -1 +1,2 @@ -0.01: First version \ No newline at end of file +0.01: First version +0.02: Fix memory leak \ No newline at end of file diff --git a/apps/widcal/metadata.json b/apps/widcal/metadata.json index 74ab6d488..fc7d6dd1d 100644 --- a/apps/widcal/metadata.json +++ b/apps/widcal/metadata.json @@ -1,7 +1,7 @@ { "id": "widcal", "name": "Calendar Widget", - "version": "0.01", + "version": "0.02", "description": "Widget with the current date", "icon": "widget.png", "type": "widget", diff --git a/apps/widcal/widget.js b/apps/widcal/widget.js index 4214d280a..d4a4676a7 100644 --- a/apps/widcal/widget.js +++ b/apps/widcal/widget.js @@ -24,7 +24,8 @@ ]); } // redraw when date changes - setTimeout(()=>WIDGETS["cal"].draw(), (86401 - Math.floor(date/1000) % 86400)*1000); + if (WIDGETS["cal"].to) clearTimeout(WIDGETS["cal"].to); + WIDGETS["cal"].to = setTimeout(()=>WIDGETS["cal"].draw(), (86401 - Math.floor(date/1000) % 86400)*1000); } }; })(); From 783a55fafa8ba82e53bbe9b24b558a15d45d0f34 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 16:28:34 +0200 Subject: [PATCH 242/312] Code cleanup --- apps/activityreminder/app.js | 23 +++++------- apps/activityreminder/boot.js | 61 +++++++++++++------------------ apps/activityreminder/settings.js | 4 +- 3 files changed, 38 insertions(+), 50 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 664249d03..f4bc67fa8 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -4,7 +4,7 @@ function drawAlert(){ buttons : {"Ok": true,"Dismiss": false} }).then(function(v) { console.log(stepsArray); // todo remove - if(v == true){ + if(v == true){ stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); require("activityreminder").saveStepsArray(stepsArray); } @@ -15,28 +15,25 @@ function drawAlert(){ load(); }); - Bangle.buzz(); + Bangle.buzz(400); setTimeout(load, 10000); } -function run() -{ - if(stepsArray.length == activityreminder.maxInnactivityMin){ - if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) - { - drawAlert(); +function run(){ + if(stepsArray.length == activityreminder.maxInnactivityMin){ + if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps){ + drawAlert(); + } + }else{ + eval(require("Storage").read("activityreminder.settings.js"))(()=>load()); } - }else{ - // todo find something else to do when there is no alert to show, showing the setting is a placeholder for now - eval(require("Storage").read("activityreminder.settings.js"))(()=>load()); - } } g.clear(); Bangle.loadWidgets(); Bangle.drawWidgets(); -global.activityreminder = require("activityreminder").loadSettings(); +activityreminder = require("activityreminder").loadSettings(); stepsArray = require("activityreminder").loadStepsArray(); run() diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index b3df062cd..6ce6c08d9 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -1,39 +1,30 @@ -global.activityreminder = require("activityreminder").loadSettings(); - -if (global.activityreminder) { - - activityreminder = - Object.assign(activityreminder, - { - run: function(){ - var now = new Date(); - var h = now.getHours(); - console.log(global.stepsArray); - if(h >= activityreminder.startHour && h < activityreminder.endHour) - { - var health = Bangle.getHealthStatus("day"); - stepsArray.unshift(health.steps); - stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); - require("activityreminder").saveStepsArray(stepsArray); +function run(){ + var now = new Date(); + var h = now.getHours(); + console.log(stepsArray); // todo remove + if(h >= activityreminder.startHour && h < activityreminder.endHour){ + var health = Bangle.getHealthStatus("day"); + stepsArray.unshift(health.steps); + stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin); + require("activityreminder").saveStepsArray(stepsArray); + } + else{ + if(stepsArray != []){ + stepsArray = []; + require("activityreminder").saveStepsArray(stepsArray); } - else{ - if(stepsArray != []) - { - stepsArray = []; - require("activityreminder").saveStepsArray(stepsArray); - } - + } + if(stepsArray.length >= activityreminder.maxInnactivityMin){ + if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps){ + load('activityreminder.app.js'); } - if(stepsArray.length == activityreminder.maxInnactivityMin){ - if (stepsArray[0] - stepsArray[stepsArray.length-1] < activityreminder.minSteps) - { - load('activityreminder.app.js'); - } - } - } - }); - - stepsArray = require("activityreminder").loadStepsArray(); // todo load from storage and save in storage on activityreminder.data. Create lib.js to read and write in it - setInterval(global.activityreminder.run, 60000); // todo change back to 60000 + } +} + + +activityreminder = require("activityreminder").loadSettings(); +if(activityreminder.enabled) { + stepsArray = require("activityreminder").loadStepsArray(); + setInterval(global.activityreminder.run, 60000); } diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index ddf4ff17a..03e3bc938 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -6,7 +6,7 @@ startHour: 9, endHour: 20, maxInnactivityMin: 30, - delayondismiss: 15, + dismissDelayMin: 15, minsteps: 50, }, require('Storage').readJSON(FILE, true) || {}); @@ -60,7 +60,7 @@ }, 'Min steps': { value: 50|settings.minSteps, - min: 5, max: 60, + min: 10, max: 500, onchange: v => { settings.minSteps = v; writeSettings(); From df3b4240d94355c1a3d1fe1ddc79d11274487ae1 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 16:34:51 +0200 Subject: [PATCH 243/312] load settings from the right file --- 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 03e3bc938..359549cbe 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -1,5 +1,5 @@ (function(back) { - var FILE = "activityreminder.json"; + var FILE = "activityreminder.settings.json"; // Load settings var settings = Object.assign({ enabled: true, From ae35eb27c053db106c9b51a1bde510e0d8c3c86e Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 16:41:57 +0200 Subject: [PATCH 244/312] move some function to lib.js --- apps/activityreminder/app.js | 2 -- apps/activityreminder/lib.js | 4 ++++ apps/activityreminder/settings.js | 26 +++++++------------------- 3 files changed, 11 insertions(+), 21 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index f4bc67fa8..2a89b4ec6 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -14,10 +14,8 @@ function drawAlert(){ } load(); }); - Bangle.buzz(400); setTimeout(load, 10000); - } function run(){ diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index 1cddfcc40..4b2d01386 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -9,6 +9,10 @@ exports.loadSettings = function() { }, require("Storage").readJSON("activityreminder.settings.json", true) || {}); } +export.writeSettings = function(settings){ + require('Storage').writeJSON("activityreminder.settings.json", settings); +} + exports.saveStepsArray = function(stepsArray) { require("Storage").writeJSON("activityreminder.stepsarray.json", stepsArray); } diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 359549cbe..99150c8d4 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -1,18 +1,6 @@ (function(back) { - var FILE = "activityreminder.settings.json"; // Load settings - var settings = Object.assign({ - enabled: true, - startHour: 9, - endHour: 20, - maxInnactivityMin: 30, - dismissDelayMin: 15, - minsteps: 50, - }, require('Storage').readJSON(FILE, true) || {}); - - function writeSettings() { - require('Storage').writeJSON(FILE, settings); - } + var settings = require("activityreminder").loadSettings(); // Show the menu E.showMenu({ @@ -23,7 +11,7 @@ format: v => v?"Yes":"No", onchange: v => { settings.enabled = v; - writeSettings(); + require("activityreminder").writeSettings(settings); } }, 'Start hour': { @@ -31,7 +19,7 @@ min: 0, max: 24, onchange: v => { settings.startHour = v; - writeSettings(); + require("activityreminder").writeSettings(settings) } }, 'End hour': { @@ -39,7 +27,7 @@ min: 0, max: 24, onchange: v => { settings.endHour = v; - writeSettings(); + require("activityreminder").writeSettings(settings) } }, 'Max innactivity': { @@ -47,7 +35,7 @@ min: 15, max: 60, onchange: v => { settings.maxInnactivityMin = v; - writeSettings(); + require("activityreminder").writeSettings(settings) } }, 'Dismiss delay': { @@ -55,7 +43,7 @@ min: 5, max: 15, onchange: v => { settings.dismissDelayMin = v; - writeSettings(); + require("activityreminder").writeSettings(settings) } }, 'Min steps': { @@ -63,7 +51,7 @@ min: 10, max: 500, onchange: v => { settings.minSteps = v; - writeSettings(); + require("activityreminder").writeSettings(settings) } } }); From bedf3fc226f2e563b6ce320d92ec55b84925353e Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 16:44:53 +0200 Subject: [PATCH 245/312] Fix issue in lib.js --- apps/activityreminder/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index 4b2d01386..5e7fd533c 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -9,7 +9,7 @@ exports.loadSettings = function() { }, require("Storage").readJSON("activityreminder.settings.json", true) || {}); } -export.writeSettings = function(settings){ +exports.writeSettings = function(settings){ require('Storage').writeJSON("activityreminder.settings.json", settings); } From b9ae26b757bcdf30aeb4fd2bdbcf2fb7bc999b8d Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 17:02:20 +0200 Subject: [PATCH 246/312] Hopefully fix the bugs --- apps/activityreminder/app.js | 3 ++- apps/activityreminder/lib.js | 10 +++++----- apps/activityreminder/settings.js | 14 +++++++++----- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 2a89b4ec6..0691b2d76 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -14,6 +14,7 @@ function drawAlert(){ } load(); }); + Bangle.buzz(400); setTimeout(load, 10000); } @@ -34,4 +35,4 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); activityreminder = require("activityreminder").loadSettings(); stepsArray = require("activityreminder").loadStepsArray(); -run() +run(); diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index 5e7fd533c..cae2977b1 100644 --- a/apps/activityreminder/lib.js +++ b/apps/activityreminder/lib.js @@ -7,16 +7,16 @@ exports.loadSettings = function() { dismissDelayMin: 15, minSteps: 50 }, require("Storage").readJSON("activityreminder.settings.json", true) || {}); -} +}; exports.writeSettings = function(settings){ - require('Storage').writeJSON("activityreminder.settings.json", settings); -} + require("Storage").writeJSON("activityreminder.settings.json", settings); +}; exports.saveStepsArray = function(stepsArray) { require("Storage").writeJSON("activityreminder.stepsarray.json", stepsArray); -} +}; exports.loadStepsArray = function(){ return require("Storage").readJSON("activityreminder.stepsarray.json") || []; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 99150c8d4..116440930 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -2,6 +2,10 @@ // Load settings var settings = require("activityreminder").loadSettings(); + function writeSettings() { + require('Storage').writeJSON(FILE, settings); + } + // Show the menu E.showMenu({ "" : { "title" : "Activity Reminder" }, @@ -19,7 +23,7 @@ min: 0, max: 24, onchange: v => { settings.startHour = v; - require("activityreminder").writeSettings(settings) + require("activityreminder").writeSettings(settings); } }, 'End hour': { @@ -27,7 +31,7 @@ min: 0, max: 24, onchange: v => { settings.endHour = v; - require("activityreminder").writeSettings(settings) + require("activityreminder").writeSettings(settings); } }, 'Max innactivity': { @@ -35,7 +39,7 @@ min: 15, max: 60, onchange: v => { settings.maxInnactivityMin = v; - require("activityreminder").writeSettings(settings) + require("activityreminder").writeSettings(settings); } }, 'Dismiss delay': { @@ -43,7 +47,7 @@ min: 5, max: 15, onchange: v => { settings.dismissDelayMin = v; - require("activityreminder").writeSettings(settings) + require("activityreminder").writeSettings(settings); } }, 'Min steps': { @@ -51,7 +55,7 @@ min: 10, max: 500, onchange: v => { settings.minSteps = v; - require("activityreminder").writeSettings(settings) + require("activityreminder").writeSettings(settings); } } }); From e00fadcb99abf5ac32c05a6e121557a3cf1d6107 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 17:15:01 +0200 Subject: [PATCH 247/312] change the file name to respect the 28 char limit --- apps/activityreminder/lib.js | 8 ++++---- apps/activityreminder/metadata.json | 2 +- apps/activityreminder/settings.js | 4 ---- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/apps/activityreminder/lib.js b/apps/activityreminder/lib.js index cae2977b1..fee30e4c3 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("activityreminder.settings.json", true) || {}); + }, require("Storage").readJSON("ar.settings.json", true) || {}); }; exports.writeSettings = function(settings){ - require("Storage").writeJSON("activityreminder.settings.json", settings); + require("Storage").writeJSON("ar.settings.json", settings); }; exports.saveStepsArray = function(stepsArray) { - require("Storage").writeJSON("activityreminder.stepsarray.json", stepsArray); + require("Storage").writeJSON("ar.stepsarray.json", stepsArray); }; exports.loadStepsArray = function(){ - return require("Storage").readJSON("activityreminder.stepsarray.json") || []; + return require("Storage").readJSON("ar.stepsarray.json") || []; }; \ No newline at end of file diff --git a/apps/activityreminder/metadata.json b/apps/activityreminder/metadata.json index 0b7633144..bc31776d6 100644 --- a/apps/activityreminder/metadata.json +++ b/apps/activityreminder/metadata.json @@ -17,6 +17,6 @@ {"name": "activityreminder.img", "url": "app-icon.js", "evaluate": true} ], "data": [ - {"name": "activityreminder.settings.json", "name": "activityreminder.stepsarray.json"} + {"name": "ar.settings.json", "name": "ar.stepsarray.json"} ] } diff --git a/apps/activityreminder/settings.js b/apps/activityreminder/settings.js index 116440930..638e7bd73 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -2,10 +2,6 @@ // Load settings var settings = require("activityreminder").loadSettings(); - function writeSettings() { - require('Storage').writeJSON(FILE, settings); - } - // Show the menu E.showMenu({ "" : { "title" : "Activity Reminder" }, From b985b61a3d45d1e724b747d31252f6f2173c8be7 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 17:30:57 +0200 Subject: [PATCH 248/312] fix boot.js (hopefully) --- apps/activityreminder/boot.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index 6ce6c08d9..de48be003 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -25,6 +25,6 @@ function run(){ activityreminder = require("activityreminder").loadSettings(); if(activityreminder.enabled) { stepsArray = require("activityreminder").loadStepsArray(); - setInterval(global.activityreminder.run, 60000); + setInterval(run, 60000); } From 8daef5459c88d4b1987dcfe1676190968ff4eafd Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 17:34:22 +0200 Subject: [PATCH 249/312] change default dismiss delay to see if it solve the issue with changing dismiss delay in settings --- 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 638e7bd73..65a19feb2 100644 --- a/apps/activityreminder/settings.js +++ b/apps/activityreminder/settings.js @@ -39,7 +39,7 @@ } }, 'Dismiss delay': { - value: 15|settings.dismissDelayMin, + value: 10|settings.dismissDelayMin, min: 5, max: 15, onchange: v => { settings.dismissDelayMin = v; From ac2941701458c01ba940a8cf3a64708b56aa9f89 Mon Sep 17 00:00:00 2001 From: Stiralbios Date: Mon, 18 Apr 2022 17:43:05 +0200 Subject: [PATCH 250/312] remove debug logs --- apps/activityreminder/app.js | 1 - apps/activityreminder/boot.js | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 0691b2d76..39c5bc71f 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -3,7 +3,6 @@ function drawAlert(){ title:"Activity reminder", buttons : {"Ok": true,"Dismiss": false} }).then(function(v) { - console.log(stepsArray); // todo remove if(v == true){ stepsArray = stepsArray.slice(0, activityreminder.maxInnactivityMin - 3); require("activityreminder").saveStepsArray(stepsArray); diff --git a/apps/activityreminder/boot.js b/apps/activityreminder/boot.js index de48be003..0f89bf543 100644 --- a/apps/activityreminder/boot.js +++ b/apps/activityreminder/boot.js @@ -1,7 +1,6 @@ function run(){ var now = new Date(); var h = now.getHours(); - console.log(stepsArray); // todo remove if(h >= activityreminder.startHour && h < activityreminder.endHour){ var health = Bangle.getHealthStatus("day"); stepsArray.unshift(health.steps); From 7bd88bc94f0b6fac74d89e679666c1e7040f3936 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 09:48:00 +0100 Subject: [PATCH 251/312] Update mosaic readme --- apps/mosaic/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/mosaic/README.md b/apps/mosaic/README.md index bf3ca671b..b2f31aef2 100644 --- a/apps/mosaic/README.md +++ b/apps/mosaic/README.md @@ -6,8 +6,9 @@ A fabulously colourful clock! * Dark and Light theme compatible, with a setting to override the digit colour scheme. * Show or hide widgets with a setting (default shows widgets). -![](mosaic_scr1.png) -![](mosaic_scr2.png) -![](mosaic_scr3.png) +![](mosaic-scr1.png) +![](mosaic-scr2.png) + +This clock is inspired by the mosaic watchface for pebble: https://apps.rebble.io/en_US/application/55386bcd2aead62b16000028 Written by: [Sir Indy](https://github.com/sir-indy) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) From 1e09140515a2f475a65c4d13dff699e2ff72bf4b Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:03:46 +0100 Subject: [PATCH 252/312] check icons is a bit more resilient --- apps/qmsched/icon.js | 3 +-- bin/sanitycheck.js | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/qmsched/icon.js b/apps/qmsched/icon.js index c0f4e2b66..53aeb55af 100644 --- a/apps/qmsched/icon.js +++ b/apps/qmsched/icon.js @@ -1,2 +1 @@ -// https://icons8.com/icon/19324/no-reminders -require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AElksF1wwtF4YwO0WiGFguBGFovfGB3MAAgwnFooxfGBAuJGEguLGEV/F5owh0YvpGH4vhGCQvd0YwQF7vMGCAveGCAvfGB4vgGBwvhGBouhGFLkIGEouIGEwvKGBguiGEQuNGEHN5owa5ouQ53P5/O5wyOGA3NDAIbBLyAUCAAQzCNBQwF0gVDXiQoBGQgAEEIILE0iSJdiozCFQw1FGBJgSABSVIeg7wQGSDDMFyQ0VCQQwdAAWcAAwPHGD4vPGD+iAAwRJGEgRLGEQRNeTwARF1wA/AH4AX")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwxH+AH4A/AH4AElksF1wwtF4YwO0WiGFguBGFovfGB3MAAgwnFooxfGBAuJGEguLGEV/F5owh0YvpGH4vhGCQvd0YwQF7vMGCAveGCAvfGB4vgGBwvhGBouhGFLkIGEouIGEwvKGBguiGEQuNGEHN5owa5ouQ53P5/O5wyOGA3NDAIbBLyAUCAAQzCNBQwF0gVDXiQoBGQgAEEIILE0iSJdiozCFQw1FGBJgSABSVIeg7wQGSDDMFyQ0VCQQwdAAWcAAwPHGD4vPGD+iAAwRJGEgRLGEQRNeTwARF1wA/AH4AX")) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index 363e86922..8fdb5a4d2 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -1,4 +1,4 @@ -#!/usr/bin/nodejs +#!/usr/bin/node /* Checks for any obvious problems in apps.json */ @@ -197,10 +197,11 @@ apps.forEach((app,appIdx) => { // warn if JS icon is the wrong size if (file.name == app.id+".img") { let icon; - let match = fileContents.match(/E\.toArrayBuffer\(atob\(\"([^"]*)\"\)\)/); + let match = fileContents.match(/^\s*E\.toArrayBuffer\(atob\(\"([^"]*)\"\)\)\s*$/); + if (match==null) match = fileContents.match(/^\s*atob\(\"([^"]*)\"\)\s*$/); if (match) icon = Buffer.from(match[1], 'base64'); else { - match = fileContents.match(/require\(\"heatshrink\"\)\.decompress\(\s*atob\(\s*\"([^"]*)\"\s*\)\s*\)/); + match = fileContents.match(/^\s*require\(\"heatshrink\"\)\.decompress\(\s*atob\(\s*\"([^"]*)\"\s*\)\s*\)\s*$/); if (match) icon = heatshrink.decompress(Buffer.from(match[1], 'base64')); else ERROR(`JS icon ${file.name} does not match the pattern 'require("heatshrink").decompress(atob("..."))'`); } From e5947807f8318dc896fb11d03a3b0c312836e17f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:04:11 +0100 Subject: [PATCH 253/312] latest core --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index e9097fa68..b04f32553 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit e9097fa680182069a5814c3e566a0bcbcb5e72a1 +Subproject commit b04f32553935f1479ad226ce1b2cff4f4b2e1a6f From 32d9ce7b557f804a32d5f29b7a1b5e53042e6c8f Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:23:10 +0100 Subject: [PATCH 254/312] new locale linked in --- lang/index.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lang/index.json b/lang/index.json index 341ddd6d1..20ceaab92 100644 --- a/lang/index.json +++ b/lang/index.json @@ -22,5 +22,6 @@ {"code":"ro_RO","name":"Romanian","url":"ro_RO.json"}, {"code":"sk_SK","name":"Slovak","url":"sk_SK.json"}, {"code":"sl_SL","name":"Slovenian","url":"sl_SL.json"}, - {"code":"nn_NO","name":"Norwegian (Nynorsk)","url":"nn_NO.json"} + {"code":"nn_NO","name":"Norwegian (Nynorsk)","url":"nn_NO.json"}, + {"code":"hr_HR","name":"Croatian","url":"hr_HR.json"} ] From 2a6f8815172dad455ac7600371b53609e007b544 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:38:46 +0100 Subject: [PATCH 255/312] minor tweak for new test code (maybe we should improve the test code) --- apps/heartzone/app-icon.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/heartzone/app-icon.js b/apps/heartzone/app-icon.js index 07c8be0b8..2e3692455 100644 --- a/apps/heartzone/app-icon.js +++ b/apps/heartzone/app-icon.js @@ -1,2 +1 @@ -// generated by http://www.espruino.com/Image+Converter from icon.png -require("heatshrink").decompress(atob("mEwwkBiIA/AHqFCAxQWJ5gABCIQGGABEQB4QABgIGGC5MMCAnAAwwuOABAwIC64/FABBIIC68ADBnAVJEP+AXLBoJ2H/4XN/54GBAIXOGAouBBAMAABQXBGAoHCAB4wDFwQARGAYvWL7CPDbBXAR46/DiAXJgK/Id4URGBHABobwHEAIwIBQQuHAAcYGA3AwIUKC4eAC4sIC5+IGAnAxAXQkAXDgQXRkQwC4EiC6QwCgQXTl0M4HiC6nghwXV93uC9MRC44WOGAIXFFx4ABC4oWQiMSC4chC6MRC4YWSiMeC4PhC6cRC4IWUGAIuVAH4AVA=")) \ No newline at end of file +require("heatshrink").decompress(atob("mEwwkBiIA/AHqFCAxQWJ5gABCIQGGABEQB4QABgIGGC5MMCAnAAwwuOABAwIC64/FABBIIC68ADBnAVJEP+AXLBoJ2H/4XN/54GBAIXOGAouBBAMAABQXBGAoHCAB4wDFwQARGAYvWL7CPDbBXAR46/DiAXJgK/Id4URGBHABobwHEAIwIBQQuHAAcYGA3AwIUKC4eAC4sIC5+IGAnAxAXQkAXDgQXRkQwC4EiC6QwCgQXTl0M4HiC6nghwXV93uC9MRC44WOGAIXFFx4ABC4oWQiMSC4chC6MRC4YWSiMeC4PhC6cRC4IWUGAIuVAH4AVA=")) From af378662d18bf9bec058a90d051f04193d6e735d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:51:10 +0100 Subject: [PATCH 256/312] remove accidental commit --- apps/messagesmusic/app.js~ | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 apps/messagesmusic/app.js~ diff --git a/apps/messagesmusic/app.js~ b/apps/messagesmusic/app.js~ deleted file mode 100644 index a02c7704f..000000000 --- a/apps/messagesmusic/app.js~ +++ /dev/null @@ -1,15 +0,0 @@ -let showMusic = () => { - Bangle.CLOCK = 1; // To pass condition in messages library - require('messages').pushMessage({"t":"add","artist":" ","album":" ","track":" ","dur":0,"c":-1,"n":-1,"id":"music","title":"Music","state":"play","new":true}); - Bangle.CLOCK = undefined; -}; - -var settings = require('Storage').readJSON('messages.settings.json', true) || {}; //read settings if they exist else set to empty dict -if (!settings.openMusic) { - settings.openMusic = true; // This app/hack works as intended only if this setting is true - require('Storage').writeJSON('messages.settings.json', settings); - E.showMessage("First run:\n\nMessages setting\n\n 'Auto-Open Music'\n\n set to 'Yes'"); - setTimeout(()=>{showMusic();}, 5000); -} else { - showMusic(); -}; From 746aee3042f49bacae0f74b7237f10c154331e21 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Tue, 19 Apr 2022 10:52:56 +0100 Subject: [PATCH 257/312] fix changelog formatting for test --- apps/pebble/ChangeLog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/pebble/ChangeLog b/apps/pebble/ChangeLog index 94ae15c8c..274c34a34 100644 --- a/apps/pebble/ChangeLog +++ b/apps/pebble/ChangeLog @@ -6,5 +6,5 @@ 0.06: Add dependancy on Pedometer Widget 0.07: Fix icon and ong file to 48x48 0.08: Add theme options and optional lock symbol -0.09 (1): Add support for internationalization (LANG placeholders + "locale" module) -0.09 (2): Get steps from built-in step counter (widpedom no more needed, fix #1697) +0.09: Add support for internationalization (LANG placeholders + "locale" module) + Get steps from built-in step counter (widpedom no more needed, fix #1697) From 6c0f16a45f7b72bc643ceb12833c09ad00e8d624 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Tue, 19 Apr 2022 14:09:52 +0200 Subject: [PATCH 258/312] Bumped to 0.32 for quiet mode auto-open setting --- apps/messages/ChangeLog | 1 + apps/messages/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 3e676c21e..75b171579 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -44,3 +44,4 @@ 0.29: Fix message list overwrites on Bangle.js 1 (fix #1642) 0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel) 0.31: Option to disable icon flashing +0.32: Added an option to allow quiet mode to override message auto-open diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index 5c1e67702..7886a7b30 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.31", + "version": "0.32", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From c4529d5c0a527c10b63c1403aefb6cacb29ad7a1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 13:22:53 +0100 Subject: [PATCH 259/312] Step counter widget (#2) * Create README.md * Add files via upload * Update metadata.json --- apps/widstep/ChangeLog | 1 + apps/widstep/README.md | 4 +++ apps/widstep/icons8-winter-boots-48.png | Bin 0 -> 1359 bytes apps/widstep/metadata.json | 15 ++++++++++ apps/widstep/widstep-dark.png | Bin 0 -> 3910 bytes apps/widstep/widstep-light.png | Bin 0 -> 3834 bytes apps/widstep/widstep.wid.js | 36 ++++++++++++++++++++++++ 7 files changed, 56 insertions(+) create mode 100644 apps/widstep/ChangeLog create mode 100644 apps/widstep/README.md create mode 100644 apps/widstep/icons8-winter-boots-48.png create mode 100644 apps/widstep/metadata.json create mode 100644 apps/widstep/widstep-dark.png create mode 100644 apps/widstep/widstep-light.png create mode 100644 apps/widstep/widstep.wid.js diff --git a/apps/widstep/ChangeLog b/apps/widstep/ChangeLog new file mode 100644 index 000000000..55cda0f21 --- /dev/null +++ b/apps/widstep/ChangeLog @@ -0,0 +1 @@ +0.01: New widget diff --git a/apps/widstep/README.md b/apps/widstep/README.md new file mode 100644 index 000000000..3441755e3 --- /dev/null +++ b/apps/widstep/README.md @@ -0,0 +1,4 @@ +# Step counter widget +This is my step counter widget. There are many like it, but this one is mine. +Designed to be as narrow as possible, but still easy to read, by sacrificing accuracy and only showing to the nearest 100 steps (0.1k). +Shows a subtle fill colour in the background for progress to the goal. The goal is picked up from the health tracker settings. diff --git a/apps/widstep/icons8-winter-boots-48.png b/apps/widstep/icons8-winter-boots-48.png new file mode 100644 index 0000000000000000000000000000000000000000..7dceceef03b8ef0f6bcb33d7665a6ce948171d71 GIT binary patch literal 1359 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 Date: Tue, 19 Apr 2022 15:10:51 +0100 Subject: [PATCH 260/312] Update metadata.json --- apps/widstep/metadata.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/widstep/metadata.json b/apps/widstep/metadata.json index 09e0efac9..ea108e0f1 100644 --- a/apps/widstep/metadata.json +++ b/apps/widstep/metadata.json @@ -3,12 +3,14 @@ "name": "Step counter widget", "version": "0.01", "description": "Step counter widget, narrow but clearly readable", + "readme": "README.md", "icon": "icons8-winter-boots-48.png", + "screenshots": [{"url":"widstep-light.png"},{"url":"widstep-dark.png"}], "type": "widget", "tags": "widget,health", "supports": ["BANGLEJS","BANGLEJS2"], "dependencies" : {"health":"app"}, - "allow_emulator":true, + "allow_emulator":false, "storage": [ {"name":"widstep.wid.js","url":"widstep.wid.js"} ] From 207dfadc58deb18c16061bd14a41874b53e54107 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:14:38 +0100 Subject: [PATCH 261/312] Update README.md --- apps/widstep/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/apps/widstep/README.md b/apps/widstep/README.md index 3441755e3..498f2ebd9 100644 --- a/apps/widstep/README.md +++ b/apps/widstep/README.md @@ -2,3 +2,7 @@ This is my step counter widget. There are many like it, but this one is mine. Designed to be as narrow as possible, but still easy to read, by sacrificing accuracy and only showing to the nearest 100 steps (0.1k). Shows a subtle fill colour in the background for progress to the goal. The goal is picked up from the health tracker settings. + + +![](widstep-light.png) +![](widstep-dark.png) From beb81356bc1598499fe6cc9ffc94ef321be4d9cb Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:24:32 +0100 Subject: [PATCH 262/312] Update app.js --- apps/health/app.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/apps/health/app.js b/apps/health/app.js index 64640603e..415edb7c5 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -31,6 +31,11 @@ function menuSettings() { min : 0, max : 3, format : v=>["Off","3 mins","10 mins","Always"][v], onchange : v => { s.hrm=v;setSettings(s); } + }, + "Daily Step Goal":{ + value : 0|s.stepGoal, + min : 0, max : 20000, step : 100, + onchange : v => { s.stepGoal=v;setSettings(s); } } }); } From 08045075cc7c61c04a2b799f16a4fa5e074cadd1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:25:08 +0100 Subject: [PATCH 263/312] Update metadata.json --- apps/health/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/health/metadata.json b/apps/health/metadata.json index 8bb986c57..5d096dc07 100644 --- a/apps/health/metadata.json +++ b/apps/health/metadata.json @@ -1,7 +1,7 @@ { "id": "health", "name": "Health Tracking", - "version": "0.11", + "version": "0.12", "description": "Logs health data and provides an app to view it", "icon": "app.png", "tags": "tool,system,health", From f318fb005d1af5617849a434e8a7221cd4dab9ba Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:25:35 +0100 Subject: [PATCH 264/312] Update ChangeLog --- apps/health/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/health/ChangeLog b/apps/health/ChangeLog index 1e4864af8..7dbb9c458 100644 --- a/apps/health/ChangeLog +++ b/apps/health/ChangeLog @@ -10,3 +10,4 @@ 0.09: Fix file naming so months are 1-based (not 0) (fix #1119) 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 From c74cd9bf367817905531b1a8059c6bcd7c6cfa6b Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:25:58 +0100 Subject: [PATCH 265/312] Update app.js --- apps/health/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/health/app.js b/apps/health/app.js index 415edb7c5..ae5a313f6 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -33,7 +33,7 @@ function menuSettings() { onchange : v => { s.hrm=v;setSettings(s); } }, "Daily Step Goal":{ - value : 0|s.stepGoal, + value : 10000|s.stepGoal, min : 0, max : 20000, step : 100, onchange : v => { s.stepGoal=v;setSettings(s); } } From e04f574f928569fc1bf60b6cf26bef6194aed26e Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:28:04 +0100 Subject: [PATCH 266/312] Update README.md --- apps/health/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/health/README.md b/apps/health/README.md index f44854e3e..c6b379c0a 100644 --- a/apps/health/README.md +++ b/apps/health/README.md @@ -24,6 +24,7 @@ Stores: * **Off** - Don't turn HRM on, but record heart rate if the HRM was turned on by another app/widget * **10 Min** - Turn HRM on every 10 minutes (for each heath entry) and turn it off after 2 minutes, or when a good reading is found * **Always** - Keep HRM on all the time (more accurate recording, but reduces battery life to ~36 hours) +* **Daily Step Goal** - Default 10000, daily step goal for pedometer apps to use ## Technical Info From 702cd09f793e600e62205564c085c2d20123f547 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:19:05 +0100 Subject: [PATCH 267/312] Update widstep.wid.js --- apps/widstep/widstep.wid.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 84c7bf843..0499384d7 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -1,9 +1,9 @@ -let settings; +let wsSettings; function loadSettings() { - settings = require('Storage').readJSON("health.json", 1) || {}; - if( settings.stepGoal === undefined ) { - settings.stepGoal = 10000; + wsSettings = require('Storage').readJSON("health.json", 1) || {}; + if( wsSettings.stepGoal === undefined ) { + wsSettings.stepGoal = 10000; } } @@ -20,7 +20,7 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, g.setColor(g.theme.bg); g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); g.setColor(g.theme.dark ? '#00f' : '#0ff'); - var progress = this.width * Math.min(steps/settings.stepGoal, 1); + var progress = this.width * Math.min(steps/wsSettings.stepGoal, 1); g.fillRect(this.x+1, this.y+1, this.x + progress -1, this.y + 23); g.setColor(g.theme.fg); g.setFontAlign(0, -1); From ea95dbfbf43366d83cd0336f460d896f6fad7c8d Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:20:01 +0100 Subject: [PATCH 268/312] Update widstep.wid.js --- apps/widstep/widstep.wid.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 0499384d7..79e3fe766 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -14,8 +14,8 @@ Bangle.on('lcdPower', function(on) { WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, draw:function() { if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off - //var steps = Bangle.getHealthStatus("day").steps; - var steps = 5285; + var steps = Bangle.getHealthStatus("day").steps; + //var steps = 5285; g.reset(); g.setColor(g.theme.bg); g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); From 20f9f2ad86c27a88076b3c2215353fec7e1715f1 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:26:56 +0100 Subject: [PATCH 269/312] Update README.md --- apps/widstep/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/widstep/README.md b/apps/widstep/README.md index 498f2ebd9..c41b025cd 100644 --- a/apps/widstep/README.md +++ b/apps/widstep/README.md @@ -1,6 +1,7 @@ # Step counter widget -This is my step counter widget. There are many like it, but this one is mine. -Designed to be as narrow as possible, but still easy to read, by sacrificing accuracy and only showing to the nearest 100 steps (0.1k). +This is my step counter. There are many like it, but this one is mine. + +A pedometer widget designed to be as narrow as possible, but still easy to read, by sacrificing accuracy and only showing to the nearest 100 steps (0.1k). Shows a subtle fill colour in the background for progress to the goal. The goal is picked up from the health tracker settings. From aedb3a0b2600be62a2e254cbd24dd3d3aceec43a Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:36:17 +0100 Subject: [PATCH 270/312] Update app.js --- apps/health/app.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/apps/health/app.js b/apps/health/app.js index ae5a313f6..7b52216b0 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -31,11 +31,6 @@ function menuSettings() { min : 0, max : 3, format : v=>["Off","3 mins","10 mins","Always"][v], onchange : v => { s.hrm=v;setSettings(s); } - }, - "Daily Step Goal":{ - value : 10000|s.stepGoal, - min : 0, max : 20000, step : 100, - onchange : v => { s.stepGoal=v;setSettings(s); } } }); } @@ -43,11 +38,17 @@ function menuSettings() { function menuStepCount() { swipe_enabled = false; clearButton(); + var s=getSettings(); E.showMenu({ "":{title:"Step Counting"}, "< Back":()=>menuMain(), "per hour":()=>stepsPerHour(), - "per day":()=>stepsPerDay() + "per day":()=>stepsPerDay(), + "Daily Step Goal":{ + value : 10000|s.stepGoal, + min : 0, max : 20000, step : 100, + onchange : v => { s.stepGoal=v;setSettings(s); } + } }); } From 4a960430487c1f710309b9b1b6d0fc2a2f4d4aef Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 17:04:56 +0100 Subject: [PATCH 271/312] Update app.js --- apps/health/app.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/health/app.js b/apps/health/app.js index 7b52216b0..75e46a1e8 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -2,8 +2,8 @@ function getSettings() { return require("Storage").readJSON("health.json",1)||{}; } -function setSettings(s) { - require("Storage").writeJSON("health.json",s); +function setSettings(healthSettings) { + require("Storage").writeJSON("health.json",healthSettings); } function menuMain() { @@ -22,15 +22,15 @@ function menuMain() { function menuSettings() { swipe_enabled = false; clearButton(); - var s=getSettings(); + var healthSettings=getSettings(); E.showMenu({ "":{title:"Health Tracking"}, "< Back":()=>menuMain(), "Heart Rt":{ - value : 0|s.hrm, + value : 0|healthSettings.hrm, min : 0, max : 3, format : v=>["Off","3 mins","10 mins","Always"][v], - onchange : v => { s.hrm=v;setSettings(s); } + onchange : v => { healthSettings.hrm=v;setSettings(healthSettings); } } }); } @@ -38,16 +38,16 @@ function menuSettings() { function menuStepCount() { swipe_enabled = false; clearButton(); - var s=getSettings(); + var healthSettings=getSettings(); E.showMenu({ "":{title:"Step Counting"}, "< Back":()=>menuMain(), "per hour":()=>stepsPerHour(), "per day":()=>stepsPerDay(), "Daily Step Goal":{ - value : 10000|s.stepGoal, + value : 10000|healthSettings.stepGoal, min : 0, max : 20000, step : 100, - onchange : v => { s.stepGoal=v;setSettings(s); } + onchange : v => { healthSettings.stepGoal=v;setSettings(healthSettings); } } }); } From f0ba8ac6eaf6988177d3b7d9025fb7d831712f82 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Tue, 19 Apr 2022 20:35:04 +0100 Subject: [PATCH 272/312] Update app.js --- apps/health/app.js | 34 ++++++++++++---------------------- 1 file changed, 12 insertions(+), 22 deletions(-) diff --git a/apps/health/app.js b/apps/health/app.js index 75e46a1e8..20c7f9fd7 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -2,8 +2,8 @@ function getSettings() { return require("Storage").readJSON("health.json",1)||{}; } -function setSettings(healthSettings) { - require("Storage").writeJSON("health.json",healthSettings); +function setSettings(s) { + require("Storage").writeJSON("health.json",s); } function menuMain() { @@ -15,39 +15,22 @@ function menuMain() { "Step Counting":()=>menuStepCount(), "Movement":()=>menuMovement(), "Heart Rate":()=>menuHRM(), - "Settings":()=>menuSettings() - }); -} - -function menuSettings() { - swipe_enabled = false; - clearButton(); - var healthSettings=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); } - } }); } function menuStepCount() { swipe_enabled = false; clearButton(); - var healthSettings=getSettings(); + var s=getSettings(); E.showMenu({ "":{title:"Step Counting"}, "< Back":()=>menuMain(), "per hour":()=>stepsPerHour(), "per day":()=>stepsPerDay(), "Daily Step Goal":{ - value : 10000|healthSettings.stepGoal, + value : (s.stepGoal ? s.stepGoal : 10000), min : 0, max : 20000, step : 100, - onchange : v => { healthSettings.stepGoal=v;setSettings(healthSettings); } + onchange : v => { s.stepGoal=v;setSettings(s); } } }); } @@ -66,11 +49,18 @@ function menuMovement() { function menuHRM() { swipe_enabled = false; clearButton(); + var s=getSettings(); E.showMenu({ "":{title:"Heart Rate"}, "< Back":()=>menuMain(), "per hour":()=>hrmPerHour(), "per day":()=>hrmPerDay(), + "Log interval":{ + value : 0|s.hrm, + min : 0, max : 3, + format : v=>["Off","3 mins","10 mins","Always"][v], + onchange : v => { s.hrm=v;setSettings(s); } + } }); } From 2db18d66785e9fb73408924db378636995c481c6 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:37:24 -0700 Subject: [PATCH 273/312] Update appb2.js --- apps/choozi/appb2.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/apps/choozi/appb2.js b/apps/choozi/appb2.js index d5c542be3..5f217f638 100644 --- a/apps/choozi/appb2.js +++ b/apps/choozi/appb2.js @@ -1,6 +1,3 @@ -//g.setTheme({fg : 0xFFFF, fg2 : 0xFFFF,bg2 : 0x0007,fgH : 0xFFFF,bgH : 0x02F7,dark : true}); - - /* Choozi - Choose people or things at random using Bangle.js. * Inspired by the "Chwazi" Android app * @@ -77,7 +74,7 @@ function arc(minR, maxR, minAngle, maxAngle) { inside.push(centreY+s*minR); outside.unshift(centreY+s*maxR); outside.unshift(centreX+c*maxR); - + var vertices = inside.concat(outside); g.fillPoly(vertices, true); } @@ -133,6 +130,7 @@ function animateChoice(target) { g.fillCircle(x, y, ballSize); oldx=x; oldy=y; + g.flip(); } } @@ -154,7 +152,7 @@ function choose() { // draw the current value of N in the middle of the screen, with // up/down arrows function drawN() { - g.setColor('#000000'); + g.setColor(g.theme.fg); g.setFont("Vector",fontSize); g.drawString(N,centreX-g.stringWidth(N)/2+4,centreY-fontSize/2); if (N < maxN) From fd7d0db7e98a642576a7484614a8905a4bb1f4b6 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:37:54 -0700 Subject: [PATCH 274/312] Update ChangeLog --- apps/choozi/ChangeLog | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/choozi/ChangeLog b/apps/choozi/ChangeLog index 7aabe5c89..03f7ef832 100644 --- a/apps/choozi/ChangeLog +++ b/apps/choozi/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Support Bangle.js 2 +0.03: Fix bug for Bangle.js 2 where g.flip was not being called. From beff9975fc516e3721a49282ffc9872c7e49106a Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:38:03 -0700 Subject: [PATCH 275/312] Update metadata.json --- apps/choozi/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/choozi/metadata.json b/apps/choozi/metadata.json index a10448ed5..79af76fa2 100644 --- a/apps/choozi/metadata.json +++ b/apps/choozi/metadata.json @@ -1,7 +1,7 @@ { "id": "choozi", "name": "Choozi", - "version": "0.02", + "version": "0.03", "description": "Choose people or things at random using Bangle.js.", "icon": "app.png", "tags": "tool", From 5a86b8e4d09454ac951136aad1333ad64cdb45c7 Mon Sep 17 00:00:00 2001 From: Ronin0000 <89286474+Ronin0000@users.noreply.github.com> Date: Tue, 19 Apr 2022 16:46:04 -0700 Subject: [PATCH 276/312] Update lcars.settings.js --- apps/lcars/lcars.settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 830907fc5..2656a54ab 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -27,7 +27,7 @@ var dataOptions = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"]; var speedOptions = ["kph", "mph"]; var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White']; - var bg_code = ['#0f0','#FF9900','#0094FF','#FF00DC','#f00','#00f','#ffef00','#FFFFFF']; + var bg_code = ['#00ff00','#FF9900','#0094FF','#FF00DC','#ff0000','#0000ff','#ffef00','#FFFFFF']; E.showMenu({ '': { 'title': 'LCARS Clock' }, From 28546c15d14d3e090693e3fd997486df8efd7eb3 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 20 Apr 2022 09:58:41 +0100 Subject: [PATCH 277/312] Revert "main.css: Force line break for smaller resolutions" --- css/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/main.css b/css/main.css index a986df22e..f4850babe 100644 --- a/css/main.css +++ b/css/main.css @@ -81,7 +81,7 @@ a.btn.btn-link.dropdown-toggle { min-height: 8em; } -.tile-content { position: relative; word-break: break-all; } +.tile-content { position: relative; } .link-github { position:absolute; top: 36px; From 51c285b39cf9adc6fb8010f94ee7438d816648d4 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 12:38:09 +0100 Subject: [PATCH 278/312] Update widstep.wid.js --- apps/widstep/widstep.wid.js | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 79e3fe766..39c825521 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -1,11 +1,4 @@ -let wsSettings; - -function loadSettings() { - wsSettings = require('Storage').readJSON("health.json", 1) || {}; - if( wsSettings.stepGoal === undefined ) { - wsSettings.stepGoal = 10000; - } -} +let wsSettingsGoal; Bangle.on('step', function(s) { WIDGETS["widstep"].draw(); }); Bangle.on('lcdPower', function(on) { @@ -15,12 +8,11 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, draw:function() { if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off var steps = Bangle.getHealthStatus("day").steps; - //var steps = 5285; g.reset(); g.setColor(g.theme.bg); g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); g.setColor(g.theme.dark ? '#00f' : '#0ff'); - var progress = this.width * Math.min(steps/wsSettings.stepGoal, 1); + var progress = this.width * Math.min(steps/wsSettingsGoal, 1); g.fillRect(this.x+1, this.y+1, this.x + progress -1, this.y + 23); g.setColor(g.theme.fg); g.setFontAlign(0, -1); @@ -29,7 +21,7 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, g.setFont('4x6').drawString('steps', this.x+this.width/2, this.y + 2); //g.drawRect(this.x, this.y, this.x + this.width, this.y + 23); }, reload:function() { - loadSettings(); + wsSettingsGoal = (require('Storage').readJSON("health.json", 1) || {}).stepGoal || 10000; WIDGETS["widstep"].draw(); } }; From 7621776a833a18057feb5ed53d702bc3ff9adb5a Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 12:39:41 +0100 Subject: [PATCH 279/312] Update app.js --- apps/health/app.js | 37 +++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/apps/health/app.js b/apps/health/app.js index 20c7f9fd7..efd18c4e1 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -15,23 +15,39 @@ function menuMain() { "Step Counting":()=>menuStepCount(), "Movement":()=>menuMovement(), "Heart Rate":()=>menuHRM(), + "Settings":()=>menuSettings() + }); +} + +function menuSettings() { + swipe_enabled = false; + clearButton(); + var s=getSettings(); + E.showMenu({ + "":{title:"Health Tracking"}, + "< Back":()=>menuMain(), + "Heart Rt":{ + value : 0|s.hrm, + min : 0, max : 3, + format : v=>["Off","3 mins","10 mins","Always"][v], + onchange : v => { s.hrm=v;setSettings(s); } + }, + "Daily Step Goal":{ + value : (s.stepGoal ? s.stepGoal : 10000), + min : 0, max : 20000, step : 100, + onchange : v => { s.stepGoal=v;setSettings(s); } + } }); } function menuStepCount() { swipe_enabled = false; clearButton(); - var s=getSettings(); E.showMenu({ "":{title:"Step Counting"}, "< Back":()=>menuMain(), "per hour":()=>stepsPerHour(), - "per day":()=>stepsPerDay(), - "Daily Step Goal":{ - value : (s.stepGoal ? s.stepGoal : 10000), - min : 0, max : 20000, step : 100, - onchange : v => { s.stepGoal=v;setSettings(s); } - } + "per day":()=>stepsPerDay() }); } @@ -49,18 +65,11 @@ function menuMovement() { function menuHRM() { swipe_enabled = false; clearButton(); - var s=getSettings(); E.showMenu({ "":{title:"Heart Rate"}, "< Back":()=>menuMain(), "per hour":()=>hrmPerHour(), "per day":()=>hrmPerDay(), - "Log interval":{ - value : 0|s.hrm, - min : 0, max : 3, - format : v=>["Off","3 mins","10 mins","Always"][v], - onchange : v => { s.hrm=v;setSettings(s); } - } }); } From 7bfe23d809627ca5d690419f133477977bcf4330 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 12:48:28 +0100 Subject: [PATCH 280/312] Update widstep.wid.js --- apps/widstep/widstep.wid.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 39c825521..1defcb146 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -1,4 +1,4 @@ -let wsSettingsGoal; +let wsSettingsGoal = 10000; Bangle.on('step', function(s) { WIDGETS["widstep"].draw(); }); Bangle.on('lcdPower', function(on) { @@ -25,4 +25,3 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, WIDGETS["widstep"].draw(); } }; -loadSettings(); From b0a43413c8d828acc5376d8f21795aae4db224fb Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:12:46 +0200 Subject: [PATCH 281/312] [Scheduler] Export new functions - newDefaultAlarm - newDefaultTimer - get/setSettings --- apps/sched/README.md | 25 +++++++++++++------- apps/sched/lib.js | 55 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/apps/sched/README.md b/apps/sched/README.md index ed08139eb..319778067 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -53,21 +53,27 @@ use too much RAM. It can be used as follows: ``` -// add/update an existing alarm +// Get a new alarm with default values +let alarm = require("sched").newDefaultAlarm(); + +// Get a new timer with default values +let timer = require("sched").newDefaultTimer(); + +// Add/update an existing alarm require("sched").setAlarm("mytimer", { msg : "Wake up", - timer : 10*60*1000, // 10 Minutes + timer : 10 * 60 * 1000 // 10 minutes }); // Ensure the widget and alarm timer updates to schedule the new alarm properly require("sched").reload(); // Get the time to the next alarm for us -var timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer")); -// timeToNext===undefined if no alarm or alarm disabled +let timeToNext = require("sched").getTimeToAlarm(require("sched").getAlarm("mytimer")); +// timeToNext === undefined if no alarm or alarm disabled -// delete an alarm +// Delete an alarm require("sched").setAlarm("mytimer", undefined); -// reload after deleting... +// Reload after deleting require("sched").reload(); // Or add an alarm that runs your own code - in this case @@ -76,12 +82,15 @@ require("sched").reload(); require("sched").setAlarm("customrunner", { appid : "myapp", js : "load('setting.app.js')", - timer : 1*60*1000, // 1 Minute + timer : 1 * 60 * 1000 // 1 minute }); // If you have been specifying `appid` you can also find any alarms that // your app has created with the following: -require("sched").getAlarms().filter(a=>a.appid=="myapp"); +require("sched").getAlarms().filter(a => a.appid == "myapp"); + +// Get the scheduler settings +let settings = require("sched").getSettings(); ``` If your app requires alarms, you can specify that the alarms app needs to diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 48094c86f..bfad1ac2d 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -52,3 +52,58 @@ exports.reload = function() { Bangle.drawWidgets(); } }; +// Factory that creates a new alarm with default values +exports.newDefaultAlarm = function () { + const settings = exports.getSettings(); + + let alarm = { + t: 12 * 3600000, // Default to 12:00 + on: true, + rp: false, // repeat not the default + as: settings.defaultAutoSnooze || false, + dow: 0b1111111, + last: 0, + vibrate: settings.defaultAlarmPattern, + }; + + delete settings; + + return alarm; +} +// Factory that creates a new timer with default values +exports.newDefaultTimer = function () { + const settings = exports.getSettings(); + + let timer = { + timer: 5 * 60 * 1000, // 5 minutes + on: true, + rp: false, + as: false, + dow: 0b1111111, + last: 0, + vibrate: settings.defaultTimerPattern + } + + delete settings; + + return timer; +}; +// Return the scheduler settings +exports.getSettings = function () { + return Object.assign( + { + unlockAtBuzz: false, + defaultSnoozeMillis: 600000, // 10 minutes + defaultAutoSnooze: false, + buzzCount: 10, + buzzIntervalMillis: 3000, // 3 seconds + defaultAlarmPattern: "..", + defaultTimerPattern: ".." + }, + require("Storage").readJSON("sched.settings.json", true) || {} + ); +} +// Write the updated settings back to storage +exports.setSettings = function(settings) { + require("Storage").writeJSON("sched.settings.json", settings); +}; \ No newline at end of file From a84c1d4f771a5f405b921d7783fc4b4671635922 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:13:33 +0200 Subject: [PATCH 282/312] [Scheduler] Add Settings page --- apps/sched/README.md | 11 ++++++- apps/sched/settings.js | 72 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 apps/sched/settings.js diff --git a/apps/sched/README.md b/apps/sched/README.md index 319778067..47507fc14 100644 --- a/apps/sched/README.md +++ b/apps/sched/README.md @@ -8,8 +8,17 @@ Other apps can use this to provide alarm functionality. App --- -The Alarm app allows you to add/modify any running timers. +The **Alarms & Timers** app allows you to add/modify any running alarms and timers. +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 +- `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 Internals / Library ------------------- diff --git a/apps/sched/settings.js b/apps/sched/settings.js new file mode 100644 index 000000000..642e43b43 --- /dev/null +++ b/apps/sched/settings.js @@ -0,0 +1,72 @@ +(function (back) { + let settings = require("sched").getSettings(); + + E.showMenu({ + "": { "title": /*LANG*/"Scheduler" }, + + /*LANG*/"< Back": () => back(), + + /*LANG*/"Unlock at Buzz": { + value: settings.unlockAtBuzz, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => { + settings.unlockAtBuzz = v; + require("sched").setSettings(settings); + } + }, + + /*LANG*/"Default Auto Snooze": { + value: settings.defaultAutoSnooze, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => { + settings.defaultAutoSnooze = v; + require("sched").setSettings(settings); + } + }, + + /*LANG*/"Default Snooze": { + value: settings.defaultSnoozeMillis / 60000, + min: 5, + max: 30, + step: 5, + format: v => v + /*LANG*/" min", + onchange: v => { + settings.defaultSnoozeMillis = v * 60000; + require("sched").setSettings(settings); + } + }, + + /*LANG*/"Buzz Count": { + value: settings.buzzCount, + min: 5, + max: 15, + step: 1, + onchange: v => { + settings.buzzCount = v; + require("sched").setSettings(settings); + } + }, + + /*LANG*/"Buzz Interval": { + value: settings.buzzIntervalMillis / 1000, + min: 1, + max: 5, + step: 1, + format: v => v + /*LANG*/"s", + onchange: v => { + settings.buzzIntervalMillis = v * 1000; + require("sched").setSettings(settings); + } + }, + + /*LANG*/"Default Alarm Pattern": require("buzz_menu").pattern(settings.defaultAlarmPattern, v => { + settings.defaultAlarmPattern = v; + require("sched").setSettings(settings); + }), + + /*LANG*/"Default Timer Pattern": require("buzz_menu").pattern(settings.defaultTimerPattern, v => { + settings.defaultTimerPattern = v; + require("sched").setSettings(settings); + }) + }); +}); From 9c9b48ce39df58bd7c5df43283d3233a432a956a Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:14:35 +0200 Subject: [PATCH 283/312] [Scheduler] Integrate the new settings into the code --- apps/sched/sched.js | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/apps/sched/sched.js b/apps/sched/sched.js index 9096fe4bf..83f03ac01 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -18,7 +18,9 @@ function formatTime(t) { } function showAlarm(alarm) { - var msg = ""; + const settings = require("sched").getSettings(); + + let msg = ""; msg += alarm.timer ? formatTime(alarm.timer) : formatTime(alarm.t); if (alarm.msg) { msg += "\n"+alarm.msg; @@ -28,9 +30,12 @@ function showAlarm(alarm) { else msg = atob("AC0swgF97///RcEpMlVVVVVVf9VVVVVVVVX/9VVf9VVf/1VVV///1Vf9VX///VVX///VWqqlV///1Vf//9aqqqqpf//9V///2qqqqqqn///V///6qqqqqqr///X//+qqoAAKqqv//3//6qoAAAAKqr//3//qqAAAAAAqq//3/+qoAADwAAKqv/3/+qgAADwAACqv/3/aqAAADwAAAqp/19qoAAADwAAAKqfV1qgAAADwAAACqXVWqgAAADwAAACqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVWqAAAADwAAAAqlVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAADwAAAAKpVaoAAAAOsAAAAKpVaoAAAAOsAAAAKpVaoAAAAL/AAAAKpVaoAAAAgPwAAAKpVaoAAACAD8AAAKpVWqAAAIAA/AAAqlVWqAAAgAAPwAAqlVWqAACAAADwAAqlVWqgAIAAAAAACqlVVqgAgAAAAAACqVVVqoAAAAAAAAKqVVVaqAAAAAAAAqpVVVWqgAAAAAACqlVVVWqoAAAAAAKqlVVVVqqAAAAAAqqVVVVVaqoAAAAKqpVVVVVeqqoAAKqqtVVVVV/6qqqqqqr/VVVVX/2qqqqqqn/1VVVf/VaqqqqpV/9VVVf9VVWqqlVVf9VVVf1VVVVVVVVX9VQ==")+" "+msg; } + Bangle.loadWidgets(); Bangle.drawWidgets(); - var buzzCount = 10; + + let buzzCount = settings.buzzCount; + E.showPrompt(msg,{ title:alarm.timer ? /*LANG*/"TIMER!" : /*LANG*/"ALARM!", buttons : {/*LANG*/"Snooze":true,/*LANG*/"Ok":false} // default is sleep so it'll come back in 10 mins @@ -38,7 +43,7 @@ function showAlarm(alarm) { buzzCount = 0; if (sleep) { if(alarm.ot===undefined) alarm.ot = alarm.t; - alarm.t += 10*60*1000; // 10 minutes + alarm.t += settings.defaultSnoozeMillis; } else { if (!alarm.timer) alarm.last = (new Date()).getDate(); if (alarm.ot!==undefined) { @@ -51,24 +56,35 @@ function showAlarm(alarm) { require("sched").setAlarms(alarms); load(); }); + function buzz() { - require("buzz").pattern(alarm.vibrate===undefined?"..":alarm.vibrate).then(function() { - if (buzzCount--) - setTimeout(buzz, 3000); - else if(alarm.as) { // auto-snooze - buzzCount = 10; - setTimeout(buzz, 600000); + if (settings.unlockAtBuzz) { + Bangle.setLocked(false); + } + + require("buzz").pattern(alarm.vibrate === undefined ? ".." : alarm.vibrate).then(() => { + if (buzzCount--) { + setTimeout(buzz, settings.buzzIntervalMillis); + } else if (alarm.as) { // auto-snooze + buzzCount = settings.buzzCount; + setTimeout(buzz, settings.defaultSnoozeMillis); } }); } - if ((require('Storage').readJSON('setting.json',1)||{}).quiet>1) return; + + if ((require("Storage").readJSON("setting.json", 1) || {}).quiet > 1) + return; + buzz(); } // Check for alarms -var alarms = require("sched").getAlarms(); -var active = require("sched").getActiveAlarms(alarms); -if (active.length) // if there's an alarm, show it +let alarms = require("sched").getAlarms(); +let active = require("sched").getActiveAlarms(alarms); +if (active.length) { + // if there's an alarm, show it showAlarm(active[0]); -else // otherwise just go back to default app +} else { + // otherwise just go back to default app setTimeout(load, 100); +} From cb0913468f0793d4ef62fa4596279b14545bfaf1 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:15:23 +0200 Subject: [PATCH 284/312] [Scheduler] Update metadata & changelog --- apps/sched/ChangeLog | 1 + apps/sched/metadata.json | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index a2d6c370f..0f935caf8 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -2,3 +2,4 @@ 0.02: Fix scheduling of other alarms if there is a pending alarm from the past (fix #1667) 0.03: Fix `getTimeToAlarm` for a timer already used at same day, don't set `last` for timers. 0.04: Fix `getTimeToAlarm` to check for next dow if alarm.t lower currentTime. +0.05: Export new functions (`newDefaultAlarm/Timer`), add Settings page diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index ffa346a44..3454d2397 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.04", + "version": "0.05", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", @@ -12,7 +12,8 @@ {"name":"sched.boot.js","url":"boot.js"}, {"name":"sched.js","url":"sched.js"}, {"name":"sched.img","url":"app-icon.js","evaluate":true}, - {"name":"sched","url":"lib.js"} + {"name":"sched","url":"lib.js"}, + {"name":"sched.settings.js","url":"settings.js"} ], - "data": [{"name":"sched.json"}] + "data": [{"name":"sched.json"}, {"name":"sched.settings.json"}] } From bcae05d257aaf016cc5a101dbb19d0096aa6d90e Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:18:11 +0200 Subject: [PATCH 285/312] [Alarms & Timers] Update labels and add LANG placeholders --- apps/alarm/app.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index b9404358e..ccf1d7bf0 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -39,7 +39,7 @@ function showMainMenu() { // Timer img "\0"+atob("DhKBAP////MDDAwwMGGBzgPwB4AeAPwHOBhgwMMzDez////w") // Alarm img "\0"+atob("FBSBAABgA4YcMPDGP8Zn/mx/48//PP/zD/8A//AP/wD/8A//AP/wH/+D//w//8AAAADwAAYA") const menu = { - '': { 'title': 'Alarm/Timer' }, + '': { 'title': /*LANG*/'Alarms&Timers' }, /*LANG*/'< Back' : ()=>{load();}, /*LANG*/'New Alarm': ()=>editAlarm(-1), /*LANG*/'New Timer': ()=>editTimer(-1) @@ -76,13 +76,13 @@ function showMainMenu() { function editDOW(dow, onchange) { const menu = { '': { 'title': /*LANG*/'Days of Week' }, - '< Back' : () => onchange(dow) + /*LANG*/'< Back' : () => onchange(dow) }; for (var i = 0; i < 7; i++) (i => { var dayOfWeek = require("locale").dow({ getDay: () => i }); menu[dayOfWeek] = { value: !!(dow&(1< v ? "Yes" : "No", + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", onchange: v => v ? dow |= 1< showMainMenu(), + /*LANG*/'< Back' : () => showMainMenu(), /*LANG*/'Hours': { value: t.hrs, min : 0, max : 23, wrap : true, onchange: v => t.hrs=v @@ -117,23 +117,23 @@ function editAlarm(alarmIndex, alarm) { }, /*LANG*/'Enabled': { value: a.on, - format: v=>v?"On":"Off", + format: v => v ? /*LANG*/"On" : /*LANG*/"Off", onchange: v=>a.on=v }, /*LANG*/'Repeat': { value: a.rp, - format: v=>v?"Yes":"No", - onchange: v=>a.rp=v + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => a.rp = v }, /*LANG*/'Days': { value: "SMTWTFS".split("").map((d,n)=>a.dow&(1< editDOW(a.dow, d=>{a.dow=d;editAlarm(alarmIndex,a)}) }, /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ), - /*LANG*/'Auto snooze': { + /*LANG*/'Auto Snooze': { value: a.as, - format: v=>v?"Yes":"No", - onchange: v=>a.as=v + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => a.as = v } }; menu[/*LANG*/"Save"] = function() { @@ -171,7 +171,7 @@ function editTimer(alarmIndex, alarm) { const menu = { '': { 'title': /*LANG*/'Timer' }, - '< Back' : () => showMainMenu(), + /*LANG*/'< Back' : () => showMainMenu(), /*LANG*/'Hours': { value: t.hrs, min : 0, max : 23, wrap : true, onchange: v => t.hrs=v @@ -182,8 +182,8 @@ function editTimer(alarmIndex, alarm) { }, /*LANG*/'Enabled': { value: a.on, - format: v=>v?"On":"Off", - onchange: v=>a.on=v + format: v => v ? /*LANG*/"On" : /*LANG*/"Off", + onchange: v => a.on = v }, /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ), }; From c5e28b96eca668350057bf91a737bafce8dc1542 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:23:13 +0200 Subject: [PATCH 286/312] [Alarms & Timers] Integrate with new 'sched' factories Minor code clean up (let instead of var, whitespaces between operators, etc.) --- apps/alarm/app.js | 48 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index ccf1d7bf0..1fc32ecb9 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -1,28 +1,28 @@ Bangle.loadWidgets(); Bangle.drawWidgets(); -var alarms = require("sched").getAlarms(); // An array of alarm objects (see sched/README.md) +let alarms = require("sched").getAlarms(); // time in ms -> { hrs, mins } function decodeTime(t) { - t = 0|t; // sanitise - var hrs = 0|(t/3600000); - return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) }; + t = 0 | t; // sanitise + let hrs = 0 | (t / 3600000); + return { hrs: hrs, mins: Math.round((t - hrs * 3600000) / 60000) }; } // time in { hrs, mins } -> ms function encodeTime(o) { - return o.hrs*3600000 + o.mins*60000; + return o.hrs * 3600000 + o.mins * 60000; } function formatTime(t) { - var o = decodeTime(t); - return o.hrs+":"+("0"+o.mins).substr(-2); + let o = decodeTime(t); + return o.hrs + ":" + ("0" + o.mins).substr(-2); } function getCurrentTime() { - var time = new Date(); + let time = new Date(); return ( time.getHours() * 3600000 + time.getMinutes() * 60000 + @@ -78,8 +78,8 @@ function editDOW(dow, onchange) { '': { 'title': /*LANG*/'Days of Week' }, /*LANG*/'< Back' : () => onchange(dow) }; - for (var i = 0; i < 7; i++) (i => { - var dayOfWeek = require("locale").dow({ getDay: () => i }); + for (let i = 0; i < 7; i++) (i => { + let dayOfWeek = require("locale").dow({ getDay: () => i }); menu[dayOfWeek] = { value: !!(dow&(1< v ? /*LANG*/"Yes" : /*LANG*/"No", @@ -90,19 +90,11 @@ function editDOW(dow, onchange) { } function editAlarm(alarmIndex, alarm) { - var newAlarm = alarmIndex<0; - var a = { - t : 12*3600000, // 12 o clock default - on : true, - rp : false, // repeat not the default - as : false, - dow : 0b1111111, - last : 0, - vibrate : ".." - } + let newAlarm = alarmIndex < 0; + let a = require("sched").newDefaultAlarm(); if (!newAlarm) Object.assign(a, alarms[alarmIndex]); if (alarm) Object.assign(a,alarm); - var t = decodeTime(a.t); + let t = decodeTime(a.t); const menu = { '': { 'title': /*LANG*/'Alarm' }, @@ -155,19 +147,11 @@ function editAlarm(alarmIndex, alarm) { } function editTimer(alarmIndex, alarm) { - var newAlarm = alarmIndex<0; - var a = { - timer : 5*60*1000, // 5 minutes - on : true, - rp : false, - as : false, - dow : 0b1111111, - last : 0, - vibrate : ".." - } + let newAlarm = alarmIndex < 0; + let a = require("sched").newDefaultTimer(); if (!newAlarm) Object.assign(a, alarms[alarmIndex]); if (alarm) Object.assign(a,alarm); - var t = decodeTime(a.timer); + let t = decodeTime(a.timer); const menu = { '': { 'title': /*LANG*/'Timer' }, From cfff375e566c2529c6ed48593e8ec5540a485f01 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 14:23:45 +0200 Subject: [PATCH 287/312] [Alarms & Timers] Update metadata & changelog --- apps/alarm/ChangeLog | 1 + apps/alarm/metadata.json | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index fcafc386f..3f56f4c20 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -18,3 +18,4 @@ 0.17: Moving alarm internals to 'sched' library 0.18: Cope with >1 identical alarm at once (#1667) 0.19: Ensure rescheduled alarms that already fired have 'last' reset +0.20: Use the new 'sched' factories to initialize new alarms/timers diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index 9636257ca..db36b3ca9 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -1,8 +1,8 @@ { "id": "alarm", - "name": "Alarm & Timer", + "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.19", + "version": "0.20", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From 2e5f198d666379ae7dac0efbedcba7861ee0da77 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Mon, 18 Apr 2022 22:03:37 +0200 Subject: [PATCH 288/312] [Launcher] Update labels - Shorten settings title - Change menu items to Camel Case --- apps/launch/settings.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/launch/settings.js b/apps/launch/settings.js index 60422e75c..3364864bd 100644 --- a/apps/launch/settings.js +++ b/apps/launch/settings.js @@ -8,7 +8,7 @@ require("Storage").write("launch.json",settings); } const appMenu = { - "": {"title": /*LANG*/"Launcher Settings"}, + "": { "title": /*LANG*/"Launcher" }, /*LANG*/"< Back": back, /*LANG*/"Font": { value: fonts.includes(settings.font)? fonts.indexOf(settings.font) : fonts.indexOf("12x20"), @@ -16,12 +16,12 @@ onchange: (m) => {save("font", fonts[m])}, format: v => fonts[v] }, - /*LANG*/"Vector font size": { + /*LANG*/"Vector Font Size": { value: settings.vectorsize || 10, min:10, max: 20,step:1,wrap:true, onchange: (m) => {save("vectorsize", m)} }, - /*LANG*/"Show clocks": { + /*LANG*/"Show Clocks": { value: settings.showClocks == true, format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", onchange: (m) => {save("showClocks", m)} From 7afa90710fafd9546df2d5eca4465144be25e7b7 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Mon, 18 Apr 2022 22:05:07 +0200 Subject: [PATCH 289/312] [Launcher] Add new "fullscreen" option --- apps/launch/settings.js | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/launch/settings.js b/apps/launch/settings.js index 3364864bd..5d37e1c1b 100644 --- a/apps/launch/settings.js +++ b/apps/launch/settings.js @@ -1,6 +1,9 @@ // make sure to enclose the function in parentheses (function(back) { - let settings = Object.assign({ showClocks: true }, require("Storage").readJSON("launch.json", true) || {}); + let settings = Object.assign({ + showClocks: true, + fullscreen: false + }, require("Storage").readJSON("launch.json", true) || {}); let fonts = g.getFonts(); function save(key, value) { @@ -24,7 +27,12 @@ /*LANG*/"Show Clocks": { value: settings.showClocks == true, format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", - onchange: (m) => {save("showClocks", m)} + onchange: (m) => { save("showClocks", m) } + }, + /*LANG*/"Fullscreen": { + value: settings.fullscreen == true, + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: (m) => { save("fullscreen", m) } } }; E.showMenu(appMenu); From c2a5d13bd63a741c790b51db83166db6eb0eec1d Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Mon, 18 Apr 2022 22:05:59 +0200 Subject: [PATCH 290/312] [Launcher] Load & draw widgets iff not in fullscreen mode --- apps/launch/app.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/apps/launch/app.js b/apps/launch/app.js index 4ceabe751..556e61bfd 100644 --- a/apps/launch/app.js +++ b/apps/launch/app.js @@ -2,7 +2,10 @@ var s = require("Storage"); var scaleval = 1; var vectorval = 20; var font = g.getFonts().includes("12x20") ? "12x20" : "6x8:2"; -let settings = Object.assign({ showClocks: true }, s.readJSON("launch.json", true) || {}); +let settings = Object.assign({ + showClocks: true, + fullscreen: false +}, s.readJSON("launch.json", true) || {}); if ("vectorsize" in settings) { vectorval = parseInt(settings.vectorsize); @@ -44,8 +47,11 @@ function drawApp(i, r) { } g.clear(); -Bangle.loadWidgets(); -Bangle.drawWidgets(); + +if (!settings.fullscreen) { + Bangle.loadWidgets(); + Bangle.drawWidgets(); +} E.showScroller({ h : 64*scaleval, c : apps.length, From 7c96e04d050ba1b4c31c18fe33fba9a361a68cde Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Mon, 18 Apr 2022 22:06:45 +0200 Subject: [PATCH 291/312] [Launcher] Update metadata & changelog --- apps/launch/ChangeLog | 1 + apps/launch/metadata.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/launch/ChangeLog b/apps/launch/ChangeLog index b8c198d50..7248f69c3 100644 --- a/apps/launch/ChangeLog +++ b/apps/launch/ChangeLog @@ -12,3 +12,4 @@ 0.11: Merge Bangle.js 1 and 2 launchers, again 0.12: Add an option to hide clocks from the app list (fix #1015) Add /*LANG*/ tags for internationalisation +0.13: Add fullscreen mode diff --git a/apps/launch/metadata.json b/apps/launch/metadata.json index 96bbf104b..ab218412d 100644 --- a/apps/launch/metadata.json +++ b/apps/launch/metadata.json @@ -2,7 +2,7 @@ "id": "launch", "name": "Launcher", "shortName": "Launcher", - "version": "0.12", + "version": "0.13", "description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", "icon": "app.png", "type": "launch", From c377a4f194670f65e8e1b61c1616f6fa97b51973 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 14:32:23 +0100 Subject: [PATCH 292/312] Update app.js --- apps/health/app.js | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/apps/health/app.js b/apps/health/app.js index efd18c4e1..e39590e2d 100644 --- a/apps/health/app.js +++ b/apps/health/app.js @@ -2,8 +2,8 @@ function getSettings() { return require("Storage").readJSON("health.json",1)||{}; } -function setSettings(s) { - require("Storage").writeJSON("health.json",s); +function setSettings(healthSettings) { + require("Storage").writeJSON("health.json",healthSettings); } function menuMain() { @@ -22,20 +22,21 @@ function menuMain() { function menuSettings() { swipe_enabled = false; clearButton(); - var s=getSettings(); + var healthSettings=getSettings(); + //print(healthSettings); E.showMenu({ "":{title:"Health Tracking"}, "< Back":()=>menuMain(), "Heart Rt":{ - value : 0|s.hrm, + value : 0|healthSettings.hrm, min : 0, max : 3, format : v=>["Off","3 mins","10 mins","Always"][v], - onchange : v => { s.hrm=v;setSettings(s); } + onchange : v => { healthSettings.hrm=v;setSettings(healthSettings); } }, "Daily Step Goal":{ - value : (s.stepGoal ? s.stepGoal : 10000), + value : (healthSettings.stepGoal ? healthSettings.stepGoal : 10000), min : 0, max : 20000, step : 100, - onchange : v => { s.stepGoal=v;setSettings(s); } + onchange : v => { healthSettings.stepGoal=v;setSettings(healthSettings); } } }); } @@ -204,7 +205,7 @@ function drawBarChart() { for (bar = 1; bar < 10; bar++) { if (bar == 5) { g.setFont('6x8', 2); - g.setFontAlign(0,-1) + g.setFontAlign(0,-1); g.setColor(g.theme.fg); g.drawString(chart_label + " " + (chart_index + bar -1) + " " + chart_data[chart_index + bar - 1], g.getWidth()/2, 150); g.setColor("#00f"); From a7bab80dc3108f416b9fb1bf769d844c062a1049 Mon Sep 17 00:00:00 2001 From: Eskild Hustvedt Date: Wed, 20 Apr 2022 15:39:11 +0200 Subject: [PATCH 293/312] Allow timeouts to run on the message list screen Stops the app from displaying a message that then gets removed and after that permanently "hanging" on the message screen. --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 -- apps/messages/metadata.json | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 75b171579..a96f125d3 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -45,3 +45,4 @@ 0.30: Add new Icons (Youtube, Twitch, MS TODO, Teams, Snapchat, Signal, Post & DHL, Nina, Lieferando, Kalender, Discord, Corona Warn, Bibel) 0.31: Option to disable icon flashing 0.32: Added an option to allow quiet mode to override message auto-open +0.33: Timeout from the message list screen if the message being displayed is removed and there is a timer going diff --git a/apps/messages/app.js b/apps/messages/app.js index 821813108..617801f61 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -470,8 +470,6 @@ function checkMessages(options) { // no new messages - go to clock? if (options.clockIfAllRead && newMessages.length==0) return load(); - // we don't have to time out of this screen... - cancelReloadTimeout(); active = "main"; // Otherwise show a menu E.showScroller({ diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index 7886a7b30..228e44d35 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.32", + "version": "0.33", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From 09bd9bb252ace4c8aed40993d38ba06f2dbd33c2 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 15:15:55 +0100 Subject: [PATCH 294/312] Update widstep.wid.js Looks like reload was never being called, so just read in the important setting at the top of the file. --- apps/widstep/widstep.wid.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 1defcb146..74c5a59ea 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -1,4 +1,4 @@ -let wsSettingsGoal = 10000; +let wsSettingsGoal = (require('Storage').readJSON("health.json", 1) || {}).stepGoal || 10000; Bangle.on('step', function(s) { WIDGETS["widstep"].draw(); }); Bangle.on('lcdPower', function(on) { @@ -8,6 +8,7 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, draw:function() { if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off var steps = Bangle.getHealthStatus("day").steps; + print('draw', wsSettingsGoal, steps); g.reset(); g.setColor(g.theme.bg); g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); @@ -19,9 +20,5 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, var steps_k = (steps/1000).toFixed(1) + 'k'; g.setFont('6x15').drawString(steps_k, this.x+this.width/2, this.y + 10); g.setFont('4x6').drawString('steps', this.x+this.width/2, this.y + 2); - //g.drawRect(this.x, this.y, this.x + this.width, this.y + 23); - }, reload:function() { - wsSettingsGoal = (require('Storage').readJSON("health.json", 1) || {}).stepGoal || 10000; - WIDGETS["widstep"].draw(); } }; From f59f2872e6b2d7beb85b97d7f9f74f903109e898 Mon Sep 17 00:00:00 2001 From: sir-indy <53864146+sir-indy@users.noreply.github.com> Date: Wed, 20 Apr 2022 15:16:19 +0100 Subject: [PATCH 295/312] Update widstep.wid.js Remove stray print statement! --- apps/widstep/widstep.wid.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/widstep/widstep.wid.js b/apps/widstep/widstep.wid.js index 74c5a59ea..6ad971af7 100644 --- a/apps/widstep/widstep.wid.js +++ b/apps/widstep/widstep.wid.js @@ -8,7 +8,6 @@ WIDGETS["widstep"]={area:"tl", sortorder:-1, width:28, draw:function() { if (!Bangle.isLCDOn()) return; // dont redraw if LCD is off var steps = Bangle.getHealthStatus("day").steps; - print('draw', wsSettingsGoal, steps); g.reset(); g.setColor(g.theme.bg); g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); From d8bfad06ae46a018c3a7ede4779c52e1345f7782 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:03:15 +0200 Subject: [PATCH 296/312] LCARS V0.22 - Fixed alarm and use build in steps function as fallback. --- apps/lcars/ChangeLog | 1 + apps/lcars/README.md | 3 +-- apps/lcars/lcars.app.js | 22 +++++++++++++--------- apps/lcars/metadata.json | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 9c17376bb..e622feb1f 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -19,3 +19,4 @@ 0.19: Alarms can not go bigger than 100. 0.20: Use alarm for alarm functionality instead of own implementation. 0.21: Add custom theming. +0.22: Fix alarm and add build in function for step counting. \ No newline at end of file diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 65e31b3cc..6d4b18b9a 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -1,8 +1,7 @@ # LCARS clock A simple LCARS inspired clock. -Note: To display the steps, the wpedom app is required. To show weather data -such as temperature, humidity or window you BangleJS must be connected +To show weather data such as temperature, humidity or window you BangleJS must be connected with Gadgetbride and the weather app must be installed. To use the timer the "sched" app must be installed on your device. diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 3210d6832..aa50fb348 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,3 +1,4 @@ +const TIMER_IDX = "lcars"; const SETTINGS_FILE = "lcars.setting.json"; const locale = require('locale'); const storage = require('Storage') @@ -35,7 +36,7 @@ let lcarsViewPos = 0; var plotMonth = false; -function convert24to16(input) +function convert24to16(input) { let RGB888 = parseInt(input.replace(/^#/, ''), 16); let r = (RGB888 & 0xFF0000) >> 16; @@ -171,7 +172,7 @@ Graphics.prototype.setFontAntonioLarge = function(scale) { */ var drawTimeout; function queueDraw() { - + // Faster updates during alarm to ensure that it is // shown correctly... var timeout = isAlarmEnabled() ? 10000 : 60000; @@ -556,17 +557,20 @@ function draw(){ * Step counter via widget */ function getSteps() { + var steps = 0; try{ if (WIDGETS.wpedom !== undefined) { - return WIDGETS.wpedom.getSteps(); + steps = WIDGETS.wpedom.getSteps(); } else if (WIDGETS.activepedom !== undefined) { - return WIDGETS.activepedom.getSteps(); + steps = WIDGETS.activepedom.getSteps(); + } else { + steps = Bangle.getHealthStatus("day").steps; } } catch(ex) { // In case we failed, we can only show 0 steps. } - return 0; + return steps; } @@ -639,7 +643,7 @@ function increaseAlarm(){ var minutes = isAlarmEnabled() ? getAlarmMinutes() : 0; var alarm = require('sched') alarm.setAlarm(TIMER_IDX, { - timer : (minutes+5)*60*1000, + timer : (minutes+5)*60*1000, }); alarm.reload(); } catch(ex){ } @@ -654,9 +658,9 @@ function decreaseAlarm(){ alarm.setAlarm(TIMER_IDX, undefined); if(minutes > 0){ - alarm.setAlarm(TIMER_IDX, { - timer : minutes*60*1000, - }); + alarm.setAlarm(TIMER_IDX, { + timer : minutes*60*1000, + }); } alarm.reload(); diff --git a/apps/lcars/metadata.json b/apps/lcars/metadata.json index 5f3eaa971..40da1b37f 100644 --- a/apps/lcars/metadata.json +++ b/apps/lcars/metadata.json @@ -3,7 +3,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.21", + "version":"0.22", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", From a02e6d79c4af51639f255d1b5ea79b8de148145e Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:05:05 +0200 Subject: [PATCH 297/312] Use same data for settings otherwise settings change after first save. --- apps/lcars/lcars.settings.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 2656a54ab..c948c7763 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -5,9 +5,9 @@ const storage = require('Storage') let settings = { alarm: -1, - dataRow1: "Battery", - dataRow2: "Steps", - dataRow3: "Temp", + dataRow1: "Steps", + dataRow2: "Temp", + dataRow3: "Battery", speed: "kph", fullscreen: false, themeColor1BG: "#FF9900", @@ -23,7 +23,7 @@ storage.write(SETTINGS_FILE, settings) } - + var dataOptions = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "Wind", "Altitude", "CoreT"]; var speedOptions = ["kph", "mph"]; var color_options = ['Green','Orange','Cyan','Purple','Red','Blue','Yellow','White']; From 058beeae94fb397e7bfecdc11a5a4d29351b9082 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:09:33 +0200 Subject: [PATCH 298/312] Better stability for weather --- apps/lcars/lcars.app.js | 49 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 26 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index aa50fb348..590ae56bb 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -579,38 +579,35 @@ function getWeather(){ try { weatherJson = storage.readJSON('weather.json'); + var weather = weatherJson.weather; + + // Temperature + weather.temp = locale.temp(weather.temp-273.15); + + // Humidity + weather.hum = weather.hum + "%"; + + // Wind + const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); + var speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934; + weather.wind = Math.round(wind[1] * speedFactor); + + return weather + } catch(ex) { // Return default } - if(weatherJson === undefined){ - return { - temp: "-", - hum: "-", - txt: "-", - wind: "-", - wdir: "-", - wrose: "-" - }; - } - - var weather = weatherJson.weather; - - // Temperature - weather.temp = locale.temp(weather.temp-273.15); - - // Humidity - weather.hum = weather.hum + "%"; - - // Wind - const wind = locale.speed(weather.wind).match(/^(\D*\d*)(.*)$/); - var speedFactor = settings.speed == "kph" ? 1.0 : 1.0 / 1.60934; - weather.wind = Math.round(wind[1] * speedFactor); - - return weather + return { + temp: " ? ", + hum: " ? ", + txt: " ? ", + wind: " ? ", + wdir: " ? ", + wrose: " ? " + }; } - /* * Handle alarm */ From 945bc31b366b4693c1c1e07cd2e5aafb412c0637 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:15:10 +0200 Subject: [PATCH 299/312] Fix info alignment --- apps/lcars/lcars.app.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 590ae56bb..072eead54 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -291,6 +291,9 @@ function drawInfo(){ return; } + // Draw Infor is called from different sources so + // we have to ensure that the alignment is always the same. + g.setFontAlign(-1, -1, 0); g.setFontAntonioMedium(); g.setColor(color2); g.clearRect(120, 10, g.getWidth(), 75); From f8a2c280fe6c1f8bb42bf4151423ce09606fc1e9 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:24:11 +0200 Subject: [PATCH 300/312] Show last healt status for HRM --- apps/lcars/lcars.app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 072eead54..92c4e8e7c 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -238,7 +238,7 @@ function _drawData(key, y, c){ value = E.getAnalogVRef().toFixed(2) + "V"; } else if(key == "HRM"){ - value = Math.round(Bangle.getHealthStatus("day").bpm); + value = Math.round(Bangle.getHealthStatus("last").bpm); } else if (key == "TEMP"){ var weather = getWeather(); From 088453d8ce5ffbd0ae8f30d0f3af76ca691d2bf4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 20 Apr 2022 17:24:50 +0200 Subject: [PATCH 301/312] HRM as default --- apps/lcars/lcars.app.js | 2 +- apps/lcars/lcars.settings.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 92c4e8e7c..07ca51fd9 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -5,7 +5,7 @@ const storage = require('Storage') let settings = { alarm: -1, dataRow1: "Steps", - dataRow2: "Temp", + dataRow2: "HRM", dataRow3: "Battery", speed: "kph", fullscreen: false, diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index c948c7763..b64feb30e 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -6,7 +6,7 @@ let settings = { alarm: -1, dataRow1: "Steps", - dataRow2: "Temp", + dataRow2: "HRM", dataRow3: "Battery", speed: "kph", fullscreen: false, From 8c048f321c5cbf441620b3c6f276db55209cbd3a Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Wed, 20 Apr 2022 19:32:23 +0200 Subject: [PATCH 302/312] Refactor some methods to scheduling library --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 29 ++++++----------------------- apps/alarm/metadata.json | 2 +- apps/sched/ChangeLog | 1 + apps/sched/lib.js | 19 ++++++++++++++++++- apps/sched/metadata.json | 2 +- apps/sched/sched.js | 14 +------------- apps/sleepphasealarm/ChangeLog | 1 + apps/sleepphasealarm/app.js | 10 +--------- apps/sleepphasealarm/metadata.json | 3 ++- css/main.css | 2 +- 11 files changed, 34 insertions(+), 50 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 3f56f4c20..876459e82 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -19,3 +19,4 @@ 0.18: Cope with >1 identical alarm at once (#1667) 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: Refactor some methods to scheduling library diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 1fc32ecb9..0caada4df 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -4,23 +4,6 @@ Bangle.drawWidgets(); // An array of alarm objects (see sched/README.md) let alarms = require("sched").getAlarms(); -// time in ms -> { hrs, mins } -function decodeTime(t) { - t = 0 | t; // sanitise - let hrs = 0 | (t / 3600000); - return { hrs: hrs, mins: Math.round((t - hrs * 3600000) / 60000) }; -} - -// time in { hrs, mins } -> ms -function encodeTime(o) { - return o.hrs * 3600000 + o.mins * 60000; -} - -function formatTime(t) { - let o = decodeTime(t); - return o.hrs + ":" + ("0" + o.mins).substr(-2); -} - function getCurrentTime() { let time = new Date(); return ( @@ -48,10 +31,10 @@ function showMainMenu() { var type,txt; // a leading space is currently required (JS error in Espruino 2v12) if (alarm.timer) { type = /*LANG*/"Timer"; - txt = " "+formatTime(alarm.timer); + txt = " "+require("sched").formatTime(alarm.timer); } else { type = /*LANG*/"Alarm"; - txt = " "+formatTime(alarm.t); + txt = " "+require("sched").formatTime(alarm.t); } if (alarm.rp) txt += "\0"+atob("FBaBAAABgAAcAAHn//////wAHsABzAAYwAAMAADAAAAAAwAAMAADGAAzgAN4AD//////54AAOAABgAA="); // rename duplicate alarms @@ -94,7 +77,7 @@ function editAlarm(alarmIndex, alarm) { let a = require("sched").newDefaultAlarm(); if (!newAlarm) Object.assign(a, alarms[alarmIndex]); if (alarm) Object.assign(a,alarm); - let t = decodeTime(a.t); + let t = require("sched").decodeTime(a.t); const menu = { '': { 'title': /*LANG*/'Alarm' }, @@ -129,7 +112,7 @@ function editAlarm(alarmIndex, alarm) { } }; menu[/*LANG*/"Save"] = function() { - a.t = encodeTime(t); + a.t = require("sched").encodeTime(t); a.last = (a.t < getCurrentTime()) ? (new Date()).getDate() : 0; if (newAlarm) alarms.push(a); else alarms[alarmIndex] = a; @@ -151,7 +134,7 @@ function editTimer(alarmIndex, alarm) { let a = require("sched").newDefaultTimer(); if (!newAlarm) Object.assign(a, alarms[alarmIndex]); if (alarm) Object.assign(a,alarm); - let t = decodeTime(a.timer); + let t = require("sched").decodeTime(a.timer); const menu = { '': { 'title': /*LANG*/'Timer' }, @@ -172,7 +155,7 @@ function editTimer(alarmIndex, alarm) { /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ), }; menu[/*LANG*/"Save"] = function() { - a.timer = encodeTime(t); + a.timer = require("sched").encodeTime(t); a.t = getCurrentTime() + a.timer; a.last = 0; if (newAlarm) alarms.push(a); diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index db36b3ca9..5c443dcec 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.20", + "version": "0.21", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", diff --git a/apps/sched/ChangeLog b/apps/sched/ChangeLog index 0f935caf8..7372f9c4a 100644 --- a/apps/sched/ChangeLog +++ b/apps/sched/ChangeLog @@ -3,3 +3,4 @@ 0.03: Fix `getTimeToAlarm` for a timer already used at same day, don't set `last` for timers. 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 diff --git a/apps/sched/lib.js b/apps/sched/lib.js index bfad1ac2d..8f3f9c88a 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -106,4 +106,21 @@ exports.getSettings = function () { // Write the updated settings back to storage exports.setSettings = function(settings) { require("Storage").writeJSON("sched.settings.json", settings); -}; \ No newline at end of file +}; + +// 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) }; +} + +// time in { hrs, mins } -> ms +exports.encodeTime = function(o) { + return o.hrs * 3600000 + o.mins * 60000; +} + +exports.formatTime = function(t) { + let o = decodeTime(t); + return o.hrs + ":" + ("0" + o.mins).substr(-2); +} diff --git a/apps/sched/metadata.json b/apps/sched/metadata.json index 3454d2397..5f61d7d04 100644 --- a/apps/sched/metadata.json +++ b/apps/sched/metadata.json @@ -1,7 +1,7 @@ { "id": "sched", "name": "Scheduler", - "version": "0.05", + "version": "0.06", "description": "Scheduling library for alarms and timers", "icon": "app.png", "type": "scheduler", diff --git a/apps/sched/sched.js b/apps/sched/sched.js index 83f03ac01..7c97600d9 100644 --- a/apps/sched/sched.js +++ b/apps/sched/sched.js @@ -5,23 +5,11 @@ if (Bangle.SCHED) { delete Bangle.SCHED; } -// time in ms -> { hrs, mins } -function decodeTime(t) { - t = 0|t; // sanitise - var hrs = 0|(t/3600000); - return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) }; -} - -function formatTime(t) { - var o = decodeTime(t); - return o.hrs+":"+("0"+o.mins).substr(-2); -} - function showAlarm(alarm) { const settings = require("sched").getSettings(); let msg = ""; - msg += alarm.timer ? formatTime(alarm.timer) : formatTime(alarm.t); + msg += alarm.timer ? require("sched").formatTime(alarm.timer) : require("sched").formatTime(alarm.t); if (alarm.msg) { msg += "\n"+alarm.msg; } else { diff --git a/apps/sleepphasealarm/ChangeLog b/apps/sleepphasealarm/ChangeLog index b07c5b9f7..875b3c1da 100644 --- a/apps/sleepphasealarm/ChangeLog +++ b/apps/sleepphasealarm/ChangeLog @@ -2,3 +2,4 @@ 0.02: Respect Quiet Mode 0.03: Add compatibility for Bangle.js 2 and new firmware, added "Alarm at " for the alarm time 0.04: Read alarms from new scheduling library, account for higher acceleration sensor noise on Bangle.js 2 +0.05: Refactor decodeTime() to scheduling library diff --git a/apps/sleepphasealarm/app.js b/apps/sleepphasealarm/app.js index dcd176617..236b71c0b 100644 --- a/apps/sleepphasealarm/app.js +++ b/apps/sleepphasealarm/app.js @@ -38,19 +38,11 @@ function calc_ess(acc_magn) { } } -// copied from alarm app -// time in ms -> { hrs, mins } -function decodeTime(t) { - t = 0|t; // sanitise - var hrs = 0|(t/3600000); - return { hrs : hrs, mins : Math.round((t-hrs*3600000)/60000) }; -} - // locate next alarm var nextAlarm; active.forEach(alarm => { const now = new Date(); - const t = decodeTime(alarm.t); + const t = require("sched").decodeTime(alarm.t); var dateAlarm = new Date(now.getFullYear(), now.getMonth(), now.getDate(), t.hrs, t.mins); if (dateAlarm < now) { // dateAlarm in the past, add 24h dateAlarm.setTime(dateAlarm.getTime() + (24*60*60*1000)); diff --git a/apps/sleepphasealarm/metadata.json b/apps/sleepphasealarm/metadata.json index bc75027c2..aecfa36e4 100644 --- a/apps/sleepphasealarm/metadata.json +++ b/apps/sleepphasealarm/metadata.json @@ -2,11 +2,12 @@ "id": "sleepphasealarm", "name": "SleepPhaseAlarm", "shortName": "SleepPhaseAlarm", - "version": "0.04", + "version": "0.05", "description": "Uses the accelerometer to estimate sleep and wake states with the principle of Estimation of Stationary Sleep-segments (ESS, see https://ubicomp.eti.uni-siegen.de/home/datasets/ichi14/index.html.en). This app will read the next alarm from the alarm application and will wake you up to 30 minutes early at the best guessed time when you are almost already awake.", "icon": "app.png", "tags": "alarm", "supports": ["BANGLEJS","BANGLEJS2"], + "dependencies": {"scheduler":"type"}, "storage": [ {"name":"sleepphasealarm.app.js","url":"app.js"}, {"name":"sleepphasealarm.img","url":"app-icon.js","evaluate":true} diff --git a/css/main.css b/css/main.css index f4850babe..c4e5286cc 100644 --- a/css/main.css +++ b/css/main.css @@ -81,7 +81,7 @@ a.btn.btn-link.dropdown-toggle { min-height: 8em; } -.tile-content { position: relative; } +.tile-content { position: relative; word-break: break-word; } .link-github { position:absolute; top: 36px; From 5e847a56fd00ad978650be434b52907c3bfeed2a Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Wed, 20 Apr 2022 20:26:06 +0200 Subject: [PATCH 303/312] sched: fix formatTime reference --- apps/sched/lib.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/sched/lib.js b/apps/sched/lib.js index 8f3f9c88a..58ba5daf0 100644 --- a/apps/sched/lib.js +++ b/apps/sched/lib.js @@ -121,6 +121,6 @@ exports.encodeTime = function(o) { } exports.formatTime = function(t) { - let o = decodeTime(t); + let o = exports.decodeTime(t); return o.hrs + ":" + ("0" + o.mins).substr(-2); } From d832610a55e5b285bf49ba8cff6e68c647f22d52 Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Wed, 20 Apr 2022 20:50:48 +0200 Subject: [PATCH 304/312] Ignore Jekyll local output folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 523dc5f20..fce2efb1a 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ appdates.csv _config.yml tests/Layout/bin/tmp.* tests/Layout/testresult.bmp -apps.local.json \ No newline at end of file +apps.local.json +_site From 109ef4f417748252b0220d06fc38bcb0aa150faa Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Thu, 21 Apr 2022 09:56:52 +0200 Subject: [PATCH 305/312] [Launcher] Add README --- apps/launch/README.md | 14 ++++++++++++++ apps/launch/metadata.json | 1 + 2 files changed, 15 insertions(+) create mode 100644 apps/launch/README.md diff --git a/apps/launch/README.md b/apps/launch/README.md new file mode 100644 index 000000000..4e6185dea --- /dev/null +++ b/apps/launch/README.md @@ -0,0 +1,14 @@ +Launcher +======== + +This is the default launcher but you can replace it with a customised launcher. + +The app is needed to display a menu with all the apps installed on your Bangle. You can launch an app by touching its name/icon. + +Settings +-------- + +- `Font` - The font used (`4x6`, `6x8`, `12x20`, `6x15` or `Vector`). Default `12x20`. +- `Vector Font Size` - The size of the font if `Font` is set to `Vector`. Default `10`. +- `Show Clocks` - If set to `No` then clocks won't appear in the app list. Default `Yes`. +- `Fullscreen` - If set to `Yes` then widgets won't be loaded. Default `No`. diff --git a/apps/launch/metadata.json b/apps/launch/metadata.json index ab218412d..da76fc4bb 100644 --- a/apps/launch/metadata.json +++ b/apps/launch/metadata.json @@ -4,6 +4,7 @@ "shortName": "Launcher", "version": "0.13", "description": "This is needed to display a menu allowing you to choose your own applications. You can replace this with a customised launcher.", + "readme": "README.md", "icon": "app.png", "type": "launch", "tags": "tool,system,launcher", From 3ab7add1ef3328f93c2cb28e0aca2af1ecc21c4e Mon Sep 17 00:00:00 2001 From: Marco H Date: Thu, 21 Apr 2022 10:45:04 +0200 Subject: [PATCH 306/312] Fix typo --- apps/activityreminder/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/activityreminder/app.js b/apps/activityreminder/app.js index 39c5bc71f..9fb52e9ac 100644 --- a/apps/activityreminder/app.js +++ b/apps/activityreminder/app.js @@ -1,5 +1,5 @@ function drawAlert(){ - E.showPrompt("Innactivity detected",{ + E.showPrompt("Inactivity detected",{ title:"Activity reminder", buttons : {"Ok": true,"Dismiss": false} }).then(function(v) { From 85268b8f826e1920bc843b9ff3b99c806aeecd3e Mon Sep 17 00:00:00 2001 From: Alessandro Cocco Date: Thu, 21 Apr 2022 11:15:49 +0200 Subject: [PATCH 307/312] [Alarms & Timers] Avoid time reset after a dow change --- apps/alarm/ChangeLog | 1 + apps/alarm/app.js | 6 +++++- apps/alarm/metadata.json | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/apps/alarm/ChangeLog b/apps/alarm/ChangeLog index 3f56f4c20..906169a04 100644 --- a/apps/alarm/ChangeLog +++ b/apps/alarm/ChangeLog @@ -19,3 +19,4 @@ 0.18: Cope with >1 identical alarm at once (#1667) 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) diff --git a/apps/alarm/app.js b/apps/alarm/app.js index 1fc32ecb9..e895f9041 100644 --- a/apps/alarm/app.js +++ b/apps/alarm/app.js @@ -119,7 +119,11 @@ function editAlarm(alarmIndex, alarm) { }, /*LANG*/'Days': { value: "SMTWTFS".split("").map((d,n)=>a.dow&(1< editDOW(a.dow, d=>{a.dow=d;editAlarm(alarmIndex,a)}) + onchange: () => editDOW(a.dow, d => { + a.dow = d; + a.t = encodeTime(t); + editAlarm(alarmIndex, a); + }) }, /*LANG*/'Vibrate': require("buzz_menu").pattern(a.vibrate, v => a.vibrate=v ), /*LANG*/'Auto Snooze': { diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index db36b3ca9..5c443dcec 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.20", + "version": "0.21", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From d6f6fea82b8723d8a26f250c17c2715e10893a33 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 21 Apr 2022 10:26:20 +0100 Subject: [PATCH 308/312] Lower chunk size - makes uploads a bit slower but should help with reliability for some folks - https://github.com/espruino/BangleApps/issues/1069 --- core | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core b/core index b04f32553..89049a5c7 160000 --- a/core +++ b/core @@ -1 +1 @@ -Subproject commit b04f32553935f1479ad226ce1b2cff4f4b2e1a6f +Subproject commit 89049a5c7c80d2b56dc235d135fc63b80789db96 From b9e76dd2931bed7654d14cf9a03b65252802a8dd Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Thu, 21 Apr 2022 10:29:10 +0100 Subject: [PATCH 309/312] messages 0.34: Don't buzz for 'map' update messages --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 3 ++- apps/messages/metadata.json | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index a96f125d3..a3ee37326 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -46,3 +46,4 @@ 0.31: Option to disable icon flashing 0.32: Added an option to allow quiet mode to override message auto-open 0.33: Timeout from the message list screen if the message being displayed is removed and there is a timer going +0.34: Don't buzz for 'map' update messages diff --git a/apps/messages/app.js b/apps/messages/app.js index 617801f61..85d818bd5 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -52,7 +52,8 @@ var MESSAGES = require("Storage").readJSON("messages.json",1)||[]; if (!Array.isArray(MESSAGES)) MESSAGES=[]; var onMessagesModified = function(msg) { // TODO: if new, show this new one - if (msg && msg.id!=="music" && msg.new && !((require('Storage').readJSON('setting.json', 1) || {}).quiet)) { + if (msg && msg.id!=="music" && msg.new && active!="map" && + !((require('Storage').readJSON('setting.json', 1) || {}).quiet)) { if (WIDGETS["messages"]) WIDGETS["messages"].buzz(); else Bangle.buzz(); } diff --git a/apps/messages/metadata.json b/apps/messages/metadata.json index 228e44d35..ffb4f8b8a 100644 --- a/apps/messages/metadata.json +++ b/apps/messages/metadata.json @@ -1,7 +1,7 @@ { "id": "messages", "name": "Messages", - "version": "0.33", + "version": "0.34", "description": "App to display notifications from iOS and Gadgetbridge/Android", "icon": "app.png", "type": "app", From 03c1f330adc22dbdf295e13e4e22840c53442162 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Thu, 21 Apr 2022 11:50:23 +0200 Subject: [PATCH 310/312] revert main.css --- css/main.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/css/main.css b/css/main.css index c4e5286cc..f4850babe 100644 --- a/css/main.css +++ b/css/main.css @@ -81,7 +81,7 @@ a.btn.btn-link.dropdown-toggle { min-height: 8em; } -.tile-content { position: relative; word-break: break-word; } +.tile-content { position: relative; } .link-github { position:absolute; top: 36px; From 856164a58e21300ef137751d787a568c1e3e9408 Mon Sep 17 00:00:00 2001 From: Erik Andresen Date: Thu, 21 Apr 2022 11:56:39 +0200 Subject: [PATCH 311/312] alarm update version to 0.22 --- apps/alarm/metadata.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/alarm/metadata.json b/apps/alarm/metadata.json index 5c443dcec..906df810f 100644 --- a/apps/alarm/metadata.json +++ b/apps/alarm/metadata.json @@ -2,7 +2,7 @@ "id": "alarm", "name": "Alarms & Timers", "shortName": "Alarms", - "version": "0.21", + "version": "0.22", "description": "Set alarms and timers on your Bangle", "icon": "app.png", "tags": "tool,alarm,widget", From 7e7ccc3085e314630b5caac3c879ba27d4f09177 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Fri, 22 Apr 2022 09:34:23 +0100 Subject: [PATCH 312/312] 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

    -
  • See official mapping guidelines here.
  • -
  • All holes and features must be within the target course's area.
  • -
  • Supported features are greens, fairways, tees, bunkers, water hazards and holes.
  • -
  • All features for a given hole should have the "ref" tag with the hole number as value. Shared features should - list ref values separated by ';'. example.
  • -
  • There must be 18 holes and they must have the following tags: handicap, par, ref, dist
  • -
  • For any mapping assistance or issues, please file in the official - repo
  • -