From 629426077c8140eeb01c4244bdd8c17ea782118f Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 17:44:53 +0100 Subject: [PATCH 01/30] Update travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 0ec304a..b976ad2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ cache: before_install: - npm install -g node-gyp - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi + - node_modules/.bin/electron-rebuild # These commands are executed before the scripts are executed install: From 68bcc4e913e1b125ff4185a3d9695851b4add7a8 Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 17:49:41 +0100 Subject: [PATCH 02/30] Update travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b976ad2..c8e8fa7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,12 +40,12 @@ cache: before_install: - npm install -g node-gyp - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi - - node_modules/.bin/electron-rebuild # These commands are executed before the scripts are executed install: # Install all dependencies listed in your package.json file - npm install + - node_modules/.bin/electron-rebuild script: - tsc From 7fb03e3354d4fd3c844fd14ee9aa7eb956913f3a Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 17:54:06 +0100 Subject: [PATCH 03/30] Change g++-5 to g++ --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c8e8fa7..44772fc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,7 +16,7 @@ addons: sources: - ubuntu-toolchain-r-test packages: - - g++-5 + - g++ # A list of operating systems which are used for tests os: @@ -28,7 +28,7 @@ env: - ELECTRON_CACHE=$HOME/.cache/electron - ELECTRON_BUILDER_CACHE=$HOME/.cache/electron-builder - YARN-GPG=no - - CXX=g++-5 + - CXX=g++ cache: yarn: true From 4e27802de153a5f0e4eca6e6e95fc48db32bf2b1 Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 17:58:34 +0100 Subject: [PATCH 04/30] Update travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 44772fc..908f7bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,6 +40,7 @@ cache: before_install: - npm install -g node-gyp - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; apt-get install libsecret-1-dev; fi # These commands are executed before the scripts are executed install: From 7743060f2fc9e23347f703f0062164a06a8c1fd4 Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 18:01:38 +0100 Subject: [PATCH 05/30] Update travis.yml --- .travis.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index 908f7bc..1062a73 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,24 +1,20 @@ -osx_image: xcode10.3 # define OS X image which will be mounted +osx_image: xcode10.3 -dist: xenial # use Ubuntu Xenial for Linux operation system +dist: xenial -# Note: if you switch to sudo: false, you'll need to launch chrome with --no-sandbox. -# See https://github.com/travis-ci/travis-ci/issues/8836 sudo: required -# Define Node.js as the programming language as we have a web application language: node_js node_js: '11' addons: - chrome: stable # Install chrome stable on operating systems + chrome: stable apt: sources: - ubuntu-toolchain-r-test packages: - g++ -# A list of operating systems which are used for tests os: - linux - osx @@ -42,9 +38,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; apt-get install libsecret-1-dev; fi -# These commands are executed before the scripts are executed install: - # Install all dependencies listed in your package.json file - npm install - node_modules/.bin/electron-rebuild @@ -52,6 +46,5 @@ script: - tsc - echo "Deploy linux release to GitHub" - if [[ "$TRAVIS_BRANCH" == "canary" ]] && [[ "$TRAVIS_OS_NAME" == "linux" ]]; then npm run publish:linux; fi - - echo "Deploy mac release to GitHub" - if [[ "$TRAVIS_BRANCH" == "canary" ]] && [[ "$TRAVIS_OS_NAME" == "osx" ]]; then npm run publish:mac; fi From 86e592e74eb068752e09171562152cef9e7c86e1 Mon Sep 17 00:00:00 2001 From: QuiiBz <43268759+QuiiBz@users.noreply.github.com> Date: Tue, 25 Feb 2020 18:33:49 +0100 Subject: [PATCH 06/30] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 1062a73..2a166d8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ cache: before_install: - npm install -g node-gyp - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; apt-get install libsecret-1-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install libsecret-1-dev; fi install: - npm install From bcf75ea282cab1fcc41d315856a6efb49601d711 Mon Sep 17 00:00:00 2001 From: QuiiBz <43268759+QuiiBz@users.noreply.github.com> Date: Tue, 25 Feb 2020 18:38:16 +0100 Subject: [PATCH 07/30] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2a166d8..a11af94 100644 --- a/.travis.yml +++ b/.travis.yml @@ -36,7 +36,7 @@ cache: before_install: - npm install -g node-gyp - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install python; fi - - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then apt-get install libsecret-1-dev; fi + - if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get install libsecret-1-dev; fi install: - npm install From 5218a91ee8b7edf456f3ce2c9f0ccceaeaea9dec Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Tue, 25 Feb 2020 19:00:58 +0100 Subject: [PATCH 08/30] Edit version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 2ddf215..9228e1b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "squid", - "version": "1.0.4", + "version": "1.0.5", "author": "QuiiBz", "productName": "Squid", "description": "A terminal for everyone", From 5420970249dc6fb0ff589193d5dfca4fd226f099 Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Wed, 26 Feb 2020 10:10:10 +0100 Subject: [PATCH 09/30] Fix logo not showing --- ui/images/logo.png | Bin 0 -> 26327 bytes ui/index.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 ui/images/logo.png diff --git a/ui/images/logo.png b/ui/images/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..499d9c16952defdbf59e9307fb510881228eab8f GIT binary patch literal 26327 zcmd42XIN8P*ESkJz=EJ60!mZ2pwdA)NkG}4RFx8t-lcZ}33Xc#X}XajT@esM?=1vH zKtTvaAhe+L9w9&=p`5ki^StN#@m}B0a~-aWk~Q0yW87nmdyct?zOS!!`sBrv5D4V- zy}KF@ArPiT@cTFm@I){7$1L!R*Z*%*e?u=Pf26IiBShW7%g#~go`zOwRdy$7qWA7cJYK>AvNKy2)Q^w zuOQ^~r1ZS+I6ii{i}H0eMClvZqulJ39In7&LaIT^zyuzS{Nkb;tgw49Qn%q=k?87XObNhu{s z>09Db(#ldw%2Luo|M|KCtmfPL>&_moW*wf!ONZix!>VId@aP+hHb@BFh@$wV`XSB8R3h;+s0VMsi1rKjM zz5kim)9*iu0#qg$Wa}*{Eg>c8;Q{W8-rLXrq2vE6#{b&e&nVd2QSzaqpI3mdJzx)~ ztN$Gg=6WaNjGgT*aXWh% z1#u^ZTT0?evQmoTc8+q=_D*tuHtcWxcb@-kyp*i8hLoK29XZ**)upBXR=<5m>W;d? zElp`n_1n@icclJ1_MWGozpbaebrcLOxjpIvJ>`nm)aJWsH!K<}9;4T| zxi}O&a;Hpa@1WzpgQW^<4+pc{#wck!nfali1jeQam@;v&nxj1d@fE*?6CmOG6cAr9 zb<94Id=Ll^i!od>khQOO%KTsvO3)@TB`5iJPcA)3RWKrHd* zo`J$zqMiz&`rBcZdsN9X1k(DLWv4DYF6{7I#v7F=zhAypE-QLXeboi&JEYvY#>3l# zR?$RlRnpe0l}3SOcq>%#NmllGevdJ&^c}JuO=GL~_0&WQVDeV$0KZEiS=L7hdNgeQ zfy>?voMKwJ?wAm%R%mqGJeYIcZ$>le|{@o>uaii4=X*)yt2UYn8 zKKntK<_L)#TrRG^8aG+Zp+zd*dk^)@=@)Pn>~LYSMUHF?L*FhK$)@=~zM7Y$TMjbp5 zORi~w^;N?kkBv;j+(WthSlgl(OHz+g`b7_&L{)(8U=w3<&1fsp`JpW?M~K0efocTv z*2e4X;aUFqBSlp9uxh?FFyDkigK1h#Yp-V6G@50*SqH14&tc2QL_G|dEUC3{F%5{wPzV7{@WZKSm#r;p6 zc`s=igJDH3M;?P=SBujCZLvM+$v=SW(ctMjlldO2v*GT2nEJYopRCG*)p)tJZ22|8 zlMBFVcX9{uK1bErD^8kw94gBU(D0z(fH8QqRZSp;K2J&@9Dk4))^cg|6|4yJ&G;xP z`Pt9I^n7fm%4rBh>c?j9)=`5?RllfE-MOoQ&eZEHTN7N~*HPKU`;vMp(@=me@SJGa zrQ$Tbj1RIE)X$Z}90Z2*kx_`DRxzRxPns8z3ZIcFjJGO3M5O5aJPZ~}@fc3|HZOxxMB#n6;S7dYl$~Vf7l&3Zz48yVhbC#&7^Ld-MqP7iydr#-EG$4L~Q<|gNw`3ot~7V z_b$%ZaG;^NXEe+zL|bi&<{ehOx0#T>V@Bc!p4Yt!-hg|JJzxkWecm%7&z;hvnd_x* zf~xR7^_Kf6aI3bFLobl8mTQZ0YfVsoEtUdUBLexVVFU1x4-qZhK!~d3nV5QEwG@IV z0*3w8FA59$ZoH+$5Q+>1kaBNu9_tLOG!gkd0XI=?aB{KfL-@|Vb1vdp*=9Vr4r@_Z z{C8EQ-_HF}j?4$L(hgBH;4#l}!voblUWU*pV1-S}E;4P$mc#{2guIOC56{b%WZvT6 zeLM&wR>va&@)*%1)sIgSQLe} z;BlahHQZW&tFO)l_{!hgjLzpjku(l0On6%)*b5)Ur!!LJ`C_bm>Su^o!T##=-PY?1 zdJLhLHbYuj-y>52AAtlG4dUN&oLEFY1{6MjXPk5Z%wWUq*t@R=M*=JU+*r(nXK$|q zUCU#fXu)J3hJ)VOFlCl>Rl}<%7z<&JwCb^5<%OnM;6i-x20Ju>>w0~biR0q{9CKRF@{U0VmN=q;%SNaTbD;vj^P3Q67Z1pbhUSMu*;Y$Pv$ zeI41kUI02(Qv+6q9Py82=jT=2*`W&Jx)b4m%n*CW~T^!pH`bv}SB+|U6-e9>Hf$*rTp?L`ywgCox}29VsudP{kw^g$os zllwBQRrIcVh1DF}&?mcqE7q&Slfofhx2$D9dcE-` zdQ1l&jyb{W7s|Zk)uBx2=X+M()@!Vxpk^c9vCou*^<}x=-Ze5iOS<(dq%uo#ZJxr} zQ7+h}7Y+|fTS_L$o8gm6RvMl`aoI0M zD_>eplGR$Ed!KIq$gB%XN!&KkMd;}H!_TZtUUFPPdp@%+^Zeo(&`@n*$qK@y-pltI z)#*4s`BO+f?2PPWUggD5*;j}=Auig7hvPljSMi@yhPExt%4+RoP3-alluU|Zu6>~N z7E?Z>Ls!~<(^+Q|uc`U9YNy@aR^<^WU)A=n&CtSDD+7)Ip>PTujX7W3P2Mszr`feA zoBXr)C_pY5qcEen(z6*_c4a@=<2OiGTZvzjHreJB>M9Kaxb0=;secn5d1aCWSohTb z4ioAx6tORQ^!N(x;rAge;utl{7K$%p0+qV@Qfyg%$b<1Q*3_iixhab3{2k3a)nP_r ziYChMzMWvf$q7~sz4O(CW*e6lm6;&yN&-sGXEK3%Cj|cfUNXU{x01tdkdSPXg;@yB4vy`=u#?%vA>-7<+Py<*cJgdMU-qoFN|+notNgqkLbsl`c`zb4 zOPa(Lu5#Y62UnM7L%jHVrJn`CwT3D>v53vd5)2eW;#0^=SlQ(f)hnQn|8#olo;2;n z+p*BpY5xxW-pCOzJHHxlQWyd^EX_+VLOJghtRQAkD;C9am!YDc%pb6VP?lz&AKfhW zf4(_tp;X3^bmp6YK5V%#e{RS>SpPsxtd1D#R)Vn43n+Z*ug(wdsYACk)tR9_bduGs z1^ppBDp({#7N;<_tt ztD-JAwulrnS-2Vb&6mYnfv+_#LEoh#_azDu(UZdH9b;Z#-vWDdGS%m3j`c6U z?boTL7j)jWh^{q+oo!fIH=v9E`ea1^vDWq1zQZ9?!-c6u+}%|1Cl`Jc*jXQ_-55aD z9QZ1whvjZ-x<4E8r;CF!dlza=F%t90jDAa1Ba_UI=_?8v?R~n}fDCh!$#2q;?$3(D zl%(k7AwjL$9G^?xN#`2lZYr>^MSs1+`#v>Gu-IYci~k;~YM@D+L>Kv1f9Xy0JhHA| zX_}^jG8P=~RMShdHKHe)8 zrUd1o{U#hy({lJcVJft~xXAj2b64ilZDr7DCh)kg%S&~=>G&Zn9aCpMhs&+sHmkgb zIQw1Tmqs2*b~@F}_tU)+%l_DKJA|`OpAz$lUt-}6ucTQ?xOHZeaDLjo9wQ4E?0F#E z%^&4{R-w=P03D_8pm^S#V-yZO6gF6E5gBG$i~U3FU)4 ze>qSKVar?+e&sA(-#imiY4uy}x@XwqL{djJhX;h`wn-lY&&7s^sH%r(Pmk<#y?fCV zdmu)Ylte!s;q)myNU4};w7EvdY@p$V@bo2t7fj{}9d?vY5Bbzw@03kbL7;27j{-XGIyh$lV9ewKX>! ze3`zJbtBUEz1)gEsK8q4mKx!8Ak>VQ$F>+iHYoi-2L#Ek6#W;wCp7<&N>hYh?J1< z%Ckdb*Mc-5M{^Z4*MLa3N;2tDiyz(SUnEAp-iqV|0}~!@-~We=UoV8lm8eXLxeQPf?)*#%C9piYa-LIu$kG7l$=tR z(eWgbr&j;R2G#C6c)ViRtTNl!rq zSnIN`j}*<}+79|$^X~xQ?ol!QTS0zCo0fNO7*wi_*yrHqn@p2h+IOR9f&*wl9uE_Y zp1COU!>J|uL_vyP?fzKPmww{@20=n>Z$d;A?B#0HUbQ^3^t_E4xx?@?>%m{_5op&+ z3$N|_4N;9H*SVSU5!}Cwg0&`Jv$tZMnE4~nloWla;mgl!++jR6i3chJeoeHzVH7!_ z9UNc&4|^;0VS5P0lryCF7Q@#7SGHQ;gGc1jc@^^pOOTpHJdhcOny#m1tqEKR;t4Vn zwXH>eY_7tJLKtjFqtooIS?OKxy(hKo-l2;uT$tN(xH#uBdy3Z0hct_g5vu3G$o721 z0czb#mhjAsjz;w|*?yc=Nhf)l1mb=iJ}5?vK>u_y@N~q}dQ%#M*F%Oo0-rx@X`(eb zr+bIV4Ua3NSr-DmcAm;ELRR0ZdbJRql2yY!-Bj9C%$C3CQq+ztVY88ta_8^K5JEtM zuT^Q$a#q~4_2~JjF@ckJ4)yE0o0=a?z9?}OAI7*nFu%uYlVYaMYBMqyx^QYTvBGP` zNcTsT!11e>r{+Qm$dkQDK2UC!N2OW#AFSH8^~FT?+`p!lLh8u;NJ}9|Q_lq?Byh<8 zIeC3F6_cQe*&JcZy@tgq&%O zk?3@CE3x>*0#UIwxByW}<|^TCEO7U5UIosL**8P!w0j*hF$Uy+0HJxG_JOR_N>TpoL|7NAt4J-hGLomuVV1r_CoB z>M!lsFqC^3ZXcSiW=V_(PX@C?N4YBv#7qk8OByeB4_y*C2^qHo(Cl&8{@NJB(dj;z zQS%H(gjaffUlIhJWi`*Yw-zlm-y~vJL|lk$6?d5W3i~(o?@$)dkUJU|aASzYC@Y}qJ*{G( z^SmV;CYFbGk2~Ed_s!;3ehdOjzF##Qt*cCMv<8EF#JKB7qO`Rj$*ZmAGiwv(W~eC5 zbVm*nq=KA>{H|T>dkHYJ`NqykG&}mkL=17OVr8g-P;4?8!`^BRfd6-LG)iKA#a{2O zwU{kGA#}8Ev$3Wjzf7+~}>R z3Ij7*m7)7^ShOQGlmkS>%gVXh^rSqFP7O0Ca))o{(N4{(pX}tF_%~o4@g_??iT2&G zmF&&iLAnIvHr zN*<$yybVO`*78aG*F(K;`)ESKC4-JZX2cOafd8eHm7@Ql4YDrKLi^Y+MEDfwO1AQJ ze>O6#D9d=_(e6O7J4LbD!LB|TDj5dxwjBWs{F@D>Tach)0F?*MbN`d+4eJ2W1poKa%iX&4}22(2COAZ zdn_ufdL}|T*Ilx;{`CH~`*(jY7D)EsXQ9Hh@GjQJlTRuvumWyF&!ZTnG{1j`bhuOD z!0`~1@u&v>*j7lyS#K%>lTdF<_qjK1!79RCJEL!@In&-!tx!4I&&rBOt|%9EGv3}Dhu zvyjVP5s14nqVVbdSIlrFUcZt3EU29~EHwQS^M2b8klAgoQa?KDsCRxtz1y+{(V%Ht zUMA8NJX~0b#jZuRp81-4-EiB^Wi*O`ClnUX%)`VfZQh$*XMfY^>GNN&L*?=B48AlF zV!1eu*?a*!n8!x}@oTe77@S$}$1*X=Z8VAtc?^`)cMVl(eHs-myEsl{ZHyE#6-Ynnswc>llxcRJH}Y?J=tVV2Vz* zCw0f9W1Au_8Gs8M8zI~$>&eK_XNQv$O}S{bfPaJH_~ zp=&E*Zf9f(Rrt0UAI0U*gM9&efZwJD4URDIh_3_YY50cr47aR4;L@y3snZd}w+IXc z1Ezaw3bYlfV-0I-7lsiw{*Hp#H-{!fRKXY!@hPJkpTziZ9TxQE#>1u_UT3#)sCPPTb6$Aav1#SDtX{TP z3+X8hZ_7swEm$I-a>UTI11>KUHt$28XK?vPob4-gwrhm-!NWZtM{OKmEE!m+A}#RH z^E4#&#ppw^n`IW~`fNiOQ6$(_y9^5$7^NV}J%3@5M-7QOQdXP|`elj^;yFx!1F=1| zP|B84kCI+Hs&Zrlv(QhNTc?q3N66mESQ1ZPv=j=^~5uarc=BfGC2yN z@XiQ#C1HBhwPxASKe0Ia=yFb5P&`wj*Co~;?;t!*nm!S>S*asyzC8mPW=iC@qOrL} zd(Q8Ra}*e`VRE%M@$?h~)BQf)qXxUQ=K8rULOR)AEuI;ut+FX}i$m@}Um)Kb8fY2Q znz=g6;u##p0Mr90TyJ~Y%=?+_ny3GrKxFTD0_-~Mo#G4wovI`uMD^Mag+JgGo-`QC z@{mqgswi(;=qlL%Bg#!59H3TK(B(S%)UQBl$Cs_X;h(HOjG;bCSsIK%vb@0BpzlRC0>~F`PR?_6T1p3fU$Vsbq2k4Y;8~1xl;DFF-?yLK? z;&SH;Z8Z=hgcZQ65g5JXl_6p1nV%kxm^I*VR4c5TR=4YaYkMZqB_rIG2 z&UeE3_^0CQpg3rlcimLu5#LXdIo2S~9-i0s%=E_}i^i{I)OmQZdS32)&Ue+f7-CZo zLhfsI+B+3|79xQCS8X|CxG^YWwJsU*+&hc4^|x+w_ld!!#UF-qDiJuCeswobze~r- zfSdF^xc6nfC`4JyZe#_toUiXu?3b|r;vj2cO3y!pt3VjkZB*HgO_KhZ?Cbtj`by`^ zKYLOag&I(j1WqXZ7Unulg4q&(*L(_k8I6BH58sChZYO0nz0{(_gh<$twbz z=5HXExUR%J9f5pfuh9_S9~DgBm)v86H!es=w94;z2JB7D;>#}#Y}~o>t!MNa#-)vW z-%()JTmzBgE=d(vI%A2Z572)>?ntAUq|R@OxfEorbBCVmjYK|7s(5dRSB_!_ncw*4 z*aua^u_8dUb(?}y#nArb$2MUUAd8yP7O?w(G@7)PVXs;R1pC1B>-X!1enZ)RWefb@N z6z+`WQ@Lpfi+E>~{Z}gxDvK=Me)vbFoL|XlmSDSZy0tuZ9Kxoq=0$ngHuT)X<`O5i z(X!O6Tbh3OwS4PfpwW~i^^K)AFQgvP!GU}S`t|DPV@<}T_m({j<=mOZFTs5QEDpkc zf@y=Wr#5*5$?IGp!oW{hKmM=1mWiL&iA7K>6~2!^2~zK2(}ljswQtkjN`bmxEO>S3 z{Ima9)1+=W`K4T>JDhsz9H0IZ(DF>xOe5LoNKdZnE?jUjK+s3%N!S zk=YgoZ^*g9@jv(%TLT@LDaH1-%=|Vy^Pv#7>YFiN{+4Yh)hmr`;=khrI0m4vOpYHO zToaM}fD+)(3Db0&R7EzfzY#BDRQ5(PU@be&7}FDDpkhrgqe02TPm`}sPxM@WnB=jJ z_0ixz1=Tx%_=qg~dtO}p z5$bsvBCSHKTc~Ld3iqkS)=AB+uxk|6D65hnA;=SD3i&vM1*tt5|83y>3#LH%v})o- zgAf8Mh>Nuo0YfUXX))(rYEsx(xi!=El$8P050(M-UN@g1P|LXEJaAj}r29LEjoRE_jW^r;MS-JJ)7d`E z!|~f{tbaBV7?HI&^+Y0rsfiQs;RA-l`gDfIEV0Xz%Sz?wvslZU4fGS*>4tVJ;xBd^ zBqJ*RhByO1xT_|ntsb{wwxL$fFXSS=^amkymORenUjVKz`JoQDU;{kE9UW0B(&cc` zhQf#vEgGw5l=`^p!^ra^!m75e?#^pP;CUlZu6P1HVzN;a8SoHYjPPLwQ{W*--^niw zP5gc4fXcxvbTdaq^yI3OTG{wZ14dxxiAjwysne_TU&>Dwor)#&FTS z!owi}`Yffc5zm1J^KcjLv>m40OXZF?{85$GMk9*Z?Ypnut5@3jRcRp!( z={u&{q0W*w(*Rg;hA@o8saN~V-q?mzC4ETYTtA$9t0M2>;Z30#XZVrXOW$x?e zFwxsnfp)gyQZ3+xjWGfvFptf-(`=s!m2;ONY}bME2}|I)Om|J@z;qvGoBIH_24(=T zIF5lb+EBETyEb^~(A0mQ$;rH9}_V zJr`RemUk2y5TzQ7f#MkpC;UO^b)8ghg=qPYPefv0(9c5dqFG*V?=m&<;hQ?Rz=hTf zJ}BsYh=d+rOcyu?DlgEV+24kP5rufINEd`<%hj;P(I$n7YVsrL&$3OacY%l@5ii=4 zIuLi7gDxPNVG^+4_)J$au&sy&R(>0`gCW_)_1mn00(i7@9{}w?cvs93oj}pIY&P7VgC|cdCSCCXcRgOowQ`Uo0fg_&7ep21 zs`UqSt4rpTjlMj&>Z>v3-f;okur?Pmg2C9Nv8d$ZO7XAKmn!9_X0-EOsd$%Rb#>?CPxKV9UP1rRgeex{(E|Wi!xl87Vo?~5gRV8Jr*Zo6}%X*XN z`V@%rH7o=(4ZQTVQ};phmX}1dn5~Ol=#2!#O=qN^3w8wLm6vrNi4o30VCG!^iU4vXqPyb5BTA$oIAZb`0F>7CI1wzD|ICTjpS}Q) zTJ=AMhp=E3-UaqtEU$`KXH#yq0oB)PxNNaD22?xD*;d_expchZ(=qxJv2-R~bKl-C zOaAEj@brYEs-*qh_-jh}bf&Dp0F|ejPt>Wh*|44s#o*cjk$D_?0Uz;Kn-X)@%*Fj< zr4+^Pu97k0chryhsXDLqzft zhK~=#@?&~AS!hQrr%Y~e&CPN7^l$wQ z)y|WEnSm{#FZ3bov5n`_f%4$bVR@Q;dvXP%%}0>+zwpOw6F!!;JJp;6PCNCd_;**9 zWi;Kt)W|qNq*TFp{n~=dyhLJ0m{@AgWDYnUJ>}S-&#s!|mAsPZ%jikF`8)CI7tJhqS?NbZ2C1hORV-5egCx%r3zzcl zPncA9-Cu8%6Vi$jOyDq+V2}6(6q#*~7yMiq8p^lqC8?hIDXt_uODG?%e)Qi%l~oE? z<#zo=^Px0W#^!6CPx&s%17u#y=FhtCQ_%64IYQ+>?9FZErsbT4*IrqBNly$3T8O6&v5za2v44SUOvxdvO zVodid5Mp>%0F8fo#LG#q?@K0b#+fEyfcq{Kk5q>*+t-R#A8v4iv=8ID9SF>+iVGojiw#{6zejy{(cDXuNQM&qo{yu z!^_>kyjlfWhqHnmUdoJyo=wm6^uaK$?IL@8*H0ZrKU)M@7J}`OU zq$dU2Xf~&Y>>Thhft%xjG@xo90>Jdi%g|=+xSZpa1j`PcI!RAIt-3#&9N(|=DaRsk zq)a%jXo@NJIKW?GUt|<{8I9zcBXjwafHK$Af?o_Rt}>pz^)bkfu6PokHIF{^e>QFN zV<@kztbJ~PLN5skO*$2|JjzTMs_zTIEk(B8rBHeXfD#X~d+js`ZnoHo`9>4rRqiwr zLiG&K(qYR(DrzSf;3mL+S@ihV|la?11b(QJ@t6F#%=`NkBLAq}HxDDk!9OdP) z9PO+sbIxY9@&7o@E@d}-718fE-NIG!SONF`y-I9+{j&xReIRizp(gb?_XKO1Ib3UPq zT-d;SfhSLZ7`MIby9CVqhb*(zHwU`NmQqB1w=N#rDj__k)?$W0yFI^_gXng=Lw9Z@gsIsm5i)yf6-R82azKfi~tLW z^y^=Z>nG-0^1q&Ei(AFG`Bb=j)zQF1h>ZgyRrACG7X8Mufu+snYH3GYKHljrcOOH? z6M!4qzw`WOucrP2zCGl?Mz=lEl4hNi;nG>b%02x(kv8*{iR`oc!(tV#%z27dVCP!P z$(dNPsC&z!l7F&9*r_BVXw$X%_d)l@nBR!q+;geV zSh*&tvz>T}FH8xN?a@(`_Q-jDE7ghWCp~D@!RWvOuEfE$kB^MqJ?7EPL(QF&rj|r8 z(#D(uVkR!7w6kHMti2oFe69=|BtDF&4ctO^C6QN#PR+e|d5H%Emge0;7XC7Y#6typ z>x277{lxwwD~x5*PiURg=+o4tb6v6-f}!3pc7g1;P}Y2%Am9xDOW1s}#NIyF{GT4` zveS1-efguKKwZ54m*u#g`uz@Vi>B%elZ_G#ADgbdDX-gvW~I7z?hhEPx)EoXI-O>| z7S8j-q|IBVkU~r-l}EgN>ByQT#X0Q61mR`eJk-jKkvh@xZPV7ME*M9iD$BAKC;9wX z=?O1IBS=1^b+Ura+HnjWpjRJPJ&LcP-frLwy|N=`HnXm;Jg05PvU#B8JY&OYrw?tE z)Q8scXc^#BjJMj`2Bo2c`&@>`;RiSs@(f9qfS3Q}RCwYR@4W1+!*vun>5@;2OUjgK zOALb{NQG2=IPPW}9JdD)Q$kB<#W z+d}}4`P|)A6KCo<*0n91W?_|(lGVV6Kiq34)>0PAlDNK&O`ThGl-eY*cvide(Pp_`-Kwu$|GBkf+={Xh$P*SbC0+T`WZVNLFB&(aY z(5W@#VBB{7qXWn0VXC%8Vb%k}*`EUSA$z`Z$8j70>#@&^A6ky9e}J{G$`c>8QKv^0$bmoa3->(9D|)K07)1|~oQq=@AHs~gKzh?!@Cw`>o_ zvE^Y)+iNA7x4X(i7r(fx?#>=69_-p>gpwl9eNTWYTG!T+e)Lcj>%QQI#v21HTyIl3 z1)+TSaMHsJ^!lUyIRIfTM#~Zto+~sH&b~5)WQX>4qc^*h6Of-{-v;WoA5sgZ9VldJ zbHN1Pk2~_8R1qBpa+l{C%ELu5bFnM#dd&_2bNQR4*&OkUe4>O2d@3*R}XcNHjODc6M36CVi!a z&6}!j?_)fEJyKu+O8fQQ@AT)hd@oca+k zTG%oF2kYo|J{hl4I z0&ni*kPD8eb3q5sR&KT!!oDc&Ew=1_RLIh|%B$*h;T9PD8q@0mf0T@iUj`yxm4OQy=IoZ-Lm!ZYc(@Lp{yPg>T>mnaze3XDb( zlz8@Y^J9n9S4xm?K7WCr^-KH_^=d`KZolbXiC5C$$sh3}0>rnrul+FqKYC{DL-jP8D!3K4=)RyaCm1Y!Qxp1cIT zs06;3*8A<&u?IAY7G~(BWcXgU<2CHg75Y9Fe@-oZ(SmKh-c`YEc5hT<2OsrCk?R=E zF)yQt$Q%pjB#O?_2C2oUw8rk1Uavn&bRnGdPLVu20CY>=SsUlhKHMspp>D7EEDhxC z4#E!x31bh<>6MSa+V%_$pj^0(OSrReiXWWY&#&t0_Ch+48AM`QJ?h&H>-cn`fP25gv=v)zo21(A5JW+y*{jRx_k7@diPn- zMmzUR&4^V@47VhT0itQzeHFsP(crjq%6j+q+tqAEpZD$of{u9+go?Mjzq$20I>UcO z62kpEbfg$TrjQW66uC=CLBR)$F0R47b_Q7mf`r1BQo?S)XruU!t*z=5h|QbM&;*Fh zmY%+T2P^D% zC1fAeRQb$CHdO5SE%d+P2;XhW6S_wsHXQ z`aOQyI~Y4=dhqv1>2!YqdwUc-{E9xTSxP3UrBga1JH){{WEKcAzc~2#aPXrq8Yh;l z_oumMX1^uclP_NaHTzX>b&5u$bQHk03w=We6}!X|lUk-IvYmE;wx4yRpE}K}Y((Pu zVxoxQLLGAH0;)k$Vbp@~#;t|7yjt>f7T>!xSfHaAengvs4=*4LRGZ6AENac{nqe02 zD44l~S?&4JTJZu2oE+k@YkpsIZyLb%96~k|v&EY1=;y9;4b1Y0Q5dy9p`#PFQ<0jP z$-lB7tuz@A=6E8xqOIcS#Zag1zwJM>_P@LaaQ<*lDZc92vuC?swP5E2_kXf>`)~o* zui%M7&C?_N_b1kw8Ns68*xBVO);1H_d7(RWfyS;I%oEosfG*C^ z!XHk0)o6+DAg5;D9jjtgyxIvcwHi`mMc zGBns_)%>+-@_cp5>=*srDTZX{9u9tGqnGy_+nuSu@{QYnC06B~-0f#wfWA`C{!ook zM4@24Ey(cEdEz>uH`H)A`76g1JD=iDTl$Hoa;7sOWv$FWb>j;m8;Uc&3kMlPm|fwC zki8L`ywi`<)7EeO+E>d6dYsKo5t%JbRc+k--NunHITZcpWP=zH2%ddi$sFkE*~_$d zA~-wnLTtKq+DW-umXV182Qz5h_^%82{G}1z-l_yiaq$}$z}qLOkG&a6hQg!LS(`-|JD_1Mw&mrr{b&)l#c)krG z;wOL;D*|~3c7xHe98l1RC?j5gV;KOfQl^8XNvuw^&{i=gW90OEP;| zWgrpE^Mon@uP|Lc=IxfLUl4KzS!K!xxhhqQJ_gBM_!7j(=C4rcsr`)lP&IhSu6G6$EuWl{^2he-Z^o^-;!w_mRh&LQ3Az?d_4BrDAH~=e zpl(IJDtinTR&~jjp{Lrx>nN#+oi)Ew>SVQwv6w)H#NS_06i?a57dZ5^Fl)|!D#1^$ zol>7?^=0J{*iwUNMqm>lSFhK#Y_1FEKa#Ff{H4xzoq2j)>;oQ;Pf7ao^8cer&-%}9 zuiBium-jMLQ&YY3t^mFXxg!8c-yeDFjy}UyGa)UjRG2F8=W(A%!M^cV?`|%C`mI&O zFOH?!2ePXqZ{voC;EPKUzv^m6x6kmbBZJ&9w?HT5c@)53(IAl{J0Y*2VDI74^8~`f zurA49<37i`6<5QySlb}mEH5u_7Z5N6Hh~3!`LpfgNe>(5oHDl5-* zcX$7}*AS|l-0m$d^K9RgV+g%(iK|?{+#ItnwGJkpwJ|yRJ0CV@EL%d98Z9viqzk>0 z*ouoOQ{{3&Hd8b6&Q%rpyQ3=4$QDZQ@WT*`dhbt6bh@Ik(3{CQFx4I>y0WpHP}+gP zTT!G~eym7ZC0s(RdDmx(v8R06&r7j-nPMF_`e)3Kh{G|rGNqV9_EKxB1VosBi3)E+Kq)4r-h3eXTNL>N`)tGrpco)0%Jt=5|6`>l- zu)Ud3Di2(~P}gSJ-&&}LAMP#a+-0@d1?z9eu)EVS(om?S2|=0v&Or<}jR){&sEN z=LSHUR-^t#g|F1gG^Wv9YiLuJdT(WA#j);tLfF>TKlh9G=Nv*^U2m3JG@Og#5R5N6 z=SlPo2$t=|HS;Z4H=Z3ygDftw<)11O>rB_{)~5NzBno^TpIuKamVGVQf!*v91zt~x z1q%3pbv%9W(daClNkaMGyCRmVb-;1h8=G;*+1pVHPFby~-)+>U!EYct9pHG5nNln4 zqr*RO>W%Y5Ah!s1AaOKH%GIN%6A}lXDUzL4;bAubLqE5tJ`shh?e!~2-ke3AYEYS{ zO&x`WET~M~pyXf_==jgsw3=-WTpFJ`tSu>n+wM`FPAr)5l{Q`b!B*LfIcy-^f@4V5 z(Q$GJmX^s&Ud<0a2e1G8ZDp7q?e90F)dDEO!)We>^ZNLCO$C5q^OeES;y|Tt*D?*9JbH@^iul#<~M-W5r)nII4|Z=JKE%R<-O=Jfqh=J`02_vWzCl!RwM%K0glIO->rGvR;tB@JIK@9r{0Jd_DRlcxW3!PM_LRyI6+v zh62Y9KcDr{6@iX3!Fz8-H)_IZuFV_MaTR5}uMVi@Q&bbxgRMbFq%QFp{WY{RUx#W` z3#gsp`<-*&mle7HZS=WzD&F$u0zRe8$&sdg>EFPaWvBgi1qr#e+ZLB*a!>GfOofnp zb`#-yi2$bwyMJiuL%#^T?7K1DzT2VD^5BstS`Y!kXp|VX7iXL_9(Dh4;&5NIEQQK2 zb8|&|)-!droA(FZJ!BfL?VzVbQo8G#lb{to#DNQt3*GrPPmaSJi(L9`Pv7%&Wvh^l_T9{>y-Z($P>b0b z3w$WWcfbFLW~WNY?6!J(_BZ!bJ&(arcgjqjpcQYr+el^d7r}#m!FJN&I;n$6;pONtW)7_a}&0GRE2bw_O)~lYsHPbOSqQ4|EsH7W3i>=ismsWI`ci8*Ds9&m=@psY074O2qZHiyCA_FN6iD z#H($cc>YL|s8URd$E7~6Tc-f1^891!Z~wHH?n9yx|amH;YBA)=sX2HB2>7Ily*#w5Zd1c{c;wWDJ0=IS*;p*ss`l;m!0>vC+ldphoZ=3 zNAn6W0dp_Qsa=|~|Kk1qRcCmNNLJ7lVi?Us@)nQ))o|S_=9JY@Lul{!?_Wk*c53P= zM6`X|^ZAm6o~GcsUcJs3IGhW2xZbb0+Z0nF~E5=H`-1(nttXQMQJuaLLBb)5`ro7rm}?MxzlC1LsSSri_3OiDEiIE za$f)eU-LFIGp;R)qjPcbaco>%dmZjzZFia*$CEDavAl;5^?4VofXq&C&Q=sCg9Qlp z@@JpvMZ8;{t=JljX0qSF;FK@^KgB(HIGfqm(ap4q8dX}`babfNnznWl-Dn5ZO6-I( zEv0DeA;Hvi6h&1nwYO?XtZ8el(AJVEB~*i2OGF}yBB4U~-j|tg=IL*K&)4}q-}8O{ zc=EpY+HBm?+^1rR zR?~dsaeVw6OJf;BH4`9~8TwXpwr|gr27CDY_Qb?Q^jK3=(Bga7B6WruiEVx-K0f3i zpC$28%J9RXO3(DF7(UCs7cUG314nRk)Ur_Z`ZZ1&nE_v4?yE+-6x&sma!E<|8XQy} zLy~)?WZ&z4TeiwI`G}jbm%`whuHIP9^4Bbh3W0_A>Tv@DTI9lR*kR{KJ)zI8c^2E~ z?rGj7L}2L4PE1S?E-mz;LR7M_^RM0C>8YvnInkflmSm;+0AJ8Pt&Gawnp3f>Y?6!D zGvCgUdb`liUL__S)2-Mu`%yBMrUx}uc=c$L1)a-%f$ z{?c=qK3g0%Z~V$3&`D6wSsF_ydkZxzRTTn z?)7P!;TxMLbwa#S%5@-?bw^;wUY4MjP7jR5g=mr|rl$xal2TH)U;1x_mS3G*H*8zc z9&a@gzhG+Gd`m!_aA_XaT|r@V-X0MG^JXnb+seD)koFUWJ0Z-tN2TX%nbhH8!tS)@1b6oZtV!P8wHwjQDz{XahN!qpb)Q{{Hf2<=L3`sy zIXk>=2d+3s_beNqs$xql!5-E~etsu^=|SBv_K}uI$ymEYoIcbh%h$F&`K}FfaR}6%C_F&}!qFO~IB;>heLA9gu@ z%>LO}JL~$ws(c&A>{_7EMs6WHXYu|LaqQxoeR5Entmt%FLZ5l4PEX6e_U_a3whMKV zVWFq#=I9goH0O%ba4;h8H1g?8zXKF2us`>5_LP6}V*Y33ATm^WJIC~Z+u4ZaywoEd zkF(>EQ|-Q5ftA{zl(2CZvt#ChPv8pmqy}hDi51wK1E#Wt_3CK{hNQ1lm>I~ZQzW@` zr!38%+q^TzNBBTGbRLqAdD~`#hKe2qJy0O3zOYeMkBE; zKTD_xJ+}H_uO7W2#}~IZ*=uWExUb-BjP_Pft3Mdfl(v^Tz$lPRb4Yt)YgvBx(XwAg ziN=&=3vUZd<1mA zLXkn1tK#_6cGp~s>5_)Dl>;CfZ!=}TkLOIJ#VtUs>x4d7F zEz%*@P-6IIVeVQtbdV_G3#ye<(&3`>{S5O?J*(Iq-m3AjVt2A; z9{J(kZtou}U}xK3O4hBN;z(h5t61QA1k{3b@TfQqui9KXA5Z#b0|5c3BqOFFPLLkw zej>z^sNQpy;Nv0vE|Nh0nPs{PqL{PwA0Oa@DYA-^rf6H%>qQy^o-s{o75csI< z{bk|stI(T3wU|w?jUJ#e{MYJiYzaor*3KU~PR`D7(iT@UnI0V{`EzXUfOGtP4*;=0 zn)F+=nGnAy-_GYDqW2n}Y8EC^GMb>ZbH-Gf5-884*GTPbGfOH2nkg@4Idc^}#114H7*M}V+?J=W)6{1-B}HyxOPAvPQ-kb zAZ+qaRr7a$BeXUfRlhk%$)_v)2DyJPlfy2FT9DdT`_LORIszASzf?B%ZVy1fzb*Px zCzJjooU&e#*w+X4;`#vT_W4@r{s%<;21<_Zt|eONpa29b@g*65u`(Mr<5Osy&DI>_ z=o`santv$H@PV&Yod1>O-ZUW9gE{gLKnH8NlcBG8Y(K}p7Z|2U4`5f-EpwK<2COd$ zLzF20-nbbE6JvBC4(7k$2A^X#6*7%9__c;~Q>!=l)furvoewgEs7}f9Ob2X(?Wpm; zRqKroe{ZDq-Ts+{_>YHTC!IRFQ8-3ez%-MajBvMCof3&Tu;ELU%B1Z});3A8*pnWE zj&0+ALq5aWzi0o{`^aQ;cp80Cojl2A;g}(Lb*eMp^Pi_fsA)c3lI6#wb zvbojjJ`us);4(nYkRf;BE~XU+xbl zNJ;gR*Q3)B*N=F88lYh938jIsP{elspoXp>{YR`T>D}=m-k;pBaO6901)&Frx+_5I(uitIu@jcp4mhL{_xtd3r#gas`D~=RZS_*hi6P0Yy)G%!U(qH zP}Qu`{7OnbbDP!E)ZpK&KgN82cA@#*Qe}&)3$9}Qr4eQDuuHv;^mk=f;F1l+S3T|r z+yYl7XJq_ts7~l5>0ACDt0mQnFc}Y*1&iK1hG6Xk0@*5;+BoN9e|t#($xIz{4%`ia zlYE5RAymom-~(fQ=EP@gu`!$>I9?h6oNSJ(Gid0X;Nyj2-rq1l2ZvpB>?+NfOVqtJ z`@sDW&R8$C{-A?O4h4Bo(fe)E>F(>%lQ*VGDzoM{j_Rvg;;z|YRW-;3Wn9KWI$WG~ z>qwttbmOZHcbx}F3t^IlnCsR`+NCo|nw+VDOhpwchNxaZtGun-+#X~eL-I7<4-F4A(o_*rVvQ4H*^B= z81?*muTr;|mHB>wOUg93z&@7?3Vh*HznwXs$G+9qHzot4O=DPGda2xc=U%O z(B=x8aZZ_7S;55+cbn3R)G;8)Ky|Iu?2UAmS5l(u~$G0@;UANwN3od z;hv^ntMzv{^8_7~_-S49v0|j`g!v?HXu#m7iurWGMtU320g#7Ij0+J?p~rEWONi<+ z=SMC^Ci`W+mxvk-(&nwQT6eJ7t1)zJZMHNK3ac6Ca4_yG%|3y5S|tDI?h8ek`pO>G zY)W&+U5}#JGtLFulw6jL8fmVX2d1=)a_beP--kuBtB z>$4&zu^7et7z7bIb3ugHVJ%y=hAMAAsZpkxeLK+k8TL4@U4ODSGR0H#v!q47thPOH zlIT(@6`LND2)#e^!w99eZ!sh+6ejPY)A2Y&>)wp3V{LZtTcZoiy`b;?qV+eqNla~s zP=y_Bw9j7eVhOF|VZe91jDl!NfrM`2BX6Pdl6k5`tY&wZqjhC&d-95DiUH9Gl52ZVb<{T2FVfTNvUdbsV0E9`;iKxGo@TR^>P z@lLu5VbW%x`g z-nTG3bbCQADFTJh2AVrhUde=;2{5e!j!^H10>;Nce0-xk=M$R$*8O0Vk(1b}6DA|x zS@zM5uoJXN;i^Ef(QRy{5Z#RcCP!BuA^k1TY(hxbut5f{^g#@?Kjh&~W{O9JEhc6~ zt}AN-4CONK0qG?=Kmk!JBAogj8N&rjjY^kWGdg%A_IZx8L6{1ah!o)N24CM@xH?S2 z#fPtr4&Po>4PN-;?L?OjP_Wdh+r465CtUBQS2Rdv=G}z};(fT|?eWq^6k7Ya9Bs}VZdhRR$TYl#%tFFe%ph1J*d^&FN;T-tR-lqfmup@H|*XUY> zt#8+`srMP+gaqQGE$2!g`Ooa_EbB_pc|5SeMfy=k#+ydc=hqw`19&29{jpAoFaTS= z+oyi@QrX0tEJ0?8rN@!}sZPqTLxVs|HS|iRT3{~*VbE})W-iNEJzouYdt+-03yZ0= zg1^iX0z2sG>&Z-Wz(}+lsci*AF--VyQK&nM`#$?}!J??fN39sG;vvh4AD6?2-7EHW zHwq(2kIcZCw`rTLm3O3U;R*(8P}LCaOe+B1J~Bft%!1LH)pHw!_lbasP6z6LWP+Tj z2(IWz)Q5l2?aVQ3H!7w3cBxG|f_)+~WWzF8%ktPKu{%MezVGiI3==i%0%rMq<4UG% zSc3a01IN%6b6y#8mgxa>!QRf0TqkrS#C8^jqsq=wa+&Lz*ChbKd6Crqu7-FiJyz3m zn|>tw>Ex)Ixqco6qwPx;mB5d+!`AWZClNimV^#oR7DA;LbJmWK?3%0%Z(vAaz zObp>wn5lZ+I?(ANqjBAm(cE(Fx`B6vt=!}&KRz_o{Stf|1Y%9yH--HiM7YdHS~t%nIbzC@MM(F;0URuE(foy0y)p$PJ#*qwse1R; zQt)dI1T=3ipeJRqz00#|xn_%pBtJeCcax`z;-iu4FzQ_xAm*Kc@(5m=&U!n$%~X*6 zKIXnAfAyYeTJPFff-hGEP&-F$D+WpS-7-*HRY3M*qqvfpr&cygjpexh6e-MX1h9%- zvLvi$u)^}wfN=V?N4c5fv(@kEiozI`S7!)eX)FQmF<=}QUa1hn?A>VH?C!;70WFJ$ zAj}z_V;=WMf;v|nY#-0<&NAb8BlL&LMzQMK*h{CliCw6IPZR_%!op_+n8snL=jz3@nviy~)VdpuGNPf#k!LrJP@vR(z)eD5M zRF>rBRzM>S)LtX{!$hWIKddbw!O{_@nt%)z?>&fh5yKDM%v-@0XV-QH-b2Vw}hnh*mzQHrqlE2;=C2S zPysg=36SoK?^)pjV9e?V$g;C5?2>|9{kyiMJuT(wn3d)*#eP@T^m$Gsel6fx{7;gd zz`q57w0S|Pjs;x*XRhk>b0`<^3y9M>6^h zU}erbM5WX&kC#{)8+bbzl=aI~Q_OJ+{kg2F0p33W?>q;46(nkor|uV2GhwU-@k(vvCv-u&%z2KJbpL`bza&DC`ZKO@&DUef zR<0c2i@wxv3x%KU9hSA8z1F$QAV;~GIfkj-X^@$Y9l3g9=uVx{E*bN`bWE|&ic}|h5Qy^45e#Cp}wd7-^iAD9O};>|7f<`2ZtKjg>yF`k5R06h31g$4;QkCbfA+$e(o;@1{|o(D{h0s& literal 0 HcmV?d00001 diff --git a/ui/index.html b/ui/index.html index 1334756..9d189e8 100644 --- a/ui/index.html +++ b/ui/index.html @@ -21,7 +21,7 @@
- +

