Replaced compose dropdown with a custom implementation based on context menu
This commit is contained in:
parent
37348a5dfc
commit
f9ccf87030
@ -28,6 +28,7 @@ object AppIcons {
|
||||
const val LOCK = "lock.svg"
|
||||
const val LOGO = "logo.svg"
|
||||
const val MERGE = "merge.svg"
|
||||
const val MESSAGE = "message.svg"
|
||||
const val MORE_VERT = "more_vert.svg"
|
||||
const val OPEN = "open.svg"
|
||||
const val PERSON = "person.svg"
|
||||
|
@ -7,7 +7,10 @@ import androidx.compose.foundation.Image
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.Icon
|
||||
import androidx.compose.material.IconButton
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.material.Text
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.ExperimentalComposeUiApi
|
||||
@ -192,7 +195,7 @@ fun ExtendedMenuButton(
|
||||
title: String,
|
||||
icon: Painter,
|
||||
onClick: () -> Unit,
|
||||
extendedListItems: List<DropDownContentData>,
|
||||
extendedListItems: List<ContextMenuElement>,
|
||||
) {
|
||||
var showDropDownMenu by remember { mutableStateOf(false) }
|
||||
|
||||
@ -229,31 +232,36 @@ fun ExtendedMenuButton(
|
||||
)
|
||||
}
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.ignoreKeyEvents(),
|
||||
contentAlignment = Alignment.Center,
|
||||
DropdownMenu(
|
||||
items = { extendedListItems }
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.fillMaxHeight()
|
||||
.ignoreKeyEvents(),
|
||||
contentAlignment = Alignment.Center,
|
||||
) {
|
||||
|
||||
Icon(
|
||||
painterResource(AppIcons.EXPAND_MORE),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
Icon(
|
||||
painterResource(AppIcons.EXPAND_MORE),
|
||||
contentDescription = null,
|
||||
tint = MaterialTheme.colors.onBackground,
|
||||
modifier = Modifier.size(16.dp)
|
||||
)
|
||||
|
||||
DropdownMenu(
|
||||
onDismissRequest = {
|
||||
showDropDownMenu = false
|
||||
},
|
||||
content = {
|
||||
for (item in extendedListItems) {
|
||||
DropDownContent(item, onDismiss = { showDropDownMenu = false })
|
||||
}
|
||||
},
|
||||
expanded = showDropDownMenu,
|
||||
)
|
||||
}
|
||||
|
||||
// DropdownMenu(
|
||||
// onDismissRequest = {
|
||||
// showDropDownMenu = false
|
||||
// },
|
||||
// content = {
|
||||
// for (item in extendedListItems) {
|
||||
// DropDownContent(item, onDismiss = { showDropDownMenu = false })
|
||||
// }
|
||||
// },
|
||||
// expanded = showDropDownMenu,
|
||||
// )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -321,7 +321,8 @@ fun LazyListScope.submodules(
|
||||
items(submodules, key = { it.first }) { submodule ->
|
||||
Submodule(
|
||||
submodule,
|
||||
onInitializeModule = { submodulesViewModel.initializeSubmodule(submodule.first) }
|
||||
onInitializeModule = { submodulesViewModel.initializeSubmodule(submodule.first) },
|
||||
onOpenSubmoduleInTab = { submodulesViewModel.onOpenSubmoduleInTab(submodule.first) },
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -464,12 +465,14 @@ private fun Stash(
|
||||
private fun Submodule(
|
||||
submodulePair: Pair<String, SubmoduleStatus>,
|
||||
onInitializeModule: () -> Unit,
|
||||
onOpenSubmoduleInTab: () -> Unit,
|
||||
) {
|
||||
ContextMenu(
|
||||
items = {
|
||||
submoduleContextMenuItems(
|
||||
submodulePair.second,
|
||||
onInitializeModule = onInitializeModule
|
||||
onInitializeModule = onInitializeModule,
|
||||
onOpenSubmoduleInTab = onOpenSubmoduleInTab,
|
||||
)
|
||||
}
|
||||
) {
|
||||
|
@ -13,9 +13,11 @@ import androidx.compose.ui.awt.awtEventOrNull
|
||||
import androidx.compose.ui.draw.shadow
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.geometry.Offset
|
||||
import androidx.compose.ui.graphics.painter.Painter
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.pointer.*
|
||||
import androidx.compose.ui.layout.onGloballyPositioned
|
||||
import androidx.compose.ui.unit.*
|
||||
import androidx.compose.ui.window.Popup
|
||||
import androidx.compose.ui.window.PopupPositionProvider
|
||||
@ -36,6 +38,13 @@ fun ContextMenu(items: () -> List<ContextMenuElement>, function: @Composable ()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DropdownMenu(items: () -> List<ContextMenuElement>, function: @Composable () -> Unit) {
|
||||
Box(modifier = Modifier.dropdownMenu(items), propagateMinConstraints = true) {
|
||||
function()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
private fun Modifier.contextMenu(items: () -> List<ContextMenuElement>): Modifier {
|
||||
@ -66,6 +75,51 @@ private fun Modifier.contextMenu(items: () -> List<ContextMenuElement>): Modifie
|
||||
lastMouseEventState.x,
|
||||
lastMouseEventState.y,
|
||||
items(),
|
||||
onDismissRequest = { setLastMouseEventState(null) }
|
||||
)
|
||||
}
|
||||
|
||||
return mod
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalComposeUiApi::class)
|
||||
@Composable
|
||||
private fun Modifier.dropdownMenu(items: () -> List<ContextMenuElement>): Modifier {
|
||||
val (lastMouseEventState, setLastMouseEventState) = remember { mutableStateOf<MouseEvent?>(null) }
|
||||
val (offset, setOffset) = remember { mutableStateOf<Offset?>(null) }
|
||||
val mod = this
|
||||
.onGloballyPositioned { layoutCoordinates ->
|
||||
val offsetToRoot = layoutCoordinates.localToRoot(Offset.Zero)
|
||||
println(offsetToRoot)
|
||||
|
||||
val offsetToBottomOfComponent = offsetToRoot.copy(y = offsetToRoot.y + layoutCoordinates.size.height)
|
||||
setOffset(offsetToBottomOfComponent)
|
||||
}
|
||||
.pointerInput(Unit) {
|
||||
while (true) {
|
||||
val lastMouseEvent = awaitPointerEventScope { awaitFirstDownEvent() }
|
||||
val mouseEvent = lastMouseEvent.awtEventOrNull
|
||||
|
||||
if (mouseEvent != null) {
|
||||
if (lastMouseEvent.button.isPrimary) {
|
||||
val currentCheck = System.currentTimeMillis()
|
||||
if (lastCheck != 0L && currentCheck - lastCheck < MIN_TIME_BETWEEN_POPUPS) {
|
||||
println("IGNORE POPUP TRIGGERED!")
|
||||
} else {
|
||||
lastCheck = currentCheck
|
||||
|
||||
setLastMouseEventState(mouseEvent)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (offset != null && lastMouseEventState != null) {
|
||||
showPopup(
|
||||
offset.x.toInt(),
|
||||
offset.y.toInt(),
|
||||
items(),
|
||||
onDismissRequest = { setLastMouseEventState(null) })
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ fun pullContextMenuItems(
|
||||
onPullWith: () -> Unit,
|
||||
onFetchAll: () -> Unit,
|
||||
isPullWithRebaseDefault: Boolean,
|
||||
): List<DropDownContentData> {
|
||||
): List<ContextMenuElement> {
|
||||
val pullWithText = if (isPullWithRebaseDefault) {
|
||||
"Pull with merge"
|
||||
} else {
|
||||
@ -12,11 +12,11 @@ fun pullContextMenuItems(
|
||||
}
|
||||
|
||||
return mutableListOf(
|
||||
DropDownContentData(
|
||||
ContextMenuElement.ContextTextEntry(
|
||||
label = pullWithText,
|
||||
onClick = onPullWith,
|
||||
),
|
||||
DropDownContentData(
|
||||
ContextMenuElement.ContextTextEntry(
|
||||
label = "Fetch all",
|
||||
onClick = onFetchAll,
|
||||
),
|
||||
|
@ -1,18 +1,15 @@
|
||||
package com.jetpackduba.gitnuro.ui.context_menu
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
fun pushContextMenuItems(
|
||||
onPushWithTags: () -> Unit,
|
||||
onForcePush: () -> Unit,
|
||||
): List<DropDownContentData> {
|
||||
): List<ContextMenuElement> {
|
||||
return mutableListOf(
|
||||
DropDownContentData(
|
||||
ContextMenuElement.ContextTextEntry(
|
||||
label = "Push including tags",
|
||||
onClick = onPushWithTags,
|
||||
),
|
||||
DropDownContentData(
|
||||
ContextMenuElement.ContextTextEntry(
|
||||
label = "Force push",
|
||||
onClick = onForcePush,
|
||||
),
|
||||
|
@ -1,15 +1,16 @@
|
||||
package com.jetpackduba.gitnuro.ui.context_menu
|
||||
|
||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import com.jetpackduba.gitnuro.AppIcons
|
||||
|
||||
@OptIn(ExperimentalFoundationApi::class)
|
||||
fun stashContextMenuItems(
|
||||
onStashWithMessage: () -> Unit,
|
||||
): List<DropDownContentData> {
|
||||
): List<ContextMenuElement> {
|
||||
return mutableListOf(
|
||||
DropDownContentData(
|
||||
ContextMenuElement.ContextTextEntry(
|
||||
label = "Stash with message",
|
||||
onClick = onStashWithMessage,
|
||||
icon = { painterResource(AppIcons.MESSAGE) }
|
||||
),
|
||||
)
|
||||
}
|
||||
|
1
src/main/resources/message.svg
Normal file
1
src/main/resources/message.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 0h24v24H0V0z" fill="none"/><path d="M4 4h16v12H5.17L4 17.17V4m0-2c-1.1 0-1.99.9-1.99 2L2 22l4-4h14c1.1 0 2-.9 2-2V4c0-1.1-.9-2-2-2H4zm2 10h12v2H6v-2zm0-3h12v2H6V9zm0-3h12v2H6V6z"/></svg>
|
After Width: | Height: | Size: 300 B |
Loading…
Reference in New Issue
Block a user