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:
+5
-9
@@ -78,15 +78,11 @@ fun AudioWaveformReadOnly(
|
|||||||
amplitudes: List<Float>,
|
amplitudes: List<Float>,
|
||||||
onProgressChange: (Float) -> Unit,
|
onProgressChange: (Float) -> Unit,
|
||||||
) {
|
) {
|
||||||
val progressState = remember(progress) { progress.coerceIn(MIN_PROGRESS, MAX_PROGRESS) }
|
val progressState = progress.coerceIn(MIN_PROGRESS, MAX_PROGRESS)
|
||||||
val spikeWidthState =
|
val spikeWidthState = spikeWidth.coerceIn(MinSpikeWidthDp, MaxSpikeWidthDp)
|
||||||
remember(spikeWidth) { spikeWidth.coerceIn(MinSpikeWidthDp, MaxSpikeWidthDp) }
|
val spikePaddingState = spikePadding.coerceIn(MinSpikePaddingDp, MaxSpikePaddingDp)
|
||||||
val spikePaddingState =
|
val spikeRadiusState = spikeRadius.coerceIn(MinSpikeRadiusDp, MaxSpikeRadiusDp)
|
||||||
remember(spikePadding) { spikePadding.coerceIn(MinSpikePaddingDp, MaxSpikePaddingDp) }
|
val spikeTotalWidthState = spikeWidthState + spikePaddingState
|
||||||
val spikeRadiusState =
|
|
||||||
remember(spikeRadius) { spikeRadius.coerceIn(MinSpikeRadiusDp, MaxSpikeRadiusDp) }
|
|
||||||
val spikeTotalWidthState =
|
|
||||||
remember(spikeWidth, spikePadding) { spikeWidthState + spikePaddingState }
|
|
||||||
var canvasSize by remember { mutableStateOf(Size(0f, 0f)) }
|
var canvasSize by remember { mutableStateOf(Size(0f, 0f)) }
|
||||||
var spikes by remember { mutableFloatStateOf(0F) }
|
var spikes by remember { mutableFloatStateOf(0F) }
|
||||||
val spikesAmplitudes =
|
val spikesAmplitudes =
|
||||||
|
|||||||
+2
-2
@@ -334,8 +334,8 @@ private fun DialogContent(
|
|||||||
|
|
||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = controllerVisible.value,
|
visible = controllerVisible.value,
|
||||||
enter = remember { fadeIn() },
|
enter = fadeIn(),
|
||||||
exit = remember { fadeOut() },
|
exit = fadeOut(),
|
||||||
// Also fade with the grow animation so controls appear/disappear alongside it.
|
// Also fade with the grow animation so controls appear/disappear alongside it.
|
||||||
modifier = Modifier.graphicsLayer { alpha = progress().coerceIn(0f, 1f) },
|
modifier = Modifier.graphicsLayer { alpha = progress().coerceIn(0f, 1f) },
|
||||||
) {
|
) {
|
||||||
|
|||||||
+4
-4
@@ -404,8 +404,8 @@ fun LocalImageView(
|
|||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = controllerVisible.value,
|
visible = controllerVisible.value,
|
||||||
modifier = Modifier.align(Alignment.TopEnd),
|
modifier = Modifier.align(Alignment.TopEnd),
|
||||||
enter = remember { fadeIn() },
|
enter = fadeIn(),
|
||||||
exit = remember { fadeOut() },
|
exit = fadeOut(),
|
||||||
) {
|
) {
|
||||||
Box(Modifier.align(Alignment.TopEnd), contentAlignment = Alignment.TopEnd) {
|
Box(Modifier.align(Alignment.TopEnd), contentAlignment = Alignment.TopEnd) {
|
||||||
HashVerificationSymbol(it)
|
HashVerificationSymbol(it)
|
||||||
@@ -649,8 +649,8 @@ fun ShowHashAnimated(
|
|||||||
AnimatedVisibility(
|
AnimatedVisibility(
|
||||||
visible = controllerVisible.value,
|
visible = controllerVisible.value,
|
||||||
modifier = modifier,
|
modifier = modifier,
|
||||||
enter = remember { fadeIn() },
|
enter = fadeIn(),
|
||||||
exit = remember { fadeOut() },
|
exit = fadeOut(),
|
||||||
) {
|
) {
|
||||||
Box(modifier, contentAlignment = Alignment.TopEnd) {
|
Box(modifier, contentAlignment = Alignment.TopEnd) {
|
||||||
ShowHash(content)
|
ShowHash(content)
|
||||||
|
|||||||
@@ -332,7 +332,7 @@ fun RenderZapGallery(
|
|||||||
modifier = WidthAuthorPictureModifier,
|
modifier = WidthAuthorPictureModifier,
|
||||||
) {
|
) {
|
||||||
ZappedIcon(
|
ZappedIcon(
|
||||||
modifier = remember { Modifier.size(Size25dp).align(Alignment.TopEnd) },
|
modifier = Modifier.size(Size25dp).align(Alignment.TopEnd),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +353,7 @@ fun RenderBoostGallery(
|
|||||||
modifier = NotificationIconModifierSmaller,
|
modifier = NotificationIconModifierSmaller,
|
||||||
) {
|
) {
|
||||||
RepostedIcon(
|
RepostedIcon(
|
||||||
modifier = remember { Modifier.size(Size20dp).align(Alignment.TopEnd) },
|
modifier = Modifier.size(Size20dp).align(Alignment.TopEnd),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -374,7 +374,7 @@ fun RenderBoostGallery(
|
|||||||
modifier = NotificationIconModifierSmaller,
|
modifier = NotificationIconModifierSmaller,
|
||||||
) {
|
) {
|
||||||
RepostedIcon(
|
RepostedIcon(
|
||||||
modifier = remember { Modifier.size(Size20dp).align(Alignment.TopEnd) },
|
modifier = Modifier.size(Size20dp).align(Alignment.TopEnd),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1513,7 +1513,7 @@ fun SecondUserInfoRow(
|
|||||||
verticalAlignment = CenterVertically,
|
verticalAlignment = CenterVertically,
|
||||||
modifier = UserNameMaxRowHeight,
|
modifier = UserNameMaxRowHeight,
|
||||||
) {
|
) {
|
||||||
Column(modifier = remember { Modifier.weight(1f) }) {
|
Column(modifier = Modifier.weight(1f)) {
|
||||||
if (noteEvent is IForkableEvent && noteEvent.isAFork()) {
|
if (noteEvent is IForkableEvent && noteEvent.isAFork()) {
|
||||||
ShowForkInformation(noteEvent, Modifier, accountViewModel, nav)
|
ShowForkInformation(noteEvent, Modifier, accountViewModel, nav)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.text.style.TextOverflow
|
import androidx.compose.ui.text.style.TextOverflow
|
||||||
@@ -136,7 +135,7 @@ fun UserComposeNoAction(
|
|||||||
) {
|
) {
|
||||||
UserPicture(baseUser, Size55dp, accountViewModel = accountViewModel, nav = nav)
|
UserPicture(baseUser, Size55dp, accountViewModel = accountViewModel, nav = nav)
|
||||||
|
|
||||||
Column(modifier = remember { Modifier.padding(start = 10.dp).weight(1f) }) {
|
Column(modifier = Modifier.padding(start = 10.dp).weight(1f)) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
UsernameDisplay(baseUser, accountViewModel = accountViewModel)
|
UsernameDisplay(baseUser, accountViewModel = accountViewModel)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import androidx.compose.material3.MaterialTheme
|
|||||||
import androidx.compose.material3.Text
|
import androidx.compose.material3.Text
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.getValue
|
import androidx.compose.runtime.getValue
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
import androidx.compose.ui.Alignment.Companion.CenterVertically
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
@@ -75,19 +74,19 @@ fun UserReactionsRow(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
Row(verticalAlignment = CenterVertically, modifier = Modifier.weight(1f)) {
|
||||||
UserReplyModel(model)
|
UserReplyModel(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
Row(verticalAlignment = CenterVertically, modifier = Modifier.weight(1f)) {
|
||||||
UserBoostModel(model)
|
UserBoostModel(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
Row(verticalAlignment = CenterVertically, modifier = Modifier.weight(1f)) {
|
||||||
UserReactionModel(model)
|
UserReactionModel(model)
|
||||||
}
|
}
|
||||||
|
|
||||||
Row(verticalAlignment = CenterVertically, modifier = remember { Modifier.weight(1f) }) {
|
Row(verticalAlignment = CenterVertically, modifier = Modifier.weight(1f)) {
|
||||||
UserZapModel(model)
|
UserZapModel(model)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.layout.size
|
import androidx.compose.foundation.layout.size
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
@@ -78,7 +77,7 @@ fun ZapUserSetCompose(
|
|||||||
modifier = Size55Modifier,
|
modifier = Size55Modifier,
|
||||||
) {
|
) {
|
||||||
ZappedIcon(
|
ZappedIcon(
|
||||||
remember { Modifier.size(Size25dp).align(Alignment.TopEnd) },
|
Modifier.size(Size25dp).align(Alignment.TopEnd),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +102,7 @@ fun ZapUserSetCompose(
|
|||||||
nav = nav,
|
nav = nav,
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(modifier = remember { Modifier.padding(start = 10.dp).weight(1f) }) {
|
Column(modifier = Modifier.padding(start = 10.dp).weight(1f)) {
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) { UsernameDisplay(zapSetCard.user, accountViewModel = accountViewModel) }
|
Row(verticalAlignment = Alignment.CenterVertically) { UsernameDisplay(zapSetCard.user, accountViewModel = accountViewModel) }
|
||||||
|
|
||||||
AboutDisplay(zapSetCard.user, accountViewModel)
|
AboutDisplay(zapSetCard.user, accountViewModel)
|
||||||
|
|||||||
+1
-1
@@ -167,7 +167,7 @@ fun LongPublicChatChannelHeader(
|
|||||||
modifier = Modifier.width(75.dp),
|
modifier = Modifier.width(75.dp),
|
||||||
)
|
)
|
||||||
Spacer(DoubleHorzSpacer)
|
Spacer(DoubleHorzSpacer)
|
||||||
NormalTimeAgo(note, remember { Modifier.weight(1f) })
|
NormalTimeAgo(note, Modifier.weight(1f))
|
||||||
MoreOptionsButton(note, null, accountViewModel, nav)
|
MoreOptionsButton(note, null, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -116,7 +116,7 @@ fun LongLiveActivityChannelHeader(
|
|||||||
modifier = Modifier.width(75.dp),
|
modifier = Modifier.width(75.dp),
|
||||||
)
|
)
|
||||||
Spacer(DoubleHorzSpacer)
|
Spacer(DoubleHorzSpacer)
|
||||||
NormalTimeAgo(note, remember { Modifier.weight(1f) })
|
NormalTimeAgo(note, Modifier.weight(1f))
|
||||||
MoreOptionsButton(note, null, accountViewModel, nav)
|
MoreOptionsButton(note, null, accountViewModel, nav)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-2
@@ -30,7 +30,6 @@ import androidx.compose.foundation.verticalScroll
|
|||||||
import androidx.compose.material3.IconButton
|
import androidx.compose.material3.IconButton
|
||||||
import androidx.compose.material3.MaterialTheme
|
import androidx.compose.material3.MaterialTheme
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.remember
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
import com.vitorpamplona.amethyst.commons.icons.symbols.Icon
|
||||||
@@ -57,7 +56,7 @@ fun DisplayReplyingToNote(
|
|||||||
.animateContentSize(),
|
.animateContentSize(),
|
||||||
) {
|
) {
|
||||||
if (replyingNote != null) {
|
if (replyingNote != null) {
|
||||||
Column(remember { Modifier.weight(1f) }) {
|
Column(Modifier.weight(1f)) {
|
||||||
ChatroomMessageCompose(
|
ChatroomMessageCompose(
|
||||||
baseNote = replyingNote,
|
baseNote = replyingNote,
|
||||||
null,
|
null,
|
||||||
|
|||||||
+1
-1
@@ -535,7 +535,7 @@ private fun FullBleedNoteCompose(
|
|||||||
|
|
||||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||||
Column(
|
Column(
|
||||||
remember { Modifier.weight(1f) },
|
Modifier.weight(1f),
|
||||||
) {
|
) {
|
||||||
if (noteEvent is IForkableEvent && noteEvent.isAFork()) {
|
if (noteEvent is IForkableEvent && noteEvent.isAFork()) {
|
||||||
ShowForkInformation(noteEvent, Modifier, accountViewModel, nav)
|
ShowForkInformation(noteEvent, Modifier, accountViewModel, nav)
|
||||||
|
|||||||
+1
-1
@@ -79,7 +79,7 @@ fun BookmarksScreen(
|
|||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
val connectedRelays = relayStatuses.keys
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
// Tab state
|
// Tab state
|
||||||
|
|||||||
@@ -280,7 +280,7 @@ fun FeedScreen(
|
|||||||
val followedUsers by localCache.followedUsers.collectAsState()
|
val followedUsers by localCache.followedUsers.collectAsState()
|
||||||
|
|
||||||
// Available relay URLs — subscribe triggers connection on-demand
|
// 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)
|
// Feed relays from relay categories (NIP-65 outbox, minus blocked, with fallback)
|
||||||
val relayCategories = LocalRelayCategories.current
|
val relayCategories = LocalRelayCategories.current
|
||||||
|
|||||||
+1
-1
@@ -115,7 +115,7 @@ fun NotificationsScreen(
|
|||||||
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator? = null,
|
subscriptionsCoordinator: DesktopRelaySubscriptionsCoordinator? = null,
|
||||||
) {
|
) {
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
val connectedRelays = relayStatuses.keys
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
val notificationState =
|
val notificationState =
|
||||||
remember {
|
remember {
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ fun ReadsScreen(
|
|||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
val connectedRelays = relayStatuses.keys
|
||||||
val scope = rememberCoroutineScope()
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
val eventState =
|
val eventState =
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ fun SearchScreen(
|
|||||||
|
|
||||||
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
val connectedRelays by relayManager.connectedRelays.collectAsState()
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val allRelayUrls = remember(relayStatuses) { relayStatuses.keys }
|
val allRelayUrls = relayStatuses.keys
|
||||||
val relayCategories = LocalRelayCategories.current
|
val relayCategories = LocalRelayCategories.current
|
||||||
val searchRelays by relayCategories.searchRelays.collectAsState()
|
val searchRelays by relayCategories.searchRelays.collectAsState()
|
||||||
val displayText by state.displayText.collectAsState()
|
val displayText by state.displayText.collectAsState()
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ fun ThreadScreen(
|
|||||||
onReply: (Event) -> Unit = {},
|
onReply: (Event) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
val connectedRelays = relayStatuses.keys
|
||||||
|
|
||||||
// Lightbox state
|
// Lightbox state
|
||||||
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
var lightboxState by remember { mutableStateOf<LightboxState?>(null) }
|
||||||
|
|||||||
+1
-1
@@ -122,7 +122,7 @@ fun UserProfileScreen(
|
|||||||
onZapFeedback: (ZapFeedback) -> Unit = {},
|
onZapFeedback: (ZapFeedback) -> Unit = {},
|
||||||
) {
|
) {
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
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
|
// User metadata — seed from cache so returning to profile is instant
|
||||||
val cachedUser = remember(pubKeyHex) { localCache.getUserIfExists(pubKeyHex) }
|
val cachedUser = remember(pubKeyHex) { localCache.getUserIfExists(pubKeyHex) }
|
||||||
|
|||||||
+1
-1
@@ -78,7 +78,7 @@ fun NewDmDialog(
|
|||||||
val relaySearchResults by searchState.relaySearchResults.collectAsState()
|
val relaySearchResults by searchState.relaySearchResults.collectAsState()
|
||||||
val isSearchingRelays by searchState.isSearchingRelays.collectAsState()
|
val isSearchingRelays by searchState.isSearchingRelays.collectAsState()
|
||||||
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
val relayStatuses by relayManager.relayStatuses.collectAsState()
|
||||||
val connectedRelays = remember(relayStatuses) { relayStatuses.keys }
|
val connectedRelays = relayStatuses.keys
|
||||||
val focusRequester = remember { FocusRequester() }
|
val focusRequester = remember { FocusRequester() }
|
||||||
|
|
||||||
// NIP-50 relay search when local cache has few/no results
|
// NIP-50 relay search when local cache has few/no results
|
||||||
|
|||||||
Reference in New Issue
Block a user