Improves rendering performance of the ExoPlayer

This commit is contained in:
Vitor Pamplona
2023-05-31 22:09:18 -04:00
parent 93e2af3c1f
commit 91f34000f5
2 changed files with 38 additions and 21 deletions
@@ -43,6 +43,15 @@ import com.vitorpamplona.amethyst.service.nip19.Nip19
import com.vitorpamplona.amethyst.ui.note.NoteCompose import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.amethyst.ui.uriToRoute import com.vitorpamplona.amethyst.ui.uriToRoute
import kotlinx.collections.immutable.ImmutableList
import kotlinx.collections.immutable.ImmutableMap
import kotlinx.collections.immutable.ImmutableSet
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.persistentMapOf
import kotlinx.collections.immutable.persistentSetOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.collections.immutable.toImmutableMap
import kotlinx.collections.immutable.toImmutableSet
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.net.MalformedURLException import java.net.MalformedURLException
@@ -108,10 +117,10 @@ fun RichTextViewer(
@Stable @Stable
class RichTextViewerState( class RichTextViewerState(
val content: String, val content: String,
val urlSet: Set<String>, val urlSet: ImmutableSet<String>,
val imagesForPager: Map<String, ZoomableUrlContent>, val imagesForPager: ImmutableMap<String, ZoomableUrlContent>,
val imageList: List<ZoomableUrlContent>, val imageList: ImmutableList<ZoomableUrlContent>,
val customEmoji: Map<String, String> val customEmoji: ImmutableMap<String, String>
) )
@Composable @Composable
@@ -124,7 +133,15 @@ private fun RenderRegular(
nav: (String) -> Unit nav: (String) -> Unit
) { ) {
var state by remember(content) { var state by remember(content) {
mutableStateOf(RichTextViewerState(content, emptySet(), emptyMap(), emptyList(), emptyMap())) mutableStateOf(
RichTextViewerState(
content,
persistentSetOf(),
persistentMapOf(),
persistentListOf(),
persistentMapOf()
)
)
} }
LaunchedEffect(key1 = content) { LaunchedEffect(key1 = content) {
@@ -146,7 +163,13 @@ private fun RenderRegular(
val emojiMap = tags?.filter { it.size > 2 && it[0] == "emoji" }?.associate { ":${it[1]}:" to it[2] } ?: emptyMap() val emojiMap = tags?.filter { it.size > 2 && it[0] == "emoji" }?.associate { ":${it[1]}:" to it[2] } ?: emptyMap()
if (urlSet.isNotEmpty() || emojiMap.isNotEmpty()) { if (urlSet.isNotEmpty() || emojiMap.isNotEmpty()) {
state = RichTextViewerState(content, urlSet, imagesForPager, imageList, emojiMap) state = RichTextViewerState(
content,
urlSet.toImmutableSet(),
imagesForPager.toImmutableMap(),
imageList.toImmutableList(),
emojiMap.toImmutableMap()
)
} }
} }
} }
@@ -54,7 +54,6 @@ import coil.request.ImageRequest
import com.google.android.exoplayer2.C import com.google.android.exoplayer2.C
import com.google.android.exoplayer2.ExoPlayer import com.google.android.exoplayer2.ExoPlayer
import com.google.android.exoplayer2.MediaItem import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.MediaMetadata
import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.source.ProgressiveMediaSource import com.google.android.exoplayer2.source.ProgressiveMediaSource
import com.google.android.exoplayer2.ui.AspectRatioFrameLayout import com.google.android.exoplayer2.ui.AspectRatioFrameLayout
@@ -126,17 +125,17 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul
var exoPlayer by remember { mutableStateOf<ExoPlayer?>(null) } var exoPlayer by remember { mutableStateOf<ExoPlayer?>(null) }
LaunchedEffect(key1 = videoUri) { LaunchedEffect(key1 = videoUri) {
val mediaBuilder = MediaItem.Builder().setUri(videoUri) if (exoPlayer == null) {
launch(Dispatchers.Default) {
description?.let { exoPlayer = ExoPlayer.Builder(context).build()
mediaBuilder.setMediaMetadata( }
MediaMetadata.Builder().setDisplayTitle(it).build() }
)
} }
val media = mediaBuilder.build() exoPlayer?.let {
val media = remember { MediaItem.Builder().setUri(videoUri).build() }
exoPlayer = ExoPlayer.Builder(context).build().apply { it.apply {
repeatMode = Player.REPEAT_MODE_ALL repeatMode = Player.REPEAT_MODE_ALL
videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT videoScalingMode = C.VIDEO_SCALING_MODE_SCALE_TO_FIT
volume = if (mutedInstance.value) 0f else 1f volume = if (mutedInstance.value) 0f else 1f
@@ -151,9 +150,7 @@ fun VideoView(videoUri: Uri, description: String? = null, thumb: Drawable? = nul
} }
prepare() prepare()
} }
}
exoPlayer?.let {
RenderVideoPlayer(it, context, thumb, onDialog, mutedInstance) RenderVideoPlayer(it, context, thumb, onDialog, mutedInstance)
} }
@@ -232,14 +229,11 @@ fun Modifier.onVisibilityChanges(onVisibilityChanges: (Boolean) -> Unit): Modifi
val view = LocalView.current val view = LocalView.current
var isVisible: Boolean? by remember { mutableStateOf(null) } var isVisible: Boolean? by remember { mutableStateOf(null) }
LaunchedEffect(isVisible) {
onVisibilityChanges(isVisible == true)
}
onGloballyPositioned { coordinates -> onGloballyPositioned { coordinates ->
val newIsVisible = coordinates.isCompletelyVisible(view) val newIsVisible = coordinates.isCompletelyVisible(view)
if (isVisible != newIsVisible) { if (isVisible != newIsVisible) {
isVisible = newIsVisible isVisible = newIsVisible
onVisibilityChanges(isVisible == true)
} }
} }
} }