unify markdown rendering of chat messages

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2023-07-07 14:45:54 +02:00
parent d124301809
commit fa8fd7b229
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
14 changed files with 321 additions and 137 deletions

View File

@ -264,14 +264,15 @@ dependencies {
implementation "com.afollestad.material-dialogs:lifecycle:${materialDialogsVersion}"
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.google.android.exoplayer:exoplayer:2.18.7'
implementation 'com.google.android.exoplayer:exoplayer:2.19.0'
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 "io.noties.markwon:ext-tables:$markwonVersion"
implementation "io.noties.markwon:ext-tasklist:$markwonVersion"
implementation 'com.github.nextcloud-deps:ImagePicker:2.1.0.2'
implementation 'com.elyeproj.libraries:loaderviewlibrary:2.0.0'

View File

@ -40,6 +40,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject
@ -60,6 +61,9 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -77,6 +81,22 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
sharedApplication!!.componentApplication.inject(this)
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
var processedMessageText = messageUtils.enrichChatMessageText(
binding.messageText.context,
message,
binding.messageText.context.resources.getColor(R.color.nc_incoming_text_default)
)
processedMessageText = messageUtils.processMessageParameters(
binding.messageText.context,
viewThemeUtils,
processedMessageText!!,
message,
itemView
)
binding.messageText.text = processedMessageText
setAvatarAndAuthorOnMessageItem(message)
colorizeMessageBubble(message)
@ -174,7 +194,14 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
binding.messageQuote.quotedMessage.context.resources.getColor(
R.color.nc_incoming_text_default
)
)
binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))

View File

@ -51,6 +51,7 @@ import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import java.net.URLEncoder
@ -76,6 +77,9 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -175,7 +179,14 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
binding.messageQuote.quotedMessage.context.resources.getColor(
R.color.nc_incoming_text_default
)
)
binding.messageQuote.quotedMessageAuthor
.setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast, null))

View File

@ -40,6 +40,7 @@ import com.nextcloud.talk.polls.ui.PollMainDialogFragment
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject
@ -59,6 +60,9 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -198,7 +202,14 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
binding.messageQuote.quotedMessage.context.resources.getColor(
R.color.nc_incoming_text_default
)
)
binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))

View File

@ -27,9 +27,6 @@
package com.nextcloud.talk.adapters.messages
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.text.Spanned
import android.text.TextUtils
import android.util.TypedValue
import android.view.View
@ -49,6 +46,7 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.TextMatchers
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject
@ -65,6 +63,9 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var appPreferences: AppPreferences
@ -85,12 +86,25 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
var textSize = context.resources!!.getDimension(R.dimen.chat_text_size)
var processedMessageText = DisplayUtils.getRenderedMarkdownText(context, message.message)
var processedMessageText = messageUtils.enrichChatMessageText(
binding.messageText.context,
message,
binding.messageText.context.resources.getColor(R.color.nc_incoming_text_default)
)
processedMessageText = messageUtils.processMessageParameters(
binding.messageText.context,
viewThemeUtils,
processedMessageText!!,
message,
itemView
)
val messageParameters = message.messageParameters
if (messageParameters != null && messageParameters.size > 0) {
processedMessageText = processMessageParameters(messageParameters, message, processedMessageText)
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
if (
(messageParameters == null || messageParameters.size <= 0) &&
TextMatchers.isMessageWithSingleEmoticonOnly(message.text)
) {
textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
itemView.isSelected = true
binding.messageAuthor.visibility = View.GONE
@ -188,7 +202,12 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
} else {
parentChatMessage.actorDisplayName
}
binding.messageQuote.quotedMessage.text = DisplayUtils.ellipsize(parentChatMessage.text, MAX_REPLY_LENGTH)
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
DisplayUtils.ellipsize(parentChatMessage.text, MAX_REPLY_LENGTH),
binding.messageQuote.quotedMessage.context.resources.getColor(R.color.nc_incoming_text_default)
)
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
viewThemeUtils.platform.colorViewBackground(binding.messageQuote.quoteColoredView)
@ -215,47 +234,6 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) :
}
}
private fun processMessageParameters(
messageParameters: HashMap<String?, HashMap<String?, String?>>,
message: ChatMessage,
messageString: Spanned
): Spanned {
var messageStringInternal = messageString
for (key in messageParameters.keys) {
val individualHashMap = message.messageParameters!![key]
if (individualHashMap != null) {
when (individualHashMap["type"]) {
"user", "guest", "call", "user-group" -> {
val chip = if (individualHashMap["id"] == message.activeUser!!.userId) {
R.xml.chip_you
} else {
R.xml.chip_others
}
messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
key,
binding.messageText.context,
messageStringInternal,
individualHashMap["id"]!!,
individualHashMap["name"]!!,
individualHashMap["type"]!!,
message.activeUser!!,
chip,
viewThemeUtils
)
}
"file" -> {
itemView.setOnClickListener { v ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
context.startActivity(browserIntent)
}
}
}
}
}
return messageStringInternal
}
fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) {
this.commonMessageInterface = commonMessageInterface
}

