From fcf8a0b1f097466f8e6688e645b1977f2ef8cee7 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sat, 25 Dec 2021 23:58:46 +0100 Subject: [PATCH 001/169] added ISO weeknumber * update changelog, screenshots and readme * created a settings dialog --- 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 6 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 apps/ffcniftya/ffcniftya.settings.js create mode 100644 apps/ffcniftya/screenshot_settings_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..5ec8ab681 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) +## 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..33722b3a3 100644 --- a/apps/ffcniftya/app.js +++ b/apps/ffcniftya/app.js @@ -1,5 +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}; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -16,6 +17,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 +42,25 @@ 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 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); + if (CFG.showWeek) g.drawString(d02(ISO8601_week_no(now)), 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 5ad730fb87a50a975a72be55acf766e06e915d45 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 002/169] fix settings + added screenshots and changed README --- apps/ffcniftya/README.md | 16 ++++++++++++++-- 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 6 files changed, 15 insertions(+), 3 deletions(-) create mode 100644 apps/ffcniftya/photo_nifty.png create mode 100644 apps/ffcniftya/photo_settings_nifty.png diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 5ec8ab681..122483243 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -1,9 +1,21 @@ # Nifty-A Clock +Colors are black/white - photos have non correct camera color "blue" + ## This is the clock ![](screenshot_nifty.png) +[i]emulated[/i] + +![](phptp_nifty.png) +[i]photo[/i] + +## The week number can be turned of in settings +(default is [b]"On"[/b]) -## The week number can be turned On/Off via settings ![](screenshot_settings_nifty.png) -default is "On" +[i]emulated[/i] + +![](photo_settings_nifty.png) +[i]photo[/i] + 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 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 Pg(-ultDnm{r-UW|MyW+1 literal 46504 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 From ece0c1c1de6403821fefd5ef94f149327f5cafc1 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 003/169] 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 e5e9f8f02..f2c5bbce0 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 026a55f4fe96264953744e04bd2a4f740f5fe5c1 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 004/169] 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 f2c5bbce0..6c516bae5 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 1fb1489577a09e24a6f9b23ee734f795e4475d00 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 005/169] 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 aadc5eb65dde7a4f6f3b0ab3aff8975ca180f7a4 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 01:30:48 +0100 Subject: [PATCH 006/169] Update README.md --- apps/ffcniftya/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 122483243..0c5e88b3d 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -4,18 +4,18 @@ Colors are black/white - photos have non correct camera color "blue" ## This is the clock ![](screenshot_nifty.png) -[i]emulated[/i] +*emulated* -![](phptp_nifty.png) -[i]photo[/i] +![](photo_nifty.png) +*photo* ## The week number can be turned of in settings (default is [b]"On"[/b]) ![](screenshot_settings_nifty.png) -[i]emulated[/i] +*emulated* ![](photo_settings_nifty.png) -[i]photo[/i] +*photo* From 85b4468e818620e2bd0d13aacf1d7f5c455e4b66 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 02:40:32 +0100 Subject: [PATCH 007/169] Update README.md --- apps/ffcniftya/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 0c5e88b3d..a4ef073dd 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -10,7 +10,7 @@ Colors are black/white - photos have non correct camera color "blue" *photo* ## The week number can be turned of in settings -(default is [b]"On"[/b]) +(default is **"On"**) ![](screenshot_settings_nifty.png) *emulated* From 12d5fb28ef2ced37f854eb4a632cf3d453bff6f9 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 008/169] 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 02:56:59 +0100 Subject: [PATCH 009/169] Update README.md --- apps/ffcniftya/README.md | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index a4ef073dd..769cbcb74 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -3,19 +3,16 @@ Colors are black/white - photos have non correct camera color "blue" ## This is the clock -![](screenshot_nifty.png) -*emulated* +![](screenshot_nifty.png) (*emulated*) -![](photo_nifty.png) -*photo* + +![](photo_nifty.png) (*photo*) ## The week number can be turned of in settings (default is **"On"**) -![](screenshot_settings_nifty.png) -*emulated* +![](screenshot_settings_nifty.png) (*emulated*) -![](photo_settings_nifty.png) -*photo* +![](photo_settings_nifty.png) (*photo*) From f9c3827596c8b9a2e380009990a9a8dd8b71777e Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:17:48 +0100 Subject: [PATCH 010/169] Update app.js --- apps/ffcniftya/app.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 33722b3a3..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; @@ -43,6 +43,7 @@ function draw() { const day = d02(now.getDate()); const month = d02(now.getMonth() + 1); const year = now.getFullYear(now); + const weekNum = d02(ISO8601_week_no(now)); const monthName = locale.month(now, 3); const dayName = locale.dow(now, 3); From 8d6a16dc7446671b5ca201234eaf2f23b544253c Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:30:19 +0100 Subject: [PATCH 011/169] settings showWeekNum --- apps/ffcniftya/app.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/app.js b/apps/ffcniftya/app.js index 5f23599a0..5da1ec48e 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", 1) || {showWeek: true}; +const CFG = require('Storage').readJSON("ffcniftya.json", 1) || {showWeekNum: true}; /* Clock *********************************************/ const scale = g.getWidth() / 176; @@ -59,7 +59,7 @@ function draw() { g.drawString(year, centerDatesScaleX, center.y - 62 * scale); g.drawString(month, centerDatesScaleX, center.y - 44 * scale); g.drawString(day, centerDatesScaleX, center.y - 26 * scale); - if (CFG.showWeek) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); + if (CFG.showWeekNum) g.drawString(d02(ISO8601_week_no(now)), centerDatesScaleX, center.y + 15 * scale); g.drawString(monthName, centerDatesScaleX, center.y + 48 * scale); g.drawString(dayName, centerDatesScaleX, center.y + 66 * scale); } From 13483ee80cc5d6a09dd89f9f5373d8b59df289c4 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Sun, 26 Dec 2021 03:38:26 +0100 Subject: [PATCH 012/169] 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 69276a06babd56e57cd82454ad652f9c4ba9a07e 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 013/169] 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 9d30fe8139aff7613ffcfad17b75f1ef2a52cf5d 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 014/169] 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 604f6f6c476c3bf2cc963a75bfdff1bf9c2b1cb1 Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:33:53 -0500 Subject: [PATCH 015/169] Add time and life app --- apps.json | 17 +++ apps/timeandlife/ChangeLog | 1 + apps/timeandlife/README.md | 7 + apps/timeandlife/app-icon.js | 1 + apps/timeandlife/app.js | 278 +++++++++++++++++++++++++++++++++++ apps/timeandlife/app.png | Bin 0 -> 605 bytes 6 files changed, 304 insertions(+) create mode 100644 apps/timeandlife/ChangeLog create mode 100644 apps/timeandlife/README.md create mode 100644 apps/timeandlife/app-icon.js create mode 100644 apps/timeandlife/app.js create mode 100644 apps/timeandlife/app.png diff --git a/apps.json b/apps.json index e5e9f8f02..02ee3d469 100644 --- a/apps.json +++ b/apps.json @@ -5062,5 +5062,22 @@ {"name":"ltherm.app.js","url":"app.js"}, {"name":"ltherm.img","url":"icon.js","evaluate":true} ] + }, + { + "id": "timeandlife", + "name": "Time and Life", + "shortName":"Time and Lfie", + "icon": "app.png", + "version":"0.0.1", + "description": "A simple watchface which displays the time when the screen is tapped and decay according to the rules of Conway's game of life.", + "type": "clock", + "tags": "clock", + "supports": ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"timeandlife.app.js","url":"app.js"}, + {"name":"timeandlife.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/timeandlife/ChangeLog b/apps/timeandlife/ChangeLog new file mode 100644 index 000000000..115067b80 --- /dev/null +++ b/apps/timeandlife/ChangeLog @@ -0,0 +1 @@ +0.01: New app diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md new file mode 100644 index 000000000..af92d8cb8 --- /dev/null +++ b/apps/timeandlife/README.md @@ -0,0 +1,7 @@ +# Time and Life + +A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). + +![](screenshot1.png) +![](screenshot2.png) +![](screenshot3.png) diff --git a/apps/timeandlife/app-icon.js b/apps/timeandlife/app-icon.js new file mode 100644 index 000000000..d7608fca4 --- /dev/null +++ b/apps/timeandlife/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwkB/4AGCY4PHC/4X/C/4X/C/4XvJ/4X/C/4X/C/4X3AH4A/AH4A/AH4A/")) diff --git a/apps/timeandlife/app.js b/apps/timeandlife/app.js new file mode 100644 index 000000000..905ec3031 --- /dev/null +++ b/apps/timeandlife/app.js @@ -0,0 +1,278 @@ +// Globals +const X = 176, + Y = 176; // screen resolution of bangle 2 +const STEP_TIMEOUT = 1000; +const PAUSE_TIME = 3000; + +// Each of my pixels is an 8x8 square. +const ON = { + width: 8, + height: 8, + bpp: 1, + transparent: 0, + buffer: new Uint8Array([ + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + 0xff, + ]).buffer, + state: 1, +}; +const OFF = { + width: 8, + height: 8, + bpp: 1, + transparent: 1, + buffer: new Uint8Array([ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + ]).buffer, + state: 0, +}; + +const ONE = [ + [0, 1, 0], + [1, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [1, 1, 1], +]; +const TWO = [ + [0, 1, 0], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [1, 0, 0], + [1, 0, 0], + [1, 1, 1], +]; +const THREE = [ + [0, 1, 0], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const FOUR = [ + [0, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 1, 1], + [0, 0, 1], + [0, 0, 1], + [0, 0, 1], +]; +const FIVE = [ + [1, 1, 1], + [1, 0, 0], + [1, 0, 0], + [0, 1, 0], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const SIX = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 0], + [1, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const SEVEN = [ + [1, 1, 1], + [1, 0, 1], + [0, 0, 1], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], + [0, 1, 0], +]; +const EIGHT = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const NINE = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [0, 1, 1], + [0, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const ZERO = [ + [0, 1, 0], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [1, 0, 1], + [0, 1, 0], +]; +const NUMBERS = [ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE]; + +// Arraybuffers to store game state +// 484 8 bit integers that are either 1 or 0 form the 22 x 22 grid +let emptySeed = []; +for (i = 0; i < 484; i++) { + emptySeed.push(0); +} +let data = E.toUint8Array(emptySeed); +let nextData = E.toUint8Array(emptySeed); +const dataAddr = E.getAddressOf(data, true); +const nextDataAddr = E.getAddressOf(nextData, true); + +let lastPaused = new Date(); + +const forAllElements = fn => { + let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; + numbers.forEach(i => { + numbers.forEach(j => { + fn(i, j); + }); + }); +}; + +// Conway's game of life +// if < 2 neighbours, set off +// if 2 or 3 neighbours, set on +// if > 3 neighbours, set off +const updateStateC = E.compiledC(` +// void run(int, int) +void run(char* n, char* m){ + // n is a pointer to the first byte in data, m is for nextdata + int count = 0; + for (int i=0;i<484;i++) { + // Add 8 neighbours, wrapping around + count = + *(n+(i+484-23)%484) + + *(n+(i+484-22)%484) + + *(n+(i+484-21)%484) + + *(n+(i+484-1)%484) + + *(n+(i+484+1)%484) + + *(n+(i+484+21)%484) + + *(n+(i+484+22)%484) + + *(n+(i+484+23)%484); + if (count < 2 || count > 3) { + *(m+i) = 0; + } else { + *(m+i) = 1; + } + } +} +`); +const copyStateC = E.compiledC(` +// void run(int, int) +void run(char* n, char* m){ + // n is a pointer to the first byte in data, m is for nextdata + for (int i=0;i<484;i++) { + *(n+i) = *(m+i); + } +} +`); + +const step = () => { + if (new Date() - lastPaused < PAUSE_TIME) { + return; + } + let startTime = new Date(); + updateStateC.run(dataAddr, nextDataAddr); + nextData.forEach((e, i) => { + if (e && !data[i]) { + g.drawImage(ON, Math.floor(i / 22) * 8, i % 22 * 8); + } else if (data[i]) { + g.drawImage(OFF, Math.floor(i / 22) * 8, i % 22 * 8); + } + }); + copyStateC.run(dataAddr, nextDataAddr); +}; + +const drawPixel = (i, j, value) => { + g.drawImage(value, j * 8, i * 8); + data[j * 22 + i] = value.state; + nextData[j * 22 + i] = value.state; +}; + +const drawNum = (character, i, j) => { + const startJ = j; + character.forEach(row => { + j = startJ; + row.forEach(pixel => { + if (pixel) { + drawPixel(i, j, ON); + } + j++; + }); + i++; + }); +}; + +const drawDots = () => { + drawPixel(10, 10, ON); + drawPixel(12, 10, ON); +}; + +const drawTime = () => { + lastPaused = new Date(); + g.clear(); + data.forEach((el, i) => { + data[i] = 0; + }); + const d = new Date(); + const hourTens = Math.floor(d.getHours() / 10); + const hourOnes = d.getHours() % 10; + const minuteTens = Math.floor(d.getMinutes() / 10); + const minuteOnes = d.getMinutes() % 10; + drawNum(NUMBERS[hourTens], 8, 1); + drawNum(NUMBERS[hourOnes], 8, 6); + drawDots(); + drawNum(NUMBERS[minuteTens], 8, 13); + drawNum(NUMBERS[minuteOnes], 8, 18); +}; + +const start = () => { + Bangle.setUI("clock"); // Show launcher when middle button pressed + g.clear(); + Bangle.setLCDTimeout(20); // backlight/lock timeout in seconds + let stepInterval = setInterval(step, STEP_TIMEOUT); + + // Handlers + Bangle.on('touch', drawTime); + + // Sleep mode + Bangle.on('lock', isLocked => { + if (stepInterval) { + clearInterval(stepInterval); + } + stepInterval = undefined; + if (!isLocked) { + drawTime(); + stepInterval = setInterval(step, STEP_TIMEOUT); + } + }); + + drawTime(); +}; + +start(); diff --git a/apps/timeandlife/app.png b/apps/timeandlife/app.png new file mode 100644 index 0000000000000000000000000000000000000000..b1e837d258215458c7427ee87669e9bbac4a6cff GIT binary patch literal 605 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1SD@Hc}*5j~)%+dI0Z`UZ9TaH&0ol7?IxJKYaYEcX0Eb^M5Usybh)`_$$my-IXYqFW{daW%a!F zk%YE4*GJ2bGaSWL>YnU+^GW*oq{DUdB#k%Ctb8P~G2m6w&hE&Y0iDY`9(Sz@+-LuM z)1k`l%~5MNf3y9`eV8>jb>?f6_KAm-rYSfz^jK-FIONn6)+-_`dCR}*2fOTk551W& zq6S4e3)n;_J!b#keE;sOqbE7dHRrH2>2LdM$kbBS7$1N0nDxpV8r5TsRNT2Pd=c+H@LRGrSgzw9Q*Cx${@dC)b_|iP zv}&1UWSADKo{IZkQJ!C(|9@WQ_wUTwQbk=Q7Cfhb(ZX5a5n0T@pr;JNj1^1m%YcIH zC7!;n>`!^5g?X8JOXb~wLXst}5hc#~xw)x%B@E6*sfi`2DGKG8B^e6tp1uL$jeO!j zMed$1jv*0;-(EY&$)Lc);&}dFb)V@ScbByLLhPSB)6z^;SKizH`FoX)0vIf~@0j_1 o>aXTcb(@SJA_|_9RAS#UOgP19!;<*A7ic7dr>mdKI;Vst02rI_VgLXD literal 0 HcmV?d00001 From fb14142593aff4a48411251d593cf26a386a60da Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:38:57 -0500 Subject: [PATCH 016/169] fix screenshot --- apps/timeandlife/README.md | 4 +--- apps/timeandlife/screenshot.png | Bin 0 -> 811 bytes 2 files changed, 1 insertion(+), 3 deletions(-) create mode 100644 apps/timeandlife/screenshot.png diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md index af92d8cb8..b03cbf2fb 100644 --- a/apps/timeandlife/README.md +++ b/apps/timeandlife/README.md @@ -2,6 +2,4 @@ A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). -![](screenshot1.png) -![](screenshot2.png) -![](screenshot3.png) +![](screenshot.png) diff --git a/apps/timeandlife/screenshot.png b/apps/timeandlife/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5ffda5bf052b411fab011024b6e8cf9a6b4aedb0 GIT binary patch literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^`+;~L2OE$~*>-O+kYXuz@(kesf*OvL4j^B$#5JNM zI6tkVJh3R1Aw4fYH&wSdxhOR?uQ(&WkRs=z)Wnj^{5*w_%-mE4Um(NC zT)`zZS;5G_$WXz+$jaEl%D_?~z*qO>a-g+L9iA?ZAr*7p-gV46Y#`upan+Z9(?1=& zBE6;C@x+t;+j&*Iew;~4dh^xh{J*9JTfd9hd*0v9&#=8?zRt(Vs&$)=_)q(BQpi5? zk-GPvl+M8`Sm(FzXVmNS*T3IWx34?%^L*XED_{PoVYvHR#`*fHe(Tce^R>6W{J#6I zcG>gUMn5q;=vMvjcJ;08)_dLSfBzTBx1WC!BN$4*?6b}P{_XcEpS%0w{@ZUqpZ*CW zylTJ9tKX$Q?;n3bb^qUQzrWo{!>Z>0w%g}-{{3S6cM2A3zFO}2cExzz_4$UF&b+ox jzxpH==MTb2t79xWAF@BqJ@q&+Av1Wo`njxgN@xNAJLr-e literal 0 HcmV?d00001 From 27be246c82c14f31943567875392469b548cbb2d Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:43:37 -0500 Subject: [PATCH 017/169] fix screenshot and description --- apps.json | 2 +- apps/timeandlife/README.md | 2 +- apps/timeandlife/screenshot.png | Bin 811 -> 1634 bytes 3 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 02ee3d469..62e78b8da 100644 --- a/apps.json +++ b/apps.json @@ -5069,7 +5069,7 @@ "shortName":"Time and Lfie", "icon": "app.png", "version":"0.0.1", - "description": "A simple watchface which displays the time when the screen is tapped and decay according to the rules of Conway's game of life.", + "description": "A simple watchface which displays the time when the screen is tapped and decays according to the rules of Conway's game of life.", "type": "clock", "tags": "clock", "supports": ["BANGLEJS2"], diff --git a/apps/timeandlife/README.md b/apps/timeandlife/README.md index b03cbf2fb..4a638c952 100644 --- a/apps/timeandlife/README.md +++ b/apps/timeandlife/README.md @@ -1,5 +1,5 @@ # Time and Life -A simple watchface which displays the time when the screen is tapped and decay according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). +A simple watchface which displays the time when the screen is tapped and decays according to the rules of [Conway's game of life](https://en.wikipedia.org/wiki/Conway%27s_Game_of_Life). ![](screenshot.png) diff --git a/apps/timeandlife/screenshot.png b/apps/timeandlife/screenshot.png index 5ffda5bf052b411fab011024b6e8cf9a6b4aedb0..3058c9346bbcb23f5348729b81179b6d6b80f37a 100644 GIT binary patch literal 1634 zcmeHIZA@Bc6utsQvBj^}W}*_hR!C)GC#$-1|oh&)E>oL(CuCH=%fOR`#=Rksa|_HeHk9@bbzPZ ze?c(;KS|^x#fxruwmzncRwO-;Pi*%aVP>N^>K0v8ZTW+Js@i*`@P<0;(kb&;PzY=F zTHJw6Q{}*2qH13eHsIHx)_?;II@%Kg9mZ$IF2CU`k3$Z5!8X;DjYckQL6nQe%idiFjU{bm(i(t*KC~zu+1)Tf2 z%XoRakyjPm#s4I8>5RXWc1On@73BAZVGqxLu^S<}&uDP=!laTfO?aHFL}y~#{W?sC zHsqL%{*e&-jX`R4eDt(~EFNS1G;j6OZ6);C3}{->aD!TpiHG!4YE_1-d3pi(Ah*1o))?Yv+!?^jBo{$GA>%jwMfJYA zoX)s@n1tssu=oYouVV^2n9wR@b2_%pU`HfP6Vy7Q^4fz;PX1tk_Txm;GD9F429sWS z93tc`gO2G{;YFp5Qdi<=$YRpBfkW9WZlI@+Sz~k7O17Y{<$%%-#xhWZ+wi+=J1jTC zdnv&poFHE!LIrZBcvbi5sbFtYg$vnVVnMJmVS+$*V){-{V zZ2A1rJ?$#6zH8eH~hTgZsal^9Z5qyfHj{ z#TlB|PpmHvst(?plyxH=S0arH(X)GXxhbixLk;+~(s5!lkQkGDQZ0ZIP^UD-!-t%AJ2YtW;C(BEA(jq N#RVlCRUZGde*iBqFmwO_ literal 811 zcmeAS@N?(olHy`uVBq!ia0vp^`+;~L2OE$~*>-O+kYXuz@(kesf*OvL4j^B$#5JNM zI6tkVJh3R1Aw4fYH&wSdxhOR?uQ(&WkRs=z)Wnj^{5*w_%-mE4Um(NC zT)`zZS;5G_$WXz+$jaEl%D_?~z*qO>a-g+L9iA?ZAr*7p-gV46Y#`upan+Z9(?1=& zBE6;C@x+t;+j&*Iew;~4dh^xh{J*9JTfd9hd*0v9&#=8?zRt(Vs&$)=_)q(BQpi5? zk-GPvl+M8`Sm(FzXVmNS*T3IWx34?%^L*XED_{PoVYvHR#`*fHe(Tce^R>6W{J#6I zcG>gUMn5q;=vMvjcJ;08)_dLSfBzTBx1WC!BN$4*?6b}P{_XcEpS%0w{@ZUqpZ*CW zylTJ9tKX$Q?;n3bb^qUQzrWo{!>Z>0w%g}-{{3S6cM2A3zFO}2cExzz_4$UF&b+ox jzxpH==MTb2t79xWAF@BqJ@q&+Av1Wo`njxgN@xNAJLr-e From b9cda9b829e29a7075d49eaf56e3d8110ae19f9f Mon Sep 17 00:00:00 2001 From: phil Date: Mon, 27 Dec 2021 14:55:22 -0500 Subject: [PATCH 018/169] version number --- apps.json | 2 +- apps/timeandlife/ChangeLog | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index 62e78b8da..15d3005c6 100644 --- a/apps.json +++ b/apps.json @@ -5068,7 +5068,7 @@ "name": "Time and Life", "shortName":"Time and Lfie", "icon": "app.png", - "version":"0.0.1", + "version":"0.1", "description": "A simple watchface which displays the time when the screen is tapped and decays according to the rules of Conway's game of life.", "type": "clock", "tags": "clock", diff --git a/apps/timeandlife/ChangeLog b/apps/timeandlife/ChangeLog index 115067b80..c7b309a74 100644 --- a/apps/timeandlife/ChangeLog +++ b/apps/timeandlife/ChangeLog @@ -1 +1 @@ -0.01: New app +0.1: New app From 77d785bb68d3fdc1380110d58a8e6dec9ff0831c Mon Sep 17 00:00:00 2001 From: phil Date: Wed, 29 Dec 2021 22:31:58 -0500 Subject: [PATCH 019/169] remove unused code --- apps/timeandlife/app.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/apps/timeandlife/app.js b/apps/timeandlife/app.js index 905ec3031..7532f9bc8 100644 --- a/apps/timeandlife/app.js +++ b/apps/timeandlife/app.js @@ -145,15 +145,6 @@ const nextDataAddr = E.getAddressOf(nextData, true); let lastPaused = new Date(); -const forAllElements = fn => { - let numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]; - numbers.forEach(i => { - numbers.forEach(j => { - fn(i, j); - }); - }); -}; - // Conway's game of life // if < 2 neighbours, set off // if 2 or 3 neighbours, set on From 1ef8a0bfb0b52107cac461c7f009a7e74a6efa36 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 5 Jan 2022 01:00:03 +0100 Subject: [PATCH 020/169] 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 670c232f28e0c746ae8f356c81a8f65e4fef340f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:01 +0100 Subject: [PATCH 021/169] Create LICENSE --- apps/colorful_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/colorful_clock/LICENSE diff --git a/apps/colorful_clock/LICENSE b/apps/colorful_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/colorful_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +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. From 49bee5390bff6e8c03710fb094227b0f5b45f5e9 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:06 +0100 Subject: [PATCH 022/169] Create LICENSE --- apps/themesetter/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/themesetter/LICENSE diff --git a/apps/themesetter/LICENSE b/apps/themesetter/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/themesetter/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +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. From 754e752a8bd292bdcccf73f3eb8a7ef172cd99cb Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:09 +0100 Subject: [PATCH 023/169] Create LICENSE --- apps/simple_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/simple_clock/LICENSE diff --git a/apps/simple_clock/LICENSE b/apps/simple_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/simple_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +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. From 117348cb16f74003180f4474c125efca0523e98e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:17 +0100 Subject: [PATCH 024/169] Create app.js --- apps/configurable_clock/app.js | 1336 ++++++++++++++++++++++++++++++++ 1 file changed, 1336 insertions(+) create mode 100644 apps/configurable_clock/app.js diff --git a/apps/configurable_clock/app.js b/apps/configurable_clock/app.js new file mode 100644 index 000000000..19dc363e4 --- /dev/null +++ b/apps/configurable_clock/app.js @@ -0,0 +1,1336 @@ + let Layout = require('Layout'); + + let Caret = require("heatshrink").decompress(atob("hEUgMAsFgmEwjEYhkMg0GAYIHBBYIPBgAA==")); + + let ScreenWidth = g.getWidth(), CenterX; + let ScreenHeight = g.getHeight(), CenterY, outerRadius; + + Bangle.loadWidgets(); + +/**** updateClockFaceSize ****/ + + function updateClockFaceSize () { + CenterX = ScreenWidth/2; + CenterY = ScreenHeight/2; + + outerRadius = Math.min(CenterX,CenterY) * 0.9; + + if (global.WIDGETS == null) { return; } + + let WidgetLayouts = { + tl:{ x:0, y:0, Direction:0 }, + tr:{ x:ScreenWidth-1, y:0, Direction:1 }, + bl:{ x:0, y:ScreenHeight-24, Direction:0 }, + br:{ x:ScreenWidth-1, y:ScreenHeight-24, Direction:1 } + }; + + for (let Widget of WIDGETS) { + let WidgetLayout = WidgetLayouts[Widget.area]; // reference, not copy! + if (WidgetLayout == null) { continue; } + + Widget.x = WidgetLayout.x - WidgetLayout.Direction * Widget.width; + Widget.y = WidgetLayout.y; + + WidgetLayout.x += Widget.width * (1-2*WidgetLayout.Direction); + } + + let x,y, dx,dy; + let cx = CenterX, cy = CenterY, r = outerRadius, r2 = r*r; + + x = WidgetLayouts.tl.x; y = WidgetLayouts.tl.y+24; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.tr.x; y = WidgetLayouts.tr.y+24; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY + 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.bl.x; y = WidgetLayouts.bl.y; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + x = WidgetLayouts.br.x; y = WidgetLayouts.br.y; dx = x - cx; dy = y - cy; + if (dx*dx + dy*dy < r2) { + cy = CenterY - 12; dy = y - cy; r2 = dx*dx + dy*dy; r = Math.sqrt(r2); + } + + CenterX = cx; CenterY = cy; outerRadius = r * 0.9; + } + + updateClockFaceSize(); + +/**** custom version of Bangle.drawWidgets (does not clear the widget areas) ****/ + + Bangle.drawWidgets = function () { + var w = g.getWidth(), h = g.getHeight(); + + var pos = { + tl:{x:0, y:0, r:0, c:0}, // if r==1, we're right->left + tr:{x:w-1, y:0, r:1, c:0}, + bl:{x:0, y:h-24, r:0, c:0}, + br:{x:w-1, y:h-24, r:1, c:0} + }; + + if (global.WIDGETS) { + for (var wd of WIDGETS) { + var p = pos[wd.area]; + if (!p) continue; + + wd.x = p.x - p.r*wd.width; + wd.y = p.y; + + p.x += wd.width*(1-2*p.r); + p.c++; + } + + g.reset(); // also loads the current theme + + if (pos.tl.c || pos.tr.c) { + g.setClipRect(0,h-24,w-1,h-1); + g.reset(); // also (re)loads the current theme + } + + if (pos.bl.c || pos.br.c) { + g.setClipRect(0,h-24,w-1,h-1); + g.reset(); // also (re)loads the current theme + } + + try { + for (wd of WIDGETS) { + g.clearRect(wd.x,wd.y, wd.x+wd.width-1,23); + wd.draw(wd); + } + } catch (e) { print(e); } + } + }; + +/**** EventConsumerAtPoint ****/ + + let activeLayout; + + function EventConsumerAtPoint (HandlerName, x,y) { + let Layout = (activeLayout || {}).l; + if (Layout == null) { return; } + + function ConsumerIn (Control) { + if ( + (x < Control.x) || (x >= Control.x + Control.w) || + (y < Control.y) || (y >= Control.y + Control.h) + ) { return undefined; } + + if (typeof Control[HandlerName] === 'function') { return Control; } + + if (Control.c != null) { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let Consumer = ConsumerIn(ControlList[i]); + if (Consumer != null) { return Consumer; } + } + } + + return undefined; + } + + return ConsumerIn(Layout); + } + +/**** dispatchTouchEvent ****/ + + function dispatchTouchEvent (DefaultHandler) { + function handleTouchEvent (Button, xy) { + if (activeLayout == null) { + if (typeof DefaultHandler === 'function') { + DefaultHandler(); + } + } else { + let Control = EventConsumerAtPoint('onTouch', xy.x,xy.y); + if (Control != null) { + Control.onTouch(Control, Button, xy); + } + } + } + Bangle.on('touch',handleTouchEvent); + } + dispatchTouchEvent(); + +/**** dispatchStrokeEvent ****/ + + function dispatchStrokeEvent (DefaultHandler) { + function handleStrokeEvent (Coordinates) { + if (activeLayout == null) { + if (typeof DefaultHandler === 'function') { + DefaultHandler(); + } + } else { + let Control = EventConsumerAtPoint('onStroke', Coordinates.xy[0],Coordinates.xy[1]); + if (Control != null) { + Control.onStroke(Control, Coordinates); + } + } + } + Bangle.on('stroke',handleStrokeEvent); + } + dispatchStrokeEvent(); +/**** Label ****/ + + function Label (Text, Options) { + function renderLabel (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2; + let Height = Details.h, halfHeight = Height/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + let bold = Details.bold ? 1 : 0; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + g.setClipRect( + x+Border+Padding,y+Border+Padding, + x + Width-Border-Padding-1,y + Height-Border-Padding-1 + ); + + x += halfWidth + xAlignment*(halfWidth - Border - Padding); + y += halfHeight + yAlignment*(halfHeight - Border - Padding); + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + if (Details.font != null) { g.setFont(Details.font); } + g.setFontAlign(xAlignment,yAlignment); + + g.drawString(Details.label, x,y); + if (bold !== 0) { + g.drawString(Details.label, x+1,y); + g.drawString(Details.label, x,y+1); + g.drawString(Details.label, x+1,y+1); + } + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderLabel, label:Text || '' + }); + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + let TextMetrics; + if (! Result.width || ! Result.height) { + if (Result.font == null) { + Result.font = g.getFont(); + } else { + g.setFont(Result.font); + } + TextMetrics = g.stringMetrics(Result.label); + } + + if (Result.col == null) { Result.col = g.getColor(); } + if (Result.bgCol == null) { Result.bgCol = g.getBgColor(); } + + Result.width = Result.width || TextMetrics.width + 2*Border + 2*Padding; + Result.height = Result.height || TextMetrics.height + 2*Border + 2*Padding; + return Result; + } + +/**** Image ****/ + + function Image (Image, Options) { + function renderImage (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - Details.ImageWidth/2; + let Height = Details.h, halfHeight = Height/2 - Details.ImageHeight/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + g.setClipRect( + x+Border+Padding,y+Border+Padding, + x + Width-Border-Padding-1,y + Height-Border-Padding-1 + ); + + x += halfWidth + xAlignment*(halfWidth - Border - Padding); + y += halfHeight + yAlignment*(halfHeight - Border - Padding); + + if ('rotate' in Details) { // "rotate" centers image at x,y! + x += Details.ImageWidth/2; + y += Details.ImageHeight/2; + } + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + g.drawImage(Image, x,y, Details.ImageOptions); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderImage, Image:Image + }); + let ImageMetrics = g.imageMetrics(Image); + let Scale = Result.scale || 1; + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + Result.ImageWidth = Scale * ImageMetrics.width; + Result.ImageHeight = Scale * ImageMetrics.height; + + if (('rotate' in Result) || ('scale' in Result) || ('frame' in Result)) { + Result.ImageOptions = {}; + if ('rotate' in Result) { Result.ImageOptions.rotate = Result.rotate; } + if ('scale' in Result) { Result.ImageOptions.scale = Result.scale; } + if ('frame' in Result) { Result.ImageOptions.frame = Result.frame; } + } + + Result.width = Result.width || Result.ImageWidth + 2*Border + 2*Padding; + Result.height = Result.height || Result.ImageHeight + 2*Border + 2*Padding; + return Result; + } + +/**** Drawable ****/ + + function Drawable (Callback, Options) { + function renderDrawable (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, DrawableWidth = Details.DrawableWidth || Width; + let Height = Details.h, DrawableHeight = Details.DrawableHeight || Height; + + let halfWidth = Width/2 - DrawableWidth/2; + let halfHeight = Height/2 - DrawableHeight/2; + + let Border = Details.border || 0, BorderColor = Details.BorderColor; + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Hilite || (Details.bgCol != null)) { + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if ((Border > 0) && (BorderColor !== null)) {// draw border of layout cell + g.setColor(BorderColor || Details.col || g.theme.fg); + + switch (Border) { + case 2: g.drawRect(x+1,y+1, x+Width-2,y+Height-2);// no break here! + case 1: g.drawRect(x,y, x+Width-1,y+Height-1); break; + default: g.fillPoly([ + x,y, x+Width,y, x+Width,y+Height, x,y+Height, x,y, + x+Border,y+Border, x+Border,y+Height-Border, + x+Width-Border,y+Height-Border, x+Width-Border,y+Border, + x+Border,y+Border + ]); + } + } + + let DrawableX = x + halfWidth + xAlignment*(halfWidth - Border - Padding); + let DrawableY = y + halfHeight + yAlignment*(halfHeight - Border - Padding); + + g.setClipRect( + Math.max(x+Border+Padding,DrawableX), + Math.max(y+Border+Padding,DrawableY), + Math.min(x+Width -Border-Padding,DrawableX+DrawableWidth)-1, + Math.min(y+Height-Border-Padding,DrawableY+DrawableHeight)-1 + ); + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + Callback(DrawableX,DrawableY, DrawableWidth,DrawableHeight, Details); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderDrawable, cb:Callback + }); + let DrawableWidth = Result.DrawableWidth || 10; + let DrawableHeight = Result.DrawableHeight || 10; + + let Border = Result.border || 0; + let Padding = Result.pad || 0; + + Result.width = Result.width || DrawableWidth + 2*Border + 2*Padding; + Result.height = Result.height || DrawableHeight + 2*Border + 2*Padding; + return Result; + } + + if (g.drawRoundedRect == null) { + g.drawRoundedRect = function drawRoundedRect (x1,y1, x2,y2, r) { + let x,y; + if (x1 > x2) { x = x1; x1 = x2; x2 = x; } + if (y1 > y2) { y = y1; y1 = y2; y2 = y; } + + r = Math.min(r || 0, (x2-x1)/2, (y2-y1)/2); + + let cx1 = x1+r, cx2 = x2-r; + let cy1 = y1+r, cy2 = y2-r; + + this.drawLine(cx1,y1, cx2,y1); + this.drawLine(cx1,y2, cx2,y2); + this.drawLine(x1,cy1, x1,cy2); + this.drawLine(x2,cy1, x2,cy2); + + x = r; y = 0; + + let dx,dy, Error = 0; + while (y <= x) { + dy = 1 + 2*y; y++; Error -= dy; + if (Error < 0) { + dx = 1 - 2*x; x--; Error -= dx; + } + + this.setPixel(cx1 - x, cy1 - y); this.setPixel(cx1 - y, cy1 - x); + this.setPixel(cx2 + x, cy1 - y); this.setPixel(cx2 + y, cy1 - x); + this.setPixel(cx2 + x, cy2 + y); this.setPixel(cx2 + y, cy2 + x); + this.setPixel(cx1 - x, cy2 + y); this.setPixel(cx1 - y, cy2 + x); + } + }; + } + + if (g.fillRoundedRect == null) { + g.fillRoundedRect = function fillRoundedRect (x1,y1, x2,y2, r) { + let x,y; + if (x1 > x2) { x = x1; x1 = x2; x2 = x; } + if (y1 > y2) { y = y1; y1 = y2; y2 = y; } + + r = Math.min(r || 0, (x2-x1)/2, (y2-y1)/2); + + let cx1 = x1+r, cx2 = x2-r; + let cy1 = y1+r, cy2 = y2-r; + + this.fillRect(x1,cy1, x2,cy2); + + x = r; y = 0; + + let dx,dy, Error = 0; + while (y <= x) { + dy = 1 + 2*y; y++; Error -= dy; + if (Error < 0) { + dx = 1 - 2*x; x--; Error -= dx; + } + + this.drawLine(cx1 - x, cy1 - y, cx2 + x, cy1 - y); + this.drawLine(cx1 - y, cy1 - x, cx2 + y, cy1 - x); + this.drawLine(cx1 - x, cy2 + y, cx2 + x, cy2 + y); + this.drawLine(cx1 - y, cy2 + x, cx2 + y, cy2 + x); + } + }; + } + + +/**** Button ****/ + + function Button (Text, Options) { + function renderButton (Details) { + let x = Details.x, Width = Details.w, halfWidth = Width/2; + let y = Details.y, Height = Details.h, halfHeight = Height/2; + + let Padding = Details.pad || 0; + let Hilite = Details.hilite || false; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + if (Hilite) { + g.setColor(g.theme.bgH); // no typo! + g.fillRoundedRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1,8); + } + + g.setColor (Hilite ? g.theme.fgH : Details.col || g.theme.fg); + g.setBgColor(Hilite ? g.theme.bgH : Details.bgCol || g.theme.bg); + + if (Details.font != null) { g.setFont(Details.font); } + g.setFontAlign(0,0); + + g.drawRoundedRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1,8); + + g.setClipRect(x+Padding,y+Padding, x+Width-Padding-1,y+Height-Padding-1); + + g.drawString(Details.label, x+halfWidth,y+halfHeight); + g.drawString(Details.label, x+halfWidth+1,y+halfHeight); + g.drawString(Details.label, x+halfWidth,y+halfHeight+1); + g.drawString(Details.label, x+halfWidth+1,y+halfHeight+1); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderButton, label:Text || 'Tap' + }); + let Padding = Result.pad || 0; + + let TextMetrics; + if (! Result.width || ! Result.height) { + if (Result.font == null) { + Result.font = g.getFont(); + } else { + g.setFont(Result.font); + } + TextMetrics = g.stringMetrics(Result.label); + } + + Result.width = Result.width || TextMetrics.width + 2*10 + 2*Padding; + Result.height = Result.height || TextMetrics.height + 2*5 + 2*Padding; + return Result; + } + + const Checkbox_checked = require("heatshrink").decompress(atob("ikUgMf/+GgEGoEAlEAgOAgEYsFhw8OjE54OB/EYh4OB+EYj+BwecjFw8OGg0YDocUgECsEAsP//A")); + const Checkbox_unchecked = require("heatshrink").decompress(atob("ikUgMf/+GgEGoEAlEAgOAgEYAjkUgECsEAsP//A=")); + +/**** Checkbox ****/ + + function Checkbox (Options) { + function renderCheckbox (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - 10; + let Height = Details.h, halfHeight = Height/2 - 10; + + let Padding = Details.pad || 0; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + x += halfWidth + xAlignment*(halfWidth - Padding); + y += halfHeight + yAlignment*(halfHeight - Padding); + + g.setColor (Details.col || g.theme.fg); + g.setBgColor(Details.bgCol || g.theme.bg); + + g.drawImage( + Details.checked ? Checkbox_checked : Checkbox_unchecked, x,y + ); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderCheckbox, onTouch:toggleCheckbox + }); + let Padding = Result.pad || 0; + + Result.width = Result.width || 20 + 2*Padding; + Result.height = Result.height || 20 + 2*Padding; + + if (Result.checked == null) { Result.checked = false; } + return Result; + } + + /* private */ function toggleCheckbox (Control) { + g.reset(); + + Control.checked = ! Control.checked; + Control.render(Control); + + if (typeof Control.onChange === 'function') { + Control.onChange(Control); + } + } + +/**** toggleInnerCheckbox ****/ + + /* export */ function toggleInnerCheckbox (Control) { + if (Control.c == null) { + if (('checked' in Control) && ! ('GroupName' in Control)) { + toggleCheckbox(Control); + return true; + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let done = toggleInnerCheckbox(ControlList[i]); + if (done) { return true; } + } + } + } + + const Radiobutton_checked = require("heatshrink").decompress(atob("ikUgMB/EAsFgjEBwUAgkggFEgECoEAlEPgOB/EYj+BAgmA+EUCYciDodBwEYg0GgEfwA")); + const Radiobutton_unchecked = require("heatshrink").decompress(atob("ikUgMB/EAsFgjEBwUAgkggFEgECoEAlEAgOAgEYAhEUCYciDodBwEYg0GgEfwAA=")); + +/**** Radiobutton ****/ + + function Radiobutton (Options) { + function renderRadiobutton (Details) { + let x = Details.x, xAlignment = Details.halign || 0; + let y = Details.y, yAlignment = Details.valign || 0; + + let Width = Details.w, halfWidth = Width/2 - 10; + let Height = Details.h, halfHeight = Height/2 - 10; + + let Padding = Details.pad || 0; + + if (Details.bgCol != null) { + g.setBgColor(Details.bgCol); + g.clearRect(x,y, x + Width-1,y + Height-1); + } + + x += halfWidth + xAlignment*(halfWidth - Padding); + y += halfHeight + yAlignment*(halfHeight - Padding); + + g.setColor (Details.col || g.theme.fg); + g.setBgColor(Details.bgCol || g.theme.bg); + + g.drawImage( + Details.checked ? Radiobutton_checked : Radiobutton_unchecked, x,y + ); + } + + let Result = Object.assign(( + Options == null ? {} : Object.assign({}, Options.common || {}, Options) + ), { + type:'custom', render:renderRadiobutton, onTouch:checkRadiobutton + }); + let Padding = Result.pad || 0; + + Result.width = Result.width || 20 + 2*Padding; + Result.height = Result.height || 20 + 2*Padding; + + if (Result.checked == null) { Result.checked = false; } + return Result; + } + + /* private */ function checkRadiobutton (Control) { + if (! Control.checked) { + uncheckRadiobuttonsIn((activeLayout || {}).l,Control.GroupName); + toggleRadiobutton(Control); + + if (typeof Control.onChange === 'function') { + Control.onChange(Control); + } + } + } + + /* private */ function toggleRadiobutton (Control) { + g.reset(); + + Control.checked = ! Control.checked; + Control.render(Control); + } + + /* private */ function uncheckRadiobuttonsIn (Control,GroupName) { + if ((Control == null) || (GroupName == null)) { return; } + + if (Control.c == null) { + if (('checked' in Control) && (Control.GroupName === GroupName)) { + if (Control.checked) { toggleRadiobutton(Control); } + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + uncheckRadiobuttonsIn(ControlList[i],GroupName); + } + } + } + +/**** checkInnerRadiobutton ****/ + + /* export */ function checkInnerRadiobutton (Control) { + if (Control.c == null) { + if (('checked' in Control) && ('GroupName' in Control)) { + checkRadiobutton(Control); + return true; + } + } else { + let ControlList = Control.c; + for (let i = 0, l = ControlList.length; i < l; i++) { + let done = checkInnerRadiobutton(ControlList[i]); + if (done) { return true; } + } + } + } + + + let Theme = g.theme; + g.clear(true); + +/**** Settings ****/ + + let Settings; + + function readSettings () { + Settings = Object.assign({}, + { + Face:'1-12', colored:true, + Hands:'rounded', withSeconds:true, + Foreground:'Theme', Background:'Theme', Seconds:'#FF0000' + }, + require('Storage').readJSON('configurable_clock.json', true) || {} + ); + + prepareTransformedPolygon(); + } + + function saveSettings () { + require('Storage').writeJSON('configurable_clock.json', Settings); + prepareTransformedPolygon(); + } + + function prepareTransformedPolygon () { + switch (Settings.Hands) { + case 'simple': transformedPolygon = new Array(simpleHourHandPolygon.length); break; + case 'rounded': transformedPolygon = new Array(roundedHandPolygon.length); break; + case 'hollow': transformedPolygon = new Array(hollowHandPolygon.length); + } + } + +//readSettings(); // not yet + + +/**** Hands ****/ + + let HourHandLength = outerRadius * 0.5; + let HourHandWidth = 2*3, halfHourHandWidth = HourHandWidth/2; + + let MinuteHandLength = outerRadius * 0.8; + let MinuteHandWidth = 2*2, halfMinuteHandWidth = MinuteHandWidth/2; + + let SecondHandLength = outerRadius * 0.9; + let SecondHandOffset = 10; + + let twoPi = 2*Math.PI, deg2rad = Math.PI/180; + let Pi = Math.PI; + let halfPi = Math.PI/2; + + let sin = Math.sin, cos = Math.cos; + +/**** simple Hands ****/ + + let simpleHourHandPolygon = [ + -halfHourHandWidth,halfHourHandWidth, + -halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth-HourHandLength, + halfHourHandWidth,halfHourHandWidth, + ]; + + let simpleMinuteHandPolygon = [ + -halfMinuteHandWidth,halfMinuteHandWidth, + -halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth-MinuteHandLength, + halfMinuteHandWidth,halfMinuteHandWidth, + ]; + + +/**** rounded Hands ****/ + + let outerBoltRadius = halfHourHandWidth + 2; + let innerBoltRadius = outerBoltRadius - 4; + let roundedHandOffset = outerBoltRadius + 4; + + let sine = [0, sin(30*deg2rad), sin(60*deg2rad), 1]; + + let roundedHandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0], + ]; + + let roundedHourHandPolygon = new Array(roundedHandPolygon.length); + for (let i = 0, l = roundedHandPolygon.length; i < l; i+=2) { + roundedHourHandPolygon[i] = halfHourHandWidth*roundedHandPolygon[i]; + roundedHourHandPolygon[i+1] = halfHourHandWidth*roundedHandPolygon[i+1]; + if (i < l/2) { roundedHourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { roundedHourHandPolygon[i+1] += roundedHandOffset; } + } + let roundedMinuteHandPolygon = new Array(roundedHandPolygon.length); + for (let i = 0, l = roundedHandPolygon.length; i < l; i+=2) { + roundedMinuteHandPolygon[i] = halfMinuteHandWidth*roundedHandPolygon[i]; + roundedMinuteHandPolygon[i+1] = halfMinuteHandWidth*roundedHandPolygon[i+1]; + if (i < l/2) { roundedMinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { roundedMinuteHandPolygon[i+1] += roundedHandOffset; } + } + + +/**** hollow Hands ****/ + + let BoltRadius = 3; + let hollowHandOffset = BoltRadius + 15; + + let hollowHandPolygon = [ + -sine[3],-sine[0], -sine[2],-sine[1], -sine[1],-sine[2], -sine[0],-sine[3], + sine[0],-sine[3], sine[1],-sine[2], sine[2],-sine[1], sine[3],-sine[0], + sine[3], sine[0], sine[2], sine[1], sine[1], sine[2], sine[0], sine[3], + 0,0, + -sine[0], sine[3], -sine[1], sine[2], -sine[2], sine[1], -sine[3], sine[0] + ]; + + let hollowHourHandPolygon = new Array(hollowHandPolygon.length); + for (let i = 0, l = hollowHandPolygon.length; i < l; i+=2) { + hollowHourHandPolygon[i] = halfHourHandWidth*hollowHandPolygon[i]; + hollowHourHandPolygon[i+1] = halfHourHandWidth*hollowHandPolygon[i+1]; + if (i < l/2) { hollowHourHandPolygon[i+1] -= HourHandLength; } + if (i > l/2) { hollowHourHandPolygon[i+1] -= hollowHandOffset; } + } + hollowHourHandPolygon[25] = -BoltRadius; + + let hollowMinuteHandPolygon = new Array(hollowHandPolygon.length); + for (let i = 0, l = hollowHandPolygon.length; i < l; i+=2) { + hollowMinuteHandPolygon[i] = halfMinuteHandWidth*hollowHandPolygon[i]; + hollowMinuteHandPolygon[i+1] = halfMinuteHandWidth*hollowHandPolygon[i+1]; + if (i < l/2) { hollowMinuteHandPolygon[i+1] -= MinuteHandLength; } + if (i > l/2) { hollowMinuteHandPolygon[i+1] -= hollowHandOffset; } + } + hollowMinuteHandPolygon[25] = -BoltRadius; + + + +/**** transform polygon ****/ + + let transformedPolygon; + + function transformPolygon (originalPolygon, OriginX,OriginY, Phi) { + let sPhi = sin(Phi), cPhi = cos(Phi), x,y; + + for (let i = 0, l = originalPolygon.length; i < l; i+=2) { + x = originalPolygon[i]; + y = originalPolygon[i+1]; + + transformedPolygon[i] = OriginX + x*cPhi + y*sPhi; + transformedPolygon[i+1] = OriginY + x*sPhi - y*cPhi; + } + } + +/**** refreshClock ****/ + + let Timer; + function refreshClock () { + activeLayout = null; + + g.setTheme({ + fg:(Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'), + bg:(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF') + }); + g.clear(true); // also installs the current theme + + Bangle.drawWidgets(); + renderClock(); + + let Period = (Settings.withSeconds ? 1000 : 60000); + + let Pause = Period - (Date.now() % Period); + Timer = setTimeout(refreshClock,Pause); + } + +/**** renderClock ****/ + + function renderClock () { + g.setColor (Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'); + g.setBgColor(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF'); + + switch (Settings.Face) { + case 'none': + break; + case '3,6,9,12': + g.setFont('Vector', 22); + + g.setFontAlign(0,-1); + g.drawString('12', CenterX,CenterY-outerRadius); + + g.setFontAlign(1,0); + g.drawString('3', CenterX+outerRadius,CenterY); + + g.setFontAlign(0,1); + g.drawString('6', CenterX,CenterY+outerRadius); + + g.setFontAlign(-1,0); + g.drawString('9', CenterX-outerRadius,CenterY); + break; + case '1-12': + let innerRadius = outerRadius * 0.9 - 10; + + for (let i = 0; i < 60; i++) { + let Phi = i * twoPi/60; + + let x = CenterX + outerRadius * sin(Phi); + let y = CenterY - outerRadius * cos(Phi); + + if (Settings.colored) { + let Color = E.HSBtoRGB(i/60,1,1, true); + g.setColor(Color[0]/255,Color[1]/255,Color[2]/255); + } + + g.fillCircle(x,y, 1); + } + + g.setFont('Vector', 20); + g.setFontAlign(0,0); + + for (let i = 0; i < 12; i++) { + let Phi = i * twoPi/12; + + let Radius = innerRadius; + if (i >= 10) { Radius -= 4; } + + let x = CenterX + Radius * sin(Phi); + let y = CenterY - Radius * cos(Phi); + + if (Settings.colored) { + let Color = E.HSBtoRGB(i/12,1,1, true); + g.setColor(Color[0]/255,Color[1]/255,Color[2]/255); + } + + g.drawString(i == 0 ? '12' : '' + i, x,y); + } + } + + let now = new Date(); + + let Hours = now.getHours() % 12; + let Minutes = now.getMinutes(); + + let HoursAngle = (Hours+(Minutes/60))/12 * twoPi - Pi; + let MinutesAngle = (Minutes/60) * twoPi - Pi; + + g.setColor(Settings.Foreground === 'Theme' ? Theme.fg : Settings.Foreground || '#000000'); + + switch (Settings.Hands) { + case 'simple': + transformPolygon(simpleHourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + + transformPolygon(simpleMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + break; + case 'rounded': + transformPolygon(roundedHourHandPolygon, CenterX,CenterY, HoursAngle); + g.fillPoly(transformedPolygon); + + transformPolygon(roundedMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.fillPoly(transformedPolygon); + +// g.setColor(Settings.Foreground === 'Theme' ? Theme.fg || '#000000'); + g.fillCircle(CenterX,CenterY, outerBoltRadius); + + g.setColor(Settings.Background === 'Theme' ? Theme.bg : Settings.Background || '#FFFFFF'); + g.drawCircle(CenterX,CenterY, outerBoltRadius); + g.fillCircle(CenterX,CenterY, innerBoltRadius); + break; + case 'hollow': + transformPolygon(hollowHourHandPolygon, CenterX,CenterY, HoursAngle); + g.drawPoly(transformedPolygon,true); + + transformPolygon(hollowMinuteHandPolygon, CenterX,CenterY, MinutesAngle); + g.drawPoly(transformedPolygon,true); + + g.drawCircle(CenterX,CenterY, BoltRadius); + } + + if (Settings.withSeconds) { + g.setColor(Settings.Seconds === 'Theme' ? Theme.fgH : Settings.Seconds || '#FF0000'); + + let Seconds = now.getSeconds(); + let SecondsAngle = (Seconds/60) * twoPi - Pi; + + let sPhi = Math.sin(SecondsAngle), cPhi = Math.cos(SecondsAngle); + + g.drawLine( + CenterX + SecondHandOffset*sPhi, + CenterY - SecondHandOffset*cPhi, + CenterX - SecondHandLength*sPhi, + CenterY + SecondHandLength*cPhi + ); + } + } + + +/**** MainScreen Logic ****/ + + let Changes = {}, KeysToChange; + + let fullScreen = { + x:0,y:0, w:ScreenWidth,h:ScreenHeight, x2:ScreenWidth-1,y2:ScreenHeight-1 + }; + let AppRect; + + function openMainScreen () { + if (Timer != null) { clearTimeout(Timer); Timer = undefined; } + if (AppRect == null) { AppRect = Bangle.appRect; Bangle.appRect = fullScreen; } + + KeysToChange = 'Face colored Hands withSeconds Foreground Background Seconds'; + + g.setTheme({ fg:'#000000', bg:'#FFFFFF' }); + g.clear(true); // also installs the current theme + + (activeLayout = MainScreen).render(); + } + + function applySettings () { saveSettings(); Bangle.appRect = AppRect; refreshClock(); } + function withdrawSettings () { readSettings(); Bangle.appRect = AppRect; refreshClock(); } + +/**** FacesScreen Logic ****/ + + function openFacesScreen () { + KeysToChange = 'Face colored'; + Bangle.appRect = fullScreen; + refreshFacesScreen(); + } + + function refreshFacesScreen () { + activeLayout = FacesScreen; + activeLayout['none'].checked = ((Changes.Face || Settings.Face) === 'none'); + activeLayout['3,6,9,12'].checked = ((Changes.Face || Settings.Face) === '3,6,9,12'); + activeLayout['1-12'].checked = ((Changes.Face || Settings.Face) === '1-12'); + activeLayout['colored'].checked = (Changes.colored == null ? Settings.colored : Changes.colored); + activeLayout.render(); + } + + function chooseFace (Control) { Changes.Face = Control.id; refreshFacesScreen(); } + function toggleColored () { Changes.colored = ! Changes.colored; refreshFacesScreen(); } + +/**** HandsScreen Logic ****/ + + function openHandsScreen () { + KeysToChange = 'Hands withSeconds'; + Bangle.appRect = fullScreen; + refreshHandsScreen(); + } + + function refreshHandsScreen () { + activeLayout = HandsScreen; + activeLayout['simple'].checked = ((Changes.Hands || Settings.Hands) === 'simple'); + activeLayout['rounded'].checked = ((Changes.Hands || Settings.Hands) === 'rounded'); + activeLayout['hollow'].checked = ((Changes.Hands || Settings.Hands) === 'hollow'); + activeLayout['withSeconds'].checked = (Changes.withSeconds == null ? Settings.withSeconds : Changes.withSeconds); + activeLayout.render(); + } + + function chooseHand (Control) { Changes.Hands = Control.id; refreshHandsScreen(); } + function toggleSeconds () { Changes.withSeconds = ! Changes.withSeconds; refreshHandsScreen(); } + +/**** ColorsScreen Logic ****/ + + function openColorsScreen () { + KeysToChange = 'Foreground Background Seconds'; + Bangle.appRect = fullScreen; + refreshColorsScreen(); + } + + function refreshColorsScreen () { + let Foreground = (Changes.Foreground == null ? Settings.Foreground : Changes.Foreground); + let Background = (Changes.Background == null ? Settings.Background : Changes.Background); + let Seconds = (Changes.Seconds == null ? Settings.Seconds : Changes.Seconds); + + activeLayout = ColorsScreen; + activeLayout['Foreground'].bgCol = (Foreground === 'Theme' ? Theme.fg : Foreground); + activeLayout['Background'].bgCol = (Background === 'Theme' ? Theme.bg : Background); + activeLayout['Seconds'].bgCol = (Seconds === 'Theme' ? Theme.fgH : Seconds); + activeLayout.render(); + } + + function selectForegroundColor () { ColorToChange = 'Foreground'; openColorChoiceScreen(); } + function selectBackgroundColor () { ColorToChange = 'Background'; openColorChoiceScreen(); } + function selectSecondsColor () { ColorToChange = 'Seconds'; openColorChoiceScreen(); } + +/**** ColorChoiceScreen Logic ****/ + + let ColorToChange, chosenColor; + + function openColorChoiceScreen () { + chosenColor = ( + Changes[ColorToChange] == null ? Settings[ColorToChange] : Changes[ColorToChange] + ); + Bangle.appRect = fullScreen; + refreshColorChoiceScreen(); + } + + function refreshColorChoiceScreen () { + activeLayout = ColorChoiceScreen; + activeLayout['#000000'].selected = (chosenColor === '#000000'); + activeLayout['#FF0000'].selected = (chosenColor === '#FF0000'); + activeLayout['#00FF00'].selected = (chosenColor === '#00FF00'); + activeLayout['#0000FF'].selected = (chosenColor === '#0000FF'); + activeLayout['#FFFF00'].selected = (chosenColor === '#FFFF00'); + activeLayout['#FF00FF'].selected = (chosenColor === '#FF00FF'); + activeLayout['#00FFFF'].selected = (chosenColor === '#00FFFF'); + activeLayout['#FFFFFF'].selected = (chosenColor === '#FFFFFF'); + activeLayout['Theme'].selected = (chosenColor === 'Theme'); + activeLayout.render(); + } + + function chooseColor (Control) { chosenColor = Control.id; refreshColorChoiceScreen(); } + function chooseThemeColor () { chosenColor = 'Theme'; refreshColorChoiceScreen(); } + + function applyColor () { + Changes[ColorToChange] = chosenColor; + openColorsScreen(); + } + + function withdrawColor () { + openColorsScreen(); + } + +/**** common logic for multiple screens ****/ + + function applyChanges () { + Settings = Object.assign(Settings,Changes); + Changes = {}; + openMainScreen(); + } + + function withdrawChanges () { + Changes = {}; + openMainScreen(); + } + + + g.setFont12x20(); // does not seem to be respected in layout! + + let OkCancelWidth = Math.max( + g.stringWidth('Ok'), g.stringWidth('Cancel') + ) + 2*10; + + let StdFont = { font:'12x20' }; + let legible = Object.assign({ col:'#000000', bgCol:'#FFFFFF' }, StdFont); + let leftAligned = Object.assign({ halign:-1, valign:0 }, legible); + let ColorView = Object.assign({ width:30, border:1, BorderColor:'#000000' }, StdFont); + let ColorChoice = Object.assign({ DrawableWidth:30, DrawableHeight:30, onTouch:chooseColor }, StdFont); + +/**** MainScreen ****/ + + let MainScreen = new Layout({ + type:'v', c:[ + Label('Settings', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Label('Faces', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openFacesScreen }, + { type:'h', c:[ + Label('Hands', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openHandsScreen }, + { type:'h', c:[ + Label('Colors', { common:leftAligned, fillx:1 }), + Image(Caret, { common:leftAligned }), + ], filly:1, onTouch:openColorsScreen }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applySettings }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawSettings }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** FacesScreen ****/ + + let FacesScreen = new Layout({ + type:'v', c:[ + Label('Clock Faces', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Radiobutton({ id:'none', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' no Face', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'3,6,9,12', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' 3, 6, 9 and 12', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'1-12', GroupName:'Faces', common:legible, onChange:chooseFace }), + Label(' numbers 1...12', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + { width:30 }, + Checkbox({ id:'colored', common:legible, onChange:toggleColored }), + Label(' colorful', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:toggleInnerCheckbox }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** HandsScreen ****/ + + let HandsScreen = new Layout({ + type:'v', c:[ + Label('Clock Hands', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Radiobutton({ id:'simple', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' simple', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'rounded', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' rounded + Bolt', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Radiobutton({ id:'hollow', GroupName:'Faces', common:legible, onChange:chooseHand }), + Label(' hollow + Bolt', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:checkInnerRadiobutton }, + { type:'h', c:[ + Checkbox({ id:'withSeconds', common:legible, onChange:toggleSeconds }), + Label(' show Seconds', { common:leftAligned, pad:4, fillx:1 }), + ], filly:1, onTouch:toggleInnerCheckbox }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** ColorsScreen ****/ + + let ColorsScreen = new Layout({ + type:'v', c:[ + Label('Clock Colors', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Label('Foreground', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Foreground', common:ColorView, bgCol:Theme.fg }), + ], filly:1, onTouch:selectForegroundColor }, + { type:'h', c:[ + Label('Background', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Background', common:ColorView, bgCol:Theme.bg }), + ], filly:1, onTouch:selectBackgroundColor }, + { type:'h', c:[ + Label('Seconds', { common:leftAligned, pad:4, fillx:1 }), + Label('', { id:'Seconds', common:ColorView, bgCol:Theme.fgH }), + ], filly:1, onTouch:selectSecondsColor }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyChanges }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawChanges }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + +/**** ColorChoiceScreen ****/ + + function drawColorChoice (x,y, Width,Height, Details) { + let selected = Details.selected; + if (selected) { + g.setColor('#FF0000'); + g.fillPoly([ + x,y, x+Width-1,y, x+Width-1,y+Height-1, x,y+Height-1, x,y, + x+3,y+3, x+3,y+Height-4, x+Width-4,y+Height-4, x+Width-4,y+3, x+3,y+3 + ]); + } else { + g.setColor('#000000'); + g.drawRect(x+3,y+3, x+Width-4,y+Height-4); + } + + g.setColor(Details.col); + g.fillRect(x+4,y+4, x+Width-5,y+Height-5); + } + + let ColorChoiceScreen = new Layout({ + type:'v', c:[ + Label('Choose Color', { common:legible, bold:true, filly:1 }), + { height:4 }, + { type:'h', c:[ + Drawable(drawColorChoice, { id:'#000000', common:ColorChoice, col:'#000000' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FF0000', common:ColorChoice, col:'#FF0000' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#00FF00', common:ColorChoice, col:'#00FF00' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#0000FF', common:ColorChoice, col:'#0000FF' }), + ], filly:1 }, + { type:'h', c:[ + Drawable(drawColorChoice, { id:'#FFFFFF', common:ColorChoice, col:'#FFFFFF' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FFFF00', common:ColorChoice, col:'#FFFF00' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#FF00FF', common:ColorChoice, col:'#FF00FF' }), + { width:8 }, + Drawable(drawColorChoice, { id:'#00FFFF', common:ColorChoice, col:'#00FFFF' }), + ], filly:1 }, + { type:'h', c:[ + Label('use Theme:', { id:'Theme', common:leftAligned, pad:4 }), + { width:10 }, + Drawable(drawColorChoice, { id:'Theme', common:ColorChoice, col:Theme.fg }), + ], filly:1, onTouch:chooseThemeColor }, + { height:4 }, + { type:'h', c:[ + Button('Ok', { common:legible, width:OkCancelWidth, onTouch:applyColor }), + { width:4 }, + Button('Cancel', { common:legible, width:OkCancelWidth, onTouch:withdrawColor }), + ], filly:1 }, + ], bgCol:'#FFFFFF' + }); + + + + readSettings(); + + Bangle.on('swipe', (Direction) => { + if (Direction === 0) { openMainScreen(); } + }); + + setTimeout(refreshClock, 500); // enqueue first draw request + + Bangle.on('lcdPower', (on) => { + if (on) { + if (Timer != null) { clearTimeout(Timer); Timer = undefined; } + refreshClock(); + } + }); + + Bangle.setUI('clock'); From 56a25fb3f6230e9559ef0065490c89da72045828 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:20 +0100 Subject: [PATCH 025/169] Create app-screenshot.png --- apps/configurable_clock/app-screenshot.png | Bin 0 -> 3218 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/app-screenshot.png diff --git a/apps/configurable_clock/app-screenshot.png b/apps/configurable_clock/app-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..5287217593fe6c4482120906e42c36c0d8860ee9 GIT binary patch literal 3218 zcmb7{*H;th7RA2=LP)4$=vr=t-aRyJ)QHgQ>-kExsW1A005WCRYRNKPWnge zY`RC4QOb2SC^=SP7-ltl1}V2o z^Ez&A^*)6D@0#H_F|`b}4_&cw@YB#xqArNJ2duAU8cp2q1I?DFO_g*nYrrV?b;WLS zVk2P|6N%fA2-?jvm`icjl!f);;SYEOra)k{$m)QEyL?C`MF;=UA-tXCyYth0sDI%) zm69p5jkvad*V#DX%5k`2hbC-Vcd889XG>EIPdB;3^1WSakq;~Dq%&&*$TZSY;c@vj%L&LY<_C_F6z#g;GrNdA59HmB=n}|0F zB4O0MuX)Q{5RAi}BJ$&^=kt3g(U_mX2}wfrOa1AON(9-XhiDGyp$P}$)jkfEsDzvd z(E;1<#h?qnAl77eTf%f5Mp@B<@CesF3!bA_w>mg}rpPyY@6PaHFzTN3HNHFkkXbDcdo&=0{Pdh}zy*3Ir$pQZC+i&FKMV#;8 z2$I#eW2Y%I;%Z5JJ-~DiiV00Luk9$`)2@Q*p}m4s1G=A^A%8qKf3Hca3s^7K-j zk8ZIL5V~gnTa%#rE)*1YeuNG~gP5%25K} z?bwXu1X%=D!tOc$|Cr!gNS(X@=SLJi*4F8L_csG~3RqmaYvY~rQ#ss2eKPT004R>n ze4qf4+OL}S=tK1&xl;<4I~(U1O%@p_{Ur>L`{Cl~>X+%?m`ddU6Gwmesy6oAO|DYG+!SHFh-lsXrEczZ56!?j?%{qyUW@ zsA;OP>LRzMa<=uOe(4uGYg0 z%E2SG41CP$q4aX@hrc#Oog`OB=UR4Kjl7!s$4?k96_iCkM;gt*W}>boFQ?Z6_*FXc zRU#CA)$El|ShC~dA6BJLhxy8f)z*;P(XU&|p?ck-?Xm1nMS2r)S%jg5cZi@~hea+= z7X4s}r%RiTrl;*>D=U?ZgjdoQK=4KNze<;`r#>8ikY^QlFc(vU>}HD6wFI-i$dpak zEuOd%v*Z2;GQP6P!>FcuhM;93eDYkVW5PL^)q{&OkRFqjj7f9WVtbgv7dxb)(XG3# zvt(Sh-F2GvpIv{o&ipdvHT6G@Rtj5ke!;8SMYf>|6{E+hkph+jgHw<#lM0auYOlD~G z9GdZ}XTD>nTj$Dv_WnJ~5TUY+pbA1+afP2>1QLE(G^f{=-~Jzpx#O5Xd=#KGlI9+JccpsX$Y`xo( znU$eav)!^dmh<^2cVPEL{*G~X;KpH)lJ(8FvWE%3G}BE6HY<>U{A6MW8XSe(@=jxL zS7=chB9u_%Po7x-ygXy=aIc;AFjrwG@hv73m$e%Ez2gzBn%0)+vx|t#XQeV zrslnj+#g!y)BM`V3g!pi4#;Joae*hP`4{xslU{=GNCH!n;#MvRnsI5}Px4XICi-P7 zv>M2!m@lYi4bbKUF_9$({cr+=R12rxz&f9Obfu~z^8oKZc10>!w%QJ^D~{j@-?tCY ze>{++@~xC2LA7IYOg6{Pi^DLPW%zC0wxrmA+R;cwjZbcJDh2mrwtov`yzI6^~gNi)oL2Abz1G2hd>Q+k-*0Rj3n&PANUi6y| z#17#;cTPN7=y)|`wz@0AI+(W5cJ5|+(N+;kA6rkZqVFuSKCw#pTGP8kZsH;dQ}V~* z6Cw`JD3#;=xFGPu5QJSVubxO6S6(@%phHNV;Mh=kW{^zQ(&nL1%jDO8=s7YC*xP_u zncyt_ri++U@TZMc$n>{K`LhE;tDW_SjiHc!{;=ckef zYB$OvNd4LtFNEnVN3Ey_#Egi_so6MXM5&PiU5&vIv&(eEb{f(gUFJhdZ|QW=2C^n9i)f;h-+s5Wf~c(4QhU?X{kg zQ|9I%_*vI$t@^132I$<6<|b4@qOEANb_+-}s#zrS9RL~5nLgeyQg8X_Arw1Im;x<% zks0-nZK*hykf$Jg@=aia0%$iWvUipOE~*W=)f^y*@2hP#f?)sPyVN?AlFJ$~=?SIT iO1v6u1OIaE7d%+S$$YPr_s8#&0Zfc63~TkV_x=x}ck>Yd literal 0 HcmV?d00001 From 9eaf501ce7b91ba1b171360bb775097d0cba9c4c Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:24 +0100 Subject: [PATCH 026/169] Create app-icon.png --- apps/configurable_clock/app-icon.png | Bin 0 -> 4369 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/app-icon.png diff --git a/apps/configurable_clock/app-icon.png b/apps/configurable_clock/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..58f50365d4ed18b6b1f5e006a3e2a4398452cbbb GIT binary patch literal 4369 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 D06kr; literal 0 HcmV?d00001 From a499ad279a3c95a54fbde1736f46399594907ed4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:27 +0100 Subject: [PATCH 027/169] Create app-icon.js --- apps/configurable_clock/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/configurable_clock/app-icon.js diff --git a/apps/configurable_clock/app-icon.js b/apps/configurable_clock/app-icon.js new file mode 100644 index 000000000..b0cf74241 --- /dev/null +++ b/apps/configurable_clock/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgZC/AB1RgkQsAQMyUKAYMIkAPJgNFiEBgACBg0YCRMogEJkGSAwMSEZNAAQMAEAMGgBKHgXAlECwMgzcAmkAhgRGilRssUgMEEYcBwARFiBHBgQKB7AjCawIQEgoCCigDBjEBwwEBEwIAGlmSEYYABI4PAEYhEBNYIjCAYVtwCSElG2xdoAwQjDhpZEEAMUqAHDCIaPBEYlAiwjItkAgYjFqJHDCIdhI4j1CAAhlEZoTUEAAcGEYZKEEYWgCIgjEWYkBoqwCCITLBgcMmPXhgjCgUB2iFDm3pw0YLAMygEgc4QjF49cmA3BbQQjDgGkI5OwNZZ9FEYoRLEYxmBCI5jBEYQACyQRHgmAEYsEEZEka4kAhEEEY8BCIMJCIYjKgGChAFDCwKzDNYyKEJgUDlgRBAoPDRQQjEZQZzEjScIhgjBEwQjEH4aXEgIjBjYCBjQCBMYYADmAjDFIjcGKocAjBKCgJRCAAwaCEARQBmARIhBrEgSMEAApEBmHAAQJrCABUCjFhwwQMI4oA7")) \ No newline at end of file From db5cb644fd36460d61d76ce9014bd5a6a542c118 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:32 +0100 Subject: [PATCH 028/169] Create LICENSE --- apps/configurable_clock/LICENSE | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 apps/configurable_clock/LICENSE diff --git a/apps/configurable_clock/LICENSE b/apps/configurable_clock/LICENSE new file mode 100644 index 000000000..7487dd5da --- /dev/null +++ b/apps/configurable_clock/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 Andreas Rozek + +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. From 54ee423106d32237a7c8738d319458c3888c9730 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:34 +0100 Subject: [PATCH 029/169] Create Screenshot-01.png --- apps/configurable_clock/Screenshot-01.png | Bin 0 -> 1621 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-01.png diff --git a/apps/configurable_clock/Screenshot-01.png b/apps/configurable_clock/Screenshot-01.png new file mode 100644 index 0000000000000000000000000000000000000000..b2367784c76e682019d944c899f572357ab0fded GIT binary patch literal 1621 zcmds2+f!3_5dNKn1PDh61|{ez7gLK=g^1M#L2e=enMn|^PJs|+6icN-0E4kf@B|Q| zLji?BsS1kIf^9+UfJu?dNzH(j78EO?f^Z1bl%`;Ua%ne1ATkR8*(EkAB1x1s_k5~g zY&VQPUa@#}20v{4DfSC_4fJ+Z_8I^89!R>LySlqAr(ea%z9e~q_q&7o3j+Yt zp~VS|n@osjIyu=LC>IxlLNK`99|-jNd=cuA$piR^MrQy!A9Vt(<@V4NbnLniLR0t+ z_lZA->j^;76Iy0}SvEof*;1*q3zPU?7F?-CFZGUQ2PyfKcDt_BjcS8G=^3GvjxV7; zrOHK`s5>;rcizbZH&0kL_q>V&OCM<0uIEZ=mmt`9%ba6vjDt#*-TkvUcpmCgzx$Di zbjc3R&8ki;>)navR85kZYE6`6 zD@NtJ80Ww~$#%8E4mJv@lk07Pa7h+MU1m$fHjIYb!luTPnV6SGH}rJzBy4!n9Wm~* z1LM!b+B7*dp$w3ly~!e7tM|N&j_1rfY9}k{cyVyi$|(j}gco{y%3tq`1D>#pF}+!v z0bI!TB4&~?5cMtE7vlPLrXN;)!>1mu?Lu&x%qP@!`|M`W0Ndz84H-{${L21|%q|CGoEFg@ep_^ z^-A$6)bcrK4n;(Mk+}(F$61Dj`b3fHj<8N_4Ka=VfCc46qwIGr3%iEoiqJ?g$;efO z9C$+$Xm*}<$~_rOe1(7@ zuhS7s)eSj2Qv@gC(JZl;V82Xev6_AV?egLqAWcWwsRcXdPv&Pg((?swwo^sdLLmu$ z1#2+bUdXvTh(*Cw@r(i6v~KsvI93nr`w)a=NN>K70V)Al&@2V}RK6%XV2EZH-e)i2)AmC*M zZ?+})e04!c0mb=r6(K&no}` literal 0 HcmV?d00001 From d89f1eef84e353336078f1a7243e90ec5ec38d2a Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:37 +0100 Subject: [PATCH 030/169] Create Screenshot-02.png --- apps/configurable_clock/Screenshot-02.png | Bin 0 -> 1959 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-02.png diff --git a/apps/configurable_clock/Screenshot-02.png b/apps/configurable_clock/Screenshot-02.png new file mode 100644 index 0000000000000000000000000000000000000000..909a2a04a3559d66b724b7c265ee61a68b4a17d2 GIT binary patch literal 1959 zcmb7FYc!kL8vcCq;iGXTg1A@2y{@H2qljxFh>mpH6iuVr6NYLSv&c~L9hWvmqpYS? zf_9G4o>Ro2bk)(%4AnC_X-S8=PTYz?C(1OYZYQ(W{5yYU_FC_L-}UV0+56qkpI2~< zPSMde(FOoOCyW{#t;&+$1J+RO%^h!NzIl3Kr=opIN*2|YgIg*K1;x8 zR4MZor#cx6Io&|uE(Slg`>1js%xnMDEv#ZhwUmbbSePa+L<1ZtWBw4^})>HZF{-jk3>ZS&v)HN7U5xr_|Q(5OKiB2EbF)S=;b?b%G|XaQ_2#u-ezpS7hR2Va{qJ*m{8rdeVc~R`vs1##2$rmopo93&t{Z4Wc)bQvlfPaqdzpMZTfktHDQGmT&rH|AhlZ7Sa(#Xw7@a zTsd2I$sg(8*L50)QyO{>lwd)tG`#s%vquR^oj5ar@d(uF3h&w(==RR9Sxv^+DRRSB zipTqYa3elIQyknEN4uZCR7oDA{}#foZn);A#GMZ!tdU@y)}^|knlV!kh0f&QT=kzvAo;?hOl{D6TlTgBCv*^{!cm${9bDd5e1C?K>>08RabG@=9Bf zKrKOUkSy2MZ9?UtrJjNg3qR_7rMs1+#U&%b>R!)x*v^ldS%D*qL6Ewwa*Y|CAZ9X;uEJ7gvWe8D9Xxz1}lULIAw zHnxuGo4lY`%3Ky>YH1>E^`?5$>RPDZjpt(o5h=|U;gARho3e{cyx;|=uM$cntR`fPr!ry_hhls+VRS7BO^5g zl+;?6i7Vtw)`vgD9u~ZvKwp$)o{`2lKAKh4d0=Wz2IQhB9LVr@1*RD3wIfhoX8D6G5OQ()WrQ- z8pp&(rWU68aH8zNamldgep^V^-rn?^)UUI?Z|5B0qu(Fcefmuoj>GdB*SSB5cW*-* zO{>Q5`5uz|YLs+X5Z>@frr#EgqzLl8U4EibZ}QYL2g5CXh%Pe@N>&=UR(YC%#o71c4 zud%mD7$jfD2;8m%U{t}2p%E>D;)|l-TT}qC`^82qa3%T=OOz{xGgF z{xDDZC}S4ix7)AVSv#8NA$_+$oi)C0+2_>GJ;W*lQnbdt-0prpER4{^zv{F} zTuuwnPEvVSx8WQRE8G`NHC1_5->emreS5M6g?b3+K&o6Zvo)P8q)L_ r5PmQp*46`Iv)s5M8IJrXp4?Vb#?4qzK6hiPCNB^cLJw{VWdGxT>q%q& literal 0 HcmV?d00001 From 350458f9e0e53bf105234238d24e0c2a29c276b1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:39 +0100 Subject: [PATCH 031/169] Create Screenshot-03.png --- apps/configurable_clock/Screenshot-03.png | Bin 0 -> 2814 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-03.png diff --git a/apps/configurable_clock/Screenshot-03.png b/apps/configurable_clock/Screenshot-03.png new file mode 100644 index 0000000000000000000000000000000000000000..80407c84f0b4d317b0fca562ff3eaec1c396d188 GIT binary patch literal 2814 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 O1&${Owh!^-wEqH%A`7|z literal 0 HcmV?d00001 From ea0104878867a101755eedd82617e1be795ec44f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:42 +0100 Subject: [PATCH 032/169] Create Screenshot-04.png --- apps/configurable_clock/Screenshot-04.png | Bin 0 -> 3302 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-04.png diff --git a/apps/configurable_clock/Screenshot-04.png b/apps/configurable_clock/Screenshot-04.png new file mode 100644 index 0000000000000000000000000000000000000000..175476c81ba153ec1b69e9537484a232d1706259 GIT binary patch literal 3302 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 Date: Thu, 6 Jan 2022 06:33:46 +0100 Subject: [PATCH 033/169] Create Screenshot-11.png --- apps/configurable_clock/Screenshot-11.png | Bin 0 -> 1570 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-11.png diff --git a/apps/configurable_clock/Screenshot-11.png b/apps/configurable_clock/Screenshot-11.png new file mode 100644 index 0000000000000000000000000000000000000000..bca534613173b18345c9c900cb584f6e2bdee4fe GIT binary patch literal 1570 zcmeHH?N3v882#Or-mc{WRhTWdg2nNovDk_tSVKioUUZ1)bQ+*c9gt|CP=(8&aA^Tc z6p7PWGtgo(qBCk0U#PQ`%e=EjEGWc*Qs5Sy1ff#p)dFQK+4d*w(>^@UNltRkNuHBD z6$$atZp_6@0DxO;OjP1L-u!DmgXg!d;Z4dsK=Q=sP2ff=Zx8^QB{nK@H=1JW>DeWjm0m7#5m?#=0`J40z@x#PB+`v&RE&f1KUb=ZmCnuEn&fK%E| z1HlS~yN8fk=L(V>4xUdc9LEOwvGMQ?IC3@^$OebxDCQlM49ND*0Xqmu_yyo~x;876 zR(lk}wn?=QsZTc!Qh>%7ah!g>x-!Lj3G=LrA(>0qGigsKa=QTNVY~*e?kKz+50qRy3|KVm>0zbyXfEC4IjIUF9!v#I#=f!jGyB9;b*Yf z;M3m$m7@aUvJ3KIy?Tc$r++O=yI4q!FVN0Q?=GMYH_3tp98xzl+V|qcQN(U;j7;(n z;ga`A|9&-OluKEik%(ROK&gihU|NeOVTwlVC&bFBE;W>?_f>QKW}h#_xDPj5I4knK z@ycc>6Zye_kf%si9uc>nDND~#i&eB$babhZpgvdnK&Wsfp|S=@VEd_B)`)uD;7%;B zycA8xFH}(tA>>3D;pyjo3ZOzun`!AquX;IxUugCb(9y)lts;;I7u@6ZSBSXLkcD&g zm^X2~?(H=y8gI(l6-sC(tD1^t@(a3GPkZhJr249~Z@a~>JUn0xE=pcC(#=H+Mtcnv zjgc^KJDmHIN0P?LO3af@mX_9 z#4Wbn1{<5vi(FE}n`T>RGvkYlMVBUI<}b+)`{>oqobG&rB!XOF#%NCPw9AL>)?!4oozl1=^P>|xwS^nauuX7LU6%qZs%^74a!e3 z+A~ll@v{EfdUDUaVMdTX%^$B4`Z9DQC4tT_bMEM#1voQ~`~0zt_-Sb0xJ|r#M;8YR ztfT!~$Q>RT%NLt~#Ty}Gn*%B#G%+UYA8NQar*GqSbyygMY?cY64quzNgCTim-3m5X z;|dGUv$AC_xXNlM2`sG^Qb@*v#*)A&9uKmohGmfqYrsi>rbqQ{97gn`*;pQIh;Vw= zXDtmVQ;1-)rZtzb0>~1+J}75`nvR#jku>1WJbWY`!sP3_{jUH#@|#NYav+OOf8g>t z2n)J)E1U*e2ajlKDS%$KHuN&U!!Ott?gnJ-%|~y&K-lHm$x0^RdHvp1LjeOv?`=zf mFx9V%t9OC_!~Q#fmxh?8^Mp2eDh?qi$?URsIQ;s<7Pv literal 0 HcmV?d00001 From 9cc680155ccea5bdf513c94e11e5174ac22586e3 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:48 +0100 Subject: [PATCH 034/169] Create Screenshot-12.png --- apps/configurable_clock/Screenshot-12.png | Bin 0 -> 1682 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-12.png diff --git a/apps/configurable_clock/Screenshot-12.png b/apps/configurable_clock/Screenshot-12.png new file mode 100644 index 0000000000000000000000000000000000000000..973b6da5e62b45e5d55918ed7878b65da00c10d4 GIT binary patch literal 1682 zcmd^A>r+#A5dGcUkOT-2u$4CngD+YMiP9+wrXkRYhy_F|s5EMQq!2O$`UF=ur!Uj?`LeRsCsShi!8auRV?)WaDsv&b3tt7C<)sZqYe43V;sJdN>nYsM z{?Ao1ym-FAAiOwV$PP!9cS6WUKS?d(O;80Nkb2XbVgG@YAg2FeWLUoF%bWED_lg3~ zJ`DBO2O!?8faQswBduKY6J8Jeu~fv{-hEv&b_MaKAK&nNApr{YNRDnWKezC)+Qtvv zaGvTF=PwQtk^fzH1a2p2uq}69_++zIe*=VyS?X>m&m1pR;K?5{DN(jA`V?B38$&(i z80Fxi@0CK+cEitdpzI5sGw+UVCYTe1loz37lct?kb=Czd$_$AoGSQ@?RwwM#AgSG2 zzaWKlC64MwM_9|CO5Hhg*PIad+;b}C_5E~M#S~e{+|ULDmV|nc#$?+ddxG5wMh%rt zG_z3(m1Hx@=101*wo6#@*UPdTR7;Yk8RTI4ADByX=0F|IxUAR;;Za5 zkdTy6J?Qx(GIM$Cvc168>daBHvsmN?Z2^A-8Hr_C&iDivZzPHrlu<|?2FZD*TQ5IANP6s z5d>nTmX{6<;tn9M*VHI|_-wKXpx;N*PV(N33EGjF?7b6a#qm?TzDYr)oIOc?-#@c> zvg%dcN~~ Date: Thu, 6 Jan 2022 06:33:50 +0100 Subject: [PATCH 035/169] Create Screenshot-13.png --- apps/configurable_clock/Screenshot-13.png | Bin 0 -> 1739 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-13.png diff --git a/apps/configurable_clock/Screenshot-13.png b/apps/configurable_clock/Screenshot-13.png new file mode 100644 index 0000000000000000000000000000000000000000..b87d977124e6ce8a9c16202362d61aba3cd02c4b GIT binary patch literal 1739 zcmd^=`#)597{|{XU(C_cn5kUTRC8f->$MfTu2aL9Xo#*W*X^?8GVVt$Ii?h=8)e#J zD8#lC)5V%iypC-ODWp}3I7C)0Gl(RYo!$Lu|AGBwe|VnH`}O(Zd4735uP4(-z|+++ z)`1{Mm+!&#Rjcf;B5SF8W%WRyT1aueyp2#ri|H@~X&vKpIor^{kym|*#txskg`f+^ z1qSQhQ>}xOEn6E0Uh|%Z$3-ZfRs8fr*vpCG_?fSgSIW$>FEE3V{F{}4>~*vhp`gQ4 z782Za*F^{uM-}!XkFfv9oF(wVLW?`DV_%CP47r=}qs=vjie@Y5OUP&0V$W|(@=Jjl z#4Obn^c#h7Kmtrdb^QVqlaozIcf-5#+q7xjWa^62eX}Wu7a_OO%mpkV$LcjxUta&v zP+vTJf`K959Zd>T@`K^Brg()rV5#(bN^9AehWX=ql83e%*%b07pc2t4pqIuLLhT%V zSi3&go*X`8h>38-6ja4!;~WC$rN8{rozNo~qiI!s=kVo4NH^(VnK|a*N|S3m6KsW( z(pfQVSyK$01ha(yhG@vEU$>2AwNj-e13ge=I~9(GJc)lScNwFHY@KX`*}+VeyRfO5 zd{^HbvrG33bSFqf46`)x?Q^&W9dU$g!YnXtS1Jkxw)?`1(-~uQynYav0S|(cCTd0; z$!Bm8q%EeQ6gs9&(z9l(=y-E1mF?Os*HjOz334aE36pBNdJ7OhVwomJqZ_Zzp+|LQ z;3h>*{-N0(@QYt`F$b(Ri)N4P9ohg!!IZV2pL?PHI@uH~&D6KwXkoXB;7Wkts8M$o z&hdF-m|0vB8w*C;;2hg-Ip6CpJFLJN#-n^MKZ*mxrBo%WXVAk}9f zux8F~;?9Lj4LykC>5=XIN`H!r^_%YVjUoZzn77b1oT%e+xI8Aet041+76r}j?dnj1 zIxEKbE)BBd0~>}afmP@D2+d`U|LjgdO{(8qYdBnIg%uVwmPCctnd$WIG#-(0^YI;+ z(yi`s12^??0UpDy$!V3`ar5qL=n}r!2PZX&_03WuW~1hQ?=dQ@d}t;h_yvt;q|C9> z_r0kmr|@H%btkDx?%c@4T8vH3kC}1K>!4OmP9iIADe{1%EyD=r*$nKj`vA7x^QWSQ zeXY9lb92X)L6Y^w7f&y!@9hfi9bK?xR*?Oyvu);3KhGs%4a~lLBw^L)81InhZ%*MJ zzjoH@Vl`)-f`ldb*^hE&GBx8>^-3XiTnFy`el~n+e%)DQ7K0bAerf;$ioAWeW^jH? z>cB+4z2r}kXO=H7w^Wt2Hh`#4FTA95RauJ~-@ee3GKBHYf%~L%VOQ(^(Dj&0m>T_B z6N9&7E+K!r)tMcGC-Wav-ze_i#R-NN=&Df;?>?_xokTylmCI5USuPbHc}O118X1|` zo&rXI*=)erFuYT8#HLFB0xkll0t5tU{<<=&9PMyc#dumXRj&T2_oi*r4v0&E8SX`p zP`;-+AUU{(DkqPMQU;0@OO@yKQWfpZNPe57%c=cc*IRDUOk? Date: Thu, 6 Jan 2022 06:33:53 +0100 Subject: [PATCH 036/169] Create Screenshot-21.png --- apps/configurable_clock/Screenshot-21.png | Bin 0 -> 2678 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-21.png diff --git a/apps/configurable_clock/Screenshot-21.png b/apps/configurable_clock/Screenshot-21.png new file mode 100644 index 0000000000000000000000000000000000000000..46d799e6d2aa1296d73600ee22a335ac60756964 GIT binary patch literal 2678 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 Nm>F9c(G73J{Tl;|?qmP} literal 0 HcmV?d00001 From b28719da164d9ccb2fce2e6ccb72f2b6caba1e40 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:33:55 +0100 Subject: [PATCH 037/169] Create Screenshot-22.png --- apps/configurable_clock/Screenshot-22.png | Bin 0 -> 3508 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-22.png diff --git a/apps/configurable_clock/Screenshot-22.png b/apps/configurable_clock/Screenshot-22.png new file mode 100644 index 0000000000000000000000000000000000000000..7ee02568ea7332cdcc302903eb0e8b2e54b84ed1 GIT binary patch literal 3508 zcmV;l4NLNgP)Px?Zb?KzRCr$Po!ge}rVd0;|NlpKhLbpl5KxtbFxb?7+z26+rnz|8?w{Y^-{1e~ zpA>kh0zbO|{PXkEmGHjCS~jz{z{mW&>Qp!{*?DlJR-hWCw^p z1F&Z=ZJqv^8O<82_U#3@w|pY7th2*tzP%Mf09VTuD@bHt+yemZyUXIW?u4M25qO^E zI4cM1BCGTD>_=DFesTu(LTL%l%*fIHy``9e-UAw11w0qV3P??TSO1WK#AWxu$WOFL z(SEIi6Pm5ry{fe(Kzd~X$mEhWmH;+R)~FCq0*v<7(O5h)dhZ9L7DPxp0o>Um&)x&~ z4lUl9ubxp+!Jk+~Pz(q<6eH@N-M;-En1vMy>zTbQTQp0K+=X~5hY^TSj3d4yeYXO* zK9ToeK~N(<)=bJA+B^_@3Xc3Tu`&B-_Qw!(7#^L?Bf$P=f>?csV+6l}L&b*jU?+9#q-+_Hst!d!f&^ zU%rLNPDuXFQa}KoRqxMbD}X;&(z6m0z-QI_bJ+^u&z1D7gaq(e_5NJ80{C+!Ju4vr zd{(_bm#qN)TuIMLNC2Nz@6Tl`fInB#vl0@(XVv?2*_r@*o}vAmGD_$b3N!(}!A0LX z*x_+HR%PZ<%gfiBa$h!j;{{i?aaCG(=>HCym0{AJV zpB+a4KdZM!OIF}dfHP)LuMe~*Mek#kIxs7TcLrwO5GiBu9C$sp$@Tu6yX62|ptipE z)q5=nLF@&%SLv3Yp6^lH&(Ss^q3gT;Y43G8e2vl(U`y5?>K;a zg+w!WYr9as8O-z-!1`=0R-G-%-Gah2j-{rOuu<$J;&3Qx6x|g5G1I5CBV_y z`WytuGJOTW7Jv-AUVxE(J!ZyzU^M1fnZMh6*-yy`JnKh*$e{;~XWbQGZoPSaU9;|P zXn*Xx*p>n83scropsm0$k5dYOZz^!i1MS}|pR&>`MPlI93h1TISC>!03t%zuY6S%F ztIMb01+W-+wE_b8)#X$00$2>ZS^)w4>hdXg0W1byt$+Z2b@>#$eu)zUuU26Bvk;!g z5Lu;XJgzt+PBx#Yo%az^WWS>ZOP@ybJP6Jf5fy>;Q`*glGZKflk4K9VPWEFnS3I6E zyzw*k%bo{DiKF&ba*;krB;*sdBmXno+1Tot)%*1$cAOcxE&~`P6A>lSXEcr(W1^VY zb|$vcCc4rvZJ zbK&6oGYc8{GqLq-wg9-bY-YnYB6Q{~*D6F5N|Y07uVa~QKLYC30FMgUnw=0RUNIwk z(_UWI3V|Ss!p`K2#`dgC%y=0#Tg<>&u%QB=_K2XYPj(hZ{&oNu#Td~s+D8CKmHWFN zQ%qzNh0^1fNfY_Id@wf5SXnl&0hkdE+0^aGo)MYxfo$FaFv^3`E8Aw-ePAR;1hyGI zk>F@dX4ZNGz)YSZe86Xj`VE>=lwmtbwaNFMt$A|Wa6}nXZgAMF@JNzx)6I~Teb1Tgusk4fc%=8 zt_GM1e#Q(i!zYuAY;qM?`Z#57D)M%s0?Qw0KT&k$oTq?ZDazAQo)##empT`St|9Xj z5Wsm_%F_Y`1n>gUHDsOw0ys}gd0L==0A3)vhRjny0Ox5bPYV{W&xlcgksqWPY9B6I0{YDam=eMcc4g=mhe5H%9+U%Lmf-)zvcJ-KeS(r#L>$SX~hB*-6mv>Pse$^ zQgjU(U2@98dVE-k)@?`>Yvy3vYQb7#vPETPvdG2B6cuU3__%DMexm)@xc*b8zgE!x zS0&M&=wH*h<3d1*Mj=4(XZf{&_iA?e@?8AvHXsT`6kt@-k$Ac*js-AU`dUR~3xSf& z0?h(?b_@)dCwprl*vjx)(++V(1 zu%iMn-*)K1&m26__*pQqepovcceLI7Hk!5&|Nr2#r%)bSR5-6MuYGrECcZk9H5Ssq z-1F-Y=bM3_-WGTv@!CfL&KhR~-aikUJKjdCPr*nmYhU}+A+Ej~!yMq4;-TEFy?8Gs z<{V&+>y3%YGivh+fYEK8834D6#1_?4U}THhp9a_)PZUhH-?E>Qkq{O@)?vq*aeFhn z=kU}!7nCzD$}Rg4XT@~K)w{@B|Ig@)0AsdV$OqHD3}7ZW*+>DTz|oIWB5~BdzXC@; z(7u0p6d_VTuM{DL)V{R>dZ}~k@+df@fB;4cseNk&1n}17QE*5B0gMz<`_>8w;H}G} z;E)0W7%8OotrZZ!TbD<{Aq505Qb_GvDTIC3ScB!uRSsY_YRJ&RUu*< z_0xMLss^C^{scPYMs!7eW&!E-yCuL^5;XuNM6EW@cEq|6>ajhxSKm?l-n(n4uoiF# z##TG(gW`FreJg-V07{T7c<(+ez^E`DfY`!E#=HT@$jdYS>b<-d{Otg)Aubc@71OhY zK*cP_L$`$N4a}Jn`OTxz%7W;Ct%rPdkTYWX9CRT!_1gjdCY=v#IFE0 z)XOTo#}BgYg{wXA$Yl`dYc2cbp7+!(gl1q4s_kar)`9KGL)fYGh8-pM@k z5Vy-+2m$R z*W-=;f@b++_V%*?wr)?BD;pDIq(-y)91HL)LFM;Z1(pGP&j_BSza>p%_I*}jjW$z( zo!28Rj2zOOL0Pk8E#YHI~fGL?| zw5tLFc-P7(E=mCbOvxmpT@?_(yH-YVQ3?oPN+ucYs(=9AwK9r}Qa}JxGRbIH1>6Al zo>tm5!C7%-{|YEw|EiQ%R|;VCM#L;gcJ`a0NrsP|HHyUM)x-o?56f^R@ap8X=c4$Y z6{AxZU_GYj2ZGUzvGI@m?H=X}z`vbMhlKV+!Dz!OPISzy=cH$>x;}O2I zXHVDW7GgEP)`|RHFua@nr^=QEFr&d!Ic1I0%89+}@EU-b+e!7OMOhKD3Ss%l0GQR_ ziF`80cm&{;vu~YX3Fez-q?U%Pt{x3`x^O+9M_13LuJs{~71|RpYl{-=LA+Zbvj9e~ z`0ti?R-Jo(jsX~52&~XiyC(rg+l|(lp_iBSQSrJ@maXR^JOW^A3628k?KczPIu-=* zWnZ5etb8KCvoYM`Mkkoh1H1#gSCO6s*jjEgX4?A#Xu;R=Z=G94?;w2|;9cO|1>idl z1Q`Mo?ZZp|$W{RV{7|d8XJ17*bQ(Q912apw2Q*|`wxjJps~z<@?hxk@+{t3d{7Hbl z@YY*`$PC;A7>T7Bn3#cA&%RG?A<(wTbKB8lD}XzfDq33D*=9AwGiP8AXtQiRTZmSv zQJs(5LbPrZt%UgN0DCTsV*&QuzUke&Tm^9!z#a`+ds`1^*6POoq>p0w{2ti4^-~|z zddm>n7ovkkM*9fB9t~LAIw$6K7qeaS{OEynWhR^L?*pR~ae0MX`>5z13yI9Oj{=Oq z^!$w5ikSg8I|lS?U>d-^Q#4z=)9qUDmKP>dsM9sDAx0(g$jE`YU-h!ufZxfq++=-=&SP6~P}Ij`^xoQzFgMBnff0=PVd>fnL* zz2zMegw1`IM7oaas!vNH+B)qSx9T!{1jFC9n^zMG;4)k02KTn=BnFl}drH^8isRMQ i4R9g@awP?Z75D>?eJSBek!TA50000 Date: Thu, 6 Jan 2022 06:33:57 +0100 Subject: [PATCH 038/169] Create Screenshot-23.png --- apps/configurable_clock/Screenshot-23.png | Bin 0 -> 3506 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-23.png diff --git a/apps/configurable_clock/Screenshot-23.png b/apps/configurable_clock/Screenshot-23.png new file mode 100644 index 0000000000000000000000000000000000000000..f3248993bafcf568d1bcc3b4b62b227fe33a8a3a GIT binary patch literal 3506 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

EGBAq8Mt^3+q)og)k|F}jMX IxQI>oKk(JLumAu6 literal 0 HcmV?d00001 From 59eb274eeb734c9178e3fea29b4aa606ed599be4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:34:00 +0100 Subject: [PATCH 039/169] Create Screenshot-24.png --- apps/configurable_clock/Screenshot-24.png | Bin 0 -> 3040 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-24.png diff --git a/apps/configurable_clock/Screenshot-24.png b/apps/configurable_clock/Screenshot-24.png new file mode 100644 index 0000000000000000000000000000000000000000..8a7753bfc5dd89b2dbb0ee9b034900f5b3151889 GIT binary patch literal 3040 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 literal 0 HcmV?d00001 From 01d6e37f185ea9de7c22c50eb2250294c01daa04 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:34:02 +0100 Subject: [PATCH 040/169] Create Screenshot-25.png --- apps/configurable_clock/Screenshot-25.png | Bin 0 -> 2775 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/configurable_clock/Screenshot-25.png diff --git a/apps/configurable_clock/Screenshot-25.png b/apps/configurable_clock/Screenshot-25.png new file mode 100644 index 0000000000000000000000000000000000000000..c2950d7b2ab4e1a58829bc51f2d0f739f4012f5a GIT binary patch literal 2775 zcmV;|3Mlo7P)Pxw!e}8}R z9|TTH;D*2_%^cHy5I|r=I5mOc0^e@8DzK%SS;t(h!%_G+#+AnVB&I_J-b>Dslsnw3 z3as)$;1_{m0&kPEt^%#Aj+5Y7VjVu23i_!<;VlA}5>S&kldM^!bmkEW7QG&w>*(>( z`0sjsdVyFT(pYl;Lbz3!ZEZ+vB(?eWSnBcz^2;Pu5S;@sm)i@r#B zW$bMq9wkDJ-+P)w0&nM_UdM7=ZG3ecC2qZriI}x|eR_eNO1qZ&u}8SGmhasy-suG16VnmxXl(6?5slkgVD)^Fz|lCRiurDNA1;h~CoWrI z9Izu}uP*Qm@*?o2tVAtGtqM8EeL@AEMP3Bn5m;TAxr-45c8TrBPt!s;`@kb&qblRf zK}lKEVmaqi``wo3RIaf{3<9sHMhR86`XcdbNsP{oz-4l85jfgvineLgP4uWYRkw|t z#o_kaw!0=u3*qpIVoQ7Fwf*xWJbF}DWz1m$EBmrbGMs9p_Nwli9+CXpn@o*Y-^{2b zujO?(?4q0~vh|1=DsUw6UbTp}t<&e!P-VWcuMh-wi9LR$vfl%d7Q#yi0(-pv|I8`^ z>)4))xPHXwf%RNGBB{V0Fa-8^$1@ z9=!T(x2E5+r2>0-l%uJ@GAb&tfr<+JohzeM;EZLzkKyB#2O08V9v2{=g>Z@SR1zC4*cG@91e?YFXs^H{Qo^LX8(>480F^uQi3DViQw!bA`3 zVfr0?M6&3-N5-ZCM|A(@k!>`OSs0DLA);Ra>_T|F*oDaQVizJoj$MdD(Ab4IfR9}W zA09oh$L!L(5FRQoI{O~_tX~snUS9r7(M>;%c6>UF00EBx0(-oOo{RtjPnHm-;}Jk$ zj~CIC5kTO{62f#m0toE!B6>0c2s~Lrn2tvPfjwSCPeuTNCrb#^@dzNW$Ln*W@83io z{a=G0tV7_@Nt^Y22s~?Mn3qHVfh9}?%}QV`aDzvC^)efuhZbU1p+?WEu~-N^I)PU| z9|F&9fcn|n`)7`q*zD(z=O$5^9Ri;#ZF`a;aG&3Jei+jDM!9ScjKG_M(^xEe;LZgd zff4wRV$q{_`+C%uZhO#Le5O}b1g_mfrSmCsbFcUL#4W!=ww^=8U8)6C;1}$gP;1Z; z^qTB7sa=T`f%imJ1d6U9;!&GpG_EA+3cTj)%C00ZEAYB1DmxZ?lJ1G+PIw_2;? zMiMQr9~mzaQQfhK#!=@Ov6PrlfnS)SMc2~Tsc~EBN(pg$MO6;9f8M*6?e(hvepHy9 zZ%Vk=yel#SOZPcJvl2kySu?}DBmxL5VIpW&0th^7W|)^m0D&b;1kFkSfoIJO^O6Yg zyATp4f@URvz_VtCc}WBiSi(dQ1ey|P{#J6+*)bRd0s;t(BBv&Rz^6_hlSg12I5hzT zK6Uz-JObmusR_t;KN!uf52o6B z>L|>V81Jl~AHBy6fg9#ukyD9jIHivm$`%;N`MmGK=BbtjTjN@+!0#4V`8681*-w)* z4{Rl{!oZx`+rvxOq_(N25m?!#TmRPXJu51N5gBYDu*zV>^|U<45P{!WeYY1_`a>!u zpfd@4pI?cg%GF^o+jXn5XP=%$uHPF9Drj}GPF!?hwaPSGB3lU@{W-7Mu3OD@l;_$w zmk~G%NKHT#H&WoJ-B5oCwA6|@eRww3xd|^J@ZKXh60gRM!5#cTOM;7zu+yAto-nHX7t_nsQgnqfq2sbV`f z>Bm;!Z4wiHcho!D9hM&Om8(c@?j*1IL{*+Mv?^@?>`h*F+tAuha#>m_BcaW5-yv?a3! zQ`?VxS0!#$fgJ|U8xii)ExV1jtOvG>ypOHG+Y7F>340&riTc8*Piyh|5rG{BYOK2p zQQDR)adFnyS_1%L|vU>t#2;2KHE>DA@DJM5cn9s+R-(xQ+^|(4}vkHB5)thmcUfuToU%= zrH#ljja=kg$$74Sjzr*wFjqtEKGjM+@OC$Vg~xtkmR%2(lN;Yhi}^=YIPud`$vn2$ zs%tSua{ALA<}#54USI9r9__SLI!sKhw(6 Date: Thu, 6 Jan 2022 06:34:05 +0100 Subject: [PATCH 041/169] Create BangleApps__apps__variable_clock__README.md --- ...angleApps__apps__variable_clock__README.md | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 apps/configurable_clock/BangleApps__apps__variable_clock__README.md diff --git a/apps/configurable_clock/BangleApps__apps__variable_clock__README.md b/apps/configurable_clock/BangleApps__apps__variable_clock__README.md new file mode 100644 index 000000000..da5bed56d --- /dev/null +++ b/apps/configurable_clock/BangleApps__apps__variable_clock__README.md @@ -0,0 +1,27 @@ +# Variable Analog Clock # + +This app implements an analog clock with various faces, hands and colors to +choose from. + +You have the choice between: + +* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Just swipe up or down to switch from clock display to configuration screen + +![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) +![](Screenshot_24.png) ![](Screenshot_25.png) + +Chosen settings will be written to the Bangle.js's flash memory and restored +whenever the clock is started again. + +This clock also acts as an example for the building blocks found in the author's +[GitHub repository](https://github.com/rozek/banglejs-2-activities) + +## License ## + +[MIT License](LICENSE) From 4ffee250d7c9eb258fc8651e86704e456387869b Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:36:08 +0100 Subject: [PATCH 042/169] Create README.md --- apps/configurable_clock/README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 apps/configurable_clock/README.md diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md new file mode 100644 index 000000000..fd7527d0b --- /dev/null +++ b/apps/configurable_clock/README.md @@ -0,0 +1,27 @@ +# Configurable Analog Clock # + +This app implements an analog clock with various faces, hands and colors to +choose from. + +You have the choice between: + +* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Just swipe up or down to switch from clock display to configuration screen + +![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) +![](Screenshot_24.png) ![](Screenshot_25.png) + +Chosen settings will be written to the Bangle.js's flash memory and restored +whenever the clock is started again. + +This clock also acts as an example for the building blocks found in the author's +[GitHub repository](https://github.com/rozek/banglejs-2-activities) + +## License ## + +[MIT License](LICENSE) From f495cddef5d30ad826f761ddf392ceb0e2c6c4a4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:49:46 +0100 Subject: [PATCH 043/169] Update app.js --- apps/configurable_clock/app.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/apps/configurable_clock/app.js b/apps/configurable_clock/app.js index 19dc363e4..5ed52b33b 100644 --- a/apps/configurable_clock/app.js +++ b/apps/configurable_clock/app.js @@ -1147,16 +1147,22 @@ Label('Settings', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Label('Faces', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openFacesScreen }, { type:'h', c:[ + { width:4 }, Label('Hands', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openHandsScreen }, { type:'h', c:[ + { width:4 }, Label('Colors', { common:leftAligned, fillx:1 }), Image(Caret, { common:leftAligned }), + { width:4 }, ], filly:1, onTouch:openColorsScreen }, { height:4 }, { type:'h', c:[ @@ -1175,14 +1181,17 @@ Label('Clock Faces', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'none', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' no Face', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'3,6,9,12', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' 3, 6, 9 and 12', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'1-12', GroupName:'Faces', common:legible, onChange:chooseFace }), Label(' numbers 1...12', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, @@ -1208,18 +1217,22 @@ Label('Clock Hands', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'simple', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' simple', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'rounded', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' rounded + Bolt', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Radiobutton({ id:'hollow', GroupName:'Faces', common:legible, onChange:chooseHand }), Label(' hollow + Bolt', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:checkInnerRadiobutton }, { type:'h', c:[ + { width:4 }, Checkbox({ id:'withSeconds', common:legible, onChange:toggleSeconds }), Label(' show Seconds', { common:leftAligned, pad:4, fillx:1 }), ], filly:1, onTouch:toggleInnerCheckbox }, @@ -1240,16 +1253,22 @@ Label('Clock Colors', { common:legible, bold:true, filly:1 }), { height:4 }, { type:'h', c:[ + { width:4 }, Label('Foreground', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Foreground', common:ColorView, bgCol:Theme.fg }), + { width:4 }, ], filly:1, onTouch:selectForegroundColor }, { type:'h', c:[ + { width:4 }, Label('Background', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Background', common:ColorView, bgCol:Theme.bg }), + { width:4 }, ], filly:1, onTouch:selectBackgroundColor }, { type:'h', c:[ + { width:4 }, Label('Seconds', { common:leftAligned, pad:4, fillx:1 }), Label('', { id:'Seconds', common:ColorView, bgCol:Theme.fgH }), + { width:4 }, ], filly:1, onTouch:selectSecondsColor }, { height:4 }, { type:'h', c:[ From 8338c671c2d3e1572fb6192e617588eaf04019a6 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 06:53:26 +0100 Subject: [PATCH 044/169] Update apps.json --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index ebafa9c97..6021608e2 100644 --- a/apps.json +++ b/apps.json @@ -5427,5 +5427,22 @@ {"name":"puzzle15.img","url":"puzzle15.app-icon.js","evaluate":true} ], "data": [{"name":"puzzle15.json"}] + }, + { "id": "configurable_clock", + "name": "Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.01", + "description": "an analog clock with several kinds of faces, hands and colors to choose from", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"configurable_clock.app.js","url":"app.js"}, + {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} + ] } ] From 4d4071e1514c29db60f6506f48335d4333f133b1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 07:05:49 +0100 Subject: [PATCH 045/169] Update README.md --- apps/configurable_clock/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md index fd7527d0b..e1c2bb574 100644 --- a/apps/configurable_clock/README.md +++ b/apps/configurable_clock/README.md @@ -5,16 +5,16 @@ choose from. You have the choice between: -* 4 different clock faces ![](Screenshot_01.png) ![](Screenshot_02.png) ![](Screenshot_03.png) ![](Screenshot_04.png) and -* 3 different clock hands (optionally with or without second hands) ![](Screenshot_11.png) ![](Screenshot_12.png) ![](Screenshot_13.png) +* 4 different clock faces ![](Screenshot-01.png) ![](Screenshot-02.png) ![](Screenshot-03.png) ![](Screenshot-04.png) and +* 3 different clock hands (optionally with or without second hands) ![](Screenshot-11.png) ![](Screenshot-12.png) ![](Screenshot-13.png) Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. Just swipe up or down to switch from clock display to configuration screen -![](Screenshot_21.png) ![](Screenshot_22.png) ![](Screenshot_23.png) -![](Screenshot_24.png) ![](Screenshot_25.png) +![](Screenshot-21.png) ![](Screenshot-22.png) ![](Screenshot-23.png) +![](Screenshot-24.png) ![](Screenshot-25.png) Chosen settings will be written to the Bangle.js's flash memory and restored whenever the clock is started again. From 3571435499e824ff600b6a47f1cb22672a969bad Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 6 Jan 2022 07:19:43 +0100 Subject: [PATCH 046/169] Update README.md --- apps/configurable_clock/README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/apps/configurable_clock/README.md b/apps/configurable_clock/README.md index e1c2bb574..faddd092a 100644 --- a/apps/configurable_clock/README.md +++ b/apps/configurable_clock/README.md @@ -5,16 +5,18 @@ choose from. You have the choice between: -* 4 different clock faces ![](Screenshot-01.png) ![](Screenshot-02.png) ![](Screenshot-03.png) ![](Screenshot-04.png) and -* 3 different clock hands (optionally with or without second hands) ![](Screenshot-11.png) ![](Screenshot-12.png) ![](Screenshot-13.png) +* 4 different clock faces
![](Screenshot-01.png)   ![](Screenshot-02.png)   ![](Screenshot-03.png)   ![](Screenshot-04.png) and +* 3 different clock hands (optionally with or without second hands)
![](Screenshot-11.png)   ![](Screenshot-12.png)   ![](Screenshot-13.png) Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. -Just swipe up or down to switch from clock display to configuration screen +Just swipe up or down to switch from clock display to the first configuration +screen and continue from there -![](Screenshot-21.png) ![](Screenshot-22.png) ![](Screenshot-23.png) -![](Screenshot-24.png) ![](Screenshot-25.png) +![](Screenshot-21.png)   ![](Screenshot-22.png)   +![](Screenshot-23.png)   ![](Screenshot-24.png)   +![](Screenshot-25.png) Chosen settings will be written to the Bangle.js's flash memory and restored whenever the clock is started again. From 436aecbca3f6fc772c83205daa4ae9ce1baea7c0 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Fri, 7 Jan 2022 20:28:00 +0100 Subject: [PATCH 047/169] ISO8601 added in changelog and readme --- apps/ffcniftya/ChangeLog | 2 +- apps/ffcniftya/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ffcniftya/ChangeLog b/apps/ffcniftya/ChangeLog index bf70a213b..420c553f5 100644 --- a/apps/ffcniftya/ChangeLog +++ b/apps/ffcniftya/ChangeLog @@ -1,2 +1,2 @@ 0.01: New Clock Nifty A -0.02: Shows the current week number, can be disabled via settings "" +0.02: Shows the current week number (ISO8601), can be disabled via settings "" diff --git a/apps/ffcniftya/README.md b/apps/ffcniftya/README.md index 769cbcb74..66acd1421 100644 --- a/apps/ffcniftya/README.md +++ b/apps/ffcniftya/README.md @@ -8,7 +8,7 @@ Colors are black/white - photos have non correct camera color "blue" ![](photo_nifty.png) (*photo*) -## The week number can be turned of in settings +## The week number (ISO8601) can be turned of in settings (default is **"On"**) ![](screenshot_settings_nifty.png) (*emulated*) From b711b50f888ecfb96f5a5cf4e2340507a6087c87 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Mon, 10 Jan 2022 16:10:42 +0100 Subject: [PATCH 048/169] Initial version of BanglExercise --- apps.json | 19 ++- apps/banglexercise/ChangeLog | 1 + apps/banglexercise/README.md | 35 ++++ apps/banglexercise/app-icon.js | 1 + apps/banglexercise/app.js | 259 ++++++++++++++++++++++++++++++ apps/banglexercise/app.png | Bin 0 -> 690 bytes apps/banglexercise/screenshot.png | Bin 0 -> 2043 bytes 7 files changed, 314 insertions(+), 1 deletion(-) create mode 100644 apps/banglexercise/ChangeLog create mode 100644 apps/banglexercise/README.md create mode 100644 apps/banglexercise/app-icon.js create mode 100644 apps/banglexercise/app.js create mode 100644 apps/banglexercise/app.png create mode 100644 apps/banglexercise/screenshot.png diff --git a/apps.json b/apps.json index 389603249..0adb4abc5 100644 --- a/apps.json +++ b/apps.json @@ -5149,7 +5149,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", @@ -5503,5 +5503,22 @@ {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] + }, + { "id": "banglexercise", + "name": "BanglExercise", + "shortName":"BanglExercise", + "version":"0.01", + "description": "Can automatically track exercises while wearing the Bangle.js watch.", + "icon": "app.png", + "screenshots": [{"url":"screenshot.png"}], + "type": "app", + "tags": "sport", + "supports" : ["BANGLEJS2"], + "allow_emulator":true, + "readme": "README.md", + "storage": [ + {"name":"banglexercise.app.js","url":"app.js"}, + {"name":"banglexercise.img","url":"app-icon.js","evaluate":true} + ] } ] diff --git a/apps/banglexercise/ChangeLog b/apps/banglexercise/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/banglexercise/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md new file mode 100644 index 000000000..e7ac9573d --- /dev/null +++ b/apps/banglexercise/README.md @@ -0,0 +1,35 @@ +# Banglexercise + +Can automatically track exercises while wearing the Bangle.js watch. + +Currently only push ups are supported. + + +## Usage + +Select the exercise type you want to practive and go for it! +Press stop to end your exercise. + + +## Screenshots +![](screenshot.png) + +## TODO +* Add other exercise types: + * Rope jumps + * Curls + * Sit ups + * ... +* Save exercises to file system +* Add settings (vibration, beep, ...) +* Find a nicer icon + + +## Contribute +Feel free to send in improvements and remarks. + +## Creator +Marco ([myxor](https://github.com/myxor)) + +## Icons +Icons taken from [materialdesignicons](https://materialdesignicons.com) under Apache License 2.0 diff --git a/apps/banglexercise/app-icon.js b/apps/banglexercise/app-icon.js new file mode 100644 index 000000000..e1923bf54 --- /dev/null +++ b/apps/banglexercise/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwwIbYh/8AYM/+EP/wFBv4FB/4FB/4FHAwIEBAv4FPAgIGCAosHAofggYFD4EABgXgOgIFLDAQWBAo0BAoOAVIV/UYQABj/4AocDCwQFTg46CEY4vFAopBBApIAVA==")) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js new file mode 100644 index 000000000..feb3a1127 --- /dev/null +++ b/apps/banglexercise/app.js @@ -0,0 +1,259 @@ +const Layout = require("Layout"); + +let historyY = []; +let historyZ = []; +const avgSize = 10; + +const thresholdY = 2500; +const thresholdPushUpTime = 1400; // mininmal time between two push ups +let tStart; + +let avgY; +let avgZ; +let historyAvgY = []; +let historyAvgZ = []; +let historySlopeY = []; +let historySlopeZ = []; + +let lastZeroPassType; +let lastZeroPassTime = 0; +let lastPushUpCmpltTime = 0; + +let exerciseType = ""; +let pushUpCounter = 0; + +let layout; + +let recordActive = false; + + +function showMenu() { + let menu; + if (pushUpCounter == 0) { + menu = { + "": { + title: "Banglexercise" + }, + "Start push ups": function() { + exerciseType = "push ups"; + E.showMenu(); + startRecording(); + } + }; + } else { + menu = { + "": { + title: "Banglexercise" + }, + "Last:": { + value: pushUpCounter + " push ups" + }, + "Start push ups": function() { + exerciseType = "push ups"; + E.showMenu(); + startRecording(); + } + }; + } + E.showMenu(menu); +} + +function accelHandler(accel) { + const t = Math.round(new Date().getTime()); // time in ms + const y = accel.y * 8192; + const z = accel.z * 8192; + //console.log(t, y, z); + + while (historyY.length > avgSize) + historyY.shift(); + historyY.push(y); + + if (historyY.length > avgSize / 2) + avgY = E.sum(historyY) / historyY.length; + + while (historyZ.length > avgSize) + historyZ.shift(); + historyZ.push(z); + + if (historyZ.length > avgSize / 2) + avgZ = E.sum(historyZ) / historyZ.length; + + if (avgY) { + //console.log(avgY, avgZ); + historyAvgY.push([t, avgY]); + historyAvgZ.push([t, avgZ]); + } + + let mY; + let mZ; + // slope for Y + let l = historyAvgY.length; + if (l > 1) { + const p1 = historyAvgY[l - 2]; + const p2 = historyAvgY[l - 1]; + mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); + if (Math.abs(mY) >= thresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, mY]); + //console.log(t, Math.abs(mY)); + + const lMY = historySlopeY.length; + if (lMY > 1) { + const pMY1 = historySlopeY[lMY - 2][1]; + const pMY2 = historySlopeY[lMY - 1][1]; + isValidPushUp(pMY1, pMY2, t); + } + } + } + + // slope for Z + l = historyAvgZ.length; + if (l > 1) { + const p1 = historyAvgZ[l - 2]; + const p2 = historyAvgZ[l - 1]; + mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + historyAvgZ.shift(); + historySlopeZ.push([p2[0] - p1[0], mZ]); + } +} + +function isValidPushUp(p1, p2, t) { + if (p1 > 0 && p2 < 0) { + + if (lastZeroPassType == "-+") { + console.log(t, "Push up half complete..."); + + layout.progress.label = "..."; + layout.render(layout.progress); + } + + lastZeroPassType = "+-"; + lastZeroPassTime = t; + } + if (p2 > 0 && p1 < 0) { + + if (lastZeroPassType == "+-") { + // potential complete push up. Let's check the time difference... + const tDiffLastPushUp = t - lastPushUpCmpltTime; + const tDiffStart = t - tStart; + console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + + if ((lastPushUpCmpltTime <= 0 && tDiffStart >= thresholdPushUpTime) || tDiffLastPushUp >= thresholdPushUpTime) { + console.log(t, "Push up complete!!!"); + + lastPushUpCmpltTime = t; + pushUpCounter++; + + layout.count.label = pushUpCounter; + layout.render(layout.count); + layout.progress.label = ""; + layout.render(layout.progress); + + Bangle.buzz(100, 0.3); // TODO make configurable + } else { + console.log(t, "Push up to quick for threshold!"); + } + } + + lastZeroPassType = "-+"; + lastZeroPassTime = t; + } +} + +/* + +function calcPushUps() { + const l = historySlopeY.length; + for (let i = 1; i < l; i++) { + const p1 = historySlopeY[i - 1][1]; + const p2 = historySlopeY[i][1]; + const t = historySlopeY[i][0]; + isValidPushUp(p1, p2, t); + } +} +*/ + +function reset() { + historyY = []; + historyZ = []; + historyAvgY = []; + historyAvgZ = []; + historySlopeY = []; + historySlopeZ = []; + + lastZeroPassType = ""; + lastZeroPassTime = 0; + lastPushUpCmpltTime = 0; + pushUpCounter = 0; +} + + +function startRecording() { + if (recordActive) return; + g.clear(1); + reset(); + layout = new Layout({ + type: "v", + c: [{ + type: "txt", + id: "type", + font: "6x8:2", + label: exerciseType, + pad: 5 + }, + { + type: "txt", + id: "count", + font: "6x8:9", + label: pushUpCounter, + pad: 5, + bgCol: g.theme.bg + }, + { + type: "txt", + id: "progress", + font: "6x8:2", + label: "", + pad: 5 + }, + { + type: "txt", + id: "recording", + font: "6x8:2", + label: "RECORDING", + bgCol: "#f00", + pad: 5, + fillx: 1 + }, + ] + }, { + btns: [ + { + label: "STOP", + cb: () => { + stopRecording(); + } + } + ] + }); + layout.render(); + + Bangle.setPollInterval(80); // 12.5 Hz + Bangle.on('accel', accelHandler); + Bangle.buzz(200, 1); + tStart = new Date().getTime(); + recordActive = true; +} + +function stopRecording() { + if (!recordActive) return; + g.clear(1); + Bangle.removeListener('accel', accelHandler); + showMenu(); + console.log("Found " + pushUpCounter + " push ups!"); + recordActive = false; +} + +g.clear(1); +Bangle.drawWidgets(); +showMenu(); diff --git a/apps/banglexercise/app.png b/apps/banglexercise/app.png new file mode 100644 index 0000000000000000000000000000000000000000..ee733206310029c15e866e4fc6bef39305d70668 GIT binary patch literal 690 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTCmUKs7M+SzC{oH>NS%G|oWRD45dJguM!v-tY$DUh!@P+6=(yLU`z6LcLCBs@Y8vBJ&@uo z@Q5r1(g|SvA=~LZ0|Vn0PZ!6KjC*fqZuC0rAk)5ISX|cS=uz>4qEPnOCH@cIG_P3P zFGDWi zNGnrbNL|R7G5egyoLkxdBkfxbtgvmLFk!~jikVyTJQzLaunJ`CzH(+>eiw_(tM5ID zCxaKT>-gQeKjZ#PZ`Muf7F<@rVfw%ShRjWzrNDVa4Hc#BdJrKWAyK=c`uohKOXBRS z7i6&M&E|RIp%;De^8uL)tYJyZ&wgNABYF7x`R1LH8)UCF6mu=pVXB?2D!xxh=y%`w zvwFGbP5q~azSwr`;=Yw1ZzZe9Wl8+~?RF@-QMWVkzz65fv&UH090_!2JnVKjno+s% zjis=&wZJj^z|x7+T(&#?Q18sW|I6{rTaII}*{P}%1L#X5Imj9~9Jam|MPl%6IS=VU&;E=?<Hxi+V}Sty2#I1U-4_X;bU=*PM1S-^ErIH(Bc9_KZH+1;!FW?Xq@{?d#wat2 zqSPaenYJE9vqHzCE!82k>QzeX6>8#H&He5_^T(`p*S-JUv(`C#?X~wgd+)PNP;eAqEM1m z_SP0|asJCCgE3v@PMo1! z*f|v3#LSzFzS{I!!rV21lYAG;c$8rSY` zrtv;c`F-*otRXP}(DjxKjPZJTgeC>x=>7yoFGVWJH|o)xX+XB^NKHex&wPl`a~=~X za(P8aF({q6xR8)IKj56l)xcxv656}p+2QGn?xOha*4FfUv5E=1o8>8@ke5^X-Alra z{?c-FSdtCn#41uNW-umNx0VFrlWLa)#(@Ij$rUqQ#GSv%Zi@XPBg}gPCyKWp&p8}M z6HV+)2y3H)YaQ^Mom$c5vW71elfNdWFPDfG{GjOe_VwTz(o~)T+9W+c*{D*%tK9*e zoJ~|W+Yzo%+X)vnc0{$qEqCJk=RJ4*O9-72(B~Uzi@Es|RQEyjmgu4b^j7ydTi6Z= zTKjLeV4AP--+63`7du)}g~nr62CXHl@SB==)Cgk4oJWBwo1uoLt@$Jzoe zC8XG-fYql4>_h}+N$)&!8#8LB2x!D1B(J^4SIpD$WT!%~SBvItV#w}Bu^X$Pk*we;?6cI0@-D(Q=rGO_|R9q%_clHFEW>WP@3PJ2lX6b9WH_gJ#2oO{P>u;wA8BEkN?TPq z%^@Y+O-FLEsH-w~$0{or?;P%C_!V_W>sRIRoIl=dlz?e=`(Rq?PWbD0J3{ciJg-L; zxvZ9qEgR}wlM84&H3=%LDFm|q3jH11uV|iGtX+s^Gmi0ynq5i*$3#_ zg+J!w${3g@L`bGr#cC#`$MNK5&VPC>2@A?DFMX?x#pRoMyH9t@B^7G+?s{Oh_8X0G zdxIWdXd?sP7~p>UV*XhE!$E*z;+B&8<4Q^M4d>$>b`fhPoA)+AQJd17ewQEr$U-(Z zi?LMG(ytl$U}&R@dAxoWMG>q1h-<}t6VKQVm+sCMa7sP7#%G{990ok zZaza$U~;u;dV?Im+ikXvp0`kdvfQSWgVmHyrEgp=ZF(@0w^`k28dzQ*VFU;ceDdf(o`Cg>Bmg3o{v-Hn zd2^(E?-x3$-1VX;Tbvj|TjlUy#vZ*@U9b6V39?(t1J}IJ@v@K-((+>Q%!fY+P7m~> z)!xYJRn$*Dw4B`OQ+_C%Wykju9`})?N8H^aB$=bl;ZJN}EjlY>dhI#z)la1C1rXhwz1fgbiQh50C;I)_p2 z20-=scl5QzK*vM-t?q$nFKrt?G64N@O6e*^3d{M literal 0 HcmV?d00001 From bfe2725483e55f657f0592e519e60c077abe1897 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Mon, 10 Jan 2022 19:02:39 +0100 Subject: [PATCH 049/169] Show heart rate during training Alot of code cleanup and improvements --- apps/banglexercise/README.md | 2 +- apps/banglexercise/app.js | 269 +++++++++++++++++++---------------- 2 files changed, 151 insertions(+), 120 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index e7ac9573d..efc87424d 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -1,4 +1,4 @@ -# Banglexercise +# BanglExercise Can automatically track exercises while wearing the Bangle.js watch. diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index feb3a1127..e18faf554 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,15 +1,9 @@ const Layout = require("Layout"); +const heatshrink = require('heatshrink'); +let tStart; let historyY = []; let historyZ = []; -const avgSize = 10; - -const thresholdY = 2500; -const thresholdPushUpTime = 1400; // mininmal time between two push ups -let tStart; - -let avgY; -let avgZ; let historyAvgY = []; let historyAvgZ = []; let historySlopeY = []; @@ -17,103 +11,122 @@ let historySlopeZ = []; let lastZeroPassType; let lastZeroPassTime = 0; -let lastPushUpCmpltTime = 0; -let exerciseType = ""; -let pushUpCounter = 0; +let lastExerciseCmpltTime = 0; + +let exerciseType = { + "name": "" +}; +const exerciseTypes = [{ + "id": "pushup", + "name": "Push ups", + "useYaxe": true, + "useZaxe": false + } // add other exercises here +]; +let exerciseCounter = 0; let layout; - let recordActive = false; +/** + * Thresholds + */ +const avgSize = 6; +const pushUpThresholdY = 2500; +const pushUpThresholdTime = 1400; // mininmal time between two push ups -function showMenu() { +let hrtValue; + +function showMainMenu() { let menu; - if (pushUpCounter == 0) { - menu = { - "": { - title: "Banglexercise" - }, - "Start push ups": function() { - exerciseType = "push ups"; - E.showMenu(); - startRecording(); - } + menu = { + "": { + title: "BanglExercise" + } + }; + + exerciseTypes.forEach(function(et) { + menu["Do " + et.name] = function() { + exerciseType = et; + E.showMenu(); + startRecording(); }; - } else { - menu = { - "": { - title: "Banglexercise" - }, - "Last:": { - value: pushUpCounter + " push ups" - }, - "Start push ups": function() { - exerciseType = "push ups"; - E.showMenu(); - startRecording(); - } + }); + + if (exerciseCounter > 0) { + menu["----"] = {}; + menu["Last:"] = { + value: exerciseCounter + " " + exerciseType.name }; } + E.showMenu(menu); } function accelHandler(accel) { + if (!exerciseType) return; const t = Math.round(new Date().getTime()); // time in ms - const y = accel.y * 8192; - const z = accel.z * 8192; + const y = exerciseType.useYaxe ? accel.y * 8192 : 0; + const z = exerciseType.useZaxe ? accel.z * 8192 : 0; //console.log(t, y, z); - while (historyY.length > avgSize) - historyY.shift(); - historyY.push(y); + if (exerciseType.useYaxe) { + while (historyY.length > avgSize) + historyY.shift(); - if (historyY.length > avgSize / 2) - avgY = E.sum(historyY) / historyY.length; + historyY.push(y); - while (historyZ.length > avgSize) - historyZ.shift(); - historyZ.push(z); - - if (historyZ.length > avgSize / 2) - avgZ = E.sum(historyZ) / historyZ.length; - - if (avgY) { - //console.log(avgY, avgZ); - historyAvgY.push([t, avgY]); - historyAvgZ.push([t, avgZ]); + if (historyY.length > avgSize / 2) { + const avgY = E.sum(historyY) / historyY.length; + historyAvgY.push([t, avgY]); + } } - let mY; - let mZ; - // slope for Y - let l = historyAvgY.length; - if (l > 1) { - const p1 = historyAvgY[l - 2]; - const p2 = historyAvgY[l - 1]; - mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - if (Math.abs(mY) >= thresholdY) { - historyAvgY.shift(); - historySlopeY.push([t, mY]); - //console.log(t, Math.abs(mY)); + if (exerciseType.useYaxe) { + while (historyZ.length > avgSize) + historyZ.shift(); - const lMY = historySlopeY.length; - if (lMY > 1) { - const pMY1 = historySlopeY[lMY - 2][1]; - const pMY2 = historySlopeY[lMY - 1][1]; - isValidPushUp(pMY1, pMY2, t); + historyZ.push(z); + + if (historyZ.length > avgSize / 2) { + const avgZ = E.sum(historyZ) / historyZ.length; + historyAvgZ.push([t, avgZ]); + } + } + + // slope for Y + if (exerciseType.useYaxe) { + let l = historyAvgY.length; + if (l > 1) { + const p1 = historyAvgY[l - 2]; + const p2 = historyAvgY[l - 1]; + const mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); + if (Math.abs(mY) >= pushUpThresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, mY]); + //console.log(t, Math.abs(mY)); + + const lMY = historySlopeY.length; + if (lMY > 1) { + const pMY1 = historySlopeY[lMY - 2][1]; + const pMY2 = historySlopeY[lMY - 1][1]; + isValidPushUp(pMY1, pMY2, t); + } } } } // slope for Z - l = historyAvgZ.length; - if (l > 1) { - const p1 = historyAvgZ[l - 2]; - const p2 = historyAvgZ[l - 1]; - mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); - historyAvgZ.shift(); - historySlopeZ.push([p2[0] - p1[0], mZ]); + if (exerciseType.useZaxe) { + l = historyAvgZ.length; + if (l > 1) { + const p1 = historyAvgZ[l - 2]; + const p2 = historyAvgZ[l - 1]; + const mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + historyAvgZ.shift(); + historySlopeZ.push([p2[0] - p1[0], mZ]); + } } } @@ -123,8 +136,8 @@ function isValidPushUp(p1, p2, t) { if (lastZeroPassType == "-+") { console.log(t, "Push up half complete..."); - layout.progress.label = "..."; - layout.render(layout.progress); + layout.progress.label = "*"; + layout.render(); } lastZeroPassType = "+-"; @@ -134,20 +147,19 @@ function isValidPushUp(p1, p2, t) { if (lastZeroPassType == "+-") { // potential complete push up. Let's check the time difference... - const tDiffLastPushUp = t - lastPushUpCmpltTime; + const tDiffLastPushUp = t - lastExerciseCmpltTime; const tDiffStart = t - tStart; console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); - if ((lastPushUpCmpltTime <= 0 && tDiffStart >= thresholdPushUpTime) || tDiffLastPushUp >= thresholdPushUpTime) { + if ((lastExerciseCmpltTime <= 0 && tDiffStart >= pushUpThresholdTime) || tDiffLastPushUp >= pushUpThresholdTime) { console.log(t, "Push up complete!!!"); - lastPushUpCmpltTime = t; - pushUpCounter++; + lastExerciseCmpltTime = t; + exerciseCounter++; - layout.count.label = pushUpCounter; - layout.render(layout.count); + layout.count.label = exerciseCounter; layout.progress.label = ""; - layout.render(layout.progress); + layout.render(); Bangle.buzz(100, 0.3); // TODO make configurable } else { @@ -160,19 +172,6 @@ function isValidPushUp(p1, p2, t) { } } -/* - -function calcPushUps() { - const l = historySlopeY.length; - for (let i = 1; i < l; i++) { - const p1 = historySlopeY[i - 1][1]; - const p2 = historySlopeY[i][1]; - const t = historySlopeY[i][0]; - isValidPushUp(p1, p2, t); - } -} -*/ - function reset() { historyY = []; historyZ = []; @@ -183,8 +182,9 @@ function reset() { lastZeroPassType = ""; lastZeroPassTime = 0; - lastPushUpCmpltTime = 0; - pushUpCounter = 0; + lastExerciseCmpltTime = 0; + exerciseCounter = 0; + tStart = 0; } @@ -192,29 +192,54 @@ function startRecording() { if (recordActive) return; g.clear(1); reset(); + Bangle.setHRMPower(1, "banglexercise"); + if (!hrtValue) hrtValue = "..."; + layout = new Layout({ type: "v", c: [{ type: "txt", id: "type", font: "6x8:2", - label: exerciseType, + label: exerciseType.name, pad: 5 }, { - type: "txt", - id: "count", - font: "6x8:9", - label: pushUpCounter, - pad: 5, - bgCol: g.theme.bg + type: "h", + c: [{ + type: "txt", + id: "count", + font: "6x8:10", + label: exerciseCounter, + pad: 5, + bgCol: g.theme.bg + }, + { + type: "txt", + id: "progress", + font: "6x8:2", + label: "", + pad: 5 + }, + ] }, { - type: "txt", - id: "progress", - font: "6x8:2", - label: "", - pad: 5 + type: "h", + c: [{ + type: "img", + pad: 4, + src: function() { + return heatshrink.decompress(atob("h0OwYOLkmQhMkgACByVJgESpIFBpEEBAIFBCgIFCCgsABwcAgQOCAAMSpAwDyBNM")); + } + }, + { + type: "txt", + id: "hrtRate", + font: "6x8:2", + label: hrtValue, + pad: 5 + }, + ] }, { type: "txt", @@ -234,7 +259,8 @@ function startRecording() { stopRecording(); } } - ] + ], + lazy: true }); layout.render(); @@ -248,12 +274,17 @@ function startRecording() { function stopRecording() { if (!recordActive) return; g.clear(1); + + Bangle.setHRMPower(0, "banglexercise"); + Bangle.removeListener('accel', accelHandler); - showMenu(); - console.log("Found " + pushUpCounter + " push ups!"); + showMainMenu(); recordActive = false; } +Bangle.on('HRM', function(hrm) { + hrtValue = hrm.bpm; +}); + g.clear(1); -Bangle.drawWidgets(); -showMenu(); +showMainMenu(); From c9fa1b8f65db32d3dae0063630228332f0679c3f Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 11:44:07 +0100 Subject: [PATCH 050/169] Update screenshot --- apps/banglexercise/screenshot.png | Bin 2043 -> 2181 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/banglexercise/screenshot.png b/apps/banglexercise/screenshot.png index 9a325d87378dd297bab31da0521462e06d5c1ab9..417be685b08802657be55b02498c4c292128b70d 100644 GIT binary patch literal 2181 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 From 83aa32ee840a6aec7fcaf0995de8f3a1278e4a89 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 12:38:19 +0100 Subject: [PATCH 051/169] Moved exercise threshold values to the exercise type configuration & initial support for curls --- apps/banglexercise/README.md | 9 ++- apps/banglexercise/app.js | 148 +++++++++++++++++++++-------------- 2 files changed, 98 insertions(+), 59 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index efc87424d..9d8ee7be4 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -2,7 +2,13 @@ Can automatically track exercises while wearing the Bangle.js watch. -Currently only push ups are supported. +Currently only push ups and curls are supported. + +## Disclaimer + +This app is very experimental. +It could be and is likely that the threshold values for detecting exercises do not work for everyone. +Therefore it would be great if we could improve this app together :-) ## Usage @@ -17,7 +23,6 @@ Press stop to end your exercise. ## TODO * Add other exercise types: * Rope jumps - * Curls * Sit ups * ... * Save exercises to file system diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index e18faf554..3f710cf1e 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -15,26 +15,35 @@ let lastZeroPassTime = 0; let lastExerciseCmpltTime = 0; let exerciseType = { + "id": "", "name": "" }; + +// add new exercises here: const exerciseTypes = [{ "id": "pushup", "name": "Push ups", "useYaxe": true, - "useZaxe": false - } // add other exercises here + "useZaxe": false, + "thresholdY": 2500, + "thresholdTime": 1400 // mininmal time between two push ups + }, + { + "id": "curl", + "name": "Curls", + "useYaxe": true, + "useZaxe": false, + "thresholdY": 2500, + "thresholdTime": 1000 // mininmal time between two curls + } ]; let exerciseCounter = 0; let layout; let recordActive = false; -/** - * Thresholds - */ +// Size of average window for data analysis const avgSize = 6; -const pushUpThresholdY = 2500; -const pushUpThresholdTime = 1400; // mininmal time between two push ups let hrtValue; @@ -55,7 +64,9 @@ function showMainMenu() { }); if (exerciseCounter > 0) { - menu["----"] = {}; + menu["----"] = { + value: "" + }; menu["Last:"] = { value: exerciseCounter + " " + exerciseType.name }; @@ -101,19 +112,18 @@ function accelHandler(accel) { if (l > 1) { const p1 = historyAvgY[l - 2]; const p2 = historyAvgY[l - 1]; - const mY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - if (Math.abs(mY) >= pushUpThresholdY) { - historyAvgY.shift(); - historySlopeY.push([t, mY]); - //console.log(t, Math.abs(mY)); + const slopeY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - const lMY = historySlopeY.length; - if (lMY > 1) { - const pMY1 = historySlopeY[lMY - 2][1]; - const pMY2 = historySlopeY[lMY - 1][1]; - isValidPushUp(pMY1, pMY2, t); - } + // we use this data for exercises which can be detected by using Y axis data + switch (exerciseType.id) { + case "pushup": + isValidYAxisExercise(slopeY, t); + break; + case "curl": + isValidYAxisExercise(slopeY, t); + break; } + } } @@ -123,55 +133,81 @@ function accelHandler(accel) { if (l > 1) { const p1 = historyAvgZ[l - 2]; const p2 = historyAvgZ[l - 1]; - const mZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); + const slopeZ = (p2[1] - p1[1]) / (p2[0] - p1[0]); historyAvgZ.shift(); - historySlopeZ.push([p2[0] - p1[0], mZ]); + historySlopeZ.push([p2[0] - p1[0], slopeZ]); + + // TODO: we can use this data for some exercises which can be detected by using Z axis data } } } -function isValidPushUp(p1, p2, t) { - if (p1 > 0 && p2 < 0) { +/* + * Check if slope value of Y-axis data looks like an exercise + * + * In detail we look for slop values which are bigger than the configured Y threshold for the current exercise + * Then we look for two consecutive slope values of which one is above 0 and the other is below zero. + * If we find one pair of these values this could be part of one exercise. + * Then we look for a pair of values which cross the zero from the otherwise direction + */ +function isValidYAxisExercise(slopeY, t) { + if (!exerciseType) return; - if (lastZeroPassType == "-+") { - console.log(t, "Push up half complete..."); + const thresholdY = exerciseType.thresholdY; + const thresholdTime = exerciseType.thresholdTime; + const exerciseName = exerciseType.name; - layout.progress.label = "*"; - layout.render(); - } + if (Math.abs(slopeY) >= thresholdY) { + historyAvgY.shift(); + historySlopeY.push([t, slopeY]); + //console.log(t, Math.abs(slopeY)); - lastZeroPassType = "+-"; - lastZeroPassTime = t; - } - if (p2 > 0 && p1 < 0) { + const lSlopeY = historySlopeY.length; + if (lSlopeY > 1) { + const p1 = historySlopeY[lSlopeY - 2][1]; + const p2 = historySlopeY[lSlopeY - 1][1]; + if (p1 > 0 && p2 < 0) { + if (lastZeroPassType == "-+") { + console.log(t, exerciseName + " half complete..."); - if (lastZeroPassType == "+-") { - // potential complete push up. Let's check the time difference... - const tDiffLastPushUp = t - lastExerciseCmpltTime; - const tDiffStart = t - tStart; - console.log(t, "Push up maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + layout.progress.label = "*"; + layout.render(); + } - if ((lastExerciseCmpltTime <= 0 && tDiffStart >= pushUpThresholdTime) || tDiffLastPushUp >= pushUpThresholdTime) { - console.log(t, "Push up complete!!!"); + lastZeroPassType = "+-"; + lastZeroPassTime = t; + } + if (p2 > 0 && p1 < 0) { + if (lastZeroPassType == "+-") { + // potential complete exercise. Let's check the time difference... + const tDiffLastPushUp = t - lastExerciseCmpltTime; + const tDiffStart = t - tStart; + console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); - lastExerciseCmpltTime = t; - exerciseCounter++; + if ((lastExerciseCmpltTime <= 0 && tDiffStart >= thresholdTime) || tDiffLastPushUp >= thresholdTime) { + console.log(t, exerciseName + " complete!!!"); - layout.count.label = exerciseCounter; - layout.progress.label = ""; - layout.render(); + lastExerciseCmpltTime = t; + exerciseCounter++; - Bangle.buzz(100, 0.3); // TODO make configurable - } else { - console.log(t, "Push up to quick for threshold!"); + layout.count.label = exerciseCounter; + layout.progress.label = ""; + layout.render(); + + Bangle.buzz(100, 0.4); // TODO make configurable + } else { + console.log(t, exerciseName + " to quick for time threshold!"); + } + } + + lastZeroPassType = "-+"; + lastZeroPassTime = t; } } - - lastZeroPassType = "-+"; - lastZeroPassTime = t; } } + function reset() { historyY = []; historyZ = []; @@ -252,14 +288,12 @@ function startRecording() { }, ] }, { - btns: [ - { - label: "STOP", - cb: () => { - stopRecording(); - } + btns: [{ + label: "STOP", + cb: () => { + stopRecording(); } - ], + }], lazy: true }); layout.render(); From a3ada12a928931646e078a083bc394012f3c646e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:04:54 +0100 Subject: [PATCH 052/169] Add settings for buzz; more timeouts to better detect activities; reduce memory usage --- apps.json | 6 ++- apps/banglexercise/app.js | 99 ++++++++++++++++++++++------------ apps/banglexercise/settings.js | 21 ++++++++ 3 files changed, 92 insertions(+), 34 deletions(-) create mode 100644 apps/banglexercise/settings.js diff --git a/apps.json b/apps.json index 0adb4abc5..230a37b67 100644 --- a/apps.json +++ b/apps.json @@ -5518,7 +5518,11 @@ "readme": "README.md", "storage": [ {"name":"banglexercise.app.js","url":"app.js"}, - {"name":"banglexercise.img","url":"app-icon.js","evaluate":true} + {"name":"banglexercise.img","url":"app-icon.js","evaluate":true}, + {"name":"banglexercise.settings.js","url":"settings.js"} + ], + "data": [ + {"name":"banglexercise.json"} ] } ] diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 3f710cf1e..ac4153239 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -9,10 +9,11 @@ let historyAvgZ = []; let historySlopeY = []; let historySlopeZ = []; -let lastZeroPassType; +let lastZeroPassCameFromPositive; let lastZeroPassTime = 0; -let lastExerciseCmpltTime = 0; +let lastExerciseCompletionTime = 0; +let lastExerciseHalfCompletionTime = 0; let exerciseType = { "id": "", @@ -22,19 +23,23 @@ let exerciseType = { // add new exercises here: const exerciseTypes = [{ "id": "pushup", - "name": "Push ups", + "name": "push ups", "useYaxe": true, "useZaxe": false, "thresholdY": 2500, - "thresholdTime": 1400 // mininmal time between two push ups + "thresholdMinTime": 1400, // mininmal time between two push ups in ms + "thresholdMaxTime": 5000, // maximal time between two push ups in ms + "thresholdMinDurationTime": 700, // mininmal duration of half a push ups in ms }, { "id": "curl", - "name": "Curls", + "name": "curls", "useYaxe": true, "useZaxe": false, "thresholdY": 2500, - "thresholdTime": 1000 // mininmal time between two curls + "thresholdMinTime": 1000, // mininmal time between two curls in ms + "thresholdMaxTime": 5000, // maximal time between two curls in ms + "thresholdMinDurationTime": 500, // mininmal duration of half a push ups in ms } ]; let exerciseCounter = 0; @@ -47,6 +52,10 @@ const avgSize = 6; let hrtValue; +let settings = storage.readJSON("banglexercise.json", 1) || { + 'buzz': true +}; + function showMainMenu() { let menu; menu = { @@ -64,7 +73,7 @@ function showMainMenu() { }); if (exerciseCounter > 0) { - menu["----"] = { + menu["--------"] = { value: "" }; menu["Last:"] = { @@ -91,6 +100,8 @@ function accelHandler(accel) { if (historyY.length > avgSize / 2) { const avgY = E.sum(historyY) / historyY.length; historyAvgY.push([t, avgY]); + while (historyAvgY.length > avgSize) + historyAvgY.shift(); } } @@ -103,6 +114,8 @@ function accelHandler(accel) { if (historyZ.length > avgSize / 2) { const avgZ = E.sum(historyZ) / historyZ.length; historyAvgZ.push([t, avgZ]); + while (historyAvgZ.length > avgSize) + historyAvgZ.shift(); } } @@ -113,7 +126,6 @@ function accelHandler(accel) { const p1 = historyAvgY[l - 2]; const p2 = historyAvgY[l - 1]; const slopeY = (p2[1] - p1[1]) / (p2[0] / 1000 - p1[0] / 1000); - // we use this data for exercises which can be detected by using Y axis data switch (exerciseType.id) { case "pushup": @@ -154,7 +166,9 @@ function isValidYAxisExercise(slopeY, t) { if (!exerciseType) return; const thresholdY = exerciseType.thresholdY; - const thresholdTime = exerciseType.thresholdTime; + const thresholdMinTime = exerciseType.thresholdMinTime; + const thresholdMaxTime = exerciseType.thresholdMaxTime; + const thresholdMinDurationTime = exerciseType.thresholdMinDurationTime; const exerciseName = exerciseType.name; if (Math.abs(slopeY) >= thresholdY) { @@ -164,43 +178,61 @@ function isValidYAxisExercise(slopeY, t) { const lSlopeY = historySlopeY.length; if (lSlopeY > 1) { - const p1 = historySlopeY[lSlopeY - 2][1]; - const p2 = historySlopeY[lSlopeY - 1][1]; + const p1 = historySlopeY[lSlopeY - 1][1]; + const p2 = historySlopeY[lSlopeY - 2][1]; if (p1 > 0 && p2 < 0) { - if (lastZeroPassType == "-+") { + if (lastZeroPassCameFromPositive == false) { + lastExerciseHalfCompletionTime = t; console.log(t, exerciseName + " half complete..."); - layout.progress.label = "*"; + layout.progress.label = "½"; layout.render(); } - lastZeroPassType = "+-"; + lastZeroPassCameFromPositive = true; lastZeroPassTime = t; } if (p2 > 0 && p1 < 0) { - if (lastZeroPassType == "+-") { - // potential complete exercise. Let's check the time difference... - const tDiffLastPushUp = t - lastExerciseCmpltTime; + if (lastZeroPassCameFromPositive == true) { + const tDiffLastExercise = t - lastExerciseCompletionTime; const tDiffStart = t - tStart; - console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastPushUp), Math.round(tDiffStart)); + console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); - if ((lastExerciseCmpltTime <= 0 && tDiffStart >= thresholdTime) || tDiffLastPushUp >= thresholdTime) { - console.log(t, exerciseName + " complete!!!"); + // check minimal time between exercises: + if ((lastExerciseCompletionTime <= 0 && tDiffStart >= thresholdMinTime) || tDiffLastExercise >= thresholdMinTime) { - lastExerciseCmpltTime = t; - exerciseCounter++; + // check maximal time between exercises: + if (lastExerciseCompletionTime <= 0 || tDiffLastExercise <= thresholdMaxTime) { - layout.count.label = exerciseCounter; - layout.progress.label = ""; - layout.render(); + // check minimal duration of exercise: + const tDiffExerciseHalfCompletion = t - lastExerciseHalfCompletionTime; + if (tDiffExerciseHalfCompletion > thresholdMinDurationTime) { + console.log(t, exerciseName + " complete!!!"); - Bangle.buzz(100, 0.4); // TODO make configurable + lastExerciseCompletionTime = t; + exerciseCounter++; + + layout.count.label = exerciseCounter; + layout.progress.label = ""; + layout.render(); + + if (settings.buzz) + Bangle.buzz(100, 0.4); + } else { + console.log(t, exerciseName + " to quick for duration time threshold!"); + lastExerciseCompletionTime = t; + } + } else { + console.log(t, exerciseName + " to slow for time threshold!"); + lastExerciseCompletionTime = t; + } } else { console.log(t, exerciseName + " to quick for time threshold!"); + lastExerciseCompletionTime = t; } } - lastZeroPassType = "-+"; + lastZeroPassCameFromPositive = false; lastZeroPassTime = t; } } @@ -216,9 +248,10 @@ function reset() { historySlopeY = []; historySlopeZ = []; - lastZeroPassType = ""; + lastZeroPassCameFromPositive = undefined; lastZeroPassTime = 0; - lastExerciseCmpltTime = 0; + lastExerciseHalfCompletionTime = 0; + lastExerciseCompletionTime = 0; exerciseCounter = 0; tStart = 0; } @@ -300,18 +333,18 @@ function startRecording() { Bangle.setPollInterval(80); // 12.5 Hz Bangle.on('accel', accelHandler); - Bangle.buzz(200, 1); tStart = new Date().getTime(); recordActive = true; + if (settings.buzz) + Bangle.buzz(200, 1); } function stopRecording() { if (!recordActive) return; + g.clear(1); - - Bangle.setHRMPower(0, "banglexercise"); - Bangle.removeListener('accel', accelHandler); + Bangle.setHRMPower(0, "banglexercise"); showMainMenu(); recordActive = false; } diff --git a/apps/banglexercise/settings.js b/apps/banglexercise/settings.js new file mode 100644 index 000000000..3208c6eca --- /dev/null +++ b/apps/banglexercise/settings.js @@ -0,0 +1,21 @@ +(function(back) { + const SETTINGS_FILE = "banglexercise.json"; + const storage = require('Storage'); + let settings = storage.readJSON(SETTINGS_FILE, 1) || {}; + function save(key, value) { + settings[key] = value; + storage.write(SETTINGS_FILE, settings); + } + E.showMenu({ + '': { 'title': 'BanglExercise' }, + '< Back': back, + 'Buzz': { + value: "buzz" in settings ? settings.buzz : false, + format: () => (settings.buzz ? 'Yes' : 'No'), + onchange: () => { + settings.buzz = !settings.buzz; + save('buzz', settings.buzz); + } + } + }); +}); From cc5a1f5d5a3756bc99d9b8cb66783a7cc34f0890 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:09:02 +0100 Subject: [PATCH 053/169] Fix missing module requirement --- apps/banglexercise/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index ac4153239..3e53cff61 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,5 +1,6 @@ const Layout = require("Layout"); const heatshrink = require('heatshrink'); +const storage = require('storage'); let tStart; let historyY = []; From 800624f2d405270deb9f7ed5cab41946d494b41e Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Tue, 11 Jan 2022 16:18:10 +0100 Subject: [PATCH 054/169] Fix missing module requirement --- apps/banglexercise/app.js | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index ac4153239..f5a532408 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -1,5 +1,6 @@ const Layout = require("Layout"); const heatshrink = require('heatshrink'); +const storage = require('Storage'); let tStart; let historyY = []; From e669138023cfb661bd599308c4b8b21e427c3cc1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:28:48 +0100 Subject: [PATCH 055/169] Update apps.json --- apps.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/apps.json b/apps.json index c93efd152..a62bb19cf 100644 --- a/apps.json +++ b/apps.json @@ -5538,5 +5538,22 @@ {"name":"limelight.settings.js","url":"limelight.settings.js"}, {"name":"limelight.img","url":"limelight.icon.js","evaluate":true} ] + }, + { "id": "configurable_clock", + "name": "Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.02", + "description": "an analog clock with several kinds of faces, hands and colors to choose from", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "storage": [ + {"name":"configurable_clock.app.js","url":"app.js"}, + {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} + ] } ] From 216610780f734f111704c99964f567fb2b8b24a0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:29:19 +0100 Subject: [PATCH 056/169] Create app.js --- apps/ac_ac/app.js | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 apps/ac_ac/app.js diff --git a/apps/ac_ac/app.js b/apps/ac_ac/app.js new file mode 100644 index 000000000..1d9b2e3c6 --- /dev/null +++ b/apps/ac_ac/app.js @@ -0,0 +1,2 @@ +let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); +Clockwork.windUp(); \ No newline at end of file From 0666181c8d8b83161364b54264de82d8fc774e5a Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:29:24 +0100 Subject: [PATCH 057/169] Create README.md --- apps/ac_ac/README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 apps/ac_ac/README.md diff --git a/apps/ac_ac/README.md b/apps/ac_ac/README.md new file mode 100644 index 000000000..0e0084b64 --- /dev/null +++ b/apps/ac_ac/README.md @@ -0,0 +1,34 @@ +# AC-AC - A Configurable Analog Clock # + +This app implements an analog clock with various faces, hands and complications +to choose from before uploading to a Bangle.js 2. + +It is based on the [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit) +and makes most of the currently implemented parts available with a few mouse +clicks - just click on "Upload" and you will be directed to a web form where +you compose your very own, personal analog clock. + +You currently have the choice between + +* 2 different clock sizes, +* 4 different clock faces, +* 3 different clock hands and +* 4 different complications + +Alternatively, you may specify the GitHub URL of ACCK compatible modules for +external clock sizes, faces, hands or complications. + +Additionally, you may use the currently configured global theme or configure +your own colors for clock fore- and background and second hands. + +Consequently, even without external modules you already have the choice between +87552 combinations! + + + +## License ## + +[MIT License](LICENSE) From 16b50228bdaee15584a5c2b5e7a9b5d38ff1cdbe Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:30:27 +0100 Subject: [PATCH 058/169] Update apps.json --- apps.json | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/apps.json b/apps.json index a62bb19cf..aa626a609 100644 --- a/apps.json +++ b/apps.json @@ -5555,5 +5555,23 @@ {"name":"configurable_clock.app.js","url":"app.js"}, {"name":"configurable_clock.img","url":"app-icon.js","evaluate":true} ] + }, + { "id": "ac_ac", + "name": "A Configurable Analog Clock", + "shortName":"Configurable Clock", + "version":"0.02", + "description": "a highly customizable analog clock", + "icon": "app-icon.png", + "type": "clock", + "tags": "clock", + "supports" : ["BANGLEJS2"], + "allow_emulator": true, + "screenshots": [{"url":"app-screenshot.png"}], + "readme": "README.md", + "custom": "Customizer.html", + "storage": [ + {"name":"ac_ac.app.js","url":"app.js"}, + {"name":"ac_ac.img","url":"app-icon.js","evaluate":true} + ] } ] From 3715ae433a796088c1ac0444b507c42162329b7f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Tue, 11 Jan 2022 16:30:48 +0100 Subject: [PATCH 059/169] Create Customizer.html --- apps/ac_ac/Customizer.html | 91 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 apps/ac_ac/Customizer.html diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html new file mode 100644 index 000000000..6637b5df4 --- /dev/null +++ b/apps/ac_ac/Customizer.html @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + +

A Configurable Analog Clock

+ + Please customize your analog clock for the Bangle.js 2 according to your needs. + When finished, click on "Upload". + +

Clock Size Calculation

+ +
+
+ +  
+ +

Clock Face

+ +
+
+  
+
+  
+
+  
+ +

Clock Hands

+ +
+
+
+   Hand Fill Color
+ +

Complications

+ +

Settings

+ + Foreground Color:
+ + Background Color:
+ + Second Hand Color:
+ + + + + From 1cdcedc997db4286270eaa5c3b7782b57310f073 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 17:41:02 +0100 Subject: [PATCH 060/169] Bugfix: If the weather module does not exist, an exception was thrown. Now its hidden in a function. --- apps/lcars/lcars.app.js | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 09998ccf5..39d01a687 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -1,10 +1,5 @@ const SETTINGS_FILE = "lcars.setting.json"; -const Storage = require("Storage"); -const weather = require('weather'); - - -// ...and overwrite them with any saved values -// This way saved values are preserved if a new version adds more settings +const locale = require('locale'); const storage = require('Storage') let settings = { alarm: -1, @@ -39,7 +34,7 @@ var disableInfoUpdate = true; // When gadgetbridge connects, step infos cannot b /* * Requirements and globals */ -const locale = require('locale'); + var bgLeft = { width : 27, height : 176, bpp : 3, @@ -124,7 +119,7 @@ function queueDraw() { function printData(key, y, c){ g.setFontAlign(-1,-1,0); var text = "ERR"; - var value = "NOT FOUND"; + var value = "ERR"; if(key == "Battery"){ text = "BAT"; @@ -136,7 +131,7 @@ function printData(key, y, c){ } else if(key == "Temp."){ text = "TEMP"; - value = Math.floor(E.getTemperature()) + "C"; + value = locale.temp(parseInt(E.getTemperature())); } else if(key == "HRM"){ text = "HRM"; @@ -148,12 +143,8 @@ function printData(key, y, c){ } else if (key == "Weather"){ text = "TEMP"; - const w = weather.get(); - if (!w) { - value = "ERR"; - } else { - value = require('locale').temp(w.temp-273.15); // applies conversion - } + var weather = getWeather(); + value = locale.temp(parseInt(weather.temp-273.15)); } g.setColor(c); @@ -429,6 +420,21 @@ function getSteps() { } +function getWeather(){ + let weather; + + try { + weather = require('weather'); + } catch(ex) { + return { + temp: 0.0 + }; + } + + return weather.get(); +} + + /* * Handle alarm */ From 5de8ca8184909f17b65900e1883204810b82c3e5 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 18:10:05 +0100 Subject: [PATCH 061/169] Updated changelog, readme, screenshots etc. More consistent naming of datapoints. --- apps/lcars/ChangeLog | 4 ++-- apps/lcars/README.md | 36 +++++++++++++++------------- apps/lcars/lcars.app.js | 45 ++++++++++++++++------------------- apps/lcars/lcars.settings.js | 2 +- apps/lcars/screenshot.png | Bin 5259 -> 5547 bytes 5 files changed, 44 insertions(+), 43 deletions(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index 45d7a8dd7..bcaddeb56 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -7,5 +7,5 @@ 0.07: Added settings to adjust data that is shown for each row. 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. -0.10: Fix - Clock is unresponsive, if gadgetbridge connects. -0.11: Added getting the gadgetbridge weather \ No newline at end of file +0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. +0.11: Show the gadgetbridge weather temperature (settings). \ No newline at end of file diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 4bf5218f6..510e5637c 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -4,20 +4,27 @@ A simple LCARS inspired clock. Note: To display the steps, the health app is required. If this app is not installed, the data will not be shown. To contribute you can open a PR at this [GitHub Repo]( https://github.com/peerdavid/BangleApps) +## Control + * Tap left / right to change between screens. + * Tap top / bottom to control the current screen. + ## Features * LCARS Style watch face. - * Full screen mode - widgets are still loaded. - * Supports multiple screens with different data. - * Tab anywhere to open the launcher. - * [Screen 1] Date + Time + Lock status. - * [Screen 1] Shows randomly images of real planets. - * [Screen 1] Shows different states such as (charging, out of battery, GPS on etc.) - * [Screen 1] Swipe up/down to activate an alarm. - * [Screen 1] Shows 3 customizable datapoints on the first screen. - * [Screen 1] The lower orange line indicates the battery level. - * [Screen 2] Display graphs for steps + hrm on the second screen. - * [Screen 2] Switch between day/month via swipe up/down. + * Full screen mode - widgets are still loaded but not shown. + * Tab on left/right to switch between different screens. + * Cusomizable data that is shown on screen 1 (steps, weather etc.) + * Shows random images of real planets. + * Tap on top/bottom of screen 1 to activate an alarm. + * The lower orange line indicates the battery level. + * Display graphs for steps + hrm on the second screen. +## Data that can be configured + * Steps - Steps loaded via the health module + * Battery - Current battery level in % + * VREF - Voltage of battery + * HRM - Last measured HRM + * Temp - Weather temperature loaded via the weather module + gadgetbridge + * CoreT - Temperature of device ## Multiple screens support Access different screens via swipe left/ right @@ -26,10 +33,7 @@ Access different screens via swipe left/ right ![](screenshot_2.png) -## Icons -
- - ## Contributors -- Creator: [David Peer](https://github.com/peerdavid). +- Initial creation and improvements: [David Peer](https://github.com/peerdavid). - Improvements: [Adam Schmalhofer](https://github.com/adamschmalhofer). +- Improvements: [Jon Warrington](https://github.com/BartokW). diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 39d01a687..521f661e7 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -28,7 +28,7 @@ let cGrey = "#9E9E9E"; let lcarsViewPos = 0; let drag; let hrmValue = 0; -var plotWeek = false; +var plotMonth = false; var disableInfoUpdate = true; // When gadgetbridge connects, step infos cannot be loaded /* @@ -118,33 +118,30 @@ function queueDraw() { function printData(key, y, c){ g.setFontAlign(-1,-1,0); - var text = "ERR"; + key = key.toUpperCase() + var text = key; var value = "ERR"; - if(key == "Battery"){ - text = "BAT"; - value = E.getBattery() + "%"; - - } else if(key == "Steps"){ + if(key == "STEPS"){ text = "STEP"; value = getSteps(); - } else if(key == "Temp."){ - text = "TEMP"; - value = locale.temp(parseInt(E.getTemperature())); - - } else if(key == "HRM"){ - text = "HRM"; - value = hrmValue; + } else if(key == "BATTERY"){ + text = "BAT"; + value = E.getBattery() + "%"; } else if (key == "VREF"){ - text = "VREF"; value = E.getAnalogVRef().toFixed(2) + "V"; - } else if (key == "Weather"){ - text = "TEMP"; + } else if(key == "HRM"){ + value = hrmValue; + + } else if (key == "TEMP"){ var weather = getWeather(); value = locale.temp(parseInt(weather.temp-273.15)); + + } else if(key == "CORET"){ + value = locale.temp(parseInt(E.getTemperature())); } g.setColor(c); @@ -300,7 +297,7 @@ function drawPosition1(){ } // Plot HRM graph - if(plotWeek){ + if(plotMonth){ var data = new Uint16Array(32); var cnt = new Uint8Array(32); health.readDailySummaries(new Date(), h=>{ @@ -337,8 +334,8 @@ function drawPosition1(){ g.setFontAlign(1, 1, 0); g.setFontAntonioMedium(); g.setColor(cWhite); - g.drawString("WEEK HRM", 154, 27); - g.drawString("WEEK STEPS [K]", 154, 115); + g.drawString("M-HRM", 154, 27); + g.drawString("M-STEPS [K]", 154, 115); // Plot day } else { @@ -378,8 +375,8 @@ function drawPosition1(){ g.setFontAlign(1, 1, 0); g.setFontAntonioMedium(); g.setColor(cWhite); - g.drawString("DAY HRM", 154, 27); - g.drawString("DAY STEPS", 154, 115); + g.drawString("D-HRM", 154, 27); + g.drawString("D-STEPS", 154, 115); } } @@ -568,9 +565,9 @@ Bangle.on('touch', function(btn, e){ drawState(); return; } - } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotWeek != is_lower){ + } else if (lcarsViewPos == 1 && (is_upper || is_lower) && plotMonth != is_lower){ feedback(); - plotWeek = is_lower; + plotMonth = is_lower; draw(); return; } diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index a0e54f9b4..1dd6e8d73 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -18,7 +18,7 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Battery", "Steps", "Temp.", "HRM", "VREF", "Weather"]; + var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "CoreT"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index 5d7603b45e6c7aadcc01aa0afdf13ff4d579eb93..5381492b242865bae924e11daf9a5cd40313188f 100644 GIT binary patch literal 5547 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 literal 5259 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 Date: Tue, 11 Jan 2022 18:11:49 +0100 Subject: [PATCH 062/169] Updated screenshot. --- apps/lcars/screenshot.png | Bin 5547 -> 5721 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/lcars/screenshot.png b/apps/lcars/screenshot.png index 5381492b242865bae924e11daf9a5cd40313188f..319062dcce36640c38e24378d97b7724ab3a9f74 100644 GIT binary patch literal 5721 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 From 755f44cf3f3896a3a646f96bea49ce48aa94b90d Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 18:20:53 +0100 Subject: [PATCH 063/169] Bugfix: Alarm not working. --- apps/lcars/ChangeLog | 3 ++- apps/lcars/lcars.app.js | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index bcaddeb56..bb5270b70 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -8,4 +8,5 @@ 0.08: Support for multiple screens. 24h graph for steps + HRM. Fullscreen Mode. 0.09: Tab anywhere to open the launcher. 0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. -0.11: Show the gadgetbridge weather temperature (settings). \ No newline at end of file +0.11: Show the gadgetbridge weather temperature (settings). +0.12: Refactoring and stability improvements. \ No newline at end of file diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 521f661e7..c4e675873 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -470,7 +470,7 @@ function handleAlarm(){ .then(() => { // Update alarm state to disabled settings.alarm = -1; - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); }); } @@ -510,7 +510,7 @@ function increaseAlarm(){ settings.alarm = getCurrentTimeInMinutes() + 5; } - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); } @@ -521,7 +521,7 @@ function decreaseAlarm(){ settings.alarm = -1; } - Storage.writeJSON(SETTINGS_FILE, settings); + storage.writeJSON(SETTINGS_FILE, settings); } function feedback(){ From 8467a8810af3a651ae85af6d6866f97222f2abeb Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:16:05 +0100 Subject: [PATCH 064/169] messages: app-specific icon colors --- apps.json | 2 +- apps/messages/ChangeLog | 1 + apps/messages/app.js | 31 +++++++++++++++++++++++++++++-- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..71a60ec88 100644 --- a/apps.json +++ b/apps.json @@ -77,7 +77,7 @@ { "id": "messages", "name": "Messages", - "version": "0.17", + "version": "0.18", "description": "App to display notifications from iOS and Gadgetbridge", "icon": "app.png", "type": "app", diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 4f0498e92..84dc67288 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -24,3 +24,4 @@ 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.17: Fix: Get dynamic dimensions of notify icon, fixed notification font +0.18: Use app-specific icon colors diff --git a/apps/messages/app.js b/apps/messages/app.js index 6e51c2b33..f670c39a2 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -101,6 +101,31 @@ function getMessageImage(msg) { if (msg.id=="back") return getBackImage(); return getNotificationImage(); } +function getMessageImageCol(msg,def) { + return { + // generic colors, using B2-safe colors + "calendar": "#f00", + "mail": "#ff0", + "music": "#f0f", + "phone": "#0f0", + "sms message": "#0ff", + // brands, according to https://www.schemecolor.com/?s (picking one for multicolored logos) + // all dithered on B2, but we only use the color for the icons. (Could maybe pick the closest 3-bit color for B2?) + "facebook": "#4267b2", + "gmail": "#ea4335", + "google home": "#fbbc05", + "hangouts": "#1ba261", + "instagram": "#dd2a7b", + "messenger": "#0078ff", + "outlook mail": "#0072c6", + "skype": "#00aff0", + "slack": "#e51670", + "telegram": "#0088cc", + "twitter": "#1da1f2", + "whatsapp": "#4fce5d", + "wordfeud": "#dcc8bd", + }[(msg.src||"").toLowerCase()]||(def !== undefined?def:g.theme.fg); +} function showMapMessage(msg) { var m; @@ -248,7 +273,7 @@ function showMessage(msgid) { var body = (lines.length>4) ? lines.slice(0,4).join("\n")+"..." : lines.join("\n"); layout = new Layout({ type:"v", c: [ {type:"h", fillx:1, bgCol:colBg, c: [ - { type:"btn", src:getMessageImage(msg), pad: 3, cb:()=>{ + { type:"btn", src:getMessageImage(msg), col:getMessageImageCol(msg), pad: 3, cb:()=>{ cancelReloadTimeout(); // don't auto-reload to clock now showMessageSettings(msg); }}, @@ -310,7 +335,9 @@ function checkMessages(options) { body = msg.track; } if (img) { - g.drawImage(img, x+24, r.y+24, {rotate:0}); // force centering + var fg = g.getColor(); + g.setColor(getMessageImageCol(msg,fg)).drawImage(img, x+24, r.y+24, {rotate:0}) // force centering + .setColor(fg); // only color the icon x += 50; } var m = msg.title+"\n"+msg.body; From d32674f825a0906ca9d1149505371dc4e0f101e2 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:17:16 +0100 Subject: [PATCH 065/169] messages: Spread message action buttons out --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 ++ 2 files changed, 3 insertions(+) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 84dc67288..4a28f7cd9 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -25,3 +25,4 @@ 0.16: Fix text wrapping so it fits the screen even if title is big (fix #1147) 0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font 0.18: Use app-specific icon colors + Spread message action buttons out diff --git a/apps/messages/app.js b/apps/messages/app.js index f670c39a2..5161ce665 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -253,6 +253,7 @@ function showMessage(msgid) { }} // back ]; if (msg.positive) { + buttons.push({fillx:1}); buttons.push({type:"btn", src:getPosImage(), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now @@ -261,6 +262,7 @@ function showMessage(msgid) { }}); } if (msg.negative) { + buttons.push({fillx:1}); buttons.push({type:"btn", src:getNegImage(), cb:()=>{ msg.new = false; saveMessages(); cancelReloadTimeout(); // don't auto-reload to clock now From a945a32f51a7d2a1a42a5a70bed38309aab2d555 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Tue, 11 Jan 2022 19:18:19 +0100 Subject: [PATCH 066/169] messages: Back button now goes back to list of messages --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 4a28f7cd9..0c02a76e1 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -26,3 +26,4 @@ 0.17: Fix: Get dynamic dimensions of notify icon, fixed notification font 0.18: Use app-specific icon colors Spread message action buttons out + Back button now goes back to list of messages diff --git a/apps/messages/app.js b/apps/messages/app.js index 5161ce665..4704c422f 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -249,7 +249,7 @@ function showMessage(msgid) { {type:"btn", src:getBackImage(), cb:()=>{ msg.new = false; saveMessages(); // read mail cancelReloadTimeout(); // don't auto-reload to clock now - checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:1}); + checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:0}); }} // back ]; if (msg.positive) { From 1f06e6cfc578473c86214f76c5c43d9715b905a4 Mon Sep 17 00:00:00 2001 From: David Peer Date: Tue, 11 Jan 2022 21:24:23 +0100 Subject: [PATCH 067/169] Added humidity --- apps/lcars/README.md | 1 + apps/lcars/lcars.app.js | 28 +++++++++++++++++++--------- apps/lcars/lcars.settings.js | 10 +++++----- 3 files changed, 25 insertions(+), 14 deletions(-) diff --git a/apps/lcars/README.md b/apps/lcars/README.md index 510e5637c..46e134f78 100644 --- a/apps/lcars/README.md +++ b/apps/lcars/README.md @@ -24,6 +24,7 @@ To contribute you can open a PR at this [GitHub Repo]( https://github.com/peerda * VREF - Voltage of battery * HRM - Last measured HRM * Temp - Weather temperature loaded via the weather module + gadgetbridge + * Humidity - Humidity loaded via the weather module + gadgetbridge * CoreT - Temperature of device ## Multiple screens support diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index c4e675873..0005e9016 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -3,9 +3,9 @@ const locale = require('locale'); const storage = require('Storage') let settings = { alarm: -1, - dataRow1: "Battery", - dataRow2: "Steps", - dataRow3: "Temp." + dataRow1: "Steps", + dataRow2: "Temp", + dataRow3: "Battery" }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; for (const key in saved_settings) { @@ -140,6 +140,11 @@ function printData(key, y, c){ var weather = getWeather(); value = locale.temp(parseInt(weather.temp-273.15)); + } else if (key == "HUMIDITY"){ + text = "HUM"; + var weather = getWeather(); + value = parseInt(weather.hum) + "%"; + } else if(key == "CORET"){ value = locale.temp(parseInt(E.getTemperature())); } @@ -418,17 +423,22 @@ function getSteps() { function getWeather(){ - let weather; + var weather = { + temp: 0, + hum: 0, + txt: "", + wind: 0, + wdir: 0, + wrose: "" + }; try { - weather = require('weather'); + weather = require('weather').get(); } catch(ex) { - return { - temp: 0.0 - }; + // Return default } - return weather.get(); + return weather; } diff --git a/apps/lcars/lcars.settings.js b/apps/lcars/lcars.settings.js index 1dd6e8d73..ba630799a 100644 --- a/apps/lcars/lcars.settings.js +++ b/apps/lcars/lcars.settings.js @@ -7,7 +7,7 @@ alarm: -1, dataRow1: "Battery", dataRow2: "Steps", - dataRow3: "Temp." + dataRow3: "Temp" }; let saved_settings = storage.readJSON(SETTINGS_FILE, 1) || settings; for (const key in saved_settings) { @@ -18,14 +18,14 @@ storage.write(SETTINGS_FILE, settings) } - var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "CoreT"]; + var data_options = ["Steps", "Battery", "VREF", "HRM", "Temp", "Humidity", "CoreT"]; E.showMenu({ '': { 'title': 'LCARS Clock' }, '< Back': back, 'Row 1': { value: 0 | data_options.indexOf(settings.dataRow1), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow1 = data_options[v]; @@ -34,7 +34,7 @@ }, 'Row 2': { value: 0 | data_options.indexOf(settings.dataRow2), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow2 = data_options[v]; @@ -43,7 +43,7 @@ }, 'Row 3': { value: 0 | data_options.indexOf(settings.dataRow3), - min: 0, max: 5, + min: 0, max: 6, format: v => data_options[v], onchange: v => { settings.dataRow3 = data_options[v]; From 009df38104965fc2b3119ebdd5fcb8e95d3223f5 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:16:01 +0100 Subject: [PATCH 068/169] fixed and aligned for bangle2 *bugfix* stopwatch broken with v0.03 setUI realigned quick n dirty screen positions help adjusted to fit bangle1 & bangle2 screen-size with widgets fixed bangle2 colors for chrono and last lap highlight added screen for bangle2 and a small README --- apps.json | 5 +- apps/devstopwatch/ChangeLog | 5 ++ apps/devstopwatch/README.md | 16 ++++++ apps/devstopwatch/app.js | 46 +++++++++++------- .../bangle1-dev-stopwatch-screenshot.png | Bin 3825 -> 2469 bytes .../bangle2-dev-stopwatch-screenshot.png | Bin 0 -> 2382 bytes 6 files changed, 52 insertions(+), 20 deletions(-) create mode 100644 apps/devstopwatch/README.md create mode 100644 apps/devstopwatch/bangle2-dev-stopwatch-screenshot.png diff --git a/apps.json b/apps.json index b5929a56c..f1872f337 100644 --- a/apps.json +++ b/apps.json @@ -2095,12 +2095,13 @@ "id": "devstopwatch", "name": "Dev Stopwatch", "shortName": "Dev Stopwatch", - "version": "0.03", + "version": "0.04", "description": "Stopwatch with 5 laps supported (cyclically replaced)", "icon": "app.png", "tags": "stopwatch,chrono,timer,chronometer", "supports": ["BANGLEJS","BANGLEJS2"], - "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"}], + "screenshots": [{"url":"bangle1-dev-stopwatch-screenshot.png"},{"url":"bangle2-dev-stopwatch-screenshot.png"}], + "readme": "README.md", "allow_emulator": true, "storage": [ {"name":"devstopwatch.app.js","url":"app.js"}, diff --git a/apps/devstopwatch/ChangeLog b/apps/devstopwatch/ChangeLog index e2b392fe9..7e90e061e 100644 --- a/apps/devstopwatch/ChangeLog +++ b/apps/devstopwatch/ChangeLog @@ -1,3 +1,8 @@ 0.01: App created 0.02: Persist state to storage to enable stopwatch to continue in the background 0.03: Modified to use setUI, theme and different screens +0.04: *bugfix* stopwatch broken with v0.03 setUI + realigned quick n dirty screen positions + help adjusted to fit bangle1 & bangle2 screen-size with widgets + fixed bangle2 colors for chrono and last lap highlight + added screen for bangle2 and a small README \ No newline at end of file diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md new file mode 100644 index 000000000..c068aadfe --- /dev/null +++ b/apps/devstopwatch/README.md @@ -0,0 +1,16 @@ +# dev stop watch + +stores state at kill + +Look and control: + +![](bangle1-dev-stopwatch-screenshot.png) +BTN1: start/lap +BTN2: launcher +BTN3: reset + +![](bangle2-dev-stopwatch-screenshot.png) +TAP top right: start/lap +TAP bottom right: reset +Use BTN to get to launcher + diff --git a/apps/devstopwatch/app.js b/apps/devstopwatch/app.js index 83bb693a9..d2a4b1117 100644 --- a/apps/devstopwatch/app.js +++ b/apps/devstopwatch/app.js @@ -3,11 +3,11 @@ const EMPTY_H = '00:00:000'; const MAX_LAPS = 6; const XY_CENTER = g.getWidth() / 2; const big = g.getWidth()>200; -const Y_CHRONO = 40; -const Y_HEADER = big?80:60; -const Y_LAPS = big?125:90; +const Y_CHRONO = big?40:30; +const Y_HEADER = big?95:65; +const Y_LAPS = big?125:80; const H_LAPS = big?15:8; -const Y_BTN3 = big?225:165; +const Y_HELP = big?225:135; const FONT = '6x8'; const CHRONO = '/* C H R O N O */'; @@ -27,18 +27,17 @@ var state = require("Storage").readJSON("devstopwatch.state.json",1) || { // Show launcher when button pressed Bangle.setUI("clockupdown", btn=>{ - if (btn==0) { - reset = false; - - if (state.started) { - changeLap(); - } else { - if (!reset) { - chronoInterval = setInterval(chronometer, 10); - } + switch (btn) { + case -1: + if (state.started) { + changeLap(); + } else { + chronoInterval = setInterval(chronometer, 10); + } + break; + case 1: resetChrono(); break; + default: Bangle.showLauncher(); break; //launcher handeled by ROM } -} - if (btn==1) resetChrono(); }); function resetChrono() { @@ -105,6 +104,7 @@ function printChrono() { var print = ''; + g.setColor(g.theme.fg); g.setFont(FONT, big?2:1); print = CHRONO; g.drawString(print, XY_CENTER, Y_CHRONO, true); @@ -124,7 +124,8 @@ function printChrono() { let suffix = ' '; if (state.currentLapIndex === i) { let suffix = '*'; - g.setColor("#f70"); + if (process.env.HWVERSION==2) g.setColor("#0ee"); + else g.setColor("#f70"); } const lapLine = `L${i - 1} ${state.laps[i]} ${suffix}\n`; @@ -133,8 +134,17 @@ function printChrono() { g.setColor(g.theme.fg); g.setFont(FONT, 1); - print = 'Press 3 to reset'; - g.drawString(print, XY_CENTER, Y_BTN3, true); + //help for model 2 or 1 + if (process.env.HWVERSION==2) { + print = /*LANG*/'TAP right top/bottom'; + g.drawString(print, XY_CENTER, Y_HELP, true); + print = /*LANG*/'start&lap/reset, BTN1: EXIT'; + g.drawString(print, XY_CENTER, Y_HELP+10, true); + } + else { + print = /*LANG*/'BTNs 1:startlap 2:exit 3:reset'; + g.drawString(print, XY_CENTER, Y_HELP, true); + } g.flip(); } diff --git a/apps/devstopwatch/bangle1-dev-stopwatch-screenshot.png b/apps/devstopwatch/bangle1-dev-stopwatch-screenshot.png index b668794b1f94f728fff6fbce8cfcfdc3c28e7787..8a9c9b46e33b4aa403bc90a43e0e4eca14b908ac 100644 GIT binary patch literal 2469 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 Z7IZMz?QhEcvOf^uGQ`cL@{-@9-vN`~z(@c9 literal 0 HcmV?d00001 From 30f8546319c83f79221fa73dcc9708aa6f131b31 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:17:23 +0100 Subject: [PATCH 069/169] Update README.md --- apps/devstopwatch/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md index c068aadfe..efead677b 100644 --- a/apps/devstopwatch/README.md +++ b/apps/devstopwatch/README.md @@ -5,11 +5,13 @@ stores state at kill Look and control: ![](bangle1-dev-stopwatch-screenshot.png) + BTN1: start/lap BTN2: launcher BTN3: reset ![](bangle2-dev-stopwatch-screenshot.png) + TAP top right: start/lap TAP bottom right: reset Use BTN to get to launcher From 382dce1176f8794fd117f587825fac2bb3453e9d Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 00:18:52 +0100 Subject: [PATCH 070/169] Update README.md --- apps/devstopwatch/README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/devstopwatch/README.md b/apps/devstopwatch/README.md index efead677b..02a13151f 100644 --- a/apps/devstopwatch/README.md +++ b/apps/devstopwatch/README.md @@ -2,17 +2,17 @@ stores state at kill -Look and control: - +## Bangle 1 ![](bangle1-dev-stopwatch-screenshot.png) -BTN1: start/lap -BTN2: launcher -BTN3: reset +* BTN1: start/lap +* BTN2: launcher +* BTN3: reset +## Bangle 2 ![](bangle2-dev-stopwatch-screenshot.png) -TAP top right: start/lap -TAP bottom right: reset -Use BTN to get to launcher +* TAP top right: start/lap +* TAP bottom right: reset +* Use BTN to get to launcher From dfd04df0f3d6237559e8319957eca9c0c5021f39 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 12 Jan 2022 07:20:08 +0100 Subject: [PATCH 071/169] Fixed weather --- apps/lcars/lcars.app.js | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/lcars/lcars.app.js b/apps/lcars/lcars.app.js index 0005e9016..2674d323f 100644 --- a/apps/lcars/lcars.app.js +++ b/apps/lcars/lcars.app.js @@ -138,7 +138,7 @@ function printData(key, y, c){ } else if (key == "TEMP"){ var weather = getWeather(); - value = locale.temp(parseInt(weather.temp-273.15)); + value = weather.temp; } else if (key == "HUMIDITY"){ text = "HUM"; @@ -423,14 +423,7 @@ function getSteps() { function getWeather(){ - var weather = { - temp: 0, - hum: 0, - txt: "", - wind: 0, - wdir: 0, - wrose: "" - }; + var weather; try { weather = require('weather').get(); @@ -438,6 +431,19 @@ function getWeather(){ // Return default } + if (weather === undefined){ + weather = { + temp: "-", + hum: "-", + txt: "-", + wind: "-", + wdir: "-", + wrose: "-" + }; + } else { + weather.temp = locale.temp(parseInt(weather.temp-273.15)) + } + return weather; } From 2e564e06913e10ff6f06b67477dc9d3104e92440 Mon Sep 17 00:00:00 2001 From: David Peer Date: Wed, 12 Jan 2022 07:20:52 +0100 Subject: [PATCH 072/169] Created V0.12 --- apps.json | 6 +++--- apps/lcars/ChangeLog | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..0a4a80a72 100644 --- a/apps.json +++ b/apps.json @@ -1357,7 +1357,7 @@ "shortName":"HR Alarm", "version":"0.01", "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", - "icon": "widget.png", + "icon": "widget.png", "type": "widget", "tags": "widget", "supports" : ["BANGLEJS2"], @@ -4514,7 +4514,7 @@ "name": "LCARS Clock", "shortName":"LCARS", "icon": "lcars.png", - "version":"0.11", + "version":"0.12", "readme": "README.md", "supports": ["BANGLEJS2"], "description": "Library Computer Access Retrieval System (LCARS) clock.", @@ -5184,7 +5184,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", diff --git a/apps/lcars/ChangeLog b/apps/lcars/ChangeLog index bb5270b70..702ef58b9 100644 --- a/apps/lcars/ChangeLog +++ b/apps/lcars/ChangeLog @@ -9,4 +9,4 @@ 0.09: Tab anywhere to open the launcher. 0.10: Removed swipes to be compatible with the Pattern Launcher. Stability improvements. 0.11: Show the gadgetbridge weather temperature (settings). -0.12: Refactoring and stability improvements. \ No newline at end of file +0.12: Added humidity to data. \ No newline at end of file From fcfa78cb989f9b0823c69cc70367fe78932b5fb0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:21 +0100 Subject: [PATCH 073/169] Create none.png --- apps/ac_ac/none.png | Bin 0 -> 1430 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/none.png diff --git a/apps/ac_ac/none.png b/apps/ac_ac/none.png new file mode 100644 index 0000000000000000000000000000000000000000..6f8d8ae14912ac974d77928fd613c80692486969 GIT binary patch literal 1430 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfi=L>#WAEJ z?(NKreX|WjT&Dm3pRp>oQ_HEdmiOBx=03iL^sPW(`mO0Skq@3{2jSlPg$`F}`FIh>(&$tZcyNVcu}y z(hmu_#zKc(j4acR9sj`5!+eQXVS|ZXn|p%Hggl1Er5_D#m>xHb8i_Y7qdE5E-mahY zd!O^yrH$9~_Wi%LR=%?FF5}q>>ACR*+KqS1rb~X3`(7|LA}S$V!}w^e`i9GaPGJds ze2-^Y@B1LeR9v#+^c%H}OAfr*SDJWUTkuC!`Q>#b%?4{{9O}IjSNBtP#$)G$w=N4U z=XLOVa8dRNPxhBz*W3%9-u`p>eEo8BrvCk3F0Yf&{jc+8xnq@e<$JsN>)ywfpV|EC zr){IQ{zH=r?mU&f%-NE>b-R`tF^9&%=>#} z)(YbfmznO>*11mT>e=f*^;Ge{Q&KE;wHK4w|7mAkd*+a!*r>fbo7LL7VChoVY`4?v z=gf@Gt~xLM^Sh*bhon%rRb)&4uiU3)4?gGbwp}0^vDftK{i5pq%<+OdK1G+UZ{BRW zch6IddEPN9Jb1$7w*4jBLfs92?1X^@ OErX}4pUXO@geCxFHD;9n literal 0 HcmV?d00001 From 4b4a4e117b4f436d22528cf0f8b2c5164e0beb66 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:25 +0100 Subject: [PATCH 074/169] Create custom.png --- apps/ac_ac/custom.png | Bin 0 -> 1668 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/custom.png diff --git a/apps/ac_ac/custom.png b/apps/ac_ac/custom.png new file mode 100644 index 0000000000000000000000000000000000000000..14d797ba32005a45ae28d36b2f6775989a01836a GIT binary patch literal 1668 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfz8g-#WAEJ z?(NNsMYr7qTrPh2Z$C@ZdYaeKh8K}e3TaO!hw~q}cU!!>wP^SK_uuRPv>ymyGH2q? z^?P%lg~O-iA`6GjF1v@EXBtOYGz$ZL(H~{IYt0Jw-`{$1#)0eW>W;p-bUl@+ob}R; zg{K#n-YJOUxbrmA?(l@ZrSg&K+rP#r6_|6lbNOEXw`FTtb@9H~2YC#W8r=W?UC#NZ z+kLrdtkwsAJFA+G`zzlp=6`(s_3kyV*E0Rj-JQSvZr1^J&XUS3e!b+EpXTp+rZ@Xy zs`ZEa1vNiTS{F>;y4Ux?V*fX`UoG2o zDF5Zwtp+un2ecPV;yC{vnP9V_&ZonV+U5By15-!?uFy9Z#dZS8V0qu%ac&r(RXb%fH#n z{`lrBjz0>|y(ad{b40Jd9g_9*`?oZ$Np)vJ&TqQ9bMfo7G4V4!g_iSO()%y_|K2x_ zK*0ijho`?n8~6W<(<;vnU&|F^`TU)%ecaA{n=)-aseR~c6lFXwQnC8N)P4)5`s4p* zy-#HScX-7v>vdi+wF273SIygGExPyH1Zuu`?W_GcUHn(h#HpV*%2q^9oUXSch5g>I zh6vmErJt`~tgp9mT4G-rTDEs@sr=dMFOBw9Z0qWT_oTeM7x?+#vG{ckb=$b#>+aDy zf6DgTzb{`Z=C^#fx%ZOuN1gm%yNg@hcO8GFHd&%(`;Phf7EJ%!7X`iO3Yf}Xxaq*l z-oj}c{#OUbs}?-vyl>@R7whnK<@z_v*4G>ft*?Lmbx+Zp9}&f-kFCodT;2XM(rN!& zo;|+;H*bA#>c7Pe=C2ihvpC)B?dPtZU&|gMH|12+r8B42&3aclZNv0;2iDhU?BQ;? zzf$;x();}R_bOX{^u_MzyZJY(QE;LHh^WG0rpn7)je z42{Oh!o8dVI|?lqr82Rc>+vxGDmeDEV;ZM`g|X4a84Qim)0Lw}H4Tw~_@IArAD4~) T%p(VY)e3{BtDnm{r-UW|FwpmH literal 0 HcmV?d00001 From 4039f71dd60df8137121de6631403d54544b9f66 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:37 +0100 Subject: [PATCH 075/169] Create fourfoldClockFace.png --- apps/ac_ac/fourfoldClockFace.png | Bin 0 -> 2121 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/fourfoldClockFace.png diff --git a/apps/ac_ac/fourfoldClockFace.png b/apps/ac_ac/fourfoldClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..391303b31d4d1ce4b1bacdb4bd67501a22ab53a2 GIT binary patch literal 2121 zcmeHJ`#;oq7ytVD4qr|9&S+6)t*=WWCE>%CpR~m?kDEVN4gwrDvYkbNTK051t>+=Y2lsbzbMZU+28e>zuNn zKws4@JGKA-pz81E6(YyBe+sN5e_OjGG&v|74e|8=T81bu0RUF?_i_)*p)FjA&bn@i z5FTx6E$lVyEw=L8u)X?QYQscB*dpBPfAhtg4+T;JcA9(<5pvQ;|I)MbNM2E9-Gb?o zD-pYp#M5M6G9~4t*2VK>)}`Ak@KZNjs@ja1RGMLg89o#QY05gXMizK?UNekON_F~> zNCA_TOtK8%-=aLLOykDFW(S`{b(Sxd;r9vl+9kNp@!)Ci=h}tkzwh^?&yan-*J8!; z)+hGKKOuRN{L5=OPO}=%MgAqr)~T+l*cmG0v(=ffLoLI7K{KXKx-i2lft0i2mwfz( zQvBC&H@c(!z;(&&s3TZ8jDy(IM3~WU{8{%q!$pke^YK$7+J;<{ z94j$;HHSUm{B2!#{!{j!_GO60z=S2F8RAJtZ%xbTLKV12&_Ey3t-ZRox&72E|gOvqZ1$0_Ai2leKmb)&sr7QRp@bGmLzd)zBBJ?({wG4ouiR z2?nDFA7h?^T#vKkp6XcNTvRb43|Ra|w>7lnS{Q`3ff4z;z|w!InqX<~7NUpP{``7n zxg}es2eCU|mCFf~gpf|+TOt|gefoCr$?M%WzZEG zMo>Fa&RXRcp4(0CBasTbh2P zT)QkAl9D1Ducp2w5L`NV@axfF*R@077lUgHEnKDj%4132)~AuMVNoVY*m5;>mH_dq zcnq|_;Z;I?q`0Y!izg7TjgPp@G=MSTG>5jYy(b=OY$-ULOA_9^mOM5n>ABm@Kp8v! zOt|7F<_f6FocUYzxn!)B$!WrV|FX7(o$$Jvzz-dNP7xaXkh!Qu;5YF+8R(Eq^lF9( zK8>10Q>FvoEgosd4FvgXYP_!RWAaHig2cg+o;&z$@7h9XI*SPD`cFouqIoh4*Mdv^ zf~1~z3q#xmtD3Oss+3wY>C{jbcdSKeGD1AwdNE43_p2jzf#jTi^S&&T)IHK+pO{@~ z2kZh7?cBm}T@P_9m9oonn!h5Bg*IQY_5J9QjY*=KvGl9EX+^kzTWDa@fIpuSqL$N~ zCA?I#yIDtv;3L{xek=tWvuEhJp_OYN`L!t!*s4BYQ!#NK9L>zEXQ^Z3fbT{pb@+^T z!8XufsWA73E+0}7%@$bwq(g*CHu&8WG~T%7afqEk3GRBF`H5Q2ZcB9OorlYL*16Te z(dsX>2z5#4#uOWp*U38_EJ93|TLh{YYbBEQV`(b5#F_h}^+_cf zZ%o-I*3cS}jF=Da=V#KEXM4_f6)TCp^IHd0XcGVCp4b~87 zrV9jV)BYZ{dm4xkPWe>!oK-p%3cm?2cOhZat!`qohj6X;dvh(U!_t7M83kFOR2CV` z5R)Hn8`Lktqv8h5(IVXFqDhrEfOQC}qCEhNY8h&H8UPbmMqMWXu$q3;Pg4OJ(x;}V zC_omy`&ee6JSKaR48jLbT+)w%5c|_+zZgMCH)P}eGpr|1lTMX`O8luflAOWM5;o%Y z|Ahauq=C58m!rGieJI!&rk5^n24>MbF!if`y53y)Hc&Y&d60YFZCXzVQ;6ximkxw+ zG}@cH5;MdA-){%-SR2EAnDdD+<=?6=xHQndqFPjdV7LOq$c}k*yO&x~Pnnw-xcOhF z8fVLV2_RsgWHhUehcflojCE}6rs}TtEOGbH#Q+CUIQ>+kb7iB5s%;Bmifq2oxAP`n zyS;p7fY|#f4EjUdJ9@$t*>V_P#LMd~flP_mEKz Date: Wed, 12 Jan 2022 08:50:40 +0100 Subject: [PATCH 076/169] Create twelvefoldClockFace.png --- apps/ac_ac/twelvefoldClockFace.png | Bin 0 -> 2493 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/twelvefoldClockFace.png diff --git a/apps/ac_ac/twelvefoldClockFace.png b/apps/ac_ac/twelvefoldClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..fc04d865e38f930ea094d7e03dd4729eaae70a66 GIT binary patch literal 2493 zcmV;u2}1UXP)Px;cS%G+RCr$Poo$z^Dhx(%|NoEfUCy)}k5x!QKoa)(cGiRto@^s8Y9G(%^Z6hD zP#~xR4*(9DIl}%?0Du7@v;qL^kiN&`@$n*=k?rlbhLSc8VWxBez>R6uz<9Jhb`8k- zWB{;Uv){SbuIlbxlpq9Pqu7OJ0BqFsIBj_U{|eyJG($TDF@~J782}s8x8vu4n zsTN@1^${L`eRTY6tJS6ufa@gq%S}jtwev=;y+vY41)d4s5t>+Z)V2u+uoeQXy;i`t zy%ykFrMAW)X*Ws}Ni3~4VF1>id}-~Qg{R!x_g6z%yoLP)qjXzd3M<+iReY7(Xb zYsJ^v-$vEIjx%Z!2H=5trmH{-0C1pW5$d-B01OqO6#(GS=_7amhJnxu0C4E^5j+6H zKxhR3ICT059)MvWv;qJeI(-BWz%US60RRr2K7t2e7znKZ0EbRroZyd7!bxAot&PwH zVC`p8?4jS=C>Xq{*fVCgn+hjkh&|ZUypVoCo;FWVTz(=WTZ@8BJ?lqWo z(trO*x13oQV4nE~;QLt!6@g~aem1by_FskbX}ydNo~Xc~I5Y)oS-4-Vb*`q9+Q6v5 zTE!N$FKvZM>YsPj{pX^f0xw9UV#qVYyA6X1tVrf+rma(kAHZHee&aP|U=F+*g@*CA zR^4}(z2Uv30w1r$5rZ`3aM>na@E)sgNl?i=`l`Ko3Q;@bes_3w*l`t1%RrVT&S~JD z;GR|B6abg5O5k-O(cq>ByoNALP0SV8)EkYaQy?u*yq`iw z2RYl`u4a9aej6=wHD0yqF1HUXg?JMtN;L-FUyRdN;Ll`#_i9V+7Bw@(fctOumH}7` z@{AAz?|1204&a~LPQYpmyyy4LB>|39jRChj;aeKu*{d<|)>bPEE#hiYNT(H}=Ef`U z?bdR&+%}q25Glkxx7(dGM5^XFZqY7;#-S*}U`B4$_y91K_i(CKDHf+cPf@DCwZw_4 zPB2)n!mVksZ+EK84qm{$IFtb3{#T0>~Y}+ck!A2Y`XM4)12s4DgkcWA`NFJ0YLD7x2nxtyr1n zz;B<`Io`#&zDwkRoou=t=f7O+wuCkTeAZ>jp)JIOtqxmfz+29-bB~^X^SS44%7=XQ$RQUm5m0TQLc*y1H1Asl$r22ZOXz~HTCfRn4 zfVWk_ruG2bB;U`I*X%sBYS_>ofE&aE-WKtE+5&Kkj#S?k^<3HlaEpup+@hXKTL8Ao z2)tJ1T-yP#RZal5D(Bh`fGu(YuSK;kZ2;IJD*#(m>(T~*wXy=QR!pvGSwn3-Oq6W zZ&!GaQ_j}AbGIpk=T+8S(R~L1++A)@HktuWwTJ`W?(j}mf!`zUbyPS+(Z50Pp}wJl zw|C}Jf!o8FzysBHf+Xle0AQ-Go|=hT0PydmjH$y!P-;Q}U;x(eGMy~|1MqZEY61da zrVkokrn3cL0G-SQB8X zZ<^}@fYYRM&4GjjxcOC;MJsT#ZWCT3>jAtdyuSyI4-tZ`Z%K$caWVp6Cm|!a0pI{x zD!#6=aP{3+;7Ap=hFr)BTpCpACDYX(n=EQmBW2RRrvjMjTiG*x&4G^}*xOn~t;#6@ zK265r(+BAyE*i*d01Ui8rCG9w1K^wHN=zT>!b?5_7Hv9_rUJ8gs{<@q`~q;Bj;7XB zUz2SAH1hmfPJ1+R4=F0}tkw58=e&Dm? zX@_*GT!aUB##`U4084fv?z*^C)b5Pa06dHE5mx#szGL@-I6T1CE4Np>jK{UTwDRx^ zz#b~@Z)pjSYn>%>bqBz%a^^hka+b)|9RRz^3Bb;BR^0(`RU(~1ghiZgL~~mMuycMg z9u_!DyA%N6yOgJ27X|(YT-Iz_?m;3>00000NkvXX Hu0mjfm>s5V literal 0 HcmV?d00001 From d20f6ddd1e06370dadcf0afe7debc8bf0f563334 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:43 +0100 Subject: [PATCH 077/169] Create RainbowClockFace.png --- apps/ac_ac/RainbowClockFace.png | Bin 0 -> 3493 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/RainbowClockFace.png diff --git a/apps/ac_ac/RainbowClockFace.png b/apps/ac_ac/RainbowClockFace.png new file mode 100644 index 0000000000000000000000000000000000000000..2defa759bc33a9c441c844e9f9950c6e0801ab5f GIT binary patch literal 3493 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 Date: Wed, 12 Jan 2022 08:50:48 +0100 Subject: [PATCH 078/169] Create simpleClockSize.png --- apps/ac_ac/simpleClockSize.png | Bin 0 -> 3203 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/simpleClockSize.png diff --git a/apps/ac_ac/simpleClockSize.png b/apps/ac_ac/simpleClockSize.png new file mode 100644 index 0000000000000000000000000000000000000000..49650586e01cdda1e25b2ac3aa464cb58f80d042 GIT binary patch literal 3203 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 Date: Wed, 12 Jan 2022 08:50:51 +0100 Subject: [PATCH 079/169] Create smartClockSize.png --- apps/ac_ac/smartClockSize.png | Bin 0 -> 3291 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/smartClockSize.png diff --git a/apps/ac_ac/smartClockSize.png b/apps/ac_ac/smartClockSize.png new file mode 100644 index 0000000000000000000000000000000000000000..6891acc89e7b1a3bbdd28e1d6e0944673e67aace GIT binary patch literal 3291 zcmV<13?%c3P)Px>l}SWFRCr$Poza#nDF{Vx{{N$MS0!B?W2=AyqMmt~HC-0MVN0QvWFF7w^Z5_| zK!HUScmUu3?8xK>~a-a8e5cpoSwk^J(}I#&2;joB?k3py!i)C!}nOT@s~^%MZW z>*Wj{Ckg;y;IOm;0C?&2!FdyawPfXP;INU?QhYr-CID+3qe!Vr>4tYb{Kh>t z0eIZ4f3Gv-{GU9boG}`{XxZSvNsXbdYx%m09RRGDDGDy?`sE5WX7svZxFJjdV8t|e zz~wQAq9o>~mIC-vsd*hCF9{}#mNM6D2|E@vUs(8Cp!%iuOZVL}^ z)Z|`%rLa-}x3Uy1#%TUDwTu4KQmcpwfQJfc_syul-O_#E*b8vP1sc((TAIQGti+eO znI3>8Cm7}dEII)IR!W={V8E**dOvj-cU;B^Nz(kw*a_6gLl#;KuX7Y$8rR~(j<(ImnKm3HvWB=hYQ3jk*R-*k6M`cAP-0eDtVR648WzA@S<=@DY_V8HAc&BOWH*(dd= z^?JEL`Js7TdM>Rwcg>au0|1zjNp1yam@*pzfX$?ZVJKjyfLR5$a~YPQz()Z93>ubJ z001wYJ~*!iu*Z%Q=~`O>3q}C&+Dt6vJpf)RU2wK_POo(|saAn|(j{Gy`B|ry2tB@^ zdQY?*OaoXV1a(LcknNXK)Eu}2ToZ!(ZQfF<05AZySKw!cyltR9bkb@wq%DYBkef{u zIR{fJu=Jb57Z0T>3xMaZl-W7x23X5+ZUqLw^I3;S z0C)*h;yEcfMXGr}6<{q%(L!h`>1Rg+UM+9CE3ldakH^at^_ybofwdIxw-X86;U2hO zhVMI3fwh#hwG$EEp&nREE&!~hq^%u|e$~Q5Q43)a1Q+1E&9LyrLf{>2dT8A{hdaR3 zJM}x^rI#Hw81O3DcA50#OzP3r0Ka;jpUqw_4B(ZbA|JmE!1B;>2NbYXK-5Cmx&rG^ zK&}7)mTQJP0x1B110@5l$Q1y_rz1`4oRhz;UI2%9PZfXxznea`u5W*vs#3IJd;5&*E7w25H=Y^E{*Hj@?r zyGV-`!a?R{1(qIZIQYBJ6sW)>$>OpHfJam&?*+u9M3n)d0FL^Fz+Q3r_nil@R<2b5 z<|nE=lKLe7{@Hywj{xrDK@X%^md*fpX0FWv zKKU1Q&RMAS0%5HI05&SlSK^+pH_7kU$?yL@@73~DfJY{8{b0$6T_fI9&3<70ZXr&A zxU~0?E?zDpX6L{)2egh^REbkI27uo`*qHva9KiQulVU>}7-cWQbpRX$U=0{fJxa?V zKBaxgnc=nqy{wsS;#v+_2h}Tv)_pguyT{4V%UT07fKT1TrIj{6iQpuB#W6E;Z4U73 zASpRMvR;uh0r(5=b!@i(%M8wj-DCo!7 zazSh7x_|$U3T&Bs(@mVE7DWw``p8sKET3NLgdG5K^Oj zcVmrgwG1_QQ;_Sm04)SJ(^A#|@Q<=mcwe1u_BElp4FEh9VD99rj-%i$wF$hJ7{7J< znAgeP46rJ&w^N?;ap0|evpWBj9a;#_%>A72a5i!NZu!ip1#hXH_>KTAgjGh5t-vX~ z+!mp#jS#gEl8uaHtQABv?H&nmY4dd@fpelD>wVMI(h#RG-gnm8lG0e}o|&Lo z&3zQWwKLoF@6xt{8vjXL8{is{l3zCBok?4vG{>$8V5`Sfo;=386|q_^(718+S6{k~ z$QMzonzlgogqW)vCt1C=rUKl045p8CjsUGORF&i=z0`W}7aQF|q&;?YfVGPb0Im>B z!FzAQN(+X1tW(!}Pa>#fMyS9`0z6s?zqT}w&#$-SRg6j?*AEKbRuVXyB+eLa56so3 zwcx00T-~T~rMUS|BFeh#x~PSanQo8fRFTm(g6ex~AIK>!p!{z&`0I;rj}}7q)X^lS zY->8e)T4W3W!C^M^|GlS`Qp0Ar+;rfCCZC)eSlkwcqC6Fm`?*ZecaUo7!@T2HHEO& zva~Alb*+{_%HBJ^eE`mN8huhu0a&9?mGzMFF!RdEt@e4P&EdW6)Y_m~6<8xDHI+GS zl{7;d{&rVjmC2KhTq*d`3e2hU_q?r*WbPaFVfK1|U$4Tg#a!~ydhv5Mm7@%d-v7#P z?}vFtCztn-()Im4o&p2_*Y%~es}%t%W1|cW0ZchZU9VTE_Xov$Md8lNu}}59vKFG< z2Xi2iyjG@kkX+~ZHmeWruD}ujN@HgMEb%+t1m5k)SX;y2$VvR1HP*7waATSdaK3UQ zh*EBf+cFJ^)~g zWu^vjgw?1ekWKa74`8X@7K{MkEDNPRcf9w#C)uk92EbAU9LC#KUsT}G71)6-mnm!k z2E^J)RBIu$9h+g#wtYYwVUbe+oTzGFeNln6AqK!diuzPv0K5#q77aT$_?~z7KGoL_ z;GUSddiIXz|>I;B-7eh7Iy&tEf99bD)y>s7^N;YS~(nU+=DS_Q9h1=0{r}u=Fc%M7VnLB)!MA z0!y9K8t+|wsWaJk*YasywBoGUnbn_K$MxE?oKS(itM3ee^BBJx7Q>$@@PM@Wbcq14 zb%n@}m`XjO)(*WD%f}D>3S664TU%{=qYEHJ1-2B0Y9F+F-&Q63B+I4;rYrw=+hUok z9+-~-*z3(3?}dU5!1pvg_k;j=Gzjkf9xpDaD)>2OvV)kb#}4C;23Wg& zXjQ-zmUlG-z#0oEJiwYgSN&X8L&~=e&L-|%h4nXbT2W|fuH{qph%mw_MDv(ru_GY< zaTWm9fcvNltRWa>0{~MB>0S>Hux_~a)^-5cUM0O50I;5x%^vt~Ux`hehV)AV9Cfon z9i>G$g@~%16lwr0Rg5{l2Jx&V}JwTG5rSb2Ec;??)!oEHL4E)2Ed&P!~lE@;21G@@kCn#&;7ax= zc&O_dfO6(o89oi)0dS{^9Jr`4)b&o+j=Bv18>Sn88jAa48UWjCj2R3S0KkUg!nC~t Z{{b@j@|O7s$qE1f002ovPDHLkV1h@MC+z?L literal 0 HcmV?d00001 From 4fcad7444e3d6bcf2334ecf48c520704a71f8632 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 08:50:53 +0100 Subject: [PATCH 080/169] Create simpleClockHands.png --- apps/ac_ac/simpleClockHands.png | Bin 0 -> 1446 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/simpleClockHands.png diff --git a/apps/ac_ac/simpleClockHands.png b/apps/ac_ac/simpleClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..820606f27cc11a8cbce78c9d8ef2da401f61dc12 GIT binary patch literal 1446 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfi=O?#WAEJ z?(N;zWs4$2S}%V3D}PHa?a8%HH> zcK*G_a6n;+G=qh$-9yGSg}V#~UVh}{H(-9r#^BfQU(q1xVa`xcRda~>jKeO*hRctI zpQFVAN_lJhh{_eLbUNg

zG{7^zIy>?kTHy4;|a4cR+f^ zi5MlYrYOq{nf0@GOs(bl{q3RhVa5DMe(#yB^FK&49bWX8V_Wmu>K)2Q*dO%U|4>wX zpYd9b>x2KEc9%Vy*H%j$*#1F|>to-?cmLGh$vyC9+->Xk=F5qK9kX|6c9gSMK9Bxx z;NG!b`u+FwnmaysDD3a$-&D%a{zLFYy=|rSe_OdeRI47I-~DiJ zl@!a5XkBNevXmd6U)mlBe>Ib-aV!@zV58R?Opr_w>HYJ$>w@;vwr5yUHpEJUq3bbzC7w*yynKyTE+?{|OoA_dD!zXfM9c^kC=Nzd!b6cjy=B$J^H{ z=YM;=t##A8m$?ja6|?5cCzrCmi=W<9bx(m|-u2sW-&gGqoc*o(LVdi Date: Wed, 12 Jan 2022 08:50:56 +0100 Subject: [PATCH 081/169] Create roundedClockHands.png --- apps/ac_ac/roundedClockHands.png | Bin 0 -> 1390 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/roundedClockHands.png diff --git a/apps/ac_ac/roundedClockHands.png b/apps/ac_ac/roundedClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..cbd48e856985e2cb0c840b2336394bcb719f788a GIT binary patch literal 1390 zcmeAS@N?(olHy`uVBq!ia0vp^8$g(Y4M?uv{v-}aF%}28J29*~C-ahlfmOrP#WAEJ z?(LnoeYYY6SS~#MD?dy0qLARU{%%9zU9X;`A8T8;PWd(46ib=@VF3?1;uUF*euUzCW1E zxZbW;abB;5)CaAk{|9DwTgVw4DK1>+6UTUCXGQCwGuf*cfGXy8KTlZ4yr&B&#`ehT zfWY|!JB?Cx6P`a3mAhZ>Yy05p@{PqG%ahoC?2ilEx3gI9pWP9L_!6d%-x+Jo1P_>- zZDG1O@sZ@(`9CcWlz-#-c%Gr=dn`lUhJ&I<&K-R(RP(;BVg4KbN8cN2f8{lZo9|(| zxwE2hrga?K2kz4?KU!1&URcVof5!`uYJI)0y{8%PZP+7vWP6|R^4~JXW;%Z^+HdJM z+f}*vyTbgis`uh+9QIV+HP8RTa&O1^@Q?HEKkK<&oc#FF`aI@}$8z$viSzfW>^X0? ziZH)zlAlFulsjz^0!~_ zx7SVD_<6_Uc)ka7wPRX$7Tx`t(I@v`pZkF<<9vIi>TlU`+aK&TPqWTyC}*juTIt^L zzSeHfXO7VLX$*U|&*MIFUH|W!lQorp=lQ?9{Cb()O2&T-58U;CzTlpazW7b26|2dC z^H*vfJpXRzeD71(+ZBxW7NxaU+xl~36M3W_ Date: Wed, 12 Jan 2022 08:50:59 +0100 Subject: [PATCH 082/169] Create hollowClockHands.png --- apps/ac_ac/hollowClockHands.png | Bin 0 -> 1669 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/hollowClockHands.png diff --git a/apps/ac_ac/hollowClockHands.png b/apps/ac_ac/hollowClockHands.png new file mode 100644 index 0000000000000000000000000000000000000000..2dce42ef598eece0c07beaf0fe57fb6b38555834 GIT binary patch literal 1669 zcmeHI`#02i82)@`%#g@V%E=5iO|eMGu`^OExisVwyRk8Ju*z)=a=%Rx$EnS#M2Fp3 zotW%oMvVI~-?hogEv6z3^W}(!#tf~?4#w)Vf5QH_KfKTLoacGZdEfK?@)r7dxoN87 z)d2vSlrzr0J6!jv)UZ3qZJr6}mg@z}G4K0r`BUqRB6e?SIK8-^pThVMX!I1LdOK0)lvn&z0o>K6uv)AR|)0ld#7B z>eCGn9>b!vZ*(Qyd_u3AYfLwVNxU^KVRA#@7+m0!)GYymt|+|!yVl^feT+D(vS$ki zOgUv(d53Lvyi0YT4O3m7HNu%lGql&5Hi6tKnXG}iEsB?F3x<^upEbr(5h)%Hlsq^# zBSg`%MzHaoPg$y>^s0aiR6xVPTy45KZ0@hVHhp1?1$}Tow>yG2E&=Vn&XF$zNJo&@ zX4f;8TFO`$Q9>2n0-GvQ=@h@$zF!|4Md1D@^hWMcLq&GA_`h1qH0ux5Ew|p2RSNt!}D{;xV&t6s1|tLT3vEq+GKHV7u8QlvyP7b*&g8hssb*G%xuk^P)3zMDh~_F z0x%obXp#CXW4kf_BU?x6=DnuINV#ka+vT;@9f9q_x4x7M?=;IjXm&5Jyf%j>YZ`KJ z;#Fn#=o_|pW^1F#p{t_`1L7#Mi7)}PWuo+`K~&PCI@Gnt}> zvzHjVq5L=clY8g*4_~eq9rjJ3lq{z7GD+l{!KXu z<0^`6(5TK*{f^MgHv7Fp!O>vwO!7s(ho7w?A<#^DlN`7TT8`9KHC_if2_Xh)$I<-# z^mF`6_xk~Q)9mW&=s$|RQ4n@L7FAo8A(+&V>%hjX_RhouIBR%#u_GHw8W((Q$0W|O ze1LMFJY2X&JzHC5?eMdvCCoIEFURBh0n1hSdqj2ISG+3kk`|}D>9_GX*mKIYIzgDP zb%Sbn;ZAO|%@gVo~yCyYv-V3~{%XtddMD zKx@#S_SQuMY-&J7aTf@7?_DvRo|D@EbSAmW90N8@PYF|Q)NqP02M`WYuZ3Q>Jtri+ z9ph|38gdT2I;n^B1&f6E()88 zETtPHa!52bGNRMq>bOHCR?R0!h?TYfccG|%CxXv8pof+<%`*YKWt|fG--U8j>OiIW U{v?a^oxcJoE?&+Yr;FGA0bv~;9{>OV literal 0 HcmV?d00001 From 657cf26dc54e0b94bac8baa9cd865493202e2a37 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 09:43:39 +0100 Subject: [PATCH 083/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 531 ++++++++++++++++++++++++++++++++++--- 1 file changed, 491 insertions(+), 40 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 6637b5df4..203235e3d 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -19,73 +19,524 @@ } + + + + + + + + + + - - - + + + -

A Configurable Analog Clock

- +

Please customize your analog clock for the Bangle.js 2 according to your needs. - When finished, click on "Upload". + When finished, click on "Upload" at the bottom of this form. +

-

Clock Size Calculation

+

Clock Size Calculation

-
-
- -  
+

+ Click on the desired clock size calculator (if you installed some widgets + on your Bangle.js 2, the smart one may produce larger clock faces than the + simple one): +

+ + + -

Clock Face

+ -
-
-  
-
-  
-
-  
+ + +
+
+ simple +
+
+ smart +
+
+ (custom) +
+

+ If you prefer a "custom" clock size calculator, please enter the URL + of its JavaScript module below: +

+ custom URL: +

-

Clock Hands

+

Clock Face

-
-
-
-   Hand Fill Color
+

+ Click on the desired clock face: +

+ + + -

Complications

+ -

Settings

+ - Foreground Color:
+ - Background Color:
+ + +
+
+ none +
+
+ four-fold +
+
+ twelve-fold +
+
+ "rainbow"
colored +
+
+ (custom) +
+

+ Clock faces are drawn in the configured foreground and background colors + (you may select them at the end of this form) +

+ The "twelve-fold" and "rainbow"-colored faces may be drawn with or without + dots marking the position of every minute. Which variant do you prefer? +

+ without dots
+ with dots +

+ If you prefer a "custom" clock face, please enter the URL + of its JavaScript module below: +

+ custom URL: +

- Second Hand Color:
+

Clock Hands

+

+ Click on the desired clock hands: +

+ + + + + + + + + + +
+
+ simple +
+
+ rounded +
+
+ hollow +
+
+ (custom) +
+

+ Clock hands are drawn in the configured foreground and background colors + (you may select them at the end of this form) +

+ Additionally, all clock hands may be drawn with or without second hands. + If you want them to be drawn, please click on their desired color below + (or choose "themed" to use your Bangle's configured theme) - if not, just + select "none": +

+ Second Hand Color:
+ + + + + + + + + + +

+ If you prefer "custom" clock hands, please enter the URL + of their JavaScript module below: +

+ custom URL: +

+ +

Complications

+ +

+ Complications are small displays for additional information. If you want + one or multiple complications to be added to your clock, you'll have to + specify which one to be loaded and where it should be placed. +

+ Up to 6 possible positions exist (top-left, top-right, left, right, + bottom-left and bottom-right). Alternatively, the positions "top-left" and + "top-right" may be traded for a slightly larger complication at position + "top" or "bottom-left" and "bottom-right" for one at the "bottom". +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
top-left:
  Complication: + +
custom URL:
top:
  Complication: + +
custom URL:
top-right:
  Complication: + +
custom URL:
left:
  Complication: + +
custom URL:
right:
  Complication: + +
custom URL:
bottom-left:
  Complication: + +
custom URL:
bottom:
  Complication: + +
custom URL:
bottom-right:
  Complication: + +
custom URL:
+

+ +

Settings

+ +

+ Color faces, hands and complications are often drawn using configurable + foreground and background colors. +

+ Here you may specify these colors. Click on a color to select it - or on + "themed" if you want the clock to use the currently configured theme on + your Bangle.js 2: +

+ Foreground Color:
+ +

+ +
+ + + + + + + + +

+ Background Color:
+ + + + + + + + + +

+ When you are satisfied with your configuration, just click on "Upload" in + order to generate the specified clock and upload it to your Bangle.js 2: +

+

From 10896c63ddb881ececcf1749c142989c07062dc0 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:07:15 +0100 Subject: [PATCH 084/169] Create app-icon.png --- apps/ac_ac/app-icon.png | Bin 0 -> 4120 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/app-icon.png diff --git a/apps/ac_ac/app-icon.png b/apps/ac_ac/app-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..b83541133fb2fcdcc215cf294baa7f5565215f58 GIT binary patch literal 4120 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 WA~L?Y2T6SZ0000 Date: Wed, 12 Jan 2022 10:07:18 +0100 Subject: [PATCH 085/169] Create app-icon.js --- apps/ac_ac/app-icon.js | 1 + 1 file changed, 1 insertion(+) create mode 100644 apps/ac_ac/app-icon.js diff --git a/apps/ac_ac/app-icon.js b/apps/ac_ac/app-icon.js new file mode 100644 index 000000000..20caf2c8e --- /dev/null +++ b/apps/ac_ac/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEwgn/ABH+AQPvBpIAI/n8/3f5/PCp/v9oHF7w1CABffGxAYMH4f9z/514YDCxW/O4gFBxwHD/ZEL7/9GgX8GwQLCBQQXH/uP/Hf/2N44IBAgIXJ7oaD/3v/3uAYIIB9wQGAA2+/iRG5oSIM4f+1nrPYgAB3aHIAC77QYYRoCAAP676ICABXYFIntDoPf3+PC5f+BoPOX4vPNBn7IogEB/eu3QXC9wNEAAeKBIP+dgbSCDYMwgEApQVEygPCeRH8iAWBAAMHPwXDgoRGAonACwYABgN5uMAC4q8GC4U0DQsAggRF9gXFgggB/2hC4kdVAQCBVAX7xwXCVAnGCwUadAeeDYfr7IhEAAf93e+A4gpB9yRB/mqcgndRgQAHzqRE1gEC/KoCjLZEsgCB9evO4gOC/RyEgqdC2KnFO4S/KgFYsC/Ga5EBs1AX5bXHgx1C2YXEnp7GCARgB4AfE64WCnawFCgf9VAK/G/3M7zWDz4PF/maXJIAD7D8EVAP85QXN3OP/42DfoQXN/wvE/ySGABa8FAC37AgepVwQ9E1SfBAAJIEAAnrBQ39xgwJ7pRHFQX+3QECCAbyG9bPDzwXC9QMBdgQXIAAf41wEC5pLCJJBcF9fZQ5IAGYYn81q7RJQwWC/wXM9/tA4veCxooDIAPv55PEABwpB97rDAAw")) \ No newline at end of file From 54ad33318a382b741a41e9d5fce4ad9b869449ae Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:08:42 +0100 Subject: [PATCH 086/169] Update README.md --- apps/ac_ac/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/ac_ac/README.md b/apps/ac_ac/README.md index 0e0084b64..05e5f4798 100644 --- a/apps/ac_ac/README.md +++ b/apps/ac_ac/README.md @@ -22,10 +22,10 @@ Additionally, you may use the currently configured global theme or configure your own colors for clock fore- and background and second hands. Consequently, even without external modules you already have the choice between -87552 combinations! +102144 combinations! From 5e353b6755d97021a349a980db632aef75486bff Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 09:14:33 +0000 Subject: [PATCH 087/169] messages : If showMessage called with no message (eg all messages deleted) now return to the clock (fix #1267) --- apps/messages/ChangeLog | 1 + apps/messages/app.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/messages/ChangeLog b/apps/messages/ChangeLog index 0c02a76e1..522534af0 100644 --- a/apps/messages/ChangeLog +++ b/apps/messages/ChangeLog @@ -27,3 +27,4 @@ 0.18: Use app-specific icon colors Spread message action buttons out Back button now goes back to list of messages + If showMessage called with no message (eg all messages deleted) now return to the clock (fix #1267) diff --git a/apps/messages/app.js b/apps/messages/app.js index 4704c422f..80e4a3244 100644 --- a/apps/messages/app.js +++ b/apps/messages/app.js @@ -225,7 +225,7 @@ function showMessageSettings(msg) { function showMessage(msgid) { var msg = MESSAGES.find(m=>m.id==msgid); - if (!msg) return checkMessages({clockIfNoMsg:0,clockIfAllRead:0,showMsgIfUnread:0}); // go home if no message found + if (!msg) return checkMessages({clockIfNoMsg:1,clockIfAllRead:0,showMsgIfUnread:0}); // go home if no message found if (msg.src=="Maps") { cancelReloadTimeout(); // don't auto-reload to clock now return showMapMessage(msg); From 3e6cfc95a9c4aaa6991dbe30c9b82fca681c87a8 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 10:27:39 +0100 Subject: [PATCH 088/169] Improve layout and add exit menu item --- apps/banglexercise/README.md | 6 +++--- apps/banglexercise/app.js | 14 +++++++++----- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index 9d8ee7be4..729fb60e3 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -6,7 +6,7 @@ Currently only push ups and curls are supported. ## Disclaimer -This app is very experimental. +This app is experimental but it seems to work quiet reliable for me. It could be and is likely that the threshold values for detecting exercises do not work for everyone. Therefore it would be great if we could improve this app together :-) @@ -25,8 +25,8 @@ Press stop to end your exercise. * Rope jumps * Sit ups * ... -* Save exercises to file system -* Add settings (vibration, beep, ...) +* Save exercise summaries to file system +* Configure daily goal for exercises * Find a nicer icon diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index f5a532408..778207d26 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -81,6 +81,9 @@ function showMainMenu() { value: exerciseCounter + " " + exerciseType.name }; } + menu.Exit = function() { + load(); + }; E.showMenu(menu); } @@ -187,6 +190,7 @@ function isValidYAxisExercise(slopeY, t) { console.log(t, exerciseName + " half complete..."); layout.progress.label = "½"; + g.clear(); layout.render(); } @@ -215,6 +219,7 @@ function isValidYAxisExercise(slopeY, t) { layout.count.label = exerciseCounter; layout.progress.label = ""; + g.clear(); layout.render(); if (settings.buzz) @@ -279,10 +284,9 @@ function startRecording() { c: [{ type: "txt", id: "count", - font: "6x8:10", - label: exerciseCounter, - pad: 5, - bgCol: g.theme.bg + font: exerciseCounter < 100 ? "6x8:9" : "6x8:8", + label: 10, + pad: 5 }, { type: "txt", @@ -328,7 +332,7 @@ function startRecording() { stopRecording(); } }], - lazy: true + lazy: false }); layout.render(); From 4b8490645d11ca3c69ff99a4b78c6fbd8b4dc60f Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 10:31:05 +0100 Subject: [PATCH 089/169] Fix typo and disable debug logging --- apps/banglexercise/README.md | 2 +- apps/banglexercise/app.js | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/banglexercise/README.md b/apps/banglexercise/README.md index 729fb60e3..28b276a59 100644 --- a/apps/banglexercise/README.md +++ b/apps/banglexercise/README.md @@ -13,7 +13,7 @@ Therefore it would be great if we could improve this app together :-) ## Usage -Select the exercise type you want to practive and go for it! +Select the exercise type you want to practice and go for it! Press stop to end your exercise. diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 778207d26..99ebd121e 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -187,7 +187,7 @@ function isValidYAxisExercise(slopeY, t) { if (p1 > 0 && p2 < 0) { if (lastZeroPassCameFromPositive == false) { lastExerciseHalfCompletionTime = t; - console.log(t, exerciseName + " half complete..."); + //console.log(t, exerciseName + " half complete..."); layout.progress.label = "½"; g.clear(); @@ -201,7 +201,7 @@ function isValidYAxisExercise(slopeY, t) { if (lastZeroPassCameFromPositive == true) { const tDiffLastExercise = t - lastExerciseCompletionTime; const tDiffStart = t - tStart; - console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); + //console.log(t, exerciseName + " maybe complete?", Math.round(tDiffLastExercise), Math.round(tDiffStart)); // check minimal time between exercises: if ((lastExerciseCompletionTime <= 0 && tDiffStart >= thresholdMinTime) || tDiffLastExercise >= thresholdMinTime) { @@ -212,7 +212,7 @@ function isValidYAxisExercise(slopeY, t) { // check minimal duration of exercise: const tDiffExerciseHalfCompletion = t - lastExerciseHalfCompletionTime; if (tDiffExerciseHalfCompletion > thresholdMinDurationTime) { - console.log(t, exerciseName + " complete!!!"); + //console.log(t, exerciseName + " complete!!!"); lastExerciseCompletionTime = t; exerciseCounter++; @@ -225,15 +225,15 @@ function isValidYAxisExercise(slopeY, t) { if (settings.buzz) Bangle.buzz(100, 0.4); } else { - console.log(t, exerciseName + " to quick for duration time threshold!"); + //console.log(t, exerciseName + " to quick for duration time threshold!"); lastExerciseCompletionTime = t; } } else { - console.log(t, exerciseName + " to slow for time threshold!"); + //console.log(t, exerciseName + " to slow for time threshold!"); lastExerciseCompletionTime = t; } } else { - console.log(t, exerciseName + " to quick for time threshold!"); + //console.log(t, exerciseName + " to quick for time threshold!"); lastExerciseCompletionTime = t; } } From 797d5fbd8185f6459187c494b5433b12a5732f84 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:57:10 +0100 Subject: [PATCH 090/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 186 +++++++++++++++++++++---------------- 1 file changed, 106 insertions(+), 80 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 203235e3d..59c08f2cd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -26,11 +26,12 @@ default-src 'self' 'unsafe-inline' 'unsafe-eval' file: https:; "> - + + - + @@ -279,23 +302,24 @@ (or choose "themed" to use your Bangle's configured theme) - if not, just select "none":

- Second Hand Color:
- - - - - - - - - - + Second Hand Color: +

+ + + + + + + + + +

If you prefer "custom" clock hands, please enter the URL of their JavaScript module below: @@ -504,33 +528,35 @@ "themed" if you want the clock to use the currently configured theme on your Bangle.js 2:

- Foreground Color:
- -

- -
- - - - - - - - + Foreground Color:

- Background Color:
- - - - - - - - - + + + + + + + + + +

+ Background Color: +

+ + + + + + + + +

When you are satisfied with your configuration, just click on "Upload" in order to generate the specified clock and upload it to your Bangle.js 2: From f878a336529815a2ea358361d9a748fb5599cda1 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 10:58:21 +0100 Subject: [PATCH 091/169] Create app-screenshot.png --- apps/ac_ac/app-screenshot.png | Bin 0 -> 4042 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 apps/ac_ac/app-screenshot.png diff --git a/apps/ac_ac/app-screenshot.png b/apps/ac_ac/app-screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..e0e3bb0b95de844ed0656d16023e71708c117f96 GIT binary patch literal 4042 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 literal 0 HcmV?d00001 From ffcdcbce6bf15fc19bc605130235dbd608f3d913 Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 11:24:04 +0100 Subject: [PATCH 092/169] Rename "recording" to "training" (because there is no recording for now) --- apps/banglexercise/app.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/banglexercise/app.js b/apps/banglexercise/app.js index 99ebd121e..0d5c814bf 100644 --- a/apps/banglexercise/app.js +++ b/apps/banglexercise/app.js @@ -69,7 +69,7 @@ function showMainMenu() { menu["Do " + et.name] = function() { exerciseType = et; E.showMenu(); - startRecording(); + startTraining(); }; }); @@ -263,7 +263,7 @@ function reset() { } -function startRecording() { +function startTraining() { if (recordActive) return; g.clear(1); reset(); @@ -319,7 +319,7 @@ function startRecording() { type: "txt", id: "recording", font: "6x8:2", - label: "RECORDING", + label: "TRAINING", bgCol: "#f00", pad: 5, fillx: 1 @@ -329,7 +329,7 @@ function startRecording() { btns: [{ label: "STOP", cb: () => { - stopRecording(); + stopTraining(); } }], lazy: false @@ -344,7 +344,7 @@ function startRecording() { Bangle.buzz(200, 1); } -function stopRecording() { +function stopTraining() { if (!recordActive) return; g.clear(1); From ea44abb791634b60c454dbfb746c493ffac20614 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 10:58:47 +0000 Subject: [PATCH 093/169] android 0.06: Option to keep messages after a disconnect (default false) (fix #1186) --- apps.json | 8 ++++--- apps/android/ChangeLog | 1 + apps/android/README.md | 48 ++++++++++++++++++++++++++++++++++++++++ apps/android/boot.js | 6 ++++- apps/android/settings.js | 20 +++++++++++++---- 5 files changed, 75 insertions(+), 8 deletions(-) create mode 100644 apps/android/README.md diff --git a/apps.json b/apps.json index 882816204..bb55dcc17 100644 --- a/apps.json +++ b/apps.json @@ -99,18 +99,20 @@ "id": "android", "name": "Android Integration", "shortName": "Android", - "version": "0.05", + "version": "0.06", "description": "Display notifications/music/etc sent from the Gadgetbridge app on Android. This replaces the old 'Gadgetbridge' Bangle.js widget.", "icon": "app.png", "tags": "tool,system,messages,notifications", "dependencies": {"messages":"app"}, "supports": ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", "storage": [ {"name":"android.app.js","url":"app.js"}, {"name":"android.settings.js","url":"settings.js"}, {"name":"android.img","url":"app-icon.js","evaluate":true}, {"name":"android.boot.js","url":"boot.js"} ], + "data": [{"name":"android.settings.json"}], "sortorder": -8 }, { @@ -1357,7 +1359,7 @@ "shortName":"HR Alarm", "version":"0.01", "description": "This invisible widget vibrates whenever the heart rate gets close to the upper limit or goes over or under the configured limits", - "icon": "widget.png", + "icon": "widget.png", "type": "widget", "tags": "widget", "supports" : ["BANGLEJS2"], @@ -5185,7 +5187,7 @@ {"name":"mmind.app.js","url":"mmind.app.js"}, {"name":"mmind.img","url":"mmind.icon.js","evaluate":true} ] - }, + }, { "id": "presentor", "name": "Presentor", diff --git a/apps/android/ChangeLog b/apps/android/ChangeLog index c2c4ea6be..0d837fe43 100644 --- a/apps/android/ChangeLog +++ b/apps/android/ChangeLog @@ -4,3 +4,4 @@ 0.03: Handling of message actions (ok/clear) 0.04: Android icon now goes to settings page with 'find phone' 0.05: Fix handling of message actions +0.06: Option to keep messages after a disconnect (default false) (fix #1186) diff --git a/apps/android/README.md b/apps/android/README.md new file mode 100644 index 000000000..c10718aac --- /dev/null +++ b/apps/android/README.md @@ -0,0 +1,48 @@ +# Android Integration + +This app allows your Bangle.js to receive notifications [from the Gadgetbridge app on Android](http://www.espruino.com/Gadgetbridge) + +See [this link](http://www.espruino.com/Gadgetbridge) for notes on how to install +the Android app (and how it works). + +It requires the `Messages` app on Bangle.js (which should be automatically installed) to +display any notifications that are received. + +## Settings + +You can access the settings menu either from the `Android` icon in the launcher, +or from `App Settings` in the `Settings` menu. + +It contains: + +* `Connected` - shows whether there is an active Bluetooth connection or not +* `Find Phone` - opens a submenu where you can activate the `Find Phone` functionality +of Gadgetbridge - making your phone make noise so you can find it. +* `Keep Msgs` - default is `Off`. When Gadgetbridge disconnects, should Bangle.js +keep any messages it has received, or should it delete them? +* `Messages` - launches the messages app, showing a list of messages + +## How it works + +Gadgetbridge on Android connects to Bangle.js, and sends commands over the +BLE UART connection. These take the form of `GB({ ... JSON ... })\n` - so they +call a global function called `GB` which then interprets the JSON. + +Responses are sent back to Gadgetbridge simply as one line of JSON. + +More info on message formats on http://www.espruino.com/Gadgetbridge + +## Testing + +Bangle.js can only hold one connection open at a time, so it's hard to see +if there are any errors when handling Gadgetbridge messages. + +However you can: + +* Use the `Gadgetbridge Debug` app on Bangle.js to display/log the messages received from Gadgetbridge +* Connect with the Web IDE and manually enter the Gadgetbridge messages on the left-hand side to +execute them as if they came from Gadgetbridge, for instance: + +``` +GB({"t":"notify","id":1575479849,"src":"Hangouts","title":"A Name","body":"message contents"}) +``` diff --git a/apps/android/boot.js b/apps/android/boot.js index 59ffe006d..fff9ad444 100644 --- a/apps/android/boot.js +++ b/apps/android/boot.js @@ -4,6 +4,7 @@ Bluetooth.println(JSON.stringify(message)); } + var settings = require("Storage").readJSON("android.settings.json",1)||{}; var _GB = global.GB; global.GB = (event) => { // feed a copy to other handlers if there were any @@ -51,7 +52,8 @@ // Battery monitor function sendBattery() { gbSend({ t: "status", bat: E.getBattery() }); } NRF.on("connect", () => setTimeout(sendBattery, 2000)); - NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect + if (!settings.keep) + NRF.on("disconnect", () => require("messages").clearAll()); // remove all messages on disconnect setInterval(sendBattery, 10*60*1000); // Health tracking Bangle.on('health', health=>{ @@ -68,4 +70,6 @@ if (isFinite(msg.id)) return gbSend({ t: "notify", n:response?"OPEN":"DISMISS", id: msg.id }); // error/warn here? }; + // remove settings object so it's not taking up RAM + delete settings; })(); diff --git a/apps/android/settings.js b/apps/android/settings.js index d241397a4..7c46a1fc0 100644 --- a/apps/android/settings.js +++ b/apps/android/settings.js @@ -2,17 +2,29 @@ function gb(j) { Bluetooth.println(JSON.stringify(j)); } + var settings = require("Storage").readJSON("android.settings.json",1)||{}; + function updateSettings() { + require("Storage").writeJSON("android.settings.json", settings); + } var mainmenu = { "" : { "title" : "Android" }, "< Back" : back, - "Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, + /*LANG*/"Connected" : { value : NRF.getSecurityStatus().connected?"Yes":"No" }, "Find Phone" : () => E.showMenu({ "" : { "title" : "Find Phone" }, "< Back" : ()=>E.showMenu(mainmenu), - "On" : _=>gb({t:"findPhone",n:true}), - "Off" : _=>gb({t:"findPhone",n:false}), + /*LANG*/"On" : _=>gb({t:"findPhone",n:true}), + /*LANG*/"Off" : _=>gb({t:"findPhone",n:false}), }), - "Messages" : ()=>load("messages.app.js") + /*LANG*/"Keep Msgs" : { + value : !!settings.keep, + format : v=>v?/*LANG*/"Yes":/*LANG*/"No", + onchange: v => { + settings.keep = v; + updateSettings(); + } + }, + /*LANG*/"Messages" : ()=>load("messages.app.js") }; E.showMenu(mainmenu); }) From 569c5f9e2b5ef2d59770e244db4adffed8a1d586 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 10:59:02 +0000 Subject: [PATCH 094/169] Add LANG tags to settings for translations --- apps/setting/settings.js | 122 +++++++++++++++++++-------------------- 1 file changed, 61 insertions(+), 61 deletions(-) diff --git a/apps/setting/settings.js b/apps/setting/settings.js index 27ce24e50..514adf1dd 100644 --- a/apps/setting/settings.js +++ b/apps/setting/settings.js @@ -63,7 +63,7 @@ const boolFormat = v => v ? /*LANG*/"On" : /*LANG*/"Off"; function showMainMenu() { const mainmenu = { - '': { 'title': 'Settings' }, + '': { 'title': /*LANG*/'Settings' }, '< Back': ()=>load(), /*LANG*/'Apps': ()=>showAppSettingsMenu(), /*LANG*/'System': ()=>showSystemMenu(), @@ -78,7 +78,7 @@ function showMainMenu() { function showSystemMenu() { const mainmenu = { - '': { 'title': 'System' }, + '': { 'title': /*LANG*/'System' }, '< Back': ()=>showMainMenu(), /*LANG*/'Theme': ()=>showThemeMenu(), /*LANG*/'LCD': ()=>showLCDMenu(), @@ -122,7 +122,7 @@ function showAlertsMenu() { } const mainmenu = { - '': { 'title': 'Alerts' }, + '': { 'title': /*LANG*/'Alerts' }, '< Back': ()=>showMainMenu(), /*LANG*/'Beep': beepMenuItem, /*LANG*/'Vibration': { @@ -159,8 +159,8 @@ function showBLEMenu() { E.showMenu({ '': { 'title': 'Bluetooth' }, '< Back': ()=>showMainMenu(), - 'Make Connectable': ()=>makeConnectable(), - 'BLE': { + /*LANG*/'Make Connectable': ()=>makeConnectable(), + /*LANG*/'BLE': { value: settings.ble, format: boolFormat, onchange: () => { @@ -168,7 +168,7 @@ function showBLEMenu() { updateSettings(); } }, - 'Programmable': { + /*LANG*/'Programmable': { value: settings.blerepl, format: boolFormat, onchange: () => { @@ -176,7 +176,7 @@ function showBLEMenu() { updateSettings(); } }, - 'HID': { + /*LANG*/'HID': { value: Math.max(0,0 | hidV.indexOf(settings.HID)), min: 0, max: 3, format: v => hidN[v], @@ -185,11 +185,11 @@ function showBLEMenu() { updateSettings(); } }, - 'Passkey BETA': { + /*LANG*/'Passkey BETA': { value: settings.passkey?settings.passkey:"none", onchange: () => setTimeout(showPasskeyMenu) // graphical_menu redraws after the call }, - 'Whitelist': { + /*LANG*/'Whitelist': { value: settings.whitelist?(settings.whitelist.length+" devs"):"off", onchange: () => setTimeout(showWhitelistMenu) // graphical_menu redraws after the call } @@ -213,7 +213,7 @@ function showThemeMenu() { var m = E.showMenu({ '':{title:'Theme'}, '< Back': ()=>showSystemMenu(), - 'Dark BW': ()=>{ + /*LANG*/'Dark BW': ()=>{ upd({ fg:cl("#fff"), bg:cl("#000"), fg2:cl("#0ff"), bg2:cl("#000"), @@ -221,7 +221,7 @@ function showThemeMenu() { dark:true }); }, - 'Light BW': ()=>{ + /*LANG*/'Light BW': ()=>{ upd({ fg:cl("#000"), bg:cl("#fff"), fg2:cl("#000"), bg2:cl("#cff"), @@ -229,7 +229,7 @@ function showThemeMenu() { dark:false }); }, - 'Customize': ()=>showCustomThemeMenu(), + /*LANG*/'Customize': ()=>showCustomThemeMenu(), }); function showCustomThemeMenu() { @@ -261,9 +261,9 @@ function showThemeMenu() { "< Back": () => showThemeMenu() }; const labels = { - fg: 'Foreground', bg: 'Background', - fg2: 'Foreground 2', bg2: 'Background 2', - fgH: 'Highlight FG', bgH: 'Highlight BG', + fg: /*LANG*/'Foreground', bg: /*LANG*/'Background', + fg2: /*LANG*/'Foreground 2', bg2: /*LANG*/'Background 2', + fgH: /*LANG*/'Highlight FG', bgH: /*LANG*/'Highlight BG', }; ["fg", "bg", "fg2", "bg2", "fgH", "bgH"].forEach(t => { menu[labels[t]] = { @@ -292,7 +292,7 @@ function showThemeMenu() { function showPasskeyMenu() { var menu = { "< Back" : ()=>showBLEMenu(), - "Disable" : () => { + /*LANG*/"Disable" : () => { settings.passkey = undefined; updateSettings(); showBLEMenu(); @@ -320,7 +320,7 @@ function showPasskeyMenu() { function showWhitelistMenu() { var menu = { "< Back" : ()=>showBLEMenu(), - "Disable" : () => { + /*LANG*/"Disable" : () => { settings.whitelist = undefined; updateSettings(); showBLEMenu(); @@ -328,7 +328,7 @@ function showWhitelistMenu() { }; if (settings.whitelist) settings.whitelist.forEach(function(d){ menu[d.substr(0,17)] = function() { - E.showPrompt('Remove\n'+d).then((v) => { + E.showPrompt(/*LANG*/'Remove\n'+d).then((v) => { if (v) { settings.whitelist.splice(settings.whitelist.indexOf(d),1); updateSettings(); @@ -337,8 +337,8 @@ function showWhitelistMenu() { }); } }); - menu['Add Device']=function() { - E.showAlert("Connect device\nto add to\nwhitelist","Whitelist").then(function() { + menu[/*LANG*/'Add Device']=function() { + E.showAlert(/*LANG*/"Connect device\nto add to\nwhitelist",/*LANG*/"Whitelist").then(function() { NRF.removeAllListeners('connect'); showWhitelistMenu(); }); @@ -358,7 +358,7 @@ function showLCDMenu() { const lcdMenu = { '': { 'title': 'LCD' }, '< Back': ()=>showSystemMenu(), - 'LCD Brightness': { + /*LANG*/'LCD Brightness': { value: settings.brightness, min: 0.1, max: 1, @@ -369,7 +369,7 @@ function showLCDMenu() { Bangle.setLCDBrightness(settings.brightness); } }, - 'LCD Timeout': { + /*LANG*/'LCD Timeout': { value: settings.timeout, min: 0, max: 60, @@ -380,7 +380,7 @@ function showLCDMenu() { Bangle.setLCDTimeout(settings.timeout); } }, - 'Wake on BTN1': { + /*LANG*/'Wake on BTN1': { value: settings.options.wakeOnBTN1, format: boolFormat, onchange: () => { @@ -391,7 +391,7 @@ function showLCDMenu() { }; if (!BANGLEJS2) Object.assign(lcdMenu, { - 'Wake on BTN2': { + /*LANG*/'Wake on BTN2': { value: settings.options.wakeOnBTN2, format: boolFormat, onchange: () => { @@ -399,7 +399,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on BTN3': { + /*LANG*/'Wake on BTN3': { value: settings.options.wakeOnBTN3, format: boolFormat, onchange: () => { @@ -408,7 +408,7 @@ function showLCDMenu() { } }}); Object.assign(lcdMenu, { - 'Wake on FaceUp': { + /*LANG*/'Wake on FaceUp': { value: settings.options.wakeOnFaceUp, format: boolFormat, onchange: () => { @@ -416,7 +416,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on Touch': { + /*LANG*/'Wake on Touch': { value: settings.options.wakeOnTouch, format: boolFormat, onchange: () => { @@ -424,7 +424,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Wake on Twist': { + /*LANG*/'Wake on Twist': { value: settings.options.wakeOnTwist, format: boolFormat, onchange: () => { @@ -432,7 +432,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Threshold': { + /*LANG*/'Twist Threshold': { value: internalToG(settings.options.twistThreshold), min: -0.5, max: 0.5, @@ -442,7 +442,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Max Y': { + /*LANG*/'Twist Max Y': { value: settings.options.twistMaxY, min: -1500, max: 1500, @@ -452,7 +452,7 @@ function showLCDMenu() { updateOptions(); } }, - 'Twist Timeout': { + /*LANG*/'Twist Timeout': { value: settings.options.twistTimeout, min: 0, max: 2000, @@ -468,9 +468,9 @@ function showLCDMenu() { function showLocaleMenu() { const localemenu = { - '': { 'title': 'Locale' }, + '': { 'title': /*LANG*/'Locale' }, '< Back': ()=>showSystemMenu(), - 'Time Zone': { + /*LANG*/'Time Zone': { value: settings.timezone, min: -11, max: 13, @@ -480,7 +480,7 @@ function showLocaleMenu() { updateSettings(); } }, - 'Clock Style': { + /*LANG*/'Clock Style': { value: !!settings["12hour"], format: v => v ? "12hr" : "24hr", onchange: v => { @@ -494,29 +494,29 @@ function showLocaleMenu() { function showUtilMenu() { var menu = { - '': { 'title': 'Utilities' }, + '': { 'title': /*LANG*/'Utilities' }, '< Back': ()=>showMainMenu(), - 'Debug Info': { + /*LANG*/'Debug Info': { value: E.clip(0|settings.log,0,2), min: 0, max: 2, - format: v => ["Hide","Show","Log"][E.clip(0|v,0,2)], + format: v => [/*LANG*/"Hide",/*LANG*/"Show",/*LANG*/"Log"][E.clip(0|v,0,2)], onchange: v => { settings.log = v; updateSettings(); } }, - 'Compact Storage': () => { - E.showMessage("Compacting...\nTakes approx\n1 minute",{title:"Storage"}); + /*LANG*/'Compact Storage': () => { + E.showMessage(/*LANG*/"Compacting...\nTakes approx\n1 minute",{title:/*LANG*/"Storage"}); require("Storage").compact(); showUtilMenu(); }, - 'Rewrite Settings': () => { + /*LANG*/'Rewrite Settings': () => { require("Storage").write(".boot0","eval(require('Storage').read('bootupdate.js'));"); load("setting.app.js"); }, - 'Flatten Battery': () => { - E.showMessage('Flattening battery - this can take hours.\nLong-press button to cancel.'); + /*LANG*/'Flatten Battery': () => { + E.showMessage(/*LANG*/'Flattening battery - this can take hours.\nLong-press button to cancel.'); Bangle.setLCDTimeout(0); Bangle.setLCDPower(1); if (Bangle.setGPSPower) Bangle.setGPSPower(1,"flat"); @@ -528,8 +528,8 @@ function showUtilMenu() { var i=1000;while (i--); }, 1); }, - 'Reset Settings': () => { - E.showPrompt('Reset to Defaults?',{title:"Settings"}).then((v) => { + /*LANG*/'Reset Settings': () => { + E.showPrompt(/*LANG*/'Reset to Defaults?',{title:/*LANG*/"Settings"}).then((v) => { if (v) { E.showMessage('Resetting'); resetSettings(); @@ -540,8 +540,8 @@ function showUtilMenu() { /*LANG*/'Turn Off': ()=>{ if (Bangle.softOff) Bangle.softOff(); else Bangle.off() } }; if (Bangle.factoryReset) { - menu['Factory Reset'] = ()=>{ - E.showPrompt('This will remove everything!',{title:"Factory Reset"}).then((v) => { + menu[/*LANG*/'Factory Reset'] = ()=>{ + E.showPrompt(/*LANG*/'This will remove everything!',{title:/*LANG*/"Factory Reset"}).then((v) => { if (v) { E.showMessage(); Terminal.setConsole(); @@ -558,7 +558,7 @@ function makeConnectable() { try { NRF.wake(); } catch (e) { } Bluetooth.setConsole(1); var name = "Bangle.js " + NRF.getAddress().substr(-5).replace(":", ""); - E.showPrompt(name + "\nStay Connectable?", { title: "Connectable" }).then(r => { + E.showPrompt(name + /*LANG*/"\nStay Connectable?", { title: /*LANG*/"Connectable" }).then(r => { if (settings.ble != r) { settings.ble = r; updateSettings(); @@ -574,7 +574,7 @@ function showClockMenu() { .sort((a, b) => a.sortorder - b.sortorder); const clockMenu = { '': { - 'title': 'Select Clock', + 'title': /*LANG*/'Select Clock', }, '< Back': ()=>showSystemMenu(), }; @@ -592,7 +592,7 @@ function showClockMenu() { }; }); if (clockApps.length === 0) { - clockMenu["No Clocks Found"] = () => { }; + clockMenu[/*LANG*/"No Clocks Found"] = () => { }; } return E.showMenu(clockMenu); } @@ -600,47 +600,47 @@ function showClockMenu() { function showSetTimeMenu() { d = new Date(); const timemenu = { - '': { 'title': 'Set Time' }, + '': { 'title': /*LANG*/'Set Time' }, '< Back': function () { setTime(d.getTime() / 1000); showSystemMenu(); }, - 'Hour': { + /*LANG*/'Hour': { value: d.getHours(), onchange: function (v) { this.value = (v+24)%24; d.setHours(this.value); } }, - 'Minute': { + /*LANG*/'Minute': { value: d.getMinutes(), onchange: function (v) { this.value = (v+60)%60; d.setMinutes(this.value); } }, - 'Second': { + /*LANG*/'Second': { value: d.getSeconds(), onchange: function (v) { this.value = (v+60)%60; d.setSeconds(this.value); } }, - 'Date': { + /*LANG*/'Date': { value: d.getDate(), onchange: function (v) { this.value = ((v+30)%31)+1; d.setDate(this.value); } }, - 'Month': { + /*LANG*/'Month': { value: d.getMonth() + 1, onchange: function (v) { this.value = ((v+11)%12)+1; d.setMonth(this.value - 1); } }, - 'Year': { + /*LANG*/'Year': { value: d.getFullYear(), min: 2019, max: 2100, @@ -654,7 +654,7 @@ function showSetTimeMenu() { function showAppSettingsMenu() { let appmenu = { - '': { 'title': 'App Settings' }, + '': { 'title': /*LANG*/'App Settings' }, '< Back': ()=>showMainMenu(), } const apps = storage.list(/\.settings\.js$/) @@ -671,7 +671,7 @@ function showAppSettingsMenu() { return 0; }) if (apps.length === 0) { - appmenu['No app has settings'] = () => { }; + appmenu[/*LANG*/'No app has settings'] = () => { }; } apps.forEach(function (app) { appmenu[app.name] = () => { showAppSettings(app) }; @@ -688,17 +688,17 @@ function showAppSettings(app) { appSettings = eval(appSettings); } catch (e) { console.log(`${app.name} settings error:`, e) - return showError('Error in settings'); + return showError(/*LANG*/'Error in settings'); } if (typeof appSettings !== "function") { - return showError('Invalid settings'); + return showError(/*LANG*/'Invalid settings'); } try { // pass showAppSettingsMenu as "back" argument appSettings(()=>showAppSettingsMenu()); } catch (e) { console.log(`${app.name} settings error:`, e) - return showError('Error in settings'); + return showError(/*LANG*/'Error in settings'); } } From fc8e089fbe43621862b00df5b2a014d61f0bfca9 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 11:05:27 +0000 Subject: [PATCH 095/169] improve sanity checking - no false warnings for apps files with `supports` field --- bin/sanitycheck.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/bin/sanitycheck.js b/bin/sanitycheck.js index e50256fb6..98fd1275f 100755 --- a/bin/sanitycheck.js +++ b/bin/sanitycheck.js @@ -58,6 +58,7 @@ const APP_KEYS = [ ]; const STORAGE_KEYS = ['name', 'url', 'content', 'evaluate', 'noOverwite', 'supports']; const DATA_KEYS = ['name', 'wildcard', 'storageFile', 'url', 'content', 'evaluate']; +const SUPPORTS_DEVICES = ["BANGLEJS","BANGLEJS2"]; // device IDs allowed for 'supports' const FORBIDDEN_FILE_NAME_CHARS = /[,;]/; // used as separators in appid.info const VALID_DUPLICATES = [ '.tfmodel', '.tfnames' ]; const GRANDFATHERED_ICONS = ["s7clk", "snek", "astral", "alpinenav", "slomoclock", "arrow", "pebble", "rebble"]; @@ -90,7 +91,7 @@ apps.forEach((app,appIdx) => { if (!Array.isArray(app.supports)) ERROR(`App ${app.id} has no 'supports' field or it's not an array`); else { app.supports.forEach(dev => { - if (!["BANGLEJS","BANGLEJS2"].includes(dev)) + if (!SUPPORTS_DEVICES.includes(dev)) ERROR(`App ${app.id} has unknown device in 'supports' field - ${dev}`); }); } @@ -140,6 +141,13 @@ apps.forEach((app,appIdx) => { if (char) ERROR(`App ${app.id} storage file ${file.name} contains invalid character "${char[0]}"`) if (fileNames.includes(file.name) && !file.supports) // assume that there aren't duplicates if 'supports' is set ERROR(`App ${app.id} file ${file.name} is a duplicate`); + if (file.supports && !Array.isArray(file.supports)) + ERROR(`App ${app.id} file ${file.name} supports field must be an array`); + if (file.supports) + file.supports.forEach(dev => { + if (!SUPPORTS_DEVICES.includes(dev)) + ERROR(`App ${app.id} file ${file.name} has unknown device in 'supports' field - ${dev}`); + }); fileNames.push(file.name); allFiles.push({app: app.id, file: file.name}); if (file.url) if (!fs.existsSync(appDir+file.url)) ERROR(`App ${app.id} file ${file.url} doesn't exist`); @@ -271,7 +279,8 @@ while(fileA=allFiles.pop()) { if (globA.test(nameB)||globB.test(nameA)) { if (isGlob(nameA)||isGlob(nameB)) ERROR(`App ${fileB.app} ${typeB} file ${nameB} matches app ${fileA.app} ${typeB} file ${nameA}`) - else WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) + else if (fileA.app != fileB.app) + WARN(`App ${fileB.app} ${typeB} file ${nameB} is also listed as ${typeA} file for app ${fileA.app}`) } }) } From bda5512db423bf6e2c9f7ceb0b622e874f0bf85e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 13:02:52 +0100 Subject: [PATCH 096/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 335 ++++++++++++++++++++++++++++++------- 1 file changed, 279 insertions(+), 56 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 59c08f2cd..5c60c0aa4 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -26,13 +26,10 @@ default-src 'self' 'unsafe-inline' 'unsafe-eval' file: https:; "> - - + - - - - + + @@ -235,17 +212,17 @@ switch (ClockSize) { case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clock-size/main/ClockSize.js')" case 'smart': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-smart-clock-size/main/ClockSize.js')" - case 'custom': return 'require(' + ClockSizeURL + ')' + case 'custom': return "require('" + ClockSizeURL + "')" } } function chosenClockFace () { switch (ClockFace) { - case 'none': return undefined + case 'none': return "undefined" case 'four-fold': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-four-fold-clock-face/main/ClockFace.js')" case 'twelve-fold': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-twelve-fold-clock-face/main/ClockFace.js')" case 'rainbow': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-rainbow-clock-face/main/ClockFace.js')" - case 'custom': return 'require(' + ClockFaceURL + ')' + case 'custom': return "require('" + ClockFaceURL + "')" } } @@ -254,18 +231,18 @@ case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simpled-clock-hands/main/ClockHands.js')" case 'rounded': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-rounded-clock-hands/main/ClockHands.js')" case 'hollow': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-hollow-clock-hands/main/ClockHands.js')" - case 'custom': return 'require(' + ClockHandsURL + ')' + case 'custom': return "require('" + ClockHandsURL + "')" } } function chosenComplication (Complication, customURL) { switch (Complication) { - case 'none': return undefined + case 'none': return "undefined" case 'date': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-date-complication/main/Complication.js')" case 'weekday': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-weekday-complication/main/Complication.js')" case 'calendar-week': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-calendar-week-complication/main/Complication.js')" case 'moon-phase': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-moon-phase-complication/main/Complication.js')" - case 'custom': return 'require(' + customURL + ')' + case 'custom': return "require('" + customURL + "')" } } function chosenComplicationAt (Position) { @@ -282,7 +259,7 @@ } function chosenColor (ColorChoice) { - return (ColorChoice === 'none' ? undefined : ColorChoice) + return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + '"') } function chosenForeground () { return chosenColor(Foreground) } @@ -290,7 +267,7 @@ function chosenSecondHand () { return chosenColor(SecondHand) } function chosenFillColor () { return chosenColor(FillColor) } - function chosenDots () { return (ClockFaceDots === 'with-dots') } + function chosenDots () { return (ClockFaceDots === 'with-dots' ? 'true' : 'false') } let AppSource = ` let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); From 8bd074131da4d9c09aa9521297d603018345e4f7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 15:55:00 +0100 Subject: [PATCH 108/169] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ef111b1d..fd0920156 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 3636b32084fbfec92ff1db5ecfcbdacb71883adf Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 15:58:20 +0100 Subject: [PATCH 109/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 113f4279b..2bfab8d51 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -295,6 +295,9 @@ Clockwork.windUp({ FillColor: ${chosenFillColor()} }); ` +console.log('the configured AC-AC app looks as follows:') +console.log(AppSource) + sendCustomizedApp({ storage:[ {name:'ac-ac.app.js', url:'app.js', content:AppSource}, From 4429288362574ad7b23f3bb7b495dba4aa45207c Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:02:28 +0100 Subject: [PATCH 110/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 2bfab8d51..f2387f9dd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -259,7 +259,7 @@ } function chosenColor (ColorChoice) { - return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + '"') + return (ColorChoice === 'none' ? 'undefined' : "'" + ColorChoice + "'") } function chosenForeground () { return chosenColor(Foreground) } From 40c8d69b1e64ee691eb69f66d579bcd4c260123f Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:02:30 +0100 Subject: [PATCH 111/169] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd0920156..1ef111b1d 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.02", + "version":"0.01", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 116dec3cb98aa074e72cfa8a7cd1ab6e8be7c51e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:36:28 +0100 Subject: [PATCH 112/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index f2387f9dd..f50def79b 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -300,7 +300,7 @@ console.log(AppSource) sendCustomizedApp({ storage:[ - {name:'ac-ac.app.js', url:'app.js', content:AppSource}, + {name:'ac_ac.app.js', url:'app.js', content:AppSource}, ] }) } From f6b064d20f45be365b4463a981f6613638469701 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:36:31 +0100 Subject: [PATCH 113/169] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 1ef111b1d..fd0920156 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 276fdd647e757b60de647b9ae6b56ecda5172fc4 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:45:28 +0100 Subject: [PATCH 114/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index f50def79b..a2798b6bd 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -208,6 +208,14 @@ /**** createAndUploadApp ****/ function createAndUploadApp () { + function WidgetsOnBackground () { + return ( + ClockSize === 'smart' + ? "require('https://raw.githubusercontent.com/rozek/banglejs-2-widgets-on-background/main/drawWidgets.js');" + : '' + ) + } + function chosenClockSize () { switch (ClockSize) { case 'simple': return "require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clock-size/main/ClockSize.js')" @@ -270,6 +278,8 @@ function chosenDots () { return (ClockFaceDots === 'with-dots' ? 'true' : 'false') } let AppSource = ` +${WidgetsOnBackground()} + let Clockwork = require('https://raw.githubusercontent.com/rozek/banglejs-2-simple-clockwork/main/Clockwork.js'); Clockwork.windUp({ From 3fdbfd6b850c2f4c4bb616d550a66ac3c2dea3a7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Wed, 12 Jan 2022 16:45:32 +0100 Subject: [PATCH 115/169] Update apps.json --- apps.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps.json b/apps.json index fd0920156..1ef111b1d 100644 --- a/apps.json +++ b/apps.json @@ -32,7 +32,7 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.02", + "version":"0.01", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", From 12254e06f3cfde37db3c5992d04c2586d2d0ecd5 Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 15:46:38 +0000 Subject: [PATCH 116/169] Add 'run' app --- apps.json | 13 ++++ apps/run/ChangeLog | 1 + apps/run/README.md | 33 +++++++++ apps/run/app-icon.js | 1 + apps/run/app.js | 159 +++++++++++++++++++++++++++++++++++++++++++ apps/run/app.png | Bin 0 -> 1479 bytes 6 files changed, 207 insertions(+) create mode 100644 apps/run/ChangeLog create mode 100644 apps/run/README.md create mode 100644 apps/run/app-icon.js create mode 100644 apps/run/app.js create mode 100644 apps/run/app.png diff --git a/apps.json b/apps.json index 93b1cf44e..adc98ff2b 100644 --- a/apps.json +++ b/apps.json @@ -2277,6 +2277,19 @@ {"name":"buffgym.img","url":"buffgym-icon.js","evaluate":true} ] }, + { "id": "run", + "name": "Run", + "version":"0.01", + "description": "Displays distance, time, steps, cadence, pace and more for runners.", + "icon": "app.png", + "tags": "run,running,fitness,outdoors,gps", + "supports" : ["BANGLEJS","BANGLEJS2"], + "readme": "README.md", + "storage": [ + {"name":"run.app.js","url":"app.js"}, + {"name":"run.img","url":"app-icon.js","evaluate":true} + ] + }, { "id": "banglerun", "name": "BangleRun", diff --git a/apps/run/ChangeLog b/apps/run/ChangeLog new file mode 100644 index 000000000..5560f00bc --- /dev/null +++ b/apps/run/ChangeLog @@ -0,0 +1 @@ +0.01: New App! diff --git a/apps/run/README.md b/apps/run/README.md new file mode 100644 index 000000000..34ad6511b --- /dev/null +++ b/apps/run/README.md @@ -0,0 +1,33 @@ +# Run App + +This app allows you to display the status of your run. + +To use it, start the app and press the middle button so that +the red `STOP` in the bottom right turns to a green `RUN`. + +## Display + +* `DIST` - the distance travelled based on the GPS (if you have a GPS lock). + * NOTE: this is based on the GPS coordinates which are not 100% accurate, especially initially. As + the GPS updates your position as it gets more satellites your position changes and the distance + shown will increase, even if you are standing still. +* `TIME` - the elapsed time for your run +* `PACE` - the number of minutes it takes you to run a kilometer **based on your run so far** +* `HEART` - Your heart rate +* `STEPS` - Steps since you started exercising +* `CADENCE` - Steps per second based on your step rate *over the last minute* +* `GPS` - this is green if you have a GPS lock. GPS is turned on automatically +so if you have no GPS lock you just need to wait. +* The current time is displayed right at the bottom of the screen +* `RUN/STOP` - whether the distance for your run is being displayed or not + +## Recording Tracks + +`Run` doesn't directly allow you to record your tracks at the moment. +However you can just install the `Recorder` app, turn recording on in +that, and then start the `Run` app. + +## TODO + +* Allow this app to trigger the `Recorder` app on and off directly. +* Keep a log of each run's stats (distance/steps/etc) diff --git a/apps/run/app-icon.js b/apps/run/app-icon.js new file mode 100644 index 000000000..a97d1b8ce --- /dev/null +++ b/apps/run/app-icon.js @@ -0,0 +1 @@ +require("heatshrink").decompress(atob("mEw4UA///pH9vEFt9TIW0FqALJitUBZNVqoLqgo4BHZAUBtBTHgILB1XAEREV1WsEQ9AgWq1ALHgEO1WtBYxCBhWq0pdInWq2tABY8q1WVBZGq1XFBZS/IKQRvCDIsP9WsBZP60CTCBYs//+wLxALBTQ4AB///+AKHgYLB/gLK/4LHh//AIIwFitVr/8DIIwFLANXBAILIqogBn7DBEYrXBeQRgIBYKmHDgYLLZRBACBZYKJZIILKKRZeWgJGKAFQA==")) diff --git a/apps/run/app.js b/apps/run/app.js new file mode 100644 index 000000000..a10d3841f --- /dev/null +++ b/apps/run/app.js @@ -0,0 +1,159 @@ +var B2 = process.env.HWVERSION==2; +var Layout = require("Layout"); +var locale = require("locale") +var fontHeading = "6x8:2"; +var fontValue = B2 ? "6x15:2" : "6x8:3"; +var headingCol = "#888"; +var running = false; +var startTime; +var startSteps; +// This & previous GPS readings +var lastGPS, thisGPS; +var distance = 0; ///< distance in meters +var startSteps = Bangle.getStepCount(); ///< number of steps when we started +var lastStepCount = startSteps; // last time 'step' was called +var stepHistory = new Uint8Array(60); // steps each second for the last minute (0 = current minute) + +g.clear(); +Bangle.loadWidgets(); +Bangle.drawWidgets(); + +// --------------------------- + +function formatTime(ms) { + var s = Math.round(ms/1000); + var min = Math.floor(s/60).toString(); + s = (s%60).toString(); + return min.padStart(2,0)+":"+s.padStart(2,0); +} + +// Format speed in meters/second +function formatPace(speed) { + if (speed < 0.1667) { + return `__'__"`; + } + const pace = Math.round(1000 / speed); // seconds for 1km + const min = Math.floor(pace / 60); // minutes for 1km + const sec = pace % 60; + return ('0' + min).substr(-2) + `'` + ('0' + sec).substr(-2) + `"`; +} + +// --------------------------- + +function clearState() { + distance = 0; + startSteps = Bangle.getStepCount(); + stepHistory.fill(0); + layout.dist.label=locale.distance(distance); + layout.time.label="00:00"; + layout.pace.label=formatPace(0); + layout.hrm.label="--"; + layout.steps.label=0; + layout.cadence.label= "0"; + layout.status.bgCol = "#f00"; + layout.gps.bgCol = "#f00"; +} + +function onStartStop() { + running = !running; + layout.button.label = running ? "STOP" : "START"; + layout.status.label = running ? "RUN" : "STOP"; + layout.status.bgCol = running ? "#0f0" : "#f00"; + if (running) { + clearState(); + startTime = Date.now(); + } + // if stopping running, don't clear state + // so we can at least refer to what we've done + layout.render(); +} + +var layout = new Layout( { + type:"v", c: [ + { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"DIST", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"TIME", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:"0.00", id:"dist", fillx:1 }, + {type:"txt", font:fontValue, label:"00:00", id:"time", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"PACE", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"HEART", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:`__'__"`, id:"pace", fillx:1 }, + {type:"txt", font:fontValue, label:"--", id:"hrm", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"STEPS", fillx:1, col:headingCol }, + {type:"txt", font:fontHeading, label:"CADENCE", fillx:1, col:headingCol } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontValue, label:"0", id:"steps", fillx:1 }, + {type:"txt", font:fontValue, label:"0", id:"cadence", fillx:1 } + ]}, { type:"h", filly:1, c:[ + {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1 }, + {type:"txt", font:fontHeading, label:"00:00", id:"clock", fillx:1, bgCol:g.theme.fg, col:g.theme.bg }, + {type:"txt", font:fontHeading, label:"STOP", id:"status", fillx:1 } + ]}, + + ] +},{lazy:true, btns:[{ label:"START", cb: onStartStop, id:"button"}]}); +clearState(); +layout.render(); + + + +function onTimer() { + layout.clock.label = locale.time(new Date(),1); + if (!running) { + layout.render(); + return; + } + // called once a second + var duration = Date.now() - startTime; // in ms + // set cadence based on steps over last minute + var stepsInMinute = E.sum(stepHistory); + var cadence = 60000 * stepsInMinute / Math.min(duration,60000); + // update layout + layout.time.label = formatTime(duration); + layout.steps.label = Bangle.getStepCount()-startSteps; + layout.cadence.label = Math.round(cadence); + layout.render(); + // move step history onwards + stepHistory.set(stepHistory,1); + stepHistory[0]=0; +} + +Bangle.on("GPS", function(fix) { + layout.gps.bgCol = fix.fix ? "#0f0" : "#f00"; + lastGPS = thisGPS; + thisGPS = fix; + if (running && fix.fix && lastGPS.fix) { + // work out distance - moving from a to b + var a = Bangle.project(lastGPS); + var b = Bangle.project(thisGPS); + var dx = a.x-b.x, dy = a.y-b.y; + var d = Math.sqrt(dx*dx+dy*dy); // this should be the distance in meters + distance += d; + layout.dist.label=locale.distance(distance); + var duration = Date.now() - startTime; // in ms + var speed = distance * 1000 / duration; // meters/sec + layout.pace.label = formatPace(speed); + } +}); +Bangle.on("HRM", function(h) { + layout.hrm.label = h.bpm; +}); +Bangle.on("step", function(steps) { + if (running) { + layout.steps.label = steps-Bangle.getStepCount(); + stepHistory[0] += steps-lastStepCount; + } + lastStepCount = steps; +}); + +// We always call ourselves once a second, if only to update the time +setInterval(onTimer, 1000); + +/* Turn GPS and HRM on right at the start to ensure +we get the highest chance of a lock. */ +Bangle.setHRMPower(true,"app"); +Bangle.setGPSPower(true,"app"); diff --git a/apps/run/app.png b/apps/run/app.png new file mode 100644 index 0000000000000000000000000000000000000000..7059b8b015e20039a96de8b65c8a6b68a5e51e18 GIT binary patch literal 1479 zcmV;&1vvVNP)b0~r9hI1hzN2C_Hz2bec46d zz32!1f7|Dr^Zft+eV+5aXV1bTJi@~b@gPX$zNip1Yz1>vN2mz2DMEkvlG@MN zqD@lE?a)(59(>u0=Kppec*EA5(*zQ(EG3+(+KI->CEFJ!ACP%5!I+F&=p{{UFEnH!o7WN}(7DfEF{6T=^qRTOGUUmDCINa`%K?dqCzyBw&^& zdx;n90#h)O*AZj`^*@L)UE%?ZC>&z+*w0Pj=Mr*u5X*l)p2LibbmVEnr6riETg&$lZ8)JSSrFFIvt>|1LfBuoykZR)&GJv4Nif!en;z zv+6Z;L-k`+==0YD>-(E?LK%{G3lE#^`JOB$P&RcWluLnM)#~Vk(_duC*`K_4L>V>S z)_4dF#+CBq(XN1$@$$f&f%ft_-N11%bdLd>txt@&{Fx`lWV(+H188fpdoMWEz{=c= zcS=M^psn$7;>Mk!^KP#d`utPCk6iBMM%oOs0tuJ37nQ16rohH)E z9ia`tY}y~?;W9hY+Ci=jL57GcSZ9mZX%$dBo+%nx{F~SG>u0QvN67NBtqYU0IzJ12 z!D%4xE@^d0`F6j&s+C&7&h>F)stg0CXcP_pe^xQKQS72jOY-(wh zZbX~G&?_#4KvUbwYbW!Gs64aVQ65`xr~;X3@&0)ixmMMvar5@_BseI*>bwB=Hsh4X zYQh$!?Cq~z?1DoTIA3l2sj5-q2GG>pLe-60r0n}JscF?|Pu=!AaWEs^-w{4*u-m|v z)cN}2e|5diF%6APc(zvE@zj|5xTt9M^e(*}a5ghB(al~?Yp}~eT3VX+_&;u68O^;r zFm#Zy>3N^}(KCW>&hyn7OqS~|H4F%<8>aciPOVnaXAj8ih*=;qfnl~5NeLTDd^m8~ zvnv)fz-)*f*%Y>B(}4>B-+uJwvah5;)T5WD&l4qTwmGbG5^Ni*$W&M4^}G>c@+r0 zm&L6n!K$N!Oe1_uD^fG^zOXju@RlWhrFCBC&eabb;-_mPZum831lFJkDuuov#6kU5 z4CF+`AmwiE&BPU?TrL(A+P>=nva%L?1T`4WzcBdbD0fZgQOG$4`W)s&T>c@z;lw?$ z*r#$R-lF#xBG~4P-1p~Z&LlR|e(BYTGQ71roRQk)24wckiNM_6L75_6I@Icn{4O=n ze($4X(0i|)Kwp^SEDqOJAUkp)FsXM?t`S20EwnAT>>nDL9jAl(3m`*#gmZ Date: Wed, 12 Jan 2022 16:50:37 +0100 Subject: [PATCH 117/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index a2798b6bd..8552eaf70 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -777,7 +777,13 @@ console.log(AppSource)

-

 

+

+ This application is based on the author's + [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit). + If you need a different "clockwork", clock size calculation or clock face, + or specific clock hands or complications, just follow the link to learn how to + implement your own clock parts. +

From 1d8febed9f0559e1a4716ed9afb1b7d12e197d7c Mon Sep 17 00:00:00 2001 From: Marco Heiming Date: Wed, 12 Jan 2022 16:57:42 +0100 Subject: [PATCH 118/169] Do not overwrite circle on event (e.g. charging) if there is a circle configured for that place --- apps/circlesclock/app.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/apps/circlesclock/app.js b/apps/circlesclock/app.js index 822802afa..88a04d4b9 100644 --- a/apps/circlesclock/app.js +++ b/apps/circlesclock/app.js @@ -136,8 +136,10 @@ function getCirclePosition(type) { if (setting == type) return circlePosX[i - 1]; } for (let i = 0; i < defaultCircleTypes.length; i++) { - if (type == defaultCircleTypes[i]) return circlePosX[i]; - } + if (type == defaultCircleTypes[i] && (!settings || settings['circle' + (i + 1)] == undefined)) { + return circlePosX[i]; + } + } return undefined; } From 910c3c0b5bfec2d04cd206c64c0329ae6a8ea87d Mon Sep 17 00:00:00 2001 From: Gordon Williams Date: Wed, 12 Jan 2022 15:59:30 +0000 Subject: [PATCH 119/169] add screenshot, minor tweaks --- apps.json | 3 ++- apps/run/app.js | 9 ++++----- apps/run/screenshot.png | Bin 0 -> 3716 bytes 3 files changed, 6 insertions(+), 6 deletions(-) create mode 100644 apps/run/screenshot.png diff --git a/apps.json b/apps.json index adc98ff2b..4c6f3bdcf 100644 --- a/apps.json +++ b/apps.json @@ -2284,12 +2284,13 @@ "icon": "app.png", "tags": "run,running,fitness,outdoors,gps", "supports" : ["BANGLEJS","BANGLEJS2"], + "screenshots": [{"url":"screenshot.png"}], "readme": "README.md", "storage": [ {"name":"run.app.js","url":"app.js"}, {"name":"run.img","url":"app-icon.js","evaluate":true} ] - }, + }, { "id": "banglerun", "name": "BangleRun", diff --git a/apps/run/app.js b/apps/run/app.js index a10d3841f..44c42711c 100644 --- a/apps/run/app.js +++ b/apps/run/app.js @@ -51,18 +51,17 @@ function clearState() { layout.steps.label=0; layout.cadence.label= "0"; layout.status.bgCol = "#f00"; - layout.gps.bgCol = "#f00"; } function onStartStop() { running = !running; - layout.button.label = running ? "STOP" : "START"; - layout.status.label = running ? "RUN" : "STOP"; - layout.status.bgCol = running ? "#0f0" : "#f00"; if (running) { clearState(); startTime = Date.now(); } + layout.button.label = running ? "STOP" : "START"; + layout.status.label = running ? "RUN" : "STOP"; + layout.status.bgCol = running ? "#0f0" : "#f00"; // if stopping running, don't clear state // so we can at least refer to what we've done layout.render(); @@ -89,7 +88,7 @@ var layout = new Layout( { {type:"txt", font:fontValue, label:"0", id:"steps", fillx:1 }, {type:"txt", font:fontValue, label:"0", id:"cadence", fillx:1 } ]}, { type:"h", filly:1, c:[ - {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1 }, + {type:"txt", font:fontHeading, label:"GPS", id:"gps", fillx:1, bgCol:"#f00" }, {type:"txt", font:fontHeading, label:"00:00", id:"clock", fillx:1, bgCol:g.theme.fg, col:g.theme.bg }, {type:"txt", font:fontHeading, label:"STOP", id:"status", fillx:1 } ]}, diff --git a/apps/run/screenshot.png b/apps/run/screenshot.png new file mode 100644 index 0000000000000000000000000000000000000000..1a813f19dfe304e3d8bf711692fd2abf1013c391 GIT binary patch literal 3716 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 Date: Wed, 12 Jan 2022 17:18:29 +0100 Subject: [PATCH 120/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 8552eaf70..2846352d6 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -779,7 +779,7 @@ console.log(AppSource)

This application is based on the author's - [Analog Clock Construction Kit (ACCK)](https://github.com/rozek/banglejs-2-analog-clock-construction-kit). + Analog Clock Construction Kit (ACCK). If you need a different "clockwork", clock size calculation or clock face, or specific clock hands or complications, just follow the link to learn how to implement your own clock parts. From 9691d0bb0466535af2858f6876b39f1ddef80dc1 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 12 Jan 2022 19:19:16 +0200 Subject: [PATCH 121/169] RAM efficient version of `fourTwentyTz.js` As suggested by @gfwilliams here: https://github.com/espruino/BangleApps/pull/1152#issuecomment-1009739110 Also make `apps.json` entry more accurate, and play nice with dark theme. --- apps.json | 5 +- apps/ftclock/ChangeLog | 1 + apps/ftclock/app.js | 3 +- apps/ftclock/fourTwenty.js | 12 +- apps/ftclock/fourTwentyTz.js | 492 +++------------------------------ apps/ftclock/mkFourTwentyTz.js | 17 +- 6 files changed, 57 insertions(+), 473 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..761e9d363 100644 --- a/apps.json +++ b/apps.json @@ -5169,14 +5169,13 @@ { "id": "ftclock", "name": "Four Twenty Clock", - "version": "0.01", + "version": "0.02", "description": "A clock that tells when and where it's going to be 4:20 next", "icon": "app.png", "screenshots": [{"url":"screenshot.png"}, {"url":"screenshot1.png"}], "type": "clock", "tags": "clock", - "supports": ["BANGLEJS","BANGLEJS2"], - "allow_emulator": true, + "supports": ["BANGLEJS2"], "readme": "README.md", "storage": [ {"name":"ftclock.app.js","url":"app.js"}, diff --git a/apps/ftclock/ChangeLog b/apps/ftclock/ChangeLog index 9db0e26c5..c944dd9ac 100644 --- a/apps/ftclock/ChangeLog +++ b/apps/ftclock/ChangeLog @@ -1 +1,2 @@ 0.01: first release +0.02: RAM efficient version of `fourTwentyTz.js` (as suggested by @gfwilliams). diff --git a/apps/ftclock/app.js b/apps/ftclock/app.js index 1aed8da54..b12db10f1 100644 --- a/apps/ftclock/app.js +++ b/apps/ftclock/app.js @@ -17,14 +17,13 @@ function queueDraw() { function draw() { g.reset(); - g.setBgColor("#ffffff"); let date = new Date(); let timeStr = require("locale").time(date,1); let next420 = getNextFourTwenty(); g.clearRect(0,26,g.getWidth(),g.getHeight()); g.setColor("#00ff00").setFontAlign(0,-1).setFont("Teletext10x18Ascii",2); g.drawString(next420.minutes? timeStr: `\0${leaf_img}${timeStr}\0${leaf_img}`, g.getWidth()/2, 28); - g.setColor("#000000"); + g.setColor(g.theme.fg); g.setFontAlign(-1,-1).setFont("Teletext10x18Ascii"); g.drawString(g.wrapString(next420.text, g.getWidth()-8).join("\n"),4,60); diff --git a/apps/ftclock/fourTwenty.js b/apps/ftclock/fourTwenty.js index ac15f40e6..b2a2aa8fb 100644 --- a/apps/ftclock/fourTwenty.js +++ b/apps/ftclock/fourTwenty.js @@ -1,4 +1,6 @@ -let timezones = require("fourTwentyTz").timezones; +let ftz = require("fourTwentyTz"), + offsets = ftz.offsets, + timezones = ftz.timezones; function get420offset() { let current_time = Math.floor((Date.now()%(24*3600*1000))/60000); @@ -24,10 +26,10 @@ function makeFourTwentyText(minutes, places) { function getNextFourTwenty() { let offs = get420offset(); - for (let i=0; i { if (err) { console.log("Can't open output file"); @@ -65,8 +69,17 @@ fs.createReadStream(__dirname+'/country.csv') fs.write(fd, "// Generated by mkFourTwentyTz.js\n", handleWrite); fs.write(fd, `// ${Date()}\n`, handleWrite); fs.write(fd, "// Data source: https://timezonedb.com/files/timezonedb.csv.zip\n", handleWrite); - fs.write(fd, "exports.timezones = ", handleWrite); - fs.write(fd, JSON.stringify(offsdict, null, 4), handleWrite); + fs.write(fd, "exports.offsets = ", handleWrite); + fs.write(fd, JSON.stringify(offsets), handleWrite); + fs.write(fd, ";\n", handleWrite); + fs.write(fd, "exports.timezones = function(offs) {\n", handleWrite); + fs.write(fd, " switch (offs) {\n", handleWrite); + for (o in offsdict) { + fs.write(fd, ` case ${o}: return ${JSON.stringify(offsdict[o])};\n`, handleWrite); + } + fs.write(fd, " default: return [\"Houston, we have a bug.\"];\n", handleWrite); + fs.write(fd, " };\n", handleWrite); + fs.write(fd, "};\n", handleWrite); console.log('Done.'); }); }) From 1c8083ba6e9bc423b7592390d624ed41d830fef2 Mon Sep 17 00:00:00 2001 From: The Dod Date: Wed, 12 Jan 2022 19:36:27 +0200 Subject: [PATCH 122/169] Remove a `;` that was disturbing Travis Also make `fourTwentyTz.js` sorted (to minimize diffs in the future). --- apps/ftclock/fourTwentyTz.js | 48 +++++++++++++++++----------------- apps/ftclock/mkFourTwentyTz.js | 5 ++-- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/apps/ftclock/fourTwentyTz.js b/apps/ftclock/fourTwentyTz.js index d02402e2f..5fa6cdab7 100644 --- a/apps/ftclock/fourTwentyTz.js +++ b/apps/ftclock/fourTwentyTz.js @@ -1,33 +1,33 @@ // Generated by mkFourTwentyTz.js -// Wed Jan 12 2022 17:49:39 GMT+0200 (Israel Standard Time) +// Wed Jan 12 2022 19:35:36 GMT+0200 (Israel Standard Time) // Data source: https://timezonedb.com/files/timezonedb.csv.zip exports.offsets = [1380,1320,1260,1200,1140,1080,1020,960,900,840,780,720,660,600,540,480,420,360,300,240,180,120,60,0]; exports.timezones = function(offs) { switch (offs) { - case 0: return ["Troll, Antarctica","Ouagadougou, Burkina Faso","Abidjan, Côte d'Ivoire","Canary, Spain","Faroe, Faroe Islands","London, United Kingdom of Great Britain and Northern Ireland","Guernsey, Guernsey","Accra, Ghana","Danmarkshavn, Greenland","Banjul, Gambia","Conakry, Guinea","Bissau, Guinea-Bissau","Dublin, Ireland","Isle of_Man, Isle of Man","Reykjavik, Iceland","Jersey, Jersey","Monrovia, Liberia","Bamako, Mali","Nouakchott, Mauritania","Lisbon, Portugal","Madeira, Portugal","St Helena, Saint Helena, Ascension and Tristan da Cunha","Freetown, Sierra Leone","Dakar, Senegal","Sao Tome, Sao Tome and Principe","Lome, Togo"]; - case 60: return ["Andorra, Andorra","Tirane, Albania","Luanda, Angola","Vienna, Austria","Sarajevo, Bosnia and Herzegovina","Brussels, Belgium","Porto-Novo, Benin","Kinshasa, Congo, Democratic Republic of the","Bangui, Central African Republic","Brazzaville, Congo","Zurich, Switzerland","Douala, Cameroon","Prague, Czechia","Berlin, Germany","Busingen, Germany","Copenhagen, Denmark","Algiers, Algeria","El Aaiun, Western Sahara","Madrid, Spain","Ceuta, Spain","Paris, France","Libreville, Gabon","Gibraltar, Gibraltar","Malabo, Equatorial Guinea","Zagreb, Croatia","Budapest, Hungary","Rome, Italy","Vaduz, Liechtenstein","Luxembourg, Luxembourg","Casablanca, Morocco","Monaco, Monaco","Podgorica, Montenegro","Skopje, North Macedonia","Malta, Malta","Niamey, Niger","Lagos, Nigeria","Amsterdam, Netherlands","Oslo, Norway","Warsaw, Poland","Belgrade, Serbia","Stockholm, Sweden","Ljubljana, Slovenia","Longyearbyen, Svalbard and Jan Mayen","Bratislava, Slovakia","San Marino, San Marino","Ndjamena, Chad","Tunis, Tunisia","Vatican, Holy See"]; - case 120: return ["Mariehamn, Åland Islands","Sofia, Bulgaria","Bujumbura, Burundi","Gaborone, Botswana","Lubumbashi, Congo, Democratic Republic of the","Nicosia, Cyprus","Famagusta, Cyprus","Tallinn, Estonia","Cairo, Egypt","Helsinki, Finland","Athens, Greece","Jerusalem, Israel","Amman, Jordan","Beirut, Lebanon","Maseru, Lesotho","Vilnius, Lithuania","Riga, Latvia","Tripoli, Libya","Chisinau, Moldova, Republic of","Blantyre, Malawi","Maputo, Mozambique","Windhoek, Namibia","Gaza, Palestine, State of","Hebron, Palestine, State of","Bucharest, Romania","Kaliningrad, Russian Federation","Kigali, Rwanda","Khartoum, Sudan","Juba, South Sudan","Damascus, Syrian Arab Republic","Mbabane, Eswatini","Kiev, Ukraine","Uzhgorod, Ukraine","Zaporozhye, Ukraine","Johannesburg, South Africa","Lusaka, Zambia","Harare, Zimbabwe"]; - case 180: return ["Syowa, Antarctica","Bahrain, Bahrain","Minsk, Belarus","Djibouti, Djibouti","Asmara, Eritrea","Addis Ababa, Ethiopia","Baghdad, Iraq","Nairobi, Kenya","Comoro, Comoros","Kuwait, Kuwait","Antananarivo, Madagascar","Qatar, Qatar","Moscow, Russian Federation","Simferopol, Ukraine","Kirov, Russian Federation","Volgograd, Russian Federation","Riyadh, Saudi Arabia","Mogadishu, Somalia","Istanbul, Turkey","Dar es_Salaam, Tanzania, United Republic of","Kampala, Uganda","Aden, Yemen","Mayotte, Mayotte"]; - case 240: return ["Dubai, United Arab Emirates","Yerevan, Armenia","Baku, Azerbaijan","Tbilisi, Georgia","Mauritius, Mauritius","Muscat, Oman","Reunion, Réunion","Astrakhan, Russian Federation","Saratov, Russian Federation","Ulyanovsk, Russian Federation","Samara, Russian Federation","Mahe, Seychelles"]; + case 1380: return ["Cape Verde, Cabo Verde","Scoresbysund, Greenland","Azores, Portugal"]; + case 1320: return ["Noronha, Brazil","South Georgia, South Georgia and the South Sandwich Islands"]; + case 1260: return ["Palmer, Antarctica","Rothera, Antarctica","Buenos Aires, Argentina","Cordoba, Argentina","Salta, Argentina","Jujuy, Argentina","Tucuman, Argentina","Catamarca, Argentina","La Rioja, Argentina","San Juan, Argentina","Mendoza, Argentina","San Luis, Argentina","Rio Gallegos, Argentina","Ushuaia, Argentina","Belem, Brazil","Fortaleza, Brazil","Recife, Brazil","Araguaina, Brazil","Maceio, Brazil","Bahia, Brazil","Sao Paulo, Brazil","Santarem, Brazil","Santiago, Chile","Punta Arenas, Chile","Stanley, Falkland Islands (Malvinas)","Cayenne, French Guiana","Nuuk, Greenland","Miquelon, Saint Pierre and Miquelon","Asuncion, Paraguay","Paramaribo, Suriname","Montevideo, Uruguay"]; + case 1200: return ["Antigua, Antigua and Barbuda","Anguilla, Anguilla","Aruba, Aruba","Barbados, Barbados","St Barthelemy, Saint Barthélemy","Bermuda, Bermuda","La Paz, Bolivia (Plurinational State of)","Kralendijk, Bonaire, Sint Eustatius and Saba","Campo Grande, Brazil","Cuiaba, Brazil","Porto Velho, Brazil","Boa Vista, Brazil","Manaus, Brazil","Halifax, Canada","Glace Bay, Canada","Moncton, Canada","Goose Bay, Canada","Blanc-Sablon, Canada","Curacao, Curaçao","Dominica, Dominica","Santo Domingo, Dominican Republic","Grenada, Grenada","Thule, Greenland","Guadeloupe, Guadeloupe","Guyana, Guyana","St Kitts, Saint Kitts and Nevis","St Lucia, Saint Lucia","Marigot, Saint Martin (French part)","Martinique, Martinique","Montserrat, Montserrat","Puerto Rico, Puerto Rico","Lower Princes, Sint Maarten (Dutch part)","Port of_Spain, Trinidad and Tobago","St Vincent, Saint Vincent and the Grenadines","Caracas, Venezuela (Bolivarian Republic of)","Tortola, Virgin Islands (British)","St Thomas, Virgin Islands (U.S.)"]; + case 1140: return ["Eirunepe, Brazil","Rio Branco, Brazil","Nassau, Bahamas","Toronto, Canada","Nipigon, Canada","Thunder Bay, Canada","Iqaluit, Canada","Pangnirtung, Canada","Atikokan, Canada","Easter, Chile","Bogota, Colombia","Havana, Cuba","Guayaquil, Ecuador","Port-au-Prince, Haiti","Jamaica, Jamaica","Cayman, Cayman Islands","Cancun, Mexico","Panama, Panama","Lima, Peru","Grand Turk, Turks and Caicos Islands","New York, United States of America","Detroit, United States of America","Louisville, Kentucky","Monticello, Kentucky","Indianapolis, Indiana","Vincennes, Indiana","Winamac, Indiana","Marengo, Indiana","Petersburg, Indiana","Vevay, Indiana"]; + case 1080: return ["Belize, Belize","Winnipeg, Canada","Rainy River, Canada","Resolute, Canada","Rankin Inlet, Canada","Regina, Canada","Swift Current, Canada","Costa Rica, Costa Rica","Galapagos, Ecuador","Guatemala, Guatemala","Tegucigalpa, Honduras","Mexico City, Mexico","Merida, Mexico","Monterrey, Mexico","Matamoros, Mexico","Bahia Banderas, Mexico","Managua, Nicaragua","El Salvador, El Salvador","Chicago, United States of America","Tell City, Indiana","Knox, Indiana","Menominee, United States of America","Center, North Dakota","New_Salem, North Dakota","Beulah, North Dakota"]; + case 1020: return ["Edmonton, Canada","Cambridge Bay, Canada","Yellowknife, Canada","Inuvik, Canada","Creston, Canada","Dawson Creek, Canada","Fort Nelson, Canada","Whitehorse, Canada","Dawson, Canada","Mazatlan, Mexico","Chihuahua, Mexico","Ojinaga, Mexico","Hermosillo, Mexico","Denver, United States of America","Boise, United States of America","Phoenix, United States of America"]; + case 960: return ["Vancouver, Canada","Tijuana, Mexico","Pitcairn, Pitcairn","Los Angeles, United States of America"]; + case 900: return ["Gambier, French Polynesia","Anchorage, United States of America","Juneau, United States of America","Sitka, United States of America","Metlakatla, United States of America","Yakutat, United States of America","Nome, United States of America"]; + case 840: return ["Rarotonga, Cook Islands","Kiritimati, Kiribati","Tahiti, French Polynesia","Adak, United States of America","Honolulu, United States of America"]; + case 780: return ["McMurdo, Antarctica","Pago Pago, American Samoa","Fiji, Fiji","Kanton, Kiribati","Niue, Niue","Auckland, New Zealand","Fakaofo, Tokelau","Tongatapu, Tonga","Midway, United States Minor Outlying Islands","Apia, Samoa"]; + case 720: return ["Tarawa, Kiribati","Majuro, Marshall Islands","Kwajalein, Marshall Islands","Norfolk, Norfolk Island","Nauru, Nauru","Kamchatka, Russian Federation","Anadyr, Russian Federation","Funafuti, Tuvalu","Wake, United States Minor Outlying Islands","Wallis, Wallis and Futuna"]; + case 660: return ["Casey, Antarctica","Lord Howe, Australia","Macquarie, Australia","Hobart, Australia","Melbourne, Australia","Sydney, Australia","Pohnpei, Micronesia (Federated States of)","Kosrae, Micronesia (Federated States of)","Noumea, New Caledonia","Bougainville, Papua New Guinea","Magadan, Russian Federation","Sakhalin, Russian Federation","Srednekolymsk, Russian Federation","Guadalcanal, Solomon Islands","Efate, Vanuatu"]; + case 600: return ["DumontDUrville, Antarctica","Brisbane, Australia","Lindeman, Australia","Chuuk, Micronesia (Federated States of)","Guam, Guam","Saipan, Northern Mariana Islands","Port Moresby, Papua New Guinea","Vladivostok, Russian Federation","Ust-Nera, Russian Federation"]; + case 540: return ["Jayapura, Indonesia","Tokyo, Japan","Pyongyang, Korea (Democratic People's Republic of)","Seoul, Korea, Republic of","Palau, Palau","Chita, Russian Federation","Yakutsk, Russian Federation","Khandyga, Russian Federation","Dili, Timor-Leste"]; + case 480: return ["Perth, Australia","Brunei, Brunei Darussalam","Shanghai, China","Hong Kong, Hong Kong","Makassar, Indonesia","Ulaanbaatar, Mongolia","Choibalsan, Mongolia","Macau, Macao","Kuala Lumpur, Malaysia","Kuching, Malaysia","Manila, Philippines","Irkutsk, Russian Federation","Singapore, Singapore","Taipei, Taiwan, Province of China"]; + case 420: return ["Davis, Antarctica","Christmas, Christmas Island","Jakarta, Indonesia","Pontianak, Indonesia","Phnom Penh, Cambodia","Vientiane, Lao People's Democratic Republic","Hovd, Mongolia","Novosibirsk, Russian Federation","Barnaul, Russian Federation","Tomsk, Russian Federation","Novokuznetsk, Russian Federation","Krasnoyarsk, Russian Federation","Bangkok, Thailand","Ho Chi_Minh, Viet Nam"]; case 360: return ["Vostok, Antarctica","Dhaka, Bangladesh","Thimphu, Bhutan","Urumqi, China","Chagos, British Indian Ocean Territory","Bishkek, Kyrgyzstan","Almaty, Kazakhstan","Qostanay, Kazakhstan","Omsk, Russian Federation"]; case 300: return ["Mawson, Antarctica","Qyzylorda, Kazakhstan","Aqtobe, Kazakhstan","Aqtau, Kazakhstan","Atyrau, Kazakhstan","Oral, Kazakhstan","Maldives, Maldives","Karachi, Pakistan","Yekaterinburg, Russian Federation","Kerguelen, French Southern Territories","Dushanbe, Tajikistan","Ashgabat, Turkmenistan","Samarkand, Uzbekistan","Tashkent, Uzbekistan"]; - case 420: return ["Davis, Antarctica","Christmas, Christmas Island","Jakarta, Indonesia","Pontianak, Indonesia","Phnom Penh, Cambodia","Vientiane, Lao People's Democratic Republic","Hovd, Mongolia","Novosibirsk, Russian Federation","Barnaul, Russian Federation","Tomsk, Russian Federation","Novokuznetsk, Russian Federation","Krasnoyarsk, Russian Federation","Bangkok, Thailand","Ho Chi_Minh, Viet Nam"]; - case 480: return ["Perth, Australia","Brunei, Brunei Darussalam","Shanghai, China","Hong Kong, Hong Kong","Makassar, Indonesia","Ulaanbaatar, Mongolia","Choibalsan, Mongolia","Macau, Macao","Kuala Lumpur, Malaysia","Kuching, Malaysia","Manila, Philippines","Irkutsk, Russian Federation","Singapore, Singapore","Taipei, Taiwan, Province of China"]; - case 540: return ["Jayapura, Indonesia","Tokyo, Japan","Pyongyang, Korea (Democratic People's Republic of)","Seoul, Korea, Republic of","Palau, Palau","Chita, Russian Federation","Yakutsk, Russian Federation","Khandyga, Russian Federation","Dili, Timor-Leste"]; - case 600: return ["DumontDUrville, Antarctica","Brisbane, Australia","Lindeman, Australia","Chuuk, Micronesia (Federated States of)","Guam, Guam","Saipan, Northern Mariana Islands","Port Moresby, Papua New Guinea","Vladivostok, Russian Federation","Ust-Nera, Russian Federation"]; - case 660: return ["Casey, Antarctica","Lord Howe, Australia","Macquarie, Australia","Hobart, Australia","Melbourne, Australia","Sydney, Australia","Pohnpei, Micronesia (Federated States of)","Kosrae, Micronesia (Federated States of)","Noumea, New Caledonia","Bougainville, Papua New Guinea","Magadan, Russian Federation","Sakhalin, Russian Federation","Srednekolymsk, Russian Federation","Guadalcanal, Solomon Islands","Efate, Vanuatu"]; - case 720: return ["Tarawa, Kiribati","Majuro, Marshall Islands","Kwajalein, Marshall Islands","Norfolk, Norfolk Island","Nauru, Nauru","Kamchatka, Russian Federation","Anadyr, Russian Federation","Funafuti, Tuvalu","Wake, United States Minor Outlying Islands","Wallis, Wallis and Futuna"]; - case 780: return ["McMurdo, Antarctica","Pago Pago, American Samoa","Fiji, Fiji","Kanton, Kiribati","Niue, Niue","Auckland, New Zealand","Fakaofo, Tokelau","Tongatapu, Tonga","Midway, United States Minor Outlying Islands","Apia, Samoa"]; - case 840: return ["Rarotonga, Cook Islands","Kiritimati, Kiribati","Tahiti, French Polynesia","Adak, United States of America","Honolulu, United States of America"]; - case 900: return ["Gambier, French Polynesia","Anchorage, United States of America","Juneau, United States of America","Sitka, United States of America","Metlakatla, United States of America","Yakutat, United States of America","Nome, United States of America"]; - case 960: return ["Vancouver, Canada","Tijuana, Mexico","Pitcairn, Pitcairn","Los Angeles, United States of America"]; - case 1020: return ["Edmonton, Canada","Cambridge Bay, Canada","Yellowknife, Canada","Inuvik, Canada","Creston, Canada","Dawson Creek, Canada","Fort Nelson, Canada","Whitehorse, Canada","Dawson, Canada","Mazatlan, Mexico","Chihuahua, Mexico","Ojinaga, Mexico","Hermosillo, Mexico","Denver, United States of America","Boise, United States of America","Phoenix, United States of America"]; - case 1080: return ["Belize, Belize","Winnipeg, Canada","Rainy River, Canada","Resolute, Canada","Rankin Inlet, Canada","Regina, Canada","Swift Current, Canada","Costa Rica, Costa Rica","Galapagos, Ecuador","Guatemala, Guatemala","Tegucigalpa, Honduras","Mexico City, Mexico","Merida, Mexico","Monterrey, Mexico","Matamoros, Mexico","Bahia Banderas, Mexico","Managua, Nicaragua","El Salvador, El Salvador","Chicago, United States of America","Tell City, Indiana","Knox, Indiana","Menominee, United States of America","Center, North Dakota","New_Salem, North Dakota","Beulah, North Dakota"]; - case 1140: return ["Eirunepe, Brazil","Rio Branco, Brazil","Nassau, Bahamas","Toronto, Canada","Nipigon, Canada","Thunder Bay, Canada","Iqaluit, Canada","Pangnirtung, Canada","Atikokan, Canada","Easter, Chile","Bogota, Colombia","Havana, Cuba","Guayaquil, Ecuador","Port-au-Prince, Haiti","Jamaica, Jamaica","Cayman, Cayman Islands","Cancun, Mexico","Panama, Panama","Lima, Peru","Grand Turk, Turks and Caicos Islands","New York, United States of America","Detroit, United States of America","Louisville, Kentucky","Monticello, Kentucky","Indianapolis, Indiana","Vincennes, Indiana","Winamac, Indiana","Marengo, Indiana","Petersburg, Indiana","Vevay, Indiana"]; - case 1200: return ["Antigua, Antigua and Barbuda","Anguilla, Anguilla","Aruba, Aruba","Barbados, Barbados","St Barthelemy, Saint Barthélemy","Bermuda, Bermuda","La Paz, Bolivia (Plurinational State of)","Kralendijk, Bonaire, Sint Eustatius and Saba","Campo Grande, Brazil","Cuiaba, Brazil","Porto Velho, Brazil","Boa Vista, Brazil","Manaus, Brazil","Halifax, Canada","Glace Bay, Canada","Moncton, Canada","Goose Bay, Canada","Blanc-Sablon, Canada","Curacao, Curaçao","Dominica, Dominica","Santo Domingo, Dominican Republic","Grenada, Grenada","Thule, Greenland","Guadeloupe, Guadeloupe","Guyana, Guyana","St Kitts, Saint Kitts and Nevis","St Lucia, Saint Lucia","Marigot, Saint Martin (French part)","Martinique, Martinique","Montserrat, Montserrat","Puerto Rico, Puerto Rico","Lower Princes, Sint Maarten (Dutch part)","Port of_Spain, Trinidad and Tobago","St Vincent, Saint Vincent and the Grenadines","Caracas, Venezuela (Bolivarian Republic of)","Tortola, Virgin Islands (British)","St Thomas, Virgin Islands (U.S.)"]; - case 1260: return ["Palmer, Antarctica","Rothera, Antarctica","Buenos Aires, Argentina","Cordoba, Argentina","Salta, Argentina","Jujuy, Argentina","Tucuman, Argentina","Catamarca, Argentina","La Rioja, Argentina","San Juan, Argentina","Mendoza, Argentina","San Luis, Argentina","Rio Gallegos, Argentina","Ushuaia, Argentina","Belem, Brazil","Fortaleza, Brazil","Recife, Brazil","Araguaina, Brazil","Maceio, Brazil","Bahia, Brazil","Sao Paulo, Brazil","Santarem, Brazil","Santiago, Chile","Punta Arenas, Chile","Stanley, Falkland Islands (Malvinas)","Cayenne, French Guiana","Nuuk, Greenland","Miquelon, Saint Pierre and Miquelon","Asuncion, Paraguay","Paramaribo, Suriname","Montevideo, Uruguay"]; - case 1320: return ["Noronha, Brazil","South Georgia, South Georgia and the South Sandwich Islands"]; - case 1380: return ["Cape Verde, Cabo Verde","Scoresbysund, Greenland","Azores, Portugal"]; + case 240: return ["Dubai, United Arab Emirates","Yerevan, Armenia","Baku, Azerbaijan","Tbilisi, Georgia","Mauritius, Mauritius","Muscat, Oman","Reunion, Réunion","Astrakhan, Russian Federation","Saratov, Russian Federation","Ulyanovsk, Russian Federation","Samara, Russian Federation","Mahe, Seychelles"]; + case 180: return ["Syowa, Antarctica","Bahrain, Bahrain","Minsk, Belarus","Djibouti, Djibouti","Asmara, Eritrea","Addis Ababa, Ethiopia","Baghdad, Iraq","Nairobi, Kenya","Comoro, Comoros","Kuwait, Kuwait","Antananarivo, Madagascar","Qatar, Qatar","Moscow, Russian Federation","Simferopol, Ukraine","Kirov, Russian Federation","Volgograd, Russian Federation","Riyadh, Saudi Arabia","Mogadishu, Somalia","Istanbul, Turkey","Dar es_Salaam, Tanzania, United Republic of","Kampala, Uganda","Aden, Yemen","Mayotte, Mayotte"]; + case 120: return ["Mariehamn, Åland Islands","Sofia, Bulgaria","Bujumbura, Burundi","Gaborone, Botswana","Lubumbashi, Congo, Democratic Republic of the","Nicosia, Cyprus","Famagusta, Cyprus","Tallinn, Estonia","Cairo, Egypt","Helsinki, Finland","Athens, Greece","Jerusalem, Israel","Amman, Jordan","Beirut, Lebanon","Maseru, Lesotho","Vilnius, Lithuania","Riga, Latvia","Tripoli, Libya","Chisinau, Moldova, Republic of","Blantyre, Malawi","Maputo, Mozambique","Windhoek, Namibia","Gaza, Palestine, State of","Hebron, Palestine, State of","Bucharest, Romania","Kaliningrad, Russian Federation","Kigali, Rwanda","Khartoum, Sudan","Juba, South Sudan","Damascus, Syrian Arab Republic","Mbabane, Eswatini","Kiev, Ukraine","Uzhgorod, Ukraine","Zaporozhye, Ukraine","Johannesburg, South Africa","Lusaka, Zambia","Harare, Zimbabwe"]; + case 60: return ["Andorra, Andorra","Tirane, Albania","Luanda, Angola","Vienna, Austria","Sarajevo, Bosnia and Herzegovina","Brussels, Belgium","Porto-Novo, Benin","Kinshasa, Congo, Democratic Republic of the","Bangui, Central African Republic","Brazzaville, Congo","Zurich, Switzerland","Douala, Cameroon","Prague, Czechia","Berlin, Germany","Busingen, Germany","Copenhagen, Denmark","Algiers, Algeria","El Aaiun, Western Sahara","Madrid, Spain","Ceuta, Spain","Paris, France","Libreville, Gabon","Gibraltar, Gibraltar","Malabo, Equatorial Guinea","Zagreb, Croatia","Budapest, Hungary","Rome, Italy","Vaduz, Liechtenstein","Luxembourg, Luxembourg","Casablanca, Morocco","Monaco, Monaco","Podgorica, Montenegro","Skopje, North Macedonia","Malta, Malta","Niamey, Niger","Lagos, Nigeria","Amsterdam, Netherlands","Oslo, Norway","Warsaw, Poland","Belgrade, Serbia","Stockholm, Sweden","Ljubljana, Slovenia","Longyearbyen, Svalbard and Jan Mayen","Bratislava, Slovakia","San Marino, San Marino","Ndjamena, Chad","Tunis, Tunisia","Vatican, Holy See"]; + case 0: return ["Troll, Antarctica","Ouagadougou, Burkina Faso","Abidjan, Côte d'Ivoire","Canary, Spain","Faroe, Faroe Islands","London, United Kingdom of Great Britain and Northern Ireland","Guernsey, Guernsey","Accra, Ghana","Danmarkshavn, Greenland","Banjul, Gambia","Conakry, Guinea","Bissau, Guinea-Bissau","Dublin, Ireland","Isle of_Man, Isle of Man","Reykjavik, Iceland","Jersey, Jersey","Monrovia, Liberia","Bamako, Mali","Nouakchott, Mauritania","Lisbon, Portugal","Madeira, Portugal","St Helena, Saint Helena, Ascension and Tristan da Cunha","Freetown, Sierra Leone","Dakar, Senegal","Sao Tome, Sao Tome and Principe","Lome, Togo"]; default: return ["Houston, we have a bug."]; - }; + } }; diff --git a/apps/ftclock/mkFourTwentyTz.js b/apps/ftclock/mkFourTwentyTz.js index 2be18f88a..4571c15f7 100644 --- a/apps/ftclock/mkFourTwentyTz.js +++ b/apps/ftclock/mkFourTwentyTz.js @@ -74,11 +74,12 @@ fs.createReadStream(__dirname+'/country.csv') fs.write(fd, ";\n", handleWrite); fs.write(fd, "exports.timezones = function(offs) {\n", handleWrite); fs.write(fd, " switch (offs) {\n", handleWrite); - for (o in offsdict) { + for (i=0; i Date: Wed, 12 Jan 2022 18:36:07 +0100 Subject: [PATCH 123/169] Select which GNSS system to use fewer GNSS systems could decrease time to fix. This patch adds a checkbox for each choice. --- apps.json | 2 +- apps/assistedgps/ChangeLog | 1 + apps/assistedgps/custom.html | 34 ++++++++++++++++++++++++++++++++-- 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..88db38bbb 100644 --- a/apps.json +++ b/apps.json @@ -1536,7 +1536,7 @@ { "id": "assistedgps", "name": "Assisted GPS Update (AGPS)", - "version": "0.02", + "version": "0.03", "description": "Downloads assisted GPS (AGPS) data to Bangle.js 1 or 2 for faster GPS startup and more accurate fixes. **No app will be installed**, this just uploads new data to the GPS chip.", "icon": "app.png", "type": "RAM", diff --git a/apps/assistedgps/ChangeLog b/apps/assistedgps/ChangeLog index 4ec2c8f71..739ccf915 100644 --- a/apps/assistedgps/ChangeLog +++ b/apps/assistedgps/ChangeLog @@ -1,2 +1,3 @@ 0.01: New App! 0.02: Update to work with Bangle.js 2 +0.03: Select GNSS systems to use for Bangle.js 2 diff --git a/apps/assistedgps/custom.html b/apps/assistedgps/custom.html index fa11b696c..80d68a71f 100644 --- a/apps/assistedgps/custom.html +++ b/apps/assistedgps/custom.html @@ -27,6 +27,31 @@

@@ -116,8 +141,13 @@ } if (isB2) { // CASIC - // Disable BDS, use just GPS (supposedly improve lock time) - js += `\x10Serial1.println("${CASIC_CHECKSUM("$PCAS04,1")}")\n`; // set GPS-only mode + // Select what GNSS System to use for decreased fix time. + var radios = document.getElementsByName('gnss_select'); + var gnss_select="1"; + for (var i=0; i Date: Wed, 12 Jan 2022 19:33:22 +0100 Subject: [PATCH 124/169] Update app-screenshot.png --- apps/ac_ac/app-screenshot.png | Bin 4042 -> 3459 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/apps/ac_ac/app-screenshot.png b/apps/ac_ac/app-screenshot.png index e0e3bb0b95de844ed0656d16023e71708c117f96..0aef3fa3815fe19d368bcf37f6afd3aa1f9e335c 100644 GIT binary patch delta 3444 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

P0Nr8KQ7MDGw1#ySt+-U>WBeK-J~ zIf*MltOajcveRsr0B$sy2QZ_POPON%?=hH}>b#UQ@y`9#V*bGe6YD2OK@bM^g>YE)66hwe?X+jO|hJRCbJ+w#lLb1a(0p3A@w*ffL z)_&%^C5FIm6JW(Fba+#{De!Oy@=oXg^ZbQdm(qk4(+7OC(=8SS*m#bNRU)jF(Tq>j z7M#Q(7xoG{atUH<@P-r@ya;Nse-#{Dfv4XD4RpX2*gz1x3!n7Bq6%Dz)e7mwXw()~ zSj<)X0e`&mLl7)l($5#paj_xq2e2#fJLayy*mbbj=Q}~ZF`N{t_ETWWsCRm(u+vy5 zu}f^e3ve9yVs+0~j9r1z?|v0r7mFWaN!2X%#b8*!slZquC^@nQSd=zCuCQ3B9N?UX zNMI4(Fvi-!KEEFG{&jNobO)nR@VNsla9TJ-135lQ8`A!Lp56^@JHXvt m>?i2y0SCCJcfIZI9{3NXIof%KH)?hO0000 From 73062edf8321892b65d4372f6f0c2f304d2c25a3 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 12 Jan 2022 19:08:19 +0100 Subject: [PATCH 125/169] qmsched: switch theme fixes #1266 --- apps.json | 4 +-- apps/qmsched/ChangeLog | 3 ++- apps/qmsched/README.md | 5 ++++ apps/qmsched/app.js | 60 +++++++++++++++++++++++++++++++----------- apps/qmsched/boot.js | 4 ++- apps/qmsched/lib.js | 36 ++++++++++++++++++++++++- apps/qmsched/widget.js | 2 +- 7 files changed, 93 insertions(+), 21 deletions(-) diff --git a/apps.json b/apps.json index b5929a56c..870c7b49f 100644 --- a/apps.json +++ b/apps.json @@ -3919,8 +3919,8 @@ "id": "qmsched", "name": "Quiet Mode Schedule and Widget", "shortName": "Quiet Mode", - "version": "0.06", - "description": "Automatically turn Quiet Mode on or off at set times, and change LCD options while Quiet Mode is active.", + "version": "0.07", + "description": "Automatically turn Quiet Mode on or off at set times, change theme and LCD options while Quiet Mode is active.", "icon": "app.png", "screenshots": [{"url":"screenshot_b1_main.png"},{"url":"screenshot_b1_edit.png"},{"url":"screenshot_b1_lcd.png"}, {"url":"screenshot_b2_main.png"},{"url":"screenshot_b2_edit.png"},{"url":"screenshot_b2_lcd.png"}], diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index 35832a300..cc0050cdd 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -3,4 +3,5 @@ 0.03: Bangle.js 2 support 0.04: Move Quiet Mode LCD options from global settings to this app 0.05: Avoid immediately redrawing widgets on load -0.06: Fix: don't try to redraw widget when widgets not loaded \ No newline at end of file +0.06: Fix: don't try to redraw widget when widgets not loaded +0.07: Option to switch theme diff --git a/apps/qmsched/README.md b/apps/qmsched/README.md index 535ae56e4..660bda787 100644 --- a/apps/qmsched/README.md +++ b/apps/qmsched/README.md @@ -9,6 +9,11 @@ Automatically turn Quiet Mode on or off at set times, and display a widget when | ![Edit Schedule menu](screenshot_b1_edit.png) | ![Edit Schedule menu](screenshot_b2_edit.png) | | ![LCD Options menu](screenshot_b1_lcd.png) | ![LCD Options menu](screenshot_b2_lcd.png) | +### Switch Theme: + +Switch to dark theme during Quiet Mode. + * **NOTE**: This switches between the default "Dark BW" and "Light BW" themes, so custom theme settings will be lost. + ### LCD Settings: If set, these override the default LCD settings while Quiet Mode is active. \ No newline at end of file diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js index 7be3339fb..433dab409 100644 --- a/apps/qmsched/app.js +++ b/apps/qmsched/app.js @@ -3,7 +3,7 @@ Bangle.drawWidgets(); const modeNames = ["Off", "Alarms", "Silent"]; -// load global brightness setting +// load global settings let bSettings = require('Storage').readJSON('setting.json',true)||{}; let current = 0|bSettings.quiet; delete bSettings; // we don't need any other global settings @@ -18,6 +18,7 @@ delete bSettings; // we don't need any other global settings */ function save() { require('Storage').writeJSON('qmsched.json', settings); + eval(require('Storage').read('qmsched.boot.js')); // apply new schedules right away } function get(key, def) { return (key in settings) ? settings[key] : def; @@ -77,37 +78,66 @@ function formatTime(t) { const mins = Math.round((t-hrs)*60); return (" "+hrs).substr(-2)+":"+("0"+mins).substr(-2); } +/** + * Apply theme + */ +function applyTheme() { + const theme = (require("Storage").readJSON("setting.json", 1) || {}).theme; + if (theme && theme.dark===g.theme.dark) return; // already correct + g.theme = theme; + delete g.reset; + g._reset = g.reset; + g.reset = function(n) { return g._reset().setColor(g.theme.fg).setBgColor(g.theme.bg); }; + g.clear = function(n) { if (n) g.reset(); return g.clearRect(0,0,g.getWidth(),g.getHeight()); }; + g.clear(1); + Bangle.drawWidgets(); + delete m.lastIdx; // force redraw + m.draw(); +} +/** + * Library uses this to make the app update itself + * @param {int} mode New Quite Mode + */ +function setAppMode(mode) { + if (mode === current) return; + current = mode; + delete m.lastIdx; // force redraw + applyTheme(); + if (m.lastIdx===undefined) m.draw(); // applyTheme didn't redraw menu, but we need to show updated mode +} + +let m; function showMainMenu() { - let _m, menu = { + let menu = { "": {"title": "Quiet Mode"}, "< Exit": () => load() }; // "Current Mode""Silent" won't fit on Bangle.js 2 menu["Current"+((process.env.HWVERSION===2) ? "" : " Mode")] = { value: current, - format: v => modeNames[v], - onchange: function(v) { - if (v<0) {v = 2;} - if (v>2) {v = 0;} - require("qmsched").setMode(v); - current = v; - this.value = v; - }, + min:0, max:2, wrap: true, + format: () => modeNames[current], + onchange: require("qmsched").setMode, // library calls setAppMode(), which updates `current` }; scheds.sort((a, b) => (a.hr-b.hr)); scheds.forEach((sched, idx) => { menu[formatTime(sched.hr)] = { format: () => modeNames[sched.mode], // abuse format to right-align text - onchange: function() { - _m.draw = ()=> {}; // prevent redraw of main menu over edit menu + onchange: () => { + m.draw = ()=> {}; // prevent redraw of main menu over edit menu (needed because we abuse format/onchange) showEditMenu(idx); } }; }); menu["Add Schedule"] = () => showEditMenu(-1); + menu["Switch Theme"] = { + value: !!get("switchTheme"), + format: v => v ? /*LANG*/"Yes" : /*LANG*/"No", + onchange: v => v ? set("switchTheme", v) : unset("switchTheme"), + }; menu["LCD Settings"] = () => showOptionsMenu(); - _m = E.showMenu(menu); + m = E.showMenu(menu); } function showEditMenu(index) { @@ -174,7 +204,7 @@ function showEditMenu(index) { showMainMenu(); }; } - return E.showMenu(menu); + m = E.showMenu(menu); } function showOptionsMenu() { @@ -244,7 +274,7 @@ function showOptionsMenu() { onchange: () => {toggle("wakeOnTwist");}, }, }; - return E.showMenu(oMenu); + m = E.showMenu(oMenu); } loadSettings(); diff --git a/apps/qmsched/boot.js b/apps/qmsched/boot.js index c3bc49b58..c4610ce3e 100644 --- a/apps/qmsched/boot.js +++ b/apps/qmsched/boot.js @@ -1,5 +1,7 @@ // apply Quiet Mode schedules (function qm() { + if (Bangle.qmTimeout) clearTimeout(Bangle.qmTimeout); // so the app can eval() this file to apply changes right away + delete Bangle.qmTimeout; let bSettings = require('Storage').readJSON('setting.json',true)||{}; const curr = 0|bSettings.quiet; delete bSettings; @@ -18,7 +20,7 @@ let t = 3600000*(next.hr-hr); // timeout in milliseconds if (t<0) {t += 86400000;} // scheduled for tomorrow: add a day /* update quiet mode at the correct time. */ - setTimeout(() => { + Bangle.qmTimeout=setTimeout(() => { require("qmsched").setMode(mode); qm(); // schedule next update }, t); diff --git a/apps/qmsched/lib.js b/apps/qmsched/lib.js index e9ed3ec90..e048d15bf 100644 --- a/apps/qmsched/lib.js +++ b/apps/qmsched/lib.js @@ -1,5 +1,37 @@ /** - * Apply LCD options for given mode + * Apply appropriate theme for given mode + * @param {int} mode Quiet Mode + */ +function switchTheme(mode) { + if (!!mode === g.theme.dark) return; // nothing to do + let s = require("Storage").readJSON("setting.json", 1) || {}; + // default themes, copied from settings.js:showThemeMenu() + function cl(x) { return g.setColor(x).getColor(); } + s.theme = mode ? { + // 'Dark BW' + fg: cl("#fff"), bg: cl("#000"), + fg2: cl("#0ff"), bg2: cl("#000"), + fgH: cl("#fff"), bgH: cl("#00f"), + dark: true + } : { + // 'Light BW' + fg: cl("#000"), bg: cl("#fff"), + fg2: cl("#000"), bg2: cl("#cff"), + fgH: cl("#000"), bgH: cl("#0ff"), + dark: false + }; + require("Storage").writeJSON("setting.json", s); + if (typeof __FILE__ === 'string') { // undefined means it loaded the default clock + const info = require("Storage").readJSON(__FILE__.split(".")[0]+".info", 1); + if (info && info.type!=="clock") { // info can have no type (but then it isn't a clock) + return; // not a clock: wait for user to switch apps + } + } + // current app is a clock: reload it with new theme + load(global.__FILE__); +} +/** + * Apply LCD options and theme for given mode * @param {int} mode Quiet Mode */ exports.applyOptions = function(mode) { @@ -8,6 +40,7 @@ exports.applyOptions = function(mode) { Bangle.setOptions(get("options", {})); Bangle.setLCDBrightness(get("brightness", 1)); Bangle.setLCDTimeout(get("timeout", 10)); + if ((require("Storage").readJSON("qmsched.json", 1) || {}).switchTheme) switchTheme(mode); }; /** * Set new Quiet Mode and apply Bangle options @@ -20,4 +53,5 @@ exports.setMode = function(mode) { )); exports.applyOptions(mode); if (typeof WIDGETS === "object" && "qmsched" in WIDGETS) WIDGETS["qmsched"].draw(); + if (global.__FILE__ === "qmsched.app.js") setAppMode(mode); }; diff --git a/apps/qmsched/widget.js b/apps/qmsched/widget.js index b25192b06..daa11ac71 100644 --- a/apps/qmsched/widget.js +++ b/apps/qmsched/widget.js @@ -18,7 +18,7 @@ return; // drawWidgets will call draw again } let x = this.x, y = this.y; - g.clearRect(x, y, x+23, y+23); + g.reset().clearRect(x, y, x+23, y+23); // quiet mode: draw red one-way-street sign (dim red on Bangle.js 1) x = this.x+11;y = this.y+11; // center of widget g.setColor(process.env.HWVERSION===2 ? 1 : 0.8, 0, 0).fillCircle(x, y, 8); From 0b455f921c5b4d2514db5061b5ade73f817050a5 Mon Sep 17 00:00:00 2001 From: Richard de Boer Date: Wed, 12 Jan 2022 19:09:00 +0100 Subject: [PATCH 126/169] qmsched: set minutes in 5-min steps --- apps/qmsched/ChangeLog | 1 + apps/qmsched/app.js | 24 ++++++------------------ 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/apps/qmsched/ChangeLog b/apps/qmsched/ChangeLog index cc0050cdd..c868b6668 100644 --- a/apps/qmsched/ChangeLog +++ b/apps/qmsched/ChangeLog @@ -5,3 +5,4 @@ 0.05: Avoid immediately redrawing widgets on load 0.06: Fix: don't try to redraw widget when widgets not loaded 0.07: Option to switch theme + Changed time selection to 5-minute intervals \ No newline at end of file diff --git a/apps/qmsched/app.js b/apps/qmsched/app.js index 433dab409..b65761d5c 100644 --- a/apps/qmsched/app.js +++ b/apps/qmsched/app.js @@ -155,31 +155,19 @@ function showEditMenu(index) { "< Cancel": () => showMainMenu(), "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' + min:0, max:23, wrap:true, + onchange: v => {hrs = v;}, }, "Minutes": { value: mins, - onchange: function(v) { - if (v<0) {v = 59;} - if (v>59) {v = 0;} - mins = v; - this.value = v; - }, // no arrow fn -> preserve 'this' + min:0, max:55, step:5, wrap:true, + onchange: v => {mins = v;}, }, "Switch to": { value: mode, + min:0, max:2, wrap:true, format: v => modeNames[v], - onchange: function(v) { - if (v<0) {v = 2;} - if (v>2) {v = 0;} - mode = v; - this.value = v; - }, // no arrow fn -> preserve 'this' + onchange: v => {mode = v;}, }, }; function getSched() { From 8edda16ca2b9bfe47d358b50655d707657e71871 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:48:24 +0100 Subject: [PATCH 127/169] Log pressure if sensor is available --- apps/recorder/widget.js | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 8f82f1f37..bffa15283 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -133,8 +133,38 @@ draw : (x,y) => g.reset().drawImage(atob("DAwBAAMMeeeeeeeecOMMAAMMMMAA"),x,y) }; } - // TODO: recAltitude from pressure sensor }; + if (Bangle.getPressure){ + recorders['baro'] = function() { + var temp="",press="",alt=""; + function onPress(c) { + temp=c.temperature; + press=c.pressure; + alt=c.altitude; + } + return { + name : "Baro", + fields : ["Barometer Temperature", "Barometer Pressure", "Barometer Altitude"], + getValues : () => { + var r = [temp,press,alt]; + temp=""; + press=""; + alt=""; + return r; + }, + start : () => { + Bangle.setBarometerPower(1,"recorder"); + Bangle.on('pressure', onPress); + }, + stop : () => { + Bangle.setBarometerPower(0,"recorder"); + Bangle.removeListener('pressure', onPress); + }, + draw : (x,y) => g.setColor("#0f0").drawImage(atob("DAwBAAH4EIHIEIHIEIHIEIEIH4AA"),x,y) + }; + } + } + /* eg. foobar.recorder.js (function(recorders) { recorders.foobar = { From 58e9a4705192156ce7e58158cee79b07997145ab Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:35:52 +0100 Subject: [PATCH 128/169] Record empty string if no value instead of 0 --- apps/recorder/widget.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index bffa15283..9d66e0a02 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -52,7 +52,7 @@ }; }, hrm:function() { - var bpm = 0, bpmConfidence = 0; + var bpm = "", bpmConfidence = ""; function onHRM(h) { if (h.confidence >= bpmConfidence) { bpmConfidence = h.confidence; @@ -64,7 +64,7 @@ fields : ["Heartrate", "Confidence"], getValues : () => { var r = [bpm,bpmConfidence]; - bpm = 0; bpmConfidence = 0; + bpm = ""; bpmConfidence = ""; return r; }, start : () => { From c9efc0958199f5ed1f515e4ec09369a0d18d33cb Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:45:32 +0100 Subject: [PATCH 129/169] Always log bpm and confidence --- apps/recorder/widget.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 9d66e0a02..359af721f 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -54,10 +54,8 @@ hrm:function() { var bpm = "", bpmConfidence = ""; function onHRM(h) { - if (h.confidence >= bpmConfidence) { - bpmConfidence = h.confidence; - bpm = h.bpm; - } + bpmConfidence = h.confidence; + bpm = h.bpm; } return { name : "HR", From 412b5dd20c08787bb334af2f287423cd8ede4f3e Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:56:03 +0100 Subject: [PATCH 130/169] Move recorder code to plugin in coretemp app --- apps.json | 3 ++- apps/coretemp/ChangeLog | 1 + apps/coretemp/recorder.js | 31 +++++++++++++++++++++++++++++++ apps/recorder/widget.js | 26 -------------------------- 4 files changed, 34 insertions(+), 27 deletions(-) create mode 100644 apps/coretemp/recorder.js diff --git a/apps.json b/apps.json index 4c6f3bdcf..e3964fd2a 100644 --- a/apps.json +++ b/apps.json @@ -5046,7 +5046,7 @@ { "id": "coretemp", "name": "CoreTemp", - "version": "0.02", + "version": "0.03", "description": "Display CoreTemp device sensor data", "icon": "coretemp.png", "type": "app", @@ -5056,6 +5056,7 @@ "storage": [ {"name":"coretemp.wid.js","url":"widget.js"}, {"name":"coretemp.app.js","url":"coretemp.js"}, + {"name":"coretemp.recorder.js","url":"recorder.js"}, {"name":"coretemp.settings.js","url":"settings.js"}, {"name":"coretemp.img","url":"coretemp-icon.js","evaluate":true}, {"name":"coretemp.boot.js","url":"boot.js"} diff --git a/apps/coretemp/ChangeLog b/apps/coretemp/ChangeLog index ea6911f1a..ad6f0742d 100644 --- a/apps/coretemp/ChangeLog +++ b/apps/coretemp/ChangeLog @@ -1,2 +1,3 @@ 0.01: New app 0.02: Cleanup interface and add settings, widget, add skin temp reporting. +0.03: Move code for recording to this app diff --git a/apps/coretemp/recorder.js b/apps/coretemp/recorder.js new file mode 100644 index 000000000..1499605f3 --- /dev/null +++ b/apps/coretemp/recorder.js @@ -0,0 +1,31 @@ +(function(recorders) { + recorders.coretemp = function() { + var core = "", skin = ""; + var hasCore = false; + function onCore(c) { + core=c.core; + skin=c.skin; + hasCore = true; + } + return { + name : "Core", + fields : ["Core","Skin"], + getValues : () => { + var r = [core,skin]; + core = ""; + skin = ""; + return r; + }, + start : () => { + hasCore = false; + Bangle.on('CoreTemp', onCore); + }, + stop : () => { + hasCore = false; + Bangle.removeListener('CoreTemp', onCore); + }, + draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAyBAAHh0js3EuDMA8A8AWBnDj9A8A=="),x,y) + }; + } +}) + diff --git a/apps/recorder/widget.js b/apps/recorder/widget.js index 359af721f..de465b7c1 100644 --- a/apps/recorder/widget.js +++ b/apps/recorder/widget.js @@ -90,32 +90,6 @@ draw : (x,y) => g.setColor(Bangle.isCharging() ? "#0f0" : "#ff0").drawImage(atob("DAwBAABgH4G4EYG4H4H4H4GIH4AA"),x,y) }; }, - temp:function() { - var core = 0, skin = 0; - var hasCore = false; - function onCore(c) { - core=c.core; - skin=c.skin; - hasCore = true; - } - return { - name : "Core", - fields : ["Core","Skin"], - getValues : () => { - var r = [core,skin]; - return r; - }, - start : () => { - hasCore = false; - Bangle.on('CoreTemp', onCore); - }, - stop : () => { - hasCore = false; - Bangle.removeListener('CoreTemp', onCore); - }, - draw : (x,y) => g.setColor(hasCore?"#0f0":"#8f8").drawImage(atob("DAwBAAAOAKPOfgZgZgZgZgfgPAAA"),x,y) - }; - }, steps:function() { var lastSteps = 0; return { From 6b22bd84866a13e1d21f29fca670109f4cb10059 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 22:52:03 +0100 Subject: [PATCH 131/169] Bump version and changelog for recorder --- apps.json | 2 +- apps/recorder/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index e3964fd2a..d121ddccc 100644 --- a/apps.json +++ b/apps.json @@ -770,7 +770,7 @@ "id": "recorder", "name": "Recorder (BETA)", "shortName": "Recorder", - "version": "0.06", + "version": "0.07", "description": "Record GPS position, heart rate and more in the background, then download to your PC.", "icon": "app.png", "tags": "tool,outdoors,gps,widget", diff --git a/apps/recorder/ChangeLog b/apps/recorder/ChangeLog index dbf086f7d..e2ae0111b 100644 --- a/apps/recorder/ChangeLog +++ b/apps/recorder/ChangeLog @@ -8,3 +8,6 @@ Fix execution of other recorders (*.recorder.js) Modified icons and colors for better visibility Only show plotting speed if Latitude is available +0.07: Add recording for Barometer + Record all HRM events + Move recording for CoreTemp to its own app From 225c5566cda17464b5a5d6be0af2a06188b4b9ac Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 20:26:07 +0100 Subject: [PATCH 132/169] Move previously registered HRM listener over if needed --- apps/bthrm/boot.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 0aa8d5c96..85333feb1 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -12,7 +12,6 @@ Bangle.isHRMOn = function() { var settings = require('Storage').readJSON("bthrm.json", true) || {}; - print(settings); if (settings.enabled && !settings.replace){ return origIsHRMOn(); } else if (settings.enabled && settings.replace){ @@ -107,8 +106,20 @@ if (settings.enabled || !isOn){ Bangle.setBTHRMPower(isOn, app); } - if (settings.enabled && !settings.replace || !isOn){ + if ((settings.enabled && !settings.replace) || !settings.enabled || !isOn){ origSetHRMPower(isOn, app); } } + + var settings = require('Storage').readJSON("bthrm.json", true) || {}; + if (settings.enabled && settings.replace){ + if (!(Bangle._PWR===undefined) && !(Bangle._PWR.HRM===undefined)){ + for (var i = 0; i < Bangle._PWR.HRM.length; i++){ + var app = Bangle._PWR.HRM[i]; + origSetHRMPower(0, app); + Bangle.setBTHRMPower(1, app); + if (Bangle._PWR.HRM===undefined) break; + } + } +} })(); From 92139253bebb1846d910e1392d83689e6b31886a Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:44:18 +0100 Subject: [PATCH 133/169] Set src property if emitting an event --- apps/bthrm/boot.js | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/apps/bthrm/boot.js b/apps/bthrm/boot.js index 85333feb1..fbc872630 100644 --- a/apps/bthrm/boot.js +++ b/apps/bthrm/boot.js @@ -68,13 +68,11 @@ var interval = dv.getUint16(idx,1); // in milliseconds }*/ - - var eventName = settings.replace ? "HRM" : "BTHRM"; - - Bangle.emit(eventName, { + Bangle.emit(settings.replace?"HRM":"BTHRM", { bpm:bpm, - confidence:100 - }); + confidence:100, + src:settings.replace?"bthrm":undefined + }); }); return characteristic.startNotifications(); }).then(function() { From b02befe3dd0b9ba65b46339acee17358bd9c85d8 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 19:46:15 +0100 Subject: [PATCH 134/169] Record empty string if no value instead of 0 --- apps/bthrm/recorder.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/bthrm/recorder.js b/apps/bthrm/recorder.js index 40f64a676..b1c27660d 100644 --- a/apps/bthrm/recorder.js +++ b/apps/bthrm/recorder.js @@ -1,15 +1,15 @@ (function(recorders) { recorders.bthrm = function() { - var bpm = 0; + var bpm = ""; function onHRM(h) { - bpm = h.bpm; + bpm = h.bpm; } return { name : "BTHR", fields : ["BT Heartrate"], getValues : () => { result = [bpm]; - bpm = 0; + bpm = ""; return result; }, start : () => { From e0a4cea3b8d3666686d11fb8387b135915c4b88c Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:24:38 +0100 Subject: [PATCH 135/169] Explicit call to setBTHRMPower is not needed --- apps/bthrm/bthrm.js | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 7c80c735f..81d5d5997 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -35,7 +35,6 @@ Bangle.on('BTHRM', onBtHrm); Bangle.on('HRM', onHrm); Bangle.setHRMPower(1,'bthrm') -Bangle.setBTHRMPower(1,'bthrm') g.clear(); Bangle.loadWidgets(); From 9aba113acb72fbd6b277844cfc5abfe7a3a02ca2 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:31:44 +0100 Subject: [PATCH 136/169] Show actual source for HRM event --- apps/bthrm/bthrm.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/bthrm/bthrm.js b/apps/bthrm/bthrm.js index 81d5d5997..712344b11 100644 --- a/apps/bthrm/bthrm.js +++ b/apps/bthrm/bthrm.js @@ -9,13 +9,14 @@ function draw(y, event, type, counter) { var px = g.getWidth()/2; g.reset(); g.setFontAlign(0,0); - g.clearRect(0,y,g.getWidth(),y+80); + g.clearRect(0,y,g.getWidth(),y+75); if (type == null || event == null || counter == 0) return; var str = event.bpm + ""; g.setFontVector(40).drawString(str,px,y+20); str = "Confidence: " + event.confidence; g.setFontVector(12).drawString(str,px,y+50); str = "Event: " + type; + if (type == "HRM") str += " Source: " + (event.src ? event.src : "internal"); g.setFontVector(12).drawString(str,px,y+60); } From 56e33ed98ba854f52a807cd066ca139cfbf28062 Mon Sep 17 00:00:00 2001 From: Martin Boonk Date: Wed, 12 Jan 2022 23:10:36 +0100 Subject: [PATCH 137/169] Bump version and changelog --- apps.json | 2 +- apps/bthrm/ChangeLog | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..dc887d255 100644 --- a/apps.json +++ b/apps.json @@ -1042,7 +1042,7 @@ "id": "bthrm", "name": "Bluetooth Heart Rate Monitor", "shortName": "BT HRM", - "version": "0.02", + "version": "0.03", "description": "Overrides Bangle.js's build in heart rate monitor with an external Bluetooth one.", "icon": "app.png", "type": "app", diff --git a/apps/bthrm/ChangeLog b/apps/bthrm/ChangeLog index 27a58dd78..481d855c8 100644 --- a/apps/bthrm/ChangeLog +++ b/apps/bthrm/ChangeLog @@ -2,3 +2,6 @@ 0.02: Make overriding the HRM event optional Emit BTHRM event for external sensor Add recorder app plugin +0.03: Prevent readings from internal sensor mixing into BT values + Mark events with src property + Show actual source of event in app From a98a6015b1c381476901aae9abb89370034c243b Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 12 Jan 2022 22:45:42 +0000 Subject: [PATCH 138/169] Simple Pedometer and Lato Pedometer widgets --- apps.json | 32 ++++++++++++++++++++++++++++++++ apps/widpa/README.md | 16 ++++++++++++++++ apps/widpa/screenshot_widpa.png | Bin 0 -> 246 bytes apps/widpa/widpa.wid.js | 17 +++++++++++++++++ apps/widpb/README.md | 17 +++++++++++++++++ apps/widpb/screenshot_widpb.png | Bin 0 -> 338 bytes apps/widpb/widpb.wid.js | 20 ++++++++++++++++++++ 7 files changed, 102 insertions(+) create mode 100644 apps/widpa/README.md create mode 100644 apps/widpa/screenshot_widpa.png create mode 100644 apps/widpa/widpa.wid.js create mode 100644 apps/widpb/README.md create mode 100644 apps/widpb/screenshot_widpb.png create mode 100644 apps/widpb/widpb.wid.js diff --git a/apps.json b/apps.json index 4c6f3bdcf..56ddbed2d 100644 --- a/apps.json +++ b/apps.json @@ -5577,5 +5577,37 @@ "data": [ {"name":"banglexercise.json"} ] + }, + { + "id": "widpa", + "name": "Simple Pedometer", + "shortName":"Simple Pedometer", + "icon": "screenshot_widpa.png", + "screenshots": [{"url":"screenshot_widpa.png"}], + "version":"0.01", + "type": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in 12x16 font, requires firmware v2.11.21 or later", + "tags": "widget,battery", + "storage": [ + {"name":"widpa.wid.js","url":"widpa.wid.js"} + ] + }, + { + "id": "widpb", + "name": "Lato Pedometer", + "shortName":"Lato Pedometer", + "icon": "screenshot_widpb.png", + "screenshots": [{"url":"screenshot_widpb.png"}], + "version":"0.01", + "type": "widget", + "supports": ["BANGLEJS", "BANGLEJS2"], + "readme": "README.md", + "description": "Displays the current step count from `Bangle.getHealthStatus(\"day\").steps` in the Lato font, requires firmware v2.11.21 or later", + "tags": "widget,battery", + "storage": [ + {"name":"widpb.wid.js","url":"widpb.wid.js"} + ] } ] diff --git a/apps/widpa/README.md b/apps/widpa/README.md new file mode 100644 index 000000000..92fbb8c11 --- /dev/null +++ b/apps/widpa/README.md @@ -0,0 +1,16 @@ +# Simple Pedometer Widget + +*Displays the current step count from `Bangle.getHealthStatus("day").steps` in (6x8,2) font, Requires firmware v2.11.21 or later* + +* Designed to be small, minimal, does one thing well, no settings +* Supports Bangle 1 and Bangle 2 + +## Notes + +* Requires firmware v2.11.21 or later +* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press +* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded. + +![](screenshot_widpa.png) + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/widpa/screenshot_widpa.png b/apps/widpa/screenshot_widpa.png new file mode 100644 index 0000000000000000000000000000000000000000..e33550f50d6376cdec0f5faeaaec87a548e979f3 GIT binary patch literal 246 zcmVPx#ut`KgR9HvtR?!ZCAPAKI|7hFVXv)Gv%MBU5LKnv!1l3w=IsBm{;Y7hy!if+i zt`bDlHCbC=GLK*SD_<(j-;?;SN*ql>V`}XP=SdudYmIA4cS;~Itw=-?;acNE5}LPn zd3@HcJOjg-2t@*I71R-{-B#^qQX)w-?ftr)kiF%s-rLE#9ainMijU5kr=Io{-~9)k w#YeOA%wRYYNItLexL2&#j%#(L5?&O$01ECQ%Y=MG this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;} + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); + g.setColor(g.theme.fg); + g.setFont('6x8',2); + g.setFontAlign(-1, 0); + g.drawString(steps, this.x, this.y + 12); +}}; diff --git a/apps/widpb/README.md b/apps/widpb/README.md new file mode 100644 index 000000000..bec127b6b --- /dev/null +++ b/apps/widpb/README.md @@ -0,0 +1,17 @@ +# Lato Pedometer Widget + +*Displays the current step count from `Bangle.getHealthStatus("day").steps` in the Lato font, Requires firmware v2.11.21 or later* + +* Designed to be minimal, does one thing well, no settings +* Supports Bangle 1 and Bangle 2 + +## Notes + +* Requires firmware v2.11.21 or later +* Uses the Lato custom font, so memory footprint is 500 bytes larger than 'Simple Pedometer Widget' +* `Bangle.getHealthStatus("day").steps` is reset to zero if you reboot your watch with a long BTN Press +* The step count displayed may be a few steps more than that reported by widpedpm as widpedom may not always be loaded. + +![](screenshot_widpb.png) + +Written by: [Hugh Barney](https://github.com/hughbarney) For support and discussion please post in the [Bangle JS Forum](http://forum.espruino.com/microcosms/1424/) diff --git a/apps/widpb/screenshot_widpb.png b/apps/widpb/screenshot_widpb.png new file mode 100644 index 0000000000000000000000000000000000000000..af1222e7e8663af2945d6f4c2978cad7a4cac5b8 GIT binary patch literal 338 zcmV-Y0j>UtP)Px$3`s;mR9HvtSkVrIAPhVH|D!RO!{FR#y9Yyvz8N=Y*KTlEYOVFR!BajWi>bK3 zBBhk8=207sF{40i+cA6eb$e`xCF&8hNkpP=jL6vhSvZDZ(xStFt2!bhkuB zk)~GG^WKS!M)1QD!3{x;yRIn6%d>;et2%04rqT+g+g&SrF0c*j5uRBqO$7OQ this.width) {this.width = w; setTimeout(() => Bangle.drawWidgets(),10); return;} + g.reset(); + g.setColor(g.theme.bg); + g.fillRect(this.x, this.y, this.x + this.width, this.y + 23); // erase background + g.setColor(g.theme.fg); + // Lato from fonts.google.com, Actual height 17 (17 - 1), Numeric only + const scale = 1; + g.setFontCustom(atob("AAAAABwAAOAAAgAAHAADwAD4AB8AB8AA+AAeAADAAAAOAAP+AH/8B4DwMAGBgAwMAGBgAwOAOA//gD/4AD4AAAAAAAABgAAcAwDAGAwAwP/+B//wAAGAAAwAAGAAAAAAAAIAwHgOA4DwMA+BgOwMDmBg4wOeGA/gwDwGAAAAAAAAAGAHA8A4DwMAGBhAwMMGBjgwOcOA+/gDj4AAAAABgAAcAAHgADsAA5gAOMAHBgBwMAP/+B//wABgAAMAAAAAAAgD4OB/AwOYGBjAwMYGBjBwMe8Bh/AIHwAAAAAAAAAfAAP8AHxwB8GAdgwPMGBxgwMOOAB/gAH4AAAAAAABgAAMAABgAwMAeBgPgMHwBj4AN8AB+AAPAABAAAAAAAMfAH38B/xwMcGBhgwMMGBjgwP+OA+/gDj4AAAAAAAAOAAH4AA/gQMMGBgzwME8BhvAOPgA/4AD8AAEAAAAAAGAwA4OAHBwAAA="), 46, atob("BAgMDAwMDAwMDAwMBQ=="), 21+(scale<<8)+(1<<16)); + g.setFontAlign(-1, 0); + g.drawString(steps, this.x, this.y + 12); +}}; From 60bb06a655595a6bab3f539c4f266eea1f934f63 Mon Sep 17 00:00:00 2001 From: hughbarney Date: Wed, 12 Jan 2022 22:46:16 +0000 Subject: [PATCH 139/169] Simple Pedometer and Lato Pedometer widgets --- apps/widpa/ChangeLog | 1 + apps/widpb/ChangeLog | 1 + 2 files changed, 2 insertions(+) create mode 100644 apps/widpa/ChangeLog create mode 100644 apps/widpb/ChangeLog diff --git a/apps/widpa/ChangeLog b/apps/widpa/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/widpa/ChangeLog @@ -0,0 +1 @@ +0.01: First release diff --git a/apps/widpb/ChangeLog b/apps/widpb/ChangeLog new file mode 100644 index 000000000..7b83706bf --- /dev/null +++ b/apps/widpb/ChangeLog @@ -0,0 +1 @@ +0.01: First release From 223f6b6b8120f34e5063e7fa4ccde04deeb22f83 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Wed, 12 Jan 2022 23:57:44 +0100 Subject: [PATCH 140/169] fixes #1271 & some code rework + moved settings-helper method def to load settings method + settingsfile as const + isBangle1 via HWVERSION==1 --- apps.json | 2 +- apps/antonclk/ChangeLog | 5 ++++- apps/antonclk/README.md | 6 +++--- apps/antonclk/app.js | 36 +++++++++++++++++++++++------------- apps/antonclk/settings.js | 4 ++-- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/apps.json b/apps.json index 4c6f3bdcf..dd2ddbcb3 100644 --- a/apps.json +++ b/apps.json @@ -4279,7 +4279,7 @@ { "id": "antonclk", "name": "Anton Clock", - "version": "0.05", + "version": "0.06", "description": "A clock using the bold Anton font, optionally showing seconds and date in ISO-8601 format.", "readme":"README.md", "icon": "app.png", diff --git a/apps/antonclk/ChangeLog b/apps/antonclk/ChangeLog index fdf20c175..4dca8053e 100644 --- a/apps/antonclk/ChangeLog +++ b/apps/antonclk/ChangeLog @@ -4,4 +4,7 @@ 0.04: Clock can optionally show seconds, date optionally in ISO-8601 format, weekdays and uppercase configurable, too. 0.05: Clock can optionally show ISO-8601 calendar weeknumber (default: Off) when weekday name "Off": week #: - when weekday name "On": weekday name is cut at 6th position and .# is added \ No newline at end of file + when weekday name "On": weekday name is cut at 6th position and .# is added +0.06: fixes #1271 - wrong settings name + when weekday name and calendar weeknumber are on then display is # + week is buffered until date or timezone changes \ No newline at end of file diff --git a/apps/antonclk/README.md b/apps/antonclk/README.md index 85c03788d..28a38f5fd 100644 --- a/apps/antonclk/README.md +++ b/apps/antonclk/README.md @@ -40,9 +40,9 @@ The main menu contains several settings covering Anton clock in general. * **Show Weekday** - Weekday is shown in the time presentation without seconds. Weekday name depends on the current locale. If seconds are shown, the weekday is never shown as there is not enough space on the watch face. -* **Show Weeknumber** - Week-number (ISO-8601) is shown. (default: Off) -If "Show Weekday" is "Off" the week-number is displayed as "week #:". -If "Show Weekday" is "On" the weekday name is cut at 6th position and suffixed with ".#". +* **Show CalWeek** - Week-number (ISO-8601) is shown. (default: Off) +If "Show Weekday" is "Off" displays the week-number as "week #". +If "Show Weekday" is "On" displays "weekday name short" with " #" . If seconds are shown, the week number is never shown as there is not enough space on the watch face. * **Vector font** - Use the built-in vector font for dates and weekday. This can improve readability. diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 05758cbfd..7d8c8ce89 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -1,6 +1,6 @@ // Clock with large digits using the "Anton" bold font -var SETTINGSFILE = "antonclk.json"; +const SETTINGSFILE = "antonclk.json"; Graphics.prototype.setFontAnton = function(scale) { // Actual height 69 (68 - 0) @@ -28,7 +28,7 @@ var drawTimeout; var queueMillis = 1000; var secondsScreen = true; -var isBangle1 = (g.getWidth() == 240); +var isBangle1 = (process.env.HWVERSION == 1); //For development purposes /* @@ -50,13 +50,11 @@ require('Storage').writeJSON(SETTINGSFILE, { require('Storage').erase(SETTINGSFILE); */ -// Helper method for loading the settings -function def(value, def) { - return (value !== undefined ? value : def); -} - // Load settings function loadSettings() { + // Helper function default setting + function def (value, def) {return value !== undefined ? value : def;} + var settings = require('Storage').readJSON(SETTINGSFILE, true) || {}; secondsMode = def(settings.secondsMode, "Never"); secondsColoured = def(settings.secondsColoured, true); @@ -104,7 +102,14 @@ function isoStr(date) { return date.getFullYear() + "-" + ("0" + (date.getMonth() + 1)).substr(-2) + "-" + ("0" + date.getDate()).substr(-2); } +var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 + console.log(date); + dateNoTime = date; dateNoTime.setHours(0,0,0,0); + console.log(dateNoTime); + if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; + calWeekBuffer[0] = date.getTimezoneOffset(); + calWeekBuffer[1] = dateNoTime; var tdt = new Date(date.valueOf()); var dayn = (date.getDay() + 6) % 7; tdt.setDate(tdt.getDate() - dayn + 3); @@ -113,7 +118,8 @@ function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu if (tdt.getDay() !== 4) { tdt.setMonth(0, 1 + ((4 - tdt.getDay()) + 7) % 7); } - return 1 + Math.ceil((firstThursday - tdt) / 604800000); + calWeekBuffer[2] = 1 + Math.ceil((firstThursday - tdt) / 604800000); + return calWeekBuffer[2]; } function doColor() { @@ -186,13 +192,17 @@ function draw() { else g.setFont("6x8", 2); g.drawString(dateStr, x, y); - if (weekDay || calWeek) { - var dowwumStr = require("locale").dow(date); + if (calWeek || weekDay) { + var dowcwStr = ""; if (calWeek) - dowwumStr = (weekDay ? dowwumStr.substr(0,Math.min(dowwumStr.length,6)) + (dowwumStr.length>=6 ? "." : "") : "week ") + "#" + ISO8601calWeek(date); //TODO: locale for "week" + dowcwStr = " #" + ("0" + ISO8601calWeek(date)).substring(-2); + if (weekDay) + dowcwStr = require("locale").dow(date, calWeek ? 1 : 0) + dowcwStr; //weekDay e.g. Monday or weekDayShort # e.g. Mon #01 + else //week #01 + dowcwStr = /*LANG*/"week" + dowcwStr; if (upperCase) - dowwumStr = dowwumStr.toUpperCase(); - g.drawString(dowwumStr, x, y + (vectorFont ? 26 : 16)); + dowcwStr = dowcwStr.toUpperCase(); + g.drawString(dowcwStr, x, y + (vectorFont ? 26 : 16)); } } diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 293aa0438..45c89f0a4 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -48,10 +48,10 @@ } }, "Show Weeknumber": { - value: (settings.weekNum !== undefined ? settings.weekNum : true), + value: (settings.calWeek !== undefined ? settings.calWeek : false), format: v => v ? "On" : "Off", onchange: v => { - settings.weekNum = v; + settings.calWeek = v; writeSettings(); } }, From b9031b1844be8ad0f3951c8baa9ea301d1c70085 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 13 Jan 2022 00:06:49 +0100 Subject: [PATCH 141/169] settings txt weeknumber was to long --- apps/antonclk/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/antonclk/settings.js b/apps/antonclk/settings.js index 45c89f0a4..e452b02c7 100644 --- a/apps/antonclk/settings.js +++ b/apps/antonclk/settings.js @@ -47,7 +47,7 @@ writeSettings(); } }, - "Show Weeknumber": { + "Show CalWeek": { value: (settings.calWeek !== undefined ? settings.calWeek : false), format: v => v ? "On" : "Off", onchange: v => { From 6098af08b8d36a6b8cdf33a8f440802de876ac69 Mon Sep 17 00:00:00 2001 From: Danny <31635744+DDDanny@users.noreply.github.com> Date: Thu, 13 Jan 2022 01:02:02 +0100 Subject: [PATCH 142/169] removed two log statements --- apps/antonclk/app.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/apps/antonclk/app.js b/apps/antonclk/app.js index 7d8c8ce89..7b40d8eb5 100644 --- a/apps/antonclk/app.js +++ b/apps/antonclk/app.js @@ -104,9 +104,7 @@ function isoStr(date) { var calWeekBuffer = [false,false,false]; //buffer tz, date, week no (once calculated until other tz or date is requested) function ISO8601calWeek(date) { //copied from: https://gist.github.com/IamSilviu/5899269#gistcomment-3035480 - console.log(date); dateNoTime = date; dateNoTime.setHours(0,0,0,0); - console.log(dateNoTime); if (calWeekBuffer[0] === date.getTimezoneOffset() && calWeekBuffer[1] === dateNoTime) return calWeekBuffer[2]; calWeekBuffer[0] = date.getTimezoneOffset(); calWeekBuffer[1] = dateNoTime; From 5e4cd77313f3f25193d50365b4bde8c4bbc539d7 Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 13 Jan 2022 06:41:37 +0100 Subject: [PATCH 143/169] Update apps.json --- apps.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps.json b/apps.json index b90deb045..bef974af8 100644 --- a/apps.json +++ b/apps.json @@ -32,13 +32,13 @@ { "id": "ac_ac", "name": "A Configurable Analog Clock", "shortName":"Configurable Clock", - "version":"0.01", + "version":"0.02", "description": "AC-AC, a highly customizable analog clock", "icon": "app-icon.png", "type": "clock", "tags": "clock", "supports" : ["BANGLEJS2"], - "allow_emulator": true, + "allow_emulator": false, "screenshots": [{"url":"app-screenshot.png"}], "readme": "README.md", "custom": "Customizer.html", From ee02b17196fe4b62e8049ab619be3e55102ae21e Mon Sep 17 00:00:00 2001 From: Andreas Rozek Date: Thu, 13 Jan 2022 06:42:13 +0100 Subject: [PATCH 144/169] Update Customizer.html --- apps/ac_ac/Customizer.html | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/apps/ac_ac/Customizer.html b/apps/ac_ac/Customizer.html index 2846352d6..8cddbb4da 100644 --- a/apps/ac_ac/Customizer.html +++ b/apps/ac_ac/Customizer.html @@ -101,7 +101,7 @@