feat: enhance chat and requests screens with avatar handling, pinning, and user blocking functionalities

This commit is contained in:
2026-02-11 05:50:08 +05:00
parent a0ef378909
commit 8c8a651500
13 changed files with 1244 additions and 451 deletions

View File

@@ -7,18 +7,18 @@ import kotlinx.coroutines.flow.asStateFlow
/**
* 📨 Менеджер для пересылки сообщений (Forward)
*
*
* Логика как в десктопе:
* 1. Пользователь выбирает сообщения в чате
* 2. Нажимает Forward
* 3. Открывается список чатов
* 4. Выбирает чат куда переслать
* 5. Переходит в выбранный чат с сообщениями в Reply панели (как Forward)
*
* 3. Открывается список чатов (мультивыбор)
* 4. Выбирает один или несколько чатов
* 5. Первый чат — навигация с reply панелью, остальные — прямая отправка
*
* Singleton для передачи данных между экранами
*/
object ForwardManager {
/**
* Сообщение для пересылки
*/
@@ -29,25 +29,31 @@ object ForwardManager {
val isOutgoing: Boolean,
val senderPublicKey: String, // publicKey отправителя сообщения
val originalChatPublicKey: String, // publicKey чата откуда пересылается
val senderName: String = "", // Имя отправителя для атрибуции
val attachments: List<MessageAttachment> = emptyList()
)
// Сообщения для пересылки
private val _forwardMessages = MutableStateFlow<List<ForwardMessage>>(emptyList())
val forwardMessages: StateFlow<List<ForwardMessage>> = _forwardMessages.asStateFlow()
// Флаг показа выбора чата
private val _showChatPicker = MutableStateFlow(false)
val showChatPicker: StateFlow<Boolean> = _showChatPicker.asStateFlow()
// Выбранный чат (publicKey собеседника)
private val _selectedChatPublicKey = MutableStateFlow<String?>(null)
val selectedChatPublicKey: StateFlow<String?> = _selectedChatPublicKey.asStateFlow()
// Выбранные чаты (publicKeys собеседников) — поддержка мультивыбора
private val _selectedChatPublicKeys = MutableStateFlow<List<String>>(emptyList())
val selectedChatPublicKeys: StateFlow<List<String>> = _selectedChatPublicKeys.asStateFlow()
// Обратная совместимость: первый выбранный чат
val selectedChatPublicKey: StateFlow<String?> get() = MutableStateFlow(
_selectedChatPublicKeys.value.firstOrNull()
)
// 🔥 Счётчик для триггера перезагрузки диалога при forward
private val _forwardTrigger = MutableStateFlow(0)
val forwardTrigger: StateFlow<Int> = _forwardTrigger.asStateFlow()
/**
* Установить сообщения для пересылки и показать выбор чата
*/
@@ -60,24 +66,31 @@ object ForwardManager {
_showChatPicker.value = true
}
}
/**
* Выбрать чат для пересылки
* Выбрать один чат для пересылки (обратная совместимость)
*/
fun selectChat(publicKey: String) {
_selectedChatPublicKey.value = publicKey
selectChats(listOf(publicKey))
}
/**
* Выбрать несколько чатов для пересылки
*/
fun selectChats(publicKeys: List<String>) {
_selectedChatPublicKeys.value = publicKeys
_showChatPicker.value = false
// 🔥 Увеличиваем триггер чтобы ChatDetailScreen перезагрузил диалог
_forwardTrigger.value++
}
/**
* Скрыть выбор чата (отмена)
*/
fun hideChatPicker() {
_showChatPicker.value = false
}
/**
* Получить сообщения и очистить состояние
* Вызывается при открытии выбранного чата
@@ -86,57 +99,64 @@ object ForwardManager {
val messages = _forwardMessages.value
return messages
}
/**
* Очистить все данные (после применения или отмены)
*/
fun clear() {
_forwardMessages.value = emptyList()
_showChatPicker.value = false
_selectedChatPublicKey.value = null
_selectedChatPublicKeys.value = emptyList()
}
/**
* Проверить есть ли сообщения для пересылки
*/
fun hasForwardMessages(): Boolean = _forwardMessages.value.isNotEmpty()
/**
* Проверить есть ли сообщения для конкретного чата
*/
fun hasForwardMessagesForChat(publicKey: String): Boolean {
val selectedKey = _selectedChatPublicKey.value
val selectedKeys = _selectedChatPublicKeys.value
val hasMessages = _forwardMessages.value.isNotEmpty()
return selectedKey == publicKey && hasMessages
return publicKey in selectedKeys && hasMessages
}
/**
* Установить выбранный чат и вернуть сообщения для него
* Комбинированный метод для атомарного получения данных
*/
fun getForwardMessagesForChat(publicKey: String): List<ForwardMessage> {
val selectedKey = _selectedChatPublicKey.value
return if (selectedKey == publicKey && _forwardMessages.value.isNotEmpty()) {
val selectedKeys = _selectedChatPublicKeys.value
return if (publicKey in selectedKeys && _forwardMessages.value.isNotEmpty()) {
_forwardMessages.value
} else {
emptyList()
}
}
/**
* Получить список дополнительных чатов (кроме основного, куда навигируемся)
*/
fun getAdditionalChatKeys(primaryKey: String): List<String> {
return _selectedChatPublicKeys.value.filter { it != primaryKey }
}
/**
* Атомарно получить forward-сообщения для конкретного чата и очистить pending state.
* Это повторяет desktop-подход "consume once" после перехода в целевой диалог.
*/
@Synchronized
fun consumeForwardMessagesForChat(publicKey: String): List<ForwardMessage> {
val selectedKey = _selectedChatPublicKey.value
val selectedKeys = _selectedChatPublicKeys.value
val pending = _forwardMessages.value
if (selectedKey != publicKey || pending.isEmpty()) {
if (publicKey !in selectedKeys || pending.isEmpty()) {
return emptyList()
}
_forwardMessages.value = emptyList()
_selectedChatPublicKey.value = null
_selectedChatPublicKeys.value = emptyList()
_showChatPicker.value = false
return pending
}