fix(nests): emit canonical title tag and keep mute badge visible while muted
Two interrelated bugs from the deployed-schema flip:
1. Rooms created in Amethyst didn't appear in nostrnests's "Live Now"
lobby. The lobby filter in NestsUI's skeleton.js requires a `title`
tag on every kind:30312 — events without one are dropped from
`live`/`planned`/`ended`. RoomNameTag still emitted the legacy
`room` name, so our rooms passed our own readers (which tolerate
both names) but were invisible to NestsUI. Flip canonical to
`title`, keep `room` as legacy on read.
2. The mute badge over the avatar disappeared shortly after toggling
mute, even though the broadcaster was still muted. Two causes:
- ParticipantsGrid gated both the muted ring and the MicStateBadge
on `member.publishing`. But per the deployed kind-10312 semantics
`publishing=0` whenever `muted=1` (NestRoomPresencePublisher
mirrors this — `publishingNow = broadcasting && !isMuted`), so
the badge that was supposed to *indicate* mute was hidden
exactly when it became relevant. Show the badge when on stage
and either publishing OR muted; gate the muted ring on `muted`
alone.
- The presence heartbeat captured `micMutedTag` / `publishingTag`
/ `onstageTag` / `handRaised` at LaunchedEffect launch and never
refreshed them. The 500 ms debounced LaunchedEffect did publish
the new mute state, but ~30 s later the heartbeat overwrote it
with the captured pre-toggle values, flipping `publishing`
back to 1 and `muted` back to 0 server-side. Wrap the dynamic
fields in `rememberUpdatedState` so the heartbeat reads the
latest snapshot on every refresh; keep the existing key set
(event/handRaised/onstage) for prompt re-emission on those
transitions.
Tests updated for the new canonical `title` emission; both jvmTest
suites pass.
This commit is contained in:
+12
-5
@@ -23,17 +23,24 @@ package com.vitorpamplona.quartz.nip53LiveActivities.meetingSpaces.tags
|
||||
import com.vitorpamplona.quartz.nip01Core.core.has
|
||||
import com.vitorpamplona.quartz.utils.ensure
|
||||
|
||||
/**
|
||||
* Room display name on a NIP-53 / nests `kind:30312` event. Matches
|
||||
* the deployed nostrnests reference, which writes `["title", name]`
|
||||
* AND filters its lobby on the `title` tag's presence — kind-30312
|
||||
* events without a `title` are dropped from "Live Now". The early
|
||||
* EGG-01 draft called this `room`; we accept that name on read for
|
||||
* older events but always emit `title`.
|
||||
*/
|
||||
class RoomNameTag {
|
||||
companion object Companion {
|
||||
const val TAG_NAME = "room"
|
||||
const val TAG_NAME = "title"
|
||||
|
||||
/**
|
||||
* Legacy alias used by first-generation nostrnests web clients,
|
||||
* which reused the NIP-53 streaming-event `title` tag for the
|
||||
* kind-30312 room name. Accepted on read; we always emit the
|
||||
* Earlier EGG-01 draft name for the room display name.
|
||||
* Accepted on read for back-compat; we always emit the
|
||||
* canonical [TAG_NAME].
|
||||
*/
|
||||
const val LEGACY_TAG_NAME = "title"
|
||||
const val LEGACY_TAG_NAME = "room"
|
||||
|
||||
fun parse(tag: Array<String>): String? {
|
||||
ensure(tag.has(1)) { return null }
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ class MeetingSpaceEventBuildTest {
|
||||
val byName = template.tags.groupBy { it[0] }
|
||||
|
||||
assertEquals("main-hall", byName["d"]?.single()?.get(1))
|
||||
assertEquals("Main Hall", byName["room"]?.single()?.get(1))
|
||||
assertEquals("Main Hall", byName["title"]?.single()?.get(1))
|
||||
assertEquals("live", byName["status"]?.single()?.get(1))
|
||||
assertEquals("https://meet.example.com/hall", byName["auth"]?.single()?.get(1))
|
||||
assertEquals("https://api.example.com/hall", byName["streaming"]?.single()?.get(1))
|
||||
|
||||
Reference in New Issue
Block a user