From b8352381e562591cfa42a2a473872407194dace7 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Tue, 28 Apr 2026 11:31:36 +0200 Subject: [PATCH 1/2] links in parent messages are not clickable Signed-off-by: sowjanyakch --- .../talk/ui/chat/ChatMessageScaffold.kt | 16 ++++++++-- .../talk/ui/chat/MentionEnrichedText.kt | 30 ++++++++++++++----- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt index 9a5e85c020..29434ff637 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt @@ -136,6 +136,10 @@ private fun shouldShowTimeNextToContent( private val mentionChipTypes = setOf("user", "guest", "call", "user-group", "email", "circle") +private val parentMessageLinkRegex = Regex( + """https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/[^\s)]*)?""" +) + private fun ChatMessageUi.hasMentionChips(): Boolean = messageParameters.any { (key, parameter) -> message.contains("{$key}") && parameter["type"] in mentionChipTypes @@ -686,9 +690,13 @@ fun CommonMessageQuote(message: ChatMessageUi) { fontSize = authorTextSize, color = colorResource(R.color.no_emphasis_text) ) + + val hasParentLink = parentMessageLinkRegex.containsMatchIn(message.message) + EnrichedText( - message = message, - modifier = Modifier.padding(end = 4.dp), + message, + Modifier.padding(start = 10.dp), + !hasParentLink, maxLines = 4 ) } @@ -800,7 +808,8 @@ internal fun resolveMarkdownSource(message: ChatMessageUi): String { } @Composable -fun EnrichedText(message: ChatMessageUi, modifier: Modifier, maxLines: Int = Int.MAX_VALUE) { +fun EnrichedText(message: ChatMessageUi, modifier: Modifier, enableLinks: Boolean = true,maxLines: Int = Int + .MAX_VALUE) { val isInspectionMode = LocalInspectionMode.current val isSingleEmoji = !isInspectionMode && message.messageParameters.isEmpty() && @@ -824,6 +833,7 @@ fun EnrichedText(message: ChatMessageUi, modifier: Modifier, maxLines: Int = Int color = colorScheme.onSurface, lineHeight = fontSize * LINE_SPACING ), + enableLinks = enableLinks, maxLines = maxLines ) } diff --git a/app/src/main/java/com/nextcloud/talk/ui/chat/MentionEnrichedText.kt b/app/src/main/java/com/nextcloud/talk/ui/chat/MentionEnrichedText.kt index 9e6cc8831a..dc21ac899d 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/chat/MentionEnrichedText.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/chat/MentionEnrichedText.kt @@ -38,6 +38,7 @@ fun MentionEnrichedText( message: ChatMessageUi, modifier: Modifier = Modifier, textStyle: TextStyle, + enableLinks: Boolean = true, maxLines: Int = Int.MAX_VALUE ) { var isMultilineLayout by remember(message.id, message.message) { @@ -45,13 +46,14 @@ fun MentionEnrichedText( } val linkColor = MaterialTheme.colorScheme.primary val codeBackground = MaterialTheme.colorScheme.surfaceVariant - val richText = remember(message, isMultilineLayout, linkColor, codeBackground, textStyle) { + val richText = remember(message, isMultilineLayout, linkColor, codeBackground, textStyle, enableLinks) { buildMentionRichText( message = message, linkColor = linkColor, codeBackground = codeBackground, textStyle = textStyle, - isMultilineLayout = isMultilineLayout + isMultilineLayout = isMultilineLayout, + enableLinks = enableLinks ) } val resolvedTextStyle = if (richText.inlineContent.isEmpty()) { @@ -76,12 +78,14 @@ fun MentionEnrichedText( ) } +@Suppress("LongParameterList") private fun buildMentionRichText( message: ChatMessageUi, linkColor: Color, codeBackground: Color, textStyle: TextStyle, - isMultilineLayout: Boolean + isMultilineLayout: Boolean, + enableLinks: Boolean ): MentionRichText { val inlineContent = linkedMapOf() var mentionCounter = 0 @@ -136,10 +140,13 @@ private fun buildMentionRichText( token.startsWith("[") -> { val textPart = token.substringAfter("[").substringBefore("]") val url = token.substringAfter("(").substringBefore(")") - appendLinkedToken(textPart, url, linkColor) + appendLinkedToken(textPart, url, linkColor, enableLinks) } - token.startsWith("http") -> appendLinkedToken(token, token, linkColor) + token.startsWith("http") -> appendLinkedToken(token, token, linkColor, enableLinks) + token.matches( + Regex("""https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}(/[^\s)]*)?""") + ) -> appendLinkedToken(token, token, linkColor, enableLinks) } lastIndex = range.last + 1 @@ -159,11 +166,18 @@ private fun AnnotatedString.Builder.appendStyledToken(text: String, style: SpanS addStyle(style, start, length) } -private fun AnnotatedString.Builder.appendLinkedToken(text: String, url: String, linkColor: Color) { +private fun AnnotatedString.Builder.appendLinkedToken( + text: String, + url: String, + linkColor: Color, + enableLinks: Boolean +) { val start = length append(text) - addStyle(SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline), start, length) - addLink(LinkAnnotation.Url(url), start, length) + if (enableLinks) { + addStyle(SpanStyle(color = linkColor, textDecoration = TextDecoration.Underline), start, length) + addLink(LinkAnnotation.Url(url), start, length) + } } private fun AnnotatedString.Builder.appendFallbackParameter( From 8ebaa1e6242e052e277c558dc4851f680f1183a8 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 4 May 2026 12:31:52 +0200 Subject: [PATCH 2/2] fix lint Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt index 29434ff637..2039c026d3 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/chat/ChatMessageScaffold.kt @@ -808,8 +808,12 @@ internal fun resolveMarkdownSource(message: ChatMessageUi): String { } @Composable -fun EnrichedText(message: ChatMessageUi, modifier: Modifier, enableLinks: Boolean = true,maxLines: Int = Int - .MAX_VALUE) { +fun EnrichedText( + message: ChatMessageUi, + modifier: Modifier, + enableLinks: Boolean = true, + maxLines: Int = Int.MAX_VALUE +) { val isInspectionMode = LocalInspectionMode.current val isSingleEmoji = !isInspectionMode && message.messageParameters.isEmpty() &&