Browse Source

Message queuing : remove RetrySendMenu classes and usages

pull/3011/head
ganfra 4 months ago
parent
commit
53a1cb5a3c
  1. 4
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt
  2. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt
  3. 4
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt
  4. 9
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
  5. 1
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt
  6. 26
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuEvents.kt
  7. 71
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt
  8. 26
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuState.kt
  9. 36
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuStateProvider.kt
  10. 159
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt
  11. 3
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt
  12. 163
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenterTest.kt
  13. 90
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenuTest.kt

4
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesPresenter.kt

@ -46,7 +46,6 @@ import io.element.android.features.messages.impl.timeline.TimelineState @@ -46,7 +46,6 @@ import io.element.android.features.messages.impl.timeline.TimelineState
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionPresenter
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetPresenter
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuPresenter
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemAudioContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemEncryptedContent
@ -106,7 +105,6 @@ class MessagesPresenter @AssistedInject constructor( @@ -106,7 +105,6 @@ class MessagesPresenter @AssistedInject constructor(
private val actionListPresenter: ActionListPresenter,
private val customReactionPresenter: CustomReactionPresenter,
private val reactionSummaryPresenter: ReactionSummaryPresenter,
private val retrySendMenuPresenter: RetrySendMenuPresenter,
private val readReceiptBottomSheetPresenter: ReadReceiptBottomSheetPresenter,
private val networkMonitor: NetworkMonitor,
private val snackbarDispatcher: SnackbarDispatcher,
@ -139,7 +137,6 @@ class MessagesPresenter @AssistedInject constructor( @@ -139,7 +137,6 @@ class MessagesPresenter @AssistedInject constructor(
val actionListState = actionListPresenter.present()
val customReactionState = customReactionPresenter.present()
val reactionSummaryState = reactionSummaryPresenter.present()
val retryState = retrySendMenuPresenter.present()
val readReceiptBottomSheetState = readReceiptBottomSheetPresenter.present()
val syncUpdateFlow = room.syncUpdateFlow.collectAsState()
@ -230,7 +227,6 @@ class MessagesPresenter @AssistedInject constructor( @@ -230,7 +227,6 @@ class MessagesPresenter @AssistedInject constructor(
actionListState = actionListState,
customReactionState = customReactionState,
reactionSummaryState = reactionSummaryState,
retrySendMenuState = retryState,
readReceiptBottomSheetState = readReceiptBottomSheetState,
hasNetworkConnection = networkConnectionStatus == NetworkStatus.Online,
snackbarMessage = snackbarMessage,

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesState.kt

@ -23,7 +23,6 @@ import io.element.android.features.messages.impl.timeline.TimelineState @@ -23,7 +23,6 @@ import io.element.android.features.messages.impl.timeline.TimelineState
import io.element.android.features.messages.impl.timeline.components.customreaction.CustomReactionState
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
import io.element.android.features.messages.impl.typing.TypingNotificationState
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState
import io.element.android.libraries.architecture.AsyncData
@ -47,7 +46,6 @@ data class MessagesState( @@ -47,7 +46,6 @@ data class MessagesState(
val actionListState: ActionListState,
val customReactionState: CustomReactionState,
val reactionSummaryState: ReactionSummaryState,
val retrySendMenuState: RetrySendMenuState,
val readReceiptBottomSheetState: ReadReceiptBottomSheetState,
val hasNetworkConnection: Boolean,
val snackbarMessage: SnackbarMessage?,

4
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesStateProvider.kt

@ -31,8 +31,6 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum @@ -31,8 +31,6 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryState
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetState
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuState
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.aRetrySendMenuState
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemTextContent
import io.element.android.features.messages.impl.typing.aTypingNotificationState
@ -110,7 +108,6 @@ fun aMessagesState( @@ -110,7 +108,6 @@ fun aMessagesState(
// Render a focused event for an event with sender information displayed
focusedEventIndex = 2,
),
retrySendMenuState: RetrySendMenuState = aRetrySendMenuState(),
readReceiptBottomSheetState: ReadReceiptBottomSheetState = aReadReceiptBottomSheetState(),
actionListState: ActionListState = anActionListState(),
customReactionState: CustomReactionState = aCustomReactionState(),
@ -132,7 +129,6 @@ fun aMessagesState( @@ -132,7 +129,6 @@ fun aMessagesState(
voiceMessageComposerState = voiceMessageComposerState,
typingNotificationState = aTypingNotificationState(),
timelineState = timelineState,
retrySendMenuState = retrySendMenuState,
readReceiptBottomSheetState = readReceiptBottomSheetState,
actionListState = actionListState,
customReactionState = customReactionState,

9
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt

@ -76,8 +76,6 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum @@ -76,8 +76,6 @@ import io.element.android.features.messages.impl.timeline.components.reactionsum
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryView
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheet
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetEvents
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuEvents
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMessageMenu
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerEvents
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessagePermissionRationaleDialog
@ -215,11 +213,7 @@ fun MessagesView( @@ -215,11 +213,7 @@ fun MessagesView(
onMessageLongClick = ::onMessageLongClick,
onUserDataClick = onUserDataClick,
onLinkClick = onLinkClick,
onTimestampClick = { event ->
if (event.localSendState is LocalEventSendState.SendingFailed) {
state.retrySendMenuState.eventSink(RetrySendMenuEvents.EventSelected(event))
}
},
onTimestampClick = { /* no-op */ },
onReactionClick = ::onEmojiReactionClick,
onReactionLongClick = ::onEmojiReactionLongClick,
onMoreReactionsClick = ::onMoreReactionsClick,
@ -260,7 +254,6 @@ fun MessagesView( @@ -260,7 +254,6 @@ fun MessagesView(
)
ReactionSummaryView(state = state.reactionSummaryState)
RetrySendMessageMenu(state = state.retrySendMenuState)
ReadReceiptBottomSheet(
state = state.readReceiptBottomSheetState,
onUserDataClick = onUserDataClick,

1
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/receipt/bottomsheet/ReadReceiptBottomSheet.kt

@ -123,7 +123,6 @@ private fun ReadReceiptBottomSheetContent( @@ -123,7 +123,6 @@ private fun ReadReceiptBottomSheetContent(
@PreviewsDayNight
@Composable
internal fun ReadReceiptBottomSheetPreview(@PreviewParameter(ReadReceiptBottomSheetStateProvider::class) state: ReadReceiptBottomSheetState) = ElementPreview {
// TODO restore RetrySendMessageMenuBottomSheet once the issue with bottom sheet not being previewable is fixed
Column {
ReadReceiptBottomSheetContent(
state = state,

26
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuEvents.kt

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import io.element.android.features.messages.impl.timeline.model.TimelineItem
sealed interface RetrySendMenuEvents {
data class EventSelected(val event: TimelineItem.Event) : RetrySendMenuEvents
data object Retry : RetrySendMenuEvents
data object Remove : RetrySendMenuEvents
data object Dismiss : RetrySendMenuEvents
}

71
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenter.kt

@ -1,71 +0,0 @@ @@ -1,71 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.libraries.architecture.Presenter
import io.element.android.libraries.matrix.api.room.MatrixRoom
import kotlinx.coroutines.launch
import javax.inject.Inject
class RetrySendMenuPresenter @Inject constructor(
private val room: MatrixRoom,
) : Presenter<RetrySendMenuState> {
@Composable
override fun present(): RetrySendMenuState {
val coroutineScope = rememberCoroutineScope()
var selectedEvent: TimelineItem.Event? by remember { mutableStateOf(null) }
fun handleEvent(event: RetrySendMenuEvents) {
when (event) {
is RetrySendMenuEvents.EventSelected -> {
selectedEvent = event.event
}
RetrySendMenuEvents.Retry -> {
coroutineScope.launch {
selectedEvent?.transactionId?.let { transactionId ->
room.retrySendMessage(transactionId)
}
selectedEvent = null
}
}
RetrySendMenuEvents.Remove -> {
coroutineScope.launch {
selectedEvent?.transactionId?.let { transactionId ->
room.cancelSend(transactionId)
}
selectedEvent = null
}
}
RetrySendMenuEvents.Dismiss -> {
selectedEvent = null
}
}
}
return RetrySendMenuState(
selectedEvent = selectedEvent,
eventSink = { handleEvent(it) },
)
}
}

26
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuState.kt

@ -1,26 +0,0 @@ @@ -1,26 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import androidx.compose.runtime.Immutable
import io.element.android.features.messages.impl.timeline.model.TimelineItem
@Immutable
data class RetrySendMenuState(
val selectedEvent: TimelineItem.Event?,
val eventSink: (RetrySendMenuEvents) -> Unit,
)

36
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuStateProvider.kt

@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.features.messages.impl.timeline.model.TimelineItem
class RetrySendMenuStateProvider : PreviewParameterProvider<RetrySendMenuState> {
override val values: Sequence<RetrySendMenuState> = sequenceOf(
aRetrySendMenuState(),
aRetrySendMenuState(event = aTimelineItemEvent()),
)
}
fun aRetrySendMenuState(
event: TimelineItem.Event? = null,
eventSink: (RetrySendMenuEvents) -> Unit = {},
) = RetrySendMenuState(
selectedEvent = event,
eventSink = eventSink,
)

159
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenu.kt

@ -1,159 +0,0 @@ @@ -1,159 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.ColumnScope
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.height
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ListItem
import androidx.compose.material3.ListItemDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.SheetState
import androidx.compose.material3.rememberModalBottomSheetState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme
import io.element.android.features.messages.impl.R
import io.element.android.libraries.designsystem.preview.ElementPreview
import io.element.android.libraries.designsystem.preview.PreviewsDayNight
import io.element.android.libraries.designsystem.theme.components.ModalBottomSheet
import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.ui.strings.CommonStrings
import kotlinx.coroutines.launch
@Composable
internal fun RetrySendMessageMenu(
state: RetrySendMenuState,
modifier: Modifier = Modifier,
) {
val isVisible = state.selectedEvent != null
fun onDismiss() {
state.eventSink(RetrySendMenuEvents.Dismiss)
}
fun onRetry() {
state.eventSink(RetrySendMenuEvents.Retry)
}
fun onRemove() {
state.eventSink(RetrySendMenuEvents.Remove)
}
RetrySendMessageMenuBottomSheet(
modifier = modifier,
isVisible = isVisible,
onRetry = ::onRetry,
onRemove = ::onRemove,
onDismiss = ::onDismiss
)
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun RetrySendMessageMenuBottomSheet(
isVisible: Boolean,
onRetry: () -> Unit,
onRemove: () -> Unit,
onDismiss: () -> Unit,
modifier: Modifier = Modifier,
) {
val sheetState = rememberModalBottomSheetState()
val coroutineScope = rememberCoroutineScope()
if (isVisible) {
ModalBottomSheet(
modifier = modifier,
// modifier = modifier.navigationBarsPadding() - FIXME after https://issuetracker.google.com/issues/275849044
// .imePadding()
sheetState = sheetState,
onDismissRequest = {
coroutineScope.launch {
sheetState.hide()
onDismiss()
}
}
) {
RetrySendMenuContents(
onRetry = onRetry,
onRemove = onRemove,
)
// FIXME remove after https://issuetracker.google.com/issues/275849044
Spacer(modifier = Modifier.height(32.dp))
}
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ColumnScope.RetrySendMenuContents(
onRetry: () -> Unit,
onRemove: () -> Unit,
sheetState: SheetState = rememberModalBottomSheetState(),
) {
val coroutineScope = rememberCoroutineScope()
ListItem(headlineContent = {
Text(
text = stringResource(R.string.screen_room_retry_send_menu_title),
style = ElementTheme.typography.fontBodyLgMedium,
)
})
ListItem(
headlineContent = {
Text(
text = stringResource(R.string.screen_room_retry_send_menu_send_again_action),
style = ElementTheme.typography.fontBodyLgRegular,
)
},
modifier = Modifier.clickable {
coroutineScope.launch {
sheetState.hide()
onRetry()
}
}
)
ListItem(
headlineContent = {
Text(
text = stringResource(CommonStrings.action_remove),
style = ElementTheme.typography.fontBodyLgRegular,
)
},
colors = ListItemDefaults.colors(headlineColor = MaterialTheme.colorScheme.error),
modifier = Modifier.clickable {
coroutineScope.launch {
sheetState.hide()
onRemove()
}
}
)
}
@PreviewsDayNight
@Composable
internal fun RetrySendMessageMenuPreview(@PreviewParameter(RetrySendMenuStateProvider::class) state: RetrySendMenuState) = ElementPreview {
RetrySendMessageMenu(
state = state,
)
}

3
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/MessagesPresenterTest.kt

@ -38,7 +38,6 @@ import io.element.android.features.messages.impl.timeline.components.customreact @@ -38,7 +38,6 @@ import io.element.android.features.messages.impl.timeline.components.customreact
import io.element.android.features.messages.impl.timeline.components.customreaction.FakeEmojibaseProvider
import io.element.android.features.messages.impl.timeline.components.reactionsummary.ReactionSummaryPresenter
import io.element.android.features.messages.impl.timeline.components.receipt.bottomsheet.ReadReceiptBottomSheetPresenter
import io.element.android.features.messages.impl.timeline.components.retrysendmenu.RetrySendMenuPresenter
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemFileContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemImageContent
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemTextContent
@ -839,7 +838,6 @@ class MessagesPresenterTest { @@ -839,7 +838,6 @@ class MessagesPresenterTest {
val readReceiptBottomSheetPresenter = ReadReceiptBottomSheetPresenter()
val customReactionPresenter = CustomReactionPresenter(emojibaseProvider = FakeEmojibaseProvider())
val reactionSummaryPresenter = ReactionSummaryPresenter(room = matrixRoom)
val retrySendMenuPresenter = RetrySendMenuPresenter(room = matrixRoom)
return MessagesPresenter(
room = matrixRoom,
composerPresenter = messageComposerPresenter,
@ -849,7 +847,6 @@ class MessagesPresenterTest { @@ -849,7 +847,6 @@ class MessagesPresenterTest {
actionListPresenter = actionListPresenter,
customReactionPresenter = customReactionPresenter,
reactionSummaryPresenter = reactionSummaryPresenter,
retrySendMenuPresenter = retrySendMenuPresenter,
readReceiptBottomSheetPresenter = readReceiptBottomSheetPresenter,
networkMonitor = FakeNetworkMonitor(),
snackbarDispatcher = SnackbarDispatcher(),

163
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMenuPresenterTest.kt

@ -1,163 +0,0 @@ @@ -1,163 +0,0 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import app.cash.molecule.RecompositionMode
import app.cash.molecule.moleculeFlow
import app.cash.turbine.test
import com.google.common.truth.Truth.assertThat
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.libraries.matrix.test.A_TRANSACTION_ID
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.tests.testutils.WarmUpRule
import kotlinx.coroutines.test.runTest
import org.junit.Rule
import org.junit.Test
class RetrySendMenuPresenterTest {
@get:Rule
val warmUpRule = WarmUpRule()
private val room = FakeMatrixRoom()
private val presenter = RetrySendMenuPresenter(room)
@Test
fun `present - handle event selected`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent()
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
assertThat(awaitItem().selectedEvent).isSameInstanceAs(selectedEvent)
}
}
@Test
fun `present - handle dismiss`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent()
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Dismiss)
assertThat(room.cancelSendCount).isEqualTo(0)
assertThat(room.retrySendMessageCount).isEqualTo(0)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle resend with transactionId`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = A_TRANSACTION_ID)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Retry)
assertThat(room.cancelSendCount).isEqualTo(0)
assertThat(room.retrySendMessageCount).isEqualTo(1)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle resend without transactionId`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = null)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Retry)
assertThat(room.cancelSendCount).isEqualTo(0)
assertThat(room.retrySendMessageCount).isEqualTo(0)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle resend with error`() = runTest {
room.givenRetrySendMessageResult(Result.failure(IllegalStateException("An error")))
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = A_TRANSACTION_ID)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Retry)
assertThat(room.cancelSendCount).isEqualTo(0)
assertThat(room.retrySendMessageCount).isEqualTo(1)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle remove failed message with transactionId`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = A_TRANSACTION_ID)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Remove)
assertThat(room.cancelSendCount).isEqualTo(1)
assertThat(room.retrySendMessageCount).isEqualTo(0)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle remove failed message without transactionId`() = runTest {
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = null)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Remove)
assertThat(room.cancelSendCount).isEqualTo(0)
assertThat(room.retrySendMessageCount).isEqualTo(0)
assertThat(awaitItem().selectedEvent).isNull()
}
}
@Test
fun `present - handle remove failed message with error`() = runTest {
room.givenRetrySendMessageResult(Result.failure(IllegalStateException("An error")))
moleculeFlow(RecompositionMode.Immediate) {
presenter.present()
}.test {
val initialState = awaitItem()
val selectedEvent = aTimelineItemEvent(transactionId = A_TRANSACTION_ID)
initialState.eventSink(RetrySendMenuEvents.EventSelected(selectedEvent))
skipItems(1)
initialState.eventSink(RetrySendMenuEvents.Remove)
assertThat(room.cancelSendCount).isEqualTo(1)
assertThat(room.retrySendMessageCount).isEqualTo(0)
assertThat(awaitItem().selectedEvent).isNull()
}
}
}

90
features/messages/impl/src/test/kotlin/io/element/android/features/messages/impl/timeline/components/retrysendmenu/RetrySendMessageMenuTest.kt

@ -1,90 +0,0 @@ @@ -1,90 +0,0 @@
/*
* Copyright (c) 2024 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.element.android.features.messages.impl.timeline.components.retrysendmenu
import androidx.activity.ComponentActivity
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import io.element.android.features.messages.impl.R
import io.element.android.features.messages.impl.timeline.aTimelineItemEvent
import io.element.android.libraries.ui.strings.CommonStrings
import io.element.android.tests.testutils.EventsRecorder
import io.element.android.tests.testutils.clickOn
import io.element.android.tests.testutils.pressBackKey
import org.junit.Rule
import org.junit.Test
import org.junit.rules.TestRule
import org.junit.runner.RunWith
import org.robolectric.annotation.Config
@RunWith(AndroidJUnit4::class)
class RetrySendMessageMenuTest {
@get:Rule val rule = createAndroidComposeRule<ComponentActivity>()
@Test
fun `dismiss the bottom sheet emits the expected event`() {
val eventsRecorder = EventsRecorder<RetrySendMenuEvents>()
rule.setRetrySendMessageMenu(
aRetrySendMenuState(
event = aTimelineItemEvent(),
eventSink = eventsRecorder
),
)
rule.pressBackKey()
// Cannot test this for now.
// eventsRecorder.assertSingle(RetrySendMenuEvents.Dismiss)
}
@Config(qualifiers = "h1024dp")
@Test
fun `retry to send the event emits the expected event`() {
val eventsRecorder = EventsRecorder<RetrySendMenuEvents>()
rule.setRetrySendMessageMenu(
aRetrySendMenuState(
event = aTimelineItemEvent(),
eventSink = eventsRecorder
),
)
rule.clickOn(R.string.screen_room_retry_send_menu_send_again_action)
eventsRecorder.assertSingle(RetrySendMenuEvents.Retry)
}
@Config(qualifiers = "h1024dp")
@Test
fun `remove the event emits the expected event`() {
val eventsRecorder = EventsRecorder<RetrySendMenuEvents>()
rule.setRetrySendMessageMenu(
aRetrySendMenuState(
event = aTimelineItemEvent(),
eventSink = eventsRecorder
),
)
rule.clickOn(CommonStrings.action_remove)
eventsRecorder.assertSingle(RetrySendMenuEvents.Remove)
}
}
private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setRetrySendMessageMenu(
state: RetrySendMenuState,
) {
setContent {
RetrySendMessageMenu(
state = state,
)
}
}
Loading…
Cancel
Save