feat: Implement block/unblock user functionality with confirmation dialogs in ChatDetailScreen
This commit is contained in:
@@ -21,7 +21,7 @@
|
||||
android:exported="true"
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/Theme.RosettaAndroid"
|
||||
android:windowSoftInputMode="adjustNothing">
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
|
||||
@@ -195,6 +195,18 @@ interface MessageDao {
|
||||
@Query("DELETE FROM messages WHERE account = :account AND dialog_key = :dialogKey")
|
||||
suspend fun deleteDialog(account: String, dialogKey: String)
|
||||
|
||||
/**
|
||||
* Удалить все сообщения между двумя пользователями
|
||||
*/
|
||||
@Query("""
|
||||
DELETE FROM messages
|
||||
WHERE account = :account AND (
|
||||
(from_public_key = :user1 AND to_public_key = :user2) OR
|
||||
(from_public_key = :user2 AND to_public_key = :user1)
|
||||
)
|
||||
""")
|
||||
suspend fun deleteMessagesBetweenUsers(account: String, user1: String, user2: String)
|
||||
|
||||
/**
|
||||
* Количество непрочитанных сообщений в диалоге
|
||||
*/
|
||||
|
||||
@@ -243,6 +243,13 @@ fun ChatDetailScreen(
|
||||
var showMenu by remember { mutableStateOf(false) }
|
||||
var showDeleteConfirm by remember { mutableStateOf(false) }
|
||||
var showBlockConfirm by remember { mutableStateOf(false) }
|
||||
var showUnblockConfirm by remember { mutableStateOf(false) }
|
||||
|
||||
// Проверяем, заблокирован ли пользователь
|
||||
var isBlocked by remember { mutableStateOf(false) }
|
||||
LaunchedEffect(user.publicKey, currentUserPublicKey) {
|
||||
isBlocked = database.blacklistDao().isUserBlocked(user.publicKey, currentUserPublicKey)
|
||||
}
|
||||
|
||||
// Подключаем к ViewModel
|
||||
val messages by viewModel.messages.collectAsState()
|
||||
@@ -625,29 +632,33 @@ fun ChatDetailScreen(
|
||||
}
|
||||
)
|
||||
|
||||
// Block User (не показываем для Saved Messages)
|
||||
// Block/Unblock User (не показываем для Saved Messages)
|
||||
if (!isSavedMessages) {
|
||||
DropdownMenuItem(
|
||||
text = {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
Icons.Default.Block,
|
||||
if (isBlocked) Icons.Default.Check else Icons.Default.Block,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFFFF3B30),
|
||||
tint = if (isBlocked) PrimaryBlue else Color(0xFFFF3B30),
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(12.dp))
|
||||
Text(
|
||||
"Block User",
|
||||
color = Color(0xFFFF3B30),
|
||||
if (isBlocked) "Unblock User" else "Block User",
|
||||
color = if (isBlocked) PrimaryBlue else Color(0xFFFF3B30),
|
||||
fontSize = 16.sp
|
||||
)
|
||||
}
|
||||
},
|
||||
onClick = {
|
||||
showMenu = false
|
||||
if (isBlocked) {
|
||||
showUnblockConfirm = true
|
||||
} else {
|
||||
showBlockConfirm = true
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -675,6 +686,7 @@ fun ChatDetailScreen(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(paddingValues)
|
||||
.imePadding() // ⌨️ Поднимаем контент при появлении клавиатуры
|
||||
) {
|
||||
// Список сообщений - занимает весь экран
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
@@ -901,11 +913,13 @@ fun ChatDetailScreen(
|
||||
backgroundColor = inputBackgroundColor,
|
||||
textColor = textColor,
|
||||
placeholderColor = secondaryTextColor,
|
||||
secondaryTextColor = secondaryTextColor,
|
||||
// Reply state
|
||||
replyMessages = replyMessages,
|
||||
isForwardMode = isForwardMode,
|
||||
onCloseReply = { viewModel.clearReplyMessages() },
|
||||
chatTitle = chatTitle
|
||||
chatTitle = chatTitle,
|
||||
isBlocked = isBlocked
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1107,18 +1121,21 @@ fun ChatDetailScreen(
|
||||
showDeleteConfirm = false
|
||||
scope.launch {
|
||||
try {
|
||||
// Delete all messages in this dialog
|
||||
database.messageDao().deleteDialog(
|
||||
// Удаляем все сообщения из диалога
|
||||
// DELETE FROM messages WHERE ((from_public_key = ? AND to_public_key = ?) OR (from_public_key = ? AND to_public_key = ?)) AND account = ?
|
||||
database.messageDao().deleteMessagesBetweenUsers(
|
||||
account = currentUserPublicKey,
|
||||
dialogKey = user.publicKey
|
||||
user1 = user.publicKey,
|
||||
user2 = currentUserPublicKey
|
||||
)
|
||||
// Delete dialog cache
|
||||
// Очищаем кеш диалога
|
||||
database.dialogDao().deleteDialog(
|
||||
account = currentUserPublicKey,
|
||||
opponentKey = user.publicKey
|
||||
)
|
||||
android.util.Log.d("ChatDetail", "✅ Chat deleted with: ${user.publicKey.take(10)}")
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("ChatDetail", "Error deleting chat", e)
|
||||
android.util.Log.e("ChatDetail", "❌ Error deleting chat", e)
|
||||
}
|
||||
}
|
||||
onBack()
|
||||
@@ -1159,19 +1176,20 @@ fun ChatDetailScreen(
|
||||
showBlockConfirm = false
|
||||
scope.launch {
|
||||
try {
|
||||
// Add user to blacklist
|
||||
android.util.Log.d("ChatDetail", "🚫 Blocking user: ${user.publicKey.take(10)}")
|
||||
// Добавляем пользователя в blacklist
|
||||
database.blacklistDao().blockUser(
|
||||
com.rosetta.messenger.database.BlacklistEntity(
|
||||
publicKey = user.publicKey,
|
||||
account = currentUserPublicKey
|
||||
)
|
||||
)
|
||||
android.util.Log.d("ChatDetail", "User blocked: ${user.publicKey.take(10)}")
|
||||
isBlocked = true
|
||||
android.util.Log.d("ChatDetail", "✅ User blocked: ${user.publicKey.take(10)}")
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("ChatDetail", "Error blocking user", e)
|
||||
android.util.Log.e("ChatDetail", "❌ Error blocking user", e)
|
||||
}
|
||||
}
|
||||
onBack()
|
||||
}
|
||||
) {
|
||||
Text("Block", color = Color(0xFFFF3B30))
|
||||
@@ -1184,6 +1202,55 @@ fun ChatDetailScreen(
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Диалог подтверждения разблокировки
|
||||
if (showUnblockConfirm) {
|
||||
AlertDialog(
|
||||
onDismissRequest = { showUnblockConfirm = false },
|
||||
containerColor = if (isDarkTheme) Color(0xFF2C2C2E) else Color.White,
|
||||
title = {
|
||||
Text(
|
||||
"Unblock ${user.title.ifEmpty { "User" }}",
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = textColor
|
||||
)
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
"Are you sure you want to unblock this user? They will be able to send you messages again.",
|
||||
color = secondaryTextColor
|
||||
)
|
||||
},
|
||||
confirmButton = {
|
||||
TextButton(
|
||||
onClick = {
|
||||
showUnblockConfirm = false
|
||||
scope.launch {
|
||||
try {
|
||||
android.util.Log.d("ChatDetail", "✅ Unblocking user: ${user.publicKey.take(10)}")
|
||||
// Удаляем пользователя из blacklist
|
||||
database.blacklistDao().unblockUser(
|
||||
publicKey = user.publicKey,
|
||||
account = currentUserPublicKey
|
||||
)
|
||||
isBlocked = false
|
||||
android.util.Log.d("ChatDetail", "✅ User unblocked: ${user.publicKey.take(10)}")
|
||||
} catch (e: Exception) {
|
||||
android.util.Log.e("ChatDetail", "❌ Error unblocking user", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
) {
|
||||
Text("Unblock", color = PrimaryBlue)
|
||||
}
|
||||
},
|
||||
dismissButton = {
|
||||
TextButton(onClick = { showUnblockConfirm = false }) {
|
||||
Text("Cancel", color = Color(0xFF8E8E93))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** 🚀 Анимация появления сообщения Telegram-style */
|
||||
@@ -1454,11 +1521,13 @@ private fun MessageInputBar(
|
||||
backgroundColor: Color,
|
||||
textColor: Color,
|
||||
placeholderColor: Color,
|
||||
secondaryTextColor: Color,
|
||||
// Reply state (как в React Native)
|
||||
replyMessages: List<ChatViewModel.ReplyMessage> = emptyList(),
|
||||
isForwardMode: Boolean = false,
|
||||
onCloseReply: () -> Unit = {},
|
||||
chatTitle: String = ""
|
||||
chatTitle: String = "",
|
||||
isBlocked: Boolean = false
|
||||
) {
|
||||
val hasReply = replyMessages.isNotEmpty()
|
||||
var showEmojiPicker by remember { mutableStateOf(false) }
|
||||
@@ -1523,61 +1592,111 @@ private fun MessageInputBar(
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
) {
|
||||
// 🔥 TELEGRAM-STYLE FLOATING LIQUID GLASS INPUT
|
||||
// Используем Column вместо Row для reply panel внутри
|
||||
// Если пользователь заблокирован - показываем BlockedChatFooter
|
||||
if (isBlocked) {
|
||||
// BLOCKED CHAT FOOTER
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 16.dp, vertical = 16.dp)
|
||||
.background(
|
||||
color = if (isDarkTheme) Color(0xFF2C2C2E) else Color(0xFFF2F3F5),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = if (isDarkTheme) Color(0xFF3A3A3C) else Color(0xFFE5E5EA),
|
||||
shape = RoundedCornerShape(12.dp)
|
||||
)
|
||||
.padding(16.dp),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
horizontalArrangement = Arrangement.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Block,
|
||||
contentDescription = null,
|
||||
tint = Color(0xFFFF6B6B),
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.width(8.dp))
|
||||
Text(
|
||||
text = "You need to unblock user to send messages.",
|
||||
fontSize = 14.sp,
|
||||
color = secondaryTextColor,
|
||||
textAlign = androidx.compose.ui.text.style.TextAlign.Center
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// 🔥 REACT NATIVE STYLE: Attach | Glass Input | Mic
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 14.dp, vertical = 16.dp),
|
||||
verticalAlignment = Alignment.Bottom,
|
||||
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
||||
) {
|
||||
// ATTACH BUTTON - круглая кнопка слева
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
if (isDarkTheme) Color(0xFF3C3C3C).copy(alpha = 0.8f)
|
||||
else Color(0xFFF0F0F0).copy(alpha = 0.85f)
|
||||
)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.25f)
|
||||
else Color.Black.copy(alpha = 0.1f),
|
||||
shape = CircleShape
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = null
|
||||
) { /* TODO: Attach */ },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Attachment,
|
||||
contentDescription = "Attach",
|
||||
tint = if (isDarkTheme) Color.White else Color(0xFF333333),
|
||||
modifier = Modifier.size(22.dp).graphicsLayer { rotationZ = -45f }
|
||||
)
|
||||
}
|
||||
|
||||
// GLASS INPUT - расширяется, содержит Emoji + TextField + Send
|
||||
Column(
|
||||
modifier =
|
||||
Modifier.fillMaxWidth()
|
||||
.padding(horizontal = 8.dp, vertical = 16.dp)
|
||||
// Инпут растёт вверх до 6 строк (~140dp) + reply
|
||||
.heightIn(min = 44.dp, max = if (hasReply) 200.dp else 140.dp)
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.heightIn(min = 48.dp, max = if (hasReply) 200.dp else 140.dp)
|
||||
.shadow(
|
||||
elevation = 4.dp,
|
||||
shape = RoundedCornerShape(22.dp),
|
||||
shape = RoundedCornerShape(if (hasReply) 16.dp else 22.dp),
|
||||
clip = false,
|
||||
ambientColor = Color.Black.copy(alpha = 0.2f),
|
||||
spotColor = Color.Black.copy(alpha = 0.2f)
|
||||
)
|
||||
.clip(RoundedCornerShape(22.dp))
|
||||
.clip(RoundedCornerShape(if (hasReply) 16.dp else 22.dp))
|
||||
.background(
|
||||
brush =
|
||||
Brush.verticalGradient(
|
||||
colors =
|
||||
if (isDarkTheme) {
|
||||
brush = Brush.verticalGradient(
|
||||
colors = if (isDarkTheme) {
|
||||
listOf(
|
||||
Color(0xFF2D2D2F)
|
||||
.copy(alpha = 0.92f),
|
||||
Color(0xFF1C1C1E)
|
||||
.copy(alpha = 0.96f)
|
||||
Color(0xFF3C3C3C).copy(alpha = 0.9f),
|
||||
Color(0xFF2C2C2C).copy(alpha = 0.95f)
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
Color(0xFFF2F2F7)
|
||||
.copy(alpha = 0.94f),
|
||||
Color(0xFFE5E5EA)
|
||||
.copy(alpha = 0.97f)
|
||||
Color(0xFFF0F0F0).copy(alpha = 0.92f),
|
||||
Color(0xFFE8E8E8).copy(alpha = 0.96f)
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
brush =
|
||||
Brush.verticalGradient(
|
||||
colors =
|
||||
if (isDarkTheme) {
|
||||
listOf(
|
||||
Color.White.copy(alpha = 0.18f),
|
||||
Color.White.copy(alpha = 0.06f)
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
Color.White.copy(alpha = 0.9f),
|
||||
Color.Black.copy(alpha = 0.05f)
|
||||
)
|
||||
}
|
||||
),
|
||||
shape = RoundedCornerShape(22.dp)
|
||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.25f)
|
||||
else Color.Black.copy(alpha = 0.1f),
|
||||
shape = RoundedCornerShape(if (hasReply) 16.dp else 22.dp)
|
||||
)
|
||||
) {
|
||||
// 🔥 REPLY PANEL внутри glass (как в React Native)
|
||||
@@ -1642,17 +1761,46 @@ private fun MessageInputBar(
|
||||
}
|
||||
}
|
||||
|
||||
// Input Row
|
||||
// Input Row внутри Glass
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = 6.dp, vertical = 4.dp),
|
||||
.padding(start = 14.dp, end = 6.dp, top = 4.dp, bottom = 4.dp),
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
// TEXT INPUT
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(1f)
|
||||
.align(Alignment.CenterVertically),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
) {
|
||||
AppleEmojiTextField(
|
||||
value = value,
|
||||
onValueChange = { newValue -> onValueChange(newValue) },
|
||||
textColor = textColor,
|
||||
textSize = 16f,
|
||||
hint = "Message",
|
||||
hintColor = if (isDarkTheme) Color.White.copy(alpha = 0.35f)
|
||||
else Color.Black.copy(alpha = 0.35f),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
// Right Zone: Emoji + Send (как в React Native)
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.align(Alignment.Bottom)
|
||||
.padding(bottom = 8.dp),
|
||||
contentAlignment = Alignment.BottomEnd
|
||||
) {
|
||||
Row(
|
||||
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||
verticalAlignment = Alignment.Bottom
|
||||
) {
|
||||
// EMOJI BUTTON
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.align(Alignment.Bottom)
|
||||
modifier = Modifier
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable(
|
||||
@@ -1666,112 +1814,95 @@ private fun MessageInputBar(
|
||||
if (showEmojiPicker) Icons.Default.Keyboard
|
||||
else Icons.Default.SentimentSatisfiedAlt,
|
||||
contentDescription = "Emoji",
|
||||
tint =
|
||||
if (showEmojiPicker) PrimaryBlue
|
||||
else {
|
||||
if (isDarkTheme) Color.White.copy(alpha = 0.65f)
|
||||
else Color.Black.copy(alpha = 0.55f)
|
||||
},
|
||||
modifier = Modifier.size(26.dp)
|
||||
tint = if (isDarkTheme) Color.White.copy(alpha = 0.62f)
|
||||
else Color.Black.copy(alpha = 0.5f),
|
||||
modifier = Modifier.size(24.dp)
|
||||
)
|
||||
}
|
||||
|
||||
// TEXT INPUT
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.weight(1f)
|
||||
.align(Alignment.CenterVertically)
|
||||
.padding(horizontal = 4.dp),
|
||||
contentAlignment = Alignment.CenterStart
|
||||
// SEND BUTTON - только когда canSend
|
||||
androidx.compose.animation.AnimatedVisibility(
|
||||
visible = canSend,
|
||||
enter = fadeIn(tween(200)) + scaleIn(
|
||||
initialScale = 0.5f,
|
||||
animationSpec = tween(220, easing = FastOutSlowInEasing)
|
||||
),
|
||||
exit = fadeOut(tween(200)) + scaleOut(
|
||||
targetScale = 0.5f,
|
||||
animationSpec = tween(220)
|
||||
)
|
||||
) {
|
||||
AppleEmojiTextField(
|
||||
value = value,
|
||||
onValueChange = { newValue -> onValueChange(newValue) },
|
||||
textColor = textColor,
|
||||
textSize = 17f,
|
||||
hint = "Message",
|
||||
hintColor =
|
||||
if (isDarkTheme) Color.White.copy(alpha = 0.35f)
|
||||
else Color.Black.copy(alpha = 0.35f),
|
||||
modifier = Modifier.fillMaxWidth()
|
||||
)
|
||||
}
|
||||
|
||||
// ATTACH BUTTON
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.align(Alignment.Bottom)
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = null
|
||||
) { /* TODO: Attach */},
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Attachment,
|
||||
contentDescription = "Attach",
|
||||
tint =
|
||||
if (isDarkTheme) Color.White.copy(alpha = 0.65f)
|
||||
else Color.Black.copy(alpha = 0.55f),
|
||||
modifier = Modifier.size(24.dp).graphicsLayer { rotationZ = -45f }
|
||||
)
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.width(2.dp))
|
||||
|
||||
// MIC / SEND BUTTON
|
||||
Box(
|
||||
modifier =
|
||||
Modifier.align(Alignment.Bottom)
|
||||
.size(36.dp)
|
||||
.clip(CircleShape)
|
||||
.then(
|
||||
if (canSend) {
|
||||
Modifier.background(PrimaryBlue)
|
||||
} else {
|
||||
Modifier
|
||||
}
|
||||
)
|
||||
modifier = Modifier
|
||||
.width(52.dp)
|
||||
.height(34.dp)
|
||||
.clip(RoundedCornerShape(17.dp))
|
||||
.background(PrimaryBlue)
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = null,
|
||||
onClick = {
|
||||
if (canSend) handleSend()
|
||||
else { /* TODO: Voice recording */ }
|
||||
}
|
||||
onClick = { handleSend() }
|
||||
),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
androidx.compose.animation.Crossfade(
|
||||
targetState = canSend,
|
||||
animationSpec = tween(150),
|
||||
label = "iconCrossfade"
|
||||
) { showSend ->
|
||||
if (showSend) {
|
||||
Icon(
|
||||
imageVector = TelegramSendIcon,
|
||||
contentDescription = "Send",
|
||||
tint = Color.White,
|
||||
modifier = Modifier.size(20.dp)
|
||||
)
|
||||
} else {
|
||||
Icon(
|
||||
Icons.Default.Mic,
|
||||
contentDescription = "Voice",
|
||||
tint =
|
||||
if (isDarkTheme) Color.White.copy(alpha = 0.65f)
|
||||
else Color.Black.copy(alpha = 0.55f),
|
||||
modifier = Modifier.size(22.dp)
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // End of Input Row
|
||||
} // End of Glass Column
|
||||
|
||||
// Apple Emoji Picker
|
||||
// MIC BUTTON - справа снаружи (как в React Native)
|
||||
androidx.compose.animation.AnimatedVisibility(
|
||||
visible = !canSend,
|
||||
enter = fadeIn(tween(200)) + slideInHorizontally(
|
||||
initialOffsetX = { it / 2 },
|
||||
animationSpec = tween(250)
|
||||
),
|
||||
exit = fadeOut(tween(200)) + slideOutHorizontally(
|
||||
targetOffsetX = { it / 2 },
|
||||
animationSpec = tween(250)
|
||||
)
|
||||
) {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(48.dp)
|
||||
.clip(CircleShape)
|
||||
.background(
|
||||
if (isDarkTheme) Color(0xFF3C3C3C).copy(alpha = 0.8f)
|
||||
else Color(0xFFF0F0F0).copy(alpha = 0.85f)
|
||||
)
|
||||
.border(
|
||||
width = 1.dp,
|
||||
color = if (isDarkTheme) Color.White.copy(alpha = 0.25f)
|
||||
else Color.Black.copy(alpha = 0.1f),
|
||||
shape = CircleShape
|
||||
)
|
||||
.clickable(
|
||||
interactionSource = interactionSource,
|
||||
indication = null
|
||||
) { /* TODO: Voice recording */ },
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
Icons.Default.Mic,
|
||||
contentDescription = "Voice",
|
||||
tint = if (isDarkTheme) Color.White else Color(0xFF333333),
|
||||
modifier = Modifier.size(22.dp)
|
||||
)
|
||||
}
|
||||
}
|
||||
} // End of outer Row
|
||||
} // End of else (not blocked)
|
||||
|
||||
// Apple Emoji Picker - только показываем если не заблокирован
|
||||
if (!isBlocked) {
|
||||
AnimatedVisibility(
|
||||
visible = showEmojiPicker,
|
||||
enter = expandVertically(expandFrom = Alignment.Bottom) + fadeIn(),
|
||||
@@ -1783,6 +1914,7 @@ private fun MessageInputBar(
|
||||
onClose = { showEmojiPicker = false }
|
||||
)
|
||||
}
|
||||
} // End of if (!isBlocked) for emoji picker
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user