Skip to content

Commit

Permalink
always sync release state to main activity
Browse files Browse the repository at this point in the history
  • Loading branch information
qimiko committed Jan 6, 2024
1 parent 7bd9c39 commit 88cba69
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 26 deletions.
2 changes: 2 additions & 0 deletions app/src/main/java/com/geode/launcher/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ fun MainScreen(
LaunchedEffect(shouldUpdate) {
if (shouldUpdate && !releaseViewModel.hasPerformedCheck) {
releaseViewModel.runReleaseCheck()
} else {
releaseViewModel.useGlobalCheckState()
}
}

Expand Down
37 changes: 23 additions & 14 deletions app/src/main/java/com/geode/launcher/api/ReleaseViewModel.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ import androidx.lifecycle.viewmodel.initializer
import androidx.lifecycle.viewmodel.viewModelFactory
import com.geode.launcher.utils.ReleaseManager
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.transformWhile
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch

class ReleaseViewModel(private val application: Application): ViewModel() {
Expand Down Expand Up @@ -65,26 +66,34 @@ class ReleaseViewModel(private val application: Application): ViewModel() {
}
}

private suspend fun syncUiState(
flow: StateFlow<ReleaseManager.ReleaseManagerState>
) {
flow.map(ReleaseUIState::managerStateToUI).collect {
// send the mapped state to the ui
_uiState.value = it
}
}

fun useGlobalCheckState() {
hasPerformedCheck = true

viewModelScope.launch {
val releaseFlow = ReleaseManager.get(application)
.uiState

syncUiState(releaseFlow)
}
}

fun runReleaseCheck() {
hasPerformedCheck = true

viewModelScope.launch {
val releaseFlow = ReleaseManager.get(application)
.checkForUpdates()

releaseFlow
.transformWhile {
// map the ui state into something that can be used
emit(ReleaseUIState.managerStateToUI(it))

// end collection once ReleaseManager reaches a state of "completion"
it !is ReleaseManager.ReleaseManagerState.Finished &&
it !is ReleaseManager.ReleaseManagerState.Failure
}
.collect {
// send the mapped state to the ui
_uiState.value = it
}
syncUiState(releaseFlow)
}
}
}
26 changes: 14 additions & 12 deletions app/src/main/java/com/geode/launcher/utils/ReleaseManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ class ReleaseManager private constructor(

private var updateJob: Job? = null

private val uiState = MutableStateFlow<ReleaseManagerState>(ReleaseManagerState.Finished())
private val _uiState = MutableStateFlow<ReleaseManagerState>(ReleaseManagerState.Finished())
val uiState = _uiState.asStateFlow()

val isInUpdate: Boolean
get() = uiState.value !is ReleaseManagerState.Failure && uiState.value !is ReleaseManagerState.Finished
get() = _uiState.value !is ReleaseManagerState.Failure && _uiState.value !is ReleaseManagerState.Finished

// runs a given function, retrying until it succeeds or max attempts are reached
private suspend fun <R> retry(block: suspend () -> R): R {
Expand All @@ -72,7 +74,7 @@ class ReleaseManager private constructor(
}

private fun sendError(e: Exception) {
uiState.value = ReleaseManagerState.Failure(e)
_uiState.value = ReleaseManagerState.Failure(e)
e.printStackTrace()
}

Expand All @@ -95,13 +97,13 @@ class ReleaseManager private constructor(
val releaseAsset = release.getAndroidDownload()
if (releaseAsset == null) {
val noAssetException = Exception("missing Android download")
uiState.value = ReleaseManagerState.Failure(noAssetException)
_uiState.value = ReleaseManagerState.Failure(noAssetException)

return
}

// set an initial download size
uiState.value = ReleaseManagerState.InDownload(0, releaseAsset.size.toLong())
_uiState.value = ReleaseManagerState.InDownload(0, releaseAsset.size.toLong())

try {
val file = performDownload(releaseAsset.browserDownloadUrl)
Expand All @@ -113,7 +115,7 @@ class ReleaseManager private constructor(

// extraction performed
updatePreferences(release)
uiState.value = ReleaseManagerState.Finished(true)
_uiState.value = ReleaseManagerState.Finished(true)
}

private suspend fun checkForNewRelease() {
Expand All @@ -125,7 +127,7 @@ class ReleaseManager private constructor(
}

if (release == null) {
uiState.value = ReleaseManagerState.Finished()
_uiState.value = ReleaseManagerState.Finished()
return
}

Expand All @@ -136,7 +138,7 @@ class ReleaseManager private constructor(

// check if an update is needed
if (latestVersion <= currentVersion) {
uiState.value = ReleaseManagerState.Finished()
_uiState.value = ReleaseManagerState.Finished()
return
}

Expand All @@ -161,7 +163,7 @@ class ReleaseManager private constructor(

private suspend fun performDownload(url: String): File {
return DownloadUtils.downloadFile(applicationContext, url, "geode-release.zip") { progress, outOf ->
uiState.value = ReleaseManagerState.InDownload(progress, outOf)
_uiState.value = ReleaseManagerState.InDownload(progress, outOf)
}
}

Expand Down Expand Up @@ -191,7 +193,7 @@ class ReleaseManager private constructor(
updateJob?.cancelAndJoin()
updateJob = null

uiState.value = ReleaseManagerState.Finished()
_uiState.value = ReleaseManagerState.Finished()
}

/**
Expand All @@ -201,12 +203,12 @@ class ReleaseManager private constructor(
@OptIn(DelicateCoroutinesApi::class)
fun checkForUpdates(): StateFlow<ReleaseManagerState> {
if (!isInUpdate) {
uiState.value = ReleaseManagerState.InUpdateCheck
_uiState.value = ReleaseManagerState.InUpdateCheck
updateJob = GlobalScope.launch {
checkForNewRelease()
}
}

return uiState.asStateFlow()
return _uiState.asStateFlow()
}
}

0 comments on commit 88cba69

Please sign in to comment.