mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Try to fix the scrolling issue
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user