From 9fe08f6c458559d0b91bcfb6739c5ea14d7df963 Mon Sep 17 00:00:00 2001 From: Believethehype <1097224+believethehype@users.noreply.github.com> Date: Sun, 30 Jun 2024 22:29:11 +0200 Subject: [PATCH] allow videos in the gallery --- .../amethyst/ui/components/VideoView.kt | 25 +++++++---- .../ui/dal/UserProfileGalleryFeedFilter.kt | 22 ++++----- .../ui/screen/loggedIn/ProfileGallery.kt | 45 +++++++++++++------ .../vitorpamplona/amethyst/ui/theme/Shape.kt | 1 + .../vitorpamplona/amethyst/ui/theme/Theme.kt | 30 +++++++++++++ 5 files changed, 92 insertions(+), 31 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index 239d88b0d..41e6fe1cb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -109,15 +109,13 @@ import com.vitorpamplona.amethyst.ui.note.MutedIcon import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.amethyst.ui.theme.PinBottomIconSize -import com.vitorpamplona.amethyst.ui.theme.Size110dp -import com.vitorpamplona.amethyst.ui.theme.Size165dp import com.vitorpamplona.amethyst.ui.theme.Size20Modifier import com.vitorpamplona.amethyst.ui.theme.Size22Modifier import com.vitorpamplona.amethyst.ui.theme.Size50Modifier -import com.vitorpamplona.amethyst.ui.theme.Size55dp import com.vitorpamplona.amethyst.ui.theme.Size75dp import com.vitorpamplona.amethyst.ui.theme.VolumeBottomIconSize import com.vitorpamplona.amethyst.ui.theme.imageModifier +import com.vitorpamplona.amethyst.ui.theme.videoGalleryModifier import kotlinx.collections.immutable.ImmutableList import kotlinx.coroutines.CancellationException import kotlinx.coroutines.Dispatchers @@ -204,6 +202,7 @@ fun VideoView( title: String? = null, thumb: VideoThumb? = null, roundedCorner: Boolean, + gallery: Boolean = false, isFiniteHeight: Boolean, waveform: ImmutableList? = null, artworkUri: String? = null, @@ -247,6 +246,7 @@ fun VideoView( title = title, thumb = thumb, roundedCorner = roundedCorner, + gallery = gallery, isFiniteHeight = isFiniteHeight, waveform = waveform, artworkUri = artworkUri, @@ -324,6 +324,7 @@ fun VideoViewInner( title: String? = null, thumb: VideoThumb? = null, roundedCorner: Boolean, + gallery: Boolean = false, isFiniteHeight: Boolean, waveform: ImmutableList? = null, artworkUri: String? = null, @@ -348,6 +349,7 @@ fun VideoViewInner( controller = controller, thumbData = thumb, roundedCorner = roundedCorner, + gallery = gallery, isFiniteHeight = isFiniteHeight, nostrUriCallback = nostrUriCallback, waveform = waveform, @@ -695,6 +697,7 @@ private fun RenderVideoPlayer( controller: MediaController, thumbData: VideoThumb?, roundedCorner: Boolean, + gallery: Boolean = false, isFiniteHeight: Boolean, nostrUriCallback: String?, waveform: ImmutableList? = null, @@ -712,13 +715,18 @@ private fun RenderVideoPlayer( Box { val borders = MaterialTheme.colorScheme.imageModifier - + val bordersSquare = MaterialTheme.colorScheme.videoGalleryModifier val myModifier = remember(controller) { if (roundedCorner) { modifier.then( borders.defaultMinSize(minHeight = 75.dp).align(Alignment.Center), ) + } else if (gallery) { + Modifier + modifier.then( + bordersSquare.defaultMinSize(minHeight = 75.dp).align(Alignment.Center), + ) } else { modifier.fillMaxWidth().defaultMinSize(minHeight = 75.dp).align(Alignment.Center) } @@ -737,6 +745,7 @@ private fun RenderVideoPlayer( setBackgroundColor(Color.Transparent.toArgb()) setShutterBackgroundColor(Color.Transparent.toArgb()) controllerAutoShow = false + useController = !gallery thumbData?.thumb?.let { defaultArtwork = it } hideController() resizeMode = @@ -745,7 +754,7 @@ private fun RenderVideoPlayer( } else { AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH } - onDialog?.let { innerOnDialog -> + /*onDialog?.let { innerOnDialog -> setFullscreenButtonClickListener { controller.pause() innerOnDialog(it) @@ -756,11 +765,11 @@ private fun RenderVideoPlayer( controllerVisible.value = visible == View.VISIBLE onControllerVisibilityChanged?.let { callback -> callback(visible == View.VISIBLE) } }, - ) + ) */ } }, ) - +/* waveform?.let { Waveform(it, controller, remember { Modifier.align(Alignment.Center) }) } val startingMuteState = remember(controller) { controller.volume < 0.001 } @@ -811,7 +820,7 @@ private fun RenderVideoPlayer( AnimatedShareButton(controllerVisible, Modifier.align(Alignment.TopEnd).padding(end = Size165dp)) { popupExpanded, toggle -> ShareImageAction(accountViewModel = accountViewModel, popupExpanded, videoUri, nostrUriCallback, toggle) - } + } */ } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileGalleryFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileGalleryFeedFilter.kt index 59faa9376..8d726b89c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileGalleryFeedFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileGalleryFeedFilter.kt @@ -34,19 +34,21 @@ class UserProfileGalleryFeedFilter(val user: User, val account: Account) : FeedF val notes = user.latestGalleryList ?.taggedGalleryEntries() - ?.map { Pair(LocalCache.getOrCreateNote(it.id), it.url) } + ?.map { + Pair( + // ( + // if (ATag.isATag(it.id)) { + // ATag.parse(it.id, null)?.let { it1 -> LocalCache.getOrCreateAddressableNote(it1) } + // } else { + LocalCache.getOrCreateNote(it.id), + // } + // )!! + it.url, + ) + } ?.toSet() ?: emptySet() - /*val addresses = - user.latestGalleryList - ?.taggedAddresses() - ?.map { LocalCache.getOrCreateAddressableNote(it) } - ?.toSet() - ?: emptySet() */ - - // .sortedWith(DefaultFeedOrder) - var finalnotes = setOf() for (pair in notes) { pair.first.headerImage = pair.second diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileGallery.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileGallery.kt index 606916fb7..0bde747d0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileGallery.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileGallery.kt @@ -56,6 +56,7 @@ import coil.compose.AsyncImage import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.components.SensitivityWarning +import com.vitorpamplona.amethyst.ui.components.VideoView import com.vitorpamplona.amethyst.ui.note.CheckHiddenFeedWatchBlockAndReport import com.vitorpamplona.amethyst.ui.note.ClickableNote import com.vitorpamplona.amethyst.ui.note.LongPressToQuickActionGallery @@ -301,12 +302,12 @@ fun RenderGalleryThumb( ), ) - InnerRenderGalleryThumb(card as GalleryThumb, baseNote) + InnerRenderGalleryThumb(card as GalleryThumb, baseNote, accountViewModel) } @Preview @Composable -fun RenderGalleryThumbPreview() { +fun RenderGalleryThumbPreview(accountViewModel: AccountViewModel) { Surface(Modifier.size(200.dp)) { InnerRenderGalleryThumb( card = @@ -317,6 +318,7 @@ fun RenderGalleryThumbPreview() { // price = Price("800000", "SATS", null), ), note = Note("hex"), + accountViewModel = accountViewModel, ) } } @@ -325,6 +327,7 @@ fun RenderGalleryThumbPreview() { fun InnerRenderGalleryThumb( card: GalleryThumb, note: Note, + accountViewModel: AccountViewModel, ) { Box( Modifier @@ -333,15 +336,31 @@ fun InnerRenderGalleryThumb( contentAlignment = BottomStart, ) { card.image?.let { - AsyncImage( - model = it, - contentDescription = null, - contentScale = ContentScale.Crop, - modifier = Modifier.fillMaxSize(), - ) - } ?: run { DisplayGalleryAuthorBanner(note) } - - // TODO what if video? + if (it.endsWith("mp4") || it.endsWith("mov") || it.endsWith("mpeg")) { + // TODO how to long press? + VideoView( + videoUri = it, + mimeType = null, + title = "", + dimensions = "1x1", + authorName = note.author?.toBestDisplayName(), + roundedCorner = false, + gallery = true, + isFiniteHeight = false, + alwaysShowVideo = true, + accountViewModel = accountViewModel, + ) + } else { + AsyncImage( + model = it, + contentDescription = null, + contentScale = ContentScale.Crop, + modifier = Modifier.fillMaxSize(), + ) + } + } + ?: run { DisplayGalleryAuthorBanner(note) } + } /* Row( Modifier @@ -382,8 +401,8 @@ fun InnerRenderGalleryThumb( color = Color.White, ) } - }*/ - } + } + }*/ } @Composable diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt index 2af199445..954c525c8 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Shape.kt @@ -56,6 +56,7 @@ val TabRowHeight = Modifier val SmallBorder = RoundedCornerShape(7.dp) val SmallishBorder = RoundedCornerShape(9.dp) val QuoteBorder = RoundedCornerShape(15.dp) + val ButtonBorder = RoundedCornerShape(20.dp) val EditFieldBorder = RoundedCornerShape(25.dp) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt index ef220986b..4fedca007 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/theme/Theme.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.ColorFilter +import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.compositeOver import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalView @@ -124,6 +125,18 @@ val LightImageModifier = .clip(shape = QuoteBorder) .border(1.dp, LightSubtleBorder, QuoteBorder) +val DarkVideoModifier = + Modifier + .fillMaxWidth() + .clip(shape = RectangleShape) + .border(1.dp, DarkSubtleBorder, RectangleShape) + +val LightVideoModifier = + Modifier + .fillMaxWidth() + .clip(shape = RectangleShape) + .border(1.dp, LightSubtleBorder, RectangleShape) + val DarkProfile35dpModifier = Modifier .size(Size35dp) @@ -148,6 +161,20 @@ val LightReplyBorderModifier = .clip(shape = QuoteBorder) .border(1.dp, LightSubtleBorder, QuoteBorder) +val DarkVideoBorderModifier = + Modifier + .padding(top = 5.dp) + .fillMaxWidth() + .clip(shape = RectangleShape) + .border(1.dp, DarkSubtleBorder, RectangleShape) + +val LightVideoBorderModifier = + Modifier + .padding(top = 2.dp, bottom = 0.dp, start = 0.dp, end = 0.dp) + .fillMaxWidth() + .clip(shape = RectangleShape) + .border(1.dp, LightSubtleBorder, RectangleShape) + val DarkInnerPostBorderModifier = Modifier .padding(vertical = 5.dp) @@ -356,6 +383,9 @@ val ColorScheme.markdownStyle: RichTextStyle val ColorScheme.imageModifier: Modifier get() = if (isLight) LightImageModifier else DarkImageModifier +val ColorScheme.videoGalleryModifier: Modifier + get() = if (isLight) LightVideoModifier else DarkVideoModifier + val ColorScheme.profile35dpModifier: Modifier get() = if (isLight) LightProfile35dpModifier else DarkProfile35dpModifier