fix: give each Feeds top nav filter its own Account + LocalPreferences flow
- Follow Packs was piggybacking on the Discovery top nav filter; give it a dedicated defaultFollowPacksFollowList StateFlow, liveFollowPacksFollowLists, and a DEFAULT_FOLLOW_PACKS_FOLLOW_LIST preference key so its top nav filter no longer mutates Discovery (and vice versa). - Persist Communities, Badges, Browse Emoji Sets, and Follow Packs top nav filters in encrypted SharedPreferences so they survive app restart. - Longs top nav was restricted to kind3GlobalPeople; switch it to kind3GlobalPeopleRoutes to match the other media/reading feeds and expose hashtag/geohash/relay/interest-set filters.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -192,6 +192,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,
|
||||
@@ -577,6 +578,17 @@ class AccountSettings(
|
||||
}
|
||||
}
|
||||
|
||||
fun changeDefaultFollowPacksFollowList(name: FeedDefinition) {
|
||||
changeDefaultFollowPacksFollowList(name.code)
|
||||
}
|
||||
|
||||
fun changeDefaultFollowPacksFollowList(name: TopFilter) {
|
||||
if (defaultFollowPacksFollowList.value != name) {
|
||||
defaultFollowPacksFollowList.tryEmit(name)
|
||||
saveAccountSettings()
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
// language services
|
||||
// ---
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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()
|
||||
|
||||
+2
-2
@@ -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,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+10
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user