Implemented manual refresh with F5

This commit is contained in:
Abdelilah El Aissaoui 2022-06-27 20:36:24 +02:00
parent 0f835edc35
commit 4c48cd995e
3 changed files with 195 additions and 159 deletions

View File

@ -115,34 +115,36 @@ class TabState @Inject constructor(
refreshEvenIfCrashes: Boolean = false, refreshEvenIfCrashes: Boolean = false,
block: suspend (git: Git) -> Unit block: suspend (git: Git) -> Unit
) = managerScope.launch(Dispatchers.IO) { ) = managerScope.launch(Dispatchers.IO) {
var hasProcessFailed = false mutex.withLock {
var hasProcessFailed = false
operationRunning = true operationRunning = true
try { try {
block(safeGit) block(safeGit)
if (refreshType != RefreshType.NONE) if (refreshType != RefreshType.NONE)
_refreshData.emit(refreshType) _refreshData.emit(refreshType)
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
hasProcessFailed = true hasProcessFailed = true
if (showError) if (showError)
errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) errorsManager.addError(newErrorNow(ex, ex.localizedMessage))
} finally { } finally {
launch { launch {
// Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the // 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 // 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 // refresh because there have been changes in the git dir). This can be easily triggered by interactive
// rebase. // rebase.
delay(500) delay(500)
operationRunning = false 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, refreshEvenIfCrashes: Boolean = false,
block: suspend (git: Git) -> Unit block: suspend (git: Git) -> Unit
) = withContext(Dispatchers.IO) { ) = withContext(Dispatchers.IO) {
var hasProcessFailed = false mutex.withLock {
var hasProcessFailed = false
operationRunning = true operationRunning = true
try { try {
block(safeGit) block(safeGit)
if (refreshType != RefreshType.NONE) if (refreshType != RefreshType.NONE)
_refreshData.emit(refreshType) _refreshData.emit(refreshType)
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
hasProcessFailed = true hasProcessFailed = true
if (showError) if (showError)
errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) errorsManager.addError(newErrorNow(ex, ex.localizedMessage))
} finally { } finally {
launch { launch {
// Add a slight delay because sometimes the file watcher takes a few moments to notify a change in the // 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 // 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 // refresh because there have been changes in the git dir). This can be easily triggered by interactive
// rebase. // rebase.
delay(500) delay(500)
operationRunning = false operationRunning = false
}
if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes))
_refreshData.emit(refreshType)
} }
if (refreshType != RefreshType.NONE && (!hasProcessFailed || refreshEvenIfCrashes))
_refreshData.emit(refreshType)
} }
} }

View File

