From 7d2293208f4f8c6038d6e74ec9b7e6798bd3ded4 Mon Sep 17 00:00:00 2001 From: Joey Kimsey Date: Fri, 7 Feb 2025 16:14:00 -0500 Subject: [PATCH] Apple PWA fixes --- .gitattributes | 1 + .gitignore | 2 +- app/js/main.js | 37 ++++++++++++++++++-- app/js/sw.js | 1 + app/models/sessions.php | 2 +- app/templates/default/default.tpl | 5 +++ app/views/faq.html | 4 +-- app/views/pwa.html | 13 +++++-- composer.lock | 54 ++++++++++++++++-------------- images/apple-touch-icon.png | Bin 0 -> 28873 bytes images/share-icon.png | Bin 0 -> 3233 bytes 11 files changed, 84 insertions(+), 35 deletions(-) create mode 100644 .gitattributes create mode 100644 app/js/sw.js create mode 100644 images/apple-touch-icon.png create mode 100644 images/share-icon.png diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.gitignore b/.gitignore index 9bc33e0..fb931a2 100644 --- a/.gitignore +++ b/.gitignore @@ -65,4 +65,4 @@ vendor/canary/logs/* components/* mailhog.log uploads/* -images/qr-codes/ +images/qr-codes/* diff --git a/app/js/main.js b/app/js/main.js index 160b06e..95869a2 100644 --- a/app/js/main.js +++ b/app/js/main.js @@ -8,25 +8,48 @@ * @link https://TheTempusProject.com * @license https://opensource.org/licenses/MIT [MIT LICENSE] */ +/** + * Progressive Web-App + **/ let deferredPrompt; const installPrompt = document.getElementById("install-prompt"); +const chromeMessage = document.getElementById("chrome-install-message"); +const iosMessage = document.getElementById("ios-install-message"); const installButton = document.getElementById("install-button"); const dismissButton = document.querySelector("#install-prompt .btn-close"); // Check if the user previously dismissed the prompt -if (!localStorage.getItem("pwaInstallDismissed")) { +if ( ! localStorage.getItem("pwaInstallDismissed") ) { window.addEventListener("beforeinstallprompt", (event) => { event.preventDefault(); deferredPrompt = event; installPrompt.classList.remove("d-none"); - installPrompt.classList.add("d-block"); // Show the prompt + installPrompt.classList.add("d-block"); // Show the alert + chromeMessage.classList.remove("d-none"); + chromeMessage.classList.add("d-block"); // Show the prompt }); + + if ( isIos() && ! isInStandaloneMode() ) { + installPrompt.classList.remove("d-none"); + installPrompt.classList.add("d-block"); // Show the alert + iosMessage.classList.remove("d-none"); + iosMessage.classList.add("d-block"); // Show the prompt + } } +// ios REQUIRES a service worker +if ( 'serviceWorker' in navigator ) { + navigator.serviceWorker.register('app/js/sw.js') + .then(() => console.log('Service Worker Registered')); +} +// self.addEventListener('install', () => self.skipWaiting()); +// self.addEventListener('activate', () => self.clients.claim()); +// self.addEventListener('fetch', () => {}); // No file interception + // Handle Install Button Click if ( installButton ) { installButton.addEventListener("click", async () => { - if (deferredPrompt) { + if ( deferredPrompt ) { deferredPrompt.prompt(); const { outcome } = await deferredPrompt.userChoice; @@ -65,6 +88,14 @@ if (localStorage.getItem("pwaInstallDismissed")) { } } +function isIos() { + return /iphone|ipad|ipod/i.test(navigator.userAgent); +} + +function isInStandaloneMode() { + return window.matchMedia('(display-mode: standalone)').matches || window.navigator.standalone; +} + /** * Automatically selects/de-selects all check boxes associated with that field **/ diff --git a/app/js/sw.js b/app/js/sw.js new file mode 100644 index 0000000..89c3448 --- /dev/null +++ b/app/js/sw.js @@ -0,0 +1 @@ +self.addEventListener('fetch', () => {}); \ No newline at end of file diff --git a/app/models/sessions.php b/app/models/sessions.php index 2070dde..df5f2b2 100644 --- a/app/models/sessions.php +++ b/app/models/sessions.php @@ -59,7 +59,7 @@ class Sessions extends DatabaseModel { public function checkSession( $sessionID ) { $user = new User; // @todo lets put this on some sort of realistic checking regime other than check everything every time - if ( $sessionID == false ) { + if ( empty( $sessionID ) ) { Debug::log( 'sessionID false' ); return false; } diff --git a/app/templates/default/default.tpl b/app/templates/default/default.tpl index 0e9aa7a..24e5a02 100644 --- a/app/templates/default/default.tpl +++ b/app/templates/default/default.tpl @@ -28,7 +28,12 @@ {AUTHOR} {ROBOT} + + + + + diff --git a/app/views/faq.html b/app/views/faq.html index 956f2b6..b914758 100644 --- a/app/views/faq.html +++ b/app/views/faq.html @@ -56,8 +56,8 @@
- {SITENAME} is open source and available free of charge through GitLab and Packagist. - The developer behind the project is Joey Kimsey and he can be contacted through his website for development services. + {SITENAME} is open source and available free of charge through GitLab and Packagist. + The developer behind the project is Joey Kimsey and he can be contacted through his website for development services.
diff --git a/app/views/pwa.html b/app/views/pwa.html index 200ae97..45bfae8 100644 --- a/app/views/pwa.html +++ b/app/views/pwa.html @@ -1,11 +1,18 @@
-
\ No newline at end of file diff --git a/composer.lock b/composer.lock index d520825..8bc84cf 100644 --- a/composer.lock +++ b/composer.lock @@ -244,9 +244,9 @@ }, "require": { "php": ">=8.1.0", - "thetempusproject/canary": "1.0.6", - "thetempusproject/hermes": "1.0.3", - "thetempusproject/houdini": "2.0.2" + "thetempusproject/canary": "1.0.9", + "thetempusproject/hermes": "1.0.5", + "thetempusproject/houdini": "2.0.5" }, "type": "library", "autoload": { @@ -272,20 +272,22 @@ } ], "description": "Bedrock is intended as the core functionality used by The Tempus Project: a rapid prototyping framework. This library utilizes the MVC architecture in addition to a custom templating engine designed to make building web applications simple.", - "homepage": "https://git.thetempusproject.com/the-tempus-project/bedrock", + "homepage": "https://thetempusproject.com/libraries/bedrock", "keywords": [ "framework", - "mvc" + "mvc", + "php", + "thetempusproject" ], "time": "2025-02-06T03:02:46+00:00" }, { "name": "thetempusproject/canary", - "version": "1.0.6", + "version": "1.0.9", "source": { "type": "git", "url": "https://git.thetempusproject.com/the-tempus-project/canary", - "reference": "44b2ad688cff933964ec2ff50b408d94c7f51e40" + "reference": "77cef522e9919573836901eb82b59b20f453fb61" }, "require": { "php": ">=8.1.0" @@ -313,22 +315,23 @@ } ], "description": "Functionality for tracking, logging, and sending log messages to chrome for debugging.", - "homepage": "https://git.thetempusproject.com/the-tempus-project/canary", + "homepage": "https://thetempusproject.com/libraries/canary", "keywords": [ "debugging", + "logging", "php", "thetempusproject", "tools" ], - "time": "2025-01-22T01:39:34+00:00" + "time": "2025-02-04T12:16:29+00:00" }, { "name": "thetempusproject/hermes", - "version": "1.0.3", + "version": "1.0.5", "source": { "type": "git", "url": "https://git.thetempusproject.com/the-tempus-project/hermes", - "reference": "4b4e06a98f0f01695bda18de240bb3294d096ef4" + "reference": "802581b1d2d70877ccc75d8954b33efcc05d9371" }, "require": { "php": ">=8.1.0" @@ -355,28 +358,29 @@ "role": "Lead Developer" } ], - "description": "Php functions that aid in routing and redirecting; requests and responses.", - "homepage": "https://git.thetempusproject.com/the-tempus-project/hermes", + "description": "This library handles redirects, provides a common backbone for routing, and can handle autoloading in cases where composer is unavailable.", + "homepage": "https://thetempusproject.com/libraries/hermes", "keywords": [ + "autoloader", "php", "routing", "thetempusproject", "tools" ], - "time": "2025-01-22T01:43:15+00:00" + "time": "2025-02-02T23:22:15+00:00" }, { "name": "thetempusproject/houdini", - "version": "2.0.2", + "version": "2.0.5", "source": { "type": "git", "url": "https://git.thetempusproject.com/the-tempus-project/houdini", - "reference": "fb027a4ebc327e709ad3da29a4cf112894c2b7e6" + "reference": "2c7538471ab1f900048ccdb2c71d6bf2bee975e0" }, "require": { "php": ">=8.1.0", - "thetempusproject/canary": "1.0.6", - "thetempusproject/hermes": "1.0.3" + "thetempusproject/canary": "1.0.9", + "thetempusproject/hermes": "1.0.5" }, "type": "library", "autoload": { @@ -399,15 +403,15 @@ "role": "Lead Developer" } ], - "description": "Php functions that aid in creating, managing, and displaying frontend components.", - "homepage": "https://git.thetempusproject.com/the-tempus-project/houdini", + "description": "This library handles creating, managing, and displaying frontend components.", + "homepage": "https://thetempusproject.com/libraries/houdini", "keywords": [ "frontend", "php", "thetempusproject", "tools" ], - "time": "2025-01-27T05:02:14+00:00" + "time": "2025-02-04T12:19:25+00:00" }, { "name": "twbs/bootstrap", @@ -463,10 +467,10 @@ "packages-dev": [], "aliases": [], "minimum-stability": "dev", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": true, "prefer-lowest": false, - "platform": [], - "platform-dev": [], - "plugin-api-version": "2.3.0" + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" } diff --git a/images/apple-touch-icon.png b/images/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..213fa018fda2ede177ce75bed7d0a062f2acbcaf GIT binary patch literal 28873 zcmeIb2UJwc)~MSA$vLV7$vHJSXQatWMnLE$i_nB7=bR*G5D+DUL;=ZB5J5mPA{itj zlB2wK2exOQeeUId|9$U{dj~y6)00|r&Z_#VYOYyp^;jMDKvfI4%(k@1lL>%X8-_0%}Pe*!2?Su4C-hJwWCsyk)g74 zfSOx9H3I-#KWAuIXlksHh#k%BODl!?CMZGGiP5Okr6YWaVi{Pd(eV^Rsk0}EAGYDk z$sv=ye-Vll73KSk_#qosIK~9(67|cdfLEd6AI|1IURjSd9)11zqk3F?rDQLoY5=tr z4J!%6^N`OMt5BK}e=eZAvul2dL(&g}&JKWwR%J@3!ox23zY>}iU3Lmw8P~9x?BJvbEQrpzyv#hOF_pR z1SqcswD#j+Rsztl09+44gO~xx9suL_w6v~(z*GRy{aqc=@2sVGD=ctQsgK$%BUfj98J^%4$l{OXfnqyJ0AL>G{pklAXVqO_5fopWA1~>*ku4u%zHmBeBP_mhoWc1+#mqvg+QF)z<4hG{w#Aa%MdM2imz?4xAUp6zkx(u7IJF~6f9x-?yw zWjjL>pXCFTKM_aph-EJ@G(kF4V#L#hwJsb10J{y)wh<;YBwx#b`2m;9ZxR>sFX#cj z<_dB40Kj8eIu6YbRTAB30D$ZZKbCSSvi-K(Y^^BdZMVL(VV)cF2TId*woBtlW0?Aq zI~X&U_)9Yde=Mh9G3FeRq~L9RXc-)Dhr`jX^%h6W4)+v{mf6PC=!cFh^&X87O#L|& z0TQlD8-+%i8gxwE20|u?prh&uC3;As6w3z!s)uV*X@Mwq#T*cYLJaQL$BMiMaQmMJ zH_8JO{3;)cjbK&F)D;Na4ZQynbI=q9Op7LYkv{0~=C0T?{_K^(VoTi5(c&`QT&=6O zQF%I_a&dHZNLL85p~su_R?w7S6?fe&*DgV72sEVtpU9l(E#Y#Ir=UM7^tz zkpYpk&pFmuU{e3^MDflt-ZJkpidhP`l-8>>_346aO?#y;HF;2HsCP|%HF*_j-vtXhm^h$2)Pm_w`fb$P z7I$23m!&A@-5HL!)2+!R0NhAfNySZtYU#4nuy_*3e!xgnOk_wTW8u^+EXpgIDZhhTLM3hC8yFd1QeED%K zl`mZkIL^J2zLGwkK3i-2$n_ChO+n3DGlj~fM|pbNHI24GkA(Dcb+sNDR^5M{@tS_D z;dMhketw;5ylQdgm_<<`N^jpPm@3=m-?rKg`I6Pgo5h@| z$KyEI@m^-`;qoU5%&bH%>)8@-H5oNOi|Q3xP7}^po!8^#wYe@uN8oRy;)mi6S&QO} zq5?DAGkQjS0OypGv+n*(Mn2xY`+yw&;#$)u|ZVuS8zm!Hx^@1 zNRUpjM3h~q?%hwoWImTqUt}C-Wlv?3WM|SXfNDZz?23FW;zb-!L_Z7E^VUmrahU7% zjp}CTDm+yp7vf+k<+pv>JbS*i7qXDCfVt>Fn!@?s(9SKpzkNR_pQMn3fK50_QaMyr zFkwdukEMX*8T~Gy3w;!ZTRTO&1r6sX{!gJ3G6pP^s=FW-75BK!*hW4#x_3OeY|C|l zjD<0c%Gk=&>B5;LY0gwO++xB_z<{{e7<=g=YL)mJi*<{y=FYt(Wg-tsZ*gHTd&ChNzozN!yXF#^xOWnFF&v=hw7 z)#L^%>9AAier+mwB2+1A?>2?8NPLSmSR188^lf+zi_NH7@s>_{;zMTL*`7Q=G{knWh>7YGmqOwTQlL zG|TVl|0p7%nWMR{d8*03Jv3bn9zVAIv`yyGc*wgsI;G!ubRpi;Jf(%8r7~(hYIde@ zR&^v%8dkJ+oOEVm_*&J*eyba42~L9;f?W^N);gF6`L+ z*jka#yB28eWZjn5j?ib1D6xetxx>Z z*!qn7x%|{U+~>TadTxq)nmtyZ*Zha$Ep`WJd2^h6F`jx^zf9liPQa%dyc+A+hPEJ$LBQyQ70yl4)-T#*6;mhDjI3?bnTJjYj*DTT+uU z(;=f0`aix*eEZ__q}Aoc-ls3}M<_u713zL9qH$$zMW;sh24e?rWD1H42`xxCT&$hv z%M6$fFl3Vcc=@BZl$3Ngdb zwHS@m&kCt@RUS~uKpo7e_&E63O}My$R02XAKt4VJ0d6)bZZ04%Cl`uS~|kyoZ&tAgUCNxI%>MvnQ^L{IYONrOw8n*;Vq&4r^Y+N)Xn~adkt4`^?!6^ z_vcpTpWAhH_&;KVS(*QbhWtG8AI;2Mt^R}A&m+H^{Whn5A8JuJbzvC?GcXM5pb3RO z75{y@{_C1^AW)c3 zNEpb=%Ec$l!}W`k-!=c{Lj}HwOu;blzj@&n=He0N;r`Xjzv%wm57gAk-0fOk{?h!# zhpCCMIn==h3=_Aq0b7`H+Syu&a{g8Li{@{$S6IQ;5eBw3F;kEghZk^IS(yr(fZ@xX z$DE5@K!_K}F2Kjj&n{$UYQ`>L3WNxlazpq8P0fG9p`!Au`MyC9!2;ZZ+~7Ye`o-D5Rix%% z1rLSbr@!d@?29S9GCp%tL36MW54#D(oR6Jfkk^DA%xA*Q4&gQfLLfk16CecmXBGe8 z=HIFUSvkVzo!c+-5k4z_3w9c2_WxS?=YgkIzXdHju!E!7&owPZ^XH@}a z-%OAlY|1Od4(2uCW#{EKF%jVBf&lp;@F4Tw83uTy0Sfa1|BN*M`-b7KS!`knwzV)b z73ci3XMYy_pEPm;JY1#%Ch#yNBm_@VxJ-EA!)MMX$Zl%FB?K|y7vkeL75uY*|L+#i z-_8*?Blkz}gW5WqIs8|`A3Vr{;pwcIgQK{)1Js5JY-jh>$^`r~lyW-Tn*NawUY&uc zU{I=GPLscL|Ha4ukF(U&%)#ov5@CL6rOBU|sQwS@^M5<0UN2MmZ^qPLv$y{XR_5>L z$bZdN{>*^>J-hjtAH&l;+23d9{hw><=PCAop3K1W5%@+!_?LM2XL@V!U$y;7{ujW%Brl>@kxEzw`V{J*0yQ-g z=Mm-nr{Z6H{&g6BQ|iI*_oT!f)#atB6y#+1fkOQJ?A#piwD%wNe)02j+a?Upis2dB zZy{71Zu4(tf7jRjncY5h`Yn6q;ri{x3H7;wMYW(O?oDvj|%9oefe`x7J42_&DNe(L-Mz}iiEvbjC_mXDS zazY6ZV%>RjZ=uDiB*YBH;ZX(R(KQ*kJ9v1wG>EiFWLiKij?AZ~lP0H58Xxa{=H_YO znLX*_88|8own}?z2h^Rj4`~fjvLxj&kZ!P>C-@u`QSx97M`~=5Pdb^xm%>k>^|mn` z7x~V*vla`Na_itY-XIbTG2O4a)xns42Ut#IIiA}~VVgWy*Y&{oC5HzhD!_x)tw~Y^ z=dxHS*{M}}&c;~09Pya5yse3R4gA);L41OELJ8fI*N*Cee&-@OA{3zv5sDb$8~vqs zi9q-cOTt@JBqJ0Yr{nLXNSR1qnLf?hTWu25KN=13(hNFA+@R?weU;QS3g%AM-`@%Sx-lb9=2)lC|qa zN{R2=MEf-Eugf}MaZ%pRo85XTFrq4SoaF+L*df|UQ(EN~wn!{d^+lb~W6X&69atS+ zc!8iiA>y0thno0>BioROm=*>R);l;c@kPHle{I!z(MpR`A7&_>EYyYAfFuu?)qH6Y zA=GNviUijdM5j&sGK&~>>;91pWEMl&1%0dC>Nc+Dt+#-R3Dd)7Y4(&rZelp8D>7RLaAgikSzMTD(BIg{J6blde^^ly0j zzeDD%eeZ;~PN3kj)}$lL*iVV&bk3k2-@g;w`W5xQ*L zLNeBU-FAM6mN73L-{E%pBR}Du_v<)Uk8qnP1WG4#LvjPaxjsEltHr^0#UO-qe};Qd z48|ggqxG{3t)gVIydq*ct-&GtBzp&RLx8eoh8+gihg~ne9SS_2OmM48Rf8UBX!@#z zYM;Ip`KG(Uy|WKdu$XQ?O<0Yx916uF&j-E z>h$M|R*(oj?&iM3Az?HAVb4%{1$TV?)&zUxzW6;VB0p+Al-TB^i8Jl(u zX~Hra4jnHS{lwZCo)rqD)bMuZ8Q-h!$fC;aP8Q03wcb5Kw*lQbYm{#Y?57MVK&C)z z3r1v=li<}RQ#K-@AtxN7=oG>0q6T6wN7>Ht#&v67!soj-T$}ui#*e$MT+|cEau+be z5+KpPWp2Wyx^;|8&`J0%7qnLDARnSyLONBF9_UJLC~e_8P|*J+?$xXaK(HTqodxU> z-NUN1$VT~%arN29(uD1I>YdoOI^??;Edyut$%BPJ6ju`F_(Ua7T4A)QhM*C2SNi$A zcSYWBV`w&43T!h%jT!<~qfinPL{{c&)o$T%`{6$hm@KA+b)&L1`4ZiZewn$8!Ko6~ zErFqOs~K9gPSrBtQKw|-@#U3vq-U$-aOwSVGSMo!P9u`ecM4?{siQvnqxVQ#qcmzR z(b1b!ItOCvJvp-3-#$NQwDu;uO&Q+$UN}In_|z3ApWq&&K_O|c9MUB%wPU z1Qq_&zyTM(&s{75(fp}j_yst4M6von6V2_Txo0t_8oZ(cQfB(g1b2U+R#=g2x&zLF zRBk_#c`0@`Bf(bnczYwXcUsaQmF?hVJ zp4TnfG)X!W-Xr~<(=0by@ygew*Gqi@a9#(x^kU%p0(ioL^`r8I+FJRF&7n|Qo1XO3 z7dek7Ka;F-boq!x4(iZu1xNU0w-z#Rz3iWBI>0Bf2{+kaoM`YUvt!;Q7YrMWj}dK# zEU3R|H)$QSjZgjFc1czNO?EC>ABLY4yXWtQXC>6@z+R3UnCzSui9en;wHYdX(HDOB zHc&NkVE$R4CX&-KP9ZR5mhx*P-@L5YXVoo1qO}Lh?ews+z+%Vu73Ap83QK(@-!C0O z-+i=!ucHtOj_lUQ6^JuSA3b>R2{S`BmDM8KMboIT z&zml2Lx_;_IpaCb*8Ee`^?0jUN!(H+jY;?s+7G3C=C<(faB`a}!zKd2%{Q4&i7qdL|=n8^9rG)3ZA zulbIRz33`Hr#y5}E*SBkE{&}1{g-zvR)r|aW?Npdj6{d2$t=#}dc1|)j{!c$#n#ew zT4f=BU|X9KxE(3y%!Gq*XjSTWve6-mXQbwSE6&j}#PEHoDhSA>2%SidrQt@^8=DUA zgg;Mj8a&^HrZcd)pi}0;lQ;7sTR5su2f+o;NU5BO>1#R!d|#M{Xnq^!LVm_R?+)LncwF@}9ioA3}O)ch+dje@lgd z*S(;0m42_kHIjsHv^49)Re1HtzBw47mXTfdB`rn`HOr?7g%QVDX8QBt7o3toTsLxlc)0A3S4qCT*VQN`6zm`R+YVYxYfYIMplCH zT_!KX zw9_K@6e%=(&Z9J5UK|V9{K+^_=Q(2$hmU@)Yh@CJhXqq#5h`uA(z{}3EW4a;-|h0A z4>tA;jkRF|7;2qPL}N(x_tXu2Po1QKK&kGB@pz=o zI6@0|%Zi$F)M7obq4*^FjiX-ZIBDUag559Am2 zR3LP>$nZ@d=m#+HYmqfhQO+lt*@JU=hBiH_A1UwpaU!ZwZB44ux`h~j7da3Ds z{t7Q&e5ywV(_^A;QpPb-ifO1=Tr`-@!1U2ve&+sxMp}=_olpp#J8AfXGO%w7fc#!K zNOx^>)ZTr6V%(a*M5vHl=m-$9CR<9n_qoGh9@k;Zr+#9>s&d>e z+n*V7LLip^L-)zh=mWj*kyT1zT{JPjp-v%5FQwOQQ`Q~Y17N`S%G`D{A@@GY{L2H3 zg#<;jLxa3-PkfRxb9r0?v8ssSEX>{gZZJH!KP&o{_@RM@ooSoARbyGQb2tsFc!X*v zwM}~ULNQ@51Q0T+-5zekpvDo!Gv6e$-aM%S5|#B~Xdiu|l@c6SYEF=P%(ZiipfB8U zEKq1Y44}rb4R+0F%P|kYc;&KiMC*_2CSq!4?dyV-6nx1zTkbv}t}@=tRzJCn zc_NSWPS+Tg#wgEFq@aN3t|@Nu_Ci)3#q`+%oADQ>vbL6_5VzVUoh@C}5=Y*ZYv|E-0bA7NlMHfiW5e%0@TYYRNr*a3f*!SaYf=rkE~_ zAED3`(|i0O&>2!;hZLsdO7VU303e}Oak1SRJHwKBX7|cUMQUBmbb1M)z_^y?;J|&@ zs=mYS@@!i44OeHS4L*DbjBm^Koa;4N>0@%`5#nnskfb|_6@8T(@KI$hCVxdCJh?}8 z;s|Jwl%~;`7a>N01uBm@b*VTDW7w4x$FOB(>Gph?v2qy0%rKBBPG_HH5W!umX7z|6 zz#qnx{aT=vPaTuaK?^hCrtxp`Z6J&-cE%AOT? z^gRm}XO7Cru!0RgkJh{ik$jKb137_GMsHEl6|Baul3F9-bEJ_hbxj&R{RX_FF>Bpc zfb1Rqb~yrnR5$hOBl#@rMWu|vk2s9`s+}&fO-RfO6R5-}D~-(%b@f(PnQ#a(@-$0+qu>*wuu&6yKH3^3yUZkMn! zl?${5>8L&AU}fi$;-xq9PLwl`r^u#&BHi7Ul=h{{72a-(8-|`P?lCdwi+A0_3>%#MjxJ?Y00;jrO5vjN6N1M|NrS`*D5^Qos+Y<5D{>b5 z;i)?(c~1tKF~{Uns)PwLnp)y$y-qCWXnp%*dJ=AlJ?G(j-w7A$_3A6W??# z9q~b_MbZl8bM@~pDo4<5)P>&$HB(2GF@4fr57Qji+I>yU$K~NvHojA~Z<86%j7Z`o zgjQ~<6iAr4y<}15gddf%$=@fVtNt=d8ZoK#om)>Ab=)|6VL9k)93zYwOt7G()M*`B z>`Cuy<*-{WY;u0_?PzD_6fG33wLkpYtCjW?n)lw%qh@4b$qR*ko$cK=um+P2my3NWIbr)2FzggP|aL#noKqG3<}|7-^Uk_2@mj6ls3QkM&+4 zY>nwTw^qW|0Vw;`GA$e0L-&u?2I-C6T2$_38-`lfsU?r3VdzeSD`CaRV;25eQ!4EY zW8sffY=Lgvpf>nZ-;gmDCz{RyN9iAH$U zh~kv^U@MH3Jo7j~KT?y^y^kB=@_F-i$!DoYHzK2APu^EK@1NMPYaV9zh4pVWW z;WX$)QDMCEsl_gbik(w6qVF;uE2s2mM&Uc5^wy+4KQ!=dxu@T~lwC3WyoR?g0MkSF zEl@d#x;m+$ox!Bax_%F#LUsaUwCdSTG5tkUpgWY@XX)VFlIs|B*RX!;j1%sk1?Wr)Ulv~ zpZ7zcv+)oOOc*?VH>I^<3;cwod@Qb)1f0{nr;koxSE=~T1aHcTFzA4#Ib$Jh6YSQW zY6aVRiSLe2pqZ)Qtt+zAjGZkX@76rePk*XySVOHPS-bkJtb(oh00pCWOY0Fc<+Lqfb^?hanOfGK@uDYH+7i$QYxl~P zaZqK~Pg#(lT8%>)2r>irx$6WD7r*ixl+n2NZ=KdFQQuR4l3URs+i8R^7ovfFQA7ad zq(AWIooX?9(e`?nel&;qrGVbZX~oBvVCvq9GP5a+Pum>VDW;+Z&*5d`#=r5Xl33 zITk04+myD{CZ;OqyOjCy!se^Wx8;r4bWFD4o>8VvlMq5+gDkoiq1SM6FyK;lA(IiQ zMHyI1S>4A={rzr_X7hOLSBc!f!cd7e98~;!Bll=<85#@-+!Mvar3|W5Q=ApIDo#<< ziFxgDc4gZaVQ4)b8Cdiry*qLQin9!J+KQ})%k-Oz^Tn%E_AcT=978GA(jf=-5sIr} zRyDK1ny)zN4djeM+7|b1zI};<_zU^Fs!dMPmA$Gp$n|12M(R21BR7^=y>n8p=eQmyf!SFMA5VjJj0^zr{;fR1Y!mN5;Ewq_`3H$7x=1qdR1AkgT%`+WX*P{*|hqzoExOrx4FQQ;t(SdH*A^41W?5<2(wa>+&0tM6X?oX$HnnB4Oq; zL2ZJjuhta8QU>=4%JODcrjgFNGTgAe-t%S8Qh(*0BxJTr!NHB4F?@_A3KmL^@SCcd za6vqDI_EA7IX9zApu*Px%?8&ErbzFy<=mUt*}&f2r0?g;?m!>&RlZw`>NhL0DQzRK zIPBk<|0QGj$E!6mOC!0jQt}qGT1SNT)g27I8gZbN@0Lw*$c>?ar%71ZQU1yvGVukQ^n24iBF`x0w;!D?#{hsc;p&Pg^oH2p@a0N z$8g1RBw=6j#p&jqi+@vX&E+rFHZdYAH$`ho&@Cqb(f1FSmCxSYwB{y7{M0#Rb%)Yg z_{{`feanO#x{x_wC3ny4P;@ zp2k}irH8IPHdA%>LJYhhRK4P`J&w3;s+GInXo9}P&y#GXORF$;Z$(GQt*)|7htHmQ z%_x7yFVWzmmt2FOLJ-ci(1mv-?SkHg4+bPmVK1K;AhLMTD&*`1g@%pcxDY!G?y0PX zgv!nNnK~Jy%{M!OW_qfLxcpLj%EFemcYe${L$Zr`VoCrZP_yuO0;$tt#!Gy!**#IZ{(i6Mi){l8&&g zVEeq!m=4A`6xAuX~S>x~hN4jI{r~QVx#vDpdI_WwCbkLtCB1LpD zTk3zM8#+Nrdf&Ad88|zE$&C9Qe`g2q z-jjd;nEI^G2*fkl&|J;F0~W%&yE&aVe&RLr3f?ufm^a5qioS!d*a+vPjiGc%9?X;Z zPlIA^e_dmKFN%eJ@ETOvLo??SAvAZ39%ij?OnKOL9t|J$i>l*7El|mB1biQ~8aOU( ztTso}RFi5R0hMx)%ux0waa0A_tH2avy!0Mm5W}iwL9D5|645v?dVN&4zb3${FGl9J~yk|<21dqNeZEAcT*gtE$ zP)PH-|C&LyNX#%2nORF@HD!#tr`IAb4?D{paoEj?6KaFmxRwyldN*5t3UMkXRJcK^ zsr}pDA>*8RrYea~0H%m&p8Jl`u+8d`TT7T%Bp&NF+~mAXfl*f(T?Jkp{!SBJF(-UA zUi8>)-{)pjr3!L<(N}&qtVb{a>w_J9d^BK{8R31HJ!}Z|o@lRgY?Y`V`Yau}eS_N& zUmUNk#6}^ua5{3&Vv;Kd+xK{99nq+hnxNW;Wfc&5CJ*xGGzTyF@y#M;?wvKtoECCE z&VBO!88_{&XXl0s!X542qqD|j+AVJNY$U_JuJlSP5yU*O z`#uc0q}9pnNmP35MsywJ`tX}8Tks~(G$of|3Tjc9!Y@p-=ZeIp-M&XRxdfOqg12JA z`-dDFP>UjXq)4AT6!dgG@R)nk5SUI;KOPM>tJM5uzWOyXdOHE zN=|{_O8a23p6%s6K?QctOCdaa{1(4G%<%lUE+2UeQOaj26JzG}RkJH%c+71{3cI^{ z@Rh^(T%3wBpW*?WXD*H%x4I71_8#el__tD|<6;$%`$hJtkJ`f*pYf48}$x^QphDG?=-P=U3O< zGRK*_G?1RcQlwR%T^!*}x4mBp*?t1Q9WwAeTYzS{?eHP9I6U7V33Dr5&;L+`vo>3a zh#qDb9Ej9M>o&0YN7?=##=@1Ym(1>6ZkDZLbBxX<+aN-)#^vkBE?THUyOw*a~VSY z(eQXQ^F$wUHwvbS+)*R!F*tRO ziL0!kLb78#T&N)Ig_Jw5i#nLJ7!SvDIZ#dT)vMP9uu9Q7DrsOuA3@I#QcvIZ6HBwy z=}@n!kR?n=bt+UE)_yPO6bKbEcoO4I(UH(f=o?lqK5i-V^g9nTA(peWe%O{wI3A@A z%8Cea#e%3@YPJE|v_~^2b%GXeYGX$VW(!VykBc<$Fpo(h`8M z>YVr1CjTKs`APZb{vVX*r6+X;GBsQ#E!GcvGC7~>AeKof2Xj*Cv9dBp16Y#> zZ%IeSx#4Q5z<=bZ792{S8=K-*s$MIg*?u2iTG>M?CwoZS@MXxAv=j=8LP<6kt(*RG8@eYzdf`A#ks|FfijNLs9G#C>S2>SA#!4NUvP&(O_O`e#5 zh*vt9gpR8~u4gJID}=5QIymm|ppHgyRRz6FpDk;gRsrc#%&7AP{F^8MON3@$QUYgyn9~O$rj)oQFLGm3v#ds0AwXfltm@E=q{~))2hT_U=P$x2$f?SfN*nwCKk>I|m;e9( literal 0 HcmV?d00001 diff --git a/images/share-icon.png b/images/share-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a731a1e2dbab928e422e1fffd11ac5ed9de37ce4 GIT binary patch literal 3233 zcmV;S3|{kzP)U3)@9*a3=C!r8xVX5^&d$5LyR@{l!NI}5zrWtz-uU_bZY8i*}

7)P5%!wJ0N?(d!B_O8P zlai8>l9G~=l9G~=l9Kv;o2GG+Y1*C( z%q8#EZq@gqy1#O#$GzNJm*~dILZB1r(Ljh>dJlKWjx~`U# z>r&!;4^QH5ARx^#f-R>hCxP#AyH<4WnE#oIEHG&fx|s8kH^(h$*O3o4jV8UvEos+M z#7Uz;CuvLD#w)TYH9^vQD*@WJCQ}=$$fcxhVbY8?^=+BjNck+O>yhTPWojeEoVtd6 z#9%W6awY64G5@Ha)Unj|taFd$!ex22ojM_AL(;U%WHJ9}Od7as8s`r!Iq_8TAiTgu;rpADc_^3kJeFZ zt|4KkWp#D3)AL2nk8wo~WS`oJeA{rOWuL^7Pj5<9$rsc&(nU_v9K-E5&ft91s;(J^ zEepTBz^v_FM_CQ9`*7A=gp26s7h^%XLJhDZn0Wnjk5bo*(uu{WsK@`7{7|t&H73h3 zyspfeiGYiEL~SyP@*Qw0U|klupejRvv~FC3RD{rn<-gzNpah4=)jjLVNFeF7h7M90 z0?Y`m-WhCUl%K%5B9uOusbCEf1cKqJx<}8QR!4;&;X$9lx-=B(r4}|b4$&n~155-_ zr-_ZDozEKAJ|Qhc0#+)R)MqV4%LW2_dS>$@$mxF)nYUnEmo5~++Y$8*oI(|i@Of% z$}mVx*4b#lLd+h%?;yOJZO9~~tb@UHJrZIKv!mTd9uNfK=ym$Ao~<7~HthTfg2CqH zeLefKp1$6%@{+p->*_#AYp{DZEyM)69*jc3z*qA*U%4JBBjx+oJ- zN9*-wpt8>3Uzi%UPrLV#G6Bz`-L0P1vn@%tB+9xnj95aGzRzLTF8t`i8MT%RCMR(Z z2@>0IF08wbjakm9;otM86G}B0tY@?F;50b|f+dgo{jjj5E)%34Hyv5-D$B(=CFEj{Kd*lqRf;A%CxO`2EbRio_bsm9T zXHLbOPOt9%9PWlpKW?{s)?fLC;coXhM6&kjy|(K8g6rwSb%J%c+bxnCzJ6)O8WV0@ zI)%+_1aV|eIK(oI2yra1{@4F#tvll7E%)oe=%8C9Yr1sAoJSef%H(z#w#ph4ZL$V| z%yyY)V-C%RqicrQ$8-v;|9!Rh=h)oH-FxzFj%MwmCdVx6tNASPxhZQ@w5fVe_gyzq zYqN%x45kKStS9k-vYPMk5zkuJ91n3xY!(t@#vXun145QH*sgtbCQQj*kiQdXN}1WgTxdpLG>% z6zdZIQ2Lr13EvCjk=0zw(AzZehc@u6VJ%a10Xs3KGqNs0P5PP_>1tUn6^h>~!1SMH zozQ`GDhF~K@{87u$zzLH9}n$}bxBeKYS$vd&-U#j6TS8n@8uK(XPu2Luc3nLA?ZU4 zSs#u)2Wx5|`>Ym+O>Z~4_-m^1UgAL%u+9sn=$dK?YyLlvdA)D8E7rxRNeZ%J#) zub?Q1BGx(4(0c`WH`0q(EA$Bz`X9!ceIfz9onFAY0(KSa64Dveg0#i%fr+!u2BYWR z1Ir%ASSutPjP5s^?Px_=Pm~q^GzjSvXzjBuBTd*d3)#B|c<%UgK zWKCEZQk~Y6^_QRP<@?h$nOt2>$o+gaUaogf^wU+a+CDF5uQx5Tt_rh4KA@)qJ*yccIW7@`r?HOx^ONB<vEwYVozVU zGq}A3VRy#5ESytZx(AhrT0t7@v1nr4Kf8*Fgcg|oZ_TLQkLTAp?^D1>_b z^9xE5BkC}*)gJu@>~oK@-#_=)6f^PfWbO(zofsYYHTnm6Enk95ioOd$e%JUx5uD^L zUxPb}UQ3iOEQpD{8zN`ksgL;BM9-EEl9Wqd+iGeqbK@`Yd-(bwGBZKI~If|W12%c=v|o_wcZzI?518-c7gU5PqRZNsJpB2gEpRoJdA zv${+Sb~~jXf7!0A_KM}V^@4Qy#_nqQ7Ofqc`iM)d+LmvkuTsQPvQcU?|L`R0YDH|Z z=haSamekU!aRMJPYtwc;dIiL@BxfV&=W=KHvo zB;7=Q6v2Ai+4F`3r^vbBN7!I8&<>=uoDrJ~ti*DeM{wdN9X8pnB~!XBL3Uf<7KY