Merge branch 'develop' into feat/variable-playback-speed
This commit is contained in:
commit
0c004d933c
8020 changed files with 56825 additions and 29988 deletions
|
|
@ -1,14 +1,14 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.voiceplayer.impl
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.architecture.Presenter
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
import io.element.android.libraries.di.annotations.SessionCoroutineScope
|
||||
|
|
@ -21,7 +21,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||
import kotlin.time.Duration
|
||||
|
||||
@ContributesBinding(RoomScope::class)
|
||||
@Inject
|
||||
class DefaultVoiceMessagePresenterFactory(
|
||||
private val analyticsService: AnalyticsService,
|
||||
@SessionCoroutineScope
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,14 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.libraries.voiceplayer.impl
|
||||
|
||||
import dev.zacsweers.metro.ContributesBinding
|
||||
import dev.zacsweers.metro.Inject
|
||||
import io.element.android.libraries.core.extensions.mapCatchingExceptions
|
||||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.di.RoomScope
|
||||
|
|
@ -124,8 +124,7 @@ class DefaultVoiceMessagePlayer(
|
|||
filename: String?,
|
||||
) : VoiceMessagePlayer {
|
||||
@ContributesBinding(RoomScope::class) // Scoped types can't use @Inject.
|
||||
@Inject
|
||||
class Factory(
|
||||
class Factory(
|
||||
private val mediaPlayer: MediaPlayer,
|
||||
private val voiceMessageMediaRepoFactory: VoiceMessageMediaRepo.Factory,
|
||||
) : VoiceMessagePlayer.Factory {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2024, 2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
@ -87,7 +88,7 @@ class VoiceMessagePresenter(
|
|||
}
|
||||
}
|
||||
|
||||
fun eventSink(event: VoiceMessageEvents) {
|
||||
fun handleEvent(event: VoiceMessageEvents) {
|
||||
when (event) {
|
||||
is VoiceMessageEvents.PlayPause -> {
|
||||
if (playerState.isPlaying) {
|
||||
|
|
@ -130,7 +131,7 @@ class VoiceMessagePresenter(
|
|||
time = time,
|
||||
showCursor = showCursor,
|
||||
playbackSpeed = playbackSpeed.value,
|
||||
eventSink = { eventSink(it) },
|
||||
eventSink = ::handleEvent,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
@ -11,8 +12,8 @@ import com.google.common.truth.Truth.assertThat
|
|||
import io.element.android.libraries.core.mimetype.MimeTypes
|
||||
import io.element.android.libraries.matrix.api.media.MatrixMediaLoader
|
||||
import io.element.android.libraries.matrix.api.media.MediaSource
|
||||
import io.element.android.libraries.matrix.api.mxc.MxcTools
|
||||
import io.element.android.libraries.matrix.test.media.FakeMatrixMediaLoader
|
||||
import io.element.android.libraries.matrix.test.mxc.FakeMxcTools
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import org.junit.Rule
|
||||
import org.junit.Test
|
||||
|
|
@ -130,7 +131,7 @@ private fun createDefaultVoiceMessageMediaRepo(
|
|||
mxcUri: String = MXC_URI,
|
||||
) = DefaultVoiceMessageMediaRepo(
|
||||
cacheDir = temporaryFolder.root,
|
||||
mxcTools = MxcTools(),
|
||||
mxcTools = FakeMxcTools(),
|
||||
matrixMediaLoader = matrixMediaLoader,
|
||||
mediaSource = MediaSource(
|
||||
url = mxcUri,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
@ -114,7 +115,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
assertThat(player1.prepare().isSuccess).isTrue()
|
||||
matchReadyState(1_000L)
|
||||
player1.play()
|
||||
awaitItem().let { // it plays until the end.
|
||||
awaitItem().let {
|
||||
// it plays until the end.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isTrue()
|
||||
|
|
@ -127,14 +129,16 @@ class DefaultVoiceMessagePlayerTest {
|
|||
player2.state.test {
|
||||
matchInitialState()
|
||||
assertThat(player2.prepare().isSuccess).isTrue()
|
||||
awaitItem().let { // Additional spurious state due to MediaPlayer owner change.
|
||||
awaitItem().let {
|
||||
// Additional spurious state due to MediaPlayer owner change.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isTrue()
|
||||
assertThat(it.currentPosition).isEqualTo(1000)
|
||||
assertThat(it.duration).isEqualTo(1000)
|
||||
}
|
||||
awaitItem().let { // Additional spurious state due to MediaPlayer owner change.
|
||||
awaitItem().let {
|
||||
// Additional spurious state due to MediaPlayer owner change.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isFalse()
|
||||
|
|
@ -143,7 +147,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
}
|
||||
matchReadyState(1_000L)
|
||||
player2.play()
|
||||
awaitItem().let { // it plays until the end.
|
||||
awaitItem().let {
|
||||
// it plays until the end.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isTrue()
|
||||
|
|
@ -154,7 +159,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
|
||||
// Play player1 again.
|
||||
player1.state.test {
|
||||
awaitItem().let { // Last previous state/
|
||||
awaitItem().let {
|
||||
// Last previous state/
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isTrue()
|
||||
|
|
@ -162,7 +168,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
assertThat(it.duration).isEqualTo(1000)
|
||||
}
|
||||
assertThat(player1.prepare().isSuccess).isTrue()
|
||||
awaitItem().let { // Additional spurious state due to MediaPlayer owner change.
|
||||
awaitItem().let {
|
||||
// Additional spurious state due to MediaPlayer owner change.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isFalse()
|
||||
|
|
@ -171,7 +178,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
}
|
||||
matchReadyState(1_000L)
|
||||
player1.play()
|
||||
awaitItem().let { // it played again until the end.
|
||||
awaitItem().let {
|
||||
// it played again until the end.
|
||||
assertThat(it.isReady).isFalse()
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
assertThat(it.isEnded).isTrue()
|
||||
|
|
@ -189,7 +197,8 @@ class DefaultVoiceMessagePlayerTest {
|
|||
assertThat(player.prepare().isSuccess).isTrue()
|
||||
matchReadyState()
|
||||
player.play()
|
||||
skipItems(1) // skip play state
|
||||
// skip play state
|
||||
skipItems(1)
|
||||
player.pause()
|
||||
awaitItem().let {
|
||||
assertThat(it.isPlaying).isFalse()
|
||||
|
|
@ -206,9 +215,11 @@ class DefaultVoiceMessagePlayerTest {
|
|||
assertThat(player.prepare().isSuccess).isTrue()
|
||||
matchReadyState()
|
||||
player.play()
|
||||
skipItems(1) // skip play state
|
||||
// skip play state
|
||||
skipItems(1)
|
||||
player.pause()
|
||||
skipItems(1) // skip pause state
|
||||
// skip pause state
|
||||
skipItems(1)
|
||||
player.play()
|
||||
awaitItem().let {
|
||||
assertThat(it.isPlaying).isTrue()
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* Copyright 2023, 2024 New Vector Ltd.
|
||||
* Copyright (c) 2025 Element Creations Ltd.
|
||||
* Copyright 2023-2025 New Vector Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue