diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt index 6deda72..65c426d 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/SidePanel.kt @@ -18,9 +18,9 @@ import com.jetpackduba.gitnuro.extensions.simpleName import com.jetpackduba.gitnuro.theme.onBackgroundSecondary import com.jetpackduba.gitnuro.ui.components.* import com.jetpackduba.gitnuro.ui.context_menu.* -import com.jetpackduba.gitnuro.ui.dialogs.SetDefaultUpstreamBranchDialog -import com.jetpackduba.gitnuro.ui.dialogs.EditRemotesDialog import com.jetpackduba.gitnuro.ui.dialogs.AddSubmodulesDialog +import com.jetpackduba.gitnuro.ui.dialogs.EditRemotesDialog +import com.jetpackduba.gitnuro.ui.dialogs.SetDefaultUpstreamBranchDialog import com.jetpackduba.gitnuro.viewmodels.sidepanel.* import org.eclipse.jgit.lib.Ref import org.eclipse.jgit.revwalk.RevCommit @@ -199,34 +199,30 @@ fun LazyListScope.remotes( val remotes = remotesState.remotes item { - ContextMenu( - items = { remoteBranchesContextMenu(onShowEditRemotesDialog) } - ) { - SideMenuHeader( - text = "Remotes", - icon = painterResource(AppIcons.CLOUD), - itemsCount = remotes.count(), - hoverIcon = { - IconButton( - onClick = onShowEditRemotesDialog, + SideMenuHeader( + text = "Remotes", + icon = painterResource(AppIcons.CLOUD), + itemsCount = remotes.count(), + hoverIcon = { + IconButton( + onClick = onShowEditRemotesDialog, + modifier = Modifier + .padding(end = 16.dp) + .size(16.dp) + .handOnHover(), + ) { + Icon( + painter = painterResource(AppIcons.SETTINGS), + contentDescription = null, modifier = Modifier - .padding(end = 16.dp) - .size(16.dp) - .handOnHover(), - ) { - Icon( - painter = painterResource(AppIcons.SETTINGS), - contentDescription = null, - modifier = Modifier - .fillMaxSize(), - tint = MaterialTheme.colors.onBackground, - ) - } - }, - isExpanded = isExpanded, - onExpand = { remotesViewModel.onExpand() } - ) - } + .fillMaxSize(), + tint = MaterialTheme.colors.onBackground, + ) + } + }, + isExpanded = isExpanded, + onExpand = { remotesViewModel.onExpand() } + ) } if (isExpanded) { @@ -242,9 +238,12 @@ fun LazyListScope.remotes( items(remote.remoteInfo.branchesList) { remoteBranch -> RemoteBranches( remoteBranch = remoteBranch, + currentBranch = remotesState.currentBranch, onBranchClicked = { remotesViewModel.selectBranch(remoteBranch) }, - onDoubleClick = { remotesViewModel.checkoutRemoteBranch(remoteBranch) }, + onCheckoutBranch = { remotesViewModel.checkoutRemoteBranch(remoteBranch) }, onDeleteBranch = { remotesViewModel.deleteRemoteBranch(remoteBranch) }, + onPushRemoteBranch = { remotesViewModel.pushToRemoteBranch(remoteBranch) }, + onPullRemoteBranch = { remotesViewModel.pullFromRemoteBranch(remoteBranch) }, ) } } @@ -443,14 +442,28 @@ private fun Remote( @Composable private fun RemoteBranches( remoteBranch: Ref, + currentBranch: Ref?, onBranchClicked: () -> Unit, - onDoubleClick: () -> Unit, + onCheckoutBranch: () -> Unit, onDeleteBranch: () -> Unit, + onPushRemoteBranch: () -> Unit, + onPullRemoteBranch: () -> Unit, ) { ContextMenu( items = { - remoteBranchesContextMenu( - onDeleteBranch = onDeleteBranch + branchContextMenuItems( + branch = remoteBranch, + currentBranch = currentBranch, + isCurrentBranch = false, + isLocal = false, + onCheckoutBranch = onCheckoutBranch, + onMergeBranch = {}, + onDeleteBranch = {}, + onDeleteRemoteBranch = onDeleteBranch, + onRebaseBranch = {}, + onPushToRemoteBranch = onPushRemoteBranch, + onPullFromRemoteBranch = onPullRemoteBranch, + onChangeDefaultUpstreamBranch = {}, ) } ) { @@ -459,7 +472,7 @@ private fun RemoteBranches( extraPadding = 24.dp, iconResourcePath = AppIcons.BRANCH, onClick = onBranchClicked, - onDoubleClick = onDoubleClick, + onDoubleClick = onCheckoutBranch, ) } } diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteBranchesContextMenu.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteBranchesContextMenu.kt deleted file mode 100644 index 86ad64b..0000000 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/context_menu/RemoteBranchesContextMenu.kt +++ /dev/null @@ -1,19 +0,0 @@ -@file:OptIn(ExperimentalFoundationApi::class) - -package com.jetpackduba.gitnuro.ui.context_menu - -import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.ui.res.painterResource -import com.jetpackduba.gitnuro.AppIcons - -fun remoteBranchesContextMenu( - onDeleteBranch: () -> Unit -): List { - return listOf( - ContextMenuElement.ContextTextEntry( - label = "Delete remote branch", - icon = { painterResource(AppIcons.DELETE) }, - onClick = onDeleteBranch - ), - ) -} \ No newline at end of file diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt index 20543af..d3c9bf5 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/sidepanel/RemotesViewModel.kt @@ -7,8 +7,11 @@ import com.jetpackduba.gitnuro.git.RefreshType import com.jetpackduba.gitnuro.git.TabState import com.jetpackduba.gitnuro.git.branches.CheckoutRefUseCase import com.jetpackduba.gitnuro.git.branches.DeleteLocallyRemoteBranchesUseCase +import com.jetpackduba.gitnuro.git.branches.GetCurrentBranchUseCase import com.jetpackduba.gitnuro.git.branches.GetRemoteBranchesUseCase import com.jetpackduba.gitnuro.git.remote_operations.DeleteRemoteBranchUseCase +import com.jetpackduba.gitnuro.git.remote_operations.PullFromSpecificBranchUseCase +import com.jetpackduba.gitnuro.git.remote_operations.PushToSpecificBranchUseCase import com.jetpackduba.gitnuro.git.remotes.* import com.jetpackduba.gitnuro.ui.dialogs.RemoteWrapper import dagger.assisted.Assisted @@ -27,39 +30,45 @@ class RemotesViewModel @AssistedInject constructor( private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase, private val getRemoteBranchesUseCase: GetRemoteBranchesUseCase, private val getRemotesUseCase: GetRemotesUseCase, + private val getCurrentBranchUseCase: GetCurrentBranchUseCase, private val deleteRemoteUseCase: DeleteRemoteUseCase, private val addRemoteUseCase: AddRemoteUseCase, private val updateRemoteUseCase: UpdateRemoteUseCase, private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranchesUseCase, private val checkoutRefUseCase: CheckoutRefUseCase, + private val pushToSpecificBranchUseCase: PushToSpecificBranchUseCase, + private val pullFromSpecificBranchUseCase: PullFromSpecificBranchUseCase, private val tabScope: CoroutineScope, @Assisted private val filter: StateFlow ) : SidePanelChildViewModel(false) { private val remotes = MutableStateFlow>(listOf()) + private val currentBranch = MutableStateFlow(null) - val remoteState: StateFlow = combine(remotes, isExpanded, filter) { remotes, isExpanded, filter -> - val remotesFiltered = remotes.map { remote -> - val remoteInfo = remote.remoteInfo + val remoteState: StateFlow = + combine(remotes, isExpanded, filter, currentBranch) { remotes, isExpanded, filter, currentBranch -> + val remotesFiltered = remotes.map { remote -> + val remoteInfo = remote.remoteInfo - val newRemoteInfo = remoteInfo.copy( - branchesList = remoteInfo.branchesList.filter { branch -> - branch.simpleName.lowercaseContains(filter) - } + val newRemoteInfo = remoteInfo.copy( + branchesList = remoteInfo.branchesList.filter { branch -> + branch.simpleName.lowercaseContains(filter) + } + ) + + remote.copy(remoteInfo = newRemoteInfo) + } + + RemotesState( + remotesFiltered, + isExpanded, + currentBranch ) - - remote.copy(remoteInfo = newRemoteInfo) - } - - RemotesState( - remotesFiltered, - isExpanded + }.stateIn( + scope = tabScope, + started = SharingStarted.Eagerly, + initialValue = RemotesState(emptyList(), isExpanded.value, null) ) - }.stateIn( - scope = tabScope, - started = SharingStarted.Eagerly, - initialValue = RemotesState(emptyList(), isExpanded.value) - ) init { tabScope.launch { @@ -73,12 +82,14 @@ class RemotesViewModel @AssistedInject constructor( val allRemoteBranches = getRemoteBranchesUseCase(git) val remoteInfoList = getRemotesUseCase(git, allRemoteBranches) + val currentBranch = getCurrentBranchUseCase(git) val remoteViewList = remoteInfoList.map { remoteInfo -> RemoteView(remoteInfo, true) } this@RemotesViewModel.remotes.value = remoteViewList + this@RemotesViewModel.currentBranch.value = currentBranch } fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing( @@ -177,8 +188,30 @@ class RemotesViewModel @AssistedInject constructor( ) { git -> checkoutRefUseCase(git, remoteBranch) } + + + fun pushToRemoteBranch(branch: Ref) = tabState.safeProcessing( + refreshType = RefreshType.ALL_DATA, + ) { git -> + pushToSpecificBranchUseCase( + git = git, + force = false, + pushTags = false, + remoteBranch = branch, + ) + } + + fun pullFromRemoteBranch(branch: Ref) = tabState.safeProcessing( + refreshType = RefreshType.ALL_DATA, + ) { git -> + pullFromSpecificBranchUseCase( + git = git, + rebase = false, + remoteBranch = branch, + ) + } } data class RemoteView(val remoteInfo: RemoteInfo, val isExpanded: Boolean) -data class RemotesState(val remotes: List, val isExpanded: Boolean) \ No newline at end of file +data class RemotesState(val remotes: List, val isExpanded: Boolean, val currentBranch: Ref?) \ No newline at end of file