diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/nip96/ServerInfoRetriever.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/nip96/ServerInfoRetriever.kt index 2906bbe140..71b83c426b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/nip96/ServerInfoRetriever.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/uploads/nip96/ServerInfoRetriever.kt @@ -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() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt index 8c8e28174a..39b2762b44 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/LoadUrlPreview.kt @@ -73,6 +73,11 @@ fun LoadUrlPreviewDirect( is UrlPreviewState.Loaded -> { RenderLoaded(state, url, callbackUri, accountViewModel) } + is UrlPreviewState.Loading -> { + WaitAndDisplay { + DisplayUrlWithLoadingSymbol(url) + } + } else -> { ClickableUrl(urlText, url) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt index 73975d3a4c..c3af28ddd0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/ZoomableContentView.kt @@ -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() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt index 305474f9c8..c45d97bd2b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/creators/previews/PreviewUrl.kt @@ -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) + } + } + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt index 8822f0a11e..bf341da686 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/NewPostScreen.kt @@ -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) + } } } }