diff --git a/app/src/main/java/com/aurora/extensions/Collection.kt b/app/src/main/java/com/aurora/extensions/Collection.kt index efb6f5cf1..8bdab0bb2 100644 --- a/app/src/main/java/com/aurora/extensions/Collection.kt +++ b/app/src/main/java/com/aurora/extensions/Collection.kt @@ -19,18 +19,8 @@ package com.aurora.extensions -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile -fun MutableList.flushAndAdd(list: List) { - clear() - addAll(list) -} - -fun MutableSet.flushAndAdd(list: Set) { - clear() - addAll(list) -} - -fun List.requiresObbDir(): Boolean { - return this.any { it.type == File.FileType.OBB || it.type == File.FileType.PATCH } +fun List.requiresObbDir(): Boolean { + return this.any { it.type == PlayFile.Type.OBB } } diff --git a/app/src/main/java/com/aurora/store/data/event/BusEvent.kt b/app/src/main/java/com/aurora/store/data/event/BusEvent.kt index 9dcb2282e..b6b92af90 100644 --- a/app/src/main/java/com/aurora/store/data/event/BusEvent.kt +++ b/app/src/main/java/com/aurora/store/data/event/BusEvent.kt @@ -26,7 +26,7 @@ sealed class BusEvent : Event() { lateinit var error: String data class Blacklisted(val packageName: String) : BusEvent() - data class ManualDownload(val packageName: String, val versionCode: Int) : BusEvent() + data class ManualDownload(val packageName: String, val versionCode: Long) : BusEvent() } sealed class AuthEvent : Event() { diff --git a/app/src/main/java/com/aurora/store/data/helper/DownloadHelper.kt b/app/src/main/java/com/aurora/store/data/helper/DownloadHelper.kt index 14b593873..608ed0ac0 100644 --- a/app/src/main/java/com/aurora/store/data/helper/DownloadHelper.kt +++ b/app/src/main/java/com/aurora/store/data/helper/DownloadHelper.kt @@ -107,7 +107,7 @@ class DownloadHelper @Inject constructor( * @param packageName Name of the package of the app * @param versionCode Version of the package */ - suspend fun clearDownload(packageName: String, versionCode: Int) { + suspend fun clearDownload(packageName: String, versionCode: Long) { Log.i(TAG, "Clearing downloads for $packageName ($versionCode)") downloadDao.delete(packageName) PathUtil.getAppDownloadDir(context, packageName, versionCode) diff --git a/app/src/main/java/com/aurora/store/data/installer/RootInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/RootInstaller.kt index 84a7924f4..51203f5e7 100644 --- a/app/src/main/java/com/aurora/store/data/installer/RootInstaller.kt +++ b/app/src/main/java/com/aurora/store/data/installer/RootInstaller.kt @@ -81,7 +81,7 @@ class RootInstaller @Inject constructor( } } - private fun xInstall(packageName: String, versionCode: Int, sharedLibPkgName: String = "") { + private fun xInstall(packageName: String, versionCode: Long, sharedLibPkgName: String = "") { var totalSize = 0 for (file in getFiles(packageName, versionCode, sharedLibPkgName)) diff --git a/app/src/main/java/com/aurora/store/data/installer/SessionInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/SessionInstaller.kt index 4e296af74..786871b96 100644 --- a/app/src/main/java/com/aurora/store/data/installer/SessionInstaller.kt +++ b/app/src/main/java/com/aurora/store/data/installer/SessionInstaller.kt @@ -183,7 +183,7 @@ class SessionInstaller @Inject constructor( private fun stageInstall( packageName: String, - versionCode: Int, + versionCode: Long, sharedLibPkgName: String = "" ): Int? { val resolvedPackageName = sharedLibPkgName.ifBlank { packageName } diff --git a/app/src/main/java/com/aurora/store/data/installer/ShizukuInstaller.kt b/app/src/main/java/com/aurora/store/data/installer/ShizukuInstaller.kt index c664021f7..71e4f53d5 100644 --- a/app/src/main/java/com/aurora/store/data/installer/ShizukuInstaller.kt +++ b/app/src/main/java/com/aurora/store/data/installer/ShizukuInstaller.kt @@ -129,7 +129,7 @@ class ShizukuInstaller @Inject constructor( private fun install( packageName: String, - versionCode: Int, + versionCode: Long, sharedLibPkgName: String = "", displayName: String = "" ) { diff --git a/app/src/main/java/com/aurora/store/data/installer/base/InstallerBase.kt b/app/src/main/java/com/aurora/store/data/installer/base/InstallerBase.kt index 0895eda8e..9a13d36f8 100644 --- a/app/src/main/java/com/aurora/store/data/installer/base/InstallerBase.kt +++ b/app/src/main/java/com/aurora/store/data/installer/base/InstallerBase.kt @@ -103,7 +103,7 @@ abstract class InstallerBase(private val context: Context) : IInstaller { fun getFiles( packageName: String, - versionCode: Int, + versionCode: Long, sharedLibPackageName: String = "" ): List { val downloadDir = if (sharedLibPackageName.isNotBlank()) { diff --git a/app/src/main/java/com/aurora/store/data/model/MinimalApp.kt b/app/src/main/java/com/aurora/store/data/model/MinimalApp.kt index 722fa275f..1794e701c 100644 --- a/app/src/main/java/com/aurora/store/data/model/MinimalApp.kt +++ b/app/src/main/java/com/aurora/store/data/model/MinimalApp.kt @@ -1,13 +1,9 @@ package com.aurora.store.data.model -import android.content.Context -import android.content.pm.PackageInfo import android.graphics.Bitmap import android.os.Parcelable -import androidx.core.content.pm.PackageInfoCompat import com.aurora.gplayapi.data.models.App import com.aurora.store.data.room.update.Update -import com.aurora.store.util.PackageUtil import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -15,7 +11,7 @@ import kotlinx.parcelize.Parcelize data class MinimalApp( val packageName: String, val versionName: String, - val versionCode: Int, + val versionCode: Long, val displayName: String, @IgnoredOnParcel val icon: Bitmap? = null @@ -32,14 +28,6 @@ data class MinimalApp( ) } - fun toApp(minimalApp: MinimalApp): App { - return App(minimalApp.packageName).apply { - versionName = minimalApp.versionName ?: "" - versionCode = minimalApp.versionCode - displayName = minimalApp.displayName - } - } - fun fromUpdate(update: Update): MinimalApp { return MinimalApp( update.packageName, @@ -49,14 +37,5 @@ data class MinimalApp( ) } - fun fromPackageInfo(context: Context, packageInfo: PackageInfo): MinimalApp { - return MinimalApp( - packageInfo.packageName, - packageInfo.versionName ?: "", - PackageInfoCompat.getLongVersionCode(packageInfo).toInt(), - packageInfo.applicationInfo!!.loadLabel(context.packageManager).toString(), - PackageUtil.getIconForPackage(context, packageInfo.packageName) - ) - } } } diff --git a/app/src/main/java/com/aurora/store/data/model/SelfUpdate.kt b/app/src/main/java/com/aurora/store/data/model/SelfUpdate.kt index dc0d746bd..0cfd32a90 100644 --- a/app/src/main/java/com/aurora/store/data/model/SelfUpdate.kt +++ b/app/src/main/java/com/aurora/store/data/model/SelfUpdate.kt @@ -23,7 +23,7 @@ import android.content.Context import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.Artwork import com.aurora.gplayapi.data.models.EncodedCertificateSet -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.BuildConfig import com.aurora.store.R import com.aurora.store.util.CertUtil @@ -31,7 +31,7 @@ import com.google.gson.annotations.SerializedName data class SelfUpdate( @SerializedName("version_name") var versionName: String = String(), - @SerializedName("version_code") var versionCode: Int = 0, + @SerializedName("version_code") var versionCode: Long = 0, @SerializedName("aurora_build") var auroraBuild: String = String(), @SerializedName("fdroid_build") var fdroidBuild: String = String(), @SerializedName("updated_on") var updatedOn: String = String(), @@ -63,7 +63,7 @@ data class SelfUpdate( developerName = "Rahul Kumar Patel", iconArtwork = Artwork(url = "$BASE_URL/$icon"), fileList = mutableListOf( - File( + PlayFile( name = "${context.packageName}.apk", url = downloadURL, size = selfUpdate.size diff --git a/app/src/main/java/com/aurora/store/data/model/SessionInfo.kt b/app/src/main/java/com/aurora/store/data/model/SessionInfo.kt index a09a15e88..e253db335 100644 --- a/app/src/main/java/com/aurora/store/data/model/SessionInfo.kt +++ b/app/src/main/java/com/aurora/store/data/model/SessionInfo.kt @@ -3,6 +3,6 @@ package com.aurora.store.data.model data class SessionInfo( val sessionId: Int, val packageName: String, - val versionCode: Int, + val versionCode: Long, val displayName: String = String() ) diff --git a/app/src/main/java/com/aurora/store/data/receiver/InstallerStatusReceiver.kt b/app/src/main/java/com/aurora/store/data/receiver/InstallerStatusReceiver.kt index f571ee33c..8e0c1ced1 100644 --- a/app/src/main/java/com/aurora/store/data/receiver/InstallerStatusReceiver.kt +++ b/app/src/main/java/com/aurora/store/data/receiver/InstallerStatusReceiver.kt @@ -52,7 +52,7 @@ class InstallerStatusReceiver : BroadcastReceiver() { if (context != null && intent?.action == ACTION_INSTALL_STATUS) { val packageName = intent.getStringExtra(EXTRA_PACKAGE_NAME)!! val displayName = intent.getStringExtra(EXTRA_DISPLAY_NAME)!! - val versionCode = intent.getIntExtra(EXTRA_VERSION_CODE, -1) + val versionCode = intent.getLongExtra(EXTRA_VERSION_CODE, -1) val status = intent.getIntExtra(PackageInstaller.EXTRA_STATUS, -1) val extra = intent.getStringExtra(PackageInstaller.EXTRA_STATUS_MESSAGE) diff --git a/app/src/main/java/com/aurora/store/data/room/download/Download.kt b/app/src/main/java/com/aurora/store/data/room/download/Download.kt index 4bf120518..dadfc6202 100644 --- a/app/src/main/java/com/aurora/store/data/room/download/Download.kt +++ b/app/src/main/java/com/aurora/store/data/room/download/Download.kt @@ -4,7 +4,7 @@ import android.os.Parcelable import androidx.room.Entity import androidx.room.PrimaryKey import com.aurora.gplayapi.data.models.App -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.room.update.Update import kotlinx.parcelize.Parcelize @@ -14,7 +14,7 @@ import java.util.Date @Entity(tableName = "download") data class Download( @PrimaryKey val packageName: String, - val versionCode: Int, + val versionCode: Long, val offerType: Int, val isInstalled: Boolean, val displayName: String, @@ -27,7 +27,7 @@ data class Download( var timeRemaining: Long, var totalFiles: Int, var downloadedFiles: Int, - var fileList: List, + var fileList: List, val sharedLibs: List, val targetSdk: Int = 1, val downloadedAt: Long = 0 diff --git a/app/src/main/java/com/aurora/store/data/room/download/DownloadConverter.kt b/app/src/main/java/com/aurora/store/data/room/download/DownloadConverter.kt index 65cc4d053..edc1699e6 100644 --- a/app/src/main/java/com/aurora/store/data/room/download/DownloadConverter.kt +++ b/app/src/main/java/com/aurora/store/data/room/download/DownloadConverter.kt @@ -2,7 +2,7 @@ package com.aurora.store.data.room.download import androidx.room.ProvidedTypeConverter import androidx.room.TypeConverter -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.google.gson.Gson import com.google.gson.reflect.TypeToken import javax.inject.Inject @@ -24,13 +24,13 @@ class DownloadConverter @Inject constructor(private val gson: Gson) { } @TypeConverter - fun toGPlayFileList(string: String): List { - val listType = object : TypeToken>() {}.type + fun toGPlayFileList(string: String): List { + val listType = object : TypeToken>() {}.type return gson.fromJson(string, listType) } @TypeConverter - fun fromGPlayFileList(list: List): String { + fun fromGPlayFileList(list: List): String { return gson.toJson(list) } } diff --git a/app/src/main/java/com/aurora/store/data/room/download/DownloadDao.kt b/app/src/main/java/com/aurora/store/data/room/download/DownloadDao.kt index de2b795d0..dc6eb8dc2 100644 --- a/app/src/main/java/com/aurora/store/data/room/download/DownloadDao.kt +++ b/app/src/main/java/com/aurora/store/data/room/download/DownloadDao.kt @@ -4,7 +4,7 @@ import androidx.room.Dao import androidx.room.Insert import androidx.room.OnConflictStrategy import androidx.room.Query -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.data.model.DownloadStatus import kotlinx.coroutines.flow.Flow @@ -18,7 +18,7 @@ interface DownloadDao { suspend fun updateStatus(packageName: String, downloadStatus: DownloadStatus) @Query("UPDATE download SET fileList=:fileList WHERE packageName=:packageName") - suspend fun updateFiles(packageName: String, fileList: List) + suspend fun updateFiles(packageName: String, fileList: List) @Query("UPDATE download SET sharedLibs=:sharedLibs WHERE packageName=:packageName") suspend fun updateSharedLibs(packageName: String, sharedLibs: List) diff --git a/app/src/main/java/com/aurora/store/data/room/download/SharedLib.kt b/app/src/main/java/com/aurora/store/data/room/download/SharedLib.kt index 89afc83b1..70ff63076 100644 --- a/app/src/main/java/com/aurora/store/data/room/download/SharedLib.kt +++ b/app/src/main/java/com/aurora/store/data/room/download/SharedLib.kt @@ -2,14 +2,14 @@ package com.aurora.store.data.room.download import android.os.Parcelable import com.aurora.gplayapi.data.models.App -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import kotlinx.parcelize.Parcelize @Parcelize data class SharedLib( val packageName: String, - val versionCode: Int, - var fileList: List + val versionCode: Long, + var fileList: List ) : Parcelable { companion object { fun fromApp(app: App): SharedLib { diff --git a/app/src/main/java/com/aurora/store/data/room/update/Update.kt b/app/src/main/java/com/aurora/store/data/room/update/Update.kt index d18b89565..1dfb216e0 100644 --- a/app/src/main/java/com/aurora/store/data/room/update/Update.kt +++ b/app/src/main/java/com/aurora/store/data/room/update/Update.kt @@ -5,7 +5,7 @@ import android.os.Parcelable import androidx.room.Entity import androidx.room.PrimaryKey import com.aurora.gplayapi.data.models.App -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.data.room.download.SharedLib import com.aurora.store.util.CertUtil import com.aurora.store.util.PackageUtil @@ -16,7 +16,7 @@ import kotlinx.parcelize.Parcelize data class Update( @PrimaryKey val packageName: String, - val versionCode: Int, + val versionCode: Long, val versionName: String, val displayName: String, val iconURL: String, @@ -27,7 +27,7 @@ data class Update( val updatedOn: String, val hasValidCert: Boolean, val offerType: Int, - var fileList: List, + var fileList: List, val sharedLibs: List, val targetSdk: Int = 1 ) : Parcelable { diff --git a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt index e09e41762..082a0ae81 100644 --- a/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt +++ b/app/src/main/java/com/aurora/store/data/work/DownloadWorker.kt @@ -24,6 +24,7 @@ import com.aurora.extensions.isPAndAbove import com.aurora.extensions.isQAndAbove import com.aurora.extensions.isSAndAbove import com.aurora.extensions.requiresObbDir +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.gplayapi.helpers.PurchaseHelper import com.aurora.gplayapi.network.IHttpClient import com.aurora.store.AuroraApp @@ -55,7 +56,6 @@ import java.security.DigestInputStream import java.security.MessageDigest import kotlin.coroutines.cancellation.CancellationException import kotlin.properties.Delegates -import com.aurora.gplayapi.data.models.File as GPlayFile /** * An expedited long-running worker to download and trigger installation for given apps. @@ -127,7 +127,7 @@ class DownloadWorker @AssistedInject constructor( PathUtil.getObbDownloadDir(download.packageName).mkdirs() } - val files = mutableListOf() + val files = mutableListOf() // Check if shared libs are present, if yes, handle them first if (download.sharedLibs.isNotEmpty()) { @@ -245,7 +245,7 @@ class DownloadWorker @AssistedInject constructor( * @param offerType Offer type of the app (free/paid) * @return A list of purchased files */ - private fun purchase(packageName: String, versionCode: Int, offerType: Int): List { + private fun purchase(packageName: String, versionCode: Long, offerType: Int): List { try { // Android 9.0+ supports key rotation, so purchase with latest certificate's hash return if (isPAndAbove && download.isInstalled) { @@ -267,10 +267,10 @@ class DownloadWorker @AssistedInject constructor( /** * Downloads the file from the given request. * Failed downloads aren't removed and persists as long as [CacheWorker] doesn't cleans them. - * @param gFile A [GPlayFile] to download + * @param gFile A [PlayFile] to download * @return A [Boolean] indicating whether the file was downloaded or not. */ - private suspend fun downloadFile(packageName: String, gFile: GPlayFile): Boolean { + private suspend fun downloadFile(packageName: String, gFile: PlayFile): Boolean { return withContext(Dispatchers.IO) { Log.i(TAG, "Downloading $packageName @ ${gFile.name}") val file = PathUtil.getLocalFile(context, gFile, download) @@ -414,11 +414,11 @@ class DownloadWorker @AssistedInject constructor( } /** - * Verifies integrity of a downloaded [GPlayFile]. - * @param gFile [GPlayFile] to verify + * Verifies integrity of a downloaded [PlayFile]. + * @param gFile [PlayFile] to verify */ @OptIn(ExperimentalStdlibApi::class) - private suspend fun verifyFile(gFile: GPlayFile): Boolean { + private suspend fun verifyFile(gFile: PlayFile): Boolean { val file = PathUtil.getLocalFile(context, gFile, download) Log.i(TAG, "Verifying $file") @@ -446,7 +446,7 @@ class DownloadWorker @AssistedInject constructor( } } - private fun deleteFile(file: GPlayFile) { + private fun deleteFile(file: PlayFile) { val apkFile = PathUtil.getLocalFile(context, file, download) if (apkFile.exists()) { apkFile.delete() diff --git a/app/src/main/java/com/aurora/store/data/work/ExportWorker.kt b/app/src/main/java/com/aurora/store/data/work/ExportWorker.kt index caf8cb9f1..aa5023be5 100644 --- a/app/src/main/java/com/aurora/store/data/work/ExportWorker.kt +++ b/app/src/main/java/com/aurora/store/data/work/ExportWorker.kt @@ -77,7 +77,7 @@ class ExportWorker @AssistedInject constructor( .putString(URI, uri.toString()) .putString(DISPLAY_NAME, download.displayName) .putString(PACKAGE_NAME, download.packageName) - .putInt(VERSION_CODE, download.versionCode) + .putLong(VERSION_CODE, download.versionCode) .build() val oneTimeWorkRequest = OneTimeWorkRequestBuilder() @@ -99,11 +99,11 @@ class ExportWorker @AssistedInject constructor( val uri = inputData.getString(URI)!!.toUri() val packageName = inputData.getString(PACKAGE_NAME) val displayName = inputData.getString(DISPLAY_NAME) - val versionCode = inputData.getInt(VERSION_CODE, -1) + val versionCode = inputData.getLong(VERSION_CODE, -1) notificationManager = context.getSystemService()!! - if (packageName.isNullOrEmpty() || isDownload && versionCode == -1) { + if (packageName.isNullOrEmpty() || isDownload && versionCode == -1L) { Log.e(TAG, "Input data is corrupt, bailing out!") notifyStatus(displayName ?: String(), uri, false) return Result.failure() @@ -156,7 +156,7 @@ class ExportWorker @AssistedInject constructor( bundleAllAPKs(fileList.filterNotNull(), uri) } - private fun copyDownloadedApp(packageName: String, versionCode: Int, uri: Uri) { + private fun copyDownloadedApp(packageName: String, versionCode: Long, uri: Uri) { return bundleAllAPKs( PathUtil.getAppDownloadDir(context, packageName, versionCode).listFiles()!!.toList(), uri diff --git a/app/src/main/java/com/aurora/store/util/PackageUtil.kt b/app/src/main/java/com/aurora/store/util/PackageUtil.kt index 800159d29..0f9cab3a0 100644 --- a/app/src/main/java/com/aurora/store/util/PackageUtil.kt +++ b/app/src/main/java/com/aurora/store/util/PackageUtil.kt @@ -51,8 +51,8 @@ object PackageUtil { private const val TAG = "PackageUtil" const val PACKAGE_NAME_GMS = "com.google.android.gms" - private const val VERSION_CODE_MICRO_G = 240913402 - private const val VERSION_CODE_MICRO_G_HUAWEI = 240913007 + private const val VERSION_CODE_MICRO_G: Long = 240913402 + private const val VERSION_CODE_MICRO_G_HUAWEI: Long = 240913007 fun getAllValidPackages(context: Context): List { return context.packageManager.getInstalledPackages(PackageManager.GET_META_DATA) @@ -85,7 +85,7 @@ object PackageUtil { } } - fun isInstalled(context: Context, packageName: String, versionCode: Int): Boolean { + fun isInstalled(context: Context, packageName: String, versionCode: Long): Boolean { return try { val packageInfo = getPackageInfo(context, packageName) return PackageInfoCompat.getLongVersionCode(packageInfo) >= versionCode.toLong() @@ -110,17 +110,17 @@ object PackageUtil { } } - fun isSharedLibraryInstalled(context: Context, packageName: String, versionCode: Int): Boolean { + fun isSharedLibraryInstalled(context: Context, packageName: String, versionCode: Long): Boolean { return if (isOAndAbove) { val sharedLibraries = getAllSharedLibraries(context) if (isPAndAbove) { sharedLibraries.any { - it.name == packageName && it.longVersion == versionCode.toLong() + it.name == packageName && it.longVersion == versionCode } } else { sharedLibraries.any { @Suppress("DEPRECATION") - it.name == packageName && it.version == versionCode + it.name == packageName && it.version == versionCode.toInt() } } } else { diff --git a/app/src/main/java/com/aurora/store/util/PathUtil.kt b/app/src/main/java/com/aurora/store/util/PathUtil.kt index 1687150f9..6fd369e6f 100644 --- a/app/src/main/java/com/aurora/store/util/PathUtil.kt +++ b/app/src/main/java/com/aurora/store/util/PathUtil.kt @@ -21,10 +21,10 @@ package com.aurora.store.util import android.content.Context import android.os.Environment +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.data.room.download.Download import java.io.File import java.util.UUID -import com.aurora.gplayapi.data.models.File as GPlayFile object PathUtil { @@ -47,14 +47,14 @@ object PathUtil { return File(getDownloadDirectory(context), packageName) } - fun getAppDownloadDir(context: Context, packageName: String, versionCode: Int): File { + fun getAppDownloadDir(context: Context, packageName: String, versionCode: Long): File { return File(getPackageDirectory(context, packageName), versionCode.toString()) } fun getLibDownloadDir( context: Context, packageName: String, - versionCode: Int, + versionCode: Long, sharedLibPackageName: String ): File { return File( @@ -64,15 +64,15 @@ object PathUtil { } /** - * Returns an instance of java's [File] class for the given [GPlayFile] + * Returns an instance of java's [File] class for the given [PlayFile] * @param context [Context] - * @param gFile [GPlayFile] to download + * @param playFile [PlayFile] to download * @param download An instance of [Download] */ - fun getLocalFile(context: Context, gFile: GPlayFile, download: Download): File { - val sharedLib = download.sharedLibs.find { it.fileList.contains(gFile) } - return when (gFile.type) { - GPlayFile.FileType.BASE, GPlayFile.FileType.SPLIT -> { + fun getLocalFile(context: Context, playFile: PlayFile, download: Download): File { + val sharedLib = download.sharedLibs.find { it.fileList.contains(playFile) } + return when (playFile.type) { + PlayFile.Type.BASE, PlayFile.Type.SPLIT -> { val downloadDir = if (sharedLib != null) { getLibDownloadDir( context, @@ -83,16 +83,16 @@ object PathUtil { } else { getAppDownloadDir(context, download.packageName, download.versionCode) } - return File(downloadDir, gFile.name) + return File(downloadDir, playFile.name) } - GPlayFile.FileType.OBB, GPlayFile.FileType.PATCH -> { - File(getObbDownloadDir(download.packageName), gFile.name) + PlayFile.Type.OBB, PlayFile.Type.PATCH -> { + File(getObbDownloadDir(download.packageName), playFile.name) } } } - fun getZipFile(context: Context, packageName: String, versionCode: Int): File { + fun getZipFile(context: Context, packageName: String, versionCode: Long): File { return File( getAppDownloadDir( context, diff --git a/app/src/main/java/com/aurora/store/view/epoxy/views/details/FileView.kt b/app/src/main/java/com/aurora/store/view/epoxy/views/details/FileView.kt index 5b23f8686..4ad237176 100644 --- a/app/src/main/java/com/aurora/store/view/epoxy/views/details/FileView.kt +++ b/app/src/main/java/com/aurora/store/view/epoxy/views/details/FileView.kt @@ -23,7 +23,7 @@ import android.content.Context import android.util.AttributeSet import com.airbnb.epoxy.ModelProp import com.airbnb.epoxy.ModelView -import com.aurora.gplayapi.data.models.File +import com.aurora.gplayapi.data.models.PlayFile import com.aurora.store.databinding.ViewFileBinding import com.aurora.store.util.CommonUtil import com.aurora.store.view.epoxy.views.BaseModel @@ -40,7 +40,7 @@ class FileView @JvmOverloads constructor( ) : BaseView(context, attrs, defStyleAttr) { @ModelProp - fun file(file: File) { + fun file(file: PlayFile) { binding.line1.text = file.name binding.line2.text = CommonUtil.addSiPrefix(file.size) } diff --git a/app/src/main/java/com/aurora/store/view/ui/commons/CategoryBrowseFragment.kt b/app/src/main/java/com/aurora/store/view/ui/commons/CategoryBrowseFragment.kt index 7fc2cb8e4..5b88e5c59 100644 --- a/app/src/main/java/com/aurora/store/view/ui/commons/CategoryBrowseFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/commons/CategoryBrowseFragment.kt @@ -27,8 +27,6 @@ import androidx.navigation.fragment.navArgs import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.StreamBundle import com.aurora.gplayapi.data.models.StreamCluster -import com.aurora.gplayapi.helpers.contracts.StreamContract -import com.aurora.gplayapi.utils.CategoryUtil import com.aurora.store.data.model.ViewState import com.aurora.store.data.model.ViewState.Loading.getDataAs import com.aurora.store.databinding.FragmentGenericWithToolbarBinding @@ -44,14 +42,11 @@ class CategoryBrowseFragment : BaseFragment() private val args: CategoryBrowseFragmentArgs by navArgs() private val viewModel: CategoryStreamViewModel by activityViewModels() - private lateinit var category: StreamContract.Category private var streamBundle: StreamBundle? = StreamBundle() override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - category = CategoryUtil.getCategoryFromUrl(args.browseUrl) - val genericCarouselController = CategoryCarouselController(this) // Toolbar @@ -64,11 +59,11 @@ class CategoryBrowseFragment : BaseFragment() binding.recycler.setController(genericCarouselController) binding.recycler.addOnScrollListener(object : EndlessRecyclerOnScrollListener() { override fun onLoadMore(currentPage: Int) { - viewModel.observe(category) + viewModel.observe(args.browseUrl) } }) - viewModel.getStreamBundle(category) + viewModel.getStreamBundle(args.browseUrl) viewModel.liveData.observe(viewLifecycleOwner) { when (it) { is ViewState.Loading -> { @@ -77,7 +72,7 @@ class CategoryBrowseFragment : BaseFragment() is ViewState.Success<*> -> { val stash = it.getDataAs>() - streamBundle = stash[category.value] + streamBundle = stash[args.browseUrl] genericCarouselController.setData(streamBundle) } @@ -92,7 +87,7 @@ class CategoryBrowseFragment : BaseFragment() } override fun onClusterScrolled(streamCluster: StreamCluster) { - viewModel.observeCluster(category, streamCluster) + viewModel.observeCluster(args.browseUrl, streamCluster) } override fun onAppClick(app: App) { diff --git a/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt b/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt index b0782e684..9bccd2c5a 100644 --- a/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt +++ b/app/src/main/java/com/aurora/store/view/ui/details/AppDetailsFragment.kt @@ -136,8 +136,8 @@ class AppDetailsFragment : BaseFragment() { val requestedApp = app.copy( versionCode = event.versionCode, dependencies = app.dependencies.copy( - dependentLibraries = app.dependencies.dependentLibraries.onEach { lib -> - lib.versionCode = event.versionCode + dependentLibraries = app.dependencies.dependentLibraries.map { lib -> + lib.copy(versionCode = event.versionCode) } ) ) @@ -173,11 +173,10 @@ class AppDetailsFragment : BaseFragment() { override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - app = args.app ?: App(args.packageName) - app.apply { - // Check whether app is installed or not + app = args.app ?: App( + packageName = args.packageName, isInstalled = PackageUtil.isInstalled(requireContext(), app.packageName) - } + ) // Show the basic app details, while the rest of the data is being fetched updateAppHeader(app, false) @@ -204,7 +203,7 @@ class AppDetailsFragment : BaseFragment() { updateExtraDetails(app) updateCompatibilityInfo() - if (app.versionCode == 0) { + if (app.versionCode == 0L) { warnAppUnavailable(app) } @@ -607,7 +606,7 @@ class AppDetailsFragment : BaseFragment() { } private fun checkAndSetupInstall() { - app.isInstalled = PackageUtil.isInstalled(requireContext(), app.packageName) + app = app.copy(isInstalled = PackageUtil.isInstalled(requireContext(), app.packageName)) // Setup primary and secondary action buttons binding.layoutDetailsApp.btnPrimaryAction.isEnabled = true @@ -634,7 +633,7 @@ class AppDetailsFragment : BaseFragment() { binding.layoutDetailsApp.btnPrimaryAction.apply { text = getString(R.string.action_update) setOnClickListener { - if (app.versionCode == 0) { + if (app.versionCode == 0L) { toast(R.string.toast_app_unavailable) setText(R.string.status_unavailable) } else { @@ -692,7 +691,7 @@ class AppDetailsFragment : BaseFragment() { if (viewModel.authProvider.isAnonymous && !app.isFree) { toast(R.string.toast_purchase_blocked) return@setOnClickListener - } else if (app.versionCode == 0) { + } else if (app.versionCode == 0L) { toast(R.string.toast_app_unavailable) return@setOnClickListener } diff --git a/app/src/main/java/com/aurora/store/view/ui/sheets/ManualDownloadSheet.kt b/app/src/main/java/com/aurora/store/view/ui/sheets/ManualDownloadSheet.kt index 5ee223dd6..2ba21f3be 100644 --- a/app/src/main/java/com/aurora/store/view/ui/sheets/ManualDownloadSheet.kt +++ b/app/src/main/java/com/aurora/store/view/ui/sheets/ManualDownloadSheet.kt @@ -95,7 +95,7 @@ class ManualDownloadSheet : BaseDialogSheet() { if (customVersionString.isEmpty()) binding.versionCodeInp.error = "Enter version code" else { - viewModel.purchase(args.app, customVersionString.toInt()) + viewModel.purchase(args.app, customVersionString.toLong()) } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/browse/ExpandedStreamBrowseViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/browse/ExpandedStreamBrowseViewModel.kt index 2df8f3cd0..f974fe503 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/browse/ExpandedStreamBrowseViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/browse/ExpandedStreamBrowseViewModel.kt @@ -67,10 +67,10 @@ class ExpandedStreamBrowseViewModel @Inject constructor( streamCluster.clusterNextPageUrl ) - streamCluster.apply { - clusterAppList.addAll(newCluster.clusterAppList) + streamCluster = streamCluster.copy( + clusterAppList = streamCluster.clusterAppList + newCluster.clusterAppList, clusterNextPageUrl = newCluster.clusterNextPageUrl - } + ) liveData.postValue(streamCluster) diff --git a/app/src/main/java/com/aurora/store/viewmodel/browse/StreamBrowseViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/browse/StreamBrowseViewModel.kt index 6c5cc97c5..2915d638a 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/browse/StreamBrowseViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/browse/StreamBrowseViewModel.kt @@ -56,10 +56,10 @@ class StreamBrowseViewModel @Inject constructor( streamCluster.clusterNextPageUrl ) - streamCluster.apply { - clusterAppList.addAll(nextCluster.clusterAppList) - clusterNextPageUrl = nextCluster.clusterNextPageUrl - } + streamCluster = streamCluster.copy( + clusterNextPageUrl = nextCluster.clusterNextPageUrl, + clusterAppList = streamCluster.clusterAppList + nextCluster.clusterAppList + ) liveData.postValue(streamCluster) } else { diff --git a/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt index 09f4f5718..84bd99405 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/details/AppDetailsViewModel.kt @@ -96,9 +96,9 @@ class AppDetailsViewModel @Inject constructor( checkFavourite(packageName) val app: App = appStash.getOrPut(packageName) { - appDetailsHelper.getAppByPackageName(packageName).apply { + appDetailsHelper.getAppByPackageName(packageName).copy( isInstalled = PackageUtil.isInstalled(context, packageName) - } + ) } _app.emit(app) diff --git a/app/src/main/java/com/aurora/store/viewmodel/details/DetailsClusterViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/details/DetailsClusterViewModel.kt index f9d65505c..a069e1aab 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/details/DetailsClusterViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/details/DetailsClusterViewModel.kt @@ -62,10 +62,11 @@ class DetailsClusterViewModel @Inject constructor( if (!bundle.hasCluster() || bundle.hasNext()) { val newBundle = appDetailsHelper.getDetailsStream(streamUrl) - bundle.apply { - streamClusters.putAll(newBundle.streamClusters) + val mergedBundle = bundle.copy( + streamClusters = bundle.streamClusters + newBundle.streamClusters, streamNextPageUrl = newBundle.streamNextPageUrl - } + ) + stash[streamUrl] = mergedBundle liveData.postValue(ViewState.Success(stash)) } @@ -87,7 +88,6 @@ class DetailsClusterViewModel @Inject constructor( liveData.postValue(ViewState.Success(stash)) } else { Log.i(TAG, "End of cluster") - streamCluster.clusterNextPageUrl = String() } } catch (e: Exception) { liveData.postValue(ViewState.Error(e.message)) @@ -101,9 +101,18 @@ class DetailsClusterViewModel @Inject constructor( clusterID: Int, newCluster: StreamCluster ) { - targetBundle(url).streamClusters[clusterID]?.apply { - clusterAppList.addAll(newCluster.clusterAppList) - clusterNextPageUrl = newCluster.clusterNextPageUrl + val bundle = targetBundle(url) + bundle.streamClusters[clusterID]?.let { oldCluster -> + val mergedCluster = oldCluster.copy( + clusterNextPageUrl = newCluster.clusterNextPageUrl, + clusterAppList = oldCluster.clusterAppList + newCluster.clusterAppList + ) + val newStreamClusters = bundle.streamClusters.toMutableMap().also { + it.remove(clusterID) + it[clusterID] = mergedCluster + } + + stash.put(url, bundle.copy(streamClusters = newStreamClusters)) } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/details/DevProfileViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/details/DevProfileViewModel.kt index 77bf00469..28da92cea 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/details/DevProfileViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/details/DevProfileViewModel.kt @@ -76,7 +76,6 @@ class DevProfileViewModel @Inject constructor( liveData.postValue(ViewState.Success(devStream)) } else { Log.i(TAG, "End of cluster") - streamCluster.clusterNextPageUrl = String() } } catch (e: Exception) { liveData.postValue(ViewState.Error(e.message)) @@ -86,9 +85,17 @@ class DevProfileViewModel @Inject constructor( } private fun updateCluster(newCluster: StreamCluster) { - streamBundle.streamClusters[newCluster.id]?.apply { - clusterAppList.addAll(newCluster.clusterAppList) - clusterNextPageUrl = newCluster.clusterNextPageUrl + streamBundle.streamClusters[newCluster.id]?.let { oldCluster -> + val mergedCluster = oldCluster.copy( + clusterNextPageUrl = newCluster.clusterNextPageUrl, + clusterAppList = oldCluster.clusterAppList + newCluster.clusterAppList + ) + val newStreamClusters = streamBundle.streamClusters.toMutableMap().also { + it.remove(newCluster.id) + it[newCluster.id] = mergedCluster + } + + streamBundle = streamBundle.copy(streamClusters = newStreamClusters) } } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/homestream/StreamViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/homestream/StreamViewModel.kt index 4ee641da3..4e28d0676 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/homestream/StreamViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/homestream/StreamViewModel.kt @@ -76,10 +76,11 @@ class StreamViewModel @Inject constructor( } //Update old bundle - bundle.apply { - streamClusters.putAll(newBundle.streamClusters) + val mergedBundle = bundle.copy( + streamClusters = bundle.streamClusters + newBundle.streamClusters, streamNextPageUrl = newBundle.streamNextPageUrl - } + ) + stash[category] = mergedBundle //Post updated to UI liveData.postValue(ViewState.Success(stash)) @@ -98,13 +99,13 @@ class StreamViewModel @Inject constructor( supervisorScope { try { if (streamCluster.hasNext()) { - val newCluster = - streamContract.nextStreamCluster(streamCluster.clusterNextPageUrl) + val newCluster = streamContract.nextStreamCluster( + streamCluster.clusterNextPageUrl + ) updateCluster(category, streamCluster.id, newCluster) liveData.postValue(ViewState.Success(stash)) } else { Log.i(TAG, "End of cluster") - streamCluster.clusterNextPageUrl = String() } } catch (e: Exception) { liveData.postValue(ViewState.Error(e.message)) @@ -118,9 +119,18 @@ class StreamViewModel @Inject constructor( clusterID: Int, newCluster: StreamCluster ) { - targetBundle(category).streamClusters[clusterID]?.apply { - clusterAppList.addAll(newCluster.clusterAppList) - clusterNextPageUrl = newCluster.clusterNextPageUrl + val bundle = targetBundle(category) + bundle.streamClusters[clusterID]?.let { oldCluster -> + val mergedCluster = oldCluster.copy( + clusterNextPageUrl = newCluster.clusterNextPageUrl, + clusterAppList = oldCluster.clusterAppList + newCluster.clusterAppList + ) + val newStreamClusters = bundle.streamClusters.toMutableMap().also { + it.remove(clusterID) + it[clusterID] = mergedCluster + } + + stash.put(category, bundle.copy(streamClusters = newStreamClusters)) } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/review/ReviewViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/review/ReviewViewModel.kt index 12fc58b30..9cc4a7d5c 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/review/ReviewViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/review/ReviewViewModel.kt @@ -57,11 +57,10 @@ class ReviewViewModel @Inject constructor( supervisorScope { try { val nextReviewCluster = reviewsHelper.next(nextReviewPageUrl) - reviewsCluster.copy( - nextPageUrl = nextReviewCluster.nextPageUrl - ).apply { - reviewList.addAll(nextReviewCluster.reviewList) - } + reviewsCluster = reviewsCluster.copy( + nextPageUrl = nextReviewCluster.nextPageUrl, + reviewList = nextReviewCluster.reviewList + nextReviewCluster.reviewList + ) liveData.postValue(reviewsCluster) } catch (_: Exception) { diff --git a/app/src/main/java/com/aurora/store/viewmodel/search/SearchResultViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/search/SearchResultViewModel.kt index 3eaf3e08f..ae2ef978f 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/search/SearchResultViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/search/SearchResultViewModel.kt @@ -23,7 +23,6 @@ import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import com.aurora.extensions.flushAndAdd import com.aurora.gplayapi.data.models.SearchBundle import com.aurora.gplayapi.helpers.SearchHelper import com.aurora.gplayapi.helpers.contracts.SearchContract @@ -54,10 +53,6 @@ class SearchResultViewModel @Inject constructor( get() = if (authProvider.isAnonymous) webSearchHelper else searchHelper fun observeSearchResults(query: String) { - //Clear old results - searchBundle.subBundles.clear() - searchBundle.appList.clear() - //Fetch new results viewModelScope.launch(Dispatchers.IO) { supervisorScope { try { @@ -75,17 +70,17 @@ class SearchResultViewModel @Inject constructor( } @Synchronized - fun next(nextSubBundleSet: MutableSet) { + fun next(nextSubBundleSet: Set) { viewModelScope.launch(Dispatchers.IO) { supervisorScope { try { if (nextSubBundleSet.isNotEmpty()) { - val newSearchBundle = helper.next(nextSubBundleSet) + val newSearchBundle = helper.next(nextSubBundleSet.toMutableSet()) if (newSearchBundle.appList.isNotEmpty()) { - searchBundle.apply { - subBundles.flushAndAdd(newSearchBundle.subBundles) - appList.addAll(newSearchBundle.appList) - } + searchBundle = searchBundle.copy( + subBundles = newSearchBundle.subBundles, + appList = searchBundle.appList + newSearchBundle.appList + ) liveData.postValue(searchBundle) } diff --git a/app/src/main/java/com/aurora/store/viewmodel/sheets/ManualDownloadViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/sheets/ManualDownloadViewModel.kt index ba66e6be2..d7fb25fec 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/sheets/ManualDownloadViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/sheets/ManualDownloadViewModel.kt @@ -24,7 +24,7 @@ class ManualDownloadViewModel @Inject constructor( private val _purchaseStatus = MutableSharedFlow() val purchaseStatus = _purchaseStatus.asSharedFlow() - fun purchase(app: App, customVersion: Int) { + fun purchase(app: App, customVersion: Long) { viewModelScope.launch(Dispatchers.IO) { try { val files = purchaseHelper.purchase(app.packageName, customVersion, app.offerType) diff --git a/app/src/main/java/com/aurora/store/viewmodel/subcategory/CategoryStreamViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/subcategory/CategoryStreamViewModel.kt index a51c54727..cc1af5ca9 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/subcategory/CategoryStreamViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/subcategory/CategoryStreamViewModel.kt @@ -49,38 +49,38 @@ class CategoryStreamViewModel @Inject constructor( private val categoryStreamContract: CategoryStreamContract get() = webCategoryStreamHelper - fun getStreamBundle(category: StreamContract.Category) { + fun getStreamBundle(browseUrl: String) { liveData.postValue(ViewState.Loading) - observe(category) + observe(browseUrl) } - fun observe(category: StreamContract.Category) { + fun observe(browseUrl: String) { liveData.postValue(ViewState.Loading) viewModelScope.launch(Dispatchers.IO) { supervisorScope { - val bundle = targetBundle(category) + val bundle = targetBundle(browseUrl) if (bundle.streamClusters.isNotEmpty()) { liveData.postValue(ViewState.Success(stash)) } try { if (!bundle.hasCluster() || bundle.hasNext()) { - //Fetch new stream bundle val newBundle = if (bundle.streamClusters.isEmpty()) { - categoryStreamContract.fetch(category.value) + categoryStreamContract.fetch(browseUrl) } else { categoryStreamContract.nextStreamBundle( - category, + StreamContract.Category.NONE, bundle.streamNextPageUrl ) } //Update old bundle - bundle.apply { - streamClusters.putAll(newBundle.streamClusters) + val mergedBundle = bundle.copy( + streamClusters = bundle.streamClusters + newBundle.streamClusters, streamNextPageUrl = newBundle.streamNextPageUrl - } + ) + stash[browseUrl] = mergedBundle //Post updated to UI liveData.postValue(ViewState.Success(stash)) @@ -94,18 +94,18 @@ class CategoryStreamViewModel @Inject constructor( } } - fun observeCluster(category: StreamContract.Category, streamCluster: StreamCluster) { + fun observeCluster(browseUrl: String, streamCluster: StreamCluster) { viewModelScope.launch(Dispatchers.IO) { supervisorScope { try { if (streamCluster.hasNext()) { - val newCluster = - categoryStreamContract.nextStreamCluster(streamCluster.clusterNextPageUrl) - updateCluster(category, streamCluster.id, newCluster) + val newCluster = categoryStreamContract.nextStreamCluster( + streamCluster.clusterNextPageUrl + ) + updateCluster(browseUrl, streamCluster.id, newCluster) liveData.postValue(ViewState.Success(stash)) } else { Log.i(TAG, "End of cluster") - streamCluster.clusterNextPageUrl = String() } } catch (e: Exception) { liveData.postValue(ViewState.Error(e.message)) @@ -114,22 +114,24 @@ class CategoryStreamViewModel @Inject constructor( } } - private fun updateCluster( - category: StreamContract.Category, - clusterID: Int, - newCluster: StreamCluster - ) { - targetBundle(category).streamClusters[clusterID]?.apply { - clusterAppList.addAll(newCluster.clusterAppList) - clusterNextPageUrl = newCluster.clusterNextPageUrl + private fun updateCluster(browseUrl: String, clusterID: Int, newCluster: StreamCluster) { + val bundle = targetBundle(browseUrl) + bundle.streamClusters[clusterID]?.let { oldCluster -> + val mergedCluster = oldCluster.copy( + clusterNextPageUrl = newCluster.clusterNextPageUrl, + clusterAppList = oldCluster.clusterAppList + newCluster.clusterAppList + ) + val newStreamClusters = bundle.streamClusters.toMutableMap().also { + it.remove(clusterID) + it[clusterID] = mergedCluster + } + + stash.put(browseUrl, bundle.copy(streamClusters = newStreamClusters)) } } - private fun targetBundle(category: StreamContract.Category): StreamBundle { - val streamBundle = stash.getOrPut(category.value) { - StreamBundle() - } - + private fun targetBundle(browseUrl: String): StreamBundle { + val streamBundle = stash.getOrPut(browseUrl) { StreamBundle() } return streamBundle } } diff --git a/app/src/main/java/com/aurora/store/viewmodel/topchart/TopChartViewModel.kt b/app/src/main/java/com/aurora/store/viewmodel/topchart/TopChartViewModel.kt index 37a1999fb..4fc52da0d 100644 --- a/app/src/main/java/com/aurora/store/viewmodel/topchart/TopChartViewModel.kt +++ b/app/src/main/java/com/aurora/store/viewmodel/topchart/TopChartViewModel.kt @@ -85,10 +85,13 @@ class TopChartViewModel @Inject constructor( chart: TopChartsContract.Chart, newCluster: StreamCluster ) { - targetCluster(type, chart).apply { - clusterAppList.addAll(newCluster.clusterAppList) - clusterNextPageUrl = newCluster.clusterNextPageUrl - } + val streamCluster = targetCluster(type, chart) + val mergedCluster = streamCluster.copy( + clusterNextPageUrl = newCluster.clusterNextPageUrl, + clusterAppList = streamCluster.clusterAppList + newCluster.clusterAppList + ) + + stash[type] = mutableMapOf(chart to mergedCluster) } private fun targetCluster( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 402a9754c..c42b5af48 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -9,7 +9,7 @@ composeBom = "2025.05.00" core = "1.16.0" epoxy = "5.1.4" espresso = "3.6.1" -gplayapi = "3.4.6" +gplayapi = "3.5.0" gson = "2.13.1" hiddenapibypass = "6.1" hilt = "2.56.2"