From efdb93d13679b55019f8794b05e3c66e11fc6772 Mon Sep 17 00:00:00 2001 From: k1ngsterr1 Date: Mon, 9 Feb 2026 14:34:23 +0500 Subject: [PATCH] feat: add swipe gesture handling for drawer opening in ChatsListScreen --- .../messenger/ui/chats/ChatsListScreen.kt | 96 ++++++++++++++++++- 1 file changed, 95 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListScreen.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListScreen.kt index 0a89415..3197fab 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListScreen.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListScreen.kt @@ -242,6 +242,9 @@ fun ChatsListScreen( val textColor = remember(isDarkTheme) { if (isDarkTheme) Color.White else Color.Black } val secondaryTextColor = remember(isDarkTheme) { if (isDarkTheme) Color(0xFF8E8E8E) else Color(0xFF8E8E93) } + val drawerGrabZonePx = with(androidx.compose.ui.platform.LocalDensity.current) { 88.dp.toPx() } + val drawerOpenDistancePx = with(androidx.compose.ui.platform.LocalDensity.current) { 20.dp.toPx() } + val drawerOpenVelocityThresholdPx = with(androidx.compose.ui.platform.LocalDensity.current) { 110.dp.toPx() } // Protocol connection state val protocolState by ProtocolManager.state.collectAsState() @@ -417,7 +420,98 @@ fun ChatsListScreen( } // Simple background - Box(modifier = Modifier.fillMaxSize().background(backgroundColor).navigationBarsPadding()) { + Box( + modifier = + Modifier.fillMaxSize() + .background(backgroundColor) + .navigationBarsPadding() + .pointerInput(drawerState.isOpen, showRequestsScreen) { + if (showRequestsScreen) return@pointerInput + + val velocityTracker = VelocityTracker() + val relaxedTouchSlop = viewConfiguration.touchSlop * 0.45f + + awaitEachGesture { + val down = + awaitFirstDown(requireUnconsumed = false) + + if (drawerState.isOpen || down.position.x > drawerGrabZonePx) { + return@awaitEachGesture + } + + velocityTracker.resetTracking() + velocityTracker.addPosition( + down.uptimeMillis, + down.position + ) + var totalDragX = 0f + var totalDragY = 0f + var claimed = false + + while (true) { + val event = awaitPointerEvent() + val change = + event.changes.firstOrNull { + it.id == down.id + } + ?: break + + if (change.changedToUpIgnoreConsumed()) break + + val delta = change.positionChange() + totalDragX += delta.x + totalDragY += delta.y + velocityTracker.addPosition( + change.uptimeMillis, + change.position + ) + + if (!claimed) { + val distance = + kotlin.math.sqrt( + totalDragX * + totalDragX + + totalDragY * + totalDragY + ) + if (distance < relaxedTouchSlop) + continue + + val horizontalDominance = + kotlin.math.abs( + totalDragX + ) > + kotlin.math.abs( + totalDragY + ) * 1.15f + if ( + totalDragX > 0 && + horizontalDominance + ) { + claimed = true + change.consume() + } else { + break + } + } else { + change.consume() + } + } + + val velocityX = velocityTracker.calculateVelocity().x + val shouldOpenDrawer = + claimed && + (totalDragX >= + drawerOpenDistancePx || + velocityX > + drawerOpenVelocityThresholdPx) + + if (shouldOpenDrawer && drawerState.isClosed) { + scope.launch { drawerState.open() } + } + } + } + ) { ModalNavigationDrawer( drawerState = drawerState, gesturesEnabled = true, // 🔥 Явно включаем свайп для открытия drawer