package io.nexilis.alpha.ui.components import android.net.Uri import androidx.compose.foundation.background import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding 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.AlertDialog import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.material3.TextField import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateListOf import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.saveable.rememberSaveable import androidx.compose.runtime.setValue 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.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 @Composable fun InputChat( navController: NavHostController, pin: String, me: Buddy, placeHolderText: String = "Typing here...", enableAttachment: Boolean = true, enableEmpty: Boolean = false, popAfterSent: Boolean = false, attachments: ArrayList = arrayListOf() ) { val context = LocalContext.current val messageModel: MessageViewModel = hiltViewModel() var textInput by rememberSaveable(stateSaver = TextFieldValue.Saver) { mutableStateOf(TextFieldValue("", TextRange(0, 7))) } var openAlertDialog by remember { mutableStateOf(false) } val attachmentState = remember { mutableStateListOf() } attachmentState.addAll(attachments) val leadingIcon: (@Composable () -> Unit)? = if (enableAttachment) { { 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.surfaceContainerLowest), onAttachment = { list -> attachmentState.addAll(list) val items = list.map { context.toAttachmentItem(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 } } ) } } else null TextField( modifier = Modifier .fillMaxWidth() .padding(4.dp) .graphicsLayer { shape = RoundedCornerShape(16.dp) clip = true }, value = textInput, onValueChange = { textInput = it }, label = null, placeholder = { Text(text = placeHolderText, color = MaterialTheme.colorScheme.onSurface) }, leadingIcon = leadingIcon, trailingIcon = { Row { IconButton(onClick = { if (pin.trim().isEmpty()) { return@IconButton } if (!enableEmpty && textInput.text.trim().isEmpty()) { return@IconButton } me.let { messageModel.send( context = context, entity = 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 (attachmentState.size > 0) attachmentState[0] else Uri.EMPTY ) ) textInput = TextFieldValue("") if (popAfterSent) navController.popBackStack() } }) { Icon( imageVector = Icons.AutoMirrored.Filled.Send, contentDescription = "", tint = MaterialTheme.colorScheme.primary ) } } }, colors = TextFieldDefaults.colors( focusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLowest, unfocusedContainerColor = MaterialTheme.colorScheme.surfaceContainerLowest, disabledContainerColor = MaterialTheme.colorScheme.surfaceContainerLowest, 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 ${attachmentState.size} documents to ${it.first_name} ${it.last_name}?".trim()) }, onDismissRequest = { openAlertDialog = false }, confirmButton = { TextButton( onClick = { openAlertDialog = false me.let { attachmentState.forEach { uri -> messageModel.send( context = context, entity = 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") } } ) } } }