|
@@ -11,38 +11,39 @@ import androidx.activity.compose.rememberLauncherForActivityResult
|
|
|
import androidx.activity.result.contract.ActivityResultContracts
|
|
|
import androidx.compose.foundation.background
|
|
|
import androidx.compose.foundation.clickable
|
|
|
+import androidx.compose.foundation.layout.Arrangement
|
|
|
import androidx.compose.foundation.layout.Box
|
|
|
import androidx.compose.foundation.layout.Column
|
|
|
+import androidx.compose.foundation.layout.ExperimentalLayoutApi
|
|
|
+import androidx.compose.foundation.layout.PaddingValues
|
|
|
import androidx.compose.foundation.layout.Row
|
|
|
import androidx.compose.foundation.layout.Spacer
|
|
|
+import androidx.compose.foundation.layout.consumeWindowInsets
|
|
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
|
-import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
+import androidx.compose.foundation.layout.imeNestedScroll
|
|
|
+import androidx.compose.foundation.layout.imePadding
|
|
|
import androidx.compose.foundation.layout.padding
|
|
|
import androidx.compose.foundation.layout.size
|
|
|
+import androidx.compose.foundation.lazy.LazyColumn
|
|
|
import androidx.compose.foundation.shape.CircleShape
|
|
|
-import androidx.compose.foundation.text.KeyboardOptions
|
|
|
import androidx.compose.material.icons.Icons
|
|
|
-import androidx.compose.material.icons.automirrored.filled.Send
|
|
|
import androidx.compose.material.icons.filled.Add
|
|
|
import androidx.compose.material.icons.filled.AttachFile
|
|
|
import androidx.compose.material.icons.filled.Camera
|
|
|
import androidx.compose.material.icons.filled.Headset
|
|
|
import androidx.compose.material.icons.filled.Image
|
|
|
import androidx.compose.material.icons.filled.LocationOn
|
|
|
-import androidx.compose.material.icons.filled.Person
|
|
|
+import androidx.compose.material.icons.filled.PhotoCamera
|
|
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
|
|
import androidx.compose.material3.Icon
|
|
|
import androidx.compose.material3.IconButton
|
|
|
import androidx.compose.material3.MaterialTheme
|
|
|
import androidx.compose.material3.Text
|
|
|
-import androidx.compose.material3.TextField
|
|
|
-import androidx.compose.material3.TextFieldDefaults
|
|
|
import androidx.compose.material3.TooltipDefaults
|
|
|
import androidx.compose.runtime.Composable
|
|
|
import androidx.compose.runtime.getValue
|
|
|
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.Alignment
|
|
|
import androidx.compose.ui.Modifier
|
|
@@ -52,14 +53,10 @@ import androidx.compose.ui.layout.ContentScale
|
|
|
import androidx.compose.ui.platform.LocalContext
|
|
|
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
|
import androidx.compose.ui.res.painterResource
|
|
|
-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.compose.ui.window.Popup
|
|
|
import androidx.core.content.FileProvider
|
|
|
import androidx.core.net.toUri
|
|
|
-import androidx.hilt.navigation.compose.hiltViewModel
|
|
|
import androidx.navigation.NavHostController
|
|
|
import androidx.navigation.NavType
|
|
|
import coil.compose.AsyncImage
|
|
@@ -72,9 +69,7 @@ import io.nexilis.service.core.Orange
|
|
|
import io.nexilis.service.core.Purple
|
|
|
import io.nexilis.service.core.createFile
|
|
|
import io.nexilis.service.core.getMimeType
|
|
|
-import io.nexilis.service.core.getSharedPreferences
|
|
|
-import io.nexilis.service.data.entities.Message
|
|
|
-import io.nexilis.service.data.viewmodels.MessageViewModel
|
|
|
+import io.nexilis.service.data.entities.Buddy
|
|
|
import kotlinx.parcelize.Parcelize
|
|
|
import kotlinx.serialization.KSerializer
|
|
|
import kotlinx.serialization.Serializable
|
|
@@ -152,6 +147,32 @@ fun Attachments(modifier: Modifier, onAttachment: (List<Uri>) -> Unit) {
|
|
|
.show()
|
|
|
}
|
|
|
}
|
|
|
+ val launcherCaptureVideo =
|
|
|
+ rememberLauncherForActivityResult(ActivityResultContracts.CaptureVideo()) {
|
|
|
+ if (it) {
|
|
|
+ onAttachment(listOf(tempUri))
|
|
|
+ }
|
|
|
+ isOpenMenu = false
|
|
|
+ }
|
|
|
+ val permissionLauncherCaptureVideo = rememberLauncherForActivityResult(
|
|
|
+ ActivityResultContracts.RequestMultiplePermissions()
|
|
|
+ ) {
|
|
|
+ var accept = true
|
|
|
+ it.values.forEach { r ->
|
|
|
+ if (!r) accept = false
|
|
|
+ }
|
|
|
+ if (accept) {
|
|
|
+ val file = context.createFile(".mp4")
|
|
|
+ tempUri = FileProvider.getUriForFile(
|
|
|
+ context,
|
|
|
+ BuildConfig.APPLICATION_ID + ".provider", file
|
|
|
+ )
|
|
|
+ launcherCaptureVideo.launch(tempUri)
|
|
|
+ } else {
|
|
|
+ Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT)
|
|
|
+ .show()
|
|
|
+ }
|
|
|
+ }
|
|
|
Column {
|
|
|
AttachmentButton(
|
|
|
color = MaterialTheme.colorScheme.primary,
|
|
@@ -168,16 +189,17 @@ fun Attachments(modifier: Modifier, onAttachment: (List<Uri>) -> Unit) {
|
|
|
)
|
|
|
}
|
|
|
Spacer(modifier = Modifier.size(32.dp))
|
|
|
- AttachmentButton(color = Color.Orange, onClick = {
|
|
|
+ AttachmentButton(color = Color.Purple, onClick = {
|
|
|
mimeType = arrayOf(
|
|
|
- "audio/*"
|
|
|
+ "image/*",
|
|
|
+ "video/*"
|
|
|
)
|
|
|
permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
|
}, text = {
|
|
|
- Text(text = "Audio", style = MaterialTheme.typography.bodySmall)
|
|
|
+ Text(text = "Gallery", style = MaterialTheme.typography.bodySmall)
|
|
|
}) {
|
|
|
Icon(
|
|
|
- imageVector = Icons.Default.Headset,
|
|
|
+ imageVector = Icons.Default.Image,
|
|
|
contentDescription = "",
|
|
|
tint = Color.White
|
|
|
)
|
|
@@ -188,20 +210,25 @@ fun Attachments(modifier: Modifier, onAttachment: (List<Uri>) -> Unit) {
|
|
|
AttachmentButton(color = Color.Red, onClick = {
|
|
|
permissionLauncherCamera.launch(Manifest.permission.CAMERA)
|
|
|
}, text = {
|
|
|
- Text(text = "Camera", style = MaterialTheme.typography.bodySmall)
|
|
|
+ Text(text = "Photo", style = MaterialTheme.typography.bodySmall)
|
|
|
}) {
|
|
|
Icon(
|
|
|
- imageVector = Icons.Default.Camera,
|
|
|
+ imageVector = Icons.Default.PhotoCamera,
|
|
|
contentDescription = "",
|
|
|
tint = Color.White
|
|
|
)
|
|
|
}
|
|
|
Spacer(modifier = Modifier.size(32.dp))
|
|
|
- AttachmentButton(color = Color.DarkLimeGreen, onClick = {}, text = {
|
|
|
- Text(text = "Location", style = MaterialTheme.typography.bodySmall)
|
|
|
+ AttachmentButton(color = Color.Orange, onClick = {
|
|
|
+ mimeType = arrayOf(
|
|
|
+ "audio/*"
|
|
|
+ )
|
|
|
+ permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
|
+ }, text = {
|
|
|
+ Text(text = "Audio", style = MaterialTheme.typography.bodySmall)
|
|
|
}) {
|
|
|
Icon(
|
|
|
- imageVector = Icons.Default.LocationOn,
|
|
|
+ imageVector = Icons.Default.Headset,
|
|
|
contentDescription = "",
|
|
|
tint = Color.White
|
|
|
)
|
|
@@ -209,27 +236,28 @@ fun Attachments(modifier: Modifier, onAttachment: (List<Uri>) -> Unit) {
|
|
|
}
|
|
|
Spacer(modifier = Modifier.size(16.dp))
|
|
|
Column {
|
|
|
- AttachmentButton(color = Color.Purple, onClick = {
|
|
|
- mimeType = arrayOf(
|
|
|
- "image/*",
|
|
|
- "video/*"
|
|
|
+ AttachmentButton(color = Color.DarkLimeGreen, onClick = {
|
|
|
+ permissionLauncherCaptureVideo.launch(
|
|
|
+ arrayOf(
|
|
|
+ Manifest.permission.CAMERA,
|
|
|
+ Manifest.permission.RECORD_AUDIO
|
|
|
+ )
|
|
|
)
|
|
|
- permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
|
|
|
}, text = {
|
|
|
- Text(text = "Gallery", style = MaterialTheme.typography.bodySmall)
|
|
|
+ Text(text = "Video", style = MaterialTheme.typography.bodySmall)
|
|
|
}) {
|
|
|
Icon(
|
|
|
- imageVector = Icons.Default.Image,
|
|
|
+ imageVector = Icons.Default.Camera,
|
|
|
contentDescription = "",
|
|
|
tint = Color.White
|
|
|
)
|
|
|
}
|
|
|
Spacer(modifier = Modifier.size(32.dp))
|
|
|
AttachmentButton(color = Color.BlueSky, onClick = {}, text = {
|
|
|
- Text(text = "Contact", style = MaterialTheme.typography.bodySmall)
|
|
|
+ Text(text = "Location", style = MaterialTheme.typography.bodySmall)
|
|
|
}) {
|
|
|
Icon(
|
|
|
- imageVector = Icons.Default.Person,
|
|
|
+ imageVector = Icons.Default.LocationOn,
|
|
|
contentDescription = "",
|
|
|
tint = Color.White
|
|
|
)
|
|
@@ -329,94 +357,71 @@ val AttachmentItemListType = object : NavType<AttachmentItemList>(isNullableAllo
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+@OptIn(ExperimentalLayoutApi::class)
|
|
|
@Composable
|
|
|
fun AttachmentCaption(
|
|
|
navController: NavHostController,
|
|
|
+ contentPadding: PaddingValues,
|
|
|
pin: String,
|
|
|
+ me: Buddy,
|
|
|
attachments: AttachmentItemList
|
|
|
) {
|
|
|
- var textInput by rememberSaveable(stateSaver = TextFieldValue.Saver) {
|
|
|
- mutableStateOf(TextFieldValue("", TextRange(0, 7)))
|
|
|
- }
|
|
|
- val messageModel: MessageViewModel = hiltViewModel()
|
|
|
- val context = LocalContext.current
|
|
|
- Column(modifier = Modifier.fillMaxSize()) {
|
|
|
- attachments.list[0]?.let {
|
|
|
- if (it.mimeType.startsWith("image")) {
|
|
|
- AsyncImage(
|
|
|
- model = ImageRequest.Builder(LocalContext.current)
|
|
|
- .data(it.uri)
|
|
|
- .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
|
|
|
- .crossfade(true)
|
|
|
- .build(),
|
|
|
- placeholder = painterResource(R.drawable.ic_placeholder),
|
|
|
- contentDescription = "",
|
|
|
- contentScale = ContentScale.Fit,
|
|
|
- modifier = Modifier
|
|
|
- .weight(1f)
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- TextField(
|
|
|
- modifier = Modifier
|
|
|
- .fillMaxWidth()
|
|
|
- .graphicsLayer {
|
|
|
- shape = CircleShape
|
|
|
- clip = true
|
|
|
- },
|
|
|
- value = textInput,
|
|
|
- onValueChange = { textInput = it },
|
|
|
- label = null,
|
|
|
- placeholder = {
|
|
|
- Text(text = "Add a caption...", color = MaterialTheme.colorScheme.onSurface)
|
|
|
- },
|
|
|
- trailingIcon = {
|
|
|
- Row {
|
|
|
- IconButton(onClick = {
|
|
|
- val me = context.getSharedPreferences().getString("pin", null)
|
|
|
- me?.let {
|
|
|
- attachments.list[0]?.let { item ->
|
|
|
- messageModel.send(
|
|
|
- context,
|
|
|
- Message(
|
|
|
- message_id = System.nanoTime().toString(),
|
|
|
- f_pin = it,
|
|
|
- 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 = "",
|
|
|
- message_large_text = "",
|
|
|
- message_text_plain = "",
|
|
|
- uri = item.uri
|
|
|
- )
|
|
|
- )
|
|
|
- }
|
|
|
- }
|
|
|
- textInput = TextFieldValue("")
|
|
|
- navController.popBackStack()
|
|
|
- }) {
|
|
|
- Icon(
|
|
|
- imageVector = Icons.AutoMirrored.Filled.Send,
|
|
|
+ Column(
|
|
|
+ modifier = Modifier
|
|
|
+ .fillMaxSize()
|
|
|
+ .consumeWindowInsets(contentPadding)
|
|
|
+ .imePadding()
|
|
|
+ .imeNestedScroll()
|
|
|
+ ) {
|
|
|
+ LazyColumn(
|
|
|
+ modifier = Modifier.weight(1.0f),
|
|
|
+ reverseLayout = true,
|
|
|
+ verticalArrangement = Arrangement.Top
|
|
|
+ ) {
|
|
|
+ attachments.list[0]?.let {
|
|
|
+ item {
|
|
|
+ if (it.mimeType.startsWith("image")) {
|
|
|
+ AsyncImage(
|
|
|
+ model = ImageRequest.Builder(LocalContext.current)
|
|
|
+ .data(it.uri)
|
|
|
+ .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
|
|
|
+ .crossfade(true)
|
|
|
+ .build(),
|
|
|
+ placeholder = painterResource(R.drawable.ic_placeholder),
|
|
|
contentDescription = "",
|
|
|
- tint = MaterialTheme.colorScheme.primary
|
|
|
+ contentScale = ContentScale.Fit,
|
|
|
+ modifier = Modifier.fillMaxSize()
|
|
|
)
|
|
|
+ } else if (it.mimeType.startsWith("video")) {
|
|
|
+
|
|
|
+ } else if (it.mimeType.startsWith("audio")) {
|
|
|
+ Icon(
|
|
|
+ imageVector = Icons.Default.Headset,
|
|
|
+ contentDescription = null,
|
|
|
+ modifier = Modifier.fillMaxSize(),
|
|
|
+ tint = Color.Orange
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+
|
|
|
}
|
|
|
}
|
|
|
- },
|
|
|
- colors = TextFieldDefaults.colors(
|
|
|
- focusedContainerColor = MaterialTheme.colorScheme.surface,
|
|
|
- unfocusedContainerColor = MaterialTheme.colorScheme.surface,
|
|
|
- disabledContainerColor = MaterialTheme.colorScheme.surface,
|
|
|
- focusedIndicatorColor = Color.Transparent,
|
|
|
- unfocusedIndicatorColor = Color.Transparent,
|
|
|
- disabledIndicatorColor = Color.Transparent,
|
|
|
- errorIndicatorColor = Color.Transparent,
|
|
|
- ),
|
|
|
- keyboardOptions = KeyboardOptions(KeyboardCapitalization.Sentences),
|
|
|
- maxLines = 3
|
|
|
+ }
|
|
|
+ }
|
|
|
+ val list = arrayListOf<Uri>()
|
|
|
+ attachments.list.forEach {
|
|
|
+ it?.let {
|
|
|
+ list.add(it.uri)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ InputChat(
|
|
|
+ navController = navController,
|
|
|
+ pin = pin,
|
|
|
+ me = me,
|
|
|
+ placeHolderText = "Add a caption...",
|
|
|
+ enableAttachment = false,
|
|
|
+ enableEmpty = true,
|
|
|
+ popAfterSent = true,
|
|
|
+ attachments = list
|
|
|
)
|
|
|
}
|
|
|
}
|