Merge pull request #2490 from vitorpamplona/claude/fix-feeds-topnavfilter-ZfdnN

Add follow packs support to default follow list preferences
This commit is contained in:
Vitor Pamplona
2026-04-21 19:19:42 -04:00
committed by GitHub
9 changed files with 52 additions and 7 deletions
@@ -107,6 +107,10 @@ private object PrefKeys {
const val DEFAULT_LIVE_STREAMS_FOLLOW_LIST = "defaultLiveStreamsFollowList"
const val DEFAULT_LONGS_FOLLOW_LIST = "defaultLongsFollowList"
const val DEFAULT_ARTICLES_FOLLOW_LIST = "defaultArticlesFollowList"
const val DEFAULT_BADGES_FOLLOW_LIST = "defaultBadgesFollowList"
const val DEFAULT_BROWSE_EMOJI_SETS_FOLLOW_LIST = "defaultBrowseEmojiSetsFollowList"
const val DEFAULT_COMMUNITIES_FOLLOW_LIST = "defaultCommunitiesFollowList"
const val DEFAULT_FOLLOW_PACKS_FOLLOW_LIST = "defaultFollowPacksFollowList"
const val ZAP_PAYMENT_REQUEST_SERVER = "zapPaymentServer" // legacy, kept for migration
const val NWC_WALLETS = "nwcWallets"
const val DEFAULT_NWC_WALLET_ID = "defaultNwcWalletId"
@@ -354,6 +358,10 @@ object LocalPreferences {
putString(PrefKeys.DEFAULT_LIVE_STREAMS_FOLLOW_LIST, JsonMapper.toJson(settings.defaultLiveStreamsFollowList.value))
putString(PrefKeys.DEFAULT_LONGS_FOLLOW_LIST, JsonMapper.toJson(settings.defaultLongsFollowList.value))
putString(PrefKeys.DEFAULT_ARTICLES_FOLLOW_LIST, JsonMapper.toJson(settings.defaultArticlesFollowList.value))
putString(PrefKeys.DEFAULT_BADGES_FOLLOW_LIST, JsonMapper.toJson(settings.defaultBadgesFollowList.value))
putString(PrefKeys.DEFAULT_BROWSE_EMOJI_SETS_FOLLOW_LIST, JsonMapper.toJson(settings.defaultBrowseEmojiSetsFollowList.value))
putString(PrefKeys.DEFAULT_COMMUNITIES_FOLLOW_LIST, JsonMapper.toJson(settings.defaultCommunitiesFollowList.value))
putString(PrefKeys.DEFAULT_FOLLOW_PACKS_FOLLOW_LIST, JsonMapper.toJson(settings.defaultFollowPacksFollowList.value))
val walletEntries = settings.nwcWallets.value.mapNotNull { it.denormalize() }
if (walletEntries.isNotEmpty()) {
@@ -619,6 +627,10 @@ object LocalPreferences {
defaultLiveStreamsFollowList = MutableStateFlow(followListPrefs.liveStreams),
defaultLongsFollowList = MutableStateFlow(followListPrefs.longs),
defaultArticlesFollowList = MutableStateFlow(followListPrefs.articles),
defaultBadgesFollowList = MutableStateFlow(followListPrefs.badges),
defaultBrowseEmojiSetsFollowList = MutableStateFlow(followListPrefs.browseEmojiSets),
defaultCommunitiesFollowList = MutableStateFlow(followListPrefs.communities),
defaultFollowPacksFollowList = MutableStateFlow(followListPrefs.followPacks),
nwcWallets = MutableStateFlow(nwcWalletsLoaded.await().first),
defaultNwcWalletId = MutableStateFlow(nwcWalletsLoaded.await().second),
hideDeleteRequestDialog = hideDeleteRequestDialog,
@@ -683,6 +695,10 @@ object LocalPreferences {
val liveStreams: TopFilter,
val longs: TopFilter,
val articles: TopFilter,
val badges: TopFilter,
val browseEmojiSets: TopFilter,
val communities: TopFilter,
val followPacks: TopFilter,
)
private fun SharedPreferences.loadFollowListPrefs(): FollowListPrefs =
@@ -699,6 +715,10 @@ object LocalPreferences {
liveStreams = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_LIVE_STREAMS_FOLLOW_LIST, null), TopFilter.Global),
longs = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_LONGS_FOLLOW_LIST, null), TopFilter.Global),
articles = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_ARTICLES_FOLLOW_LIST, null), TopFilter.AllFollows),
badges = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_BADGES_FOLLOW_LIST, null), TopFilter.Mine),
browseEmojiSets = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_BROWSE_EMOJI_SETS_FOLLOW_LIST, null), TopFilter.Global),
communities = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_COMMUNITIES_FOLLOW_LIST, null), TopFilter.AllFollows),
followPacks = parseTopFilterOrDefault(getString(PrefKeys.DEFAULT_FOLLOW_PACKS_FOLLOW_LIST, null), TopFilter.Global),
)
private inline fun <reified T : Any> parseOrNull(value: String?): T? {
@@ -497,6 +497,9 @@ class Account(
val liveCommunitiesFollowLists: StateFlow<IFeedTopNavFilter> = topNavFilterFlow(settings.defaultCommunitiesFollowList)
val liveCommunitiesFollowListsPerRelay = OutboxLoaderState(liveCommunitiesFollowLists, cache, scope).flow
val liveFollowPacksFollowLists: StateFlow<IFeedTopNavFilter> = topNavFilterFlow(settings.defaultFollowPacksFollowList)
val liveFollowPacksFollowListsPerRelay = OutboxLoaderState(liveFollowPacksFollowLists, cache, scope).flow
override fun isWriteable(): Boolean = settings.isWriteable()
suspend fun updateWarnReports(warnReports: Boolean): Boolean {
@@ -164,6 +164,7 @@ class AccountSettings(
val defaultBadgesFollowList: MutableStateFlow<TopFilter> = MutableStateFlow(TopFilter.Mine),
val defaultBrowseEmojiSetsFollowList: MutableStateFlow<TopFilter> = MutableStateFlow(TopFilter.Global),
val defaultCommunitiesFollowList: MutableStateFlow<TopFilter> = MutableStateFlow(TopFilter.AllFollows),
val defaultFollowPacksFollowList: MutableStateFlow<TopFilter> = MutableStateFlow(TopFilter.Global),
val nwcWallets: MutableStateFlow<List<NwcWalletEntryNorm>> = MutableStateFlow(emptyList()),
val defaultNwcWalletId: MutableStateFlow<String?> = MutableStateFlow(null),
var hideDeleteRequestDialog: Boolean = false,
@@ -549,6 +550,17 @@ class AccountSettings(
}
}
fun changeDefaultFollowPacksFollowList(name: FeedDefinition) {
changeDefaultFollowPacksFollowList(name.code)
}
fun changeDefaultFollowPacksFollowList(name: TopFilter) {
if (defaultFollowPacksFollowList.value != name) {
defaultFollowPacksFollowList.tryEmit(name)
saveAccountSettings()
}
}
// ---
// language services
// ---
@@ -59,7 +59,7 @@ open class DiscoverFollowSetsFeedFilter(
override fun applyFilter(newItems: Set<Note>): Set<Note> = innerApplyFilter(newItems)
fun buildFilterParams(account: Account): FilterByListParams =
open fun buildFilterParams(account: Account): FilterByListParams =
FilterByListParams.create(
account.liveDiscoveryFollowLists.value,
account.hiddenUsers.flow.value,
@@ -102,7 +102,7 @@ fun WatchAccountForFollowPacksScreen(
feedState: FeedContentState,
accountViewModel: AccountViewModel,
) {
val listState by accountViewModel.account.liveDiscoveryFollowLists.collectAsStateWithLifecycle()
val listState by accountViewModel.account.liveFollowPacksFollowLists.collectAsStateWithLifecycle()
val hiddenUsers =
accountViewModel.account.hiddenUsers.flow
.collectAsStateWithLifecycle()
@@ -39,14 +39,14 @@ fun FollowPacksTopBar(
nav: INav,
) {
UserDrawerSearchTopBar(accountViewModel, nav) {
val list by accountViewModel.account.settings.defaultDiscoveryFollowList
val list by accountViewModel.account.settings.defaultFollowPacksFollowList
.collectAsStateWithLifecycle()
FollowPacksTopNavFilterBar(
followListsModel = accountViewModel.feedStates.feedListOptions,
listName = list,
accountViewModel = accountViewModel,
onChange = accountViewModel.account.settings::changeDefaultDiscoveryFollowList,
onChange = accountViewModel.account.settings::changeDefaultFollowPacksFollowList,
)
}
}
@@ -21,10 +21,20 @@
package com.vitorpamplona.amethyst.ui.screen.loggedIn.followPacks.list.dal
import com.vitorpamplona.amethyst.model.Account
import com.vitorpamplona.amethyst.model.TopFilter
import com.vitorpamplona.amethyst.ui.dal.FilterByListParams
import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.DiscoverFollowSetsFeedFilter
class FollowPacksFeedFilter(
account: Account,
) : DiscoverFollowSetsFeedFilter(account) {
override fun feedKey(): String = "follow-packs-" + account.userProfile().pubkeyHex + "-" + followList().code
override fun followList(): TopFilter = account.settings.defaultFollowPacksFollowList.value
override fun buildFilterParams(account: Account): FilterByListParams =
FilterByListParams.create(
account.liveFollowPacksFollowLists.value,
account.hiddenUsers.flow.value,
)
}
@@ -52,11 +52,11 @@ class FollowPacksSubAssembler(
override fun list(key: FollowPacksQueryState) = key.listName()
fun FollowPacksQueryState.listNameFlow() = account.settings.defaultDiscoveryFollowList
fun FollowPacksQueryState.listNameFlow() = account.settings.defaultFollowPacksFollowList
fun FollowPacksQueryState.listName() = listNameFlow().value
fun FollowPacksQueryState.followsPerRelayFlow() = account.liveDiscoveryFollowListsPerRelay
fun FollowPacksQueryState.followsPerRelayFlow() = account.liveFollowPacksFollowListsPerRelay
fun FollowPacksQueryState.followsPerRelay() = followsPerRelayFlow().value
@@ -58,7 +58,7 @@ private fun LongsTopNavFilterBar(
accountViewModel: AccountViewModel,
onChange: (FeedDefinition) -> Unit,
) {
val allLists by followListsModel.kind3GlobalPeople.collectAsStateWithLifecycle()
val allLists by followListsModel.kind3GlobalPeopleRoutes.collectAsStateWithLifecycle()
FeedFilterSpinner(
placeholderCode = listName,