Adds a special case for loading previews with just 1 item in the new post screen

This commit is contained in:
Vitor Pamplona
2025-04-25 17:41:06 -04:00
parent 92eff02f0a
commit 08025f7df7
5 changed files with 151 additions and 7 deletions
@@ -42,10 +42,7 @@ class ServerInfoRetriever {
.url(parser.assembleUrl(baseUrl))
.build()
println("AABBCC $baseUrl Request ${parser.assembleUrl(baseUrl)}")
okHttpClient(baseUrl).newCall(request).execute().use { response ->
println("AABBCC $baseUrl Response")
checkNotInMainThread()
response.use {
val body = it.body.string()
@@ -73,6 +73,11 @@ fun LoadUrlPreviewDirect(
is UrlPreviewState.Loaded -> {
RenderLoaded(state, url, callbackUri, accountViewModel)
}
is UrlPreviewState.Loading -> {
WaitAndDisplay {
DisplayUrlWithLoadingSymbol(url)
}
}
else -> {
ClickableUrl(urlText, url)
}
@@ -610,6 +610,38 @@ fun DisplayUrlWithLoadingSymbol(content: BaseMediaContent) {
}
}
@Composable
fun DisplayUrlWithLoadingSymbol(url: String) {
val uri = LocalUriHandler.current
val primary = MaterialTheme.colorScheme.primary
val annotatedTermsString =
remember {
buildAnnotatedString {
withStyle(SpanStyle(color = primary)) {
pushStringAnnotation("routeToImage", "")
append("$url ")
pop()
}
}
}
val pressIndicator = remember { Modifier.clickable { runCatching { uri.openUri(url) } } }
Row(
modifier = Modifier.width(IntrinsicSize.Max),
horizontalArrangement = Arrangement.spacedBy(2.dp),
) {
Text(
text = annotatedTermsString,
modifier = pressIndicator.weight(1f, fill = false),
overflow = TextOverflow.Ellipsis,
maxLines = 1,
)
InlineLoadingIcon()
}
}
@Composable
private fun InlineLoadingIcon() = LoadingAnimation()
@@ -25,6 +25,7 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -45,7 +46,10 @@ import com.vitorpamplona.amethyst.model.UrlCachedPreviewer
import com.vitorpamplona.amethyst.service.playback.composable.VideoView
import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled
import com.vitorpamplona.amethyst.ui.components.ClickableUrl
import com.vitorpamplona.amethyst.ui.components.DisplayUrlWithLoadingSymbol
import com.vitorpamplona.amethyst.ui.components.UrlPreviewCard
import com.vitorpamplona.amethyst.ui.components.UrlPreviewState
import com.vitorpamplona.amethyst.ui.components.WaitAndDisplay
import com.vitorpamplona.amethyst.ui.navigation.INav
import com.vitorpamplona.amethyst.ui.note.NoteCompose
import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel
@@ -93,6 +97,49 @@ fun PreviewUrl(
}
}
@Composable
fun PreviewUrlFillWidth(
myUrlPreview: String,
accountViewModel: AccountViewModel,
nav: INav,
) {
if (RichTextParser.isValidURL(myUrlPreview)) {
if (RichTextParser.isImageUrl(myUrlPreview)) {
AsyncImage(
model = myUrlPreview,
contentDescription = myUrlPreview,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxHeight().aspectRatio(1f),
)
} else if (RichTextParser.isVideoUrl(myUrlPreview)) {
VideoView(
myUrlPreview,
mimeType = null,
roundedCorner = false,
gallery = false,
contentScale = ContentScale.FillWidth,
accountViewModel = accountViewModel,
)
} else {
MyLoadUrlPreviewDirectFillWidth(myUrlPreview, myUrlPreview, accountViewModel)
}
} else if (RichTextParser.startsWithNIP19Scheme(myUrlPreview)) {
val bgColor = MaterialTheme.colorScheme.background
val backgroundColor = remember { mutableStateOf(bgColor) }
BechLinkPreview(
word = myUrlPreview,
canPreview = true,
quotesLeft = 1,
backgroundColor = backgroundColor,
accountViewModel = accountViewModel,
nav = nav,
)
} else if (RichTextParser.isUrlWithoutScheme(myUrlPreview)) {
MyLoadUrlPreviewDirectFillWidth("https://$myUrlPreview", myUrlPreview, accountViewModel)
}
}
@Composable
private fun BechLinkPreview(
word: String,
@@ -196,3 +243,59 @@ private fun MyLoadUrlPreviewDirect(
}
}
}
@Composable
private fun MyLoadUrlPreviewDirectFillWidth(
url: String,
urlText: String,
accountViewModel: AccountViewModel,
) {
@Suppress("ProduceStateDoesNotAssignValue")
val urlPreviewState by
produceState(
initialValue = UrlCachedPreviewer.cache.get(url) ?: UrlPreviewState.Loading,
key1 = url,
) {
if (value == UrlPreviewState.Loading) {
accountViewModel.urlPreview(url) { value = it }
}
}
CrossfadeIfEnabled(
targetState = urlPreviewState,
label = "UrlPreview",
accountViewModel = accountViewModel,
) { state ->
when (state) {
is UrlPreviewState.Loaded -> {
if (state.previewInfo.mimeType.type == "image") {
AsyncImage(
model = state.previewInfo.url,
contentDescription = null,
contentScale = ContentScale.FillWidth,
modifier = Modifier.fillMaxWidth(),
)
} else if (state.previewInfo.mimeType.type == "video") {
VideoView(
state.previewInfo.url,
mimeType = state.previewInfo.mimeType.toString(),
roundedCorner = false,
gallery = false,
contentScale = ContentScale.FillWidth,
accountViewModel = accountViewModel,
)
} else {
UrlPreviewCard(url, previewInfo = state.previewInfo)
}
}
is UrlPreviewState.Loading -> {
WaitAndDisplay {
DisplayUrlWithLoadingSymbol(url)
}
}
else -> {
ClickableUrl(urlText, url)
}
}
}
}
@@ -108,6 +108,7 @@ import com.vitorpamplona.amethyst.ui.note.creators.location.AddGeoHashButton
import com.vitorpamplona.amethyst.ui.note.creators.location.LocationAsHash
import com.vitorpamplona.amethyst.ui.note.creators.messagefield.MessageField
import com.vitorpamplona.amethyst.ui.note.creators.previews.PreviewUrl
import com.vitorpamplona.amethyst.ui.note.creators.previews.PreviewUrlFillWidth
import com.vitorpamplona.amethyst.ui.note.creators.products.AddClassifiedsButton
import com.vitorpamplona.amethyst.ui.note.creators.products.SellProduct
import com.vitorpamplona.amethyst.ui.note.creators.secretEmoji.AddSecretEmojiButton
@@ -576,12 +577,18 @@ fun DisplayPreviews(
if (urlPreviews.isNotEmpty()) {
Row(modifier = Modifier.padding(vertical = Size5dp)) {
LazyRow(modifier = Modifier.height(100.dp)) {
items(urlPreviews) {
Box(modifier = Modifier.aspectRatio(1f).clip(shape = QuoteBorder)) {
PreviewUrl(it, accountViewModel, nav)
if (urlPreviews.size > 1) {
LazyRow(modifier = Modifier.height(100.dp)) {
items(urlPreviews) {
Box(modifier = Modifier.aspectRatio(1f).clip(shape = QuoteBorder)) {
PreviewUrl(it, accountViewModel, nav)
}
}
}
} else {
Box(modifier = Modifier.fillMaxWidth().clip(shape = QuoteBorder)) {
PreviewUrlFillWidth(urlPreviews[0], accountViewModel, nav)
}
}
}
}