Terminals

From dc2718fa4bac75debb1b21c97e53623690fd0d30 Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Wed, 26 Feb 2020 10:16:00 +0100 Subject: [PATCH 10/30] Add travis badge to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3b1cb47..62768f4 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,6 @@ ![](https://i.imgur.com/gcAGPt1.png) +[![Build Status](https://travis-ci.org/QuiiBz/squid.svg?branch=canary)](https://travis-ci.org/QuiiBz/squid) [![Known Vulnerabilities](https://snyk.io/test/github/QuiiBz/squid/badge.svg?targetFile=package.json)](https://snyk.io/test/github/QuiiBz/squid?targetFile=package.json) [![Quality score](https://www.code-inspector.com/project/4175/score/svg)](https://www.code-inspector.com/project/4175/score/svg) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/QuiiBz/squid/issues) From cb378bb3cd258beb6ca37e6b5f8f6dede133a0eb Mon Sep 17 00:00:00 2001 From: Tom LIENARD Date: Wed, 26 Feb 2020 18:14:11 +0100 Subject: [PATCH 11/30] Change UI, improve SSH hosts --- app/components/Pane.ts | 19 ++++ app/components/Panes.ts | 44 +++++++- app/components/SSHTerminal.ts | 2 - app/components/SquidTerminal.ts | 14 --- app/hosts/HostHandler.ts | 12 +- app/hosts/hostHelper.ts | 111 +++++++++++++++++-- ui/css/app.css | 144 ------------------------ ui/css/index.css | 188 ++++++++++++++++++++++++++++++++ ui/icons/close.png | Bin 0 -> 328 bytes ui/icons/search.png | Bin 0 -> 494 bytes ui/index.html | 78 +++++++++++-- 11 files changed, 422 insertions(+), 190 deletions(-) create mode 100644 ui/css/index.css create mode 100644 ui/icons/close.png create mode 100644 ui/icons/search.png diff --git a/app/components/Pane.ts b/app/components/Pane.ts index 8a5a09d..fb1efde 100644 --- a/app/components/Pane.ts +++ b/app/components/Pane.ts @@ -4,11 +4,30 @@ export default class Pane { protected settings: Settings; protected id: number; + protected opened: boolean; constructor(settings: Settings, id: number) { this.settings = settings; this.id = id; + this.opened = false; + } + + /** + * Return if the pane is opened or in the index + * @return If the pane is opened + */ + isOpened(): boolean { + + return this.opened; + } + + /** + * Set the pane to opened + */ + setOpened() { + + this.opened = true; } /** diff --git a/app/components/Panes.ts b/app/components/Panes.ts index d967379..bb692bb 100644 --- a/app/components/Panes.ts +++ b/app/components/Panes.ts @@ -2,10 +2,10 @@ import { remote } from 'electron'; import Settings, { ISettings } from '../settings/Settings'; import * as dragula from 'dragula'; import { Drake } from 'dragula'; -import SquidTerminal from "./SquidTerminal"; +import SquidTerminal from './SquidTerminal'; import * as os from 'os'; import HostHandler, {IHost} from '../hosts/HostHandler'; -import { createHostElement } from '../hosts/hostHelper'; +import { addListeners, createHostElement, openSide, closeSide, provideHost} from '../hosts/hostHelper'; import SSHTerminal from './SSHTerminal'; export default class Panes { @@ -39,10 +39,36 @@ export default class Panes { const node = document.getElementById('hosts-container'); this.hostHandler.on('keytarLoaded', () => this.hostHandler.getHosts().forEach(current => { - const element = createHostElement(current, (event: MouseEvent) => this.open(event, null, current)); - - node.appendChild(element); + node.appendChild(createHostElement(current, () => openSide('edit', current),(event: MouseEvent) => this.open(event, null, current))); })); + + document.getElementById('valid-create-host').addEventListener('click', (event) => { + + event.preventDefault(); + closeSide('create'); + + const host: IHost = provideHost('create'); + + this.hostHandler.addHost(host, () => { + + node.appendChild(createHostElement(host, () => openSide('edit', host),(event: MouseEvent) => this.open(event, null, host))); + }); + }); + + document.getElementById('valid-edit-host').addEventListener('click', (event) => { + + event.preventDefault(); + closeSide('edit'); + + const host: IHost = provideHost('edit'); + + this.hostHandler.addHost(host, () => { + + node.appendChild(createHostElement(host, () => openSide('edit', host),(event: MouseEvent) => this.open(event, null, host))); + }); + }); + + addListeners(); } /** @@ -53,7 +79,8 @@ export default class Panes { */ open(event: MouseEvent, path: string, host?: IHost) { - event.preventDefault(); + if(event) + event.preventDefault(); this.hideIndex(); @@ -64,6 +91,8 @@ export default class Panes { } else this.currentPane.open(path); + + this.currentPane.setOpened(); } /** @@ -181,6 +210,9 @@ export default class Panes { tab.classList.add('active'); + closeSide('create'); + closeSide('edit'); + // Old pane document.getElementById(this.currentPane.getPrefixId()).classList.add('hidden'); document.getElementById('tab-' + this.currentPane.getId()).classList.remove('active'); diff --git a/app/components/SSHTerminal.ts b/app/components/SSHTerminal.ts index fc37c14..3b9edde 100644 --- a/app/components/SSHTerminal.ts +++ b/app/components/SSHTerminal.ts @@ -35,8 +35,6 @@ export default class SSHTerminal extends SquidTerminal { window.onresize = () => this.fit(); - this.opened = true; - this.adapt(); this.setupConnection(); } diff --git a/app/components/SquidTerminal.ts b/app/components/SquidTerminal.ts index c3d6f0c..b38c39c 100644 --- a/app/components/SquidTerminal.ts +++ b/app/components/SquidTerminal.ts @@ -14,13 +14,10 @@ export default class SquidTerminal extends Pane { protected xterm: Terminal; private ptyProcess: IPty; private fitAddon: FitAddon; - protected opened: boolean; constructor(settings: Settings, id: number) { super(settings, id); - - this.opened = false; } /** @@ -46,8 +43,6 @@ export default class SquidTerminal extends Pane { window.onresize = () => this.fit(); - this.opened = true; - this.adapt(); } @@ -63,15 +58,6 @@ export default class SquidTerminal extends Pane { } } - /** - * Return if the pane is opened or in the index - * @return If the pane is opened - */ - isOpened(): boolean { - - return this.opened; - } - /** * Build the terminal object * @return The terminal diff --git a/app/hosts/HostHandler.ts b/app/hosts/HostHandler.ts index 6c621e0..35da122 100644 --- a/app/hosts/HostHandler.ts +++ b/app/hosts/HostHandler.ts @@ -74,12 +74,14 @@ export default class HostHandler extends events.EventEmitter { const name = host.name; - if(this.hostNames.includes(host.name)) - return; + if(!this.hostNames.includes(host.name)) + this.hostNames.push(name); - this.hostNames.push(name); + keytar.setPassword('squid', name, JSON.stringify(host)).then(() => { - keytar.setPassword('squid', name, JSON.stringify(host)).then(() => done()); + this.save(); + done(); + }); } /** @@ -93,8 +95,6 @@ export default class HostHandler extends events.EventEmitter { this.hosts.forEach(current => { - console.log(current.name + ' ' + name); - if(current.name == name) host = current; }); diff --git a/app/hosts/hostHelper.ts b/app/hosts/hostHelper.ts index b4b62e3..aab8422 100644 --- a/app/hosts/hostHelper.ts +++ b/app/hosts/hostHelper.ts @@ -1,31 +1,120 @@ import { IHost } from './HostHandler'; -export function createHostElement(current: IHost, onClick: (event: MouseEvent) => void): HTMLElement { +type side = 'create' | 'edit'; + +/** + * Add listeners + */ +export function addListeners() { + + document.getElementById('create-host').addEventListener('click', (event) => { + + event.preventDefault(); + openSide('create', { + name: '', + ip: '', + port: 22, + username: 'root', + password: '' + }); + }); + + document.getElementById('close-create-host').addEventListener('click', (event) => { + + event.preventDefault(); + closeSide('create'); + }); + + document.getElementById('close-edit-host').addEventListener('click', (event) => { + + event.preventDefault(); + closeSide('edit'); + }); +} + +export function openSide(type: side, host: IHost) { + + fillInputs(type, host); + document.getElementById(type + '-host-container').classList.add('visible'); +} + +export function closeSide(type: side) { + + document.getElementById(type + '-host-container').classList.remove('visible'); +} + +/** + * Get a host with filled inputs + * @return The IHost + */ +export function provideHost(type: side): IHost { + + return { + name: (document.getElementById(type + '-host-name') as HTMLInputElement).value, + ip: (document.getElementById(type + '-host-ip') as HTMLInputElement).value, + port: Number((document.getElementById(type + '-host-port') as HTMLInputElement).value), + username: (document.getElementById(type + '-host-username') as HTMLInputElement).value, + password: (document.getElementById(type + '-host-password') as HTMLInputElement).value, + }; +} + +/** + * Fill the inputs with the host credentials + * @param type + * @param host + */ +export function fillInputs(type: side, host: IHost) { + + (document.getElementById(type + '-host-name') as HTMLInputElement).value = host.name; + (document.getElementById(type + '-host-ip') as HTMLInputElement).value = host.ip; + (document.getElementById(type + '-host-port') as HTMLInputElement).value = String(host.port); + (document.getElementById(type + '-host-username') as HTMLInputElement).value = host.username; + (document.getElementById(type + '-host-password') as HTMLInputElement).value = host.password; +} + +/** + * Create a host element or replace the old one + * @param current + * @param infoClick + * @param sshClick + * @return The created DOM element + */ +export function createHostElement(current: IHost, infoClick: (event: MouseEvent) => void, sshClick: (event: MouseEvent) => void): HTMLElement { + + const old = document.getElementById('host-' + current.name); + + if(old) + old.remove(); const host = document.createElement('div'); host.className = 'host'; + host.id = 'host-' + current.name; const infoContainer = document.createElement('div'); - infoContainer.className = 'host-info-container'; + infoContainer.className = 'info'; const hostName = document.createElement('p'); - hostName.className = 'host-name'; + hostName.className = 'name'; hostName.innerText = current.name; const hostInfo = document.createElement('p'); - hostInfo.className = 'host-info'; + hostInfo.className = 'description'; hostInfo.innerText = current.username + '@' + current.ip + ':' + current.port; - const ssh = document.createElement('div'); - ssh.className = 'host-btn ssh'; + const buttons = document.createElement('div'); + buttons.className = 'buttons'; + const ssh = document.createElement('button'); + ssh.className = 'btn'; ssh.innerText = 'SSH'; - const sftp = document.createElement('div'); - sftp.className = 'host-btn sftp'; + const sftp = document.createElement('button'); + sftp.className = 'btn blue'; sftp.innerText = 'SFTP'; infoContainer.appendChild(hostName); infoContainer.appendChild(hostInfo); host.appendChild(infoContainer); - host.appendChild(ssh); - host.appendChild(sftp); + host.appendChild(buttons); + buttons.appendChild(ssh); + buttons.appendChild(sftp); - ssh.addEventListener('click', (event: MouseEvent) => onClick(event)); + infoContainer.addEventListener('click', (event: MouseEvent) => infoClick(event)); + ssh.addEventListener('click', (event: MouseEvent) => sshClick(event)); return host; } diff --git a/ui/css/app.css b/ui/css/app.css index 1cc3f58..105c2a4 100644 --- a/ui/css/app.css +++ b/ui/css/app.css @@ -164,150 +164,6 @@ body { cursor: pointer; } -.index { - - flex-direction: column; - align-items: center; - justify-content: space-around; - - width: 100vw; - - position: absolute; - top: 50%; - transform: translateY(-50%); -} - -.index h2 { - - font-size: 20px; - color: #ffffff; - font-weight: 100; - - margin: 50px 0 20px 0; -} - -.logo { - - width: 15%; -} - -.index-buttons { - - display: flex; - align-items: center; - flex-direction: row; -} - -.index-btn { - - font-family: 'Fira Code'; - font-size: 14px; - - background: none; - color: #646464; - - border: 1px solid #151515; - border-radius: 5px; - padding: 10px 20px; - - display: flex; - flex-direction: row; - align-items: center; - - margin: 0 10px; - - transition: .3s ease; -} - -.index-btn:hover { - - background-color: #151515; - color: #FFFFFF; - - cursor: pointer; -} - -.index-btn svg { - - width: 15px; - margin-right: 10px; -} - -.hosts { - - overflow-y: scroll; - max-height: 30vh; -} - -.host { - - display: flex; - flex-direction: row; - align-items: center; - - padding: 10px 20px; - - border: 1px solid #151515; - border-radius: 5px; -} - -.host-info-container { - - display: flex; - flex-direction: column; -} - -.host-name { - - font-size: 18px; - color: #ffffff; - margin: 0; -} - -.host-info { - - font-size: 12px; - color: #646464; - margin: 0; -} - -.host-btn { - - background: none; - color: #22da6e; - font-size: 14px; - - border: 1px solid #22da6e; - border-radius: 5px; - - padding: 5px 10px; - text-shadow: 0 0 1px #22da6e; - margin-left: 50px; - - transition: .3s ease; -} - -.host-btn:hover { - - text-shadow: 0 0 10px #22da6e; - cursor: pointer; -} - -.host-btn.sftp { - - color: #82aaff; - border: 1px solid #82aaff; - text-shadow: 0 0 1px #82aaff; - - margin-left: 10px; -} - -.host-btn.sftp:hover { - - text-shadow: 0 0 10px #82aaff; - cursor: not-allowed; -} - ::-webkit-scrollbar { background: none; diff --git a/ui/css/index.css b/ui/css/index.css new file mode 100644 index 0000000..6aa2495 --- /dev/null +++ b/ui/css/index.css @@ -0,0 +1,188 @@ +.index { + + flex-direction: column; + justify-content: space-between; + align-items: center; + margin: auto; + width: 40vw; + height: 100vh; +} + +.logo-container { + + height: 20vh; + display: flex; + justify-content: center; + + margin-bottom: 50px; +} + +.logo { + + width: 200px; + height: 200px; +} + +.terminals, .hosts { + + width: 100%; + height: 40vh; +} + +.index .title { + + display: flex; + flex-direction: row; + justify-content: space-between; + border-bottom: 1px solid #151515; + margin-bottom: 25px; +} + +.index .title h1 { + + font-size: 25px; + font-weight: normal; + margin: 0; + color: #ffffff; +} + +.index .title .search { + + display: flex; + flex-direction: row; +} + +.index .title .search input { + + background: none; + border: none; + color: #646464; + text-align: right; + margin-right: 20px; + font-size: 14px; +} + +.index .title .button { + + background: none; + border: none; + padding: 0; +} + +.index .title .button:hover { + + cursor: pointer; +} + +.index .scroll-container { + + scroll-snap-type: y mandatory; + overflow-y: scroll; + height: calc(40vh - 120px); +} + +.host { + + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + padding: 10px; + background: #151515; + border-radius: 5px; + margin-top: 10px; + scroll-snap-align: start; +} + +.host .info .name { + + color: #ffffff; + font-size: 18px; + margin: 0; +} + +.host .info .description { + + color: #646464; + font-size: 12px; + margin: 0; +} + +.btn { + + background: none; + border: 1px solid #22da6e; + padding: 5px 10px; + border-radius: 5px; + color: #22da6e; + font-size: 16px; + margin: 0 5px; + text-shadow: 0 0 1px #22da6e; + transition: .3s ease; +} + +.btn.blue { + + border: 1px solid #82aaff; + color: #82aaff; + text-shadow: 0 0 1px #82aaff; +} + +.btn:hover { + + text-shadow: 0 0 5px #22da6e; + cursor: pointer; +} + +.btn.blue:hover { + + text-shadow: 0 0 5px #82aaff; +} + +#add-host { + + position: absolute; + left: calc(30% - 60px); +} + +.create-host-container, .edit-host-container { + + display: none; + position: absolute; + width: 100vw; + height: 100vh; + background: rgba(0, 0, 0, 0.5); + flex-direction: row-reverse; +} + +.create-host-container.visible, .edit-host-container.visible { + + display: flex; +} + +.side { + + height: 100vh; + width: 350px; + background: #0F0F0F; + padding: 20px; + display: flex; + flex-direction: column; +} + +.side input { + + margin: 10px; + background: #151515; + border: none; + border-radius: 5px; + padding: 10px; + font-size: 16px; + color: #ffffff; +} + +#valid-create-host, #valid-edit-host { + + width: 50%; + margin: 20px auto; +} diff --git a/ui/icons/close.png b/ui/icons/close.png new file mode 100644 index 0000000000000000000000000000000000000000..00b9cee3efbc1d764ada9f122126d23903005b2a GIT binary patch literal 328 zcmV-O0k{5%P);}Lx^QCE;FE)H-S?-AF4xs3|?rQ3~?q~nMnfateN9+mU;0ysR zfa6xwhXHsQImq+e8e{fa)Q9zb|7qK{FoJABW0+jk0BX?`Ce8$=P&p@}MFCuz^CB+5 z7&<00Rnv#9B21(|)hvVs!APWtVM*}+&c+a<&A+-s7hM2zX$MhnQGC@L(or=3s%=88 zA)scW7LA?iGtERzqnE<86E!RcEv7+N>nqh~3DhnYtQL!*X7&WUnE9;T)^n7I9dn#T` zr_(MozX9mh99nztZ{s+YAiKxKuavJ)(%4wNjy_ZNva^CUIlqO})G5q7tgBpErPg{&M4h7^YOTja^e%@^`B<*9_x?JLW9ifVqR7q|BjxYQm@)HH zs5oWVF?Ct%$s>xQcB9dd=I-R-q_K;+m3fvdt_ms494n>fp`P8%vOt^7ra-b03oTIw zpiM+~l8sVoScUF@rD+)CiguR-GjEb4nTcolB_bBJLeK-?sm7M?bn+a literal 0 HcmV?d00001 diff --git a/ui/index.html b/ui/index.html index 9d189e8..21107af 100644 --- a/ui/index.html +++ b/ui/index.html @@ -8,6 +8,7 @@ +