From babdea67abab4c8835d8154fa213e7aa76543294 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 10 Jul 2026 15:51:51 +0000 Subject: [PATCH] feat: list joined groups' relays as filter chips in Relay Groups discovery MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit You had to Favorite a relay (kind-10012) before it appeared as a chip in the Relay Groups top-nav filter — even for relays you already have groups on. Now the host relay of every group in your joined list (kind-10009) also shows up as a relay chip, so you can browse the other groups on those relays without favoriting them first. Added only to the relay-groups discovery catalog (not git/podcasts/etc.), deduped against relays already present as favorites. Selecting one resolves to that relay's groups (filtered by the relay-signed self-key check as usual). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01B5MLY4hq5LXJ2D5WeLRyXj --- .../amethyst/ui/screen/TopNavFilterState.kt | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt index 53e54b2b8b..80a1ce25b2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/TopNavFilterState.kt @@ -32,6 +32,7 @@ import com.vitorpamplona.amethyst.service.checkNotInMainThread import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.stringRes import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.RelayUrlNormalizer import com.vitorpamplona.quartz.nip01Core.relay.normalizer.displayUrl import com.vitorpamplona.quartz.nip51Lists.followList.FollowListEvent import com.vitorpamplona.quartz.nip51Lists.interestSet.InterestSetEvent @@ -332,16 +333,32 @@ class TopNavFilterState( combineTransform( livePeopleListsFlow, liveInterestFlows, - ) { peopleLists, interests -> + account.relayGroupList.liveRelayGroupServers, + ) { peopleLists, interests, joinedServers -> checkNotInMainThread() + // A relay chip per host relay of every group the user joined (kind-10009), so they can + // browse the OTHER groups on those relays without first having to Favorite them. Deduped + // against relays that are already chips because they were favorited (kind-10012, already + // in `interests`). Only in this catalog — other feeds (git, podcasts, …) don't want them. + val alreadyChip = interests.mapNotNullTo(HashSet()) { (it.code as? TopFilter.Relay)?.url } + val joinedRelayChips = + joinedServers + .asSequence() + .mapNotNull { RelayUrlNormalizer.normalizeOrNull(it) } + .filter { it.url !in alreadyChip } + .distinctBy { it.url } + .map { FeedDefinition(TopFilter.Relay(it.url), RelayName(it)) } + .sortedBy { it.name.name() } + .toList() emit( listOf( - // Relay-group discovery routes to relays by author, hashtag and geohash, plus a - // favorite-relay chip; "Mine" (the joined-groups view) sits last in the base - // group to match the ordering every other feed uses. + // Relay-group discovery routes to relays by author, hashtag and geohash, plus + // favorited + joined-group relay chips; "Mine" (the joined-groups view) sits last + // in the base group to match the ordering every other feed uses. listOf(allFollows, userFollows, kind3Follows, aroundMe, globalFollow, mineFollow), peopleLists, interests, + joinedRelayChips, listOf(muteListFollow), ).flatten().toImmutableList(), )