perf(feeds): remember isSensitive and content warning reasons per note

These derivations iterate every tag and parse every iMeta, so running
them on each recomposition churns through feed scrolls. Cache them in
remember(note) alongside the other per-note derivations.
This commit is contained in:
Claude
2026-04-19 14:47:20 +00:00
parent 60a56440d1
commit dcaa6607ea
5 changed files with 17 additions and 17 deletions
@@ -67,9 +67,9 @@ fun PictureDisplay(
nav: INav,
) {
val event = (note.event as? PictureEvent) ?: return
val uri = note.toNostrUri()
val isSensitive = event.isSensitiveOrNSFW()
val reasons = collectContentWarningReasons(event)
val uri = remember(note) { note.toNostrUri() }
val isSensitive = remember(note) { event.isSensitiveOrNSFW() }
val reasons = remember(note) { collectContentWarningReasons(event) }
val images by
remember(note) {
@@ -53,9 +53,9 @@ fun JustVideoDisplay(
val event = (videoEvent as? Event) ?: return
val imeta = videoEvent.imetaTags().getOrNull(0) ?: return
val isSensitive = event.isSensitiveOrNSFW()
val reasons = collectContentWarningReasons(event)
val isImage = imeta.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(imeta.url)
val isSensitive = remember(note) { event.isSensitiveOrNSFW() }
val reasons = remember(note) { collectContentWarningReasons(event) }
val isImage = remember(note) { imeta.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(imeta.url) }
val content by
remember(note) {
@@ -97,9 +97,9 @@ private fun PictureCardImage(
backgroundColor: MutableState<Color>,
accountViewModel: AccountViewModel,
) {
val uri = note.toNostrUri()
val isSensitive = event.isSensitiveOrNSFW()
val reasons = collectContentWarningReasons(event)
val uri = remember(note) { note.toNostrUri() }
val isSensitive = remember(note) { event.isSensitiveOrNSFW() }
val reasons = remember(note) { collectContentWarningReasons(event) }
val images by
remember(note) {
@@ -103,9 +103,9 @@ private fun VideoCardImage(
val event = (event as? Event) ?: return
val imeta = videoEvent.imetaTags().getOrNull(0) ?: return
val isSensitive = event.isSensitiveOrNSFW()
val reasons = collectContentWarningReasons(event)
val isImage = imeta.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(imeta.url)
val isSensitive = remember(note) { event.isSensitiveOrNSFW() }
val reasons = remember(note) { collectContentWarningReasons(event) }
val isImage = remember(note) { imeta.mimeType?.startsWith("image/") == true || RichTextParser.isImageUrl(imeta.url) }
val content by
remember(note) {
@@ -100,11 +100,11 @@ private fun FileHeaderCardImage(
) {
val fullUrl = event.url() ?: return
val isSensitive = event.isSensitiveOrNSFW()
val reasons = collectContentWarningReasons(event)
val isImage = event.mimeType()?.startsWith("image/") == true || RichTextParser.isImageUrl(fullUrl)
val blurHash = event.blurhash()
val dimensions = event.dimensions()
val isSensitive = remember(note) { event.isSensitiveOrNSFW() }
val reasons = remember(note) { collectContentWarningReasons(event) }
val isImage = remember(note) { event.mimeType()?.startsWith("image/") == true || RichTextParser.isImageUrl(fullUrl) }
val blurHash = remember(note) { event.blurhash() }
val dimensions = remember(note) { event.dimensions() }
val content by remember(note) {
val hash = event.hash()