From dab3ec5f84b4df3ab24b3f225be060386cc7046c Mon Sep 17 00:00:00 2001 From: tigeren Date: Wed, 27 Aug 2025 15:39:31 +0000 Subject: [PATCH] feat: enhance scanning functionality with library selection - Updated the scan API to allow scanning of specific libraries or all libraries based on user input. - Enhanced the SettingsPage component to support selection of multiple libraries for scanning. - Added visual feedback for scanning progress and status updates for individual libraries. - Introduced new functions for scanning selected libraries and specific libraries, improving user experience and control over the scanning process. --- media.db | Bin 258048 -> 364544 bytes src/app/api/scan/route.ts | 18 ++- src/app/settings/page.tsx | 232 +++++++++++++++++++++++++++++++++----- src/lib/scanner.ts | 8 ++ 4 files changed, 225 insertions(+), 33 deletions(-) diff --git a/media.db b/media.db index 6e59859274007741c31e665d456586b2f822e782..d6cbc9c7fb5e85713de45f7fc50c61cc80ed66e4 100644 GIT binary patch literal 364544 zcmeEv2S8M3w*L$>OfTt^x|t-JU=qr7#xw!3f(5b1C@N7B6=O?`G2z|;>CLWSLqJ4D z#6p*Bb~oG0%a*rq-?kUHcV_nOuKV_F`|s|5|NrxyOS!;Yq9_W^W!+z9?%ekM&R5QN z&iT$aZ*D@`mQ?eb>6_N4Y%$v;_ei8t$t1H`A_*}`B$CDO|DHb;e318if&WT*p9Ma` zJtFe%(;NRL(W?F|F}`N}n&EePgW(hHuQWR}_p95~NpM*F6B!U05E&2|5E&2|5E&SG z29|0SCWlG7J#EA4)c4X>zqfpS>gu$V<(s#pY+Al5ed~rT_+1y56d#iuZ=ODDa{MB5 zpwrB=XPNQTu)a$ttkoz@ub8BidcfURrl-HXK4sI}yeDV{p3wi)zNhp*K4HFEVX~N{ z@AN*1yv643!lbRnZ<;}m=zkKqIUWh)I7nMP;Z2p&9lSx;?AS-CD1-vU9^eb3~W*o1iQ?aW~sGyJ8k25BV6PmND9 z&qJwN$uHuWJ*DYAf7a||^Q`#^3Ea<{QnsXRSTpEH zbKJD}xS8g#?w?rzggnC&y2T znV*nsj+>v91TV6j9GsUNlQ@UFWb4M&H+spG*-7!!r_RDc_7P`Jik}h>Pl$`3*IoTU zYJ}v;@d@!zVdG-v#l=jH2OcKSFDjI#C!dsNK8GClN}>0IvLDyIhi^6CV}ve`MUGW+ zR}9jHl?WlUA5D1ZhACQ?wsKR-rtQo7Dlu0tHl}P@Yfg?|1ogAKj+*Dsnm%`aJoodK z?Hg13|J;2%ZOc0D2k!gkwD(hcDs=Z5YqzdnxgjNO9bV2I>ya?m3-z4eTXmzl@73EA z3Z0R%ZO!uTRsp?aLf;J{x^FQIiTA7ReQZtO*LUu4TIyzV7*u*v#V3R+NPjEA-fHtZ z>tH&&JZ0;abo}1k2U$>Jia9cc>4g`hi@E-WJ9TsFJ6lsXtV->^vgfP3pTGzF7`7p0 zed>#F>I6zA#r8$b$9wj^UGImGe)s7;e8ZJTu#yl8EFlV0{F6cy^geXCrT3!@23azn zm+0aDGUINE@%P3n@E`F{WI$vs$Ytt_nUWlT*)C^@OtM+v96Vv=_BgOLu1VjtJ(4NA z%I?o*_hogp!3Kx9BH=RqT=!_CIwai4t$f>O=mCDx7=o0BID`WOFn8VFXc}-XQaqr#%?z+PT#u8JTGl^syS@-n{TGA zN=sR1PT0OFZIyWe988}Ov3{d{8~HSHx0fyQ{CnhaW8Sfi|t@Tll;tJ56ioET-D80DrnY6-_{Ow>#{^-%zhtBbwWnauf)&Wt=D)w{Q* zt2LvmIfu>5Bb4tu)YV>W?##&VYA*2~JO(0QDvO!Q)85=1wmgHWYG+E$UTdR3BHq?E zUv7*4WD!$R${x=KS@aP-vd;*0{qEC#Y>(XIc$8Zm(Sa$C_B^8j%4xNUS}&)c3PAa( zYW8v?+mr=0yQ`^?sir$KintG0tPMNYjlSV}(638$0vJy#35uI}b($$rMo9y3n|A?PfSD<+VUN^zwN;zLxM~Z%N?-Tv`+}2R|K9n2MIGXF-YeTI z0zIXZdRD2Es8^Y$%60^J|xj9bs3~e(%15K9LS}#;f^~e(x%D zZr_VK+%BOP^@J!$&E0IG7RqUDfOoCx@Mjk>dB>Tm9H_u-P6nG<*45qteY>x=mOWV1 z>B;Hz)OOOXot{jn&s|OD*aKC)^*PL6*2=VBFf&ybyP8^kr*<=y7ue%%&{ehiPZY3a z4LlLujweYnU)$D?ypet=PY8CqEpP>QcpeBPLior;t&-EG!9wtRD5m&4v-doaz#-bd ze~&k-&RIvUBZExVWlMScA{ zuiHU=W;1_`y^YV4#>T1n0=Z3(?h}jMZH*EV%cF8K_R37u8ae$~0I_73`ihE(Oft)W zdjGk-?8SW`6JVdoD23)hgi)UBZ#~MKJPPvgb+i*T2-Kdci{8D*{GN8^Y7Rp;G98}l z70m5?qU5jPIsHU)yB^LHj@>Sx7}+V83?y1?@~;C#<)z$DKkz&RcZ;4BZBHz#=R1)Sj_>F}o0n*gWM zs{!Nbg@AGNbif#TBH$!C9Pl-oT=fe55a3I+7BHIn2+&Dw0kl$SfRWT2fDu#@U^q1e z@Og^dA&er=9Zx+6_zd*~;8WCnfM22%fKR*+@Yn``M^^$oOrHNxBESQ20QW}&-18!U z@fiTa!vK0+2%ywR(g8>u@Si-x|1%hL|I~g>^G)^FL*i85Qg$l-S0N95N**bjL{7T( zfA`T3$TKH|M8chWJ_cU=FjQbeB-Bo(t%a#-@?I@s>PwmGY(L$~T*!iI>dmLwJ%wz> zDK_(%_fUIR(-Cq`)kW^K&yQ4IYbqwaWM&6*u7qi<^U}@UqmcEo?^y zbd+QgS$2sns$zC!G4+{|HtvDY9K2OWxrcB!=AI0FZ0}vY`_GdT@(bav%>F#4ItTud z6N>l3Ke#mnkl|`tu6QSLse$b_dh>$ zCj9e^3ew<>@Om#&@5(*tAv_}oKWb%2!FhAbVmS)gbFJRC<6aNV=I-&HIp)p0!d^T9 ztPm?m8{O4X2Qu@)+a2lPWX3j}Al8u_P$~{Wsi9b1O|`M?`7$z))t8c?4c5z?IUO5m zi2{8DZo^&O)tpaepjFM?56R18+V`+IC8UO&ZD1-hy(PPtLp3n@2U5J{$C$dKgqoZ( zD1PJs*_?#JKS`y@J@fgp8C8XkW{O(5f-`kjfLb>93{!XphJ3F0P%Su)xpROuUv@2< zRnMN>4Gi>_HyZ2WW+<+iS||4`9ks=E`5KRLMF9hYH}^6iQ9>fj@)T2b1;#64pX7B>FmdW_vJNb+Bpb^6 z9F-#X#EshWT6=qTwxJqK-(;kPe#irTdcL;^OtPnkD5i}oW(gECD(HqGu3MIrLE&GZ zK9GC1-;9hw74h%6;yVEiE8BN6i`22Y3O1+lb5M(_4nY6OsW;x%Vi+O)S-Y8*1HSs4 zuBO9G-U&FTTRCdW@X~e6zFPPf33``5F9YuA1EcPq6Ta&G{^PA+bcC^($+^Oo7y4=s zvYt|=vKDMGV10xS{+dRjrZgV|%dq!Ym7m(3Dd!B3y`*3|i`YN66|{kXrS9ll07 zP)YheFff7ICiko#T?~NY!Ja)q-oLDZIenPuoTsZfPCz^1Xki<615r%naqlIfWD?Rc z+SvRKCZ~#MaECL!mm8p@-pkdb@dF#>#9aYIMOv}!pFr6kp)K;vRl_Pf+tAD$yu`Ma z`f>{9%#Z0-#&W>yehgj$njllSudBV#pIyK-H!#^5VBh!VwEN2&e3?z%iW%rxr%K=- zbjqNH!Q6?-ZUIf&*AA^Yk10Oc)l$i{Ww1FNT)pto#ZUmI@{;#(9rW7%mexpHgtw)d z9Lze)6gLsYt-2Zh!3}+D3=Ne?ZMG0z5VR$FqRlI`t`MJ1m7Z0}Dlv&BBq0U^`Y z0Efu@Kg4)KV*CMs_$M+TG9WS_G9WS_G9WS_G9WS_G9WS_G9WS_GH^#2hzJi+NTh0; z&D=YAcbZ}LZ;#^7=ea|ciBZl7DVz?*0-20=J}jAr^DVHrh`)*&50U);Qsdtx#=irI ze- zz7IP9Y&5=YeAAd>d>!@xNHQiGrx{;`Jpk;+NaORy@kX=pG2=tVdyP7y(imd+zlOgV z{@3t(gWu3)_?6*jh94V#VEDG-Q^S`HZH7iegW;T^#&FVb)NshK*HCQ8Gh`Vu3_A?l z4DT4$8P*t98kQLr8Ri*g8KxU18(uR^G&l@Vh8GOa8lEydZZH|{Gw2N}gG~P~{r}Pb zNqp#)A>zni!^>zBw`bzyV{bBt+eThC_ze}H?e_y{v zzd^rNzf%9Yet~|DeujRs{#AXn-l~65|E%7ue^mc~-k?|MLv;Vt{YCc&-EVYVx?k#k zs{2g$9o?t8k994&OS(E;jjlphuG_CG(dFqfbsy^9({0kN)4i!%p|?zT>Fsr9<4?z z*ZfQKH_ab4ztymsUu%A*`H|*(nr~=6(X?rO@U^YCPVYSW{YNn zX02wW=5@^i%^b}P&1B81nrMwx^P=Wijal=k<^hdCqtb+^|Ed0q`VZ>gsJqm^RR2`{ znfg2GPt_l*Thy1-b?O>*g}Pk5UtOZkQ)j9_RKKU*q+X|fQ@ujHM4hajrJkmaRllru zs-x7;tH-Ioq<&a^pIWC@s3oeutNx_=y~?NhT=jF+PgFlpeM|LK)m2rKszG&DRjoR% zI;`5ODpKXBXw?U*ZK{o`w^XZDZ>Scjl2i$*DXK}Ti7LA)LKUWZTJ^Z!Susm7O%bbjS>aSf zDV|r1Q+!GBu;M<2PN7gpLjNB6r_kSr`a(Ys{dwq5LVpnYtR7k9L)?nE1#vUtCd79THzKAZZa`d* zxDN4c#J3RB5Z5BEL3|T26>&Ab5ho+YA;u!cAWlMj4e?dPR}f!D zdNC4526v#fT%~*A!-pd zh-yR?q7qSo7>X!Ilp%&7N)aUlCI1icUx@z~@t=tQK>R!6|3Um4;$IQ}g7{~|KOz1v z;vW(J2k{Sx*ARb?_&dbkBK|kxZxH>6K144fi^w2$A$B5uj`&}QzefBO;x7?@f%tR8 z|3v&5;(s9i6!G5?e}ed9#2+F45b-m_e?$BM;`b51hxlE@?;w5~@mq-BMEnNg*AYKO z{2Jm{5x;`?3F4O#KSu08yo%V4*oN4O*n-%M*o4@Kcm?q?;w8k3hz*Dr5bF`oBi13F zLp+Ok2C)|LG-3_nDa2~TD#S{}lZX|FClHS#9z#5ecm%N=u?+Dr;vvL?hzAh&Bkn`o zi?|1IH)1Jb31Tr~5n>@?0b)L49%3$H4q`UqF2pRvOhgYNjYuJ8$Ym<&M+813u#>9ge1cmm@HJVW4V0#6Yz z6L^xqmk2yT;Bf+v5qOlqBLp5MU?T7kfd>gZK;V7?_Yt_4z&!+v1Plc91at(n1T+L- z_dk_XMLtB9Mg32T`kxf_KPl>eQq=#XsQ*b(|C6HrCq?~Fiu#`v^*<@VHzy|D>q@Nm2ikqW&jE{ZESepA_{!De8Yx)c>TY|4C8*lcN47 zMg32T`kxf_KPl>eQq=#XsQ*b(|C6HrCq?~Fiu#`v^*<@VHzy|D>q@Nm2ikqW&jE{ZE>Kwd*6q4-t1Fet@_G@qNVYi0>i3i?|JO zE8-T!&4`;2-$C4nn2xvsaXsQX#J3UOLQF$ki?{~yO~h2h)rhMQS0bh$u0ULl_y*!K z#Mcp*A}&E(jJODKA>snW`H0Dg^AM8|=OWHQoQ*gOF%dBVaVFvn#Oa9B5T_zeL5xS7 zj2MR)ix`7A3Gp?=R}o)9d>Qd2#EFP*#Arkpq7%`9Xh*amS`jUXQHYU<5s2Z4FCxBx z_&nkS#4yC?5T8XHk2ntT8N{a%pF%VvK8g4x#3v9RM|=$NQN%|OA4W7GK7{xn;sc2H zBi@I2FXBCjMnnUm9#My=Mbsdw5mksvL|B@de4?jfw4DsI( ze}MRX#P1<~7x6oY-$wiv;x`e$f%tXAPZ7U{_*KNOAbx`QWyFsWI}ooTwj;J7wj#D5 zHX}A6HX>d@yo`7W@giaa;swNd#Pf)Ci02T`BA!94MLdmIgLn$D8nFto67eKr1>y#Qli-5ceYPLEMd4idceJj97$Nh**G_kC=y;i>p$JjX@$Q)1KDcrz%u- zDJ`Ktl!u43NEh5e&7X?qZK|o3+IYLm!RB{gyj$kBwAHEUUwqolZmKyT(E{0<-cG0J z$X=7nOjL}V+B$fzNpD#hvj_InG?PvGa2Hlz%NgI*X4t&~w!!FXt%6OEn2v*FR}9$U zuH!Q7Wf8mGyf}U9Ci6Tfl{swon{TGAN=sR1#{F{53rJD>b}t^e+shVt{++*1=g2&% zZ$Hmyw_9MdXg9r4OE_L*qGrmej{3pt}n1Z5Y%kgzKN-( zVFP0B16J#^YzcY)|Yx-2&U3k)6&i1NCq@>@N=+ z5!JA;?;~tWf4&gdXY=;^k6rAO!EJu1Ed9%^{e*HGpWi1XmpxiwquXeDshTv5#U|<% zIrYw9Dfv7noKDjBTrGgDxcso!S9N|@>wZEsZzFCXx)b(4?SGEhf2bBD2^$M~PvtYa z&O(#v%qWEYKzpSzQa6`fwyfc^J`&IAW7p}7b_Cuq*+oUEV5{deQ=*KL2H+O9EV|ri zW=d<=BlWQ5kvWX3w$Q8ebRF{uqF!a1D%%m@ zjf>8(`?Gy}4~H|A`~62Mpd;*R+V9<0&?nNN&UiIn((he`&h2|qhubCeqMi^1skxg? z)IvF}4e+j29scYhChs^?l>-%+&B=g0wY%Copl^o_&e?-Sot~UdPi-gN+Ud!J`V2eY zvInZT9jc)|hxyA|nf422*liHDnyDe}9cX%EMB|`YfM6Ht3rolq+dnl&(JhS&ak-#C^zkiQ6tIl6m16{q@pK*w- zI08Eb!d_jZBEgpPu&Y-U*~SezcV8`R)!RsZh3)?i6!rD*ylw~ena%t$_BK9G8XKqP z3*2NYN!EmPh4e?3J0QHFEl~0Aj)2h-3%aw=3vG~s-~Brag;4zl~3VO;3#XGeaj(m($j&Qz#1AqHsedeb{H zYJ7lKZ}s@gVed+qs}ME%;4$CTdf0vshA+^ZueF!Q#c{nWbM64sysxh)H+1k@rseZQ3SYZFYAUQWe)QBh$NMSlfspuP*r8JE5-b(1-aDY@uBvYWYB zKjC@{e&aWhl-ja{dAPCr@mPs+3#cP$&l#(s{5(t51O~tF6DnKpHxJLmdUiz zgYd%$|IrUVOr-LHi89KlxWQ6kF6|{7zQQOC3Tt6GQ&1fi=%F)HHl=P@ostIs_*&^r-(|z<#eA{c)ctzpVzb+v_JG~J#ZGTD5ncpmx6IWN z-~Mbfu)ce$SH?8z>=N6*5TO-AIL5-&~m zTJC>sVQ(uQ;b%yH{8&OiQb(>xeU#hWj=+kK#h#^q2q^cAH+j^s-TUCGNG3jIS7E-y z9uI{iKZxh%b z$dtM~m)yC%!kc%cd&bPusQ9|n*e-(X!z)&Pg&Di0;nhd0JFv!Qu~Cmc2-CKurq^Vf z160QHOKeRuseR2Cnd}o?&H12L_qJSC=-0L1_(eYk1D)6Ra#pv?8n}P5QL7&ydV|)K zE~B0a@Ol-L|HvU<0eM5R^>BGDY~T#d!k1mkG+uzQlxNcEn{}}_desv7o_@u-k?VQI zblRPPi)p2%-w(6>?WSdN>Ry3TmP0ASSx*)yLgvH;VVoueHZb;3eZN^h7VbJumi%h< zj6sF^g6nu?u|^9FDOP&=ePl>UG*K2gl^UQl=PF?$00ud>xD3Pwx{m*1mH%X!|J-5t z3Z0wpN|yi3LH59Lw(uBO;CvTr2lqCE=WpySzikNp<(>T)x}{I(`C2-OSPaxdZX z6%+N8oSHwFOK(xWub3G4!H&r^!xq~`#JCCUHs`}vvp2sPnya_0$)8biJsjS;+ev=; zVZYjSYwpbB%x)LxGAvZcJTt%8rAwMBFtkE#9k@U|BLVm506M z`7rXrh)hQ6@-}lsM1*-t%Jx+A!t@Pm%-7m-$Y$t!FLZ+Sx(tTw!|ahFhN?3APQwiR zFwk10FK?z+O}w}Iowd$}4UN_xOE2f1#JZx`n}xPC&q z$@|FP{)=-U!#8ouUV5x^;;@=mEW#m|3Bc z7c%>b*>g>7`7vTys=vT^ieZ*aW*4A;7J7UoXZ_jWGdRjWlW3|Q@T}GP;hu%raHg-M zohfSdW}fh!+0T|AVJg8+)#K{nDXxQu5_q4{^;Xiq>^aa+bff77c@@Fo3fvz?xyk%r zEB&Ly@UZTm+8OFjRj1cc zP)sgXF}n+V$Ib?HT|tHQpWesN4WM?Cld0oalTS9V)Ok3>d3y(VuSV?dvafBf=U0>w zc~GywZ7!=7JI2sK7C(!N8uttg!zreC`S!uxVkbp+(s`X!K_^wyN$u+NfG36g>+SD` zIzejx>aX~P6gs!>J>6D|Ko8}n)K9}}&NkWPYX-k28E(ri5rcJIuK!4R@7o19E~)%x zKX>hbQ~KT|+9lLmx~VBo!7Sii(^5HQ4EQocncI5|{CZFmIfoz2x}oQ6I?Yt=gDF4% z1+V8^`7*^EK9lg$UvybtL0m4oEAVtCntr2y>rxL0su_`L*;n|HYP)x+bp>c#9>bHQ z``Tfmmdok;2iFxQE8pL8zM=2Ui!9aoV@1ZaGB6`Ov})7A`PvL6!A^ zk?rC|Z)w?b=%~`yr*7C{PJh#!l)gS?!>ZKfX7DRBl@%~c?yJrtcmI%&^@aUN9GOS; z(d=*uDJ)J;08a4)6MI*u38IvMDl{zdErxu0nS@~48#BiBX4dtQ-8HLZpGXi4w|@ibJ{8{9F))h zZGW(Yiuv&X!Q9q&;7QCT)G;{dM;;{&BiuyYE2rYGS7P8cW3p<@^R}dJG^cEaz*`W} zF!;Zb+el9SSNRvSdA)b!aT6sFie+(lQXe6;Sq** z7*km9t2sz!`{gxYMDUj9GIiNzqPXYO6Q5O62HXWq1)%sarEN?}6K4wTHM@lK?JnVS z(l%^Q+rR}p_X`jj9j_uSDM{@oBYwwuM+oYZv)vgj;PiBm`M+8cC(+Z|EX^#{%Zg2* z4tYe#({Si||2(h1NUBPtiN0S>2QanGNKZ9SOWT~1ws~zDj34v1q`)wmvMwFe*jdwN zc6xFu0+^MyaU-jG)pthT^0R8|`;f1Zq(Pnsy1oN^5wF+n*_UB427rDl_rDqGjDhmYar zDVx&QB&KiJyal7Ec%I*I&cxfNP2a@zlK*3RhtKXXZ`DVG)hXaf1sWz!AT-38sORL= z(!n$&uT6!ydP>@c&Fjr%Fp4iJ>)Eo;-jK{R9Q<}IKHzMX1L zUYoYr9A;jHk!CBmn`cB!S(jq&Bj%RgG33Ylp5#+?%Wlpi&mu4#v06P-!$^Pfl!*?N z)9%6KrL0TY0KGVw8E4f)|9!3fsF`W<_$u<*oMJK_R2&3n8aSYc=5Xm4%rqe4hWP2S zYP=;LfAxNtv;oUZSvxG*0sjrG?;)#{vOv4Y@Mkr8^AErjub#>B5MOL%IoVg&8exI| zt>0+JC1ZE;1r)Ul?0nJOsdwpp=3H6^`&R<55!OOS|U2%KVa3wu?EF#0|fgYB(1CRFuSkG97a~d z?9b+yCy_~J(pR=!X6kc%ZRepmvU$z^)>7}KyN|Vf+W;Y`FqV}vg$G~(0duO9sW})9bAMRD5e^;z=wSW(^NHB^W{1Pz$kbg4X9^B< zwVWl#$dbL&;Y=ab)qI3K*AUK><4B>Wi5R`S71o z=yd%B)&7&mh#ATZu6wqmur~xO+?*7X6mL$PKW}=R?<92MeGa*?`tr}c+V$*!DmCVW z&|CX#ZkH`^P?j}{?Eg1Ts*ymR|7}Jy-|8zH(p?+S3uTlmTZ61;LSVxbdP^S zPQ5nx1-UE{H*b-67OcVa+yVC=ZDt(8!*i4o()SE_(K}^nBrg=ULQV~=Ik(IxO&%~| zmYjNWK!JzpARxDUo*EB}M+V$)bh&fLYra4|B&P??Y3{Jgk-XQ7Uy{WPAa82w7V~Ua zWlw$%r!l`yDW%x&LGwsMKi&?blT))W`E`>@1-;B$$auI z5dk!-DG}2nk|Ia|I+L}Vt)ZFngGBY~Sw{`wJm#?U?)+?n;xy5v6FFT@Jvg9%lVfJj zoJ|a!-U}DmOI6;YOs44!vC8obq+pdpBa3;#^vUtF$@@h?l)QAnop`RM1!>z-%n2zZ zASi{GG_EgQoJC_?B6&!%TWa{NVLR-am!qGrAFn&B3)h~3edeMxzmT^`cFXFelaU&neD_whx@&-`elAN}hRd2+vwDCw&)rc&yQ4IYXb9EKFLuAo@w+r;}Wl3WD!{N6}I67w~~*o-`mw%1hZ9N zM>bfn;T$&O6v+p-_ZWMrHPT9QnB{{XgFF--MC=`BPJ6Ew!JELM1^DdGXk+R#$#R%0 zSzw}#&@GsI%hP#Q>2XfE$F)#G%D{;?&V2kP&`2Dm(o@pHO^0x8C?A>+D zd*lRYVguw2i(?9j`>DeN=_8n3S=>+=X(P4ZCHg*j=J+vR3vPyop1NVNcXx*mh@9{^ z;S{I`ljPI{HBXZyX`}lk7Q3;8TBPp9%PBp-1rEC9_2ftkvCGyEyb0#B8!AVfjFQM{ zS-{K4^y4;U{gZzPiIxYx!0pQh8TuZq2p;fw-$w6 zB8MxvMD@0uT0HQY5z5o6hTu(FJ>X&9+nB|e6j&3$D>TB{w6*Ky)Utua9yj4fJhj2IMo=j4c^xW0E|2#P% zzmP2a-Ji!)=fFR5Lh)Ys2e*fmWw36k`^N0vE51w3J_wzvC^d&!`vSEC{a}`@U&{|B z8hB2h2wX1Lz=b+JBA{P)l6t(;6fRF0c0Kmymc?>pu;*I6ZO6SH8tjYSGshsO27B=Y zNo)vqtTwu2=X_U@4T;v)%NJeBsT~3-!gn=L$qjGLT#UBpCNjF?AJe zPUGiLcdHJNL=ITFy{*OGl3o6+-Au~?Uwuwj(_tp>1f0`dgJC^7UB~RJg@2J?V1(&0 z(B&_yU``(<&Ej;mKQDtkqrTV&J0|Qo!8YuMHpEmO_g*6H06qhyY<>r1NhRTYV1m5d z;H#>I>_$-My{9{XXL7@u#z?LjJ9^3GeGf@~wT#be_fI@Zqbve7)|7UeAWB?$6H}P1ZV(E&K0)2&{unq^^}4G0UQLd5RoJ>s%eB@yP8RkJkByqXao)+ zscKCfa7!}PLM3m_@VB(X*KT5Q&Wb%S#~yxv{_Ba~8ceLMk65R}GH^k6PhIusZ3d{T z%S`L#6z;+?tnQd8&-d=FAnh#oayW#1HIjt*S(!|AGiN^M`U&_7|48lWG19<%oOBZ4 z?x;NF^Xy{kkND2-gMehRtHJR`IOsop7V0>uvKbl7IUw$ok3LNLZM+pM)9{^aVhd_O z0AR5%neU8oMkK_LfL44V*nGvGag2pte1CoTz-Ept-snZ9Z|(X4pXwXAo+l4j2r(dn zw_6@g&*N4ij~#bd9$hVap<9MN2hwxlirWrY7(?=LweRsB$sp`ko*}gr_IM~d&9r59 zizgfMdcoE!IlXd%b2w4m9`W4s*qP-wFCK>@dSHlak9epB7Lxx#YJzCPM+V1N--x>m z>)(xB5b|LCbNs?x@3mO(EYZ;xyTcYeaLkHwPK4a;RtL2uiWKZY({>2|8eFj9c@(jT z!@E>kJL5%uVQ>5{eZ{uB1$JPu!m|BHvdBbm+5XM@XOV-Ozl~&HeZO^fH+M%KH!h37 zk}SI?I)bbuF`1|x;QAk2C#K#RH#!n}hn^j>d*)C0wek+U22XT0p-6oDmT<^-7GoMO zUmQSeyzmH)OWpxVRYGyU0(Sq#duo(LXmvN{|C7v+7#j53bmKIK)p5$7DOSoE+3V6D z!r>eE^C;rTD7e^^CZnDpMYwCV67b3S+S|=xt_j2wxp8g!mh>;uDf(X`duu;mVAp>! zij+*&9To?d;SY@7j_|1HaI4eIjdvD{M-dxjf{4CxL2#ES%lj$e*DHwV2|Pgv%_)f> zVuDN%?i&{bcS-1+_lDCV+<4`29&l5OYl_GU~w~=$dY@TOy~2ruN%&?)q9n zUn__jyiaFOcSLV}jhF%AZpsY6HZ(H_FR`tqzMO(N^J8GH0tP*@m?7^Nm^h$!WeWFo zwHK1v4n%ZiXF&daZ%(_vyup{*)NRiK^Av=CohkvF9%nd(#j;?7^0mV@8+nlQudAh! z?7ETD!P#7VbTOF-Rl;KPI;OZ3(#e4H+1pZ04rZNYikpbN3um-&LvCUZTO7d5n0zfc z;w#GaRg@F^;qC(e(R`Tx!e^NB4!9>QV2`ve58IIXZl4K}_gxwP<$fbY_fI_D9qxg% zgKplV=r>;_ypJFIyjvqk#9T=M3Crston($d`4NiCYd9&AohHC8fwCmW(JV})TL}pw z=t#=|qIus#YQFt9eh1Y36OU+%V_>TBUZRs<0iwYiGeX932u1X^o&yT_HgV2?4J8Lg z*yE+_(E|*1*qd{q+g6Sya$m(6vH-Za)LT?ftg1){)M9c~(LOde!wb8xLX|{oOb?@MwxRku!_=Iu3!!hJPRE zc1Q)c4XEI}@A7N=&hkal{S!|T_Nc&;h;q}jUm}t)-Zd_?n~A*Xv*zNb(EA@a(w|qd zYY6(&+=KIEa9sv4>Yhltj8%6Hqt_SFhB16Nf5lJg*&SLwclN&82+6nwtlw^WCM2zw zW-9L*?p)Us4+lZw-j-9K)4&H`&TjBeM7nw%Huy=^kl4m&)5T-c?h33WL`7>t7D^0~ zM2Y+n#S5X2Ywl6suX;%Nh$K;(WcY{vFS>u|blL}Gv*9H22V0MNW)Cr~r)Ba?4iBi%!-lY17Ac{-fE6@eHL4z+WO!+Kec|6Das@%7MGWep*Z z!ol0}=Xo%ZIOpEI!*K(*KYFfb?l^4kb;$Ike1p&R`RvSLeDAf*5;ZU~q}#1w^E{Xk z+;SPVGh3RydpL68JF~5BN8oTqi_N2+N#v4#hn?AXs=W-uw;i%7=EmjGYdv*XU4wQ{ z?QSDhk75RqMG(b2ak}CS#XNDBC>w_rYGdhh7CNj>p_nJDM?IYgVyWqE8TDikM0l9P zEKxTeYtwy=qOsp{r0X3w;A&o@usa6s+}hVDrUhA}fc0ND8VJZ;5?b`v8}FI=dC(nJ zn(r>4`>+PHD zd_hDBtnwo*B0k6j!8xXGXuRew3He>ta9V_eCkRWlGqBs42x4-O3Bq~fErPp5acWqh zu};1qobJHU6c&pn7pLYsxE%op8e4^hdko znd!qaa*m1^R11kgLzbXRu8715 z6Sru2Z1TM1$$N5GU5=t*x9H~Suvw~YL!%r4Bd*yKC;^O)LZC0V#r43eUOEmH|66JRkS3?iW*BE}OKcjn3 z8?U)f^{bHYNq0*YsH3Dmll)cnjT^BB&=cjETgR?1)E+?+l2`0v&bP67c_gI}CLiK* zwm_00E|*Jpt|w}*_hKu%znN(x{&Y4!*WX%7R$4)-D7wz?X(#^r>=sCD4_kzH``HsF z%(X2ZKiB10x?o=Nk{z)&`{bR=rY51Ky;|gMNbaV_&mZr$&bB(|$0sB&jEjx^FlYK36DZ^4H2W;;((yap(~{>V#Jd+xo-xI~A}X01 z2kJ%20#P<~u{(Zp!qSA;1+lg$>zt^t1v|&Zar-4nE{K!`qHM~Ng-LezvPsjT=1iTQ zoH%RpidohPiCi>kgGgB*%Hoq}PMu^MXItd7&zTWpbvSoUNwz2B20N0AB4vRnb4R=8 z+G2OWL}0pe?(DFg@s=sDcoz3ZkX)k85R*H0N5qj*JNwdvLTYA-L@S*mG1TbiX#b`; zuAZj+gW_Q5BpDM@2#3YL8)Sf)P-y=VpDb%*H%+4A7zmA6>BmsswYlj?vNz=Ux9e#`-2^V(O|&q>%q+{&mY{wD|bk; zHz2Qke=cP95U#IFgPT{LKevZh?vNz&{Xq4V?~ip@tOGZS>kg5F`nn{zdFA|$n4QJ0TtFx&tDYWyz;V<_3+9a zlH@7_@ygF8W_P*;Qj@?A%@T=D@;iy4QNKYqUh{MH9@Pw`H1tREGFeK;gSf(nduYCz`r3XCgSU>9_Yi*~KM+nEzqQNH|EpgPA_QCv=E;BB>mIp^Em z%!Q0@YtZmptDq9HSRRNtz7FDYSOxlY7ybNOggA%ksgTjV`f9ku^=4b+Mndv+e!m4J z-0?mGj>{&bu({|dX@sn$qkc@dMF!g*iz3fx+jB@3o*k&x@r{fwYm{Jfow7E_h!iw^ z$xBZKB9d?Vaz)t%ro2!i*8~}ng0`-Zf3yT5l5gvBx}yZm|mg3{&)rbZ==t&=f%yfClAP6+a8T7AluN zB8v!#lP-c&ZvKx-lY8b5D;(o?ta-hYZZ>xhn|p>SJmcMa%zNgTH}i_OJfF#_ zhX{V|97v+)%dTa!>e-XK`8&aJa@rCMMdjM|)?g?qHy&&YhN5yh#Jj;zR8H@FFBpo- z%~iGsLs7XPn)j)-a?iX`JJ{T!**r0QtRx#VF1_1JY7XN@)>T1LT5fP%9VDgY#@Ey! zDJ?g|z8NH?gC$an0xEp~xD z?|{Xv!Nj7VS4YzPRG_-Z_v(PZR+z;t!Nj7lODFqiAQt&9o#<$x{THL@*v;K62F2ha z7;wC4VIUIu@y5{*g%Q{<1_6(o2#JZKejVqn7@-5iQ%N$m3}&w{pbBcAfQAUny+fG0 zn}cixb!%zje-37?|1wQjN+{se2Ie;2?aT@5)19S(nB(iy(N>{Z2{4y_w=*ZGLrce1 z2V#z|L`O%t1)}z%x%vN($^1VBK~3fKC)9^3UjUmGI4v$k1=&enWAG%PFZJ0X=Gpc zD=(Upbmr339fRvcZ}082I2?iNgVjREQK5vo(QhWP^TRc|I_kXCdG_K7$h_#QtLzTr zpbj&qO5mR$bv==^M7jq+fkQLtZ^F1{9sMqa-T`5=a> zjj~{(QLvMjoG}NYk=MyPEl~oSyh3esQ6XcaKfD!!!R#*J`aReHwyVj*RPKY$kQ++;hfa63l=W`+I>h=hVbyl`9|u#|zdwv}3Dv+T z7*=4L;ju8R+!`8%`@=Wa2BMMQA4WL^mIhdX#*c!DMZxY+x_DC{7Wv&_l-(V8hDuoc zFql{rG#pD8{4)@XJj1aw3R1cUw2%-McLo!Sf`()1?~4Pm$TJ)}qb%;gCQriR2f@Um zpy61m^9N#)XE=sc6+)wQ6z$qUSRDPZ#=~~HrL!oiX4cP%mBI0L+(lWz-^(8s} zvR#o;cBc6f%y8M`CwzGqNbdZCTv+$cwB&U)<*^yNVdHvpS5t=XYBO6@<=uPPcm4?X zm7EH{G1Osi&INLV16P=gLvYl)w}#0pV@jGJnH^h@%~W3UHe6+|G%)p<UeKO)vvoHNuOxDVLm1|H66W=NaX&B^%64*t5rdbTNCr(3^jNn7VTg zv$=)-GY8rBI#)D%_5@Q}@p;A(=6o~E9DP@^*v2!y!V~PJ1HQ~sm=}7hj4=hLCjE0cld)I5-1y>6Du+bBv!{BEJ^o=+P{RLL#~%MyeDSZ0 zJ<4H=1wwhp*rS|#@vCF+#qG#=``CN&XngVJvG?LGeDRjC_u@``@z$~T;tqWAHuW^g z;t{d$kG+o8!pZXMdadNCk9vmaEh(1BIq91=M1q>>&&Xwn%VP`{jq8fPH3r|D>x;iR z2H%`(Vc!^oZ_f3`pN_#d=LW#9!30+cS~m5nobFY&1GQvyUXGqg=(b33FfPZiRpM#f zGzJC0soCEidv9*#=Ko(FgKy4p{xKK-|5u5jS-(m5f~HG-MD?~ZJoK9Uf^2h$L-N-f z^81gSlj(`neI#NeZq#Q3u=aZ7*@o(_rWP=LfeYT}0l$2{x9GGt_w;b0+e5c}dvL%= z|7cE|%`FfVYXkP~4FdKAgE&LAUzFe3X|vh|LT(6q_XGiZg29`i>jLH?<_B-uqFk=P zVTXi0V-T<>9JIOXo^AGB$8!?+Y^hfOPC&kzLc2?lG*k8KUa9zR&q>JnJxZ?yt@ z`XFFWI7su6fJ+VeL7G+wHVj<%taJpWBka92>ep1?#F$GAB)rvRM`;OTqkl2ptyss1Q<(nr^&FCXJvC6X<>f4L!s1|ocz-J_KG6gdje>fM<}@d%CTV4_h_fsuUwN+25f3XC;MV4oBiMB*q_FwrQi$pl)YOm;Bq>l-c6 zLRvIgsH_Yo8UAZmX|M@D7MQER8tA*tMSE+mwe-I2sgww}@mQ%qr(2_DoAWnICpq+MCv_QCl9h&~5LEH4XG!FfmK6hyI z1A!=Y^DOsvr$ByktDT-qJwhm5GwS`ox4h{G@D58n0nGP(9uT|TEs$f>?lDmh1CLos zQ=H7LQmJf0;pdocXXW;|lr5=i(l>37WXi6x`?J}7SzRspk!(XVbMO+|TI$Ow=v@g3 zV+50TjLq+WL4YaT*VSI=&n{q^8<^}2wkgY-)6T7jWZUSjmO2vNj%ik54JJvmbGZ@L zNkXO=UpvIBqM7BIId_IN$uVw{dv^Tt_$aG$repD( zKG6vOuBho39125ppZq>6fU7Naqwk>H|Y9UlKxU4iK1hgjI69ReDh4d{Cy80ZrYt@y*TK=koLD{QVPfj}P{ z9ZB6!=zC@KYZf=rcmpUA(i#6fn6|$D&gO6m=(je`|9@IyeAw`!ev&R(yH1m#-m5w- zPW(j%Lmj#@kWdR&PyNyW47J zFqE~st!9nxwt6d;TM;vYWEb)OYowVH!&&`eokDX_y-cN1ESA^E9)g47-)&*QW1yY` zvsLESvG2&SN04m+Dt0mF+t|E3$W_4i!FXE_aXubULcnd~qxO0)wzB)1nYLoGr9*zM zzqJ&Odt0i(_v81p!w2vrv6;tM54ft(e={|H{&=@_w$(X5J|THwTx{%zVLPH{P49IQ z4Dq|+{N(HP-#9@c&x#VcE{P;em}^@+ey+>0biusjB|Bnm_Q^Y!O-<^R$PmA4lO@+L zk#K5!k3`0}M{T6r$Q-9T+A+gA)4ISBw$r(2*5Vb3_Q}i80E|A%A%0gr+;5XNfiwFI z%T8;wfOp#I38%)10=upzv~aO=XI#{WGv_5tnmOJ&bwT2yxJAwtvAs=bh~HJ|{Wd}q zIFlzZOO${ozzLBq&w#*!Gsulo`}#$?aEG@1X0T(Wf1VtN+bQ7AbJ9uF(}dD@OfQ5i zA9fhP?U>Zx@<)Yn>Rq`f zJ$MRj4&(ATNe*NDzhs@nFk5$2J5K#w)i%ZVLZ6i#33&hx-r_&cILZR?8=0#h&V7u> z@Y*6slsYVm%R0*xH<6`r)y?paM75vV<*z7Zk5qLBxtARA73KOW%HbzwcY*(CK69=F zKC^oY$>qExNF+Vc)Wz=j$q7pnVi&~PqO5bG!WQft7w5*!yfBV#h~HKB9N>q62%Om$ zy5w?O1U3na_JmSVJ#rf3iKRwJPSfnOtV_r5bWcm3n-K3_IC;ht`--UK*}W0FL;SA% ziR^lV-d!MwNKp_&HJF92$upKmkBgZX?_B2Eu_9?^-1u2ZJK}l;F~skxgtx9=5aXzb z9zlpbSD>D2k$aro>6$kqVb=5=6Jq8pn;k#tL)W-Py@D9xceQITzvmJ-lh<=O>;j7p zTrk3fi*g#O!R%NVJ>TMpnm#Ui+Wg6rW{sQYm^pXRd<RGmy^JmJUQ8% z0#S!9dLH#6k<%k4lWgX&1LH?U>OyM-4C~w~w_Y`%Hw7XY^vi3wM2N8ZjjV^mbcp15 zP7B)si|q422OvX#-yn~lWDgtpWLtQ&T7?q85?WsnY3)ZVZeffy8$ZdOn8v5o%A?g1 zC9vJGi{3^(PiT!F`|C4rRc*D8OPW4z{1ofrq)E;xJCf#%TQXxs%#4KI?tX~h@A+JP z{o`&pHGwcsR>qF;ad)Iw{W=q6PVK(MVjW|Otntp|JO-BAo>3f>)y~lt!7oV$_)yu{9m%>kS*}TZO8&ZZIgS} z-;D8vDcqA0Yd6z! zz*nEs)pVH2I|1i-A!l$=6{IL8DTgsdaU_h(kXsmL=>D<_=Ja96fWw@w_UC1gXVe$_ zs77Yb3ASN3%;K5KGOO_lENxbQd-;#s0Ri3#<8o7SM zmdMp9TT(2MbJ90$i1apG^=ITVV%qfL{O+_Hw&h_PQs12rv3{fdWqP7KbL-e`y(6uM z2`s_KMq4RzH)M7ffqWClU6sh)klYQCXGKyiayKM*Lu3t-oD#Vkk~@LP2e#Q7k-H(e z6PRfucc*EKJag699cM?#^Cn<*M#|2Kl-;0fMp8%o|7vNp#IQ(LuT`m6DF03IjC^kh z3x~wNAsFyHPfa9-uJo~QnY55t1}=~Rc6lOE3A}KIuGT#E&|zOkHdE9}tQ}P(#({jm zz=!Vh!L$NbRkbr7lE@GCbn+IFM8m|b5w|d5iFNACm=)G>D-!1|x6O&&Iem5<`i0Oc zKg93qdw`0uN@L|H- zn1u0@`|`#O@w=vT{Pj9vNaJz!h+~X9VMbOQ%VU%0B~PBV)49T8`~U5o349yHz4*0~ zY|A&d%h6&8fh3SfdrAsNNCG(^ADH@|D< zb5i-(iQ>2k_aN0oo9d=ppU)ojRdTAcxH9qZ1Oh(IOPp%Z55U7Cb>A)f;jw-(Ef{kh zE6kVr4}W;n$cOL0gP*~UTp-<^*lw zqsHCC4-eikdQ_l)@XkBM_+!(<`J7)qK|VGXR}znn$Xje3hVGMK->04;hk^nBM1I74 zsJT2=nmA#=f;-t!Tu{_BE^T`2;e760zbEgL#g)W;;;r`MMfZuf?^93r>CP#4kG`G1 zj-M_GWp@qdL}|gODZ-RQgjWyeJ#r~|pDeBuhPxoom{r651f-`O( z<0~6IcFOpB?s)hfZs7RD%BY9)IU_D6?~}!q#C@{VwF7y~U5*PJ(;e;!#h#)I3cpZL zn%|Fk+4&XM49E05Hg}k3c+SY|JF`ajuoN~u6?)bko_Si zCmf|>2}A=#4{nJZS%D4~o{X(J8a-HxVg>43)o^2E<)&C@sj_z`+(p<~II^iF7FrPv zcfv9J7p;Nem$V%73Yu5@$AH0`)q7uJ1_8ou|DR@%#5lm?CmAF$uRR3sW?V=Mmis?K zUvr0F?pxCxibv7{mT|+ z@jLD944UC3ZHE6*21zVx62B9g4|99(6}uDa>P6}**sy4c_pGV1XE!_*r?84B+Dpv1 z7rI}&>75xTH-5ZNWSrdiAwQXMa^qF&*YmQ=9R-ee9mUQfcOjGgwBudoKV2J~ty#~z z7kTc;nO<;Z{qOe0gsfVIzT;c);wX&Q)yW9K@xt(bGD6m%rYnCVBV-L|vVPOyaJ>~D z(4Q$|h|+ER{CLxW#*C|wC1JsvGEQ*4`uWDp5L{;5m7l?FcP^|u=fZN2Z9F`(@dz1e z!o}*?cQaIaZ14FVivKTgyy+-fSvVj+lD92)mglD**qYgX93!s83j#K-!y1gk$dlP z5?UYu%@^d&t5#{y?#L);ntqRi`;hj_{NZvET9AO|_nVhw<9+h2p^*sM?7sPUo?TCh zwiwg^YDdgRmy!SzMZNq!iPIupQv$j*fFm*%pyp)O0BT3f$}SRMqI{R%Cj`tR;x&N7 zGZvs0pP~WOj+n&;fIRUCa{-Ha4?V)SXDmR?K&b)Lj+h@`M2Bt!IcLSdGIl4J?+iO?+ouyW+*Qe*l={i?H?1gE`(wZW<#xo-IfIam`Kj}#Ow zrb`&CPlRr^S)V#vH<6c%Ynu+qCRrzxBPl5Ota5F&^*{3kN6~i*R~O98zbW@Go;P#m zXAAD%xwbjW;Y5ahyjWH`noZJe38n8cXS z#{HaRH5w7ddomnjl1|R7ypY70(8>Lr$Xh(r2;=w+$C#v&hCmyD|z| zlIoHKjZj_K04@ZOYQ9DzZEQwCOHx#l<}^Z4VWEybs&bJE4Y}vWWE8X{wIpl8G;&TO z)Dl*(GE*aHqcaMcrda5PK^R9#&u7Awcwm6kS?Y7dq5w=Igv9m;`)A3;X` z5*e1ZYQ=W7a#Lg-q}n&((*5|d51X1lX{(2vd!_Ouq@pTE_eJDmk#9RZ;h;OMHeiogWsyGUaV}Z zh97i6{Yv5EwOQM~fr2}xZn07OaO<(+Y7dey@C*yWozr;!wuN(=0 z&#-};0mpHP2H?19;C*kJ0rw9~02lqNc^x1g0e{d2ZU#J{#X}l^&3ueFrByirM zPz)~u@CR(*X29_ltp?z@X;8%|GvGl2xDfPNtd~T2X6Swd{F;($TvP2i99|B1PDT+f z1Z?!xyZE_O(1~e85CRtQRf6mf-3O4vGyA6b_-vKJNm`mZJ~o7=5ld5nw_0T(bkj2s zUD5)T5e<8C5erm-^I5#S5W0Ia5M5G?i?c0AKDER$Rq#m`dN4vaEd$XdEmob|vPg8q zVwDg2EP^u-x~Un6E@{c?Dm9EcV#x}oON(_r59p?3Ai5;$xpT2$Q%+*x%8Nk@>p60X zO-AT4*g>20wq+WgA|GDjZOaQ58#eMh+W#*HvNVgciwX-bp)}jyV56|V*aU0>HUXP} zO~58#6F9R3G9xMac#UopD;;3x|G(r8XH><9%*y{KhPr?&K5WXkXPn1^Z_YTuIV|{= z&{y5z=RQyQX7DPjdpjb>H%G#3?MLVx@D1THS!0=6en*&6QBhURk%}ljEUJj#oo*Ic48QW$7lRdc!BgP-lHu z@~vq7@9{kCD0UYW6c!a+lh5ak%DoR7?2k>rCSVh=3D^W|0ycp&Kp^xLclf^3Dx|J7 zE{Uw%iqx2z!-EH_hmS_LFIN^;D%*~A9XrrfAIgRk%dic@6I9#E%H>D-QWNd2mY zT`smq!&S=urfBObb@l$};sfgDqtF=JxhHxQbg#u~MTN2#_Q2R4mDi)tLhV;63wK0c zZ&Pb`Kun_dql$*9(r{_WxZxjFEW;gwg1oVcP3ne2@GA#*NA}@W#Hh>=7OxyeXNItN zwJ;|1v^)Gj+7DxWg)lZVZY`@VhwehP;O3v7TieyX66P!=v`B>|TjLJ3`eba)A;^|U{ z;Jgf)>HEmTLrS zTB1U9>+Y`hcBOt#sHl+iP9mMxC9 z)^v5Oj#Rh74^pt*GTczfuiD6F0dUs#58e4q%D!^&l%*gs&sQU$zNrIY(F@ zH4w&4?k5+S5#~t3KA%PGIwCyFCae+0%Nqk>+~j=dEi=MAK{yZ)En*h~@}$sXh_LHy zO|P`f5+-wR*53?KjQGWsn0o_K&>{{w0GULOBC2+BVsdh#4 z#0GAbx@9>t50WEhz{#1}AF!I4(FmVu12+S1IZ+RB|JV#TIZ^w0tJ1N40RFHI+zhzo z!ehX@_nHA0h&LnDqqETN5b$yvxEXL9m19svaMQq&A!fiu61d1)0GDw5|CNqnS5Z!3 zenD~m#d#&USJJoaw|i_8unE`%Yyvg`n}AK=3=qgjw-65Zzb7MQ$2FWLWTfnPEm4+{ zvg5Vv#Eg_38%`!=r0m#AH#s!l9ez2}-2W`L2~Tmti?Z19SM<8{6;CUgP&lbzTK*Gx zV{(Uh2ImaUz9nmr>wlepVgBU!tLt`j(OLamBwymL9C%uJ7@xJKAjol3#-+R9d+vB0 zgugLEx4qP=wm7~I1O}pTr`e}9*v{Iv4rg~aI<3T%wx#FgGV88<^t5E}6IQm-jN)wIpEnoDk3>a!9j!2AO5_4}<>mBZ zXYM5u8`v~wE_LWrA2F&*`;WQdW`u`g?f6a*n9oQ}2^abt5AypnQ(MC6l2ZXd@Z9MrkTBZk>mK9vgX04rGgQ99 zT`8W{?D$!=w=+P7?Kws!wJvmOwdwfG2(Oalg45jrmwNexkAcrEp(otoiD#NmABv*qEvV|z{&DB;2J47I7fa{ODwbkbiuC9DoCcY{6Jtz_6#76Q;H2H+l&;L2!2C-fy!xh1-L zwc6OEG_L|(?W2l%NL*8vtWp;)QTNtHcWxZ_^4upMeI9byP|io8lNsW;$T1l@?6{-w z>H=^6?RhhDpYiNxM&|saxW8j^_WRjG^MuobE`*s`log>^k9B*3`vzuT?wu`2&!* zs4UxRBK@H?(aL3!gC|h2iKW|>>LX=Shr`nWUzMHfAz=u%BtV>6_hMNgodEs_rUEK{ zv~!12Uk7h7W#?k=i@Id!!37za=Rk<@A)i~Gc}gK7JC7jV+ON`odCME>8Jc?`+wF|)@gXZ=6C3vbv@8s$O*s25b zM`Yy=sE`xcvl5aZ;a%*VHujEk^zvnWoLCP3_i?ak9M5U9Lx1S#y`dp)dB!O_3Ob;= z<#n>7dX1h<4QN*0yd^$!;_R%*zPd=wI%IT$G%&5VU^;=QlkV_TQZFoP70Rg`m-Tb+hwXtu++@6%xOam3>E$T2`}Lse{LE6RtKDX*M9EC;H7CK>A7a$c|lQp((XIJ|Mm{)ODY7gRKANi{w?)9Ok zU;tZ9E1F_|J_j(bwC%&_iqHWKDABDK`QK*yq~Vt+89?@(tK?r5Sc2moLCV*0t%Lx*GQ9 zZ0y$9Ei?LrQHH&;yFFV(MqhvxEcSmESQzck+SskJV@>n4^7;bE>R~?G5%xJYc5CdG z`}JCEA1fu&DFZ$+XuhGBHrk)Dv0G!uW*oz4$4wU7Bon*#27H{wCbEK0empcAVINFe zL5*{wK$=w9a4oqm^;H_LvH=wcg67p>0QKT6kQ-p;b=sQ{CT7zM3fiU{IY zG6$li9_{@1JTr)d9_%t!uoXFpkw=8$nxmo(#f5j$X6R-)`1k#3p9U!gjuZ(+=^svxh*i=X= zx_|ALHWiWzHo-Z5m616nc&Rl_z8sPWPAguZhtTPsWBv6a%`M0D;5$ z3R(4wtj(^4)kCigk^>!=m{KME zx1uPR*D4o8c|vFbqB{F*#pd+kv1)0!c4gmS#*{Ez2OzB5!Z(YMel1gxnmqlu$$8?0 z8B)Wu&smhQ)kf+3Ohsz)=;J2m3p>q_8XkOK&~HASqEY%vrXsZr%5bh&ZibX7wj2KI2DpJdUiwE{zZ-$f%xDW)%!W}KZDE(@tBDD;rxM<{YGo)lNh2XP_VL?b= z%2cFyv1o`-!A%xgRDe)Tc`0bVEtG(ezL=>HUXQ!c_mv;_(hlWTN673LG0O)48bA?Eisn^ZRX?C}Si zO)49GzWLN$TF&&}C?$$G;*+4;ZB z3OJGaksp-vA@ZU!=W|B{_m#aKf~Z8Qwz~w{@!{~%NYj?+_L}I)wP?$TlXYlYfX;d~ z{6@6q7?cpjyFCa)c)Z(#7TKb001hPrm*5L^-~?;Fxi(+KS1UkoxsB*Vl>f*~(iq+lS1*%`yoGL6Og&|78<$ut%yWNPuA3dn+-g&2;e zBm(nuj6;))PTZV!}{xbDu7?7v`~pmvn?x2MQ~7ff*T2LcwM zssVX|>_Xf!F%!*l8g$?AYm%hdH0X!@Ma)$pzdT8HBBU9ah>G|0G`?DJ+l9kSQ&M2F zEMlPYu;rVn0*|ON8B5h{q~f*v&y#cemX-fl{j ze2GhfsBPJty4aME|KH;YJBmF;7ZiS>;JW;q^Cm$JfN<)v-)^x9*aU0>HUXP}O~58_ z#t5W;Pyp6{9ls4d>JD4(n%U#dX+0Eh>pRvuw8m$$LXW${6Z&|}&gU=%b#HRdWT(BL zc-S&Ip}FqxtUi86S=hS}c5zjzH+*uu2JOnK#hj6O9LNg2zh2$EOx?If39W}+Wuf{a z+W)V*9jY%TcCXZuDE<_B(H)+hF*279&}#?&In(6Us{{Te)8y9c|NRy3|M#||Xj|d9 z{7>_?=iZ$2^X%8Mu64CKZ*jbR#@_Mg@)yao*yT{1O{EiYiS)ZU`0WMy@rw|IlH9 zJP|Gu^obT_B}JcnpL{VO55Jr?qg;sW*#m)2>Ygp+a8DZL@$t<2OvZC}qx+>+Gq~t9 zF`fm^ynGkHyAj%Da8bF~;fwiiW_9ZQ)ul>G-#D>_{lJ-GokTE~%O?2x1x zgC7!a%AWK0B)Oop2DXUamIQbq`~XGtLxfsCKvIj-79U8l8=g znp}iXzLYj714>J0*Rh4_!7b6Fn@r+(x7X;(0zX94h}n2B3aGqfTb6rN3R(Owh(Ri` z<`V)0?oN{nGn=eI3)9JJZ5RIh2j*lGQ*9t9ScRG)vIUtRB6`X8Alx1Kls&(KTm@SF_tf$JM4IsTP#g6kvw-x()39_oxE;{?}Z zdmvB6;mBux<|tZII3)j@d5`5j;(0jdq3j2jUlDJPC2?S)_5>l*#?!n z)Hf=X)~eFjqB^C$DzdT>0uN%l*T%LsP8bJgqoG=5+1k?R*4?p1%VNt9C?`VT6Hu!g zy4u>K6(P0hBzVqID*}YMrub7yR_}ry)42$3G5%T)q7B zXv1BL4s>s``{I+2&6?8#hjZGQtlI{bljgm?&@asv4jZ!s!13ra76I^=vf@ylA1VYw zugaxhv6Uy5^mpIatD&bJd_$>Sqi$+YjwufU|j;OVZl-A=g%9KUz z(as&wMZ1)v2Vm&IHIbE@P#E9Ij;{7)(QQ?+4Lk7t?dn|7)maB#D&@o)W!o`jZ$nqd zex>=4a(pxRTa>kj)T6tV`rY1VX1!EiIsj%v*kD<^^JK&LQ658fW%oIP0GG6lQk;Mv z2wY7M0eBG_3E&3TsdI&&`J|h9#@Rf1n44ZY~c|hNzPa`1moN?R31Oa)5d<77wWYQ*r zij5bHf;SQb@+b}ASj*m06gs#B%0*Q`8a|HBj7L$itT8qMhp6d|`9Jy$514Ds!L`->bPx`{qSQjdtVv&<(SUv(-(5`lO z^da*1h)6r@604o3LgY^%@&znb)9^yLS{_6nqCk&`w6o451%@JQW)E6`K$N@{c6=21 zzXYZpPxRglm64?=C&@c)>>cGO z$dZLJr{(Z}A19SdJQv5(!+G(&ndH#1xRM~lCZ%u~$PA!?j6cBkNJc+@^T%I06&biP zPKFBxBxA^`fy@mwkO_#1cb3^m(9d80!&^^92CgK?h!ztL1oK`dU*Gr1_{)7#Pft_) zd~omwJ(JO{B*<7U=Yw*I++Qc-?z{60yjFUgXX58`4^P@~Dm3t`2sAz`izh;J9Svx> zK;q4m`Z)Q^_4BUskDfaf8n`rpCg7JWjKS!6>PN%##P>MU_{;V4W1e=MiVR#ykP#%w zP%f~04i*C7r@Pkn(;3}_J^JYgZ_WAlhvCk+-VGcf$3tJ}7cux)%fW}%|AmeZ9EF_) z%krPgyC?TX&$T(1XJ44*asAu*XXbZsitdl>k%yvrXJ*L_?gx6O6`wyJ_%tsp%)uYY zK{<}@CAy)7sr%>G$#E7x8Nb;)RC_h%gLcm}qF>IEgNQ|Wubr|zjN`K%575nm@XKLo zaYM3ay!%`NgcPuNPir6o)PW$}b68m1;P~mxf2Ixz!ac`JLQ*aH_=u2TMEI!#L3rsf z2;EEP8oxLd1mUIQ#UQAJWX)a!2#GongtHEVzzwc~lG{>25Y9SY6j+NnLX_RIsDp6z zE^wm{%n?w{1^{UB8yEy`c<}!WPRs67i77(#N#?G5QG_Q$pl(1wH6tSj+~9cU-s02& z5x~`~k@uDtB;LY)i$L(yfk=6O;s(d=M~hNH1W6DaYaYrV3SffdFo<5;`j>7}x4cf; z*K||5q*?fLTn51HQVdA0T0~XO98Y1v0eI|Fv z`9Z|S5%DaH{O*TFmpt|C)kTjOikF*SNFd^a7V`=(UnTnxq8TN(x}WQnJ_=>+&c`U? zx)E`{R6;2yFJV3Jn2aIAbp#)uXz?QEp5(+e&e z#u+l<^?{UfZGsgz$t~X1eC05C2(ldXD+$ea%idnm@(IeZLlBV*Q%Q930pxY8twE&` z+ZT7WEmkX*!+yO`;Hn~e;uvfi7g>2Y+S-J_qD$c%E}e*e!I~pV#X4;BR~Bzj8rsyF zB`8v}`4B`Et49u^B2Dm%+IM@;!{3bGjPvxji}G^~&cXB04PprS1dEp%mzT{rE_O(c z;$cOvf(_uG1-Ire$m`7gXYQ?@1=&A#NbdWx1~a+L&z%Qc3v+hD#o8w{(H-t*l^GNd zCjYRaQ9U4cb#7K`R;bm>y4oN}w;fq_S~?*x_rr=NrS%vLFQ_8}!MM@7E$Z^N*ou%6 zYJo8msoj9yfQ{A4!VVOXz9NJ}#$&tI<3MuwJ?fekrL7HzkK<5s{7!^ZT^$`=ovYwC zz+a4oJJrR9)mkX!RtJSZVCY5<9f05CE%UNk=r61Yn2$n}+~NLdB9flf@~d=`30D26 zyznp6NhVmpBbk1YPBOt-9Le)%ppQ5$@dS1|1Xzf4tATdwV+JBsz$IK25 zbIY$$IDfMG4S0rH0rWdChgtz}*aGt`^8Xh*COV4#SQst%dH!2@-^@Mc*_*Q^dsSAg zyTUck`2;fqPWS!;{`RrRen*wRolS8m>MhR87p)=9n%IQ|C*#Hyf#Xg6?ZQwWC+Emx zbQUgZVh`99ucF=({N2SSCxv8*w?JH7)2k86yGANtC80{88sOfgm+P3llLEuvtVJmxRX8>DegrUw>a}(`GW}y z!oeu8Y*Nx2!6Hk(1F@hgJO{rC3D-MraO~On?Nky(;Q+zsH}$>41A+#{Na_X!2UenP zKO&wF^cLpd+yC1Hg}#|Ia=!~cKB+)&d{Fp+#R&RX5Fwg63tizTd*^Kv7Wx*@n1v7a ztw{~ifpLLY45yDp>Jy@CkNFQjX2ODaM);rv(fz3`_@QDDSlmt@3#|B)vxUACI8pmc z6Bb074L->87FjHa#W4CQw>aLp{zDTM zg#OJ3AmYXR83};?eXGub9{rn3(ZBVUYcKt+2?|30<^vG-V}-&a-$LK8NYTGJ+~WLc z!9yl22>qM)2mBTxI01M>Zl;e#ivG>%`u8*8fhH^n{TmX#{TBXze;%ytb3Jc6iYF9p zEc{*JEd@*R-^(AE`!8s+KQ;lIfK9+AU=y$j*aT=HAP;m`PClhq>^x?z^zf(8X>nQR z8XFa=NsMAiEQeHkNA(_!5QBvR91Jzhqlro(!G zjGvkg>k%;lYC5c&T_GLZ;V5$4js5@cYySV^o~1btXLDI@*SpT0%-7&#?>_Qi`Cc%q zgm3J1rhQ*e5a^y#IWXAIeDO)rY>itS^6!tE*j@+|z99KcP59u>@XG_`X$aWBlK#C+ zwWS3Zj4mTD+%SHpp^!B83=uYdK@$AN(yMVlm?RI9r|PhJSx}x9STJ`OVc`bH(T^WV z9b1GKK#(|}nOP5pmIOmrA5XI2~yA^rVdqRm;kis ziWf?W48aYK_E*NHf*|8Upl-2Q1vPlc1aRoxgFw&~bD9z_#Nrm_!QWPypdjOg1oQlP zjYW<;US~m%&znsh6}aW`;5{ZN$YH_zO)F39!(tqL!y+YIh{Y|*CFZd93?~zz$h^Q= zytR3FMDC`K1zx2R>n=TWz_GV@xXHL6mlC|sXAyskSlmS)3v6N_S?ETGlQpsl3v!{r zNv1_@;2GiaT%S5Fbu4hWH|5TBEMQnhajwhxa`xeDch=8x4( zVZEp|bA2yI!TG6>lv1<@#eXy2-r0c9^{i&PuYlI!LG*N3+f;(Nk)96YjY4jsr^8yg zIA*ZJ!Q9msW-_zMK`&0uT-TRpFunLZ)4!K9*g4)6C{@StLm7AdJ@(bU3sx%EcY0uM z=*ykdH|k&p^yN-$rLjz!Y=u@gK=W~Bv-GO~&-|wmJxxT9J_f%g!ezEWORQFYX zsqgm`TWXlA`+iTcd5wWRx>5cAYDdxc3pW-#n?EeC$n%Swec21L#<{O_{+c-kr_RX- zf(IT0n@k!84Z9i(qRIO zum+1hU%)IGOc<&Gdn8SP;b0WfG>BW6!XJ+?0Y;jPg8|muy`%w~nWn%};!}`a8OEHW ze(t|afRT3PplId248kM%aGC}K=9eNW)ogyv`Rp*n!y6_Kt7nJ4`fQX3MyX%yqvETo6TTk zz)HZfWD5fJK$-$eiC953ZqN*Nz4uj<5k|(W_yZPdD?E{d7~f zlvNR@uZm7g-E0DkSQQC=pH+!Ee;%WP|9`22`Cb0M^LFG)A31ga*0gsi(9=_K-h!wl}3K^Oiw%A`}R4 zh=#s$H~?Tr-WEp=aP7O+==hei;MJjF4EVJ%&`L#L16p7A(a={;(E7TaioW`^zV4=? zuQ+&V7ZrWQ^XpC;`pV*%n!TZcZn;mVoWpwyW8FgqR!Mub_EXVUJY^lEqOYRH^#B!p z#j492g=LN$c(iDE!tf+}lnT1|<#nVlYlOUrgOU1C0Tkc-!w@(%y|1reU@?eRFt5|V zmBVk?tyJ_CPp{jk=qrB3w&48#mmNhvENm&L%YPwnM(&-S!8w;^{nP!S>s!t}%reKz zXJxf7Un0*1OO3qXGZ_N=);>UBfPsi#(krGl6dWG&t5k~&VUQ6;*q+y?0fTwcp z1%u{!)*6?u(9Q*iy%O(iJr4H$4?U?|h&UFJlOzi+9E_KzXy<|hmkBPo!8N_=;Z!a} zVHJ_%1LjG`EaLJc?Obr^Il%=tINtZ|OXWg@rHCBMTFkqM%M-M7f#?b2%NjQ@-`qAk zl?xF~A+mnaV%|ku9;clP1W6dV;0DLi8%#DnA%Z4E7AhH-uL)SF=JaLYl7@xCunU`b zx^TmNFa9HS5Rs}d3m+?3gXCE{tTc--NnJW6+m2czBn0_A~Rm zkIkGnll7L(nfr_vHsy^~)F}Jwm4@orhAQv*_3Mk8rRmux=FFQ@hL7EiuaR7#HL*+$ z_(Y4@JrJ53hLj3Mo?LRdYdi&lYnC7^w|02xvwt&)EhVJ(2Y3s+MIiKo{2EQSThc7x zy4c!r_R8msazoVzzbK(isYJgdS=??v2>vQnf@_v)U2yFYiiT z9iJ=DM}pHbvuRN}SZ?jm^W(3 z(+#8GUQ405^2;A-Q-I63&D36kSgZxz_^{kRRT`%|Q-F>d>c=VLH zuif;XE?^!sBvV*jN(>MoU}5w?s9vHCRicoS1**ga&O*a_Efp2Mlt5**hbN0ry+|dh z#EZj1e(i$7`wb={t4j$~zMzGV2cdd_N>qvY$3lMX0_RovOmaD^-D% z6a}aXcp6wi!x#Xw2b!{0QqfmD4XmPJ8o((at7*WhR{>r_MPKnWu$GFx;*8LBRP+_c zey^vZuULKEKt*5iJkUr*U$N@ag#7;(IG%SD=M)tcURrQfe!sjyxvVFUGc0>-R+;-= z*F(-(%+qkenfpLsz=g;dLrY+Qpxsu@CR2uwvq%1pw7)=W+}0xb{G7R`nDc?)7f>a* z_U!3`YsapSe`*w5Bm@`z=0;sj@M5Y2Cqg0w?btnLzESW*P=w?YEOwyL1TUgWaKd9M zXveOj{f&Yre5R6*gCGhsv!W(=AytACPE$cUcHUotW9gpx-LiD+p719!6r7mVEz5?o5X%~NQzbZ|uZr4n z&JCN4f+zGqV4?)6-*|=+2Cwr^mS988fnX8~vWgMECd`1W(6z zVE_M%3IG4~d4qEW&&@d_4F3NY&+MxooJH3la|2OJXoYN`Y$oJG8LoV{_PQSgMbNa9)W z7@NAmk>FpVN^rtigyY*i%@d4*C!9qRR0=cCP1El97pW4Qe8RQk>=w6CaN-%~0#R0&Qvi+JrgpP6G6JmD;oIJ9T9=}e#T3v5}XKb!h!EOKe@_y#}mO#5(`Cs%mrsb zU%d+s4 zf)n~GM03EqtYFFlqu_+T>I+zufaX}_|Ihb4;wYY4)Li&!;q3)W^WV=Ol=s!#|H{1t zn(dEGz$Rc5unE`%Yyvic(;z^N69;Vwk6hHF=;^WUR3A-Gk9DW|7pNpcehueK4 zO}CpPJVp38r`WJ9UKvMtibURG*As1=528wN!c)X)$2l{S1SdR2uqTy8WD|P82T~1h0_y{2Q4O9tEIKiR( zHF}B9`?*nY!VNBn7Ww}i68w6q1Sj-W2;~65bN=HYqu_+TD)3g(i%9VPR0&S#tDJV6 z^T;-%;Do*^z%D4}Zg3>{byNvX=&MkD4DNW=B*SLXWgMZe3OBJHGDsQQ;qCnkisS=#fS8-)ukJA|O!4di@FIjB4$?@3#ztKU|{Qq12c)jNT z#?vtO+yBHSU=y$j*aU0>HUXQ!=ORFZBSq7|J ziVh`)BoYU*o#kc?F!#tdGouZ%5Xk=SnVjjqlZVksnqxs@2QX zwXN!&%~82tZLNzeS@X&9TBUluT2mL>y;kkq=MSiRwkXTCepu0@v>uDLHbsvtRFCeC z)@@M_t%+7HiyS-=Y1ybQ-L6z0DVsVRHWr4j%Fgv_^+}~lyRvm}bbnY~wJuU!1%D*g zcraSorYvfYcJ5H>>y)GWl%0#c&w3#@8Q$_*;ahy@{vJbGK{>+F0bAQ!L@NXV!Z3;< zB-|d@>yg!A@ZfWV(*r8OS~&0np;yDVAqaCyN?dnSHxd#Iv?KQ)zeA1#l7J{$WceZj zx6(@>;RDi+Tx$=K1PK2Rn1(Gf+Yy0V=p~SF25CpG%3~w}!Vv^TVtW_^H`7ZX;T6)3 zvc?!P1PPB&z$aLEgwPlmN-u$gdq_KSD%Io|AY4O!s0MEC6GH@o^b$z;iL@i;7q5^6 z2p^H(5AGDxz$&U!o65K=tyJ&}n?>|f4 z_A(;W#m`&$|NY<_l#tZ4>{kW55q0Z-W%xM%zD}duL~xUz^I4?9Bf&+g1SjvecIZd zoX~P5$?ENf0(Cj61WzcoWl+Wfp7;DFV~G!zP;MpBYKJlj`~RCr|Nmd({{N=TTK3!0 z+5~I@HUXP}O~5A52MAE%NYT_zW)T&A#Xj|FD*CD|;FuaJ`igz(i)rwwW53@L8nEL1 zXqj3n`ikv}byV~f`_z|G(O2wKucxA~_}OZpqOY3KfLWI3n&Y_0@p~8Z4fs!O@xYwj z*+0q7%HrJRp4amF=T6H1Ufy4wYl|io&M#<&9TGq5Cp6U^zR~HO{meY?V>9Q?WW8l` z=04*EPj{@MM%iDlG*rhnRC$s2{D9omxmm4Q0dDlJwvMj$cH}*8>5No&n)u6?x5ZY3 zlu%2weRrgGLuBPqrLkIB*r9F=DJw$QFCN>qKJJBA*R&{YZOW=$%Bs*LcesCF>d-Fi z(vL3Mr7o!hnY%hVx;j^ZNPr*~?o<~aR%^F(wbgaCS4GxWMh_hT!MtT&wsZg+9H@o! z{WP6qf*MRHMDe{oH*iktK6UT5!9ppMnJ+%cJOq z7QCsDSdXUD+ZR?N=vDRZlgxB2{@>B)DEfQhp9}t&|4H7ja~038a(!44CIBXb{Fx41pL2cp!Z7Y6FBs*q+}PfUSMZ!uEI{jD))>hL8y2 z!!dlWhOGt&i4Z=>R|%L$DQgh!q8LIVpby9MxoQpdeAq-dpWi3KUPqQAVJyWE62W~q zw$F9okYOYwLi_wa-eUVMZ6u7L7(ya(1sC0Qe)}~8ghc9!-^U5&l_@m{qbY`v$X&q& zcwOAL3=k68D}J9Z(8I(yiedArNtWVHF|kvq<9 zjmemTBqpC=Vea9%H=4kZp7@8gj0 zSJ(Fp>D=(d!F7rGoAX=LcHlXfzo(@mCLCc9$ArIT-?KV-FtH>i5o*PlPD~s;aZ}Uq ziNmoa-IVl5lh+MpVqh%sBqQFUmNX2d((sftWQ0SCx*6eb*>5gQ8b|`kh_%>7L1Q#I z4H@A`vTjCtT-lEd)fQkJi6kQ*nDs25wMl8n$f$VZZ_ek|C5HUXP} zO~5A5GlBFeSdo0EEFY&#^3{KCYElfc`(hy(k(SJ z(o8JfRP#`piKW|W%2E8kC;R)3qMsHXELf8NSl+F^bnA* z4nL-c{5jL8WQ;MG9eHQ!X6Pakk2ZbI+(~NY)WX!Z-@mKc~4<%zFb8TR6Q;WPd G{{I8sB~MiV delta 735 zcmX|;T}V_x6vyYx+`T*Z?!9;1NL^QJ*XTuzcGc4SS~sO0LQ*rW2xFH7LD2-YC#Cfx ze28M@M$;F#R1aDa=B2$z5PeW2J&5$uqll0YnH3qKXtNT%9A^IK_y5muPAriTTVQdo z47CWMsxf~EL+#VZ14c1RBDTVkmOJ*4If^ksJ?8wGB6G!;A$m4q-N2D8bP}-)BVP||O|EwJl5(9+imWkecTT}6r$^mprV-0E zj_Rkic2~c8O-ayc!Q7@iF$14@0qrXd_YcZbQE$tm!=X2bb}9C3y`Y zp7w&Q@?(|61r@yOCRyaiD+rZnF>3serBmT@5AKzQ_&FckOJ$VV@jGNE@JKmv*#)J< z3vh)C$)7EnI|eUG!<{(L+0`3pjrK+h0`(VCa_X(HmO2gT(nz)d?79$9!44iG0FcN1 zkMVat{ti2=H)qRIg=FCsxQTkEKJI-Tj5crN04j%>@7e diff --git a/src/app/api/scan/route.ts b/src/app/api/scan/route.ts index c37671d..dfcfb06 100644 --- a/src/app/api/scan/route.ts +++ b/src/app/api/scan/route.ts @@ -1,11 +1,21 @@ import { NextResponse } from "next/server"; -import { scanAllLibraries } from "@/lib/scanner"; +import { scanAllLibraries, scanSelectedLibrary } from "@/lib/scanner"; -export async function POST() { +export async function POST(request: Request) { try { - await scanAllLibraries(); - return NextResponse.json({ message: "Scan complete" }); + const body = await request.json(); + const { libraryId } = body; + + if (libraryId) { + // Scan specific library + await scanSelectedLibrary(libraryId); + return NextResponse.json({ message: `Library ${libraryId} scan complete` }); + } else { + // Scan all libraries + await scanAllLibraries(); + return NextResponse.json({ message: "All libraries scan complete" }); + } } catch (error: any) { return NextResponse.json({ error: error.message }, { status: 500 }); } diff --git a/src/app/settings/page.tsx b/src/app/settings/page.tsx index 9e015fa..2de3e33 100644 --- a/src/app/settings/page.tsx +++ b/src/app/settings/page.tsx @@ -8,7 +8,7 @@ import { Input } from "@/components/ui/input"; import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"; import { Header } from "@/components/ui/header"; import { Alert, AlertDescription } from "@/components/ui/alert"; -import { Trash2, Plus, Folder, HardDrive } from "lucide-react"; +import { Trash2, Plus, Folder, HardDrive, Scan, CheckSquare, Square, RefreshCw } from "lucide-react"; interface Library { id: number; @@ -20,6 +20,8 @@ const SettingsPage = () => { const [newLibraryPath, setNewLibraryPath] = useState(""); const [error, setError] = useState(null); const [scanStatus, setScanStatus] = useState(""); + const [selectedLibraries, setSelectedLibraries] = useState([]); + const [scanProgress, setScanProgress] = useState>({}); useEffect(() => { fetchLibraries(); @@ -82,17 +84,37 @@ const SettingsPage = () => { const [isScanning, setIsScanning] = useState(false); + const toggleLibrarySelection = (libraryId: number) => { + setSelectedLibraries(prev => + prev.includes(libraryId) + ? prev.filter(id => id !== libraryId) + : [...prev, libraryId] + ); + }; + + const selectAllLibraries = () => { + if (selectedLibraries.length === libraries.length) { + setSelectedLibraries([]); + } else { + setSelectedLibraries(libraries.map(lib => lib.id)); + } + }; + const scanLibraries = async () => { setIsScanning(true); - setScanStatus("Scanning libraries..."); + setScanStatus("Scanning all libraries..."); try { const res = await fetch("/api/scan", { method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({}), }); if (res.ok) { - setScanStatus("Scan completed successfully!"); + setScanStatus("All libraries scan completed successfully!"); setTimeout(() => setScanStatus(""), 3000); } else { setScanStatus("Scan failed. Please try again."); @@ -104,6 +126,80 @@ const SettingsPage = () => { } }; + const scanSelectedLibraries = async () => { + if (selectedLibraries.length === 0) return; + + setIsScanning(true); + const libraryMap = new Map(libraries.map(lib => [lib.id, lib.path])); + + try { + setScanStatus(`Scanning ${selectedLibraries.length} selected library${selectedLibraries.length > 1 ? 'ies' : ''}...`); + + // Set all selected libraries as scanning + const progressMap: Record = {}; + selectedLibraries.forEach(id => progressMap[id] = true); + setScanProgress(progressMap); + + // Scan each library sequentially to avoid overwhelming the server + for (const libraryId of selectedLibraries) { + const res = await fetch("/api/scan", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ libraryId }), + }); + + // Update progress for this library + setScanProgress(prev => ({ ...prev, [libraryId]: false })); + + if (!res.ok) { + const data = await res.json(); + setScanStatus(`Error scanning library ${libraryMap.get(libraryId)}: ${data.error || 'Unknown error'}`); + break; + } + } + + setScanStatus(`${selectedLibraries.length} library${selectedLibraries.length > 1 ? 'ies' : ''} scan completed successfully!`); + setSelectedLibraries([]); // Clear selection after scan + setTimeout(() => setScanStatus(""), 3000); + } catch (error) { + setScanStatus("Network error during scan"); + } finally { + setIsScanning(false); + setScanProgress({}); + } + }; + + const scanSpecificLibrary = async (libraryId: number, libraryPath: string) => { + setIsScanning(true); + setScanProgress(prev => ({ ...prev, [libraryId]: true })); + setScanStatus(`Scanning library: ${libraryPath}...`); + + try { + const res = await fetch("/api/scan", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ libraryId }), + }); + + if (res.ok) { + setScanStatus(`Library "${libraryPath}" scan completed successfully!`); + setTimeout(() => setScanStatus(""), 3000); + } else { + const data = await res.json(); + setScanStatus(`Scan failed: ${data.error || 'Please try again.'}`); + } + } catch (error) { + setScanStatus("Network error during scan"); + } finally { + setIsScanning(false); + setScanProgress(prev => ({ ...prev, [libraryId]: false })); + } + }; + const getTotalStorage = () => { return libraries.reduce((total, lib) => { // Rough estimation based on path length @@ -167,27 +263,74 @@ const SettingsPage = () => { {libraries.length > 0 && (
-