@ -3,13 +3,21 @@
package app.ui package app.ui
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.focusable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier 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.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.PointerIcon
import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.unit.dp 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 val rebaseInteractiveViewModel = tabViewModel.rebaseInteractiveViewModel
if (repositoryState == RepositoryState.REBASING_INTERACTIVE && rebaseInteractiveViewModel != null) { if (repositoryState == RepositoryState.REBASING_INTERACTIVE && rebaseInteractiveViewModel != null) {
@ -166,6 +192,7 @@ fun RepoContent(
} }
@OptIn(ExperimentalComposeUiApi::class)
@Composable @Composable
fun MainContentView( fun MainContentView(
tabViewModel: TabViewModel, tabViewModel: TabViewModel,
@ -174,134 +201,132 @@ fun MainContentView(
repositoryState: RepositoryState, repositoryState: RepositoryState,
blameState: BlameState blameState: BlameState
) { ) {
Row { HorizontalSplitPane {
HorizontalSplitPane { first(minSize = 250.dp) {
first(minSize = 250.dp) { ScrollableColumn(modifier = Modifier.fillMaxHeight()) {
ScrollableColumn(modifier = Modifier.fillMaxHeight( )) { Branches(
Branches( branchesViewModel = tabViewModel.branchesViewModel,
branchesViewModel = tabViewModel.branchesViewModel, )
) Remotes(
Remotes( remotesViewModel = tabViewModel.remotesViewModel,
remotesViewModel = tabViewModel.remotesViewModel, )
) Tags(
Tags( tagsViewModel = tabViewModel.tagsViewModel,
tagsViewModel = tabViewModel.tagsViewModel, )
) Stashes(
Stashes( stashesViewModel = tabViewModel.stashesViewModel,
stashesViewModel = tabViewModel.stashesViewModel, )
)
}
} }
}
splitter { splitter {
this.repositorySplitter() this.repositorySplitter()
} }
second { second {
HorizontalSplitPane( HorizontalSplitPane(
splitPaneState = rememberSplitPaneState(0.9f) splitPaneState = rememberSplitPaneState(0.9f)
) { ) {
first { first {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
) { ) {
if (blameState is BlameState.Loaded && !blameState.isMinimized) { if (blameState is BlameState.Loaded && !blameState.isMinimized) {
Blame( Blame(
filePath = blameState.filePath, filePath = blameState.filePath,
blameResult = blameState.blameResult, blameResult = blameState.blameResult,
onClose = { tabViewModel.resetBlameState() }, onClose = { tabViewModel.resetBlameState() },
onSelectCommit = { tabViewModel.selectCommit(it) } onSelectCommit = { tabViewModel.selectCommit(it) }
) )
} else { } else {
Column { Column {
Box(modifier = Modifier.weight(1f, true)) { Box(modifier = Modifier.weight(1f, true)) {
when (diffSelected) { when (diffSelected) {
null -> { null -> {
Log( Log(
logViewModel = tabViewModel.logViewModel, logViewModel = tabViewModel.logViewModel,
selectedItem = selectedItem, selectedItem = selectedItem,
repositoryState = repositoryState, 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 if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here
MinimizedBlame( MinimizedBlame(
filePath = blameState.filePath, filePath = blameState.filePath,
onExpand = { tabViewModel.expandBlame() }, onExpand = { tabViewModel.expandBlame() },
onClose = { tabViewModel.resetBlameState() } onClose = { tabViewModel.resetBlameState() }
) )
}
} }
} }
} }
} }
}
splitter { splitter {
this.repositorySplitter() this.repositorySplitter()
} }
second(minSize = 300.dp) { second(minSize = 300.dp) {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
) { ) {
val safeSelectedItem = selectedItem val safeSelectedItem = selectedItem
if (safeSelectedItem == SelectedItem.UncommitedChanges) { if (safeSelectedItem == SelectedItem.UncommitedChanges) {
UncommitedChanges( UncommitedChanges(
statusViewModel = tabViewModel.statusViewModel, statusViewModel = tabViewModel.statusViewModel,
selectedEntryType = diffSelected, selectedEntryType = diffSelected,
repositoryState = repositoryState, repositoryState = repositoryState,
onStagedDiffEntrySelected = { diffEntry -> onStagedDiffEntrySelected = { diffEntry ->
tabViewModel.minimizeBlame() tabViewModel.minimizeBlame()
tabViewModel.newDiffSelected = if (diffEntry != null) {
if (repositoryState == RepositoryState.SAFE)
DiffEntryType.SafeStagedDiff(diffEntry)
else
DiffEntryType.UnsafeStagedDiff(diffEntry)
} else {
null
}
},
onUnstagedDiffEntrySelected = { diffEntry ->
tabViewModel.minimizeBlame()
tabViewModel.newDiffSelected = if (diffEntry != null) {
if (repositoryState == RepositoryState.SAFE) if (repositoryState == RepositoryState.SAFE)
tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry) DiffEntryType.SafeStagedDiff(diffEntry)
else else
tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry) DiffEntryType.UnsafeStagedDiff(diffEntry)
}, } else {
onBlameFile = { tabViewModel.blameFile(it) }, null
onHistoryFile = { tabViewModel.fileHistory(it) } }
) },
} else if (safeSelectedItem is SelectedItem.CommitBasedItem) { onUnstagedDiffEntrySelected = { diffEntry ->
CommitChanges( tabViewModel.minimizeBlame()
commitChangesViewModel = tabViewModel.commitChangesViewModel,
selectedItem = safeSelectedItem, if (repositoryState == RepositoryState.SAFE)
diffSelected = diffSelected, tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry)
onDiffSelected = { diffEntry -> else
tabViewModel.minimizeBlame() tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry)
tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry) },
}, onBlameFile = { tabViewModel.blameFile(it) },
onBlame = { tabViewModel.blameFile(it) }, onHistoryFile = { tabViewModel.fileHistory(it) }
onHistory = { 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) },
)
} }
} }
} }

View File

@ -313,7 +313,7 @@ class TabViewModel @Inject constructor(
loadRepositoryState(git) loadRepositoryState(git)
} }
private suspend fun refreshRepositoryInfo() = tabState.safeProcessing( private fun refreshRepositoryInfo() = tabState.safeProcessing(
refreshType = RefreshType.NONE, refreshType = RefreshType.NONE,
) { git -> ) { git ->
loadRepositoryState(git) loadRepositoryState(git)
@ -427,6 +427,13 @@ class TabViewModel @Inject constructor(
_showHistory.value = false _showHistory.value = false
historyViewModel = null historyViewModel = null
} }
fun refreshAll() {
printLog(TAG, "Manual refresh triggered")
if (!tabState.operationRunning) {
refreshRepositoryInfo()
}
}
} }