From f5d1eb210ed851cfca803ba62bd35422e9434b17 Mon Sep 17 00:00:00 2001 From: mrfluffy Date: Wed, 25 Feb 2026 12:49:07 +0000 Subject: [PATCH] balls --- .../fluffytrix/ui/screens/main/MainScreen.kt | 1 + .../ui/screens/main/MainViewModel.kt | 24 +++++++++- .../ui/screens/main/components/ChannelList.kt | 47 ++++++++++--------- 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainScreen.kt b/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainScreen.kt index 012e15f..da54e0e 100644 --- a/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainScreen.kt +++ b/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainScreen.kt @@ -150,6 +150,7 @@ fun MainScreen( isReorderMode = isReorderMode, onToggleReorderMode = { viewModel.toggleReorderMode() }, onMoveChannel = { from, to -> viewModel.moveChannel(from, to) }, + onMoveChannelById = { id, delta -> viewModel.moveChannelById(id, delta) }, onMoveChildSpace = { from, to -> viewModel.moveChildSpace(from, to) }, ) } diff --git a/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainViewModel.kt b/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainViewModel.kt index a501023..2a5ce73 100644 --- a/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainViewModel.kt +++ b/app/src/main/java/com/example/fluffytrix/ui/screens/main/MainViewModel.kt @@ -348,8 +348,13 @@ class MainViewModel( // Child space sections for ((csId, csName, csRoomIds) in childSpaces) { - val sectionChannels = csRoomIds.mapNotNull { channelMap[it] } + val csChannels = csRoomIds.mapNotNull { channelMap[it] } .filter { it.id !in usedIds } + // Respect saved channel order within child space sections + val sectionChannels = if (savedOrder != null) { + val idxMap = savedOrder.withIndex().associate { (i, id) -> id to i } + csChannels.sortedBy { idxMap[it.id] ?: Int.MAX_VALUE } + } else csChannels if (sectionChannels.isNotEmpty()) { sectionList.add(ChannelSection(spaceId = csId, spaceName = csName, channels = sectionChannels)) usedIds.addAll(sectionChannels.map { it.id }) @@ -1128,6 +1133,23 @@ class MainViewModel( } } + fun moveChannelById(channelId: String, delta: Int) { + val current = _channels.value.toMutableList() + val fromIdx = current.indexOfFirst { it.id == channelId } + if (fromIdx < 0) return + val toIdx = (fromIdx + delta).coerceIn(0, current.lastIndex) + if (fromIdx == toIdx) return + val item = current.removeAt(fromIdx) + current.add(toIdx, item) + _channels.value = current + val spaceId = _selectedSpace.value ?: return + val roomIds = current.map { it.id } + _channelOrderMap.value = _channelOrderMap.value + (spaceId to roomIds) + viewModelScope.launch { + preferencesManager.saveChannelOrder(spaceId, roomIds) + } + } + fun moveChildSpace(from: Int, to: Int) { val spaceId = _selectedSpace.value ?: return val current = _directChildSpaces.value[spaceId]?.toMutableList() ?: return diff --git a/app/src/main/java/com/example/fluffytrix/ui/screens/main/components/ChannelList.kt b/app/src/main/java/com/example/fluffytrix/ui/screens/main/components/ChannelList.kt index d6cb9e7..1a993e8 100644 --- a/app/src/main/java/com/example/fluffytrix/ui/screens/main/components/ChannelList.kt +++ b/app/src/main/java/com/example/fluffytrix/ui/screens/main/components/ChannelList.kt @@ -74,14 +74,15 @@ fun ChannelList( isReorderMode: Boolean = false, onToggleReorderMode: () -> Unit = {}, onMoveChannel: (from: Int, to: Int) -> Unit = { _, _ -> }, + onMoveChannelById: (channelId: String, delta: Int) -> Unit = { _, _ -> }, onMoveChildSpace: (from: Int, to: Int) -> Unit = { _, _ -> }, ) { var showLogoutDialog by remember { mutableStateOf(false) } val collapsedSections = remember { mutableStateMapOf() } - // Channel drag state - var draggingIndex by remember { mutableIntStateOf(-1) } - var dragOffsetY by remember { mutableFloatStateOf(0f) } + // Channel drag state — track by ID, no visual offset (let LazyColumn handle positioning) + var draggingChannelId by remember { mutableStateOf(null) } + var dragAccumulator by remember { mutableFloatStateOf(0f) } // Section drag state var draggingSectionIndex by remember { mutableIntStateOf(-1) } @@ -260,9 +261,7 @@ fun ChannelList( itemsIndexed(section.channels, key = { _, ch -> ch.id }) { index, channel -> val isSelected = channel.id == selectedChannel val hasUnread = channel.unreadStatus != UnreadStatus.NONE - val globalIndex = channels.indexOfFirst { it.id == channel.id } - val isDragging = draggingIndex == globalIndex - val elevation by animateDpAsState(if (isDragging) 8.dp else 0.dp, label = "elevation") + val isDragging = draggingChannelId == channel.id Row( modifier = Modifier @@ -270,8 +269,7 @@ fun ChannelList( .then( if (isDragging) Modifier .zIndex(1f) - .offset { IntOffset(0, dragOffsetY.roundToInt()) } - .shadow(elevation, RoundedCornerShape(8.dp)) + .background(MaterialTheme.colorScheme.surfaceContainerHigh) else Modifier ) .clip(RoundedCornerShape(8.dp)) @@ -287,7 +285,9 @@ fun ChannelList( verticalAlignment = Alignment.CenterVertically, ) { if (isReorderMode) { - val currentGlobalIndex by rememberUpdatedState(globalIndex) + val currentChannelId by rememberUpdatedState(channel.id) + val currentSectionSize by rememberUpdatedState(section.channels.size) + val currentLocalIndex by rememberUpdatedState(index) Icon( imageVector = Icons.Default.DragHandle, contentDescription = "Drag to reorder", @@ -296,28 +296,29 @@ fun ChannelList( .pointerInput(Unit) { detectDragGesturesAfterLongPress( onDragStart = { - draggingIndex = currentGlobalIndex - dragOffsetY = 0f + draggingChannelId = currentChannelId + dragAccumulator = 0f }, onDrag = { change, dragAmount -> change.consume() - dragOffsetY += dragAmount.y - val itemHeight = 40.dp.toPx() - val draggedPositions = (dragOffsetY / itemHeight).roundToInt() - val targetIndex = (draggingIndex + draggedPositions).coerceIn(0, channels.lastIndex) - if (targetIndex != draggingIndex) { - onMoveChannel(draggingIndex, targetIndex) - dragOffsetY -= (targetIndex - draggingIndex) * itemHeight - draggingIndex = targetIndex + dragAccumulator += dragAmount.y + val itemHeight = 56.dp.toPx() + val id = draggingChannelId ?: return@detectDragGesturesAfterLongPress + if (dragAccumulator > itemHeight * 0.6f && currentLocalIndex < currentSectionSize - 1) { + onMoveChannelById(id, 1) + dragAccumulator = 0f + } else if (dragAccumulator < -itemHeight * 0.6f && currentLocalIndex > 0) { + onMoveChannelById(id, -1) + dragAccumulator = 0f } }, onDragEnd = { - draggingIndex = -1 - dragOffsetY = 0f + draggingChannelId = null + dragAccumulator = 0f }, onDragCancel = { - draggingIndex = -1 - dragOffsetY = 0f + draggingChannelId = null + dragAccumulator = 0f }, ) },