From 08536b2caa257638a92364dff94af1ef9aa1ec61 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Wed, 5 Oct 2022 21:27:55 +0200 Subject: [PATCH] Removed scroll to top in favor of workspace button --- .../com/jetpackduba/gitnuro/git/TabState.kt | 14 +++- .../com/jetpackduba/gitnuro/git/TaskEvent.kt | 2 + .../kotlin/com/jetpackduba/gitnuro/ui/Menu.kt | 28 +++++-- .../jetpackduba/gitnuro/ui/RepositoryOpen.kt | 2 + .../com/jetpackduba/gitnuro/ui/log/Log.kt | 74 +++++++------------ .../gitnuro/viewmodels/LogViewModel.kt | 33 ++++++--- .../gitnuro/viewmodels/StashesViewModel.kt | 8 +- .../gitnuro/viewmodels/TabViewModel.kt | 14 +++- src/main/resources/computer.svg | 1 + 9 files changed, 104 insertions(+), 72 deletions(-) create mode 100644 src/main/resources/computer.svg diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/TabState.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/TabState.kt index 277f9e0..8f4190d 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/TabState.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/TabState.kt @@ -179,11 +179,11 @@ class TabState @Inject constructor( _refreshData.emit(refreshType) } - fun newSelectedStash(stash: RevCommit) { + suspend fun newSelectedStash(stash: RevCommit) { newSelectedItem(SelectedItem.Stash(stash)) } - fun noneSelected() { + suspend fun noneSelected() { newSelectedItem(SelectedItem.None) } @@ -194,7 +194,9 @@ class TabState @Inject constructor( newSelectedItem(SelectedItem.None) } else { val commit = findCommit(git, objectId) - newSelectedItem(SelectedItem.Ref(commit)) + val newSelectedItem = SelectedItem.Ref(commit) + newSelectedItem(newSelectedItem) + _taskEvent.emit(TaskEvent.ScrollToGraphItem(newSelectedItem)) } } @@ -202,8 +204,12 @@ class TabState @Inject constructor( return git.repository.parseCommit(objectId) } - fun newSelectedItem(selectedItem: SelectedItem) { + suspend fun newSelectedItem(selectedItem: SelectedItem, scrollToItem: Boolean = false) { _selectedItem.value = selectedItem + + if (scrollToItem) { + _taskEvent.emit(TaskEvent.ScrollToGraphItem(selectedItem)) + } } suspend fun emitNewTaskEvent(taskEvent: TaskEvent) { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/git/TaskEvent.kt b/src/main/kotlin/com/jetpackduba/gitnuro/git/TaskEvent.kt index 472ff68..53687f6 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/git/TaskEvent.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/git/TaskEvent.kt @@ -1,7 +1,9 @@ package com.jetpackduba.gitnuro.git +import com.jetpackduba.gitnuro.ui.SelectedItem import org.eclipse.jgit.revwalk.RevCommit sealed interface TaskEvent { data class RebaseInteractive(val revCommit: RevCommit) : TaskEvent + data class ScrollToGraphItem(val selectedItem: SelectedItem) : TaskEvent } \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt index f316360..9a6e216 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/Menu.kt @@ -14,20 +14,16 @@ import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier -import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.graphics.painter.Painter -import androidx.compose.ui.input.pointer.PointerIconDefaults -import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import com.jetpackduba.gitnuro.extensions.handMouseClickable import com.jetpackduba.gitnuro.extensions.handOnHover import com.jetpackduba.gitnuro.extensions.ignoreKeyEvents -import com.jetpackduba.gitnuro.theme.primaryTextColor import com.jetpackduba.gitnuro.ui.context_menu.* import com.jetpackduba.gitnuro.viewmodels.MenuViewModel @@ -37,6 +33,7 @@ fun Menu( modifier: Modifier, menuViewModel: MenuViewModel, onCreateBranch: () -> Unit, + onGoToWorkspace: () -> Unit, onStashWithMessage: () -> Unit, ) { var showAdditionalOptionsDropDownMenu by remember { mutableStateOf(false) } @@ -46,6 +43,15 @@ fun Menu( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { + MenuButton( + modifier = Modifier + .padding(start = 16.dp), + title = "Workspace", + icon = painterResource("computer.svg"), + onClick = onGoToWorkspace, + fixedWidth = false, + ) + Spacer(modifier = Modifier.weight(1f)) ExtendedMenuButton( @@ -144,6 +150,7 @@ fun MenuButton( enabled: Boolean = true, title: String, icon: Painter, + fixedWidth: Boolean = true, onClick: () -> Unit ) { Row( @@ -152,7 +159,12 @@ fun MenuButton( .clip(RoundedCornerShape(4.dp)) .background(MaterialTheme.colors.primary) .handMouseClickable { if (enabled) onClick() } - .width(100.dp), + .run { + return@run if (fixedWidth) { + this.width(100.dp) + } else + this.padding(horizontal = 16.dp) + }, horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, ) { @@ -167,7 +179,7 @@ fun MenuButton( Text( text = title, style = MaterialTheme.typography.body2, - modifier = Modifier.padding(start = 2.dp, top = 8.dp, bottom = 8.dp), + modifier = Modifier.padding(start = 2.dp, top = 8.dp, bottom = 8.dp), maxLines = 1, textAlign = TextAlign.Center, color = MaterialTheme.colors.onPrimary, @@ -209,7 +221,7 @@ fun ExtendedMenuButton( ) Text( text = title, - modifier = Modifier.padding(start = 2.dp, top = 8.dp, bottom = 8.dp), + modifier = Modifier.padding(start = 2.dp, top = 8.dp, bottom = 8.dp), style = MaterialTheme.typography.body2, color = MaterialTheme.colors.onPrimary, ) diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt index aded278..a80e914 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt @@ -136,6 +136,7 @@ fun RepositoryOpenPage(tabViewModel: TabViewModel) { menuViewModel = tabViewModel.menuViewModel, onCreateBranch = { showNewBranchDialog = true }, onStashWithMessage = { showStashWithMessageDialog = true }, + onGoToWorkspace = { tabViewModel.selectUncommitedChanges() } ) RepoContent(tabViewModel, diffSelected, selectedItem, repositoryState, blameState, showHistory) @@ -322,6 +323,7 @@ fun RepoContent( } +@OptIn(ExperimentalSplitPaneApi::class) @Composable fun MainContentView( tabViewModel: TabViewModel, diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt index 4c90478..30e714c 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/log/Log.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.input.key.KeyEventType import androidx.compose.ui.input.key.onPreviewKeyEvent import androidx.compose.ui.input.key.type import androidx.compose.ui.input.pointer.PointerIcon -import androidx.compose.ui.input.pointer.PointerIconDefaults import androidx.compose.ui.input.pointer.pointerHoverIcon import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.res.painterResource @@ -38,23 +37,23 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -import com.jetpackduba.gitnuro.git.workspace.StatusSummary +import com.jetpackduba.gitnuro.extensions.* import com.jetpackduba.gitnuro.git.graph.GraphCommitList import com.jetpackduba.gitnuro.git.graph.GraphNode +import com.jetpackduba.gitnuro.git.workspace.StatusSummary import com.jetpackduba.gitnuro.keybindings.KeybindingOption import com.jetpackduba.gitnuro.keybindings.matchesBinding +import com.jetpackduba.gitnuro.theme.* import com.jetpackduba.gitnuro.ui.SelectedItem import com.jetpackduba.gitnuro.ui.components.AvatarImage import com.jetpackduba.gitnuro.ui.components.ScrollableLazyColumn +import com.jetpackduba.gitnuro.ui.context_menu.* import com.jetpackduba.gitnuro.ui.dialogs.NewBranchDialog import com.jetpackduba.gitnuro.ui.dialogs.NewTagDialog import com.jetpackduba.gitnuro.ui.dialogs.ResetBranchDialog import com.jetpackduba.gitnuro.viewmodels.LogSearch import com.jetpackduba.gitnuro.viewmodels.LogStatus import com.jetpackduba.gitnuro.viewmodels.LogViewModel -import com.jetpackduba.gitnuro.extensions.* -import com.jetpackduba.gitnuro.theme.* -import com.jetpackduba.gitnuro.ui.context_menu.* import kotlinx.coroutines.launch import org.eclipse.jgit.lib.Ref import org.eclipse.jgit.lib.RepositoryState @@ -99,7 +98,6 @@ fun Log( val logStatus = logStatusState.value val showLogDialog by logViewModel.logDialog.collectAsState() - val selectedCommit = if (selectedItem is SelectedItem.CommitBasedItem) { selectedItem.revCommit } else { @@ -107,6 +105,7 @@ fun Log( } if (logStatus is LogStatus.Loaded) { + val coroutineScope = rememberCoroutineScope() val hasUncommitedChanges = logStatus.hasUncommitedChanges val commitList = logStatus.plotCommitList val verticalScrollState by logViewModel.verticalListState.collectAsState() @@ -117,16 +116,16 @@ fun Log( // the proper scroll position verticalScrollState.observeScrollChanges() - LaunchedEffect(selectedCommit) { - // Scroll to commit if a Ref is selected - if (selectedItem is SelectedItem.Ref) { - scrollToCommit(verticalScrollState, commitList, selectedCommit) - } - } - LaunchedEffect(Unit) { - logViewModel.focusCommit.collect { commit -> - scrollToCommit(verticalScrollState, commitList, commit) + coroutineScope.launch { + logViewModel.focusCommit.collect { commit -> + scrollToCommit(verticalScrollState, commitList, commit) + } + } + coroutineScope.launch { + logViewModel.scrollToUncommitedChanges.collect { + scrollToUncommitedChanges(verticalScrollState, commitList) + } } } @@ -218,38 +217,6 @@ fun Log( ), adapter = rememberScrollbarAdapter(horizontalScrollState) ) - - if (verticalScrollState.firstVisibleItemIndex > 0) { - Box( - modifier = Modifier - .align(Alignment.BottomEnd) - .padding(bottom = 16.dp, end = 16.dp) - .clip(RoundedCornerShape(50)) - .handMouseClickable { - scope.launch { - verticalScrollState.scrollToItem(0) - } - } - .background(MaterialTheme.colors.primary) - .padding(vertical = 8.dp, horizontal = 16.dp), - ) { - Row(verticalAlignment = Alignment.CenterVertically) { - Icon( - painterResource("align_top.svg"), - contentDescription = null, - tint = MaterialTheme.colors.onPrimary, - modifier = Modifier.size(18.dp), - ) - - Text( - text = "Scroll to top", - modifier = Modifier.padding(start = 8.dp), - color = MaterialTheme.colors.onPrimary, - style = MaterialTheme.typography.body1, - ) - } - } - } } } } @@ -267,6 +234,14 @@ suspend fun scrollToCommit( if (index >= 0) verticalScrollState.scrollToItem(index) } +suspend fun scrollToUncommitedChanges( + verticalScrollState: LazyListState, + commitList: GraphCommitList, +) { + if (commitList.isNotEmpty()) + verticalScrollState.scrollToItem(0) +} + @Composable fun SearchFilter( logViewModel: LogViewModel, @@ -306,10 +281,12 @@ fun SearchFilter( } true } + keyEvent.matchesBinding(KeybindingOption.EXIT) && keyEvent.type == KeyEventType.KeyUp -> { logViewModel.closeSearch() true } + else -> false } }, @@ -549,16 +526,19 @@ fun LogDialogs( onResetShowLogDialog() }) } + is LogDialog.NewTag -> { NewTagDialog(onReject = onResetShowLogDialog, onAccept = { tagName -> logViewModel.createTagOnCommit(tagName, showLogDialog.graphNode) onResetShowLogDialog() }) } + is LogDialog.ResetBranch -> ResetBranchDialog(onReject = onResetShowLogDialog, onAccept = { resetType -> logViewModel.resetToCommit(showLogDialog.graphNode, resetType) onResetShowLogDialog() }) + LogDialog.None -> { } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt index fd08a4e..f3a1a38 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/LogViewModel.kt @@ -3,8 +3,13 @@ package com.jetpackduba.gitnuro.viewmodels import androidx.compose.foundation.ScrollState import androidx.compose.foundation.lazy.LazyListState import com.jetpackduba.gitnuro.extensions.delayedStateChange +import com.jetpackduba.gitnuro.git.RefreshType +import com.jetpackduba.gitnuro.git.TabState +import com.jetpackduba.gitnuro.git.TaskEvent +import com.jetpackduba.gitnuro.git.branches.* import com.jetpackduba.gitnuro.git.graph.GraphCommitList import com.jetpackduba.gitnuro.git.graph.GraphNode +import com.jetpackduba.gitnuro.git.log.* import com.jetpackduba.gitnuro.git.rebase.RebaseBranchUseCase import com.jetpackduba.gitnuro.git.remote_operations.DeleteRemoteBranchUseCase import com.jetpackduba.gitnuro.git.remote_operations.PullFromSpecificBranchUseCase @@ -12,16 +17,11 @@ import com.jetpackduba.gitnuro.git.remote_operations.PushToSpecificBranchUseCase import com.jetpackduba.gitnuro.git.tags.CreateTagOnCommitUseCase import com.jetpackduba.gitnuro.git.tags.DeleteTagUseCase import com.jetpackduba.gitnuro.git.workspace.CheckHasUncommitedChangedUseCase -import com.jetpackduba.gitnuro.git.RefreshType -import com.jetpackduba.gitnuro.git.TabState import com.jetpackduba.gitnuro.git.workspace.GetStatusSummaryUseCase import com.jetpackduba.gitnuro.git.workspace.StatusSummary import com.jetpackduba.gitnuro.preferences.AppSettings import com.jetpackduba.gitnuro.ui.SelectedItem import com.jetpackduba.gitnuro.ui.log.LogDialog -import com.jetpackduba.gitnuro.git.TaskEvent -import com.jetpackduba.gitnuro.git.branches.* -import com.jetpackduba.gitnuro.git.log.* import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.flow.* @@ -74,8 +74,19 @@ class LogViewModel @Inject constructor( var savedSearchFilter: String = "" var graphPadding = 0f - private val _focusCommit = MutableSharedFlow() - val focusCommit: SharedFlow = _focusCommit + private val scrollToItem: Flow = tabState.taskEvent + .filterIsInstance() + .map { it.selectedItem } + .filterIsInstance() + .map { it.revCommit } + + val scrollToUncommitedChanges: Flow = tabState.taskEvent + .filterIsInstance() + .map { it.selectedItem } + .filterIsInstance() + + private val _focusCommit = MutableSharedFlow() + val focusCommit: Flow = merge(_focusCommit, scrollToItem) private val _logDialog = MutableStateFlow(LogDialog.None) val logDialog: StateFlow = _logDialog @@ -255,7 +266,9 @@ class LogViewModel @Inject constructor( rebaseBranchUseCase(git, ref) } - fun selectUncommitedChanges() { + fun selectUncommitedChanges() = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { tabState.newSelectedItem(SelectedItem.UncommitedChanges) val searchValue = _logSearchFilterResults.value @@ -275,7 +288,9 @@ class LogViewModel @Inject constructor( NONE_MATCHING_INDEX } - fun selectLogLine(commit: GraphNode) { + fun selectLogLine(commit: GraphNode) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { tabState.newSelectedItem(SelectedItem.Commit(commit)) val searchValue = _logSearchFilterResults.value diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StashesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StashesViewModel.kt index 1ad03ec..2b4dae8 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StashesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/StashesViewModel.kt @@ -58,11 +58,15 @@ class StashesViewModel @Inject constructor( stashDropped(stash) } - fun selectTab(stash: RevCommit) { + fun selectTab(stash: RevCommit) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { tabState.newSelectedStash(stash) } - private fun stashDropped(stash: RevCommit) { + private fun stashDropped(stash: RevCommit) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { val selectedValue = tabState.selectedItem.value if ( selectedValue is SelectedItem.Stash && diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt index eee0a54..89c9d7e 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt @@ -4,10 +4,10 @@ import com.jetpackduba.gitnuro.AppStateManager import com.jetpackduba.gitnuro.ErrorsManager import com.jetpackduba.gitnuro.credentials.CredentialsState import com.jetpackduba.gitnuro.credentials.CredentialsStateManager +import com.jetpackduba.gitnuro.git.* import com.jetpackduba.gitnuro.git.repository.GetRepositoryStateUseCase import com.jetpackduba.gitnuro.git.repository.InitLocalRepositoryUseCase import com.jetpackduba.gitnuro.git.repository.OpenRepositoryUseCase -import com.jetpackduba.gitnuro.git.* import com.jetpackduba.gitnuro.logging.printLog import com.jetpackduba.gitnuro.models.AuthorInfoSimple import com.jetpackduba.gitnuro.newErrorNow @@ -130,6 +130,8 @@ class TabViewModel @Inject constructor( tabState.taskEvent.collect { taskEvent -> when (taskEvent) { is TaskEvent.RebaseInteractive -> onRebaseInteractive(taskEvent) + else -> { /*Nothing to do here*/ + } } } } @@ -429,10 +431,18 @@ class TabViewModel @Inject constructor( } } - fun selectCommit(commit: RevCommit) { + fun selectCommit(commit: RevCommit) = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { tabState.newSelectedItem(SelectedItem.Commit(commit)) } + fun selectUncommitedChanges() = tabState.runOperation( + refreshType = RefreshType.NONE, + ) { + tabState.newSelectedItem(SelectedItem.UncommitedChanges, true) + } + fun fileHistory(filePath: String) { historyViewModel = historyViewModelProvider.get() historyViewModel?.fileHistory(filePath) diff --git a/src/main/resources/computer.svg b/src/main/resources/computer.svg new file mode 100644 index 0000000..4191072 --- /dev/null +++ b/src/main/resources/computer.svg @@ -0,0 +1 @@ + \ No newline at end of file