From 4c48cd995e529e523f13ff4c9828e519bd67cb55 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Mon, 27 Jun 2022 20:36:24 +0200 Subject: [PATCH] Implemented manual refresh with F5 --- src/main/kotlin/app/git/TabState.kt | 96 +++---- src/main/kotlin/app/ui/RepositoryOpen.kt | 249 ++++++++++-------- .../kotlin/app/viewmodels/TabViewModel.kt | 9 +- 3 files changed, 195 insertions(+), 159 deletions(-) diff --git a/src/main/kotlin/app/git/TabState.kt b/src/main/kotlin/app/git/TabState.kt index 3c5054c..d07e2ff 100644 --- a/src/main/kotlin/app/git/TabState.kt +++ b/src/main/kotlin/app/git/TabState.kt @@ -115,34 +115,36 @@ class TabState @Inject constructor( refreshEvenIfCrashes: Boolean = false, block: suspend (git: Git) -> Unit ) = managerScope.launch(Dispatchers.IO) { - var hasProcessFailed = false + mutex.withLock { + var hasProcessFailed = false - operationRunning = true - try { - block(safeGit) + operationRunning = true + try { + block(safeGit) - if (refreshType != RefreshType.NONE) - _refreshData.emit(refreshType) - } catch (ex: Exception) { - ex.printStackTrace() + if (refreshType != RefreshType.NONE) + _refreshData.emit(refreshType) + } catch (ex: Exception) { + ex.printStackTrace() - hasProcessFailed = true + hasProcessFailed = true - if (showError) - errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) - } finally { - launch { - // Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the - // filesystem, therefore notifying late and being operationRunning already false (which leads to a full - // refresh because there have been changes in the git dir). This can be easily triggered by interactive - // rebase. - delay(500) - operationRunning = false + if (showError) + errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) + } finally { + launch { + // Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the + // filesystem, therefore notifying late and being operationRunning already false (which leads to a full + // refresh because there have been changes in the git dir). This can be easily triggered by interactive + // rebase. + delay(500) + operationRunning = false + } + + + if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes)) + _refreshData.emit(refreshType) } - - - if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes)) - _refreshData.emit(refreshType) } } @@ -152,34 +154,36 @@ class TabState @Inject constructor( refreshEvenIfCrashes: Boolean = false, block: suspend (git: Git) -> Unit ) = withContext(Dispatchers.IO) { - var hasProcessFailed = false + mutex.withLock { + var hasProcessFailed = false - operationRunning = true - try { - block(safeGit) + operationRunning = true + try { + block(safeGit) - if (refreshType != RefreshType.NONE) - _refreshData.emit(refreshType) - } catch (ex: Exception) { - ex.printStackTrace() + if (refreshType != RefreshType.NONE) + _refreshData.emit(refreshType) + } catch (ex: Exception) { + ex.printStackTrace() - hasProcessFailed = true + hasProcessFailed = true - if (showError) - errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) - } finally { - launch { - // Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the - // filesystem, therefore notifying late and being operationRunning already false (which leads to a full - // refresh because there have been changes in the git dir). This can be easily triggered by interactive - // rebase. - delay(500) - operationRunning = false + if (showError) + errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) + } finally { + launch { + // Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the + // filesystem, therefore notifying late and being operationRunning already false (which leads to a full + // refresh because there have been changes in the git dir). This can be easily triggered by interactive + // rebase. + delay(500) + operationRunning = false + } + + + if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes)) + _refreshData.emit(refreshType) } - - - if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes)) - _refreshData.emit(refreshType) } } diff --git a/src/main/kotlin/app/ui/RepositoryOpen.kt b/src/main/kotlin/app/ui/RepositoryOpen.kt index 0140f1c..4d375b9 100644 --- a/src/main/kotlin/app/ui/RepositoryOpen.kt +++ b/src/main/kotlin/app/ui/RepositoryOpen.kt @@ -3,13 +3,21 @@ package app.ui import androidx.compose.foundation.background +import androidx.compose.foundation.focusable import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester import androidx.compose.ui.graphics.Color +import androidx.compose.ui.input.key.Key +import androidx.compose.ui.input.key.key +import androidx.compose.ui.input.key.onKeyEvent +import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.pointer.PointerIcon import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.unit.dp @@ -79,7 +87,25 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) { } } - Column { + val focusRequester = remember { FocusRequester() } + + LaunchedEffect(selectedItem) { + focusRequester.requestFocus() + } + + Column( + modifier = Modifier + .focusRequester(focusRequester) + .focusable() + .onKeyEvent { event -> + if (event.key == Key.F5) { + tabViewModel.refreshAll() + true + } else { + false + } + } + ) { val rebaseInteractiveViewModel = tabViewModel.rebaseInteractiveViewModel if (repositoryState == RepositoryState.REBASING_INTERACTIVE && rebaseInteractiveViewModel != null) { @@ -166,6 +192,7 @@ fun RepoContent( } +@OptIn(ExperimentalComposeUiApi::class) @Composable fun MainContentView( tabViewModel: TabViewModel, @@ -174,134 +201,132 @@ fun MainContentView( repositoryState: RepositoryState, blameState: BlameState ) { - Row { - HorizontalSplitPane { - first(minSize = 250.dp) { - ScrollableColumn(modifier = Modifier.fillMaxHeight( )) { - Branches( - branchesViewModel = tabViewModel.branchesViewModel, - ) - Remotes( - remotesViewModel = tabViewModel.remotesViewModel, - ) - Tags( - tagsViewModel = tabViewModel.tagsViewModel, - ) - Stashes( - stashesViewModel = tabViewModel.stashesViewModel, - ) - } + HorizontalSplitPane { + first(minSize = 250.dp) { + ScrollableColumn(modifier = Modifier.fillMaxHeight()) { + Branches( + branchesViewModel = tabViewModel.branchesViewModel, + ) + Remotes( + remotesViewModel = tabViewModel.remotesViewModel, + ) + Tags( + tagsViewModel = tabViewModel.tagsViewModel, + ) + Stashes( + stashesViewModel = tabViewModel.stashesViewModel, + ) } + } - splitter { - this.repositorySplitter() - } + splitter { + this.repositorySplitter() + } - second { - HorizontalSplitPane( - splitPaneState = rememberSplitPaneState(0.9f) - ) { - first { - Box( - modifier = Modifier - .fillMaxSize() - ) { - if (blameState is BlameState.Loaded && !blameState.isMinimized) { - Blame( - filePath = blameState.filePath, - blameResult = blameState.blameResult, - onClose = { tabViewModel.resetBlameState() }, - onSelectCommit = { tabViewModel.selectCommit(it) } - ) - } else { - Column { - Box(modifier = Modifier.weight(1f, true)) { - when (diffSelected) { - null -> { - Log( - logViewModel = tabViewModel.logViewModel, - selectedItem = selectedItem, - repositoryState = repositoryState, + second { + HorizontalSplitPane( + splitPaneState = rememberSplitPaneState(0.9f) + ) { + first { + Box( + modifier = Modifier + .fillMaxSize() + ) { + if (blameState is BlameState.Loaded && !blameState.isMinimized) { + Blame( + filePath = blameState.filePath, + blameResult = blameState.blameResult, + onClose = { tabViewModel.resetBlameState() }, + onSelectCommit = { tabViewModel.selectCommit(it) } + ) + } else { + Column { + Box(modifier = Modifier.weight(1f, true)) { + when (diffSelected) { + null -> { + Log( + logViewModel = tabViewModel.logViewModel, + selectedItem = selectedItem, + repositoryState = repositoryState, + ) + } + else -> { + val diffViewModel = tabViewModel.diffViewModel + + if (diffViewModel != null) { + Diff( + diffViewModel = diffViewModel, + onCloseDiffView = { + tabViewModel.newDiffSelected = null + } ) } - else -> { - val diffViewModel = tabViewModel.diffViewModel - - if (diffViewModel != null) { - Diff( - diffViewModel = diffViewModel, - onCloseDiffView = { - tabViewModel.newDiffSelected = null - } - ) - } - } } } + } - if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here - MinimizedBlame( - filePath = blameState.filePath, - onExpand = { tabViewModel.expandBlame() }, - onClose = { tabViewModel.resetBlameState() } - ) - } + if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here + MinimizedBlame( + filePath = blameState.filePath, + onExpand = { tabViewModel.expandBlame() }, + onClose = { tabViewModel.resetBlameState() } + ) } } } } + } - splitter { - this.repositorySplitter() - } + splitter { + this.repositorySplitter() + } - second(minSize = 300.dp) { - Box( - modifier = Modifier - .fillMaxHeight() - ) { - val safeSelectedItem = selectedItem - if (safeSelectedItem == SelectedItem.UncommitedChanges) { - UncommitedChanges( - statusViewModel = tabViewModel.statusViewModel, - selectedEntryType = diffSelected, - repositoryState = repositoryState, - onStagedDiffEntrySelected = { diffEntry -> - tabViewModel.minimizeBlame() - - tabViewModel.newDiffSelected = if (diffEntry != null) { - if (repositoryState == RepositoryState.SAFE) - DiffEntryType.SafeStagedDiff(diffEntry) - else - DiffEntryType.UnsafeStagedDiff(diffEntry) - } else { - null - } - }, - onUnstagedDiffEntrySelected = { diffEntry -> - tabViewModel.minimizeBlame() + second(minSize = 300.dp) { + Box( + modifier = Modifier + .fillMaxHeight() + ) { + val safeSelectedItem = selectedItem + if (safeSelectedItem == SelectedItem.UncommitedChanges) { + UncommitedChanges( + statusViewModel = tabViewModel.statusViewModel, + selectedEntryType = diffSelected, + repositoryState = repositoryState, + onStagedDiffEntrySelected = { diffEntry -> + tabViewModel.minimizeBlame() + tabViewModel.newDiffSelected = if (diffEntry != null) { if (repositoryState == RepositoryState.SAFE) - tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry) + DiffEntryType.SafeStagedDiff(diffEntry) else - tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry) - }, - onBlameFile = { tabViewModel.blameFile(it) }, - onHistoryFile = { tabViewModel.fileHistory(it) } - ) - } else if (safeSelectedItem is SelectedItem.CommitBasedItem) { - CommitChanges( - commitChangesViewModel = tabViewModel.commitChangesViewModel, - selectedItem = safeSelectedItem, - diffSelected = diffSelected, - onDiffSelected = { diffEntry -> - tabViewModel.minimizeBlame() - tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry) - }, - onBlame = { tabViewModel.blameFile(it) }, - onHistory = { tabViewModel.fileHistory(it) }, - ) - } + DiffEntryType.UnsafeStagedDiff(diffEntry) + } else { + null + } + }, + onUnstagedDiffEntrySelected = { diffEntry -> + tabViewModel.minimizeBlame() + + if (repositoryState == RepositoryState.SAFE) + tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry) + else + tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry) + }, + onBlameFile = { tabViewModel.blameFile(it) }, + onHistoryFile = { tabViewModel.fileHistory(it) } + ) + } else if (safeSelectedItem is SelectedItem.CommitBasedItem) { + CommitChanges( + commitChangesViewModel = tabViewModel.commitChangesViewModel, + selectedItem = safeSelectedItem, + diffSelected = diffSelected, + onDiffSelected = { diffEntry -> + tabViewModel.minimizeBlame() + tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry) + }, + onBlame = { tabViewModel.blameFile(it) }, + onHistory = { tabViewModel.fileHistory(it) }, + ) } } } diff --git a/src/main/kotlin/app/viewmodels/TabViewModel.kt b/src/main/kotlin/app/viewmodels/TabViewModel.kt index 0db4c5d..f089258 100644 --- a/src/main/kotlin/app/viewmodels/TabViewModel.kt +++ b/src/main/kotlin/app/viewmodels/TabViewModel.kt @@ -313,7 +313,7 @@ class TabViewModel @Inject constructor( loadRepositoryState(git) } - private suspend fun refreshRepositoryInfo() = tabState.safeProcessing( + private fun refreshRepositoryInfo() = tabState.safeProcessing( refreshType = RefreshType.NONE, ) { git -> loadRepositoryState(git) @@ -427,6 +427,13 @@ class TabViewModel @Inject constructor( _showHistory.value = false historyViewModel = null } + + fun refreshAll() { + printLog(TAG, "Manual refresh triggered") + if (!tabState.operationRunning) { + refreshRepositoryInfo() + } + } }