compose: details: Simplify and fix showing app states
Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
@@ -73,9 +73,9 @@ import com.aurora.store.compose.ui.details.components.AppTags
|
||||
import com.aurora.store.compose.ui.details.components.AppTesting
|
||||
import com.aurora.store.compose.ui.dev.DevProfileScreen
|
||||
import com.aurora.store.data.installer.AppInstaller
|
||||
import com.aurora.store.data.model.AppState
|
||||
import com.aurora.store.data.model.Report
|
||||
import com.aurora.store.data.model.Scores
|
||||
import com.aurora.store.data.room.download.Download
|
||||
import com.aurora.store.util.PackageUtil
|
||||
import com.aurora.store.util.PackageUtil.PACKAGE_NAME_GMS
|
||||
import com.aurora.store.util.ShortcutManagerUtil
|
||||
@@ -94,13 +94,12 @@ fun AppDetailsScreen(
|
||||
val context = LocalContext.current
|
||||
|
||||
val app by viewModel.app.collectAsStateWithLifecycle()
|
||||
val state by viewModel.state.collectAsStateWithLifecycle()
|
||||
val featuredReviews by viewModel.featuredReviews.collectAsStateWithLifecycle()
|
||||
val favorite by viewModel.favourite.collectAsStateWithLifecycle()
|
||||
val exodusReport by viewModel.exodusReport.collectAsStateWithLifecycle()
|
||||
val dataSafetyReport by viewModel.dataSafetyReport.collectAsStateWithLifecycle()
|
||||
val plexusScores by viewModel.plexusScores.collectAsStateWithLifecycle()
|
||||
val download by viewModel.download.collectAsStateWithLifecycle()
|
||||
val installProgress by viewModel.installProgress.collectAsStateWithLifecycle()
|
||||
val suggestions by viewModel.suggestions.collectAsStateWithLifecycle()
|
||||
|
||||
LaunchedEffect(key1 = Unit) { viewModel.fetchAppDetails(packageName) }
|
||||
@@ -117,12 +116,10 @@ fun AppDetailsScreen(
|
||||
suggestions = suggestions,
|
||||
isFavorite = favorite,
|
||||
isAnonymous = viewModel.authProvider.isAnonymous,
|
||||
download = download,
|
||||
installProgress = installProgress,
|
||||
state = state,
|
||||
plexusScores = plexusScores,
|
||||
dataSafetyReport = dataSafetyReport,
|
||||
exodusReport = exodusReport,
|
||||
hasValidUpdate = viewModel.hasValidUpdate,
|
||||
onNavigateUp = onNavigateUp,
|
||||
onNavigateToAppDetails = onNavigateToAppDetails,
|
||||
onDownload = { viewModel.purchase(this) },
|
||||
@@ -190,12 +187,10 @@ private fun ScreenContentApp(
|
||||
suggestions: List<App> = emptyList(),
|
||||
isFavorite: Boolean = false,
|
||||
isAnonymous: Boolean = true,
|
||||
download: Download? = null,
|
||||
installProgress: Float? = null,
|
||||
state: AppState = AppState.Unavailable,
|
||||
plexusScores: Scores? = null,
|
||||
dataSafetyReport: DataSafetyReport? = null,
|
||||
exodusReport: Report? = null,
|
||||
hasValidUpdate: Boolean = false,
|
||||
onNavigateUp: () -> Unit = {},
|
||||
onNavigateToAppDetails: (packageName: String) -> Unit = {},
|
||||
onDownload: () -> Unit = {},
|
||||
@@ -248,13 +243,11 @@ private fun ScreenContentApp(
|
||||
ScreenContentAppMainPane(
|
||||
app = app,
|
||||
featuredReviews = featuredReviews,
|
||||
download = download,
|
||||
installProgress = installProgress,
|
||||
state = state,
|
||||
isAnonymous = isAnonymous,
|
||||
plexusScores = plexusScores,
|
||||
dataSafetyReport = dataSafetyReport,
|
||||
exodusReport = exodusReport,
|
||||
hasValidUpdate = hasValidUpdate,
|
||||
onNavigateUp = onNavigateUp,
|
||||
onNavigateToScreen = { screen -> showExtraPane(screen) },
|
||||
onDownload = onDownload,
|
||||
@@ -316,13 +309,11 @@ private fun ScreenContentApp(
|
||||
private fun ScreenContentAppMainPane(
|
||||
app: App,
|
||||
featuredReviews: List<Review> = emptyList(),
|
||||
download: Download?,
|
||||
installProgress: Float?,
|
||||
state: AppState = AppState.Unavailable,
|
||||
isAnonymous: Boolean,
|
||||
plexusScores: Scores?,
|
||||
dataSafetyReport: DataSafetyReport?,
|
||||
exodusReport: Report?,
|
||||
hasValidUpdate: Boolean,
|
||||
onNavigateUp: () -> Unit,
|
||||
onNavigateToScreen: (screen: Screen) -> Unit,
|
||||
onDownload: () -> Unit,
|
||||
@@ -332,12 +323,11 @@ private fun ScreenContentAppMainPane(
|
||||
onTestingSubscriptionChange: (subscribe: Boolean) -> Unit,
|
||||
menuActions: @Composable (RowScope.() -> Unit) = {}
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
@Composable
|
||||
fun SetupAppActions() {
|
||||
when {
|
||||
download?.isRunning == true -> {
|
||||
when (state) {
|
||||
is AppState.Downloading -> {
|
||||
AppActions(
|
||||
primaryActionDisplayName = stringResource(R.string.action_open),
|
||||
secondaryActionDisplayName = stringResource(R.string.action_cancel),
|
||||
@@ -346,7 +336,7 @@ private fun ScreenContentAppMainPane(
|
||||
)
|
||||
}
|
||||
|
||||
app.isInstalled && hasValidUpdate -> {
|
||||
is AppState.Updatable -> {
|
||||
AppActions(
|
||||
primaryActionDisplayName = stringResource(R.string.action_update),
|
||||
secondaryActionDisplayName = stringResource(R.string.action_uninstall),
|
||||
@@ -355,7 +345,7 @@ private fun ScreenContentAppMainPane(
|
||||
)
|
||||
}
|
||||
|
||||
app.isInstalled -> {
|
||||
is AppState.Installed -> {
|
||||
AppActions(
|
||||
primaryActionDisplayName = stringResource(R.string.action_open),
|
||||
secondaryActionDisplayName = stringResource(R.string.action_uninstall),
|
||||
@@ -365,7 +355,7 @@ private fun ScreenContentAppMainPane(
|
||||
}
|
||||
|
||||
else -> {
|
||||
val primaryActionName = if (PackageUtil.isArchived(context, app.packageName)) {
|
||||
val primaryActionName = if (state is AppState.Archived) {
|
||||
stringResource(R.string.action_unarchive)
|
||||
} else {
|
||||
if (app.isFree) stringResource(R.string.action_install) else app.price
|
||||
@@ -394,20 +384,12 @@ private fun ScreenContentAppMainPane(
|
||||
.padding(dimensionResource(R.dimen.padding_medium)),
|
||||
verticalArrangement = Arrangement.spacedBy(dimensionResource(R.dimen.margin_medium))
|
||||
) {
|
||||
val isDownloading = download != null && download.isRunning
|
||||
val isInstalling = installProgress != null
|
||||
val progress = when {
|
||||
isDownloading -> download?.progress?.toFloat() ?: 0F
|
||||
isInstalling -> installProgress ?: 0F
|
||||
else -> 0F
|
||||
}
|
||||
|
||||
AppDetails(
|
||||
app = app,
|
||||
inProgress = isDownloading || isInstalling,
|
||||
progress = progress,
|
||||
inProgress = state.inProgress(),
|
||||
progress = state.progress(),
|
||||
onNavigateToDetailsDevProfile = { onNavigateToScreen(Screen.DevProfile(it)) },
|
||||
hasValidUpdate = hasValidUpdate
|
||||
isUpdatable = state is AppState.Updatable
|
||||
)
|
||||
|
||||
SetupAppActions()
|
||||
@@ -533,7 +515,6 @@ private fun AppDetailsScreenPreview(@PreviewParameter(AppPreviewProvider::class)
|
||||
ScreenContentApp(
|
||||
app = app,
|
||||
isAnonymous = false,
|
||||
hasValidUpdate = false,
|
||||
suggestions = List(10) { app.copy(id = Random.nextInt()) }
|
||||
)
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ import com.aurora.store.util.PackageUtil
|
||||
* @param progress Ongoing progress percentage out of 100, for e.g. 50.0
|
||||
* @param inProgress Whether there is some ongoing progress related to the app
|
||||
* @param onNavigateToDetailsDevProfile Callback when the developer name is tapped
|
||||
* @param hasValidUpdate Whether the app has a valid update available
|
||||
* @param isUpdatable Whether the app has a valid update available
|
||||
*/
|
||||
@Composable
|
||||
fun AppDetails(
|
||||
@@ -48,7 +48,7 @@ fun AppDetails(
|
||||
progress: Float = 0F,
|
||||
inProgress: Boolean = false,
|
||||
onNavigateToDetailsDevProfile: (developerName: String) -> Unit = {},
|
||||
hasValidUpdate: Boolean = false,
|
||||
isUpdatable: Boolean = false,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
|
||||
@@ -76,7 +76,7 @@ fun AppDetails(
|
||||
color = MaterialTheme.colorScheme.primary
|
||||
)
|
||||
Text(
|
||||
text = if (!hasValidUpdate) {
|
||||
text = if (!isUpdatable) {
|
||||
stringResource(R.string.version, app.versionName, app.versionCode)
|
||||
} else {
|
||||
stringResource(
|
||||
|
||||
@@ -32,15 +32,18 @@ sealed class AuthEvent : Event() {
|
||||
data class GoogleLogin(val success: Boolean, val email: String, val token: String) : AuthEvent()
|
||||
}
|
||||
|
||||
sealed class InstallerEvent : Event() {
|
||||
lateinit var extra: String
|
||||
lateinit var error: String
|
||||
open class InstallerEvent(open val packageName: String) : Event() {
|
||||
data class Installed(override val packageName: String) : InstallerEvent(packageName)
|
||||
data class Uninstalled(override val packageName: String) : InstallerEvent(packageName)
|
||||
|
||||
var progress: Int = -1
|
||||
data class Installing(
|
||||
override val packageName: String,
|
||||
val progress: Float = 0.0F
|
||||
) : InstallerEvent(packageName)
|
||||
|
||||
data class Installed(val packageName: String) : InstallerEvent()
|
||||
data class Uninstalled(val packageName: String) : InstallerEvent()
|
||||
data class Installing(val packageName: String) : InstallerEvent()
|
||||
data class Cancelled(val packageName: String) : InstallerEvent()
|
||||
data class Failed(val packageName: String) : InstallerEvent()
|
||||
data class Failed(
|
||||
override val packageName: String,
|
||||
val error: String? = null,
|
||||
val extra: String? = null,
|
||||
) : InstallerEvent(packageName)
|
||||
}
|
||||
|
||||
@@ -112,11 +112,12 @@ class RootInstaller @Inject constructor(
|
||||
if (packageName == download?.packageName) onInstallationSuccess()
|
||||
} else {
|
||||
removeFromInstallQueue(packageName)
|
||||
val event = InstallerEvent.Failed(packageName).apply {
|
||||
this.extra = context.getString(R.string.installer_status_failure)
|
||||
this.error = parseError(shellResult)
|
||||
}
|
||||
AuroraApp.events.send(event)
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Failed(
|
||||
packageName = packageName,
|
||||
error = parseError(shellResult)
|
||||
)
|
||||
)
|
||||
}
|
||||
} else {
|
||||
removeFromInstallQueue(packageName)
|
||||
|
||||
@@ -230,11 +230,7 @@ class ServiceInstaller @Inject constructor(
|
||||
try {
|
||||
when (returnCode) {
|
||||
PackageInstaller.STATUS_SUCCESS -> {
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Uninstalled(packageName).apply {
|
||||
this.extra = context.getString(R.string.action_uninstall_success)
|
||||
}
|
||||
)
|
||||
AuroraApp.events.send(InstallerEvent.Uninstalled(packageName = packageName))
|
||||
}
|
||||
|
||||
else -> postError(packageName, getErrorString(context, returnCode), extra)
|
||||
@@ -253,11 +249,7 @@ class ServiceInstaller @Inject constructor(
|
||||
try {
|
||||
when (returnCode) {
|
||||
PackageInstaller.STATUS_SUCCESS -> {
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Installed(packageName).apply {
|
||||
this.extra = context.getString(R.string.installer_status_success)
|
||||
}
|
||||
)
|
||||
AuroraApp.events.send(InstallerEvent.Installed(packageName = packageName))
|
||||
// Installation is not yet finished if this is a shared library
|
||||
if (packageName == download?.packageName) onInstallationSuccess()
|
||||
}
|
||||
|
||||
@@ -86,9 +86,10 @@ class SessionInstaller @Inject constructor(
|
||||
|
||||
if (packageName != null && progress > 0.0) {
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Installing(packageName).apply {
|
||||
this.progress = (progress * 100).toInt()
|
||||
}
|
||||
InstallerEvent.Installing(
|
||||
packageName = packageName,
|
||||
progress = progress
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,14 +91,14 @@ abstract class InstallerBase(private val context: Context) : IInstaller {
|
||||
}
|
||||
|
||||
open fun postError(packageName: String, error: String?, extra: String?) {
|
||||
Log.e(TAG, "Service Error :$error")
|
||||
|
||||
val event = InstallerEvent.Failed(packageName).apply {
|
||||
this.error = error ?: ""
|
||||
this.extra = extra ?: ""
|
||||
}
|
||||
|
||||
AuroraApp.events.send(event)
|
||||
Log.e(TAG, "Installer Error :$error")
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Failed(
|
||||
packageName = packageName,
|
||||
error = error,
|
||||
extra = extra
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
fun getFiles(
|
||||
|
||||
@@ -44,3 +44,38 @@ sealed class AuthState {
|
||||
data class PendingAccountManager(val email: String, val token: String) : AuthState()
|
||||
data class Failed(val status: String) : AuthState()
|
||||
}
|
||||
|
||||
/**
|
||||
* Possible states of an app to show appropriate actions on UI
|
||||
*/
|
||||
sealed class AppState {
|
||||
data class Downloading(
|
||||
val progress: Float,
|
||||
val speed: Long,
|
||||
val timeRemaining: Long
|
||||
) : AppState()
|
||||
|
||||
data class Installing(val progress: Float) : AppState()
|
||||
data object Installed : AppState()
|
||||
data object Archived : AppState()
|
||||
data object Updatable : AppState()
|
||||
data object Unavailable : AppState()
|
||||
|
||||
/**
|
||||
* Whether there is some sort of ongoing process related to the app
|
||||
*/
|
||||
fun inProgress(): Boolean {
|
||||
return this is Downloading || this is Installing
|
||||
}
|
||||
|
||||
/**
|
||||
* Progress of the process related to the app; 0 otherwise
|
||||
*/
|
||||
fun progress(): Float {
|
||||
return when (this) {
|
||||
is Downloading -> progress
|
||||
is Installing -> progress
|
||||
else -> 0F
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,26 +132,17 @@ abstract class BaseInstallerStatusReceiver : BroadcastReceiver() {
|
||||
promptUser(context, intent)
|
||||
}
|
||||
|
||||
open fun postStatus(status: Int, packageName: String?, extra: String?, context: Context) {
|
||||
open fun postStatus(status: Int, packageName: String, extra: String?, context: Context) {
|
||||
val event = when (status) {
|
||||
PackageInstaller.STATUS_SUCCESS -> {
|
||||
InstallerEvent.Installed(packageName!!).apply {
|
||||
this.extra = context.getString(R.string.installer_status_success)
|
||||
}
|
||||
}
|
||||
PackageInstaller.STATUS_SUCCESS -> InstallerEvent.Installed(
|
||||
packageName = packageName
|
||||
)
|
||||
|
||||
PackageInstaller.STATUS_FAILURE_ABORTED -> {
|
||||
InstallerEvent.Cancelled(packageName!!).apply {
|
||||
this.extra = InstallerBase.getErrorString(context, status)
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
InstallerEvent.Failed(packageName!!).apply {
|
||||
this.error = InstallerBase.getErrorString(context, status)
|
||||
this.extra = extra ?: ""
|
||||
}
|
||||
}
|
||||
else -> InstallerEvent.Failed(
|
||||
packageName = packageName,
|
||||
error = InstallerBase.getErrorString(context, status),
|
||||
extra = extra
|
||||
)
|
||||
}
|
||||
|
||||
AuroraApp.events.send(event)
|
||||
|
||||
@@ -222,11 +222,14 @@ class DownloadWorker @AssistedInject constructor(
|
||||
|
||||
else -> {
|
||||
notifyStatus(DownloadStatus.FAILED)
|
||||
AuroraApp.events.send(InstallerEvent.Failed(download.packageName).apply {
|
||||
extra =
|
||||
exception.message ?: context.getString(R.string.download_failed)
|
||||
error = exception.stackTraceToString()
|
||||
})
|
||||
AuroraApp.events.send(
|
||||
InstallerEvent.Failed(
|
||||
packageName = download.packageName,
|
||||
error = exception.stackTraceToString(),
|
||||
extra = exception.message
|
||||
?: context.getString(R.string.download_failed)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
package com.aurora.store.viewmodel.details
|
||||
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageInstaller
|
||||
import android.util.Log
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
@@ -20,8 +19,11 @@ import com.aurora.gplayapi.helpers.PurchaseHelper
|
||||
import com.aurora.gplayapi.helpers.ReviewsHelper
|
||||
import com.aurora.gplayapi.helpers.web.WebDataSafetyHelper
|
||||
import com.aurora.gplayapi.network.IHttpClient
|
||||
import com.aurora.store.AuroraApp
|
||||
import com.aurora.store.BuildConfig
|
||||
import com.aurora.store.data.event.InstallerEvent
|
||||
import com.aurora.store.data.helper.DownloadHelper
|
||||
import com.aurora.store.data.model.AppState
|
||||
import com.aurora.store.data.model.ExodusReport
|
||||
import com.aurora.store.data.model.PlexusReport
|
||||
import com.aurora.store.data.model.Report
|
||||
@@ -37,14 +39,16 @@ import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED
|
||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.callbackFlow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.filterNotNull
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.flow.stateIn
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -71,6 +75,9 @@ class AppDetailsViewModel @Inject constructor(
|
||||
private val _app = MutableStateFlow<App?>(App(""))
|
||||
val app = _app.asStateFlow()
|
||||
|
||||
private val _state = MutableStateFlow(defaultAppState)
|
||||
val state = _state.asStateFlow()
|
||||
|
||||
private val _suggestions = MutableStateFlow<List<App>>(emptyList())
|
||||
val suggestions = _suggestions.asStateFlow()
|
||||
|
||||
@@ -98,42 +105,23 @@ class AppDetailsViewModel @Inject constructor(
|
||||
private val _purchaseStatus = MutableSharedFlow<Boolean>()
|
||||
val purchaseStatus = _purchaseStatus.asSharedFlow()
|
||||
|
||||
val download = combine(app, downloadHelper.downloadsList) { a, list ->
|
||||
private val download = combine(app, downloadHelper.downloadsList) { a, list ->
|
||||
if (a?.packageName.isNullOrBlank()) return@combine null
|
||||
list.find { d -> d.packageName == a?.packageName }
|
||||
}.stateIn(viewModelScope, SharingStarted.Eagerly, null)
|
||||
|
||||
// TODO: Save sessionId to downloads to monitor packageInstall progress
|
||||
val installProgress = callbackFlow<Float?> {
|
||||
val packageInstaller = context.packageManager.packageInstaller
|
||||
val callback = object : PackageInstaller.SessionCallback() {
|
||||
override fun onActiveChanged(p0: Int, p1: Boolean) {}
|
||||
override fun onBadgingChanged(p0: Int) {}
|
||||
override fun onCreated(p0: Int) {
|
||||
// trySend(0F)
|
||||
}
|
||||
override fun onFinished(p0: Int, p1: Boolean) {
|
||||
// trySend(null)
|
||||
}
|
||||
override fun onProgressChanged(p0: Int, p1: Float) {
|
||||
// trySend(p1)
|
||||
}
|
||||
}
|
||||
private val isInstalled: Boolean
|
||||
get() = PackageUtil.isInstalled(context, app.value!!.packageName)
|
||||
|
||||
packageInstaller.registerSessionCallback(callback)
|
||||
awaitClose { packageInstaller.unregisterSessionCallback(callback) }
|
||||
}.stateIn(viewModelScope, SharingStarted.Eagerly, null)
|
||||
private val isUpdatable: Boolean
|
||||
get() = PackageUtil.isUpdatable(context, app.value!!.packageName, app.value!!.versionCode)
|
||||
|
||||
private val isArchived: Boolean
|
||||
get() = PackageUtil.isArchived(context, app.value!!.packageName)
|
||||
|
||||
private val isExtendedUpdateEnabled: Boolean
|
||||
get() = Preferences.getBoolean(context, PREFERENCE_UPDATES_EXTENDED)
|
||||
|
||||
private val isUpdatable: Boolean
|
||||
get() = PackageUtil.isUpdatable(
|
||||
context,
|
||||
app.value!!.packageName,
|
||||
app.value!!.versionCode
|
||||
)
|
||||
|
||||
private val hasValidCerts: Boolean
|
||||
get() = app.value!!.certificateSetList.any {
|
||||
it.certificateSet in CertUtil.getEncodedCertificateHashes(
|
||||
@@ -142,9 +130,19 @@ class AppDetailsViewModel @Inject constructor(
|
||||
)
|
||||
}
|
||||
|
||||
val hasValidUpdate: Boolean
|
||||
private val hasValidUpdate: Boolean
|
||||
get() = (isUpdatable && hasValidCerts) || (isUpdatable && isExtendedUpdateEnabled)
|
||||
|
||||
private val defaultAppState: AppState
|
||||
get() = when {
|
||||
isInstalled -> if (hasValidUpdate) AppState.Updatable else AppState.Installed
|
||||
else -> if (isArchived) AppState.Archived else AppState.Unavailable
|
||||
}
|
||||
|
||||
init {
|
||||
observeAppState()
|
||||
}
|
||||
|
||||
fun fetchAppDetails(packageName: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -170,18 +168,6 @@ class AppDetailsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun fetchFeaturedReviews(packageName: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
_featuredReviews.value = reviewsHelper.getReviewSummary(packageName)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to fetch featured app reviews", exception)
|
||||
_featuredReviews.value = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun updateTestingProgramStatus(packageName: String, subscribe: Boolean) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
@@ -232,7 +218,7 @@ class AppDetailsViewModel @Inject constructor(
|
||||
if (files.isNotEmpty()) download(app.copy(fileList = files.toMutableList()))
|
||||
} catch (exception: Exception) {
|
||||
_purchaseStatus.emit(false)
|
||||
Log.e(TAG, "Failed to purchase the app ", exception)
|
||||
Log.e(TAG, "Failed to purchase the app", exception)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -261,6 +247,41 @@ class AppDetailsViewModel @Inject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun observeAppState() {
|
||||
AuroraApp.events.installerEvent
|
||||
.filter { it.packageName == app.value?.packageName }
|
||||
.onEach { event ->
|
||||
_state.value = when {
|
||||
event is InstallerEvent.Installing -> AppState.Installing(event.progress)
|
||||
else -> defaultAppState
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
|
||||
download.filterNotNull().onEach {
|
||||
_state.value = when {
|
||||
it.isRunning -> AppState.Downloading(
|
||||
it.progress.toFloat(),
|
||||
it.speed,
|
||||
it.timeRemaining
|
||||
)
|
||||
|
||||
else -> defaultAppState
|
||||
}
|
||||
}.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun fetchFeaturedReviews(packageName: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
try {
|
||||
_featuredReviews.value = reviewsHelper.getReviewSummary(packageName)
|
||||
} catch (exception: Exception) {
|
||||
Log.e(TAG, "Failed to fetch featured app reviews", exception)
|
||||
_featuredReviews.value = emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun fetchFavourite(packageName: String) {
|
||||
viewModelScope.launch(Dispatchers.IO) {
|
||||
_favourite.value = favouriteDao.isFavourite(packageName)
|
||||
|
||||
Reference in New Issue
Block a user