- {libraries.length} {libraries.length === 1 ? 'Library' : 'Libraries'} -

+
+

+ {libraries.length} {libraries.length === 1 ? 'Library' : 'Libraries'} +

+ {libraries.length > 1 && ( + + )} +
{libraries.map((lib) => (
+

{lib.path}

-

Ready to scan

+

+ {scanProgress[lib.id] ? 'Scanning...' : 'Ready to scan'} +

- +
+ + +
))}
@@ -215,25 +358,56 @@ const SettingsPage = () => {

Media Scanner

-

Discover new media files

+

Discover new media files in your libraries

- + {libraries.length > 0 && ( +
+ {selectedLibraries.length > 0 && ( + + )} + + +
+ )} {scanStatus && (
@@ -246,7 +420,7 @@ const SettingsPage = () => {

{libraries.length === 0 ? "Add at least one library to enable scanning" - : "Scan will discover new videos and photos"} + : `Select libraries above or use individual scan buttons`}

diff --git a/src/lib/scanner.ts b/src/lib/scanner.ts index 8be9884..b16fccf 100644 --- a/src/lib/scanner.ts +++ b/src/lib/scanner.ts @@ -114,4 +114,12 @@ export const scanAllLibraries = async () => { for (const library of libraries) { await scanLibrary(library); } +}; + +export const scanSelectedLibrary = async (libraryId: number) => { + const library = db.prepare("SELECT * FROM libraries WHERE id = ?").get(libraryId) as { id: number; path: string } | undefined; + if (!library) { + throw new Error(`Library with ID ${libraryId} not found`); + } + await scanLibrary(library); }; \ No newline at end of file