diff --git a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenter.kt b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenter.kt index 0fae36f1ec..ff3e2df722 100644 --- a/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenter.kt +++ b/features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPresenter.kt @@ -149,6 +149,7 @@ class VoiceMessageComposerPresenter @Inject constructor( return@lambda } isSending = true + player.pause() appCoroutineScope.sendMessage( file = finishedState.file, mimeType = finishedState.mimeType, @@ -165,7 +166,10 @@ class VoiceMessageComposerPresenter @Inject constructor( is VoiceMessageComposerEvents.SendVoiceMessage -> localCoroutineScope.launch { onSendButtonPress() } - VoiceMessageComposerEvents.DeleteVoiceMessage -> localCoroutineScope.deleteRecording() + VoiceMessageComposerEvents.DeleteVoiceMessage -> { + player.pause() + localCoroutineScope.deleteRecording() + } VoiceMessageComposerEvents.DismissPermissionsRationale -> onDismissPermissionsRationale() VoiceMessageComposerEvents.AcceptPermissionRationale -> onAcceptPermissionsRationale() is VoiceMessageComposerEvents.LifecycleEvent -> onLifecycleEvent(event.event) diff --git a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt index d3cb53fb49..4cffe65036 100644 --- a/features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt +++ b/features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt @@ -209,6 +209,28 @@ class VoiceMessageComposerPresenterTest { } } + @Test + fun `present - delete while playing`() = runTest { + val presenter = createVoiceMessageComposerPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(VoiceMessageComposerEvents.RecordButtonEvent(PressEvent.PressStart)) + awaitItem().eventSink(VoiceMessageComposerEvents.RecordButtonEvent(PressEvent.LongPressEnd)) + awaitItem().eventSink(VoiceMessageComposerEvents.PlayerEvent(VoiceMessagePlayerEvent.Play)) + awaitItem().eventSink(VoiceMessageComposerEvents.DeleteVoiceMessage) + awaitItem().apply { + assertThat(voiceMessageState).isEqualTo(aPreviewState(isPlaying = false)) + } + + val finalState = awaitItem() + assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) + voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) + + testPauseAndDestroy(finalState) + } + } + @Test fun `present - send recording`() = runTest { val presenter = createVoiceMessageComposerPresenter() @@ -229,6 +251,29 @@ class VoiceMessageComposerPresenterTest { } } + @Test + fun `present - send while playing`() = runTest { + val presenter = createVoiceMessageComposerPresenter() + moleculeFlow(RecompositionMode.Immediate) { + presenter.present() + }.test { + awaitItem().eventSink(VoiceMessageComposerEvents.RecordButtonEvent(PressEvent.PressStart)) + awaitItem().eventSink(VoiceMessageComposerEvents.RecordButtonEvent(PressEvent.LongPressEnd)) + awaitItem().eventSink(VoiceMessageComposerEvents.PlayerEvent(VoiceMessagePlayerEvent.Play)) + awaitItem().eventSink(VoiceMessageComposerEvents.SendVoiceMessage) + assertThat(awaitItem().voiceMessageState).isEqualTo(aPreviewState( + isSending = true, isPlaying = false, + )) + + val finalState = awaitItem() + assertThat(finalState.voiceMessageState).isEqualTo(VoiceMessageState.Idle) + assertThat(matrixRoom.sendMediaCount).isEqualTo(1) + voiceRecorder.assertCalls(started = 1, stopped = 1, deleted = 1) + + testPauseAndDestroy(finalState) + } + } + @Test fun `present - send recording before previous completed, waits`() = runTest { val presenter = createVoiceMessageComposerPresenter() diff --git a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/media/FakeWaveformFactory.kt b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/media/FakeWaveformFactory.kt index 19b2d4e8b5..4273d95e2c 100644 --- a/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/media/FakeWaveformFactory.kt +++ b/libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/components/media/FakeWaveformFactory.kt @@ -20,17 +20,15 @@ import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.toPersistentList import kotlin.random.Random -object FakeWaveformFactory { - /** - * Generate a waveform for testing purposes. - * - * The waveform is a list of floats between 0 and 1. - * - * @param length The length of the waveform. - */ - fun createFakeWaveform(length: Int = 1000): ImmutableList { - val random = Random(seed = 2) - return List(length) { random.nextFloat() } - .toPersistentList() - } +/** + * Generate a waveform for testing purposes. + * + * The waveform is a list of floats between 0 and 1. + * + * @param length The length of the waveform. + */ +fun createFakeWaveform(length: Int = 1000): ImmutableList { + val random = Random(seed = 2) + return List(length) { random.nextFloat() } + .toPersistentList() } diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt index 3116f79ba0..5c55dbb517 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/TextComposer.kt @@ -48,7 +48,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.components.media.FakeWaveformFactory.createFakeWaveform +import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.applyScaleUp diff --git a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/VoiceMessagePreview.kt b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/VoiceMessagePreview.kt index be06f853f8..baee7d1be5 100644 --- a/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/VoiceMessagePreview.kt +++ b/libraries/textcomposer/impl/src/main/kotlin/io/element/android/libraries/textcomposer/components/VoiceMessagePreview.kt @@ -34,8 +34,8 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp -import io.element.android.libraries.designsystem.components.media.FakeWaveformFactory.createFakeWaveform import io.element.android.libraries.designsystem.components.media.WaveformPlaybackView +import io.element.android.libraries.designsystem.components.media.createFakeWaveform import io.element.android.libraries.designsystem.preview.ElementPreview import io.element.android.libraries.designsystem.preview.PreviewsDayNight import io.element.android.libraries.designsystem.text.applyScaleUp