From 2d32b77a69342b7660f865ddf7fd42efeeddcc51 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Sun, 12 Dec 2021 06:04:19 +0100 Subject: [PATCH] Implemented context menu in side panel branches/tags --- src/main/kotlin/app/Constants.kt | 3 + src/main/kotlin/app/ui/Branches.kt | 72 ++++++++++++++----- src/main/kotlin/app/ui/Remotes.kt | 8 ++- src/main/kotlin/app/ui/Tags.kt | 54 +++++++------- .../app/ui/components/SideMenuSubentry.kt | 4 +- .../app/ui/context_menu/BranchContextMenu.kt | 38 ++++++++++ .../app/ui/context_menu/TagContextMenu.kt | 22 ++++++ src/main/kotlin/app/ui/log/Log.kt | 53 ++++---------- 8 files changed, 167 insertions(+), 87 deletions(-) create mode 100644 src/main/kotlin/app/Constants.kt create mode 100644 src/main/kotlin/app/ui/context_menu/BranchContextMenu.kt create mode 100644 src/main/kotlin/app/ui/context_menu/TagContextMenu.kt diff --git a/src/main/kotlin/app/Constants.kt b/src/main/kotlin/app/Constants.kt new file mode 100644 index 0000000..314e84d --- /dev/null +++ b/src/main/kotlin/app/Constants.kt @@ -0,0 +1,3 @@ +package app + +const val MAX_SIDE_PANEL_ITEMS_HEIGHT = 300 \ No newline at end of file diff --git a/src/main/kotlin/app/ui/Branches.kt b/src/main/kotlin/app/ui/Branches.kt index 7c8c7e1..5398b40 100644 --- a/src/main/kotlin/app/ui/Branches.kt +++ b/src/main/kotlin/app/ui/Branches.kt @@ -1,5 +1,7 @@ package app.ui +import androidx.compose.foundation.ContextMenuArea +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.* @@ -7,9 +9,7 @@ import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.material.* import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.runtime.Composable -import androidx.compose.runtime.collectAsState -import androidx.compose.runtime.getValue +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -18,6 +18,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp +import app.MAX_SIDE_PANEL_ITEMS_HEIGHT +import app.extensions.isLocal import app.ui.components.ScrollableLazyColumn import app.extensions.simpleName import app.git.GitManager @@ -26,51 +28,83 @@ import app.theme.headerBackground import app.theme.headerText import app.ui.components.SideMenuEntry import app.ui.components.SideMenuSubentry +import app.ui.components.entryHeight +import app.ui.context_menu.branchContextMenuItems +import app.ui.dialogs.MergeDialog @Composable fun Branches(gitManager: GitManager) { val branches by gitManager.branches.collectAsState() val currentBranch by gitManager.currentBranch.collectAsState() + val (mergeBranch, setMergeBranch) = remember { mutableStateOf(null) } Column { SideMenuEntry("Local branches") - val branchesHeight = branches.count() * 40 - val maxHeight = if(branchesHeight < 300) + val branchesHeight = branches.count() * entryHeight + val maxHeight = if (branchesHeight < MAX_SIDE_PANEL_ITEMS_HEIGHT) branchesHeight else - 300 + MAX_SIDE_PANEL_ITEMS_HEIGHT Box(modifier = Modifier.heightIn(max = maxHeight.dp)) { ScrollableLazyColumn(modifier = Modifier.fillMaxWidth()) { itemsIndexed(branches) { _, branch -> BranchRow( branch = branch, - isCurrentBranch = currentBranch == branch.name + isCurrentBranch = currentBranch == branch.name, + onCheckoutBranch = { gitManager.checkoutRef(branch) }, + onMergeBranch = { setMergeBranch(branch) }, + onDeleteBranch = { gitManager.deleteBranch(branch) }, ) } } } } + + if(mergeBranch != null) { + MergeDialog( + currentBranch, + mergeBranchName = mergeBranch.name, + onReject = { setMergeBranch(null) }, + onAccept = { ff -> gitManager.mergeBranch(mergeBranch, ff) } + ) + } } +@OptIn(ExperimentalFoundationApi::class) @Composable private fun BranchRow( branch: Ref, - isCurrentBranch: Boolean + isCurrentBranch: Boolean, + onCheckoutBranch: () -> Unit, + onMergeBranch: () -> Unit, + onDeleteBranch: () -> Unit, ) { - SideMenuSubentry( - text = branch.simpleName, - iconResourcePath = "branch.svg", - bold = isCurrentBranch, - ) { - if (isCurrentBranch) { - Icon( - painter = painterResource("location.svg"), - contentDescription = null, - modifier = Modifier.padding(horizontal = 4.dp), - tint = MaterialTheme.colors.primary, + ContextMenuArea( + items = { + branchContextMenuItems( + isCurrentBranch = isCurrentBranch, + isLocal = branch.isLocal, + onCheckoutBranch = onCheckoutBranch, + onMergeBranch = onMergeBranch, + onDeleteBranch = onDeleteBranch, ) } + ) { + SideMenuSubentry( + text = branch.simpleName, + iconResourcePath = "branch.svg", + bold = isCurrentBranch, + ) { + if (isCurrentBranch) { + Icon( + painter = painterResource("location.svg"), + contentDescription = null, + modifier = Modifier.padding(horizontal = 4.dp), + tint = MaterialTheme.colors.primary, + ) + } + } } } \ No newline at end of file diff --git a/src/main/kotlin/app/ui/Remotes.kt b/src/main/kotlin/app/ui/Remotes.kt index ca8aa57..78268a1 100644 --- a/src/main/kotlin/app/ui/Remotes.kt +++ b/src/main/kotlin/app/ui/Remotes.kt @@ -7,12 +7,14 @@ import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp +import app.MAX_SIDE_PANEL_ITEMS_HEIGHT import app.ui.components.ScrollableLazyColumn import app.extensions.simpleVisibleName import app.git.GitManager import app.git.RemoteInfo import app.ui.components.SideMenuEntry import app.ui.components.SideMenuSubentry +import app.ui.components.entryHeight @Composable fun Remotes(gitManager: GitManager) { @@ -22,11 +24,11 @@ fun Remotes(gitManager: GitManager) { SideMenuEntry("Remotes") val allBranches = remotes.map { it.branchesList }.flatten() - val remotesHeight = (allBranches.count() + remotes.count()) * 40 - val maxHeight = if(remotesHeight < 300) + val remotesHeight = (allBranches.count() + remotes.count()) * entryHeight + val maxHeight = if(remotesHeight < MAX_SIDE_PANEL_ITEMS_HEIGHT) remotesHeight else - 300 + MAX_SIDE_PANEL_ITEMS_HEIGHT Box(modifier = Modifier.heightIn(max = maxHeight.dp)) { ScrollableLazyColumn(modifier = Modifier.fillMaxWidth()) { diff --git a/src/main/kotlin/app/ui/Tags.kt b/src/main/kotlin/app/ui/Tags.kt index aa1d305..7ca4ca9 100644 --- a/src/main/kotlin/app/ui/Tags.kt +++ b/src/main/kotlin/app/ui/Tags.kt @@ -1,29 +1,21 @@ package app.ui -import androidx.compose.foundation.background -import androidx.compose.foundation.clickable +import androidx.compose.foundation.ContextMenuArea +import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.layout.* import androidx.compose.foundation.lazy.items -import androidx.compose.material.* import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState -import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp +import app.MAX_SIDE_PANEL_ITEMS_HEIGHT import app.extensions.simpleName import app.ui.components.ScrollableLazyColumn import app.git.GitManager -import app.git.StashStatus -import org.eclipse.jgit.revwalk.RevCommit -import app.theme.headerBackground -import app.theme.headerText import app.ui.components.SideMenuEntry import app.ui.components.SideMenuSubentry +import app.ui.components.entryHeight +import app.ui.context_menu.tagContextMenuItems import org.eclipse.jgit.lib.Ref @Composable @@ -31,25 +23,25 @@ fun Tags(gitManager: GitManager) { val tagsState = gitManager.tags.collectAsState() val tags = tagsState.value - Column { SideMenuEntry( text = "Tags", ) - val branchesHeight = tags.count() * 40 - val maxHeight = if (branchesHeight < 300) - branchesHeight + val tagsHeight = tags.count() * entryHeight + val maxHeight = if (tagsHeight < MAX_SIDE_PANEL_ITEMS_HEIGHT) + tagsHeight else - 300 + MAX_SIDE_PANEL_ITEMS_HEIGHT Box(modifier = Modifier.heightIn(max = maxHeight.dp)) { ScrollableLazyColumn(modifier = Modifier.fillMaxWidth()) { items(items = tags) { tag -> TagRow( tag = tag, + onCheckoutTag = { gitManager.checkoutRef(tag) }, + onDeleteTag = { gitManager.deleteTag(tag) } ) - } } } @@ -57,10 +49,24 @@ fun Tags(gitManager: GitManager) { } +@OptIn(ExperimentalFoundationApi::class) @Composable -private fun TagRow(tag: Ref) { - SideMenuSubentry( - text = tag.simpleName, - iconResourcePath = "tag.svg", - ) +private fun TagRow( + tag: Ref, + onCheckoutTag: () -> Unit, + onDeleteTag: () -> Unit, +) { + ContextMenuArea( + items = { + tagContextMenuItems( + onCheckoutTag = onCheckoutTag, + onDeleteTag = onDeleteTag, + ) + } + ) { + SideMenuSubentry( + text = tag.simpleName, + iconResourcePath = "tag.svg", + ) + } } \ No newline at end of file diff --git a/src/main/kotlin/app/ui/components/SideMenuSubentry.kt b/src/main/kotlin/app/ui/components/SideMenuSubentry.kt index ebdc8e3..b9f6306 100644 --- a/src/main/kotlin/app/ui/components/SideMenuSubentry.kt +++ b/src/main/kotlin/app/ui/components/SideMenuSubentry.kt @@ -19,6 +19,8 @@ import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import app.theme.primaryTextColor +const val entryHeight = 40 + @Composable fun SideMenuSubentry( text: String, @@ -30,7 +32,7 @@ fun SideMenuSubentry( ) { Row( modifier = Modifier - .height(40.dp) + .height(entryHeight.dp) .fillMaxWidth() .clickable(onClick = onClick) .padding(start = extraPadding), diff --git a/src/main/kotlin/app/ui/context_menu/BranchContextMenu.kt b/src/main/kotlin/app/ui/context_menu/BranchContextMenu.kt new file mode 100644 index 0000000..e770fa6 --- /dev/null +++ b/src/main/kotlin/app/ui/context_menu/BranchContextMenu.kt @@ -0,0 +1,38 @@ +package app.ui.context_menu + +import androidx.compose.foundation.ContextMenuItem +import androidx.compose.foundation.ExperimentalFoundationApi + +@OptIn(ExperimentalFoundationApi::class) +fun branchContextMenuItems( + isCurrentBranch: Boolean, + isLocal: Boolean, + onCheckoutBranch: () -> Unit, + onMergeBranch: () -> Unit, + onDeleteBranch: () -> Unit, +): List { + return mutableListOf( + ContextMenuItem( + label = "Checkout branch", + onClick = onCheckoutBranch + ), + + ).apply { + if (!isCurrentBranch) { + add( + ContextMenuItem( + label = "Merge branch", + onClick = onMergeBranch + ) + ) + } + if (isLocal && !isCurrentBranch) { + add( + ContextMenuItem( + label = "Delete branch", + onClick = onDeleteBranch + ) + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/app/ui/context_menu/TagContextMenu.kt b/src/main/kotlin/app/ui/context_menu/TagContextMenu.kt new file mode 100644 index 0000000..2afcc7f --- /dev/null +++ b/src/main/kotlin/app/ui/context_menu/TagContextMenu.kt @@ -0,0 +1,22 @@ +package app.ui.context_menu + +import androidx.compose.foundation.ContextMenuItem +import androidx.compose.foundation.ExperimentalFoundationApi +import app.extensions.isLocal + +@OptIn(ExperimentalFoundationApi::class) +fun tagContextMenuItems( + onCheckoutTag: () -> Unit, + onDeleteTag: () -> Unit, +): List { + return mutableListOf( + ContextMenuItem( + label = "Checkout tag", + onClick = onCheckoutTag + ), + ContextMenuItem( + label = "Delete tag", + onClick = onDeleteTag + ) + ) +} \ No newline at end of file diff --git a/src/main/kotlin/app/ui/log/Log.kt b/src/main/kotlin/app/ui/log/Log.kt index bcc0d8a..d043e28 100644 --- a/src/main/kotlin/app/ui/log/Log.kt +++ b/src/main/kotlin/app/ui/log/Log.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme import androidx.compose.material.Text -import androidx.compose.material.contentColorFor import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi @@ -41,6 +40,8 @@ import app.images.rememberNetworkImage import app.theme.* import app.ui.SelectedItem import app.ui.components.ScrollableLazyColumn +import app.ui.context_menu.branchContextMenuItems +import app.ui.context_menu.tagContextMenuItems import app.ui.dialogs.MergeDialog import app.ui.dialogs.NewBranchDialog import app.ui.dialogs.NewTagDialog @@ -626,30 +627,13 @@ fun BranchChip( color: Color, ) { val contextMenuItemsList = { - mutableListOf( - ContextMenuItem( - label = "Checkout branch", - onClick = onCheckoutBranch - ), - - ).apply { - if (!isCurrentBranch) { - add( - ContextMenuItem( - label = "Merge branch", - onClick = onMergeBranch - ) - ) - } - if (ref.isLocal && !isCurrentBranch) { - add( - ContextMenuItem( - label = "Delete branch", - onClick = onDeleteBranch - ) - ) - } - } + branchContextMenuItems( + isCurrentBranch = isCurrentBranch, + isLocal = ref.isLocal, + onCheckoutBranch = onCheckoutBranch, + onMergeBranch = onMergeBranch, + onDeleteBranch = onDeleteBranch, + ) } var endingContent: @Composable () -> Unit = {} @@ -685,21 +669,10 @@ fun TagChip( color: Color, ) { val contextMenuItemsList = { - mutableListOf( - ContextMenuItem( - label = "Checkout tag", - onClick = onCheckoutTag - ) - ).apply { - if (ref.isLocal) { - add( - ContextMenuItem( - label = "Delete tag", - onClick = onDeleteTag - ) - ) - } - } + tagContextMenuItems( + onCheckoutTag = onCheckoutTag, + onDeleteTag = onDeleteTag, + ) } RefChip(