mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
+1
@@ -29,6 +29,7 @@
|
||||
<inspection_tool class="GlancePreviewNotSupportedInUnitTestFiles" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
</inspection_tool>
|
||||
<inspection_tool class="NestedLambdaShadowedImplicitParameter" enabled="false" level="WEAK WARNING" enabled_by_default="false" />
|
||||
<inspection_tool class="PreviewAnnotationInFunctionWithParameters" enabled="true" level="ERROR" enabled_by_default="true">
|
||||
<option name="composableFile" value="true" />
|
||||
<option name="previewFile" value="true" />
|
||||
|
||||
@@ -13,7 +13,7 @@ plugins {
|
||||
kotlin {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_11)
|
||||
freeCompilerArgs.add("-Xsuppress-warning=NOTHING_TO_INLINE")
|
||||
freeCompilerArgs.add("-Xwarning-level=NOTHING_TO_INLINE:disabled")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,8 +31,7 @@ object WebSocketManager {
|
||||
private val _messages = MutableSharedFlow<WebSocketMessage>(replay = 0, extraBufferCapacity = 64)
|
||||
val messages = _messages.asSharedFlow()
|
||||
|
||||
@Volatile
|
||||
private var globalHandlers = mutableListOf<((WebSocketMessage) -> Unit)>()
|
||||
private val globalHandlers = mutableListOf<((WebSocketMessage) -> Unit)>()
|
||||
|
||||
fun addGlobalMessageHandler(handler: ((WebSocketMessage) -> Unit)) {
|
||||
globalHandlers += handler
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package ru.fromchat.ui
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.animation.AnimatedVisibility
|
||||
import androidx.compose.animation.EnterTransition
|
||||
import androidx.compose.animation.fadeOut
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -10,6 +13,7 @@ import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.WindowInsetsSides
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawing
|
||||
@@ -29,8 +33,10 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||
import androidx.compose.material.icons.automirrored.filled.Send
|
||||
import androidx.compose.material.icons.filled.DoneAll
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LoadingIndicator
|
||||
import androidx.compose.material3.LocalTextStyle
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Scaffold
|
||||
@@ -51,11 +57,15 @@ import androidx.compose.ui.graphics.SolidColor
|
||||
import androidx.compose.ui.layout.onSizeChanged
|
||||
import androidx.compose.ui.platform.LocalDensity
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.datetime.TimeZone
|
||||
import kotlinx.datetime.format
|
||||
import kotlinx.datetime.toLocalDateTime
|
||||
@@ -76,7 +86,7 @@ import ru.fromchat.utils.exclude
|
||||
import kotlin.time.ExperimentalTime
|
||||
import kotlin.time.Instant
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalTime::class)
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalTime::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun PublicChatScreen() {
|
||||
val navController = LocalNavController.current
|
||||
@@ -84,8 +94,12 @@ fun PublicChatScreen() {
|
||||
val scrollState = rememberScrollState()
|
||||
|
||||
val messages = remember { mutableStateListOf<Message>() }
|
||||
var loading by remember { mutableStateOf(true) }
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
val coroutineContext = coroutineContext
|
||||
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
apiRequest {
|
||||
ApiClient.getMessages()
|
||||
}.onSuccess {
|
||||
@@ -109,7 +123,11 @@ fun PublicChatScreen() {
|
||||
}
|
||||
|
||||
delay(500)
|
||||
scrollState.animateScrollTo(scrollState.maxValue)
|
||||
withContext(coroutineContext) {
|
||||
scrollState.scrollTo(scrollState.maxValue)
|
||||
}
|
||||
loading = false
|
||||
}.join()
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
@@ -205,6 +223,7 @@ fun PublicChatScreen() {
|
||||
}
|
||||
}
|
||||
) { innerPadding ->
|
||||
Box(Modifier.fillMaxSize()) {
|
||||
Column(
|
||||
Modifier
|
||||
.padding(innerPadding)
|
||||
@@ -215,7 +234,8 @@ fun PublicChatScreen() {
|
||||
text: String,
|
||||
isAuthor: Boolean,
|
||||
isRead: Boolean,
|
||||
timestamp: String
|
||||
timestamp: String,
|
||||
username: String
|
||||
) {
|
||||
var rowWidth by remember { mutableStateOf(0.dp) }
|
||||
val density = LocalDensity.current
|
||||
@@ -225,7 +245,7 @@ fun PublicChatScreen() {
|
||||
.padding(horizontal = 16.dp, vertical = 4.dp)
|
||||
.fillMaxWidth()
|
||||
.onSizeChanged {
|
||||
rowWidth = with (density) {
|
||||
rowWidth = with(density) {
|
||||
it.width.toDp()
|
||||
}
|
||||
},
|
||||
@@ -251,6 +271,14 @@ fun PublicChatScreen() {
|
||||
.width(IntrinsicSize.Max)
|
||||
.widthIn(max = rowWidth * 0.80f)
|
||||
) {
|
||||
if (!isAuthor) {
|
||||
Text(
|
||||
text = username,
|
||||
fontWeight = FontWeight.W600,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
}
|
||||
Text(text)
|
||||
Row(
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
@@ -282,9 +310,26 @@ fun PublicChatScreen() {
|
||||
timestamp = Instant
|
||||
.parse(it.utcTimestamp)
|
||||
.toLocalDateTime(TimeZone.currentSystemDefault())
|
||||
.format(DATETIME_FORMAT)
|
||||
.format(DATETIME_FORMAT),
|
||||
username = it.username
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AnimatedVisibility(
|
||||
visible = loading,
|
||||
enter = EnterTransition.None,
|
||||
exit = fadeOut()
|
||||
) {
|
||||
Box(
|
||||
Modifier
|
||||
.background(MaterialTheme.colorScheme.surface)
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
LoadingIndicator(Modifier.size(70.dp))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[versions]
|
||||
agp = "8.12.3"
|
||||
kotlin = "2.2.10"
|
||||
kotlin = "2.2.20"
|
||||
coreKtx = "1.17.0"
|
||||
junit = "4.13.2"
|
||||
junitVersion = "1.3.0"
|
||||
@@ -11,8 +11,10 @@ activityCompose = "1.11.0"
|
||||
composeBom = "2025.09.00"
|
||||
materialIconsExtended = "1.7.8"
|
||||
navigationCompose = "2.9.4"
|
||||
ktor = "3.2.3"
|
||||
ktor = "3.3.0"
|
||||
kotlinxSerializationJson = "1.9.0"
|
||||
compose = "1.9.1"
|
||||
material3 = "1.5.0-alpha04"
|
||||
|
||||
[libraries]
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
|
||||
@@ -23,13 +25,13 @@ androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-co
|
||||
androidx-lifecycle-runtime-ktx = { group = "androidx.lifecycle", name = "lifecycle-runtime-ktx", version.ref = "lifecycleRuntimeKtx" }
|
||||
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
|
||||
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
|
||||
androidx-ui = { group = "androidx.compose.ui", name = "ui" }
|
||||
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" }
|
||||
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
|
||||
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
|
||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
|
||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3" }
|
||||
androidx-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "compose" }
|
||||
androidx-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics", version.ref = "compose" }
|
||||
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "compose" }
|
||||
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview", version.ref = "compose" }
|
||||
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest", version.ref = "compose" }
|
||||
androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit4", version.ref = "compose" }
|
||||
androidx-material3 = { group = "androidx.compose.material3", name = "material3", version.ref = "material3" }
|
||||
androidx-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "navigationCompose" }
|
||||
kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.ref = "kotlinxDatetime" }
|
||||
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor" }
|
||||
|
||||
Reference in New Issue
Block a user