From d92550cbd24e78ccaad65d159824d7e684719ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Wang?= <52880665+rivertwilight@users.noreply.github.com> Date: Mon, 19 Jan 2026 15:59:39 +0800 Subject: [PATCH] feat: dynamic favicon (#11603) * feat: dynamic favicon * feat: dynamic favicon * feat: dynamic favicon * feat: dynamic favicon --- public/favicon-32x-32-error.ico | Bin 0 -> 2482 bytes public/favicon-32x32-done-dev.ico | Bin 0 -> 2131 bytes public/favicon-32x32-done.ico | Bin 0 -> 2493 bytes public/favicon-32x32-error-dev.ico | Bin 0 -> 2131 bytes public/favicon-32x32-progress-dev.ico | Bin 0 -> 2115 bytes public/favicon-32x32-progress.ico | Bin 0 -> 2475 bytes public/favicon-done-dev.ico | Bin 0 -> 835 bytes public/favicon-done.ico | Bin 0 -> 914 bytes public/favicon-error-dev.ico | Bin 0 -> 837 bytes public/favicon-error.ico | Bin 0 -> 901 bytes public/favicon-progress-dev.ico | Bin 0 -> 828 bytes public/favicon-progress.ico | Bin 0 -> 908 bytes src/layout/GlobalProvider/FaviconProvider.tsx | 92 ++++++++++++++++++ src/layout/GlobalProvider/index.tsx | 26 ++--- 14 files changed, 107 insertions(+), 11 deletions(-) create mode 100644 public/favicon-32x-32-error.ico create mode 100644 public/favicon-32x32-done-dev.ico create mode 100644 public/favicon-32x32-done.ico create mode 100644 public/favicon-32x32-error-dev.ico create mode 100644 public/favicon-32x32-progress-dev.ico create mode 100644 public/favicon-32x32-progress.ico create mode 100644 public/favicon-done-dev.ico create mode 100644 public/favicon-done.ico create mode 100644 public/favicon-error-dev.ico create mode 100644 public/favicon-error.ico create mode 100644 public/favicon-progress-dev.ico create mode 100644 public/favicon-progress.ico create mode 100644 src/layout/GlobalProvider/FaviconProvider.tsx diff --git a/public/favicon-32x-32-error.ico b/public/favicon-32x-32-error.ico new file mode 100644 index 0000000000000000000000000000000000000000..b7f7b8534795e4397736ce7f49c01726faa946a3 GIT binary patch literal 2482 zcmV;j2~GBiP)(opbJE=FWR(W?^?&Sa6qzx>i6%5h7Njme8uL8f{{#Nok|jMp9dvV69DS4Juag zQ7bm4X-$l^N>zN+R;7ppltK}3m)F9w?9T4&&ij2Ir{5g{b-|_7{?jkHnLBgOJ>Tp1 z`+a8^{tNr~Hy^9PklCSf+02Btr~Mn}4dQ<^Hr|6ruG)9wq2%D>@$jUtu6VC~bNBNf zelJ_V@^r40sFbSkstnfx%22yN9wEsuW>|HF)DXbd{2p zb#Thd7Yw3nLh}pP-+tju4<+wz-iN+BYm%$Y%Iy0ej4v;ovI0Av`?%}1%;wd-`{bg5 zz7*z%3TU6=r_C9dqaqmgB0kZN3Go)XWRfb{d&`)5B65peL7k-a`^%#=lc+g8>s9{!|P+vd;tjC z3s%ozO4Ns_5kU3GC<+A+s?vw5=3pRO!eK)}wkVa|naY|bb-t2meU-}15faE^JPh={ z*XvpT#=$>q?kO0iUxAY=V&ODDL@^7$Pr^%Y>wXK0Zh?}4q_*fG1Eo?C^+E=tRM@^)(sKv0G7D3A`wp@c=j zYMKJx;z7M^B3+Xx)_`1%DkZb1m{r(fnD(y0u^kMhsw{1{&mwmx2Vev}TW7TT>_om> z95#tlo>pkV2vn^C)nHJm5{jRLduXvkgd;~#i7$=<5BI^>M9-=bZ0}r%7`4sl8AP>~ zCdYl?q6{W!ov#A{kH~y(3p#I@lS$YSnd7kF&#`A&eAlu^LG6$|nFcskLr8v}o zix>e2Duv|kWk3yjVAdugr+E-c#1SHJss(COwo33TBM=~LOz(W<^6$+42;;GU;O#3C zpPTG7rW#iF2=|#GRdh+zC{qWHMco(VS=#j71!D<3NX#nga5M`O(*sykauAd{qHV2P zhQm#TVlWujxou2LOnu?9*49sB;h32-z!?Ee%6-#b7tKPsDrN$Z`C**tL z51-y~LDWuHuVB0$6OfY>;b~W(Ce%Q*Q;E-N7M>8)s15(Z44hO7N+L+Raum0OG147F zu?z&OJIhLK*ERxk&X%&@gnh_l{D33mu5+IGS=r-_n_Z_WKcjYK>XV0FCSYjr^H{FHGn`__<5&NX!qG8raAmk!4K`ME|7>Ag; z5IoX?Wd8`3e)H$(JfieuC!z7rw8^A&?h@eAbMt#5)BWJB2OohU{iveYwpPf zBARHd>DjZr0c)S4U}3xkla(OJIR*aaU!h+xmoQ?0l?k{^44o8!s>cu1?Yt{(p!zj7 zymIkHcV20{^m1f(W5dh7HXq-;^Xt$x%`GA(w6x(DYo4T+ z2>pdYFkckRh#h5faS%5zS&Dm`E*|52jP+4s$%3P)(GAD_e)hSw?tyPREWL)#gW!|r zfd$)u$`I&~gA#E#)-kK0WlrBFIK7)1^MK$^G^|rFVboqDaq1t!DUI`*?Z}CdwI}F+ zYl8V+beQ=A#!EBhz(mfO-=NkpeO>J2MY|APZwwq}DE{8>9nAaPM=TfnC<`m4E^G`Hq zlF$c_vL#l?V<23_=~sYn|M&eV%zXP-D>%>JC7BhYa{~QRAW5d4k0v3v`l&t4 z`A>A2aMD58I}4}U((UHK(AqywJ@%cSYO#9dvimuYTnHKXlXOCsbed=f6)Z9VeD(yW zt*ua6TA+5cfKLlUIg8-sS5DztYNx<#3z zcGQ6*2Az@GE7scs^bbOQYwQl}eS-8dqTlu}6u@UK_1l#JZ?x9V1^h560IOc~>0+2& w{mbJbkh$iXFxBE*_ntlvde^Q!i2q0X7aOSiCpQ$m)&Kwi07*qoM6N<$f~ds7QUCw| literal 0 HcmV?d00001 diff --git a/public/favicon-32x32-done-dev.ico b/public/favicon-32x32-done-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..96b412b9023b03545503ca0a9e3d0eacfe6eed51 GIT binary patch literal 2131 zcmV-Z2(0&sP)Ta7xM`aZrD~m|snVvgjpM(y9ecgDcfGSad-=}X-Pl{!Orf4BNCJ_rD@$6nVxJIk?u%E6BoGYI+k zwhSi=L3C6Zt=()dB&7T_8l_}tXAaJU$RgL9i z*u?@LKCG=>2XK%pK6G*cb!pD+i2$WOgIGSglL0476kdxftdI?PvgR6aVi`_NT4*T` z;Rn1uG@r%!%d2Q_4PlmGIte0H6u{|eU2{2x6GJidPH}bdn8rPg7ACo32~$oGVahMa zv5m{Au4W)dVS(H)@g3XMSYnFee74okyrl8H-@U2lmNIBxBEUozwR}`hSH%Im5yRty z^SYNWBFmMvgt;17Hls7Is9@kQL6B`^IakFw#sq~4%{f1V?kqC^R|x9uBq}H4`iWM) z*ICJTG8i9Csc6v@yfmRZo|)1E@nz;UNN;r7P-8(-Ai-q_10fEd!Q@e0&G}V7K``KT zvNoCETnP{%n5i}Dg#IorXK|5o^p~pbd)m|^{Pf2XvtTdBQrLDQ>7j%s15IIt5=N@z zsPY*A+;-lm3^0Ig*br?rlh+mot)d_;dR?I6NIM+<*Fq7DPlv*dC)C%9GEiw_w3?1) z_<`oK6#kWFNFR9L5rG9WgxhRWH5Ak(M~QN^UO-fu*wazjkzhOEG6nQLK2^dSNkjfhCw zwpbXYk3?J}Tng-L^bPJV!K0f3V6eZ=g|Lt1Y_ZXgZ}b0BO%Q)bx#*Bo3hiECWvCZs zBR;be1f0u>X~(eA6Txq5fhQu(Rx`8ExK&~7Ctd2?#&|_5;oq+5?#m8FudE`RW!-0h z=3QlYxXzD$(E@emX+f+ar;8}XHbUmEGP^6Tmzq;kY5XGXBB=tHd~z2ilv4WLu?hhE z@-5vomB4rT(N~z??FBF;GicyZCNA}o=0uPVwrGFVcw ze0GU0&aoW)>hQ-*IW9=SmMmWO1<)ef)Nwdo3occXs(|N)*`CiMK z_wM00H9@0;5q?7^5zoNlJ6$XdT?G6|KDw)bf#hNlRVJvUEl0fS8g)Ef>TWZ-ijp8{WT`|+p`)+ z2Gf{lx4*Ma;h|62_-doVu}K3azlv(=;7bhzMgcxG?Bca?&0e7K!#*3$RSKW01O7f^ z7AFXZe+RGD0a&)TjXiH4344Gr%|`T{ryV$sdFP#|#_Q8*9D68$UMBLTg>@FX%S{XZ z)`<*e7MXCC;A;tufvXOV9Soo$qOgNK;!@o74BKRAT?1V0d?x2?OVC`r@P-Q~gY|O7 zxtS%6GvitGu+f*r44tBvX72GF3jc6>Q}FIQM^>WDC4 zVW9v(AcLz?bFB^gA}rF+2iLf%m>fQD#o64vq)WsYsvJR6_hW22Hya*?F^J*V5%j17 zh~R+GFK(}6!`g6fn;K_5pBIrNa=G2V+lPiq1!b+jSzoTOo2yS|jo8X^=K~R1XMGgg z_dQY&e50M$M{(UgF0RJD-mcy$03gOK@)y}g3y#@R5z_kPfFJw2EOay}d~vT2M|fXB zrdTh$E?8=t@;kxp_UF{kVfk0_UN-7K3dg!Jl)o>i13UseOM1TVy|`i;ibF~c^!vRc zBrVtzXVPRu8j*-v(hzlLFp<56TUmyO=QE`bUdZ1UF!1q4b(-=1B$HCbq^BoclafWU zGO`R@TQ>6|k6^AF3b>?-;&x4G-BlETSjxhqRO+P4txQI)jeBKwoXkA?R@U1?J6Q4V z=IG>sHDYPpuF>aG{`&vA;odqGeREFV&w4(@q7-pA_!R(B5?-CtcyTfVf5bwNEqg5? z`@R)zy|_)&!}+UCe-~Vs*L!$0JHgBPeBaOH>i#hI|1h;y9x(Jv@0erZX|4Y~Zj?Na z_cCcIPc{9!HGjY9@4K$8>Kqx^XUXn?S312k$bRpx0`A+&6AueQEq4Te8KIBO{?ow$ zlzAuaO)aLi`@p*Z-P$fr>u>O<=piC#6BgvqA%J3Oug!Y(o##of(X6T&TvSIfs{U2z zM5!S*t literal 0 HcmV?d00001 diff --git a/public/favicon-32x32-done.ico b/public/favicon-32x32-done.ico new file mode 100644 index 0000000000000000000000000000000000000000..89e6d91a32553cf7a8aad2d8f5396b800890c0f4 GIT binary patch literal 2493 zcmV;u2}1UXP)y1@?CgHwy&q-r zSeD8b+^7S-?)Te~d-W9rCv@J~$%qbr2DGpxxz@-+>K$LMk6HXqC75u@n z_RnXxuT12`(t*5*LWUum1@hS({A_qyXOr@@8VRD}F<=Qm!hzq*Ya3Q?dwTKh7vIAe zllU?jkdW-7XSXiNq-u}!rTKJ2nrPI>V^u|^CNP+;;p5>9hRX%mVGW*`4qc_7WeuF- z@&$wFYHoV*x;rks@zJ4snhxT~T~*1|CS~@6kHnVcPn&^#&wtSMT6*WI#6h`m;7Ahl zLwR&e^pkQ1=BNmUJ%~;4qd68uA|Wv>EEKE^tb74hrGi>Ohh_M2w2W)F|7qW<7vux8 zlY2(*lafQ5+wGR-zHuGc@w*)h-#t*?@X2V!o6Y5MR_+L*F)zvoQ}Fm0G+zM1_JGy0 zm>BUP;tinEKZ<<)7Ll<`+ITkP09B?y$$q@|=(xS)( zykQ1!g91Gu$N>fyS+-@vc8buNOb9azr&dEbtD$!wkH$g{MQtk56&tl`3FXaU6s5$0 zDSgYgKJ($4OYZDCI>rIXrBbubCSs$ZrL-G96Dd~bmN7oNAuRl&KK>N(cl98&f;iU;cyH?_)d`5WIZ_;&Y>& z!X&TNJ;HrvNEKZYRf^PsV^Q@5S(Y|^cfnW$4-&HqIvmZygwy~Q799koj!1j!u4CcG zd?6T&>D=~Ch);U)vewp>s0v9)qLuWTb{e|3At{a=r6ba!Zg);Ma9uU z(F&?FRiED84W+d}&V*qXy{K6ZY|6-lnuVtJ_+!zj;pI!NKc`m57lp>^AE(57>JOjX z`SpmMs$9W%Eh-?}6k&8IP~&PK(y7E|GzlXFHDbfRAPpy(gc1*uR*u51Fh;tgD3pL; z<=-Wx`q3T&bJmu!&xGA;GJePr@}pU6KKyW82l{_{$*S^5?KWxH_$eu0gOwVDl}^GoHB@O(l&m0B zzjvqF(0Jvf2VTjXRD$%=-<-%Ro;$rkFSpATIMhfy3$BJf>tZ^k*U!k*VO0OI8s(w= zu=Y{cvB?@WC29t+1_nnzLE^c+gNwh|Kwj6?;uEvYSS z2z>uRqNRatZ@*4pRWNh*Ttws35x((ml>fdK&M>i0dR;Wk7z08s8k(h&BaCr~NejRm zS}@c%g4@3LYa|Z!L19Hi{dufd`v~SEvN+(^qQ8#+%(*gQqpAm?j+0==S9UDcCHj-dtoQ!Mk<^mCk z*U$9q-&=>Z2q*|$5=BEt0IacwP34W4>zN0i<^?MeaG4k$wrpFSJBon84b}Woc;o}E>=pqO<+uhY}*b|%Pl0?b3b!KT-#^GJ(f#2)ys z#$7Rmt!ql*X1aZ1j00@(k8|>^)%V*H>mUntchbi+(l+>wcKA)IE8<9Jd zKtrm3csFSnz?le>^4!nw#|$HO#T|c@Z#}upmevX)I_;sgIv(ojwnmUWxC_9n51_XE$g;7o*8iR`!z)Fsohl7;O?8o$e6(HQ2nddG9A*gAb8=FRyR zn$kni2R~y=G@pa6 zNv~TbHK=O+jC90c!dqVd#JLB2^dIJ?lN2zvg($mpZQGW;U&?_KCHaRH0Z*jb!3F#< z$pNcY@af_hyZWKyE%xrj!f-)R&U5b-#X9_K%a+6VD$0KVYykx`r#~FF00000NkvXX Hu0mjfcHYQU literal 0 HcmV?d00001 diff --git a/public/favicon-32x32-error-dev.ico b/public/favicon-32x32-error-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..bbb9e150a0d8a199fd62eb5b06a86c15d0ce943e GIT binary patch literal 2131 zcmV-Z2(0&sP)_w_|BbO?1fDTh>^y7 z@7$SlzWL5K=Zt|*(9UWd=+WB3r_j{3K76fDH)kgGpTj}*$kW~GmA-M^JhP17F4*`6 zd)QLYdpc={*F|;(N~wopSo{T@8XjHkoLPXdTU1|c8;a-%h@daF3y&o z&HE5a+g6Yi*BLA(K3bC;|hypL%uBA2As4khejGZd+rXA&T?c8V}==!A~E1Q^)4B*f39ki5zPAsh*}v19)Q&j~t!W z+c^`G6XM;=(eZE^q%+v z1^|zp(?ec5a2qy68%^Z3nNGtLq(!SUR2*qXn!j2og0Y#VaN`N}y^;)s+!%_`&;%D~ zZd(yR1&wM^IkNbYFfPB$PtC<5(H$h1sCX zoCE=9b6`AeSlJrHUuuCzgH2WwqtLiUA^Pi1b$YeGl9}+C%X-U&G=?rNA&_I?V6T2)>blN8$^nY+a3F4|6Lj*VsTP{u}5c`^Fq} zdhJ*O_i@p87~l1D{x2hr@5!NN2HC85CWMcTs_o^y1Tm&3e=iBA`DoV zDFWcl;*#WCYt^|3i1Z82HQrZD9-p)0Tz*`_C1Pw{h+_YlKcX%fTQT&)2`s(vB=lXo zVSRbG&@X1MVAbC6g;q7pd_FBAN#tX@bF&K#Aq8cv%&f0e*v#E0b4F|x`TKzgt;-X` zANqTWov&)u|2v50Q_qU2==V3McZvW=;}JP1$7m*Pj#QAeKEB6;ot+li)+&6f%Y`TS zUPY#uFPth^?l$RngvZVG*uxIx*K2LhAB2D5>hZ#RQ6AtG;1KEgnLH0Inu3xhCHHoF zoFpVA*b!&aL_`Xah+4vsnVLc_I)smEp5zj~`q199h4&%`KHsQL(%(O2P_mfR^rUS< zGD}tl7l6wPW?baq%U44I=bxFvjW#arED1nb%EE(G>Zr=^OnSbIJ85>9%p7_v=bWL9 z%y_r4w+Bt)y3xi%I$wDH(6X*NHTh;t-@|-YOT_1=$G0NW8%60)RXAw zdluK&B{LctGSnSm| zcOw<4y`J;A9Mmopv2g?K+_?S${}tU&3$4O}Tsj2MT*fK0PJZWo(kV1vim~zVK}1f! z_yH^GIM+N7?(H4;*Z>Oc{G{H_Jbri9=8cKDivo3tMr?C4N)ccmfxgPbb>uVm?K(?L zpOtm|jrx0gqor(qEC5AKYxUYVBAFB_mU#8=ZoyQk8_!3z_W=5K7%xf&%X|O;002ov JPDHLkV1ih_3zGl< literal 0 HcmV?d00001 diff --git a/public/favicon-32x32-progress-dev.ico b/public/favicon-32x32-progress-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..a52c6872703b07561cbf96dc987d616934f63b97 GIT binary patch literal 2115 zcmV-J2)y@+P)NFJI>mT)3{ZSbnTft zGv|EwJKsI$F7OfTlGd?9T3h%SOx^9l=g;Zp!npoTRYE=ee6M=-+^BAzUcfJA9ekOi z%2Lo}7GACj;!o?M_-Dr&HHVKAz}{E%=LUzI|Hi5VKi}7ilW7P48OovRRvs8x05S!Q zIKOV;pLG!wl)@x$?IPgv|4_A!b9H(Ax_66u7as+H*e@^W?v8To9?9cpGetxLd|O7| z1;zOXcGetM-JXvrIII$w9hAlLgNAVNh z9-MOV`n7qqwnQ;OFzp19ToJ(8QC)j2iQ}h}=o#Va(n*a68!ZfT#S*5RAYznXm}4E6 zQ&Yo0d4*|mpW-{Vqmg2Y(tLJbka;QK$G>}1Po|1!O%Y(m#Tq`Ur>m6#TutKXlT*5f zFT&-@nqypzESu4pS5z=?j3CH1T+UT-jxj-DLUS(2pdE1oaE_qf&Z2TSt&gBynZvsOXFZhAWMFMfA;L(N9901W zfZNU+l_3VO4I843Ci2?Mpj8y4MX%FT9BD_M|FuvA<1D>6`NqrZlZ#`uBe zvK0Zu={zX8w@tuu-b5LI+YSXf%(;dIn{y3hY>dytd`Nv_n)gm#!^vqcxJMbsLQ!WI zV=iOh;SH**kGZh#zKl9YHcIB$dVBzsE}nw*q;+7DuaHi_`iY-QSk`!na=xz zfNUb$P+^^2kpZ#31yoLC1ewN~C{;`v>w`vg${%9NAF_ggWv+!8(T50FG$JD1SZ$%7 zJ~C;ISQ*gK7&y5#f+y|@fWiJT8O5hr&Sn~e_yPZ?YQy+_&Ow``QfT)AD?`07n+TYl zAmAKMjOGn1-3k154R9pUWHm7hjrS=GJlUmQTN-c0O8CM}z5QAq{nzIab6NKpps6#C z{dGa~iWaCdPYYrdzAnZowmvdz)~s^YSHCB0I?p&J-wUpJ??HZ3 z8#X%V<2Pgy=^`w?)5X%zMZk~n(f!L9c>cQHUJT%MaVpMbRbQw#t6yrew~vjo@HizQ z!mo;=g>N*P9kJA;BA%E4W(tNe$phWq|Gjo~{Wb$EI5h;|tw{3RTWf;9J)!a3$pWU> z?KjmaJoZ@|-)dAiI&8o!uA+uI_*w&jQGkEA=-~XIW-rkA=`I^hRSI9M1O7E;7AFXZ ze>1O204&?v#-6uN#5_P4Wh46GAM?oP%{%XmYg`yD;OJu^^e~YxO_x~MUT#|O_m3Ab zHp7Io1mDbP?7fl4(S0E_BosEYM_fspo?)8|l{CQBP8EG;)nRk-;#CLvB1+|ob7Luu zR|j2mv(d+shECB-6ZiNlLmFc&wQ)O*&#e77TFb8T(2_=K=#yw@-NO~GH+4i9urR$0 zK&XftQgf{(`ywXNUkt8sTQNR9Z^f=ZFX<97Zi-*UQ*Do;J~CKxgulY=e-gpi0lGUN z^o!eDSh6-ev{4PRo==HLGJbA%Zw;WKQbAdzH|xt4wsQ4Z*N83dpAST6J+-%RWXqoS z1ut3M{9&{epA}aFkG86JmH`ms7WtcOqv^caQVG)f%-$e&cUfp#tMJvG0X)b13Npod z;dQ|>+mzoSZnv_jZ<3W1KFGEd4kL=O( zyP<%Kxr11>Dc!YrdB=~7oP{T-)M4eXOorday)rwBA>hYbX}W?SwF zKB-b;t}Q?X!LupC&W+eusAR+d6%@*zarckkvh>A3E$(6;$|GqBVy zkLvI8r|3ZnVWR|>Lx&WTWWj5*UVZ0z(rYvkig82sFzWJuS>}VfI$dQWKK2jn{&_JG=!99YTchXSz7 tv{rA7qNb2Te4a=D-WE)(bmF;}y$2;VAaaIVwiW;Y002ovPDHLkV1hdT_uBvf literal 0 HcmV?d00001 diff --git a/public/favicon-32x32-progress.ico b/public/favicon-32x32-progress.ico new file mode 100644 index 0000000000000000000000000000000000000000..2828084c3504bec6267228b0b3aaecffd1e992e5 GIT binary patch literal 2475 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

-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 literal 0 HcmV?d00001 diff --git a/public/favicon-done-dev.ico b/public/favicon-done-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..0a9d15b45c7374d75cfa1fe278d9fce92b03f5f1 GIT binary patch literal 835 zcmV-J1HAl+P)I6|r8Ok!F22B|290_m|T+J#t)A|lGDjf+|Y(L%^Y4=Ko^HZ24} zLXaR=1>!;s7pCH5(>Ok;$$4GpasSS}qG{2AbN_q(|3BY3=R4;oY>|`iM7`OLP^TXU z=2aZc1B(@f7!H%hUUkf0z^2 zm*2&}f+{MTizQ?=z+nQc4A5ExjK+Z|?^!sTp#{-ZlG5OEQGxC&=^qvFCeotPArne0 zK$Q*f*@2zBawOF2SBbF1WyMzoW|jr!m&N%_fD=9nd5WYEDeDeSULCB3tVL{>Gf;p5 zD_INKmN}4OrDwXYvcW;I1wERe7zcn$L(i`qoCOTOgKwyuexCOg!i#`gdT8^2?lsfr zO%k6>iQ`|>c&bPURCBt_HWsbG)l6XYhlYk-gs}u+o`Hl0pHTv*NhM|=ofNqGDr+#) z5d>=Y$Ot8Y8jgIiKgab>qs5oT?bb#_(tu_I830y7Sns)F;)LY&!eUwOJD(;Q*d!-V ze((eU3uOpEsb&QQNjQ!h#D}Lx87n zpHAFlOyJRsFv`l?{n+9C3qc^XIY_!RxG1KSqDjl6o6TIKn{ci|La>z3;XaERapsRR z(MUli-?{BEZI!WzaLY0dXL6{|aT2V{{GL7y=7L{TE1bP$BcYAEzX6iK@vGx-&%yuz N002ovPDHLkV1ku$e&qlF literal 0 HcmV?d00001 diff --git a/public/favicon-done.ico b/public/favicon-done.ico new file mode 100644 index 0000000000000000000000000000000000000000..874572697badf216c1915d20d46533f6f5c549b4 GIT binary patch literal 914 zcmV;D18w|?P)tpSIuf<@PHco0@ zzJOeHp?XyY9h%pz2ytbMf@OUc(5&WzbZIcnU!I4^Q5$bNM|3Y zJ`3VDfRH>jneBU4t@(HTvS`)RBc3zYMgY!ly|?^nx3nuDy%)yYRs3c&Lory<)*+!& z6p>J5h`w>K`D4e!B}c2>69VN2M;&j{4irDydu!C$=J=s_R%QPelCW?pOx6Nhn}y&9 z%q<_#CYxZ4r*QirU#&W3VYE{g?LaP@bXwCfTV8>5UwS2#U=<@|Y7SO5CXI-F4Cu~M* z!rdE{ITPP+^*Cxrc+kCg?rceVXCkgKe!b_Pb$W-+z?F1E>r5d2U^LoWMA$TMw-f34 zt&En$%Icb54FNuGt6cdxt{mcQEDYt9(8xVd+irjhy1{S+xt2oPt|@@ggZ?Lt=#NPt zJipbu`X(TR3!Thxv=UVfqyV?p;wFB1R zWbj7M^dS!zUN03|NBD6&>JFZVPWuTq3ow72A2c1sBk?m%pQ=UPQUtcqgeAqLpxsUB zA%KQ6zt#{1WfT8^*XM#H68v2e0-I_?zVMZ9ZxI|jCqP$b#WRFaBeh^rr1<@i2lVQ8 zw~Ev|rYOJzDzd}{j^vSV4}&ThGC)8P5d-D6cXvw^DV+2|!^n#q9*>CE9VJuhC_#7Tom4Aa2N%A5oKh6H}4zKbOzh4d%U_WB&>*qe8Y3T0QrwPx!J%1+yDRo07*qoM6N<$f+uU7QUCw| literal 0 HcmV?d00001 diff --git a/public/favicon-error-dev.ico b/public/favicon-error-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..89ca25f87af9987163bad931515e54ba7c15cbf0 GIT binary patch literal 837 zcmV-L1G@Z)P)KJPsw$W68p&uA{6^(t^k5 zx&FfvcP_`ct+`OZt_m2l06hVm&If)3ffd@*Q8lB>yuT=-!enAOTCAWwV!)wLl-rCV zLy-=skO8{^I6`mAgnI2LWAGEL;5LVQjbmYr-`oedWM>{rzTja}DxiSgMzTDzeDcc( z$U%TMvOMxdN+jvoJ1th))1Xj?0hO}=C4foAz?Oo79D>iK6EP}3LHiQJdxu$gE?dAJ zHnZt{5ns>p3xA_{BMER+QMsfxR*6@;8OWmVU)#W9EJev3AyMOq$RY+G)Ux|YfRQ;q z6j#yRZUyGODuO#4)fFN>`v6LeN-DjI1YFrr(NM}T6=GN*Ag;omq(Eh|qHG`<=D0h& zn^dN|4X8OL!V?CnDf68X1?5YBaMl_{=dC*UqJS!cB?0sdUajX+78N9>hy`}3@ANlJ zz{Yq8PbZ(CcEbhC0Lsr|8WCGlEUONZ{-~0_FUq(#WB68;$p1`H}yY8^L%*f z8_dHmGDbLRDju~C4R$2kc(Q~|kXTNi#*3z{rc#7!lUhnMQAVP2*UW)CAaDBRj5b1t z+t`7Frtr8XoGZZb(#?~!T68wtH~^8lV8Wi;U}6EuiY7IIXXGl4W`=9!0@|z$71yuA z-+CoIc!HSqWn8B8HRa=GQN)?Jf_jCDAX}sR^u4jS^S7P`RdzZ(duRUvDy#Rf>TG~4 P00000NkvXXu0mjfl{#+M literal 0 HcmV?d00001 diff --git a/public/favicon-error.ico b/public/favicon-error.ico new file mode 100644 index 0000000000000000000000000000000000000000..6e023de88f51a8cb28334094deaccf6e0b672c37 GIT binary patch literal 901 zcmV;01A6?4P)PRG)i3SxYx?+<>h_vqcALX&T3jsJB8az z76r$ zu&Ws6g6`VJ{4-UK8HFV$t+fr>q2kxa>aCZX0;d8og=O%E=bUYrUNx6uOdtP6J{f@s<;4Z)Q8vML0r60jhx6>ykrHG&nt%7(-6%78piNh zLlT%ea{_W*c8Fnu+2v)RBae|xJ!PTAfjv2;n4D(?KDHp<`WaM_tu+HMoV8Yw`gicX z_1vBF3lJlAFhoXDCZIF|tZyE|z*zsR>|g?T=T9HgGoTji?4~I5F7;;$jdX(k@eJ?J zoq^BK!tdwdfBGGxLv>|<^fFa!J)tW4eX6Vi$v9kvDvXaBps#Dh7!vviKzT=frnLL; zNRgsQJ5(j=K_4-wQXHxfmEv{LmZVRd^}G0y0xUP(xDmwvqW}6{A#!bRb|&|D1j*xZ b4ZrgXek(U-hRoc200000NkvXXu0mjfl&O*q literal 0 HcmV?d00001 diff --git a/public/favicon-progress-dev.ico b/public/favicon-progress-dev.ico new file mode 100644 index 0000000000000000000000000000000000000000..b5d9d1834ee9fc7d229a474fd6a3e3f46b9b0eee GIT binary patch literal 828 zcmV-C1H=4@P)TEa5g z^T2YQ1>>F76vBT7?Oa^^kn1_?k&Z&b?Z_q&NeEaaz-cC-A;e7@yczW2*7zKpU0zx# z0eCtqj?5!C$yagcYV0-w+6{3WQh1)op+a9tt^anhLt970vs3(oO&Y*xb#~=>wdyif)HjPp}?b3;54aH52TXuZ`s3$xWl(y@5-oI}l9+iV36w7zvR=&9ypCNGcMGWx4Krnq**`w2mR) z75HsmRK2nh7mN7``|4Z~mBRN$(IEsTJmt)9U0`NG!TDwhL9V~d{p?oWp(b{tq=l2@ z8ndBYcyKm#ogv>kP!I8CFP!Qv8a^zyz32=BWx-uBMj)nCcNB*hYP|5 zVgiqXLZ#I~&FHg~0`Q&CuE!J*LZ6A^K1t|jAZ?h1iZO*+&g77M2Q~6=@dXklDKA~7 z)>w@2k1-V$Rg#2LnH>B%PJ(Tf-_zGKYmOg$Y-h*N*4@8Z(fhxX($UQT0000&?AMZjz>HCLNn*mOAL@1d(ayVQdBI%rGj`s0iY|;8LTuE{F@ZskUjG);8O1dXtfbI$+!@$sGiAsACD zX0-e*_|((C{SvM1i^YF0q9p8d+D|aBSX>|jRsU2a@LrLzn{_oe>x0#~IcXvLrj_@0-%3g-Gbq0Zl~xJV5zEuN$&$|KMyhJ1raH-t%hySOhEBr=-w3! zb!(uqytZt^$yKHifTh$`>zMu})c>|&&$S#HFX+hBY)0Z-3bB(Bkg1Dsq%Du8Gi{*t z8{i05Lsoph7BV2Rq#4!`y4!)K9Y;}QehsG`_-j%Hcq)QBiD4W((1_0zD?;ZvehgHD z_co^r0F!8YVxl=rnf?{Z{2pititlS{ASACKZ#?A}WyRRIYy!TmG=jx`@Zn=%_E|3q z8Spdfy$s3cq%oTyNb|^dguruY5O+UJ(y8}ncpsgbY#7ae{IsH*5a&w%+JGiI zA@pCzgMGUZ>5Y|k4qg*UY&K3ZA;0000 void; + setIsDevMode: (isDev: boolean) => void; +} + +const FaviconContext = createContext(null); + +export const useFavicon = () => { + const context = useContext(FaviconContext); + if (!context) { + throw new Error('useFavicon must be used within FaviconProvider'); + } + return context; +}; + +const stateToFileName: Record = { + default: '', + done: '-done', + error: '-error', + progress: '-progress', +}; + +const getFaviconPath = (state: FaviconState, isDev: boolean, size?: '32x32'): string => { + const devSuffix = isDev ? '-dev' : ''; + const stateSuffix = stateToFileName[state]; + const sizeSuffix = size ? `-${size}` : ''; + return `/favicon${sizeSuffix}${stateSuffix}${devSuffix}.ico`; +}; + +const updateFaviconDOM = (state: FaviconState, isDev: boolean) => { + if (typeof document === 'undefined') return; + + const head = document.head; + const existingLinks = document.querySelectorAll( + 'link[rel="icon"], link[rel="shortcut icon"]', + ); + + // Remove existing favicon links and create new ones to bust cache + existingLinks.forEach((link) => { + const oldHref = link.href; + const is32 = oldHref.includes('32x32'); + const rel = link.rel; + + // Remove old link + link.remove(); + + // Create new link with cache-busting query param + const newLink = document.createElement('link'); + newLink.rel = rel; + newLink.href = `${getFaviconPath(state, isDev, is32 ? '32x32' : undefined)}?v=${Date.now()}`; + head.append(newLink); + }); +}; + +const defaultIsDev = process.env.NODE_ENV === 'development'; + +export const FaviconProvider = memo<{ children: ReactNode }>(({ children }) => { + const [currentState, setCurrentState] = useState('default'); + const [isDevMode, setIsDevModeState] = useState(defaultIsDev); + + const setFavicon = useCallback( + (state: FaviconState) => { + setCurrentState(state); + updateFaviconDOM(state, isDevMode); + }, + [isDevMode], + ); + + const setIsDevMode = useCallback( + (isDev: boolean) => { + setIsDevModeState(isDev); + updateFaviconDOM(currentState, isDev); + }, + [currentState], + ); + + return ( + + {children} + + ); +}); + +FaviconProvider.displayName = 'FaviconProvider'; diff --git a/src/layout/GlobalProvider/index.tsx b/src/layout/GlobalProvider/index.tsx index 3b70af823e..2d5a7c7225 100644 --- a/src/layout/GlobalProvider/index.tsx +++ b/src/layout/GlobalProvider/index.tsx @@ -14,6 +14,7 @@ import { ServerConfigStoreProvider } from '@/store/serverConfig/Provider'; import { getAntdLocale } from '@/utils/locale'; import AppTheme from './AppTheme'; +import { FaviconProvider } from './FaviconProvider'; import { GroupWizardProvider } from './GroupWizardProvider'; import ImportSettings from './ImportSettings'; import Locale from './Locale'; @@ -65,17 +66,20 @@ const GlobalLayout = async ({ > - - - - - {children} - - - - - - + + {/* {process.env.NODE_ENV === 'development' && } */} + + + + + {children} + + + + + + + {ENABLE_BUSINESS_FEATURES ? : null}