From 465d7794016265f5e178d8313dd859d9e99f9eed Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Fri, 18 Jul 2025 23:24:58 +0200 Subject: [PATCH 1/7] extract markwon Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/utils/MarkwonUtils.kt | 43 +++++++++++++++++++ .../talk/utils/message/MessageUtils.kt | 19 ++------ 2 files changed, 46 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt diff --git a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt new file mode 100644 index 0000000000..a4a42b0f6f --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt @@ -0,0 +1,43 @@ +/* + * Nextcloud Talk - Android Client + * + * SPDX-FileCopyrightText: 2025 Your Name + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package com.nextcloud.talk.utils + +import android.content.Context +import android.util.Log +import android.view.View +import com.nextcloud.talk.R +import io.noties.markwon.AbstractMarkwonPlugin +import io.noties.markwon.Markwon +import io.noties.markwon.MarkwonConfiguration +import io.noties.markwon.core.MarkwonTheme +import io.noties.markwon.ext.strikethrough.StrikethroughPlugin +import io.noties.markwon.ext.tasklist.TaskListDrawable +import io.noties.markwon.ext.tasklist.TaskListPlugin + +object MarkwonUtils { + private const val TAG = "MarkwonUtils" + + fun build(context: Context, textColor: Int): Markwon { + val drawable = TaskListDrawable(textColor, textColor, context.getColor(R.color.bg_default)) + return Markwon.builder(context) + .usePlugin(object : AbstractMarkwonPlugin() { + override fun configureTheme(builder: MarkwonTheme.Builder) { + builder.isLinkUnderlined(true).headingBreakHeight(0) + } + + override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { + builder.linkResolver { view: View?, link: String? -> + Log.i(TAG, "Link action not implemented $view / $link") + } + } + }) + .usePlugin(TaskListPlugin.create(drawable)) + .usePlugin(StrikethroughPlugin.create()) + .build() + } +} diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index 6beeafecab..edb1f1cdf0 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -9,13 +9,13 @@ package com.nextcloud.talk.utils.message import android.content.Context import android.content.Intent import android.graphics.Typeface +import android.net.Uri import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.Spanned import android.text.style.StyleSpan import android.util.Log import android.view.View -import androidx.core.net.toUri import com.nextcloud.talk.R import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.ui.theme.ViewThemeUtils @@ -28,6 +28,7 @@ import io.noties.markwon.ext.strikethrough.StrikethroughPlugin import io.noties.markwon.ext.tables.TablePlugin import io.noties.markwon.ext.tasklist.TaskListDrawable import io.noties.markwon.ext.tasklist.TaskListPlugin +import com.nextcloud.talk.utils.MarkwonUtils class MessageUtils(val context: Context) { fun enrichChatReplyMessageText( @@ -203,21 +204,7 @@ class MessageUtils(val context: Context) { } fun getRenderedMarkdownText(context: Context, markdown: String, textColor: Int): Spanned { - val drawable = TaskListDrawable(textColor, textColor, context.getColor(R.color.bg_default)) - val markwon = Markwon.builder(context).usePlugin(object : AbstractMarkwonPlugin() { - override fun configureTheme(builder: MarkwonTheme.Builder) { - builder.isLinkUnderlined(true).headingBreakHeight(0) - } - - override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { - builder.linkResolver { view: View?, link: String? -> - Log.i(TAG, "Link action not implemented $view / $link") - } - } - }) - .usePlugin(TaskListPlugin.create(drawable)) - .usePlugin(TablePlugin.create { _ -> }) - .usePlugin(StrikethroughPlugin.create()).build() + val markwon = MarkwonUtils.build(context, textColor) return markwon.toMarkdown(markdown) } From 5fb1ae4560353fc452bae000d7ff5d25b3fcde5c Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 14:41:38 +0200 Subject: [PATCH 2/7] handle markdown links Signed-off-by: sowjanyakch --- .../com/nextcloud/talk/utils/MarkwonUtils.kt | 28 ++++++++++++++++--- .../talk/utils/message/MessageUtils.kt | 14 ++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt index a4a42b0f6f..7472454f51 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt @@ -7,17 +7,22 @@ package com.nextcloud.talk.utils +import android.annotation.SuppressLint import android.content.Context -import android.util.Log +import android.content.Intent +import android.text.method.ScrollingMovementMethod import android.view.View +import androidx.core.net.toUri import com.nextcloud.talk.R import io.noties.markwon.AbstractMarkwonPlugin +import io.noties.markwon.LinkResolverDef import io.noties.markwon.Markwon import io.noties.markwon.MarkwonConfiguration import io.noties.markwon.core.MarkwonTheme import io.noties.markwon.ext.strikethrough.StrikethroughPlugin import io.noties.markwon.ext.tasklist.TaskListDrawable import io.noties.markwon.ext.tasklist.TaskListPlugin +import io.noties.markwon.movement.MovementMethodPlugin object MarkwonUtils { private const val TAG = "MarkwonUtils" @@ -31,13 +36,28 @@ object MarkwonUtils { } override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { - builder.linkResolver { view: View?, link: String? -> - Log.i(TAG, "Link action not implemented $view / $link") - } + builder.linkResolver(object : LinkResolverDef() { + @SuppressLint("SuspiciousIndentation") + override fun resolve(view: View, link: String) { + var linkToOpen = link + if (!(linkToOpen.contains("http://") || linkToOpen.contains("https://"))) { + linkToOpen = "https://$link" + } else { + linkToOpen = link + } + + val browserIntent = Intent( + Intent.ACTION_VIEW, + linkToOpen.toUri() + ) + context.startActivity(browserIntent) + } + }) } }) .usePlugin(TaskListPlugin.create(drawable)) .usePlugin(StrikethroughPlugin.create()) + .usePlugin(MovementMethodPlugin.create(ScrollingMovementMethod.getInstance())) .build() } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index edb1f1cdf0..18f55051ae 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -16,6 +16,7 @@ import android.text.Spanned import android.text.style.StyleSpan import android.util.Log import android.view.View +import android.widget.TextView import com.nextcloud.talk.R import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.ui.theme.ViewThemeUtils @@ -208,6 +209,19 @@ class MessageUtils(val context: Context) { return markwon.toMarkdown(markdown) } + fun isMarkdownInlineLink(text: String): Boolean { + val markdownLinkRegex = Regex("""\[([^\]]+?)]\((.*?)(?:\s+"[^"]*")?\)""") + return markdownLinkRegex.containsMatchIn(text) + } + + fun hyperLinks(view: TextView, text: String) { + val isMarkdownLink = isMarkdownInlineLink(text) + if (isMarkdownLink) { + view.autoLinkMask = 0 + } else { + view.autoLinkMask = 15 + } + } companion object { private const val TAG = "MessageUtils" const val MAX_REPLY_LENGTH = 250 From ee01481a1deb965baea7828cbf2927e718ca6097 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 14:43:32 +0200 Subject: [PATCH 3/7] refactor Signed-off-by: sowjanyakch --- app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt index 7472454f51..ad7020d6cc 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt @@ -7,7 +7,6 @@ package com.nextcloud.talk.utils -import android.annotation.SuppressLint import android.content.Context import android.content.Intent import android.text.method.ScrollingMovementMethod @@ -37,15 +36,11 @@ object MarkwonUtils { override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { builder.linkResolver(object : LinkResolverDef() { - @SuppressLint("SuspiciousIndentation") override fun resolve(view: View, link: String) { var linkToOpen = link if (!(linkToOpen.contains("http://") || linkToOpen.contains("https://"))) { linkToOpen = "https://$link" - } else { - linkToOpen = link } - val browserIntent = Intent( Intent.ACTION_VIEW, linkToOpen.toUri() From 649bf48eccf80593b223d39ea354b9600208a0dc Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 17:09:25 +0200 Subject: [PATCH 4/7] markdown links work Signed-off-by: sowjanyakch --- .../messages/IncomingTextMessageViewHolder.kt | 5 +++++ .../messages/OutcomingTextMessageViewHolder.kt | 4 ++++ .../com/nextcloud/talk/utils/message/MessageUtils.kt | 11 +---------- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt index fad7b0e4af..fe05df008e 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingTextMessageViewHolder.kt @@ -106,6 +106,10 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : viewThemeUtils ) + message.message?.let { + messageUtils.hyperLinks(binding.messageText, message.message!!) + } + val spansFromString: Array = processedMessageText!!.getSpans( 0, processedMessageText.length, @@ -135,6 +139,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : message, itemView ) + val messageParameters = message.messageParameters if ( (messageParameters == null || messageParameters.size <= 0) && diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt index 412dcfbbf8..10de0843a0 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingTextMessageViewHolder.kt @@ -117,6 +117,10 @@ class OutcomingTextMessageViewHolder(itemView: View) : viewThemeUtils ) + message.message?.let { + messageUtils.hyperLinks(binding.messageText, message.message!!) + } + val spansFromString: Array = processedMessageText!!.getSpans( 0, processedMessageText.length, diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index 18f55051ae..efb006f756 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -9,26 +9,17 @@ package com.nextcloud.talk.utils.message import android.content.Context import android.content.Intent import android.graphics.Typeface -import android.net.Uri import android.text.SpannableString import android.text.SpannableStringBuilder import android.text.Spanned import android.text.style.StyleSpan -import android.util.Log import android.view.View import android.widget.TextView +import androidx.core.net.toUri import com.nextcloud.talk.R import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils -import io.noties.markwon.AbstractMarkwonPlugin -import io.noties.markwon.Markwon -import io.noties.markwon.MarkwonConfiguration -import io.noties.markwon.core.MarkwonTheme -import io.noties.markwon.ext.strikethrough.StrikethroughPlugin -import io.noties.markwon.ext.tables.TablePlugin -import io.noties.markwon.ext.tasklist.TaskListDrawable -import io.noties.markwon.ext.tasklist.TaskListPlugin import com.nextcloud.talk.utils.MarkwonUtils class MessageUtils(val context: Context) { From 27aa10a014d5f918bda3838daa66c36eb6780e95 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 17:16:05 +0200 Subject: [PATCH 5/7] use proper naming + plugins Signed-off-by: sowjanyakch --- .../talk/utils/{MarkwonUtils.kt => MarkdownUtils.kt} | 11 ++++++----- .../com/nextcloud/talk/utils/message/MessageUtils.kt | 4 ++-- 2 files changed, 8 insertions(+), 7 deletions(-) rename app/src/main/java/com/nextcloud/talk/utils/{MarkwonUtils.kt => MarkdownUtils.kt} (88%) diff --git a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt similarity index 88% rename from app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt rename to app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt index ad7020d6cc..364d6f996e 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/MarkwonUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt @@ -9,7 +9,7 @@ package com.nextcloud.talk.utils import android.content.Context import android.content.Intent -import android.text.method.ScrollingMovementMethod +import android.util.Log import android.view.View import androidx.core.net.toUri import com.nextcloud.talk.R @@ -19,12 +19,12 @@ import io.noties.markwon.Markwon import io.noties.markwon.MarkwonConfiguration import io.noties.markwon.core.MarkwonTheme import io.noties.markwon.ext.strikethrough.StrikethroughPlugin +import io.noties.markwon.ext.tables.TablePlugin import io.noties.markwon.ext.tasklist.TaskListDrawable import io.noties.markwon.ext.tasklist.TaskListPlugin -import io.noties.markwon.movement.MovementMethodPlugin -object MarkwonUtils { - private const val TAG = "MarkwonUtils" +object MarkdownUtils { + private const val TAG = "MarkdownUtils" fun build(context: Context, textColor: Int): Markwon { val drawable = TaskListDrawable(textColor, textColor, context.getColor(R.color.bg_default)) @@ -37,6 +37,7 @@ object MarkwonUtils { override fun configureConfiguration(builder: MarkwonConfiguration.Builder) { builder.linkResolver(object : LinkResolverDef() { override fun resolve(view: View, link: String) { + Log.i(TAG, "Link - $view / $link") var linkToOpen = link if (!(linkToOpen.contains("http://") || linkToOpen.contains("https://"))) { linkToOpen = "https://$link" @@ -52,7 +53,7 @@ object MarkwonUtils { }) .usePlugin(TaskListPlugin.create(drawable)) .usePlugin(StrikethroughPlugin.create()) - .usePlugin(MovementMethodPlugin.create(ScrollingMovementMethod.getInstance())) + .usePlugin(TablePlugin.create { _ -> }) .build() } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index efb006f756..146f689070 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -20,7 +20,7 @@ import com.nextcloud.talk.R import com.nextcloud.talk.chat.data.model.ChatMessage import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils -import com.nextcloud.talk.utils.MarkwonUtils +import com.nextcloud.talk.utils.MarkdownUtils class MessageUtils(val context: Context) { fun enrichChatReplyMessageText( @@ -196,7 +196,7 @@ class MessageUtils(val context: Context) { } fun getRenderedMarkdownText(context: Context, markdown: String, textColor: Int): Spanned { - val markwon = MarkwonUtils.build(context, textColor) + val markwon = MarkdownUtils.build(context, textColor) return markwon.toMarkdown(markdown) } From 0c0cae40a2631d426f261e88029c4fadf704a944 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 17:18:00 +0200 Subject: [PATCH 6/7] include copyright Signed-off-by: sowjanyakch --- app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt index 364d6f996e..8248caa535 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/MarkdownUtils.kt @@ -1,7 +1,7 @@ /* * Nextcloud Talk - Android Client * - * SPDX-FileCopyrightText: 2025 Your Name + * SPDX-FileCopyrightText: 2025 Sowjanya Kota * SPDX-License-Identifier: GPL-3.0-or-later */ From dfd5cb933531410ccd509e02d029008cb0e9c0d3 Mon Sep 17 00:00:00 2001 From: sowjanyakch Date: Mon, 21 Jul 2025 17:27:20 +0200 Subject: [PATCH 7/7] use constants Signed-off-by: sowjanyakch --- .../java/com/nextcloud/talk/utils/message/MessageUtils.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt index 146f689070..9a6547aff7 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/message/MessageUtils.kt @@ -208,13 +208,15 @@ class MessageUtils(val context: Context) { fun hyperLinks(view: TextView, text: String) { val isMarkdownLink = isMarkdownInlineLink(text) if (isMarkdownLink) { - view.autoLinkMask = 0 + view.autoLinkMask = AUTO_LINK_NONE } else { - view.autoLinkMask = 15 + view.autoLinkMask = AUTO_LINK_ALL } } companion object { private const val TAG = "MessageUtils" const val MAX_REPLY_LENGTH = 250 + const val AUTO_LINK_NONE = 0 + const val AUTO_LINK_ALL = 15 } }