perf(ui): drop remember wrappers where overhead exceeds savings

Cases removed:
- Trivial Modifier allocations (Modifier.weight/padding/size) — slot table
  cost dominates the cost of building a fresh Modifier each recomposition.
- Map.keys views over relayStatuses on desktop screens — .keys is a
  property read on the same map, no need to memoize.
- coerceIn() arithmetic on AudioWaveform Dp/Float params — two compares
  are cheaper than the slot table read+compare.
- fadeIn()/fadeOut() in AnimatedVisibility — small EnterTransition
  allocations that don't justify the slot table overhead.

Audit-only changes; no behavior changes.

https://claude.ai/code/session_011Ea2pVjwvCEx7X4izwryV4
This commit is contained in:
Claude
2026-04-26 17:02:53 +00:00
parent d589fc4614
commit 6f04edd995
20 changed files with 34 additions and 42 deletions
@@ -79,7 +79,7 @@ fun BookmarksScreen(
onZapFeedback: (ZapFeedback) -> Unit = {},
) {
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
val scope = rememberCoroutineScope()
// Tab state
@@ -280,7 +280,7 @@ fun FeedScreen(
val followedUsers by localCache.followedUsers.collectAsState()
// Available relay URLs — subscribe triggers connection on-demand
val allRelayUrls = remember(relayStatuses) { relayStatuses.keys }
val allRelayUrls = relayStatuses.keys
// Feed relays from relay categories (NIP-65 outbox, minus blocked, with fallback)
val relayCategories = LocalRelayCategories.current
@@ -115,7 +115,7 @@ fun NotificationsScreen(
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator? = null,
) {
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
val scope = rememberCoroutineScope()
val notificationState =
remember {
@@ -183,7 +183,7 @@ fun ReadsScreen(
onZapFeedback: (ZapFeedback) -> Unit = {},
) {
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
val scope = rememberCoroutineScope()
val eventState =
@@ -130,7 +130,7 @@ fun SearchScreen(
val connectedRelays by relayManager.connectedRelays.collectAsState()
val relayStatuses by relayManager.relayStatuses.collectAsState()
val allRelayUrls = remember(relayStatuses) { relayStatuses.keys }
val allRelayUrls = relayStatuses.keys
val relayCategories = LocalRelayCategories.current
val searchRelays by relayCategories.searchRelays.collectAsState()
val displayText by state.displayText.collectAsState()
@@ -90,7 +90,7 @@ fun ThreadScreen(
onReply: (Event) -> Unit = {},
) {
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
// Lightbox state
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
@@ -122,7 +122,7 @@ fun UserProfileScreen(
onZapFeedback: (ZapFeedback) -> Unit = {},
) {
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
// User metadata — seed from cache so returning to profile is instant
val cachedUser = remember(pubKeyHex) { localCache.getUserIfExists(pubKeyHex) }
@@ -78,7 +78,7 @@ fun NewDmDialog(
val relaySearchResults by searchState.relaySearchResults.collectAsState()
val isSearchingRelays by searchState.isSearchingRelays.collectAsState()
val relayStatuses by relayManager.relayStatuses.collectAsState()
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
val connectedRelays = relayStatuses.keys
val focusRequester = remember { FocusRequester() }
// NIP-50 relay search when local cache has few/no results