Improving the Stability of VideoView

pull/623/head
Vitor Pamplona 2023-09-25 17:09:36 -04:00
rodzic af9b0b444c
commit b1edf4e934
2 zmienionych plików z 52 dodań i 38 usunięć

Wyświetl plik

@ -1,5 +1,6 @@
package com.vitorpamplona.amethyst.ui.components package com.vitorpamplona.amethyst.ui.components
import android.content.Context
import android.graphics.Rect import android.graphics.Rect
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
@ -206,34 +207,36 @@ fun VideoViewInner(
) )
} }
val mediaItem = remember(videoUri) {
MediaItem.Builder()
.setMediaId(videoUri)
.setUri(videoUri)
.setMediaMetadata(
MediaMetadata.Builder()
.setArtist(authorName?.ifBlank { null })
.setTitle(title?.ifBlank { null } ?: videoUri)
.setArtworkUri(
try {
if (artworkUri != null) {
Uri.parse(artworkUri)
} else {
null
}
} catch (e: Exception) {
null
}
)
.build()
)
.build()
}
if (!automaticallyStartPlayback.value) { if (!automaticallyStartPlayback.value) {
ImageUrlWithDownloadButton(url = videoUri, showImage = automaticallyStartPlayback) ImageUrlWithDownloadButton(url = videoUri, showImage = automaticallyStartPlayback)
} else { } else {
VideoPlayerActiveMutex(videoUri) { activeOnScreen -> VideoPlayerActiveMutex(videoUri) { activeOnScreen ->
val mediaItem = remember(videoUri) {
mutableStateOf(
MediaItem.Builder()
.setMediaId(videoUri)
.setUri(videoUri)
.setMediaMetadata(
MediaMetadata.Builder()
.setArtist(authorName?.ifBlank { null })
.setTitle(title?.ifBlank { null } ?: videoUri)
.setArtworkUri(
try {
if (artworkUri != null) {
Uri.parse(artworkUri)
} else {
null
}
} catch (e: Exception) {
null
}
)
.build()
)
.build()
)
}
GetVideoController( GetVideoController(
mediaItem = mediaItem, mediaItem = mediaItem,
videoUri = videoUri, videoUri = videoUri,
@ -258,7 +261,7 @@ fun VideoViewInner(
@Composable @Composable
@OptIn(UnstableApi::class) @OptIn(UnstableApi::class)
fun GetVideoController( fun GetVideoController(
mediaItem: MediaItem, mediaItem: MutableState<MediaItem>,
videoUri: String, videoUri: String,
defaultToStart: Boolean = false, defaultToStart: Boolean = false,
nostrUriCallback: String? = null, nostrUriCallback: String? = null,
@ -311,7 +314,7 @@ fun GetVideoController(
} }
} }
controller.value?.setMediaItem(mediaItem) controller.value?.setMediaItem(mediaItem.value)
controller.value?.prepare() controller.value?.prepare()
} else if (controller.value != it) { } else if (controller.value != it) {
// discards the new controller because there is an existing one // discards the new controller because there is an existing one
@ -329,7 +332,7 @@ fun GetVideoController(
it.volume = if (defaultToStart) 0f else 1f it.volume = if (defaultToStart) 0f else 1f
} }
it.setMediaItem(mediaItem) it.setMediaItem(mediaItem.value)
it.prepare() it.prepare()
} }
} }
@ -347,7 +350,7 @@ fun GetVideoController(
it.volume = if (defaultToStart) 0f else 1f it.volume = if (defaultToStart) 0f else 1f
} }
it.setMediaItem(mediaItem) it.setMediaItem(mediaItem.value)
it.prepare() it.prepare()
} }
} }
@ -394,7 +397,7 @@ fun GetVideoController(
} }
} }
controller.value?.setMediaItem(mediaItem) controller.value?.setMediaItem(mediaItem.value)
controller.value?.prepare() controller.value?.prepare()
} else if (controller.value != it) { } else if (controller.value != it) {
// discards the new controller because there is an existing one // discards the new controller because there is an existing one
@ -460,7 +463,7 @@ fun VideoPlayerActiveMutex(videoUri: String, inner: @Composable (MutableState<Bo
} }
} }
Box( val myModifier = remember(videoUri) {
Modifier Modifier
.fillMaxWidth() .fillMaxWidth()
.defaultMinSize(minHeight = 70.dp) .defaultMinSize(minHeight = 70.dp)
@ -489,7 +492,9 @@ fun VideoPlayerActiveMutex(videoUri: String, inner: @Composable (MutableState<Bo
} }
} }
} }
) { }
Box(modifier = myModifier) {
inner(active) inner(active)
} }
} }
@ -511,8 +516,6 @@ private fun RenderVideoPlayer(
activeOnScreen: MutableState<Boolean>, activeOnScreen: MutableState<Boolean>,
onDialog: ((Boolean) -> Unit)? onDialog: ((Boolean) -> Unit)?
) { ) {
val context = LocalContext.current
ControlWhenPlayerIsActive(controller, keepPlaying, automaticallyStartPlayback, activeOnScreen) ControlWhenPlayerIsActive(controller, keepPlaying, automaticallyStartPlayback, activeOnScreen)
val controllerVisible = remember(controller) { val controllerVisible = remember(controller) {
@ -520,9 +523,11 @@ private fun RenderVideoPlayer(
} }
BoxWithConstraints() { BoxWithConstraints() {
AndroidView( val borders = MaterialTheme.colors.imageModifier
modifier = if (roundedCorner) {
MaterialTheme.colors.imageModifier val myModifier = remember {
if (roundedCorner) {
borders
.defaultMinSize(minHeight = 100.dp) .defaultMinSize(minHeight = 100.dp)
.align(Alignment.Center) .align(Alignment.Center)
} else { } else {
@ -530,8 +535,11 @@ private fun RenderVideoPlayer(
.fillMaxWidth() .fillMaxWidth()
.defaultMinSize(minHeight = 100.dp) .defaultMinSize(minHeight = 100.dp)
.align(Alignment.Center) .align(Alignment.Center)
}, }
factory = { }
val factory = remember(controller) {
{ context: Context ->
PlayerView(context).apply { PlayerView(context).apply {
player = controller player = controller
layoutParams = FrameLayout.LayoutParams( layoutParams = FrameLayout.LayoutParams(
@ -556,6 +564,11 @@ private fun RenderVideoPlayer(
) )
} }
} }
}
AndroidView(
modifier = myModifier,
factory = factory
) )
waveform?.let { waveform?.let {

Wyświetl plik

@ -63,6 +63,7 @@ class NostrChatroomFeedViewModel(val user: ChatroomKey, val account: Account) :
} }
} }
@Stable
class NostrVideoFeedViewModel(val account: Account) : FeedViewModel(VideoFeedFilter(account)) { class NostrVideoFeedViewModel(val account: Account) : FeedViewModel(VideoFeedFilter(account)) {
class Factory(val account: Account) : ViewModelProvider.Factory { class Factory(val account: Account) : ViewModelProvider.Factory {
override fun <NostrVideoFeedViewModel : ViewModel> create(modelClass: Class<NostrVideoFeedViewModel>): NostrVideoFeedViewModel { override fun <NostrVideoFeedViewModel : ViewModel> create(modelClass: Class<NostrVideoFeedViewModel>): NostrVideoFeedViewModel {