diff --git a/app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt b/app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt index 235e2e8..1855bf8 100644 --- a/app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt +++ b/app/src/main/java/com/rosetta/messenger/data/MessageRepository.kt @@ -216,6 +216,9 @@ class MessageRepository private constructor(private val context: Context) { // Обновляем диалог updateDialog(toPublicKey, text.trim(), timestamp) + // 🔥 Отмечаем что я отправлял сообщения в этот диалог (перемещает из requests в chats) + dialogDao.markIHaveSent(account, toPublicKey) + // Отправляем пакет val packet = PacketMessage().apply { this.fromPublicKey = account diff --git a/app/src/main/java/com/rosetta/messenger/database/MessageEntities.kt b/app/src/main/java/com/rosetta/messenger/database/MessageEntities.kt index fc833e2..5fd83bb 100644 --- a/app/src/main/java/com/rosetta/messenger/database/MessageEntities.kt +++ b/app/src/main/java/com/rosetta/messenger/database/MessageEntities.kt @@ -103,7 +103,10 @@ data class DialogEntity( val lastSeen: Long = 0, // Последний раз онлайн @ColumnInfo(name = "verified") - val verified: Int = 0 // Верифицирован + val verified: Int = 0, // Верифицирован + + @ColumnInfo(name = "i_have_sent", defaultValue = "0") + val iHaveSent: Int = 0 // Отправлял ли я сообщения в этот диалог (0/1) ) /** @@ -293,15 +296,10 @@ interface DialogDao { * Исключает requests (диалоги без исходящих сообщений от нас) */ @Query(""" - SELECT d.* FROM dialogs d - WHERE d.account = :account - AND EXISTS ( - SELECT 1 FROM messages m - WHERE m.account = :account - AND m.from_public_key = :account - AND m.to_public_key = d.opponent_key - ) - ORDER BY d.last_message_timestamp DESC + SELECT * FROM dialogs + WHERE account = :account + AND i_have_sent = 1 + ORDER BY last_message_timestamp DESC """) fun getDialogsFlow(account: String): Flow> @@ -309,15 +307,10 @@ interface DialogDao { * Получить requests - диалоги где нам писали, но мы не отвечали */ @Query(""" - SELECT d.* FROM dialogs d - WHERE d.account = :account - AND NOT EXISTS ( - SELECT 1 FROM messages m - WHERE m.account = :account - AND m.from_public_key = :account - AND m.to_public_key = d.opponent_key - ) - ORDER BY d.last_message_timestamp DESC + SELECT * FROM dialogs + WHERE account = :account + AND i_have_sent = 0 + ORDER BY last_message_timestamp DESC """) fun getRequestsFlow(account: String): Flow> @@ -325,14 +318,9 @@ interface DialogDao { * Получить количество requests */ @Query(""" - SELECT COUNT(*) FROM dialogs d - WHERE d.account = :account - AND NOT EXISTS ( - SELECT 1 FROM messages m - WHERE m.account = :account - AND m.from_public_key = :account - AND m.to_public_key = d.opponent_key - ) + SELECT COUNT(*) FROM dialogs + WHERE account = :account + AND i_have_sent = 0 """) fun getRequestsCountFlow(account: String): Flow @@ -371,6 +359,12 @@ interface DialogDao { @Query("UPDATE dialogs SET unread_count = 0 WHERE account = :account AND opponent_key = :opponentKey") suspend fun clearUnreadCount(account: String, opponentKey: String) + /** + * Отметить что я отправлял сообщения в этот диалог + */ + @Query("UPDATE dialogs SET i_have_sent = 1 WHERE account = :account AND opponent_key = :opponentKey") + suspend fun markIHaveSent(account: String, opponentKey: String) + /** * Обновить онлайн статус */ diff --git a/app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt b/app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt index e0fd07e..9225ac5 100644 --- a/app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt +++ b/app/src/main/java/com/rosetta/messenger/database/RosettaDatabase.kt @@ -12,7 +12,7 @@ import androidx.room.RoomDatabase DialogEntity::class, BlacklistEntity::class ], - version = 3, + version = 4, exportSchema = false ) abstract class RosettaDatabase : RoomDatabase() { diff --git a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListViewModel.kt b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListViewModel.kt index b656e0d..57a696d 100644 --- a/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListViewModel.kt +++ b/app/src/main/java/com/rosetta/messenger/ui/chats/ChatsListViewModel.kt @@ -7,6 +7,7 @@ import com.rosetta.messenger.crypto.CryptoManager import com.rosetta.messenger.database.DialogEntity import com.rosetta.messenger.database.RosettaDatabase import com.rosetta.messenger.network.PacketOnlineSubscribe +import com.rosetta.messenger.network.PacketSearch import com.rosetta.messenger.network.ProtocolManager import com.rosetta.messenger.network.SearchUser import kotlinx.coroutines.Dispatchers @@ -113,10 +114,17 @@ class ChatsListViewModel(application: Application) : AndroidViewModel(applicatio // 📬 Подписываемся на requests (запросы от новых пользователей) viewModelScope.launch { + android.util.Log.d("ChatsVM", "📬 Subscribing to requests for publicKey=${publicKey.take(16)}...") dialogDao.getRequestsFlow(publicKey) .flowOn(Dispatchers.IO) .map { requestsList -> + android.util.Log.d("ChatsVM", "📬 Received ${requestsList.size} requests from DB") requestsList.map { dialog -> + // 🔥 Загружаем информацию о пользователе если её нет + if (dialog.opponentTitle.isEmpty() || dialog.opponentTitle == dialog.opponentKey) { + loadUserInfoForRequest(dialog.opponentKey) + } + val decryptedLastMessage = try { if (privateKey.isNotEmpty() && dialog.lastMessage.isNotEmpty()) { CryptoManager.decryptWithPassword(dialog.lastMessage, privateKey) @@ -132,7 +140,7 @@ class ChatsListViewModel(application: Application) : AndroidViewModel(applicatio id = dialog.id, account = dialog.account, opponentKey = dialog.opponentKey, - opponentTitle = dialog.opponentTitle, + opponentTitle = dialog.opponentTitle, // 🔥 Показываем имя как в обычных чатах opponentUsername = dialog.opponentUsername, lastMessage = decryptedLastMessage, lastMessageTimestamp = dialog.lastMessageTimestamp, @@ -294,6 +302,34 @@ class ChatsListViewModel(application: Application) : AndroidViewModel(applicatio } } + /** + * 📬 Загрузить информацию о пользователе для request + */ + private fun loadUserInfoForRequest(publicKey: String) { + viewModelScope.launch(Dispatchers.IO) { + try { + val sharedPrefs = getApplication().getSharedPreferences("rosetta", Application.MODE_PRIVATE) + val currentUserPrivateKey = sharedPrefs.getString("private_key", "") ?: "" + + if (currentUserPrivateKey.isEmpty()) return@launch + + // 🔥 ВАЖНО: Используем хеш ключа, как в MessageRepository.requestUserInfo + val privateKeyHash = CryptoManager.generatePrivateKeyHash(currentUserPrivateKey) + + android.util.Log.d("ChatsVM", "📬 Requesting user info for: ${publicKey.take(16)}...") + + // Запрашиваем информацию о пользователе с сервера + val packet = PacketSearch().apply { + this.privateKey = privateKeyHash + this.search = publicKey + } + ProtocolManager.send(packet) + } catch (e: Exception) { + android.util.Log.e("ChatsVM", "📬 Error loading user info: ${e.message}") + } + } + } + /** * Проверить заблокирован ли пользователь */