mirror of
https://github.com/meshtastic/Meshtastic-Android.git
synced 2026-04-20 22:23:37 +00:00
feat: add drag-and-drop to channel editor
This commit is contained in:
parent
66babdf735
commit
4bf2d405ce
2 changed files with 69 additions and 15 deletions
|
|
@ -2,18 +2,20 @@ package com.geeksville.mesh.ui.components.config
|
|||
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.core.FastOutSlowInEasing
|
||||
import androidx.compose.animation.core.animateDpAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.animation.slideInHorizontally
|
||||
import androidx.compose.animation.slideOutHorizontally
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.wrapContentSize
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Chip
|
||||
import androidx.compose.material.ContentAlpha
|
||||
|
|
@ -36,8 +38,10 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.platform.LocalFocusManager
|
||||
import androidx.compose.ui.platform.LocalHapticFeedback
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.Dp
|
||||
import androidx.compose.ui.unit.dp
|
||||
import com.geeksville.mesh.ChannelProtos.ChannelSettings
|
||||
import com.geeksville.mesh.R
|
||||
|
|
@ -45,6 +49,9 @@ import com.geeksville.mesh.channelSettings
|
|||
import com.geeksville.mesh.model.Channel
|
||||
import com.geeksville.mesh.ui.components.PreferenceCategory
|
||||
import com.geeksville.mesh.ui.components.PreferenceFooter
|
||||
import com.geeksville.mesh.ui.components.dragContainer
|
||||
import com.geeksville.mesh.ui.components.dragDropItemsIndexed
|
||||
import com.geeksville.mesh.ui.components.rememberDragDropState
|
||||
|
||||
@OptIn(ExperimentalMaterialApi::class)
|
||||
@Composable
|
||||
|
|
@ -54,13 +61,14 @@ fun ChannelCard(
|
|||
enabled: Boolean,
|
||||
onEditClick: () -> Unit,
|
||||
onDeleteClick: () -> Unit,
|
||||
elevation: Dp = 4.dp,
|
||||
) {
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(vertical = 2.dp)
|
||||
.clickable(enabled = enabled) { onEditClick() },
|
||||
elevation = 4.dp
|
||||
elevation = elevation,
|
||||
) {
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
|
|
@ -96,6 +104,15 @@ fun ChannelSettingsItemList(
|
|||
val focusManager = LocalFocusManager.current
|
||||
val settingsListInput = remember(settingsList) { settingsList.toMutableStateList() }
|
||||
|
||||
val listState = rememberLazyListState()
|
||||
val dragDropState = rememberDragDropState(listState) { from, to ->
|
||||
settingsListInput.apply {
|
||||
val fromIndex = indexOfFirst { it.hashCode() == from.key }
|
||||
val toIndex = indexOfFirst { it.hashCode() == to.key }
|
||||
add(toIndex, removeAt(fromIndex))
|
||||
}
|
||||
}
|
||||
|
||||
val isEditing: Boolean = settingsList.size != settingsListInput.size
|
||||
|| settingsList.zip(settingsListInput).any { (item1, item2) -> item1 != item2 }
|
||||
|
||||
|
|
@ -123,12 +140,22 @@ fun ChannelSettingsItemList(
|
|||
.clickable(onClick = { }, enabled = false)
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier.padding(horizontal = 16.dp)
|
||||
modifier = Modifier.dragContainer(
|
||||
dragDropState = dragDropState,
|
||||
haptics = LocalHapticFeedback.current,
|
||||
),
|
||||
state = listState,
|
||||
contentPadding = PaddingValues(horizontal = 16.dp),
|
||||
) {
|
||||
item { PreferenceCategory(text = "Channels") }
|
||||
|
||||
itemsIndexed(settingsListInput) { index, channel ->
|
||||
dragDropItemsIndexed(
|
||||
items = settingsListInput,
|
||||
dragDropState = dragDropState,
|
||||
) { index, channel, isDragging ->
|
||||
val elevation by animateDpAsState(if (isDragging) 8.dp else 4.dp, label = "drag")
|
||||
ChannelCard(
|
||||
elevation = elevation,
|
||||
index = index,
|
||||
title = channel.name.ifEmpty { modemPresetName },
|
||||
enabled = enabled,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue