Browse Source

Merge branch 'develop' into langleyd/live_waveform

pull/1659/head
David Langley 11 months ago committed by GitHub
parent
commit
0745587f3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      features/messages/impl/build.gradle.kts
  2. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesNode.kt
  3. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPlayer.kt
  4. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePlayer.kt
  5. 2
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/MessagesPresenterTest.kt
  6. 2
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt
  7. 4
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt
  8. 2
      features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/timeline/VoiceMessagePresenterTest.kt
  9. 32
      libraries/mediaplayer/api/build.gradle.kts
  10. 78
      libraries/mediaplayer/api/src/main/kotlin/io/element/android/libraries/mediaplayer/api/MediaPlayer.kt
  11. 45
      libraries/mediaplayer/impl/build.gradle.kts
  12. 62
      libraries/mediaplayer/impl/src/main/kotlin/io/element/android/libraries/mediaplayer/impl/MediaPlayerImpl.kt
  13. 2
      libraries/mediaplayer/impl/src/main/kotlin/io/element/android/libraries/mediaplayer/impl/SimplePlayer.kt
  14. 27
      libraries/mediaplayer/impl/src/test/kotlin/io/element/android/libraries/mediaplayer/impl/MediaPlayerImplTest.kt
  15. 31
      libraries/mediaplayer/test/build.gradle.kts
  16. 4
      libraries/mediaplayer/test/src/main/kotlin/io/element/android/libraries/mediaplayer/test/FakeMediaPlayer.kt
  17. 2
      plugins/build.gradle.kts
  18. 1
      plugins/src/main/kotlin/extension/DependencyHandleScope.kt

2
features/messages/impl/build.gradle.kts

