diff --git a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Connections.sq b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Connections.sq index 7df9f1773a1..715c508427e 100644 --- a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Connections.sq +++ b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Connections.sq @@ -38,6 +38,9 @@ UPDATE Connection SET last_update_date = ? WHERE to_id = ?; updateNotificationFlag: UPDATE Connection SET should_notify = ? WHERE qualified_to = ?; +updateConnectionConversation: +UPDATE Connection SET conversation_id = ?, qualified_conversation = ? WHERE qualified_to = ?; + setAllConnectionsAsNotified: UPDATE Connection SET should_notify = 0 WHERE status = 'PENDING' AND should_notify = 1; diff --git a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Messages.sq b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Messages.sq index 61991e50deb..84a1b25da71 100644 --- a/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Messages.sq +++ b/persistence/src/commonMain/db_user/com/wire/kalium/persistence/Messages.sq @@ -506,3 +506,8 @@ WHERE conversation_id = ? AND id = ?; insertMessageRecipientsFailure: INSERT OR IGNORE INTO MessageRecipientFailure(message_id, conversation_id, recipient_failure_list, recipient_failure_type) VALUES(?, ?, ?, ?); + +moveMessages: +UPDATE Message +SET conversation_id = :to +WHERE conversation_id = :from; diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAO.kt index 667f5488004..f6dc4e95ce7 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAO.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAO.kt @@ -66,6 +66,7 @@ interface ConnectionDAO { suspend fun insertConnection(connectionEntity: ConnectionEntity) suspend fun insertConnections(users: List) suspend fun updateConnectionLastUpdatedTime(lastUpdate: String, id: String) + suspend fun updateConnectionConversation(conversationId: QualifiedIDEntity, userId: QualifiedIDEntity) suspend fun deleteConnectionDataAndConversation(conversationId: QualifiedIDEntity) suspend fun getConnectionRequestsForNotification(): Flow> suspend fun updateNotificationFlag(flag: Boolean, userId: QualifiedIDEntity) diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAOImpl.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAOImpl.kt index 6055ff847e5..a3f41a4ce15 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAOImpl.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/ConnectionDAOImpl.kt @@ -159,6 +159,10 @@ class ConnectionDAOImpl( connectionsQueries.updateConnectionLastUpdated(lastUpdate.toInstant(), id) } + override suspend fun updateConnectionConversation(conversationId: QualifiedIDEntity, userId: QualifiedIDEntity) { + connectionsQueries.updateConnectionConversation(conversationId.value, conversationId, userId) + } + override suspend fun deleteConnectionDataAndConversation(conversationId: QualifiedIDEntity) = withContext(queriesContext) { connectionsQueries.transaction { connectionsQueries.deleteConnection(conversationId) diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAO.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAO.kt index 06c0aecf59e..54db47261c2 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAO.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAO.kt @@ -133,5 +133,7 @@ interface MessageDAO { recipientFailureTypeEntity: RecipientFailureTypeEntity ) + suspend fun moveMessages(from: ConversationIDEntity, to: ConversationIDEntity) + val platformExtensions: MessageExtensions } diff --git a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOImpl.kt b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOImpl.kt index 9082b1f3088..35a07f5ba94 100644 --- a/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOImpl.kt +++ b/persistence/src/commonMain/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOImpl.kt @@ -385,6 +385,11 @@ internal class MessageDAOImpl internal constructor( queries.insertMessageRecipientsFailure(id, conversationsId, recipientsFailed, recipientFailureTypeEntity) } + override suspend fun moveMessages(from: ConversationIDEntity, to: ConversationIDEntity) = + withContext(coroutineContext) { + queries.moveMessages(to, from) + } + override suspend fun getConversationUnreadEventsCount(conversationId: QualifiedIDEntity): Long = withContext(coroutineContext) { unreadEventsQueries.getConversationUnreadEventsCount(conversationId).executeAsOne() } diff --git a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConnectionDaoTest.kt b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConnectionDaoTest.kt index d0c5cf473d4..263af1f05d3 100644 --- a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConnectionDaoTest.kt +++ b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/ConnectionDaoTest.kt @@ -83,15 +83,27 @@ class ConnectionDaoTest : BaseDatabaseTest() { assertEquals(false, result[1].shouldNotify) } + @Test + fun givenConnection_WhenUpdatingConnectionConversation_ThenItIsUpdated() = runTest { + val newConversationId = QualifiedIDEntity("new", "wire.com") + db.connectionDAO.insertConnection(connection1) + db.connectionDAO.updateConnectionConversation(newConversationId, connection1.qualifiedToId) + val result = db.connectionDAO.getConnectionRequests().first() + assertEquals(newConversationId, result[0].qualifiedConversationId) + assertEquals(newConversationId.value, result[0].conversationId) + } + companion object { + val OTHER_USER_ID = QualifiedIDEntity("me", "wire.com") + private fun connectionEntity(id: String = "0") = ConnectionEntity( - conversationId = "$id@wire.com", + conversationId = id, from = "from_string", lastUpdateDate = "2022-03-30T15:36:00.000Z".toInstant(), qualifiedConversationId = QualifiedIDEntity(id, "wire.com"), - qualifiedToId = QualifiedIDEntity("me", "wire.com"), + qualifiedToId = OTHER_USER_ID, status = ConnectionEntity.State.PENDING, - toId = "me@wire.com", + toId = OTHER_USER_ID.value, shouldNotify = true ) } diff --git a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOTest.kt b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOTest.kt index 0e6fa4d8f01..7f73f441362 100644 --- a/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOTest.kt +++ b/persistence/src/commonTest/kotlin/com/wire/kalium/persistence/dao/message/MessageDAOTest.kt @@ -1633,6 +1633,129 @@ class MessageDAOTest : BaseDatabaseTest() { assertTrue(result.readCount == 0L) } + @Test + fun givenExistingMessagesAtSource_whenMovingMessages_thenMessagesAreAccessibleAtDestination() = runTest { + // given + val source = conversationEntity1 + val destination = conversationEntity2 + userDAO.upsertUsers(listOf(userEntity1, userEntity2)) + conversationDAO.insertConversation(source) + conversationDAO.insertConversation(destination) + + val allMessages = listOf( + newRegularMessageEntity( + id = "1", + senderUserId = userEntity1.id, + conversationId = source.id, + content = MessageEntityContent.Text(messageBody = "Message 1") + ), + newRegularMessageEntity( + id = "2", + senderUserId = userEntity1.id, + conversationId = source.id, + content = MessageEntityContent.Text(messageBody = "Message 2") + ) + ) + messageDAO.insertOrIgnoreMessages(allMessages) + + // when + messageDAO.moveMessages(source.id, destination.id) + + // then + val retrievedMessages = messageDAO.getMessagesByConversationAndVisibility( + destination.id, + 10, + 0, + listOf(MessageEntity.Visibility.VISIBLE) + ).first() + + assertEquals( + allMessages.map { it.content }.toSet(), + retrievedMessages.map { it.content }.toSet()) + } + + @Test + fun givenExistingMessagesAtSourceAndDestination_whenMovingMessages_thenMessagesAreAccessibleAtDestination() = runTest { + // given + val source = conversationEntity1 + val destination = conversationEntity2 + userDAO.upsertUsers(listOf(userEntity1, userEntity2)) + conversationDAO.insertConversation(source) + conversationDAO.insertConversation(destination) + + val allMessages = listOf( + newRegularMessageEntity( + id = "1", + senderUserId = userEntity1.id, + conversationId = source.id, + content = MessageEntityContent.Text(messageBody = "Message 1") + ), + newRegularMessageEntity( + id = "2", + senderUserId = userEntity1.id, + conversationId = destination.id, + content = MessageEntityContent.Text(messageBody = "Message 2") + ) + ) + messageDAO.insertOrIgnoreMessages(allMessages) + + // when + messageDAO.moveMessages(source.id, destination.id) + + // then + val retrievedMessages = messageDAO.getMessagesByConversationAndVisibility( + destination.id, + 10, + 0, + listOf(MessageEntity.Visibility.VISIBLE) + ).first() + + assertEquals( + allMessages.map { it.content }.toSet(), + retrievedMessages.map { it.content }.toSet()) + } + + @Test + fun givenNoExistingMessagesAtSource_whenMovingMessages_thenExistingMessagesAreAccessibleAtDestination() = runTest { + // given + val source = conversationEntity1 + val destination = conversationEntity2 + userDAO.upsertUsers(listOf(userEntity1, userEntity2)) + conversationDAO.insertConversation(source) + conversationDAO.insertConversation(destination) + + val allMessages = listOf( + newRegularMessageEntity( + id = "1", + senderUserId = userEntity1.id, + conversationId = destination.id, + content = MessageEntityContent.Text(messageBody = "Message 1") + ), + newRegularMessageEntity( + id = "2", + senderUserId = userEntity1.id, + conversationId = destination.id, + content = MessageEntityContent.Text(messageBody = "Message 2") + ) + ) + messageDAO.insertOrIgnoreMessages(allMessages) + + // when + messageDAO.moveMessages(source.id, destination.id) + + // then + val retrievedMessages = messageDAO.getMessagesByConversationAndVisibility( + destination.id, + 10, + 0, + listOf(MessageEntity.Visibility.VISIBLE) + ).first() + + assertEquals( + allMessages.map { it.content }.toSet(), + retrievedMessages.map { it.content }.toSet()) + } + private suspend fun insertInitialData() { userDAO.upsertUsers(listOf(userEntity1, userEntity2)) conversationDAO.insertConversation(