Skip to content

Commit

Permalink
feat: archive only locally [WPB-5006] (#2162)
Browse files Browse the repository at this point in the history
* feat: archive only locally

* detekt fix
  • Loading branch information
Garzas authored Oct 25, 2023
1 parent 50fa995 commit ca4d92a
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
}
Expand All @@ -50,43 +54,92 @@ 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)")
if (!onlyLocally) {
archiveRemotely(conversationId, shouldArchiveConversation, archivedStatusTimestamp)
} 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
}
conversationRepository.updateMutedStatusRemotely(conversationId, updatedMutedStatus, archivedStatusTimestamp)
.flatMap {
conversationRepository.updateMutedStatusLocally(conversationId, updatedMutedStatus, archivedStatusTimestamp)
}.fold({
kaliumLogger.e(
"Something went wrong when updating the muting status of the convId: " +
"(${conversationId.toLogString()}) to (${updatedMutedStatus.status}"
)
}, {
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
})
// 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) {
updateMutedStatusRemotely(conversationId, updatedMutedStatus, archivedStatusTimestamp)
} 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
})

private suspend fun archiveRemotely(
conversationId: ConversationId,
shouldArchiveConversation: Boolean,
archivedStatusTimestamp: Long
) = conversationRepository.updateArchivedStatusRemotely(conversationId, shouldArchiveConversation, archivedStatusTimestamp)
.onFailure {
kaliumLogger.e(
"Something went wrong when updating remotely convId (${conversationId.toLogString()}) archiving " +
"status to archived = ($shouldArchiveConversation)"
)
}
.onSuccess {
kaliumLogger.d(
"Successfully updated remotely convId (${conversationId.toLogString()}) archiving " +
"status to archived = ($shouldArchiveConversation)"
)
}

private suspend fun updateMutedStatusRemotely(
conversationId: ConversationId,
updatedMutedStatus: MutedConversationStatus,
archivedStatusTimestamp: Long
) = 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}"
)
}
}

sealed class ArchiveStatusUpdateResult {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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) {
Expand Down

0 comments on commit ca4d92a

Please sign in to comment.