Removed scroll to top in favor of workspace button
This commit is contained in:
parent
2ffb8d9038
commit
08536b2caa
@ -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) {
|
||||
|
@ -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
|
||||
}
|
@ -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,
|
||||
)
|
||||
|
@ -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,
|
||||
|
@ -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 -> {
|
||||
}
|
||||
}
|
||||
|
@ -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<GraphNode>()
|
||||
val focusCommit: SharedFlow<GraphNode> = _focusCommit
|
||||
private val scrollToItem: Flow<RevCommit> = tabState.taskEvent
|
||||
.filterIsInstance<TaskEvent.ScrollToGraphItem>()
|
||||
.map { it.selectedItem }
|
||||
.filterIsInstance<SelectedItem.CommitBasedItem>()
|
||||
.map { it.revCommit }
|
||||
|
||||
val scrollToUncommitedChanges: Flow<SelectedItem.UncommitedChanges> = tabState.taskEvent
|
||||
.filterIsInstance<TaskEvent.ScrollToGraphItem>()
|
||||
.map { it.selectedItem }
|
||||
.filterIsInstance<SelectedItem.UncommitedChanges>()
|
||||
|
||||
private val _focusCommit = MutableSharedFlow<RevCommit>()
|
||||
val focusCommit: Flow<RevCommit> = merge(_focusCommit, scrollToItem)
|
||||
|
||||
private val _logDialog = MutableStateFlow<LogDialog>(LogDialog.None)
|
||||
val logDialog: StateFlow<LogDialog> = _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
|
||||
|
@ -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 &&
|
||||
|
@ -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)
|
||||
|
1
src/main/resources/computer.svg
Normal file
1
src/main/resources/computer.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0z" fill="none"/><path d="M20 18c1.1 0 1.99-.9 1.99-2L22 6c0-1.1-.9-2-2-2H4c-1.1 0-2 .9-2 2v10c0 1.1.9 2 2 2H0v2h24v-2h-4zM4 6h16v10H4V6z"/></svg>
|
After Width: | Height: | Size: 268 B |
Loading…
Reference in New Issue
Block a user