diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 5e2076d..9ab125b 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -13,6 +13,7 @@ plugins { kotlin { compilerOptions { jvmTarget.set(JvmTarget.JVM_11) + freeCompilerArgs.add("-Xsuppress-warning=NOTHING_TO_INLINE") } } diff --git a/app/src/main/java/ru/fromchat/ui/App.kt b/app/src/main/java/ru/fromchat/ui/App.kt index 85703b7..822d73c 100644 --- a/app/src/main/java/ru/fromchat/ui/App.kt +++ b/app/src/main/java/ru/fromchat/ui/App.kt @@ -13,8 +13,7 @@ import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import ru.fromchat.ui.auth.LoginScreen import ru.fromchat.ui.auth.RegisterScreen -import ru.fromchat.ui.chat.ChatScreen -import ru.fromchat.ui.chat.PublicChatScreen +import ru.fromchat.ui.main.MainScreen val LocalNavController = compositionLocalOf { error("") } @@ -68,7 +67,7 @@ fun App() { ) } - composable("chat") { ChatScreen() } + composable("chat") { MainScreen() } composable("chats/publicChat") { PublicChatScreen() diff --git a/app/src/main/java/ru/fromchat/ui/chat/PublicChatScreen.kt b/app/src/main/java/ru/fromchat/ui/PublicChatScreen.kt similarity index 99% rename from app/src/main/java/ru/fromchat/ui/chat/PublicChatScreen.kt rename to app/src/main/java/ru/fromchat/ui/PublicChatScreen.kt index f68c4fd..e8fcd77 100644 --- a/app/src/main/java/ru/fromchat/ui/chat/PublicChatScreen.kt +++ b/app/src/main/java/ru/fromchat/ui/PublicChatScreen.kt @@ -1,4 +1,4 @@ -package ru.fromchat.ui.chat +package ru.fromchat.ui import android.util.Log import androidx.compose.foundation.background @@ -69,7 +69,6 @@ import ru.fromchat.api.ApiClient import ru.fromchat.api.Message import ru.fromchat.api.WebSocketManager import ru.fromchat.api.apiRequest -import ru.fromchat.ui.LocalNavController import kotlin.time.ExperimentalTime import kotlin.time.Instant diff --git a/app/src/main/java/ru/fromchat/ui/main/ChatsTab.kt b/app/src/main/java/ru/fromchat/ui/main/ChatsTab.kt new file mode 100644 index 0000000..29d6a17 --- /dev/null +++ b/app/src/main/java/ru/fromchat/ui/main/ChatsTab.kt @@ -0,0 +1,52 @@ +package ru.fromchat.ui.main + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ListItem +import androidx.compose.material3.MediumTopAppBar +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.input.nestedscroll.nestedScroll +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextOverflow +import ru.fromchat.R +import ru.fromchat.ui.LocalNavController + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun ChatsTab() { + val navController = LocalNavController.current + val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior() + + Scaffold( + modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection), + topBar = { + MediumTopAppBar( + title = { + Text( + text = stringResource(R.string.chats), + maxLines = 1, + overflow = TextOverflow.Ellipsis + ) + }, + scrollBehavior = scrollBehavior + ) + } + ) { innerPadding -> + LazyColumn(contentPadding = innerPadding) { + item { + ListItem( + headlineContent = { Text(stringResource(R.string.public_chat)) }, + supportingContent = { Text(stringResource(R.string.chat_last_mesaage)) }, + modifier = Modifier.clickable { + navController.navigate("chats/publicChat") + } + ) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/ru/fromchat/ui/chat/ChatScreen.kt b/app/src/main/java/ru/fromchat/ui/main/MainScreen.kt similarity index 78% rename from app/src/main/java/ru/fromchat/ui/chat/ChatScreen.kt rename to app/src/main/java/ru/fromchat/ui/main/MainScreen.kt index 803923d..67cbfe2 100644 --- a/app/src/main/java/ru/fromchat/ui/chat/ChatScreen.kt +++ b/app/src/main/java/ru/fromchat/ui/main/MainScreen.kt @@ -1,15 +1,16 @@ -package ru.fromchat.ui.chat +package ru.fromchat.ui.main -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing import androidx.compose.material.icons.Icons import androidx.compose.material.icons.automirrored.filled.Chat import androidx.compose.material.icons.filled.Contacts import androidx.compose.material.icons.filled.Mail import androidx.compose.material3.Icon -import androidx.compose.material3.ListItem import androidx.compose.material3.NavigationBar import androidx.compose.material3.NavigationBarItem import androidx.compose.material3.Scaffold @@ -22,12 +23,11 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import ru.fromchat.R -import ru.fromchat.ui.LocalNavController +import ru.fromchat.utils.exclude @Composable -fun ChatScreen() { +fun MainScreen() { var selectedTab by remember { mutableStateOf("chats") } - val navController = LocalNavController.current Scaffold( bottomBar = { @@ -51,7 +51,8 @@ fun ChatScreen() { icon = { Icon(Icons.Filled.Mail, contentDescription = null) } ) } - } + }, + contentWindowInsets = WindowInsets.safeDrawing.exclude(WindowInsetsSides.Top) ) { innerPadding -> Column( Modifier @@ -59,15 +60,7 @@ fun ChatScreen() { .padding(innerPadding) ) { when (selectedTab) { - "chats" -> { - ListItem( - headlineContent = { Text(stringResource(R.string.public_chat)) }, - supportingContent = { Text(stringResource(R.string.chat_last_mesaage)) }, - modifier = Modifier.clickable { - navController.navigate("chats/publicChat") - } - ) - } + "chats" -> ChatsTab() "contacts" -> { Text(stringResource(R.string.coming_soon)) } diff --git a/app/src/main/java/ru/fromchat/utils/Generic.kt b/app/src/main/java/ru/fromchat/utils/Generic.kt new file mode 100644 index 0000000..6a0c6fc --- /dev/null +++ b/app/src/main/java/ru/fromchat/utils/Generic.kt @@ -0,0 +1,8 @@ +package ru.fromchat.utils + +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.exclude +import androidx.compose.foundation.layout.only + +inline fun WindowInsets.exclude(sides: WindowInsetsSides) = exclude(this.only(sides)) \ No newline at end of file diff --git a/app/src/main/java/ru/fromchat/utils/Ktor.kt b/app/src/main/java/ru/fromchat/utils/Ktor.kt index d7d8565..cb2c90c 100644 --- a/app/src/main/java/ru/fromchat/utils/Ktor.kt +++ b/app/src/main/java/ru/fromchat/utils/Ktor.kt @@ -1,7 +1,6 @@ @file:Suppress("NOTHING_TO_INLINE") package ru.fromchat.utils -import android.util.Log import io.ktor.client.HttpClientConfig import io.ktor.client.plugins.ClientRequestException import io.ktor.client.plugins.DefaultRequest @@ -76,27 +75,14 @@ inline fun HttpClientConfig<*>.logging() = logging { /** * Throws if the HTTP response status code is an error (>=400). * @return The [HttpResponse] if successful. - * @throws ClientRequestException - * @throws ServerResponseException - * @throws ResponseException on error. + * @throws ClientRequestException on 4xx error code. + * @throws ServerResponseException on 5xx error code. + * @throws ResponseException on unknown error code. */ -suspend fun HttpResponse.failOnError(): HttpResponse { - Log.d("failOnError", "Checking the response code...") - val statusCode = status.value - suspend fun body() = bodyAsText() - - Log.d("failOnError", "code: $statusCode") - - when (statusCode) { - in 400..499 -> throw ClientRequestException(this, body()) - in 500..599 -> throw ServerResponseException(this, body()) - } - - if (statusCode >= 600) { - throw ResponseException(this, body()) - } - - Log.d("failOnError", "Success") - - return this -} \ No newline at end of file +suspend fun HttpResponse.failOnError() = + when (status.value) { + in 100..399 -> this + in 400..499 -> throw ClientRequestException(this, bodyAsText()) + in 500..599 -> throw ServerResponseException(this, bodyAsText()) + else -> throw ResponseException(this, bodyAsText()) + } \ No newline at end of file