Improving the Stability of VideoView
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user