Track errors in VoiceMessagePresenter (#1667)
Story: https://github.com/vector-im/element-meta/issues/2085
This commit is contained in:
parent
473ac2dcc1
commit
b137e1f1ab
3 changed files with 28 additions and 1 deletions
|
|
@ -23,4 +23,7 @@ internal sealed class VoiceMessageException : Exception() {
|
||||||
data class PermissionMissing(
|
data class PermissionMissing(
|
||||||
override val message: String?, override val cause: Throwable?
|
override val message: String?, override val cause: Throwable?
|
||||||
) : VoiceMessageException()
|
) : VoiceMessageException()
|
||||||
|
data class PlayMessageError(
|
||||||
|
override val message: String?, override val cause: Throwable?
|
||||||
|
) : VoiceMessageException()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,11 +33,13 @@ import dagger.multibindings.IntoMap
|
||||||
import io.element.android.features.messages.impl.timeline.di.TimelineItemEventContentKey
|
import io.element.android.features.messages.impl.timeline.di.TimelineItemEventContentKey
|
||||||
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactory
|
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactory
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||||
|
import io.element.android.features.messages.impl.voicemessages.VoiceMessageException
|
||||||
import io.element.android.libraries.architecture.Async
|
import io.element.android.libraries.architecture.Async
|
||||||
import io.element.android.libraries.architecture.Presenter
|
import io.element.android.libraries.architecture.Presenter
|
||||||
import io.element.android.libraries.architecture.runUpdatingState
|
import io.element.android.libraries.architecture.runUpdatingState
|
||||||
import io.element.android.libraries.di.RoomScope
|
import io.element.android.libraries.di.RoomScope
|
||||||
import io.element.android.libraries.ui.utils.time.formatShort
|
import io.element.android.libraries.ui.utils.time.formatShort
|
||||||
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
|
||||||
|
|
@ -52,6 +54,7 @@ interface VoiceMessagePresenterModule {
|
||||||
|
|
||||||
class VoiceMessagePresenter @AssistedInject constructor(
|
class VoiceMessagePresenter @AssistedInject constructor(
|
||||||
voiceMessagePlayerFactory: VoiceMessagePlayer.Factory,
|
voiceMessagePlayerFactory: VoiceMessagePlayer.Factory,
|
||||||
|
private val analyticsService: AnalyticsService,
|
||||||
@Assisted private val content: TimelineItemVoiceContent,
|
@Assisted private val content: TimelineItemVoiceContent,
|
||||||
) : Presenter<VoiceMessageState> {
|
) : Presenter<VoiceMessageState> {
|
||||||
|
|
||||||
|
|
@ -102,7 +105,18 @@ class VoiceMessagePresenter @AssistedInject constructor(
|
||||||
if (playerState.isPlaying) {
|
if (playerState.isPlaying) {
|
||||||
player.pause()
|
player.pause()
|
||||||
} else {
|
} else {
|
||||||
scope.launch { play.runUpdatingState { player.play() } }
|
scope.launch {
|
||||||
|
play.runUpdatingState(
|
||||||
|
errorTransform = {
|
||||||
|
analyticsService.trackError(
|
||||||
|
VoiceMessageException.PlayMessageError("Error while trying to play voice message", it)
|
||||||
|
)
|
||||||
|
it
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is VoiceMessageEvents.Seek -> {
|
is VoiceMessageEvents.Seek -> {
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,15 @@ import app.cash.turbine.test
|
||||||
import com.google.common.truth.Truth
|
import com.google.common.truth.Truth
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
import io.element.android.features.messages.impl.timeline.model.event.TimelineItemVoiceContent
|
||||||
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
|
import io.element.android.features.messages.impl.timeline.model.event.aTimelineItemVoiceContent
|
||||||
|
import io.element.android.features.messages.impl.voicemessages.VoiceMessageException
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.DefaultVoiceMessagePlayer
|
import io.element.android.features.messages.impl.voicemessages.timeline.DefaultVoiceMessagePlayer
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageEvents
|
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageEvents
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageMediaRepo
|
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageMediaRepo
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessagePresenter
|
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessagePresenter
|
||||||
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageState
|
import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageState
|
||||||
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
|
import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
|
||||||
|
import io.element.android.services.analytics.api.AnalyticsService
|
||||||
|
import io.element.android.services.analytics.test.FakeAnalyticsService
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
|
|
||||||
|
|
@ -77,8 +80,10 @@ class VoiceMessagePresenterTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `pressing play downloads and fails`() = runTest {
|
fun `pressing play downloads and fails`() = runTest {
|
||||||
|
val analyticsService = FakeAnalyticsService()
|
||||||
val presenter = createVoiceMessagePresenter(
|
val presenter = createVoiceMessagePresenter(
|
||||||
voiceMessageMediaRepo = FakeVoiceMessageMediaRepo().apply { shouldFail = true },
|
voiceMessageMediaRepo = FakeVoiceMessageMediaRepo().apply { shouldFail = true },
|
||||||
|
analyticsService = analyticsService,
|
||||||
content = aTimelineItemVoiceContent(durationMs = 2_000),
|
content = aTimelineItemVoiceContent(durationMs = 2_000),
|
||||||
)
|
)
|
||||||
moleculeFlow(RecompositionMode.Immediate) {
|
moleculeFlow(RecompositionMode.Immediate) {
|
||||||
|
|
@ -102,6 +107,9 @@ class VoiceMessagePresenterTest {
|
||||||
Truth.assertThat(it.progress).isEqualTo(0f)
|
Truth.assertThat(it.progress).isEqualTo(0f)
|
||||||
Truth.assertThat(it.time).isEqualTo("0:02")
|
Truth.assertThat(it.time).isEqualTo("0:02")
|
||||||
}
|
}
|
||||||
|
analyticsService.trackedErrors.first().also {
|
||||||
|
Truth.assertThat(it).isInstanceOf(VoiceMessageException.PlayMessageError::class.java)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,6 +198,7 @@ class VoiceMessagePresenterTest {
|
||||||
|
|
||||||
fun createVoiceMessagePresenter(
|
fun createVoiceMessagePresenter(
|
||||||
voiceMessageMediaRepo: VoiceMessageMediaRepo = FakeVoiceMessageMediaRepo(),
|
voiceMessageMediaRepo: VoiceMessageMediaRepo = FakeVoiceMessageMediaRepo(),
|
||||||
|
analyticsService: AnalyticsService = FakeAnalyticsService(),
|
||||||
content: TimelineItemVoiceContent = aTimelineItemVoiceContent(),
|
content: TimelineItemVoiceContent = aTimelineItemVoiceContent(),
|
||||||
) = VoiceMessagePresenter(
|
) = VoiceMessagePresenter(
|
||||||
voiceMessagePlayerFactory = { eventId, mediaSource, mimeType, body ->
|
voiceMessagePlayerFactory = { eventId, mediaSource, mimeType, body ->
|
||||||
|
|
@ -202,5 +211,6 @@ fun createVoiceMessagePresenter(
|
||||||
body = body
|
body = body
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
analyticsService = analyticsService,
|
||||||
content = content,
|
content = content,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue