viewmodel: details: Relocate and rename viewmodels

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2025-09-17 11:14:41 +05:30
parent 36bc7a868a
commit e45999b9bc
9 changed files with 36 additions and 163 deletions

View File

@@ -34,16 +34,16 @@ import com.aurora.store.compose.composables.details.ExodusComposable
import com.aurora.store.compose.preview.AppPreviewProvider
import com.aurora.store.data.model.ExodusTracker
import com.aurora.store.viewmodel.details.AppDetailsViewModel
import com.aurora.store.viewmodel.details.DetailsExodusViewModel
import com.aurora.store.viewmodel.details.ExodusViewModel
@Composable
fun ExodusScreen(
packageName: String,
onNavigateUp: () -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
detailsExodusViewModel: DetailsExodusViewModel = hiltViewModel(
exodusViewModel: ExodusViewModel = hiltViewModel(
key = "$packageName/exodus",
creationCallback = { factory: DetailsExodusViewModel.Factory ->
creationCallback = { factory: ExodusViewModel.Factory ->
factory.create(appDetailsViewModel.exodusReport.value!!)
}
),
@@ -51,7 +51,7 @@ fun ExodusScreen(
) {
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val exodusReport by appDetailsViewModel.exodusReport.collectAsStateWithLifecycle()
val trackers by detailsExodusViewModel.trackers.collectAsStateWithLifecycle()
val trackers by exodusViewModel.trackers.collectAsStateWithLifecycle()
val topAppBarTitle = when {
windowAdaptiveInfo.isWindowCompact -> app!!.displayName

View File

@@ -43,7 +43,7 @@ import com.aurora.store.compose.composables.app.AppComposable
import com.aurora.store.compose.preview.AppPreviewProvider
import com.aurora.store.compose.preview.coilPreviewProvider
import com.aurora.store.viewmodel.details.AppDetailsViewModel
import com.aurora.store.viewmodel.details.DetailsMoreViewModel
import com.aurora.store.viewmodel.details.MoreViewModel
import java.util.Locale
@Composable
@@ -52,15 +52,15 @@ fun MoreScreen(
onNavigateUp: () -> Unit,
onNavigateToAppDetails: (packageName: String) -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
detailsMoreViewModel: DetailsMoreViewModel = hiltViewModel(
moreViewModel: MoreViewModel = hiltViewModel(
key = "$packageName/more",
creationCallback = { factory: DetailsMoreViewModel.Factory ->
creationCallback = { factory: MoreViewModel.Factory ->
factory.create(appDetailsViewModel.app.value!!.dependencies.dependentPackages)
}
)
) {
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val dependencies by detailsMoreViewModel.dependentApps.collectAsStateWithLifecycle()
val dependencies by moreViewModel.dependentApps.collectAsStateWithLifecycle()
ScreenContent(
app = app!!,

View File

@@ -33,7 +33,7 @@ import com.aurora.store.compose.composables.InfoComposable
import com.aurora.store.compose.composables.TopAppBarComposable
import com.aurora.store.compose.preview.AppPreviewProvider
import com.aurora.store.viewmodel.details.AppDetailsViewModel
import com.aurora.store.viewmodel.details.DetailsPermissionViewModel
import com.aurora.store.viewmodel.details.PermissionViewModel
import java.util.Locale
@Composable
@@ -41,16 +41,16 @@ fun PermissionScreen(
packageName: String,
onNavigateUp: () -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
detailsPermissionViewModel: DetailsPermissionViewModel = hiltViewModel(
permissionViewModel: PermissionViewModel = hiltViewModel(
key = "$packageName/permission",
creationCallback = { factory: DetailsPermissionViewModel.Factory ->
creationCallback = { factory: PermissionViewModel.Factory ->
factory.create(appDetailsViewModel.app.value!!.permissions)
}
),
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
) {
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val permissionsInfo by detailsPermissionViewModel.permissionsInfo.collectAsStateWithLifecycle()
val permissionsInfo by permissionViewModel.permissionsInfo.collectAsStateWithLifecycle()
val topAppBarTitle = when {
windowAdaptiveInfo.isWindowCompact -> app!!.displayName

View File

@@ -49,7 +49,7 @@ import com.aurora.store.compose.composables.details.ReviewComposable
import com.aurora.store.compose.preview.ReviewPreviewProvider
import com.aurora.store.compose.preview.coilPreviewProvider
import com.aurora.store.viewmodel.details.AppDetailsViewModel
import com.aurora.store.viewmodel.review.DetailsReviewViewModel
import com.aurora.store.viewmodel.details.ReviewViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlin.random.Random
@@ -58,16 +58,16 @@ fun ReviewScreen(
packageName: String,
onNavigateUp: () -> Unit,
appDetailsViewModel: AppDetailsViewModel = hiltViewModel(key = packageName),
detailsReviewViewModel: DetailsReviewViewModel = hiltViewModel(
reviewViewModel: ReviewViewModel = hiltViewModel(
key = "$packageName/review",
creationCallback = { factory: DetailsReviewViewModel.Factory ->
creationCallback = { factory: ReviewViewModel.Factory ->
factory.create(appDetailsViewModel.app.value!!.packageName)
}
),
windowAdaptiveInfo: WindowAdaptiveInfo = currentWindowAdaptiveInfo()
) {
val app by appDetailsViewModel.app.collectAsStateWithLifecycle()
val reviews = detailsReviewViewModel.reviews.collectAsLazyPagingItems()
val reviews = reviewViewModel.reviews.collectAsLazyPagingItems()
val topAppBarTitle = when {
windowAdaptiveInfo.isWindowCompact -> app!!.displayName
@@ -78,7 +78,7 @@ fun ReviewScreen(
topAppBarTitle = topAppBarTitle,
reviews = reviews,
onNavigateUp = onNavigateUp,
onFilter = { filter -> detailsReviewViewModel.fetchReviews(filter) }
onFilter = { filter -> reviewViewModel.fetchReviews(filter) }
)
}

View File

@@ -1,126 +0,0 @@
/*
* Aurora Store
* Copyright (C) 2021, Rahul Kumar Patel <whyorean@gmail.com>
*
* Aurora Store is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* Aurora Store is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Aurora Store. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.aurora.store.viewmodel.details
import android.util.Log
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.aurora.gplayapi.data.models.StreamBundle
import com.aurora.gplayapi.data.models.StreamCluster
import com.aurora.gplayapi.helpers.AppDetailsHelper
import com.aurora.gplayapi.helpers.StreamHelper
import com.aurora.gplayapi.helpers.contracts.StreamContract
import com.aurora.store.AppStreamStash
import com.aurora.store.data.model.ViewState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.supervisorScope
import javax.inject.Inject
@HiltViewModel
class DetailsClusterViewModel @Inject constructor(
private val appDetailsHelper: AppDetailsHelper,
private val streamHelper: StreamHelper
) : ViewModel() {
private val TAG = DetailsClusterViewModel::class.java.simpleName
val liveData: MutableLiveData<ViewState> = MutableLiveData()
private val stash: AppStreamStash = mutableMapOf()
lateinit var type: StreamContract.Type
lateinit var category: StreamContract.Category
fun getStreamBundle(streamUrl: String) {
viewModelScope.launch(Dispatchers.IO) {
supervisorScope {
val bundle = targetBundle(streamUrl)
if (bundle.streamClusters.isNotEmpty()) {
liveData.postValue(ViewState.Success(stash))
}
try {
if (!bundle.hasCluster() || bundle.hasNext()) {
val newBundle = appDetailsHelper.getDetailsStream(streamUrl)
val mergedBundle = bundle.copy(
streamClusters = bundle.streamClusters + newBundle.streamClusters,
streamNextPageUrl = newBundle.streamNextPageUrl
)
stash[streamUrl] = mergedBundle
liveData.postValue(ViewState.Success(stash))
}
} catch (e: Exception) {
liveData.postValue(ViewState.Error(e.message))
}
}
}
}
fun observeCluster(url: String, streamCluster: StreamCluster) {
viewModelScope.launch(Dispatchers.IO) {
supervisorScope {
try {
if (streamCluster.hasNext()) {
val newCluster =
streamHelper.getNextStreamCluster(streamCluster.clusterNextPageUrl)
updateCluster(url, streamCluster.id, newCluster)
liveData.postValue(ViewState.Success(stash))
} else {
Log.i(TAG, "End of cluster")
}
} catch (e: Exception) {
liveData.postValue(ViewState.Error(e.message))
}
}
}
}
private fun updateCluster(
url: String,
clusterID: Int,
newCluster: StreamCluster
) {
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().apply {
this[clusterID] = mergedCluster
}
stash.put(url, bundle.copy(streamClusters = newStreamClusters))
}
}
private fun targetBundle(url: String): StreamBundle {
val streamBundle = stash.getOrPut(url) {
StreamBundle()
}
return streamBundle
}
}

View File

@@ -19,15 +19,15 @@ import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import org.json.JSONObject
@HiltViewModel(assistedFactory = DetailsExodusViewModel.Factory::class)
class DetailsExodusViewModel @AssistedInject constructor(
@HiltViewModel(assistedFactory = ExodusViewModel.Factory::class)
class ExodusViewModel @AssistedInject constructor(
@Assisted private val exodusReport: Report,
private val exodusTrackers: JSONObject
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(exodusReport: Report): DetailsExodusViewModel
fun create(exodusReport: Report): ExodusViewModel
}
private val _trackers = MutableStateFlow<List<ExodusTracker>>(emptyList())

View File

@@ -20,18 +20,18 @@ import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
@HiltViewModel(assistedFactory = DetailsMoreViewModel.Factory::class)
class DetailsMoreViewModel @AssistedInject constructor(
@HiltViewModel(assistedFactory = MoreViewModel.Factory::class)
class MoreViewModel @AssistedInject constructor(
@Assisted private val dependencies: List<String>,
private val appDetailsHelper: AppDetailsHelper
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(dependencies: List<String>): DetailsMoreViewModel
fun create(dependencies: List<String>): MoreViewModel
}
private val TAG = DetailsMoreViewModel::class.java.simpleName
private val TAG = MoreViewModel::class.java.simpleName
private val _dependentApps = MutableStateFlow<List<App>?>(emptyList())
val dependentApps = _dependentApps.asStateFlow()

View File

@@ -17,15 +17,15 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
@HiltViewModel(assistedFactory = DetailsPermissionViewModel.Factory::class)
class DetailsPermissionViewModel @AssistedInject constructor(
@HiltViewModel(assistedFactory = PermissionViewModel.Factory::class)
class PermissionViewModel @AssistedInject constructor(
@Assisted private val permissions: List<String>,
@ApplicationContext private val context: Context
): ViewModel() {
@AssistedFactory
interface Factory {
fun create(permissions: List<String>): DetailsPermissionViewModel
fun create(permissions: List<String>): PermissionViewModel
}
private val _permissionsInfo = MutableStateFlow<Map<String, PermissionInfo?>>(emptyMap())

View File

@@ -1,10 +1,9 @@
/*
* SPDX-FileCopyrightText: 2021-2023 AuroraOSS
* SPDX-FileCopyrightText: 2024-2025 The Calyx Institute
* SPDX-FileCopyrightText: 2025 The Calyx Institute
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.aurora.store.viewmodel.review
package com.aurora.store.viewmodel.details
import android.util.Log
import androidx.lifecycle.ViewModel
@@ -13,7 +12,7 @@ import androidx.paging.PagingData
import androidx.paging.cachedIn
import com.aurora.gplayapi.data.models.Review
import com.aurora.gplayapi.helpers.ReviewsHelper
import com.aurora.store.data.paging.GenericPagingSource.Companion.createPager
import com.aurora.store.data.paging.GenericPagingSource
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
@@ -24,20 +23,20 @@ import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@HiltViewModel(assistedFactory = DetailsReviewViewModel.Factory::class)
class DetailsReviewViewModel @AssistedInject constructor(
@HiltViewModel(assistedFactory = ReviewViewModel.Factory::class)
class ReviewViewModel @AssistedInject constructor(
@Assisted private val packageName: String,
private val reviewsHelper: ReviewsHelper
) : ViewModel() {
@AssistedFactory
interface Factory {
fun create(packageName: String): DetailsReviewViewModel
fun create(packageName: String): ReviewViewModel
}
private val TAG = DetailsReviewViewModel::class.java.simpleName
private val TAG = ReviewViewModel::class.java.simpleName
private val _reviews = MutableStateFlow<PagingData<Review>>(PagingData.empty())
private val _reviews = MutableStateFlow<PagingData<Review>>(PagingData.Companion.empty())
val reviews = _reviews.asStateFlow()
init {
@@ -47,7 +46,7 @@ class DetailsReviewViewModel @AssistedInject constructor(
fun fetchReviews(filter: Review.Filter = Review.Filter.ALL) {
var reviewsNextPageUrl: String? = null
createPager { page ->
GenericPagingSource.Companion.createPager { page ->
try {
when (page) {
1 -> reviewsHelper.getReviews(packageName, filter).also {