diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt index b9388edba..ce7e7ea98 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/components/RichTextViewer.kt @@ -81,6 +81,7 @@ import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState import com.vitorpamplona.amethyst.commons.richtext.SchemelessUrlSegment import com.vitorpamplona.amethyst.commons.richtext.SecretEmoji import com.vitorpamplona.amethyst.commons.richtext.Segment +import com.vitorpamplona.amethyst.commons.richtext.VideoSegment import com.vitorpamplona.amethyst.commons.richtext.WithdrawSegment import com.vitorpamplona.amethyst.model.HashtagIcon import com.vitorpamplona.amethyst.model.LocalCache @@ -92,7 +93,6 @@ import com.vitorpamplona.amethyst.service.relayClient.reqCommand.user.observeUse import com.vitorpamplona.amethyst.ui.actions.CrossfadeIfEnabled import com.vitorpamplona.amethyst.ui.components.markdown.RenderContentAsMarkdown import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav -import com.vitorpamplona.amethyst.ui.navigation.navs.EmptyNav.nav import com.vitorpamplona.amethyst.ui.navigation.navs.INav import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.routeFor @@ -112,7 +112,6 @@ import com.vitorpamplona.quartz.nip01Core.core.ImmutableListOfLists import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import kotlin.text.Typography.paragraph fun isMarkdown(content: String): Boolean = content.startsWith("> ") || @@ -416,6 +415,8 @@ private fun RenderWordWithoutPreview( when (word) { // Don't preview Images is ImageSegment -> ClickableUrl(word.segmentText, word.segmentText) + // Don't preview Videos + is VideoSegment -> ClickableUrl(word.segmentText, word.segmentText) is LinkSegment -> ClickableUrl(word.segmentText, word.segmentText) is EmojiSegment -> RenderCustomEmoji(word.segmentText, state) // Don't offer to pay invoices @@ -447,6 +448,7 @@ private fun RenderWordWithPreview( ) { when (word) { is ImageSegment -> ZoomableContentView(word.segmentText, state, accountViewModel) + is VideoSegment -> ZoomableContentView(word.segmentText, state, accountViewModel) is LinkSegment -> LoadUrlPreview(word.segmentText, word.segmentText, callbackUri, accountViewModel) is EmojiSegment -> RenderCustomEmoji(word.segmentText, state) is InvoiceSegment -> MayBeInvoicePreview(word.segmentText, accountViewModel) diff --git a/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt b/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt index 51eec881d..6eb4d9700 100644 --- a/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt +++ b/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/GalleryParser.kt @@ -37,6 +37,7 @@ class GalleryParser { paragraph.words.forEach { word -> when (word) { is ImageSegment, is Base64Segment -> imageCount++ + is VideoSegment -> hasNonWhitespaceNonImageContent = true // Videos are not images is RegularTextSegment -> { if (word.segmentText.isNotBlank()) { hasNonWhitespaceNonImageContent = true @@ -146,13 +147,18 @@ class GalleryParser { val word = paragraph.words[i] if (word is ImageSegment || word is Base64Segment) { - // Collect consecutive image/whitespace segments without extra list allocations + // Collect consecutive image/whitespace segments (but not videos) val imageSegments = mutableListOf() var j = i + var hasVideo = false while (j < n) { val seg = paragraph.words[j] when { + seg is VideoSegment -> { + hasVideo = true + break + } seg is ImageSegment || seg is Base64Segment -> imageSegments.add(seg) seg is RegularTextSegment && seg.segmentText.isBlank() -> { /* skip whitespace */ } else -> break @@ -160,8 +166,9 @@ class GalleryParser { j++ } - if (imageSegments.size <= 1) { - currentParagraphSegments.add(word) + // If we found a video, don't create a gallery - render images individually + if (hasVideo || imageSegments.size <= 1) { + currentParagraphSegments.addAll(imageSegments) } else { if (currentParagraphSegments.isNotEmpty()) { resultingParagraphs.add(ParagraphState(currentParagraphSegments.toImmutableList(), paragraph.isRTL)) diff --git a/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/RichTextParser.kt b/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/RichTextParser.kt index edeebed7f..14bc34a4f 100644 --- a/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/RichTextParser.kt +++ b/commons/src/main/java/com/vitorpamplona/amethyst/commons/richtext/RichTextParser.kt @@ -139,9 +139,12 @@ class RichTextParser { val imagesForPager = urlSet.mapNotNull { fullUrl -> createMediaContent(fullUrl, imetas, content, callbackUri) }.associateBy { it.url } + val imageUrls = imagesForPager.filterValues { it is MediaUrlImage }.keys + val videoUrls = imagesForPager.filterValues { it is MediaUrlVideo }.keys + val emojiMap = CustomEmoji.createEmojiMap(tags) - val segments = findTextSegments(content, imagesForPager.keys, urlSet, emojiMap, tags) + val segments = findTextSegments(content, imageUrls, videoUrls, urlSet, emojiMap, tags) val base64Images = segments.map { it.words.filterIsInstance() }.flatten() @@ -164,6 +167,7 @@ class RichTextParser { private fun findTextSegments( content: String, images: Set, + videos: Set, urls: Set, emojis: Map, tags: ImmutableListOfLists, @@ -177,7 +181,7 @@ class RichTextParser { val wordList = paragraph.trimEnd().split(' ') val segments = ArrayList(wordList.size) wordList.forEach { word -> - segments.add(wordIdentifier(word, images, urls, emojis, tags)) + segments.add(wordIdentifier(word, images, videos, urls, emojis, tags)) } paragraphSegments.add(ParagraphState(segments.toPersistentList(), isRTL)) @@ -229,6 +233,7 @@ class RichTextParser { private fun wordIdentifier( word: String, images: Set, + videos: Set, urls: Set, emojis: Map, tags: ImmutableListOfLists, @@ -239,6 +244,8 @@ class RichTextParser { if (images.contains(word)) return ImageSegment(word) + if (videos.contains(word)) return VideoSegment(word) + if (urls.contains(word)) return LinkSegment(word) if (CustomEmoji.fastMightContainEmoji(word, emojis) && emojis.any { word.contains(it.key) }) return EmojiSegment(word)