From c28a2834ae584515060f04c997e5eb6941703506 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Sat, 11 Jun 2022 12:38:37 +0200 Subject: [PATCH] Fixed status scroll state being lost when staging files + reduced blinking on status view. --- src/main/kotlin/app/ui/UncommitedChanges.kt | 12 ++++++- .../kotlin/app/viewmodels/StatusViewModel.kt | 35 +++++++++++++++---- 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/main/kotlin/app/ui/UncommitedChanges.kt b/src/main/kotlin/app/ui/UncommitedChanges.kt index 1f96b25..7f58344 100644 --- a/src/main/kotlin/app/ui/UncommitedChanges.kt +++ b/src/main/kotlin/app/ui/UncommitedChanges.kt @@ -8,6 +8,7 @@ import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut import androidx.compose.foundation.* import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyListState import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CornerSize import androidx.compose.material.* @@ -55,17 +56,22 @@ fun UncommitedChanges( ) { val stageStatusState = statusViewModel.stageStatus.collectAsState() var commitMessage by remember { mutableStateOf(statusViewModel.savedCommitMessage.message) } + val stagedListState by statusViewModel.stagedLazyListState.collectAsState() + val unstagedListState by statusViewModel.unstagedLazyListState.collectAsState() val stageStatus = stageStatusState.value val staged: List val unstaged: List + val isLoading: Boolean if (stageStatus is StageStatus.Loaded) { staged = stageStatus.staged unstaged = stageStatus.unstaged + isLoading = stageStatus.isPartiallyReloading } else { staged = listOf() unstaged = listOf() // return empty lists if still loading + isLoading = true } val doCommit = { amend: Boolean -> @@ -85,7 +91,7 @@ fun UncommitedChanges( Column { AnimatedVisibility( - visible = stageStatus is StageStatus.Loading, + visible = isLoading, enter = fadeIn(), exit = fadeOut(), ) { @@ -103,6 +109,7 @@ fun UncommitedChanges( selectedEntryType = if (selectedEntryType is DiffEntryType.StagedDiff) selectedEntryType else null, actionColor = MaterialTheme.colors.unstageButton, statusEntries = staged, + lazyListState = stagedListState, onDiffEntrySelected = onStagedDiffEntrySelected, onDiffEntryOptionSelected = { statusViewModel.unstage(it) @@ -131,6 +138,7 @@ fun UncommitedChanges( selectedEntryType = if (selectedEntryType is DiffEntryType.UnstagedDiff) selectedEntryType else null, actionColor = MaterialTheme.colors.stageButton, statusEntries = unstaged, + lazyListState = unstagedListState, onDiffEntrySelected = onUnstagedDiffEntrySelected, onDiffEntryOptionSelected = { statusViewModel.stage(it) @@ -399,6 +407,7 @@ private fun EntriesList( actionTitle: String, actionColor: Color, statusEntries: List, + lazyListState: LazyListState, onDiffEntrySelected: (StatusEntry) -> Unit, onDiffEntryOptionSelected: (StatusEntry) -> Unit, onGenerateContextMenu: (StatusEntry) -> List, @@ -435,6 +444,7 @@ private fun EntriesList( modifier = Modifier .fillMaxSize() .background(MaterialTheme.colors.background), + state = lazyListState, ) { itemsIndexed(statusEntries) { index, statusEntry -> val isEntrySelected = selectedEntryType != null && diff --git a/src/main/kotlin/app/viewmodels/StatusViewModel.kt b/src/main/kotlin/app/viewmodels/StatusViewModel.kt index cf686a6..d3131b2 100644 --- a/src/main/kotlin/app/viewmodels/StatusViewModel.kt +++ b/src/main/kotlin/app/viewmodels/StatusViewModel.kt @@ -1,5 +1,7 @@ package app.viewmodels +import androidx.compose.foundation.lazy.LazyListState +import app.extensions.delayedStateChange import app.extensions.isMerging import app.git.* import kotlinx.coroutines.Dispatchers @@ -13,6 +15,8 @@ import org.eclipse.jgit.lib.RepositoryState import java.io.File import javax.inject.Inject +private const val MIN_TIME_IN_MS_TO_SHOW_LOAD = 500L + class StatusViewModel @Inject constructor( private val tabState: TabState, private val statusManager: StatusManager, @@ -20,7 +24,7 @@ class StatusViewModel @Inject constructor( private val mergeManager: MergeManager, private val logManager: LogManager, ) { - private val _stageStatus = MutableStateFlow(StageStatus.Loaded(listOf(), listOf())) + private val _stageStatus = MutableStateFlow(StageStatus.Loaded(listOf(), listOf(), false)) val stageStatus: StateFlow = _stageStatus var savedCommitMessage = CommitMessage("", MessageType.NORMAL) @@ -29,6 +33,9 @@ class StatusViewModel @Inject constructor( private var lastUncommitedChangesState = false + val stagedLazyListState = MutableStateFlow(LazyListState(0, 0)) + val unstagedLazyListState = MutableStateFlow(LazyListState(0, 0)) + /** * Notify the UI that the commit message has been changed by the view model */ @@ -103,12 +110,22 @@ class StatusViewModel @Inject constructor( } try { - _stageStatus.value = StageStatus.Loading - val status = statusManager.getStatus(git) - val staged = statusManager.getStaged(status) - val unstaged = statusManager.getUnstaged(status) + delayedStateChange( + delayMs = MIN_TIME_IN_MS_TO_SHOW_LOAD, + onDelayTriggered = { + if (previousStatus is StageStatus.Loaded) { + _stageStatus.value = previousStatus.copy(isPartiallyReloading = true) + } else { + _stageStatus.value = StageStatus.Loading + } + } + ) { + val status = statusManager.getStatus(git) + val staged = statusManager.getStaged(status) + val unstaged = statusManager.getUnstaged(status) - _stageStatus.value = StageStatus.Loaded(staged, unstaged) + _stageStatus.value = StageStatus.Loaded(staged, unstaged, isPartiallyReloading = false) + } } catch (ex: Exception) { _stageStatus.value = previousStatus throw ex @@ -205,7 +222,11 @@ class StatusViewModel @Inject constructor( sealed class StageStatus { object Loading : StageStatus() - data class Loaded(val staged: List, val unstaged: List) : StageStatus() + data class Loaded( + val staged: List, + val unstaged: List, + val isPartiallyReloading: Boolean + ) : StageStatus() } data class CommitMessage(val message: String, val messageType: MessageType)