123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 |
- package io.nexilis.alpha.ui.main
- import android.net.Uri
- import androidx.compose.foundation.background
- import androidx.compose.foundation.layout.*
- import androidx.compose.foundation.lazy.LazyColumn
- import androidx.compose.foundation.lazy.rememberLazyListState
- import androidx.compose.foundation.lazy.items
- import androidx.compose.foundation.shape.CircleShape
- import androidx.compose.foundation.shape.RoundedCornerShape
- import androidx.compose.foundation.text.KeyboardOptions
- import androidx.compose.material.icons.Icons
- import androidx.compose.material.icons.automirrored.filled.Send
- import androidx.compose.material3.*
- import androidx.compose.runtime.*
- import androidx.compose.runtime.livedata.observeAsState
- import androidx.compose.runtime.saveable.rememberSaveable
- import androidx.compose.ui.Modifier
- import androidx.compose.ui.graphics.Color
- import androidx.compose.ui.graphics.graphicsLayer
- import androidx.compose.ui.platform.LocalContext
- import androidx.compose.ui.text.TextRange
- import androidx.compose.ui.text.input.KeyboardCapitalization
- import androidx.compose.ui.text.input.TextFieldValue
- import androidx.compose.ui.unit.dp
- import androidx.hilt.navigation.compose.hiltViewModel
- import androidx.navigation.NavHostController
- import io.nexilis.alpha.ui.components.AttachmentItemList
- import io.nexilis.alpha.ui.components.Attachments
- import io.nexilis.alpha.ui.components.ContentChat
- import io.nexilis.alpha.ui.components.LeftBubbleChat
- import io.nexilis.alpha.ui.components.RightBubbleChat
- import io.nexilis.alpha.ui.components.getAttachmentItem
- import io.nexilis.alpha.ui.screen.Screen
- import io.nexilis.service.data.entities.Buddy
- import io.nexilis.service.data.entities.Message
- import io.nexilis.service.data.viewmodels.BuddyViewModel
- import io.nexilis.service.data.viewmodels.MessageViewModel
- import kotlinx.serialization.encodeToString
- import kotlinx.serialization.json.Json
- @OptIn(ExperimentalLayoutApi::class)
- @Composable
- fun Chat(
- navController: NavHostController,
- contentPadding: PaddingValues,
- pin: String,
- me: Buddy
- ) {
- var textInput by rememberSaveable(stateSaver = TextFieldValue.Saver) {
- mutableStateOf(TextFieldValue("", TextRange(0, 7)))
- }
- val messageModel: MessageViewModel = hiltViewModel()
- val list by messageModel.getOpposite(pin).observeAsState()
- val state = rememberLazyListState()
- val context = LocalContext.current
- var openAlertDialog by remember { mutableStateOf(false) }
- val attachments = remember { mutableStateListOf<Uri>() }
- Column(
- modifier = Modifier
- .fillMaxSize()
- .consumeWindowInsets(contentPadding)
- .imePadding()
- .imeNestedScroll()
- ) {
- LazyColumn(
- modifier = Modifier
- .weight(1f),
- state = state,
- reverseLayout = true
- ) {
- list?.let { l ->
- items(l) { message ->
- ListItem(modifier = Modifier.fillMaxWidth(), headlineContent = {
- Row(
- modifier = Modifier.fillMaxWidth(),
- horizontalArrangement = if (message.f_pin == me.f_pin) Arrangement.End else Arrangement.Start
- ) {
- if (message.f_pin == me.f_pin) {
- Spacer(modifier = Modifier.weight(0.1f))
- RightBubbleChat(
- modifier = Modifier.weight(weight = 0.9f, fill = false),
- message = message,
- ) {
- ContentChat(
- modifier = Modifier.fillMaxWidth(0.7f),
- message = message
- )
- }
- } else {
- LeftBubbleChat(
- modifier = Modifier.weight(weight = 0.9f, fill = false),
- message = message
- ) {
- ContentChat(
- modifier = Modifier.fillMaxWidth(0.7f),
- message = message
- )
- }
- Spacer(modifier = Modifier.weight(0.1f))
- }
- }
- }, colors = ListItemDefaults.colors(containerColor = Color.Transparent))
- }
- }
- }
- TextField(
- modifier = Modifier
- .fillMaxWidth()
- .graphicsLayer {
- shape = CircleShape
- clip = true
- }
- .padding(4.dp),
- value = textInput,
- onValueChange = { textInput = it },
- label = null,
- placeholder = {
- Text(text = "Typing here...", color = MaterialTheme.colorScheme.onSurface)
- },
- leadingIcon = {
- Attachments(
- modifier = Modifier
- .height(300.dp)
- .fillMaxWidth()
- .padding(start = 16.dp, end = 16.dp, bottom = 8.dp)
- .graphicsLayer {
- shape = RoundedCornerShape(16.dp)
- clip = true
- }
- .background(MaterialTheme.colorScheme.surfaceContainer),
- onAttachment = { list ->
- attachments.addAll(list)
- val items = list.map {
- context.getAttachmentItem(it)
- }
- if (items.size == 1) {
- val params = AttachmentItemList(items)
- val data = Uri.encode(Json.encodeToString(params))
- navController.navigate(Screen.AttachmentCaption.route + "?data=${data}&pin=${pin}") {
- launchSingleTop = true
- restoreState = true
- }
- } else if (items.size > 1) {
- openAlertDialog = true
- }
- }
- )
- },
- trailingIcon = {
- Row {
- IconButton(onClick = {
- if (pin.trim().isEmpty()) {
- return@IconButton
- }
- if (textInput.text.trim().isEmpty()) {
- return@IconButton
- }
- me.let {
- messageModel.send(
- context,
- Message(
- message_id = System.nanoTime().toString(),
- f_pin = it.f_pin,
- l_pin = pin,
- message_scope_id = "3", // 3: chat, 15: sms, 16: email
- server_date = System.currentTimeMillis(),
- status = "1",
- message_text = textInput.text,
- opposite_pin = pin,
- f_display_name = "${it.first_name} ${it.last_name}".trim(),
- message_large_text = "",
- message_text_plain = "",
- uri = if (attachments.size > 0) attachments[0] else Uri.EMPTY
- )
- )
- textInput = TextFieldValue("")
- }
- }) {
- Icon(
- imageVector = Icons.AutoMirrored.Filled.Send,
- contentDescription = "",
- tint = MaterialTheme.colorScheme.primary
- )
- }
- }
- },
- colors = TextFieldDefaults.colors(
- focusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- disabledContainerColor = MaterialTheme.colorScheme.surfaceContainer,
- focusedIndicatorColor = Color.Transparent,
- unfocusedIndicatorColor = Color.Transparent,
- disabledIndicatorColor = Color.Transparent,
- errorIndicatorColor = Color.Transparent,
- ),
- keyboardOptions = KeyboardOptions(KeyboardCapitalization.Sentences),
- maxLines = 3
- )
- if (openAlertDialog) {
- val buddyModel: BuddyViewModel = hiltViewModel()
- val buddy by buddyModel.getBuddy(pin).observeAsState()
- buddy?.let {
- AlertDialog(
- text = {
- Text(text = "Send ${attachments.size} documents to ${it.first_name} ${it.last_name}?".trim())
- },
- onDismissRequest = {
- openAlertDialog = false
- },
- confirmButton = {
- TextButton(
- onClick = {
- openAlertDialog = false
- me.let {
- attachments.forEach { uri ->
- messageModel.send(
- context,
- Message(
- message_id = System.nanoTime().toString(),
- f_pin = it.f_pin,
- l_pin = pin,
- message_scope_id = "3", // 3: chat, 15: sms, 16: email
- server_date = System.currentTimeMillis(),
- status = "1",
- message_text = "",
- opposite_pin = pin,
- f_display_name = "${it.first_name} ${it.last_name}".trim(),
- message_large_text = "",
- message_text_plain = "",
- uri = uri
- )
- )
- }
- textInput = TextFieldValue("")
- }
- }
- ) {
- Text("Send")
- }
- },
- dismissButton = {
- TextButton(
- onClick = {
- openAlertDialog = false
- }
- ) {
- Text("Cancel")
- }
- }
- )
- }
- }
- }
- }
|