Commit d87e13a3 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Fix markdown links and properly parsing normal links

parent a09dc8fd
package chat.rocket.android.helper package chat.rocket.android.helper
import android.app.Application import android.app.Application
import android.content.ActivityNotFoundException
import android.content.Context import android.content.Context
import android.content.Intent
import android.graphics.* import android.graphics.*
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri
import android.provider.Browser
import android.support.v4.content.ContextCompat import android.support.v4.content.ContextCompat
import android.support.v4.content.res.ResourcesCompat import android.support.v4.content.res.ResourcesCompat
import android.text.Layout import android.text.Layout
import android.text.Spannable import android.text.Spannable
import android.text.Spanned import android.text.Spanned
import android.text.style.* import android.text.style.*
import android.util.Patterns
import android.view.View
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.viewmodel.MessageViewModel import chat.rocket.android.chatroom.viewmodel.MessageViewModel
import org.commonmark.node.AbstractVisitor
import org.commonmark.node.BlockQuote import org.commonmark.node.BlockQuote
import org.commonmark.node.Text
import ru.noties.markwon.Markwon import ru.noties.markwon.Markwon
import ru.noties.markwon.SpannableBuilder import ru.noties.markwon.SpannableBuilder
import ru.noties.markwon.SpannableConfiguration import ru.noties.markwon.SpannableConfiguration
import ru.noties.markwon.renderer.SpannableMarkdownVisitor import ru.noties.markwon.renderer.SpannableMarkdownVisitor
import timber.log.Timber
import java.util.regex.Pattern import java.util.regex.Pattern
import javax.inject.Inject import javax.inject.Inject
...@@ -40,20 +49,7 @@ class MessageParser @Inject constructor(val context: Application, private val co ...@@ -40,20 +49,7 @@ class MessageParser @Inject constructor(val context: Application, private val co
*/ */
fun renderMarkdown(text: String, quote: MessageViewModel? = null, selfUsername: String? = null): CharSequence { fun renderMarkdown(text: String, quote: MessageViewModel? = null, selfUsername: String? = null): CharSequence {
val builder = SpannableBuilder() val builder = SpannableBuilder()
var content: String = text val content = text
// Replace all url links to markdown url syntax.
val matcher = regexLink.matcher(content)
val consumed = mutableListOf<String>()
while (matcher.find()) {
val link = matcher.group(0)
// skip usernames
if (!link.startsWith("@") && !consumed.contains(link)) {
content = content.replace(link, "[$link]($link)")
consumed.add(link)
}
}
val parentNode = parser.parse(toLenientMarkdown(content)) val parentNode = parser.parse(toLenientMarkdown(content))
parentNode.accept(QuoteMessageBodyVisitor(context, configuration, builder)) parentNode.accept(QuoteMessageBodyVisitor(context, configuration, builder))
quote?.apply { quote?.apply {
...@@ -63,9 +59,10 @@ class MessageParser @Inject constructor(val context: Application, private val co ...@@ -63,9 +59,10 @@ class MessageParser @Inject constructor(val context: Application, private val co
quoteNode = parser.parse("> ${toLenientMarkdown(quote.getOriginalMessage())}") quoteNode = parser.parse("> ${toLenientMarkdown(quote.getOriginalMessage())}")
quoteNode.accept(QuoteMessageBodyVisitor(context, configuration, builder)) quoteNode.accept(QuoteMessageBodyVisitor(context, configuration, builder))
} }
parentNode.accept(LinkVisitor(builder))
val result = builder.text() val result = builder.text()
applySpans(result, selfUsername) applySpans(result, selfUsername)
return result return result
} }
...@@ -144,6 +141,46 @@ class MessageParser @Inject constructor(val context: Application, private val co ...@@ -144,6 +141,46 @@ class MessageParser @Inject constructor(val context: Application, private val co
} }
} }
class LinkVisitor(private val builder: SpannableBuilder) : AbstractVisitor() {
override fun visit(text: Text) {
// Replace all url links to markdown url syntax.
val matcher = Patterns.WEB_URL.matcher(builder.text())
val consumed = mutableListOf<String>()
while (matcher.find()) {
val link = matcher.group(0)
// skip usernames
if (!link.startsWith("@") && link !in consumed) {
builder.setSpan(object : ClickableSpan() {
override fun onClick(view: View) {
val uri = getUri(link)
val context = view.context
val intent = Intent(Intent.ACTION_VIEW, uri)
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.packageName)
try {
context.startActivity(intent)
} catch (e: ActivityNotFoundException) {
Timber.e("Actvity was not found for intent, $intent")
}
}
}, matcher.start(0), matcher.end(0))
consumed.add(link)
}
}
visitChildren(text)
}
private fun getUri(link: String): Uri {
val uri = Uri.parse(link)
if (uri.scheme == null) {
return Uri.parse("http://$link")
}
return uri
}
}
class QuoteMessageBodyVisitor(private val context: Context, class QuoteMessageBodyVisitor(private val context: Context,
configuration: SpannableConfiguration, configuration: SpannableConfiguration,
private val builder: SpannableBuilder) : SpannableMarkdownVisitor(configuration, builder) { private val builder: SpannableBuilder) : SpannableMarkdownVisitor(configuration, builder) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment