From 2be99156af0f39b864577656d88e1aa6411c8523 Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Tue, 21 Oct 2025 12:08:21 -0300 Subject: [PATCH] Allow changing (preferred) repo in app details --- .../org/fdroid/ui/details/AppDetailsHeader.kt | 4 ++-- .../org/fdroid/ui/details/AppDetailsItem.kt | 2 ++ .../fdroid/ui/details/AppDetailsViewModel.kt | 14 +++++++++++ .../org/fdroid/ui/details/DetailsPresenter.kt | 24 +++++++++++++------ .../org/fdroid/ui/details/RepoChooser.kt | 4 ++-- .../org/fdroid/ui/utils/PreviewUtils.kt | 2 ++ 6 files changed, 39 insertions(+), 11 deletions(-) diff --git a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt index 66339ff33..b235f7113 100644 --- a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt +++ b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsHeader.kt @@ -160,8 +160,8 @@ fun AppDetailsHeader( repos = item.repositories, currentRepoId = item.app.repoId, preferredRepoId = item.preferredRepoId, - onRepoChanged = {}, - onPreferredRepoChanged = {}, + onRepoChanged = item.actions.onRepoChanged, + onPreferredRepoChanged = item.actions.onPreferredRepoChanged, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), ) // check user confirmation ON_RESUME to work around Android bug diff --git a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt index 786e70eea..b912b5995 100644 --- a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt +++ b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsItem.kt @@ -199,6 +199,8 @@ class AppDetailsActions( val checkUserConfirmation: (String, InstallState.UserConfirmationNeeded) -> Unit, val cancelInstall: (String) -> Unit, val onUninstallResult: (String, ActivityResult) -> Unit, + val onRepoChanged: (Long) -> Unit, + val onPreferredRepoChanged: (Long) -> Unit, val allowBetaVersions: () -> Unit, val ignoreAllUpdates: (() -> Unit)? = null, val ignoreThisUpdate: (() -> Unit)? = null, diff --git a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsViewModel.kt b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsViewModel.kt index 7f42890d9..4884a53c8 100644 --- a/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsViewModel.kt +++ b/next/src/main/kotlin/org/fdroid/ui/details/AppDetailsViewModel.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.delay import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mu.KotlinLogging @@ -44,6 +45,7 @@ class AppDetailsViewModel @Inject constructor( ) : AndroidViewModel(app) { private val log = KotlinLogging.logger { } private val packageInfoFlow = MutableStateFlow(null) + private val currentRepoIdFlow = MutableStateFlow(null) val appDetails: StateFlow = viewModelScope.launchMolecule( context = Dispatchers.IO, mode = Immediate, @@ -55,6 +57,7 @@ class AppDetailsViewModel @Inject constructor( appInstallManager = appInstallManager, viewModel = this, packageInfoFlow = packageInfoFlow, + currentRepoIdFlow = currentRepoIdFlow, ) } @@ -136,6 +139,17 @@ class AppDetailsViewModel @Inject constructor( } } + @UiThread + fun onRepoChanged(repoId: Long) { + currentRepoIdFlow.update { repoId } + } + + @UiThread + fun onPreferredRepoChanged(repoId: Long) { + val packageName = packageInfoFlow.value?.packageName ?: error("Had not package name") + repoManager.setPreferredRepoId(packageName, repoId) + } + override fun onCleared() { val packageName = packageInfoFlow.value?.packageName log.info { "App details screen left: $packageName" } diff --git a/next/src/main/kotlin/org/fdroid/ui/details/DetailsPresenter.kt b/next/src/main/kotlin/org/fdroid/ui/details/DetailsPresenter.kt index 9f4c96e26..d86e4d899 100644 --- a/next/src/main/kotlin/org/fdroid/ui/details/DetailsPresenter.kt +++ b/next/src/main/kotlin/org/fdroid/ui/details/DetailsPresenter.kt @@ -31,15 +31,17 @@ fun DetailsPresenter( appInstallManager: AppInstallManager, viewModel: AppDetailsViewModel, packageInfoFlow: StateFlow, + currentRepoIdFlow: StateFlow, ): AppDetailsItem? { val packagePair = packageInfoFlow.collectAsState().value ?: return null val packageName = packagePair.packageName - val app = db.getAppDao().getApp(packageName).asFlow().collectAsState(null).value - ?: return null + val currentRepoId = currentRepoIdFlow.collectAsState().value + val app = if (currentRepoId == null) { + db.getAppDao().getApp(packageName).asFlow().collectAsState(null).value + } else { + db.getAppDao().getApp(currentRepoId, packageName) + } ?: return null val repo = repoManager.getRepository(app.repoId) ?: return null - val preferredRepoId = remember(packageName) { - app.repoId // DB loads preferred repo first, so we remember it - } val repositories = remember(packageName) { db.getAppDao().getRepositoryIdsForApp(packageName).mapNotNull { repoId -> repoManager.getRepository(repoId) @@ -48,9 +50,15 @@ fun DetailsPresenter( val installState = appInstallManager.getAppFlow(packageName).collectAsState(InstallState.Unknown).value - val versions = - db.getVersionDao().getAppVersions(packageName).asFlow().collectAsState(null).value + val versions = if (currentRepoId == null) { + db.getVersionDao().getAppVersions(packageName) + } else { + db.getVersionDao().getAppVersions(currentRepoId, packageName) + }.asFlow().collectAsState(null).value val appPrefs = db.getAppPrefsDao().getAppPrefs(packageName).asFlow().collectAsState(null).value + val preferredRepoId = remember(packageName, appPrefs) { + appPrefs?.preferredRepoId ?: app.repoId // DB loads preferred repo first, so we remember it + } val suggestedVersion = if (versions == null || appPrefs == null) { null } else { @@ -109,6 +117,8 @@ fun DetailsPresenter( checkUserConfirmation = viewModel::checkUserConfirmation, cancelInstall = viewModel::cancelInstall, onUninstallResult = viewModel::onUninstallResult, + onRepoChanged = viewModel::onRepoChanged, + onPreferredRepoChanged = viewModel::onPreferredRepoChanged, allowBetaVersions = viewModel::allowBetaUpdates, ignoreAllUpdates = if (installedVersionCode == null) { null diff --git a/next/src/main/kotlin/org/fdroid/ui/details/RepoChooser.kt b/next/src/main/kotlin/org/fdroid/ui/details/RepoChooser.kt index 2caf9b876..06ac40f71 100644 --- a/next/src/main/kotlin/org/fdroid/ui/details/RepoChooser.kt +++ b/next/src/main/kotlin/org/fdroid/ui/details/RepoChooser.kt @@ -43,7 +43,7 @@ fun RepoChooser( repos: List, currentRepoId: Long, preferredRepoId: Long, - onRepoChanged: (Repository) -> Unit, + onRepoChanged: (Long) -> Unit, onPreferredRepoChanged: (Long) -> Unit, modifier: Modifier = Modifier, ) { @@ -116,7 +116,7 @@ fun RepoChooser( repo = repo, isPreferred = repo.repoId == preferredRepoId, onClick = { - onRepoChanged(repo) + onRepoChanged(repo.repoId) expanded = false }, modifier = modifier, diff --git a/next/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt b/next/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt index 0b6b67946..9db68795e 100644 --- a/next/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt +++ b/next/src/main/kotlin/org/fdroid/ui/utils/PreviewUtils.kt @@ -132,6 +132,8 @@ val testApp = AppDetailsItem( checkUserConfirmation = { _, _ -> }, cancelInstall = {}, onUninstallResult = { _, _ -> }, + onRepoChanged = {}, + onPreferredRepoChanged = {}, allowBetaVersions = {}, ignoreAllUpdates = {}, ignoreThisUpdate = {},