From bc9c20c5096e4f4a1eaadd3d765ffa265b71d45f Mon Sep 17 00:00:00 2001 From: bggRGjQaUbCoE Date: Mon, 14 Apr 2025 22:57:13 +0800 Subject: [PATCH] feat: search trending page Closes #684 Signed-off-by: bggRGjQaUbCoE --- assets/images/live/live_@28h.gif | Bin 0 -> 24593 bytes lib/http/api.dart | 2 + lib/http/search.dart | 16 ++ .../search_trending/search_trending.dart | 28 +++ .../search/search_trending/stat_datas.dart | 14 ++ .../search/search_trending/top_list.dart | 95 ++++++++ .../search/search_trending/trending_data.dart | 28 +++ .../search/search_trending/trending_list.dart | 47 ++++ lib/pages/search/view.dart | 8 +- lib/pages/search_result/view.dart | 2 +- lib/pages/search_trending/controller.dart | 27 +++ lib/pages/search_trending/view.dart | 207 ++++++++++++++++++ lib/pages/webview/webview_page.dart | 37 ---- lib/router/app_pages.dart | 3 + 14 files changed, 469 insertions(+), 45 deletions(-) create mode 100644 assets/images/live/live_@28h.gif create mode 100644 lib/models/search/search_trending/search_trending.dart create mode 100644 lib/models/search/search_trending/stat_datas.dart create mode 100644 lib/models/search/search_trending/top_list.dart create mode 100644 lib/models/search/search_trending/trending_data.dart create mode 100644 lib/models/search/search_trending/trending_list.dart create mode 100644 lib/pages/search_trending/controller.dart create mode 100644 lib/pages/search_trending/view.dart diff --git a/assets/images/live/live_@28h.gif b/assets/images/live/live_@28h.gif new file mode 100644 index 0000000000000000000000000000000000000000..86f5e588d159db3fa59f1336427d27350aaf3318 GIT binary patch literal 24593 zcmd?Rc|6p8-~TFZ2kV;a=j3x#{Lqd^bEJ>vrvPXSq3`U6|2}wg) z+DECh95o{qt&~bTC22bjTGgT4-_g-|UFY>X@B6wRzu$SC_w~Df{_uxKc=XTHYkPlu ze7)UgMK3{_p+2J2A2N2>*Tn^2BMbkGE&emU^xc}Re&T&4SyCij~5*nmmMB2KQdl*Y`pg5`0n4v4|aTOx%jQM>)Yw;-_CV^>*)R7dH4I( z``>#Wf4|-T{lW9^PlmrgfAjt29}{oiO}zg!@o8-0`}fJ;{7?8q{{nzmQGy~^{ zES$&Y&v$il#-fogIjVoW`oD?7O|VcjCCj$Bb5C+tqQ|c8VX}%qKyS(qy8PBjH)?Ht zozV;}4PnN$H4Z8%F6ix{2X{j(zf}#dC*!&6eTiVi+7%jvTt7Tm$P)$&a*Ft5!#JNJ zBH2KjSPbI#;B&MnqzVnZp0U>cC43jIvASt)tWT*fByQHz>l1kG z*yR^R;>yw(ky}G8Iou*!uj-D?3~mZ)odC|GoTIomD^MyNxp;=;{Vn-(F>by`WrnOl z<-ajf&o!m3tAsYe+M~hjc4zh3vW-1L0Cs?gsEG}vWC+C=^mH?B!lSGOtB40JnbP(3 zx{)+zQX(-}z|M_GWYnzglc_}VlpennnKOMikg(C8FGu;arMl~8T|L+rjm2NE*jJny z{HX(+W59)BXWJzgH(N5E>h54Z=3!`ia$+-LrURBV*6=GXpSBlG4&+si3+om;j|HBI z*k1}eEp1yM{kX!U>Kb6o$sqKg0b|?>ii9AFQ=!GAVl6A*KOqAbYWu0)-5sZC_L!fwP`U|`dZB$QJR<}LNJ46P#8*j>XtZN017V=m;|;oqxNFz%3E z9EWJ6r9`v7oE>9&s_gHQ2Uh$ofu$H(<^Jx-du#S;;(~obQ&K8-V?TKWMpxZSm5z8 z@v7Y_?Yp-K=BUhvsB@uPVZ}6KHUW?SXZPl#cg`45nL%+8?YKVCXbgU~jqF~$ z*=Sf3ft=?ZU1jZy8Qps~eJCD5Dj8<`6JN1;Lx1xwr;iHeKniL~YIiV(w1S z`S2dlM<=MJF+JCKbq+5@)h-qLDT=wax#i{s`iq;X_TG*H%g3CTC$eXejKd%@WHliR z93S;ue#YQN!}gs^M>}-Ad@mjeqjMnCPon${A9)By{@*dO{x3#u-v7VE$anu_M*ai* zwfw|i);WJ*o=c*Ua=6uF1;c;Gm=hcw#zVQ$usJ581G| z%oh*oZ^nZ#Oz_sEkOJ}gM#Za$6car@5dfYIfQY~$04=kP<_nm>jqt-UBZK%fj?3kv0GFn}E$0-VbdzlfLE~gQ{hkLas>Q)u#GF($0 z$)X>Zl6VWshiTDb0);ZST!yL#@`$l|QfHTn^Z9GdX9!3BtZQCmZNDJ0dmFdwL>}lv zb4;qYZ&(Lv9DQGqxRXf8W@UGm`?GMmn#txy(17HaQ{geMJ^}i9DcPLRm$it+dQHe9 zMGmLROEFpuPw6nkDBlawWsXYe+AFNP1=~A5?OvGl%#z_(WPVO{o=BwTZ5Q?jtA4v@ zsRzTWrb!5XpWhK{;BPuJ4mi9#%9?GO-L#!(0n2HGZjoF!%U2Hy!c#+>w_&l7vIulj z4r(HrU@<0w=TKfwV{AM;i;l)Y1fc(yY%S?koXAMDV~zW(p@?NySSZYF-<=Ayi*W+W z0B14YQIJD&BdRdwm8eZv$c@k57{FCrC)6cgB8a*rceQ8E8qJVkALXR6uspVpamuCP zCOEU^_Tm>nePq8*R@7zNJ)(i6Zk0fc3pJ7y#j)5ptFd~P8g(oj9ipK^zgj_2&MIEN zYC%n)OcX5+SJ=>|9%+St0X>G;PG?rMFInaXL8ZG_1vsnl3_eZOOnO+V1Pw>hSp4R_ z-Z0h-4t=#ZheBv3b}x!}J5#FBv3d8U^6p~dvCB~6vd}7X4Kv_yV1mQe{``- zb>_oLnJDv~y+Sjo#9ocMI4@CKfS&Bvw5yR_PPBty2C&Q~LD8{g-y_%k%eauU*&%aJ z6nY8d>FlrIISPcSQSRMrBE_Nw#;xjFfhN*goB#Or5!?D+oQ;gn2SC{o!>&hJt1xY^ zWkr3eDRwRJVy?S_MJKtzTR_prhUuBtC`wJD5slrBqs|i?$2NK$?CA1)5d=)Te<8p( zAmz3HOt&O%&I!!QsRJxviVLg5I3uH_gq6t?0gQ5qOP*S$wmSi zoAZ1?gkB(7|D?eW$!4_24>Uh;ew6`TUf_e*wXmS}P}TIh-FwAH6Wd-4}>@#W-z)NRG1Z&ipMV=RJ>x zkuOvI^SCKSEL#}@FU*Ec%mJOk2_jze@TFC)EzHw4bv4pe zX|BWt`gq7}lj=EmqAo`!8>s{CQS_|cl)CLeueRBY$k(WuzZdB0R@)y-XRj?=_5JHN zUDcv?#aiq3M^ly`j*OX0p9^S6Zb>kh3LHoII=xHOp!D-tJwoVm*`GQilGPq%WR& z$;@SGY(o7k6>UH27IWdIzIpW&Nm4f&pO(hDyY!o#91Xh8g?)Y~G@2ew89Zdi3U@lm ziq!>6<7Im&c*mEGR)OzY;F`{&ew9O0jjJ*^C#s?wo89b&cC+NuL=B|=Is{vlW%p)l z4*Mb4a=TmD*qfwbQ?9&P#mS*d<-0cA-Lt7ut}z}gmRdz#*>uq9<-%IV_b=P*wqDF1 zvTIH$mVH#6GJe?1#@+Ju*W9mB&RU2uk;qu+^V65qW5Dw5db+i;^~(4ms_Hh;M6%Lk zZ{wPZefBN4Pm4;;iy#%&DDeSDIiht{f;BIfs~DOI{raH>GL%>`SgLIJWuj9H3Ul4u z9RnKmhOIibblEC#H+5(hgA;K}u0z`{#DpqT;0z4?*u9jl3 zAA+(?8EPF?(WKU4jUb?a@%wAa^!0yoY^TiZfGQ#Tf{a4Fa#c;RD+tSI#@wUUItara zokbW%CPn)o3QQZHm!NN9q)B{>0FN=oupE2z<%^~HE22UWgGPfSYpXt5ObJdCrcCFy zqR{x&dUhKM2j6nQxI`y?KC3<#_Rp0GhH023xVhGj1Oc~SMbyBTB+^tzfdvz5=Vrb$ zql=i+;aDz`drC+CUb-mA#MleGkBiQm7;+{QsM)# zyNl>$8J3$fWy?F>lXE!{R-CJ!VCBQL$luL}jWmF;5FlN3H2R{12`O)XS5<_)W=&H4t)_clVPX?=hJB=Nd+R$E_DP z=F~u1#Cb$KVQf#XB3dGDv0H0nCoEm~8&O%sd8Hq7HR)HV#8HY8`7VLR-p^iRT(=M{ z{)=SJO3=Kr4DI%9I?l_KAm3d~BiDz8>Egp><$^zULKC|%rZvv(K%y;Fop7i;%?rq5 zId3N#CmuuNOylJKIHL?m*Ww4soDh-?dZO4^{XOa1^Un(V?iKj1hIs3)IiJ6|iR(U6 zG!ruGhC@$m6Nm|PnLwPW!QI|lo%q#@k#Cr2+qpH{5qfU!>vjnpnV8zGa&o|wp+T3q z!bzO{P+`FdGt#e2(Y?A14VF7))MfDkXWAsEKHl3wpmNeK+f_t+n^S=1i{ZYyyb&}p ze#$Va)-YVKiMG|4NkEf?BP`lZ528K8+;=Z$$%*L?-b~wnCs(zSnbZ(I^X}s%3vBRv zrX^BlMTfs>8p(UL`ABB5;E!jgj1y#{l%B6Mro>vENkLRth!@&rNKZzp&SBouE~wnL zz9Uqv!V1N54-_C0`*-g*H@b%=LY^$m+VpR$?ovo8d@-&#p?g~~R=^3&6OREHkT{Rzn|LR+%%{`7 zpnWiAQ@0nW`PE@7yCsqY#mML#Pqr?fJHJo^IK(l{{A8QuK^o_geeHZ@)3j;a<}+E`uQ8n z#RZdI(zqmJ0RV#ddNsf5>Hz@$%SRqVe55)&GeRh5)_iW4KjI*}E~^RF^@CuCt)as< zRu9go30CDR1Wc_+cu4}{T&wjg8SmdQY^)g{KbZUAF$Pv95UZa>5oWEr^=nP5^qqhprPn!f{i`IIwF!>+hKkDQR^%Q#%02m z^rlocvJMep+}SlyDf(r;*0bUiT2MQukVLVT8fnx^B!>_Y)~4GoSx6!TqzJ2D19|m# z^ghhG_*w$C`Bp#Qv3&t`<}P1Sq|zG&9Ii?I z#5pyzSHt=q!1}Ctea>DYr}`W(N&j2ZG0A|)u@^iX*}A`;!GkM*`PGxKzPD6QA-^*Z zq*!_)_%drP6J=8#y6p1su8j4ZYvF^G^$4`) zSPK@iupxzE+X$z|?i8dH<{1wG)mp@53BFEnAI{&gOSQu+g| zmc83lcQ|!5i#K-);v8{<@w7)x$%Uu-eTc^6b!-Arj}}?y2d9yK%MMXG#FyK{mALKI zIEOflQnIGG<;_Vn0Ht)_!ZvZPaL}JO46yK4zMhs#FM}3R7W{7jEsuw^HFrmZXY2y6 z?kMa~ksf{i6OZSwRqL*NO#83dJjMeFH(L3JUlFR_bXcKgAP+SEX2Z}BxWhCNJ6q}8D~eJmd@ zi7f8S!gIvSJIn+mt&gG?%KCL{+dpBY6BBtTjN1eAAQ)Vi!)JSvw1jAUliExceY26$ zUQ~7~(cTbh!eYg{o^)}}*iNCyT9bof&$37zxxBf#b4JWO2o@~BJz{~|aQtZJiVc(M zi^Ni}@YcfMIIMohrH<@tkMKLKO>0=~fWMUQg||p~*|2sRwTI>RiN$AOJ@($+0-tMZ zVx?`pU}xh@o7?4=b3GtavcM)$wv1>7*xN?VsLz++^!mqOb1Q+f5@iDOVbqP2dzU$# zk$P;gD}FGQKoY*bbFEJh@lL&a=r)rbChn7M+*b|nBlMj3ke z$tH(GUG)a(k+U6-#P(81?)km*zlF2zrml_t){6zo5esQ@`;-c6vGEORoy4v*`94pt zv?G02cCe}S^Z1yVk9-pcQCO>v$IG|rS3FkdH%V53mS{^J9C zYOZ!XedC!jf8dSe?8)Jp1p^(X-hFi*&$tO2vi=Kw5>G2D zksSOh2nv@V%iHOc*$^@blBOngWwR_W2M$@ODT&p-% zgP;F+De?|hiXZ6cbIr_!b-DYr9DIcw0xc!3W0tj>fQEiXKfw|1A~M)n8{CC#Hj;oX zaWHERjf9d+2t%92XEhqVg{>f3C#pxHN|QReS_zTzKV!Is1t1W**4^;=EoJ&?#f7023(J2V)rN?DxyIrD-U{I4XiNqp7I9d&=ui-Yi#A#)^Q0 z(Yg4ki)P#zO!qA<dGA`yC_{x@MQjeiqS`g<|8`bA%ef@4Zd))#(?TGMs{H z!64}u1{fdY=!AR)KN-&aT1eBgv1b=09? zj z^NW9%cm2&P?y(-e20WDw&(_7KYNX>ufqD6XYRkCAhlq$T?v@f6q`yU4lcT9iO6MWc zOS3*>0UktrI{<(!Hp_PA4RZfnl~L7bQybL4oZeyglA)W(6G) zVAd)9Y>+UEPsSgMgUW$)>79uJD&TgPMJGTsQO@o&pBB+=7_n>`F%dEbn~j2YtUmtI zV233{Lq->u%8!LEHp=FQ(9{B~401%`FN!-#g*B~f12#BNyPp!LQrWkOrp%jR#0TYz zA8v}6MZ@sq(^+1`%iH?-1lh}Vm+(8E?`?|t+*P)#A}aMH9A*j)8{*A{@&tSyeJC8G ziSSHz)|USl&j5ljCW1INpY4o{F2qEGq9rSFh2#uGz>2}<%_6N$ygENwKYB&m^R%bM z8W1YF!79aBHJyn_vHkKW0eZ#W>34Z_z+I`@Xcs)wVf(QSg{vqmJDWpok5H=u8)VzM zCyI&5*BP7EpK|;Bke1zMzhl#pHFmaj`A8jk&NzW4#0^wk(QLVFCTA1&^ZVE6e!hAa zw7Y-E`!)G(0_x zo%=&gWeV#hgn+c7ZU%?X0*z3&Lr+$r#nsz>SOOuIP@{}^B3(|(<3%V=V5YUoi04d=ySjsdz~o-%)TpCHwN$5&4n(!UDsdx zMekd0b0;Pg1^u5`PyRoNF)%1OQ`2u!j7jwi#Q3r@A5F?;bv3zVDKQ&fDhBuLQ72+R zLjxD7CLzRo9{cGlb9tco-nt-7W4b{!o?>zBx*BX$>NSLH+wh7b&DJ(gCWjT3zJCoX zMEYlJj@0Wi5HV)S=>PonGtwPFbjwwkO$7JK4A$t=3pRMC z&aEuoWvXv3hGaXRNX#dV&yDMkMTk~_5KaEGp4{L-)*B`e|0p(7I3L-gr)fGP4zk9C z^=iG)Lz1zl>SXLqsUTGBm`BtuhMmc&*aB@!UW)YVr}KrxKz+y6`>dDD&7L?_#yc`4 z6n(mXaP+IeW*q_qG9J0L!0;Y4`S+nmS5^sWO_m;zf_K?~3I~nSuTBJow z$Xo-rxF!?@yjE42h6@SC0M-n@)}?1v*jI&g|JG+mNtj5GcJVksW~7T!-BrZ%Q^?lTD;vk@)h|T2+1bsk7)dVLFoorZ8}*eN5acxZb#|GpJ2i?oZ2d4Z z+qu7n02#Hg+)d?3AeOK@FJVdiXFC*{&>z>0l#<*A70yI3!VV}d?1!;Bp52IB@(6c>T$2qVB+XG_}Stdke+0s1OBWEA?roPHpM3zaI=3V|} znw>|{RA1&LRgHP?tnEw5C?v|apR4?P{m_HKbC!oQic-CXeP($W$b#`ml zl^uRaGiiSS;>6ejMuSZlbU^noL61w@ixox*RrcEtE?gX^CRmcnIP)bj(P=M`jqtaD za6v5i)i&?TNu`sOWT98X{z88v^ zlZxzIUXz6Uq-AS}_2@|13v^ZV{fICm&j+M+o4!U;u*zh6;%TqR?HH_aAYkyd@@#;5 zRbk>5b2aSK62wfNnZd#QVl%k=#+9y}iX(){Jby&>^*~rpwe#DVM!I`lPArrkg|V8Q zq7+-wo`!O8-IUK25m!%wXmnW_BG58q3KjO3@588ti|t%msq^IvZ{GLgJ^jSY`Yk|< z=6~)W>z=>6fObDgp>m;rel>qjzXn{2s`1l50%F#Nx3KPKW{jRN=bs76hjJ{@7l)_@ zYi>T}38~;yNyz^(GqE2s&81qFwd27bhCO^OQ(Q~dwNEA{9m4g2YZsnI?4)e?7acwk z4Qm#Kn!WJc;J*43iKPx^RMoNgJ&a*X2reEnHEq(QIWt`3Kz)y%v5n%0aZvp^!{A zV$2dQTpZ})?U>jnt2<95U%V4Bt(N%*{={`pCy@_O#AM< z=zw_6GW{h^eLjnhY|>$uC}-1`olXaBulP47QqOeIG*V1tst(LzwQvinju<-X@48w6 zyLU-RKuXWegC~3QD)Hg=owW7@JhW|PyLbEbU09&TcH}Y7;6*&>vmlZ-UEFd1^B;ED zFrflqvA)wh1IEKXk&%JfQ*-+5q8B?dd9cq7oHT_lMh0WF0ST>W+OKG{)DbpFndLm8 z1Ut?7rUZ%^8AGV0vEW~{fjv(FoRjMMS_ung7iusSO0m=^DKfchip}k82&OH-WwczV zz$HdQl^`54i~<&_`^x&szOrMOml=9NFz^>h?@d9BL(APrYX49KQsBtM zOW?bOU8vr?l?TAfCg5OC1`H6{L}H1blrN4&qW=|f-b20faeB19TQJrFXVhvMvKp&T zvFaaoK97`<3-z?Nz6^N)@4Z)7SX~9>B9Id$U!i+gpv};`l?!y6Juo084!*)dZ08jk zcI^FCni_Jec%7%9gO_cyhKOy}qcqrN6H1V$F+F*rTG3U`T0qR0vR<+=_RD(~g=j|E zUnfmljCAU^#rYJ9AG#^ z?E@X$Utf#TD4S9mOHLILj@)`$JHDmkUXg?Fux@fi+qGqj64;s4Lbn(ov-X9wFg$|B z%GcM>Q=K%~#BB*MIxLIMhmxRTBj3Jg9j3?c#K4}@e=HcLD&8)16o9CI)L;HJsplJ& z{57fPGc9R=tqEbi*Mo=N=lrK;JPb!*@jEi9pRJ2b>fannf4da0bZC60i^uzH$Q2O_ z{2~bA06e&ox7fEpnyBf$UA?E*s4Co{34@}B0xezA7JcLTSS>`@tOk!A!>jl7*yAUV zIsN3a^wQ5pun2K>rZ%J=K3@O2HB=Tv(6x9rXnu`0_>5)}g*SYJcsuL&*AZG!cKVj} zTHTe}PQUp)QB3pV-VZXO*VmoTBpGj_^+anrX(H7iw_o0l0ZcjW_XPv}+iCPS~C6ky(RyKq& zR)tY4nc4oXM;j$r!U=a}8DE4fw%k(O=?v^cZQ~IA>0y(S$eLHKED|DdyHO%BItGis zL=Q-T{~W_EO7t=4NlBaW7NpRaV=HF3FwUQyDf(?a3k960em|Ug1%r`Hi8ST$G~H<8 zfUC+GyC73<^l!Q*XIIy8m0<@TpYJ&yks~h(B2&FmP<8um)jWA(JP`Qoj8lTvb@Am__-uu4Z&0&ls(3(O&T+`1cVsGbb9A!aXUwY&%yz7kg9k&6lS!k!k7b@YXXu%zxm%aZogJ1{b88R+;ap z@#*UDN-jRdlOkqM7Qau9xqA7-8 z$w}`Dyy>(OQ@??@Bx?4SCFQ0E8JFD>Tdb@UtbohbEL zsOa1cgsZlJ`-STaT3&026VF$|HK!`Vq9Ba^oJsd`~n5eay=hY;r{6 z$o3n=aFhukHiKx=l<97}2wKzUdCjBfDK8U>oD>PfIL*t4Z%{~Aqk^KY5-wr(F`FxF z%Z0tH*$$5{s2-Q!_PK{0RWIzLx?i9G>AVqCKvu(}UzZeQhm;$rLW{NrmM>S`8rm^4 zD4$;KFrqZo;R>hf5_zhMz^IP&FE{!}ZW&Of)sx(Ol>Qy;3z+qNB1rGtd8hF~i89C= z=@M&chF8Km$KQ`mIV^p?)pT^rgUVl?RD2lc{gYHv(SQ4K{r`Qq)po`|;Ob6k?g!Lb z>W9FMX$x|E#0lycK6U{zN!XkBJLXCn^$z0xjvj-+1J|ypbyB6D5XrPU32DUY9=xH-hSKHt zp}NMBLog$cNQh*B$ao`2fI;0KvHY!k@vx)}n=K(utj*$u8!6bx=HJE|VzrATx0 zs*BX&R&EPqJR`w&2a$OE-^9|n5hR}%iE1J1&g6dK=tErl*+9N>AFU)br)bLa2Yik2 zc8EZ1f4;K$4i-ZbS6vDFy+RDp_yd|i+5M`kLyrg36c2s+26PF{>;e;lC98si)=|r(z*+r#e3Jqv1~klI6N@Z}Kd}^> zO=Bs6FZYf=358iOI-koksKA`o?tV}NXrV-6E(@wAnxKxNaVEfCWLICV=vmKjAA!p> zQv?`m9mmD&LSLTG4l0Q`wuky%y}!p)_p2)7vXHP|!(h9d{nQN!x4Kn%CeEFG1B>Qn z3>jYqdW@2vyL~acX9aVmd<@=PD?b5WnAFI&8R?tM>E-N|7_RWDXMV8UAJm0uJ^^DLwgFrneAF6XePi6m`54pDu2vQ`?n*XqF)~Touc7LT=Qv+QVJmb1=>3Eq} zRD0_2hf31Imps;L;2$fb|B0)i|M9Z&-?fYXai#kAmzDotuT+tR7sr{BV)GQ0POaaF zr13#HDL)b|X`#L}7r%8Yl4upF6RqN<#Eqh;T(F@5NwlO9s7Fqu|64k4h62=l9 zXl6sI4^~H7{5la5*Z16{o}p21(TpqbEs(;-df+$pV4{kP%)G2G(|~vY_u#dmdYtzXieMwjM5VW zRupx_H7xYv98wr}+YKu|*!^vR{|H&&JG(R5Ieo|iU-1T-F;bwb*J|HZea!bp)Y7n8 znmZ&Y)V14M3HbIqyJ!AZBOb>-orm_tx>km>1UJ>=FWdNs4(lo}+01A*>k+YDW6$cG znMtVhP@{#c*ZY7V~#py_g#pmqe7iJS^QRwH-Y%j??LIsdgL?lwi`J z88SXf+#$JjlbsMB_NH^%+iGFKJ&PC~d>s>+c|m$Bpw<>I~>$=uG!-YDWFCqt4F&br$eHBq%$ch@Ic$e>zD@A3lv^w z{N6sf4YYDMB`2V1$}cp9WdEX;$V>jjz&WYLE>j1Vf7jpW*Bn8SA0lbIuIodx`qIxU zW$3KA$O&&(EnjuAW!0sTMyv_YG_=r{m!m3F z*U=i599y$e=SN=ZB2sRR6p^6>vygBZQbZ!Dy;g)ewJ#&M_cAie26Y!Gd8~xA4w6FG zRO9(cH-b9h!s7JZ6^E_WBeCpG;pD2q^XF+KatFTekRQC@uK|&QXTsW<%>{l(i ztC@>Xd<1J4XHa?O_aTp}EEa6!;kL36JVerx3fn*Ix?&sPtMS_*_WX zz`yGu2u4===8D|Pizwg8m42UqQ7g{<%>iq87WVSop`77n%8qIIrcJFa;pFJZFz=wa z26$=$h{0rVi^8I4c%JO>+T|~MSOgmxN@aO*bT>?}&ZbQ~C^)j(@*x=v7kJ@OdC!$7 zLm|o^XARR-WIEi9)ReNjC>jCkm#^i88$?f^S(w6EUSm{RlYF_M{ee`2h4S(+)@nso z`U!G$q*3-rNTQl`mD(u+F`|9DS)dN?B$YgwKDDO;ZyN8;8Q6F&%|r zn2e#aD?s657Tc*l_@X3ZEoJe`8t#T6RdVyNflWD3IR;bJmE@0$aAVr;8=#@yY*gk2 zlzJU@6`;opFYgV_uDWPD(Vk8}pedI2^c*>WIajHuAX+u&ZpX~Cs*`7aff(Gw<+Xwp z%dc_DMHQOUYAnj1^P1qjFcNcNK)ztL?nlQykT*zGJ~-^7l_JK~yxD5DE)dtmJ3{%q zEgl~;hxYQUf65!!Ht~{~WYB$qpV0N%GY!uX$&G0%JH7Rnd?+I5ZZIm%7%cD!yk(%Cxen~|R~9OVDg1IL?JI$uXz7IV0<}0)C(!Z#Z{ExW%dj?QZ@``JsL`q@iXA2mPJ zkwI4(tVcN4-SdNU-3aF@@W)OZw6=LV*-CElC8!hpsui8ZDjQSvsnMV6TJqVaFAsd` z&zEAbj+F_>8DB0JKSN4r6&cqf7n6>(^Qt@ETTFIy6(h525Oj1R#I=<&Mxo-K&k+|cXLe5s( zA~%$m*lvt<06^f72k5g{?9{EQJncECc!oj@+Dal zE|4?I5z6Fe4L55#Z`nAftDe|IK+9)>?0J_1U1Ukox;XGc~bZ=*R zAgU9*ccJa7Xz>&mDqfN%u>FdJ~g$_-4A0FHk%)v5Z`^K@Hc z)>eXWlWmM-bI?#TMp@1ZBtAY>ADr;jcljnh+-5XUxy$Bi^U6xgIApm0?)sm%E4JQ_ z*^jY`6G(A%CZCl$esDKDd&E6;DVWokZ+}jeps-)lA~A3{>%(-0&#sr@|C+lV9KQ^- zlWZSO-cGV9rp=2g)ZsmPE@$t(8!YBHRx6*u<-?#+--lHv`m1HFZ9GT#o#%{0tt|EN zcNB%>oW2Rnezff_Zt0E_XaHzcFZds-Zzr?ITdw7!)VucRog3&TUPe!lZaq_Xt zW&7vOA5QN$BoSvi3jTT4^nc9U{+%`b?*O*{>_Lm`9qcUWOr7=WOYjX*=^D~NvY|E~ zGSJk>g}15CC&l{4Wf{JRGBd08A%e}#KSH;?KgO@fEw~zNlNU&$$>)1Ic4;VWjMI^K z0B-dniCeGwj8dJrA!K_tIV5Y~CLv(!%3r7X6Kvy*!Ewt^rNi*rpHW-1N~F!uYdgwH zL>90{hO~ZxL#+2)e?6;k{+e6{NU$fHxC{6qKdy5M6fJ&0)inTE%#nTooWOA1Wk!A} zkwl75L9vWBwM(4JHFN8m*RaPGG?ME{w z^?K*{8*ALQ49Ro9Lj@c(UY))%i$)O1HkLMlT1n$7EOrCG8W++Y|b z9<++C#m7~AVdLqoGkvk&W!OM0HxKe!Odl8XXw;0x7qz;CWYuPu>)|)%Jl_T*gEHoQ z(bSbs8_}R~`H1qbMZe4%mCqiIbNvcH^Tz8IOz4L~`2lB8j{pgZ?TBye* z$SXeG*!5a&e`&TR57af#aLg?G-gtZrT~6C?5Yk4C$nqg%DUs@%E6F( zM32po3bCfFg{PF2>kpk&$-&qqQU+15|%NSjx)QGK~H5Q?b<@25Nmo1 z9xiN)zJQs}beg|#h46Z@Wf*PEGrfS0mb@3M-J?(GZP_06&vK>z;CY_^t~C44X8g!< zEE*5{OfLETHu*yOo5Tebg_L4-(k9FFLsZ%>G2%)mMOyQuDTVMq?!hOIlGNj|15&vL z{hUGee~@W~_@l@6|CDLfKgVM$@Wc#_kaItz+62S92y*#-mvZC3pO97ln2=S{7b9j= zT%w+kjkFBfOobe|T(32`zu8sbtjyq7eB^}-!jBg&CeQ{y4wcHZnPv9+VO}e4k|~38 zl2|ecFjw>4YWMi)^Z8mAIB(unvv-O~Ouri29=7|6#feA3!FZpJuIZmz!izOkq^uZb1pmmoOq4j+?-A*IC&l>k#Ov|uwPJ5uIF?jqz z@!6Jmgl4dFAZ}&O$8CrMMQYQzdDiV%zL)w)DNemB3vuqZ1gRN>Ei;PKi!$$)X9nOe zhxeh_&(!xxEAk-m5_0Oc8R+MVO_Q2$E9aJ)24A(H*Fl7%k)Yw0gX ztIJX&Sf>KkbkcQ3w3<9#@jQAXZXYf8s~Ix#KXfKpiQ4q78QJnLZen@qO4M4d@)bPC zFtUHs%HQQ_>g#ZnXjhbV`0k9adVckUqlXK-qQf`pVQt2FH82+i8|J#g65 zb80GusMS5y;>FT?>X*nAn@$2wZ>n`kDZf}0XNm(MPypj3w;1Mpq6QqPh3Q1HehkVJ2~hD zuY)?G{f!K6EZZI)v-Qb#=4csKt9z@`>T$rbdfiw^gmYc`rgTPeaKPgy>sQvOx3L#g2N-QTS{!S-ecFHrwKd{8E@|+ewfz78LEwfxQ`J3B2aj|J zX$#gTPm;~2P@}{LN!$u^;mYEFm$>=mB0_DlMrb~K_-EqwH=)+>BXR3kDeA!M(oMH$ z{0Q8Tdh{OMxEOy7IlZ(VQcb39Ty;Ns8425VMj?-0_*$uq(@1<|9MUh%9n#q3ZYxI0 z1UwLKJK!f$-$^AxrLSqN^ zsIQk$F1$t%ZK@uJsLKRqz2BTL#>zz$ONQg0mh`^D5?TD3V~7>aC)sd5*zXYOc959k z+mI*7yyg)n%h5W~PRRQ5ntlW>g{0goV!^3J{JR2yVMfDVpwBB0m_N1^6YPnI4(YKC zp3K=2-UiZEKY+}6BmQqk?^ecaE27cczUAv&++Mf?&tr7)=+BG>=iSpgi#B{%0uY=ZB&oYn-1o``RhfUx2%9Jf7*=8zPCn-2$yx@w7)*=Z z0#}~cQQXm2SA|b#RI9a+PP4rF(p#*^yFZ`6a7|ObxV;O;O=GWZ>oF?Y5>ww4n``pPUd)vtFZ%42 zyRyPK$g4+Fn(X?!0o`ntdRHbZLP)2$k2+|KRg+G>_kiHezTtz~)exqZ95qv%v_2zr z!qGXc*7E+WHFn*%Hm`~tu7ZZztaX_TVHo)9LIoW zZ4@mz8CG!|==H+<;-mPiyzDTWwfkygr*4XFh*@&yoZlYhn$bQB#BEQj`W$9VFG3a} zy6*mb9jYcEzi^G;xAh{`+vqH3ZSKtDAZCpqsKaE;JNl^E*d}&9v{o@{Fgn}fZpvwT zMt@*Jz^9aVr!a&#r+?BTi~n2IrGNh*M%x*OK=lqJ*=(YPon3l_=1QgE_Xr~~%?ylZOx>oHlQUFuUz(%A$9`i_Gd;>#3^>&W9|mNvAW z>xdyeXo#FPHChjxRzq(4UKPx&JhE#$o*Q^c>nEmtL@-TrALX8<0wj2;$bVf>7#K98|onunOqVK`j&%rH6~O z3R)4E$i+@^2y-Y>f$2gh)FC1p!yyDgsspE@t~k-DW9~iTvShz3OP2i;-@Nbhe4dZ( zdt#PKM%0{$SXJePJ;8?nHBPLrdTVphUzYxghi&+U8@+#&Fm?#M;(Q;nutgLKOW5JZ z$8z1!Wf$cp?zEuLdRJQY5uO!ekRh@6TG15Wqt8JJ4V>Sm1_Az&;a5{~%qF3;ZeKsur;vhPVd_!~;9a+J1ojDxxW!zNs z*B|Fqv)zP>vGy_GR#Y)3wv$!_A-!E@-&gj%f+sDq zWSbxi=BK`Swq3gCb_~AR_v4+)iy~Fe;fsPSH_700r69veadv1^&Soa&oRPxAif!lU z4=q0#*6I^8^!)(@a!9mvi-pK14XQ?u#?8;k>b!#`AL>u6tU-M3dZS+ZF+e{`sI%Fi z#85dv^1&xGgzH(F6A|hBQS2RrojeOsPSiAJJ{?%Szf4!o9rD{DAWVDne`reg z*p(!SJ)kukE<6B&4CRKFgbEjq%v@;U>Lupw_}HJ&D36XmH{rkdiu^cyW2-5SRIhuH z@b$*>1V753e5}g*tEJOth=dzMUW!Lj*{uQcm$3R;`diWmjAwjT3tCbw?VKI?Zctc9cE=&;{Ld*E1aF75-)o`=Wt@o<{?DJzEWh2+S)WC(~!YwIFlcwvWOD>E+qnPYg>ELVOUU_QLG(H#t5l8s|q z`mi~0m|_`I5jWYI#J|9Byx?+6BL2+KGN8S+6EM6@-7g0wM~JZCw2&AeD4OJUYOZcz zo>7QWx|#~~l1p?`aA+0LK0Gf*%Qt>&!&(Tei!f4x+OJwRESGjp8KY!@dz{v4)O2ZA z;gHW~?q>S6XZ?B9IBX-|GE}AyJ6I8JIW#*wpgcd_{wUHMGom8yOAXD6w1c8ai(OJA z=Evh@?lPc~eAHe^$f_C*I10)F>g%!q+GFyM=I!2YzQu0F+OCh&wpHs4^tPVP`w%s| zLU8(7Nk4A-;lhY*8~rSu80C2d{6fW@T}P75l63(0$ki-FmnLp@*NWG!58ls>MIFq> zsh0OEq;PBR6HTPzX%PQ1yv6kvqyVDDPs5p3Oc&|x^kQE^qgG{b1-J*)?bKSTU~mG* z1hi_IXJA0!;I_c*2*sd!%#yudj^xD{poN*Wv_jfmZrbG@>!4W+<~qAa=#N{)Z=<;N d+LkU=v}f6s?rK!5IqcIH^wYdJ0*?wU{{yfmE)oC$ literal 0 HcmV?d00001 diff --git a/lib/http/api.dart b/lib/http/api.dart index 469b85dbe..d82ce44e3 100644 --- a/lib/http/api.dart +++ b/lib/http/api.dart @@ -762,4 +762,6 @@ class Api { '${HttpString.liveBaseUrl}/xlive/web-ucenter/v2/emoticon/GetEmoticons'; static const String pgcTimeline = '/pgc/web/timeline'; + + static const String searchTrending = '/x/v2/search/trending/ranking'; } diff --git a/lib/http/search.dart b/lib/http/search.dart index 8e7356ac1..41dc391d1 100644 --- a/lib/http/search.dart +++ b/lib/http/search.dart @@ -1,4 +1,5 @@ import 'dart:convert'; +import 'package:PiliPlus/models/search/search_trending/trending_data.dart'; import 'package:PiliPlus/utils/extension.dart'; import 'package:flutter/material.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; @@ -207,4 +208,19 @@ class SearchHttp { return {'status': false, 'msg': res.data['message']}; } } + + static Future> searchTrending( + {int limit = 30}) async { + final dynamic res = await Request().get( + Api.searchTrending, + queryParameters: { + 'limit': limit, + }, + ); + if (res.data['code'] == 0) { + return LoadingState.success(TrendingData.fromJson(res.data['data'])); + } else { + return LoadingState.error(res.data['message']); + } + } } diff --git a/lib/models/search/search_trending/search_trending.dart b/lib/models/search/search_trending/search_trending.dart new file mode 100644 index 000000000..6a2aad778 --- /dev/null +++ b/lib/models/search/search_trending/search_trending.dart @@ -0,0 +1,28 @@ +import 'trending_data.dart'; + +class SearchTrending { + int? code; + String? message; + int? ttl; + TrendingData? data; + + SearchTrending({this.code, this.message, this.ttl, this.data}); + + factory SearchTrending.fromJson(Map json) { + return SearchTrending( + code: json['code'] as int?, + message: json['message'] as String?, + ttl: json['ttl'] as int?, + data: json['data'] == null + ? null + : TrendingData.fromJson(json['data'] as Map), + ); + } + + Map toJson() => { + 'code': code, + 'message': message, + 'ttl': ttl, + 'data': data?.toJson(), + }; +} diff --git a/lib/models/search/search_trending/stat_datas.dart b/lib/models/search/search_trending/stat_datas.dart new file mode 100644 index 000000000..c77d32d46 --- /dev/null +++ b/lib/models/search/search_trending/stat_datas.dart @@ -0,0 +1,14 @@ + +class StatDatas { + StatDatas(); + + factory StatDatas.fromJson(Map json) { + // TODO: implement fromJson + throw UnimplementedError('StatDatas.fromJson($json) is not implemented'); + } + + Map toJson() { + // TODO: implement toJson + throw UnimplementedError(); + } +} \ No newline at end of file diff --git a/lib/models/search/search_trending/top_list.dart b/lib/models/search/search_trending/top_list.dart new file mode 100644 index 000000000..679c752f4 --- /dev/null +++ b/lib/models/search/search_trending/top_list.dart @@ -0,0 +1,95 @@ +import 'stat_datas.dart'; + +class TopList { + int? hotId; + String? keyword; + String? showName; + int? score; + int? wordType; + int? gotoType; + String? gotoValue; + String? icon; + List? liveId; + int? callReason; + String? heatLayer; + int? pos; + int? id; + String? status; + String? nameType; + int? resourceId; + int? setGray; + List? cardValues; + int? heatScore; + StatDatas? statDatas; + + TopList({ + this.hotId, + this.keyword, + this.showName, + this.score, + this.wordType, + this.gotoType, + this.gotoValue, + this.icon, + this.liveId, + this.callReason, + this.heatLayer, + this.pos, + this.id, + this.status, + this.nameType, + this.resourceId, + this.setGray, + this.cardValues, + this.heatScore, + this.statDatas, + }); + + factory TopList.fromJson(Map json) => TopList( + hotId: json['hot_id'] as int?, + keyword: json['keyword'] as String?, + showName: json['show_name'] as String?, + score: json['score'] as int?, + wordType: json['word_type'] as int?, + gotoType: json['goto_type'] as int?, + gotoValue: json['goto_value'] as String?, + icon: json['icon'] as String?, + liveId: json['live_id'] as List?, + callReason: json['call_reason'] as int?, + heatLayer: json['heat_layer'] as String?, + pos: json['pos'] as int?, + id: json['id'] as int?, + status: json['status'] as String?, + nameType: json['name_type'] as String?, + resourceId: json['resource_id'] as int?, + setGray: json['set_gray'] as int?, + cardValues: json['card_values'] as List?, + heatScore: json['heat_score'] as int?, + statDatas: json['stat_datas'] == null + ? null + : StatDatas.fromJson(json['stat_datas'] as Map), + ); + + Map toJson() => { + 'hot_id': hotId, + 'keyword': keyword, + 'show_name': showName, + 'score': score, + 'word_type': wordType, + 'goto_type': gotoType, + 'goto_value': gotoValue, + 'icon': icon, + 'live_id': liveId, + 'call_reason': callReason, + 'heat_layer': heatLayer, + 'pos': pos, + 'id': id, + 'status': status, + 'name_type': nameType, + 'resource_id': resourceId, + 'set_gray': setGray, + 'card_values': cardValues, + 'heat_score': heatScore, + 'stat_datas': statDatas?.toJson(), + }; +} diff --git a/lib/models/search/search_trending/trending_data.dart b/lib/models/search/search_trending/trending_data.dart new file mode 100644 index 000000000..d3fac84d6 --- /dev/null +++ b/lib/models/search/search_trending/trending_data.dart @@ -0,0 +1,28 @@ +import 'package:PiliPlus/models/search/search_trending/trending_list.dart'; + +class TrendingData { + String? trackid; + List? list; + List? topList; + String? hotwordEggInfo; + + TrendingData({this.trackid, this.list, this.topList, this.hotwordEggInfo}); + + factory TrendingData.fromJson(Map json) => TrendingData( + trackid: json['trackid'] as String?, + list: (json['list'] as List?) + ?.map((e) => TrendingList.fromJson(e as Map)) + .toList(), + topList: (json['top_list'] as List?) + ?.map((e) => TrendingList.fromJson(e as Map)) + .toList(), + hotwordEggInfo: json['hotword_egg_info'] as String?, + ); + + Map toJson() => { + 'trackid': trackid, + 'list': list?.map((e) => e.toJson()).toList(), + 'top_list': topList?.map((e) => e.toJson()).toList(), + 'hotword_egg_info': hotwordEggInfo, + }; +} diff --git a/lib/models/search/search_trending/trending_list.dart b/lib/models/search/search_trending/trending_list.dart new file mode 100644 index 000000000..7eabbb8a1 --- /dev/null +++ b/lib/models/search/search_trending/trending_list.dart @@ -0,0 +1,47 @@ +class TrendingList { + int? position; + String? keyword; + String? showName; + int? wordType; + String? icon; + int? hotId; + String? isCommercial; + int? resourceId; + bool? showLiveIcon; + + TrendingList({ + this.position, + this.keyword, + this.showName, + this.wordType, + this.icon, + this.hotId, + this.isCommercial, + this.resourceId, + this.showLiveIcon, + }); + + factory TrendingList.fromJson(Map json) => TrendingList( + position: json['position'] as int?, + keyword: json['keyword'] as String?, + showName: json['show_name'] as String?, + wordType: json['word_type'] as int?, + icon: json['icon'] as String?, + hotId: json['hot_id'] as int?, + isCommercial: json['is_commercial'] as String?, + resourceId: json['resource_id'] as int?, + showLiveIcon: json['show_live_icon'] as bool?, + ); + + Map toJson() => { + 'position': position, + 'keyword': keyword, + 'show_name': showName, + 'word_type': wordType, + 'icon': icon, + 'hot_id': hotId, + 'is_commercial': isCommercial, + 'resource_id': resourceId, + 'show_live_icon': showLiveIcon, + }; +} diff --git a/lib/pages/search/view.dart b/lib/pages/search/view.dart index 4a582ab20..a78798853 100644 --- a/lib/pages/search/view.dart +++ b/lib/pages/search/view.dart @@ -156,13 +156,7 @@ class _SearchPageState extends State with RouteAware { GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { - Get.toNamed( - '/webview', - parameters: { - 'url': - 'https://www.bilibili.com/blackboard/activity-trending-topic.html?navhide=1&native.theme=1&night=${Get.isDarkMode ? 1 : 0}' - }, - ); + Get.toNamed('/searchTrending'); }, child: Padding( padding: diff --git a/lib/pages/search_result/view.dart b/lib/pages/search_result/view.dart index 210852f32..ce5091ae0 100644 --- a/lib/pages/search_result/view.dart +++ b/lib/pages/search_result/view.dart @@ -64,7 +64,7 @@ class _SearchResultPageState extends State ), title: GestureDetector( onTap: () { - if (Get.previousRoute.startsWith('/search')) { + if (Get.previousRoute.startsWith('/search?')) { Get.back(); } else { Get.offNamed( diff --git a/lib/pages/search_trending/controller.dart b/lib/pages/search_trending/controller.dart new file mode 100644 index 000000000..2fd8c2466 --- /dev/null +++ b/lib/pages/search_trending/controller.dart @@ -0,0 +1,27 @@ +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/http/search.dart'; +import 'package:PiliPlus/models/search/search_trending/trending_data.dart'; +import 'package:PiliPlus/models/search/search_trending/trending_list.dart'; +import 'package:PiliPlus/pages/common/common_list_controller.dart'; + +class SearchTrendingController + extends CommonListController { + int topCount = 0; + + @override + void onInit() { + super.onInit(); + queryData(); + } + + @override + List? getDataList(TrendingData response) { + List topList = (response.topList ?? []); + topCount = topList.length; + return topList + (response.list ?? []); + } + + @override + Future> customGetData() => + SearchHttp.searchTrending(); +} diff --git a/lib/pages/search_trending/view.dart b/lib/pages/search_trending/view.dart new file mode 100644 index 000000000..37541e092 --- /dev/null +++ b/lib/pages/search_trending/view.dart @@ -0,0 +1,207 @@ +import 'package:PiliPlus/common/widgets/http_error.dart'; +import 'package:PiliPlus/common/widgets/refresh_indicator.dart'; +import 'package:PiliPlus/http/loading_state.dart'; +import 'package:PiliPlus/models/search/search_trending/trending_list.dart'; +import 'package:PiliPlus/pages/search_trending/controller.dart'; +import 'package:PiliPlus/utils/extension.dart'; +import 'package:cached_network_image/cached_network_image.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; + +class SearchTrendingPage extends StatefulWidget { + const SearchTrendingPage({super.key}); + + @override + State createState() => _SearchTrendingPageState(); +} + +class _SearchTrendingPageState extends State { + final _controller = Get.put(SearchTrendingController()); + + late double _offset; + final RxDouble _scrollRatio = 0.0.obs; + + @override + void initState() { + super.initState(); + _controller.scrollController.addListener(listener); + } + + @override + void didChangeDependencies() { + super.didChangeDependencies(); + _offset = Get.width * 528 / 1125 - 56 - Get.mediaQuery.padding.top; + } + + @override + void dispose() { + _controller.scrollController.removeListener(listener); + super.dispose(); + } + + void listener() { + _scrollRatio.value = clampDouble( + _controller.scrollController.position.pixels / _offset, + 0.0, + 1.0, + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + extendBody: true, + extendBodyBehindAppBar: true, + appBar: PreferredSize( + preferredSize: Size.fromHeight(56), + child: Obx( + () { + final half = _scrollRatio.value >= 0.5; + return AppBar( + title: Opacity( + opacity: _scrollRatio.value, + child: Text( + 'B站热搜', + style: TextStyle( + color: half ? null : Colors.white, + ), + ), + ), + backgroundColor: Theme.of(context) + .colorScheme + .surface + .withOpacity(_scrollRatio.value), + foregroundColor: half ? null : Colors.white, + systemOverlayStyle: half + ? null + : SystemUiOverlayStyle( + statusBarBrightness: Brightness.dark, + statusBarIconBrightness: Brightness.light, + ), + bottom: _scrollRatio.value == 1 + ? PreferredSize( + preferredSize: Size.fromHeight(1), + child: Divider( + height: 1, + color: Theme.of(context) + .colorScheme + .outline + .withOpacity(0.1), + ), + ) + : null, + ); + }, + ), + ), + body: refreshIndicator( + onRefresh: () async { + await _controller.onRefresh(); + }, + child: CustomScrollView( + controller: _controller.scrollController, + slivers: [ + SliverToBoxAdapter( + child: CachedNetworkImage( + fit: BoxFit.fitWidth, + imageUrl: + 'https://activity.hdslb.com/blackboard/activity59158/img/hot_banner.fbb081df.png', + ), + ), + Obx(() => _buildBody(_controller.loadingState.value)), + ], + ), + ), + ); + } + + Widget _buildBody(LoadingState?> loadingState) { + return switch (loadingState) { + Loading() => SliverToBoxAdapter(child: LinearProgressIndicator()), + Success() => loadingState.response?.isNotEmpty == true + ? SliverPadding( + padding: EdgeInsets.only( + bottom: MediaQuery.paddingOf(context).bottom + 100), + sliver: SliverList.separated( + itemCount: loadingState.response!.length, + itemBuilder: (context, index) { + final item = loadingState.response![index]; + return ListTile( + dense: true, + onTap: () { + Get.toNamed( + '/searchResult', + parameters: { + 'keyword': item.keyword!, + }, + ); + }, + leading: index < _controller.topCount + ? Icon( + size: 16, + Icons.vertical_align_top_outlined, + color: const Color(0xFFd1403e), + ) + : Text( + '${index + 1 - _controller.topCount}', + style: TextStyle( + fontWeight: FontWeight.bold, + color: switch (index - _controller.topCount) { + 0 => const Color(0xFFfdad13), + 1 => const Color(0xFF8aace1), + 2 => const Color(0xFFdfa777), + _ => Theme.of(context).colorScheme.outline, + }, + fontSize: 16, + fontStyle: FontStyle.italic, + ), + ), + title: Row( + children: [ + Flexible( + child: Text( + item.keyword!, + maxLines: 1, + overflow: TextOverflow.ellipsis, + strutStyle: StrutStyle(height: 1, leading: 0), + style: TextStyle(height: 1, fontSize: 14), + ), + ), + if (item.icon?.isNotEmpty == true) ...[ + const SizedBox(width: 4), + CachedNetworkImage( + imageUrl: item.icon!.http2https, + height: 15, + ), + ] else if (item.showLiveIcon == true) ...[ + const SizedBox(width: 4), + Image.asset( + 'assets/images/live/live_@28h.gif', + width: 48, + height: 15, + ), + ], + ], + ), + ); + }, + separatorBuilder: (context, index) => Divider( + height: 1, + indent: 48, + color: Theme.of(context).colorScheme.outline.withOpacity(0.1), + ), + ), + ) + : HttpError( + callback: _controller.onReload, + ), + Error() => HttpError( + errMsg: loadingState.errMsg, + callback: _controller.onReload, + ), + _ => throw UnimplementedError(), + }; + } +} diff --git a/lib/pages/webview/webview_page.dart b/lib/pages/webview/webview_page.dart index 60064acbe..7f106b141 100644 --- a/lib/pages/webview/webview_page.dart +++ b/lib/pages/webview/webview_page.dart @@ -196,20 +196,6 @@ class _WebviewPageNewState extends State { } }, ); - controller.addJavaScriptHandler( - handlerName: "onSearch", - callback: (args) { - dynamic title = args.firstOrNull; - if (title != null) { - Get.toNamed( - '/searchResult', - parameters: { - 'keyword': title, - }, - ); - } - }, - ); }, onProgressChanged: (controller, progress) { this.progress.value = progress / 100; @@ -238,21 +224,6 @@ class _WebviewPageNewState extends State { document.styleSheets[0].insertRule('#app__display-area > div.control-panel {display:none;}', 0); ''', ); - } else if (url.startsWith( - 'https://www.bilibili.com/blackboard/activity-trending-topic.html')) { - controller.evaluateJavascript(source: ''' - document.addEventListener("click", function(e) { - const parentElement = e.target.parentElement; - if (parentElement) { - const trendingTitleElement = parentElement.querySelector(".trending-title"); - if (trendingTitleElement) { - const rankElement = trendingTitleElement.querySelector(".rank-index"); - const title = rankElement ? trendingTitleElement.innerText.replace(rankElement.innerText, "").trim() : trendingTitleElement.innerText; - window.flutter_inappwebview.callHandler("onSearch", title); - } - } - }); -'''); } // _webViewController?.evaluateJavascript( // source: ''' @@ -263,11 +234,6 @@ class _WebviewPageNewState extends State { }, onDownloadStartRequest: Platform.isAndroid ? (controller, request) { - if (_url.startsWith( - 'https://www.bilibili.com/blackboard/activity-trending-topic.html')) { - progress.value = 1; - return; - } showDialog( context: context, builder: (context) { @@ -340,9 +306,6 @@ class _WebviewPageNewState extends State { return NavigationActionPolicy.CANCEL; } else if (RegExp(r'^(?!(https?://))\S+://', caseSensitive: false) .hasMatch(url)) { - if (url.startsWith('bilibili://browser')) { - return NavigationActionPolicy.CANCEL; - } if (context.mounted) { SnackBar snackBar = SnackBar( content: const Text('当前网页将要打开外部链接,是否打开'), diff --git a/lib/router/app_pages.dart b/lib/router/app_pages.dart index ba2a1452d..b760faa59 100644 --- a/lib/router/app_pages.dart +++ b/lib/router/app_pages.dart @@ -1,6 +1,7 @@ import 'package:PiliPlus/pages/fav/view.dart'; import 'package:PiliPlus/pages/member/new/member_page.dart'; import 'package:PiliPlus/pages/member/new/widget/edit_profile_page.dart'; +import 'package:PiliPlus/pages/search_trending/view.dart'; import 'package:PiliPlus/pages/setting/navigation_bar_set.dart'; import 'package:PiliPlus/pages/setting/search_page.dart'; import 'package:PiliPlus/pages/setting/sponsor_block_page.dart'; @@ -178,6 +179,8 @@ class Routes { name: '/settingsSearch', page: () => const SettingsSearchPage()), CustomGetPage( name: '/webdavSetting', page: () => const WebDavSettingPage()), + CustomGetPage( + name: '/searchTrending', page: () => const SearchTrendingPage()), ]; }