diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt index b832c01c7..e8103b524 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/VideoView.kt @@ -154,24 +154,26 @@ fun VideoView( authorName: String? = null, nostrUriCallback: String? = null, onDialog: ((Boolean) -> Unit)? = null, + onControllerVisibilityChanged: ((Boolean) -> Unit)? = null, accountViewModel: AccountViewModel, alwaysShowVideo: Boolean = false ) { val defaultToStart by remember(videoUri) { mutableStateOf(DefaultMutedSetting.value) } VideoViewInner( - videoUri, - defaultToStart, - title, - thumb, - roundedCorner, - waveform, - artworkUri, - authorName, - nostrUriCallback, - alwaysShowVideo, - accountViewModel, - onDialog + videoUri = videoUri, + defaultToStart = defaultToStart, + title = title, + thumb = thumb, + roundedCorner = roundedCorner, + waveform = waveform, + artworkUri = artworkUri, + authorName = authorName, + nostrUriCallback = nostrUriCallback, + alwaysShowVideo = alwaysShowVideo, + accountViewModel = accountViewModel, + onControllerVisibilityChanged = onControllerVisibilityChanged, + onDialog = onDialog ) } @@ -189,6 +191,7 @@ fun VideoViewInner( nostrUriCallback: String? = null, alwaysShowVideo: Boolean = false, accountViewModel: AccountViewModel, + onControllerVisibilityChanged: ((Boolean) -> Unit)? = null, onDialog: ((Boolean) -> Unit)? = null ) { val automaticallyStartPlayback = remember { @@ -247,6 +250,7 @@ fun VideoViewInner( keepPlaying = keepPlaying, automaticallyStartPlayback = automaticallyStartPlayback, activeOnScreen = activeOnScreen, + onControllerVisibilityChanged = onControllerVisibilityChanged, onDialog = onDialog ) } @@ -514,6 +518,7 @@ private fun RenderVideoPlayer( keepPlaying: MutableState, automaticallyStartPlayback: MutableState, activeOnScreen: MutableState, + onControllerVisibilityChanged: ((Boolean) -> Unit)? = null, onDialog: ((Boolean) -> Unit)? ) { ControlWhenPlayerIsActive(controller, keepPlaying, automaticallyStartPlayback, activeOnScreen) @@ -558,8 +563,11 @@ private fun RenderVideoPlayer( } } setControllerVisibilityListener( - PlayerView.ControllerVisibilityListener { - controllerVisible.value = it == View.VISIBLE + PlayerView.ControllerVisibilityListener { visible -> + controllerVisible.value = visible == View.VISIBLE + onControllerVisibilityChanged?.let { callback -> + callback(visible == View.VISIBLE) + } } ) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt index 52e1c0353..bf4d304bb 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt @@ -6,6 +6,9 @@ import android.content.ContextWrapper import android.os.Build import android.util.Log import android.view.Window +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.animation.fadeIn +import androidx.compose.animation.fadeOut import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.clickable import androidx.compose.foundation.combinedClickable @@ -636,48 +639,87 @@ fun ZoomableImageDialog( ) { Surface(modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background) { Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.TopCenter) { - val pagerState: PagerState = rememberPagerState() { allImages.size } + DialogContent(allImages, imageUrl, onDismiss, accountViewModel) + } + } + } +} - LaunchedEffect(key1 = pagerState, key2 = imageUrl) { - val page = allImages.indexOf(imageUrl) - if (page > -1) { - pagerState.scrollToPage(page) - } - } - - if (allImages.size > 1) { - SlidingCarousel( - pagerState = pagerState - ) { index -> - RenderImageOrVideo(allImages[index], false, accountViewModel) - } - } else { - RenderImageOrVideo(imageUrl, false, accountViewModel) - } - - Row( - modifier = Modifier - .padding(10.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically - ) { - CloseButton(onPress = onDismiss) - - val myContent = allImages[pagerState.currentPage] - if (myContent is ZoomableUrlContent) { - Row() { - CopyToClipboard(content = myContent) - Spacer(modifier = StdHorzSpacer) - SaveToGallery(url = myContent.url) - } - } else if (myContent is ZoomableLocalImage && myContent.localFile != null) { - SaveToGallery( - localFile = myContent.localFile, - mimeType = myContent.mimeType - ) - } +@Composable +@OptIn(ExperimentalFoundationApi::class) +private fun DialogContent( + allImages: ImmutableList, + imageUrl: ZoomableContent, + onDismiss: () -> Unit, + accountViewModel: AccountViewModel +) { + val pagerState: PagerState = rememberPagerState() { allImages.size } + val controllerVisible = remember { mutableStateOf(false) } + val holdOn = remember { mutableStateOf(true) } + + LaunchedEffect(key1 = pagerState, key2 = imageUrl) { + launch { + val page = allImages.indexOf(imageUrl) + if (page > -1) { + pagerState.scrollToPage(page) + } + } + launch(Dispatchers.Default) { + delay(2000) + holdOn.value = false + } + } + + if (allImages.size > 1) { + SlidingCarousel( + pagerState = pagerState + ) { index -> + RenderImageOrVideo( + content = allImages[index], + roundedCorner = false, + onControllerVisibilityChanged = { + controllerVisible.value = it + }, + accountViewModel = accountViewModel + ) + } + } else { + RenderImageOrVideo( + content = imageUrl, + roundedCorner = false, + onControllerVisibilityChanged = { + controllerVisible.value = it + }, + accountViewModel = accountViewModel + ) + } + + AnimatedVisibility( + visible = holdOn.value || controllerVisible.value, + enter = fadeIn(), + exit = fadeOut() + ) { + Row( + modifier = Modifier + .padding(10.dp) + .fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically + ) { + CloseButton(onPress = onDismiss) + + val myContent = allImages[pagerState.currentPage] + if (myContent is ZoomableUrlContent) { + Row() { + CopyToClipboard(content = myContent) + Spacer(modifier = StdHorzSpacer) + SaveToGallery(url = myContent.url) } + } else if (myContent is ZoomableLocalImage && myContent.localFile != null) { + SaveToGallery( + localFile = myContent.localFile, + mimeType = myContent.mimeType + ) } } } @@ -751,7 +793,12 @@ private fun ShareImageAction( } @Composable -private fun RenderImageOrVideo(content: ZoomableContent, roundedCorner: Boolean, accountViewModel: AccountViewModel) { +private fun RenderImageOrVideo( + content: ZoomableContent, + roundedCorner: Boolean, + onControllerVisibilityChanged: ((Boolean) -> Unit)? = null, + accountViewModel: AccountViewModel +) { val mainModifier = Modifier .fillMaxSize() .zoomable(rememberZoomState()) @@ -766,6 +813,7 @@ private fun RenderImageOrVideo(content: ZoomableContent, roundedCorner: Boolean, artworkUri = content.artworkUri, authorName = content.authorName, roundedCorner = roundedCorner, + onControllerVisibilityChanged = onControllerVisibilityChanged, accountViewModel = accountViewModel, alwaysShowVideo = true ) @@ -781,6 +829,7 @@ private fun RenderImageOrVideo(content: ZoomableContent, roundedCorner: Boolean, artworkUri = content.artworkUri, authorName = content.authorName, roundedCorner = roundedCorner, + onControllerVisibilityChanged = onControllerVisibilityChanged, accountViewModel = accountViewModel, alwaysShowVideo = true )