Basic refactoring to minimize the need for user-space params in the VideoView

This commit is contained in:
Vitor Pamplona
2024-07-31 14:43:10 -04:00
parent d1278a4477
commit b24999d78c
3 changed files with 116 additions and 95 deletions

View File

@@ -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(

View File

@@ -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,

View File

@@ -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,