diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt
index 9115e39..9fb9cb7 100644
--- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt
+++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatScreen.kt
@@ -612,6 +612,7 @@ private fun ChatScreen(
state.isCounterpartRelationshipResolved &&
!state.isCounterpartContact &&
!state.isCounterpartBlocked
+ val showPrivateInfoCard = isPrivateChat && state.counterpartUserId != null
val canShowMembersTab = state.chatType.equals("group", ignoreCase = true) ||
(state.chatType.equals("channel", ignoreCase = true) && state.canManageMembers)
val timelineItems = remember(state.messages, context) { buildChatTimelineItems(state.messages, context) }
@@ -1165,6 +1166,26 @@ private fun ChatScreen(
}
}
}
+ AnimatedVisibility(
+ visible = showPrivateInfoCard,
+ enter = fadeIn(animationSpec = tween(180)) + slideInVertically(
+ initialOffsetY = { -it / 4 },
+ animationSpec = tween(180),
+ ),
+ exit = fadeOut(animationSpec = tween(120)) + slideOutVertically(
+ targetOffsetY = { -it / 4 },
+ animationSpec = tween(120),
+ ),
+ ) {
+ PrivateChatInfoCard(
+ title = state.counterpartName?.takeIf { it.isNotBlank() } ?: state.chatTitle,
+ username = state.counterpartUsername,
+ avatarUrl = state.chatAvatarUrl,
+ statusText = state.baseChatSubtitle.takeIf { it.isNotBlank() },
+ isContact = state.isCounterpartContact,
+ isBlocked = state.isCounterpartBlocked,
+ )
+ }
val strip = topAudioStrip
if (strip != null) {
Row(
@@ -2242,6 +2263,103 @@ private enum class ChatViewerMediaType {
Video,
}
+@Composable
+private fun PrivateChatInfoCard(
+ title: String,
+ username: String?,
+ avatarUrl: String?,
+ statusText: String?,
+ isContact: Boolean,
+ isBlocked: Boolean,
+) {
+ Surface(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 12.dp, vertical = 6.dp),
+ shape = RoundedCornerShape(20.dp),
+ color = MaterialTheme.colorScheme.surface.copy(alpha = 0.78f),
+ ) {
+ Row(
+ modifier = Modifier
+ .fillMaxWidth()
+ .padding(horizontal = 14.dp, vertical = 12.dp),
+ horizontalArrangement = Arrangement.spacedBy(12.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ if (!avatarUrl.isNullOrBlank()) {
+ AsyncImage(
+ model = avatarUrl,
+ contentDescription = "Private chat avatar",
+ modifier = Modifier
+ .size(54.dp)
+ .clip(CircleShape),
+ contentScale = ContentScale.Crop,
+ )
+ } else {
+ Box(
+ modifier = Modifier
+ .size(54.dp)
+ .clip(CircleShape)
+ .background(MaterialTheme.colorScheme.primary.copy(alpha = 0.18f)),
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = title.firstOrNull()?.uppercase() ?: "?",
+ style = MaterialTheme.typography.titleMedium,
+ color = MaterialTheme.colorScheme.primary,
+ fontWeight = FontWeight.Bold,
+ )
+ }
+ }
+
+ Column(
+ modifier = Modifier.weight(1f),
+ verticalArrangement = Arrangement.spacedBy(4.dp),
+ ) {
+ Text(
+ text = title.ifBlank { stringResource(id = R.string.chat_unknown_user) },
+ style = MaterialTheme.typography.titleSmall,
+ fontWeight = FontWeight.SemiBold,
+ )
+ username?.takeIf { it.isNotBlank() }?.let {
+ Text(
+ text = "@$it",
+ style = MaterialTheme.typography.bodyMedium,
+ color = MaterialTheme.colorScheme.primary,
+ )
+ }
+ statusText?.let {
+ Text(
+ text = it,
+ style = MaterialTheme.typography.bodySmall,
+ color = MaterialTheme.colorScheme.onSurfaceVariant,
+ )
+ }
+ }
+
+ Column(
+ horizontalAlignment = Alignment.End,
+ verticalArrangement = Arrangement.spacedBy(6.dp),
+ ) {
+ if (isContact) {
+ AssistChip(
+ onClick = {},
+ enabled = false,
+ label = { Text(stringResource(id = R.string.chat_private_info_contact)) },
+ )
+ }
+ if (isBlocked) {
+ AssistChip(
+ onClick = {},
+ enabled = false,
+ label = { Text(stringResource(id = R.string.chat_private_info_blocked)) },
+ )
+ }
+ }
+ }
+ }
+}
+
private data class ChatViewerMediaItem(
val url: String,
val type: ChatViewerMediaType,
diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt
index c298284..a249e5e 100644
--- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt
+++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/ChatViewModel.kt
@@ -778,6 +778,10 @@ class ChatViewModel @Inject constructor(
it.copy(
chatType = chat.type,
counterpartUserId = chat.counterpartUserId,
+ counterpartName = chat.counterpartName,
+ counterpartUsername = chat.counterpartUsername,
+ counterpartIsOnline = chat.counterpartIsOnline,
+ counterpartLastSeenAt = chat.counterpartLastSeenAt,
isCounterpartRelationshipResolved = if (chat.type.equals("private", ignoreCase = true) && chat.counterpartUserId != null) {
it.isCounterpartRelationshipResolved
} else {
diff --git a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/MessageUiState.kt b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/MessageUiState.kt
index 25d94be..7d5bab1 100644
--- a/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/MessageUiState.kt
+++ b/android/app/src/main/java/ru/daemonlord/messenger/ui/chat/MessageUiState.kt
@@ -19,6 +19,10 @@ data class MessageUiState(
val chatAvatarUrl: String? = null,
val chatType: String = "",
val counterpartUserId: Long? = null,
+ val counterpartName: String? = null,
+ val counterpartUsername: String? = null,
+ val counterpartIsOnline: Boolean? = null,
+ val counterpartLastSeenAt: String? = null,
val chatRole: String? = null,
val chatMuted: Boolean = false,
val chatUnreadCount: Int = 0,
diff --git a/android/app/src/main/res/values-ru/strings.xml b/android/app/src/main/res/values-ru/strings.xml
index d8e9570..a607e2b 100644
--- a/android/app/src/main/res/values-ru/strings.xml
+++ b/android/app/src/main/res/values-ru/strings.xml
@@ -142,6 +142,8 @@
Можно добавить этого человека в контакты или заблокировать прямо из чата.
Добавить контакт
Заблокировать
+ Контакт
+ Заблокирован
группа
канал
Медиа
diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml
index e77fc57..620b3ac 100644
--- a/android/app/src/main/res/values/strings.xml
+++ b/android/app/src/main/res/values/strings.xml
@@ -142,6 +142,8 @@
You can add this person to contacts or block them right from the chat.
Add contact
Block user
+ Contact
+ Blocked
group
channel
Media