fix: hide StageControlsBar on local intent flag for responsive tap
After tapping Leave the Stage, the bar lingered because it was gated solely on isOnStageMe — a value derived from the presence aggregator. That aggregator only updates after a presence event signs, broadcasts to relays, and loops back through LocalCache. With the recent broadcast / mute traffic contending on the signer plus the 500 ms mute debounce in NestPresencePublisher, the round-trip ran long enough that the user perceived Leave the Stage as not firing. AND the visibility gate with ui.onStageNow (the local intent flag, which flips synchronously on setOnStage(false)) so the tap hides the bar on the next frame. Host demotion still hides it via the existing isOnStageMe path.
This commit is contained in:
+15
-7
@@ -133,12 +133,20 @@ internal fun NestActionBar(
|
|||||||
* everything a speaker needs while on stage: Talk / MicMute / Retry +
|
* everything a speaker needs while on stage: Talk / MicMute / Retry +
|
||||||
* Leave the Stage. Renders nothing when the local user isn't on stage.
|
* Leave the Stage. Renders nothing when the local user isn't on stage.
|
||||||
*
|
*
|
||||||
* Visibility is gated on [isOnStage] alone — a stable signal driven
|
* Visibility uses two signals AND'd together:
|
||||||
* by the kind-30312 role + presence `onstage` flag — so connection
|
* - [isOnStage] — derived from `participantGrid.onStage` (kind-30312
|
||||||
* blips, broadcast state churn, mute toggles, and permission flows
|
* role + presence `onstage` flag); flips on a real promote/demote
|
||||||
* never make the bar appear or disappear. It only shows up on a real
|
* after the round-trip lands. Connection blips, broadcast state
|
||||||
* promote, and only goes away on a real demote (or the user tapping
|
* churn, mute toggles, and permission flows do NOT change it.
|
||||||
* Leave the Stage).
|
* - [ui.onStageNow] — the LOCAL intent flag. Flips synchronously on
|
||||||
|
* `setOnStage(false)` so a Leave-the-Stage tap hides the bar on
|
||||||
|
* the next frame, instead of waiting for the presence event to
|
||||||
|
* sign, broadcast, and loop back through LocalCache (a delay made
|
||||||
|
* visible in scenario "broadcast → mute → unmute → leave", where
|
||||||
|
* the signer queues behind a pending mute frame + 500 ms debounce).
|
||||||
|
*
|
||||||
|
* AND-of-both also handles host demotion correctly: intent stays true
|
||||||
|
* but the aggregator drops us, so the bar still hides.
|
||||||
*/
|
*/
|
||||||
@Composable
|
@Composable
|
||||||
internal fun StageControlsBar(
|
internal fun StageControlsBar(
|
||||||
@@ -149,7 +157,7 @@ internal fun StageControlsBar(
|
|||||||
speakerPubkeyHex: String,
|
speakerPubkeyHex: String,
|
||||||
modifier: Modifier = Modifier,
|
modifier: Modifier = Modifier,
|
||||||
) {
|
) {
|
||||||
if (!isOnStage) return
|
if (!isOnStage || !ui.onStageNow) return
|
||||||
Row(
|
Row(
|
||||||
modifier =
|
modifier =
|
||||||
modifier
|
modifier
|
||||||
|
|||||||
Reference in New Issue
Block a user