fix(gallery): forward imeta visual fields through video player to gallery

When the user long-pressed a playing video and tapped "Add Media to
Gallery", the share-action overlay (RenderTopButtons.kt:302) hard-coded
blurhash/dim/hash to null and built an inline MediaUrlVideo without
those fields. Result: the published ProfileGalleryEntryEvent (kind 1163)
carried only the URL, alt, e, m, and client tags — no x/dim/blurhash/
thumbhash — even when the source kind:1 imeta carried them.
This commit is contained in:
davotoula
2026-05-09 15:51:51 +02:00
parent 3cbc4fcec6
commit fb7a30fd70
6 changed files with 45 additions and 4 deletions
@@ -70,6 +70,7 @@ fun VideoView(
alwaysShowVideo: Boolean = false,
thumbhash: String? = null,
isLiveStream: Boolean = false,
hash: String? = null,
) {
val borderModifier =
if (roundedCorner) {
@@ -80,7 +81,7 @@ fun VideoView(
Modifier
}
VideoView(videoUri, mimeType, title, thumb, borderModifier, contentScale, waveform, artworkUri, authorName, dimensions, blurhash, nostrUriCallback, onDialog, alwaysShowVideo, accountViewModel = accountViewModel, thumbhash = thumbhash, isLiveStream = isLiveStream)
VideoView(videoUri, mimeType, title, thumb, borderModifier, contentScale, waveform, artworkUri, authorName, dimensions, blurhash, nostrUriCallback, onDialog, alwaysShowVideo, accountViewModel = accountViewModel, thumbhash = thumbhash, isLiveStream = isLiveStream, hash = hash)
}
@Composable
@@ -103,6 +104,7 @@ fun VideoView(
isLiveStream: Boolean = false,
accountViewModel: AccountViewModel,
thumbhash: String? = null,
hash: String? = null,
) {
val initialAutoStart = if (alwaysShowVideo) true else accountViewModel.settings.startVideoPlayback()
// Reset the manual-show toggle when the video URI changes so a recycled feed slot
@@ -160,6 +162,10 @@ fun VideoView(
isLiveStream = isLiveStream,
onZoom = onDialog,
hasBlurhash = false,
blurhash = blurhash,
dim = dimensions,
hash = hash,
thumbhash = thumbhash,
accountViewModel = accountViewModel,
showControls = showControls,
)
@@ -207,6 +213,10 @@ fun VideoView(
isLiveStream = isLiveStream,
onZoom = onDialog,
hasBlurhash = true,
blurhash = blurhash,
dim = dimensions,
hash = hash,
thumbhash = thumbhash,
accountViewModel = accountViewModel,
showControls = showControls,
)
@@ -31,6 +31,7 @@ import com.vitorpamplona.amethyst.service.playback.composable.controls.VideoQual
import com.vitorpamplona.amethyst.service.playback.composable.mainVideo.VideoPlayerActiveMutex
import com.vitorpamplona.amethyst.service.playback.composable.mediaitem.GetMediaItem
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
val DEFAULT_MUTED_SETTING = mutableStateOf(true)
@@ -54,6 +55,10 @@ fun VideoViewInner(
onZoom: (() -> Unit)? = null,
hasBlurhash: Boolean = false,
isFullscreen: Boolean = false,
blurhash: String? = null,
dim: DimensionTag? = null,
hash: String? = null,
thumbhash: String? = null,
accountViewModel: AccountViewModel,
) {
// keeps a copy of the value to avoid recompositions here when the DEFAULT value changes
@@ -76,6 +81,10 @@ fun VideoViewInner(
keepPlaying = true,
waveformData = waveform,
isLiveStream = isLiveStream,
blurhash = blurhash,
dim = dim,
hash = hash,
thumbhash = thumbhash,
) { mediaItem ->
GetVideoController(
mediaItem = mediaItem,
@@ -303,9 +303,9 @@ fun RenderTopButtons(
popupExpanded = shareDialogVisible,
videoUri = mediaData.videoUri,
postNostrUri = mediaData.callbackUri,
blurhash = null,
dim = null,
hash = null,
blurhash = mediaData.blurhash,
dim = mediaData.dim,
hash = mediaData.hash,
mimeType = mediaData.mimeType,
onDismiss = { shareDialogVisible.value = false },
content =
@@ -316,6 +316,10 @@ fun RenderTopButtons(
authorName = mediaData.authorName,
description = mediaData.title,
uri = mediaData.callbackUri,
blurhash = mediaData.blurhash,
dim = mediaData.dim,
hash = mediaData.hash,
thumbhash = mediaData.thumbhash,
),
accountViewModel = accountViewModel,
)
@@ -25,6 +25,7 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import com.vitorpamplona.amethyst.commons.compose.produceCachedState
import com.vitorpamplona.amethyst.service.playback.composable.WaveformData
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
val mediaItemCache = MediaItemCache()
@@ -41,6 +42,10 @@ fun GetMediaItem(
keepPlaying: Boolean = false,
waveformData: WaveformData? = null,
isLiveStream: Boolean = false,
blurhash: String? = null,
dim: DimensionTag? = null,
hash: String? = null,
thumbhash: String? = null,
inner: @Composable (LoadedMediaItem) -> Unit,
) {
val data =
@@ -57,6 +62,10 @@ fun GetMediaItem(
keepPlaying = keepPlaying,
waveformData = waveformData,
isLiveStream = isLiveStream,
blurhash = blurhash,
dim = dim,
hash = hash,
thumbhash = thumbhash,
)
}
@@ -23,6 +23,7 @@ package com.vitorpamplona.amethyst.service.playback.composable.mediaitem
import androidx.compose.runtime.Immutable
import androidx.media3.common.MediaItem
import com.vitorpamplona.amethyst.service.playback.composable.WaveformData
import com.vitorpamplona.quartz.nip94FileMetadata.tags.DimensionTag
@Immutable
data class MediaItemData(
@@ -40,6 +41,13 @@ data class MediaItemData(
// (e.g. multi-rendition NIP-71 videos) must leave this false so that
// ExoPlayer's SimpleCache can cache their immutable segments.
val isLiveStream: Boolean = false,
// Source-imeta visual fields — carried through so the player's "Add to Gallery" /
// "Share" actions can publish a richer ProfileGalleryEntryEvent. Optional; null when
// the surface that constructed this MediaItemData didn't have them.
val blurhash: String? = null,
val dim: DimensionTag? = null,
val hash: String? = null,
val thumbhash: String? = null,
)
@Immutable
@@ -226,6 +226,7 @@ fun ZoomableContentView(
accountViewModel = accountViewModel,
thumbhash = content.thumbhash,
isLiveStream = content.isLiveStream,
hash = content.hash,
)
}
}