fix: open NIP-29 group posts in the group chat, not a thread view

Tapping a NIP-29 message in Notifications (or the feed) fell through routeFor's
`else -> Route.Note`, opening the generic thread view instead of the group chat —
unlike every other chat NIP. Mirror the Marmot-group path: when a note is
attached to a RelayGroupChannel gatherer, route to Route.RelayGroup (the channel
carries the host relay). Add an `h`-tag + provenance-relay fallback for a
group-scoped note that isn't attached to a channel yet, so it still opens the
chat rather than a thread.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01B5MLY4hq5LXJ2D5WeLRyXj
This commit is contained in:
Claude
2026-07-09 20:24:39 +00:00
parent dae4ade55a
commit b935995fe6
@@ -46,6 +46,8 @@ import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent
import com.vitorpamplona.quartz.nip28PublicChat.base.IsInPublicChatChannel
import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent
import com.vitorpamplona.quartz.nip29RelayGroups.GroupId
import com.vitorpamplona.quartz.nip29RelayGroups.groupId
import com.vitorpamplona.quartz.nip29RelayGroups.isGroupScoped
import com.vitorpamplona.quartz.nip34Git.repository.GitRepositoryEvent
import com.vitorpamplona.quartz.nip37Drafts.DraftWrapEvent
import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent
@@ -73,8 +75,25 @@ fun routeFor(
return Route.MarmotGroupChat(marmotGroup.nostrGroupId)
}
// NIP-29 relay-group content (kind 9 chat, 11 thread, 1111 comment, polls) should open the
// group chat screen — like every other chat NIP — not the generic thread view it would fall
// through to. A consumed group message is attached to its RelayGroupChannel (which carries the
// host relay), so route via that; fall back to the note's `h` tag + provenance relay otherwise.
val relayGroup = note.inGatherers?.firstNotNullOfOrNull { it as? RelayGroupChannel }
if (relayGroup != null) {
return routeFor(relayGroup)
}
val noteEvent = note.event ?: return Route.EventRedirect(note.idHex)
if (noteEvent.isGroupScoped()) {
val groupId = noteEvent.groupId()
val hostRelay = note.relays.firstOrNull()
if (groupId != null && hostRelay != null) {
return routeFor(GroupId(groupId, hostRelay))
}
}
return routeFor(noteEvent, loggedIn)
}