From 8a5877ab13bd505fc2aee8f5f56b5ff24eb70c2d Mon Sep 17 00:00:00 2001 From: Phillip Thelen Date: Fri, 27 May 2022 15:38:02 +0200 Subject: [PATCH] Markdown improvements --- .../habitica/ui/helpers/MarkdownParser.kt | 18 +++++++++++-- .../viewHolders/tasks/BaseTaskViewHolder.kt | 25 +++++++++++-------- 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt index a1c12ccc3..c1f3a073f 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/helpers/MarkdownParser.kt @@ -30,7 +30,7 @@ import io.reactivex.rxjava3.functions.Consumer import io.reactivex.rxjava3.schedulers.Schedulers object MarkdownParser { - + private val cache = sortedMapOf() internal var markwon: Markwon? = null fun setup(context: Context) { @@ -90,9 +90,19 @@ object MarkdownParser { if (input == null) { return SpannableString("") } + val hashCode = input.hashCode() + if (cache.containsKey(hashCode)) { + return cache[hashCode] ?: SpannableString(input) + } val text = EmojiParser.parseEmojis(input) ?: input // Adding this space here bc for some reason some markdown is not rendered correctly when the whole string is supposed to be formatted - return markwon?.toMarkdown("$text ") ?: SpannableString(text) + val result = markwon?.toMarkdown("$text ") ?: SpannableString(text) + + cache[hashCode] = result + if (cache.size > 100) { + cache.remove(0) + } + return result } fun parseMarkdownAsync(input: String?, onSuccess: Consumer) { @@ -103,6 +113,10 @@ object MarkdownParser { .subscribe(onSuccess, RxErrorHandler.handleEmptyError()) } + fun hasCached(input: String?): Boolean { + return cache.containsKey(input?.hashCode()) + } + /** * Converts stylized CharSequence into markdown * diff --git a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt index f5a84728a..0f4b290a8 100644 --- a/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt +++ b/Habitica/src/main/java/com/habitrpg/android/habitica/ui/viewHolders/tasks/BaseTaskViewHolder.kt @@ -1,7 +1,6 @@ package com.habitrpg.android.habitica.ui.viewHolders.tasks import android.content.Context -import android.text.TextUtils import android.text.method.LinkMovementMethod import android.view.MotionEvent import android.view.View @@ -151,12 +150,13 @@ abstract class BaseTaskViewHolder constructor( if (canContainMarkdown()) { if (data.parsedText != null) { titleTextView.setParsedMarkdown(data.parsedText) + } else if (MarkdownParser.hasCached(data.text)) { + titleTextView.setParsedMarkdown(MarkdownParser.parseMarkdown(data.text)) } else { titleTextView.text = data.text titleTextView.setSpannableFactory(NoCopySpannableFactory.getInstance()) if (data.text.isNotEmpty()) { Single.just(data.text) - .map { TextUtils.concat(it, "\u200B").toString() } .map { MarkdownParser.parseMarkdown(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) @@ -168,10 +168,16 @@ abstract class BaseTaskViewHolder constructor( RxErrorHandler.handleEmptyError() ) } - if (displayMode != "minimal") { - if (data.parsedNotes != null) { - notesTextView?.setParsedMarkdown(data.parsedText) - } else { + } + if (displayMode != "minimal") { + when { + data.parsedNotes != null -> { + notesTextView?.setParsedMarkdown(data.parsedNotes) + } + MarkdownParser.hasCached(data.notes) -> { + notesTextView?.setParsedMarkdown(MarkdownParser.parseMarkdown(data.notes)) + } + else -> { notesTextView?.text = data.notes notesTextView?.setSpannableFactory(NoCopySpannableFactory.getInstance()) data.notes?.let { notes -> @@ -179,22 +185,21 @@ abstract class BaseTaskViewHolder constructor( return@let } Single.just(notes) - .map { TextUtils.concat(it, "\u200B").toString() } .map { MarkdownParser.parseMarkdown(it) } .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe( { parsedNotes -> - notesTextView?.text = parsedNotes + data.parsedNotes = parsedNotes notesTextView?.setParsedMarkdown(parsedNotes) }, RxErrorHandler.handleEmptyError() ) } } - } else { - notesTextView?.visibility = View.GONE } + } else { + notesTextView?.visibility = View.GONE } } else { titleTextView.text = data.text