Refactor InstallResult to be more extensible

This commit is contained in:
Torsten Grote 2020-10-08 10:16:51 -03:00 committed by Chirayu Desai
parent f45411d81b
commit 747384fb59
3 changed files with 51 additions and 15 deletions

View file

@ -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
}

View file

@ -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<String, ApkInstallResult>
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 }
/**
* 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<ApkInstallResult>
/**
* Get the [ApkInstallResult] for the given package name or null if none exists.
*/
operator fun get(packageName: String): ApkInstallResult?
}
internal class MutableInstallResult(initialCapacity: Int) : InstallResult {
private val installResults = ConcurrentHashMap<String, ApkInstallResult>(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<ApkInstallResult> {
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
}
internal class MutableInstallResult(initialCapacity: Int) :
ConcurrentHashMap<String, ApkInstallResult>(initialCapacity) {
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(

View file

@ -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)
)