From bd35b9e2be9edce6457266d0a7c90c28e2caa4c8 Mon Sep 17 00:00:00 2001 From: Bella <65065992+Bentheminernz@users.noreply.github.com> Date: Wed, 12 Mar 2025 20:15:41 +1300 Subject: [PATCH] Add update handling and UI for latest version notifications --- src/MeloNX/MeloNX.xcodeproj/project.pbxproj | 37 ++- .../xcshareddata/swiftpm/Package.resolved | 11 +- .../UserInterfaceState.xcuserstate | Bin 29397 -> 94898 bytes .../xcschemes/MeloNX - Debug.xcscheme | 114 ++++++++ .../App/Models/LatestVersionResponse.swift | 37 +++ .../Main/Updates/MeloNXUpdateSheet.swift | 64 +++++ src/MeloNX/MeloNX/App/Views/MeloNXApp.swift | 270 ++++-------------- 7 files changed, 308 insertions(+), 225 deletions(-) create mode 100644 src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX - Debug.xcscheme create mode 100644 src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift create mode 100644 src/MeloNX/MeloNX/App/Views/Main/Updates/MeloNXUpdateSheet.swift diff --git a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj index 220ac3c7d..e79c0c1fe 100644 --- a/src/MeloNX/MeloNX.xcodeproj/project.pbxproj +++ b/src/MeloNX/MeloNX.xcodeproj/project.pbxproj @@ -24,6 +24,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 256C91642D8126E300F9736D /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = 256C91632D8126E300F9736D /* Alamofire */; }; 4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */ = {isa = PBXBuildFile; productRef = 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */; }; 4E12B23C2D797CFA00FB2271 /* MeloNX.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 4E12B23B2D797CFA00FB2271 /* MeloNX.xcconfig */; }; 4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4E80AA622CD7122800029585 /* GameController.framework */; }; @@ -205,6 +206,7 @@ files = ( 4E0DED342D05695D00FEF007 /* SwiftUIJoystick in Frameworks */, CA8F9C322D3F5AB200D7E586 /* GameController.framework in Frameworks */, + 256C91642D8126E300F9736D /* Alamofire in Frameworks */, 4EA5AE822D16807500AD0B9F /* SwiftSVG in Frameworks */, 4E8A80772D5FDD2D0041B48F /* GameController.framework in Frameworks */, ); @@ -303,6 +305,7 @@ packageProductDependencies = ( 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */, 4EA5AE812D16807500AD0B9F /* SwiftSVG */, + 256C91632D8126E300F9736D /* Alamofire */, ); productName = MeloNX; productReference = 4E80A98D2CD6F54500029585 /* MeloNX.app */; @@ -395,6 +398,7 @@ packageReferences = ( 4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */, 4EA5AE802D16807500AD0B9F /* XCRemoteSwiftPackageReference "SwiftSVG" */, + 256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */, ); preferredProjectObjectVersion = 56; productRefGroup = 4E80A98E2CD6F54500029585 /* Products */; @@ -651,7 +655,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 95J8WZ4TN8; + DEVELOPMENT_TEAM = 4TD3JXVDW7; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = NO; FRAMEWORK_SEARCH_PATHS = ( @@ -710,6 +714,8 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); GCC_OPTIMIZATION_LEVEL = s; GENERATE_INFOPLIST_FILE = YES; @@ -833,9 +839,13 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); MARKETING_VERSION = "$(VERSION)"; - PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h"; @@ -854,7 +864,7 @@ CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; DEVELOPMENT_ASSET_PATHS = ""; - DEVELOPMENT_TEAM = 95J8WZ4TN8; + DEVELOPMENT_TEAM = 4TD3JXVDW7; ENABLE_PREVIEWS = YES; ENABLE_TESTABILITY = YES; FRAMEWORK_SEARCH_PATHS = ( @@ -913,6 +923,8 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); GCC_OPTIMIZATION_LEVEL = s; GENERATE_INFOPLIST_FILE = YES; @@ -1036,9 +1048,13 @@ "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", + "$(PROJECT_DIR)/MeloNX/Dependencies/Dynamic\\ Libraries", ); MARKETING_VERSION = "$(VERSION)"; - PRODUCT_BUNDLE_IDENTIFIER = com.stossy11.MeloNX; + PRODUCT_BUNDLE_IDENTIFIER = xyz.belladev.MeloNX; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_EMIT_LOC_STRINGS = YES; SWIFT_OBJC_BRIDGING_HEADER = "MeloNX/App/Core/Headers/Ryujinx-Header.h"; @@ -1235,6 +1251,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/Alamofire/Alamofire"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 5.10.2; + }; + }; 4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/michael94ellis/SwiftUIJoystick"; @@ -1254,6 +1278,11 @@ /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ + 256C91632D8126E300F9736D /* Alamofire */ = { + isa = XCSwiftPackageProductDependency; + package = 256C91622D8126E300F9736D /* XCRemoteSwiftPackageReference "Alamofire" */; + productName = Alamofire; + }; 4E0DED332D05695D00FEF007 /* SwiftUIJoystick */ = { isa = XCSwiftPackageProductDependency; package = 4E0DED322D05695D00FEF007 /* XCRemoteSwiftPackageReference "SwiftUIJoystick" */; diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index af8dd513e..1ff84bf65 100644 --- a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "d611b071fbe94fdc9900a07a218340eab4ce2c3c7168bf6542f2830c0400a72b", + "originHash" : "587a0e7c5c7d612a2c16a973e66df9a6a582b963cb51df7c89fd96cb28ef4a63", "pins" : [ + { + "identity" : "alamofire", + "kind" : "remoteSourceControl", + "location" : "https://github.com/Alamofire/Alamofire", + "state" : { + "revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5", + "version" : "5.10.2" + } + }, { "identity" : "swiftsvg", "kind" : "remoteSourceControl", diff --git a/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/benlawrence.xcuserdatad/UserInterfaceState.xcuserstate b/src/MeloNX/MeloNX.xcodeproj/project.xcworkspace/xcuserdata/benlawrence.xcuserdatad/UserInterfaceState.xcuserstate index d95c76d6512f8a9579497e23d38ec26472381107..c09dbeb943b2ba4de66e96ce2cab4486d7c3eb79 100644 GIT binary patch literal 94898 zcmdpf2Y3_5w(!o(HuXlY22%qDOecjP+cGG)#gc6d1Vz{a9E|PAGT?+Hds0d7y@4s| zA-(tB3+cW0-h1+&+11LDEraj9@BiQb-n}1=y?f4?nKNfjn=`Y^TN)c$6H}(VC=h`P zOb`W0kOf7sE*iBq7H@56ZmJy>jn}Pez`w$y63s1(Ml~-#C{~wf^$O(JO%b=NEVMAz z9;^2!fu0vs!BQ1UL=!QM?C?lu2{yql^cMyQ1BE z%7k*ELfBuZ6hcB+s1mA$8lgcrNLVd23TuQWp;>4V4i=6OGy#Mog`Bc{bG(p?wTDp!NK{X2WIC?I2>sadIP?n2|JCU8lPGhIDtJu}-8g?z)!LDQ1vm4lr>?U?IyM^7s?q?6M2icSCDfTpb ziM`BTVehf`*$3=H_9^?4eZ~G_f3tr?K_ns-nJ9{O(IGlTm*^JziT%X^;t+9^I9ePd zP8Mg1bHxI&P@FF=5KF`gF)S_;YsCY^Wnx5JC$1OU#Y4nH#SP+N;^E>Eq9%fPjChiG zvUrMkj(Dzkp4cI75x0ul#4E&W#GA!i#9PIC#rwqj#fQbm#hv17;s@d<;uqpK;t%34 z;veEa5|f5X!=&L-jx<6VDdkF|q|wqCX{{$Kaf9^KaxL|KaoFIe^!4}|5X36P>W{i(ejGrb<10pcP$@SKDK;j`O@-@<$KFdmR~J@SpK#Wt7uiMR;$D6w)(97 ztOKn>ti!D%t)s2utP`x0tohdI)>+m)t@~K#SqrVj)}Xb-T5hehR#_KWmsposqt<%s zO6x(^HP#kut97ll-MYbgg!M@4G1iUN6RoFMPq&_BJ=c1H^lW*F>lN0ktvjqY zSZ}u8X1&vTkM(}*L)J&FPgtL}K4*Qw`m*&k>zmehtnXVtvVLm)!uqxKJL`|uU#!1d z|FQ`-W|M6eo89KJd2M}d18jqB!)zmLqikbsd)V@9Q*6_0Gi`Hhd)xN471#o{1-6B@ zGTZ*Pu&u_n*mi*JKwF({g{{HXXlu5`ZEd#ownJ@)+rW0T?Ks;Bwv%nA+0L|`V>{n= zk?m4jhi#kfa@$q5Yi-xtZnE8KyTf+3?LOOswnuD_+n%yLYujmi$@Z%44cptc_iP{9 zKCyjn`^xsM?FZY>w%=@j+WxUqyJT1GHoMdAvG=j}w-2%pwddG#?PKiY?Gx>j?NjYD z?6d8A+2`8*_9FXy`+oLPdxbq@ueR6Pm)axt<@T6;m3_6n$$qdsVP9uI#D17vvma$Y z)_%PGB>SoMGwf&E&$C}>zr?=TzSVx2{Yv{a_Ur67+HbMnZokWZul)i0!}iDQPuicc zKW~50{)+u|`&;&R?H|}bwtr^-(*BM8d;3rJU+sU`|8@|E=ujM1hr{7^_#FKl106#g z!yO|XqaEWM6C9Hq`Htz1S&ls&`#9z~3LV9cprgc5?x=KBITksVIF>o0j(W#R$3c!Y zjuuC&W38jzvB7bK<4DIbj*X5J9j7=>cbw%o*KvX4V#g-O7RPqS6^^SNI~+GSZg$+} zxYKcu<9^3Ojz=9&IG%Pq=Xk;Kvg0+!n~rxJ?>jzneCqhZ@wMYS$B&L*9KSpMatco7 zl${o*-RW|Aoqe4HoP(XioFkm0oMWAPIP;uSoYR~$opYRfJNI=KI0McF&V|l0=l;&H zv&OmDd4TgkXPt9}v%%TuY<9+-ZO--1L!E~^!FjavIOhq@lbxqI&vc&SJl}bd^HOJr zbDQ&W=T**Yo!2{Wa^C8^!+E#!KIenZN1Ts4pK?Cy-06JD`Kt2`=iAQroF6(raenUn z%K5GH2j|bu-<*Fs|8Y^5Yn!4ReihjdP86`CSFBLRXP1;3{^_cP(%Q zUHiEfy2@SEu4S%>>p<5kSA**ySHjiiTI*WpI@EQ9>p0g&*Cy9i*EZJ`t}9*Fx^}p3 zblv2-&2_u$Ue|rDM_f<1cDi16z3zJ3^?~a%*XOQpUEjHWasA;YZqco{9d3`izk85- zs5{p^)}7~`?4IG?%k6gu+zZ`h?)}|$?v?IU?nd_-_rdPCd#!t&`%w1=_gU_<-RHQ^ zb)V-x-+h7mLia`Pi`|#FJKR^euXNwwzR`V?`yThb?)%*LyB~Hx?tb3A)BS?`MfaQT zx7zCVKKb z`JNe`nVwmmeLeF$i#)ZS#hxXerJe&k%RCX!fu5*mxo3rEji<@e>{;ho?`ijd=Sa^{ zo|8SNcuw`4<~hrAo@bM1v*&it9iBTqcX{si+~c{|bD!sa&jX$ZJ&$^x@jUB!#q+A? zHP3sV_dOqYzVdwS`Ns3D=SR=4p5Hvbd#RUs2YZKjhkA#3hkJ9pBfKNMx!zIU(cbai zDc;%MIo>_JMc#n7*gN05&|B`U@hQ09_c;Gd$ji$@3G$F zyeE3k@Lu4((0h@0t9P4shxa<~_1+u2w|MXHKHz=O`pXiz3+M7_kQ60(EE}1 zWA7*4PrYAyfAId{{nPuGPx8q=x6kAA`h33rzQMi;zKOm(-z48;-xOcIZ;o$I-#nk+ z7xeAttMKjbtMr9^HNGXjs4wPg_O(oH@eBQ;5rHAPc3i)Phqn*DNNlrUNtgFi>%>pg@q znnQDHF8t}h*KYi6Ld4ydx6{y6-@Go^T8x7W)x~46re&$8#qsExSj3%&4;DmQOB+_k zF>0u)8ZiuZbiY;$j zxso%{R~lQ>9B-c=kG8Dpd}{U~)xrVTT%f)oN!J|xBH=(`;$=duuvl0kEENtAmI)DU zur@>+stwbIYdPA8%Y>+~T&NT3g_y8HSgDQFaA>~E|-)k}<6 z=f|7dT8tMM-?m2Fxr^$W>tmC!6J^bbhPqhm!iK~oDcIVI%Q4~}u`8ftCr9rJCX|S`)g{{ExJ-LsmeHWW zj$MKnEdS4@jW@GXI8N9o950-(*ifrYsE-yIzw#mb%0i`W39fyL8cH$~&^TM+z2 z;iRQyq0VQE%0lIOQpB8tQ-m{xiCcwJh0}!7g)_7~ZIU)wo3d3nOE_CNM>to@*Jfxl zwY@m+`xG}cCSq}2y%n^Vq8ws61qHVx+L}lSAAcNi_p54JkrjA=K_gaQ70je#_U95| zlhALoaH%$Rv#?p4#!UrRq8ao<&A8fefaMv;aSGNnu znRu)Y&6P3aU?R2#Cu&%%iO*7fL0clxj5wU5!Fq&hSkZu4EKPL_Xe>od-Z{WAa8Q~# z-K4RdLxv6;o^Afo`ugMXXnV)7oYVv({>a=-nuJKB$1F>UhYq)8^spR!KQ4Fkc(jy~ zVPm@XC1R+RKs??YMaYP9Sl<$lweqZ+K9Bl{w@#jtpR-#iG&h}O!klxR z6uQ6DxvEpgY@J6Kgyv#A=HzCf=_tWGTnKe-9p>HIFxz$kX4IY)o)=yaUJ_oxEZW<` zXTs;gm%?|#pG3l(nH%$EJXLUsJqWct7n2H}@~n(; zR-=eS`NG!r)aI1CZ|ExbXsF%jZYBJ6XcSsw_2_@ZY8z1Ibmkt=nlvuD6fSG6NAA1n`k!w1Z`#yhv3FQ)x#p;I=hfY(|K8zn=FV$z>%ZsDJL5q87u7Rr z(%uWhRn@giV@(GiqCXRe$vcj5f?j?N0y*v_5%rC6YpNVqX*#;WHsWUtOOly*_-_}{l<|5Uh$h7=UIGuAL zG@eZ>J6CALoY^~syZFrBsqMX4xLez2w=;V`&g_G`o7uVL9lZXMB|2>On#%UJgBqIF*W~1&&)&4sE$k#Nw_{mseM__{ zwZ?Thx#s-${zNKX$7Wx3X{@oiY!QO?b?EPQ{PIizzUx0=v&~KL@gUik3DE8$z=H-l(uF{j!#o)c=$pozGuDUCt34GpUl6nsNFmVg&pq;`C zTA@~?1-4+HUKU=_inaM#87Db}uhKxYwLRP%Y{K=2>vVtKNFfiFB5tqVVhCMVGzfM2 zieI8X;vqnDlM$&DL=$zZxMvZLtxxFKFQT@4M|c-C$a}*3!Uw{KwK`Hb7GJZNy9)K8 zI<#4f^@n;(+5%0`O0?1!5anax6X8>?EW-(;w+IKchA#|lp%z3*K!7iippVYc85d@r1Y=E(Tl0R2(;smloT-t%sD2tV_s z&I7U3@KP_kJWmbVp!%EeJ6fG?h#5@m5dPrgcLNn(flRG1XY(H-qHjb{rx8k+w!c=X zg|zTiG$t}ph@@3%)mjby{D0&d5f^a_{WfjdrK(Bxo%A97P(6{p+M>;*zgD|T9Gqe@ zSh$`H-JN<`T<&4_bWu->m;Gnz>E>U`H#*6}6afeLxEi}zsJMG0J|E=UisT1}3!CFHd^yx*yj=8P3||iKx5Z}5 zSy~ipiJ=~Cs>9e5VMdxT->*iPQT;dp2RTpDd?!nYI5W}lji zZ}VInYf?3Lq#HTWDM_LwUjV+I>cfWZ_;|XBb>Fx6c&6UgBz!*GeE#5G_JQ_`?J9*rCQ-6uu*c!b^8zn%AY{Jff~mU>i6t!@SB6`J&(JqBR{ymvXp zOBWUD8Ig57>wrM}xbR)DpMmeh2MbM3y!1Q1DfMl(;lpy1)NTCX{w|#jl~tiwqOApA zhfSO>%JFq|jm|wc!#A}i;v?ebCHQV>zsroC9uRT&H>{A+<F(JAe#Dzj6ZZ!p#Y@E`$8;nei~FQA=q%hP4bc5)1@4e8q4l(ZHsRiA z8$BHNLyw^+<4)+6^cvg)y_Y^fpX_4vV#eR*Px_*%A9BbTjJ?qp9!YY^C^A}GsvV#$ z(<0h|+t9@xMaGjo$OJt{7S-ysdamPgQNv;=nhM1#)1n*QSJJ~lo=ZxH(j(=9cKw}C zcPQ#(^_~6{n!J%+Fp?=UB%kOc+ouja)@TcQwrRLKc>zBMXsNjoJpxWNp-r=iC~KqvF}C@}|c2U=!L@ z%nzbnf>XRYuX!E(h5i@f2?YxIg#m(`u*t&{n8_t+Mu!uV! z;TA;K#tgTov9aBxQ&>@@(_P8=v#O!7KAwyT4STJ>%gl~pjF4=c3uR$j95E6l(YB_# zRUsoPt&FWemN(V$9ECBnE6G6}WEE-9TD64Mw!}~yIipAC%rYHWo?;@Xh&*Czd%kP zC*s&nA`8eVi#yw_(tD#FisF74=6a^&L?Y4U&GAHJ9cHd0Ez$PI=4idK9#1D{pv#MM z)EV3v{-92xBH9q|AZK#NY?m-*N6seakW;iHG)+5fQFs*>wwzgR$$Zv^^}r`3>m9i6L-#x1X-(z_9%IR z592ZNxOSFyb_X{-y3yh4CWT%Si>}6unXc(DSGA}z^(Ltu`3_8KF`1;FCvOQ8uR;g# z1@a5nD9(g#2eON z0<ETeaz(laM>_ zw6KorCT2J1()qYqOZTPosGk&<^MOfYfWw7 zK>B>Umj565Gl5HkxkXctI-s?=F~*mj5!UJ$5_Pw!F0+m*kpE_{lwyu824DlyDiw z#F-d9_B~|?(uTUY93$Oe6Yegzx&=&AB~=e!qTyzJ@fk9D0QyFBnf6Ghd`9Ui^r7i; zT8FVqjIN+7wMVtbw8yn4v?sNvwqrPR5M7Nw*P!ZuT6+e_;o8$cZs1d$p$9#Np1~gA zMtX8?ea5o|sG`tt;Y0L=4=|o_t&l%$!VjB76Tz+kh^?VUl;4Xh<3=?9l z2~^VDA!>CqQ&`v2L(weJc6x~RtoB?7-9Y}VyTW@i-tu;qm_4Yf zEJ1AZuTIY(wPU5dqJ64;uDt-n0mQC-q?qlTy|^wOS00ZXz4E(ap4jZlPQ0Htl8YRqYM!E$!`;vr11T3(*UF1%oj3 zO^?hC)kh4TuHYkpQpy7JE-(g`WU()sL0LmzzjJ$=;PcM&Grg&e)LKD6n%Oz-wi-6 zW9+4UsC^J|&-fR5HfcRCM`(#RA7u38Ir{t(?1vf4Y@s_b%YIV&Bb<{8T&1yk9_s|K zhNb-l`V#i#W#N7LDt(RD5iO6l#+KlJb9pII<>eHHdNEl&sUo&A+S=9{(qRjc8>S9V)V|Wb*1plc)xOid*M87`ypn!p7(MzO{ht0HjG{lG zlk!v2@cjlv)qd4*iCORoYN0`$?HT=Fzb&y!_p!Ra=5krw+*prdosC=Tu*|0fDPvs)rjQsT8#gmi`#BlpFa_gbrqUny zKkXOfJpXsJyV5->IlIiwu;=K{jL48g$-vpYy=Pi2nF1cz_!M8 zV@ykz#zSZtk%NFKTGzh&-S&%gTmz!)R^52s#>{w2qfq?POz-bK}@}OqWb* zYip=q-i|rra<}`ijlRp*Itn-3@x&pYE^3s=0wKC~U=!HHYFuqq!J-Z}K{#nAn}h@= zcPH@sU6m9wv zE;G6rjt8fRmcX{6MTgZ0V$`R-g=ZC4!|e zb*o}^t4ny2JWT+8RQ>jBLD&Mc9EX%9gV_R?lKU zJV1Ov`T-dLWFU}1KnABwDJ$bPk2kE_(w-9SNpr~7uqF=O2XNEru+A+6^K~n?tAKk^ zXjt`~kK~JVTWmf`v%$$nq*wNrZRGYB$WX)7M*lNYi#fQ-$(@j--R-u?kY>BssoYKh z86I)}KWH~8x@WLUFvr2pWM{Fn**WZ7b{;#QUBE767qN?hpr#lJBp1jiAfthd0fK9B z9FXxq_5d>BDt4)1a@ZEOm2JaB_9%9_fKU?+s{>>TkiCKIgHwiBF&u@o^~ zww6c1Xf^z8>#>>?vn$3M-B$g7VWe*5M(Q>od8U=RlUu2~*xmdekV!x$8$Z!f4R?<) z)!RetQLf$|W|*_e2QsyTJ;ojfG7ZQ~Za{WniF#ql%toGJ&l~FaIb9u3=Q{KSu8wDD z)4Qr*7>3D0k(zzu<)R2Xeqi#6`J6wnXs`Vv!HxQ(UP zr5F%Ksc;IcqM@k?oqJSDV(k8LhKn znh*WoXPW=}gF+FrcbmndfHWrUt#~ZjTk$w?BmW0v4Ui_|C)(Rwx7Ac2r;2BAJ$9OS zI*=A12X}~Pie~|d16luH795J_ix;Ei6fY1j6fXkO3M2ufZHst`cqzA>Yk{o$@3)-d zcEKfH*4-NV9_)9_Cv!_2cU|`QfLp&4(8!UU;*|({Rd?9Lwpn}3kqRHZQhMRc;IrqW zJ8Nzzh}VkOb3X52(}A?3*U=%~z&Ga(!CjqhE{FK0IXkzBcN*&b4qd%(K=m%(z#WxC zx?$nIT2}3&M^oYhnCKQC1abtHo`{cN?;jO03pb$7s6{ZWU0U!5L<4etH)FxWJn<>< z=`La3i9n#IFi(6ze6iD3oPc*YWZH_?G0YR+5Z@Hv65kfz5#JTx1A~I}91G+) zASk`Zr>sUsn3q)knZca-Fg=7btwdTT)qM0{61^qoOA;kFMmUlr$&wU25$0B1#%h?TybXrITHx3x3htqbCu*VG^o^jZ+ z@sj_t=ti0=`FSJza#e$IwbX&T1*mFfWKlI{zvfE|Q9(-!q@c7PkV}DV0FH;%YVOumcoKds_L$EvxPR&B808&4x1&kF6szIzU<`MWh3zsDz%*HXz%9 zTn6NFAXfmnQjch)71GMIh~_FF*Zfb6Xv}fPr8aJuWC?9@F_5b>0-20(#KbsMIt;@W zX#z2Ty77`wnOlKew~N?BPew{7N|*=;pIu}ilbe?p+bb)lCbdhwibP14~f!qS*Rv?(c zxE%j1b!tpO2)Eg^756V8RR1XVT}m>9)7MJze|5ee@cHze@p+! z0+1(xJO$)wAkP4K76_(~o(HlM$O}M_H7@~q8OSR@UcFYPGLvypkp;3MjFK&~Rkq2J z?2w(@puYy>Q;;e^3TYcas=~yGR1MN1kPgB}Ahm;Zh+*6Z7*)%LP@9{0xBJW;Gy zfAQ1mcyiWdwr|`#fL-tz6&glu5uimhPNie{WVY)dbL zTaP7L{J1HS>0|USvlm!i*tOeyt6%T1%dB5W^<)Y^)yu2b8u8#$eP-m;pUSso0+?=0Y?Dx-}?k~vm=jTt!n?5^`pI6||pOsfsFf)Jlv_Qd(+43Gp}HF{?xqb{^|L7bMgzO=1rSEds=?c)Ih#JFg2afT!YYi z5w}0HM|0*BO`B3MeQMsEDTTB1rsq$cmRB%+R&ib+KMfjs}TnbY#7&6pXO zHFMUq8O4S9NmVCT$kkZhF7Gc_${{%{R{{A9$mc-50P-b}ueQlG@*=rbUMyp-?Q0;v zf;bk$0Els}+sEn&Q+~-pw*7v7B-c<85%(+uQvW&4R0nM>d_8on6UcyxxcA&;8?lwV zrl3qeARY_p)n1*OvAgLY9=r?U zA!Y3E%ZFmHE~9((Ge0N7719xU6?3ZMdg^TbFvyf?`4e++p&oXaIozYls()XUJMoR*h$VJR6<}M_0BcpBe>5k>vSb zyq2eDRIWlzxu2K?OwaT;x3z}#OuYeFXdG(I25wp$Q&!EIB{W~g`ZL#4M*l+%Sf<*v z((H#(nUfW=pbZa_plRlZZjz%lCv~fQ8CLhn+vM#)8Bh`3X!#1v0a1x_&)6=RrrUos zj)kdnN5%yX!!sFa^dwn5!E@Fjf9h%^d53(R;c($bh=G=+SB5~|#HILVpcd`u7vE-`VVC;7mqsL_(;nGlF60(B{iB2MKRA)b zT`@-2P&eb19f@}C@uW=_&WkCBIrkJ8KewWhA2aoVajkNM;W1vRC1M3%4lVbGFBO1`@erkVpfI3heqz+bxs6*9Z>Toqj9ifg?bJbDmXmyM_Rvo8~SNBjS zs1wyZb&@(+oucNeQ`KqebajS0Q=O&GR_CaDs(Yz>tNW;P)qT}@s$VTo3)Lbupcbq1 z)dgx$-A`SpmZ+s_nOd$^sQasxYDf*MRcf_bqb^cw)y3)(b*XxQx=f9z2dYtZxmu^z zt1)$jx>8-GHmC=wtJOwzjoPF(t1armYFuqq6Kb2fR$ZsASKHM?)I-$`>S5~P>Jh4@ zf_kKSlzOy!jC!nkoVrmxUOhoQQ9VgLSv^HPRXt5TT|GlRQ$0&PTRlfTS3OTXU%f!R zP`yaKSiMBORNbU*Ry))!>Q;4|x?R0YyB-lpEJ-l5*9-lg8H-lN{D-lyKLKA=9RKBPXZKB7LVKBhjdKA}FTKBYdbKBGRX zKBqpf?o?k;UsPXGUshjHUsYdIUsvBy-&EgH-&WsI-&NmJ-&a3SKU6_CN=xCs0fQ|(^ z4(NEGdjOpPbRy6^pp$@3208_3KG3N^rvaS~bOz9wKxYA+4Rj9BJ%R28bZ?;h0G$hT zU!e1V`hgYzEd*KwGyt?1=zO3HfCho?2XrCO5}>6(%Yc>xtpK_|&`O{opkbg@K&ye) z09^#M7U*K2OMor~dH~R6KqEj81R4dp9B3WTdZ00&D}b&9x(a9m(1U=k2HFU84bUc_ z%|Kg#9t<=Nv=wLqXdBSAK-U3X540WVAwUlWinih~poarJ0;mQQfF23-D4<6JJqGBp zc-b`2jX;kFdIHcBfu02PWT2-2Jr(F_Ku-sH2GBEso(1%5z#2VzF3|IUo)7c_pcewY z2K(7V51L$=?uLpVq z&>Ml?1oUR0w*b8r=xso62YLt4JAvK>^lqT{0KFIJeL(LA`T)=efj$KEVW5uyeH7?p zKpzMC1kfjeJ_Yn?pw9q(7U*+8p9i`V=nFt!1o{%tmw~kF(Ou>QaX02>Hw5U|0(h5#E1Y#6ZNz;XZ+?`$NnTwtSs zjRrOb*jQlWfQ<*X2e1jiCIZU?HVN2dU{iqQ1DgtL8erNV%S_o!V6%YD1~v!Sp1}43 zwl}bSfXxNAFR*!l^`oo+SRt??U;$voz~%#604xY>KVS=il>jRRRtBsbSOu{CfmH$v z0Sg1G0#*&I2G}BCwZIkwTLNq;umgZC0~P^xAh0N~<-qEI)dPzGTLEk(uvNesfE@&E zHLyltYk)NYYX;T=>|kJVV6DIsz}kSV1-1^@dSLCq4gq#3unoWt19mvDBY;zyZ0y_!V$-qtlb}F#bfSnHP3}9yhI}6y^z|H}7F0k`} zoe%5+U>5?r2(S#1T>|V@r}N1G@s)mB6k7b~UhTfL#l0 z2e9jaT@UOAU^fE03E0iRZUJ^HU;!Mv9oQYf?gVxhVBs6P2iU#9?gMr|um^xW2<#zX z4+GY_u}6VD2JCTQPXK!o*i*os2KEfFXMsHj?0H~2fxQ6iMPM%hdl}d(z+MIR8nD*^ zE7I7Tz}^D(Hn4Yqy$kF;VDAI_0N97XJ_7bJuup(}3hXmrp9A{>*q6Y*0`@hqZ-9LZ z>^orJ1N#B6l#BfY>}O!V0Q(i#Z@_*BEZ|~)0{aWt-@yI>Q2>#ENI_&E;+5?Zh%$%@ zh#1#d01Kf+8;Eug9UwYEbb;sw(F0iNB>Dg=oy5K%_5-m$hyy?z2;v|R2ZJ~S#GxP# z1FU5db3hyc;z$s4c?_)I>7)Lt?S~~^Bt1Xbx?zLA2;+5(!u=(YP|?DW3H%2K?%NHx zvT#8PSC*PRuqYg1EYZVUK9o=>5RO#%3l~O8{bj-80A?dFGZ3k$3={_!nLV;{q=_k{ zKxqN*M+!9*36>#7c~KRn9SW+-ib?_|rX$%u9#vy=figd)CnA`@C<nn#ux+jUo4u_rbDI*k4i-3H#@#(0v?z!Yx>Km}*M=g-oP}zF#o-9D zt*ppjSrjP=7F7BxgPq(T%}Gq^N}`}DSYiU#Mo^rv-=T12u%Ifv`EeX~Sa#fMY{g#| zPEFGU4m-Fj?EJ#QNOho+C%DWpP2zy#y8_}3SXJ|J{<&o9Ea-}s&(VfJO%-Hkci+EUD&t>|_bY!;2|-`YI>2P*O`OXb^}j2>5Y%ha$z5<)x^Uf+e_q3>B5J z?8-T{ZW8aW;Jr6QE3haWFp{qRiXf`45=^V=*1=NAamRJ-NpV#upf^|)2^CfbE3n-K z{!k~At2oxwu2`W$e_4cUv$Szz=W(qi2b5Yni#Yz?UGc+}0e?7B8VrSWp-5{uQeG9V zs0xQrVMhX$mF1NwN=rDUysngz@`a0-C{jMO(Yf%17NW5E*YmW4WJ871tiRD2Y za9j_76@f~fRpn*KV_XI)maO4e12eEn{gn#?Vbr~8R;q=Ajn4oxdl9S-WT?kTO(3NS zS~*%y1{yAplJeTpKv_6aQf^3`In=crdQ4By73HBY3N&_#&$x-x&T&R{!Kn_Elvn6Y zm^M32S8U)InS3g$#6eUpG#0PfJHrN-w7Gtuc$RN0_uERF(&A_95i$0^!Fx7-EGiaEED4bjxivE zxPcK0*LHef7jvjgnM*<$zCdkhL3v3^{x@;x+zgt=#P`IAEgWHN212l6L3vrA9Mx>6 zY-dW(c8)YU1F6(sSRPu`Gs+cNI##`_Hm>fDu&8oZ2s=1J=5nj?qo24doEtdKNU{Jg zTEat)8#d^ZYg(Sls=zJtS;-R3Av49;AMHK?RmUVg@03F z!v^mD7~6+@x3Fd*7BjT+q7&o7#YAI!`3n7VohI}o@jSfQg*!RHyxtJ3;g_iL+lfrn zdpPRM-J{~|V0bi;AFFL&-W-kB7vq6`lg9m=#$LOpQNr&Qz?0_sK^pVE4ZdM%5_*Ue zn!kHORlzhuA*}z1l}4KyR^Ta}$b9?*Zz)Iqm_#4#C38wbRlz``UTI>YKEY9^?!G@I zp#m%}GY&teGxuqZKV$d!g~|Qf>VUa9z^BN~K zd-okm5lYElI*;DuR3`79iXp>g4a?Jo_Z^Phi#g(V+cXwNTX;Q_QLuz%K8DZuJ}1!& zF)0gWpO%j}esOR5&pVErb!+h~S=_iZq^cFKE-5Ua5oT2|rOZtSU--~H=EYw+Sl zJT#BDlJrFMM^1E~-poy5v=OhxjmCQ%^e>!LuU20nDu8&jr!M`@>FnLBF5$%nQT!HY zPn7=Rl>EJ+gc7zIzb?uzmx#rCAZHagxn7BhS^t2ghPxuj{sn^Tn)n5byCEoZg1wl6 z@=&s%Cj08LT6#&REL4o2a0(Xn#4$Uk)2j(6#=6KNtV+}`MDK~5i<4W>oB2#vBv`|O zA6lsEX$e@poNBLBNikmG)XHl}+IkW>YhO-mUT?ZMe_=7+*xXdlue9!Izymn7aBrxg zd)Am(Rfv~lpoMHS{=(AH=6HQ;XjL@c%kkujH?%V8vF=Otru1p zt$8z+yf*a6#ZjD4uM~<=@|$SysY_#fJwTq0Z7ho=_+{EXQQL!4E9lMan#tW=S{-X1 zr&so`)AKjg*R0|f!S!q>tW!Ac@_&VPIJO2$Ch^LJuEX#Aa8c61uukK|do@8OBf8Qw zDb3`R0{==kcRTVqoaEfzkkmbm(ze!yx}LhXcdu!cHsI%6T2?hT^|*5P<+OUC>(ML3 zuZlI}Ls8`}w7K_H08y9G!`NqCsc^$u0yJsD}fYa{P zymq7A)3_IMlD%4e$z@#K+=yQ)>{0WVaeBS-4k}hPCz_MjTKenjd+Ol+oM5j^Njkxv zsD(MTUO9S|F}#X_=LUKrRl`XY^=3sNsphpj#M%w-7WcYyA-w6hIgZL6Lyfi3y7mhE zY*<}8ZvUAY;DCRfR8QkPkdx{~^oF;HH^duyqEg4H^h$K`+a|HPRorUxYg>1*WLI#K zz4C*MGIM`D&M3MWM&h8Sjy7p>!v1+LphCUyXU>}nXIg#kpsR(^L{$8*4O)9LL_GC`B7j`*C zw$+R}3*vZ1dn|4eI<1%e!m3|$SPvvK3sS6ibJ!6C zuSVr|Fefj^*hFaDu)!#N!d+ZmcVPDRJ`O%I8#q?f6qW?}zArDqFySBM@RPH_>m?;v zcu|Twn85-p!wA=Qsd}+K!jZ@C0=cTPk~i38NRM;0v02fuhC;9PFt#cyIyaiFPjRID zY)HJm21^I9L4e z947MAz%_S!(^>lxN1KqX$?iCj0<73D=j2t6*wY*a%Bq8vdFV@{f!nGBtroQ69!?FSE^?4cN{g%Uy z$qE}@pqF+Pgv-lI(u+{6KX9C^3%1R$B$X^@)2`B ze&fhlnT+L0I_FTZQ*!(#haQ)0Gz$ZP3anNNR`Ws`UVl_smcsgnWBIdTp>*wERgM_R z6^KQHRa`EOGNM$ynNi)5?6Qq=a#q;7~QDaz} ziK+f8nCYc$HXFyxx{7i5xZ}=&v(?1eoE$MLw?lynzh2*FEHV8wuE`z`$I2=_=8UFG zkF5^}&&|e>5XwqYpwmjEZ2fy2PE}co{aKd2ZBUQHK|Z93YDKz$+J)o-d%CKxLX#~s_V;j%$P)vCix#19fzaQJfVk@(N zHl>u!vT1X?6FKIzU16dW6!R)WUQ)yBBK=sAT%IaNwoT>)P+GG!&2_qgg<7$)Jad6e z<%p<;c8#c)^Hv2T$$D?I+cP*a8lVhhqx3gWipn0xo@_eBquCr~JgLC&KFYr`XO#1m z%{R*9um;JjH9-fW(_OLcWwexr#w#alaUo(&9b%#LfYnav6?V3{9A#2^ONG32F_6{< zUn~5OJK`HcWDd;FaR;U2Vr>nYEp#$;N6~~U;&9_K;L6eONiB=c;iPGA+kB3dla3Ww z6ez3;>nkBu1!}gjABP^=12h+lRQbHEl!H!42kqNRG!ugy?#_A4r>r$uU&h+_g)f_Z8E9K6$)|PZD}VPG#fdDBaKdPBw2HvJQfnc8!O7f z!Qx;lLb4skQHEzj=^p&qG!8r<8*sW-I*LP$%7D_Z+2F%VRzr6Yq+>Zo#w=7+6<`H; zXBByOh91vxGL(#=&XX$BsJh0Aeyo-6jGJsHajXorQB#SG#mVZXVNT_sV@U`%c)kUG^s5-$VgY>qOr3yLwZSv{%qIDBpwc+<_x z*1&}vVR#pW%E02R)Gy({dv^g&9bLeKGgWv%1Z%9*8bbS5fG25m53BPqi*0i@O37+^ ze)6dIl(uq86T9>&REuFiDV{GdedDwqrL@dt9CLhj%w4efN{%+93mQLHVBnz2F<0C* z9I~sB=wh)8^4D>s9Fn{%gqN*iiFGJAzYN7S91NEP^svEf;>KiWjGIN$p^eoXt~DWV z;gHCuERbb-u*AdatZm%RF$ZSDOfP1(-NnHMb%J4ScB-~L9PpQ#9l5tlmy>52aG^z# zXBkY$2RP)2PKrrLJg0@43SBe|DZ;^2e#Z7N2Orf9TxYm(eGlSrJ(H4v$2bPAE|VuE z{;Dzzf(!BJLAVl+!|>C0JS$^%=t&NrHaFeju^qFZ*!B#E#_8{wI$DtmY>QtDWH#|U zM@k#BxpsN#Dy?HC_=_AIm#^7|Va7XUCc}om!hy$i0;B%tmlBni877S%AVN{&=hxDW z!0Q|<53%A6c;=1I(gMtqpzno8R*aKa#U+77d<>XQ!kX+fh58mp^^vfC?LPXg{9IH7 zi?&k?eU}4FO#{d{DZ?ca<7Kq6csxeOE%paXs*r2u@IT=Avk-rMB2T~8EeFp5ZP<|V z#Bd7nGznhe#GTkMYH>Yz#GU)9RIG3Nm=l@UjYyauDN2qIIi;@=W8J2j|BPeq(G4@z zd`~TYnH?`!#z&h^>t&4(Tms>#3b^yb;}cYAh!mJAEbDMGii$8+bC- zs*-Mt^l z)_F$^N5rH&j>C@VxgUC@nR37F6FB%nz1k`VH)ZrK4XmTVGSAkW5N-e^@bkoRwE28$ zBY5x~6(eRl@Thn=xEP&QG-F{jVmuv+Ju1eGz1fdRobcY6g!w1*k{c$xB*P@z{Wxz4 zx9cXQ{N7VqGKR zy&aZeJkV6)QDrk`!5A2yvp*g}Jr!;mq3@Rz9E{&9g%T1&bjx=RANWA&V0C&xk(VvN3&atQU z0vqQ7bMvK`?<&B=TNaYWsq6J$#j*_>|}Uqo-47!3<51#hEakhqz#K> z(LqL8D8x7_5)9!nNFH5cXv80wTxjL!lQL%`6Fs@E{h?BRn<;KU6`8neIc}Gk%)~8> znBGV?7p9#fkKa|pg{X+I(NHZ~H}e)0`v#7-$F9(VWq8nDSIucVoc1F)-mG2W>05*P zrmCr+yKa8ikK{zUEWgYFCz*wo3$M{uXF&wjtrOAqk`WH(JaF#2|d01*jg}6_W zIv;G`xLabFV8K<43jiIS zCbOcQzT1YA%;e4zvLsTBF?)t5aTcf0Wd&ztYK1?94D4zg&gJM`>`^AV9sr|Zt4dwn zW50kS^(gb5nkO0Y^WA$6i%36 zdUb`17WKRYw{SB4?A^&Elbne{o)ie9d={d8H$1z}n=I_xIk_H|m`N_pQQ*Wdr5HfN zndTi{!HM)Rr#%p<#Qhpmny=>Q1-%&(=ZqOvrIwkIaZ2O#4ogY|=cKoVb}2?Lp%p zBfIoGIl;+nf68GtiQUGD&FpOtGl-=|c_*haySFsVQTnUGNr1*&D1BDddiA7MZ)B)122knrQ;8Q|vCm4{>T;T$HrMnWcxi<8Te`;<!xgU7u4BTNPc~&>Zg`R^yFn`ZhLh0|yrPtAp5NXN1kui+F97*~ZJf zjm7`PZIo4&l=zLBLbILMcspH0DOqokqn{JOa#_R2)5|u3Wecz~ivVRu59^uTq%y)Nwaa}+_V+oZE^}|zkf2_|gHt(; zN%u9SSM|~9ff*KeRD>}x9N~Ha%em0WNz>LJaoP(q=cQ-bT*P$Bg$n|B^&Zw{@C)g< zeaqN-v46^`mh_gYu@3(ad-nkzMfETK|7@70C)?;KBm_cD2&n`@NhKi-Qs{^w1PBCz zN$8*%ItYj~=|V#9O^OW^1yKY65kx6U6Qp-R@c%x$*(D@2!Ta3b^MCHW&rAKn?B|^G zIp@sI&YYRC#ATgmWQchcMHpY{@;PHX@Q8tH?cYCTep**P2{QD&!h%+9R>m+%eX;<=&44ZHF^z???!g5R;{OGLNJsBk5 zLB!L8mFsD@|~4@Amiox&U&GE=Ic{5uV74j@v?Q4N3&0eS4hUocMS4Eb+kQW zE|lF4Cl6v0npsae*cX;TgI;3hn12O5p_avDzAp5x0JirurDX0zwmUjMYrtbVnf*7N9SF@XkSsr3;x%& zwLX^5a-}znbv@Sontdf1vE{#xXsMw!E|*eSKba>dw(w3e{0r}m^CiFDP#(J5_YW+oH`3+#L zn(M1%(R?1KvmFTCV(Bi|~;}#JofiajZuTiiwoxzC&2r$JPCi_^=p`gCBie+xyAj zFZ|7K8*90{Fm9KLwGAfx(4dvaH`WDx_JK0W3-1K- z){E1+JY_W|fnWL72d);}ZHLJ4FEg`R@YvfZE}*klwRUxwjP=HgcD3vc%TYO_DEHPS z)^J#-gxsgtel8R^Ubl~sW##*=^YrBADa)D)>%l1ptR#&!{_=EB!E&NyInDn~o6N`9 zvi6qack?OIPVwAu!|Ba<>*5^ymNM=O?|k!gYl6J?&H^MJvfYZ+D3AX%vyYcyUw9PT zCIpWcls{tSs&^TfA2GHaQEM47-&u%fC)%8Vgy@K9p5jTXnqi)RX}8dZBLi-N+~lxuKUq~G5b^*E#IZcJmVwJNni80XvI=3c^M%f*7keT zKJD2R${!+_-`5;2%7b0*uZvIMU^kdw-PS%#m(lW_VSGk~IPu203Av8%2`7*3`^sQX z9}woM+4}CW8re=nTkAF81?puB6&4=M8be$AtmD)+j|R(NPd@P>fAZ!}Su86wxNC+> zmYo84H9_0Ba9gCeWu&KnOXZKmc>?RVN)*dFtc_D;l&8<@$Ma-4Kn;&(RE7t4iU|$n z-iDY^t_yRki#6Z~8Sv@5o&41bh>wwL7i?d2aUm@`1=-g5*^idd@?DvD#+cwFynCBR zi>__C8Yja%{m}La=TOaK-m?B!-V{g;;{rHG_~?o8_7h~xr=J{pTFg8*L**V9nHN7= z(>F;*efm$Qr$x0?(fSpcn^cZ$Sc4w_X!W%Hl$WcsIlA@tX~9F0>90`dJU>TdUE7*3 z&+=pH(Kw&^FY0WYhUWW>N52ifP920wYapb~|^?HwaPhgJ9VnWO756n+Fj|=0`;CYq=*sqgC#6I2Rm?{V{f|@W4~F(f1zE^6H{cq7#0{C z9?Tb3kX$arw<>A0cEHCn`eR?nmP>|?tn*Cin!@53*GDgY$i3u~d-;&lpLrLS+kYlQ zJvP#w5z4aGCSRn-Zc($}F5_7qgPVJH`x)`_M|$*Ho&rl#Y=duyEa0)@q zEq6GCN6FR3d2Zvf-y@?o_?J;FeVBKdlKnmzr}6XSSg$+shL291041O;(PiBTQN7gFAl_M40z`?Ark zC&=WrPwVtBH^)}{(=vYRSB?MZHqyK|uiFYaCkuJ$8E$O^W0X_qmWADq?n<)1AcF_L zYzy+Pg|zPEFTGMkYo7D=;#C>Z=U>*5iwC^j!qE-SPr`WOL4bU7NrB7p=C_sQjuHn4 z8OiVYk%(ejo^M|EW_iShHH<-qY5t;N+Hh|bcV$?her;M^7GB25|b>)g#$A(^Nn7fBp{E47+~h(LT-DOKaumi?6Kfo{SMAD zXx(Q7wM~gUVXgUbksq!X6Bm%X7@qnBKK`~hOIzd?mLt^18dOt$-1C_qw|$TU8u^G1 z`ASOL%bgtR$N>KG+4Lz%jsd+BQwL_Gm=~E?|I_lI+#y5cJhA+q%w3vlKJmtVQP!5! zm62jzAkq_~m~W1gFU!mgYd$KqT{?I0kii?hQgCZMy=AC?f}zY0w<8JR85!nx4q2*c zZKY-X0mDN+11BUp$hHHnFT*wY*WrT0Tk)0ADX?uPQfNI(=+ICG3;fr?qC%o#c>EAg zpW}ChTuNkZYhxKN=tbkjhX=E+AfXu}UVdX**D=V`tk!@5GGP4|4frT|G0}4UhBZpC zj1u;uQ68_BJld2Gm6O>E2@T~2IBV2qGHOJ@sFn_8Vp+~Xa097r#ha~yF>&k>iPcHo z562tD%sgQk%SE&v5a&J@k<$see_~q-;?P2d zkNr==Tb7h@)FE%dwN^h)#t(hD_~vgOjxr+2cAgdK4y|NNzn6>IEXa09(N=~DdFe2n zINNG|?oOT=-a&?pez}mW0t@69hIMe|U$f@WNycveaN-}YKDuSVAz6ludPY_AT*G*L%E}8X^6-V<4)XCZR5;&0w7U%bguT0M z=H>})o3ip$T|lT@o|xytjYCfv>Ir*LTc|we8?C1@Z6VELGa#N@p{(cU9D2)mPuPRL zc)Z{cdDh()@GTke315>h9?)|7-nx7w?^-2?Od0%Hd#dNQ-h8s<(cOp+{bj@_?5bb9 zy15sV^Ij8h7$l=UYnDE@p7IPZUs2(<5kK^mEBd5)lqI7+YtY9fC-qHF$sAZ(sw!^;(d)^C8ZvJ{@cp8v4XHY}cB`Mjm@BeX?po>^yG1MM(g7SQ59D3@On#p0dj2roko_s=F^Y;f=0OkGW z!JL+mi?g}RBp=AYSCTaw^JL^!FA>>xjQc1$%V~2TRTON#`^8$u0$E1Wxc(_!GxMH4 zDDZR#%TMSKeo@DA0o42qFY}|j9i%p(umxao0oy*xyQ|6ll-*T z^GY^X*?j#@9=beU_pLHQo##c6=Lhp$?{WB4e)75Lmv^36e)O~4n^ScKYp_km@q1nk zIN-`X+?GcT0rL5Zk3BrW;Y%5&$@9Wk&erDMDJbhAyR^Xd3x}^|u!jFSSiwNwyik$~ z)GGh|)~vLXhJ?I-?T`T2rL&j0z`Yij1l&T{P$ZZ#gitHt5RCs+RQCnZ`MV7;!9_lbuNhvnx33Y41ACn=4W`*d>*P3E

