mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-11 16:57:39 +00:00
perf(commons): remember derived values in the moved note cards
Audit follow-up. These renderers sit in scrolling feeds; each recomputed
event parses / string builds directly in the composable body instead of
caching them against the (immutable) event — the CLAUDE.md rule-#4 pattern.
The cards are already skippable (immutable event params + strong skipping),
so this is work redone per composition (each item scrolling into view), not
per frame; still worth removing. These patterns pre-existed in the Android
originals and were carried over faithfully — this cleans them up now that the
code is shared.
- RelayDiscoveryCard: the heaviest — 6 `joinToString` + a `.sorted()` ran in
the body. Now each display string (network / relay-type / requirements /
supported-NIPs / accepted-kinds / geohashes, the requirements lock flag, and
the relay-URL displayUrl()) is `remember`ed off its parsed list; the row
visibility checks still key off the original lists so behavior is identical.
- CalendarRsvpCard: `status` / `calendarEventAddress` / `freebusy` parses now
`remember(event)` instead of re-scanning tags every composition.
- CalendarCollectionCard: `title()` and `calendarEventAddresses().size` (which
allocated a whole List just to read size) now `remember(event)`.
- PodcastValueSplits: the `recipients.filter{}` + `totalSplit()` now
`remember(value)`.
Behavior is unchanged (same keys, conditions, and outputs). Verified:
:commons:compileKotlinJvm + :amethyst:compileFdroidDebugKotlin pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Gmrt3jwYPDJ38MJGJ6GaNr
This commit is contained in:
+5
-2
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
@@ -46,6 +47,9 @@ import org.jetbrains.compose.resources.pluralStringResource
|
||||
/** Card for a NIP-52 calendar collection (kind 31924): title, description, and event count. */
|
||||
@Composable
|
||||
fun CalendarCollectionCard(event: CalendarEvent) {
|
||||
val title = remember(event) { event.title() }
|
||||
val eventCount = remember(event) { event.calendarEventAddresses().size }
|
||||
|
||||
Column(MaterialTheme.colorScheme.replyModifier) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth().padding(start = 10.dp, end = 10.dp, top = 10.dp),
|
||||
@@ -59,7 +63,7 @@ fun CalendarCollectionCard(event: CalendarEvent) {
|
||||
)
|
||||
Spacer(modifier = Modifier.size(8.dp))
|
||||
Text(
|
||||
text = event.title() ?: "—",
|
||||
text = title ?: "—",
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.SemiBold,
|
||||
maxLines = 2,
|
||||
@@ -80,7 +84,6 @@ fun CalendarCollectionCard(event: CalendarEvent) {
|
||||
}
|
||||
|
||||
Spacer(modifier = StdVertSpacer)
|
||||
val eventCount = event.calendarEventAddresses().size
|
||||
Text(
|
||||
text = pluralStringResource(Res.plurals.calendar_collection_count, eventCount, eventCount),
|
||||
style = MaterialTheme.typography.labelMedium,
|
||||
|
||||
+4
-3
@@ -29,6 +29,7 @@ import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
@@ -49,9 +50,9 @@ import org.jetbrains.compose.resources.stringResource
|
||||
/** Card for a NIP-52 calendar RSVP (kind 31925): the going/maybe/not-going status, note, and target. */
|
||||
@Composable
|
||||
fun CalendarRsvpCard(event: CalendarRSVPEvent) {
|
||||
val status = event.status()
|
||||
val targetAddress = event.calendarEventAddress()
|
||||
val freebusy = event.freebusy()
|
||||
val status = remember(event) { event.status() }
|
||||
val targetAddress = remember(event) { event.calendarEventAddress() }
|
||||
val freebusy = remember(event) { event.freebusy() }
|
||||
|
||||
val statusLabel =
|
||||
when (status) {
|
||||
|
||||
+3
-2
@@ -31,6 +31,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
@@ -60,10 +61,10 @@ import org.jetbrains.compose.resources.stringResource
|
||||
*/
|
||||
@Composable
|
||||
fun PodcastValueSplits(value: PodcastValue) {
|
||||
val recipients = value.recipients.filter { it.split > 0 || it.address != null }
|
||||
val recipients = remember(value) { value.recipients.filter { it.split > 0 || it.address != null } }
|
||||
if (recipients.isEmpty()) return
|
||||
|
||||
val total = value.totalSplit().takeIf { it > 0 } ?: recipients.size
|
||||
val total = remember(value, recipients) { value.totalSplit().takeIf { it > 0 } ?: recipients.size }
|
||||
|
||||
Column(
|
||||
modifier =
|
||||
|
||||
+17
-16
@@ -70,17 +70,24 @@ import org.jetbrains.compose.resources.stringResource
|
||||
@OptIn(ExperimentalLayoutApi::class)
|
||||
@Composable
|
||||
fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
val relayUrl = remember(noteEvent) { noteEvent.relay() }
|
||||
val relayUrl = remember(noteEvent) { noteEvent.relay()?.displayUrl() }
|
||||
val rttOpen = remember(noteEvent) { noteEvent.rttOpen() }
|
||||
val rttRead = remember(noteEvent) { noteEvent.rttRead() }
|
||||
val rttWrite = remember(noteEvent) { noteEvent.rttWrite() }
|
||||
val networkTypes = remember(noteEvent) { noteEvent.networkTypes() }
|
||||
val networkValue = remember(networkTypes) { networkTypes.joinToString { it.code } }
|
||||
val relayTypes = remember(noteEvent) { noteEvent.relayTypes() }
|
||||
val supportedNips = remember(noteEvent) { noteEvent.supportedNips() }
|
||||
val relayTypeValue = remember(relayTypes) { relayTypes.joinToString() }
|
||||
val requirements = remember(noteEvent) { noteEvent.requirements() }
|
||||
val requirementsLocked = remember(requirements) { requirements.any { !it.negated } }
|
||||
val requirementsValue = remember(requirements) { requirements.joinToString { req -> if (req.negated) "!${req.value}" else req.value } }
|
||||
val supportedNips = remember(noteEvent) { noteEvent.supportedNips() }
|
||||
val supportedNipsValue = remember(supportedNips) { supportedNips.sorted().joinToString() }
|
||||
val acceptedKinds = remember(noteEvent) { noteEvent.acceptedKinds() }
|
||||
val acceptedKindsValue = remember(acceptedKinds) { acceptedKinds.joinToString { kind -> if (kind.negated) "!${kind.kind}" else "${kind.kind}" } }
|
||||
val topics = remember(noteEvent) { noteEvent.topics() }
|
||||
val geohashes = remember(noteEvent) { noteEvent.geohashes() }
|
||||
val geohashesValue = remember(geohashes) { geohashes.joinToString() }
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
@@ -89,7 +96,7 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
// Relay URL header
|
||||
if (relayUrl != null) {
|
||||
Text(
|
||||
text = relayUrl.displayUrl(),
|
||||
text = relayUrl,
|
||||
style = MaterialTheme.typography.titleMedium,
|
||||
fontWeight = FontWeight.Bold,
|
||||
color = MaterialTheme.colorScheme.primary,
|
||||
@@ -121,7 +128,7 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
DiscoveryInfoRow(
|
||||
icon = MaterialSymbols.Language,
|
||||
label = stringResource(Res.string.relay_monitor_network),
|
||||
value = networkTypes.joinToString { it.code },
|
||||
value = networkValue,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -130,19 +137,16 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
DiscoveryInfoRow(
|
||||
icon = MaterialSymbols.Dns,
|
||||
label = stringResource(Res.string.relay_monitor_relay_type),
|
||||
value = relayTypes.joinToString(),
|
||||
value = relayTypeValue,
|
||||
)
|
||||
}
|
||||
|
||||
// Requirements
|
||||
if (requirements.isNotEmpty()) {
|
||||
DiscoveryInfoRow(
|
||||
icon = if (requirements.any { !it.negated }) MaterialSymbols.Lock else MaterialSymbols.LockOpen,
|
||||
icon = if (requirementsLocked) MaterialSymbols.Lock else MaterialSymbols.LockOpen,
|
||||
label = stringResource(Res.string.relay_monitor_requirements),
|
||||
value =
|
||||
requirements.joinToString { req ->
|
||||
if (req.negated) "!${req.value}" else req.value
|
||||
},
|
||||
value = requirementsValue,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -151,7 +155,7 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
DiscoveryInfoRow(
|
||||
icon = MaterialSymbols.Numbers,
|
||||
label = stringResource(Res.string.relay_monitor_supported_nips),
|
||||
value = supportedNips.sorted().joinToString(),
|
||||
value = supportedNipsValue,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -160,10 +164,7 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
DiscoveryInfoRow(
|
||||
icon = MaterialSymbols.Dns,
|
||||
label = stringResource(Res.string.relay_discovery_accepted_kinds),
|
||||
value =
|
||||
acceptedKinds.joinToString { kind ->
|
||||
if (kind.negated) "!${kind.kind}" else "${kind.kind}"
|
||||
},
|
||||
value = acceptedKindsValue,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -196,7 +197,7 @@ fun RelayDiscoveryCard(noteEvent: RelayDiscoveryEvent) {
|
||||
DiscoveryInfoRow(
|
||||
icon = MaterialSymbols.TravelExplore,
|
||||
label = stringResource(Res.string.relay_discovery_geohash),
|
||||
value = geohashes.joinToString(),
|
||||
value = geohashesValue,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user