From 8d53c9025df0bbfde9159bfd65c4108a32e7bfe8 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 27 Apr 2026 19:10:12 +0000 Subject: [PATCH] feat(meetingrooms): show parent MeetingSpace link on kind:30313 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A NIP-53 kind-30313 [MeetingRoomEvent] references its parent kind-30312 [MeetingSpaceEvent] via the standard `["a", "30312::"]` tag. Without surfacing it, a meeting card in a feed lost the context of which Nest the meeting belonged to — users couldn't tell if "Office Hours Q3" lived inside their company nest or someone else's. Render a small "In " label above the meeting's title inside [RenderMeetingRoomEventInner]: - Resolves the parent address via `MeetingRoomEvent.interactiveRoom()` → `MeetingSpaceTag.address`. Bails when the address points at something other than kind:30312 (no broken links). - Loads the parent through the existing `LoadAddressableNote` helper. When the kind:30312 hasn't propagated to LocalCache yet, the row falls back to a generic "In a Nest" label and tapping routes through the standard `routeFor` thread path which auto-fetches. - Tap navigates to the parent space's thread view via `routeFor` + `nav.nav` — the same path Discovery / NoteCompose use for quote-into-thread navigation. Two new strings: - meeting_room_in_space ("In %1$s") - meeting_room_in_space_unknown ("a Nest" — fallback when the parent space isn't yet resolvable) https://claude.ai/code/session_01RDpuki4t8StSg1CZcXnV5b --- .../amethyst/ui/note/types/MeetingSpace.kt | 62 +++++++++++++++++++ amethyst/src/main/res/values/strings.xml | 2 + 2 files changed, 64 insertions(+) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt index 3d2bd891a3..c91a98cf90 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/MeetingSpace.kt @@ -249,6 +249,15 @@ fun RenderMeetingRoomEventInner( val status = remember(eventUpdates) { noteEvent.status() } val starts = remember(eventUpdates) { noteEvent.starts() } val participants = remember(eventUpdates) { noteEvent.participants() } + val interactiveRoom = remember(eventUpdates) { noteEvent.interactiveRoom() } + + interactiveRoom?.let { spaceTag -> + ParentMeetingSpaceLink( + spaceAddress = spaceTag.address, + accountViewModel = accountViewModel, + nav = nav, + ) + } Row( verticalAlignment = Alignment.CenterVertically, @@ -293,6 +302,59 @@ fun RenderMeetingRoomEventInner( RenderParticipants(participants, accountViewModel, nav) } +/** + * Small "In " row rendered above a kind-30313 + * [MeetingRoomEvent] so users see which kind-30312 space the + * meeting belongs to. Resolves the addressable note for the parent + * space; if the kind-30312 hasn't been seen yet the link still + * renders with a placeholder name and tapping navigates to its + * thread (which auto-fetches the event). When the parent address + * doesn't resolve to a kind-30312 we render nothing — keeping the + * card free of broken links. + */ +@Composable +private fun ParentMeetingSpaceLink( + spaceAddress: com.vitorpamplona.quartz.nip01Core.core.Address, + accountViewModel: AccountViewModel, + nav: INav, +) { + if (spaceAddress.kind != MeetingSpaceEvent.KIND) return + + com.vitorpamplona.amethyst.ui.note.LoadAddressableNote( + address = spaceAddress, + accountViewModel = accountViewModel, + ) { spaceNote -> + spaceNote ?: return@LoadAddressableNote + val spaceEvent = spaceNote.event as? MeetingSpaceEvent + val spaceName = + spaceEvent?.room()?.ifBlank { null } + ?: stringRes(R.string.meeting_room_in_space_unknown) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = + Modifier + .fillMaxWidth() + .clickable { + nav.nav { + com.vitorpamplona.amethyst.ui.navigation.routes.routeFor( + spaceNote, + accountViewModel.account, + ) + } + }.padding(vertical = 4.dp), + ) { + Text( + text = stringRes(R.string.meeting_room_in_space, spaceName), + style = MaterialTheme.typography.labelSmall, + color = MaterialTheme.colorScheme.placeholderText, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + } + } +} + /** * Inline renderer for kind-10312 [MeetingRoomPresenceEvent] events. * The event's `content` is empty; the interesting bits are the diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index e18e41a0c2..1807156d0d 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -489,6 +489,8 @@ Follow Packs Live Streams Nests + In %1$s + a Nest Stage Audience Raise hand