perf(note types): second pass — fix more missing remember keys
Follow-up to the first perf pass. Same goal: cut allocation cost for
note rows that scroll inside LazyColumn feeds.
- AppDefinition: key the `remember { tags.toImmutableListOfLists() }`
block by `note` so it actually invalidates when the note changes
- NIP90ContentDiscoveryResponse: drop the `remember(note) {
Modifier.fillMaxWidth() }` wrapper — `Modifier.fillMaxWidth()` is a
constant call
- PeopleList: key the `derivedStateOf` for `name` by `noteEvent`, and
switch `LaunchedEffect(Unit)` to `LaunchedEffect(noteEvent)` so the
participants reload when the underlying event changes
- PinList: replace `val pins by remember { mutableStateOf(noteEvent
.pinnedEvents()) }` with `val pins = remember(noteEvent) { … }` —
the `mutableStateOf` wrapper was unnecessary and the missing key
meant `pins` could go stale on event updates
- LongForm: return the `topics` list as `ImmutableList` so Compose
treats it as a stable parameter to the consuming `forEach`
- RelayList: drop the `mutableStateOf(RelayListCard(…))` wrap inside
4 `remember` blocks (DisplayRelaySet, DisplayNIP65RelayList write/
read, DisplayDMRelayList) — the value never changes after creation;
also key by `noteEvent` rather than `baseNote`, and cache
`noteEvent.description()`
- Torrent: wrap `noteEvent.title() + totalSizeBytes()`, content
comparison and `files().toImmutableList()` in `remember(noteEvent)`
so they don't recompute and reallocate on every recomposition
This commit is contained in:
@@ -216,7 +216,7 @@ fun RenderAppDefinition(
|
|||||||
CreateTextWithEmoji(
|
CreateTextWithEmoji(
|
||||||
text = it,
|
text = it,
|
||||||
tags =
|
tags =
|
||||||
remember {
|
remember(note) {
|
||||||
(note.event?.tags ?: emptyArray()).toImmutableListOfLists()
|
(note.event?.tags ?: emptyArray()).toImmutableListOfLists()
|
||||||
},
|
},
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ import com.vitorpamplona.amethyst.ui.theme.Size5dp
|
|||||||
import com.vitorpamplona.amethyst.ui.theme.grayText
|
import com.vitorpamplona.amethyst.ui.theme.grayText
|
||||||
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
import com.vitorpamplona.amethyst.ui.theme.replyModifier
|
||||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||||
|
import kotlinx.collections.immutable.toImmutableList
|
||||||
|
|
||||||
private const val WORDS_PER_MINUTE = 225
|
private const val WORDS_PER_MINUTE = 225
|
||||||
private val COVER_ASPECT_RATIO = 16f / 9f
|
private val COVER_ASPECT_RATIO = 16f / 9f
|
||||||
@@ -92,7 +93,14 @@ fun LongFormHeader(
|
|||||||
remember(noteEvent) {
|
remember(noteEvent) {
|
||||||
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
|
noteEvent.summary()?.ifBlank { null } ?: noteEvent.content.take(200).ifBlank { null }
|
||||||
}
|
}
|
||||||
val topics = remember(noteEvent) { noteEvent.topics().distinct().take(3) }
|
val topics =
|
||||||
|
remember(noteEvent) {
|
||||||
|
noteEvent
|
||||||
|
.topics()
|
||||||
|
.distinct()
|
||||||
|
.take(3)
|
||||||
|
.toImmutableList()
|
||||||
|
}
|
||||||
val readingMinutes = remember(noteEvent) { estimateReadingMinutes(noteEvent.content) }
|
val readingMinutes = remember(noteEvent) { estimateReadingMinutes(noteEvent.content) }
|
||||||
|
|
||||||
Column(MaterialTheme.colorScheme.replyModifier) {
|
Column(MaterialTheme.colorScheme.replyModifier) {
|
||||||
|
|||||||
+1
-2
@@ -54,7 +54,6 @@ fun RenderNIP90ContentDiscoveryResponse(
|
|||||||
note = note,
|
note = note,
|
||||||
accountViewModel = accountViewModel,
|
accountViewModel = accountViewModel,
|
||||||
) {
|
) {
|
||||||
val modifier = remember(note) { Modifier.fillMaxWidth() }
|
|
||||||
val tags =
|
val tags =
|
||||||
remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
|
remember(note) { note.event?.tags?.toImmutableListOfLists() ?: EmptyTagList }
|
||||||
|
|
||||||
@@ -62,7 +61,7 @@ fun RenderNIP90ContentDiscoveryResponse(
|
|||||||
content = noteEvent.content,
|
content = noteEvent.content,
|
||||||
canPreview = canPreview && !makeItShort,
|
canPreview = canPreview && !makeItShort,
|
||||||
quotesLeft = quotesLeft,
|
quotesLeft = quotesLeft,
|
||||||
modifier = modifier,
|
modifier = Modifier.fillMaxWidth(),
|
||||||
tags = tags,
|
tags = tags,
|
||||||
backgroundColor = backgroundColor,
|
backgroundColor = backgroundColor,
|
||||||
id = note.idHex,
|
id = note.idHex,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ fun DisplayPeopleList(
|
|||||||
members.take(3)
|
members.take(3)
|
||||||
}
|
}
|
||||||
|
|
||||||
val name by remember { derivedStateOf { "#${noteEvent.titleOrName() ?: noteEvent.dTag()}" } }
|
val name by remember(noteEvent) { derivedStateOf { "#${noteEvent.titleOrName() ?: noteEvent.dTag()}" } }
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = name,
|
text = name,
|
||||||
@@ -95,7 +95,7 @@ fun DisplayPeopleList(
|
|||||||
textAlign = TextAlign.Center,
|
textAlign = TextAlign.Center,
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(noteEvent) {
|
||||||
accountViewModel.loadUsers(noteEvent.taggedUserIds()) {
|
accountViewModel.loadUsers(noteEvent.taggedUserIds()) {
|
||||||
members = it
|
members = it
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ fun RenderPinListEvent(
|
|||||||
) {
|
) {
|
||||||
val noteEvent = baseNote.event as? PinListEvent ?: return
|
val noteEvent = baseNote.event as? PinListEvent ?: return
|
||||||
|
|
||||||
val pins by remember { mutableStateOf(noteEvent.pinnedEvents()) }
|
val pins = remember(noteEvent) { noteEvent.pinnedEvents() }
|
||||||
|
|
||||||
var expanded by remember { mutableStateOf(false) }
|
var expanded by remember { mutableStateOf(false) }
|
||||||
|
|
||||||
|
|||||||
@@ -75,12 +75,10 @@ fun DisplayRelaySet(
|
|||||||
) {
|
) {
|
||||||
val noteEvent = baseNote.event as? RelaySetEvent ?: return
|
val noteEvent = baseNote.event as? RelaySetEvent ?: return
|
||||||
|
|
||||||
val relays by
|
val relays =
|
||||||
remember(noteEvent) {
|
remember(noteEvent) {
|
||||||
mutableStateOf(
|
RelayListCard(
|
||||||
RelayListCard(
|
noteEvent.relays().toImmutableList(),
|
||||||
noteEvent.relays().toImmutableList(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,10 +87,12 @@ fun DisplayRelaySet(
|
|||||||
noteEvent.tags.firstTagValueFor("title", "name") ?: "#${noteEvent.dTag()}"
|
noteEvent.tags.firstTagValueFor("title", "name") ?: "#${noteEvent.dTag()}"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val description = remember(noteEvent) { noteEvent.description() }
|
||||||
|
|
||||||
DisplayRelaySet(
|
DisplayRelaySet(
|
||||||
relays,
|
relays,
|
||||||
relayListName,
|
relayListName,
|
||||||
noteEvent.description(),
|
description,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
accountViewModel,
|
accountViewModel,
|
||||||
nav,
|
nav,
|
||||||
@@ -108,21 +108,17 @@ fun DisplayNIP65RelayList(
|
|||||||
) {
|
) {
|
||||||
val noteEvent = baseNote.event as? AdvertisedRelayListEvent ?: return
|
val noteEvent = baseNote.event as? AdvertisedRelayListEvent ?: return
|
||||||
|
|
||||||
val writeRelays by
|
val writeRelays =
|
||||||
remember(baseNote) {
|
remember(noteEvent) {
|
||||||
mutableStateOf(
|
RelayListCard(
|
||||||
RelayListCard(
|
noteEvent.writeRelaysNorm() ?: emptyList(),
|
||||||
noteEvent.writeRelaysNorm() ?: emptyList(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val readRelays by
|
val readRelays =
|
||||||
remember(baseNote) {
|
remember(noteEvent) {
|
||||||
mutableStateOf(
|
RelayListCard(
|
||||||
RelayListCard(
|
noteEvent.readRelaysNorm() ?: emptyList(),
|
||||||
noteEvent.readRelaysNorm() ?: emptyList(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,12 +150,10 @@ fun DisplayDMRelayList(
|
|||||||
) {
|
) {
|
||||||
val noteEvent = baseNote.event as? ChatMessageRelayListEvent ?: return
|
val noteEvent = baseNote.event as? ChatMessageRelayListEvent ?: return
|
||||||
|
|
||||||
val relays by
|
val relays =
|
||||||
remember(baseNote) {
|
remember(noteEvent) {
|
||||||
mutableStateOf(
|
RelayListCard(
|
||||||
RelayListCard(
|
noteEvent.relays(),
|
||||||
noteEvent.relays(),
|
|
||||||
),
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -153,19 +153,24 @@ fun RenderTorrent(
|
|||||||
) {
|
) {
|
||||||
val noteEvent = note.event as? TorrentEvent ?: return
|
val noteEvent = note.event as? TorrentEvent ?: return
|
||||||
|
|
||||||
val name = (noteEvent.title() ?: TorrentEvent.ALT_DESCRIPTION)
|
val title =
|
||||||
val size = " (" + countToHumanReadableBytes(noteEvent.totalSizeBytes()) + ")"
|
remember(noteEvent) {
|
||||||
|
val name = noteEvent.title() ?: TorrentEvent.ALT_DESCRIPTION
|
||||||
val description =
|
val size = " (" + countToHumanReadableBytes(noteEvent.totalSizeBytes()) + ")"
|
||||||
if (noteEvent.content != name) {
|
name + size
|
||||||
noteEvent.content
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val description =
|
||||||
|
remember(noteEvent) {
|
||||||
|
val name = noteEvent.title() ?: TorrentEvent.ALT_DESCRIPTION
|
||||||
|
if (noteEvent.content != name) noteEvent.content else null
|
||||||
|
}
|
||||||
|
|
||||||
|
val files = remember(noteEvent) { noteEvent.files().toImmutableList() }
|
||||||
|
|
||||||
DisplayFileList(
|
DisplayFileList(
|
||||||
noteEvent.files().toImmutableList(),
|
files,
|
||||||
name + size,
|
title,
|
||||||
description,
|
description,
|
||||||
noteEvent::toMagnetLink,
|
noteEvent::toMagnetLink,
|
||||||
backgroundColor,
|
backgroundColor,
|
||||||
|
|||||||
Reference in New Issue
Block a user