fix(video): show blurhash instead of fake waveform while loading

VideoView already renders the blurhash underneath VideoViewInner, but the
player still showed FakeWaveformAnimation over it during loading. Two issues
combined: Tracks.isAudio() returned true for an empty track list (the state
before the player has resolved any tracks), and AudioPlayingAnimation had no
way to know the media was a video. If a blurhash is available we know this is
a video, so propagate that hint down and skip the audio waveform entirely.
Also guard isAudio() so an empty track list is no longer treated as audio.
This commit is contained in:
Claude
2026-04-18 03:06:19 +00:00
parent 898dca26af
commit 905c8eb8a7
5 changed files with 12 additions and 1 deletions
@@ -87,6 +87,7 @@ fun RenderVideoPlayer(
videoModifier: Modifier,
onDialog: (() -> Unit)? = null,
controllerVisible: MutableState<Boolean> = remember { mutableStateOf(false) },
hasBlurhash: Boolean = false,
accountViewModel: AccountViewModel,
) {
val containerSize = remember { mutableStateOf(IntSize.Zero) }
@@ -123,6 +124,7 @@ fun RenderVideoPlayer(
controllerState,
mediaItem.src.waveformData,
Modifier.fillMaxSize().align(Alignment.Center),
hasBlurhash = hasBlurhash,
)
if (showControls) {
@@ -137,6 +137,7 @@ fun VideoView(
nostrUriCallback = nostrUriCallback,
automaticallyStartPlayback = automaticallyStartPlayback.value,
onZoom = onDialog,
hasBlurhash = false,
accountViewModel = accountViewModel,
showControls = showControls,
)
@@ -183,6 +184,7 @@ fun VideoView(
nostrUriCallback = nostrUriCallback,
automaticallyStartPlayback = automaticallyStartPlayback.value,
onZoom = onDialog,
hasBlurhash = true,
accountViewModel = accountViewModel,
showControls = showControls,
)
@@ -49,6 +49,7 @@ fun VideoViewInner(
automaticallyStartPlayback: Boolean,
controllerVisible: MutableState<Boolean> = mutableStateOf(false),
onZoom: (() -> Unit)? = null,
hasBlurhash: Boolean = false,
accountViewModel: AccountViewModel,
) {
// keeps a copy of the value to avoid recompositions here when the DEFAULT value changes
@@ -82,6 +83,7 @@ fun VideoViewInner(
videoModifier = videoModifier,
controllerVisible = controllerVisible,
onDialog = onZoom,
hasBlurhash = hasBlurhash,
accountViewModel = accountViewModel,
)
}
@@ -33,14 +33,17 @@ import androidx.media3.common.Tracks
import com.vitorpamplona.amethyst.service.playback.composable.MediaControllerState
import com.vitorpamplona.amethyst.service.playback.composable.WaveformData
fun Tracks.isAudio() = groups.none { it.type == C.TRACK_TYPE_VIDEO }
fun Tracks.isAudio() = groups.isNotEmpty() && groups.none { it.type == C.TRACK_TYPE_VIDEO }
@Composable
fun AudioPlayingAnimation(
controllerState: MediaControllerState,
waveform: WaveformData?,
modifier: Modifier = Modifier,
hasBlurhash: Boolean = false,
) {
if (hasBlurhash) return
var isAudio by remember { mutableStateOf(controllerState.controller.currentTracks.isAudio()) }
DisposableEffect(controllerState.controller) {
@@ -568,6 +568,7 @@ private fun RenderImageOrVideo(
nostrUriCallback = content.uri,
automaticallyStartPlayback = true,
controllerVisible = controllerVisible,
hasBlurhash = content.blurhash != null,
accountViewModel = accountViewModel,
)
}
@@ -626,6 +627,7 @@ private fun RenderImageOrVideo(
nostrUriCallback = content.uri,
automaticallyStartPlayback = true,
controllerVisible = controllerVisible,
hasBlurhash = content.blurhash != null,
accountViewModel = accountViewModel,
)
}