diff --git a/app/build.gradle b/app/build.gradle index 5392817f18..85f377d81b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -144,12 +144,13 @@ ext { emojiVersion = "1.3.0" lifecycleVersion = '2.6.1' okhttpVersion = "4.11.0" + markwonVersion = "4.6.2" materialDialogsVersion = "3.3.0" parcelerVersion = "1.1.13" + prismVersion = "2.0.0" retrofit2Version = "2.9.0" roomVersion = "2.5.2" workVersion = "2.8.1" - markwonVersion = "4.6.2" espressoVersion = "3.5.1" } @@ -157,6 +158,7 @@ configurations.all { exclude group: 'com.google.firebase', module: 'firebase-core' exclude group: 'com.google.firebase', module: 'firebase-analytics' exclude group: 'com.google.firebase', module: 'firebase-measurement-connector' + exclude group: 'org.jetbrains', module: 'annotations-java5' // via prism4j, already using annotations explicitly } dependencies { @@ -262,12 +264,14 @@ dependencies { implementation "com.afollestad.material-dialogs:lifecycle:${materialDialogsVersion}" implementation 'com.google.code.gson:gson:2.10.1' - implementation 'com.google.android.exoplayer:exoplayer:2.19.0' + implementation 'com.google.android.exoplayer:exoplayer:2.18.7' implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'pl.droidsonroids.gif:android-gif-drawable:1.2.27' implementation "io.noties.markwon:core:$markwonVersion" + implementation "io.noties.markwon:ext-strikethrough:$markwonVersion" + implementation "io.noties.markwon:syntax-highlight:$markwonVersion" implementation 'com.github.nextcloud-deps:ImagePicker:2.1.0.2' implementation 'com.elyeproj.libraries:loaderviewlibrary:2.0.0' 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 33dcf4f37d..6d378e9186 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 @@ -29,8 +29,7 @@ package com.nextcloud.talk.adapters.messages import android.content.Context import android.content.Intent import android.net.Uri -import android.text.Spannable -import android.text.SpannableString +import android.text.Spanned import android.text.TextUtils import android.util.TypedValue import android.view.View @@ -84,13 +83,13 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : itemView.isSelected = false - var messageString: Spannable = SpannableString(message.message) - var textSize = context.resources!!.getDimension(R.dimen.chat_text_size) + var processedMessageText = DisplayUtils.getRenderedMarkdownText(context, message.message) + val messageParameters = message.messageParameters if (messageParameters != null && messageParameters.size > 0) { - messageString = processMessageParameters(messageParameters, message, messageString) + processedMessageText = processMessageParameters(messageParameters, message, processedMessageText) } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() itemView.isSelected = true @@ -98,7 +97,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : } binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) - binding.messageText.text = messageString + binding.messageText.text = processedMessageText binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) @@ -219,8 +218,8 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : private fun processMessageParameters( messageParameters: HashMap>, message: ChatMessage, - messageString: Spannable - ): Spannable { + messageString: Spanned + ): Spanned { var messageStringInternal = messageString for (key in messageParameters.keys) { val individualHashMap = message.messageParameters!![key] @@ -253,6 +252,7 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : } } } + return messageStringInternal } 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 66021b1815..65a5da5a38 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 @@ -27,8 +27,7 @@ import android.content.Context import android.content.Intent import android.graphics.PorterDuff import android.net.Uri -import android.text.Spannable -import android.text.SpannableString +import android.text.Spanned import android.util.TypedValue import android.view.View import androidx.core.content.res.ResourcesCompat @@ -70,15 +69,17 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH super.onBind(message) sharedApplication!!.componentApplication.inject(this) val messageParameters: HashMap>? = message.messageParameters - var messageString: Spannable = SpannableString(message.message) realView.isSelected = false val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams layoutParams.isWrapBefore = false var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) val textColor = viewThemeUtils.getScheme(binding.messageText.context).onSurfaceVariant + + var processedMessageText = DisplayUtils.getRenderedMarkdownText(context, message.message) + binding.messageTime.setTextColor(textColor) if (messageParameters != null && messageParameters.size > 0) { - messageString = processMessageParameters(messageParameters, message, messageString) + processedMessageText = processMessageParameters(messageParameters, message, processedMessageText) } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() layoutParams.isWrapBefore = true @@ -90,7 +91,7 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageTime.layoutParams = layoutParams binding.messageText.setTextColor(textColor) - binding.messageText.text = messageString + binding.messageText.text = processedMessageText binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp) @@ -183,8 +184,8 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH private fun processMessageParameters( messageParameters: HashMap>, message: ChatMessage, - messageString: Spannable - ): Spannable { + messageString: Spanned + ): Spanned { var messageStringInternal = messageString for (key in messageParameters.keys) { val individualHashMap: HashMap? = message.messageParameters!![key] diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index 3176cda00a..dd4df70392 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -48,6 +48,7 @@ import android.text.style.ClickableSpan; import android.text.style.ForegroundColorSpan; import android.text.style.StyleSpan; +import android.util.Log; import android.util.TypedValue; import android.view.View; import android.view.Window; @@ -87,6 +88,11 @@ import coil.request.ImageRequest; import coil.target.Target; import coil.transform.CircleCropTransformation; +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 third.parties.fresco.BetterImageSpan; import static com.nextcloud.talk.utils.FileSortOrder.sort_a_to_z_id; @@ -97,6 +103,7 @@ import static com.nextcloud.talk.utils.FileSortOrder.sort_z_to_a_id; public class DisplayUtils { + private static final String TAG = DisplayUtils.class.getSimpleName(); private static final int INDEX_LUMINATION = 2; private static final double MAX_LIGHTNESS = 0.92; @@ -246,7 +253,28 @@ public void onSuccess(@NonNull Drawable drawable) { return chip; } - public static Spannable searchAndReplaceWithMentionSpan(String key, Context context, Spannable text, + public static Spanned getRenderedMarkdownText(Context context, String markdown) { + final Markwon markwon = Markwon.builder(context) + .usePlugin(new AbstractMarkwonPlugin() { + @Override + public void configureTheme(@NonNull MarkwonTheme.Builder builder) { + builder.headingBreakHeight(0); + } + + @Override + public void configureConfiguration(@NonNull MarkwonConfiguration.Builder builder) { + builder.linkResolver((view, link) -> { + Log.i(TAG, "Link action not implemented" ); + }); + } + }) + .usePlugin(StrikethroughPlugin.create()) + .build(); + + return markwon.toMarkdown(markdown); + } + + public static Spannable searchAndReplaceWithMentionSpan(String key, Context context, Spanned text, String id, String label, String type, User conversationUser, @XmlRes int chipXmlRes, diff --git a/build.gradle b/build.gradle index 5a4c6f4f2f..53deae3408 100644 --- a/build.gradle +++ b/build.gradle @@ -47,6 +47,7 @@ buildscript { } configurations.all { + exclude group: 'org.jetbrains', module: 'annotations-java5' // via prism4j, already using annotations explicitly // check for updates every build resolutionStrategy.cacheChangingModulesFor 3600, 'seconds' }