Fixed inconsistencies with the side panel context menu

This commit is contained in:
Abdelilah El Aissaoui 2023-05-01 17:10:24 +02:00
parent 3752140a22
commit e5a2f5b6a7
No known key found for this signature in database
GPG Key ID: 7587FC860F594869
3 changed files with 100 additions and 73 deletions

View File

@ -18,9 +18,9 @@ import com.jetpackduba.gitnuro.extensions.simpleName
import com.jetpackduba.gitnuro.theme.onBackgroundSecondary import com.jetpackduba.gitnuro.theme.onBackgroundSecondary
import com.jetpackduba.gitnuro.ui.components.* import com.jetpackduba.gitnuro.ui.components.*
import com.jetpackduba.gitnuro.ui.context_menu.* 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.AddSubmodulesDialog
import com.jetpackduba.gitnuro.ui.dialogs.EditRemotesDialog
import com.jetpackduba.gitnuro.ui.dialogs.SetDefaultUpstreamBranchDialog
import com.jetpackduba.gitnuro.viewmodels.sidepanel.* import com.jetpackduba.gitnuro.viewmodels.sidepanel.*
import org.eclipse.jgit.lib.Ref import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.revwalk.RevCommit import org.eclipse.jgit.revwalk.RevCommit
@ -199,34 +199,30 @@ fun LazyListScope.remotes(
val remotes = remotesState.remotes val remotes = remotesState.remotes
item { item {
ContextMenu( SideMenuHeader(
items = { remoteBranchesContextMenu(onShowEditRemotesDialog) } text = "Remotes",
) { icon = painterResource(AppIcons.CLOUD),
SideMenuHeader( itemsCount = remotes.count(),
text = "Remotes", hoverIcon = {
icon = painterResource(AppIcons.CLOUD), IconButton(
itemsCount = remotes.count(), onClick = onShowEditRemotesDialog,
hoverIcon = { modifier = Modifier
IconButton( .padding(end = 16.dp)
onClick = onShowEditRemotesDialog, .size(16.dp)
.handOnHover(),
) {
Icon(
painter = painterResource(AppIcons.SETTINGS),
contentDescription = null,
modifier = Modifier modifier = Modifier
.padding(end = 16.dp) .fillMaxSize(),
.size(16.dp) tint = MaterialTheme.colors.onBackground,
.handOnHover(), )
) { }
Icon( },
painter = painterResource(AppIcons.SETTINGS), isExpanded = isExpanded,
contentDescription = null, onExpand = { remotesViewModel.onExpand() }
modifier = Modifier )
.fillMaxSize(),
tint = MaterialTheme.colors.onBackground,
)
}
},
isExpanded = isExpanded,
onExpand = { remotesViewModel.onExpand() }
)
}
} }
if (isExpanded) { if (isExpanded) {
@ -242,9 +238,12 @@ fun LazyListScope.remotes(
items(remote.remoteInfo.branchesList) { remoteBranch -> items(remote.remoteInfo.branchesList) { remoteBranch ->
RemoteBranches( RemoteBranches(
remoteBranch = remoteBranch, remoteBranch = remoteBranch,
currentBranch = remotesState.currentBranch,
onBranchClicked = { remotesViewModel.selectBranch(remoteBranch) }, onBranchClicked = { remotesViewModel.selectBranch(remoteBranch) },
onDoubleClick = { remotesViewModel.checkoutRemoteBranch(remoteBranch) }, onCheckoutBranch = { remotesViewModel.checkoutRemoteBranch(remoteBranch) },
onDeleteBranch = { remotesViewModel.deleteRemoteBranch(remoteBranch) }, onDeleteBranch = { remotesViewModel.deleteRemoteBranch(remoteBranch) },
onPushRemoteBranch = { remotesViewModel.pushToRemoteBranch(remoteBranch) },
onPullRemoteBranch = { remotesViewModel.pullFromRemoteBranch(remoteBranch) },
) )
} }
} }
@ -443,14 +442,28 @@ private fun Remote(
@Composable @Composable
private fun RemoteBranches( private fun RemoteBranches(
remoteBranch: Ref, remoteBranch: Ref,
currentBranch: Ref?,
onBranchClicked: () -> Unit, onBranchClicked: () -> Unit,
onDoubleClick: () -> Unit, onCheckoutBranch: () -> Unit,
onDeleteBranch: () -> Unit, onDeleteBranch: () -> Unit,
onPushRemoteBranch: () -> Unit,
onPullRemoteBranch: () -> Unit,
) { ) {
ContextMenu( ContextMenu(
items = { items = {
remoteBranchesContextMenu( branchContextMenuItems(
onDeleteBranch = onDeleteBranch 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, extraPadding = 24.dp,
iconResourcePath = AppIcons.BRANCH, iconResourcePath = AppIcons.BRANCH,
onClick = onBranchClicked, onClick = onBranchClicked,
onDoubleClick = onDoubleClick, onDoubleClick = onCheckoutBranch,
) )
} }
} }

View File

@ -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<ContextMenuElement> {
return listOf(
ContextMenuElement.ContextTextEntry(
label = "Delete remote branch",
icon = { painterResource(AppIcons.DELETE) },
onClick = onDeleteBranch
),
)
}

View File

@ -7,8 +7,11 @@ import com.jetpackduba.gitnuro.git.RefreshType
import com.jetpackduba.gitnuro.git.TabState import com.jetpackduba.gitnuro.git.TabState
import com.jetpackduba.gitnuro.git.branches.CheckoutRefUseCase import com.jetpackduba.gitnuro.git.branches.CheckoutRefUseCase
import com.jetpackduba.gitnuro.git.branches.DeleteLocallyRemoteBranchesUseCase 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.branches.GetRemoteBranchesUseCase
import com.jetpackduba.gitnuro.git.remote_operations.DeleteRemoteBranchUseCase 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.git.remotes.*
import com.jetpackduba.gitnuro.ui.dialogs.RemoteWrapper import com.jetpackduba.gitnuro.ui.dialogs.RemoteWrapper
import dagger.assisted.Assisted import dagger.assisted.Assisted
@ -27,39 +30,45 @@ class RemotesViewModel @AssistedInject constructor(
private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase, private val deleteRemoteBranchUseCase: DeleteRemoteBranchUseCase,
private val getRemoteBranchesUseCase: GetRemoteBranchesUseCase, private val getRemoteBranchesUseCase: GetRemoteBranchesUseCase,
private val getRemotesUseCase: GetRemotesUseCase, private val getRemotesUseCase: GetRemotesUseCase,
private val getCurrentBranchUseCase: GetCurrentBranchUseCase,
private val deleteRemoteUseCase: DeleteRemoteUseCase, private val deleteRemoteUseCase: DeleteRemoteUseCase,
private val addRemoteUseCase: AddRemoteUseCase, private val addRemoteUseCase: AddRemoteUseCase,
private val updateRemoteUseCase: UpdateRemoteUseCase, private val updateRemoteUseCase: UpdateRemoteUseCase,
private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranchesUseCase, private val deleteLocallyRemoteBranchesUseCase: DeleteLocallyRemoteBranchesUseCase,
private val checkoutRefUseCase: CheckoutRefUseCase, private val checkoutRefUseCase: CheckoutRefUseCase,
private val pushToSpecificBranchUseCase: PushToSpecificBranchUseCase,
private val pullFromSpecificBranchUseCase: PullFromSpecificBranchUseCase,
private val tabScope: CoroutineScope, private val tabScope: CoroutineScope,
@Assisted @Assisted
private val filter: StateFlow<String> private val filter: StateFlow<String>
) : SidePanelChildViewModel(false) { ) : SidePanelChildViewModel(false) {
private val remotes = MutableStateFlow<List<RemoteView>>(listOf()) private val remotes = MutableStateFlow<List<RemoteView>>(listOf())
private val currentBranch = MutableStateFlow<Ref?>(null)
val remoteState: StateFlow<RemotesState> = combine(remotes, isExpanded, filter) { remotes, isExpanded, filter -> val remoteState: StateFlow<RemotesState> =
val remotesFiltered = remotes.map { remote -> combine(remotes, isExpanded, filter, currentBranch) { remotes, isExpanded, filter, currentBranch ->
val remoteInfo = remote.remoteInfo val remotesFiltered = remotes.map { remote ->
val remoteInfo = remote.remoteInfo
val newRemoteInfo = remoteInfo.copy( val newRemoteInfo = remoteInfo.copy(
branchesList = remoteInfo.branchesList.filter { branch -> branchesList = remoteInfo.branchesList.filter { branch ->
branch.simpleName.lowercaseContains(filter) branch.simpleName.lowercaseContains(filter)
} }
)
remote.copy(remoteInfo = newRemoteInfo)
}
RemotesState(
remotesFiltered,
isExpanded,
currentBranch
) )
}.stateIn(
remote.copy(remoteInfo = newRemoteInfo) scope = tabScope,
} started = SharingStarted.Eagerly,
initialValue = RemotesState(emptyList(), isExpanded.value, null)
RemotesState(
remotesFiltered,
isExpanded
) )
}.stateIn(
scope = tabScope,
started = SharingStarted.Eagerly,
initialValue = RemotesState(emptyList(), isExpanded.value)
)
init { init {
tabScope.launch { tabScope.launch {
@ -73,12 +82,14 @@ class RemotesViewModel @AssistedInject constructor(
val allRemoteBranches = getRemoteBranchesUseCase(git) val allRemoteBranches = getRemoteBranchesUseCase(git)
val remoteInfoList = getRemotesUseCase(git, allRemoteBranches) val remoteInfoList = getRemotesUseCase(git, allRemoteBranches)
val currentBranch = getCurrentBranchUseCase(git)
val remoteViewList = remoteInfoList.map { remoteInfo -> val remoteViewList = remoteInfoList.map { remoteInfo ->
RemoteView(remoteInfo, true) RemoteView(remoteInfo, true)
} }
this@RemotesViewModel.remotes.value = remoteViewList this@RemotesViewModel.remotes.value = remoteViewList
this@RemotesViewModel.currentBranch.value = currentBranch
} }
fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing( fun deleteRemoteBranch(ref: Ref) = tabState.safeProcessing(
@ -177,8 +188,30 @@ class RemotesViewModel @AssistedInject constructor(
) { git -> ) { git ->
checkoutRefUseCase(git, remoteBranch) 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 RemoteView(val remoteInfo: RemoteInfo, val isExpanded: Boolean)
data class RemotesState(val remotes: List<RemoteView>, val isExpanded: Boolean) data class RemotesState(val remotes: List<RemoteView>, val isExpanded: Boolean, val currentBranch: Ref?)