Added keybindings to pull, push and create branch
This commit is contained in:
parent
0dad158275
commit
761ea59986
@ -42,6 +42,21 @@ enum class KeybindingOption {
|
||||
* Used to go down in lists
|
||||
*/
|
||||
DOWN,
|
||||
|
||||
/**
|
||||
* Used to pull in current repository
|
||||
*/
|
||||
PULL,
|
||||
|
||||
/**
|
||||
* Used to push in current repository
|
||||
*/
|
||||
PUSH,
|
||||
|
||||
/**
|
||||
* Used to show branch creation dialog
|
||||
*/
|
||||
BRANCH_CREATE,
|
||||
}
|
||||
|
||||
|
||||
@ -66,6 +81,15 @@ private fun baseKeybindings() = mapOf(
|
||||
KeybindingOption.DOWN to listOf(
|
||||
Keybinding(key = Key.DirectionDown),
|
||||
),
|
||||
KeybindingOption.PULL to listOf(
|
||||
Keybinding(key = Key.U, control = true),
|
||||
),
|
||||
KeybindingOption.PUSH to listOf(
|
||||
Keybinding(key = Key.P, control = true),
|
||||
),
|
||||
KeybindingOption.BRANCH_CREATE to listOf(
|
||||
Keybinding(key = Key.B, control = true),
|
||||
),
|
||||
)
|
||||
|
||||
private fun linuxKeybindings(): Map<KeybindingOption, List<Keybinding>> = baseKeybindings()
|
||||
|
@ -11,12 +11,14 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.input.key.onKeyEvent
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.jetpackduba.gitnuro.AppConstants
|
||||
import com.jetpackduba.gitnuro.extensions.handMouseClickable
|
||||
import com.jetpackduba.gitnuro.git.DiffType
|
||||
import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
|
||||
import com.jetpackduba.gitnuro.git.remote_operations.PullType
|
||||
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
|
||||
import com.jetpackduba.gitnuro.keybindings.matchesBinding
|
||||
import com.jetpackduba.gitnuro.models.AuthorInfoSimple
|
||||
@ -106,7 +108,31 @@ fun RepositoryOpenPage(
|
||||
LaunchedEffect(selectedItem) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
Column {
|
||||
Column (
|
||||
modifier = Modifier.onPreviewKeyEvent {
|
||||
println("Key event $it")
|
||||
when {
|
||||
it.matchesBinding(KeybindingOption.PULL) -> {
|
||||
tabViewModel.pull(PullType.DEFAULT)
|
||||
true
|
||||
}
|
||||
it.matchesBinding(KeybindingOption.PUSH) -> {
|
||||
tabViewModel.push()
|
||||
true
|
||||
}
|
||||
it.matchesBinding(KeybindingOption.BRANCH_CREATE) -> {
|
||||
if (!showNewBranchDialog) {
|
||||
showNewBranchDialog = true
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
}
|
||||
) {
|
||||
Row(modifier = Modifier.weight(1f)) {
|
||||
Column(
|
||||
modifier = Modifier
|
||||
|
@ -33,6 +33,8 @@ import androidx.compose.ui.unit.dp
|
||||
import com.jetpackduba.gitnuro.AppConstants
|
||||
import com.jetpackduba.gitnuro.AppIcons
|
||||
import com.jetpackduba.gitnuro.extensions.*
|
||||
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
|
||||
import com.jetpackduba.gitnuro.keybindings.matchesBinding
|
||||
import com.jetpackduba.gitnuro.theme.AppTheme
|
||||
import com.jetpackduba.gitnuro.theme.backgroundSelected
|
||||
import com.jetpackduba.gitnuro.theme.onBackgroundSecondary
|
||||
@ -343,8 +345,9 @@ fun RecentRepositoriesList(
|
||||
if (it.type != KeyEventType.KeyDown) {
|
||||
return@onPreviewKeyEvent false
|
||||
}
|
||||
when (it.key) {
|
||||
Key.DirectionDown -> {
|
||||
|
||||
when {
|
||||
it.matchesBinding(KeybindingOption.DOWN) -> {
|
||||
if (focusedItemIndex < filteredRepositories.lastIndex) {
|
||||
focusedItemIndex += 1
|
||||
scope.launch { listState.animateScrollToItem(focusedItemIndex) }
|
||||
@ -352,7 +355,7 @@ fun RecentRepositoriesList(
|
||||
true
|
||||
}
|
||||
|
||||
Key.DirectionUp -> {
|
||||
it.matchesBinding(KeybindingOption.UP) -> {
|
||||
if (focusedItemIndex > 0) {
|
||||
focusedItemIndex -= 1
|
||||
scope.launch { listState.animateScrollToItem(focusedItemIndex) }
|
||||
@ -360,7 +363,7 @@ fun RecentRepositoriesList(
|
||||
true
|
||||
}
|
||||
|
||||
Key.Enter -> {
|
||||
it.matchesBinding(KeybindingOption.SIMPLE_ACCEPT) -> {
|
||||
val repo = filteredRepositories.getOrNull(focusedItemIndex)
|
||||
if (repo != null && isSearchFocused) {
|
||||
onOpenKnownRepository(repo)
|
||||
|
@ -209,10 +209,6 @@ fun Diff(
|
||||
|
||||
ViewDiffResult.None -> throw NotImplementedError("None should be a possible state in the diff")
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
focusRequester.requestFocus()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,104 @@
|
||||
package com.jetpackduba.gitnuro.viewmodels
|
||||
|
||||
import com.jetpackduba.gitnuro.TaskType
|
||||
import com.jetpackduba.gitnuro.git.RefreshType
|
||||
import com.jetpackduba.gitnuro.git.TabState
|
||||
import com.jetpackduba.gitnuro.git.remote_operations.FetchAllRemotesUseCase
|
||||
import com.jetpackduba.gitnuro.git.remote_operations.PullBranchUseCase
|
||||
import com.jetpackduba.gitnuro.git.remote_operations.PullType
|
||||
import com.jetpackduba.gitnuro.git.remote_operations.PushBranchUseCase
|
||||
import com.jetpackduba.gitnuro.git.stash.PopLastStashUseCase
|
||||
import com.jetpackduba.gitnuro.git.stash.StashChangesUseCase
|
||||
import com.jetpackduba.gitnuro.managers.AppStateManager
|
||||
import com.jetpackduba.gitnuro.models.errorNotification
|
||||
import com.jetpackduba.gitnuro.models.positiveNotification
|
||||
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
||||
import com.jetpackduba.gitnuro.terminal.OpenRepositoryInTerminalUseCase
|
||||
import kotlinx.coroutines.Job
|
||||
import javax.inject.Inject
|
||||
|
||||
interface IGlobalMenuActionsViewModel {
|
||||
fun pull(pullType: PullType): Job
|
||||
fun fetchAll(): Job
|
||||
fun push(force: Boolean = false, pushTags: Boolean = false): Job
|
||||
fun stash(): Job
|
||||
fun popStash(): Job
|
||||
fun openTerminal(): Job
|
||||
}
|
||||
|
||||
class GlobalMenuActionsViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val pullBranchUseCase: PullBranchUseCase,
|
||||
private val pushBranchUseCase: PushBranchUseCase,
|
||||
private val fetchAllRemotesUseCase: FetchAllRemotesUseCase,
|
||||
private val popLastStashUseCase: PopLastStashUseCase,
|
||||
private val stashChangesUseCase: StashChangesUseCase,
|
||||
private val openRepositoryInTerminalUseCase: OpenRepositoryInTerminalUseCase,
|
||||
settings: AppSettingsRepository,
|
||||
appStateManager: AppStateManager,
|
||||
) : IGlobalMenuActionsViewModel {
|
||||
override fun pull(pullType: PullType) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Pulling",
|
||||
subtitle = "Pulling changes from the remote branch to the current branch",
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.PULL,
|
||||
) { git ->
|
||||
pullBranchUseCase(git, pullType)
|
||||
|
||||
positiveNotification("Pull completed")
|
||||
}
|
||||
|
||||
override fun fetchAll() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Fetching",
|
||||
subtitle = "Updating references from the remote repositories...",
|
||||
isCancellable = false,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.FETCH,
|
||||
) { git ->
|
||||
fetchAllRemotesUseCase(git)
|
||||
|
||||
positiveNotification("Fetch all completed")
|
||||
}
|
||||
|
||||
override fun push(force: Boolean, pushTags: Boolean) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Push",
|
||||
subtitle = "Pushing current branch to the remote repository",
|
||||
isCancellable = false,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.PUSH,
|
||||
) { git ->
|
||||
pushBranchUseCase(git, force, pushTags)
|
||||
|
||||
positiveNotification("Push completed")
|
||||
}
|
||||
|
||||
override fun stash() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.UNCOMMITTED_CHANGES_AND_LOG,
|
||||
taskType = TaskType.STASH,
|
||||
) { git ->
|
||||
if (stashChangesUseCase(git, null)) {
|
||||
positiveNotification("Changes stashed")
|
||||
} else {
|
||||
errorNotification("There are no changes to stash")
|
||||
}
|
||||
}
|
||||
|
||||
override fun popStash() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.UNCOMMITTED_CHANGES_AND_LOG,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.POP_STASH,
|
||||
) { git ->
|
||||
popLastStashUseCase(git)
|
||||
|
||||
positiveNotification("Stash popped")
|
||||
}
|
||||
|
||||
override fun openTerminal() = tabState.runOperation(
|
||||
refreshType = RefreshType.NONE
|
||||
) { git ->
|
||||
openRepositoryInTerminalUseCase(git.repository.workTree.absolutePath)
|
||||
}
|
||||
}
|
@ -20,80 +20,11 @@ import javax.inject.Inject
|
||||
|
||||
class MenuViewModel @Inject constructor(
|
||||
private val tabState: TabState,
|
||||
private val pullBranchUseCase: PullBranchUseCase,
|
||||
private val pushBranchUseCase: PushBranchUseCase,
|
||||
private val fetchAllRemotesUseCase: FetchAllRemotesUseCase,
|
||||
private val popLastStashUseCase: PopLastStashUseCase,
|
||||
private val stashChangesUseCase: StashChangesUseCase,
|
||||
private val openRepositoryInTerminalUseCase: OpenRepositoryInTerminalUseCase,
|
||||
private val globalMenuActionsViewModel: GlobalMenuActionsViewModel,
|
||||
settings: AppSettingsRepository,
|
||||
appStateManager: AppStateManager,
|
||||
) {
|
||||
): IGlobalMenuActionsViewModel by globalMenuActionsViewModel {
|
||||
val isPullWithRebaseDefault = settings.pullRebaseFlow
|
||||
val lastLoadedTabs = appStateManager.latestOpenedRepositoriesPaths
|
||||
|
||||
fun pull(pullType: PullType) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Pulling",
|
||||
subtitle = "Pulling changes from the remote branch to the current branch",
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.PULL,
|
||||
) { git ->
|
||||
pullBranchUseCase(git, pullType)
|
||||
|
||||
positiveNotification("Pull completed")
|
||||
}
|
||||
|
||||
fun fetchAll() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Fetching",
|
||||
subtitle = "Updating references from the remote repositories...",
|
||||
isCancellable = false,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.FETCH,
|
||||
) { git ->
|
||||
fetchAllRemotesUseCase(git)
|
||||
|
||||
positiveNotification("Fetch all completed")
|
||||
}
|
||||
|
||||
fun push(force: Boolean = false, pushTags: Boolean = false) = tabState.safeProcessing(
|
||||
refreshType = RefreshType.ALL_DATA,
|
||||
title = "Push",
|
||||
subtitle = "Pushing current branch to the remote repository",
|
||||
isCancellable = false,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.PUSH,
|
||||
) { git ->
|
||||
pushBranchUseCase(git, force, pushTags)
|
||||
|
||||
positiveNotification("Push completed")
|
||||
}
|
||||
|
||||
fun stash() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.UNCOMMITTED_CHANGES_AND_LOG,
|
||||
taskType = TaskType.STASH,
|
||||
) { git ->
|
||||
if (stashChangesUseCase(git, null)) {
|
||||
positiveNotification("Changes stashed")
|
||||
} else {
|
||||
errorNotification("There are no changes to stash")
|
||||
}
|
||||
}
|
||||
|
||||
fun popStash() = tabState.safeProcessing(
|
||||
refreshType = RefreshType.UNCOMMITTED_CHANGES_AND_LOG,
|
||||
refreshEvenIfCrashes = true,
|
||||
taskType = TaskType.POP_STASH,
|
||||
) { git ->
|
||||
popLastStashUseCase(git)
|
||||
|
||||
positiveNotification("Stash popped")
|
||||
}
|
||||
|
||||
fun openTerminal() = tabState.runOperation(
|
||||
refreshType = RefreshType.NONE
|
||||
) { git ->
|
||||
openRepositoryInTerminalUseCase(git.repository.workTree.absolutePath)
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@ import com.jetpackduba.gitnuro.managers.newErrorNow
|
||||
import com.jetpackduba.gitnuro.models.AuthorInfoSimple
|
||||
import com.jetpackduba.gitnuro.models.errorNotification
|
||||
import com.jetpackduba.gitnuro.models.positiveNotification
|
||||
import com.jetpackduba.gitnuro.models.warningNotification
|
||||
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
||||
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
||||
import com.jetpackduba.gitnuro.system.PickerType
|
||||
@ -77,7 +76,9 @@ class TabViewModel @Inject constructor(
|
||||
private val tabScope: CoroutineScope,
|
||||
private val verticalSplitPaneConfig: VerticalSplitPaneConfig,
|
||||
val tabViewModelsProvider: TabViewModelsProvider,
|
||||
) : IVerticalSplitPaneConfig by verticalSplitPaneConfig {
|
||||
private val globalMenuActionsViewModel: GlobalMenuActionsViewModel,
|
||||
) : IVerticalSplitPaneConfig by verticalSplitPaneConfig,
|
||||
IGlobalMenuActionsViewModel by globalMenuActionsViewModel {
|
||||
var initialPath: String? = null // Stores the path that should be opened when the tab is selected
|
||||
val errorsManager: ErrorsManager = tabState.errorsManager
|
||||
val selectedItem: StateFlow<SelectedItem> = tabState.selectedItem
|
||||
|
Loading…
Reference in New Issue
Block a user