From 4ccea084723bf4886df83cef47aac0c5368d5432 Mon Sep 17 00:00:00 2001 From: csw <471155679@qq.com> Date: Tue, 30 Jun 2026 16:05:17 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=92=AD=E6=94=BE=E5=A4=84=E7=90=86?= =?UTF-8?q?=EF=BC=8C=E4=B8=AA=E4=BA=BA=E4=B8=AD=E5=BF=83=EF=BC=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- assets/mine/copy.png | Bin 0 -> 306 bytes assets/mine/def_avatar.png | Bin 0 -> 9483 bytes assets/mine/little_left.png | Bin 0 -> 231 bytes assets/mine/little_right.png | Bin 0 -> 203 bytes assets/mine/mine_top.png | Bin 0 -> 32164 bytes assets/mine/section_bg1.png | Bin 0 -> 1921 bytes assets/mine/section_bg2.png | Bin 0 -> 1776 bytes assets/mine/section_bg3.png | Bin 0 -> 1018 bytes assets/mine/section_top_bg.png | Bin 0 -> 389 bytes assets/pics/cate_sel_left.png | Bin 0 -> 1221 bytes assets/pics/cate_sel_right.png | Bin 0 -> 1224 bytes assets/pics/esp_bg.png | Bin 0 -> 8429 bytes assets/pics/play_tag.png | Bin 0 -> 2293 bytes assets/pics/rank1.png | Bin 0 -> 2184 bytes assets/pics/rank2.png | Bin 0 -> 2215 bytes assets/pics/rank3.png | Bin 0 -> 2199 bytes lib/global/client/play_client.dart | 99 ++++- lib/global/client/user_client.dart | 11 + lib/global/request/api_const.dart | 14 +- lib/main/main_root.dart | 7 +- lib/pages/home/cate_page.dart | 318 ++++++++++++++ .../home/players/page/drama_detail_page.dart | 66 ++- .../home/players/page/drama_esp_page.dart | 220 ++++++++++ .../players/widget/player_bottom_widget.dart | 14 +- .../home/players/widget/sky_player_view.dart | 396 ++++++++++++++++++ .../home/widgets/daily_quest_widget.dart | 8 +- lib/pages/home/widgets/home_cate_widget.dart | 9 +- .../home/widgets/hot_cartridge_widget.dart | 5 +- lib/pages/home/widgets/rank_list_widget.dart | 12 +- lib/pages/like/pages/collection_page.dart | 38 +- lib/pages/mine/mine_page.dart | 106 ++++- lib/pages/mine/widget/mine_section_view.dart | 93 ++++ lib/pages/search/page/result_page.dart | 55 ++- lib/pages/search/page/search_page.dart | 35 +- .../{glimzo_user.dart => skywood_user.dart} | 12 +- lib/utils/tools/help_img.dart | 20 + lib/utils/tools/sky_time_tool.dart | 2 +- 37 files changed, 1425 insertions(+), 115 deletions(-) create mode 100644 assets/mine/copy.png create mode 100644 assets/mine/def_avatar.png create mode 100644 assets/mine/little_left.png create mode 100644 assets/mine/little_right.png create mode 100644 assets/mine/mine_top.png create mode 100644 assets/mine/section_bg1.png create mode 100644 assets/mine/section_bg2.png create mode 100644 assets/mine/section_bg3.png create mode 100644 assets/mine/section_top_bg.png create mode 100644 assets/pics/cate_sel_left.png create mode 100644 assets/pics/cate_sel_right.png create mode 100644 assets/pics/esp_bg.png create mode 100644 assets/pics/play_tag.png create mode 100644 assets/pics/rank1.png create mode 100644 assets/pics/rank2.png create mode 100644 assets/pics/rank3.png create mode 100644 lib/pages/home/cate_page.dart create mode 100644 lib/pages/home/players/page/drama_esp_page.dart create mode 100644 lib/pages/mine/widget/mine_section_view.dart rename lib/utils/models/user/{glimzo_user.dart => skywood_user.dart} (88%) diff --git a/assets/mine/copy.png b/assets/mine/copy.png new file mode 100644 index 0000000000000000000000000000000000000000..c44e0f3edde35c03bb9dc9ff0ebea3cf3926b512 GIT binary patch literal 306 zcmeAS@N?(olHy`uVBq!ia0vp^LLkh+1|-AI^@Rf|&H|6fVg?3*IUvlacGk)SD9BhG z10b%7 literal 0 HcmV?d00001 diff --git a/assets/mine/def_avatar.png b/assets/mine/def_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..1c832f02eb13337b46e7146b8aa3308b02d29698 GIT binary patch literal 9483 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%0D&$ow%xn-kn#)f?L^uMtf$&O%~Y zWb=hf=f$|+-=``@`m#zfCyft~hLkaDctXbNid!3(s(lTCW@!xky%SvU*|9Wp!>uW6 zy*EWVg|IVPqXb*ZqUVB8uvNB#(j*zUOd{Nz^a7#^8YCuIJ`$757eNMH7WkYq>kvy0 z`?x?vXz}_8&dN}cRanFuQEuSj-h1Ka=gyV()z>4T8(tz*_ErF#unO!NX=4F~ zBFO-19?>&}X=qVtS&g7gQr>;Ly>H-{=Y<(LnVhL%{tw;pPNI>lFp>~dBxs3xTM2mO zl;d=EG3Q76$srW!smG(3w^Bc)N)TIGa>`=?u9hH$Rb1rgDpynq(Hc$YlxNV+xVOG{ zqKDNO7@nM4ef5eq9l$UhP%Y!s-Gh5ky-PFQLlj%lePC8muN{$F6!3Ggh4Ag!MLZ5>?gW~X_?8*r>-YYpL`R7Gkjed~MSceZ}71khab zVe|>1lY6a!G0q>n(W*#mzJtpKj(wP^vFMh^<^ra%d9wj+r_x7q;nBOycfb)fGW~<* z!jBnMQn`?e?c&C!Z!d|7P*2aUEMzNK9G|igbUXrYrOg*ra zma6@fyYll6+VsIk6K;Gp|0>|#xcFXM6PAOX4R7$m$G99R_(}p}+UK|!{y<|#4-9`r z28Uo+r%ibYGe}`(@5vz_x{DJUq#lFR1N2kzFrj1i*H*5X}d!r>?D{tS=NF}6Z;}j7Ty!5 z4{q?d7~zwWb%CFBol)`$F8+#sUHw)c1nt)gJvmQ3SiHSqtlTyfJb=F&bbq#Y`8hLj z=G3|8^&MQl9C*8W_x{N2^FM4Xd_VBXjTCrNCU@+%l3}n8>oZPcqmQ*(MXizX01awl zgQvU%)ZBN5;v?s-?itt97!NmQ5<{xRoCsd0OmE9g7 zEGGttc>F=ZiJQ6cdRYJe*ek z`)%< zD&|JwRbr3G!0NdyNvu=#a9OD{sNh@JYnK9i@y|noIM^xuHk{on~p)P z%8*g`f}tT_T2nQwVEDIs$x`><^JbO-i1pg<6kR7)ZInV*kd?bt9*muDPv0zP%3A4@gdS?V>oX7;kp zJ@;O;ER!_u@+RemQ4?k`;qs{^0E$?*i48phH-~YpwtH&RW=2D_SgwDl?XH{CUgm@o{8f;VGn#endR)}%EnFB_ zd|6ezs>VSb=0ZO6i9EDiX?>(oKf#AEv`LEF-oTS$Tl~XPq~6+tjwge6GyiNX)Rt|Z zBL|df0b>TE+?&On}l;;aqk9&R>P_A5(Bp$-)wV()B(QjNNhaPvyI`JvPFAv zp*?7y-i*BYHj9unqE?LkD>qWL39oJUp8W!LCss|AYatoXtlT5D2zB-iWws}L$9z{3 z(@pa}%s*xXXySjiyfxbxK5lPC7+B()_vl=wd?*DENDE`w1)oO${WVxaRpZA{bbzx6 zqrCOFFD@!26yujYfZ8T1yLhHg?~f&l!N5qANyz#LINVB9!u~W8e*azfqfd-@hm| zk1WMs8a^L79!Km7(inX*w_wfF*6uae_pgl$>zr#r_@Ba~7W%ut?)30B_*OTNBl|AX z%n9y$chr#sdoGbM?oFEhgp=j()IU`n0Vhm>%o8-jZ=u&GZ2eQ(($C3y+J8(8dUNBk zrS(5P%CQrUx9N_eQ~c%KLhh8~RA3wChHrHTWI`T8AmkX1t+7U*jl11B5^6iv^HbE#L1ggXF`s+OAld8u|y*Kd|eg02^24a zhzAEvK%~88rmLHS7mI)y1BAyyjQR(S$Yteekg-*)!)h6g%x=>tY5e7cM5yu(NfF7l zRl@ndN+PsmJ9ZWaJy_kDta#N`8yid^yVeetIU!L(aECtQN2071^5euVW0F($`e@X? z)${wY&=N9M2lV2zEQ1c>N0HA8Or z{D0Ky$03*)Y_Kt*m|F#}@{aANV>tw8vf3hYjGh|V9Iphk{@DmtZL0IwBf}|48kE2~ z{5}e1N>dT|L43#Om#9G(ZfS2KkHzHca;_82_WLdPD;TM*fJ_n*g^K{Gp(DX3T+9sN z%Z9{JjBQdcyB%>KetY+k6 z52JPbSnEI`c%OM`<#k#)8w5aVs{r(NExvGz>I$eTDn>-C=?}70M$O`U<()_*Q!XZg zV_DVG$jTJe8jX@4SKZpVfdbEjJa}K03-8qH)4EL#X4N5-%+QIyC^y+5)wWr3ixdC8(IQ&Rl@u zt!!(N0sx7d!y^Bw*4bkSu898xp+)aJVTLp2dTP}nFDAZHQTN$(^L(n@=l*icdZR2w z8n2e53=Y(P;*v205~sP29;>a$eFH(@!ysv*w5Yfa^tAawS&A#~ zqfTyt5#GbYqn&^I=#>QjAE_Qr7(E=iU#U&QXh|_8xoU?N`!V!r_m<`<-Al4+7emu%tE2!qf1@ z)g{P@j`;V7UVB+Kn;78dxL#Q-e|cQd_ef><)vjr#p$~KJDlAYf#YXK?%W(*NJ};`30vXiL1#$;VMIwqX2rO%Y#lVVb5y@BrBH?*}sk;Jwo|A8@;KamG#WKL^%HmOHNq*l|5Rjuz&NLN~nmt8PE&th8cvg((U zBcvmp1raa^neq_aglP54SaqWmT=-)UIR&D4B07p$aY}=kr7LoH*eg6{a{@FfsVEd{ z3d9rRm|~Y+0c~1n_I8VPHUmlcdoyMueS(LGVE1bY8h_L+pcnia7r2eH9JJjl7^TBX z=6yverYjk8{}Oiw(!dI|{hg11UKJVh-`-NVU5&_>)-SO4!ko943ppXofU)UIQL_UU z#z`g8aGD@By2M#bD7EQebo~?ad}J;4WMV66z@1BbXHTh?da#z7v=+yT4>skO3i&Of z^Q2y7d^n(BE8C4nF-tpl-r`17Qx&%2Uc7uKaWj+1zf>(MdaSP@+wNBE@OetQBipF++@fNk^+iMi3qr~G3{dN3IPv*|kdRrRce_m*v? z=@n_yEdz!RJFx;yVwY!Mbk|IsrWJh6gkKnoX6Y-kuxCq`7sl}EyZxRQ#usoo0H1*A zJPJ75^Rg3!YqlbU;A;~?YFn{eM7J55lCPrQi?~u@ukhNZ3yNSDCO521riphrr|n%^ zkK}rXL@T1A^_JA~k!b|CSgtbIeN;{wM76e=CO30LQRfaGe?u$(1u`x{*CX*3Kyfsb zF&0`b{HswO6NTTJ_&5Ul>kfVw@yj17?D(~}{ZM0erw`n)@oHs{G14Ex^ZpD)2|W>z z+Al3y6$R=~bi!0E`5w$zP&DU&jTT;EyQ;fnx6c4ztBF@7qf!W~OLMsqV0CTi#2iq+ zAYp;k+vRQYG^*Rs<&C0XTEZ-7i>Ps^+1+POzo;kxCA)3~w|y+j1X73A@teY6O>0di z!7wp*X{aVlhGDHLM>!8kW_hh#375vcIAVtL{|tWQ!5eO4!p!|OdfDDdc@&Wy-EQ&I z7ES!gqrYGmPWe|EPgz)HSq3ZrtvPd^=Os9$hXE~7o2s5Rw%$X32672&J0=88UU3e( zzG1O3ov=&oQV|8ysidaikN80W$8Ouh25b;_qN>{gN-cr(g2QI;Co#ATM?=MDUluX?aCw~C=F1IAGos3c^q)DnE< z6n3%RYd|R#@G<|&KN62?NV}8;?$7a@eNT|iojXo7vGTw#O=&*|maIuJs@&ol=0#G& zAL(_MXa0vNgZa;Vrbqyjy!lA(FjGu$f9C$9JI|^I()&N%omQ^l)?bY-VzioA#9n_v zGAcw4)558chwiZ(D7*ZbBOFxl+77{KcI~p=&C$HAL5(zYk7*Hv1y|$#@(pYKtGcN8 z@V%(}-H8gG{yb4c=4i|Ai@6f3Z0GePi+KTfJj!jv{aKkZ%TJh|9A>L4hF#NNKiv>m zEW0HptzO{(Pd|}S%WmN)(NN2y>5mxWVWO}a+!ddKq-P1@nIl+5p#1Oe>z&*d$__5L z@Z7kDOD#w=j3PvRs&od0TL&oug+DwbieiJLPnHO4xwg^IRaRfc{RlW%qbYf_P$nmj zmkOjB8{V()jGT#A$88Rx^Nq#~;)ZsRZGHkf6q@BBSw;~YWd2rSoc1d~m2mT9LK=zJ zfIZK18XQwh|hCE$C{fkZDaQ=@@q!t67CtpNcD zr;iio2$oM0{#+epB6t)qME8~!r&MWj>uZ~C?{PlC&bAwpY-C?xZ1cFT< znjG^4R^~J=-t>N8$`V>qZp1T1FZr0mR=A-xvJ)u?ScR{^rj#2co4Naj>PQowa5|q) zLgtGcXawy@lu*xQ+iD~v=s5J2`8V8yY7y3$5)!18EeOPO7eur8jaSb41A~W5b$m9< z79q@5o{nd-eTMGGYSghW!QJaN_1^lMAPDXp)Jr>dMhgMbmB1j|1stP%YKv<$LDv6ZJd2$J7Zdu>E3Vx;7CIvTRyCMtIb``=mhcjht{R~S5mF; z_~*ovjS+p7GlgG@BAXQX7e$ZX4M+MsrB(bua)fKrRc!I`BQO|WZDn&{)hBCjB zQX;efb-7lo@BQ4-<(t>Qr7+o}nUQ~|tyhh1N_wUEqVonxFmH-SFlo6Ggmis%=kbKI!Dp6*Y8}77EnG?2qZp21U@LOI^Q4kR^Xa__J9u-2Cje7qR{MPnfo+9caBSts&EQHugT5%2FUroB~_8 zbUykXUQ3Y#!x#vcgQ$*6HVI5MT)Byvc`EX#i&Sb1q>4I5i1J}5AYBt2&FF zXn6@xEorLDT5?6X-Dmq1F+BdK++eou%gAPu`6Vh5J(OmFz znZpcLE|PxBJJDg@5i_#4_VO82jp26x9X*rOzog`VS(A0}G;ow0ZOXg7_O%xtoI;7Q$=z$ReP9Irq{HCZ~(!8~X#iFTlV zSt)ZM1pVW^XwaR^;N4l?tL?xh*{UCeEoF4DaC2K!v)Blc-*2OZ0#eTI(}-KJ-RsUN zGbwA~^mAgwzogMZ$@xm)PVzcx;Ma=sb^Hj?F~`Wy6E=q#C(zAKpJXgiQ2|>W+9Gw2##TiN(%5dhvVtFS`lmAe``PCW35>l-o2FH(9^7`Ecj`GkNB;n zo>G4sZ3lQ!Y?=dYC%;cMNQOF}*Ks>dw5(%?Eg=<*|Ai)mO_TW>I4 z+aG=PhqRgPy+jfP4Fsd$Syk+n=YGOCeXXoieO$1eX=^XH5tySf8Y3v+>mmGrZB3#A zt;v`Ti4kq1Xc5*fJLjpRE|}RCT=o4sIWS|sh#4iXFGY_KyK$GvD5I~zMb)Z{)yEK9 zrI3T2#hO-Qb{Wae1yTt(l>2KR&w^#qYB!LuhHns!*?J*dXb3b46$tP&e{xjkKjcB~ zznouE)4PL+d8rXh0L6*c%~;#IG*^pHrsJr=3Ei)0L0tOrh=!vEp!}H(FIVT#ilgbu zRF%?y*<`==T}^-+tF4CCS%TVxz(yqgTb$tl@_sLDQkaX)G$#K}7!Acm zi#nPwQTWvk^j!4F1xGB5C_RBjjV(y$CS9#$dXcGh8nlQkyQnLTq|RItjcG8zfusE7 zmk-fmg_RgpK2#tJ;u?k{bNR9k{9+??055KDLqd(KM-{B7?#M3PohlfGMiUJlHv-^W z!7OEOv0Ac_$`98j|`oPaztCFKGA2D0txgRec)3 zEUFu8<}g6NIod8dcFc&?)?0@Mi3r1QcLB`n7)H&@B3#}i>U!rigvkEQTk9glc5e?W zt_tJ#J0}?2TJv&WFkF1DgAcUe7i@cwraiIamVQ@}2(o3Z0e*YQM6lus=B@qf0U8q5iW**+1ldOOdA7L)%Q^jqpPd7CxY~fVqS}w*0r37!@TI1fWoz_mq z!mBiD9z{`07lc$N162%ZBHpAT~nMYY%@yoq)JKn;>RORBwax#X@1-ta6 zg%3{9dac^R5^60Lz8OAWS<`vIrbE|$nuSZV@xHdffG$(OQj9YCBY9IXn&a58bF|6S zRODY>p@0)Mz~!lTj5a`l7fa{b%wRvQDnT34Y~nkVdN85sCO$s5wUI>KxYmEpbm$7` z?f_sG7de6QHa6$ZJ(p;!BFA(XsAg{cq64Qeu5t-xF=&wI78#GQX|`qnBtgJYlk8=| zVCm#FX$|s%SHrW`#NN&xjM@sM-$UxA%3RxnP+l@3iXa2g=tSn)Ii6{U zBCskGM?83JO8#}^H&vv-PtbS`7vQ5QZ@UX;`FZ$GP8#BBEpGMsn0nS%JlV)QjxuZc zXAC!Y4lX6kd1w(1=-Qk+rr@tq+F}$PVtS^QBci2r8B!2*+vkMt-Ixj76!?nf%g?Ll>z=pC+)aB#{PjU{Rh;^g z4<6TRD9fxWzY7m`DG`I*zQ(6Iwo2kh%M1>$YmcDF^yO)uJeAXDQ!L*=9jC+4L86z5 ztWzsQHQQ)W_0WiH;^eoI&8f8C4!L>9$LN!mA(>`HJ8M6HHYt&a@!tIS@op8S5O_z)rXuQlW zNVcA}`1H8~mcFeM9Yv~x3=hT4jwLxRHx>A(r zmNO|s{-ydB!}$nAKL7i!?uT%C3(7xm8Rm$3iSU`MNuN+O>u5<8)_ZDPG*R{WjjHd)JI-_$*T$Q-$wGK zD|1@>Gznxzr2f|?rc||&BRbFraRuZX73Lf78nP_MR%dgc_}%fV1TGP_{p^ZR13jy9 ziIKypsI7{!2>bu~wsIpLT33u$KCgYxiz%S*%!sj6Q zv=PnEOf5LG``{o(5%`?%v`yUOH!Y7?8gsaKp%JfAMJ@)((LDbP;r98|sZi^$>g;}h z`!92K&L?n&O|TzV$0X#BEpnDy`c+01Mr+{5=55PWnhl+M!G^03Ul4e9GlvxRa4s4A zp?zmPARJEm4Dhn1>6Wt^9IJ+vu}|TeKJ9p_(jnSU2dau}8V?hvHr{M)mF8gNDLz^0 z`H+$91qghdz>*BveNrz`FB1XlKy9u#n%Aa5f&`E3)?Rf3^AiGG)Wm5=jd*p(6 zL?8HR#{AKq$o9RE&b|6n$#2 zxR*Cy7 z&q8Ab$mnVXMouWj_^Y5O78-5%Q4$+Ib;MeNc1fEsmJVbYkqC({Un4fF%woc6A^p}8 z0}DVYe-t|Li**5$5g{GyCZ$518^qq20aki-4Y~n7klCx)nNlVb*?qLGL(jtl3^ixD z(Xv?*{7e}F-70DH<$A;>DDw}bi}Nx>RZf*J@cios0ugmgr!@GgPl&!ssK-USsO*_7P#EK!t1Od(0Smh4Xc^keLv|`Z+ z$!h9VkYL-J>A;-NI{4yD7P`^X)MJB<(DF3f4C|keg()C7o?oriFW5agRTm?M)4d-v zDIG0We-u4$X52$za$ic0H#+-S^JKUWt~m}-sln0Sm28SP9ioLkX7X$!BW??|=a)QA zmxtqn-JnjqnMrnXar^Rdc?c3L4)_7?tL$gS29Um3=eu;spgd0!`*lb*uVTB}&^6|C zY8vB`h&18FALD~O{rDG>6Y}Q0sQ2R|HZ}0^O(}R#t)dD)e<3;y;?R11>Qd%n)m0L0 z?z>LILSv^QDN5+`<_WM}<42DHwOHHplU^RPGI>y1x%<{ih;NaQ8r5$aw)4q_nc>-&cjPQJVAPr5; z`9gvxP^+H$`dO}7L#?qN46V%O6g}rV>>#6rEITgAJX@lfj#&w!1>tt!(w-1R0~@pS zhtRqm`~$7cNf@zLECf*}U2=quS+^%+&_nEaY=i~nBJ9(j_yA78SSbpH*Jz9j6@A{j zxj^O`ZQe7;1D|SFQ*Ex2U=7eN%Iu@iSIi}8Iu9p(q}i149iK$|(rqK=YQu~`2mbD9 z-KeI(i98ocTQ2Yzf~_%D6z|w7M?Y0o9Vg`hz2u?wa4RFIg2!p*5@WKzH#V7~hfrPu zTjvZHid&42;dN8d+j0$-46!Sfgc<&hpFy*Q>+0TadoRgypSAd4?v%Ja@?bPAJ@?VM zEbWi{;ad4Ok%EICe@qyiEY8Z4rVdq;5=8Fewc*egncNwwKuL4yMIrdqG1Gs#q%?rY z^$wQ!@x$Y*A3Sg$3Sl8nd!^77ZR9~n)^hl_=91j$sA0{;x(HrA4yn6l?AEf)PvKp=zo(^%LV$J*>6d+tgw?A(!p2g1- z>hu(BVO5@{5uk5tf(10Jn>~^^aY4nGT0d=0{^DHDu{YPF57W$gp{P5<|NHuGEZbVl z0Xkp+4lee_k`}ED7sS+Z1wyRkXfM%#GH&+MGVHc+-(FMUP)w%`jH}mEx;1ndHyn)= zPcC~gw)HAGh>>|o;tlcihfF#oz2k-3QXXjH+GM#2CuGHQCj}(tgF{-tG2h_Q@FUbT zkNKmix()*X#+hvUlU9)qJZ`dgI|4i8>D758ab<|dNxKx{%vo6s+!eJ-1w4A^P_9WM z6R6A)QDuni)uQkEecl5O?rpEg&0|PI3ebQUBU1is>RLM^?!q_EL!Qik{(={2&OE6U zaEp#f&8IrQGJ+il`Wp=`$GuvUXYc)PMy;&>vh!?aLg4?E_f}1HEnT=U?gUu4yGwA_ z1q63@cXxO91c%`6?(PI9xN8XR?q}`2->P$Ss=goa-OQ_5vuAe?>(OI8PYFw6S>d|m ze(`>$^enU}V{ozN_-wEWMj=VFJ4rdV4Q!&AHTZ$B0B^mEhm}*B%;|j<-Cfly zUDcKFeb_1I&iflL>K~rjh8D>n8mgq-E6nXexk5ZcVD4QGk;M5n+?+>2Qqh)^jfGncB$Kg6pp+J}32Aq@G z@%L3Z#;XX0(UQB=<7LXep{-13od@RR)Yv!-wkSsqoS|NPV`)+Az1CEr9{LZQ%NsS&J!ENer&*wG3lpSCGsYG z;~DB&INHOT+pyQvkzLbz-E=}xa8>Ossze718-e_!Hn2!#k>MD+f(%U)QyF#x#qQBr zumT?|$bQ0(_C)(848ifmJD14EQ)}<_MZd^(#7JaQcyr$J_1=8Lg#+xObaK*m)=W+1 z)vR@lq(@9);yb;}#j)lM5r!GtR9thH2SI!s6IF$s3X!_#!KHv*DK|l)^-F1f1zF>@^O@z79~9`e_G>~dXes6 zw6tQdgAh@2NcnyB8gnvecULP3&W6U3Zgi6Fe@6mHI36^3&qisY}Fv%=?CBAzQO6Enj^oJ zILz66SJX}mJySb1_yL=X_)6?4__kge0CvCSd!I9H!D`Y1{s_NUeVr{+bN8sb`5#@gf1JuTwQ}jm4k1+jLa9Hp%{TP{35A-ITr=@EP(bS*7Q7 zpmr6EoyB|ry=_(6txV`p?fbTm9q;AK%J$oH?F_2;tDF{{mTDWtpIP`6#!cROdd~7! zsv0$u09Zu=yDB`wUw$WUvJ6wNBhxoj9@5x9kaw7TeVU85w7v1ImCE^o;FAOI*&MQoLk0psG6){Gd( z8P31>(3EgJ);6s4KVu9CLjqEw~`T2K~S zt*NTVfQMK3x9q!gK~}a&%Qca5W@V^nsKJIOFxcxhk2V{;wnwCw%8cb{bxQ}E6COR# zbh`y27@uATqj64)J4zGgw<5|d|8|#c53_pcPhrcKS~VzW)~ku32HN-$W))aUQzco? zwC9Rw@RS4I+k;zcI%>1ip~SpOtv=(B!hN#C)B*Ss?R#i* zkNWx3Jh2?kRg#PswJ>C$5<7)iMqu;A+`QmhHnR}&-j%xRH8wu(qp`+;%7#l zh^LOPA;so-YKn8oUt$Vz@Km(8-Bwp;6Sd%e`Va-fwr&;8#9YhMVvxqiHQFFRe<#wg z7<7pRnta1T@Lw#y0Ck1qD{XL8T;m(H*%{`Q@1E2;G*kWxzt^|g>3uOMdsAP%&th7?2ie@$c4R(24;XyV&Jq-r@Ie+`NFU2=!nfvW%yk}FF5^F_3ETeF-CybLgxK1@|e|+ z)1_(+MtiBFIQ6c?z>Rt4aDmlu=e)Fxm~XCT$L91bE7H)a*+KF3%7bu#mr3@adHHPi z+p7-KN=aGO6rAGFkY~LP#yQo;k&i+ zZ}XCcJ)jy&`6cR3_!9~`!Iywy-bOU&wvAszuqSNKaB*fAFF_G{K>j z-5&nz0b8mkERR0}HPWv+8m!vHLDDUe5-FpRXpL2jetaadYKoo=bzGKbHtc?1-ZYyi zeO%=I7Mt4C;Fd~HoTeucL5uNDdMRxJHs zxB07FJ;+eO@hcuYpz5q++BWpAD4Y2)mPW0(sEJAK$ot-Kh^`N{^6L^yec(k!9vN}d z*sNx9l#h(m1r4t#ahQa5%8GJYx+-ssYs>5mSKa#f?` zHMBUlvmmBzX*ZMK^V~*-fgv7Zv!Vr9tv?eBOn)_f)m~O11=p5LI+ayI`{|zlB#ySR z8l%o6EvIuGsB6|ualQ)M3Ijo*1Rb>IKJ20zBoP0DFj!~0f}dr)iz>WaSh1%IKSA4$ z?_jSfT~+<8&FrMT!l$)SGit{@j1Gx#pLuhzhdf}s>xE;rGW~ec+>zSjD{cyy`g|)2{(_!iR$^Dkaq5?>YuYtt?LTX}LnkVFiy!z?oBp^1R;O!_{exD#2Iu0P@tAs8;sS69y>!b_6Pf$KrT;K`{W$y{-lLtqHQG|Jw zx)Nqpedkx+g%aPj53Lel+Fv-4X;+LJKF2pq2pej3w=^j>F76n9@rt{#J`1Z7EuPjN zhha4lB{^kyXWox3CD@|!hleiSJlwX5i z)Pi+?5B92)>_Qthh5V!TCnTc*n{})-k=us&uVZ3Bp!LiiyN`4qAj?L`EITxuzb6Mk zw@XLzsCM#82S44gxJ256brDDPfk{Yg@GHzTS7~J)6oeC z(eXBJdUef~LwcE#BeVt6@)<%^IXk=k)#U4_%ckJ*y)!kdN^G;l6Kt{4vA)HSXO65z z?#p^ILmk3(HNNh|{`v9*EUVE83&Qb!b<}e;7AP#{JAumT;t8kB21c!D;(*f^bp%PB z0iv=QWD@@t^XSicWxxB?Q9gpjTjOuR@f~-mh~bA@jj-QcCX_z|2z}syH;q z<)xKQUyBvqWkA(H?fjc&WU2pXtcM563Okw83RhvLcf;Vb@oANL4#4*zXajBga)a)H z)KH*I6C}n=)Ww|TaQfNE&>Q!BpZ#iE}5%Duu{-^;>4#_&e){qo8gc_rUI&qAA7D6VL zlxrP}dNu`PM?&0@+BP~qn+=y;7_H^$CZ`(nsg0<{N(U;u`{cLTn*$cM{ofF=8{CH0 z!jv|IOg2w$6S1KHXR04|RJjVTY$KC2p*0;9Y|l~-Vn5Bq$YSdP{TuRkz%&8e;pv{zXM;dTPk@$7xmZt}f39EAh&XGfdq1@>e91CI-Ds6>`J_s|Ppl9}rirND!92!FuI^8q$4QHcm7&Ww#<(u}WT* zIZWT7OCBog0FqHw9Ded+3Q-Fu6Dm9d?!Uq|XHh+ce`GAE_J?3F^%6SJ@)Q545U=zB zdQz2OOGqD}lg+Hvjo~i7Mv=e;S3uYTLv6)HG>=NL&`SI(13~Sy-Kl6#t_w~|S8I7u zfNR8;#J*@vYFlZ>;wrz=YCGHe>e&NwT+}$nR~5lANk7> z`W6E0;u0bvc>ByO*G)lb(%`Q4KbRwHY+B;=zt1M4JN|mmY_I=eG00)2Y$tM*4wGGA zKFEKJIaB^d=N3Xs=jU@YpfOlQVbZ20r%-A;8gGR{I=PPW{^H=~bbx^1YQElLA~zB`pYc!h6>bg8 z6C)tRWP>&1>A>23b+)yjBJZ&%5Y^JkN?Ov>bFA**%e%U=fjY&${K(|Lz<(;><-7=D z!_v|uDdZKR63x^3E3<9zY6t$7QHgmBf1;gAyvg&1f5N_delp|PRX>@JusKyWMN+%D z_i8r|rWWV*}++jsuzvFeMP_+9xD}R=Ux$*T5I*XuQ0Yuo(ySi0fIx`@LP& z1+26w;n;TVpc>KY=`vL;ENOq}Wj!pbA$r5Y?iNpM!`$j@!31o!A=ErgNc#qWZ@Kpi zGS&u7=sS_S?tC1jikdXgsvt#@u-NYV%85B7o|vu`@7BOpq%x%|lK!OdIquV(1?8># zGV8#b8QNH?8a$QI`SRia_7ugWzvnI5=to6X<1LZg-zerYXm}NZ`n>-o6Pby$-3xgp-t&^Jeo_6fC&A{Vb*RJT5$61B8AZ@=l!{%b$}lz;Xq+h^@`m zxanV=wIO!C-`Qe@)~yTDg~CO75qo}4ito=vz82s`U0$f;7)2rKE79mzdhgn|R-{=& zzEmA3#@78hvqtC@WFhi!h2*v9ZfX-rvYM76Qlb#lUk0M(^^B(2h?CBLVV>q0xar58 z(p7J2%T70xgP(YV^r=H^eal6eg|#HB?CVRqQ0rtoz? z%fES0V~DXWEGMaGp^z;i?(Vo_^jVvcFe>*QKS@GW&{s=8KxEIFz3I-crdFW2?)zA2 zqISo>X)kic%u?35I%D(H8;K08y;2sb@x;O&W>ZovFl%M744aYwA!$jx14Y1qBin+ufG~gBI__O{bBIVadjRr`*t-ruM<= z&f2?*CFtCEYpyg2nVtwd^}RBMUBvry-_1f_t;*=bvz};VhGs4E{f=VHv-!z--Qbis zRR~Q~o~`H#{KgPw+e9#If+c2rAOgVK`O$Xv|Nuw(j`e`my?|mp?6~6uLs? zRY&xVheZgF8VbFwqii8ANF3LV>W2a!rplCH?lA;$ovZ|M&nm~ED45H6s%qL!GI&ne z&rqi7lsRzW;&dcR?7<*xQNl6ke$^1t6mS(9tRpacfEoIK?E}{X3&XHm4^b7vQ%BS~ zIM%v8!3?Wsy*--33OsDF3w_OPhkk4(=(!KCydqIKYAP^f3PpX&shBlH-?;hHw&$JC z!xc4>MCKG+Em>;vSXCy@rH$JFG(au;9wD}aJfn%AwYI9ue|5hD*VCdk<-Fg~x&KjP zmqUA1!FV%;5^_>aZ#xe$OA0oo29|xr-Zbfry1R$JVeAU+(of{aj$V-e_qTl?kYq^#YFe4!YG64M(P%oZ341n~D# zFljoBvL`C!ct^pBk}mjRu87Z zYqK1}_I0&uAq76sw0dQz1$fQUlPhY`6p;5d%4kYaID87BNlF`w3k&NK2Ii*CKfUYR zOMbG7vC(Y#x~u3ngx>w+!z6b#ioQfC(c0OKJWmap0_(qsnQXX5e2re z$LD+sKF#6cD<$NY(3v)O6efT27Mbg5Rx z$c}fhfoiJDX^oot&M6WL;3dIGkq$4TDUD!;m?UtNUwsu0LD& zbT-ifhv#foCd$-Nto>i(*z>+O&z% zL&xbs>gBp#ntgVi!#fy5xkJ!7soPQtuaQi*-MJ>Cd5U96wWs?8RcK!q^}blfv72O9 z!AC*K7xgT9G@A*E$cmI!3=<|(J7oKuONa7Y>lMNr~NtqCX74VHGI^g#3}tY&Wmt9Toh#WbS+yk0Ec2b);Q2 zNB{d<#dKx);w8M1u`2mumGChQ>6A@Nmxd_@MYlcrHT2ydkAA_%gz#zq=w}WI>+rpd z`d@&lb8GVRUs&|z;}k5i0&JW83nvXvJy4tBT&YRu+TW4vEyw5y<-z_^R@(KqRWOe( zL(Ea=4I5cY9#?MU_25aZEv9nUaWa4}L`@zHHn8jp-O~nAY3U|}HAFAKJQkMeWq7R=2^+N(YC*3{iLja77}xu{ztkcG$u2VZ8N-ey$if7TUx z+#G_SUICw3{i~g_$U=4>)ASuSvZzI8{SPLpCN*+53Nu?yYv_s^6Pp(7IUD~5e8wKR zx5`BCIj2}swE1s?6(&;9%298zU;7?eJ+UBWt!$0<1SMFZ@E_@~-2zyRO&6cS@PAgo zYP>m$&E-!JwRBKB=?JrE)t&A!5)THi;&wIF6X$0?e7%^^-u@dE#W1_BH=Euu`qx4B_xnPoTy&iiFGoB0J`XzEZ$fC+ z!5QA~quF*)1m`fJoSeqKBMf-@utvG78Bbaw(<_J}jj{Js-&#>(3VexeSUi!e)XTm{ zi86KmS-5tdSz_>axFEj4&axT~nkHInH~atsW02_VW=>TEbxjLXpT#s#+Ns%G;0XjG z81mY>1?qJKkH^C9`*Hl)_viuwz!0H!&u^RR(|vaQh}gRxP-{~s{DbhW&xxpp>q2@; zB`o#mJmA9gb<)I$iLweYle;;GIi8m3TbS$dU=+FD<)m$Wky0>?;4=8Ad9Jj@NC_FZ zp0j7kx9|`4yN_6_tTV-B7y6Nm^lP9}RvHohzZTnvO@i3v*BW*WuZfTl2*<^Hvtrn< zQFP|kghz%UNRN+y(J`>YPW%V6e%69ZU(RomB_THF;vwp!g9I~WAK|FIp^5pCpNxFg z_?RpDkQZkGd)Wwff0Qg3XO7A#fc;JmdQO#Mm52QC$%|D476_xs>hE+S_#t)+v&0X= z4o1jNVZ4D&5x_2ZLd|@FRWQO8@D&)py1`S7842nv-^mgfO#%k3wmuo`Ij^#THund* z4F6UUlBgNG+~hIef#a^?#0JSTJeCYqTE|vKxkbq4G49_*-d@bB4u(+W_5A`fQY#H) zSbZ=h6zkYj@>t_QDzG+d@PDWN@o+J^)o>Fg=Pw~4dR3_-)Rq5QZ`auPVf*wKpE#tg zhX|Nur!D}wN8zlr8`XeUrHIiGFOtb!UxSJ%&R8j9G+ZKYBfV_RnDNVT`0@j;;3+A`Dwn&7kM6U{_d7|Kt=ErtKT=gIL5><=%TZ!5&rMtUS#cT-GO}f9$Cq!C zbIu|4PC9ZKOlDfAOHI}pH#hoGeX5_SJr)LQLDY=JevZu_HNjYwEmYMe=ZG%2i9=&} zntlJ0Y?wrT?KmRauLQcwzqFZ0Z5b0CjNGD3)S;rh`0chB$Chg=XAVG?XeWLjW?rWF zr3U8qgR+&~O9Mlc_FkoYLm_*?EQF(28mVz0sR?=bPlcnTk@fYccW(~e7gTJE)+9wa z2@W59z)9YR5$3;jSeneTSyqyHU5-SlGC(b5r z^K^d#Tcy6l#1zwpqUUG%UU3qDiH-T6xlpRoE1BkPP2m(V@b=Yj^`4Gt zSnBrD`L~sJLvC_cNHJVEkPL7|;a?v9h!P-HsEfEIAojXKB}W zKL+I5M;1L)HswQ~RAt;~5hW+9|60pK>}=a_;B_;w^9))QNh~wFv|HD<(wCv57&0fO z!%&AUD&yAt2|*)XUzN7m5?33iH`@C4RKkS6T#Me!&}zEstbXuMtlN~o)a!sA+3J0N z0QY}YZ<_T9x#_a8#VAQuJ zQ%bql$_qVhBRcp>il|aZ!xY20YI8_@f=YHd+aU(INS_u~`koSUTQ~7w$x{*qszvBf zw559G*@36#dO$_bRiZS^xRJV96IlgQUQXptqy?Lx+;G?QpqCmg;V4H|oWQK3zI#ON zJ8y8JTmF^gPx_7)gP;)Qi1+390RJ;^AEtZ?Ze!08#wJ5a_1>sm#W8g!Th`+}fCpxl zCz8>=McfgFJNcOVor{qu*2XEk(Z00+O-m04eMTPoeWuh69-syBJG=bsb4U3kr>DujPf+~ngV#`u913dQRHnp$EeI_|lcuX8u^KtC6~#c$ zhvIEq(-C92xTimS&VO5uQ_|w+-FP_@$y}9CbJWLU&j@_BBx1Vp+S@eVd9=fjb6%eM=T=5CY(_Oyx|88L_De z%O?NG=Dc+)+ko@0QIzFD5q#c>_vpEu#N^T?-neg-@b4tZ!;OAnfJE-^8W3I~9I7MA zRcTlJDXN;YoD5!>@B16hP2VM->q7n%Rk@O;ItX5IvMqY5!`(+|_4T3NW_q|H=^4tzQZtdXSNxmw^!sTSS;9M*-zZblB38rE^CSNRTMf!uIX1R2lQHgE7oNIbyaG6LQBTJ**$qt`b2F#>QC_TL0kI@#VyWi1n! zZuf;pZ~GzovVXwX59CH|??NCB#sKq1lmCQ&>*j0PBa_X#LXO*9X&&`5q8}gG(MlG? z*I8{^R?;~9wdJy>B@FgHre`?Y7$SvQ{=2K~%U0jxZUH|?#vW|RN;`mC2p;tE<4wEb zlc2Wuu`rC4P*EUs=I~MlJ)k@pdsr0`@xX9L1|!o7hk)P?A#CawR-@Od}>BRd28(j!%uftndii31 zW)N=cwZ=oY$#<;a98&N31xR3ybrDICyek`>M*q|A&@mjk`KHl5 z{1;8W?Z$w#vNpNSIO~bj2q;zjh)%*HLWk`Caagco#yn31^OvDM{4R0;|GX{C!the9 z@schBQmRE30~(SYF!us@euVtIy_6;Pl0CJ1UFdysCcc^Jqj2np#%AZgS6mTu{>s%B zQ$R_EJK|qMl2?kN=Ck%^G>P#njO1N}#*-(7n@Tv%%NXkU_+{-B&7jJ zscB=Vh1d~%;)ZmAI$+NqXRNMQZ z(d#vVHkyTrJsX@tmZ1KwzJ_FyMK@>fgbCduJPEkCjPt;XZ88Ue>)+x(14HEBlE64eWRJyO z8Km!-aM(tgNr60rQQu@JjkNwoe(|~(sa#vuz1FcKJ_yceVar3BqxlC#C|2z^&&RgC%h3QprXE@ImH z@?D_GqtMEAM4vtLaYJ=K2!=U&G(-Xso8TvRW-StEPB<1Ub81Hx&^TEN)ZS&OA`s#n zH#?)*h1qGj1;b;0{By1yoa9zzou4qco|A(;ci9l&>vXpTpysz-%XQ9cR&+6{!5YBf zMl4)_4KQmrU4F=XJT-3jnI^&&%+GKiY^llmbMm7m`D5vj(x zsx~~HGg~!yJ9+JX+~jii;y^bNm@6Lo@TBj%3kP(Tu@5yVoK-+k`}}jfMjz8pJmVn1 zOzN`^l@>%E_|rhW-+JHuO)cAyn`*$QC`b@_GC7AwXf9K6y`2R_%_W$_Ge<}I@ zKRmI)k=O<$i;ujI7>fSQ24+52G_@I77>s-G<{90jWEd$FkSKi(?X7KMaBnct|uFa|dAykm9OJoQUOagF$A{J%8-j3*U$o8iZ z6%H?>tyIZYos;ndZS#8@h2(;GsJep zY??`)CuZB*xg!2@PQH!dd-_NA-gW$?C$4#ckwj|7QkzN()5P%2A1CaOWm-O?Hyl>z zH*y^EaK0X`+n8zD8jU_-;#hL@0MJ&(QSQ6=a&Nwu1nKTme|Ycz^>jBm>*u`MlMk}b z-N)ku*LCxPgzAA}MNdHxT`h_g?>g`057x-xg=5y#6=&o^>9n$pW@Sus1QMtG1(_C^>tC97hM;b+UKiMLT#Ks0x{Ay*I9)%Z^y)& zlVwn*R7qRw@!_7rK9`(bX%YTZ)18oBU_ep)!sYur3c%m}`Ko06MypnBeiBMfXE{21 z@8YYi+6@bO3VUw!x5eViInzRlG1KQGThLB6JgiLp)Sv*D(Ra-9?MMKMd}&EqFp}HE~Vf1JwyR zY}|uWI?(F6S)7wl`u$+W!L#J%(Bj~6%EN4TD}wE+nBJR2xYg^S%lrsGnOXBFDCmRf zm+73gnO2w?(dYJ5E6{xjpHyB5(wy zv{vm*QTk>AX2BIvuI>oIb+7l~YPxQ0gu%1)HaAg=_))ESvsh!#n%WdUiG8mGuePz@ zsZCGuNY4DA1fM?eckt7YfNdt^!hFJ{LJzw?`M0kB5ps40(+u1(>Ouu!o1#*qw0`F{ zj{Da?-E0W8!N=26+i2hI782HH^PgwUhTGa547lGvxvvko{7@Hu2H$M)DdD?$UY-9W zf4WiFf{2rI4dg~bP^E*0C31%Iy=lxILzqJ<46h)$SxU zoA;~ZxOjH$^XZ3YSc1qm*%H;R$;b8s9=0-ubfz&l1q^&Q9-@uA4rGIbdXJ@S3q@7y zN_yaT`>Q`a=(`@O*hmlH@2v$>XP4I@?~(7#c`%H_Ab4YpffKj4ASHPj{BPA<6io@+ z$U<}V$#xNQUt`B>(&}^e?B#2N@O%G=FtA>&oPhOQbrWG2Qd9s(BOpY|sb4<<-&g zlN-M8ci!E$gS|3k!E$X~3@+XZaFFK|WR@y2vuzM5w$g3i_9<}eEVR$oCLKv9NhiIq zBzSoLqkdrj5@SxLivSTgGpSYAG0YZY*ef*$M`GWBxn<6|@*MT(LSowj0hO3TZ9Ri;-R(aONN$cG zpCsOTyg@eT1%CEp$U+79Ul=ULaeI%I?$C6_VJl^YoC`em3mfrmG`|Qiqg@?xxyz0m zaxnlcW@ikVp!B_7PK6&;DfxdP-&H;~u4261q;U=4%cnT@a{;sS6^LcFU{@0Y3Wi8z zari+3;SL%el(rv%MY&g|AxUe+MjEy{D@I()YqUTGvcthHA^a*x!fA%&jb!$^0`2x% zKgfwJVIZ`7>=JI0z%^j+ZU*#2kwaAtJDox9gAs2(4UTff=Q+MSl=>K2Z0GI{5_6-l zZUxS1cei6bU1R?iU^2~bMajO-=DB|0rY{^j|F)31?Y$A+x<+AM|}qqH7zJ?14vU&>7wgmuHYof(JL3_xzKXkBe65B=YP z<61vRS69E*Kiy$2hl4Dz->!b1xE+X1pE*Soz>TwNCHjxIyjl^F={d*U4a&!91b)HY)R zCaYj8k68MC-IpsARbG^y<&MGrw5R-Dr`N-=y92G0uYqQKm)(Qf6`3D$-TMPU1>xiE zo9T^^5P?@=sLMwq{KuOx`5$*XC`~f&&9Q0!ctK(#IpY0CSxu;*iZOn5(MS_e4(-2*+Q_#QskPxMhW=6ut&L zVdw8BYeQcrI&b-)_+Q7o)3?KyOt?pIrT;e`#6ROjWXKoer|>J+MvXdVzWCm{IixO@ zmX{koF};O2<-+dSEAW9jm>A#4>q``WZNeu>7VodGep)I!3K2H-Ay&$&93t?MU|)ou z3j~Br>3LKf9|yg;-*2f32!6a}-ItCZQs>X3Ust%{cMsyF!Z~OW=A7n?FOpz!fp@*e zDq2i~04=j?+Ny-Howl(8&%NN+JpwU+HPL=Ypip7qAGHF2{<0eqgRP~A6 zVJs=N&5gTj;f(iImPuP>rC%Tuxs|y3ni$@hf zpg_bZUk^yZ#)3t=GjQc?DlZT96%zOrnkuYxUCI9(536n+0Wie%lvB)a{4YW@MKOo3 zBTN{#=1sCTl9V@OCzPF@nX_~yYLoLvCE~Xlv})y2NtDZIFp)o`S z+Bs&keTYiduR*S|SWu|8rpEqyVB~Dwf~&Y!>|A*i3SeG7a7eU0`-$#aNBiBg%K6f( zYv?HsWXTEKL3=1~VS&+~aHK?+qK6iKbr0}BLBsw=V)c@t-#e%>zfv42Q9uJao+Kg( z2rh4u$LrtFrl5+o%IO7!>iJcUx3F}_CkXY@-aijRLPFxdG?d@__xkd~@W7b_Qj=_M zV%88vR3P%}<1GIZeS_TOs?D#1hU_E%?sY-z;6z)oQ|6dYu1sQ^1EbB>MoHt~e;7Tm175 zpDnm~e_X6$gW!F)vd?GRA3+ieO9EuGP&qtrIh~K?0f`jI$Uo?VY|4Xo*X8sXjK@C) zb<*_d)&vyr_<%^T&ze1R-b#{FO6@}e6U_~^2S;J&Gc){s|2yaYKcD-PpRm&{71P1< ThUg#?bucM$d9fOxVetO}R7zf( literal 0 HcmV?d00001 diff --git a/assets/mine/section_bg1.png b/assets/mine/section_bg1.png new file mode 100644 index 0000000000000000000000000000000000000000..63cf356f0dba3406eb0e5e0c016c11a4613e1e10 GIT binary patch literal 1921 zcmeAS@N?(olHy`uVBq!ia0y~yU}9rnU<~B|k_=PMs;2-c&H|6fVg?3*IUvlacGk)S zD9BhG8tbF0yKO`X5+);L_X!%nR}t zWc#MPJtfQSq4VD-V#byU9#d`=Dm>%fV!ZHzZ*=|sCuTE?-@pACo@kX)s?NsX(89&64yv>yibL1HgB$lNCWp0{U z&Ac<~f2;)CG$DqDH<{swj_23gGBh;5pZhqz=kevMv5&w1|5JFU{>x?V_xFP(=2Sdh z&B!2AlP~-G!OM-87q8u2&Bg4^$>6X|-EW@V{vT8BvNIHj_^NI87d!iZ{eH8$x##@j zWEl?pKbB*5?(Fmb#n#8SZ&Mf7Rb^nPeE0NlsJ(!nzvo;K6T^g;IdX#Cem=)6fMu(4x{;*x?adoE7XR5gb)(_l^555fcjraLTANBU z9GGZ4+gI=I?!9%17cD{MDyUF@8K)PuE&Ac*?{#tv2M%uh_u=->k9XI7T>F;2dS`8Z z;)XZBd4VPNQ%{CB>G!rxVPHskDct<>RLaA=*0pbM=7TGd>C3bq&t_FOn|61j3D33X zV!i9v&6Q#}uyDi19J}~qAQ#&1t=Vzr?Ag;mbyq>;M{x?_i-ait|K(9u4F))1M o^5;<#2YUR&+Mevks(-l+#3sjX_`vN9tRWdZUHx3vIVCg!0MbDSKmY&$ literal 0 HcmV?d00001 diff --git a/assets/mine/section_bg2.png b/assets/mine/section_bg2.png new file mode 100644 index 0000000000000000000000000000000000000000..d6b0f3a57cd9e594d286c714d2c605c54ee44d9a GIT binary patch literal 1776 zcmeHIZB)`%7=Li0lxVhd%KtHQ+lNd#Wq8(+nFfh3WvO{EGMfd2X82MDC<+bxQ*Fj!EHnup>ZZRN%MdP) zo})KP{YbHHouN%X5>G!EnJtg9a2LPzhFrz{k#Y+^t6`31zGdhNt+Tj7!9guM-I{Nv zOxAt{5c~AL=o4>}bLtz0{+LgpLVwew%|zak5VG*S(hlPHNJeL8`et@kQ?@Z|3sjBI z!8NPEtRUD9fMWsV69K3Qz-Rx$?L+(j!ZLt`;scTWftut-$)Vk(&-;bRJYEKi?}G%xoAq6)ZZ5Oo|x z`KkIPwZ&{?PpAgP3dhJ8@+AN3-r9TjS~#d4aj4LlH=8)U>V}7gzP{9)6jdr;%H6(F z{UUS7%2r;Y=(p+TJqtTOC-j&S?A)|x=j)vqHDYvn>^6+l1dByyPku5wKBQZ`$) z9t*_o?OOoOjS04RXl)@SX;;P3?Y5jOJ4j#JeHQT`|4m)>T=9hr#q;H~^P|s-Xs8tg zcdd*&MDj)~)NRt7$H9|6&x_TP3PhwHC;4KaKg}C|#=~+Fi{7li@j-R}b=%yy+CU+b z=kpv5dLQe%F$UyL=_g9eU8Jpyu9?mSbFkrZ`}lyKAz8}1+C#%Y)#I?F?1{N$j}<|^ zH6ww64nJ2+RRtMzyn6CO|>P z;vjb?hIQv;UIIBR>5jgR3=A9lx&I`x0{MI;t`Q}{`DrEPiAAXlZkg%1iSss2OJ-nT zF7Isu1DrJR)PWQzu z%DQEp-8A)EZM@3XsE4b6E?=G|$zQU!zEbAE&7IaY(Q=#qZ)a5LlwVZ#SbWdjdf5Yy zf7Vpk{?iYy>kzVc@jd=e{CD{F?AOO1Zje8Bam`J8{`x)f(esb}_kUu}yhGyu#Wz`h zj@5PCD!KLl+0WyQbLL0Rj^9@=@%^UA|ErtJnJw%$n{7Xm|E7J#-K*W<=CAE7ueL8w zxb`D2vTr+c#iq1g>EDX4mNW0qX0QIBawclu?~gC z|5AqOk3T>By0^OLufSGox#{1t?R8FnEMpMQzxCq{|MKn3$Ley|G(~#T-x{|(O^dF%;hDlI_&1Jm+k#t&dBg##>}1X z&eV%BFlaLIF(|klU}QMLVZqQK!N|@aV7#3F`Z5NF_g1mXZ=pyiKVV=;Vv%8RIJ3iy zl_6teBQryXAka^Sm}bD0_B0Ss^z6&V@Bj1|7~+hLukSCHhB*S&fSI#DuM1{mkSp6| eW{bnx8S?p`h4cNtZ8!o9B?eDdKbLh*2~7Y4v}~RL literal 0 HcmV?d00001 diff --git a/assets/pics/cate_sel_left.png b/assets/pics/cate_sel_left.png new file mode 100644 index 0000000000000000000000000000000000000000..e87e1fc8a20ab094bfbce74178f98bd8d6a27505 GIT binary patch literal 1221 zcmV;$1UmbPP) zubYYCJmhc#?@Br^X!I_b8;{Y%I zapq<}#d;+`CV?)gkn+hfu_^>~rGP#l49HOfx_2a%-kkK`!XsN7F{@+nS6O^m%rWEZ zG|*BDg(!~V5&kw#H}=-^i)ZWkt+VF6w|VQa_hu|Ci2!HrzlxqiCgG4Et6%(nU3*>` z5W#Q7&Tr%ttQ0CQgOx(=O7O|IN}o@M$@G{#GC~~@T2NSXq$1t@o-F3LyQ7eSCF3z4 zCb7#?Csf~CyYqqkCWP#$SPz#0&Ky~Q7$UQa@(CTYNwWs~j$-ogF=iK9NML^zGtW46 z`VATEv2MA(Y$f)=F zDmwpQ?SV6&Dp~gc5C!>%7>=FkM3Egx#35@Q%M_hGs|t8eilaQ0?0jf>r!Q%P$Pk_I zRb4x;3OKg#xR7-Y3(5$;MaSOYea?(3?9Kr4AnSsZ`(l|eyE5{<)qu{jC_J!m^l-*uLwa}WK@Po*g3IKGN|$Jg;D z3FT`amM~4aczxCDKA%Ixg1oy&&Xf56qBbcW!kFt=vJSL*K|=| z3dqGMOh_PD$^_L?DEvv;;~E@ND*>|pl}v|X1=yr+;hgmnnv2&Wz)I~L=Q+t(N}xOZG0r5dRDYhVRcbgnuRVqaiS==)*q`L%c_htkmO_Ur z@Ra??YiA*ofR~gx8Fdtya*o@R4)r*k@7qf)v{BS2LM|t^Qsi<#4b&P1x#QjkLjE_W zNtz4DL40ymYjG~4z&~h<%R@#!++}GS32p$LCTU?y%()D6Dqd(tt>V;7CCUdGREgyh z#JlK#V{_!&KE2)NBMR!&O2#VzGMKgMMoe`O)FuzUQTk_U1{&O;a)-8(g;WySlsP}} j+L0Q~`&;pKeE#?k>Z>s_gG8No00000NkvXXu0mjfY|}4f literal 0 HcmV?d00001 diff --git a/assets/pics/cate_sel_right.png b/assets/pics/cate_sel_right.png new file mode 100644 index 0000000000000000000000000000000000000000..34e5aa908786bf043210d98756dabcdea6d611c8 GIT binary patch literal 1224 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 TSx9dq0JkmdZdHGK@9}>Cd17qj literal 0 HcmV?d00001 diff --git a/assets/pics/play_tag.png b/assets/pics/play_tag.png new file mode 100644 index 0000000000000000000000000000000000000000..c7fc7b1944ae4a2f2e3432e7076dfddcf9e736cf GIT binary patch literal 2293 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 KMNUMnLSTX&KoF1s literal 0 HcmV?d00001 diff --git a/assets/pics/rank2.png b/assets/pics/rank2.png new file mode 100644 index 0000000000000000000000000000000000000000..365b2397ff79a7b5f6e65bcbf49f65b564e0017a GIT binary patch literal 2215 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 Z@grhES3Cm9*f{_I002ovPDHLkV1f*PFTDT& literal 0 HcmV?d00001 diff --git a/lib/global/client/play_client.dart b/lib/global/client/play_client.dart index bed9fd6..bc3cc2d 100644 --- a/lib/global/client/play_client.dart +++ b/lib/global/client/play_client.dart @@ -1,4 +1,3 @@ - import 'package:skywood/global/request/api_const.dart'; import 'package:skywood/global/request/app_request.dart'; import 'package:skywood/global/tool/sky_log.dart'; @@ -8,7 +7,6 @@ import 'package:skywood/utils/models/drama/skywood_drama.dart'; import 'package:skywood/utils/models/drama/skywood_home.dart'; class PlayClient { - static Future> getHomeData() { return AppRequest.get(ApiStringPlay.getHomeModules).then((value) { if (value.isSuccess) { @@ -42,6 +40,20 @@ class PlayClient { }); } + static Future> getCategoriesDetail({ + required int categoryId, + int page = 1, + int pageSize = 20, + }) { + return AppRequest.fetchPage( + ApiStringPlay.getCategoriesDetail, + page: page, + pageSize: pageSize, + extraParams: {'category_id': categoryId}, + fromJson: (json) => SkywoodDrama.fromJson(json), + ); + } + // getSearchHots static Future> getSearchHots() { return AppRequest.get(ApiStringPlay.getSearchHots).then((value) { @@ -54,29 +66,53 @@ class PlayClient { }); } + // search + static Future> search({required String keyword}) { + return AppRequest.get(ApiStringPlay.getSearch, queryParameters: { + 'search': keyword, + }).then((value) { + if (value.isSuccess) { + SkyLog.print('getSearchHots: ${value.data}'); + List list = parseDataForList(value.data); + return list.map((e) => SkywoodDrama.fromJson(e)).toList(); + } + return []; + }); + } + //getCollections - static Future getCollections({ - int page = 1, int pageSize = 10 + static Future> getCollections({ + int page = 1, + int pageSize = 10, }) { Map params = _setPage(page: page, pageSize: pageSize); - return AppRequest.get(ApiStringPlay.getCollections, queryParameters: params).then((value) { + return AppRequest.get( + ApiStringPlay.getCollections, + queryParameters: params, + ).then((value) { if (value.isSuccess) { SkyLog.print('getCollections: ${value.data}'); - + List list = parseDataForList(value.data); + return list.map((e) => SkywoodDrama.fromJson(e)).toList(); } return []; }); } // getHistory - static Future getHistory({ - int page = 1, int pageSize = 10 + static Future> getHistory({ + int page = 1, + int pageSize = 10, }) { Map params = _setPage(page: page, pageSize: pageSize); - return AppRequest.get(ApiStringPlay.getHistories, queryParameters: params).then((value) { + return AppRequest.get( + ApiStringPlay.getHistories, + queryParameters: params, + ).then((value) { if (value.isSuccess) { SkyLog.print('getHistory: ${value.data}'); - + List list = parseDataForList(value.data); + return list.map((e) => SkywoodDrama.fromJson(e)).toList(); } return []; }); @@ -90,19 +126,48 @@ class PlayClient { Map params = {}; params['short_play_id'] = shortPlayId; params['short_play_video_id'] = shortPlayVideoId; - return AppRequest.get(ApiStringPlay.getVideoDetail, queryParameters: params).then((value) { + return AppRequest.get( + ApiStringPlay.getVideoDetail, + queryParameters: params, + ).then((value) { if (value.isSuccess) { - SkyLog.print('getVideoDetail: ${value.data}'); + SkyLog.print('getVideoDetail: ${value.data['data']}'); + return SkywoodDetail.fromJson(value.data['data']); } return null; }); } + // collect + static Future collect({ + required int shortPlayId, + required int videoId, + }) { + Map params = {}; + params['short_play_id'] = shortPlayId; + params['video_id'] = videoId; + return AppRequest.post(ApiStringPlay.collect, data: params).then((value) { + SkyLog.print('collecttttt: ${value.data}'); + if (value.isSuccess) {} + return value.isSuccess; + }); + } + + // cancelCollect + static Future cancelCollect({required int shortPlayId}) { + Map params = {}; + params['short_play_id'] = shortPlayId; + return AppRequest.post(ApiStringPlay.cancelCollect, data: params).then(( + value, + ) { + SkyLog.print('cancelCollectttt: ${value.data}'); + if (value.isSuccess) {} + return value.isSuccess; + }); + } + static Map _setPage({int page = 1, int pageSize = 10}) { - return { - 'current_page': page, - 'page_size': pageSize, - }; + return {'current_page': page, 'page_size': pageSize}; } static List parseDataForList(Map data) { @@ -110,4 +175,4 @@ class PlayClient { List? listData = map['list']; return listData ?? []; } -} \ No newline at end of file +} diff --git a/lib/global/client/user_client.dart b/lib/global/client/user_client.dart index a1712ea..edd0d87 100644 --- a/lib/global/client/user_client.dart +++ b/lib/global/client/user_client.dart @@ -3,6 +3,7 @@ import 'package:skywood/global/request/api_const.dart'; import 'package:skywood/global/request/app_request.dart'; import 'package:skywood/global/tool/sky_log.dart'; import 'package:skywood/utils/models/user/register_bean.dart'; +import 'package:skywood/utils/models/user/skywood_user.dart'; class UserClient { @@ -27,4 +28,14 @@ class UserClient { return null; }); } + + static Future getUserInfo() { + return AppRequest.get(ApiString.userInfo).then((value) { + if (value.isSuccess) { + SkyLog.print(value.data, tag: 'getUserInfo'); + return SkywoodUser.fromJson(value.data['data']); + } + return null; + }); + } } \ No newline at end of file diff --git a/lib/global/request/api_const.dart b/lib/global/request/api_const.dart index 75eebaa..ff3ca32 100644 --- a/lib/global/request/api_const.dart +++ b/lib/global/request/api_const.dart @@ -57,15 +57,15 @@ class ApiString { class ApiStringPlay { // getRecommandsList GET /getRecommands 推荐列表,分页参数 current_page/page_size,可带 revolution - // getVideoDetail GET /getVideoDetails 获取剧详情,query: short_play_id, video_id + /// getVideoDetail GET /getVideoDetails 获取剧详情,query: short_play_id, video_id // getDetailsRecommand GET /getDetailsRecommand 详情页推荐列表;注意方法参数 page/pageSize/data 当前没有传入请求 static const String getRecommandsList = "/getRecommands"; static const String getVideoDetail = "/getVideoDetails"; static const String getDetailsRecommand = "/getDetailsRecommand"; - /// getHomeModules GET /home/all-modules 首页全部模块数据 + ///=== getHomeModules GET /home/all-modules 首页全部模块数据 // getRankingList POST /homeRanking 首页榜单,body 带 type,支持 most_trending/top_searched/new_releases -/// getCategoriesList GET /getCategories 分类列表 +///=== getCategoriesList GET /getCategories 分类列表 // getCategoriesDetail GET /videoList 分类详情/剧列表,分页 + extraParams // getWaterflowList POST /newShortPlay 首页瀑布流,分页 + extraParams static const String getHomeModules = "/home/all-modules"; @@ -76,10 +76,10 @@ class ApiStringPlay { /// getSearchHots GET /search/hots 搜索热门列表 // getSearch GET /search 关键词搜索,query: search -// collect POST /collect 收藏,body: short_play_id, video_id -// cancelCollect POST /cancelCollect 取消收藏,body: short_play_id -// getMyCollections GET /myCollections 我的收藏列表,分页 -// getMyHistorys GET /myHistorys 播放历史列表,分页 +///==== collect POST /collect 收藏,body: short_play_id, video_id +///==== cancelCollect POST /cancelCollect 取消收藏,body: short_play_id +///==== getMyCollections GET /myCollections 我的收藏列表,分页 +///==== getMyHistorys GET /myHistorys 播放历史列表,分页 // getNoticeNum POST /noticeNum 获取通知数量 // versionControl GET /customer/versionControl 版本检查 // getLanguges GET /languges 获取语言列表,接口名拼写就是 languges diff --git a/lib/main/main_root.dart b/lib/main/main_root.dart index 419f1dc..9124085 100644 --- a/lib/main/main_root.dart +++ b/lib/main/main_root.dart @@ -4,6 +4,7 @@ import 'package:skywood/pages/home/home_page.dart'; import 'package:skywood/pages/like/like_page.dart'; import 'package:skywood/pages/mine/mine_page.dart'; import 'package:skywood/pages/search/page/search_page.dart'; +import 'package:skywood/utils/extend/app_keep_alive.dart'; import 'package:skywood/utils/tools/help_img.dart'; class MainRoot extends StatefulWidget { @@ -17,10 +18,10 @@ class MainRoot extends StatefulWidget { class _MainRootState extends State { final List _pages = const [ - HomePage(), - SearchPage(), + AppKeepAlive(child: HomePage()), + AppKeepAlive(child: SearchPage()), LikePage(), - MinePage(), + AppKeepAlive(child: MinePage()), ]; final _pageController = PageController(); diff --git a/lib/pages/home/cate_page.dart b/lib/pages/home/cate_page.dart new file mode 100644 index 0000000..b9b600d --- /dev/null +++ b/lib/pages/home/cate_page.dart @@ -0,0 +1,318 @@ +import 'package:flutter/material.dart'; +import 'package:skywood/global/client/play_client.dart'; +import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/home/players/page/drama_detail_page.dart'; +import 'package:skywood/utils/models/drama/skywood_category.dart'; +import 'package:skywood/utils/models/drama/skywood_drama.dart'; +import 'package:skywood/utils/tools/sky_time_tool.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; + +class CatePage extends StatefulWidget { + const CatePage({super.key}); + + @override + State createState() => _CatePageState(); +} + +class _CatePageState extends State { + final List _categories = []; + final List _dramas = []; + int _selectedIndex = 0; + int? _loadingCategoryId; + bool _loadingCategories = true; + bool _loadingDramas = false; + + @override + void initState() { + super.initState(); + _loadCategories(); + } + + Future _loadCategories() async { + List categories = []; + try { + categories = await PlayClient.getCategoriesList(); + } catch (_) { + if (!mounted) return; + } + + setState(() { + _categories + ..clear() + ..addAll(categories); + _loadingCategories = false; + }); + + if (categories.isNotEmpty) { + _loadCategoryDetail(categories.first.id); + } + } + + Future _loadCategoryDetail(int categoryId) async { + _loadingCategoryId = categoryId; + setState(() { + _loadingDramas = true; + _dramas.clear(); + }); + + List dramas = []; + try { + dramas = await PlayClient.getCategoriesDetail(categoryId: categoryId); + } catch (_) { + if (!mounted || _loadingCategoryId != categoryId) return; + } + + if (!mounted || _loadingCategoryId != categoryId) return; + + setState(() { + _dramas.addAll(dramas); + _loadingDramas = false; + }); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.white, + body: SafeArea( + bottom: false, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildHeader(), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildCategoryList(), + Expanded(child: _buildDramaList()), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildHeader() { + return SizedBox( + height: 49.h, + child: Stack( + children: [ + Positioned( + left: 13.w, + top: 16.h, + child: HelpImg.asset( + ConstImg.back, + width: 24.w, + height: 24.w, + ).addInkWell(onTap: () => HelpNav.back()), + ), + Positioned( + left: 94.w, + top: 22.h, + child: SkyText( + text: 'Explore Genres', + color: CommonColor.black, + fontSize: 14, + fontWeight: FontWeight.w800, + ), + ), + ], + ), + ); + } + + Widget _buildCategoryList() { + return Container( + width: 86.w, + height: double.infinity, + padding: EdgeInsets.only(top: 12.h, bottom: 18.h), + decoration: BoxDecoration( + color: const Color(0xFFF2FFF0), + borderRadius: BorderRadius.only(topRight: Radius.circular(8.r)), + ), + child: _loadingCategories + ? const SizedBox.shrink() + : ListView.builder( + padding: EdgeInsets.zero, + itemCount: _categories.length, + itemBuilder: (context, index) { + return _buildCategoryItem(index); + }, + ), + ); + } + + Widget _buildCategoryItem(int index) { + final category = _categories[index]; + final selected = index == _selectedIndex; + + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + if (selected) return; + setState(() { + _selectedIndex = index; + }); + _loadCategoryDetail(category.id); + }, + child: SizedBox( + height: 47.h, + child: Stack( + alignment: Alignment.center, + children: [ + if (selected) + Positioned( + left: 0, + top: 0, + bottom: 0, + child: HelpImg.asset( + ConstImg.cateSelLeft, + width: 20.w, + height: 50.h, + fit: BoxFit.fill, + ), + ), + if (selected) + Positioned( + right: 0, + top: 0, + bottom: 0, + child: HelpImg.asset( + ConstImg.cateSelRight, + width: 20.w, + height: 50.h, + fit: BoxFit.fill, + ), + ), + Padding( + padding: EdgeInsets.symmetric(horizontal: 12.w), + child: SkyText( + text: category.name, + color: selected + ? CommonColor.primacyColor + : Colors.black.withAlpha(100), + fontSize: 11, + fontWeight: selected ? FontWeight.w700 : FontWeight.w500, + textAlign: TextAlign.center, + maxLines: 2, + lineHeight: 1.05, + ), + ), + ], + ), + ), + ); + } + + Widget _buildDramaList() { + if (_loadingDramas) { + return const Center( + child: CircularProgressIndicator(color: CommonColor.primacyColor), + ); + } + + if (_dramas.isEmpty) { + return Center( + child: SkyText( + text: 'No Data', + color: Colors.black.withAlpha(100), + fontSize: 13, + ), + ); + } + + return ListView.separated( + padding: EdgeInsets.only(left: 8.w, right: 10.w, bottom: 24.h), + itemCount: _dramas.length, + separatorBuilder: (context, index) => SizedBox(height: 10.h), + itemBuilder: (context, index) { + return _DramaItem(drama: _dramas[index]); + }, + ); + } +} + +class _DramaItem extends StatelessWidget { + const _DramaItem({required this.drama}); + + final SkywoodDrama drama; + + @override + Widget build(BuildContext context) { + return SizedBox( + height: 80.h, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HelpImg.networkRadius( + drama.imageUrl, + width: 64.w, + height: 80.h, + fit: BoxFit.cover, + borderRadius: BorderRadius.circular(4.r), + ), + SizedBox(width: 8.w), + Expanded( + child: Padding( + padding: EdgeInsets.only(top: 2.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SkyText( + text: drama.name, + color: CommonColor.black, + fontSize: 11, + fontWeight: FontWeight.w700, + maxLines: 2, + lineHeight: 1.08, + ), + SizedBox(height: 7.h), + SkyText( + text: drama.description, + color: Colors.black.withAlpha(92), + fontSize: 9, + maxLines: 2, + lineHeight: 1.2, + ), + const Spacer(), + Row( + children: [ + _TipView(icon: ConstImg.star, text: '10.0'), + SizedBox(width: 12.w), + _TipView( + icon: ConstImg.look, + text: SkyTimeTool.formatNum(drama.watchTotal), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ).addInkWell(onTap: () => HelpNav.to(DramaDetailPage(dramaBean: drama))); + } +} + +class _TipView extends StatelessWidget { + const _TipView({required this.icon, required this.text}); + + final String icon; + final String text; + + @override + Widget build(BuildContext context) { + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + HelpImg.asset(icon, width: 8.w, height: 8.w), + SizedBox(width: 2.w), + SkyText(text: text, color: Colors.black.withAlpha(110), fontSize: 8), + ], + ); + } +} diff --git a/lib/pages/home/players/page/drama_detail_page.dart b/lib/pages/home/players/page/drama_detail_page.dart index abe59f7..11b6925 100644 --- a/lib/pages/home/players/page/drama_detail_page.dart +++ b/lib/pages/home/players/page/drama_detail_page.dart @@ -1,9 +1,13 @@ import 'package:flutter/material.dart'; import 'package:skywood/global/client/play_client.dart'; +import 'package:skywood/main/lib_file.dart'; import 'package:skywood/pages/home/players/widget/player_bottom_widget.dart'; +import 'package:skywood/pages/home/players/widget/sky_player_view.dart'; +import 'package:skywood/utils/models/drama/skywood_detail.dart'; import 'package:skywood/utils/models/drama/skywood_drama.dart'; import 'package:skywood/utils/models/drama/skywood_home.dart'; import 'package:skywood/utils/tools/widgets/sky_app_bar.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; class DramaDetailPage extends StatefulWidget { const DramaDetailPage({super.key, @@ -20,28 +24,30 @@ class DramaDetailPage extends StatefulWidget { class _DramaDetailPageState extends State { + SkywoodDetail? _detailBean; + @override void initState() { super.initState(); - // _getDetailDrama(); + _getDetailDrama(); } - // void _getDetailDrama() { - // PlayClient.getVideoDetail( - // shortPlayId: widget.shortPlayId, - // shortPlayVideoId: widget.shortPlayVideoId - // ).then((value) {}); - // } + void _getDetailDrama() { + PlayClient.getVideoDetail( + shortPlayId: widget.dramaBean.shortPlayId ?? 0, + shortPlayVideoId: widget.dramaBean.shortPlayVideoId ?? 0 + ).then((value) { + setState(() { + _detailBean = value; + }); + }); + } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.black, - appBar: SkyAppBar( - title: widget.dramaBean.name, - backgroundColor: Colors.transparent, - ), body: _bodyWidget(), ); } @@ -50,11 +56,43 @@ class _DramaDetailPageState extends State { return Stack( children: [ SizedBox(width: double.infinity, height: double.infinity), + + if (widget.dramaBean.videoUrl != null) + Positioned( + bottom: 0, left: 0, right: 0, top: 0, + child: SkyPlayerView( + videoUrl: widget.dramaBean.videoUrl!, + detailBean: _detailBean, + dramaBean: widget.dramaBean, + ), + ), + Positioned( - bottom: 0, left: 0, right: 0, - child: PlayerBottomWidget(), - ), + top: AppScreen.statusBarHeight + 5, left: 0, right: 0, + child: _headerWidget(), + ) ], ); } + + Widget _headerWidget() { + return Container( + height: 40, + padding: const EdgeInsets.only(right: 15, left: 5), + child: Row( + children: [ + IconButton( + icon: HelpImg.asset(ConstImg.back, width: 32), + onPressed: () => HelpNav.back(), + ), + Expanded(child: SkyText(text: widget.dramaBean.name, color: Colors.white, fontSize: 16, + textAlign: TextAlign.center, + fontWeight: FontWeight.bold, + )), + SizedBox(width: 40,) + ], + ), + ); + } + } \ No newline at end of file diff --git a/lib/pages/home/players/page/drama_esp_page.dart b/lib/pages/home/players/page/drama_esp_page.dart new file mode 100644 index 0000000..f7a0f81 --- /dev/null +++ b/lib/pages/home/players/page/drama_esp_page.dart @@ -0,0 +1,220 @@ +import 'package:flutter/material.dart'; +import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/utils/models/drama/skywood_detail.dart'; +import 'package:skywood/utils/models/drama/skywood_drama.dart'; +import 'package:skywood/utils/models/drama/skywood_episode.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; + +class DramaEspPage extends StatefulWidget { + const DramaEspPage({super.key, required this.detail, this.currentEpisode}); + + final SkywoodDetail detail; + final int? currentEpisode; + + @override + State createState() { + return _DramaEspPageState(); + } +} + +class _DramaEspPageState extends State { + late int _selectedEpisode; + + SkywoodDrama? get _drama => + widget.detail.shortPlayInfo ?? widget.detail.videoInfo; + + List get _episodes => widget.detail.episodeList; + + @override + void initState() { + super.initState(); + _selectedEpisode = widget.currentEpisode ?? _drama?.episode ?? 1; + } + + @override + Widget build(BuildContext context) { + final double height = 520; + + return SizedBox( + width: AppScreen.screenWidth, + height: 520, + child: Stack( + children: [ + HelpImg.asset( + ConstImg.espBg, + width: AppScreen.screenWidth, + height: height, + fit: BoxFit.fill, + ), + Positioned.fill( + child: Padding( + padding: EdgeInsets.fromLTRB(22.w, 31.h, 22.w, 54.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildDramaInfo(), + SizedBox(height: 12), + Divider( + height: 1, + thickness: 0.5, + color: Colors.black.withAlpha(18), + ), + SizedBox(height: 12), + SkyText( + text: '$_episodeTotal EP', + color: Colors.black, + fontSize: 15, + fontWeight: FontWeight.w500, + ), + SizedBox(height: 8), + Expanded(child: _buildEpisodeGrid()), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _buildDramaInfo() { + final SkywoodDrama? drama = _drama; + final SkywoodDrama? info = widget.detail.videoInfo; + final String imageUrl = drama?.imageUrl ?? ''; + + return SizedBox( + height: 130.h, + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + HelpImg.networkRadius( + imageUrl, + width: 96.w, + height: 130.h, + fit: BoxFit.cover, + borderRadius: BorderRadius.circular(2), + ), + SizedBox(width: 16.w), + Expanded( + child: Padding( + padding: EdgeInsets.only(top: 7.h), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SkyText( + text: drama?.name ?? '', + color: Colors.black, + fontSize: 18, + fontWeight: FontWeight.w700, + maxLines: 2, + lineHeight: 1.12, + ), + SizedBox(height: 10.h), + SkyText( + text: info?.description ?? '', + color: Colors.black.withAlpha(118), + fontSize: 14, + maxLines: 2, + lineHeight: 1.45, + ), + SizedBox(height: 13.h), + _buildTag(), + ], + ), + ), + ), + ], + ), + ); + } + + Widget _buildTag() { + final String name = _drama?.categoryList?.isNotEmpty == true + ? _drama!.categoryList!.first.name + : (_drama?.tagType ?? ''); + + if (name.isEmpty) return const SizedBox.shrink(); + + return Container( + padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 3.h), + decoration: BoxDecoration( + color: const Color(0xFFE7FFE5), + border: Border.all(color: const Color(0xFF86D57A), width: 1), + ), + child: SkyText( + text: name, + color: Colors.black, + fontSize: 14, + overflow: TextOverflow.visible, + ), + ); + } + + Widget _buildEpisodeGrid() { + if (_episodes.isEmpty) { + return const SizedBox.shrink(); + } + + return GridView.builder( + padding: EdgeInsets.zero, + physics: const BouncingScrollPhysics(), + itemCount: _episodes.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 5, + mainAxisSpacing: 10, + crossAxisSpacing: 10, + childAspectRatio: 61 / 50, + ), + itemBuilder: (context, index) { + return _buildEpisodeItem(_episodes[index]); + }, + ); + } + + Widget _buildEpisodeItem(SkywoodEpisode episode) { + final bool selected = episode.episode == _selectedEpisode; + final bool selectedPlayable = selected && !episode.isLock; + final bool selectedLocked = selected && episode.isLock; + + return GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () { + setState(() { + _selectedEpisode = episode.episode; + }); + }, + child: Container( + alignment: Alignment.center, + decoration: BoxDecoration( + color: selectedPlayable + ? const Color(0xFF91F476) + : const Color(0xFFF8F8F8), + borderRadius: BorderRadius.circular(12), + border: Border.all( + color: selectedPlayable + ? Colors.black + : (selectedLocked + ? CommonColor.primacyColor + : Colors.transparent), + width: selected ? 1 : 0, + ), + ), + child: Center( + child: SkyText( + text: episode.episode.toString(), + color: Colors.black.withAlpha(220), + fontSize: 20, + fontWeight: selected ? FontWeight.w700 : FontWeight.w400, + ), + ), + ), + ); + } + + int get _episodeTotal { + if (_drama?.episodeTotal != null && _drama!.episodeTotal > 0) { + return _drama!.episodeTotal; + } + return _episodes.length; + } +} diff --git a/lib/pages/home/players/widget/player_bottom_widget.dart b/lib/pages/home/players/widget/player_bottom_widget.dart index 8a06217..454a7cd 100644 --- a/lib/pages/home/players/widget/player_bottom_widget.dart +++ b/lib/pages/home/players/widget/player_bottom_widget.dart @@ -4,7 +4,13 @@ import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; class PlayerBottomWidget extends StatefulWidget { - const PlayerBottomWidget({super.key}); + const PlayerBottomWidget({super.key, + // required this.totalTime, + // required this.currentTime, + }); + + // final String totalTime; + // final String currentTime; @override State createState() { @@ -92,4 +98,10 @@ class _PlayerBottomWidgetState extends State { ), ); } + + String _formatDuration(Duration duration) { + final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); + final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); + return '$minutes:$seconds'; + } } \ No newline at end of file diff --git a/lib/pages/home/players/widget/sky_player_view.dart b/lib/pages/home/players/widget/sky_player_view.dart index e69de29..c6003c4 100644 --- a/lib/pages/home/players/widget/sky_player_view.dart +++ b/lib/pages/home/players/widget/sky_player_view.dart @@ -0,0 +1,396 @@ +import 'package:flutter/material.dart'; +import 'package:skywood/global/client/play_client.dart'; +import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/home/players/page/drama_esp_page.dart'; +import 'package:skywood/utils/models/drama/skywood_detail.dart'; +import 'package:skywood/utils/models/drama/skywood_drama.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; +import 'package:video_player/video_player.dart'; + +/// 视频播放器 +class SkyPlayerView extends StatefulWidget { + final String videoUrl; + final bool autoPlay; + final SkywoodDetail? detailBean; + final SkywoodDrama dramaBean; + + const SkyPlayerView({ + super.key, + required this.videoUrl, + this.autoPlay = true, + this.detailBean, + required this.dramaBean, + }); + + @override + State createState() => _VideoPlayerWidgetState(); +} + +class _VideoPlayerWidgetState extends State { + late VideoPlayerController _controller; + bool _controllerCreated = false; + bool _isPlaying = false; + bool _isInitialized = false; + bool _isSeeking = false; + String? _errorMessage; + Duration _currentPosition = Duration.zero; + Duration _totalDuration = Duration.zero; + bool _isLiked = false; + + @override + void initState() { + super.initState(); + _initializePlayer(); + } + + @override + void didUpdateWidget(SkyPlayerView oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.videoUrl != widget.videoUrl) { + _disposeController(); + _initializePlayer(); + } + } + + Future _initializePlayer() async { + setState(() { + _isInitialized = false; + _isPlaying = false; + _errorMessage = null; + _currentPosition = Duration.zero; + _totalDuration = Duration.zero; + _isLiked = widget.dramaBean.isCollect ?? false; + }); + + final controller = VideoPlayerController.networkUrl( + Uri.parse(widget.videoUrl), + ); + _controller = controller; + _controllerCreated = true; + controller.addListener(_handlePlayerValueChanged); + + try { + await controller.initialize(); + if (!mounted || controller != _controller || !_controllerCreated) return; + + if (widget.autoPlay) { + await controller.play(); + } + + _syncPlayerValue(); + } catch (error) { + if (!mounted || controller != _controller) return; + setState(() { + _errorMessage = error.toString(); + _isInitialized = false; + _isPlaying = false; + }); + } + } + + void _handlePlayerValueChanged() { + if (!mounted || !_controllerCreated) return; + _syncPlayerValue(); + } + + void _syncPlayerValue() { + final value = _controller.value; + final nextPosition = _isSeeking ? _currentPosition : value.position; + final nextDuration = value.duration; + final nextPlaying = value.isPlaying; + + setState(() { + _isInitialized = value.isInitialized; + _isPlaying = nextPlaying; + _currentPosition = nextPosition; + _totalDuration = nextDuration; + }); + } + + void _disposeController() { + if (!_controllerCreated) return; + _controller.removeListener(_handlePlayerValueChanged); + _controller.dispose(); + _controllerCreated = false; + } + + @override + void dispose() { + _disposeController(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (_errorMessage != null) { + return _buildErrorView(); + } + + return _isInitialized && _controllerCreated + ? _buildVideoContent() + : _buildLoadingView(); + } + + Widget _buildVideoContent() { + return Stack( + fit: StackFit.expand, + children: [ + FittedBox( + fit: BoxFit.cover, + child: SizedBox( + width: _controller.value.size.width, + height: _controller.value.size.height, + child: VideoPlayer(_controller), + ), + ), + + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onTap: _togglePlay, + child: Container(), + ), + ), + + if (widget.detailBean != null) + Positioned(bottom: 0, left: 0, right: 0, child: _buildBottomView()), + + if (!_isPlaying) + Center( + child: GestureDetector( + onTap: _togglePlay, + child: Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.white.withAlpha(204), + shape: BoxShape.circle, + ), + child: const Icon( + Icons.play_arrow_rounded, + color: Colors.black, + size: 40, + ), + ), + ), + ), + ], + ); + } + + Widget _buildLoadingView() { + return Container( + color: Colors.black, + child: const Center( + child: CircularProgressIndicator(color: Colors.white), + ), + ); + } + + Widget _buildErrorView() { + return Container( + color: Colors.black, + alignment: Alignment.center, + padding: const EdgeInsets.symmetric(horizontal: 24), + child: SkyText( + text: 'Video failed to load', + color: Colors.white.withAlpha(180), + fontSize: 14, + ), + ); + } + + void _togglePlay() { + if (!_isInitialized || !_controllerCreated) return; + + if (_controller.value.isPlaying) { + _controller.pause(); + } else { + _controller.play(); + } + } + + void _collectionDrama() { + if (_isLiked) { + PlayClient.cancelCollect(shortPlayId: widget.dramaBean.shortPlayId??0).then((value) { + setState(() { + _isLiked = value; + }); + }); + } else { + PlayClient.collect( + shortPlayId: widget.dramaBean.shortPlayId??0, + videoId: widget.dramaBean.shortPlayVideoId ?? 0, + ).then((value) { + setState(() { + _isLiked = value; + }); + }); + } + } + + Widget _buildBottomView() { + SkywoodDetail detail = widget.detailBean!; + final int currentEpisode = _currentEpisode(detail); + final int totalEpisode = _episodeTotal(detail); + + return Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + InkWell( + onTap: () => _collectionDrama(), + child: HelpImg.asset( + _isLiked ? ConstImg.liked : ConstImg.unlike, + width: 40, height: 40 + ), + ), + const SizedBox(height: 24), + Container( + height: 36, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(4), + color: Colors.white.withAlpha(30), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + HelpImg.asset(ConstImg.playLt, width: 17, height: 17), + const SizedBox(width: 10), + SkyText( + text: 'EP.$currentEpisode', + fontSize: 13, + color: Colors.white, + ), + SkyText( + text: ' / EP.${detail.episodeList.length}', + fontSize: 13, + color: Colors.white.withAlpha(126), + ), + ], + ), + Icon(Icons.arrow_forward_ios, color: Colors.white, size: 13), + ], + ), + ).addInkWell( + onTap: () { + // HelpNav.showBottom( + // DramaEspPage(detail: detail, currentEpisode: currentEpisode), + // ); + showModalBottomSheet( + context: context, + isScrollControlled: true, + backgroundColor: Colors.transparent, + builder: (context) { + return SizedBox( + height: 520, + child: DramaEspPage( + detail: detail, + currentEpisode: currentEpisode, + ), + ); + }, + ); + }, + ), + const SizedBox(height: 8), + _buildProgressBar(), + const SizedBox(height: 7), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + SkyText( + text: _formatDuration(_currentPosition), + fontSize: 13, + color: Colors.white, + ), + SkyText( + text: ' / ${_formatDuration(_totalDuration)}', + fontSize: 13, + color: Colors.white.withAlpha(126), + ), + ], + ), + SkyText(text: 'x1.0', fontSize: 13, color: Colors.white), + ], + ), + const SizedBox(height: 20), + ], + ), + ); + } + + Widget _buildProgressBar() { + final int totalMilliseconds = _totalDuration.inMilliseconds; + final double progress = totalMilliseconds <= 0 + ? 0 + : (_currentPosition.inMilliseconds / totalMilliseconds).clamp(0.0, 1.0); + + return SizedBox( + width: double.infinity, + height: 3, + child: SliderTheme( + data: SliderThemeData( + trackHeight: 3, // ✅ 进度条高度 3 + thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 1), + overlayShape: const RoundSliderOverlayShape(overlayRadius: 3), + activeTrackColor: Colors.white, // ✅ 已播放 = 白色 + inactiveTrackColor: Colors.white.withAlpha(126), // ✅ 未播放 = 灰色 + thumbColor: Colors.white, + overlayColor: Colors.white.withAlpha(76), + ), + child: Slider( + padding: EdgeInsets.zero, + value: progress, + min: 0, + max: 1, + onChangeStart: (_) { + _isSeeking = true; + }, + onChanged: (value) { + setState(() { + _currentPosition = Duration( + milliseconds: (totalMilliseconds * value).round(), + ); + }); + }, + onChangeEnd: (value) { + final position = Duration( + milliseconds: (totalMilliseconds * value).round(), + ); + _controller.seekTo(position); + _isSeeking = false; + }, + ), + ), + ); + } + + String _formatDuration(Duration duration) { + final minutes = duration.inMinutes.remainder(60).toString().padLeft(2, '0'); + final seconds = duration.inSeconds.remainder(60).toString().padLeft(2, '0'); + return '$minutes:$seconds'; + } + + int _currentEpisode(SkywoodDetail detail) { + final int? episode = + detail.videoInfo?.episode ?? + detail.videoInfo?.currentEpisode ?? + detail.shortPlayInfo?.episode ?? + detail.shortPlayInfo?.currentEpisode; + + if (episode != null && episode > 0) return episode; + return 1; + } + + int _episodeTotal(SkywoodDetail detail) { + return detail.episodeList.length; + } +} diff --git a/lib/pages/home/widgets/daily_quest_widget.dart b/lib/pages/home/widgets/daily_quest_widget.dart index 01dcc5f..4120753 100644 --- a/lib/pages/home/widgets/daily_quest_widget.dart +++ b/lib/pages/home/widgets/daily_quest_widget.dart @@ -52,7 +52,13 @@ class DailyQuestWidget extends StatelessWidget { child: Row( spacing: 5.w, children: List.generate(dramaList.length-1, (index) { - return HelpImg.network(dramaList[index+1].imageUrl, width: 95.w, height: 50.h, fit: BoxFit.cover); + final drama = dramaList[index+1]; + return InkWell( + onTap: () { + HelpNav.to(DramaDetailPage(dramaBean: drama)); + }, + child: HelpImg.network(drama.imageUrl, width: 95.w, height: 50.h, fit: BoxFit.cover), + ); }) ), ); diff --git a/lib/pages/home/widgets/home_cate_widget.dart b/lib/pages/home/widgets/home_cate_widget.dart index 7100bd9..f9a5472 100644 --- a/lib/pages/home/widgets/home_cate_widget.dart +++ b/lib/pages/home/widgets/home_cate_widget.dart @@ -3,6 +3,8 @@ import 'package:skywood/main/lib_file.dart'; import 'package:skywood/utils/models/drama/skywood_category.dart'; import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; +import '../players/page/drama_detail_page.dart'; + class HomeCateWidget extends StatelessWidget { const HomeCateWidget({super.key, @@ -25,7 +27,8 @@ class HomeCateWidget extends StatelessWidget { ), itemCount: categories.length, itemBuilder: (context, index) { - return _buildCateItem(categories[index], index);} + return _buildCateItem(categories[index], index); + } ), ); } @@ -40,7 +43,9 @@ class HomeCateWidget extends StatelessWidget { child: _customText(category.name,), ) ], - ); + ).addInkWell(onTap: () { + // HelpNav.to(DramaDetailPage(dramaBean: drama)); + }); } _customText(String text) { diff --git a/lib/pages/home/widgets/hot_cartridge_widget.dart b/lib/pages/home/widgets/hot_cartridge_widget.dart index 17b09b8..260ba36 100644 --- a/lib/pages/home/widgets/hot_cartridge_widget.dart +++ b/lib/pages/home/widgets/hot_cartridge_widget.dart @@ -3,6 +3,7 @@ import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:skywood/main/lib_file.dart'; import '../../../utils/models/drama/skywood_drama.dart'; +import '../players/page/drama_detail_page.dart'; class HotCartridgeWidget extends StatelessWidget { @@ -38,6 +39,8 @@ class HotCartridgeWidget extends StatelessWidget { ), HelpImg.asset(index<3?ConstImg.hotBg1:ConstImg.hotBg2, width: 110.w, height: 174.h) ], - ); + ).addInkWell(onTap: () { + HelpNav.to(DramaDetailPage(dramaBean: drama)); + }); } } \ No newline at end of file diff --git a/lib/pages/home/widgets/rank_list_widget.dart b/lib/pages/home/widgets/rank_list_widget.dart index ead2583..d3d9f05 100644 --- a/lib/pages/home/widgets/rank_list_widget.dart +++ b/lib/pages/home/widgets/rank_list_widget.dart @@ -67,7 +67,7 @@ class RankListWidget extends StatelessWidget { Widget _rankIndex(int index) { return SizedBox( width: 40.w, - child: SkyText(text: formatNumber(index + 1), + child: index < 3 ? _rank123(index) : SkyText(text: formatNumber(index + 1), fontSize: 15, color: CommonColor.black, fontFamily: 'Anton', @@ -77,6 +77,16 @@ class RankListWidget extends StatelessWidget { ); } + Widget _rank123(int index) { + String img = ''; + if (index == 0) img = ConstImg.rank1; + if (index == 1) img = ConstImg.rank2; + if (index == 2) img = ConstImg.rank3; + return Padding(padding: EdgeInsets.only(right: 16.w), + child: HelpImg.asset(img, width: 24.w), + ); + } + String formatNumber(int number) { return number.toString().padLeft(2, '0'); } diff --git a/lib/pages/like/pages/collection_page.dart b/lib/pages/like/pages/collection_page.dart index 311cdd6..829b3ac 100644 --- a/lib/pages/like/pages/collection_page.dart +++ b/lib/pages/like/pages/collection_page.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:skywood/global/client/play_client.dart'; import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/home/players/page/drama_detail_page.dart'; +import 'package:skywood/utils/models/drama/skywood_drama.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; class CollectionPage extends StatefulWidget { @@ -14,16 +17,19 @@ class CollectionPage extends StatefulWidget { class _CollectionPageState extends State { + List _collectionList = []; + @override void initState() { - // TODO: implement initState super.initState(); _getCollection(); } void _getCollection() { PlayClient.getCollections().then((value) { - + setState(() { + _collectionList = value; + }); }); } @@ -40,16 +46,36 @@ class _CollectionPageState extends State { itemBuilder: (context, index) { return _buildItem(index); }, - itemCount: 5, + itemCount: _collectionList.length, ); } Widget _buildItem(int index) { + final SkywoodDrama drama = _collectionList[index]; return Stack( children: [ - HelpImg.asset(ConstImg.collectionBg, width: 100.w, height: 174.w, fit: BoxFit.fill,), - + SizedBox( + width: 100.w, height: 174.w, + child: HelpImg.asset(ConstImg.collectionBg, width: 100.w, height: 174.w, fit: BoxFit.fill,), + ), + Positioned( + left: 5, right: 5, top: 32.w, + child: HelpImg.network(drama.imageUrl, height: 110.w, width: 90.w, fit: BoxFit.fill,), + ), + Positioned( + bottom: 6, left: 2, right: 2, + child: SkyText(text: drama.name, + fontSize: 13, + color: CommonColor.black, + ), + ), + Positioned( + right: 10, top: 15, + child: HelpImg.asset(ConstImg.liked, width: 18, height: 18,), + ) ], - ); + ).addInkWell(onTap: () { + HelpNav.to(DramaDetailPage(dramaBean: drama)); + },); } } \ No newline at end of file diff --git a/lib/pages/mine/mine_page.dart b/lib/pages/mine/mine_page.dart index 0daef54..d0a966b 100644 --- a/lib/pages/mine/mine_page.dart +++ b/lib/pages/mine/mine_page.dart @@ -1,6 +1,14 @@ import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:skywood/global/client/user_client.dart'; import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/mine/widget/mine_section_view.dart'; import 'package:skywood/pages/widgets/pixel_widgets.dart'; +import 'package:skywood/utils/models/user/skywood_user.dart'; +import 'package:skywood/utils/tools/app_toast.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; + +import '../widgets/common_bg_page.dart'; class MinePage extends StatefulWidget { const MinePage({super.key}); @@ -12,32 +20,92 @@ class MinePage extends StatefulWidget { } class _MainRootState extends State { + + SkywoodUser? _userInfo; + + @override + void initState() { + super.initState(); + + _getUserData(); + } + + void _getUserData() { + UserClient.getUserInfo().then((value) { + setState(() { + _userInfo = value; + }); + }); + } + @override Widget build(BuildContext context) { - return Scaffold( - body: PixelPageBackground( - child: SafeArea( + return CommonBgPage( + child: SafeArea( bottom: false, - child: CustomScrollView( - slivers: [ - SliverToBoxAdapter(child: SizedBox(height: 12.h)), - SliverToBoxAdapter(child: _buildHeader()), - SliverToBoxAdapter(child: SizedBox(height: 18.h)), - SliverToBoxAdapter(child: _buildPlayerCard()), - SliverToBoxAdapter(child: SizedBox(height: 10.h)), - SliverToBoxAdapter(child: _buildWalletShop()), - SliverToBoxAdapter(child: SizedBox(height: 10.h)), - SliverToBoxAdapter(child: _buildCheckpoint()), - SliverToBoxAdapter(child: SizedBox(height: 10.h)), - SliverToBoxAdapter(child: _buildGameMenu()), - SliverToBoxAdapter(child: SizedBox(height: 120.h)), - ], - ), - ), + child: Padding( + padding: const EdgeInsets.all(15), + child: Column( + children: [ + const SizedBox(height: 5), + mImgBg(imgName: ConstImg.mineTop), + const SizedBox(height: 10), + MineSectionView(title: 'PLAYER CARD', imgName: ConstImg.sectionBg2, paddingSpace: 16, + child: _userInfo==null ? null : _showUserInfo(), + ), + const SizedBox(height: 6), + MineSectionView(title: 'GAME MENU', imgName: ConstImg.sectionBg1), + ], + ), + ) ), ); } + Widget _showUserInfo() { + String _name = _userInfo!.givingName!.isEmpty || _userInfo!.givingName=='' + ? 'Visitor' + : _userInfo!.givingName!; + return Column( + children: [ + Row( + children: [ + _userInfo!.avator.isEmpty || _userInfo!.avator=='' + ? HelpImg.asset(ConstImg.defAvatar, width: 60) + : HelpImg.asset(ConstImg.defAvatar), + const SizedBox(width: 10), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 5), + SkyText(text: _name, fontSize: 18, fontWeight: FontWeight.bold, + color: Colors.white, + ), + const SizedBox(height: 15), + Row( + children: [ + SkyText(text: _userInfo!.customerId, + fontSize: 10, + color: Colors.white.withAlpha(200), + ), + const SizedBox(width: 6), + HelpImg.asset(ConstImg.copy, width: 12), + ], + ).addInkWell(onTap: () async { + // copy + if (_userInfo!.customerId.isEmpty) return; + await Clipboard.setData(ClipboardData(text: _userInfo!.customerId)); + AppToast.showSuccess('ID is Copied!'); + }), + const SizedBox(height: 10), + ], + ) + ], + ) + ], + ); + } + Widget _buildHeader() { return Padding( padding: EdgeInsets.symmetric(horizontal: 15.w), diff --git a/lib/pages/mine/widget/mine_section_view.dart b/lib/pages/mine/widget/mine_section_view.dart new file mode 100644 index 0000000..4eeedcf --- /dev/null +++ b/lib/pages/mine/widget/mine_section_view.dart @@ -0,0 +1,93 @@ + +import 'package:flutter/material.dart'; +import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; + +class MineSectionView extends StatelessWidget { + + const MineSectionView({ + super.key, + this.width, + this.height, + required this.title, + required this.imgName, + this.type = 1, // 1,2 + this.paddingSpace = 5, + this.child + }); + + final String title; + final double? width; + final double? height; + final String imgName; + final int type; + final double paddingSpace; + final Widget? child; + + @override + Widget build(BuildContext context) { + return Stack( + children: [ + HelpImg.asset(imgName, width: width, height: height, fit: BoxFit.fill), + Positioned( + left: paddingSpace, right: paddingSpace, top: 8, + child: Column( + children: [ + _buildHeader(), + const SizedBox(height: 10), + child ?? SizedBox() + ], + ), + ), + + ], + ); + } + + Widget _buildHeader() { + return Stack( + children: [ + HelpImg.asset(ConstImg.sectionTopBg, width: width, height: 20.h), + Positioned( + left: 7, right: 7, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + HelpImg.asset(ConstImg.littleLeft, width: 7), + const SizedBox(width: 2), + SkyText(text: title, fontSize: 12, color: Colors.white) + ], + ), + Row( + children: List.generate(3, (i) { + return HelpImg.asset(ConstImg.littleRight, width: 5); + }), + ) + ], + ), + ) + ], + ); + } +} + +class mImgBg extends StatelessWidget { + const mImgBg({super.key, + this.width, + this.height, + this.fit = BoxFit.fill, + required this.imgName, + }); + + final double? width; + final double? height; + final String imgName; + final BoxFit fit; + + @override + Widget build(BuildContext context) { + return HelpImg.asset(imgName, width: width, height: height, fit: fit); + } +} \ No newline at end of file diff --git a/lib/pages/search/page/result_page.dart b/lib/pages/search/page/result_page.dart index d4993c8..7a360b6 100644 --- a/lib/pages/search/page/result_page.dart +++ b/lib/pages/search/page/result_page.dart @@ -1,6 +1,10 @@ import 'package:flutter/material.dart'; +import 'package:skywood/global/client/play_client.dart'; import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/home/players/page/drama_detail_page.dart'; import 'package:skywood/pages/widgets/pixel_widgets.dart'; +import 'package:skywood/utils/models/drama/skywood_drama.dart'; +import 'package:skywood/utils/tools/sky_time_tool.dart'; import 'package:skywood/utils/tools/widgets/sky_app_bar.dart'; import 'package:skywood/utils/tools/widgets/sky_common_widget.dart'; @@ -25,12 +29,24 @@ class _ResultPageState extends State { List _searchHistory = []; final _searchController = TextEditingController(); final _searchFocus = FocusNode(); + List _searchResult = []; @override void initState() { super.initState(); _searchController.text = widget.keyword; + _search(); + } + + void _search() { + String keyword = _searchController.text; + if (keyword.trim().isEmpty) return; + PlayClient.search(keyword: keyword).then((valuer) { + setState(() { + _searchResult = valuer; + }); + }); } @override @@ -56,9 +72,14 @@ class _ResultPageState extends State { ), ), body: ListView.separated( - itemBuilder: (context, index) => ResultItemView(), + itemBuilder: (context, index) => ResultItemView( + drama: _searchResult[index], + onTap: () { + HelpNav.to(DramaDetailPage(dramaBean: _searchResult[index])); + }, + ), separatorBuilder: (context, index) => SizedBox(height: 12), - itemCount: 2 + itemCount: _searchResult.length ), ); } @@ -66,29 +87,41 @@ class _ResultPageState extends State { class ResultItemView extends StatelessWidget { - const ResultItemView({super.key}); + const ResultItemView({super.key, + required this.drama, + this.onTap + }); + + final SkywoodDrama drama; + final Function()? onTap; @override Widget build(BuildContext context) { + String tag = 'Satisfying'; + if (drama.categoryList!.isNotEmpty) { + tag = drama.categoryList![0].name; + } return Container( height: 140.h, padding: const EdgeInsets.symmetric(horizontal: 15), child: Row( children: [ - PosterImage(width: 105.w, height: 140.h), + HelpImg.networkRadius(drama.imageUrl, width: 105.w, height: 140.h, + borderRadius: BorderRadius.circular(6), + ), const SizedBox(width: 10), Expanded(child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - SkyText(text: 'Love in the City of Twilight', + SkyText(text: drama.name, fontSize: 14, fontWeight: FontWeight.bold, color: CommonColor.black, ), const SizedBox(height: 12), - _tagView(), + _tagView(tag), const SizedBox(height: 12), - SkyText(text: 'Haunted by fading memories, a man navigates a labyrinth of dreams and reality ds dsajkj', + SkyText(text: '${drama.description}', fontSize: 11, color: CommonColor.withValue('4D4047'), maxLines: 2, @@ -98,14 +131,14 @@ class ResultItemView extends StatelessWidget { children: [ _tipView(true, text: '10.0'), const SizedBox(width: 15), - _tipView(false, text: '10.2k'), + _tipView(false, text: SkyTimeTool.formatNum(drama.watchTotal, unit: 'k')), ], ) ], )) ], ), - ); + ).addInkWell(onTap: onTap); } Widget _tipView(bool isStar, {required String text}) { @@ -119,7 +152,7 @@ class ResultItemView extends StatelessWidget { ); } - Widget _tagView() { + Widget _tagView(String tag) { return Container( padding: const EdgeInsets.only(top: 3, left: 6, right: 6, bottom: 4), decoration: ShapeDecoration( @@ -139,7 +172,7 @@ class ResultItemView extends StatelessWidget { spacing: 10, children: [ Text( - 'Satisfying', + tag, style: TextStyle( color: const Color(0xFF040408) /* 主题黑 */, fontSize: 10, diff --git a/lib/pages/search/page/search_page.dart b/lib/pages/search/page/search_page.dart index f623878..29ec4b8 100644 --- a/lib/pages/search/page/search_page.dart +++ b/lib/pages/search/page/search_page.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; import 'package:skywood/global/client/play_client.dart'; import 'package:skywood/main/lib_file.dart'; +import 'package:skywood/pages/home/players/page/drama_detail_page.dart'; import 'package:skywood/pages/search/page/result_page.dart'; import 'package:skywood/pages/search/widget/search_util.dart'; import 'package:skywood/pages/search/widget/search_view.dart'; @@ -174,39 +175,23 @@ class _MainRootState extends State { child: Column( mainAxisAlignment: MainAxisAlignment.start, children: group.map((drama) { - return _TrendingItem(drama: drama); + return _TrendingItem(drama: drama, onTap: () { + HelpNav.to(DramaDetailPage(dramaBean: drama)); + }); }).toList(), ), ); } - // Widget _buildTrendingList() { - // return Container( - // height: 114 * 4, width: AppScreen.screenWidth, - // color: Colors.green, - // child: GridView.builder( - // padding: EdgeInsets.only(left: 15.w), - // scrollDirection: Axis.horizontal, - // gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - // crossAxisCount: 4, // 上下4行 - // crossAxisSpacing: 10, // 行间距(垂直方向) - // mainAxisSpacing: 10, // 列间距(水平方向) - // childAspectRatio: 236 / 104.0, // 宽高比(宽度/高度) - // ), - // itemCount: _searchHots.length, - // itemBuilder: (context, index) { - // final drama = _searchHots[index]; - // return Container(width: 236, height: 104, color: index%2==0 ? Colors.orangeAccent : Colors.redAccent,); - // return _TrendingItem(drama: drama); - // } - // ), - // ); - // } + } class _TrendingItem extends StatelessWidget { - const _TrendingItem({required this.drama}); + const _TrendingItem({required this.drama, + this.onTap + }); final SkywoodDrama drama; + final Function()? onTap; @override Widget build(BuildContext context) { @@ -261,6 +246,6 @@ class _TrendingItem extends StatelessWidget { ), ], ), - ); + ).addInkWell(onTap: onTap); } } diff --git a/lib/utils/models/user/glimzo_user.dart b/lib/utils/models/user/skywood_user.dart similarity index 88% rename from lib/utils/models/user/glimzo_user.dart rename to lib/utils/models/user/skywood_user.dart index 4b72edc..e60a506 100644 --- a/lib/utils/models/user/glimzo_user.dart +++ b/lib/utils/models/user/skywood_user.dart @@ -1,6 +1,6 @@ import '../model_parser.dart'; -class GlimzoUser { +class SkywoodUser { final String customerId; final bool isTourist; final String userLevel; @@ -8,7 +8,7 @@ class GlimzoUser { final String? familyName; final String? givingName; - const GlimzoUser({ + const SkywoodUser({ required this.customerId, required this.isTourist, required this.userLevel, @@ -17,8 +17,8 @@ class GlimzoUser { this.givingName, }); - factory GlimzoUser.fromJson(Map json) { - return GlimzoUser( + factory SkywoodUser.fromJson(Map json) { + return SkywoodUser( customerId: parseString(json['customer_id']), isTourist: parseBool(json['is_tourist']), userLevel: parseString(json['user_level']), @@ -39,7 +39,7 @@ class GlimzoUser { }; } - GlimzoUser copyWith({ + SkywoodUser copyWith({ String? customerId, bool? isTourist, String? userLevel, @@ -47,7 +47,7 @@ class GlimzoUser { String? familyName, String? givingName, }) { - return GlimzoUser( + return SkywoodUser( customerId: customerId ?? this.customerId, isTourist: isTourist ?? this.isTourist, userLevel: userLevel ?? this.userLevel, diff --git a/lib/utils/tools/help_img.dart b/lib/utils/tools/help_img.dart index 721610f..dc4f988 100644 --- a/lib/utils/tools/help_img.dart +++ b/lib/utils/tools/help_img.dart @@ -61,6 +61,26 @@ class ConstImg { static const String playLt = "assets/pics/player_lt.png"; static const String liked = "assets/pics/liked.png"; static const String unlike = "assets/pics/unlike.png"; + static const String espBg = "assets/pics/esp_bg.png"; + static const String cateSelLeft = "assets/pics/cate_sel_left.png"; + static const String cateSelRight = "assets/pics/cate_sel_right.png"; + + static const String playTag = "assets/pics/play_tag.png"; + static const String rank1 = "assets/pics/rank1.png"; + static const String rank2 = "assets/pics/rank2.png"; + static const String rank3 = "assets/pics/rank3.png"; + + /// mine + static const String copy = "assets/mine/copy.png"; + static const String littleLeft = "assets/mine/little_left.png"; + static const String littleRight = "assets/mine/little_right.png"; + static const String mineTop = "assets/mine/mine_top.png"; + static const String sectionTopBg = "assets/mine/section_top_bg.png"; + static const String sectionBg1 = "assets/mine/section_bg1.png"; + static const String sectionBg2 = "assets/mine/section_bg2.png"; + static const String sectionBg3 = "assets/mine/section_bg3.png"; + static const String defAvatar = "assets/mine/def_avatar.png"; + // nodata diff --git a/lib/utils/tools/sky_time_tool.dart b/lib/utils/tools/sky_time_tool.dart index bc2f74c..ff20710 100644 --- a/lib/utils/tools/sky_time_tool.dart +++ b/lib/utils/tools/sky_time_tool.dart @@ -16,7 +16,7 @@ class SkyTimeTool { num value, { int decimalDigits = 1, String separator = ',', - String unit = 'K', + String unit = 'k', }) { String removeTrailingZeros(String str) { if (str.contains('.')) {