h1^yI%IBWMu~Z<8U2wAy>w^Itj>>RRFCH#|!=5NPRzkVJF7GHKGeO}Tx^oGX z1x|Tx+jcl6L$`W`(B>T#%faNbDITd7C(o{Mw_!j+r0pp2q%0%h70R%!BaxTCSoUDK zgDZ-IFzZg~lq{m%s}zxY$1!)G$zM$JOc>Yj!sB8h&4pRZIV;PFe}!^#f040hnRU0a zi-IC!;_^HV&f)y4Cd;;Lg9TSSZ?O$mh2@XR0NXPb94@|UBP?BQ`C_p)NUoi+&AKbH zgx0T+CeDM&I~usJ*1TBPeAhwl?UA-ZuFFDVU!@Rp@3H_Tcf97?b=;EiUuD)cvs@LH zlh6E=u^`(a_?{09*F5@@&5O$zb^|h3XU;D6l}4o*L*mxA5wU$atj^c;%66u;sq$ zAwz;=;-f>Xdox{exy9>`Z;`wIri!h?Lt0x$sLoz)TJiBsqvHAc&i4c(onCHO`tc2I zUrD3I7@bjPqR=);{0#8qo!jz30M-jK@+s`{VP`qIQo7P&{PQ;BS(d@A;`4v_ps*JX zLZ>UMD<|sApPyCR`Ue$tuRZ<;m32;{&H|mIs?=DZtD-8k*w*fl(AoVYez!ZKtDYsY z&Z$bxPWt`>TnEVdx^_v)NX*Dc?$tSUV1v4KGk6Jf&rV&_c^6cZRLcw5<<0eJyx_fS zqk8ULJ0~Xkc(}WmHw%?pg(YTmZ{*?S>)}z)+uOIkpSQcGpI3cP-#nYhk9vA~czO7B zb$7Scyq3;e)LE{pt*fJR)w${F>fCkpbRIfSotLWAR+T!c;;Jfcs!~@~+*PHXs(7f1 zr>b}@*ZBw+QB_pcH7K-D6UM(A3l~-K&eCPsXW6TYud4CS8Y2HIh(D^$<6`5|`lj=8 zINBQ0C54y5yJheaBA(Qc)|+SS7W~WZY5k*k!(Xq&K0HV7iGM9a1*P@lwcFj2c{1t~ zw+ZjvFC`;|7b|2uDN1VMz%*WqH6W8WFj5b;aV{8zmzJic%3pHHZfRY+W+Z1mDH3n_ zvu(u-i>c3(n-tJDvwK=P1r_{jISS;vwK?*6Qnvc1C-&iWNAm4hatKCh#w^f9sfth5 z2+JR|(2SuUEdNj9E&o5l+Rd$X?L?VuT^n6nRjIEke%ZSAx(=$+Kvf!Lc~KlMgvv~` z^h@O9N#SXVyhCeXw{%`#*d;bOqiML3VMXfeK4Zi9w1L4X8S;aVUfsr%ItzRvgV#59PE2>}pVB3> z`vKhmQa-Ry%?{CVZhiZvbm=@WGdUwhuTQ@0q(3)3{QSC*calpDm|95HXb$LxuE6>#DqLMRxiFJ3R8_)M%~@6RtExG!D$P|TQq}yfD$%Ou>r}x;eVJx_PS7LRDf_g~8EYRXVClXI1H@Dm_&tRaJUDzU#`d?7Et9lgxpAk{c!V9l+}$d5v=3 zUE)$p-0%W%>jioR`i6Rhx&{Z=_jdL2a`$$v9~9{2>J{uA=ob>;;}Z~2{~2*tS>i?% zh#TbT=jj#V<>wme?&s<173l5h8sHsJ-?hG1U~q_!dw`#phxaq$uD8UE;^*7rd8ilQ z?H(NJ5$IaqJ;cY=%g4K(YyEoOUakT4>bbjn_=R|dxO?Vp_-0F>m;x2_^Q-3@;uYlX z>fs$spa9*o_yX}LhNA#0-C0hf<6 z?{9far*$UgekEpD$J7_P9kx&DzEYLAtlE}+%PzUI`9@XZvqs48urGAq*=^VD(S0v| z7v8$1y8WG)2?P4D3Y!;`_LeU^?UUJ7zHfJcd|JM$w8;`hRV7?i5)Nw5>kblOo$g2N zpPlqNR#I3u3uZN}s~x?el;0_eV( z@_jk-Q#t(6F)_YXbe#NOmW@v6PIl6l;X-U=n(b|Xj}8HT)BP?F0iN>r&;IT|tvf4| zbVgO${fpH8skzsXMfJsP13+IwRg!Yc(>qX}UZ*Nuo=~1{mA;I% zk0Vqi`B8c0WO-d}NsUtrZHC6$(<7v?o-k zaAQ5YSaXFmzo|-}M+u0O33$tvfEW@`Sdd0r!ejOAM4cu2IDNc6LEp-5n!Zh;cvZ9rbVMJL%ulGf#%9$}CmcswzLJ%1u?PSGA8HVd}eD z_9`5#wCu`*EZINTl?Tolbvq~bPEG8ep3Ixc>qaG~rbV}@n~|Pm{m%ZMHD#_!IjvHX`)AaZZ$0HDtr?l-|C0Y9|GZ#% zeJte-;L6`imd8T=+5qk*4J~iFR9A7tRd!qWR1`pth=}s`qdm!>R0Ml zsmgd&nUJktqhG5k9E(qthtkhIq<`j50&5{3>9=y^uHU5Jtly$4@2ScpRe3*0|FQlP zdE`D>Ri^y!AGzzl6gvHmf=A;yn;+Cz*EcA3&8+FIJBBzb^2lAklWlhu+_rnS_gj?+ z3oo@f-EXD;kKbQ-bmXr8R{y=s^LK^#xjcrd%V>(A)V>d)!_P?g!L zGDlVBstQN+AF2vNW`U|?t4fZlEL^U?kUNPl>#yjqGKsItNxaB9iI=I$N2;<({$k(! zf3x_%pT!2jEH-FVWpVB-HYm(ugVs=3Qk5mDvefd=tPuvg%KA5QJKSJz&@)C14h9Y! zmaEE&Y=gnTLDWiBS@WO$bT^bWRFDJF%TV6@(|r{K(eRoah^q?>L__OutyOa}RAUEV zsA6z7R86J2&Le{IdR zigE{F@L*fdg4-6>^%z{KR%Fi7sxvR|d)>*IZJnDMEpypmSJIk}`i6$)*=*pqJwM~O zJR^zLj|3PZnazekLy#fZ5Ml^5G&6)5!VS$097%tyD*S-^R8>AxmCsdWo2qPAl`mA~ zOI6vi+z@4%&4!ki({F|ZIh((-&gO4yr{8}3zsdYRFqxC&WbUFWUt1@0H#wQR8&V`y z*{LeKEdS(7Ib2`N+TDE&8FDVaWk^?*-Kz3!wjtBNq5gNOviHB6%YzI&W!To5f|-Un zmiar|Jbw>8BXQP`WE)n=`I}={Xjo)eY*=DgYFK7iZdhSp_k37Yj;PAds&Z6Seo>WQ zRppqf99NYSs&aCn|1!4R+X!&a!r04U;n=e{68>(zmgO9 zYgPH(I)T42A5$x%^$QJqIGk2Bz2rZYQ%vCM*53Ys<7=kxego5iU*>1C4L=$VsmeK3 zx$xgj-=l_Omg&pcTdk`6AxGf}IepI;oWAx$tyMd1_(M+LGlsJUs>5lAi>h)d$8g?o zK~CSxs&eK3f$4jVDS5r%l$gQ< z8H*cB7)u)MjSi}EOI2>G${kg?t16szyQeDmRpoD0d7vr}mmBq#nQSa&ENyo~R5g~9 zGx?v~nXJ{QTKlZKOk}OY|4rooej*!Pn8?QJs#fGqWMeHRa-pJjH>9jPq+YUK2s73* zdNDGL9!5`9Yo}@pWgESXKB`txwZ;FlAI8Rp#wJWgqrb6{v9YSvs@lS;wn$DPCu4w7 zUd&RpMOAGvS=@83JN*w{^EzM*6FOsf!3j2WjA>~<`=B8oe>>=pHmQZH%gJbrWZS5M z+up0YF#h8;kza26rNr*0#rn}U>vyTKg)z>&7c<7ny_mK{wlTg?eN|gh)f6eP8#7;I zFt*ib35Q`y)_PGzm`S%Ivd>1upS&gE{#?#2{j4`WYbsS#w#t9@m28}AoG%NR$5|e&6XQ8sS&7dco<*^RI#m41w7qG;*)VNI5 zI;+~MsM8a1JinA!D(&UQD)@1#*y})F4`vq_{8|RW#)cnp1C#o5?0o8AVc2rpBuAg?JMIC zqRtBA*T$X3UB+*WyN%x(zccPJesA1s+^1@5tJ*rM)>YNIsoJ`#)?L-sQ?(wdmR&g= z*XDzwmeSe~dh9+mUg$2x!OGk;ZWkojD-Hv0d6Q@92fJS~ejc$Y>$uAj(j z0|C~n?UuhWuVnduVF`=zyqxV9RIRUdwqKIp+@BWuOj0#&s-~{xpO0qyP2(Lo5pNl9 zt6D!*+aTL`*Z7yJZK!JhyJalKhbE02w_YY;{_66V-#7=&UtQi$8@Q$-rV>ndQ&Cef z6JJt%={HfeO>;~o3ptq_RBeFyOFvNVkpAa+Yj{1H?xxpF&Z5p@)9a>6rphKq zlar~6sts1PA*wc1)izVLVX8KKaiQCys>wxsr_q{fs+wSVSlm1-CM!YJM#?n`M)TUe z+`*gS)-Elr7fYoc|HC*gt;maPfpS3-E2%2jHqTvG7L?e#Ut)$F`YbDa{Ie}mdh?)= z+z+rMBL7EYSWTAB${)g3&i{8j3nVk8w|NnvjGep7GI^N187)d-6S<(F5!p&HrMSv< z8BKVWR|i)0u^fWc?1{ZIt)FOUY9z`mFtI0!TA-9tHIYx*F3=QW-hY~c&HK-o7a4~U zrYIRZQq{IxV2W0?u~}Xn*(pSGbu}(Couy@OSg!DzpDoe3Z@2w)bDXMW*(OUXObMn| ztfGkSo0^(!N)Y4C$7QBAOjBXVva`)XQwP%~$+1k{u zrXF%ybTf4~rKsArs`;FpR_?_Vn!xcwY%`iJiQY*(DFg^=UkrjxyQGc1z0PbVd^L9WScTI zRJUVRX11xnX@IJIL)E^SRXbnm4wzWzWg2RFTP{<{OzD;E9I$iy#ziTkI;z@EmV9QJ zRLiQAU7#s@fz~+ofR1LMJYY zOQuP3J!}nk{;z&LFLzh|9pdBZ<5kbgBhcNwUQnl$KJr;OX&Ido(|h@N1cNRagpx9dL1}xIE{-LcYmK1(yNg>Ie#KBZ2%O7T2{%}g{w2d6v+w!`|v__O! zW?F1oVp?iiW?F7qVOnWgWm>Ijd#c)0Rm(W+t!mR$Ex!%kQnl%-He;D^F|CtK8%-aX zHkmdHmn@yC%{2c*)%I1j{Zws#RXczq2(NZ286l}D-Q*fmmPBVJrguxu3^q59MrHCy zBKBZq^8RsnM(dPxmSSbFlhIrLA}%IGg`I`NKfjXlF71J?u%(_ z`!K7b^Oj&<5g=E`7ATqdm6V>GncT*jWckRNR`GJFho#Q09zH%nq3*0+3k~uMa`me3 z9_Z@l6X4IZoxn8#BGYm9pJ-8|Y^`mvsG9Z$<%W4Fd@ewJ-Nu*bAt z)LCfy-n7@W&-8<;9jt1HsM?{b_U(nH1EzzfA5Di;?K`SAOVz5Xc9 zFvlkMNlVX+Psx-yE?3|$au+>3>91n?$OXn^+P%Q1_3hP*)rgiIWL$DL zxlA=9!ThY7HuZdhSW4}YsJ~!o*9nbRj_IW7H`DK`cDSk?t7^wTYUUXe*Jg7}XHDl! zf2i6Ks&=HR9hGCcVEWT^K-G>`wPR?dY@FOHJ>Iy-3U86l3(9DBCw=W_Zy3lb@wntZ ziRp=~eB~9K&)(WnMytfszRAu_Ex)owOGoPrziGPrgvuAXZMtW=&sVjo9j9vF&8nRw z9IM$0NAn^*(?7bOV+=}(&V5o@u;cFjqsFd~qAgscc$=zxk;;WAZL22A5zGIIubP?G zr%lx~^XvICj6ySNzIg#4JKy9k=3&i7`->KfPfttB%+jpUmoHJ$RO+?YYu0ja(9qwx zQ9yX}h{&k8)@?d;N~qeKuc(9e4m!QT*e05Lz2!GstEx$`=ajeyUX2 z(W#1qbJc1t)obu)alC<@vbvh@gryL^aLfxG)6$8;>igDmp|Je+~g1y|RjB70)V>GDEVQ@%)qye&jhilLlI4(9N|qfMQZYLym>r@%JG5DrAOPBT$6Ni$h9RWm~~OEX6^PcvV$N%OPjrsglrea!>S zKX!%firJO0v$xaR8SP5hm9g`(i?(ZF7i-truCrZFy8(8C?MB#*wVPo#$8MqBCc97U z_S)^YJ8gH~?yB7lySs(#3+XN6+D?^ zlLP0u8?h>wjjBI8lH4dRbD;c!dCr#c9O{|3bZ%PI(rokbN2#)wLE8g0=Y z85oB3_#U@~urCMx-o7vTVH&0*2b-`3AA|bZQ(t@PYyTy_!cKgHUvLa3@EcCy49?*^ z{=_9*5yHU^rBM_9Xn~HPZVsa`6$?O~9H^(mMoft~=9H@r_^>Cp64*Rel2XP38 z@iVB81NCvZCWNjKC`;E2Jun7KK(1M_E?848bf<9^f8YWx;tu}8eLTQFLg+Oho}NC@ zMuEK2lRtsId?RrD$Vm>RGxNN`O8sy&Km- zo6A(eXwVmBXkVF`n1gwkk553nGQ=uFUzee;%Q5E4y@4boqZ?>jx!&l5bW8+s$}I!^ zTW&q*-*WVCIqF)Dx|aI_w71;XI1TDkUW?b^2J%@x2+?SPSj3|hD7!p)E&moWKwis} z*Ya5yhw+#K>QH_)KEmhNg%hB>@_!3ap%f^uLSs-?g)T?|{Z)Z@6^K`17)F3GTVV{| z2eB(m139Ze&MM3XZLC1vD-gfJJs~QR_liY9?kke}iZ1Yk4`^G(hG>K)Xb0L&kDUGpJwXuAuFeGeEm5Q_so+!FZ}X6z^aW$ZzGtpq-8;yaw9pSQ$0o z3)<~SIgZ44q}`6R+mXI>B%b3a&|XLK=}0~u=~Kr^n2Zmx06Cy6$0eYz9an%c>ByXQ zJST*c29)bm8QiZx#q3%_tf;v{&4)!ZmsAm=W z%ef57p#rG0b0s*U3K(I8%l*WjIgA8f?K~{EGWR zR4t0)Caz`F0{wR8M$ASL1IXYHCp&CE)-)D7R)+xPYA2tOeRu(-Y*k zrY{&THJgEQYj#5)kjI*%Fahu3eNc~@voHtqFdx|FeCW_*Q1U|iKCr!{}UF;M54 z)VU`8UGofX<1WZgOoL|)TK6csZHP2zJQCM-)hruwQqnr)uHd|kheP2qfQ_? zqYK_bKMcSiFxKj*V64>{3G!5D6*hr-)Y%5=U*~J=0)6I6J6(zG+5q&mYbuE6Ivq1W z3|DgPO0HcOU?CP`DZaoC5YLr(uDkIazQ;d8xD|y7rBN1)X}5|XcW#wY2X1hO2ZGTO zaY#UGbVMgmFSp)cT)3r!cDvC|H`?ho8uWo1b#|l9Zq(V0I=j&qZj1>x+U-VN-KeV@ zb*)LVJIRhPWhC9ieq>$?q6VkRrdjCt2;5=iQ!It z-HGEq0OZJ>^4;lw_dVDP`rn=Ycc=f|e*!VxkK$Jx#|_-V9Z-flWw=vDJ;r4{JJ4VC zil7)ufWE8O3_URc>u?x+&Z7eS&jSe0c4|G0+Zg4GMv>y=jX#ZSkfp-n7M=ws^b39W>b68@?dd-VG6qIFNVm zw&(!z?@j)_lhGYL&>!UAdkEeJx%OU!rC5Pg_z0Wv6?S1a$h$Y=$eX%)pTKW8g{!!Z zo47565B2xag7M-*8+^)u9QstiYp97ja06}enF{jZlLPAELp^+Hw{Lmy_rA2%mpuE@ zPG5gCK_Egv-hCs$Jn$v|zO>P|CwhTC_k9bQpv}It*_Sr^(q>;3!!Z)s_yT8ys85~i z*9Nibvu%C$t@XFzI2hZ03fRW4IH;pvX;gv}s-ik-f%f^)K0oU3*9g?tkNWyiU%x1{ z0Da|`fOJd)_3&E)#)Th!;I|$dK|lCy#W$c2{EmS9`~42;?Dq$*fIjfMg}Y!3H*f~= z8}!3F7>^G@ISp1|3y9ZXFAn20u7Q4Ra0fER10fh%q9J|SP!AJIgZ^w-5wF7$Rp5(O z$N=qWxB>e>eH&8Gh8J)NS3x}+QqP9uv>|2qlUIKO%7QWC&lvG1hyHcp0dElBKN$42 ze|vO5M|46e=xcxa+P^>OJAeAwpMLhIpZzD}1JGvwPw*MGV+WXj{)}(`J)pk+1qY?RNR0fRIM&zSW4b+A!sC%O*v;*~QL_HfNqC5J6 zdNvw}!5D*appP0&#B9t3{ncmzR%0E=X`_#XXiTmeGwvFb`^MzHaW&A^#%$C0a~#A^ z_!+4(O&uQBawO#2#NnkLNCCM7_-n&@CeX_N(RYeJtip}Z!P*Q621 zeUmIOmYR^iCKrWhN=BCl;3HqWbZEQLS^heW?plwax$5hZCO=n>a=3zcoVLfPL zQ~IhY{nT_j=%=P%gSrQ3LHz=#R{-@2s0?xtz?ccB1L_dq0WXmEfcLN#TR~j|$VtGj zID_j#1QIW>C}?kB1-uU08CVT9Pz%HjY>38)Knuiy@gCS7loR+SI^!*j#bivw4A9QN z9DI&1@D(UOkoE*JF9I*&DsF&r7WfzL3lUTb^g$5y3Zkt+l|bEsXm3z$G(aOXMG!&} zj!49yCEh?Hl8}sa^u+)S!e}t|g2sdX37U<$VC)4gz-o}cp!L`Y>L0WNUt<@31Y<4e z2#(?$Xj9NdTn6n3HiG;HmqSI+j$kKLMRkzlU{|=q6U`9?+7L_|g2{C-xejiN4xmlJ zO}>7n3jrjDb+bdgx+oz{mIu+pz=R;(PpngE)kT zLNp^6&1ieGcA$OD=&NQ!F$%<)1Y4A%(3uWxC>dY2SPM24(iri2Lmd>5mmsLY);=c_k=g7 zWAk8yA`Fbp=B>e4Y~CIn(F47ZhPOaFnyVOr(HMvEn2%+k9nIHaBgk)a+S2@6(2nMN z!B}X17)Qars`&}frsjWwK8w(R{6-W8HQ1oeoZ9udbte@D>Y5#%+3{*JhaD_|@|kmCq)96^pF9tsgz z5#%+}3FI`gI%=X0+(6wTz2FP#7}*F-5eV`f*$G217Rx|RA{on(lo3T+qlgv7_EGIX zTcSP$xs2Kd>K#SBqkabYi#h>58^t_``UB)K>N2k3h7i#Lc2H0RF4N4 zmnFt=i8S4?A2w;0+I!@P>24KdR(1G7M!80r;s9@Hg9e(tIe zEvmr-U5ju;qBUr5i;j2`N$861n2bGKVkrj3ZcF~IWgldq9|nSawq$I! zq`zCTeamT}PAz968_cnm^nc40ScScye`AfHKV#|7So$;889rzN+89e4W64=;3$#QW zdSMWTA`8PY3S&UIu^(V2=HM5Q!&t^pEd3jM9}k6yW1Pp)Cvo&iTq%@A1-uSNP>(nl z)Bx>`8;7kRRy=i%r*82vpfBUeT|Bvq?}S8j0lAAGi6x-T@ms*><3GlyID+4B8s|WN z#orSmfjT8nrv&C-f<5%0oP;(=2IDay4e96$@}BSxREz+5NSJ`BpuB`bI1b86psa+m zxM8_e)~XQyE)4p$RY~YT+geqI6RN@meLbP`SW465)e9-`n!1!w)gitX4+D9S=u}A=IZQmYmAQ4^A4L#5cl--`O*PgN0 zejvy}dvefz7|411F<>0FpNRKCF4|Mq_Omb-^O1waSca8YgZ20bTkr`!#~1htyYMZ( z#}7D&pYSt&#R>e5GhmFg{}Y#S4L5NI^l$qImP?c!$X5q)-+|nBAa5PWSqF08p)|-{ zhl;2K`k@2;(4jhNfj;Qq4o@&oI{3jKO~9D!5P~p7AR5e>4)j-t)@X;0coRwJiWHpRZIE(YRh%2~`Teyq+c*v!64HOhX zao9r-6Uv}GUPEP6K{eDsZMdNxyx@xlXoRK+LMXx!i5SEp0d3G8Zy*s}&<#D%3w@A* zei(=$cn8BU5@YZ#CgOce#Rr&$xtNa}EXFdd#2T!}N7#Z-@HxJ~SJ;Jb@jZUPLHvZD z@heW?cbvf=_!F0L4L5NI_wYc7P6CBc7{yQ$Iv7zJVCSVe#U^-@E4n9OS7GWt? zU^UiZBR1n>e1`4Vft}cmJ=li>ID{kk1;_ClPU9Rd;1aIl25#do{EdHvc+(DA6h#R* zz<^RHiwbxhj&OzxYN8J6!UNu@kA`TB00g5Mnj;D=5QkQ1iw>Yu-|UQJbVpD0##_il ze+i z0Y1Y{keAMkl_bVU675Oy27R1FeUj+IB>FC?8z?)8&nHa;IZh(CNne1xbRi#I3ZWr_ zK^waCM;3-52P?4}dvFMcg-GTz$tB?c@{;TeKfH+)^u#301no|yt;q*K-*vS^36T4) zk;wpHdh)Fy~VIK^;??AqlDIjaeW^DU0w87@sKz zLBI6Sf_~{ietM9f9^|J7b?8AIdQgWR<3XSH_y8M0zxJSSdYr_0{3%3Fa@CVu^|S|V z=}B99(w3gY=}DZP#Oe7iXh+ZKpnrQ3qbL2_lQ#6ch8sep(od;n!T3(4Evd96mA0f3 zBefsMduldTU=`@+)Z?Hoy~sl^^3aPs^r9WTnj#QAkqJKEi$3nP5R36We!>wUdRIbq zQ1{+#(HYde_gt`T@1;14E1<4vjKj2Ggo3zf??A;S(5^JvmG+kqeaK561#H(R1}!lW zHpQfv-UOGuSqh`H@)~Wzh$e*R@S_m@DX+gHs(`xnr*8eJTmPM)Uj6qA zF`yL4%Ye%0h_2|4C7@md*5ei)3KlSe@iH(P)NkMdFwX|A1b;uM2#O&L^uwSyFdhai z#A2MoRa_ThuqVjt;KmpX>NR*2$lGA@HkkSiq3%N%FGFf01GIAp{V-$)_F%6NL#h8z z>OYkF5A6)b;?Q1L1;)zIEg-LN7e#S22laY80n;!K^YIH#J;CsrD#?av&cnV@~aW$(W6~ps!TQR*wlWjQ$!% zn}^X~!@8jl((x(2#x5a-oA4Scfmp+n!M4LUfbE8VF2sn!(7^!uVgzN6pv@y_=ZIxk zfqO!XECekA5rHU7!5om6k&L&Iv~}d~LX4`2s&GLHsMjdw{HTvWnWMJjIOyY1=Y<$e zzDHC3XzDw<9vZ+O9nlrtF&^~6=np{MN7Kg9v~l!bLX5G40(a04V;X|Cj_D2ZGG-xG zVGXF`7|I;;rx0Vw;aEphK?}4+dt_lO-UYcDOL=3d_t*=#fm=e1D~(Fv^W%aL3C8+3 z72`mC$F0U@Y{gNW!WkjnbpU0*TON%N3UdGMAPmPyEX6ud{=4MrU2^p<^&amE#?pAk z()bjR+wtUfd=6HEGRHGM#-GI>LQG&xO<=rFZ~}Flkbu@0j1d?GJ~!bbP}d36Z^C6< z6=EX&II${R&<;r;uM=m1@+L0A5&VWzLcFI3ZF-N-y~o^nFAkLV9(jCkDyHKre2;xX zOwyn@O2P}|Vp0?I1Z|qs5A(1D%Rmk%QO+dl_&$C9ehJuvT)ZEEAaq3<-opE!uJ1EO z-~Sc|aR`42F`3U#RzUkElhes{L0u=mfj2P}~)xg-zH3@-&6dPq`?>RQhEq{W8@Fp@>0C&@WR*fU>93ms9DJ zsgytU7o5gfA*PYHX~jX_rg?(7GOaPXp$`}n)8=9^7)R5-!G6&GX%B>$UKmB;4nH&m zb)U|7nojPgzYp>@oxDx|9L%%nyM_3G&wOBj39)F8ju?+=_y9Yw2YYb|w{cg98C6gl z+)6 z&NHd=OzJ%IBIv7`cZ8Tlu4mOk9Z-i^)L|BNm^BomFa{g&DTp!aGUVs}5@NOvo!8j)52k`gjiQokM%)(B3(eHHWh1 zP}bb)pl{}SfPR@vzs#jy=FY$ZBD1qD8&3CCSg?0RSb#(MS; zjKpZ{2KC7PQHUJIWzK7;gfO%OZOEYxIn*JCI^>YI9O{w7XBIMt7V?>erO^tVkcdf` ziP<=aUvXTBMbvo_bzVfB7qtd`v#2w&u>#~}(Qmi_#@*r?px%o;K_4tmM<$kH9X5b5 zzW5TZ2(iQowZQmX!uVQ3U6zoSCDdmL^;trFmK*|gS#nZ{r8<-Y^;+5i$)LZNF2j0k z1pT{|{#{D{E~8(U)du~utP6S}4LMi|^1kc{Xv4BoLM$gQ%gN<(#>DcD=!))O3@oRu z%h%ur{>DQgR?y!o0uY4$$igs?^A+TL1vy_y+g5tR7b?bKJeWHx4}|vDUbNK3Ovm)N9QM9K%`s zA;enZtR>D`;;bd-Yl*RzoUh#nVy!(Y#JchzkL#+UFWv_2T=yLqgX?}0VtqBZ!5#el zddBJcu{ea|pzk)2(+xF2e{ARvVr-yJ8$QL?AZHs(qBP3lO)!Qw_QYCj#V101q=f_Y zU<`l682*TSeY6Ox!M2+;V61N<-lldSmz$D7A8y)&EkbNAfl?@g_F#N$roT6{&1SaQ z%r;y2{1)o7h5BqE#+Fp{#%65CmqKi%Pqwn%R_e4h7R1`h*xAaM+`1l&$&Ym?2gdEk z=@^WmAkQC@=a0$rC;Z(f&Zq{;`J^xUgBYLC?oU1w;!^|I?$g&m8J|+$PZ^(|?#2Po zAD=P*K5GDfjKyS3#YvpUpF(`@fre-V`r&i7`}|$($5H$$#J0*{>}+FxZtH;zP^WG5 z!#3Kz?JFU+E3gOc+a3$rzMXn)pN4suk5jma%R+p?`1ryPl>NnEjKC;-1Iqs5pb%dg zQ4z1B4d~l1$^DnhupZ>|%R7Rb|6qs4Xohf1#%#<5<9o+7Fkin4MGRVE4j3z6Ex|n@ zzAgkUTA(f3BL^$Nc>4M}?&E-B&*~vCL*=AQ$P?ud1AkHr0 z>>|!Ll=DqVFiyTnLMnRW3w(<`LhR=6cQf90Gv0Q0Kr*`FGwcL;`j)@{wh|nXj=>lT z`FG^-TXOiF9_3LH#QBam-x24##aM%NLhK=TdrE-*+e1C}FxK`A1Y>B=F`N+Mdk-{3 zBTU9@%mw-1OaAu~V{beT!@52OZEJY4{7b?-$17FVy>&{X+aooL`CaD{+2JL=U85 zJwCx_LLAe9SjX7z7~33Un`3Nqj5;5qykpe)cyX9O+m6496j0`IVjTYplzGC4ig+CZ zK$}hs$Itj3r-eA_i>3$!!;twXp9B1 zPk(_OLYxs`+cPD=c4ye{oQVZv>J05T^C6DmEEr#B8TV)1;10&aS;oUz#=}|KboL{V z(6_BIz9nlrtK_8yq z4cdHx_!o$Of%q3_--St_A1<83Ra_V1&p<>V3Jb6t)c4Q7gt%x2%D5PWNJL{irr`tp z3X*h@co)g-r6M3-mukWTULaqW+Jib?>I-sxiTYn!gs<@n$lay$xPXhG>`RP|OSJLQ z10gOKhduOQTwX4Na;S#tpuEdboaE!!gjK#Z{fLUNHUCqWK&<9snVJ+5UAFkscA+AxsYt-)=^}D76b-PvyR|0{Zt_2qF;!`r}#xS|ba@zjhGx<+bzp8!T5xf;L_c zLvt{0t`qnA8|VpQUZbdaZ;)bA$syGi|SQoozj@8$7`sGhG>ickjGoGpigeKLlPJ>w+7%Hi~)1=)>3?d!ypH@$iXezbn6mm z)2(Yl+_pyrybeb=gK=@YI)cywacG6M=m7feb~p4uFQj1vMuU9Z9)}4aueax7K60=U zYq0^_u>(7?8+$JLKpNb-zR1@3_Mg zKJbG-$lIM}Aa8e~5Q8qD4R=yNJMPeqJAE(|S)l%RCSeMugK>Cg7M5T+R$(pZ=Q|rg zp6`5xUHBH?V;_!y@pOlNzH<_{a2K@Y&V4)-;;shlH|`ox3a`TnRl%6M+Z6Q0-B5%h z647XhcqE}KXv^JH&>wfx(HD$~yMr(qWAQE~f_ZWG3K#=-Z{W5Ne=(;1>V!lP^Dkol zwGN+SI~dD*j~v~jzwiAc#C>vfzY-dO`rRK6`rX{9KpV72 zN6?PH(?CxC&P0C<#9$1?IJ^hi@b@&#!d%QpHfZzTM%pl*LN7XSVm)ayZE6hleq zU_b+;f-&@9I&!cHTR{#V>;v&0oWXT4pdZlI2M>gJXa_BdfVdCKp&}Ry56SmKANYZB z{V)JQ2t^oLgK_#zYIVGBM1{r-^tdr1F1 zBnJ<7;j|F{6hd``qZg)NGk(G?p%FX-NmN87IKdfp;Enodh{gy&5JC}#1hhj(yoqFV zM^E&^IIP0Q*oH6hHNM3j?8APX#3@|G9o)kMpXaBazK6xoxmUX6PIxne+i9Z2Q7-C z1RS6T`A}$sLcb|4s0sQ`sRu9k!Vk1T83^j9P&b9#Deq%CW?(kvVkOq#Q;2mas#(O~U&x%gQG|*o~ z>93;nS5fLyl=#KSO)+v(tS$mUImKvuvGyQdv9~Y?LogN-K^}@t#Y_;d*gVkoVzjx~ zr=V@c=$m5Xsn}5*1MMt!3TJU17jZ>siZi#0({II#p#rnI zKU2IRXmjzmL7BxF7sW3KO$i6Mg1#$}0{W{&Ukm{CFG2s57!T^tGl(=L$Vmy>P+~fA zuoNq>8XK?)Tk#1PuO;paO-bfZNga%!ZY9fsF;$ZMm8^yusD%jpe@)zLh!tfR2k@D& z0@*odX6KwaGiN5*vzC!tMrIUdcUv)|s6>*=Fv93!O4>z)K6EuU`cig*C@izAj4+I( z8--oaw9*V0EitJy+wA&5tF51XYT@^7_kEw||2*%q`{gWT1v2T9N!O=rW;=U0blz|f zMtY9)8|gQ)t5JzQBfAxiW;~}ei8GnPbY^lTS7ZO8>$riNSj-a4Ig(MNzep|7N?t}y z(Q4N425<5iTiA-ZMT6{MC%f2<*+puPvLGZ9jL#4CwFrn4=}(BY+xI9s&1$1>Z+@$zKHD^8s{bx z&}*VUpKlZGAlUbUbQI&!C^FT!@*ZmtwC{^`>*U9&=5-|8ya@vTFX$0si8jAk5U9 zsX233)`j!4F*rYSekRXMp4kM>K@XW3WHXqF*=Mu47I|j3au@ev-!k`S4`KG%Q>u z8<~r_=gWAOO>D>8&Uf=2`}hfW=f4GEp`YR^F5FY9v6N3KpHe=R zJF6pcXBFX{RNh-{`ccIvtMYSY*{X0ljtf);WuF(OYK_Ky7*egv4; literal 29397 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 diff --git a/src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX - Debug.xcscheme b/src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX - Debug.xcscheme new file mode 100644 index 000000000..918fa0943 --- /dev/null +++ b/src/MeloNX/MeloNX.xcodeproj/xcshareddata/xcschemes/MeloNX - Debug.xcscheme @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift b/src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift new file mode 100644 index 000000000..cbec8fba8 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Models/LatestVersionResponse.swift @@ -0,0 +1,37 @@ +// +// LatestVersionResponse.swift +// MeloNX +// +// Created by Bella on 12/03/2025. +// + +struct LatestVersionResponse: Codable { + let version_number: String + let version_number_stripped: String + let changelog: String + let download_link: String + + #if DEBUG + static let example1 = LatestVersionResponse( + version_number: "1.0.0", + version_number_stripped: "100", + changelog: """ + - Rewrite Display Code (SDL isn't used for display anymore) + - Add New Onboarding / Setup + - Better Performance + - Remove "SDL Window" option in settings + - Fix JIT Cache Regions + - Fix how JIT is detected in Settings + - Fix ABYX being swapped on controller. + - Settings are now a config.json file + - Fix Performance Overlay not showing when Virtual Controller is hidden + - Add displaying logs when Loading or in-game + - Fix Launching games from outside of the roms folder + - Add Waiting for JIT popup + - Fix spesific Games + - Added Back Herobrine ("You were supposed to be the hero, Bryan") + """, + download_link: "https://example.com" + ) + #endif +} diff --git a/src/MeloNX/MeloNX/App/Views/Main/Updates/MeloNXUpdateSheet.swift b/src/MeloNX/MeloNX/App/Views/Main/Updates/MeloNXUpdateSheet.swift new file mode 100644 index 000000000..63f50da03 --- /dev/null +++ b/src/MeloNX/MeloNX/App/Views/Main/Updates/MeloNXUpdateSheet.swift @@ -0,0 +1,64 @@ +// +// MeloNXUpdateSheet.swift +// MeloNX +// +// Created by Bella on 12/03/2025. +// + +import SwiftUI + +struct MeloNXUpdateSheet: View { + let updateInfo: LatestVersionResponse + @Binding var isPresented: Bool + + var body: some View { + iOSNav { + VStack { + Text("Version \(updateInfo.version_number) is available. You are currently on Version \(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "Unknown").") + + VStack { + Text("Changelog:") + .frame(maxWidth: .infinity, alignment: .leading) + .font(.headline) + + ScrollView { + Text(updateInfo.changelog) + .padding() + } + .frame(maxHeight: 400) + .background(Color(.secondarySystemBackground)) + .clipShape(RoundedRectangle(cornerRadius: 10)) + } + .padding(.top, 15) + + + Spacer() + Button(action: { + if let url = URL(string: updateInfo.download_link) { + UIApplication.shared.open(url) + } + }) { + Text("Download Now") + .font(.title3) + .bold() + .frame(width: 300, height: 40) + } + .buttonStyle(.borderedProminent) + .frame(alignment: .bottom) + } + .padding(.horizontal) + .navigationTitle("Version \(updateInfo.version_number) Available!") + .toolbar { + Button(action: { + isPresented = false + }) { + Text("Close") + } + } + } + } +} + +#Preview { + MeloNXUpdateSheet(updateInfo: LatestVersionResponse.example1, isPresented: .constant(true)) +} diff --git a/src/MeloNX/MeloNX/App/Views/MeloNXApp.swift b/src/MeloNX/MeloNX/App/Views/MeloNXApp.swift index 4f36da0b4..ceada2aa2 100644 --- a/src/MeloNX/MeloNX/App/Views/MeloNXApp.swift +++ b/src/MeloNX/MeloNX/App/Views/MeloNXApp.swift @@ -8,249 +8,82 @@ import SwiftUI import UIKit import CryptoKit - - +import Alamofire @main struct MeloNXApp: App { - - @State var showed = false @Environment(\.scenePhase) var scenePhase - @State var alert: UIAlertController? = nil - @State var finished = false + + // Variables for the update system :) + @State var showOutOfDateSheet = false + @State var updateInfo: LatestVersionResponse? = nil + @AppStorage("hasbeenfinished") var finishedStorage: Bool = false var body: some Scene { WindowGroup { - ZStack { - if showed || DRM != 1 { - - if finishedStorage { - ContentView() - } else { - SetupView(finished: $finished) - .onChange(of: finished) { newValue in - withAnimation { - withAnimation { - finishedStorage = newValue - } - } - } - } + VStack { + if finishedStorage { + ContentView() } else { - Group { - VStack { - Spacer() - - HStack { - Text("Loading...") - ProgressView() - } - Spacer() - - Text(UIDevice.current.identifierForVendor?.uuidString ?? "") - } - } - .onAppear { - initR() - } - .frame(maxWidth: .infinity, maxHeight: .infinity) - .background(Color.black.opacity(1)) - .foregroundColor(.white) - } - } - } - } - - func initR() { - if DRM == 1 { - DispatchQueue.main.async { [self] in - // drmcheck() - InitializeRyujinx() { bool in - if bool { - print("Ryujinx Files Initialized Successfully") - DispatchQueue.main.async { [self] in + SetupView(finished: $finished) + .onChange(of: finished) { newValue in withAnimation { - showed = true - } - - Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in - InitializeRyujinx() { bool in - if !bool, (scenePhase != .background || scenePhase == .inactive) { - withAnimation { - showed = false - } - if !(alert?.isViewLoaded ?? false) { - alert = showDMCAAlert() - } - } else { - DispatchQueue.main.async { - alert?.dismiss(animated: true) - showed = true - } - } + withAnimation { + finishedStorage = newValue } } - } - - } else { - showDMCAAlert() - } - - } - - } - - } - - } - - - func showAlert() -> UIAlertController? { - // Create the alert controller - if let mainWindow = UIApplication.shared.windows.last { - let alertController = UIAlertController(title: "Enter license", message: "Enter license key:", preferredStyle: .alert) - - // Add a text field to the alert - alertController.addTextField { textField in - textField.placeholder = "Enter key here" - } - - // Add the "OK" action - let okAction = UIAlertAction(title: "OK", style: .default) { _ in - // Get the text entered in the text field - if let textField = alertController.textFields?.first, let enteredText = textField.text { - print("Entered text: \(enteredText)") - UserDefaults.standard.set(enteredText, forKey: "MeloDRMID") - // drmcheck() { bool in - // if bool { - // showed = true - // } else { - // exit(0) - // } - // } } } - alertController.addAction(okAction) - - // Add a "Cancel" action - let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil) - alertController.addAction(cancelAction) - - // Present the alert - mainWindow.rootViewController!.present(alertController, animated: true, completion: nil) - - return alertController - } else { - return nil - } - } - - -} - -func showDMCAAlert() -> UIAlertController? { - if let mainWindow = UIApplication.shared.windows.first { - let alertController = UIAlertController(title: "Unauthorized Copy Notice", message: "This app was illegally leaked. Please report the download on the MeloNX Discord. In the meantime, check out Pomelo! \n -Stossy11", preferredStyle: .alert) - - DispatchQueue.main.async { - mainWindow.rootViewController!.present(alertController, animated: true, completion: nil) - } - - return alertController - } else { - // uhoh - return nil - } -} - -/* -func drmcheck(completion: @escaping (Bool) -> Void) { - if let deviceid = UIDevice.current.identifierForVendor?.uuidString, let base64device = deviceid.data(using: .utf8)?.base64EncodedString() { - if let value = UserDefaults.standard.string(forKey: "MeloDRMID") { - if let url = URL(string: "https://mx.stossy11.com/auth/\(value)/\(base64device)") { - print(url) - // Create a URLSession - let session = URLSession.shared - - // Create a data task - let task = session.dataTask(with: url) { data, response, error in - // Handle errors - if let error = error { - exit(0) - } - - // Check response and data - if let response = response as? HTTPURLResponse, response.statusCode == 200 { - print("Successfully Recieved API Data") - completion(true) - } else if let response = response as? HTTPURLResponse, response.statusCode == 201 { - print("Successfully Created Auth UUID") - completion(true) - } else { - completion(false) + .onAppear { + checkLatestVersion() + } + // this seems like a weird way to show the sheet but, from my history this is the most reliable way for the content to actually show in the sheet, otherwise its blank + .sheet(isPresented: Binding( + get: { showOutOfDateSheet && updateInfo != nil }, + set: { newValue in + if !newValue { + showOutOfDateSheet = false + updateInfo = nil } } - - // Start the task - task.resume() + )) { + if let updateInfo = updateInfo { + MeloNXUpdateSheet(updateInfo: updateInfo, isPresented: $showOutOfDateSheet) + } } - } else { - completion(false) } - } else { - completion(false) } -} -*/ - -func InitializeRyujinx(completion: @escaping (Bool) -> Void) { - let path = "aHR0cHM6Ly9teC5zdG9zc3kxMS5jb20v" - - guard let value = Bundle.main.object(forInfoDictionaryKey: "MeloID") as? String, !value.isEmpty else { - completion(false) - return - } - - - - if (detectRoms(path: path) != value) { - completion(false) - } - - let configuration = URLSessionConfiguration.default - configuration.requestCachePolicy = .reloadIgnoringLocalAndRemoteCacheData - configuration.urlCache = nil - - let session = URLSession(configuration: configuration) - - guard let url = URL(string: addFolders(path)!) else { - completion(false) - return - } - - let task = session.dataTask(with: url) { data, response, error in - if error != nil { - completion(false) - } + // sends a GET request to the MeloNXSite API and compares the version it returns to the current app version + func checkLatestVersion() { + let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "0.0.0" + let strippedAppVersion = appVersion.replacingOccurrences(of: ".", with: "") + #if DEBUG + // no this isnt a public ip address silly viewers (i know damn well someone thought this was my real ip), this is local :PP + let url = "http://192.168.178.116:8000/api/latest_release" + #else + // dont spam this :pray: + let url = "https://melonx.org/api/latest_release" + #endif - guard let httpResponse = response as? HTTPURLResponse else { - completion(false) - return + // actually sends the request + AF.request(url).responseDecodable(of: LatestVersionResponse.self) { response in + switch response.result { + case .success(let latestVersionResponse): + let latestAPIVersionStripped = latestVersionResponse.version_number_stripped + if Int(strippedAppVersion) ?? 0 < Int(latestAPIVersionStripped) ?? 0 { + updateInfo = latestVersionResponse + showOutOfDateSheet = true + } + case .failure(let error): + print("Error checking for new version: \(error)") + } } - - if httpResponse.statusCode == 200 { - completion(true) - } else { - completion(false) - } - return } - task.resume() } func detectRoms(path string: String) -> String { @@ -259,8 +92,6 @@ func detectRoms(path string: String) -> String { return romHash.compactMap { String(format: "%02x", $0) }.joined() } - - func addFolders(_ folderPath: String) -> String? { let fileManager = FileManager.default if let data = Data(base64Encoded: folderPath), @@ -271,7 +102,6 @@ func addFolders(_ folderPath: String) -> String? { } extension String { - func print() { Swift.print(self) }