R6TGw`Cc^e(eTB|qTg0{Avd3i#L1dV2MPZ1j-9`?g;;YSe0OdxC1Rv~CrK{9;LRruLFky6S1S2B_5Q~C3dtN+@GAQ%gz#wib-gnVi> z7qec3JueJF`4E~A`wO#tdn|*C%`vxwbsXl^Jr%RXb{>ii^dFJ%Pmas0ZI(%^5%J*! zy~$1+_TgJ|`mHYc>m^6N?;B!&{BAkl8{B-V^}um{O5H>09R)W1hB?m5+unvZ6L+Co zXSpkAgl{D@-1y1liF&}&AF|oco9aD f3JR+BjNlKW!5<9XRw@pAE@R z?qQ;ACet)OzYes*cdd?GF1q0P*6XLYvQs|0+(Jf3duYRASB?wJ|J!5PWs=zn%g+zE zg !Mr2#`m>T>%7?eC& B*C!OPj;ynHb?J$>E5} qlaQcHd&1Z>{ zP1(K0Jp|-HWdEntvJGnCkd9ZL(*+)`T+u^9i2I;yvvOAHNs?XdSV?HVpP2mk^D8QQECGY(f{iybFXHi|;1|>Nyw> zs<&j-sTAKTe9<1C!i>>=hs%kFO h&VJ4Z z^SbznBn11<|8fJPXNPff!MLlq`njJ0Kn^aaAOpWEb6d_DuB>wRw#ps3TX47v9DeW4 h9~J*5c;e&c &{s#)OS>6Bu literal 187 zcmeAS@N?(olHy`uVBq!ia0vp^2SAvE2}s`E_d5VcHF>%?hE&XXd(e;($UC&)tA8%H f{sJJAUZ6r^!+8cq?Z^j}AR9eh{an^LB{Ts5$afa9 diff --git a/PWA/public/icon-512.png b/PWA/public/icon-512.png index 5220d0f9dbfa747cdb356761a73beb1b1f1c96bb..b24e40ed9c3d8acb089fcca9ad3b418da75de8f8 100644 GIT binary patch literal 12554 zcmeIZRahHe^fo#PZbeJ6;_mK}Vl6FBaSH?~#fuat6bhw4(c)IL6j}&Sptx%YMT)xx z*A|yAzyG;9&w0+d`Yz7JH#d`+*=x_USN2}}UF&@(T37oi2_YRJ001N!&s6mR0F3zw z2Jo>lCo4||Ps|D1@rl+G06@eO-Pqt@u9;!a^tAvWfD-`V5dd(7xdq<>03Trh*nt9o zY&rlu^2lz~lgB&&+rD_J3fxDiPs6Kh=H@m-} zk<4J6d2oKe%c!F6ppK%X5EJnL<0nYW8`T@m?f %FuA&3gF#WFDVxh`AN2Q0sY92h@Cxi@nP~3^Qa#&r5p`}j7!uMB z|A6INHd>8~w^!YlyI(ylDZ!wq(-d1-HjA}Pw~VX)jvUtr+FvTOAA=Oz^^!!7$Lf9A z!y&>go_y0ePZ{${-*HMZXn4}Z@lUF0H3=PKPc-E+TxMRosg}z&VH1dD-N?87Q#8oE zhOBCrAJ-IH8`l(89#zS?+Hm*eFBuMVuUQ$HhISd7uF%Tu;RUun&Eeeda8eDY0&vvR zZ4*zk?GybuX&llCRbGD8ErBHXk{6Rk(119;A; -Y#`apr z(a$bA> R?8DHq+YRRH0z4a{kO)p8`0}uL^la~gPNX+3X^*T=NCy$ z{54+yzpgtXz~~t_)hZ!OamY#V!f^5DspN}4O%kF$Z?{KBY8g&h)gn7eTr+9&>?Sxb za=Gf<0-vmTTR_R-_d@%fZ3V4FaJFp=yTo#f712l1YG_I8i`7FOV7-XJ$%lmv`(^qD z#rZ{KQ%HR2#I=vTsrA34EPy%z+X~w6cpH2#F!ig`iKzqWJ)0)g?)i59%)dQtzHVgi zlR}}>KC?#qiqR}b5YEc6((16xdva`>t 5Xm81d-%qCShQe zSmECEwCH!fETDN4ji!jo{7Ntsbd _vthweCdM3f!qHpfs+3zF>)y7`(TAmmcIf)@^vfq zVPMekc2;p`uqZekPnd5G8{N>MbR^d{DE}EXtLPJ|5rad;EoujQ=~+2iJxu}sSsQa! z{`U!B;n;fmS1pkMb^PP@@%{3lh)OiX{N`C^#c3#r4JoYM4HB50e9fVj1#2Z$&L;&! z8S|kJvsNgWPB5d*pe4lq6nUS-Sm+i08%#)Sz*=O-;T1!qtvp6r2oE8Ei;6Y(MBT8p zp}~J1Z5W-W)%wgq!w5FNCYfY$k`#pC!!>oli`Z4J*2HJ((z{a^A4nTkS8Pg+(P_1h zox<&f=GfKDa!pjf&su1^nN3dN*vSI2cyC2qKD%=I$G4$_H|3=*(uxm+Opk*eLfaXn zcmnvQU;UxZ`p3SXben|4ZP#K3RR#2vN{>i{4B>oq*ttuR7-3=-<)kg{6k}BT=_gjU zl2aGNx6j(D>VO8QML73#vgw{vV ~@wDhZ7=NhJ8C;0gq<2jsBFypS; zI%j*`F}5Ak$Ce$w$m8~$EvLR7w_9tU{*vJvW+hm|1~+A3I)8if_U6;MDYLYN4@;7( z0}TfSg_QgCrzwRRDQq!ma06~s4X@$i3Tbm+>{ZKOT3BRO%Gc9rsW?*pEO+XDDByi= z$EUXeHvTn88|ibFcIVL`O9qRmp*~iyj%r#7VQ}>7OCYuaBSBQ@D}+)PB<^B8r>?E4 zSL)A3vlZqLCH1co+F#GwUqx%i0dC;m-S|X`eN7f<21C+` V-g=bC1;PkBw6 zYLvi@(JYQUt3l=9*8Gdxr`KceY|NJ*FWTfLEpD&{mv{60@QfRm4C nz3V*^QeZ4gY%ZyF*uQSkn7@@ zK*Tk(_SG2YWN*jV1`UhaU<$VZyF4P%vtRf$q*t4ZXkT`Y5Z+cM20kJz{Wa*%$&<4c z^>kupg?41xE=x8V3;{gAyqdy2#A2}qU;N&=7Irt}trSeX($#7Drj(iiG!V?M2HO&L zWp6x2i3PAq-7|1?I92!Imdo2jmsTL2CjBB3)d*k1ewndGRVvdZKmL*jhTZ4Ha<(ef zmAxryUh%V@@aFu6)XtGrSPTShcmKX=&~bq8*wE<|sk8h`sZ=Y+G8ciObFM(3aOqw2 zxCSPvz7}z^ zFY^K9fX?s7(QE$~P>!A>R--4xR_t@_XacDFDpfmw#ve6=| zS`q47FcEPFV&tAcV$#1~YJNq;*=2kS1+qJMt*LJajT7aFOox7|vG{Kgf!^n3##6zX z4V|>Cf$e@Z6R(KvcYYW-fSE!3G<@vINJKjWtnX4B??c6appJjLW$XHb7cTnYAv0B` zi?s(t=%|cUo;il9AslUy%?+4hlv#mlvH`Liwx+@G*0D*9MGOQi+la29rO{% 037yb!MP>Mzazriob2MJ_P5!iGS LbBT700OJW<;;dqrtSg6lCWg&CGS~h+ zmQsF>??dZ;O#mRfqIz@#PL61CyWEHWoUwT?7c}@NB+YPcs>(XVv_4K+ 6)#7) zBsm_x@IjAp8=2pohwdu_i@zk3)jy@4Ie^ w znv_-H1#=6*Y;B7JN# BtPoMu~Ouq%{xL>ga8M zzYcGbm|j&}I*}lq-fk||>I(HYtlw@ 3Z=E)yuLU-1W$QR}7}50eN3-g&IQBHF{--LIW;|yO?c~-S@p(9kaf6J|YCRXC46| zk6Gt7136oe*yGd;b@hzIBE9RIo1vydgRmzV1b~p(hL @*3>TQUzrfc zk|nU$ZM>x^MVbhKp#Nc~`~W1;0%b}Vu=U{2kf!iZ`ai1z>hk$Dk-%s??4V5F9y{hB z!XUt}Ggsk61NG)-+K6YnvU>VU;3iwt0LkP`A#B@c CUuf8OqWXE0Xj+WGXT2J;YM| zSy)wH-;W&GITwV1V#73QadT*FNmgJd+}D4pzESS^ndG4OM`FD}?Y1FJij{@D#XHyJ z$C5K=w{d5ZDm%9)bT 0J(pa#r2J%>X^wc*(+?atNAc zZGMVXjtyRQtsl9_%2S}0%>5$D2sepxwCK;AzEyYv`2Aiis9FrnE!-*HrLchGVYY{u z^T#UhcTV{YO;a#a$Z_$eKPvthD>Ac2F@$1YmXyGOH#-nW)XjXEF~Hz>$J{c?;Ee@@ zog+4x{(-*`w6q6wtx!_kUx}`rMlaL2ejoJk)oz|4fUjx18XaSRH~VU<#!TkNN{A(^ z_N9=K7ateTM;tt6;ROuKe^3$f z>zKH<&eBGiQK{OvXuQ@5@-~}=$4cOF0Q%#m0Z^PlMb-B#%C#iNyS5O`u3ZhsQY)Fd zCxq~+kb_$?VZPsW>_^})Q4x9_Dtw|yZnoF}HP8{A4>+Ikun%v~;Iyu1iVc%u2oNR} zJZ(6=V!~$1*IQ)9X?K20eX;awUFx!Rol;X+{j+BlwDW11?ibBO-GzGzQCs)%BJG7U z*DP1xX;_-;T&qdj#`#{`CJA;spa 9mG~?1`MS$Lz`FnJX*QV z$e)y-i=|*Aux>|ZkH@*y;l;p7%P^vM*iS-cmx<; W;0&lga_}m)vG5^xpZ&->YfW) zKJ?7g8)Teafgy<}kh-D5yu>S?dc X*PX8be=)yxEHbuMvxk$W?gused z&J9= n`RweOsI-jSE@}$p|L>?kYEI zG _$Vk3<7vrU!R_Zm$Pc-UBQ!sGR)C_pj}ZhozR)6`09B!EJmYa41$96?A0< ziRLZ6gxAsgPytE>z*Yd$vx;TCfszI!o`r4pZ=Zuh^PI!sFGz9Y=HXNYUd3{?hfQS< zK_lA-XL?UwIwYwHdVL-zmdm``4aLPkHePp;-NNyf*5Ee~C+y$$0LYM9dISe0T3pr^ zrf2&xy@vm4+$?G9R_`e{@QE;E9sDTcoc#C160={cAT$C;kRwY~JTMS}hUx q_(nh=adCLjYAU7CJpQF!TXNUoaM*1 zsW_aptz<#tx07lh_?ooTb3T}+nA#trfFsA>-X-7`$Y-7s<6gIvAP=j
eC=d#% =A>OXH{ zJ`ugUDRoriG=V+`c|60kNAj0ujB!BD9>YRP`lV|$c{fS7C6`w&i=KTZQ2*qqYMVLX z^qYN*ZZ&z+%|VTqSVVOou;m4%XlIf0TQr&qhys61;btgYt20^SDVK-EtAad|7$}rE zrF+0$n& KkENt?dy-Pl+4a4X1HZdlZgi3na%3-F0Z{DY`Sb_7K z=<=UsB!QO`z{^Jz%*;j8UVyY#u4h#IuRh#s_Do9|8v+&`*I_A-UfP2B7wxj?1()2I zP75K4$~w18PKY5<>r;_ -`+zr{OS zCj|^)@1p`(Wl8|D0TCSdvrjyL>KjcEa}taYNMtYoKCGwzpC t zozdP2UyryX4H+LgFRI+?69*@RtbOImqlp8ovNdk1OfSpxERk{f=N;iUbPHYdWE8fQ zR|+zdm)Aco{GPDERkW2SF11MSrytN4H#?{&vP8<3{xH7&(HJVns)x;hiH^@-jqm(p zGJlpKs;1WN?3hv}s$7PKEfi=a`ASqPW7ZGr>pi{Vi`QSa;It33pdW3BV9QLzQTN%t zak%|Tz;vAonJBVINB4jSpqSm$+l~FF$_9TlyI0*4qNBwIO))8JE=CQme*j^1Gy zjlky&TLFKBof6uU!x? U;rvTShKE`?e?Sh^|7WAahd?4s mj zbhvwbBqwZPuqnM3aHgnwfdTxLv)?MlQ^AACWAi*T=-iZRvgZ%M3;c|KF&4}GUMX^Y z^?mLyat;1-%IKbb$TSeuuFfOUAwDk8HueopxxtR9$be&B^7yx}Sl${Z|1QyZ@fP%e z2YB#v#xV;kKJcKP#U8AzF2gM1b5Cj4Kq=hGURW8Bx5*tZ1I-H70yAR#o%?ilud2h! zeOzT^>gz+=(r>3j&J^CE0gM)=-Hh~m+`#|zH@!*Qq>2(@6yKKA$+^=pJ6GQA&$IfB zMU5B|s|&O~k$5F;=<{`ev)tu8#7(y})Zmk6(VR=oAm?!HZo)%45QAhXF8y7KR%VXU z`4J?6by;Hf_Chg~3}d3>`d?h2g#Qh<`wp1R#in4rnaF?$RlT+n^g z_PvDfR|AbE@e{L&8JoC=OSlWg+q%FJ4%`~+E24vPGXrK)!-mEArI$`;Iv@Awy%9Eu z5YF_`6fFpgurdOOspDP4o969vr1z`sqQT2wKRC|Y#L{LJ;%DM*g^rZov*voH$;pq0 zL!NHSzkP|MTY3}q4>b&lqrmGp4Tewt>Z-4B!uCi}2P|`<)Le&hc&u08-?Z b)g-)xP~fV8aMjNtv)iSIU@R z8bcJQc4l4Bdis3tdq8^~X|ZJmu^!;P0A9oc-@vaUj0&EIIYr7(ur7tH!+XT1ml^9X z-#wiG=XZavjY(x8gy(%bo~BEoDUA@RJho+unOP5Ptrq$PqtD?|*uczTa%-@M0;faH zwPs+3XdxBCiitecTYd?B4Ce}Rs`u}A7~A=AmBNMrRYG+S?};5_O(VIdVp`Y$8lHTwIl}U6JCr#C7v39 *hLII-i&~iQoPY zY@GxSRUe%jr8cPb%chywC4E%NBhjU{8%ex q&V8Pe2RqnMj%Zk<~#;w&HzJou64(u^6KQ;#11}KH3J`Vj{D8gCfWJQ<` z=DYxD5jqT=9(F~)szxce&7tQB4@eH{{Z}8}eWM5dr)x*}ND{?3UffegM2}>k#VRr7 z&L!>U-f=`=P_N^B&BjTG+1M)X*5dsOOb)P0AneGZRqwjwIJ7%ipq^C|t6%&3=LcB> zewLD9#rVrep A+-n;ErwgLmNw zI4-U`iZrnHm&A-?jG_6-(|NSwd2q4=a=(@+)1MG-UD`v4Cts^$T6=zrCFmKMbQPrT zjdyn@V?A4aST&TJyK#d7yKRF#ul(y RNQ0~P(~B@Ho?#o zcZUL^J3Au%!-o$MvV8M3m6zSE#8UjPxj3xXpUm3t6Jg%voz)emvJ|5r=<1QiNt)r9 zNq{Mm^k8>kDyavH9KZXQ|9RN5W{NwF74%AGxzzMY(qkwiHpv~WH9kn1UE3${vhgK; zyWnxGSvR5inSjd6;7osNnJ!E+C3bRCs+u2%t(~6udv*CzC+@M4U#Dn!T?Zoxop>~- zOJsa)TvufYaABy3bEFd%`iOE|x@B(NNyhBd$H;%MB3|GBPE7OoX=Qct+782rq{L2? zQr(CwCi$%CJScO>;J~}6uYED=h`~%-I)KI7{2oDpI#b&Z6gZs+L69)W+Q?M9Mx*g9 zxd^!c-NaY_!i9kKfU!y`Lb$Ov MS9$?ph2;$C~d4f>bff3uVJEiTUgR>*| zsn4Iz9<;rME0tPu`fGy{8ZjIgT%xN8@(WY^(946qV|fR{het%Z*Vma}V*oyJLA LX6_ah#iw6ZC;Yq~N+D|`q?Ji9UlqZz>INWc!22bGu^f!Pf7Jo$qFPBae z^XxM{)$u%n)!S*%H0L#EpF(Z#clQ1I<`_#YE1C^}qIFI<#{qVaU6NNwT-)iAh}yH| zFp`N2CgAkr=Zy7=yqcuL0JeZ`BMN#ct?{sJJ)o$_Yx&$s|MBL>``o3AIizmUq2sL; z3X6zac+K5hplmwtSIZK&Sf(%HjTR^&2_No$5&T7DbG_ezn z@)E(}G`0KmQ5|p^wC)=E;8xCL`%$L% &f8SoFkMVkwhHtXKB#)S;$Ua5O z%GFbs(-fZ_nP#jcmPYJnQ=lRFb=rOT?~z^%vo1&Jr4wU n*Np#EL2VnzWu lo&rf#Ek>Fq6>P_$w|(kEcBq0?}>FU zY}VzNBy`>2VC-3wd;##x5HJx7V%X;t=%xMn!84MFczzR-W2wYij_6`jMC)`sdY>ab zIiTc92!9!e6{`7zy~aH7{B}gV0cmOt9sFjsgAHjbh1AD1{S1oNGG7r{I{vl5v|tv0 zcoJ0`lNN|ElYocTh5k!DMc(c31&uUWY_i5k9@rD!F5b!=;&N1T%JF;U9bRM}x Dy=2?Y=omCfxC70gIUW|k<*rZ^zo(`v~Ct(`##Ja`q5l^zix zt*xEm<1FBWS +;4^M{!1rPe52Q& zQUMuW4bnBl Wv#3~n~dj06ABT=0Yd=)%7WIVax6%Sn}Fc6HSSGv`BWps(3XC3Rh0A>W=r zqAA`#8L%JVFN8#o<^Rpzd&yQZa~ilBOTiYauMhM)JEYLquVV_`>SA(2Y9rb}?F=kS zT_>uSTMUKWMf)wDxCCy)NmDv+0CbB_JH-3W{_)exsrVobjWUY|=@tyqsQh1zSbD#n zNrOL>A-X_%vwx&ha&7_JOz~HVfB#mhJWs**Az-e|P;hrvIEtVqu>{{RaFuAyud&9! z!99zuREfqE`g{Kb;W8q6Bj0Z%`ce4p8b^#H_nT^wt|^4YoGel#hX+5o-hkb}CS8=z zIe25QgnNt^zAu2hVqQ^V*ai# 7r|4Ko AbEU z;GOGhP%(qfql0B>-xvV>8gDRR^dCl&z)+m4#BH1Ro&P&le>(@{T>smE lcdH7@^D){SA3zll=K1Gz|n923|(1?IDI06UWzHAowhb)N;5w z-cTHhB>BeKF-Jh+Y@Ub3U#l(JAnE~+cGd^gKPmoWg#~ z`lD%2PJ`B`;w3=%za8c#-)Uu<(t_-k1tE@!J@@2V`-mRFI4dPA25^broco2j;*%Bl zu5Zq+ld aE1?U=?xch9`9&-NbpKI>&@11WC+-`g@F%8SR(m#nO zcKmXl91R?yagM34U8XsEf0r}Cx yfJpM;J;qU`{$g5-v+mV ^T<0a~GXaRnYC7J|Z #o#JhosM{Y{XoX%; zJ3f*4jD5IaZdJFzWKcXi(JnIw76tel((@yxww>$L%bnLP2Q=OL 6iRK~XNn}-+Fqw?Tm`~4m!)O^kW;OKaqKc*)vs0)eA76t#?BvK&?Ogv`&et^5) zh)uR-0gj;J(JRqBj#v^Jwatq1jpEpGGX7gC`Vh!*y$w%wRo_@oR5+F?;mMnJy9a^P z=p*;|yHoarKS_+;_=^bS&QR#=ZKLPz -bYzrq&6Y7{?7 zlPc;la6A3{-Tx(=SWso)B`^ BU#mu!6)1tp3P+0f9t)%B`{0lc2=<;}I&ULApE2vM6 zuex8_caQ!ZYvsbJ lzj{VLS)kv&%nzi_WcY$_z6SOv| zAHk67oqpm!slmPXuA!?xT!ZEVvN(IkYh%tSGDzV5*|J0l5n6M_8_E1;f54jc*c^em z^@EauX9-F(_mn~QyNf1AvdeU!=5G&;OuB`65%spsr*QS{o{)}@z`(~YT179(%f;4Z z*mZT4z8kw6O}*&ct(ZIkepJ*yr=V}6K@Qgb(USJPI?!<3L`t8Aa1MfzhGFZ5HTvS- z=c2inC7CnifVVn`FS~d{I`O9lH l% +F->9h@U14{z zM@mZy|8$8Ga(#_a@F=ptgcfhV0|^-A-7=^3N#3QDB09` 0bq=1Fu~Egp1526 zF8aM`YGKUUd`}tTW?uA2TeBNPdJ&;?_1MU@l$ON)HM%WrH=Mkk&KXJZj&ig%wP&)9 zT0I&Z#sg;8(ze5sM+oi1uG1_123yrwQ2UC~_vdN=fCQPWsy-Pyb4|v2PHa#D4c5n^ z)g{NP>vX*i-Cx?HH%bbQmy;X*r*eLn^#VQzgp6xU6U}M}xRF!L;83SS(+dP~*5kZp zCtR`~GJ3@5ygPh1Ttu#J8nku3akX>f|Lt_LWO{D#=&|H<;l6G)i|ZkeyTzWle0Aj| z(LH7jghOk7Gj|BAo!%);aIwK3;LQu1HGYqn8>p^CJjE*Pe)X2NP91#G=zs2*XWzO> z 8 gR1 zpVT@85{*v_?d3)AT&jC9s@&@&g$*Z13fcWPjK=qP5Y2GOIr)M?e#eIHIg3sCUi|5m zYsRa$v7BX9C{?BgEQYE
-e2}@^&I}Jk`A# zm-^roPX`ldE^SE$h6Ib`acY6z6hu%<)cN<~(#yj>Kg>nIuJ;f+aSpgkhodzZ$X%+& zH&gRR7^6u{(e#?tnads#8N$f%Xb }Vf-U=WR^rmwgHML*GW5fKqdRC`~v zszni{GbV_RHkRXREXT#@@nQ=w`tfdI3}K;#g=_!uFpXr4p}lg{Ax$<6qkfJ^{C#jQ zcU{Tp4oc8HWN+>t`5pa4^?&1GcXWHd8GCu=Kk{iF^T7azx0;E!osGA>EbNUv<^+fe zi%JRzO9+UFz7&>`l@O5?7v&QcmK7F$E*@9;e=~4(w{vpv|9>}-bCRIM7yue-+NwX4 Hq3`||=?)pu literal 842 zcmeAS@N?(olHy`uVBq!ia0y~yU;;9k7&t&wwUqN(1_ow9PZ!6KiaBo&HUh;M4lno_ o9RH9Zlo7-k1*0J_;zHm+KGPNk#z+z0_aLu(y85}Sb4q9e0Lk|gumAu6 diff --git a/PWA/public/sw-push.js b/PWA/public/sw-push.js new file mode 100644 index 0000000..8dc1afb --- /dev/null +++ b/PWA/public/sw-push.js @@ -0,0 +1,26 @@ +self.addEventListener('push', function (event) { + var data = {}; + try { data = event.data.json(); } catch (e) { data = { title: '沈晏', body: event.data ? event.data.text() : '' }; } + event.waitUntil( + self.registration.showNotification(data.title || '沈晏', { + body: data.body || '', + icon: '/icon-192.png', + badge: '/icon-192.png', + vibrate: [200, 100, 200], + tag: 'shenyan-push', + renotify: true, + }) + ); +}); + +self.addEventListener('notificationclick', function (event) { + event.notification.close(); + event.waitUntil( + clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (list) { + for (var i = 0; i < list.length; i++) { + if (list[i].url && 'focus' in list[i]) return list[i].focus(); + } + if (clients.openWindow) return clients.openWindow('/'); + }) + ); +}); diff --git a/PWA/public/weather-cloudy.svg b/PWA/public/weather-cloudy.svg new file mode 100644 index 0000000..e707729 --- /dev/null +++ b/PWA/public/weather-cloudy.svg @@ -0,0 +1,4 @@ + \ No newline at end of file diff --git a/PWA/public/weather-fog.svg b/PWA/public/weather-fog.svg new file mode 100644 index 0000000..a26ed71 --- /dev/null +++ b/PWA/public/weather-fog.svg @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/PWA/public/weather-partly-cloudy.svg b/PWA/public/weather-partly-cloudy.svg new file mode 100644 index 0000000..5c70072 --- /dev/null +++ b/PWA/public/weather-partly-cloudy.svg @@ -0,0 +1,13 @@ + \ No newline at end of file diff --git a/PWA/public/weather-rain.svg b/PWA/public/weather-rain.svg new file mode 100644 index 0000000..64c9c7b --- /dev/null +++ b/PWA/public/weather-rain.svg @@ -0,0 +1,8 @@ + \ No newline at end of file diff --git a/PWA/public/weather-snow.svg b/PWA/public/weather-snow.svg new file mode 100644 index 0000000..95cc2cc --- /dev/null +++ b/PWA/public/weather-snow.svg @@ -0,0 +1,12 @@ + \ No newline at end of file diff --git a/PWA/public/weather-storm.svg b/PWA/public/weather-storm.svg new file mode 100644 index 0000000..5dfc9ad --- /dev/null +++ b/PWA/public/weather-storm.svg @@ -0,0 +1,6 @@ + \ No newline at end of file diff --git a/PWA/public/weather-sunny.svg b/PWA/public/weather-sunny.svg new file mode 100644 index 0000000..30aa78f --- /dev/null +++ b/PWA/public/weather-sunny.svg @@ -0,0 +1,11 @@ + \ No newline at end of file diff --git a/PWA/src/App.tsx b/PWA/src/App.tsx index 01b31fb..ebae70f 100644 --- a/PWA/src/App.tsx +++ b/PWA/src/App.tsx @@ -46,6 +46,29 @@ async function saveRemote(msgs: Message[]) { } catch { /* silent */ } } +async function setupPush() { + if (!('serviceWorker' in navigator) || !('PushManager' in window)) return + try { + const reg = await navigator.serviceWorker.ready + const existing = await reg.pushManager.getSubscription() + if (existing) return // already subscribed + + const res = await fetch('/push/vapid-public-key') + const { key } = await res.json() + + const sub = await reg.pushManager.subscribe({ + userVisibleOnly: true, + applicationServerKey: key, + }) + + await fetch('/push/subscribe', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(sub), + }) + } catch { /* silent — user may have denied */ } +} + export default function App() { const [messages, setMessages] = useState (loadLocal) const [loading, setLoading] = useState(false) @@ -59,14 +82,14 @@ export default function App() { setMessages(remote) nextId.current = Math.max(...remote.map(m => m.id)) + 1 } else { - const local = loadLocal() - if (local.length > 0) { - nextId.current = Math.max(...local.map(m => m.id)) + 1 - saveRemote(local) + if (messages.length > 0) { + nextId.current = Math.max(...messages.map(m => m.id)) + 1 + saveRemote(messages) } } setSynced(true) })() + setupPush() }, []) useEffect(() => { @@ -105,14 +128,9 @@ export default function App() { } } - const handleClear = () => { - setMessages([]) - localStorage.removeItem(STORAGE_KEY) - } - return ( -diff --git a/PWA/src/components/ChatArea.tsx b/PWA/src/components/ChatArea.tsx index a420dc4..67d7516 100644 --- a/PWA/src/components/ChatArea.tsx +++ b/PWA/src/components/ChatArea.tsx @@ -2,22 +2,24 @@ import { useRef, useEffect } from 'react' import type { Message } from '../App' export default function ChatArea({ messages }: { messages: Message[] }) { - const bottom = useRef- 沈晏 - {messages.length > 0 && ( - - )} - (null) + const container = useRef (null) useEffect(() => { - bottom.current?.scrollIntoView({ behavior: 'smooth' }) + if (container.current) { + container.current.scrollTop = container.current.scrollHeight + } }, [messages]) return ( - -++{messages.map((m) => () diff --git a/PWA/src/components/InputArea.tsx b/PWA/src/components/InputArea.tsx index aac5424..9ffaf10 100644 --- a/PWA/src/components/InputArea.tsx +++ b/PWA/src/components/InputArea.tsx @@ -12,11 +12,28 @@ export default function InputArea({ onSend, disabled }: { onSend: (text: string) return ())} - +diff --git a/PWA/src/index.css b/PWA/src/index.css index e4aee92..5351fda 100644 --- a/PWA/src/index.css +++ b/PWA/src/index.css @@ -1,18 +1,11 @@ @import "tailwindcss"; -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - html, body, #root { height: 100%; background: #000; font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "PingFang SC", sans-serif; -webkit-font-smoothing: antialiased; overflow: hidden; - user-select: none; } .no-scrollbar::-webkit-scrollbar { diff --git a/PWA/src/sw.ts b/PWA/src/sw.ts new file mode 100644 index 0000000..216a5b1 --- /dev/null +++ b/PWA/src/sw.ts @@ -0,0 +1,32 @@ +import { precacheAndRoute } from 'workbox-precaching' + +declare let self: ServiceWorkerGlobalScope + +precacheAndRoute(self.__WB_MANIFEST) + +self.addEventListener('push', (event) => { + let data: { title?: string; body?: string } = {} + try { data = event.data?.json() ?? {} } catch { data = { body: event.data?.text() ?? '' } } + event.waitUntil( + self.registration.showNotification(data.title ?? '沈晏', { + body: data.body ?? '', + icon: '/icon-192.png', + badge: '/icon-192.png', + vibrate: [200, 100, 200], + tag: 'shenyan-push', + renotify: true, + }) + ) +}) + +self.addEventListener('notificationclick', (event) => { + event.notification.close() + event.waitUntil( + self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then((list) => { + for (const client of list) { + if ('focus' in client) return client.focus() + } + return self.clients.openWindow('/') + }) + ) +}) diff --git a/PWA/tsconfig.json b/PWA/tsconfig.json index c0a7d4f..c84dd0b 100644 --- a/PWA/tsconfig.json +++ b/PWA/tsconfig.json @@ -13,5 +13,6 @@ "noEmit": true, "types": ["vite/client"] }, - "include": ["src"] + "include": ["src"], + "exclude": ["src/sw.ts"] } diff --git a/PWA/vite.config.ts b/PWA/vite.config.ts index 4aa90c5..bd4f623 100644 --- a/PWA/vite.config.ts +++ b/PWA/vite.config.ts @@ -3,10 +3,20 @@ import react from '@vitejs/plugin-react' import { VitePWA } from 'vite-plugin-pwa' export default defineConfig({ + server: { + proxy: { + '/api': 'http://localhost:3001', + '/memory': 'http://localhost:3001', + '/push': 'http://localhost:3001', + }, + }, plugins: [ react(), VitePWA({ registerType: 'autoUpdate', + strategies: 'injectManifest', + srcDir: 'src', + filename: 'sw.ts', manifest: { name: 'Elec', short_name: 'Elec', diff --git a/shenyan-app/.bundle/config b/shenyan-app/.bundle/config new file mode 100644 index 0000000..848943b --- /dev/null +++ b/shenyan-app/.bundle/config @@ -0,0 +1,2 @@ +BUNDLE_PATH: "vendor/bundle" +BUNDLE_FORCE_RUBY_PLATFORM: 1 diff --git a/shenyan-app/.eslintrc.js b/shenyan-app/.eslintrc.js new file mode 100644 index 0000000..187894b --- /dev/null +++ b/shenyan-app/.eslintrc.js @@ -0,0 +1,4 @@ +module.exports = { + root: true, + extends: '@react-native', +}; diff --git a/shenyan-app/.gitignore b/shenyan-app/.gitignore new file mode 100644 index 0000000..de99955 --- /dev/null +++ b/shenyan-app/.gitignore @@ -0,0 +1,75 @@ +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate +**/.xcode.env.local + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml +*.hprof +.cxx/ +*.keystore +!debug.keystore +.kotlin/ + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +**/fastlane/report.xml +**/fastlane/Preview.html +**/fastlane/screenshots +**/fastlane/test_output + +# Bundle artifact +*.jsbundle + +# Ruby / CocoaPods +**/Pods/ +/vendor/bundle/ + +# Temporary files created by Metro to check the health of the file watcher +.metro-health-check* + +# testing +/coverage + +# Yarn +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions diff --git a/shenyan-app/.prettierrc.js b/shenyan-app/.prettierrc.js new file mode 100644 index 0000000..06860c8 --- /dev/null +++ b/shenyan-app/.prettierrc.js @@ -0,0 +1,5 @@ +module.exports = { + arrowParens: 'avoid', + singleQuote: true, + trailingComma: 'all', +}; diff --git a/shenyan-app/.watchmanconfig b/shenyan-app/.watchmanconfig new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/shenyan-app/.watchmanconfig @@ -0,0 +1 @@ +{} diff --git a/shenyan-app/Gemfile b/shenyan-app/Gemfile new file mode 100644 index 0000000..5151523 --- /dev/null +++ b/shenyan-app/Gemfile @@ -0,0 +1,17 @@ +source 'https://rubygems.org' + +# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version +ruby ">= 2.6.10" + +# Exclude problematic versions of cocoapods and activesupport that causes build failures. +gem 'cocoapods', '>= 1.13', '!= 1.15.0', '!= 1.15.1' +gem 'activesupport', '>= 6.1.7.5', '!= 7.1.0' +gem 'xcodeproj', '< 1.26.0' +gem 'concurrent-ruby', '< 1.3.4' + +# Ruby 3.4.0 has removed some libraries from the standard library. +gem 'bigdecimal' +gem 'logger' +gem 'benchmark' +gem 'mutex_m' +gem 'nkf' diff --git a/shenyan-app/README.md b/shenyan-app/README.md new file mode 100644 index 0000000..3e2c3f8 --- /dev/null +++ b/shenyan-app/README.md @@ -0,0 +1,97 @@ +This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). + +# Getting Started + +> **Note**: Make sure you have completed the [Set Up Your Environment](https://reactnative.dev/docs/set-up-your-environment) guide before proceeding. + +## Step 1: Start Metro + +First, you will need to run **Metro**, the JavaScript build tool for React Native. + +To start the Metro dev server, run the following command from the root of your React Native project: + +```sh +# Using npm +npm start + +# OR using Yarn +yarn start +``` + +## Step 2: Build and run your app + +With Metro running, open a new terminal window/pane from the root of your React Native project, and use one of the following commands to build and run your Android or iOS app: + +### Android + +```sh +# Using npm +npm run android + +# OR using Yarn +yarn android +``` + +### iOS + +For iOS, remember to install CocoaPods dependencies (this only needs to be run on first clone or after updating native deps). + +The first time you create a new project, run the Ruby bundler to install CocoaPods itself: + +```sh +bundle install +``` + +Then, and every time you update your native dependencies, run: + +```sh +bundle exec pod install +``` + +For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html). + +```sh +# Using npm +npm run ios + +# OR using Yarn +yarn ios +``` + +If everything is set up correctly, you should see your new app running in the Android Emulator, iOS Simulator, or your connected device. + +This is one way to run your app — you can also build it directly from Android Studio or Xcode. + +## Step 3: Modify your app + +Now that you have successfully run the app, let's make changes! + +Open `App.tsx` in your text editor of choice and make some changes. When you save, your app will automatically update and reflect these changes — this is powered by [Fast Refresh](https://reactnative.dev/docs/fast-refresh). + +When you want to forcefully reload, for example to reset the state of your app, you can perform a full reload: + +- **Android**: Press the R key twice or select **"Reload"** from the **Dev Menu**, accessed via Ctrl + M (Windows/Linux) or Cmd ⌘ + M (macOS). +- **iOS**: Press R in iOS Simulator. + +## Congratulations! :tada: + +You've successfully run and modified your React Native App. :partying_face: + +### Now what? + +- If you want to add this new React Native code to an existing application, check out the [Integration guide](https://reactnative.dev/docs/integration-with-existing-apps). +- If you're curious to learn more about React Native, check out the [docs](https://reactnative.dev/docs/getting-started). + +# Troubleshooting + +If you're having issues getting the above steps to work, see the [Troubleshooting](https://reactnative.dev/docs/troubleshooting) page. + +# Learn More + +To learn more about React Native, take a look at the following resources: + +- [React Native Website](https://reactnative.dev) - learn more about React Native. +- [Getting Started](https://reactnative.dev/docs/environment-setup) - an **overview** of React Native and how setup your environment. +- [Learn the Basics](https://reactnative.dev/docs/getting-started) - a **guided tour** of the React Native **basics**. +- [Blog](https://reactnative.dev/blog) - read the latest official React Native **Blog** posts. +- [`@facebook/react-native`](https://github.com/facebook/react-native) - the Open Source; GitHub **repository** for React Native. diff --git a/shenyan-app/__tests__/App.test.tsx b/shenyan-app/__tests__/App.test.tsx new file mode 100644 index 0000000..e532f70 --- /dev/null +++ b/shenyan-app/__tests__/App.test.tsx @@ -0,0 +1,13 @@ +/** + * @format + */ + +import React from 'react'; +import ReactTestRenderer from 'react-test-renderer'; +import App from '../App'; + +test('renders correctly', async () => { + await ReactTestRenderer.act(() => { + ReactTestRenderer.create(+ -); + }); +}); diff --git a/shenyan-app/android/app/build.gradle b/shenyan-app/android/app/build.gradle new file mode 100644 index 0000000..9649f52 --- /dev/null +++ b/shenyan-app/android/app/build.gradle @@ -0,0 +1,119 @@ +apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" +apply plugin: "com.facebook.react" + +/** + * This is the configuration block to customize your React Native Android app. + * By default you don't need to apply any configuration, just uncomment the lines you need. + */ +react { + /* Folders */ + // The root of your project, i.e. where "package.json" lives. Default is '../..' + // root = file("../../") + // The folder where the react-native NPM package is. Default is ../../node_modules/react-native + // reactNativeDir = file("../../node_modules/react-native") + // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen + // codegenDir = file("../../node_modules/@react-native/codegen") + // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js + // cliFile = file("../../node_modules/react-native/cli.js") + + /* Variants */ + // The list of variants to that are debuggable. For those we're going to + // skip the bundling of the JS bundle and the assets. Default is "debug", "debugOptimized". + // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants. + // debuggableVariants = ["liteDebug", "liteDebugOptimized", "prodDebug", "prodDebugOptimized"] + + /* Bundling */ + // A list containing the node command and its flags. Default is just 'node'. + // nodeExecutableAndArgs = ["node"] + // + // The command to run when bundling. By default is 'bundle' + // bundleCommand = "ram-bundle" + // + // The path to the CLI configuration file. Default is empty. + // bundleConfig = file(../rn-cli.config.js) + // + // The name of the generated asset file containing your JS bundle + // bundleAssetName = "MyApplication.android.bundle" + // + // The entry file for bundle generation. Default is 'index.android.js' or 'index.js' + // entryFile = file("../js/MyApplication.android.js") + // + // A list of extra flags to pass to the 'bundle' commands. + // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle + // extraPackagerArgs = [] + + /* Hermes Commands */ + // The hermes compiler command to run. By default it is 'hermesc' + // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc" + // + // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map" + // hermesFlags = ["-O", "-output-source-map"] + + /* Autolinking */ + autolinkLibrariesWithApp() +} + +/** + * Set this to true to Run Proguard on Release builds to minify the Java bytecode. + */ +def enableProguardInReleaseBuilds = false + +/** + * The preferred build flavor of JavaScriptCore (JSC) + * + * For example, to use the international variant, you can use: + * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+` + * + * The international variant includes ICU i18n library and necessary data + * allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that + * give correct results when using with locales other than en-US. Note that + * this variant is about 6MiB larger per architecture than default. + */ +def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+' + +android { + ndkVersion rootProject.ext.ndkVersion + buildToolsVersion rootProject.ext.buildToolsVersion + compileSdk rootProject.ext.compileSdkVersion + + namespace "com.shenyanapp" + defaultConfig { + applicationId "com.shenyanapp" + minSdkVersion rootProject.ext.minSdkVersion + targetSdkVersion rootProject.ext.targetSdkVersion + versionCode 1 + versionName "1.0" + } + signingConfigs { + debug { + storeFile file('debug.keystore') + storePassword 'android' + keyAlias 'androiddebugkey' + keyPassword 'android' + } + } + buildTypes { + debug { + signingConfig signingConfigs.debug + } + release { + // Caution! In production, you need to generate your own keystore file. + // see https://reactnative.dev/docs/signed-apk-android. + signingConfig signingConfigs.debug + minifyEnabled enableProguardInReleaseBuilds + proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" + } + } +} + +dependencies { + // The version of react-native is set by the React Native Gradle Plugin + implementation("com.facebook.react:react-android") + + if (hermesEnabled.toBoolean()) { + implementation("com.facebook.react:hermes-android") + } else { + implementation jscFlavor + } +} diff --git a/shenyan-app/android/app/debug.keystore b/shenyan-app/android/app/debug.keystore new file mode 100644 index 0000000000000000000000000000000000000000..364e105ed39fbfd62001429a68140672b06ec0de GIT binary patch literal 2257 zcmchYXEfYt8;7T1^dLH$VOTZ%2NOdOH5j5LYLtZ0q7x-V8_6gU5)#7dkq{HTmsfNq zB3ZqcAxeY^G10@?efK?Q&)M(qInVv!xjx+IKEL}p*K@LYvIzo#AZG>st5|P) KF1_Z;y){W{<7K{nl!CPuE z_^(!C (Ol0n8 zK13*rzAtW>(wULKPRYLd7G18F8#1P`V*9`(Poj26eOXYyBVZPno~Cvvhx7vPjAuZo zF?VD!zB~QG(!zbw#qsxT8%BSpqMZ4f70ZPn-3y$L8{EVbbN9$H`B&Z1quk9tgp5FM zuxp3pJ0b8u|3+#5bkJ4SRnCF2l7#DyLYXYY8*?OuAwK4E6J{0N=O3QNVzQ$L#FKkR zi-c@&!nDvezOV$i$Lr}iF$XEcwnybQ6WZrMKuw8gCL^U#D;q3t&HpTbq yD %vG=TeDlzCT~MXUPC|Leb-Uk+ z=vnMd(|>ld?Fh>V8poP;q;;nc@en$|rnP0ytzD&fFkCeUE^kG9Kx4wUh!!rpjwKDP zyw_e|a ^x_w3E zP}}@$g>*LLJ4i0`Gx)qltL}@;mDv}D*xR^oeWcWdPkW@Uu)B^X&4W1$p6}ze!zudJ zyiLg@uggoMIArBr*27EZV7djDg@W1MaL+rcZ-lrANJQ%%>u8)ZMWU@R2qtnmG(acP z0d_^! t>}5W zpT`*2NR+0+SpTHb+6Js4b;%LJB;B_-ChhnU5py}iJtku*hm5F0!iql8Hrpcy1aYbT z1*dKC5ua6pMX@@iO NI?Hpr%h;&YaXp9n!ND7-=a%BD7v&g zOO41M6EbE24mJ#S$Ui0-b rR5M L%@|ndz^)YLMMV1atna{Fw<;TF@>d&F|!Z>8eg>>hkFrV)W+uv=`^F9^e zzzM2*oOjT9%gLoub %(R57p-`TXFe#oh1_{&N-YN z<}artH|m=d8TQuKSWE)Z%puU|g|^^NFwC#N=@dPhasyYjoy(fdEVfKR@cXK HZV-`06HsP`|Ftx;8 (YD$fFXumLWbGnu$GMqRncXYY9mwz9$ap zQtfZB^_BeNYITh^hA7+(XNFox5WMeG_LtJ%*Q}$8VKDI_p8^pqX)}NMb`0e|wgF7D zuQACY_Ua<1ri{;Jwt@_1sW9zzdgnyh_O#8y+C;LcZq6=4e^cs6KvmK@$vVpKFGbQ= z$)Eux5C|Fx;Gtmv9^#Y-g@7Rt7*eLp5n!gJmn7&B_L$G?NCN`AP>cXQEz}%F%K ;vUs{+l4Q{}eWW;ATe2 zqvXzxoIDy(u;F2q1JH7Sf;{jy_ j})F+cKlIOmNfjBGHoG^CN zM|Ho&&X|L-36f}Q-obEACz`sI%2f&k>z5c$2TyTSj~vmO)BW~+N^kt`Jt@R|s!){H ze1_eCrlNaPkJQhL$WG&iRvF*YG=gXd1IyYQ9ew|iYn7r~g!wOnw;@n42>enAxBv*A zEmV*N#sxdicyNM=A4|yaOC5MByts}s_Hpfj|y<6G=o=!3S@eIFKDdpR7|FY>L&Wat&oW&cm&X~ z5Bt>Fcq(fgnvlvLSYg&o6>&f Y`ODg4`V^lWWD=%oJ#Kbad2u~! zLECFS*??>|vDsNR&pH=Ze0Eo`sC_G`OjoEKVHY|wmwlX&(XBE<@sx3Hd^gt d-fNwUHsylg06p`U2y_={u}Bc + + + + + + diff --git a/shenyan-app/android/app/src/main/java/com/shenyanapp/MainActivity.kt b/shenyan-app/android/app/src/main/java/com/shenyanapp/MainActivity.kt new file mode 100644 index 0000000..d308e44 --- /dev/null +++ b/shenyan-app/android/app/src/main/java/com/shenyanapp/MainActivity.kt @@ -0,0 +1,22 @@ +package com.shenyanapp + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "ShenYanApp" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} diff --git a/shenyan-app/android/app/src/main/java/com/shenyanapp/MainApplication.kt b/shenyan-app/android/app/src/main/java/com/shenyanapp/MainApplication.kt new file mode 100644 index 0000000..8c346ef --- /dev/null +++ b/shenyan-app/android/app/src/main/java/com/shenyanapp/MainApplication.kt @@ -0,0 +1,27 @@ +package com.shenyanapp + +import android.app.Application +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost + +class MainApplication : Application(), ReactApplication { + + override val reactHost: ReactHost by lazy { + getDefaultReactHost( + context = applicationContext, + packageList = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + }, + ) + } + + override fun onCreate() { + super.onCreate() + loadReactNative(this) + } +} diff --git a/shenyan-app/android/app/src/main/res/drawable/rn_edit_text_material.xml b/shenyan-app/android/app/src/main/res/drawable/rn_edit_text_material.xml new file mode 100644 index 0000000..5c25e72 --- /dev/null +++ b/shenyan-app/android/app/src/main/res/drawable/rn_edit_text_material.xml @@ -0,0 +1,37 @@ + + ++ ++ ++ + + + diff --git a/shenyan-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/shenyan-app/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a2f5908281d070150700378b64a84c7db1f97aa1 GIT binary patch literal 3056 zcmV+ + + +- +
- +
(P) KhZB4W`O-$6PEY7dL@435|%iVhscI7#HXTET` zzkBaFzt27A{C?*?2n!1>p(V70me4Z57os7_P3wngt7(|N?Oyh#`(O{OZ1{A4;H+Oi zbkJV-pnX%EV7$w+V1moMaYCgzJI-a^GQPsJHL=>Zb!M$&E7r9HyP>8`*Pg_->7CeN zOX|dqbE6DBJL=}Mqt2*1e1I>(L-HP&UhjA?q1x7zSXD}D&D-Om%s C#AMr*KVk>dy;pT>Dpn#K6-YX8)fL(Q8(04+g?ah97XT2i$m2u z-*XXz7%$`O#x&6Oolq? +sA+c; zdg7fXirTU G`+!=-QudtfOZR*6Z3~!#;X;oEv56*- B z&gIGE3os@3O)sFP?zf;Z#kt18-o>IeueS!=#X^8WfI@&mfI@)!F(BkYxSfC*Gb*AM zau9@B_4f3=m1I71l8mRD>8A(lNb6V#dCpSKW%TT@VIMvFvz!K$oN1v#E@%Fp3O_sQ zmbSM-`}i8WCzSyPl?NqS^NqOYg4+tXT52ItLoTA;4mfx3-lev-HadLiA}!)%PwV)f zumi|*v}_P;*hk9-c*ibZqBd_ixhLQA+Xr>akm~QJCpfoT!u5JA_l@4qgMRf+Bi(Gh zBOtYM<*PnDOA}ls-7YrTVWimdA{y^37Q#BV>2 &NKUfl(9F9G}lZ{!-VfTnZh-}vANUA=kZz5}{^<2t=| z{D>%{4**GFekzA~Ja)m81w<3IaIXdft(FZDD2oTruW#SJ?{Iv&cKenn!x!z;LfueD zEgN@#Px>AgO$sc`OMv1T5S~rp@e3-U7LqvJvr%uyV7jUKDBZYor^n# zR8bDS*jTTdV4l8ug<>o_Wk~%F&~lzw`sQGMi5{!y oTBs|8;>L zD=nbWe5~W67Tx`B@_@apzLKH@q=Nnj$a1EoQ%5m|;3}WxR@U0q^=umZUcB}dz5n^8 zPRAi!1T)V8qs-eWs$?h4sVnc F`)j&1`Rr+-4of)XCppcuoV#0EZ8^>0Z2LYZirw#G7=POO0U*?2*&a7V zn|Dx3WhqT{6j8J_PmD=@ItKmb-GlN>yH5eJe%-WR0D8jh1;m54AEe#}goz`fh*C%j zA@%m2wr3qZET9NLoVZ5wfGuR*)rV2cmQPWftN8L9hzEHxlofT@rc|PhXZ&SGk>mLC z97(xCGaSV +)DeysP_%tl@Oe<6k9|^VIM*mQ(IU5vme)80qz-aOT3T(VOxU><7 R4#;RZfTQeI$^m&cw@}f=eBDYZ+b&N$LyX$Au8*J1b9WPC zk_wIhRHgu=f&&@Yxg-Xl1xEnl3xHOm1xE(NEy@oLx8xXme*uJ-7cg)a=lVq}gm3{! z0}fh^fyW*tAa%6Dcq0I5z(K2#0Ga*a*!mkF5#0&|BxSS`fXa(?^Be)lY0}Me1R$45 z6OI7HbFTOffV^;gfOt%b+SH$3e*q)_&;q0p$}uAcAiX>XkqU#c790SX&E2~lkOB_G zKJ`C9ki9?xz)+Cm2tYb{js(c8o9FleQsy}_Ad5d7F((TOP!GQbT (nFhx6IBlIHLQ zgXXeN84Yfl5^NsSQ!kRoGoVy hyQXsYTgXWy@*K>_h02S>)Io^59+E)h zGFV5n!hjqv%Oc>+V;J$A_ekQjz$f-;Uace07pQvY6}%aIZUZ}_m*>DHx|mL$gUlGo zpJtxJ-3l!SVB~J4l=zq>$T4VaQ7?R}!7V7tvO_bJ8`$|ImsvN@kpXGtISd6|N&r&B zkpY!Z%;q4z)rd81@12)8F>qUU_(dxjkWQYX4XAxEmH?G>4ruF!AX< 2qpdqxJ3I!SaZj(bdjDpXdS%NK!YvET$}#ao zW-QD5;qF}ZN4;`6g&z16w|Qd=`#4hg+U F^02UgmQka=%|A!5CjRL86{{mwzf=~v{&!Uo zYhJ00Shva@yJ59^Qq~$b)+5%gl79Qv*Gl#YS+BO+RQrr$dmQX)o6o-P_wHC$#H%aa z5o> q~f8c=-2(k3lb!CqFQJ;;7+2h#B$V_anm}>Zr(v{I_-09@zzZ yco6bG9zMVq_|y~s4rIt6QD_M*p(V5oh~@tmE4?#%!pj)|0000 T-ViIFIPY+_yk1-RB&z5bHD$YnPieqLK5EI`ThRCq%$YyeCI#k z>wI&j0Rb2DV5|p6T3Sy aq)GU^8BR8(!9qaEe6w+TJxLZtBeQf z`>{w%?oW}WhJSMi-;YIE3 P2FtzE8p;}`HCT>Lt1o3h65;M`4J@U(hJSYlTt_?Ucf5~AOFjBT-*WTiV_&id z?xIZPQ`>7M-B?*vptTsj)0XBk37V2zTSQ5&6`0#pVU4dg+Hj7pb;*Hq8nfP(P;0i% zZ7k>Q#cTGyguV?0<0^_L$;~g|Qqw58DUr~LB=oigZFOvHc|MCM(KB_4-l{U|t!kPu z{+2Mishq{vnwb2YD{vj{q`%Pz?~D4B&S9Jdt##WlwvtR2)d5RdqcIvrs!MY#BgDI# z+FHxTmgQp-UG66D4?!;I0$Csk<6&IL09jn+yWmHxUf)alPUi3jBIdLtG|Yhn?vga< zJQBnaQ=Z?I+FZj;ke@5f{TVVT$$CMK74HfIhE?eMQ#fvN2%FQ1PrC+PAcEu?B*`Ek zcMD{^pd?8HMV94_qC0g+B1Z0CE-pcWpK=hDdq`{6kCxxq^X`oAYOb3VU6%K=Tx;aG z*aW$1G~wsy!mL})tMisLXN<*g$Kv)zHl{2OA=?^BLb)Q^Vqgm?irrLM$ds;2n7gHt zCDfI8Y=i4)=cx_G!FU+g^_nE(Xu7tj&a&{ln46@U3)^aEf}FHHud~H%_0~Jv>X{Pm z+E&ljy!{$my1j|HYXdy;#&&l9YpovJ;5yoQYJ+hw9>!H{(^6+$(%!(HeR~&MP-UER zPR&hH$w*_)D3}#A2joDlamSP}n%Y3H@pNb1wE=G1TFH_~Lp-&?b+q%;2IF8njO(rq zQVx(bn#@hTaqZZ1V{T#&p)zL%!r8%|p|TJLgSztxmyQo|0P;eUU~a0y&4)u?eEeGZ z9M6iN2(zw9a(WoxvL%S*jx5!2$E`ACG}F|2_)U Tkqb*jyXm{3{73tLMlU%IiPK(UR4 }Uv87uZIacp(XTRUs?6D25qn)QV%Xe&LZ-4bUJM!ZXtnKhY#Ws)^axZkui_Z=7 zOlc@%Gj$nL ul=cEH-leGY`0T)`IQzNUSo}amQtL)O>v* zNJH1}B2znb; t8t f4-S6iL2_WuMVr~! zwa+Are(1_>{zqfTcoYN)lg$AVibhUwnFA33`np7$V)-5~MQcS~aE|Ha>IxGu+iU z`5{4rdTNR`nUc;CL5tfPI63~BlehRcnJ!4ecxOkD-b&G%-JG+r+}RH~wwPQoxuR(I z-89hLhH@)Hs}fNDM1>DUEO%{C;roF6#Q7w~76179D?Y9}nIJFZhWtv`=QNbzNiUmk zDSV5#xXQtc n9 zM{aI;AO6EH6GJ4^Qk!^F?$-lTQe+9ENYIeS9}cAj>Ir`dLe`4~Dulck 2#9{o}JJ8v+QRsAAp*}|A^ z1PxxbEKF xar-$a&mz95(E1mAEVp{l!eF9?^K43Ol`+3Xh5z`aC(r}oEBpJK~e>zRtQ4J3K*r1f79xFs>v z5yhl1PoYg~%s#*ga &W@K>*NW($n~au>D~{Rrf@Tg z^DN4&Bf0C`6J*kHg5nCZIsyU%2RaiZkklvEq TMo0tFeq7{pp8`8oAs7 z6~-A=MiytuV+rI2R*|N=%Y));j8>F)XBFn`Aua-)_GpV`#%pda&MxsalV15+%Oy#U zg!?Gu&m@yfCi8xHM>9*N8|p5TPNucv?3|1$aN$&X6&Ge#g}?H`)4ncN@1whNDHF7u z2vU *@9OcC-MZK}lJ-H5CC@og69P#Ielf`le^Om4BZ|}OK33~dC z9o-007j1SXiTo3P#6`YJ^T4tN;KHfgA=+Bc0h1?>NT@P?=}W;Z=U;!nqzTHQbbu37 zOawJK2$GYeHtTr7EIjL_BS8~lBKT^)+ba(OWBsQT=QR3Ka((u#*VvW=A35XWkJ#?R zpRksL`?_C~VJ9Vz?VlXr?cJgMlaJZX!yWW}pMZni(bBP>?f&c#+p2KwnKwy;D3V1{ zdcX-Pb`YfI=B5+oN?J5>?Ne>U!2oCNarQ&KW7D61$fu$`2FQEWo&*AF%68{fn%L<4 zOsDg%m|-bklj!%zjsYZr0y6BFY|dpfDvJ0R9Qkr&a*QG0F`u&Rh{8=gq(fuuAaWc8 zRmup;5 F zR3altfgBJbCrF7LP7t+8-2#HL9pn&HMVoEnPLE@KqNA~~s+Ze0ilWm}ucD8EVHs;p z@@l_VDhtt@6q zmV7pb1RO&XaRT)NOe-&7x7C>07@CZLYyn0GZl-MhPBNddM0N} 0jayB22swGh3C!m6~r;0uCdOJ6>+nYo*R9J7Pzo%#X_imc=P;u^O*#06g*l) ^?9O^cwu z>?m{qW(CawISAnzIf^A@vr*J$(bj4fMWG!DVMK9umxeS;rF)rOmvZY8%sF7i3NLrQ zCMI5u5>e<&Y4tpb@?!%PGzlgm_c^Z7Y6cO6C?)qfuF)!vOkifE(aGmXko*nI3Yr5_ zB%dP> Y)esVRQrVbP5?CtA V%1ftbeAX zSO5O8m|H+>?Ag7NFznXY-Y8iI#>Xdz<)ojC6nCuqwTY9Hlxg=lc7i-4fdWA$x8y)$ z1cEAfv{E7mnX=ZTvo30>Vc{EJ_@UqAo91Co;@r;u7&viaAa=(LUNnDMq#?t$WP2mu zy5`rr8b||Z0+BS)Iiwj0lqg10xE8QkK#>Cp6zNdxLb-wi+CW5b7zH2+M4p3Cj%WpQ zvV+J2IY@kOFU_|NN}2O}n#&F1oX*)lDd-WJICcPhckHVB{_D}UMo!YA)`reITkCv& z+h-AyO1k3@ZEIrpHB)j~Z(*sF@TFpx2IVtytZ1!gf7rg2x94b*P|1@%EFX{|BMC&F zgHR4<48Z5Wte`o!m*m@iyK=>9%pqjT=xfg Qua>)1| zzH!~jLG!rggat+qAIR%H=jrI#Ppid$J{TDkck^wb>Cbnli}}Mj8!tNfx{ tXtDDVA6#7kU4k)m;JoI1>JM_ zq-flQ5dpn>kG~=9u{Kp+hETG^OCq!Y^l7JkwUJNUU7izHmd|F@nB0=X2`Ui?!twzb zGEx%cIl)h?ZV$NTnhB6KFgkkRg&@c7ldg>o!`sBcgi%9RE?paz`QmZ@sF(jo1bt^} zOO5xhg(FXLQ|z)6 CE=`kWOCVJNJCs#Lx)8bD SWkN@122J_Z`gpPK4kwk4&%uxnuQ z^m`!#WD#Y$Wd7NSpiP4Y;lHtj;pJ#m@{GmdPp+;QnX&E&oUq!YlgQ%hIuM43b=cWO zKEo!Er{mwD8T1>Qs$i2Xj F2i zo0yfpKQUwdThrD(TOIY_s`L@_<}B|w^!j*FThM0+#t0G?oR`l(S(2v&bXR}F6HLMU zhVvD4K!6s}uUD^L;|Sxgrb+kFs%8d8Ma>5A9p~uUO=yF*;%~xvAJiA`lls1pq5J%k z6&-yQ$_vP5`-Tr56ws&75Y&Q2;zD?CB_KpRHxzC9hKCR0889>jef)|@@$A?!QIu3r qa)363hF;Bq?>HxvTY6qhhx>m(`%O(!)s{N|0000 xsEBz6iy~SX+W%nr KL2KH{`gFsDCOB6ZW0@Y j?g&st+$-t|2c4&NM7M5Tk(z5p1+IN@y}=N)4$Vmgo_?Y@Ck5u}3=}@K z);Ns<{X)3-we^O|gm)Oh1^>hg6g=|b7E-r?H6QeeKvv7{-kP9)eb76lZ>I5?WDjiX z7Qu}=I4t9`G435HO)Jp t^;4t zottB%?uUE#zt^RaO&$**I5GbJM-Nj&Z#XT#=iLsG7*JO@)I~kH1#tl@P}J@i#`XX! zEUc>l4^`@w2_Fsoa*|Guk5hF2XJq0TQ{QXsjnJ)~K{EG*sHQW(a<^vuQkM07vtNw= z{=^9J-YI<#TM>DTE6u^^Z5vsVZx{Lxr@$j8f2PsXr^)~M9 7)OdjJOe81=H#lTbl`!5}35~o;+uSbUH P+6L00V99ox@t5JT2~=-{-Zvti4(UkQKDs{%?4V4AV3L`G476;|CgCH%rI z;0kA=z$nkcwu1-wIX=yE5wwUO)D;dT0m~o7z(f`*<1B>zJhsG0hYGMgQ0h>ylQYP; zbY|ogjI;7_P6BwI^6ZstC}cL&6%I8~cYe1LP)2R}amKG>qavWEwL0HNzwt@3hu-i0 z>tX 4$uXN RX_<>h#Q`kvWAs3Y+9)i~VyAb3%4t+;Ej~o)%J#d6}9XXtC10QpHH*X!(vYjmZ zlmm6A=sN)+ Lnfb)wzL90u6B=liNgkPm2tWfvU)a0y=N2gqg_uRzguCqXO<0 zp@5n^hzkW& E&~|Znl PAz)<%Cdh;IgaTGMjVcP{dLFnX>K+DJ zd?m)lN&&u@soMY!B-jeeZNHfQIu7I&9N?AgMkXKxIC+JQibV=}9;p)91_6sP0x=oO zd9T#KhN 9M8uO4rCDa ze;J+@sfk?@C6ke`KmkokKLLvbpNHGP^1^^YoBV^rxnXe8nl%NfKS}ea`^9weO&eZ` zo3Nb?%LfcmGM4c%PpK;~v#XWF+!|RaTd$6126a6)WGQPmv0E@fm9;I@#QpU0rcGEJ zNS_DL26^sx!>ccJF}F){`A0VIvLan^$?MI%g|@ebIFlrG&W$4|8=~H%Xsb{gawm(u zEgD&|uQgc{a;4k6J|qjRZzat^hbRSXZwu7(c-+?ku6G1X0c*0%*CyUsXxlKf=%wfS z7A!7+`^?MrPvs?yo31D=ZCu!3UU`+dR^S>@R%-y+!b$RlnflhseNn10MV5M=0KfZ+ zl9DEH0jK5}{VOgmzKClJ7?+=AED&7I=*K$;ONIUM3nyT|P}|NXn@Qhn<7H$I*mKw1 axPAxe%7rDusX+w*0000 6jj zwslyNbxW4-gAj ;v!J{u#G1>?8h`uw{1?o<0nB+tYjKOW@kQM}bUbgE7^CRD4K zgurXDRXWsX-Q$uVZ0o5KpKdOl5?!YGV|1Cict&~YiG*r%TU43m2Hf99&})mPEvepe z0_$L1e8*kL@h2~YPCajw6Kkw%Bh1Pp)6B|t06|1rR3xRYjBxjSEUmZk@7wX+2&-~! z!V&EdUw!o7hqZI=T4a)^N1D|a=2scW6oZU|Q=}_)gz4pu#43{muRW1cW2WC&m-ik? zskL0dHaVZ5X4PN*v4ZEAB9m;^6r-#eJH?TnU#SN&MO`Aj%)ybFYE+Pf8Vg^T3ybTl zu50EU=3Q60vA7xg@YQ$UKD-7(jf%}8gWS$_9%)wD 1O2xB!_VxzcJdN!_qQ9j8#o^Kb$2+XTKxM8p>Ve{O8LcI(e2O zeg{tPSvIFaM+_Ivk&^FEk!WiV^;s?v8fmLglKG<7EO3ezShZ_0J-`(fM;C#i5~B@w zzx;4Hu{-SKq1{ftxbjc(dX3rj46zWzu02-kR>tAoFYDaylWMJ`>FO2QR%cfi+*^9A z54;@nFhVJEQ{88Q7n&mUvLn33icX`a355bQ=TDRS4 Uud|cnpZ?a5X|cXgeBhYN7btgj zfrwP+iKdz4?L7PUDFA_HqCI~GMy`trF@g!KZ#+y6U%p5#-nm5{bUh>vhr ^77p~ zq~UTK6@uhDVAQcL4g#8p-`vS4CnD9M_USvfi(M-;7nXjlk)~pr>zOI` {;$VXt;?VTNcCePv4 zgZm`^)VCx8{D =H2c!%Y*Sj3qbx z3Bcvv7qRAl|BGZCts{+>FZrE;#w(Yo2z D#>s3a*Bm!6 {}vF_;i)6sl_+)pUj?b%BL!T1ELx|Q*Gi=7{Z_>n0I(uv>N^kh|~nJfab z-B6Q6i-x>YYa_42Hv&m>NNuPj31wOaHZ2`_8f~BtbXc@`9CZpHzaE@9sme%_D-HH! z_+C&VZ5tjE65?}X&u-D4AHRJ|7M{hR!}PYPpANP?7wnur`Z(&LFwzUmDz}m6%m#_` zN1ihq8f|zZ&zTL92M2b-hMpPyjp;j(qwgP9x)qI?EZx@<$g#>i7(MC}@*J1VGXm6J z
tz1=RK@?%Qz^vmWNydd0K7oyrXw`TLb`z;fP6eV|NZ@9kKH zIyMqzZ9Y_)PZnC#UgW6&o7RiGXSCtSQvnrvJ07P9WCuE5TE27za*L6r1qX7pIDFiP znSaHYJF8sl^n0|3j!i{?fD%?fpQ8-}VX4%STy1t@8)G-8??Fy}j}~2_iJ79Y<9BW~ z!~)T{3Y|lwcVD5s4z^GP5M=~t`V?*W ng7gTvC9%p>ErZpM)pQVx 57>AIcf1j4QFg^w>YYB%MypIj2syoXw9$K!N8%s=iPIw!LE-+6v6*Rm zvCqdN&kwI+@pEX0FTb&P)ujD9Td-sLBVV=A$;?RiFOROnT^LC^+P ZR*u<3yl z7b%>viF-e48L=c`4Yhgb^U=+w7snP$R-gzx379%& q-0#fsMgvQlo>14~`1YOv{?^ z*^VYyiSJO8fE65P0FORgqSz#mi#9@40VO@TaPOT7pJq3WTK9*n;Niogu+4zte1FUa zyN7rIFbaQxeK{^RC3Iu@_J~ii&CvyWn^W}4wpexHwV9>GKO$zR3a&*L9&AgL=QfA$ z+G-YMq;1D{;N38`jTdN}Pw77sDCR|$2s+->;9 gh-ObE_muwxq> sEpX)ywtgCHKIATY}p&%F4bRV>R9rYpeWbT(xnE7}?(HDXFgNDdC^@gUdK& zk=MolYT3>rpR*$Ell 2!`c zjrIZftl&PUxlH2EgV+3VfQy&FjhL&5*Zg&R8xrSx?WgB?YuLO-JDaP3jr*I~qiywy z`-52A wB_6L#X ztms{{yRkRfQLbsb#Ov%`)acN(OCewI3Ex__xed17hg#g4c1blx?sK}UQg%PM@N;5d zsg{y6(|`H1Xfbz@5x{1688tu7TGkzFEBhOPDdFK(H_NQIFf|(>)ltFd!WdnkrY&mp z0y@5yU2;u1_enx%+U9tyY-LNWrd 4^Wi?x<^r`QbaLBngWL`HzX@G550 zrdyNjhPTknrrJn#jT0WD0 Z)WJRi&3FKJ#Sa&|883%QxM-?S %4niK{~k81<(c11sLk|!_7%s zH>c$`*nP-wA8Dx-K(HE~JG_@Yxxa;J+2yr+*iVlh;2Eiw?e`D1vu6*qY1+XTe8RVu z?RV%L|Mk!wO}j^S)p4H%?G37StD0Rx{_Y00%3a+V^SyOkfV@ZuFlEc;v R9r-D>cYU&plUkXL|M%1AYBQ3DI;; hF%_X@m*cT QAMZ4+FO74@AQB{A*_HtoXT@}l=8awaa7{RHC>07s?E%G{iSeRbh z?h#NM)bP`z`zdp5lij!N*df;4+sgz&U_JEr?N9#1{+UG3^11oQUOvU4W%tD1Cie3; z4zcz0SIrK-PG0(mp9gTYr(4ngx; ieH{NLq{* z;Pd=vS6KZYPV?DLbo^)~2dTpiKVBOh?|v2XNA)li)4V6B6PA!iq#XV5eO{{vL%OmU z0z3ZE2kcEkZ`kK(g^#s)#Zn5zw!R93cW^4+g0D=ydf&j4o_ti<@2WbzC>{(QhCL z(=%Zb;Ax8U=sdec9pkk|cW)1Ko;gK{-575HsDZ!w@WOQ^Up)GGorc38cGxe<$8O!6 zmQ`=@;TG{FjWq(s 0eBn5I~vVgoE}un8+#YuR$Asq?lobvVAO-`SBs3!&;QEKT>gZ0T)jG^Foo~J2YkV&mi-axlvC}-(J4S2 z;opuO)+FIV#}&4;wwisb>{XU+FJ~tyK7UaG@ZD^C1^brazu7Xkh5Od}&P)GufW=u# zMxOwfWJ3a^MZha>9OmQ)@!Y;v*4@+dg~s~NQ;q@hV~l>lw`P)d`4XF9rE?aEFe(JV zI>11}Ny%^CkO=VN>wCV?P!-?VdT3vWe4zBLV*?6XPqsC%n93bQXvydh0Mo+tXHO4^ zxQ{x0?CG{fmToCyYny7>*-tNh;Sh9=THLzkS~lBiV9)IKa^C~_p8MVZWAUb)Btjt< zVZ;l7?_KnLHelj>)M1|Q_%pk5b?Bod_&86o-#36xIEag%b+8 JqlDy@B^*YS*1; zGYT`@5nPgt)S^6Ap@b160C4d9do0iE;wYdn_Tr(vY{MS!ja!t*Z7G=Vz-=j5Z⁣ zwiG+x#%j}{0gU~J8;<|!B1@-XaB@{KORFwrYg_8rOv({b0EO#DbeQRm;B6_9=mXGf z-x|VL{zd`)#@yN}HkCSJbjbNlE|zL3Wm9Q8HY`sV)}3%pgN>cL^67{Z;PPL(*wT8N zUjXU{@|*hvm}({wsAC=x0^ok0%UAz0;sogW{B!nDqk|JJ5x~4NfTDgP49^zeu` csl?5mY@JdQdISc zFs!E{^grmkLnUk9 zny~m)1vws@5BFI<-0Tuo2JWX(0v`W|t(wg;s--L47WTvTMz-8l#TL^=OJNRS2?_Qj z3AKT+gvbyBi#H*-tJ%tWD|>EV3wy|8qxfzS!5RW;Jpl5*zo&^UBU=fG#2}UvRyNkK zA06Dy9;K1ca@r2T>yThYgI!ont$(G{6q#2QT +00r_x0(b)gsE`lBB?2gr55gq^D3Fi&p%E(p9>U %bv z kg1Jco(RbyTX7FDHOnl7-O@ zI$AaIl?9NJKPm(WiBP`1-#CB1QzU>&hKm)fpa5DKE{2$X0hGz-0uZ?cyTk(YC!Y&| zL=1VrNERSA5NA2jq7FACfX4JfPyj5XXl1yv0>~s;eF7L2$>&oMqeTFT2m$y7FlkON z_yurD1yIOvA;5C6016pyxBznGUt0kJ&k5r#;&>Jow`r)sp9R~PmK~lz$3xH%LT*1U zJdOyABZ3!FvNoR*vN$5ykHS8f`jA4zV+|L}i1C4` B2c{R0;UdYxaU|H)2avz@ z=mEYc|2S<+(B2Tj+FkX+2D+yFI!k9lWMA61DJ{)e;lum$(;O87?vGJJe!KtK04+N_ zI*P~t@dUb>9Xh{dbyl{-ZQ(UMgz7$|QfL5XSPkskt^NgctYC#;4WcZB1@%@wy@2t3 z2z0DI7&%b$*Aw~abe?GxE`ez@+6hOh-6*8fHRV{1os$EL@}uUZeG4h1&Be`98q*7j z=3-v+lhIjfWVo12!<>%V^a6lTgW3+_#W6n|p*~==zOH7z$0{LSZk(Tpd7EaD04hnA zL;#fxS0aD{`5^&D`}>0Uq?byDD-l2=!wm_bLcUl4gc(% za1p|itVANvFF>hghAS07Im1;IK;|b*W)}VDyI;BIp2=K*yu2a)j?B|f<44NI$NbmJ z#dE0>jI$fMr&@>4kN8MLFb4&2O9fEKaQg%(QO$4_1rVQywG^CmBLh#}_7gKW3vd?| z2?1^&KWq8}8I^_S0|)MowU_pw$q@nl@Nkn$z>BQq_KA^9 yaR`(R3u{{Ig;cwt z@AJ^{ODQCm^neroM9nKNUAXi9RCK`OsP_LuR0PUR(YZ CCX5dNF6VzcoK&=b^r`W?ltt|*F zpkoae%ZT{C1h~EcFui~b7fF`vb<<~j_VquuUA$}QqIKYELPp#;{u?q8Dz}WAG-(3; zjrm$i%7UbyZMM(Y{>!uJ#vNB?R~B{6Htp=>e*<{fQQ5W7V(1coCWlOON!MzZxhum| ztZBQ pGR z;~#ur^&PockKdV{Q6R>o`Pl{0x!DEbpZ7y9Y;*ZvE!*gU`V1W3znva{f=?WO5I&>B z&hw6}tjECtaghm5z|C# %M;Yf_*pI^} ;h}Vl=^r9EN=tVDj86D;C$jIJ?K7VP+00000NkvXXu0mjf D5i!M* literal 0 HcmV?d00001 diff --git a/shenyan-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/shenyan-app/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png new file mode 100644 index 0000000000000000000000000000000000000000..459ca609d3ae0d3943ab44cdc27feef9256dc6d7 GIT binary patch literal 7098 zcmV;r8%5-aP) U(QdAI7f)tS=AhH53iU?Q%B}x&gA$2B`o|*LCD1jhW zSQpS0{*?u3iXtkY?&2<)$@#zc%$?qDlF1T~d7k&lWaiv^&wbx>zVm(GIrof<%iY)A zm%|rhEg~Z$Te<*wd9Cb1SB{RkOI$-=MBtc%k*xtvYC~Uito}R@3fRUqJvco z|Bt2r9pSOcJocAEd)UN^Tz -8 2GUZlqsU;wb|2Q_1!4Rms&HO1Xyquft~#6lJoR z`$|}VSy@{k6U652FJ~bnD9(X%>CS6Wp6U>sn;f}te}%WL`rg)qE4Q=4OOhk^@ykw( ziKr^LHnAd4M?#&SQhw8zaC0 5q#Mc66K^mxY!dZ=W+#Bq1B}cQ6Y8FWd(n>#%{8Di_8$CHibtvP z-x#-g;~Q?y0vJA*8TW>ZxF?fAy1DuFy7%O1ylLF(t=ah7LjZ$=p!;8 (ZLjXAhwEkCR{wF`L=hwm>|vLK2=gR&KM1ZEG9R~53yNCZdabQoQ%VsolX zS#WlesPcpJ)7XLo6>Ly$im38oxyiizP&&>***e@KqUk3q3y+LQN^-v?ZmO>9O{Oq@ z{{He$*Z=Kf_FPR>El3iB*FULYFMnLa#Fl^l&|bFg$Omlh{xVVJ7uHm=4WE6)NflH6 z=>z4w{GV&8#MNnEY3*B7pXU!$9v-tZvdjO}9O=9r{3Wxq2QB}(n%%YI$)pS~NEd}U z)n#nv-V)K}kz9M0$hogDLsa<(OS0Hf5^WUKO-%WbR1W1ID$NpAegxHH;em?U$Eyn1 zU{&J2@WqSUn0tav=jR&&taR9XbV+Izb*PwFn|?cv0mksBdOWeGxNb~oR;`~>#w3bp zrOrEQ+BiW_*f&GARyW|nE}~oh0R>>AOH^>NHNKe%%sXLgWRu1Sy3yW0Q#L{8Y6=3d zKd=By=Nb8?#W6|LrpZm>8R o)`@cLmU;D`d64nKT~6Z!aLOS{m`@oYwD`9yily@}%yr0A>P!6O4 G|ImNb BzI`LJ0@=TfLt^f`M07vw_PvXvN{nx%4 zD8vS>8*2N}`lD>M{`v?2!nYnf%+`GRK3`_i+yq#1a1Yx~_1o~-$2@{=r~q11r0oR* zqBhFFVZFx!U0!2CcItqLs)C;|hZ|9zt3k^(2g32!KB-|(RhKbq-vh|uT>jT@tX8dN zH`TT5iytrZT#&8u=9qt=oV`NjC)2gWl%KJ;n63WwAe%-)iz&bK{k`lTSAP`hr)H $Q`Yq8-A4PBBuP*-G#hSKrnmduy6}G zrc+mcVrrxM0WZ__Y#*1$mVa2y=2I`TQ%3Vhk&=y!-?<4~iq8`XxeRG!q?@l&cG8;X zQ(qH=@6{T$$qk~l?Z0@I4HGeTG?fWL67KN#-&&CWpW0fUm}{sBGUm)Xe#=*#W{h_i zohQ=S{=n3jDc1b{h6oTy=gI!(N%ni~O$!nBUig}9u1b^uI8SJ9GS7 L#s!j;Xy*CO>N(o6z){ND5WTew%1lr? znp&*SAdJb5{L}y7q#NHbY;N_1vn-2cjb!T|MdKai%(Tg1!Ik1$Oj@@7al;uCRZS ztp@NOpB?=6Jj?v*OZLuRKjd=`L+F~;dd+YW>!a^3TGRzCKjw?i_%$0d2%AR73CwHf z`h4QFmE-7G=psYnw)B!_Cw^{=!UNZeR{(s47|V$ `3;-*gneX=;O+eN@+Efd_Zt=@H3T@v&o^%H z7QgDF8g>X~$4t 9pv35G{a_8Io>#>uGRHV{2PSk#Ea~^V8!n@9C)ZH#87~ z#{~PUaRR~4K*m4*PI16)rvzdaP|7sE8SyMQYI6!t(%JNebR%?lc$={$s?VBI0Qk!A zvrE4|#asTZA|5tB{>!7BcxOezR?QIo4U_LU?&9Im-liGSc|TrJ>;1=;W?gG)0pQaw z|6o7&I&PH!*Z=c7pNPkp)1(4W`9Z01*QKv44FkvF^2Kdz3gDNpV=A6R;Q}~V-_sZY zB9DB)F8%iFEjK?Gf4$Cwu_hA$98&pkrJM!7{l+}osR_aU2PEx!1CRCKsS`0v$LlKq z{Pg#ZeoBMv@6BcmK$-*|S9nv50or*2&EV`L7PfW$2J7R1!9Q(1SSe42eSWZ5sYU?g z2v{_QB^^jfh$)L?+|M`u-E7D=Hb?7@9O89!bRUSI7uD?Mxh63j5!4e(v)Kc&TUEqy z8;f`#(hwrIeW);FA0CK%YHz6;(WfJz^<&W#y0N3O2&Qh_yxHu?*8z1y9Ua}rECL!5 z7L1AEXx83h^}+)cY*Ko{`^0g3GtTuMP>b$kq;Aqo+2 d&+48mc#DP;Sv z*UL^nR* K7J968xR0_eTaZ`N`u_c#9bFUjTj-}0+_57(gtEJT|7PA12W=2Z>#_a z&Wg@_b=$d~wonN3h~?)gS`qxx<4J&`dI*rH9!mTSiQj(0rF-{YoNJRnOqd5IbP7p} ztDaPu$A;#osxf=z2zVe4>tpa(knS_Mp67nKcE<>Cj$G2orP(Z$Oc4;4DPwbXYZsS^ z;b>59s(LgYmx|tkRD?U{+9VZ$T}{S}L6>lQNR^a|&5joAFXtOrI07Do!vk(e$mu@Y zNdN!djB`Hq1*T8mrC@S)MLwZ`&8aM8YYtVj7i)IY{g&D1sJaY`3e=1DSFnjO+jEHH zj+|@r$$4RtpuJ!8=C`n5X;5BjU2slP9VV&m0gr+{O(I}9pYF32AMU?n$k$=x;X^E# zOb-x}p1_`@IOXAj3>HFxnmvBV9M^^9CfD7UlfuH*y^aOD?X6D82p_r*c>DF)m=9>o zgv_SDeSF6WkoVOI<_mX};FlW9rk3WgQP|vr-eVo8!wH!TiX)aiw+I|dBWJX=H6zxx z_tSI2$ChOM+?XlJwEz3!juYU6Z_b+vP-Y|m1!|ahw>Kpjrii-M_wmO@f@7;aK(I;p zqWgn+X^onc-*f)V9Vfu?AHLHHK!p2|M`R&@4H0x4hD5#l1##Plb8KsgqGZ{`d+1Ns zQ7N(V#t49wYIm9drzw`;WSa|+W+VW8Zbbx*Z+aXHSoa!c!@3F_yVww58NPH2->~Ls z2++`lSrKF(r BZLZ5_ts6_LbZG-W-3fDq^qI>|rzbc@21?)H>!?7O*!D?dKlL z6J@yulp7;Yk6Bdytq*J1JaR1!pXZz4aXQ{qfLu0;TyPWebr3|*EzCk5%ImpjUI4cP z7A$bJvo4(n2km-2JTfRKBjI9$mnJG@)LjjE9dnG&O=S;fC)@nq9K&e UHAL%yAPX7OFuD$pb_H9nhd{iE0OiI4#F-);A|&YT z|A3tvFLfR`5NYUkE?Rfr&PyUeFX-VHzcss2i*w06vn4{k1R%1_1+Ygx2oFt*HwfT> zd=PFdfFtrP1+YRs0AVr{YVp4Bnw2HQX-|P$M^9&P7pY6XSC-8;O2Ia4c{=t{NRD=z z0DeYUO 3n;p%k zNEmBntbNac&5o#&fkY1QSYA4tKqBb=w~c6yktzjyk_Po)A|?nn8>HdA31amaOf7jX z2qillM8t8V#qv5>19Cg_X`mlU*O5|C#X-kfAXAHAD*q%6+z%IK(*H6olm-N4%Ic)5 zL`?wQgXfD&qQRxWskoO^Ylb>`jelq;*~ZIwKw|#BQjOSLkgc2uy7|oFEVhC?pcnU+ z^7qz}Z2%F!WOp%JO 3y*&_7t;uRfU>)drR1q)c7lX?;A1-TuLTR zyr(`7O19`eW{ev;L%`;BvOzh?m|)Rh?W8&I $KVvUTo?@f@K!du&vf=o6kKb?hA z%e6$T0jWS7doVkN%^_k3QOksfV?aC$Ge$a)z(!C@UVs*@qzDw*OFd*JfX#>5LCXjE z_vfUrLF7D`K$U2Ld#OCnh9U!;r7%GlKo$e__Il-oba06ER{H&f#J&W@x^^5j;y$0` zs2`m6pf+{UiDb{Mjsb$rH+MCM6G_wX92so96`ODFYKD>!Xz^0y@U7T c1uON4L<>2f-oPe%FRPEZ@S#-yd7Md-i?v z)$Kgtq;%4g@>Kap3Nl2I&jnCIfGmRmcF4CXfF1H}3SfhLg8=!a0ucGaUk&c3*Ykgl z2X_L84cs+FD#cjf-nMJkVDH%XzOoh 5!X-Q$K5VZx-hGF7MQ=XKBjhZZQ@1Sh zO^vY`WQ`zi21z-+01na%<^niMFIWm-n|!?hm4X2HEHkba4YS|+HRoIR=`#Xck@ PFXaPjnP z=hC4A*0lumS+gpK=TUN!G;{WqICbMz-V=-lTP^@a#C|E!qH;T00SZh7u#?+?08g0< zV1s %-U-`T@8wGh!3pO^`zUIY{nAED7kBqg!qi&GfOp>57f2PGTV19m z0qU@1PYkf%4z_%;Sq4IY94rS+ie~pw T@O3+tg?#k_=5PIk6tV@< zwLoqM0wBVLkI#`|1w=eYMnc^aRR!t?lnUng>WekR#X!!9mYXL3g^gC7`)S7mmo{y} z9*N!d$s32Nu{cZp#O|UxEZK7eY<7hGcI=lc; HrSVL|HA|S$rhhu_DBT&l+`75d`Sj3LaM~H)P zZuk2&jor6yipafklSsPL-vMo?0yAYXpH3=LveBhkno-3{4VLWL16I-@!RM$Po>&}} zm&PX3-$i>$*yx-THZmvK2q`8Qm7B`(NMR;>VSgoGw}W|G6Xd6v04Zf;HIZ0DZU?@- z39vPe0N8w(9kl$2?eG4T?tLgY5V&aFl%~g;2)aSpi!dl?{hDgsz|3<-M(gPtwP_!n z2aB4tV?d0k+>X`+(HMYfK@qtfDK|mIJeg+A<_i-n+5wkrexFs#V0N&~+{ +qJ(wggC*52o2daaRwcu7r;S!!KwguB3!Ei7?IEY ze4V$m{8 B4Q^(VK4~Ea!V@@}Gs0HGbR5 zy~WI*21hZuoiK`=O$2a|Uce-Zi2%A*pB|?{gv)n8+_B+i&u8Ys)ePY+UwhBDlzbC& z +N00*-?a8DTC26*(3pKgeMO`fOau^-+c6Qqq}3-dpTsEEH}ds! zT^}8XAWO>c5%+qF%#M8#x_0gC+N%q8h6-%w;qidS%gai< T)vpfYuCHX Rx6O-TbC|fnj87X zBESvn(9XlXFMj6%{&BaNQ&;xixaKP)+jJ|%u&?HXvYficY}{%hf?0rNDS-X-0_Jcr zjfj~n?T;~RL#sd4ZED2Jf{*Vj+*1eP9-H+~8X^#Jb?HHabLY )EH{QD@Yh-$M`XXt@3_f-L8nBo~*C?L4~n6M92PCuzX=KFgM*j!B66er$F! z+*M(Wkk`UI@uhrL#IUz-C{K@@xtd&n-PQz%kc}7YeE{{&$?}-*y W$eG*E4jp>B_U!2`2oZuvvitN& z%RN>tE$+Yhtqb1q+xQHbp=W4uKSiIj_LZppR0=hEiVj>P0^Vcr^hu2+#Hqum+}zzo znqZ|M4oD|qd=y&JX-qob`=uqt?o%FJPIVY2w0M7BH>#sx>s#OM#9JF1(3LxMAe-vi ztJeU*G)aksP`5sP9_%|~>Pp{NmMMcay>&D+cI%H}$uSx{Su(yz$)2e$*pS%*+!Zo>DNp(P7 zI%w^D2ceEFUGCtQPKfsKr`x%^dy;Rh>lMKuhA^btz=071W=vV`_xz&m;cvd0`|!3+ z2M6uga6CNvy)%Pjw_X}5+xf###jc+?=>6chZI{BMH=haH^7ipT>(?9{weF3apk<4; z_nZFsi`@oFBXCZE^k9B1x+cH2)~9d(M nfEm;GJxG*IB zU@ly{cOTWk*K1ryX+T7m!6A >VwB-*qfH;b>`AUP19lLSA9HbfppW!={L0K)??SymOCA^V>=tOBLn2c5e ksm9QK-qMKdW>5J419kFO%DdQj-T(jq07*qoM6N<$f+5oB`~Uy| literal 0 HcmV?d00001 diff --git a/shenyan-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/shenyan-app/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca12fe024be86e868d14e91120a6902f8e88ac6 GIT binary patch literal 6464 zcma)BcR1WZxBl%e)~? {d=GL+&^aKnR?F5^S) H60AiZ4#Zw z<{%@_?XtN*4^Ysr4x}4T^65=zoh0oG>c$Zd1_pX6`i0v}uO|-e B%Q>N^ZQBm?tGlYwAcTcjWKhWpN*8Y^z}bpUe!vvcHEUBJgNGK%eQ7S zhw2AoGgwo(_hfBFVRxjN`6%=xzloqs)mKWPrm-faQ&tk^eX$WPcm-MNC>-{;_L% z0Jg#L7aw?C*LB0?_s+&330gN5n#G}+dQKW6E7x7oah`krn8p` }BEYImc@?)2KR>sX{@J2`9_`;EMqVM;E7 zM^Nq2M2@Ar`m389gX&t}L90)~SGI8us3tMfYX5};G>SN0A%5fOQLG#PPFJYkJHb 1AEB+-$fL!Bd}q*2UB9O6tebS&4I)AHoUFS6a0* zc!_!c#7&?E>%TorPH_y|o9nwb*llir-x$3!^g6R>>Q>K7ACvf%;U 5oX>e#-@UpPw1ttpskGPCiy-8# z 9;&H8tgekn Vpz>p*#TzNZQ1iL9rQenM3(5?rr(4U^UU z#ZlsmgBM9j5@V-B83P3|EhsyhgQ77 EsG%NO5A6iB2H; zZ1qN35-DS^?&>n1IF?bU|LVIJ-)a3%TDI*m*gM