Try to fix the scrolling issue

Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
2025-09-13 20:10:02 +03:00
Unverified
parent be169d0fe9
commit 29fe578b99
2 changed files with 43 additions and 39 deletions
+6
View File
@@ -5,12 +5,14 @@ import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection.
import androidx.compose.animation.core.tween import androidx.compose.animation.core.tween
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.compositionLocalOf import androidx.compose.runtime.compositionLocalOf
import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntOffset
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import ru.fromchat.api.WebSocketManager
import ru.fromchat.ui.auth.LoginScreen import ru.fromchat.ui.auth.LoginScreen
import ru.fromchat.ui.auth.RegisterScreen import ru.fromchat.ui.auth.RegisterScreen
import ru.fromchat.ui.main.MainScreen import ru.fromchat.ui.main.MainScreen
@@ -19,6 +21,10 @@ val LocalNavController = compositionLocalOf<NavController> { error("") }
@Composable @Composable
fun App() { fun App() {
LaunchedEffect(Unit) {
WebSocketManager.connect()
}
FromChatTheme(dynamicColor = false) { FromChatTheme(dynamicColor = false) {
val navController = rememberNavController() val navController = rememberNavController()
val animationSpec = tween<IntOffset>(400) val animationSpec = tween<IntOffset>(400)
@@ -21,13 +21,14 @@ import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.input.TextFieldLineLimits import androidx.compose.foundation.text.input.TextFieldLineLimits
import androidx.compose.foundation.text.input.rememberTextFieldState import androidx.compose.foundation.text.input.rememberTextFieldState
import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd import androidx.compose.foundation.text.input.setTextAndPlaceCursorAtEnd
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.Send import androidx.compose.material.icons.automirrored.filled.Send
@@ -61,11 +62,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.datetime.TimeZone import kotlinx.datetime.TimeZone
import kotlinx.datetime.format import kotlinx.datetime.format
import kotlinx.datetime.toLocalDateTime import kotlinx.datetime.toLocalDateTime
@@ -91,15 +89,21 @@ import kotlin.time.Instant
fun PublicChatScreen() { fun PublicChatScreen() {
val navController = LocalNavController.current val navController = LocalNavController.current
val scope = rememberCoroutineScope() val scope = rememberCoroutineScope()
val scrollState = rememberScrollState() val listState = rememberLazyListState()
val messages = remember { mutableStateListOf<Message>() } val messages = remember { mutableStateListOf<Message>() }
var loading by remember { mutableStateOf(true) } var loading by remember { mutableStateOf(true) }
LaunchedEffect(Unit) { suspend fun scrollDown(animated: Boolean = true) {
val coroutineContext = coroutineContext Log.d("PublicChatScreen", "Scrolling down")
if (animated) {
listState.animateScrollToItem(messages.lastIndex)
} else {
listState.scrollToItem(messages.lastIndex)
}
}
CoroutineScope(Dispatchers.IO).launch { LaunchedEffect(Unit) {
apiRequest { apiRequest {
ApiClient.getMessages() ApiClient.getMessages()
}.onSuccess { }.onSuccess {
@@ -113,8 +117,7 @@ fun PublicChatScreen() {
if (msg.type == "newMessage") { if (msg.type == "newMessage") {
try { try {
messages += Json.decodeFromJsonElement<Message>(msg.data!!) messages += Json.decodeFromJsonElement<Message>(msg.data!!)
delay(500) scrollDown()
scrollState.animateScrollTo(scrollState.maxValue)
} catch (e: Exception) { } catch (e: Exception) {
Log.e("PublicChatScreen", "Failed to process incoming message:", e) Log.e("PublicChatScreen", "Failed to process incoming message:", e)
} }
@@ -123,11 +126,8 @@ fun PublicChatScreen() {
} }
delay(500) delay(500)
withContext(coroutineContext) { scrollDown(false)
scrollState.scrollTo(scrollState.maxValue)
}
loading = false loading = false
}.join()
} }
Scaffold( Scaffold(
@@ -207,8 +207,7 @@ fun PublicChatScreen() {
) )
}.getOrNull()?.let { }.getOrNull()?.let {
messages += it.message messages += it.message
delay(500) scrollDown()
scrollState.animateScrollTo(scrollState.maxValue)
} }
message.setTextAndPlaceCursorAtEnd("") message.setTextAndPlaceCursorAtEnd("")
@@ -224,10 +223,9 @@ fun PublicChatScreen() {
} }
) { innerPadding -> ) { innerPadding ->
Box(Modifier.fillMaxSize()) { Box(Modifier.fillMaxSize()) {
Column( LazyColumn(
Modifier state = listState,
.padding(innerPadding) modifier = Modifier.padding(innerPadding)
.verticalScroll(scrollState)
) { ) {
@Composable @Composable
fun Message( fun Message(
@@ -302,7 +300,7 @@ fun PublicChatScreen() {
} }
} }
messages.forEach { items(messages, { it.id }) {
Message( Message(
text = it.content, text = it.content,
isAuthor = it.username == ApiClient.user!!.username, isAuthor = it.username == ApiClient.user!!.username,