fix: stop reordering Nest stage members by speaking state

Members were sorted to float the current speaker to the top, so a
member jumped to the front when they started talking and slid back
~250ms after they stopped — a constant shuffle in any active room.
The speaking state is already shown in-place via the mic badge and
audio-level ring, so keep members in their stable arrival order.

https://claude.ai/code/session_01GvvNS1FRn6gGvHRC7dgEtP
This commit is contained in:
Claude
2026-05-14 18:35:40 +00:00
parent d8d077b4e7
commit 2408c43918
@@ -162,15 +162,12 @@ internal fun StageGrid(
listenerCount: Int = 0, listenerCount: Int = 0,
bottomBar: (@Composable () -> Unit)? = null, bottomBar: (@Composable () -> Unit)? = null,
) { ) {
// Float currently-speaking members to the top so the listener can // Keep members in their stable arrival order. Reordering on the
// see who they're hearing without scrolling. sortedBy is stable in // speaking state made a member jump to the front when they started
// Kotlin — speakers retain relative order among themselves, as do // talking and slide back ~250ms after they stopped — a constant
// non-speakers. Memoized on (members, speakingNow) so a 250ms // shuffle in any active room. The speaking state is already shown
// speaking flip doesn't reallocate when neither input changed. // in-place via MemberCell's mic badge / audio-level ring, so no
val sortedMembers = // reordering is needed.
remember(members, speakingNow) {
members.sortedBy { if (it.pubkey in speakingNow) 0 else 1 }
}
// Wrap the strip in a tonal card so the active speakers visually // Wrap the strip in a tonal card so the active speakers visually
// live in their own zone, separated from the chat / audience tab // live in their own zone, separated from the chat / audience tab
// below. surfaceContainerLow is a quiet step up from the screen // below. surfaceContainerLow is a quiet step up from the screen
@@ -221,7 +218,7 @@ internal fun StageGrid(
horizontalArrangement = Arrangement.spacedBy(GRID_SPACING), horizontalArrangement = Arrangement.spacedBy(GRID_SPACING),
verticalArrangement = Arrangement.spacedBy(GRID_SPACING), verticalArrangement = Arrangement.spacedBy(GRID_SPACING),
) { ) {
items(items = sortedMembers, key = { it.pubkey }) { member -> items(items = members, key = { it.pubkey }) { member ->
val isSelf = myPubkey != null && member.pubkey == myPubkey val isSelf = myPubkey != null && member.pubkey == myPubkey
MemberCell( MemberCell(
member = member, member = member,