Skip to content

Commit

Permalink
chore: move remove message to conv messages view model (#2823)
Browse files Browse the repository at this point in the history
  • Loading branch information
Garzas authored Mar 26, 2024
1 parent 9e45252 commit 7e37bcb
Show file tree
Hide file tree
Showing 7 changed files with 186 additions and 183 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ fun ConversationScreen(
)
},
onSendMessage = messageComposerViewModel::trySendMessage,
onDeleteMessage = messageComposerViewModel::showDeleteMessageDialog,
onDeleteMessage = conversationMessagesViewModel::showDeleteMessageDialog,
onAssetItemClicked = conversationMessagesViewModel::downloadOrFetchAssetAndShowDialog,
onImageFullScreenMode = { message, isSelfMessage ->
with(conversationMessagesViewModel) {
Expand Down Expand Up @@ -452,8 +452,8 @@ fun ConversationScreen(
)
BackHandler { conversationScreenOnBackButtonClick(messageComposerViewModel, focusManager, navigator) }
DeleteMessageDialog(
state = messageComposerViewModel.deleteMessageDialogsState,
actions = messageComposerViewModel.deleteMessageHelper
state = conversationMessagesViewModel.deleteMessageDialogsState,
actions = conversationMessagesViewModel.deleteMessageHelper
)
DownloadedAssetDialog(
downloadedAssetDialogState = conversationMessagesViewModel.conversationViewState.downloadedAssetDialogState,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ import com.wire.android.mapper.ContactMapper
import com.wire.android.media.PingRinger
import com.wire.android.model.SnackBarMessage
import com.wire.android.navigation.SavedStateViewModel
import com.wire.android.ui.home.conversations.ConversationSnackbarMessages.ErrorDeletingMessage
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogActiveState
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogHelper
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogsState
import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.android.ui.home.conversations.model.UIMessage
import com.wire.android.ui.home.conversations.model.UriAsset
Expand Down Expand Up @@ -68,7 +64,6 @@ import com.wire.kalium.logic.feature.conversation.SendTypingEventUseCase
import com.wire.kalium.logic.feature.conversation.SetNotifiedAboutConversationUnderLegalHoldUseCase
import com.wire.kalium.logic.feature.conversation.SetUserInformedAboutVerificationUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationReadDateUseCase
import com.wire.kalium.logic.feature.message.DeleteMessageUseCase
import com.wire.kalium.logic.feature.message.RetryFailedMessageUseCase
import com.wire.kalium.logic.feature.message.SendEditTextMessageUseCase
import com.wire.kalium.logic.feature.message.SendKnockUseCase
Expand Down Expand Up @@ -101,7 +96,6 @@ class MessageComposerViewModel @Inject constructor(
private val sendTextMessage: SendTextMessageUseCase,
private val sendEditTextMessage: SendEditTextMessageUseCase,
private val retryFailedMessage: RetryFailedMessageUseCase,
private val deleteMessage: DeleteMessageUseCase,
private val dispatchers: DispatcherProvider,
private val isFileSharingEnabled: IsFileSharingEnabledUseCase,
private val observeConversationInteractionAvailability: ObserveConversationInteractionAvailabilityUseCase,
Expand Down Expand Up @@ -136,31 +130,9 @@ class MessageComposerViewModel @Inject constructor(
var tempWritableImageUri: Uri? = null
private set

// TODO: should be moved to ConversationMessagesViewModel?
var deleteMessageDialogsState: DeleteMessageDialogsState by mutableStateOf(
DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Hidden,
forEveryone = DeleteMessageDialogActiveState.Hidden
)
)
private set

private val conversationNavArgs: ConversationNavArgs = savedStateHandle.navArgs()
val conversationId: QualifiedID = conversationNavArgs.conversationId

val deleteMessageHelper = DeleteMessageDialogHelper(
viewModelScope,
conversationId,
::updateDeleteDialogState
) { messageId, deleteForEveryone, _ ->
deleteMessage(
conversationId = conversationId,
messageId = messageId,
deleteForEveryone = deleteForEveryone
)
.onFailure { onSnackbarMessage(ErrorDeletingMessage) }
}

private val _infoMessage = MutableSharedFlow<SnackBarMessage>()
val infoMessage = _infoMessage.asSharedFlow()

Expand Down Expand Up @@ -452,32 +424,6 @@ class MessageComposerViewModel @Inject constructor(
}
}

fun showDeleteMessageDialog(messageId: String, deleteForEveryone: Boolean) =
if (deleteForEveryone) {
updateDeleteDialogState {
it.copy(
forEveryone = DeleteMessageDialogActiveState.Visible(
messageId = messageId,
conversationId = conversationId
)
)
}
} else {
updateDeleteDialogState {
it.copy(
forYourself = DeleteMessageDialogActiveState.Visible(
messageId = messageId,
conversationId = conversationId
)
)
}
}

private fun updateDeleteDialogState(newValue: (DeleteMessageDialogsState.States) -> DeleteMessageDialogsState) =
(deleteMessageDialogsState as? DeleteMessageDialogsState.States)?.let {
deleteMessageDialogsState = newValue(it)
}

fun updateConversationReadDate(utcISO: String) {
viewModelScope.launch(dispatchers.io()) {
updateConversationReadDate(conversationId, Instant.parse(utcISO))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ import com.wire.android.navigation.SavedStateViewModel
import com.wire.android.ui.home.conversations.ConversationNavArgs
import com.wire.android.ui.home.conversations.ConversationSnackbarMessages
import com.wire.android.ui.home.conversations.ConversationSnackbarMessages.OnResetSession
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogActiveState
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogHelper
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogsState
import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.android.ui.home.conversations.model.UIMessage
import com.wire.android.ui.home.conversations.model.UIMessageContent
Expand All @@ -55,11 +58,13 @@ import com.wire.kalium.logic.feature.asset.UpdateAssetMessageTransferStatusUseCa
import com.wire.kalium.logic.feature.conversation.ClearUsersTypingEventsUseCase
import com.wire.kalium.logic.feature.conversation.GetConversationUnreadEventsCountUseCase
import com.wire.kalium.logic.feature.conversation.ObserveConversationDetailsUseCase
import com.wire.kalium.logic.feature.message.DeleteMessageUseCase
import com.wire.kalium.logic.feature.message.GetMessageByIdUseCase
import com.wire.kalium.logic.feature.message.GetSearchedConversationMessagePositionUseCase
import com.wire.kalium.logic.feature.message.ToggleReactionUseCase
import com.wire.kalium.logic.feature.sessionreset.ResetSessionResult
import com.wire.kalium.logic.feature.sessionreset.ResetSessionUseCase
import com.wire.kalium.logic.functional.onFailure
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.collections.immutable.toPersistentMap
import kotlinx.coroutines.delay
Expand Down Expand Up @@ -91,7 +96,8 @@ class ConversationMessagesViewModel @Inject constructor(
private val conversationAudioMessagePlayer: ConversationAudioMessagePlayer,
private val getConversationUnreadEventsCount: GetConversationUnreadEventsCountUseCase,
private val clearUsersTypingEvents: ClearUsersTypingEventsUseCase,
private val getSearchedConversationMessagePosition: GetSearchedConversationMessagePositionUseCase
private val getSearchedConversationMessagePosition: GetSearchedConversationMessagePositionUseCase,
private val deleteMessage: DeleteMessageUseCase
) : SavedStateViewModel(savedStateHandle) {

private val conversationNavArgs: ConversationNavArgs = savedStateHandle.navArgs()
Expand All @@ -105,6 +111,27 @@ class ConversationMessagesViewModel @Inject constructor(
)
private set

var deleteMessageDialogsState: DeleteMessageDialogsState by mutableStateOf(
DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Hidden,
forEveryone = DeleteMessageDialogActiveState.Hidden
)
)
private set

val deleteMessageHelper = DeleteMessageDialogHelper(
viewModelScope,
conversationId,
::updateDeleteDialogState
) { messageId, deleteForEveryone, _ ->
deleteMessage(
conversationId = conversationId,
messageId = messageId,
deleteForEveryone = deleteForEveryone
)
.onFailure { onSnackbarMessage(ConversationSnackbarMessages.ErrorDeletingMessage) }
}

private var lastImageMessageShownOnGallery: UIMessage.Regular? = null
private val _infoMessage = MutableSharedFlow<SnackBarMessage>()
val infoMessage = _infoMessage.asSharedFlow()
Expand Down Expand Up @@ -335,6 +362,11 @@ class ConversationMessagesViewModel @Inject constructor(
onSnackbarMessage(ConversationSnackbarMessages.OnFileDownloaded(assetName))
}

private fun updateDeleteDialogState(newValue: (DeleteMessageDialogsState.States) -> DeleteMessageDialogsState) =
(deleteMessageDialogsState as? DeleteMessageDialogsState.States)?.let {
deleteMessageDialogsState = newValue(it)
}

fun audioClick(messageId: String) {
viewModelScope.launch {
conversationAudioMessagePlayer.playAudio(conversationId, messageId)
Expand Down Expand Up @@ -364,6 +396,27 @@ class ConversationMessagesViewModel @Inject constructor(
return null
}

fun showDeleteMessageDialog(messageId: String, deleteForEveryone: Boolean) =
if (deleteForEveryone) {
updateDeleteDialogState {
it.copy(
forEveryone = DeleteMessageDialogActiveState.Visible(
messageId = messageId,
conversationId = conversationId
)
)
}
} else {
updateDeleteDialogState {
it.copy(
forYourself = DeleteMessageDialogActiveState.Visible(
messageId = messageId,
conversationId = conversationId
)
)
}
}

override fun onCleared() {
super.onCleared()
conversationAudioMessagePlayer.close()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ import com.wire.kalium.logic.feature.conversation.SendTypingEventUseCase
import com.wire.kalium.logic.feature.conversation.SetNotifiedAboutConversationUnderLegalHoldUseCase
import com.wire.kalium.logic.feature.conversation.SetUserInformedAboutVerificationUseCase
import com.wire.kalium.logic.feature.conversation.UpdateConversationReadDateUseCase
import com.wire.kalium.logic.feature.message.DeleteMessageUseCase
import com.wire.kalium.logic.feature.message.RetryFailedMessageUseCase
import com.wire.kalium.logic.feature.message.SendEditTextMessageUseCase
import com.wire.kalium.logic.feature.message.SendKnockUseCase
Expand Down Expand Up @@ -129,9 +128,6 @@ internal class MessageComposerViewModelArrangement {
@MockK
lateinit var sendAssetMessage: ScheduleNewAssetMessageUseCase

@MockK
lateinit var deleteMessage: DeleteMessageUseCase

@MockK
lateinit var isFileSharingEnabledUseCase: IsFileSharingEnabledUseCase

Expand Down Expand Up @@ -218,7 +214,6 @@ internal class MessageComposerViewModelArrangement {
sendTextMessage = sendTextMessage,
sendEditTextMessage = sendEditTextMessage,
sendAssetMessage = sendAssetMessage,
deleteMessage = deleteMessage,
dispatchers = TestDispatcherProvider(),
isFileSharingEnabled = isFileSharingEnabledUseCase,
kaliumFileSystem = fakeKaliumFileSystem,
Expand Down Expand Up @@ -335,11 +330,6 @@ internal class MessageComposerViewModelArrangement {
} returns Unit
}

fun withFailureOnDeletingMessages() = apply {
coEvery { deleteMessage(any(), any(), any()) } returns Either.Left(CoreFailure.Unknown(null))
return this
}

fun withGetAssetSizeLimitUseCase(isImage: Boolean, assetSizeLimit: Long) = apply {
coEvery { getAssetSizeLimitUseCase(eq(isImage)) } returns assetSizeLimit
return this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,6 @@ import androidx.core.net.toUri
import app.cash.turbine.test
import com.wire.android.config.CoroutineTestExtension
import com.wire.android.config.NavigationTestExtension
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogActiveState
import com.wire.android.ui.home.conversations.delete.DeleteMessageDialogsState
import com.wire.android.ui.home.conversations.model.AssetBundle
import com.wire.android.ui.home.conversations.model.UriAsset
import com.wire.android.ui.home.messagecomposer.state.ComposableMessageBundle
Expand All @@ -42,7 +40,6 @@ import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import okio.Path.Companion.toPath
import org.amshove.kluent.internal.assertEquals
import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.Assertions.assertInstanceOf
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
Expand All @@ -55,117 +52,6 @@ import kotlin.time.toDuration
@Suppress("LargeClass")
class MessageComposerViewModelTest {

@Test
fun `validate deleteMessageDialogsState states when deleteMessageDialog is visible for my message`() =
runTest {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.arrange()

// When
viewModel.showDeleteMessageDialog("", true)

// Then
viewModel.deleteMessageDialogsState shouldBeEqualTo DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Hidden,
forEveryone = DeleteMessageDialogActiveState.Visible("", viewModel.conversationId)
)
}

@Test
fun `validate deleteMessageDialogsState states when deleteMessageDialog is visible for others message`() =
runTest {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.arrange()

// When
viewModel.showDeleteMessageDialog("", false)

// Then
viewModel.deleteMessageDialogsState shouldBeEqualTo DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Visible("", viewModel.conversationId),
forEveryone = DeleteMessageDialogActiveState.Hidden
)
}

@Test
fun `validate deleteMessageDialogsState states when deleteMessageForYourselfDialog is visible`() =
runTest {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.arrange()

// When
viewModel.deleteMessageHelper.showDeleteMessageForYourselfDialog("")

// Then
viewModel.deleteMessageDialogsState shouldBeEqualTo DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Visible("", viewModel.conversationId),
forEveryone = DeleteMessageDialogActiveState.Hidden
)
}

@Test
fun `validate deleteMessageDialogsState states when dialogs are dismissed`() {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.arrange()

// When
viewModel.deleteMessageHelper.onDeleteDialogDismissed()

// Then
viewModel.deleteMessageDialogsState shouldBeEqualTo DeleteMessageDialogsState.States(
forYourself = DeleteMessageDialogActiveState.Hidden,
forEveryone = DeleteMessageDialogActiveState.Hidden
)
}

@Test
fun `given a failure, when deleting messages, then the error state is updated`() = runTest {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.withFailureOnDeletingMessages().arrange()

viewModel.messageComposerViewState
viewModel.infoMessage.test {

// when
expectNoEvents()
viewModel.deleteMessageHelper.onDeleteMessage("messageId", true)

// Then
assertEquals(ConversationSnackbarMessages.ErrorDeletingMessage, awaitItem())
}
}

@Test
fun `given a failure, when deleting messages, then the delete dialog state is closed`() =
runTest {
// Given
val (_, viewModel) = MessageComposerViewModelArrangement()
.withSuccessfulViewModelInit()
.withFailureOnDeletingMessages()
.arrange()

viewModel.messageComposerViewState
// When
viewModel.deleteMessageHelper.onDeleteMessage("messageId", true)

// Then
val expectedState = DeleteMessageDialogsState.States(
DeleteMessageDialogActiveState.Hidden,
DeleteMessageDialogActiveState.Hidden
)
assertEquals(expectedState, viewModel.deleteMessageDialogsState)
}

@Test
fun `given the user sends an asset message, when invoked, then sendAssetMessageUseCase gets called`() =
runTest {
Expand Down
Loading

0 comments on commit 7e37bcb

Please sign in to comment.