From dcaa6607ea0ef7e6d343e23d133f778271892258 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 19 Apr 2026 14:47:20 +0000 Subject: [PATCH] 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. --- .../amethyst/ui/note/types/PictureDisplay.kt | 6 +++--- .../amethyst/ui/note/types/VideoDisplay.kt | 6 +++--- .../ui/screen/loggedIn/pictures/PictureCardCompose.kt | 6 +++--- .../ui/screen/loggedIn/shorts/VideoCardCompose.kt | 6 +++--- .../ui/screen/loggedIn/video/FileHeaderCardCompose.kt | 10 +++++----- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/PictureDisplay.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/PictureDisplay.kt index 466764b6a..6730e72c9 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/PictureDisplay.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/PictureDisplay.kt @@ -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) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/VideoDisplay.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/VideoDisplay.kt index 50041196f..63cb577eb 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/VideoDisplay.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/VideoDisplay.kt @@ -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) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/PictureCardCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/PictureCardCompose.kt index d6c210eda..d7aa97489 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/PictureCardCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/PictureCardCompose.kt @@ -97,9 +97,9 @@ private fun PictureCardImage( backgroundColor: MutableState, 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) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/VideoCardCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/VideoCardCompose.kt index 5b0cace57..11385dd60 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/VideoCardCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/VideoCardCompose.kt @@ -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) { diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/FileHeaderCardCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/FileHeaderCardCompose.kt index 8d90d907d..2efc3243a 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/FileHeaderCardCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/video/FileHeaderCardCompose.kt @@ -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()