View File

@ -49,6 +49,7 @@ import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import java.util.concurrent.ExecutionException
@ -67,6 +68,9 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -285,7 +289,14 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
binding.messageQuote.quotedMessage.context.resources.getColor(
R.color.nc_incoming_text_default
)
)
binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))

View File

@ -39,6 +39,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject
@ -56,6 +57,9 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -79,6 +83,16 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
binding.messageTime.text = dateUtils.getLocalTimeStringFromTimestamp(message.timestamp)
colorizeMessageBubble(message)
var processedMessageText = messageUtils.enrichChatMessageText(binding.messageText.context, message, textColor)
processedMessageText = messageUtils.processMessageParameters(
binding.messageText.context,
viewThemeUtils,
processedMessageText!!,
message,
itemView
)
binding.messageText.text = processedMessageText
itemView.isSelected = false
@ -158,7 +172,12 @@ class OutcomingLinkPreviewMessageViewHolder(outcomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant
)
viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)

View File

@ -48,6 +48,7 @@ import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.stfalcon.chatkit.messages.MessageHolders
import java.net.URLEncoder
import javax.inject.Inject
@ -71,6 +72,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -221,7 +225,12 @@ class OutcomingLocationMessageViewHolder(incomingView: View) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant
)
viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)

View File

@ -40,6 +40,7 @@ import com.nextcloud.talk.polls.ui.PollMainDialogFragment
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject
@ -56,6 +57,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -183,7 +187,12 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant
)
viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)

View File

@ -24,10 +24,7 @@
package com.nextcloud.talk.adapters.messages
import android.content.Context
import android.content.Intent
import android.graphics.PorterDuff
import android.net.Uri
import android.text.Spanned
import android.util.TypedValue
import android.view.View
import androidx.core.content.res.ResourcesCompat
@ -46,6 +43,7 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.TextMatchers
import com.nextcloud.talk.utils.message.MessageUtils
import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
import javax.inject.Inject
@ -60,6 +58,9 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -68,19 +69,27 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
override fun onBind(message: ChatMessage) {
super.onBind(message)
sharedApplication!!.componentApplication.inject(this)
val messageParameters: HashMap<String?, HashMap<String?, String?>>? = message.messageParameters
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) {
processedMessageText = processMessageParameters(messageParameters, message, processedMessageText)
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
var processedMessageText = messageUtils.enrichChatMessageText(binding.messageText.context, message, textColor)
processedMessageText = messageUtils.processMessageParameters(
binding.messageText.context,
viewThemeUtils,
processedMessageText!!,
message,
itemView
)
val messageParameters = message.messageParameters
if (
(messageParameters == null || messageParameters.size <= 0) &&
TextMatchers.isMessageWithSingleEmoticonOnly(message.text)
) {
textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
layoutParams.isWrapBefore = true
realView.isSelected = true
@ -165,7 +174,12 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = DisplayUtils.ellipsize(parentChatMessage.text, MAX_REPLY_LENGTH)
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
DisplayUtils.ellipsize(parentChatMessage.text, MAX_REPLY_LENGTH),
textColor
)
binding.messageQuote.quotedMessageAuthor.setTextColor(textColor)
binding.messageQuote.quotedMessage.setTextColor(textColor)
@ -181,46 +195,6 @@ class OutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewH
viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
}
private fun processMessageParameters(
messageParameters: HashMap<String?, HashMap<String?, String?>>,
message: ChatMessage,
messageString: Spanned
): Spanned {
var messageStringInternal = messageString
for (key in messageParameters.keys) {
val individualHashMap: HashMap<String?, String?>? = message.messageParameters!![key]
if (individualHashMap != null) {
when (individualHashMap["type"]) {
"user", "guest", "call", "user-group" -> {
val chip = if (individualHashMap["id"] == message.activeUser!!.userId) {
R.xml.chip_you
} else {
R.xml.chip_others
}
messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
key,
binding.messageText.context,
messageStringInternal,
individualHashMap["id"]!!,
individualHashMap["name"]!!,
individualHashMap["type"]!!,
message.activeUser!!,
chip,
viewThemeUtils
)
}
"file" -> {
itemView.setOnClickListener { v ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
context.startActivity(browserIntent)
}
}
}
}
}
return messageStringInternal
}
fun assignCommonMessageInterface(commonMessageInterface: CommonMessageInterface) {
this.commonMessageInterface = commonMessageInterface
}

