mirror of
https://github.com/fromchat-messenger/app.git
synced 2026-09-22 19:15:05 +03:00
Add public chat screen
Signed-off-by: denis0001-dev <denis0001.dev@ya.ru>
This commit is contained in:
@@ -4,13 +4,19 @@ import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection.
|
|||||||
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection.Companion.Start
|
import androidx.compose.animation.AnimatedContentTransitionScope.SlideDirection.Companion.Start
|
||||||
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.compositionLocalOf
|
||||||
import androidx.compose.ui.unit.IntOffset
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
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.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.chat.ChatScreen
|
import ru.fromchat.ui.chat.ChatScreen
|
||||||
|
import ru.fromchat.ui.chat.PublicChatScreen
|
||||||
|
|
||||||
|
val LocalNavController = compositionLocalOf<NavController> { error("") }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun App() {
|
fun App() {
|
||||||
@@ -18,48 +24,56 @@ fun App() {
|
|||||||
val navController = rememberNavController()
|
val navController = rememberNavController()
|
||||||
val animationSpec = tween<IntOffset>(400)
|
val animationSpec = tween<IntOffset>(400)
|
||||||
|
|
||||||
NavHost(
|
CompositionLocalProvider(
|
||||||
navController = navController,
|
LocalNavController provides navController
|
||||||
startDestination = "login",
|
|
||||||
enterTransition = {
|
|
||||||
slideIntoContainer(
|
|
||||||
Start,
|
|
||||||
animationSpec = animationSpec
|
|
||||||
)
|
|
||||||
},
|
|
||||||
exitTransition = {
|
|
||||||
slideOutOfContainer(
|
|
||||||
Start,
|
|
||||||
animationSpec = animationSpec
|
|
||||||
)
|
|
||||||
},
|
|
||||||
popEnterTransition = {
|
|
||||||
slideIntoContainer(
|
|
||||||
End,
|
|
||||||
animationSpec = animationSpec
|
|
||||||
)
|
|
||||||
},
|
|
||||||
popExitTransition = {
|
|
||||||
slideOutOfContainer(
|
|
||||||
End,
|
|
||||||
animationSpec = animationSpec
|
|
||||||
)
|
|
||||||
}
|
|
||||||
) {
|
) {
|
||||||
composable("login") {
|
NavHost(
|
||||||
LoginScreen(
|
navController = navController,
|
||||||
onLoginSuccess = { navController.navigate("chat") },
|
startDestination = "login",
|
||||||
onNavigateToRegister = { navController.navigate("register") }
|
enterTransition = {
|
||||||
)
|
slideIntoContainer(
|
||||||
}
|
Start,
|
||||||
|
animationSpec = animationSpec
|
||||||
|
)
|
||||||
|
},
|
||||||
|
exitTransition = {
|
||||||
|
slideOutOfContainer(
|
||||||
|
Start,
|
||||||
|
animationSpec = animationSpec
|
||||||
|
)
|
||||||
|
},
|
||||||
|
popEnterTransition = {
|
||||||
|
slideIntoContainer(
|
||||||
|
End,
|
||||||
|
animationSpec = animationSpec
|
||||||
|
)
|
||||||
|
},
|
||||||
|
popExitTransition = {
|
||||||
|
slideOutOfContainer(
|
||||||
|
End,
|
||||||
|
animationSpec = animationSpec
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
composable("login") {
|
||||||
|
LoginScreen(
|
||||||
|
onLoginSuccess = { navController.navigate("chat") },
|
||||||
|
onNavigateToRegister = { navController.navigate("register") }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
composable("register") {
|
composable("register") {
|
||||||
RegisterScreen(
|
RegisterScreen(
|
||||||
onRegistered = { navController.navigate("login") }
|
onRegistered = { navController.navigate("login") }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
composable("chat") { ChatScreen() }
|
composable("chat") { ChatScreen() }
|
||||||
|
|
||||||
|
composable("chats/publicChat") {
|
||||||
|
PublicChatScreen()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,6 +9,7 @@ import androidx.compose.material.icons.automirrored.filled.Chat
|
|||||||
import androidx.compose.material.icons.filled.Contacts
|
import androidx.compose.material.icons.filled.Contacts
|
||||||
import androidx.compose.material.icons.filled.Mail
|
import androidx.compose.material.icons.filled.Mail
|
||||||
import androidx.compose.material3.Icon
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.ListItem
|
||||||
import androidx.compose.material3.NavigationBar
|
import androidx.compose.material3.NavigationBar
|
||||||
import androidx.compose.material3.NavigationBarItem
|
import androidx.compose.material3.NavigationBarItem
|
||||||
import androidx.compose.material3.Scaffold
|
import androidx.compose.material3.Scaffold
|
||||||
@@ -20,13 +21,14 @@ import androidx.compose.runtime.remember
|
|||||||
import androidx.compose.runtime.setValue
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
|
import ru.fromchat.ui.LocalNavController
|
||||||
|
|
||||||
enum class ChatTab { CHATS, CONTACTS, DMS }
|
enum class ChatTab { CHATS, CONTACTS, DMS }
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun ChatScreen() {
|
fun ChatScreen() {
|
||||||
var selectedTab by remember { mutableStateOf(ChatTab.CHATS) }
|
var selectedTab by remember { mutableStateOf(ChatTab.CHATS) }
|
||||||
var activeChat by remember { mutableStateOf<String?>(null) }
|
val navController = LocalNavController.current
|
||||||
|
|
||||||
Scaffold(
|
Scaffold(
|
||||||
bottomBar = {
|
bottomBar = {
|
||||||
@@ -51,16 +53,17 @@ fun ChatScreen() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
) { paddingValues ->
|
) { innerPadding ->
|
||||||
Column(modifier = Modifier.fillMaxSize().padding(paddingValues).padding(12.dp)) {
|
Column(modifier = Modifier.fillMaxSize().padding(innerPadding).padding(12.dp)) {
|
||||||
when (selectedTab) {
|
when (selectedTab) {
|
||||||
ChatTab.CHATS -> {
|
ChatTab.CHATS -> {
|
||||||
if (activeChat == null) {
|
ListItem(
|
||||||
Text("Общий чат", modifier = Modifier.clickable { activeChat = "Общий чат" }.padding(8.dp))
|
headlineContent = { Text("Public chat") },
|
||||||
Text("Общий чат 2", modifier = Modifier.clickable { activeChat = "Общий чат 2" }.padding(8.dp))
|
supportingContent = { Text("You: last message") },
|
||||||
} else {
|
modifier = Modifier.clickable {
|
||||||
BaseChat(chatTitle = activeChat!!)
|
navController.navigate("chats/publicChat")
|
||||||
}
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
ChatTab.CONTACTS -> {
|
ChatTab.CONTACTS -> {
|
||||||
Text("Скоро будет...")
|
Text("Скоро будет...")
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
package ru.fromchat.ui.chat
|
||||||
|
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.IntrinsicSize
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.Spacer
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.foundation.rememberScrollState
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.foundation.verticalScroll
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.automirrored.filled.ArrowBack
|
||||||
|
import androidx.compose.material.icons.filled.DoneAll
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.Scaffold
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TopAppBar
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.draw.clip
|
||||||
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.unit.sp
|
||||||
|
import ru.fromchat.ui.LocalNavController
|
||||||
|
|
||||||
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
|
@Composable
|
||||||
|
fun PublicChatScreen() {
|
||||||
|
val navController = LocalNavController.current
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
TopAppBar(
|
||||||
|
title = {
|
||||||
|
Text(
|
||||||
|
text = "Public Chat",
|
||||||
|
maxLines = 1,
|
||||||
|
overflow = TextOverflow.Ellipsis
|
||||||
|
)
|
||||||
|
},
|
||||||
|
navigationIcon = {
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
navController.navigateUp()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
|
||||||
|
contentDescription = "Back"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
) { innerPadding ->
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.padding(innerPadding)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
) {
|
||||||
|
@Composable
|
||||||
|
fun Message(
|
||||||
|
text: String,
|
||||||
|
isAuthor: Boolean,
|
||||||
|
isRead: Boolean,
|
||||||
|
timestamp: String
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.padding(horizontal = 16.dp, vertical = 4.dp)
|
||||||
|
.fillMaxWidth(),
|
||||||
|
horizontalArrangement = if (isAuthor) Arrangement.End else Arrangement.Start
|
||||||
|
) {
|
||||||
|
val background =
|
||||||
|
if (isAuthor)
|
||||||
|
MaterialTheme.colorScheme.primaryContainer
|
||||||
|
else MaterialTheme.colorScheme.surfaceContainer
|
||||||
|
|
||||||
|
Column(
|
||||||
|
Modifier
|
||||||
|
.clip(
|
||||||
|
RoundedCornerShape(
|
||||||
|
if (isAuthor) 16.dp else 5.dp,
|
||||||
|
16.dp,
|
||||||
|
if (isAuthor) 5.dp else 16.dp,
|
||||||
|
16.dp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.background(background)
|
||||||
|
.padding(10.dp)
|
||||||
|
.width(IntrinsicSize.Max)
|
||||||
|
) {
|
||||||
|
Text(text)
|
||||||
|
Row(
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(0.dp, Alignment.End),
|
||||||
|
modifier = Modifier.fillMaxWidth()
|
||||||
|
) {
|
||||||
|
Spacer(Modifier.weight(1f))
|
||||||
|
Text(
|
||||||
|
text = timestamp,
|
||||||
|
fontSize = 14.sp
|
||||||
|
)
|
||||||
|
if (isRead) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Filled.DoneAll,
|
||||||
|
contentDescription = "Read",
|
||||||
|
modifier = Modifier.size(17.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repeat(100) {
|
||||||
|
Message(
|
||||||
|
text = "test",
|
||||||
|
isAuthor = true,
|
||||||
|
isRead = true,
|
||||||
|
timestamp = "9:41"
|
||||||
|
)
|
||||||
|
Message(
|
||||||
|
text = "test2",
|
||||||
|
isAuthor = false,
|
||||||
|
isRead = true,
|
||||||
|
timestamp = "9:41"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user