diff --git a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCase.kt b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCase.kt index 12645b19a13..c10de7b9352 100644 --- a/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCase.kt +++ b/logic/src/commonMain/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCase.kt @@ -21,9 +21,11 @@ package com.wire.kalium.logic.feature.conversation import com.wire.kalium.logic.data.conversation.ConversationRepository import com.wire.kalium.logic.data.conversation.MutedConversationStatus import com.wire.kalium.logic.data.id.ConversationId +import com.wire.kalium.logic.functional.Either import com.wire.kalium.logic.functional.flatMap import com.wire.kalium.logic.functional.fold import com.wire.kalium.logic.functional.onFailure +import com.wire.kalium.logic.functional.onSuccess import com.wire.kalium.logic.kaliumLogger import com.wire.kalium.util.DateTimeUtil @@ -33,12 +35,14 @@ interface UpdateConversationArchivedStatusUseCase { * * @param conversationId the id of the conversation where status wants to be changed * @param shouldArchiveConversation new archived status to be updated on the given conversation + * @param onlyLocally controls if archived status should only be updated locally * @param archivedStatusTimestamp the timestamp when the archiving event occurred * @return an [ConversationUpdateStatusResult] containing Success or Failure cases */ suspend operator fun invoke( conversationId: ConversationId, shouldArchiveConversation: Boolean, + onlyLocally: Boolean, archivedStatusTimestamp: Long = DateTimeUtil.currentInstant().toEpochMilliseconds() ): ArchiveStatusUpdateResult } @@ -50,43 +54,80 @@ internal class UpdateConversationArchivedStatusUseCaseImpl( override suspend operator fun invoke( conversationId: ConversationId, shouldArchiveConversation: Boolean, + onlyLocally: Boolean, archivedStatusTimestamp: Long ): ArchiveStatusUpdateResult = - conversationRepository.updateArchivedStatusRemotely(conversationId, shouldArchiveConversation, archivedStatusTimestamp).onFailure { - kaliumLogger.e("Something went wrong when updating remotely convId (${conversationId.toLogString()}) archiving " + - "status to archived = ($shouldArchiveConversation)") - }.flatMap { - conversationRepository.updateArchivedStatusLocally(conversationId, shouldArchiveConversation, archivedStatusTimestamp) - }.fold({ - kaliumLogger.e("Something went wrong when updating locally convId (${conversationId.toLogString()}) archiving " + - "status to archived = ($shouldArchiveConversation)") - ArchiveStatusUpdateResult.Failure - }, { - kaliumLogger.d("Successfully updated remotely and locally convId (${conversationId.toLogString()}) archiving " + - "status to archived = ($shouldArchiveConversation)") - - // Now we should make sure the conversation gets muted if it's archived or un-muted if it's unarchived - val updatedMutedStatus = if (shouldArchiveConversation) { - MutedConversationStatus.AllMuted - } else { - MutedConversationStatus.AllAllowed - } - conversationRepository.updateMutedStatusRemotely(conversationId, updatedMutedStatus, archivedStatusTimestamp) - .flatMap { - conversationRepository.updateMutedStatusLocally(conversationId, updatedMutedStatus, archivedStatusTimestamp) - }.fold({ + if (!onlyLocally) { + conversationRepository.updateArchivedStatusRemotely(conversationId, shouldArchiveConversation, archivedStatusTimestamp) + .onFailure { kaliumLogger.e( - "Something went wrong when updating the muting status of the convId: " + - "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}" + "Something went wrong when updating remotely convId (${conversationId.toLogString()}) archiving " + + "status to archived = ($shouldArchiveConversation)" ) - }, { + } + .onSuccess { kaliumLogger.d( - "Successfully updated remotely and locally the muting status of the convId: " + - "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}") - }) - // Even if the muting status update fails, we should still return success as the archived status update was successful - ArchiveStatusUpdateResult.Success - }) + "Successfully updated remotely convId (${conversationId.toLogString()}) archiving " + + "status to archived = ($shouldArchiveConversation)" + ) + } + } else { + Either.Right(Unit) + } + .flatMap { + conversationRepository.updateArchivedStatusLocally(conversationId, shouldArchiveConversation, archivedStatusTimestamp) + }.fold({ + kaliumLogger.e( + "Something went wrong when updating locally convId (${conversationId.toLogString()}) archiving " + + "status to archived = ($shouldArchiveConversation)" + ) + ArchiveStatusUpdateResult.Failure + }, { + kaliumLogger.d( + "Successfully updated locally convId (${conversationId.toLogString()}) archiving " + + "status to archived = ($shouldArchiveConversation)" + ) + + // Now we should make sure the conversation gets muted if it's archived or un-muted if it's unarchived + val updatedMutedStatus = if (shouldArchiveConversation) { + MutedConversationStatus.AllMuted + } else { + MutedConversationStatus.AllAllowed + } + + if (!onlyLocally) { + conversationRepository.updateMutedStatusRemotely(conversationId, updatedMutedStatus, archivedStatusTimestamp) + .onFailure { + kaliumLogger.e( + "Something went wrong when updating remotely the muting status of the convId: " + + "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}" + ) + } + .onSuccess { + kaliumLogger.d( + "Successfully updated remotely the muting status of the convId: " + + "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}" + ) + } + } else { + Either.Right(Unit) + } + .flatMap { + conversationRepository.updateMutedStatusLocally(conversationId, updatedMutedStatus, archivedStatusTimestamp) + }.fold({ + kaliumLogger.e( + "Something went wrong when updating locally the muting status of the convId: " + + "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}" + ) + }, { + kaliumLogger.d( + "Successfully updated locally the muting status of the convId: " + + "(${conversationId.toLogString()}) to (${updatedMutedStatus.status}" + ) + }) + // Even if the muting status update fails, we should still return success as the archived status update was successful + ArchiveStatusUpdateResult.Success + }) } sealed class ArchiveStatusUpdateResult { diff --git a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCaseTest.kt b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCaseTest.kt index c910116e34b..660924e17e8 100644 --- a/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCaseTest.kt +++ b/logic/src/commonTest/kotlin/com/wire/kalium/logic/feature/conversation/UpdateConversationArchivedStatusUseCaseTest.kt @@ -42,13 +42,14 @@ class UpdateConversationArchivedStatusUseCaseTest { val conversationId = TestConversation.ID val isConversationArchived = true val archivedStatusTimestamp = 123456789L + val onlyLocally = false val (arrangement, updateConversationArchivedStatus) = Arrangement() .withSuccessfulMutingUpdates() .withUpdateArchivedStatusFullSuccess() .arrange() - val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp) + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) assertEquals(ArchiveStatusUpdateResult.Success::class, result::class) with(arrangement) { @@ -64,18 +65,48 @@ class UpdateConversationArchivedStatusUseCaseTest { } } + @Test + fun givenAConversationId_whenInvokingAnArchivedStatusChangeAndUserIsNotMember_thenShouldArchiveOnlyLocally() = + runTest { + val conversationId = TestConversation.ID + val isConversationArchived = true + val archivedStatusTimestamp = 123456789L + val onlyLocally = true + + val (arrangement, updateConversationArchivedStatus) = Arrangement() + .withSuccessfulMutingUpdates() + .withUpdateArchivedStatusFullSuccess() + .arrange() + + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) + assertEquals(ArchiveStatusUpdateResult.Success::class, result::class) + + with(arrangement) { + verify(conversationRepository) + .suspendFunction(conversationRepository::updateArchivedStatusRemotely) + .with(any(), any()) + .wasNotInvoked() + + verify(conversationRepository) + .suspendFunction(conversationRepository::updateArchivedStatusLocally) + .with(any(), eq(isConversationArchived), matching { it == archivedStatusTimestamp }) + .wasInvoked(exactly = once) + } + } + @Test fun givenAConversationId_whenInvokingAnArchivedStatusChangeAndFails_thenShouldDelegateTheCallAndReturnAFailureResult() = runTest { val conversationId = TestConversation.ID val isConversationArchived = true val archivedStatusTimestamp = 123456789L + val onlyLocally = false val (arrangement, updateConversationArchivedStatus) = Arrangement() .withSuccessfulMutingUpdates() .withRemoteUpdateArchivedStatusFailure() .arrange() - val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp) + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) assertEquals(ArchiveStatusUpdateResult.Failure::class, result::class) with(arrangement) { @@ -96,13 +127,14 @@ class UpdateConversationArchivedStatusUseCaseTest { val conversationId = TestConversation.ID val isConversationArchived = true val archivedStatusTimestamp = 123456789L + val onlyLocally = false val (arrangement, updateConversationArchivedStatus) = Arrangement() .withLocalUpdateArchivedStatusFailure() .withSuccessfulMutingUpdates() .arrange() - val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp) + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) assertEquals(ArchiveStatusUpdateResult.Failure::class, result::class) with(arrangement) { @@ -124,13 +156,14 @@ class UpdateConversationArchivedStatusUseCaseTest { val conversationId = TestConversation.ID val isConversationArchived = true val archivedStatusTimestamp = 123456789L + val onlyLocally = false val (arrangement, updateConversationArchivedStatus) = Arrangement() .withUpdateArchivedStatusFullSuccess() .withRemoteErrorMutingUpdates() .arrange() - val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp) + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) assertTrue(result is ArchiveStatusUpdateResult.Success) with(arrangement) { @@ -152,13 +185,14 @@ class UpdateConversationArchivedStatusUseCaseTest { val conversationId = TestConversation.ID val isConversationArchived = true val archivedStatusTimestamp = 123456789L + val onlyLocally = false val (arrangement, updateConversationArchivedStatus) = Arrangement() .withUpdateArchivedStatusFullSuccess() .withLocalErrorMutingUpdates() .arrange() - val result = updateConversationArchivedStatus(conversationId, isConversationArchived, archivedStatusTimestamp) + val result = updateConversationArchivedStatus(conversationId, isConversationArchived, onlyLocally, archivedStatusTimestamp) assertTrue(result is ArchiveStatusUpdateResult.Success) with(arrangement) {