View File

@ -45,6 +45,7 @@ import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import java.util.concurrent.ExecutionException
@ -63,6 +64,9 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var messageUtils: MessageUtils
@Inject
lateinit var dateUtils: DateUtils
@ -271,7 +275,12 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) :
}
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.text = messageUtils
.enrichChatMessageText(
binding.messageQuote.quotedMessage.context,
parentChatMessage.text,
viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant
)
viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)

View File

@ -23,6 +23,7 @@ package com.nextcloud.talk.dagger.modules
import android.content.Context
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.message.MessageUtils
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtil
import com.nextcloud.talk.utils.permissions.PlatformPermissionUtilImpl
import dagger.Module
@ -42,4 +43,10 @@ class UtilsModule {
fun provideDateUtils(context: Context): DateUtils {
return DateUtils(context)
}
@Provides
@Reusable
fun provideMessageUtils(context: Context): MessageUtils {
return MessageUtils(context)
}
}

View File

@ -48,7 +48,6 @@ import android.text.style.AbsoluteSizeSpan;
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;
@ -88,11 +87,6 @@ import coil.Coil;
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;
@ -253,27 +247,6 @@ public class DisplayUtils {
return chip;
}
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,

View File

@ -0,0 +1,145 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2023 Andy Scherzinger <info@andy-scherzinger.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.utils.message
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.text.Spanned
import android.util.Log
import android.view.View
import com.nextcloud.talk.R
import com.nextcloud.talk.models.json.chat.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
class MessageUtils(val context: Context) {
fun enrichChatMessageText(context: Context, message: ChatMessage, textColor: Int): Spanned? {
return if (message.message == null) {
null
} else {
enrichChatMessageText(context, message.message!!, textColor)
}
}
fun enrichChatMessageText(context: Context, message: String, textColor: Int): Spanned {
return getRenderedMarkdownText(context, message, textColor)
}
fun processMessageParameters(
themingContext: Context,
viewThemeUtils: ViewThemeUtils,
spannedText: Spanned,
message: ChatMessage,
itemView: View
): Spanned {
var processedMessageText = spannedText
val messageParameters = message.messageParameters
if (messageParameters != null && messageParameters.size > 0) {
processedMessageText = processMessageParameters(
themingContext,
viewThemeUtils,
messageParameters,
message,
processedMessageText,
itemView
)
}
return processedMessageText
}
private fun processMessageParameters(
themingContext: Context,
viewThemeUtils: ViewThemeUtils,
messageParameters: HashMap<String?, HashMap<String?, String?>>,
message: ChatMessage,
messageString: Spanned,
itemView: View
): Spanned {
var messageStringInternal = messageString
for (key in messageParameters.keys) {
val individualHashMap = message.messageParameters!![key]
if (individualHashMap != null) {
when (individualHashMap["type"]) {
"user", "guest", "call", "user-group" -> {
val chip = if (individualHashMap["id"] == message.activeUser!!.userId) {
R.xml.chip_you
} else {
R.xml.chip_others
}
messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
key,
themingContext,
messageStringInternal,
individualHashMap["id"]!!,
individualHashMap["name"]!!,
individualHashMap["type"]!!,
message.activeUser!!,
chip,
viewThemeUtils
)
}
"file" -> {
itemView.setOnClickListener { v ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
context.startActivity(browserIntent)
}
}
}
}
}
return messageStringInternal
}
private 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(TablePlugin.create(context))
.usePlugin(TaskListPlugin.create(drawable))
.usePlugin(StrikethroughPlugin.create()).build()
return markwon.toMarkdown(markdown)
}
companion object {
private const val TAG = "MessageUtils"
}
}