perf(RichTextViewer): share isMarkdown decision via CachedRichTextParser

The markdown check is purely a function of `content`, but it was a
top-level function in RichTextViewer.kt — every distinct instance of
the same content (e.g. a quoted note rendered inside its quoter,
or the same viral note shown multiple places in a feed) re-scanned
the string.

Move the decision into `CachedRichTextParser` with its own small
LRU keyed on content.hashCode(). Composables still wrap the call in
`remember(content)` so recompositions skip even the LRU lookup.
This commit is contained in:
Claude
2026-05-10 22:34:48 +00:00
parent c66acfa131
commit 680e5bc0be
2 changed files with 21 additions and 10 deletions
@@ -28,6 +28,7 @@ import com.vitorpamplona.amethyst.commons.richtext.UrlParser
object CachedRichTextParser {
private val richTextCache = LruCache<Int, RichTextViewerState>(50)
private val isMarkdownCache = LruCache<Int, Boolean>(200)
private fun hashCodeCache(
content: String,
@@ -69,6 +70,25 @@ object CachedRichTextParser {
newUrls
}
}
// Shared across every RichTextViewer instance so that the same content quoted in multiple
// notes only pays for the scan once. The decision is purely a function of `content`.
fun isMarkdown(content: String): Boolean {
val key = content.hashCode()
isMarkdownCache[key]?.let { return it }
val result = computeIsMarkdown(content)
isMarkdownCache.put(key, result)
return result
}
private fun computeIsMarkdown(content: String): Boolean =
content.startsWith("> ") ||
content.startsWith("# ") ||
content.contains("##") ||
content.contains("__") ||
content.contains("**") ||
content.contains("```") ||
content.contains("](")
}
object CachedUrlParser {
@@ -122,15 +122,6 @@ import com.vitorpamplona.quartz.nipB7Blossom.BlossomUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
fun isMarkdown(content: String): Boolean =
content.startsWith("> ") ||
content.startsWith("# ") ||
content.contains("##") ||
content.contains("__") ||
content.contains("**") ||
content.contains("```") ||
content.contains("](")
@Composable
fun RichTextViewer(
content: String,
@@ -145,7 +136,7 @@ fun RichTextViewer(
nav: INav,
) {
Column(modifier = modifier) {
if (remember(content) { isMarkdown(content) }) {
if (remember(content) { CachedRichTextParser.isMarkdown(content) }) {
RenderContentAsMarkdown(content, tags, canPreview, quotesLeft, backgroundColor, callbackUri, accountViewModel, nav)
} else {
RenderRegular(content, tags, canPreview, quotesLeft, backgroundColor, callbackUri, authorPubKey, accountViewModel, nav)