diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/datasource/FilterBadges.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/datasource/FilterBadges.kt index fde9c08ecb..a6784a40e2 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/datasource/FilterBadges.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/badges/datasource/FilterBadges.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.Aut import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.ExplainedFilter import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.SubPurpose +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter @@ -47,7 +48,7 @@ fun makeBadgesFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterBadgesByMutedAuthors(feedSettings, since, defaultSince) is GlobalTopNavPerRelayFilterSet -> filterBadgesGlobal(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) private fun filterBadgesByAuthorsOnRelay( relay: NormalizedRelayUrl, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/calendars/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/calendars/datasource/SubAssemblyHelper.kt index fff17417a6..5ada462939 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/calendars/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/calendars/datasource/SubAssemblyHelper.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavP import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.calendars.datasource.subassemblies.filterCalendarsByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.calendars.datasource.subassemblies.filterCalendarsByFollows @@ -49,4 +50,4 @@ fun makeCalendarsFilter( is LocationTopNavPerRelayFilterSet -> filterCalendarsByGeohashes(feedSettings, since, defaultSince) is MutedAuthorsTopNavPerRelayFilterSet -> filterCalendarsByMutedAuthors(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoveryFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoveryFilter.kt index 446c26f336..f510d09c74 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoveryFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoveryFilter.kt @@ -30,6 +30,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.Aut import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.relay.RelayTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.relayGroup.datasource.subassemblies.filterRelayGroupsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.relayGroup.datasource.subassemblies.filterRelayGroupsByAuthors @@ -58,4 +59,4 @@ fun filterRelayGroupsDiscovery( is RelayTopNavPerRelayFilterSet -> filterRelayGroupsByRelay(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterRelayGroupsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoverySubAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoverySubAssembler.kt index 24c9ec5e14..533e638f0f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoverySubAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/chats/publicChannels/relayGroup/datasource/RelayGroupsDiscoverySubAssembler.kt @@ -22,6 +22,7 @@ package com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.publicChannels.relay import com.vitorpamplona.amethyst.commons.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.TopFilter import com.vitorpamplona.amethyst.model.User @@ -88,7 +89,9 @@ class RelayGroupsDiscoverySubAssembler( ) } - return base + extra + // `base` is scoped by its own builder; these host-relay rosters are built here, so they get + // the same selection stamped on them rather than showing up as an unexplained extra. + return base + extra.scopedTo(feedSettings) } /** Relays that host NIP-29 groups the user is connected to: joined (kind-10009) + favorited (kind-10012). */ diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/SubAssemblyHelper.kt index 5b084b3d7b..4caa8189af 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies.filterLongFormByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.subassemblies.filterLongFormByAuthors @@ -54,4 +55,4 @@ fun makeLongFormFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterLongFormByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterLongFormByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip28Chats/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip28Chats/SubAssemblyHelper.kt index 4cef2d6b60..3b7d225445 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip28Chats/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip28Chats/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies.filterPublicChatsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.subassemblies.filterPublicChatsByAuthors @@ -54,4 +55,4 @@ fun makePublicChatsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterPublicChatsByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterPublicChatsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip51FollowSets/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip51FollowSets/SubAssemblyHelper.kt index eaf3b772ae..f87c6e1bd1 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip51FollowSets/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip51FollowSets/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies.filterFollowSetsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.subassemblies.filterFollowSetsByAuthors @@ -54,4 +55,4 @@ fun makeFollowSetsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterFollowSetsByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterFollowSetsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip53LiveActivities/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip53LiveActivities/SubAssemblyHelper.kt index 1c971dcc0a..12cab5f61b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip53LiveActivities/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip53LiveActivities/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies.filterLiveActivitiesByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.subassemblies.filterLiveActivitiesByAuthors @@ -54,4 +55,4 @@ fun makeLiveActivitiesFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterLiveActivitiesByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterLiveActivitiesByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip72Communities/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip72Communities/SubAssemblyHelper.kt index 362c942fce..e63a9392af 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip72Communities/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip72Communities/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies.filterCommunitiesByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip72Communities.subassemblies.filterCommunitiesByAuthors @@ -54,4 +55,4 @@ fun makeCommunitiesFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterCommunitiesByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterCommunitiesByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/SubAssemblyHelper.kt index 2f984e5a2f..4623328113 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip90DVMs/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies.filterContentDVMsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.subassemblies.filterContentDVMsByAuthors @@ -54,4 +55,4 @@ fun makeContentDVMsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterContentDVMsByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterContentDVMsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SubAssemblyHelper.kt index ef6822c706..bb0f59d628 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip99Classifieds/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies.filterClassifiedsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.subassemblies.filterClassifiedsByAuthors @@ -54,4 +55,4 @@ fun makeClassifiedsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterClassifiedsByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterClassifiedsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/browse/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/browse/datasource/SubAssemblyHelper.kt index d801597e56..3d547bbd30 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/browse/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/emojipacks/browse/datasource/SubAssemblyHelper.kt @@ -26,6 +26,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavP import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.emojipacks.browse.datasource.subassemblies.filterBrowseEmojiSetsByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.emojipacks.browse.datasource.subassemblies.filterBrowseEmojiSetsByFollows @@ -46,4 +47,4 @@ fun makeBrowseEmojiSetsFilter( is GlobalTopNavPerRelayFilterSet -> filterBrowseEmojiSetsGlobal(feedSettings, since, defaultSince) is HashtagTopNavPerRelayFilterSet -> filterBrowseEmojiSetsByHashtag(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/datasource/GitRepositoriesFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/datasource/GitRepositoriesFilter.kt index f2d6907931..131e02ff9f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/datasource/GitRepositoriesFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/gitRepositories/datasource/GitRepositoriesFilter.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.gitRepositories.datasource.subassemblies.filterGitRepositoriesByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.gitRepositories.datasource.subassemblies.filterGitRepositoriesByAuthors @@ -55,4 +56,4 @@ fun makeGitRepositoriesFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterGitRepositoriesByMutedAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterGitRepositoriesByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/highlights/datasource/HighlightsFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/highlights/datasource/HighlightsFilter.kt index 081757b928..10123b7961 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/highlights/datasource/HighlightsFilter.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/highlights/datasource/HighlightsFilter.kt @@ -27,6 +27,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavP import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.highlights.datasource.subassemblies.filterHighlightsByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.highlights.datasource.subassemblies.filterHighlightsByFollows @@ -57,4 +58,4 @@ fun makeHighlightsFilter( is LocationTopNavPerRelayFilterSet -> filterHighlightsByGeohashes(feedSettings, since, defaultSince) is MutedAuthorsTopNavPerRelayFilterSet -> filterHighlightsByMutedAuthors(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/HomeOutboxEventsEoseManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/HomeOutboxEventsEoseManager.kt index b9e14c1e2a..bd6a313c80 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/HomeOutboxEventsEoseManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/home/datasource/nip65Follows/HomeOutboxEventsEoseManager.kt @@ -30,6 +30,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.Aut import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.relay.RelayTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.model.HomeFeedType import com.vitorpamplona.amethyst.model.TopFilter import com.vitorpamplona.amethyst.model.User @@ -78,7 +79,7 @@ class HomeOutboxEventsEoseManager( is SingleCommunityTopNavPerRelayFilterSet -> filterHomePostsByCommunity(feedSettings, since, newThreadSince) is FavoriteAlgoFeedTopNavPerRelayFilterSet -> filterHomePostsByAlgoFeedIds(feedSettings, since, newThreadSince) else -> emptyList() - } + }.scopedTo(feedSettings) // Drop the kinds the user turned off in Settings › Home from every home relay filter, so a // disabled group is never downloaded regardless of which top-nav strategy built the filters. diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/longs/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/longs/datasource/SubAssemblyHelper.kt index bf38841bdf..8d31577519 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/longs/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/longs/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.longs.datasource.subassemblies.filterLongsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.longs.datasource.subassemblies.filterLongsByAuthors @@ -55,4 +56,4 @@ fun makeLongsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterLongsByMutedAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterLongsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/music/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/music/datasource/SubAssemblyHelper.kt index 3bd3dfb23e..66fb95cb19 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/music/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/music/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.music.datasource.subassemblies.MUSIC_PLAYLIST_KINDS import com.vitorpamplona.amethyst.ui.screen.loggedIn.music.datasource.subassemblies.MUSIC_TRACK_KINDS @@ -82,4 +83,4 @@ private fun makeMusicFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterMusicEventsByMutedAuthors(feedSettings, kinds, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterMusicEventsByCommunity(feedSettings, kinds, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/datasource/SubAssemblyHelper.kt index a4fde42d99..1989a85064 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/napplets/datasource/SubAssemblyHelper.kt @@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.allFollows.AllFollow import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.napplets.datasource.subassemblies.filterNappletsByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.napplets.datasource.subassemblies.filterNappletsByFollows @@ -51,4 +52,4 @@ fun makeNappletsFilter( is GlobalTopNavPerRelayFilterSet -> filterNappletsGlobal(feedSettings, since, defaultSince) is MutedAuthorsTopNavPerRelayFilterSet -> filterNappletsByMutedAuthors(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/SubAssemblyHelper.kt index b0bf34fdf3..ed939269dc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nests/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.subassemblies.filterNestsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.nests.datasource.subassemblies.filterNestsByAuthors @@ -56,7 +57,7 @@ fun makeNestsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterNestsByAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterNestsByCommunity(feedSettings, since, defaultSince) else -> return emptyList() - } + }.scopedTo(feedSettings) if (rooms.isEmpty()) return rooms // Add a single presence probe per relay we're already querying for diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nsites/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nsites/datasource/SubAssemblyHelper.kt index 27cb00fabd..9aadcfdb2d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nsites/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/nsites/datasource/SubAssemblyHelper.kt @@ -25,6 +25,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.allFollows.AllFollow import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.nsites.datasource.subassemblies.filterNsitesByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.nsites.datasource.subassemblies.filterNsitesByFollows @@ -51,4 +52,4 @@ fun makeNsitesFilter( is GlobalTopNavPerRelayFilterSet -> filterNsitesGlobal(feedSettings, since, defaultSince) is MutedAuthorsTopNavPerRelayFilterSet -> filterNsitesByMutedAuthors(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/datasource/SubAssemblyHelper.kt index 617bb66573..048cb8e4e7 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/pictures/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.pictures.datasource.subassemblies.filterPicturesByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.pictures.datasource.subassemblies.filterPicturesByAuthors @@ -55,4 +56,4 @@ fun makePicturesFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterPicturesByMutedAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterPicturesByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/podcasts/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/podcasts/datasource/SubAssemblyHelper.kt index ff87f90c63..663eaeded3 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/podcasts/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/podcasts/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.podcasts.datasource.subassemblies.PODCASTING20_METADATA_KINDS import com.vitorpamplona.amethyst.ui.screen.loggedIn.podcasts.datasource.subassemblies.PODCAST_EPISODE_KINDS @@ -78,4 +79,4 @@ private fun makePodcastFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterPodcastEventsByMutedAuthors(feedSettings, kinds, since, defaultSince, additionalTags) is SingleCommunityTopNavPerRelayFilterSet -> filterPodcastEventsByCommunity(feedSettings, kinds, since, defaultSince, additionalTags) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/datasource/SubAssemblyHelper.kt index 862140b65f..add0a3780c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/polls/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.polls.datasource.subassemblies.filterPollsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.polls.datasource.subassemblies.filterPollsByAuthors @@ -55,4 +56,4 @@ fun makePollsFilter( is LocationTopNavPerRelayFilterSet -> filterPollsByGeohashes(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterPollsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsScreen.kt index 130f83f3a5..52dc8b0c68 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsScreen.kt @@ -60,6 +60,15 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.amethyst.R +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.allFollows.AllFollowsTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.aroundMe.LocationTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.favoriteAlgoFeeds.FavoriteAlgoFeedTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommunities.AllCommunitiesTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilter import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.SubPurpose import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.SubPurposeGroup import com.vitorpamplona.amethyst.model.LocalCache @@ -284,6 +293,29 @@ private fun PurposeCard( } } +/** + * The feed selection a discovery filter is searching within, in the app's own words. + * + * Hashtags and geohashes read out their own values — they are short, and the whole point is *which* + * hashtag. The author-based selections do not: a follow list is thousands of keys, and per relay it + * is a different slice of them, so naming the kind is the honest summary. + */ +@Composable +private fun scopeLabel(scope: IFeedTopNavPerRelayFilter): String? = + when (scope) { + is GlobalTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_global) + is AllFollowsTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_follows) + is AuthorsTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_authors) + is MutedAuthorsTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_muted) + is AllCommunitiesTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_all_communities) + is FavoriteAlgoFeedTopNavPerRelayFilter -> stringRes(R.string.active_subs_scope_algo) + is HashtagTopNavPerRelayFilter -> scope.hashtags.sorted().joinToString(", ") { "#$it" } + is LocationTopNavPerRelayFilter -> scope.geotags.sorted().joinToString(", ") + // The community and the relay already name themselves — the community through its own + // entity row, the relay through the row's relay list — so repeating it here would be noise. + else -> null + } + /** The entity's name, coloured as a link only when tapping it actually goes somewhere. */ @Composable private fun EntityLabelText( @@ -400,7 +432,12 @@ private fun EntityBlock( // Deliberately not falling back to `entity.detail`: that field is a developer breadcrumb set in // `commons`, where Android string resources do not exist, so it is hardcoded English and could // never be translated. A localized "no entity" line is better than an untranslatable one. - val label = resolved?.name ?: stringRes(R.string.active_subs_no_entity) + // + // A discovery filter has no entity by nature — it searches for chats and articles rather than + // serving ones already named — but it does carry the selection it searches within, which is a + // far better answer than "no entity". The scope arrives as a typed value for exactly this + // reason: the wording is chosen here, where translations exist. + val label = resolved?.name ?: entity.scope?.let { scopeLabel(it) } ?: stringRes(R.string.active_subs_no_entity) Column { Row( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsViewModel.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsViewModel.kt index 889cd6cb08..1074c360a0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsViewModel.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/relays/subscriptions/ActiveSubscriptionsViewModel.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.Immutable import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.vitorpamplona.amethyst.Amethyst +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilter import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.ExplainedFilter import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.SubPurpose import com.vitorpamplona.quartz.nip01Core.core.HexKey @@ -56,11 +57,29 @@ import kotlinx.coroutines.withContext data class SubscriptionEntityRow( /** Null when the filter named no entity — "the rest of this purpose", not a real entity. */ val entityId: HexKey?, + /** + * The top-nav selection behind a filter that names no entity — what a discovery filter is + * searching *within*. Null for filters that name a real entity, which speaks for itself. + */ + val scope: IFeedTopNavPerRelayFilter?, val detail: String?, val relays: List, val filterCount: Int, ) +/** + * What makes two filters the same row. + * + * [scopeKey] is the scope's **type**, not its contents: an author-based selection carries a + * different slice of the follow list to every relay, so keying on contents would shatter "People you + * follow" into one row per relay — the opposite of what this screen is for. Selections whose + * contents are the same everywhere (a hashtag, a geohash) render theirs from the retained instance. + */ +private data class EntityKey( + val entityId: HexKey?, + val scopeKey: String?, +) + @Immutable data class SubscriptionPurposeRow( val purpose: SubPurpose, @@ -109,8 +128,9 @@ class ActiveSubscriptionsViewModel : ViewModel() { val client = Amethyst.instance.client // account -> purpose -> entity -> relays / count - val byAccount = mutableMapOf>>>() - val detailOf = mutableMapOf, String?>() + val byAccount = mutableMapOf>>>() + val detailOf = mutableMapOf, String?>() + val scopeOf = mutableMapOf, IFeedTopNavPerRelayFilter>() var total = 0 var untagged = 0 val allRelays = mutableSetOf() @@ -124,17 +144,23 @@ class ActiveSubscriptionsViewModel : ViewModel() { return@forEach } allRelays.add(relay) + // Discovery filters name no entity — they go looking for things rather than + // serving known ones — but they do carry the selection they search within, which + // is what keeps them from collapsing into one nameless row per purpose. + val scopeKey = explained.scope?.let { it::class.simpleName } // A batched filter serves several entities at once — relay-group state is one #d // filter per host relay carrying every joined group on it — so it contributes a // row to each of them rather than collapsing to "All". val entities: List = explained.entityIds?.takeIf { it.isNotEmpty() } ?: listOf(null) entities.forEach { entityId -> + val key = EntityKey(entityId, scopeKey) byAccount .getOrPut(explained.accountPubKey) { mutableMapOf() } .getOrPut(explained.purpose) { mutableMapOf() } - .getOrPut(entityId) { mutableListOf() } + .getOrPut(key) { mutableListOf() } .add(relay) - detailOf[explained.purpose to entityId] = explained.purposeDetail + detailOf[explained.purpose to key] = explained.purposeDetail + explained.scope?.let { scopeOf.getOrPut(explained.purpose to key) { it } } } } } @@ -147,10 +173,11 @@ class ActiveSubscriptionsViewModel : ViewModel() { .map { (purpose, entities) -> val entityRows = entities - .map { (entityId, relays) -> + .map { (key, relays) -> SubscriptionEntityRow( - entityId = entityId, - detail = detailOf[purpose to entityId], + entityId = key.entityId, + scope = scopeOf[purpose to key], + detail = detailOf[purpose to key], relays = relays.distinct().sortedBy { it.url }, filterCount = relays.size, ) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/datasource/SubAssemblyHelper.kt index e53a715c45..5b7100b3cc 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/shorts/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.shorts.datasource.subassemblies.filterShortsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.shorts.datasource.subassemblies.filterShortsByAuthors @@ -55,4 +56,4 @@ fun makeShortsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterShortsByMutedAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterShortsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/softwareapps/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/softwareapps/datasource/SubAssemblyHelper.kt index 36339f10e3..a5f4f7969d 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/softwareapps/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/softwareapps/datasource/SubAssemblyHelper.kt @@ -26,6 +26,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.global.GlobalTopNavP import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.softwareapps.datasource.subassemblies.filterSoftwareAppsByAuthors import com.vitorpamplona.amethyst.ui.screen.loggedIn.softwareapps.datasource.subassemblies.filterSoftwareAppsByFollows @@ -48,4 +49,4 @@ fun makeSoftwareAppsFilter( is HashtagTopNavPerRelayFilterSet -> filterSoftwareAppsByHashtag(feedSettings, since, defaultSince) is MutedAuthorsTopNavPerRelayFilterSet -> filterSoftwareAppsByMutedAuthors(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/datasource/SubAssemblyHelper.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/datasource/SubAssemblyHelper.kt index 33f39d9d4f..72ec1e2da0 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/datasource/SubAssemblyHelper.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/workouts/datasource/SubAssemblyHelper.kt @@ -29,6 +29,7 @@ import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.allcommuni import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.author.AuthorsTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.community.SingleCommunityTopNavPerRelayFilterSet import com.vitorpamplona.amethyst.commons.model.topNavFeeds.noteBased.muted.MutedAuthorsTopNavPerRelayFilterSet +import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.scopedTo import com.vitorpamplona.amethyst.service.relays.SincePerRelayMap import com.vitorpamplona.amethyst.ui.screen.loggedIn.workouts.datasource.subassemblies.filterWorkoutsByAllCommunities import com.vitorpamplona.amethyst.ui.screen.loggedIn.workouts.datasource.subassemblies.filterWorkoutsByAuthors @@ -55,4 +56,4 @@ fun makeWorkoutsFilter( is MutedAuthorsTopNavPerRelayFilterSet -> filterWorkoutsByMutedAuthors(feedSettings, since, defaultSince) is SingleCommunityTopNavPerRelayFilterSet -> filterWorkoutsByCommunity(feedSettings, since, defaultSince) else -> emptyList() - } + }.scopedTo(feedSettings) diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index 6dcd4e12e3..3a7bb51880 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -2151,6 +2151,12 @@ %1$s \u00b7 %2$s Not attributed to an account All + Everyone + People you follow + A chosen list of people + Muted people + Your communities + A favorite algo feed %1$d%% of all subscriptions filters relays requests reqs connections why diagnostics Posts by people you follow, read from the relays each of them publishes to. diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/IFeedTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/IFeedTopNavPerRelayFilterSet.kt index ece74cd8c9..4addcf75f7 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/IFeedTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/IFeedTopNavPerRelayFilterSet.kt @@ -20,4 +20,19 @@ */ package com.vitorpamplona.amethyst.commons.model.topNavFeeds -interface IFeedTopNavPerRelayFilterSet +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl + +interface IFeedTopNavPerRelayFilterSet { + /** + * What this feed selection asks of one relay — the follows, hashtags, geohashes or communities + * scoped to it — or null when the set says nothing per relay. + * + * Declared here so an `ExplainedFilter` can carry the scope that produced it. A discovery filter + * names no entity (it searches for things rather than serving known ones), which used to leave + * the Active Subscriptions screen with a nameless row it could only label "no entity". The + * selection behind it was always known at build time; it just had nowhere to travel. Returning + * the per-relay value rather than the whole set keeps it exact: the filter is already per relay, + * so it carries only the slice that applies to it. + */ + fun scopeFor(relay: NormalizedRelayUrl): IFeedTopNavPerRelayFilter? +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/allFollows/AllFollowsTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/allFollows/AllFollowsTopNavPerRelayFilterSet.kt index cc7481733b..1e550dbdda 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/allFollows/AllFollowsTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/allFollows/AllFollowsTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class AllFollowsTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/aroundMe/LocationTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/aroundMe/LocationTopNavPerRelayFilterSet.kt index 565cbb2c07..00f3ed6995 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/aroundMe/LocationTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/aroundMe/LocationTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class LocationTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/favoriteAlgoFeeds/FavoriteAlgoFeedTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/favoriteAlgoFeeds/FavoriteAlgoFeedTopNavPerRelayFilterSet.kt index 9ad81f1e0e..130ff04adc 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/favoriteAlgoFeeds/FavoriteAlgoFeedTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/favoriteAlgoFeeds/FavoriteAlgoFeedTopNavPerRelayFilterSet.kt @@ -39,4 +39,8 @@ class FavoriteAlgoFeedTopNavPerRelayFilterSet( val contentFetches: Map, val listenRelays: Set, val requestIds: Set, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + // Only the content half is per-relay. [listenRelays] is where the DVMs answer, which is a + // delivery address rather than a scope, so a filter aimed there carries none. + override fun scopeFor(relay: NormalizedRelayUrl) = contentFetches[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/global/GlobalTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/global/GlobalTopNavPerRelayFilterSet.kt index 26a032841b..128d9f8386 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/global/GlobalTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/global/GlobalTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class GlobalTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/hashtag/HashtagTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/hashtag/HashtagTopNavPerRelayFilterSet.kt index 1621d64ca3..8ae9a41aec 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/hashtag/HashtagTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/hashtag/HashtagTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class HashtagTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/allcommunities/AllCommunitiesTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/allcommunities/AllCommunitiesTopNavPerRelayFilterSet.kt index 541647c10f..b7d9406a3c 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/allcommunities/AllCommunitiesTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/allcommunities/AllCommunitiesTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class AllCommunitiesTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/author/AuthorsTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/author/AuthorsTopNavPerRelayFilterSet.kt index 6c72c0b6d2..cffff74dc5 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/author/AuthorsTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/author/AuthorsTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class AuthorsTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/community/SingleCommunityTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/community/SingleCommunityTopNavPerRelayFilterSet.kt index d64a809749..d0178373bd 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/community/SingleCommunityTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/community/SingleCommunityTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class SingleCommunityTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/muted/MutedAuthorsTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/muted/MutedAuthorsTopNavPerRelayFilterSet.kt index 2f52a15003..942adce733 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/muted/MutedAuthorsTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/noteBased/muted/MutedAuthorsTopNavPerRelayFilterSet.kt @@ -25,4 +25,6 @@ import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class MutedAuthorsTopNavPerRelayFilterSet( val set: Map, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl) = set[relay] +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/relay/RelayTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/relay/RelayTopNavPerRelayFilterSet.kt index b3d891b5ba..bf57ace838 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/relay/RelayTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/relay/RelayTopNavPerRelayFilterSet.kt @@ -20,9 +20,14 @@ */ package com.vitorpamplona.amethyst.commons.model.topNavFeeds.relay +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilter import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilterSet import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl class RelayTopNavPerRelayFilterSet( val relayUrl: NormalizedRelayUrl, -) : IFeedTopNavPerRelayFilterSet +) : IFeedTopNavPerRelayFilterSet { + // The relay *is* the whole selection here, so there is nothing per-relay left to say — the + // filter's own relay already carries it. + override fun scopeFor(relay: NormalizedRelayUrl): IFeedTopNavPerRelayFilter? = null +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/unknown/UnknownTopNavPerRelayFilterSet.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/unknown/UnknownTopNavPerRelayFilterSet.kt index 7c01d40708..612c5da309 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/unknown/UnknownTopNavPerRelayFilterSet.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/model/topNavFeeds/unknown/UnknownTopNavPerRelayFilterSet.kt @@ -20,6 +20,10 @@ */ package com.vitorpamplona.amethyst.commons.model.topNavFeeds.unknown +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilter import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilterSet +import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl -object UnknownTopNavPerRelayFilterSet : IFeedTopNavPerRelayFilterSet +object UnknownTopNavPerRelayFilterSet : IFeedTopNavPerRelayFilterSet { + override fun scopeFor(relay: NormalizedRelayUrl): IFeedTopNavPerRelayFilter? = null +} diff --git a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilter.kt b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilter.kt index 65d9821165..7c46aea5ac 100644 --- a/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilter.kt +++ b/commons/src/commonMain/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilter.kt @@ -20,6 +20,8 @@ */ package com.vitorpamplona.amethyst.commons.relayClient.subscriptions +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilter +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.IFeedTopNavPerRelayFilterSet import com.vitorpamplona.quartz.nip01Core.core.HexKey import com.vitorpamplona.quartz.nip01Core.core.Kind import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter @@ -89,6 +91,24 @@ class ExplainedFilter( * account alive. */ val accountPubKey: HexKey? = null, + /** + * The top-nav selection that produced this filter — Global, the user's follows, a hashtag, a + * geohash, a community. + * + * [entityIds] answers "which known thing does this serve"; discovery filters have no such thing, + * because they go looking for chats/articles/streams rather than serving ones already named. That + * is not the same as having no explanation: the feed selection behind them was always known where + * the filter was built, it simply had nowhere to travel, so the screen could only render those + * rows as "no entity". + * + * The per-relay value, not the whole set: this filter is already scoped to one relay, so it + * carries only the slice that applies to it and holds no reference to the other relays' authors. + * + * A typed value rather than a formatted string, because [purposeDetail] taught the lesson — + * text built in `commons` can never be translated. The UI matches on the type and picks its own + * localized wording. + */ + val scope: IFeedTopNavPerRelayFilter? = null, ) : Filter(ids, authors, kinds, tags, tagsAll, since, until, limit, search) { override fun copy( ids: List?, @@ -100,7 +120,7 @@ class ExplainedFilter( until: Long?, limit: Int?, search: String?, - ) = ExplainedFilter(ids, authors, kinds, tags, tagsAll, since, until, limit, search, purpose, purposeDetail, entityIds, accountPubKey) + ) = ExplainedFilter(ids, authors, kinds, tags, tagsAll, since, until, limit, search, purpose, purposeDetail, entityIds, accountPubKey, scope) companion object { /** Tags [filter] with a [purpose], preserving every protocol field. */ @@ -110,6 +130,7 @@ class ExplainedFilter( detail: String? = null, entityIds: List? = null, accountPubKey: HexKey? = null, + scope: IFeedTopNavPerRelayFilter? = null, ) = ExplainedFilter( filter.ids, filter.authors, @@ -124,6 +145,7 @@ class ExplainedFilter( detail, entityIds, accountPubKey, + scope, ) } } @@ -173,7 +195,31 @@ fun List.attributedTo(accountPubKey: HexKey): List.scopedTo(feedSettings: IFeedTopNavPerRelayFilterSet): List = + map { relayFilter -> + val filter = relayFilter.filter + val scope = if (filter is ExplainedFilter && filter.scope == null) feedSettings.scopeFor(relayFilter.relay) else null + if (filter is ExplainedFilter && scope != null) { + RelayBasedFilter( + relay = relayFilter.relay, + filter = ExplainedFilter.of(filter, filter.purpose, filter.purposeDetail, filter.entityIds, filter.accountPubKey, scope), ) } else { relayFilter diff --git a/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilterTest.kt b/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilterTest.kt index fb348a933e..61baa6bc71 100644 --- a/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilterTest.kt +++ b/commons/src/jvmTest/kotlin/com/vitorpamplona/amethyst/commons/relayClient/subscriptions/ExplainedFilterTest.kt @@ -20,6 +20,7 @@ */ package com.vitorpamplona.amethyst.commons.relayClient.subscriptions +import com.vitorpamplona.amethyst.commons.model.topNavFeeds.hashtag.HashtagTopNavPerRelayFilter import com.vitorpamplona.quartz.nip01Core.relay.client.pool.FiltersChanged import com.vitorpamplona.quartz.nip01Core.relay.commands.toRelay.ReqCmd import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter @@ -56,8 +57,9 @@ class ExplainedFilterTest { limit = 20, purpose = SubPurpose.NOTIFICATIONS, purposeDetail = "inbox relays for the active account", - entityId = "cafe0000000000000000000000000000000000000000000000000000000000ff", + entityIds = listOf("cafe0000000000000000000000000000000000000000000000000000000000ff"), accountPubKey = pubkey, + scope = HashtagTopNavPerRelayFilter(setOf("askednostr")), ) // ---- the wire must not learn why we asked ------------------------------- @@ -81,6 +83,11 @@ class ExplainedFilterTest { assertFalse("detail leaked to the wire: $json", json.contains("inbox relays", ignoreCase = true)) assertFalse("entityId leaked to the wire: $json", json.contains("cafe0000", ignoreCase = true)) assertFalse("accountPubKey leaked as a field: $json", json.contains("accountPubKey", ignoreCase = true)) + // The scope is the feed selection behind the filter — a hashtag here, but for a follows feed + // it is a slice of the user's follow list. Handing a relay the *selection* rather than the + // authors it already sees would tell it which of its neighbours' filters belong together. + assertFalse("scope leaked to the wire: $json", json.contains("askednostr", ignoreCase = true)) + assertFalse("scope leaked as a field: $json", json.contains("scope", ignoreCase = true)) } /** The filter is serialized as part of a REQ, so check the real command too, not just the filter. */ @@ -106,9 +113,10 @@ class ExplainedFilterTest { assertTrue("copy() must stay an ExplainedFilter", advanced is ExplainedFilter) assertEquals(SubPurpose.NOTIFICATIONS, advanced.purposeOrNull()) assertEquals("inbox relays for the active account", (advanced as ExplainedFilter).purposeDetail) - // entityId/accountPubKey ride the same path and would vanish just as silently - assertEquals("cafe0000000000000000000000000000000000000000000000000000000000ff", advanced.entityId) + // entityIds/accountPubKey/scope ride the same path and would vanish just as silently + assertEquals(listOf("cafe0000000000000000000000000000000000000000000000000000000000ff"), advanced.entityIds) assertEquals(pubkey, advanced.accountPubKey) + assertEquals(setOf("askednostr"), (advanced.scope as? HashtagTopNavPerRelayFilter)?.hashtags) assertEquals(1_785_379_272L, advanced.since) // and the protocol fields came along untouched assertEquals(listOf(pubkey), advanced.authors)