Adds Relay Url to the Rich Text viewer

This commit is contained in:
Vitor Pamplona
2026-03-01 12:45:47 -05:00
parent ca6af92411
commit 7212e9a879
3 changed files with 74 additions and 2 deletions
@@ -0,0 +1,60 @@
/*
* Copyright (c) 2025 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 android.R.attr.maxLines
import android.R.attr.onClick
import androidx.compose.foundation.combinedClickable
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.style.TextOverflow
import com.vitorpamplona.amethyst.ui.components.appendLink
import com.vitorpamplona.amethyst.ui.navigation.navs.INav
import com.vitorpamplona.amethyst.ui.navigation.routes.Route
@Composable
fun ClickableRelayUrl(
relayUrl: String,
nav: INav,
) {
val clipboardManager = LocalClipboardManager.current
val clickableModifier =
remember(relayUrl) {
Modifier
.combinedClickable(
onLongClick = { clipboardManager.setText(AnnotatedString(relayUrl)) },
onClick = { nav.nav(Route.RelayInfo(relayUrl)) },
)
}
Text(
text = relayUrl,
modifier = clickableModifier,
color = MaterialTheme.colorScheme.primary,
overflow = TextOverflow.MiddleEllipsis,
maxLines = 1,
)
}
@@ -79,6 +79,7 @@ import com.vitorpamplona.amethyst.commons.richtext.LinkSegment
import com.vitorpamplona.amethyst.commons.richtext.ParagraphState
import com.vitorpamplona.amethyst.commons.richtext.PhoneSegment
import com.vitorpamplona.amethyst.commons.richtext.RegularTextSegment
import com.vitorpamplona.amethyst.commons.richtext.RelayUrlSegment
import com.vitorpamplona.amethyst.commons.richtext.RichTextViewerState
import com.vitorpamplona.amethyst.commons.richtext.SchemelessUrlSegment
import com.vitorpamplona.amethyst.commons.richtext.SecretEmoji
@@ -148,7 +149,7 @@ fun RichTextViewer(
fun RenderStrangeNamePreview() {
Column(modifier = Modifier.padding(10.dp)) {
RenderRegular(
"If you want to FreeFrom Official \uD80C\uDD66 stream or download the music from nostr:npub1sctag667a7np6p6ety2up94pnwwxhd2ep8n8afr2gtr47cwd4ewsvdmmjm can you here",
"If you want to FreeFrom Official \uD80C\uDD66 stream or download the music from nostr:npub1sctag667a7np6p6ety2up94pnwwxhd2ep8n8afr2gtr47cwd4ewsvdmmjm at wss://relay.damus.io can you here",
EmptyTagList,
) { paragraph, state, spaceWidth, modifier ->
RenderTextParagraph(paragraph, spaceWidth, modifier) { word ->
@@ -163,6 +164,10 @@ fun RenderStrangeNamePreview() {
is RegularTextSegment -> {
Text(word.segmentText)
}
is RelayUrlSegment -> {
ClickableRelayUrl(word.segmentText, EmptyNav())
}
}
}
}
@@ -254,6 +259,8 @@ fun RenderRegularPreview2() {
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
is RelayUrlSegment -> ClickableRelayUrl(word.segmentText, EmptyNav())
}
}
}
@@ -302,6 +309,8 @@ fun RenderRegularPreview3() {
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
is RelayUrlSegment -> ClickableRelayUrl(word.segmentText, EmptyNav())
}
}
}
@@ -478,6 +487,8 @@ private fun RenderWordWithoutPreview(
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
is RelayUrlSegment -> ClickableRelayUrl(word.segmentText, nav)
}
}
@@ -509,6 +520,7 @@ private fun RenderWordWithPreview(
is SchemelessUrlSegment -> NoProtocolUrlRenderer(word)
is RegularTextSegment -> Text(word.segmentText)
is Base64Segment -> ZoomableContentView(word.segmentText, state, accountViewModel)
is RelayUrlSegment -> ClickableRelayUrl(word.segmentText, nav)
}
}
@@ -245,7 +245,7 @@ class RichTextParser {
if (videos.contains(word)) return VideoSegment(word)
if (word.startsWith("ws://", ignoreCase = true) || word.startsWith("wss://", ignoreCase = true)) return RelayUrlSegment(word)
if (word.startsWith("ws://") || word.startsWith("wss://")) return RelayUrlSegment(word)
if (urls.contains(word)) return LinkSegment(word)