@ -52,6 +52,7 @@ dependencies {
implementation(projects.libraries.permissions.api) implementation(projects.libraries.permissions.api)
implementation(projects.libraries.preferences.api) implementation(projects.libraries.preferences.api)
implementation(projects.libraries.voicerecorder.api) implementation(projects.libraries.voicerecorder.api)
implementation(projects.libraries.mediaplayer.api)
implementation(projects.libraries.uiUtils) implementation(projects.libraries.uiUtils)
implementation(projects.features.networkmonitor.api) implementation(projects.features.networkmonitor.api)
implementation(projects.services.analytics.api) implementation(projects.services.analytics.api)
@ -83,6 +84,7 @@ dependencies {
testImplementation(projects.libraries.preferences.test) testImplementation(projects.libraries.preferences.test)
testImplementation(projects.libraries.textcomposer.test) testImplementation(projects.libraries.textcomposer.test)
testImplementation(projects.libraries.voicerecorder.test) testImplementation(projects.libraries.voicerecorder.test)
testImplementation(projects.libraries.mediaplayer.test)
testImplementation(libs.test.mockk) testImplementation(libs.test.mockk)
ksp(libs.showkase.processor) ksp(libs.showkase.processor)

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

@ -31,7 +31,7 @@ import io.element.android.features.messages.impl.attachments.Attachment
import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.LocalTimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories import io.element.android.features.messages.impl.timeline.di.TimelineItemPresenterFactories
import io.element.android.features.messages.impl.timeline.model.TimelineItem import io.element.android.features.messages.impl.timeline.model.TimelineItem
import io.element.android.features.messages.impl.mediaplayer.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.core.RoomId import io.element.android.libraries.matrix.api.core.RoomId

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/composer/VoiceMessageComposerPlayer.kt

@ -16,7 +16,7 @@
package io.element.android.features.messages.impl.voicemessages.composer package io.element.android.features.messages.impl.voicemessages.composer
import io.element.android.features.messages.impl.mediaplayer.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/voicemessages/timeline/VoiceMessagePlayer.kt

@ -17,7 +17,7 @@
package io.element.android.features.messages.impl.voicemessages.timeline package io.element.android.features.messages.impl.voicemessages.timeline
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.messages.impl.mediaplayer.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource

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

@ -43,7 +43,7 @@ import io.element.android.features.messages.impl.timeline.model.event.TimelineIt
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPresenter import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPresenter
import io.element.android.features.messages.media.FakeLocalMediaFactory import io.element.android.features.messages.media.FakeLocalMediaFactory
import io.element.android.features.messages.mediaplayer.FakeMediaPlayer import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.features.messages.textcomposer.TestRichTextEditorStateFactory import io.element.android.features.messages.textcomposer.TestRichTextEditorStateFactory
import io.element.android.features.messages.timeline.components.customreaction.FakeEmojibaseProvider import io.element.android.features.messages.timeline.components.customreaction.FakeEmojibaseProvider
import io.element.android.features.messages.utils.messagesummary.FakeMessageSummaryFormatter import io.element.android.features.messages.utils.messagesummary.FakeMessageSummaryFormatter

2
features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/composer/VoiceMessageComposerPresenterTest.kt

@ -30,7 +30,7 @@ import io.element.android.features.messages.impl.voicemessages.composer.VoiceMes
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerState
import io.element.android.features.messages.impl.voicemessages.VoiceMessageException import io.element.android.features.messages.impl.voicemessages.VoiceMessageException
import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer import io.element.android.features.messages.impl.voicemessages.composer.VoiceMessageComposerPlayer
import io.element.android.features.messages.mediaplayer.FakeMediaPlayer import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.libraries.matrix.test.room.FakeMatrixRoom import io.element.android.libraries.matrix.test.room.FakeMatrixRoom
import io.element.android.libraries.mediaupload.api.MediaSender import io.element.android.libraries.mediaupload.api.MediaSender
import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor import io.element.android.libraries.mediaupload.test.FakeMediaPreProcessor

4
features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/timeline/DefaultVoiceMessagePlayerTest.kt

@ -18,10 +18,10 @@ package io.element.android.features.messages.voicemessages.timeline
import app.cash.turbine.test import app.cash.turbine.test
import com.google.common.truth.Truth import com.google.common.truth.Truth
import io.element.android.features.messages.impl.mediaplayer.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
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.VoiceMessageMediaRepo import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMessageMediaRepo
import io.element.android.features.messages.mediaplayer.FakeMediaPlayer import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.matrix.api.core.EventId
import io.element.android.libraries.matrix.api.media.MediaSource import io.element.android.libraries.matrix.api.media.MediaSource
import io.element.android.libraries.matrix.test.AN_EVENT_ID import io.element.android.libraries.matrix.test.AN_EVENT_ID

2
features/messages/impl/src/test/kotlin/io/element/android/features/messages/voicemessages/timeline/VoiceMessagePresenterTest.kt

@ -27,7 +27,7 @@ import io.element.android.features.messages.impl.voicemessages.timeline.VoiceMes
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.features.messages.mediaplayer.FakeMediaPlayer import io.element.android.libraries.mediaplayer.test.FakeMediaPlayer
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Test import org.junit.Test

32
libraries/mediaplayer/api/build.gradle.kts

@ -0,0 +1,32 @@
/*
* 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.
*/
plugins {
id("io.element.android-library")
alias(libs.plugins.anvil)
}
android {
namespace = "io.element.android.libraries.mediaplayer.api"
}
anvil {
generateDaggerFactories.set(true)
}
dependencies {
implementation(projects.libraries.matrix.api)
implementation(libs.coroutines.core)
}

78
libraries/mediaplayer/api/src/main/kotlin/io/element/android/libraries/mediaplayer/api/MediaPlayer.kt

@ -0,0 +1,78 @@
/*
* 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.libraries.mediaplayer.api
import io.element.android.libraries.matrix.api.core.EventId
import kotlinx.coroutines.flow.StateFlow
/**
* A media player for Element X.
*/
interface MediaPlayer : AutoCloseable {
/**
* The current state of the player.
*/
val state: StateFlow<State>
/**
* Acquires control of the player and starts playing the given media.
*/
fun acquireControlAndPlay(
uri: String,
mediaId: String,
mimeType: String,
)
/**
* Plays the current media.
*/
fun play()
/**
* Pauses the current media.
*/
fun pause()
/**
* Seeks the current media to the given position.
*/
fun seekTo(positionMs: Long)
/**
* Releases any resources associated with this player.
*/
override fun close()
data class State(
/**
* Whether the player is currently playing.
*/
val isPlaying: Boolean,
/**
* The id of the media which is currently playing.
*
* NB: This is usually the string representation of the [EventId] of the event
* which contains the media.
*/
val mediaId: String?,
/**
* The current position of the player.
*/
val currentPosition: Long,
)
}

45
libraries/mediaplayer/impl/build.gradle.kts

@ -0,0 +1,45 @@
/*
* 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.
*/
plugins {
id("io.element.android-library")
alias(libs.plugins.anvil)
}
android {
namespace = "io.element.android.libraries.mediaplayer.impl"
}
anvil {
generateDaggerFactories.set(true)
}
dependencies {
api(projects.libraries.mediaplayer.api)
implementation(libs.androidx.media3.exoplayer)
implementation(libs.dagger)
implementation(projects.libraries.di)
implementation(libs.coroutines.core)
testImplementation(projects.tests.testutils)
testImplementation(libs.test.junit)
testImplementation(libs.test.truth)
testImplementation(libs.test.mockk)
testImplementation(libs.test.turbine)
testImplementation(libs.coroutines.core)
testImplementation(libs.coroutines.test)
}

62
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mediaplayer/MediaPlayer.kt → libraries/mediaplayer/impl/src/main/kotlin/io/element/android/libraries/mediaplayer/impl/MediaPlayerImpl.kt

@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.impl.mediaplayer package io.element.android.libraries.mediaplayer.impl
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem
import androidx.media3.common.Player import androidx.media3.common.Player
import com.squareup.anvil.annotations.ContributesBinding import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.libraries.di.RoomScope import io.element.android.libraries.di.RoomScope
import io.element.android.libraries.di.SingleIn import io.element.android.libraries.di.SingleIn
import io.element.android.libraries.matrix.api.core.EventId import io.element.android.libraries.mediaplayer.api.MediaPlayer
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -33,64 +33,6 @@ import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import javax.inject.Inject import javax.inject.Inject
/**
* A media player for Element X.
*/
interface MediaPlayer : AutoCloseable {
/**
* The current state of the player.
*/
val state: StateFlow<State>
/**
* Acquires control of the player and starts playing the given media.
*/
fun acquireControlAndPlay(
uri: String,
mediaId: String,
mimeType: String,
)
/**
* Plays the current media.
*/
fun play()
/**
* Pauses the current media.
*/
fun pause()
/**
* Seeks the current media to the given position.
*/
fun seekTo(positionMs: Long)
/**
* Releases any resources associated with this player.
*/
override fun close()
data class State(
/**
* Whether the player is currently playing.
*/
val isPlaying: Boolean,
/**
* The id of the media which is currently playing.
*
* NB: This is usually the string representation of the [EventId] of the event
* which contains the media.
*/
val mediaId: String?,
/**
* The current position of the player.
*/
val currentPosition: Long,
)
}
/** /**
* Default implementation of [MediaPlayer] backed by a [SimplePlayer]. * Default implementation of [MediaPlayer] backed by a [SimplePlayer].
*/ */

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/mediaplayer/SimplePlayer.kt → libraries/mediaplayer/impl/src/main/kotlin/io/element/android/libraries/mediaplayer/impl/SimplePlayer.kt

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.impl.mediaplayer package io.element.android.libraries.mediaplayer.impl
import android.content.Context import android.content.Context
import androidx.media3.common.MediaItem import androidx.media3.common.MediaItem

27
libraries/mediaplayer/impl/src/test/kotlin/io/element/android/libraries/mediaplayer/impl/MediaPlayerImplTest.kt

@ -0,0 +1,27 @@
/*
* 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.libraries.mediaplayer.impl
import kotlinx.coroutines.test.runTest
import org.junit.Test
class MediaPlayerImplTest {
@Test
fun `default test`() = runTest {
// TODO
}
}

31
libraries/mediaplayer/test/build.gradle.kts

@ -0,0 +1,31 @@
/*
* 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.
*/
plugins {
id("io.element.android-library")
}
android {
namespace = "io.element.android.libraries.mediaplayer.test"
}
dependencies {
api(projects.libraries.mediaplayer.api)
implementation(projects.tests.testutils)
implementation(libs.coroutines.test)
implementation(libs.test.truth)
}

4
features/messages/impl/src/test/kotlin/io/element/android/features/messages/mediaplayer/FakeMediaPlayer.kt → libraries/mediaplayer/test/src/main/kotlin/io/element/android/libraries/mediaplayer/test/FakeMediaPlayer.kt

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
package io.element.android.features.messages.mediaplayer package io.element.android.libraries.mediaplayer.test
import io.element.android.features.messages.impl.mediaplayer.MediaPlayer import io.element.android.libraries.mediaplayer.api.MediaPlayer
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.flow.asStateFlow

2
plugins/build.gradle.kts

@ -28,6 +28,6 @@ dependencies {
implementation(libs.kotlin.gradle.plugin) implementation(libs.kotlin.gradle.plugin)
implementation(platform(libs.google.firebase.bom)) implementation(platform(libs.google.firebase.bom))
// FIXME: using the bom ^, it should not be necessary to provide the version v... // FIXME: using the bom ^, it should not be necessary to provide the version v...
implementation("com.google.firebase:firebase-appdistribution-gradle:4.0.0") implementation("com.google.firebase:firebase-appdistribution-gradle:4.0.1")
implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location)) implementation(files(libs.javaClass.superclass.protectionDomain.codeSource.location))
} }

1
plugins/src/main/kotlin/extension/DependencyHandleScope.kt

@ -103,6 +103,7 @@ fun DependencyHandlerScope.allLibrariesImpl() {
implementation(project(":libraries:textcomposer:impl")) implementation(project(":libraries:textcomposer:impl"))
implementation(project(":libraries:cryptography:impl")) implementation(project(":libraries:cryptography:impl"))
implementation(project(":libraries:voicerecorder:impl")) implementation(project(":libraries:voicerecorder:impl"))
implementation(project(":libraries:mediaplayer:impl"))
} }
fun DependencyHandlerScope.allServicesImpl() { fun DependencyHandlerScope.allServicesImpl() {

Loading…
Cancel
Save