mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2025-09-26 09:16:35 +02:00
Basic refactoring to minimize the need for user-space params in the VideoView
This commit is contained in:
@@ -30,6 +30,7 @@ import android.util.Log
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.FrameLayout
|
import android.widget.FrameLayout
|
||||||
|
import android.widget.VideoView
|
||||||
import androidx.annotation.OptIn
|
import androidx.annotation.OptIn
|
||||||
import androidx.compose.animation.AnimatedVisibility
|
import androidx.compose.animation.AnimatedVisibility
|
||||||
import androidx.compose.animation.core.LinearEasing
|
import androidx.compose.animation.core.LinearEasing
|
||||||
@@ -40,9 +41,9 @@ import androidx.compose.foundation.background
|
|||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.Box
|
||||||
import androidx.compose.foundation.layout.Row
|
import androidx.compose.foundation.layout.Row
|
||||||
import androidx.compose.foundation.layout.aspectRatio
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
import androidx.compose.foundation.layout.defaultMinSize
|
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.heightIn
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.foundation.shape.CircleShape
|
import androidx.compose.foundation.shape.CircleShape
|
||||||
@@ -217,6 +218,37 @@ fun VideoView(
|
|||||||
onControllerVisibilityChanged: ((Boolean) -> Unit)? = null,
|
onControllerVisibilityChanged: ((Boolean) -> Unit)? = null,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
alwaysShowVideo: Boolean = false,
|
alwaysShowVideo: Boolean = false,
|
||||||
|
) {
|
||||||
|
val borderModifier =
|
||||||
|
if (roundedCorner) {
|
||||||
|
MaterialTheme.colorScheme.imageModifier
|
||||||
|
} else if (gallery) {
|
||||||
|
MaterialTheme.colorScheme.videoGalleryModifier
|
||||||
|
} else {
|
||||||
|
Modifier
|
||||||
|
}
|
||||||
|
|
||||||
|
VideoView(videoUri, mimeType, title, thumb, borderModifier, isFiniteHeight, waveform, artworkUri, authorName, dimensions, blurhash, nostrUriCallback, onDialog, onControllerVisibilityChanged, accountViewModel, alwaysShowVideo)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun VideoView(
|
||||||
|
videoUri: String,
|
||||||
|
mimeType: String?,
|
||||||
|
title: String? = null,
|
||||||
|
thumb: VideoThumb? = null,
|
||||||
|
borderModifier: Modifier,
|
||||||
|
isFiniteHeight: Boolean,
|
||||||
|
waveform: ImmutableList<Int>? = null,
|
||||||
|
artworkUri: String? = null,
|
||||||
|
authorName: String? = null,
|
||||||
|
dimensions: String? = null,
|
||||||
|
blurhash: String? = null,
|
||||||
|
nostrUriCallback: String? = null,
|
||||||
|
onDialog: ((Boolean) -> Unit)? = null,
|
||||||
|
onControllerVisibilityChanged: ((Boolean) -> Unit)? = null,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
alwaysShowVideo: Boolean = false,
|
||||||
) {
|
) {
|
||||||
val defaultToStart by remember(videoUri) { mutableStateOf(DEFAULT_MUTED_SETTING.value) }
|
val defaultToStart by remember(videoUri) { mutableStateOf(DEFAULT_MUTED_SETTING.value) }
|
||||||
|
|
||||||
@@ -248,8 +280,7 @@ fun VideoView(
|
|||||||
defaultToStart = defaultToStart,
|
defaultToStart = defaultToStart,
|
||||||
title = title,
|
title = title,
|
||||||
thumb = thumb,
|
thumb = thumb,
|
||||||
roundedCorner = roundedCorner,
|
borderModifier = borderModifier,
|
||||||
gallery = gallery,
|
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
waveform = waveform,
|
waveform = waveform,
|
||||||
artworkUri = artworkUri,
|
artworkUri = artworkUri,
|
||||||
@@ -273,19 +304,12 @@ fun VideoView(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Box(modifier, contentAlignment = Alignment.Center) {
|
Box(modifier, contentAlignment = Alignment.Center) {
|
||||||
val image =
|
|
||||||
if (roundedCorner) {
|
|
||||||
MaterialTheme.colorScheme.imageModifier
|
|
||||||
} else {
|
|
||||||
Modifier.fillMaxWidth()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Always displays Blurharh to avoid size flickering
|
// Always displays Blurharh to avoid size flickering
|
||||||
DisplayBlurHash(
|
DisplayBlurHash(
|
||||||
blurhash,
|
blurhash,
|
||||||
null,
|
null,
|
||||||
if (isFiniteHeight) ContentScale.FillWidth else ContentScale.FillWidth,
|
if (isFiniteHeight) ContentScale.FillWidth else ContentScale.FillWidth,
|
||||||
if (ratio != null) image.aspectRatio(ratio) else modifier,
|
if (ratio != null) borderModifier.aspectRatio(ratio) else borderModifier,
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!automaticallyStartPlayback.value) {
|
if (!automaticallyStartPlayback.value) {
|
||||||
@@ -302,7 +326,7 @@ fun VideoView(
|
|||||||
defaultToStart = defaultToStart,
|
defaultToStart = defaultToStart,
|
||||||
title = title,
|
title = title,
|
||||||
thumb = thumb,
|
thumb = thumb,
|
||||||
roundedCorner = roundedCorner,
|
borderModifier = borderModifier,
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
waveform = waveform,
|
waveform = waveform,
|
||||||
artworkUri = artworkUri,
|
artworkUri = artworkUri,
|
||||||
@@ -326,9 +350,9 @@ fun VideoViewInner(
|
|||||||
defaultToStart: Boolean = false,
|
defaultToStart: Boolean = false,
|
||||||
title: String? = null,
|
title: String? = null,
|
||||||
thumb: VideoThumb? = null,
|
thumb: VideoThumb? = null,
|
||||||
roundedCorner: Boolean,
|
showControls: Boolean = false,
|
||||||
gallery: Boolean = false,
|
|
||||||
isFiniteHeight: Boolean,
|
isFiniteHeight: Boolean,
|
||||||
|
borderModifier: Modifier,
|
||||||
waveform: ImmutableList<Int>? = null,
|
waveform: ImmutableList<Int>? = null,
|
||||||
artworkUri: String? = null,
|
artworkUri: String? = null,
|
||||||
authorName: String? = null,
|
authorName: String? = null,
|
||||||
@@ -338,7 +362,7 @@ fun VideoViewInner(
|
|||||||
onDialog: ((Boolean) -> Unit)? = null,
|
onDialog: ((Boolean) -> Unit)? = null,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
VideoPlayerActiveMutex(videoUri) { modifier, activeOnScreen ->
|
VideoPlayerActiveMutex(videoUri) { videoModifier, activeOnScreen ->
|
||||||
GetMediaItem(videoUri, title, artworkUri, authorName) { mediaItem ->
|
GetMediaItem(videoUri, title, artworkUri, authorName) { mediaItem ->
|
||||||
GetVideoController(
|
GetVideoController(
|
||||||
mediaItem = mediaItem,
|
mediaItem = mediaItem,
|
||||||
@@ -351,15 +375,15 @@ fun VideoViewInner(
|
|||||||
mimeType = mimeType,
|
mimeType = mimeType,
|
||||||
controller = controller,
|
controller = controller,
|
||||||
thumbData = thumb,
|
thumbData = thumb,
|
||||||
roundedCorner = roundedCorner,
|
hideControls = showControls,
|
||||||
gallery = gallery,
|
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
nostrUriCallback = nostrUriCallback,
|
nostrUriCallback = nostrUriCallback,
|
||||||
waveform = waveform,
|
waveform = waveform,
|
||||||
keepPlaying = keepPlaying,
|
keepPlaying = keepPlaying,
|
||||||
automaticallyStartPlayback = automaticallyStartPlayback,
|
automaticallyStartPlayback = automaticallyStartPlayback,
|
||||||
activeOnScreen = activeOnScreen,
|
activeOnScreen = activeOnScreen,
|
||||||
modifier = modifier,
|
borderModifier = borderModifier,
|
||||||
|
videoModifier = videoModifier,
|
||||||
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
||||||
onDialog = onDialog,
|
onDialog = onDialog,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
@@ -655,9 +679,9 @@ fun VideoPlayerActiveMutex(
|
|||||||
onDispose { trackingVideos.remove(myCache) }
|
onDispose { trackingVideos.remove(myCache) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val myModifier =
|
val videoModifier =
|
||||||
remember(videoUri) {
|
remember(videoUri) {
|
||||||
Modifier.fillMaxWidth().defaultMinSize(minHeight = 70.dp).onVisiblePositionChanges { distanceToCenter ->
|
Modifier.fillMaxWidth().heightIn(min = 100.dp).onVisiblePositionChanges { distanceToCenter ->
|
||||||
myCache.distanceToCenter = distanceToCenter
|
myCache.distanceToCenter = distanceToCenter
|
||||||
|
|
||||||
if (distanceToCenter != null) {
|
if (distanceToCenter != null) {
|
||||||
@@ -684,7 +708,7 @@ fun VideoPlayerActiveMutex(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner(myModifier, active)
|
inner(videoModifier, active)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Stable
|
@Stable
|
||||||
@@ -699,15 +723,15 @@ private fun RenderVideoPlayer(
|
|||||||
mimeType: String?,
|
mimeType: String?,
|
||||||
controller: MediaController,
|
controller: MediaController,
|
||||||
thumbData: VideoThumb?,
|
thumbData: VideoThumb?,
|
||||||
roundedCorner: Boolean,
|
hideControls: Boolean = false,
|
||||||
gallery: Boolean = false,
|
|
||||||
isFiniteHeight: Boolean,
|
isFiniteHeight: Boolean,
|
||||||
nostrUriCallback: String?,
|
nostrUriCallback: String?,
|
||||||
waveform: ImmutableList<Int>? = null,
|
waveform: ImmutableList<Int>? = null,
|
||||||
keepPlaying: MutableState<Boolean>,
|
keepPlaying: MutableState<Boolean>,
|
||||||
automaticallyStartPlayback: State<Boolean>,
|
automaticallyStartPlayback: State<Boolean>,
|
||||||
activeOnScreen: MutableState<Boolean>,
|
activeOnScreen: MutableState<Boolean>,
|
||||||
modifier: Modifier,
|
borderModifier: Modifier,
|
||||||
|
videoModifier: Modifier,
|
||||||
onControllerVisibilityChanged: ((Boolean) -> Unit)? = null,
|
onControllerVisibilityChanged: ((Boolean) -> Unit)? = null,
|
||||||
onDialog: ((Boolean) -> Unit)?,
|
onDialog: ((Boolean) -> Unit)?,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
@@ -716,27 +740,9 @@ private fun RenderVideoPlayer(
|
|||||||
|
|
||||||
val controllerVisible = remember(controller) { mutableStateOf(false) }
|
val controllerVisible = remember(controller) { mutableStateOf(false) }
|
||||||
|
|
||||||
Box {
|
Box(modifier = borderModifier) {
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AndroidView(
|
AndroidView(
|
||||||
modifier = myModifier,
|
modifier = videoModifier,
|
||||||
factory = { context: Context ->
|
factory = { context: Context ->
|
||||||
PlayerView(context).apply {
|
PlayerView(context).apply {
|
||||||
player = controller
|
player = controller
|
||||||
@@ -748,7 +754,7 @@ private fun RenderVideoPlayer(
|
|||||||
setBackgroundColor(Color.Transparent.toArgb())
|
setBackgroundColor(Color.Transparent.toArgb())
|
||||||
setShutterBackgroundColor(Color.Transparent.toArgb())
|
setShutterBackgroundColor(Color.Transparent.toArgb())
|
||||||
controllerAutoShow = false
|
controllerAutoShow = false
|
||||||
useController = !gallery
|
useController = !hideControls
|
||||||
thumbData?.thumb?.let { defaultArtwork = it }
|
thumbData?.thumb?.let { defaultArtwork = it }
|
||||||
hideController()
|
hideController()
|
||||||
resizeMode =
|
resizeMode =
|
||||||
@@ -757,7 +763,7 @@ private fun RenderVideoPlayer(
|
|||||||
} else {
|
} else {
|
||||||
AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
AspectRatioFrameLayout.RESIZE_MODE_FIXED_WIDTH
|
||||||
}
|
}
|
||||||
if (!gallery) {
|
if (!hideControls) {
|
||||||
onDialog?.let { innerOnDialog ->
|
onDialog?.let { innerOnDialog ->
|
||||||
setFullscreenButtonClickListener {
|
setFullscreenButtonClickListener {
|
||||||
controller.pause()
|
controller.pause()
|
||||||
@@ -776,7 +782,8 @@ private fun RenderVideoPlayer(
|
|||||||
)
|
)
|
||||||
|
|
||||||
waveform?.let { Waveform(it, controller, remember { Modifier.align(Alignment.Center) }) }
|
waveform?.let { Waveform(it, controller, remember { Modifier.align(Alignment.Center) }) }
|
||||||
if (!gallery) {
|
|
||||||
|
if (!hideControls) {
|
||||||
val startingMuteState = remember(controller) { controller.volume < 0.001 }
|
val startingMuteState = remember(controller) { controller.volume < 0.001 }
|
||||||
|
|
||||||
MuteButton(
|
MuteButton(
|
||||||
|
@@ -89,6 +89,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size10dp
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Size15dp
|
import com.vitorpamplona.amethyst.ui.theme.Size15dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
import com.vitorpamplona.amethyst.ui.theme.Size20Modifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
||||||
import kotlinx.collections.immutable.ImmutableList
|
import kotlinx.collections.immutable.ImmutableList
|
||||||
import kotlinx.collections.immutable.toImmutableList
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
@@ -388,6 +389,12 @@ private fun RenderImageOrVideo(
|
|||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
val automaticallyStartPlayback = remember { mutableStateOf<Boolean>(true) }
|
val automaticallyStartPlayback = remember { mutableStateOf<Boolean>(true) }
|
||||||
|
val contentScale =
|
||||||
|
if (isFiniteHeight) {
|
||||||
|
ContentScale.Fit
|
||||||
|
} else {
|
||||||
|
ContentScale.FillWidth
|
||||||
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
|
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center, modifier = Modifier.fillMaxWidth()) {
|
||||||
if (content is MediaUrlImage) {
|
if (content is MediaUrlImage) {
|
||||||
@@ -405,21 +412,28 @@ private fun RenderImageOrVideo(
|
|||||||
|
|
||||||
UrlImageView(
|
UrlImageView(
|
||||||
content = content,
|
content = content,
|
||||||
|
contentScale = contentScale,
|
||||||
mainImageModifier = mainModifier,
|
mainImageModifier = mainModifier,
|
||||||
loadedImageModifier = Modifier.fillMaxWidth(),
|
loadedImageModifier = Modifier.fillMaxWidth(),
|
||||||
isFiniteHeight = isFiniteHeight,
|
|
||||||
controllerVisible = controllerVisible,
|
controllerVisible = controllerVisible,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
alwayShowImage = true,
|
alwayShowImage = true,
|
||||||
)
|
)
|
||||||
} else if (content is MediaUrlVideo) {
|
} else if (content is MediaUrlVideo) {
|
||||||
|
val borderModifier =
|
||||||
|
if (roundedCorner) {
|
||||||
|
MaterialTheme.colorScheme.imageModifier
|
||||||
|
} else {
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
}
|
||||||
|
|
||||||
VideoViewInner(
|
VideoViewInner(
|
||||||
videoUri = content.url,
|
videoUri = content.url,
|
||||||
mimeType = content.mimeType,
|
mimeType = content.mimeType,
|
||||||
title = content.description,
|
title = content.description,
|
||||||
artworkUri = content.artworkUri,
|
artworkUri = content.artworkUri,
|
||||||
authorName = content.authorName,
|
authorName = content.authorName,
|
||||||
roundedCorner = roundedCorner,
|
borderModifier = borderModifier,
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
automaticallyStartPlayback = automaticallyStartPlayback,
|
automaticallyStartPlayback = automaticallyStartPlayback,
|
||||||
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
||||||
@@ -440,14 +454,21 @@ private fun RenderImageOrVideo(
|
|||||||
|
|
||||||
LocalImageView(
|
LocalImageView(
|
||||||
content = content,
|
content = content,
|
||||||
|
contentScale = contentScale,
|
||||||
mainImageModifier = mainModifier,
|
mainImageModifier = mainModifier,
|
||||||
loadedImageModifier = Modifier.fillMaxWidth(),
|
loadedImageModifier = Modifier.fillMaxWidth(),
|
||||||
isFiniteHeight = isFiniteHeight,
|
|
||||||
controllerVisible = controllerVisible,
|
controllerVisible = controllerVisible,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
alwayShowImage = true,
|
alwayShowImage = true,
|
||||||
)
|
)
|
||||||
} else if (content is MediaLocalVideo) {
|
} else if (content is MediaLocalVideo) {
|
||||||
|
val borderModifier =
|
||||||
|
if (roundedCorner) {
|
||||||
|
MaterialTheme.colorScheme.imageModifier
|
||||||
|
} else {
|
||||||
|
Modifier.fillMaxWidth()
|
||||||
|
}
|
||||||
|
|
||||||
content.localFile?.let {
|
content.localFile?.let {
|
||||||
VideoViewInner(
|
VideoViewInner(
|
||||||
videoUri = it.toUri().toString(),
|
videoUri = it.toUri().toString(),
|
||||||
@@ -455,7 +476,7 @@ private fun RenderImageOrVideo(
|
|||||||
title = content.description,
|
title = content.description,
|
||||||
artworkUri = content.artworkUri,
|
artworkUri = content.artworkUri,
|
||||||
authorName = content.authorName,
|
authorName = content.authorName,
|
||||||
roundedCorner = roundedCorner,
|
borderModifier = borderModifier,
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
automaticallyStartPlayback = automaticallyStartPlayback,
|
automaticallyStartPlayback = automaticallyStartPlayback,
|
||||||
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
onControllerVisibilityChanged = onControllerVisibilityChanged,
|
||||||
|
@@ -79,6 +79,7 @@ import com.vitorpamplona.amethyst.commons.richtext.MediaUrlContent
|
|||||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlImage
|
||||||
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
|
import com.vitorpamplona.amethyst.commons.richtext.MediaUrlVideo
|
||||||
import com.vitorpamplona.amethyst.service.BlurHashRequester
|
import com.vitorpamplona.amethyst.service.BlurHashRequester
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
import com.vitorpamplona.amethyst.ui.actions.InformationDialog
|
import com.vitorpamplona.amethyst.ui.actions.InformationDialog
|
||||||
import com.vitorpamplona.amethyst.ui.actions.LoadingAnimation
|
import com.vitorpamplona.amethyst.ui.actions.LoadingAnimation
|
||||||
import com.vitorpamplona.amethyst.ui.note.BlankNote
|
import com.vitorpamplona.amethyst.ui.note.BlankNote
|
||||||
@@ -94,6 +95,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size30dp
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.Size75dp
|
import com.vitorpamplona.amethyst.ui.theme.Size75dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.hashVerifierMark
|
import com.vitorpamplona.amethyst.ui.theme.hashVerifierMark
|
||||||
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.videoGalleryModifier
|
||||||
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
import com.vitorpamplona.quartz.crypto.CryptoUtils
|
||||||
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
import com.vitorpamplona.quartz.encoders.Nip19Bech32
|
||||||
import com.vitorpamplona.quartz.encoders.toHexKey
|
import com.vitorpamplona.quartz.encoders.toHexKey
|
||||||
@@ -116,6 +118,13 @@ fun ZoomableContentView(
|
|||||||
) {
|
) {
|
||||||
var dialogOpen by remember(content) { mutableStateOf(false) }
|
var dialogOpen by remember(content) { mutableStateOf(false) }
|
||||||
|
|
||||||
|
val contentScale =
|
||||||
|
if (isFiniteHeight) {
|
||||||
|
ContentScale.Fit
|
||||||
|
} else {
|
||||||
|
ContentScale.FillWidth
|
||||||
|
}
|
||||||
|
|
||||||
when (content) {
|
when (content) {
|
||||||
is MediaUrlImage ->
|
is MediaUrlImage ->
|
||||||
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
SensitivityWarning(content.contentWarning != null, accountViewModel) {
|
||||||
@@ -123,7 +132,7 @@ fun ZoomableContentView(
|
|||||||
val mainImageModifier = Modifier.fillMaxWidth().clickable { dialogOpen = true }
|
val mainImageModifier = Modifier.fillMaxWidth().clickable { dialogOpen = true }
|
||||||
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
||||||
|
|
||||||
UrlImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel)
|
UrlImageView(content, contentScale, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is MediaUrlVideo ->
|
is MediaUrlVideo ->
|
||||||
@@ -150,7 +159,7 @@ fun ZoomableContentView(
|
|||||||
val mainImageModifier = Modifier.fillMaxWidth().clickable { dialogOpen = true }
|
val mainImageModifier = Modifier.fillMaxWidth().clickable { dialogOpen = true }
|
||||||
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
||||||
|
|
||||||
LocalImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel)
|
LocalImageView(content, contentScale, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||||
}
|
}
|
||||||
is MediaLocalVideo ->
|
is MediaLocalVideo ->
|
||||||
content.localFile?.let {
|
content.localFile?.let {
|
||||||
@@ -190,7 +199,7 @@ fun GalleryContentView(
|
|||||||
val mainImageModifier = Modifier.fillMaxWidth()
|
val mainImageModifier = Modifier.fillMaxWidth()
|
||||||
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
||||||
|
|
||||||
UrlImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel, gallery = true)
|
UrlImageView(content, ContentScale.Crop, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is MediaUrlVideo ->
|
is MediaUrlVideo ->
|
||||||
@@ -201,11 +210,10 @@ fun GalleryContentView(
|
|||||||
mimeType = content.mimeType,
|
mimeType = content.mimeType,
|
||||||
title = content.description,
|
title = content.description,
|
||||||
artworkUri = content.artworkUri,
|
artworkUri = content.artworkUri,
|
||||||
gallery = true,
|
borderModifier = MaterialTheme.colorScheme.videoGalleryModifier,
|
||||||
authorName = content.authorName,
|
authorName = content.authorName,
|
||||||
dimensions = content.dim,
|
dimensions = content.dim,
|
||||||
blurhash = content.blurhash,
|
blurhash = content.blurhash,
|
||||||
roundedCorner = roundedCorner,
|
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
nostrUriCallback = content.uri,
|
nostrUriCallback = content.uri,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
@@ -217,7 +225,7 @@ fun GalleryContentView(
|
|||||||
val mainImageModifier = Modifier.fillMaxWidth()
|
val mainImageModifier = Modifier.fillMaxWidth()
|
||||||
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
val loadedImageModifier = if (roundedCorner) MaterialTheme.colorScheme.imageModifier else Modifier.fillMaxWidth()
|
||||||
|
|
||||||
LocalImageView(content, mainImageModifier, loadedImageModifier, isFiniteHeight, controllerVisible, accountViewModel = accountViewModel)
|
LocalImageView(content, ContentScale.Crop, mainImageModifier, loadedImageModifier, controllerVisible, accountViewModel = accountViewModel)
|
||||||
}
|
}
|
||||||
is MediaLocalVideo ->
|
is MediaLocalVideo ->
|
||||||
content.localFile?.let {
|
content.localFile?.let {
|
||||||
@@ -228,8 +236,7 @@ fun GalleryContentView(
|
|||||||
title = content.description,
|
title = content.description,
|
||||||
artworkUri = content.artworkUri,
|
artworkUri = content.artworkUri,
|
||||||
authorName = content.authorName,
|
authorName = content.authorName,
|
||||||
gallery = true,
|
borderModifier = MaterialTheme.colorScheme.videoGalleryModifier,
|
||||||
roundedCorner = roundedCorner,
|
|
||||||
isFiniteHeight = isFiniteHeight,
|
isFiniteHeight = isFiniteHeight,
|
||||||
nostrUriCallback = content.uri,
|
nostrUriCallback = content.uri,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
@@ -257,30 +264,24 @@ fun TwoSecondController(
|
|||||||
@Composable
|
@Composable
|
||||||
fun LocalImageView(
|
fun LocalImageView(
|
||||||
content: MediaLocalImage,
|
content: MediaLocalImage,
|
||||||
|
contentScale: ContentScale,
|
||||||
mainImageModifier: Modifier,
|
mainImageModifier: Modifier,
|
||||||
loadedImageModifier: Modifier,
|
loadedImageModifier: Modifier,
|
||||||
isFiniteHeight: Boolean,
|
|
||||||
controllerVisible: MutableState<Boolean>,
|
controllerVisible: MutableState<Boolean>,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
alwayShowImage: Boolean = false,
|
alwayShowImage: Boolean = false,
|
||||||
) {
|
) {
|
||||||
if (content.localFileExists()) {
|
if (content.localFileExists()) {
|
||||||
Box(contentAlignment = Alignment.Center) {
|
val showImage =
|
||||||
val showImage =
|
remember {
|
||||||
remember {
|
mutableStateOf(
|
||||||
mutableStateOf(
|
if (alwayShowImage) true else accountViewModel.settings.showImages.value,
|
||||||
if (alwayShowImage) true else accountViewModel.settings.showImages.value,
|
)
|
||||||
)
|
}
|
||||||
}
|
|
||||||
|
|
||||||
val contentScale =
|
val ratio = remember(content) { aspectRatio(content.dim) }
|
||||||
remember {
|
CrossfadeIfEnabled(targetState = showImage.value, contentAlignment = Alignment.Center, accountViewModel = accountViewModel) {
|
||||||
if (isFiniteHeight) ContentScale.Fit else ContentScale.FillWidth
|
if (it) {
|
||||||
}
|
|
||||||
|
|
||||||
val ratio = remember(content) { aspectRatio(content.dim) }
|
|
||||||
|
|
||||||
if (showImage.value) {
|
|
||||||
SubcomposeAsyncImage(
|
SubcomposeAsyncImage(
|
||||||
model = content.localFile,
|
model = content.localFile,
|
||||||
contentDescription = content.description,
|
contentDescription = content.description,
|
||||||
@@ -361,36 +362,28 @@ fun LocalImageView(
|
|||||||
@Composable
|
@Composable
|
||||||
fun UrlImageView(
|
fun UrlImageView(
|
||||||
content: MediaUrlImage,
|
content: MediaUrlImage,
|
||||||
|
contentScale: ContentScale,
|
||||||
mainImageModifier: Modifier,
|
mainImageModifier: Modifier,
|
||||||
loadedImageModifier: Modifier,
|
loadedImageModifier: Modifier,
|
||||||
isFiniteHeight: Boolean,
|
|
||||||
controllerVisible: MutableState<Boolean>,
|
controllerVisible: MutableState<Boolean>,
|
||||||
accountViewModel: AccountViewModel,
|
accountViewModel: AccountViewModel,
|
||||||
gallery: Boolean = false,
|
|
||||||
alwayShowImage: Boolean = false,
|
alwayShowImage: Boolean = false,
|
||||||
) {
|
) {
|
||||||
Box(contentAlignment = Alignment.Center) {
|
val ratio = remember(content) { aspectRatio(content.dim) }
|
||||||
val showImage =
|
|
||||||
remember {
|
|
||||||
mutableStateOf(
|
|
||||||
if (alwayShowImage) true else accountViewModel.settings.showImages.value,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val ratio = remember(content) { aspectRatio(content.dim) }
|
val showImage =
|
||||||
|
remember {
|
||||||
|
mutableStateOf(
|
||||||
|
if (alwayShowImage) true else accountViewModel.settings.showImages.value,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
if (showImage.value) {
|
CrossfadeIfEnabled(targetState = showImage.value, contentAlignment = Alignment.Center, accountViewModel = accountViewModel) {
|
||||||
|
if (it) {
|
||||||
SubcomposeAsyncImage(
|
SubcomposeAsyncImage(
|
||||||
model = content.url,
|
model = content.url,
|
||||||
contentDescription = content.description,
|
contentDescription = content.description,
|
||||||
contentScale =
|
contentScale = contentScale,
|
||||||
if (gallery) {
|
|
||||||
ContentScale.Crop
|
|
||||||
} else if (isFiniteHeight) {
|
|
||||||
ContentScale.Fit
|
|
||||||
} else {
|
|
||||||
ContentScale.FillWidth
|
|
||||||
},
|
|
||||||
modifier = mainImageModifier,
|
modifier = mainImageModifier,
|
||||||
) {
|
) {
|
||||||
when (painter.state) {
|
when (painter.state) {
|
||||||
@@ -493,7 +486,7 @@ fun ImageUrlWithDownloadButton(
|
|||||||
|
|
||||||
val inlineContent = mapOf("inlineContent" to InlineDownloadIcon(showImage))
|
val inlineContent = mapOf("inlineContent" to InlineDownloadIcon(showImage))
|
||||||
|
|
||||||
val pressIndicator = remember { Modifier.clickable { runCatching { uri.openUri(url) } } }
|
val pressIndicator = remember { Modifier.fillMaxWidth().clickable { runCatching { uri.openUri(url) } } }
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = annotatedTermsString,
|
text = annotatedTermsString,
|
||||||
|
Reference in New Issue
Block a user