From 747384fb59e3fb8ed5fe4d5e398be763d39eb08d Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Thu, 8 Oct 2020 10:16:51 -0300 Subject: [PATCH] Refactor InstallResult to be more extensible --- .../install/InstallProgressFragment.kt | 6 +- .../restore/install/InstallResult.kt | 56 ++++++++++++++++--- .../restore/install/ApkRestoreTest.kt | 4 +- 3 files changed, 51 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallProgressFragment.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallProgressFragment.kt index e4ee4589..447fcb3a 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallProgressFragment.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallProgressFragment.kt @@ -15,7 +15,6 @@ import androidx.recyclerview.widget.LinearLayoutManager.VERTICAL import androidx.recyclerview.widget.RecyclerView import com.stevesoltys.seedvault.R import com.stevesoltys.seedvault.restore.RestoreViewModel -import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED import org.koin.androidx.viewmodel.ext.android.sharedViewModel class InstallProgressFragment : Fragment() { @@ -75,12 +74,11 @@ class InstallProgressFragment : Fragment() { // skip this screen, if there are no apps to install if (installResult.isEmpty()) viewModel.onNextClicked() - val result = installResult.filterValues { it.state != QUEUED } val position = layoutManager.findFirstVisibleItemPosition() - adapter.update(result.values) + adapter.update(installResult.getNotQueued()) if (position == 0) layoutManager.scrollToPosition(0) - result.getInProgress()?.let { + installResult.getInProgress()?.let { progressBar.progress = it.progress progressBar.max = it.total } diff --git a/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallResult.kt b/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallResult.kt index 01c06729..99d968b5 100644 --- a/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallResult.kt +++ b/app/src/main/java/com/stevesoltys/seedvault/restore/install/InstallResult.kt @@ -1,28 +1,66 @@ package com.stevesoltys.seedvault.restore.install import android.graphics.drawable.Drawable +import com.stevesoltys.seedvault.restore.install.ApkInstallState.IN_PROGRESS +import com.stevesoltys.seedvault.restore.install.ApkInstallState.QUEUED import java.util.concurrent.ConcurrentHashMap -internal typealias InstallResult = Map +internal interface InstallResult { + /** + * Returns true, if there is no packages to install and false otherwise. + */ + fun isEmpty(): Boolean -internal fun InstallResult.getInProgress(): ApkInstallResult? { - val filtered = filterValues { result -> result.state == ApkInstallState.IN_PROGRESS } - if (filtered.isEmpty()) return null - check(filtered.size == 1) { "More than one package in progress: ${filtered.keys}" } - return filtered.values.first() + /** + * Returns the [ApkInstallResult] of the package currently [IN_PROGRESS] + * or null if there is no such package. + */ + fun getInProgress(): ApkInstallResult? + + /** + * Get all [ApkInstallResult]s that are not in state [QUEUED]. + */ + fun getNotQueued(): Collection + + /** + * Get the [ApkInstallResult] for the given package name or null if none exists. + */ + operator fun get(packageName: String): ApkInstallResult? } -internal class MutableInstallResult(initialCapacity: Int) : - ConcurrentHashMap(initialCapacity) { +internal class MutableInstallResult(initialCapacity: Int) : InstallResult { + + private val installResults = ConcurrentHashMap(initialCapacity) + + override fun isEmpty() = installResults.isEmpty() + + override fun getInProgress(): ApkInstallResult? { + val filtered = installResults.filterValues { result -> result.state == IN_PROGRESS } + if (filtered.isEmpty()) return null + check(filtered.size == 1) { "More than one package in progress: ${filtered.keys}" } + return filtered.values.first() + } + + override fun getNotQueued(): Collection { + return installResults.filterValues { result -> result.state != QUEUED }.values + } + + override fun get(packageName: String) = installResults[packageName] + + operator fun set(packageName: String, installResult: ApkInstallResult) { + installResults[packageName] = installResult + } + fun update( packageName: String, updateFun: (ApkInstallResult) -> ApkInstallResult ): MutableInstallResult { val result = get(packageName) check(result != null) { "ApkRestoreResult for $packageName does not exist." } - set(packageName, updateFun(result)) + installResults[packageName] = updateFun(result) return this } + } internal data class ApkInstallResult( diff --git a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt index 7cda2601..d68418dc 100644 --- a/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt +++ b/app/src/test/java/com/stevesoltys/seedvault/restore/install/ApkRestoreTest.kt @@ -167,7 +167,7 @@ internal class ApkRestoreTest : TransportTest() { @Test fun `test successful run`(@TempDir tmpDir: Path) = runBlocking { val installResult = MutableInstallResult(1).apply { - put( + set( packageName, ApkInstallResult( packageName, progress = 1, @@ -244,7 +244,7 @@ internal class ApkRestoreTest : TransportTest() { every { installedPackageInfo.longVersionCode } returns packageMetadata.version!! - 1 if (!willFail) { val installResult = MutableInstallResult(1).apply { - put( + set( packageName, ApkInstallResult(packageName, progress = 1, total = 1, state = SUCCEEDED) )