Extending AsyncImage to correctly use pre-loaded aspect ratio and avoid screen jittering
This commit is contained in:
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2024 Vitor Pamplona
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
* this software and associated documentation files (the "Software"), to deal in
|
||||||
|
* the Software without restriction, including without limitation the rights to use,
|
||||||
|
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||||
|
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
* subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||||
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package com.vitorpamplona.amethyst.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.aspectRatio
|
||||||
|
import androidx.compose.foundation.layout.size
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.SideEffect
|
||||||
|
import androidx.compose.runtime.collectAsState
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.layout.ContentScale
|
||||||
|
import coil3.compose.AsyncImagePainter
|
||||||
|
import coil3.compose.SubcomposeAsyncImage
|
||||||
|
import coil3.compose.SubcomposeAsyncImageContent
|
||||||
|
import com.vitorpamplona.amethyst.model.MediaAspectRatioCache
|
||||||
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.DownloadForOfflineIcon
|
||||||
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size40dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size6dp
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.Size75dp
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MyAsyncImage(
|
||||||
|
imageUrl: String,
|
||||||
|
contentDescription: String?,
|
||||||
|
contentScale: ContentScale,
|
||||||
|
mainImageModifier: Modifier,
|
||||||
|
loadedImageModifier: Modifier,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
onError: @Composable () -> Unit,
|
||||||
|
) {
|
||||||
|
val ratio = MediaAspectRatioCache.get(imageUrl)
|
||||||
|
val showImage = remember { mutableStateOf(accountViewModel.settings.showImages.value) }
|
||||||
|
|
||||||
|
CrossfadeIfEnabled(targetState = showImage.value, contentAlignment = Alignment.Center, accountViewModel = accountViewModel) {
|
||||||
|
if (it) {
|
||||||
|
SubcomposeAsyncImage(
|
||||||
|
model = imageUrl,
|
||||||
|
contentDescription = contentDescription,
|
||||||
|
contentScale = contentScale,
|
||||||
|
modifier = mainImageModifier,
|
||||||
|
) {
|
||||||
|
val state by painter.state.collectAsState()
|
||||||
|
when (state) {
|
||||||
|
is AsyncImagePainter.State.Loading -> {
|
||||||
|
if (ratio != null) {
|
||||||
|
Box(loadedImageModifier.aspectRatio(ratio), contentAlignment = Alignment.Center) {
|
||||||
|
LoadingAnimation(Size40dp, Size6dp)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
WaitAndDisplay {
|
||||||
|
DisplayUrlWithLoadingSymbol(imageUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is AsyncImagePainter.State.Error -> {
|
||||||
|
onError()
|
||||||
|
}
|
||||||
|
is AsyncImagePainter.State.Success -> {
|
||||||
|
SubcomposeAsyncImageContent(loadedImageModifier)
|
||||||
|
|
||||||
|
SideEffect {
|
||||||
|
val drawable = (state as AsyncImagePainter.State.Success).result.image
|
||||||
|
MediaAspectRatioCache.add(imageUrl, drawable.width, drawable.height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ratio != null) {
|
||||||
|
Box(loadedImageModifier.aspectRatio(ratio), contentAlignment = Alignment.Center) {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.size(Size75dp),
|
||||||
|
onClick = { showImage.value = true },
|
||||||
|
) {
|
||||||
|
DownloadForOfflineIcon(Size75dp, MaterialTheme.colorScheme.onBackground)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Box(loadedImageModifier.aspectRatio(16 / 9.0f), contentAlignment = Alignment.Center) {
|
||||||
|
IconButton(
|
||||||
|
modifier = Modifier.size(Size75dp),
|
||||||
|
onClick = { showImage.value = true },
|
||||||
|
) {
|
||||||
|
DownloadForOfflineIcon(Size75dp, MaterialTheme.colorScheme.onBackground)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -70,7 +70,7 @@ fun WatchAuthor(
|
|||||||
inner(noteAuthor)
|
inner(noteAuthor)
|
||||||
} else {
|
} else {
|
||||||
val authorState by observeNote(baseNote, accountViewModel)
|
val authorState by observeNote(baseNote, accountViewModel)
|
||||||
authorState?.note?.author?.let {
|
authorState.note.author?.let {
|
||||||
inner(it)
|
inner(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-5
@@ -30,11 +30,11 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
import com.vitorpamplona.amethyst.model.User
|
import com.vitorpamplona.amethyst.model.User
|
||||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserBanner
|
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUserBanner
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
import com.vitorpamplona.amethyst.ui.note.BaseUserPicture
|
||||||
import com.vitorpamplona.amethyst.ui.note.WatchAuthor
|
import com.vitorpamplona.amethyst.ui.note.WatchAuthor
|
||||||
import com.vitorpamplona.amethyst.ui.painterRes
|
import com.vitorpamplona.amethyst.ui.painterRes
|
||||||
@@ -67,25 +67,35 @@ fun BannerImage(
|
|||||||
) {
|
) {
|
||||||
val banner by observeUserBanner(author, accountViewModel)
|
val banner by observeUserBanner(author, accountViewModel)
|
||||||
|
|
||||||
BannerImage(banner, modifier)
|
BannerImage(banner, modifier, accountViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun BannerImage(
|
fun BannerImage(
|
||||||
banner: String?,
|
banner: String?,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
) {
|
) {
|
||||||
if (!banner.isNullOrBlank()) {
|
if (!banner.isNullOrBlank()) {
|
||||||
AsyncImage(
|
MyAsyncImage(
|
||||||
model = banner,
|
imageUrl = banner,
|
||||||
contentDescription =
|
contentDescription =
|
||||||
stringRes(
|
stringRes(
|
||||||
R.string.preview_card_image_for,
|
R.string.preview_card_image_for,
|
||||||
banner,
|
banner,
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.Crop,
|
contentScale = ContentScale.Crop,
|
||||||
|
mainImageModifier = Modifier,
|
||||||
|
loadedImageModifier = modifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = {
|
||||||
|
Image(
|
||||||
|
painter = painterRes(R.drawable.profile_banner),
|
||||||
|
contentDescription = stringRes(R.string.profile_banner),
|
||||||
|
contentScale = ContentScale.Crop,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
placeholder = painterRes(R.drawable.profile_banner),
|
)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
Image(
|
Image(
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import androidx.compose.ui.text.font.FontWeight
|
|||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.tooling.preview.Preview
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.LocalCache
|
import com.vitorpamplona.amethyst.model.LocalCache
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
@@ -52,12 +51,14 @@ import com.vitorpamplona.amethyst.model.User
|
|||||||
import com.vitorpamplona.amethyst.service.playback.composable.VideoView
|
import com.vitorpamplona.amethyst.service.playback.composable.VideoView
|
||||||
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
|
import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNote
|
||||||
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.EmptyNav
|
import com.vitorpamplona.amethyst.ui.navigation.EmptyNav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
import com.vitorpamplona.amethyst.ui.navigation.routeFor
|
||||||
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture
|
||||||
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
import com.vitorpamplona.amethyst.ui.note.DisplayAuthorBanner
|
||||||
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
import com.vitorpamplona.amethyst.ui.note.UsernameDisplay
|
||||||
|
import com.vitorpamplona.amethyst.ui.note.elements.DefaultImageHeader
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.LiveFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.LiveFlag
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.ScheduledFlag
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.nip53LiveActivities.ScheduledFlag
|
||||||
@@ -220,7 +221,19 @@ fun RenderLiveActivityEventInner(
|
|||||||
Row(
|
Row(
|
||||||
verticalAlignment = Alignment.CenterVertically,
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
) {
|
) {
|
||||||
AsyncImage(model = it, contentDescription = null, modifier = MaterialTheme.colorScheme.imageModifier)
|
MyAsyncImage(
|
||||||
|
imageUrl = it,
|
||||||
|
contentDescription =
|
||||||
|
stringRes(
|
||||||
|
R.string.preview_card_image_for,
|
||||||
|
it,
|
||||||
|
),
|
||||||
|
contentScale = ContentScale.FillWidth,
|
||||||
|
mainImageModifier = Modifier.fillMaxWidth(),
|
||||||
|
loadedImageModifier = MaterialTheme.colorScheme.imageModifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = { DefaultImageHeader(baseNote, accountViewModel) },
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: run { DisplayAuthorBanner(baseNote, accountViewModel) }
|
} ?: run { DisplayAuthorBanner(baseNote, accountViewModel) }
|
||||||
|
|
||||||
|
|||||||
@@ -35,9 +35,9 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.DefaultImageHeader
|
import com.vitorpamplona.amethyst.ui.note.elements.DefaultImageHeader
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -83,22 +83,23 @@ fun LongFormHeader(
|
|||||||
QuoteBorder,
|
QuoteBorder,
|
||||||
),
|
),
|
||||||
) {
|
) {
|
||||||
if (accountViewModel.settings.showImages.value) {
|
|
||||||
image?.let {
|
image?.let {
|
||||||
AsyncImage(
|
MyAsyncImage(
|
||||||
model = it,
|
imageUrl = it,
|
||||||
contentDescription =
|
contentDescription =
|
||||||
stringRes(
|
stringRes(
|
||||||
R.string.preview_card_image_for,
|
R.string.preview_card_image_for,
|
||||||
it,
|
it,
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
mainImageModifier = Modifier.fillMaxWidth(),
|
||||||
|
loadedImageModifier = Modifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = { DefaultImageHeader(note, accountViewModel) },
|
||||||
)
|
)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
DefaultImageHeader(note, accountViewModel)
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
title?.let {
|
title?.let {
|
||||||
Text(
|
Text(
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ import androidx.compose.ui.platform.LocalUriHandler
|
|||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
|
import com.vitorpamplona.amethyst.commons.richtext.BaseMediaContent
|
||||||
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.commons.richtext.RichTextParser
|
import com.vitorpamplona.amethyst.commons.richtext.RichTextParser
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
import com.vitorpamplona.amethyst.ui.components.SensitivityWarning
|
||||||
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer
|
||||||
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
||||||
@@ -131,15 +131,18 @@ fun VideoDisplay(
|
|||||||
modifier = Modifier.clickable { runCatching { uri.openUri(imeta.url) } },
|
modifier = Modifier.clickable { runCatching { uri.openUri(imeta.url) } },
|
||||||
) {
|
) {
|
||||||
image?.let {
|
image?.let {
|
||||||
AsyncImage(
|
MyAsyncImage(
|
||||||
model = it,
|
imageUrl = it,
|
||||||
contentDescription =
|
contentDescription =
|
||||||
stringRes(
|
stringRes(
|
||||||
R.string.preview_card_image_for,
|
R.string.preview_card_image_for,
|
||||||
it,
|
it,
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = MaterialTheme.colorScheme.imageModifier,
|
mainImageModifier = Modifier,
|
||||||
|
loadedImageModifier = MaterialTheme.colorScheme.imageModifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = { DefaultImageHeader(note, accountViewModel) },
|
||||||
)
|
)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
DefaultImageHeader(note, accountViewModel)
|
DefaultImageHeader(note, accountViewModel)
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ import androidx.compose.ui.graphics.Color
|
|||||||
import androidx.compose.ui.layout.ContentScale
|
import androidx.compose.ui.layout.ContentScale
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil3.compose.AsyncImage
|
|
||||||
import com.vitorpamplona.amethyst.R
|
import com.vitorpamplona.amethyst.R
|
||||||
import com.vitorpamplona.amethyst.model.Note
|
import com.vitorpamplona.amethyst.model.Note
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.navigation.INav
|
import com.vitorpamplona.amethyst.ui.navigation.INav
|
||||||
import com.vitorpamplona.amethyst.ui.note.elements.DefaultImageHeader
|
import com.vitorpamplona.amethyst.ui.note.elements.DefaultImageHeader
|
||||||
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
|
||||||
@@ -46,6 +46,7 @@ import com.vitorpamplona.amethyst.ui.stringRes
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
import com.vitorpamplona.amethyst.ui.theme.QuoteBorder
|
||||||
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
||||||
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer
|
||||||
|
import com.vitorpamplona.amethyst.ui.theme.imageModifier
|
||||||
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
import com.vitorpamplona.amethyst.ui.theme.subtleBorder
|
||||||
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent
|
||||||
|
|
||||||
@@ -91,15 +92,18 @@ private fun WikiNoteHeader(
|
|||||||
|
|
||||||
if (automaticallyShowUrlPreview) {
|
if (automaticallyShowUrlPreview) {
|
||||||
image?.let {
|
image?.let {
|
||||||
AsyncImage(
|
MyAsyncImage(
|
||||||
model = it,
|
imageUrl = it,
|
||||||
contentDescription =
|
contentDescription =
|
||||||
stringRes(
|
stringRes(
|
||||||
R.string.preview_card_image_for,
|
R.string.preview_card_image_for,
|
||||||
it,
|
it,
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = Modifier.fillMaxWidth(),
|
mainImageModifier = Modifier,
|
||||||
|
loadedImageModifier = MaterialTheme.colorScheme.imageModifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = { DefaultImageHeader(note, accountViewModel) },
|
||||||
)
|
)
|
||||||
} ?: run {
|
} ?: run {
|
||||||
DefaultImageHeader(note, accountViewModel)
|
DefaultImageHeader(note, accountViewModel)
|
||||||
|
|||||||
+15
-5
@@ -78,6 +78,7 @@ import com.vitorpamplona.amethyst.model.Note
|
|||||||
import com.vitorpamplona.amethyst.ui.components.AutoNonlazyGrid
|
import com.vitorpamplona.amethyst.ui.components.AutoNonlazyGrid
|
||||||
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
import com.vitorpamplona.amethyst.ui.components.GenericLoadable
|
||||||
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
import com.vitorpamplona.amethyst.ui.components.LoadNote
|
||||||
|
import com.vitorpamplona.amethyst.ui.components.MyAsyncImage
|
||||||
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
|
import com.vitorpamplona.amethyst.ui.components.ObserveDisplayNip05Status
|
||||||
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
import com.vitorpamplona.amethyst.ui.components.ZoomableContentView
|
||||||
import com.vitorpamplona.amethyst.ui.feeds.FeedState
|
import com.vitorpamplona.amethyst.ui.feeds.FeedState
|
||||||
@@ -504,7 +505,7 @@ private fun FullBleedNoteCompose(
|
|||||||
|
|
||||||
when (noteEvent) {
|
when (noteEvent) {
|
||||||
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote, accountViewModel)
|
is BadgeDefinitionEvent -> BadgeDisplay(baseNote = baseNote, accountViewModel)
|
||||||
is LongTextNoteEvent -> RenderLongFormHeaderForThread(noteEvent)
|
is LongTextNoteEvent -> RenderLongFormHeaderForThread(noteEvent, baseNote, accountViewModel)
|
||||||
is WikiNoteEvent -> RenderWikiHeaderForThread(noteEvent, accountViewModel, nav)
|
is WikiNoteEvent -> RenderWikiHeaderForThread(noteEvent, accountViewModel, nav)
|
||||||
is ClassifiedsEvent -> RenderClassifiedsReaderForThread(noteEvent, baseNote, accountViewModel, nav)
|
is ClassifiedsEvent -> RenderClassifiedsReaderForThread(noteEvent, baseNote, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
@@ -925,19 +926,28 @@ private fun RenderClassifiedsReaderForThread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) {
|
private fun RenderLongFormHeaderForThread(
|
||||||
|
noteEvent: LongTextNoteEvent,
|
||||||
|
note: Note,
|
||||||
|
accountViewModel: AccountViewModel,
|
||||||
|
) {
|
||||||
Column(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
|
Column(modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 12.dp)) {
|
||||||
noteEvent.image()?.let {
|
noteEvent.image()?.let {
|
||||||
AsyncImage(
|
MyAsyncImage(
|
||||||
model = it,
|
imageUrl = it,
|
||||||
contentDescription =
|
contentDescription =
|
||||||
stringRes(
|
stringRes(
|
||||||
R.string.preview_card_image_for,
|
R.string.preview_card_image_for,
|
||||||
it,
|
it,
|
||||||
),
|
),
|
||||||
contentScale = ContentScale.FillWidth,
|
contentScale = ContentScale.FillWidth,
|
||||||
modifier = MaterialTheme.colorScheme.imageModifier,
|
mainImageModifier = Modifier,
|
||||||
|
loadedImageModifier = MaterialTheme.colorScheme.imageModifier,
|
||||||
|
accountViewModel = accountViewModel,
|
||||||
|
onError = { DefaultImageHeader(note, accountViewModel) },
|
||||||
)
|
)
|
||||||
|
} ?: run {
|
||||||
|
DefaultImageHeader(note, accountViewModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
noteEvent.title()?.let {
|
noteEvent.title()?.let {
|
||||||
|
|||||||
Reference in New Issue
Block a user