libs: Bump gplyapi to 3.5.0
* Map versionCode as Long * Handle all cases of immutable object modification Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -19,18 +19,8 @@
|
||||
|
||||
package com.aurora.extensions
|
||||
|
||||
import com.aurora.gplayapi.data.models.File
|
||||
import com.aurora.gplayapi.data.models.PlayFile
|
||||
|
||||
fun <T> MutableList<T>.flushAndAdd(list: List<T>) {
|
||||
clear()
|
||||
addAll(list)
|
||||
}
|
||||
|
||||
fun <T> MutableSet<T>.flushAndAdd(list: Set<T>) {
|
||||
clear()
|
||||
addAll(list)
|
||||
}
|
||||
|
||||
fun List<File>.requiresObbDir(): Boolean {
|
||||
return this.any { it.type == File.FileType.OBB || it.type == File.FileType.PATCH }
|
||||
fun List<PlayFile>.requiresObbDir(): Boolean {
|
||||
return this.any { it.type == PlayFile.Type.OBB }
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -129,7 +129,7 @@ class ShizukuInstaller @Inject constructor(
|
||||
|
||||
private fun install(
|
||||
packageName: String,
|
||||
versionCode: Int,
|
||||
versionCode: Long,
|
||||
sharedLibPkgName: String = "",
|
||||
displayName: String = ""
|
||||
) {
|
||||
|
||||
@@ -103,7 +103,7 @@ abstract class InstallerBase(private val context: Context) : IInstaller {
|
||||
|
||||
fun getFiles(
|
||||
packageName: String,
|
||||
versionCode: Int,
|
||||
versionCode: Long,
|
||||
sharedLibPackageName: String = ""
|
||||
): List<File> {
|
||||
val downloadDir = if (sharedLibPackageName.isNotBlank()) {
|
||||
|
||||
@@ -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)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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<File>,
|
||||
var fileList: List<PlayFile>,
|
||||
val sharedLibs: List<SharedLib>,
|
||||
val targetSdk: Int = 1,
|
||||
val downloadedAt: Long = 0
|
||||
|
||||
@@ -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<File> {
|
||||
val listType = object : TypeToken<List<File>>() {}.type
|
||||
fun toGPlayFileList(string: String): List<PlayFile> {
|
||||
val listType = object : TypeToken<List<PlayFile>>() {}.type
|
||||
return gson.fromJson(string, listType)
|
||||
}
|
||||
|
||||
@TypeConverter
|
||||
fun fromGPlayFileList(list: List<File>): String {
|
||||
fun fromGPlayFileList(list: List<PlayFile>): String {
|
||||
return gson.toJson(list)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<File>)
|
||||
suspend fun updateFiles(packageName: String, fileList: List<PlayFile>)
|
||||
|
||||
@Query("UPDATE download SET sharedLibs=:sharedLibs WHERE packageName=:packageName")
|
||||
suspend fun updateSharedLibs(packageName: String, sharedLibs: List<SharedLib>)
|
||||
|
||||
@@ -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<File>
|
||||
val versionCode: Long,
|
||||
var fileList: List<PlayFile>
|
||||
) : Parcelable {
|
||||
companion object {
|
||||
fun fromApp(app: App): SharedLib {
|
||||
|
||||
@@ -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<File>,
|
||||
var fileList: List<PlayFile>,
|
||||
val sharedLibs: List<SharedLib>,
|
||||
val targetSdk: Int = 1
|
||||
) : Parcelable {
|
||||
|
||||
@@ -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<GPlayFile>()
|
||||
val files = mutableListOf<PlayFile>()
|
||||
|
||||
// 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<GPlayFile> {
|
||||
private fun purchase(packageName: String, versionCode: Long, offerType: Int): List<PlayFile> {
|
||||
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()
|
||||
|
||||
@@ -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<ExportWorker>()
|
||||
@@ -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<NotificationManager>()!!
|
||||
|
||||
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
|
||||
|
||||
@@ -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<PackageInfo> {
|
||||
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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<ViewFileBinding>(context, attrs, defStyleAttr) {
|
||||
|
||||
@ModelProp
|
||||
fun file(file: File) {
|
||||
fun file(file: PlayFile) {
|
||||
binding.line1.text = file.name
|
||||
binding.line2.text = CommonUtil.addSiPrefix(file.size)
|
||||
}
|
||||
|
||||
@@ -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<FragmentGenericWithToolbarBinding>()
|
||||
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<FragmentGenericWithToolbarBinding>()
|
||||
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<FragmentGenericWithToolbarBinding>()
|
||||
|
||||
is ViewState.Success<*> -> {
|
||||
val stash = it.getDataAs<Map<String, StreamBundle>>()
|
||||
streamBundle = stash[category.value]
|
||||
streamBundle = stash[args.browseUrl]
|
||||
|
||||
genericCarouselController.setData(streamBundle)
|
||||
}
|
||||
@@ -92,7 +87,7 @@ class CategoryBrowseFragment : BaseFragment<FragmentGenericWithToolbarBinding>()
|
||||
}
|
||||
|
||||
override fun onClusterScrolled(streamCluster: StreamCluster) {
|
||||
viewModel.observeCluster(category, streamCluster)
|
||||
viewModel.observeCluster(args.browseUrl, streamCluster)
|
||||
}
|
||||
|
||||
override fun onAppClick(app: App) {
|
||||
|
||||
@@ -136,8 +136,8 @@ class AppDetailsFragment : BaseFragment<FragmentDetailsBinding>() {
|
||||
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<FragmentDetailsBinding>() {
|
||||
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<FragmentDetailsBinding>() {
|
||||
updateExtraDetails(app)
|
||||
updateCompatibilityInfo()
|
||||
|
||||
if (app.versionCode == 0) {
|
||||
if (app.versionCode == 0L) {
|
||||
warnAppUnavailable(app)
|
||||
}
|
||||
|
||||
@@ -607,7 +606,7 @@ class AppDetailsFragment : BaseFragment<FragmentDetailsBinding>() {
|
||||
}
|
||||
|
||||
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<FragmentDetailsBinding>() {
|
||||
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<FragmentDetailsBinding>() {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ class ManualDownloadSheet : BaseDialogSheet<SheetManualDownloadBinding>() {
|
||||
if (customVersionString.isEmpty())
|
||||
binding.versionCodeInp.error = "Enter version code"
|
||||
else {
|
||||
viewModel.purchase(args.app, customVersionString.toInt())
|
||||
viewModel.purchase(args.app, customVersionString.toLong())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<SearchBundle.SubBundle>) {
|
||||
fun next(nextSubBundleSet: Set<SearchBundle.SubBundle>) {
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class ManualDownloadViewModel @Inject constructor(
|
||||
private val _purchaseStatus = MutableSharedFlow<Boolean>()
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user