diff --git a/Manager/META-INF/CERT.RSA b/Manager/META-INF/CERT.RSA new file mode 100644 index 0000000..d34f5a3 Binary files /dev/null and b/Manager/META-INF/CERT.RSA differ diff --git a/Manager/META-INF/MANIFEST.MF b/Manager/META-INF/MANIFEST.MF new file mode 100644 index 0000000..0f749d3 --- /dev/null +++ b/Manager/META-INF/MANIFEST.MF @@ -0,0 +1,1014 @@ +Manifest-Version: 1.0 +Built-By: Signflinger +Created-By: Android Gradle 9.0.0 + +Name: AndroidManifest.xml +SHA-256-Digest: IiLvz2TM7pwLZBKZlNZFGTbYdaMt42gEUexjxqSO2fs= + +Name: META-INF/androidx/annotation/annotation/LICENSE.txt +SHA-256-Digest: gJ+h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA= + +Name: META-INF/androidx/collection/collection-ktx/LICENSE.txt +SHA-256-Digest: gJ+h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA= + +Name: META-INF/androidx/collection/collection/LICENSE.txt +SHA-256-Digest: gJ+h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA= + +Name: META-INF/androidx/lifecycle/lifecycle-common-java8/LICENSE.txt +SHA-256-Digest: gJ+h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA= + +Name: META-INF/androidx/lifecycle/lifecycle-common/LICENSE.txt +SHA-256-Digest: gJ+h7SFFD1mCfR6a7HILvEtodDT6Iig8bLXdgqR6ucA= + +Name: META-INF/com/android/build/gradle/app-metadata.properties +SHA-256-Digest: 7kO0OrtT3GaVrMY9vcWm3KRuSyy4gkAR81Yj3dLt3Ls= + +Name: META-INF/native-image/okhttp/okhttp/native-image.properties +SHA-256-Digest: EotkddP73qmhoP5Es5JhP7GyamL9gWaIPTKxgJN0W2c= + +Name: META-INF/services/coil3.util.FetcherServiceLoaderTarget +SHA-256-Digest: 3YTR7nyfdzBk2UzhVv/iDmVwxbiHIoej2L9ESqmmQC4= + +Name: META-INF/services/io.ktor.serialization.kotlinx.KotlinxSerializa + tionExtensionProvider +SHA-256-Digest: IoyJ4jiDGnCRSsJzUCogfnrCtwP+yxSzPKoltPENM10= + +Name: META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler +SHA-256-Digest: MSm47fbbB95vj/R2leIXfIu6Tu0pYtMIXHGeWsu1ijM= + +Name: META-INF/services/kotlinx.coroutines.internal.MainDispatcherFact + ory +SHA-256-Digest: oep36o+T9Bkla25m8pcT+VDY1ukEQrYI2ICkgAO163I= + +Name: META-INF/version-control-info.textproto +SHA-256-Digest: ONN3r6drY2Tlv1Uc9P/sGogaRhAqAEf1I/vxSODfaSg= + +Name: assets/PublicSuffixDatabase.list +SHA-256-Digest: x1q4J6/X//9ZpRsUcpwl2/w7RSN+tAzPAr7Ht9RDBKQ= + +Name: assets/dexopt/baseline.prof +SHA-256-Digest: BcEdrcpUqDGGgUfYTxuKgRHBd2LT3gHiz3cGcoPZl9A= + +Name: assets/dexopt/baseline.profm +SHA-256-Digest: lbyxhwgS9vy8el7CuosoW/3nEEC2jcGy6jKH9uo85jo= + +Name: classes.dex +SHA-256-Digest: MN2aXvy+/X6oLjkeJi59jZH8qHu0yVBPdrzwBadU+LI= + +Name: classes2.dex +SHA-256-Digest: NH7cGC5TslEeC2SO5aEn/vxrdJgoyxO3wohcRc2hLjg= + +Name: classes3.dex +SHA-256-Digest: VMqFwDOtZszes7M6LhOrr9oIQ2sTSpulq5eDJgwnX/A= + +Name: lib/arm64-v8a/libandroidx.graphics.path.so +SHA-256-Digest: Qemnk8Q6D0/dsZ4z80a6zkZPMPiIunuer5YpTqEVv7Y= + +Name: lib/arm64-v8a/libziprs.so +SHA-256-Digest: cUShKFZX1cutaB63LmpTVQuRl1P1ahODmySO/YwobVA= + +Name: lib/armeabi-v7a/libandroidx.graphics.path.so +SHA-256-Digest: QTmeum/Cpg9vFGQjdcGCTzzyXrj+xzl9dTcwo87aPis= + +Name: lib/armeabi-v7a/libziprs.so +SHA-256-Digest: IDRKRyCLNGVe11x9FU3d5daGEMYizJTLk/d2hbSh9us= + +Name: lib/x86_64/libandroidx.graphics.path.so +SHA-256-Digest: TlbJlvE2cOcAgmWN54gMQCDqv08l5DOH+I7XinE/yfA= + +Name: lib/x86_64/libziprs.so +SHA-256-Digest: 4yrLpNA0LV9Q0bgFvJ94O1Qvm7bj4svDnJY/voInLOs= + +Name: res/-B.png +SHA-256-Digest: Q8zx8KXp6e2abfM+Gz03jUnbyNxg2Dsc25heXkj1JJc= + +Name: res/-N.png +SHA-256-Digest: a0Wu+L9DdnwsHIPe4r2c65AXmU++9mE4kea8IV4qXuM= + +Name: res/0K.xml +SHA-256-Digest: i+S7MXjCCCdZdIQKFZ77J5jiFsv6DAgbsNjItJCmZTg= + +Name: res/0c.9.png +SHA-256-Digest: +U4hKRgMC6aSRDA3RAJFYDXc1rb/99BfbefiQZajrzU= + +Name: res/0k.xml +SHA-256-Digest: UqIjwA1CXY2LB9slierS1XQaES6w+Xh1S5GLmkIFgBE= + +Name: res/0x.9.png +SHA-256-Digest: Y21/JL5obpUV99aDDOk2uqClQWRoIg6U6OJXVHln4iw= + +Name: res/1I.9.png +SHA-256-Digest: 4aK4ZNARSoRxZi+OMP/Lsuuf/UFNNiOWEt74x3kqRQo= + +Name: res/1J.9.png +SHA-256-Digest: TS/kWoFp82gFLJISMKJoup9T6l/tvLCf81EHRzVR5Qw= + +Name: res/1e.9.png +SHA-256-Digest: SZAwc6sjq/wRpV4TM+spBcdD4bOCAGwnwVQ0/XbgIHw= + +Name: res/1e.xml +SHA-256-Digest: fGAgLvv3fLcv0PhsfNJxhpQsdvwzr9LgnJ7hTaTsbLI= + +Name: res/27.xml +SHA-256-Digest: HW14lQHwLJG8g5rkOXeJ+oiyVw1qMlCsSM49e2Zptes= + +Name: res/2D.xml +SHA-256-Digest: UhUuvVySFGRo1pNjjMhoaNf1u9DyC3GYEik7Z70Ux/E= + +Name: res/2P.png +SHA-256-Digest: ZGAhzHfn9L1oq1n7MtMG+BogQhJebNqhYYSgYqgYP3k= + +Name: res/2d.png +SHA-256-Digest: n4Vt0ApPKB0RmOZnmshhH8Z9MB8owHrql1BCRLoWy0Q= + +Name: res/2f.xml +SHA-256-Digest: kCx+m9pbDfYYpBVQ+0Y19ukhXkg5bf5OJqrmzEEu0es= + +Name: res/33.9.png +SHA-256-Digest: x5VOK/vQHlu8nXdN1NdD0/iiZhMSn6yAcbdBurMBirA= + +Name: res/42.9.png +SHA-256-Digest: cn14/sP5A6JxwEdqUOjAZNKLMveCmwFq4KB9pTuDsoE= + +Name: res/49.png +SHA-256-Digest: Ty+MKnsELlWqj0P0zoE0syF+6c2kMsX/jUwz0J2G32g= + +Name: res/4F.xml +SHA-256-Digest: nYto7CBUixllmj5zwaNFNewQnkRP4hV+gSM1Fcihq60= + +Name: res/4O.xml +SHA-256-Digest: VgTiYsbRCSBClsK3zVgbomZM6WolhCLdNTtcAVkBnsQ= + +Name: res/4Q.xml +SHA-256-Digest: pnAieIUsVVFCwF1to44ilHKfu1GJvALARY8lqpJzgM0= + +Name: res/4_.xml +SHA-256-Digest: tADo1/XVyJDuHv0Z/QVc3vkCMZOQqY5Dfv/7S71lvMw= + +Name: res/4k.png +SHA-256-Digest: DmMdv+JXXdFtP9bFlkHfpKu14WLWD1kEnkRZ8K8p+/Y= + +Name: res/4u.xml +SHA-256-Digest: j2U56tMMQdw78w4Zti9y0Gxn5ta0pOD1SUTiMZW9O+w= + +Name: res/5D.9.png +SHA-256-Digest: mR9zvmAK2IIaZ0PbVK9RP5sEcFjpUGbiL83R1yAyvFg= + +Name: res/5T.xml +SHA-256-Digest: 1jDoYRbPX1rmg473c2I4xJFocD2PNkmcFKtQXi1pQm8= + +Name: res/5U.png +SHA-256-Digest: pHVZSufHcQkqOicYmB4nEMc3hE9EpEAfctOVN1Nkmno= + +Name: res/5Z.xml +SHA-256-Digest: UQCHJvBgN0V3qpOI5f9nRClpFyl6dWtMisFvP75W1oc= + +Name: res/62.9.png +SHA-256-Digest: dlby8ZqEzvwr+fr8AHYCFnddMz/AsI64X/HgAGtG/CA= + +Name: res/6Q.xml +SHA-256-Digest: cu2/FVXpQhjl6mRrDl+szr/Penu4HeATtW0b8kV/cuo= + +Name: res/6S.xml +SHA-256-Digest: 7MBvD81TGXXH1IQTOxQR0trLt3b0+szgYUeEggXsjDU= + +Name: res/6t.png +SHA-256-Digest: XsoCgL04poh7bkF2XPXaVzEzh0YlAB65AVbq6zX74Ig= + +Name: res/7C.9.png +SHA-256-Digest: JVLNG83ZiC1sJYgz+3C8CBoxoqCT75wlb5JDE3Cm5d4= + +Name: res/7H.xml +SHA-256-Digest: 2//I7SpXqIy99zwELuybayUlC3x9UOhTf1ruLA5Z6Hw= + +Name: res/7I.9.png +SHA-256-Digest: sLLcLK54EcEkrlKNcUMYuxBDtZ2CpkDyLEes5kwoP+w= + +Name: res/7N.xml +SHA-256-Digest: SfTuAzo2i+YoZQGneGuxeDIBAJh/lZvDPJjn2h/IYfE= + +Name: res/7_.9.png +SHA-256-Digest: EAzGrjhw3XaaJS5EYIqBlWUi6GdnT4VGGbp8aNMUytc= + +Name: res/7i.png +SHA-256-Digest: UICwfrSGugXt5ze1Z+sruJ17eaPttcLKgUHG66ASt10= + +Name: res/7o.9.png +SHA-256-Digest: AH2/X6LcRmpJQLCmpz2rSMtyH2TTWPcf81qq25Ywtew= + +Name: res/80.xml +SHA-256-Digest: wtRYWzguzopUUUniZ38EHxEx5nOdx1RQiKoDByNpPq0= + +Name: res/8G.xml +SHA-256-Digest: d0bzL+Yf2X+eUGzWVd08/YHlMQDJUoGyEfWDNpJ3LhQ= + +Name: res/8O.der +SHA-256-Digest: jSXNlyKdv3A1a9pOs8xzQDHiTPAPr8/TLcdutYQcfqg= + +Name: res/8Q.xml +SHA-256-Digest: 9e6X9W83R45DZEIChFcaMxAEhXbwfv9peFZLFceY4+8= + +Name: res/8c.png +SHA-256-Digest: TfYA6Bjr9JR1wEHaDJeIZ7YvoeRGwqzUvwm431BTI24= + +Name: res/8h.png +SHA-256-Digest: UzQLCw9SmybbavYyoBEnCCM78xJEjFuJoTV7LNcLP0I= + +Name: res/8j.xml +SHA-256-Digest: yRC5r2g0u2HPaNY8W77zoVpBGbSnIA3tSbylDRdTkZI= + +Name: res/9N.9.png +SHA-256-Digest: DKrqAGCzdyukM8Dp46VFLybzQhulAjyFUVcnC8Z1swk= + +Name: res/9P.xml +SHA-256-Digest: BbW67c1Y/ZlfsBPyBnyH27X5SJ15NXI4KajfgD1Qdgk= + +Name: res/9T.xml +SHA-256-Digest: HQFRT6DQKIpHnffecz6XDg4N69yZfo1GcPz0dCGVU6A= + +Name: res/9T1.xml +SHA-256-Digest: Fv6veimFHbwZOoFO0wqS7Y7i0O1sv/Ooelv5Yn0HKno= + +Name: res/9T2.xml +SHA-256-Digest: BGP3qPMADBr4mqUips63/BiXYsih1LxvavgW7tz32dk= + +Name: res/9V.xml +SHA-256-Digest: XXmAxwYs+N1MeSy/Jo+UNOyNn23xYChAiwT1tY8CySI= + +Name: res/9X.9.png +SHA-256-Digest: lP6YJHFK2UwAL+YhnnI8DYDHy+OmEw16pJNzC2filNE= + +Name: res/9n.9.png +SHA-256-Digest: FBGuZdgWBXPBZtKlchBv0RA8EvJC9n/uxf6qVQGX5fU= + +Name: res/9w.png +SHA-256-Digest: Lfq07mqsiILS3i8qgg4xnmA//7Is0broD4a6rlddfi4= + +Name: res/9z.png +SHA-256-Digest: caK6Y6XU6R98FDJPocPrkpC3PLezx4KAGNBa2xz6q0U= + +Name: res/A4.xml +SHA-256-Digest: EXipiaQf1MGnnV+KiRBLagxgvpNQXmzOg1QM3s2IeBo= + +Name: res/A7.der +SHA-256-Digest: sIXXC5ZPGRpz5K8NVK56Dgeq/a+bcd0IYhOKtzJaJKI= + +Name: res/AA.xml +SHA-256-Digest: cWU+euyaktsllNA7lHDgG0bgeWj2bAe7b4OfMiXRPRE= + +Name: res/Av.xml +SHA-256-Digest: nM9fakHYr6XxlNYv8uuzQaEFIlK22VNVg5jCFCmyvdc= + +Name: res/B3.xml +SHA-256-Digest: tIhGC/jUUhtGuUxouZdyUN/+2Aiy5r82m3lu/lSDxBU= + +Name: res/BG.9.png +SHA-256-Digest: qmEinNcCOSeBCcXr5yXnJITQJS76SQKhcZI2aUJ0kok= + +Name: res/BJ.xml +SHA-256-Digest: 4Ootgip6kbY1FBl0F6TIRuj7WTOeTek51P5lSs9hbGo= + +Name: res/BL.9.png +SHA-256-Digest: 9lqH76L1PW/i2EjPyh9skK6l6fxn/0f1lJpt0qduvhs= + +Name: res/BM.png +SHA-256-Digest: Wmyh0NL+pTgT2ls8kDdAgIf591P1jdLhKKSkj3aJdp8= + +Name: res/BW.xml +SHA-256-Digest: ObPpFQcD/DznWpan3/jenmELzw0R+rIo4HnBhtuqJiI= + +Name: res/BW1.xml +SHA-256-Digest: i+S7MXjCCCdZdIQKFZ77J5jiFsv6DAgbsNjItJCmZTg= + +Name: res/BX.xml +SHA-256-Digest: 3aMeYTbnQRgr/4e+XO4S72CIR8VDDDDSDrsIe5PihYk= + +Name: res/Be.xml +SHA-256-Digest: tRrL7Slv1YhHh2EhAr3b2199QPhnhmjfCH1Nn9/VA7c= + +Name: res/CK.9.png +SHA-256-Digest: Zx0n5aS0IREXS4iNVxGOBQdaVW1wO9VPkzUgLSpBZ5E= + +Name: res/CN.xml +SHA-256-Digest: oG97vlfsk5rtLaj31B7h+Y5/1O6cHEuX8ILuoSS+HB4= + +Name: res/Cc.xml +SHA-256-Digest: dAhghVS07ZlY+KLAZBRFPKQxSKn/VRSoo8dhDhY5Bfk= + +Name: res/Cg.xml +SHA-256-Digest: Id91MW/AeaHgVqIVt8BaavIzkksk3qNiuvEQNY01mjg= + +Name: res/D5.xml +SHA-256-Digest: nWeZK0SjdtGNjpHhXKp5awvLdRooEBpZoe+7bt1DyEU= + +Name: res/D8.xml +SHA-256-Digest: MtMMa2LDzvUAgWY64NqJvuIZx20tkVxgmHyXiADy0Z4= + +Name: res/DL.9.png +SHA-256-Digest: JfJREsxGsoV2fee1sFjPwKnv1fIc/nJK8DFQXWap7Os= + +Name: res/DZ.xml +SHA-256-Digest: qNc0HCDQfJ/atgLnw5GHyau5yvX7+bKDLNbZ8YoshsI= + +Name: res/D_.9.png +SHA-256-Digest: n9N8gvh98ARkVUNE3d3qVeSA0JwztQWsEyUgNtTWJ24= + +Name: res/EA.9.png +SHA-256-Digest: oNY+x27CHUD+lqS2+09KrFthprY6Y0ctqwVeDZ6YkLE= + +Name: res/EP.png +SHA-256-Digest: U1hzfLaA6hzda6QA0zMW+r+HL9RPag4Se/yL3RYys3Q= + +Name: res/Ed.xml +SHA-256-Digest: e3sD+aJeaPkPLL6UizHEWgmawdj8Hrb5dVg6/yUIjRs= + +Name: res/Eg.xml +SHA-256-Digest: oQr2JTf4WalHEAqt8fVVEvdL9snPexcEj0ZD+USyejU= + +Name: res/FS.png +SHA-256-Digest: UxlV3DSNUM2K24W8uttOBguLfvEAQjX60nIGsgNZlgc= + +Name: res/FW.png +SHA-256-Digest: GGIMFRMwKJu6GWwcweJpn5gGGjW+NVGHYpaoxNWSuhc= + +Name: res/Fu.xml +SHA-256-Digest: x1yAeneK8pRZMHqRj22dcHQ4TOY/eMMaCYPrw4RS3nM= + +Name: res/G2.9.png +SHA-256-Digest: q5SvyyuzJVRMDBEDv1EJuCe/Bw9EH675CfhWrilaHPA= + +Name: res/GC.xml +SHA-256-Digest: FVuWavpodI0mh4eNftvsqljiAfKjlXOo3poUUh6kCS0= + +Name: res/GD.xml +SHA-256-Digest: MNVt6GZ+bN7vtI2aKgBLQFILzbxlp8DIQ2eQIuFxafs= + +Name: res/GK.xml +SHA-256-Digest: SlJ42w9+UNYqAOlU+v/+DMYlHTBc4C4MBUdg57XzK34= + +Name: res/GR.xml +SHA-256-Digest: KGFsdGznJDpnytndTWW5Qt712dupwq8YZBmVbeSn6BI= + +Name: res/Gc.png +SHA-256-Digest: FAiwUR3ptu4JXUdshsAesEdvO6cgn01K+7Z1nuMqCJQ= + +Name: res/Gf.png +SHA-256-Digest: Du2Z0KXjakaLVXYF5szqSVwCnzVphEpF9LXY2t131Kc= + +Name: res/Gt.9.png +SHA-256-Digest: 5+NsPLztyXvCiv+R7XLEMQsWwzFxOhaYppLGbUb2Mic= + +Name: res/H-.png +SHA-256-Digest: D9L1OUbrk7MVT0S9r8iJbqkxlaZM5fxkBJ6LcpPNaAE= + +Name: res/II.xml +SHA-256-Digest: ixpvFhe55YcIDKclXfM0bjVlhwmjmNcYaEeyeEP7CX8= + +Name: res/IR.xml +SHA-256-Digest: xGlfE3CCN4lwewgmITb0r5SF0xPVP88PpbVSjHDU330= + +Name: res/IX.9.png +SHA-256-Digest: H33Ys1ITU69HP0GFCIfpOFz2HDkMbjTk4r2ZGSHM/fg= + +Name: res/Ik.der +SHA-256-Digest: NNinPuII2bzbDZVlIJNLTkDmlIJZbotvc8hCawEKb0g= + +Name: res/In.xml +SHA-256-Digest: ckR9fh9Updg1oMU80cvrW4OSCwdoPIifHyDkPPLU5Ug= + +Name: res/It.xml +SHA-256-Digest: A4TMp6tyspvi1SY6PJWI+msc3GeCLOYn+3Hta1Scui4= + +Name: res/JJ.9.png +SHA-256-Digest: oEcINpq+CSDe0g2H1Yrr9pkuu2fv76JIqEIYle/FNT8= + +Name: res/Jl.xml +SHA-256-Digest: Pqck4RgyhkfW1Kg/7lFG2KLWgsmX49e3/ae8uNSQ2oA= + +Name: res/K5.xml +SHA-256-Digest: bAQhFXh+BZrSPDqUr6KkiiGRXJy8A4dm0YBYsBRzNl8= + +Name: res/KH.9.png +SHA-256-Digest: RoYHYBFAlVshxgkYl7/GX2CdOG+mjVbBmSAYleA7P7w= + +Name: res/KM.png +SHA-256-Digest: HjsC4k+kMbGr4Kl61nI/rUPfef2oF2wQYLb70xF4YZ8= + +Name: res/K_.9.png +SHA-256-Digest: +3HhHAkBM6l/6E+jt2omO0KckDLsRnhUsOMqMVel66U= + +Name: res/Ke.xml +SHA-256-Digest: juYVEA+/ui/QjNEcAB1GKgKv5scqY0EjKV+In3KH7q0= + +Name: res/L_.xml +SHA-256-Digest: e/ZkvpHpTwuaitF7yzHfBw2UwaHcYye5zIM9dQo095Q= + +Name: res/Lf.xml +SHA-256-Digest: GIQUuKY3c2d0Xdrce8IyazdtMxKprhjrJnnkxFbf9fY= + +Name: res/Li.9.png +SHA-256-Digest: qCUvUmOMgN8RnbAxYmGYpKjUsy7mGOlsOja5uUbiaJQ= + +Name: res/M7.xml +SHA-256-Digest: h2dbR54xcgotcnXxNXyHpdZrRbltrwI7ZL2eEnhTu7I= + +Name: res/MF.9.png +SHA-256-Digest: tK9z5SJmvlcMLBY9mH5kNIBm2zEbQeejggAFKcATbGs= + +Name: res/MQ.png +SHA-256-Digest: 2DVD8MgrYs9JnyYYrZlDH571DaYLQVmA7I4OULkOOJM= + +Name: res/NA.9.png +SHA-256-Digest: w2e3OjOpM0KeHVfTP8+/JD8CdOfNuiIaC5g+4VtbrKk= + +Name: res/NF.xml +SHA-256-Digest: CrO8grO5/YSZICyv49SUqfZvuiSNAekLkOkyyISZR8w= + +Name: res/NG.png +SHA-256-Digest: E20I+rD+QW/H4OypxJjmPGg1eyyqQkH0RLvD8m+adMk= + +Name: res/NM.xml +SHA-256-Digest: fW2rllLG0P4FeKGCuWEhXLiDCKnBxFxUqofSQTRpTUY= + +Name: res/NZ.9.png +SHA-256-Digest: d5omBqkxo5miydO9AfPFEMQS8pFkeKpofkMOYAOwpfM= + +Name: res/Nk.9.png +SHA-256-Digest: XHxoL/tk9LUx3g+VScDaEcM3V25CZhhSK/0dNaRRpBQ= + +Name: res/No.9.png +SHA-256-Digest: aCxGbT5POeMfEUq8FjLYXnNFV705gU47p9fGHq4tBps= + +Name: res/Nu.xml +SHA-256-Digest: KhKikZN5HTSbtRJFL1Tj1ndV3tZ5xHtLjhVA6IaV5y8= + +Name: res/Ny.ttf +SHA-256-Digest: slmG0Ycwlgx7JzhKsrxQCFauf+nnHJhQAZGV/5AZ8LI= + +Name: res/Ol.xml +SHA-256-Digest: 8sTN9lyqWYHFJRG8ofPlQTaV+CRFGD1qldDdgSDdahQ= + +Name: res/P4.xml +SHA-256-Digest: B6+1E8fAiH7viPXLh1ffLkklACb9zMm2TKuHSaQPYO0= + +Name: res/Pa.9.png +SHA-256-Digest: j89bnaA8aN/2Wt+ocT25zjteQjqfUEbxeFq2QMKmR/s= + +Name: res/Pb.png +SHA-256-Digest: aDaR157xHoY/5OyE3cYxaW5ZhLVYT8RUnWWG26yiIMc= + +Name: res/Pg.9.png +SHA-256-Digest: XUFhv5SCtdKiNGzT+ic57DID2ZW+usAuiacylDNou/w= + +Name: res/QJ.9.png +SHA-256-Digest: I0ObiJn0tj1orpOF6qSShqS5W5X3m4uNN947Dk/bx0c= + +Name: res/QZ.xml +SHA-256-Digest: mwrHkaP6lT4otSbgIP0uYptAgS7hvEaT/1/f7xUEQgI= + +Name: res/Qd.xml +SHA-256-Digest: o9v+TlywZ4j21Xvee5COwoVkMmG9IavxrnMY0qyhvDk= + +Name: res/Qr.xml +SHA-256-Digest: M08VbFNcdNTPoxnZ2MEK+7M/n1afL014VidfW0XmyvI= + +Name: res/Qt.xml +SHA-256-Digest: kJ9EaLc4I8tQBXCrRwZ6QbNzCqxzcpr9tz6jJdPdoEs= + +Name: res/Qv.xml +SHA-256-Digest: lYgT+DAOfOah0xUgfqbPsS8/2fJ/wigEuT0o9LON/P4= + +Name: res/Qz.xml +SHA-256-Digest: pxiEbpeAH0dbeIVVk7xPjk5YbC7u0aq8AsSvEN4+Sxw= + +Name: res/RJ.png +SHA-256-Digest: 9xbyPJeKF3+DEFcfAPBpjcn2RPuDFEiHArDH5H/Q+eU= + +Name: res/RV.png +SHA-256-Digest: dELNplOsus35rvJWqhkeXrtgcaF0cxKuxF4duCUqPPs= + +Name: res/SV.9.png +SHA-256-Digest: 28CvYfRAuz9TgrjqP6V4ZZ92x6au9iCmivxDqQny4OU= + +Name: res/SV.xml +SHA-256-Digest: +pg776eH5agsGVxlRF/yvmv/NJ6tGGSYQmTIwNL0rsY= + +Name: res/Sj.xml +SHA-256-Digest: UsdIVX2sTUjKnU6Kmh4nsKpzmndvHUsQFM7rgxN+TJw= + +Name: res/Su.9.png +SHA-256-Digest: S8j00T0qzMwTOPc/+QzZdpXZIQ4E3l2pJCFSQ8iVC/M= + +Name: res/TM.xml +SHA-256-Digest: gsjdJjIEeR1ATOGzNjpsAm7s94uLEiA9NQfn2U+gCWg= + +Name: res/Th.png +SHA-256-Digest: Aq0Opv9aVg6UdFLH1k9nmvogVrRPhuo7cHocsXXCzrA= + +Name: res/Tj.9.png +SHA-256-Digest: D6F9h1TW0WPMQz8IfK1sCDFzrIetcJfnaVCiXuxfPpA= + +Name: res/U8.xml +SHA-256-Digest: 5hjS/+llrkdfRiKBo0nAF3t2vJXB0LrCGTJYc6K1Gtc= + +Name: res/UE.9.png +SHA-256-Digest: hDZiQiD7okaugWo6qzed/X/ypIQoSrJMOvSYl3hwW7M= + +Name: res/UO.xml +SHA-256-Digest: aWXIcdxo4g/0FnIfZg831R2Ur0p6CnCoRw5Loh4xQGE= + +Name: res/UR.png +SHA-256-Digest: PP0FVIRIlrUAwzUTseie1iAo0MgN9z08WTVHn0lwSjw= + +Name: res/UX.xml +SHA-256-Digest: 12zIhfYyg+nw4dCDX8TvO8Odtag/XfaBEz9wHC02Cqc= + +Name: res/Uz.der +SHA-256-Digest: 2UdDKr3nt/qQ/C5rWRAbEoDg4cfk5A+jxoh//1en9M8= + +Name: res/V1.xml +SHA-256-Digest: swMzn7PPNVnp3dUjMWmOWCzrXzUJZj+rVTaPzCe9PPg= + +Name: res/V7.xml +SHA-256-Digest: 6rCxkzWElSwdxnN8uQlWdR5SSRkN1FCDez+x/NOyAxU= + +Name: res/VM.xml +SHA-256-Digest: CrO8grO5/YSZICyv49SUqfZvuiSNAekLkOkyyISZR8w= + +Name: res/VN.xml +SHA-256-Digest: n9ASsJakinjkapA+F4I+mkNoLEO671qdsYlRbA2FVVg= + +Name: res/VT.xml +SHA-256-Digest: 0ufnePUnX1KqNSg9VxuDfRODw0igdEDdPrVPafxQ47k= + +Name: res/Vy.xml +SHA-256-Digest: 4LvKZM9QJ51o/VVq+/k+KFtuGOefAu7zQpksb7Y4uUM= + +Name: res/Wh.png +SHA-256-Digest: I51gLJxl8Vb+AkYTIHlVrI+905WubsPvpRvpjjpEc/Q= + +Name: res/Wr.png +SHA-256-Digest: g6RieeL2XYUslFLIbjgybvnz3vb1vsLvFBbHKBWl+/o= + +Name: res/Wz.png +SHA-256-Digest: wTGrDi65h5vQY+c2q4ExPFpPR+qi9KDsnsqToaFQ7Xk= + +Name: res/X3.9.png +SHA-256-Digest: RMKXZrLYi3inE5Oz46dxyn7vX1UmMMYHTzPWKRJB0Lk= + +Name: res/X3.xml +SHA-256-Digest: DvYEo4npMW5VjuOYc8FE+xTA8QaGc7DezfZ4gJLkXQg= + +Name: res/X4.9.png +SHA-256-Digest: yNE+VoejTVuFAY/3qfDyKHCil7Jh/xQLPtBBzn5/S4E= + +Name: res/XK.xml +SHA-256-Digest: 5Jo9ZUn4/86e9nFqHc4Ab2R5fqrmC8CRsWxWDiDuWb0= + +Name: res/XW.xml +SHA-256-Digest: mwrHkaP6lT4otSbgIP0uYptAgS7hvEaT/1/f7xUEQgI= + +Name: res/XY.xml +SHA-256-Digest: XEBGynF7/4KlXT1NPl7oY1+63+ZKw1iqOW/UZkCF6mA= + +Name: res/Xx.xml +SHA-256-Digest: llq+VP1C2y7i6FS0KLC6F4DR1jQldDxk6n/Fz6YNfOA= + +Name: res/Y7.9.png +SHA-256-Digest: p3qqIH/VefZDgzI7k/BI7pQ040XKi7ZBdDp3kBtDg8I= + +Name: res/YG.9.png +SHA-256-Digest: Xj8T7oVPpBNUynN4NYuZ+OQfOxyZaMMTtjCwLehwTm4= + +Name: res/YW.xml +SHA-256-Digest: y0hkc7wPfWyQ3qVk/WG7YSSWNxtrC8q4K5WhDPcNtB4= + +Name: res/Yi.xml +SHA-256-Digest: wQ/6wiLY000PPeyHv+EJGIbORirWmMnVk24fJ2OcHmw= + +Name: res/Yw.9.png +SHA-256-Digest: qTOq676uSJ3qhOeOf7xAef39pXb73rM5QB/abNwD52Q= + +Name: res/Z8.png +SHA-256-Digest: r7yu3mapfdybVMTZiRwJQVy2lE15xMGuhEDNpVOWOVc= + +Name: res/ZC.der +SHA-256-Digest: aXKbjhWobvwXelevtxcd/GSt0owvyozxUH40RTzLFHA= + +Name: res/ZL.xml +SHA-256-Digest: hNvfeK2ZRyhm/X+fQER/yuN3wC4HgJNZh6lgvbbWnsw= + +Name: res/ZN.xml +SHA-256-Digest: 54+bSAPehrdceAFG/idIsYAzMo1kZlAuMSPtSBuwc4M= + +Name: res/Zg.xml +SHA-256-Digest: zv1O54HhRnz9EIGeVGOulAjZ8WFLbadgfXomPC3w/s8= + +Name: res/_o.xml +SHA-256-Digest: aLf8DoGcUmx+McFBOxghvAzPz0q1UMNWp/dAqdhJF9w= + +Name: res/_q.png +SHA-256-Digest: UlSajQtsNfryeV799rTF/iyzS36LEDnMp6onabbKs9A= + +Name: res/aF.xml +SHA-256-Digest: 0QMblRUxecAabbZYNj+bv8z4Kge/UVI4Vt8axwj3lNk= + +Name: res/aM.xml +SHA-256-Digest: zrkVeGTlzFYqIfHkZjE5JA1zKJ/FGjDJlqjC7o6J7F0= + +Name: res/aU.9.png +SHA-256-Digest: xjqU5xNs7u9DsK3otJ6OHvTRBg1YT2y5q1i31uqhYxI= + +Name: res/aW.xml +SHA-256-Digest: mwrHkaP6lT4otSbgIP0uYptAgS7hvEaT/1/f7xUEQgI= + +Name: res/ar.png +SHA-256-Digest: KZU72AGd2Wt3ATKbmiA8/2NGBRlUm5zKml63T5sbCTA= + +Name: res/bL.xml +SHA-256-Digest: fd5AWouHpFz+fbkf53+B4Tw09ucLvmpavBTzT3umw3Q= + +Name: res/bX.9.png +SHA-256-Digest: ovGjevjmmTIKL62+VO6qYRLVo1ItV9aC7fBP6XvjtH4= + +Name: res/bt.xml +SHA-256-Digest: rWBZncfx/Zh0/8w5Umf33n9kUsYE3K6FnYy/KAtcOWo= + +Name: res/c5.xml +SHA-256-Digest: aLf8DoGcUmx+McFBOxghvAzPz0q1UMNWp/dAqdhJF9w= + +Name: res/cL.xml +SHA-256-Digest: dPE5EMY0prRzDeT6mcWllc1JOd8CH755paT3P2CUVlo= + +Name: res/cm.xml +SHA-256-Digest: OBbIPULSPA3Ia5f4h7MVIAkYDEUs87vlGr1pkNRFKaU= + +Name: res/color-v23/abc_color_highlight_material.xml +SHA-256-Digest: kqsSAFdeh0l5iVoTs0glNBmj1NCavKScu/096LLYxSQ= + +Name: res/color-v23/abc_tint_btn_checkable.xml +SHA-256-Digest: eFCFh1Q5vKzt40EWDxMm52XRUxEWNlCI4El5VUhfi9Y= + +Name: res/color-v23/abc_tint_default.xml +SHA-256-Digest: bYKCHc0Bj6hy/jh5JL42xUvfn5kwL+gjDAl3xDoysco= + +Name: res/color-v23/abc_tint_edittext.xml +SHA-256-Digest: 2W5VsZZankAOxznCnBtq3ZXTw/f51FRsvFFfqIUv+QM= + +Name: res/color-v23/abc_tint_seek_thumb.xml +SHA-256-Digest: spWuEAM0DJAef/eKekIi+jdQ29mYn4oFrIkNxhdvx6U= + +Name: res/color-v23/abc_tint_spinner.xml +SHA-256-Digest: 2W5VsZZankAOxznCnBtq3ZXTw/f51FRsvFFfqIUv+QM= + +Name: res/color-v23/abc_tint_switch_track.xml +SHA-256-Digest: iJqC3luX8zIPQ421kVTgdw4AxeMdJ5As+LpMkkf9sBk= + +Name: res/color/abc_hint_foreground_material_dark.xml +SHA-256-Digest: lSqow+CLZmuLZF1YZZaEF/KhMjtyFDrknIaC1Bd66rg= + +Name: res/color/abc_hint_foreground_material_light.xml +SHA-256-Digest: WlIVmauU4tf5OJB2XM2LlV5IwQuX/JWCI0VlghSx99w= + +Name: res/color/abc_primary_text_material_dark.xml +SHA-256-Digest: OZf6TN8RLteJ4bOJdMnp2BmJzqJ14SA2P9F3o02yc1E= + +Name: res/color/abc_search_url_text.xml +SHA-256-Digest: HkFx7f4YdepIh/y7jQTHi3LeQhszZ9+PcV5JQbpfG5Q= + +Name: res/color/switch_thumb_material_dark.xml +SHA-256-Digest: nUNhCdo9WWBD0uiY34S2+X8PP1U69aHUMnevoxN8oRk= + +Name: res/d3.png +SHA-256-Digest: L6UkzaeNfr1mFkqJagQid7ela4ZY+zGPxwChFMsE97I= + +Name: res/d5.9.png +SHA-256-Digest: u0sJKuacQp6dT3/5fGC6EMLkQ6Kwyhmp9sd4VL8y4pM= + +Name: res/dO.xml +SHA-256-Digest: luyd9YDTuZ8WsxcYBf3NF/kvVT1MTlUuv5+JMhKgVt8= + +Name: res/dW.png +SHA-256-Digest: QTODD0P5uqCw7TzIDXmLIAcdqfUf4S72sL0Jq8jV0zo= + +Name: res/dY.png +SHA-256-Digest: XO0qt3SFMFAlXXMJ4Qt2IXgT1W8/irj7c6w/Y12QxnY= + +Name: res/eA.xml +SHA-256-Digest: dd8hfVSHwuhOEpOOmwrXGn+hGYNUJGFuh8FGeHDKkn8= + +Name: res/eR.png +SHA-256-Digest: yIJc1jflmgJQDYt1GFYvDJG+8u3Zcbo+WtD0FnlNYY4= + +Name: res/eT.9.png +SHA-256-Digest: gFApeTAt7nNT9HX1WMSXrmaX93GBpR98yAtA1ywuDEw= + +Name: res/ee.xml +SHA-256-Digest: ByJ8h2lOtRYjAFiw1SbjhMtcnf7XIPAzibItr74OyPI= + +Name: res/ej.9.png +SHA-256-Digest: N4aUcG+3JW3SJI4q+FTv1x7H6IhfYdouFqK9Mvzz0Kk= + +Name: res/es.xml +SHA-256-Digest: sPdLTtg5gUHT+8M9tP//Mn4lyH1HgTbBRJ+U53AWLz4= + +Name: res/ev.9.png +SHA-256-Digest: icKOiHsNYMAbNdzSvmVPQWv/tm6FZXFtyYPjsCBJZ+g= + +Name: res/fM.9.png +SHA-256-Digest: tSIoo1Ug4teG6WLoUBP+f3yX/7Qmd/O9q8Ay+7cJlSo= + +Name: res/fO.png +SHA-256-Digest: YZO0tUugP6Ju/9SAMIOSuH+FqkoPsWDZNY9ZtGLSmNc= + +Name: res/fp.xml +SHA-256-Digest: E2Sqp18hEMcchN/K68OwtwEjA/h/roIaYg/9sH6n2DE= + +Name: res/g-.png +SHA-256-Digest: Pbutkm1UBYbWvRIw8ykxCHdMlec/ZgTwu/iMOhFTAiM= + +Name: res/gZ.9.png +SHA-256-Digest: vYk3g8jSvrsWesBaJ82upd/WUf6NZLyzDBTnuSU4DHk= + +Name: res/gj.9.png +SHA-256-Digest: 1o0Dln+yIvfjV3Ki4GN/c7TdDWy7nuPytEMtL5DCV9s= + +Name: res/gt.9.png +SHA-256-Digest: mhpIA4qNHcBBA1tJzHMtsj4AjRJsiy5oB0ndKWFqN7M= + +Name: res/h4.xml +SHA-256-Digest: NWDFwJkHhZ5lcO6ie8vH9Ve9if+9Fq9F9pE8wEbGKNE= + +Name: res/h7.9.png +SHA-256-Digest: n4SbzXiK3Osy9MGlqoknSb0eJEo3h7+/vTDTtvXY6ds= + +Name: res/hP.xml +SHA-256-Digest: 1v9qzAwDdkeAT/nCU13BqtvpfPghc8smE2Vq4gJQ0bA= + +Name: res/hP1.xml +SHA-256-Digest: CXjkAuP48SM0F8A6sGmX7VcEqp5uVix+cCkFhxuCARs= + +Name: res/hZ.9.png +SHA-256-Digest: N4aUcG+3JW3SJI4q+FTv1x7H6IhfYdouFqK9Mvzz0Kk= + +Name: res/hh.9.png +SHA-256-Digest: 1cZEsA7nm9Tx/LeJ67+J55wMb+qHjfvEqMZMO+NLWwM= + +Name: res/hq.xml +SHA-256-Digest: srjqtXA1dhCnMyLnd5FJNqHrY5mt4wkGeD6uGg1jJWQ= + +Name: res/i6.9.png +SHA-256-Digest: 9i16ofkpcwKkMzKlmDR1XtvTo4ZwuMUjYUrhNmtflH8= + +Name: res/iH.xml +SHA-256-Digest: dmVh2MRkcLA5sG16lgGc/YTSoOewW3QCGstigQH0FVI= + +Name: res/iO.png +SHA-256-Digest: uEoneAf487tTeOY1PZnRNEruEL2aBfR8MK/jgy2cp/A= + +Name: res/iR.9.png +SHA-256-Digest: Lj1wIwl3rzfG13OYmac+Y5N+69/m2ALxqVfEPC8qsTE= + +Name: res/io.9.png +SHA-256-Digest: FBdXQTTF6TIcCxj+pxGghEjM9JlX9V4Qztr7EyN1EPc= + +Name: res/j3.xml +SHA-256-Digest: a+EedRNpXxCf67mq7B6aqrmb4yZHidiL6rgfZOl1GQQ= + +Name: res/j4.png +SHA-256-Digest: YALrVng7lWtfkebd/682zIZ0AqAaIl5ie0wlyNIaTiM= + +Name: res/jS.9.png +SHA-256-Digest: /XGeSXqvCRwxZstRv0QEykvDtlRd+++/qgzzHweQt9E= + +Name: res/jS1.9.png +SHA-256-Digest: N4aUcG+3JW3SJI4q+FTv1x7H6IhfYdouFqK9Mvzz0Kk= + +Name: res/jW.png +SHA-256-Digest: JPXbIm8c1W5ed1+Cw39l89HuyQkbJrdIYWKcrwAZw70= + +Name: res/ju.der +SHA-256-Digest: NJ36QFjF4mMSOzmK55VXPE4TE8g/5o+TVWzV6AMbPH0= + +Name: res/kJ.9.png +SHA-256-Digest: wPkwpyKhbfmGkjv0GQgdEJD5R2pyh8i2Vas2/8CAZMs= + +Name: res/k_.xml +SHA-256-Digest: mt7Zf3HH6jb4aeNyukR+qH6qYTenkyDStzn9tDHoPdE= + +Name: res/kj.xml +SHA-256-Digest: g2OTeGlCBs5Q5fxfrO9jxrZDIaEjGx8b0m2Odtc/bkM= + +Name: res/kn.xml +SHA-256-Digest: n/OcwpKr2DEvS2qgRbohP4ZXR4MLMdnQfpXYzmK4dPY= + +Name: res/kp.png +SHA-256-Digest: 9fNJwelJ8OZjdPg7Zn/A0PR3N5YU82kSreIqKZ8hlNU= + +Name: res/lN.xml +SHA-256-Digest: qNc0HCDQfJ/atgLnw5GHyau5yvX7+bKDLNbZ8YoshsI= + +Name: res/lP.9.png +SHA-256-Digest: uLJnCNcbTHpc9TEavN+nQf7jnJ9eE4PUnKDGd/zbA80= + +Name: res/ly.png +SHA-256-Digest: 3AivnRTmtnO/nzHCSCNvBFezIkZANmR0c+OjKiN3Pw4= + +Name: res/m0.png +SHA-256-Digest: d3oc9TggqkZyZ9H2Tl+SNlb5MEcDjqY3W8ziV7UXkw4= + +Name: res/mG.der +SHA-256-Digest: lrzsBiZJdvN0YHeazyjFp8/oo8Cq4RqP/O4FwL3fCMY= + +Name: res/mm.9.png +SHA-256-Digest: 1NKw27A58cY5UYOr6UWzlHCtmop7aApA+nkN9sZFu0M= + +Name: res/nI.9.png +SHA-256-Digest: xWq5N1sUm6HF7iaPIrPPZQe7R5hvYoORUA+6OBR9qyg= + +Name: res/nT.xml +SHA-256-Digest: nZjLDWOgYzR1e2eKHpvVdmURtptWMd5y8U0xr3TAOJE= + +Name: res/nf.png +SHA-256-Digest: XgeZoNC11D7Vrjo3iqoIR6gQzu/1jbmg94Nuv07xcUY= + +Name: res/o-.png +SHA-256-Digest: CEg9lidNJk4Zq3zOmyWWioHrYBsBvuud3g0DJevVDPg= + +Name: res/o9.9.png +SHA-256-Digest: lK4ic6M1ZywcZ5iOevWV1C6AUm7bf1ZU7hMNzgb9QNc= + +Name: res/oI.xml +SHA-256-Digest: wRd+g2VP6V/FQpjQUSvCKUM6KDeLNGxN1TBh1b9LYtk= + +Name: res/oP.xml +SHA-256-Digest: jWX63ADAgA4WCUCRuymouQilEMfVUTJDVuKIEeerIvI= + +Name: res/o_.png +SHA-256-Digest: 0ZCSJUqkEz+6i3eV+121YK1dzRbG95IBvsMbDx6bYIs= + +Name: res/op.9.png +SHA-256-Digest: +BQSxRMQRqg/XZ3h0Q4rSzH24mV8TAh0OCXNQPYF/dM= + +Name: res/pN.xml +SHA-256-Digest: 82XR8Y2s2J7MODAkJs3u4PIrnEtjGQZVXxxrWzioQKE= + +Name: res/pR.xml +SHA-256-Digest: KUcnMc8eGAGxJBv08C70dif9w39klFSLzDB8yI0ewTw= + +Name: res/pk.png +SHA-256-Digest: sKoBDnqIXkt6ZpwWx7oQ/NhioS3/PxQsc1R3hEKmP94= + +Name: res/ps.9.png +SHA-256-Digest: uAD6x9Lwp1sX+tcAlwfqSRNJGeSJhOiYFanSTA+nBNg= + +Name: res/py.9.png +SHA-256-Digest: oVFx6tSxzZuAxYuTwO+0U7DPiJtxTMhZ7iybk39LN9A= + +Name: res/q1.xml +SHA-256-Digest: YNmjt3TpF5kJjaHPK/V+8FomSGAojk7nI00eRiNuljk= + +Name: res/qD.9.png +SHA-256-Digest: H5U4dFz9MgnMCe1FHBmDAqrDocXaQehzlDd4FLG8xe4= + +Name: res/qh.xml +SHA-256-Digest: uhGGpRbgRBB6M3rVGzhyF8PcMn3T46V+EJ+un8kYJzA= + +Name: res/qp.png +SHA-256-Digest: YVFFDs46uWZyE8OYe22P/6Jbr5/0PVO82clP2Op2FtA= + +Name: res/qx.xml +SHA-256-Digest: c48go/g9WpD1pqSekWZX5ltbuFfXJgv+SppdDz5idYE= + +Name: res/qz.xml +SHA-256-Digest: k1Nb/mGQ84B0vsYZa3E05x4BRvwQFEZ9LgmJyfp0xns= + +Name: res/rW.xml +SHA-256-Digest: LIpQXng2h2qA528xPanRrKuNa3zxaM8cFeS1kp7RVTI= + +Name: res/rj.9.png +SHA-256-Digest: AKGsdNgWTLXEdJoLLnfixtpKkKvoc9hgTymEHBk1fGY= + +Name: res/rx.xml +SHA-256-Digest: M55JmB2yRwh1fE2K0z0fX6Rl6LMTZO/qqdomiLLOAtg= + +Name: res/s0.png +SHA-256-Digest: Y/rQoZy55BZYYEnUC2IWGwzEwlE9g5MdOFLi9acubRM= + +Name: res/s3.9.png +SHA-256-Digest: jGhG9BBe8cAhB+hCFC6c5gsIgZKW6VELLQwSz0VgxeE= + +Name: res/s9.xml +SHA-256-Digest: ey71eqYIoJDkrrNEGLHX1hNFMNQBKsDJAzHfHZ5jcOc= + +Name: res/sA.xml +SHA-256-Digest: l8YBYfjpOWpw6ZP/u75qnXCWtitjnQA5LpufPbzAcqI= + +Name: res/sg.9.png +SHA-256-Digest: Z+cBR2knB42Jqwu7Of/xLWlwJZKnpCgjeiEWiiHsEDg= + +Name: res/sn.xml +SHA-256-Digest: gjfUe6/DurkJi9k0SxLcbIf92Hmk4fAchWQAxZXymPA= + +Name: res/t8.xml +SHA-256-Digest: niPbSlyZ4UZx4Wq9B3IhCOckVYv6Z7C0LsVC/3k2hKo= + +Name: res/tG.png +SHA-256-Digest: UqA1jlRDk3PKOfmc2Dzzp75zwlfwf66D7dg8m0iRiV0= + +Name: res/tL.xml +SHA-256-Digest: tqXza20bZxrPXXjFTqfpSJqSmB+DXsKj+jO5jpFtzF0= + +Name: res/tS.png +SHA-256-Digest: yvHkc99nAsKmqV1zjx1vK3MZZ2a1BOX/Mzs8jnR+BHs= + +Name: res/tZ.9.png +SHA-256-Digest: ayNytBSrwc/P1xyY9RkBqExGxbcSBGquAZthEN4mUXU= + +Name: res/te.png +SHA-256-Digest: SYsMvQm2tP7tisqe130jX1uycsU9IbMyZJoA6ULZido= + +Name: res/u0.xml +SHA-256-Digest: jRsGSjjYb82oFdQ60MBuQkb4jFyvf7VYoTroVBzaSow= + +Name: res/u3.png +SHA-256-Digest: Vbwndy9tNb6TNPuAw3GzJ9sl+qmmCYw8FASekmVKwb8= + +Name: res/uL.9.png +SHA-256-Digest: AG8twlusw55za8cg4mplRd90J7bBA7Ldd8Hrhyw/MwY= + +Name: res/uj.9.png +SHA-256-Digest: yG2TSlgJ8yWZ5CFD4wbtbgZrIk/h+j8yreFgMHTlsTY= + +Name: res/ut.9.png +SHA-256-Digest: Viy6GtG5q9UC2pwD9MELsr1ygCLFRvGAWTGfKtKTKA4= + +Name: res/uu.9.png +SHA-256-Digest: NjPsmdZqrkMy+aay29NIBRNDMAGo7sDnltK8tp11tz8= + +Name: res/v4.9.png +SHA-256-Digest: p1I8zwN/fDHPh6GG/uy5E575LYfgcCyrsIoxkUsrUD4= + +Name: res/vY.xml +SHA-256-Digest: lVugqJ4vhXAzgKagEm/+X7YDMIZK5K7iXUWSTFK6juE= + +Name: res/vq.xml +SHA-256-Digest: zquYpznCufQs3Fvtd0n0JcfTVN+SypN25Xa2gXmaJB0= + +Name: res/vz.9.png +SHA-256-Digest: +lAWK9s1Aca1DPo2wU2rnJTkjVf1WGB+yYWBJNcEEvk= + +Name: res/wL.9.png +SHA-256-Digest: jD3lOJpP7fI7Hv3xx3N8p+tE84HCI2kVPfqXJhOkxEg= + +Name: res/w_.png +SHA-256-Digest: BV1fh7G7tmdwlrx+t+rOV+QCFsuX8rK5JtJsEmP5q84= + +Name: res/wb.png +SHA-256-Digest: as4/SBilq02Np2Sj4gxxUsOBJSQWrVVTF4ov6+YpOZs= + +Name: res/xH.png +SHA-256-Digest: fIRytyRBzCihrFOgi08MFPMQrzOBdbpsRv1jQqyM4v8= + +Name: res/xR.9.png +SHA-256-Digest: mpyUDqEz9+CsjbbwbhPoUlCGM8IfjHHyl0gxZaBtkus= + +Name: res/xj.xml +SHA-256-Digest: AIq5nsVZHPbjepgm7pRRVmui4+iCGQXwF1BsNMAtx6o= + +Name: res/xp.xml +SHA-256-Digest: L58q1Vb/eTg0+Wz5Ai8DRAmXYffkUeoy9lgjIfiWHaE= + +Name: res/yH.9.png +SHA-256-Digest: WulZQkCtpeU1AOJSQhWz4rPJHm3ZWwXgrN0n2djFfnI= + +Name: res/yY.9.png +SHA-256-Digest: 8jJxTMvsypetxjsIEdYmKQV8d9y9CwYsguJnVMt0SDE= + +Name: res/yg.9.png +SHA-256-Digest: Ykd63HTU5oNuPA5LUzfDfXSMs/lAM/QsYpk47xjTi0E= + +Name: res/yn.png +SHA-256-Digest: o3hOCekPpzt/F1vDbg28YnKMwE3PthukuNnwgKu8SPQ= + +Name: res/yw.xml +SHA-256-Digest: UxYjgwmJdAq3IB+lChHIiw7oiHsZrQxfMXB5/2wPqEs= + +Name: res/z9.9.png +SHA-256-Digest: d/DrqyQWQE6x1WI0LkMVQdiFaG3R5J1tyTvhqGwic8Q= + +Name: res/zE.png +SHA-256-Digest: pUdDH+vxCMz6lYiribEHjjh7s1HrVNdyOUMyGH93C3Q= + +Name: res/zR.png +SHA-256-Digest: Z2iw1gQNChHxjGPKBuj1ETaakZYEacCUTFF2zeAioCw= + +Name: res/zV.9.png +SHA-256-Digest: D422BdY78dbTX9ZH1ZKsTnDJpxL/XRwhFMjVioi4Ioo= + +Name: res/zz.xml +SHA-256-Digest: 6qHUsMyWOgI626ejo4dpjKQgLAUcpoWK9fSzxncYuqg= + +Name: resources.arsc +SHA-256-Digest: GxocxHQtFbXzrUh1d0SFWRag91R63jVAQCAyregksh0= + diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ManagerApplication.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ManagerApplication.kt index b37863e..179c417 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ManagerApplication.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ManagerApplication.kt @@ -18,7 +18,6 @@ import com.meowarex.rlmobile.ui.screens.about.AboutModel import com.meowarex.rlmobile.ui.screens.componentopts.ComponentOptionsModel import com.meowarex.rlmobile.ui.screens.home.HomeModel import com.meowarex.rlmobile.ui.screens.log.LogScreenModel -import com.meowarex.rlmobile.ui.screens.logs.LogsListScreenModel import com.meowarex.rlmobile.ui.screens.patching.PatchingScreenModel import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionsModel import com.meowarex.rlmobile.ui.screens.permissions.PermissionsModel @@ -64,7 +63,6 @@ class ManagerApplication : Application() { factoryOf(::PatchOptionsModel) factoryOf(::ComponentOptionsModel) factoryOf(::LogScreenModel) - factoryOf(::LogsListScreenModel) factoryOf(::PermissionsModel) viewModelOf(::UpdaterViewModel) }) diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/manager/InstallLogManager.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/manager/InstallLogManager.kt index 7d24747..165d42c 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/manager/InstallLogManager.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/manager/InstallLogManager.kt @@ -12,8 +12,6 @@ import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptions import com.meowarex.rlmobile.util.* import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream -import java.io.IOException import java.text.SimpleDateFormat import java.util.Date import java.util.Locale @@ -21,52 +19,19 @@ import kotlin.time.Duration import kotlin.time.Instant /** - * Central manager for storing all attempted installations and - * their associated logs/crashes (not including manager crashes themselves). + * In-memory store for the most recent install attempts */ class InstallLogManager( private val application: Application, private val prefs: PreferencesManager, - private val json: Json, + @Suppress("unused") private val json: Json, ) { - val logsDir = application.filesDir.resolve("install-logs").apply { mkdir() } + private val entries = linkedMapOf() - /** - * Lists all the install data entries that exist on disk, sorted decreasing by - * the file creation date. - * @return List of installation ids, most recent installation first. - */ - fun fetchInstallDataEntries(): List { - val files = logsDir.listFiles { it.extension == "json" } ?: emptyArray() - - return files - .sortedByDescending { it.lastModified() } - .map { it.nameWithoutExtension } + fun fetchInstallData(id: String): InstallLogData? = synchronized(entries) { + entries[id] } - /** - * Loads the install log from disk, if it exists. - */ - fun fetchInstallData(id: String): InstallLogData? { - val path = logsDir.resolve("$id.json") - if (!path.exists()) return null - - return try { - json.decodeFromStream(path.inputStream()) - } catch (t: Throwable) { - Log.e(BuildConfig.TAG, "Failed to open install log $id", t) - null - } - } - - fun deleteAllEntries() { - logsDir.deleteRecursively() - logsDir.mkdir() - } - - /** - * Writes an install log entry to disk. - */ suspend fun storeInstallData( id: String, installDate: Instant, @@ -75,8 +40,6 @@ class InstallLogManager( log: String, error: Throwable?, ) { - val path = logsDir.resolve("$id.json") - val data = InstallLogData( id = id, installDate = installDate, @@ -87,16 +50,16 @@ class InstallLogManager( errorStacktrace = error?.let { Log.getStackTraceString(it).trimEnd() }, ) - try { - path.writeText(json.encodeToString(data)) - } catch (e: IOException) { - Log.e(BuildConfig.TAG, "Failed to write log to disk", e) + synchronized(entries) { + entries[id] = data + // Keep only the most recent few in memory. + while (entries.size > MAX_ENTRIES) { + val oldest = entries.keys.iterator().next() + entries.remove(oldest) + } } } - /** - * Creates a list of details about the current installation environment. - */ @Suppress("KotlinConstantConditions", "SimplifyBooleanWithConstants") @SuppressLint("UsableSpace") suspend fun getEnvironmentInfo(): String { @@ -139,6 +102,10 @@ class InstallLogManager( SOC: $soc """.trimIndent() } + + private companion object { + const val MAX_ENTRIES = 8 + } } @Immutable diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/patcher/steps/patch/SmaliPatchStep.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/patcher/steps/patch/SmaliPatchStep.kt index 80a94fe..d78f9d3 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/patcher/steps/patch/SmaliPatchStep.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/patcher/steps/patch/SmaliPatchStep.kt @@ -92,18 +92,25 @@ class SmaliPatchStep( container.log("Recorded rl-locals bump: $smaliPath method≈\"$methodSubstring\" >= $newValue") } - val targetLine = lines.firstOrNull { it.startsWith("--- a/") } - ?: throw Error("Patch $patchFile is missing a '--- a/...' header") - val fullClassName = targetLine - .removePrefix("--- a/") - .removeSuffix(".smali") - .trim() - val patch = LoadedPatch( - fullClassName = fullClassName, - patch = UnifiedDiffUtils.parseUnifiedDiff(lines), - ) - patches.add(patch) - container.log("Loaded patch file $patchFile for class ${patch.fullClassName}") + // Split into per-target sections — a single .patch may contain multiple + // `--- a/...` blocks targeting different classes. + val sections = splitMultiTargetPatch(lines) + if (sections.isEmpty()) { + throw Error("Patch $patchFile is missing a '--- a/...' header") + } + for (section in sections) { + val targetLine = section.first { it.startsWith("--- a/") } + val fullClassName = targetLine + .removePrefix("--- a/") + .removeSuffix(".smali") + .trim() + val patch = LoadedPatch( + fullClassName = fullClassName, + patch = UnifiedDiffUtils.parseUnifiedDiff(section), + ) + patches.add(patch) + container.log("Loaded patch file $patchFile for class ${patch.fullClassName}") + } } catch (t: Throwable) { throw Error("Failed to parse patch file $patchFile", t) } @@ -314,6 +321,28 @@ class SmaliPatchStep( private companion object { val LOCALS_DIRECTIVE = Regex("""^#\s*rl-locals:\s+(\S+)\s+(\S+)\s+(\d+)\s*$""") } + + /** + * Splits a unified diff into per-target sections. A single `.patch` file may bundle + * multiple file diffs (each starting with `--- a/...`); each section becomes its own + * patch with its own target class. The header lines before the first `--- a/` (and + * any `# rl-locals:` directives) are preserved by being copied into every section so + * that `UnifiedDiffUtils.parseUnifiedDiff` can still parse the section in isolation. + */ + private fun splitMultiTargetPatch(lines: List): List> { + val headerEnd = lines.indexOfFirst { it.startsWith("--- a/") } + if (headerEnd < 0) return emptyList() + val header = lines.subList(0, headerEnd) + + val sectionStarts = lines.withIndex() + .filter { (_, line) -> line.startsWith("--- a/") } + .map { it.index } + + return sectionStarts.mapIndexed { i, start -> + val end = sectionStarts.getOrNull(i + 1) ?: lines.size + header + lines.subList(start, end) + } + } } private data class LoadedPatch( diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/dialogs/DeleteLogsDialogPreview.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/dialogs/DeleteLogsDialogPreview.kt deleted file mode 100644 index 658f574..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/dialogs/DeleteLogsDialogPreview.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.meowarex.rlmobile.ui.previews.dialogs - -import android.content.res.Configuration -import androidx.compose.runtime.Composable -import androidx.compose.ui.tooling.preview.Preview -import com.meowarex.rlmobile.ui.screens.logs.components.dialogs.DeleteLogsDialog -import com.meowarex.rlmobile.ui.theme.ManagerTheme - -@Composable -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) -private fun DeleteLogsDialogPreview() { - ManagerTheme { - DeleteLogsDialog( - onConfirm = {}, - onDismiss = {}, - ) - } -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenLoadedPreview.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenLoadedPreview.kt deleted file mode 100644 index f86751c..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenLoadedPreview.kt +++ /dev/null @@ -1,78 +0,0 @@ -package com.meowarex.rlmobile.ui.previews.screens.logs - -import android.content.res.Configuration -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateListOf -import androidx.compose.runtime.snapshots.SnapshotStateList -import androidx.compose.ui.tooling.preview.Preview -import com.meowarex.rlmobile.ui.screens.logs.LogEntry -import com.meowarex.rlmobile.ui.screens.logs.LogsScreenContent -import com.meowarex.rlmobile.ui.theme.ManagerTheme -import kotlinx.collections.immutable.persistentListOf -import java.util.UUID - -@Composable -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) -private fun LogsListScreenNonePreview() { - ManagerTheme { - LogsScreenContent( - logs = logs, - onOpenLog = {}, - onDeleteLogs = {}, - ) - } -} - -private val logs: SnapshotStateList = mutableStateListOf( - LogEntry( - id = UUID.randomUUID().toString(), - isError = false, - installDate = "5 min. ago, 10:18 AM", - durationSecs = 18.555f, - stacktracePreview = null, - ), - LogEntry( - id = UUID.randomUUID().toString(), - isError = true, - installDate = "7 min. ago, 10:17 AM", - durationSecs = 73.095f, - stacktracePreview = persistentListOf( - "kotlinx.coroutines.JobCancellationException: Job was cancelled; job=SupervisorJobImpl{Cancelling}@833e76f]", - ), - ), - LogEntry( - id = UUID.randomUUID().toString(), - isError = false, - installDate = "Yesterday, 11:37 PM", - durationSecs = 58.439f, - stacktracePreview = null, - ), - LogEntry( - id = UUID.randomUUID().toString(), - isError = true, - installDate = "Yesterday, 11:17 PM", - durationSecs = 24.405f, - stacktracePreview = persistentListOf( - "java.lang.Error: Installation was aborted or cancelled", - ), - ), - LogEntry( - id = UUID.randomUUID().toString(), - isError = true, - installDate = "Yesterday, 11:17 PM", - durationSecs = 0.057f, - stacktracePreview = persistentListOf( - "java.lang.IllegalStateException: balls", - "\tat com.meowarex.rlmobile.patcher.steps.prepare.FetchInfoStep.execute(FetchInfoStep.kt:31)", - "\tat com.meowarex.rlmobile.patcher.steps.prepare.FetchInfoStep\$execute\\$1.invokeSuspend(Unknown Source:15)", - ), - ), - LogEntry( - id = UUID.randomUUID().toString(), - isError = false, - installDate = "Yesterday, 1:11 PM", - durationSecs = 210.539f, - stacktracePreview = null, - ), -) diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenNonePreview.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenNonePreview.kt deleted file mode 100644 index da80c69..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/previews/screens/logs/LogsListScreenNonePreview.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.meowarex.rlmobile.ui.previews.screens.logs - -import android.content.res.Configuration -import androidx.compose.runtime.* -import androidx.compose.ui.tooling.preview.Preview -import com.meowarex.rlmobile.ui.screens.logs.LogsScreenContent -import com.meowarex.rlmobile.ui.theme.ManagerTheme - -@Composable -@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) -@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) -private fun LogsListScreenNonePreview() { - ManagerTheme { - LogsScreenContent( - logs = remember { mutableStateListOf() }, - onOpenLog = {}, - onDeleteLogs = {}, - ) - } -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/home/HomeScreen.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/home/HomeScreen.kt index 45c2295..4a2aec5 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/home/HomeScreen.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/home/HomeScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.asImageBitmap import androidx.compose.ui.graphics.painter.BitmapPainter +import androidx.activity.ComponentActivity import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -32,13 +33,14 @@ import com.meowarex.rlmobile.ui.components.SegmentedButton import com.meowarex.rlmobile.ui.components.Tag import com.meowarex.rlmobile.ui.screens.about.AboutScreen import com.meowarex.rlmobile.ui.screens.home.components.CommitList -import com.meowarex.rlmobile.ui.screens.logs.LogsListScreen import com.meowarex.rlmobile.ui.screens.patchopts.PatchOptionsScreen import com.meowarex.rlmobile.ui.screens.settings.SettingsScreen import com.meowarex.rlmobile.ui.widgets.managerupdate.ManagerUpdateDialog +import com.meowarex.rlmobile.ui.widgets.updater.UpdaterViewModel import com.meowarex.rlmobile.util.* import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize +import org.koin.androidx.compose.koinViewModel @Parcelize class HomeScreen : Screen, Parcelable { @@ -50,6 +52,9 @@ class HomeScreen : Screen, Parcelable { val navigator = LocalNavigator.currentOrThrow val scope = rememberCoroutineScope() val model = koinScreenModel() + val activity = LocalContext.current as ComponentActivity + val updater = koinViewModel(viewModelStoreOwner = activity) + val managerUpdateAvailable = updater.targetVersion != null LifecycleResumeEffect(Unit) { model.refresh(delay = true) @@ -67,18 +72,20 @@ class HomeScreen : Screen, Parcelable { contentDescription = stringResource(R.string.navigation_refresh), ) } + if (managerUpdateAvailable) { + IconButton(onClick = updater::reopenDialog) { + Icon( + painterResource(R.drawable.ic_update), + contentDescription = stringResource(R.string.action_update), + ) + } + } IconButton(onClick = { navigator.push(AboutScreen()) }) { Icon( painterResource(R.drawable.ic_info), contentDescription = stringResource(R.string.navigation_about), ) } - IconButton(onClick = { navigator.push(LogsListScreen()) }) { - Icon( - painterResource(R.drawable.ic_receipt), - contentDescription = stringResource(R.string.navigation_logs), - ) - } IconButton(onClick = { navigator.push(SettingsScreen()) }) { Icon( painterResource(R.drawable.ic_settings), @@ -107,6 +114,7 @@ class HomeScreen : Screen, Parcelable { is HomeState.Loaded -> HomeContent( state = state, commits = model.commits, + managerUpdateAvailable = managerUpdateAvailable, onInstall = { navigator.pushOnce(PatchOptionsScreen()) }, onRepatch = { scope.launchIO { @@ -134,6 +142,7 @@ class HomeScreen : Screen, Parcelable { private fun ColumnScope.HomeContent( state: HomeState.Loaded, commits: kotlinx.coroutines.flow.Flow>, + managerUpdateAvailable: Boolean, onInstall: () -> Unit, onRepatch: () -> Unit, onLaunch: () -> Unit, @@ -200,12 +209,14 @@ private fun ColumnScope.HomeContent( } } + val blockedByManagerUpdate = managerUpdateAvailable && (patchesBehind || tidalBehind) Button( onClick = if (install == null) onInstall else onRepatch, - enabled = state.latestTidalVersionCode != null, + enabled = state.latestTidalVersionCode != null && !blockedByManagerUpdate, modifier = Modifier.fillMaxWidth(), ) { val label = when { + blockedByManagerUpdate -> "Manager Update Required" state.latestTidalVersionCode == null -> "Loading…" install == null -> "Install" patchesBehind && tidalBehind -> "Update Patches & TIDAL" diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreen.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreen.kt deleted file mode 100644 index c5347e0..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreen.kt +++ /dev/null @@ -1,99 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs - -import android.os.Parcelable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.items -import androidx.compose.material3.Scaffold -import androidx.compose.runtime.* -import androidx.compose.runtime.snapshots.SnapshotStateList -import androidx.compose.ui.Modifier -import androidx.compose.ui.unit.dp -import cafe.adriel.voyager.core.screen.Screen -import cafe.adriel.voyager.core.screen.ScreenKey -import cafe.adriel.voyager.koin.koinScreenModel -import cafe.adriel.voyager.navigator.LocalNavigator -import cafe.adriel.voyager.navigator.currentOrThrow -import com.meowarex.rlmobile.ui.screens.log.LogScreen -import com.meowarex.rlmobile.ui.screens.logs.components.* -import com.meowarex.rlmobile.ui.screens.logs.components.dialogs.DeleteLogsDialog -import com.meowarex.rlmobile.ui.util.paddings.PaddingValuesSides -import com.meowarex.rlmobile.ui.util.paddings.exclude -import kotlinx.parcelize.IgnoredOnParcel -import kotlinx.parcelize.Parcelize - -@Parcelize -class LogsListScreen : Screen, Parcelable { - @IgnoredOnParcel - override val key: ScreenKey - get() = "LogsScreen" - - @Composable - override fun Content() { - val navigator = LocalNavigator.currentOrThrow - val model = koinScreenModel() - - var showWipeConfirmDialog by remember { mutableStateOf(false) } - - if (showWipeConfirmDialog) { - DeleteLogsDialog( - onConfirm = { - showWipeConfirmDialog = false - model.deleteLogs() - }, - onDismiss = { - showWipeConfirmDialog = false - }, - ) - } - - LogsScreenContent( - logs = model.logEntries, - onOpenLog = { navigator.push(LogScreen(installId = it)) }, - onDeleteLogs = { showWipeConfirmDialog = true }, - ) - } -} - -@Composable -fun LogsScreenContent( - logs: SnapshotStateList, - onOpenLog: (id: String) -> Unit, - onDeleteLogs: () -> Unit, -) { - Scaffold( - topBar = { - LogsListAppBar( - onDeleteLogs = onDeleteLogs, - ) - }, - ) { paddingValues -> - LazyColumn( - verticalArrangement = Arrangement.spacedBy(16.dp), - contentPadding = paddingValues.exclude(PaddingValuesSides.Horizontal + PaddingValuesSides.Top), - modifier = Modifier - .padding(paddingValues.exclude(PaddingValuesSides.Bottom)) - .padding(vertical = 12.dp, horizontal = 22.dp) - ) { - if (logs.isEmpty()) { - item(key = "EMPTY") { - LogsNone( - modifier = Modifier.fillParentMaxSize(), - ) - } - } - - items( - items = logs, - contentType = { "LOG" }, - key = { it.id }, - ) { data -> - LogEntryCard( - data = data, - onClick = remember(onOpenLog, data.id) { { onOpenLog(data.id) } }, - modifier = Modifier.fillMaxWidth(), - ) - } - } - } -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreenModel.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreenModel.kt deleted file mode 100644 index 567517a..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/LogsListScreenModel.kt +++ /dev/null @@ -1,71 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs - -import android.app.Application -import android.text.format.DateUtils -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.mutableStateListOf -import cafe.adriel.voyager.core.model.ScreenModel -import cafe.adriel.voyager.core.model.screenModelScope -import com.meowarex.rlmobile.R -import com.meowarex.rlmobile.manager.InstallLogManager -import com.meowarex.rlmobile.util.* -import kotlinx.collections.immutable.ImmutableList -import kotlinx.collections.immutable.toImmutableList - -class LogsListScreenModel( - private val logsManager: InstallLogManager, - private val application: Application, -) : ScreenModel { - /** - * All the loaded log entries sorted descending by creation date. - */ - val logEntries = mutableStateListOf() - - init { - loadLogsList() - } - - fun deleteLogs() = screenModelScope.launchIO { - logsManager.deleteAllEntries() - - mainThread { - logEntries.clear() - application.showToast(R.string.logs_status_delete_success) - } - } - - private fun loadLogsList() = screenModelScope.launchIO { - for (installId in logsManager.fetchInstallDataEntries()) { - val data = logsManager.fetchInstallData(id = installId) - ?: continue - - val entry = LogEntry( - id = data.id, - isError = data.isError, - installDate = DateUtils.getRelativeDateTimeString( - /* c = */ application, - /* time = */ data.installDate.toEpochMilliseconds(), - /* minResolution = */ DateUtils.SECOND_IN_MILLIS, - /* transitionResolution = */ DateUtils.WEEK_IN_MILLIS, - /* flags = */ DateUtils.FORMAT_ABBREV_ALL, - ).toString(), - durationSecs = data.installDuration.inWholeMilliseconds / 1000f, - stacktracePreview = data.errorStacktrace - ?.splitToSequence('\n') - ?.take(3) - ?.toImmutableList(), - ) - - mainThread { logEntries += entry } - } - } -} - -@Immutable -data class LogEntry( - val id: String, - val isError: Boolean, - val installDate: String, - val durationSecs: Float, - val stacktracePreview: ImmutableList?, -) diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogEntryCard.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogEntryCard.kt deleted file mode 100644 index edfb1b8..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogEntryCard.kt +++ /dev/null @@ -1,122 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs.components - -import androidx.compose.foundation.clickable -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.key -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.* -import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.geometry.Size -import androidx.compose.ui.graphics.* -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import com.meowarex.rlmobile.R -import com.meowarex.rlmobile.patcher.steps.base.StepState -import com.meowarex.rlmobile.ui.screens.logs.LogEntry -import com.meowarex.rlmobile.ui.screens.patching.components.StepStateIcon -import com.meowarex.rlmobile.ui.screens.patching.components.TimeElapsed - -@Composable -fun LogEntryCard( - data: LogEntry, - onClick: () -> Unit, - modifier: Modifier = Modifier, -) { - val errorColor = MaterialTheme.colorScheme.error - - ElevatedCard( - shape = RectangleShape, - modifier = modifier - .clickable(onClick = onClick) - .clip(RoundedCornerShape(topStart = 6.dp, 12.0.dp, bottomStart = 6.dp, bottomEnd = 12.0.dp)) - .drawWithCache { - val color = when (data.isError) { - true -> errorColor - false -> Color(0xFF59B463) - } - - onDrawWithContent { - drawContent() - drawRect( - color = color, - alpha = .8f, - topLeft = Offset.Zero, - size = Size(4.dp.toPx(), size.height), - ) - } - } - ) { - Row( - horizontalArrangement = Arrangement.spacedBy(14.dp), - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(vertical = 18.dp, horizontal = 22.dp), - ) { - StepStateIcon( - state = if (data.isError) StepState.Error else StepState.Success, - size = 24.dp, - ) - - Column { - Text( - text = when (data.isError) { - true -> stringResource(R.string.status_failed) - false -> stringResource(R.string.status_success) - }, - ) - - Text( - text = data.installDate, - style = MaterialTheme.typography.labelSmall, - modifier = Modifier.alpha(.6f), - ) - } - - Spacer(Modifier.weight(1f, fill = true)) - - TimeElapsed( - seconds = data.durationSecs, - modifier = Modifier.alpha(.9f), - ) - } - - if (data.stacktracePreview != null) { - Column( - modifier = Modifier - .padding(start = 26.dp, end = 20.dp, bottom = 18.dp) - // https://stackoverflow.com/a/76270310/13964629 - .graphicsLayer( - alpha = .95f, - compositingStrategy = CompositingStrategy.Offscreen, - ) - .drawWithContent { - val colors = listOf(Color.Black, Color.Black, Color.Transparent) - drawContent() - drawRect( - brush = Brush.verticalGradient(colors), - blendMode = BlendMode.DstIn, - ) - } - ) { - // The stacktrace is separated into multiple Text elements because ellipsis is not supported per-line - for (line in data.stacktracePreview) key(line) { - Text( - text = line, - softWrap = false, - overflow = TextOverflow.Ellipsis, - lineHeight = 18.sp, - style = MaterialTheme.typography.labelSmall, - fontFamily = FontFamily.Companion.Monospace, - ) - } - } - } - } -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsListAppBar.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsListAppBar.kt deleted file mode 100644 index ec86ab4..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsListAppBar.kt +++ /dev/null @@ -1,37 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs.components - -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import cafe.adriel.voyager.navigator.LocalNavigator -import com.meowarex.rlmobile.R -import com.meowarex.rlmobile.ui.components.BackButton -import com.meowarex.rlmobile.ui.screens.settings.SettingsScreen - -@Composable -fun LogsListAppBar( - onDeleteLogs: () -> Unit, -) { - TopAppBar( - navigationIcon = { BackButton() }, - title = { Text(stringResource(R.string.logs_title)) }, - actions = { - val navigator = LocalNavigator.current - - IconButton(onClick = onDeleteLogs) { - Icon( - painter = painterResource(R.drawable.ic_delete_forever), - contentDescription = stringResource(R.string.logs_action_delete_all) - ) - } - - IconButton(onClick = { navigator?.push(SettingsScreen()) }) { - Icon( - painter = painterResource(R.drawable.ic_settings), - contentDescription = stringResource(R.string.navigation_settings) - ) - } - } - ) -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsNone.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsNone.kt deleted file mode 100644 index 0b64045..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/LogsNone.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs.components - -import androidx.compose.foundation.layout.* -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.unit.dp -import com.meowarex.rlmobile.R - -@Composable -fun LogsNone(modifier: Modifier = Modifier) { - Box(modifier = modifier) { - Column( - modifier = Modifier.align(Alignment.Center), - verticalArrangement = Arrangement.spacedBy(4.dp), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Icon( - painter = painterResource(R.drawable.ic_reciept_off), - contentDescription = null, - ) - Text( - text = stringResource(R.string.logs_none), - style = MaterialTheme.typography.bodyLarge, - modifier = Modifier.alpha(.8f), - ) - } - } -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/dialogs/DeleteLogsDialog.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/dialogs/DeleteLogsDialog.kt deleted file mode 100644 index 14b6b13..0000000 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/logs/components/dialogs/DeleteLogsDialog.kt +++ /dev/null @@ -1,53 +0,0 @@ -package com.meowarex.rlmobile.ui.screens.logs.components.dialogs - -import androidx.compose.foundation.layout.size -import androidx.compose.material3.* -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import com.meowarex.rlmobile.R - -@Composable -fun DeleteLogsDialog( - onConfirm: () -> Unit, - onDismiss: () -> Unit, -) { - AlertDialog( - onDismissRequest = onDismiss, - icon = { - Icon( - painter = painterResource(R.drawable.ic_delete_forever), - contentDescription = null, - modifier = Modifier.size(32.dp), - ) - }, - title = { Text(stringResource(R.string.logs_wipe_title)) }, - text = { - Text( - text = stringResource(R.string.logs_wipe_desc), - textAlign = TextAlign.Center, - ) - }, - confirmButton = { - Button( - onClick = onConfirm, - ) { - Text(stringResource(R.string.action_confirm)) - } - }, - dismissButton = { - Button( - onClick = onDismiss, - colors = ButtonDefaults.buttonColors( - contentColor = MaterialTheme.colorScheme.onSecondaryContainer, - containerColor = MaterialTheme.colorScheme.secondaryContainer - ) - ) { - Text(stringResource(R.string.action_cancel)) - } - } - ) -} diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt index 9dae2b3..3176276 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/screens/patchopts/KnownPatch.kt @@ -63,6 +63,16 @@ enum class KnownPatch( titleRes = R.string.patch_player_backdrop_title, descRes = R.string.patch_player_backdrop_desc, ), + CoverEverywhere( + order = 35, + fileNames = listOf( + "home-backdrop.patch", + "collection-backdrop.patch", + "cover-capture.patch", + ), + titleRes = R.string.patch_cover_everywhere_title, + descRes = R.string.patch_cover_everywhere_desc, + ), DebugMenuUnlock( order = 100, fileNames = listOf("debug-menu-unlock.patch"), @@ -93,6 +103,7 @@ enum class KnownPatch( LyricsKeepControlsVisible, PlayerBackdrop, LyricsProgressPill, + CoverEverywhere, ), ); diff --git a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/widgets/updater/UpdaterViewModel.kt b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/widgets/updater/UpdaterViewModel.kt index 9b2089f..7368982 100644 --- a/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/widgets/updater/UpdaterViewModel.kt +++ b/Manager/app/src/main/kotlin/com/meowarex/rlmobile/ui/widgets/updater/UpdaterViewModel.kt @@ -55,6 +55,10 @@ class UpdaterViewModel( showDialog = false } + fun reopenDialog() { + if (targetVersion != null) showDialog = true + } + fun triggerUpdate() = viewModelScope.launchIO { if (!isWorking.compareAndSet(expect = false, update = true)) return@launchIO diff --git a/Manager/app/src/main/res/drawable/ic_receipt.xml b/Manager/app/src/main/res/drawable/ic_receipt.xml deleted file mode 100644 index 0b9203d..0000000 --- a/Manager/app/src/main/res/drawable/ic_receipt.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/Manager/app/src/main/res/drawable/ic_reciept_off.xml b/Manager/app/src/main/res/drawable/ic_reciept_off.xml deleted file mode 100644 index e7c6f35..0000000 --- a/Manager/app/src/main/res/drawable/ic_reciept_off.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - diff --git a/Manager/app/src/main/res/drawable/ic_update.xml b/Manager/app/src/main/res/drawable/ic_update.xml index 297f620..d682d6e 100644 --- a/Manager/app/src/main/res/drawable/ic_update.xml +++ b/Manager/app/src/main/res/drawable/ic_update.xml @@ -5,5 +5,5 @@ android:viewportHeight="960"> + android:pathData="M480,640q17,0 28.5,-11.5T520,600v-184l64,64q11,11 28,11t28,-11q11,-11 11,-28t-11,-28L508,308q-12,-12 -28,-12t-28,12L324,424q-11,11 -11,28t11,28q11,11 28,11t28,-11l64,-64v184q0,17 11.5,28.5T480,640Zm0,240q-83,0 -156,-31.5T197,763q-54,-54 -85.5,-127T80,480q0,-83 31.5,-156T197,197q54,-54 127,-85.5T480,80q83,0 156,31.5T763,197q54,54 85.5,127T880,480q0,83 -31.5,156T763,763q-54,54 -127,85.5T480,880Z" /> diff --git a/Manager/app/src/main/res/values/strings.xml b/Manager/app/src/main/res/values/strings.xml index 1a1befc..07d2f44 100644 --- a/Manager/app/src/main/res/values/strings.xml +++ b/Manager/app/src/main/res/values/strings.xml @@ -129,7 +129,6 @@ Back About - Logs Settings Refresh @@ -269,6 +268,8 @@ >Inverts the auto-hide behavior on the lyrics screen, playback controls stay visible by default and only hide when you tap them off. Player Backdrop Restores the legacy translucent backdrop blur behind the player. + Cover Everywhere - WIP + Applies the blurred backdrop to every Compose based page (Home & Collection) Replace Share Button Export APK Share log - Logs - No logs present! - Delete all logs - Successfully deleted all logs - Clear Logs - Are you sure you want to permanently delete all the logs? - Active installation Progress notifications sent during a minimized installation Radiant Lyrics installation ready! diff --git a/patches/collection-backdrop.patch b/patches/collection-backdrop.patch new file mode 100644 index 0000000..7c5b8fe --- /dev/null +++ b/patches/collection-backdrop.patch @@ -0,0 +1,22 @@ +--- a/com/tidal/wave2/foundation/WaveScaffoldKt.smali ++++ b/com/tidal/wave2/foundation/WaveScaffoldKt.smali +@@ -889,6 +889,10 @@ + .line 386 + .line 387 + :cond_20 ++ const/4 v0, 0x0 # render $changed flag ++ ++ invoke-static {v1, v0}, Lradiant/HomeBackdrop;->render(Landroidx/compose/runtime/Composer;I)V # render album-art backdrop ++ + new-instance v0, Lcom/tidal/wave2/foundation/WaveScaffoldKt$WaveScaffold$2; + + .line 388 +@@ -991,7 +995,7 @@ + + .line 436 + .line 437 +- move-wide v15, v10 ++ const-wide/16 v15, 0x0 # transparent containerColor + + .line 438 + const/4 v11, 0x0 diff --git a/patches/cover-capture.patch b/patches/cover-capture.patch new file mode 100644 index 0000000..8873981 --- /dev/null +++ b/patches/cover-capture.patch @@ -0,0 +1,11 @@ +--- a/com/tidal/android/feature/appscaffold/ui/p.smali ++++ b/com/tidal/android/feature/appscaffold/ui/p.smali +@@ -51,6 +51,8 @@ + .line 10 + iput-object p4, p0, Lcom/tidal/android/feature/appscaffold/ui/p;->d:Ljava/lang/String; + ++ invoke-static {p3, p4}, Lradiant/HomeBackdrop;->fromMiniPlayer(ILjava/lang/String;)V # capture cover state ++ + .line 11 + .line 12 + iput-boolean p5, p0, Lcom/tidal/android/feature/appscaffold/ui/p;->e:Z diff --git a/patches/data.json b/patches/data.json index 5cb2888..0c2c3ea 100644 --- a/patches/data.json +++ b/patches/data.json @@ -1,5 +1,5 @@ { "tidalVersionCode": 9090, "tidalApkUrl": "https://github.com/meowarex/rl-mobile/releases/download/latest/tidal-stock.apk", - "patchesVersion": "0.8.7" + "patchesVersion": "0.9.1" } diff --git a/patches/extension/radiant/HomeBackdrop.smali b/patches/extension/radiant/HomeBackdrop.smali new file mode 100644 index 0000000..036a0fd --- /dev/null +++ b/patches/extension/radiant/HomeBackdrop.smali @@ -0,0 +1,370 @@ +.class public final Lradiant/HomeBackdrop; +.super Ljava/lang/Object; + + +# static fields +.field public static volatile currentAlbumId:I + +.field public static coverUuidState:Landroidx/compose/runtime/MutableState; + .annotation system Ldalvik/annotation/Signature; + value = { + "Landroidx/compose/runtime/MutableState<", + "Ljava/lang/String;", + ">;" + } + .end annotation +.end field + + +# direct methods +.method static constructor ()V + .locals 4 + + const/4 v0, 0x0 + + sput v0, Lradiant/HomeBackdrop;->currentAlbumId:I + + const/4 v0, 0x0 + + const/4 v1, 0x0 + + const/4 v2, 0x2 + + const/4 v3, 0x0 + + invoke-static {v0, v1, v2, v3}, Landroidx/compose/runtime/SnapshotStateKt;->mutableStateOf$default(Ljava/lang/Object;Landroidx/compose/runtime/SnapshotMutationPolicy;ILjava/lang/Object;)Landroidx/compose/runtime/MutableState; + + move-result-object v0 + + sput-object v0, Lradiant/HomeBackdrop;->coverUuidState:Landroidx/compose/runtime/MutableState; + + return-void +.end method + + +.method private constructor ()V + .locals 0 + + invoke-direct {p0}, Ljava/lang/Object;->()V + + return-void +.end method + + +.method public static dlog(Ljava/lang/String;)V + .locals 1 + + const-string v0, "RLHomeBackdrop" + + invoke-static {v0, p0}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I + + return-void +.end method + + +.method private static isDebugMenuStack()Z + .locals 6 + + new-instance v0, Ljava/lang/Throwable; + + invoke-direct {v0}, Ljava/lang/Throwable;->()V + + invoke-virtual {v0}, Ljava/lang/Throwable;->getStackTrace()[Ljava/lang/StackTraceElement; + + move-result-object v0 + + array-length v1, v0 + + const/4 v2, 0x0 + + :loop_start + if-ge v2, v1, :loop_end + + aget-object v3, v0, v2 + + invoke-virtual {v3}, Ljava/lang/StackTraceElement;->getClassName()Ljava/lang/String; + + move-result-object v3 + + const-string v4, "debugmenu" + + invoke-virtual {v3, v4}, Ljava/lang/String;->contains(Ljava/lang/CharSequence;)Z + + move-result v5 + + if-eqz v5, :next + + const/4 v0, 0x1 + + return v0 + + :next + add-int/lit8 v2, v2, 0x1 + + goto :loop_start + + :loop_end + const/4 v0, 0x0 + + return v0 +.end method + + +.method public static fromMiniPlayer(ILjava/lang/String;)V + .locals 2 + + new-instance v0, Ljava/lang/StringBuilder; + + const-string v1, "fromMiniPlayer: id=" + + invoke-direct {v0, v1}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V + + invoke-virtual {v0, p0}, Ljava/lang/StringBuilder;->append(I)Ljava/lang/StringBuilder; + + const-string v1, " cover=" + + invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + invoke-virtual {v0, p1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v0 + + invoke-static {v0}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + sput p0, Lradiant/HomeBackdrop;->currentAlbumId:I + + sget-object v0, Lradiant/HomeBackdrop;->coverUuidState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v0, p1}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + return-void +.end method + + +.method public static onTrack(Lcom/aspiro/wamp/model/Track;)V + .locals 3 + + const-string v0, "onTrack: entered" + + invoke-static {v0}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + if-eqz p0, :clear + + :try_start + invoke-virtual {p0}, Lcom/aspiro/wamp/model/MediaItem;->getAlbum()Lcom/aspiro/wamp/model/Album; + + move-result-object v0 + + if-eqz v0, :clear + + invoke-virtual {v0}, Lcom/aspiro/wamp/model/Album;->getId()I + + move-result v1 + + sput v1, Lradiant/HomeBackdrop;->currentAlbumId:I + + invoke-virtual {v0}, Lcom/aspiro/wamp/model/Album;->getCover()Ljava/lang/String; + + move-result-object v0 + + sget-object v1, Lradiant/HomeBackdrop;->coverUuidState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v1, v0}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + new-instance v1, Ljava/lang/StringBuilder; + + const-string v2, "onTrack: set uuid=" + + invoke-direct {v1, v2}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V + + invoke-virtual {v1, v0}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + invoke-virtual {v1}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v0 + + invoke-static {v0}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + :try_end + .catch Ljava/lang/Throwable; {:try_start .. :try_end} :swallow + + return-void + + :clear + const-string v0, "onTrack: clearing (null track/album)" + + invoke-static {v0}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + const/4 v0, 0x0 + + sput v0, Lradiant/HomeBackdrop;->currentAlbumId:I + + sget-object v1, Lradiant/HomeBackdrop;->coverUuidState:Landroidx/compose/runtime/MutableState; + + const/4 v2, 0x0 + + invoke-interface {v1, v2}, Landroidx/compose/runtime/MutableState;->setValue(Ljava/lang/Object;)V + + return-void + + :swallow + const-string v0, "onTrack: caught throwable" + + invoke-static {v0}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + return-void +.end method + + +.method public static render(Landroidx/compose/runtime/Composer;I)V + .locals 16 + .annotation build Landroidx/compose/runtime/Composable; + .end annotation + + invoke-static {}, Lradiant/HomeBackdrop;->isDebugMenuStack()Z + + move-result v0 + + if-eqz v0, :proceed + + return-void + + :proceed + move-object/from16 v0, p0 + + const-string v1, "render: entered" + + invoke-static {v1}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + const v1, 0x52414449 + + invoke-interface {v0, v1}, Landroidx/compose/runtime/Composer;->startReplaceGroup(I)V + + sget-object v1, Lradiant/HomeBackdrop;->coverUuidState:Landroidx/compose/runtime/MutableState; + + invoke-interface {v1}, Landroidx/compose/runtime/State;->getValue()Ljava/lang/Object; + + move-result-object v1 + + check-cast v1, Ljava/lang/String; + + new-instance v2, Ljava/lang/StringBuilder; + + const-string v3, "render: uuid=" + + invoke-direct {v2, v3}, Ljava/lang/StringBuilder;->(Ljava/lang/String;)V + + invoke-virtual {v2, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder; + + invoke-virtual {v2}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String; + + move-result-object v2 + + invoke-static {v2}, Lradiant/HomeBackdrop;->dlog(Ljava/lang/String;)V + + if-eqz v1, :skip + + invoke-virtual {v1}, Ljava/lang/String;->length()I + + move-result v2 + + if-eqz v2, :skip + + sget v2, Lradiant/HomeBackdrop;->currentAlbumId:I + + new-instance v3, Lcom/tidal/android/feature/playerscreen/ui/composables/n0; + + invoke-direct {v3, v2, v1}, Lcom/tidal/android/feature/playerscreen/ui/composables/n0;->(ILjava/lang/String;)V + + sget-object v4, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; + + const/4 v5, 0x0 + + const/4 v6, 0x1 + + const/4 v7, 0x0 + + invoke-static {v4, v5, v6, v7}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxSize$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier; + + move-result-object v4 + + const/high16 v5, 0x42200000 + + invoke-static {v5}, Landroidx/compose/ui/unit/Dp;->constructor-impl(F)F + + move-result v5 + + sget-object v6, Landroidx/compose/ui/draw/BlurredEdgeTreatment;->Companion:Landroidx/compose/ui/draw/BlurredEdgeTreatment$Companion; + + invoke-virtual {v6}, Landroidx/compose/ui/draw/BlurredEdgeTreatment$Companion;->getRectangle---Goahg()Landroidx/compose/ui/graphics/Shape; + + move-result-object v6 + + invoke-static {v4, v5, v6}, Landroidx/compose/ui/draw/BlurKt;->blur-F8QBwvs(Landroidx/compose/ui/Modifier;FLandroidx/compose/ui/graphics/Shape;)Landroidx/compose/ui/Modifier; + + move-result-object v4 + + sget-object v5, Landroidx/compose/ui/layout/ContentScale;->Companion:Landroidx/compose/ui/layout/ContentScale$Companion; + + invoke-virtual {v5}, Landroidx/compose/ui/layout/ContentScale$Companion;->getCrop()Landroidx/compose/ui/layout/ContentScale; + + move-result-object v5 + + move-object/from16 v6, v3 + + const/4 v7, 0x0 + + move-object/from16 v8, v4 + + const/4 v9, 0x0 + + move-object/from16 v10, v5 + + move-object/from16 v11, v1 # uuid as cache key + + const/4 v12, 0x0 + + move-object/from16 v13, v0 + + const/4 v14, 0x0 + + const/16 v15, 0x48 + + invoke-static/range {v6 .. v15}, Lxd0/f;->a(Lyl0/l;Ljava/lang/String;Landroidx/compose/ui/Modifier;Landroidx/compose/ui/graphics/ColorFilter;Landroidx/compose/ui/layout/ContentScale;Ljava/lang/Object;Lyl0/a;Landroidx/compose/runtime/Composer;II)V + + sget-object v3, Landroidx/compose/ui/Modifier;->Companion:Landroidx/compose/ui/Modifier$Companion; + + const/4 v4, 0x0 + + const/4 v5, 0x1 + + const/4 v6, 0x0 + + invoke-static {v3, v4, v5, v6}, Landroidx/compose/foundation/layout/SizeKt;->fillMaxSize$default(Landroidx/compose/ui/Modifier;FILjava/lang/Object;)Landroidx/compose/ui/Modifier; + + move-result-object v3 + + const v4, -0x80000000 + + invoke-static {v4}, Landroidx/compose/ui/graphics/ColorKt;->Color(I)J + + move-result-wide v4 + + invoke-static {}, Landroidx/compose/ui/graphics/RectangleShapeKt;->getRectangleShape()Landroidx/compose/ui/graphics/Shape; + + move-result-object v6 + + invoke-static {v3, v4, v5, v6}, Landroidx/compose/foundation/BackgroundKt;->background-bw27NRU(Landroidx/compose/ui/Modifier;JLandroidx/compose/ui/graphics/Shape;)Landroidx/compose/ui/Modifier; + + move-result-object v3 + + const/4 v4, 0x0 + + invoke-static {v3, v0, v4}, Landroidx/compose/foundation/layout/SpacerKt;->Spacer(Landroidx/compose/ui/Modifier;Landroidx/compose/runtime/Composer;I)V + + :skip + invoke-interface {v0}, Landroidx/compose/runtime/Composer;->endReplaceGroup()V + + return-void +.end method diff --git a/patches/extension/radiant/RLAPILyricsHook.smali b/patches/extension/radiant/RLAPILyricsHook.smali index abac4a2..ef3b63f 100644 --- a/patches/extension/radiant/RLAPILyricsHook.smali +++ b/patches/extension/radiant/RLAPILyricsHook.smali @@ -63,6 +63,8 @@ .method public static onWampTrack(Lcom/tidal/android/feature/playerscreen/ui/PlayerViewModel;Lcom/aspiro/wamp/model/Track;)V .locals 11 + invoke-static {p1}, Lradiant/HomeBackdrop;->onTrack(Lcom/aspiro/wamp/model/Track;)V + const/4 v3, 0x0 sput-boolean v3, Lradiant/RLAPILyricsHook;->isRlState:Z diff --git a/patches/home-backdrop.patch b/patches/home-backdrop.patch new file mode 100644 index 0000000..00d2c30 --- /dev/null +++ b/patches/home-backdrop.patch @@ -0,0 +1,43 @@ +--- a/com/tidal/android/feature/home/ui/k.smali ++++ b/com/tidal/android/feature/home/ui/k.smali +@@ -424,7 +424,7 @@ + const/4 v6, 0x0 + + .line 181 +- move-wide v7, v8 ++ const-wide/16 v7, 0x0 # transparent containerColor + + .line 182 + const-wide/16 v9, 0x0 +--- a/com/tidal/android/feature/home/ui/p.smali ++++ b/com/tidal/android/feature/home/ui/p.smali +@@ -187,6 +187,10 @@ + .line 61 + .line 62 + :cond_3 ++ const/4 v0, 0x0 # render $changed flag ++ ++ invoke-static {v4, v0}, Lradiant/HomeBackdrop;->render(Landroidx/compose/runtime/Composer;I)V # render album-art backdrop ++ + invoke-interface {p1}, Landroidx/compose/foundation/layout/PaddingValues;->calculateTopPadding-D9Ej5fM()F + + .line 63 +--- a/com/tidal/android/feature/home/ui/composables/e.smali ++++ b/com/tidal/android/feature/home/ui/composables/e.smali +@@ -790,6 +790,8 @@ + .line 104 + move-result-wide v14 + ++ const-wide/16 v14, 0x0 # transparent topBar background ++ + .line 105 + const/16 v17, 0x2 + +@@ -850,6 +852,8 @@ + .line 134 + move-result-wide v14 + ++ const-wide/16 v14, 0x0 # transparent TopAppBar containerColor ++ + .line 135 + sget-object v3, Landroidx/compose/ui/graphics/Color;->Companion:Landroidx/compose/ui/graphics/Color$Companion;