diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/DiscoverNIP89FeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/DiscoverNIP89FeedFilter.kt new file mode 100644 index 000000000..397a1003c --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/DiscoverNIP89FeedFilter.kt @@ -0,0 +1,84 @@ +/** + * Copyright (c) 2024 Vitor Pamplona + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to use, + * copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the + * Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +package com.vitorpamplona.amethyst.ui.dal + +import com.vitorpamplona.amethyst.model.Account +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.quartz.events.AppDefinitionEvent +import com.vitorpamplona.quartz.events.MuteListEvent +import com.vitorpamplona.quartz.events.PeopleListEvent + +open class DiscoverNIP89FeedFilter( + val ktag: Int, + val account: Account, +) : AdditiveFeedFilter() { + override fun feedKey(): String { + return account.userProfile().pubkeyHex + "-" + followList() + } + + open fun followList(): String { + return account.defaultDiscoveryFollowList.value + } + + override fun showHiddenKey(): Boolean { + return followList() == PeopleListEvent.blockListFor(account.userProfile().pubkeyHex) || + followList() == MuteListEvent.blockListFor(account.userProfile().pubkeyHex) + } + + override fun feed(): List { + val params = buildFilterParams(account) + + val notes = + LocalCache.notes.filterIntoSet { _, it -> + val noteEvent = it.event + noteEvent is AppDefinitionEvent // && params.match(noteEvent) + } + + return sort(notes) + } + + override fun applyFilter(collection: Set): Set { + return innerApplyFilter(collection) + } + + fun buildFilterParams(account: Account): FilterByListParams { + return FilterByListParams.create( + account.userProfile().pubkeyHex, + account.defaultDiscoveryFollowList.value, + account.liveDiscoveryFollowLists.value, + account.flowHiddenUsers.value, + ) + } + + protected open fun innerApplyFilter(collection: Collection): Set { + val params = buildFilterParams(account) + + return collection.filterTo(HashSet()) { + val noteEvent = it.event + noteEvent is AppDefinitionEvent // && params.match(noteEvent) + } + } + + override fun sort(collection: Set): List { + return collection.sortedWith(compareBy({ it.createdAt() }, { it.idHex })).reversed() + } +} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt index bd13a00b0..ebbcc0ff5 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/navigation/AppNavigation.kt @@ -48,6 +48,7 @@ import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverChatFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverCommunityFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverLiveFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverMarketplaceFeedViewModel +import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverNIP89FeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel @@ -86,6 +87,7 @@ fun AppNavigation( newFeedViewModel: NostrChatroomListNewFeedViewModel, videoFeedViewModel: NostrVideoFeedViewModel, discoverMarketplaceFeedViewModel: NostrDiscoverMarketplaceFeedViewModel, + discoverNip89FeedViewModel: NostrDiscoverNIP89FeedViewModel, discoveryLiveFeedViewModel: NostrDiscoverLiveFeedViewModel, discoveryCommunityFeedViewModel: NostrDiscoverCommunityFeedViewModel, discoveryChatFeedViewModel: NostrDiscoverChatFeedViewModel, @@ -173,6 +175,7 @@ fun AppNavigation( route.arguments, content = { DiscoverScreen( + discoveryContentNIP89FeedViewModel = discoverNip89FeedViewModel, discoveryMarketplaceFeedViewModel = discoverMarketplaceFeedViewModel, discoveryLiveFeedViewModel = discoveryLiveFeedViewModel, discoveryCommunityFeedViewModel = discoveryCommunityFeedViewModel, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt index 7378ecf59..852705688 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt @@ -47,6 +47,7 @@ import com.vitorpamplona.amethyst.ui.dal.DiscoverChatFeedFilter import com.vitorpamplona.amethyst.ui.dal.DiscoverCommunityFeedFilter import com.vitorpamplona.amethyst.ui.dal.DiscoverLiveFeedFilter import com.vitorpamplona.amethyst.ui.dal.DiscoverMarketplaceFeedFilter +import com.vitorpamplona.amethyst.ui.dal.DiscoverNIP89FeedFilter import com.vitorpamplona.amethyst.ui.dal.DraftEventsFeedFilter import com.vitorpamplona.amethyst.ui.dal.FeedFilter import com.vitorpamplona.amethyst.ui.dal.GeoHashFeedFilter @@ -109,6 +110,17 @@ class NostrDiscoverMarketplaceFeedViewModel(val account: Account) : } } +class NostrDiscoverNIP89FeedViewModel(val account: Account) : + FeedViewModel( + DiscoverNIP89FeedFilter(5003, account), + ) { + class Factory(val account: Account) : ViewModelProvider.Factory { + override fun create(modelClass: Class): NostrDiscoverNIP89FeedViewModel { + return NostrDiscoverNIP89FeedViewModel(account) as NostrDiscoverNIP89FeedViewModel + } + } +} + class NostrDiscoverLiveFeedViewModel(val account: Account) : FeedViewModel(DiscoverLiveFeedFilter(account)) { class Factory(val account: Account) : ViewModelProvider.Factory { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RememberForeverStates.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RememberForeverStates.kt index b2d928fcc..e44a437ef 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RememberForeverStates.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/RememberForeverStates.kt @@ -43,6 +43,7 @@ object ScrollStateKeys { val HOME_FOLLOWS = Route.Home.base + "Follows" val HOME_REPLIES = Route.Home.base + "FollowsReplies" + val DISCOVER_CONTENT = Route.Home.base + "Content" val DISCOVER_MARKETPLACE = Route.Home.base + "Marketplace" val DISCOVER_LIVE = Route.Home.base + "Live" val DISCOVER_COMMUNITY = Route.Home.base + "Communities" diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/DiscoverScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/DiscoverScreen.kt index e6bf7d8d2..1d0050200 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/DiscoverScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/DiscoverScreen.kt @@ -69,6 +69,7 @@ import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverChatFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverCommunityFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverLiveFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverMarketplaceFeedViewModel +import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverNIP89FeedViewModel import com.vitorpamplona.amethyst.ui.screen.PagerStateKeys import com.vitorpamplona.amethyst.ui.screen.RefresheableBox import com.vitorpamplona.amethyst.ui.screen.SaveableFeedState @@ -78,6 +79,7 @@ import com.vitorpamplona.amethyst.ui.screen.rememberForeverPagerState import com.vitorpamplona.amethyst.ui.theme.DividerThickness import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.amethyst.ui.theme.TabRowHeight +import com.vitorpamplona.quartz.events.AppDefinitionEvent import com.vitorpamplona.quartz.events.ChannelCreateEvent import com.vitorpamplona.quartz.events.ClassifiedsEvent import com.vitorpamplona.quartz.events.CommunityDefinitionEvent @@ -89,6 +91,7 @@ import kotlinx.coroutines.launch @OptIn(ExperimentalFoundationApi::class) @Composable fun DiscoverScreen( + discoveryContentNIP89FeedViewModel: NostrDiscoverNIP89FeedViewModel, discoveryMarketplaceFeedViewModel: NostrDiscoverMarketplaceFeedViewModel, discoveryLiveFeedViewModel: NostrDiscoverLiveFeedViewModel, discoveryCommunityFeedViewModel: NostrDiscoverCommunityFeedViewModel, @@ -106,6 +109,13 @@ fun DiscoverScreen( ) { mutableStateOf( listOf( + TabItem( + R.string.discover_content, + discoveryContentNIP89FeedViewModel, + Route.Discover.base + "Content", + ScrollStateKeys.DISCOVER_CONTENT, + AppDefinitionEvent.KIND, + ), TabItem( R.string.discover_marketplace, discoveryMarketplaceFeedViewModel, diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt index c04eb1a56..73f4d923d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/MainScreen.kt @@ -104,6 +104,7 @@ import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverChatFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverCommunityFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverLiveFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverMarketplaceFeedViewModel +import com.vitorpamplona.amethyst.ui.screen.NostrDiscoverNIP89FeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrVideoFeedViewModel @@ -207,6 +208,12 @@ fun MainScreen( factory = NostrDiscoverMarketplaceFeedViewModel.Factory(accountViewModel.account), ) + val discoverNIP89FeedViewModel: NostrDiscoverNIP89FeedViewModel = + viewModel( + key = "NostrDiscoveryNIP89FeedViewModel", + factory = NostrDiscoverNIP89FeedViewModel.Factory(accountViewModel.account), + ) + val discoveryLiveFeedViewModel: NostrDiscoverLiveFeedViewModel = viewModel( key = "NostrDiscoveryLiveFeedViewModel", @@ -411,6 +418,7 @@ fun MainScreen( knownFeedViewModel = knownFeedViewModel, newFeedViewModel = newFeedViewModel, videoFeedViewModel = videoFeedViewModel, + discoverNip89FeedViewModel = discoverNIP89FeedViewModel, discoverMarketplaceFeedViewModel = discoverMarketplaceFeedViewModel, discoveryLiveFeedViewModel = discoveryLiveFeedViewModel, discoveryCommunityFeedViewModel = discoveryCommunityFeedViewModel, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 82fb9fb56..14908ddb3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -490,6 +490,7 @@ Relays + Note Discovery Marketplace Live Community