Gitnuro/src/main/kotlin/com/jetpackduba/gitnuro/ui/dialogs/QuickActionsDialog.kt
2023-08-23 15:48:20 +02:00

132 lines
5.0 KiB
Kotlin

package com.jetpackduba.gitnuro.ui.dialogs
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.input.key.onKeyEvent
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppIcons
import com.jetpackduba.gitnuro.extensions.backgroundIf
import com.jetpackduba.gitnuro.extensions.handMouseClickable
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
import com.jetpackduba.gitnuro.keybindings.matchesBinding
import com.jetpackduba.gitnuro.theme.backgroundSelected
import com.jetpackduba.gitnuro.ui.components.AdjustableOutlinedTextField
@Composable
fun QuickActionsDialog(
onClose: () -> Unit,
onAction: (QuickActionType) -> Unit,
) {
val textFieldFocusRequester = remember { FocusRequester() }
val items = remember {
listOf(
QuickAction(AppIcons.CODE, "Open repository in file manager", QuickActionType.OPEN_DIR_IN_FILE_MANAGER),
QuickAction(AppIcons.DOWNLOAD, "Clone new repository", QuickActionType.CLONE),
QuickAction(AppIcons.REFRESH, "Refresh repository data", QuickActionType.REFRESH),
QuickAction(AppIcons.SIGN, "Signoff config", QuickActionType.SIGN_OFF),
)
}
var searchFilter by remember { mutableStateOf("") }
val filteredItems by remember(searchFilter) {
derivedStateOf { items.filter { it.title.contains(searchFilter, ignoreCase = true) } }
}
var selectedIndex by remember(filteredItems) {
mutableStateOf(0)
}
MaterialDialog(
onCloseRequested = onClose,
background = MaterialTheme.colors.surface,
) {
Column(
modifier = Modifier.width(680.dp)
.height(400.dp)
.onKeyEvent { keyEvent ->
if (keyEvent.matchesBinding(KeybindingOption.DOWN)) {
if (selectedIndex < filteredItems.count() - 1)
selectedIndex++
true
} else if (keyEvent.matchesBinding(KeybindingOption.UP)) {
if (selectedIndex > 0)
selectedIndex--
true
} else if (keyEvent.matchesBinding(KeybindingOption.SIMPLE_ACCEPT)) {
val item = filteredItems.getOrNull(selectedIndex)
if (item != null)
onAction(item.type)
true
} else
false
}
) {
AdjustableOutlinedTextField(
value = searchFilter,
hint = "Search for an action or press ESC to close the dialog", // TODO don't hardcode ESC here, fix keybinding toString
onValueChange = { searchFilter = it },
maxLines = 1,
modifier = Modifier.fillMaxWidth()
.padding(bottom = 16.dp)
.focusRequester(textFieldFocusRequester)
)
LazyColumn(
modifier = Modifier
.fillMaxWidth()
.weight(1f)
) {
itemsIndexed(filteredItems) { index, item ->
Row(
verticalAlignment = Alignment.CenterVertically,
modifier = Modifier
.fillMaxWidth()
.clip(RoundedCornerShape(4.dp))
.backgroundIf(selectedIndex == index, MaterialTheme.colors.backgroundSelected)
.handMouseClickable { onAction(item.type) }
) {
Icon(
painterResource(item.icon),
contentDescription = null,
modifier = Modifier.padding(vertical = 16.dp, horizontal = 16.dp),
tint = MaterialTheme.colors.onBackground,
)
Text(
item.title,
color = MaterialTheme.colors.onBackground,
style = MaterialTheme.typography.body1,
)
}
}
}
LaunchedEffect(Unit) {
textFieldFocusRequester.requestFocus()
}
}
}
}
data class QuickAction(val icon: String, val title: String, val type: QuickActionType)
enum class QuickActionType {
OPEN_DIR_IN_FILE_MANAGER,
CLONE,
REFRESH,
SIGN_OFF
}