From fcd70001bfe398f85cf5ad43a7d571d8721fb392 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Tue, 6 May 2025 15:48:03 -0400 Subject: [PATCH] Adds a Reads feed to the discovery tab --- .../com/vitorpamplona/amethyst/model/Note.kt | 19 ++++- .../amethyst/ui/dal/DefaultFeedOrder.kt | 2 +- .../ui/feeds/RememberForeverStates.kt | 1 + .../amethyst/ui/note/types/LongForm.kt | 7 +- .../loggedIn/AccountFeedContentStates.kt | 6 ++ .../loggedIn/discover/ChannelCardCompose.kt | 24 +++--- .../loggedIn/discover/DiscoverScreen.kt | 16 +++- .../datasource/DiscoveryFilterAssembler.kt | 23 +++++- .../DiscoverLongFormFeedFilter.kt | 76 +++++++++++++++++++ .../discover/nip23LongForm/LongFormCard.kt | 47 ++++++++++++ .../loggedIn/threadview/ThreadFeedView.kt | 10 ++- amethyst/src/main/res/values/strings.xml | 1 + 12 files changed, 202 insertions(+), 30 deletions(-) create mode 100644 amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/DiscoverLongFormFeedFilter.kt create mode 100644 amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormCard.kt diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt index 73bd84e62..a385b32ac 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/Note.kt @@ -63,12 +63,15 @@ import com.vitorpamplona.quartz.nip47WalletConnect.LnZapPaymentResponseEvent import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceSuccessResponse import com.vitorpamplona.quartz.nip53LiveActivities.chat.LiveActivitiesChatMessageEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent +import com.vitorpamplona.quartz.nip54Wiki.WikiNoteEvent import com.vitorpamplona.quartz.nip56Reports.ReportEvent import com.vitorpamplona.quartz.nip56Reports.ReportType import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent import com.vitorpamplona.quartz.nip57Zaps.LnZapRequestEvent import com.vitorpamplona.quartz.nip59Giftwrap.WrappedEvent +import com.vitorpamplona.quartz.nip71Video.VideoEvent import com.vitorpamplona.quartz.nip72ModCommunities.approval.CommunityPostApprovalEvent +import com.vitorpamplona.quartz.nip99Classifieds.ClassifiedsEvent import com.vitorpamplona.quartz.utils.Hex import com.vitorpamplona.quartz.utils.TimeUtils import com.vitorpamplona.quartz.utils.containsAny @@ -94,12 +97,20 @@ class AddressableNote( override fun address() = address override fun createdAt(): Long? { - if (event == null) return null + val currentEvent = event - val publishedAt = (event as? LongTextNoteEvent)?.publishedAt() ?: Long.MAX_VALUE - val lastCreatedAt = event?.createdAt ?: Long.MAX_VALUE + if (currentEvent == null) return null - return minOf(publishedAt, lastCreatedAt) + val publishedAt = + when (currentEvent) { + is LongTextNoteEvent -> currentEvent.publishedAt() ?: Long.MAX_VALUE + is WikiNoteEvent -> currentEvent.publishedAt() ?: Long.MAX_VALUE + is VideoEvent -> currentEvent.publishedAt() ?: Long.MAX_VALUE + is ClassifiedsEvent -> currentEvent.publishedAt() ?: Long.MAX_VALUE + else -> Long.MAX_VALUE + } + + return minOf(publishedAt, currentEvent.createdAt) } fun dTag(): String = address.dTag diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/DefaultFeedOrder.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/DefaultFeedOrder.kt index b0c18026e..0175781ac 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/DefaultFeedOrder.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/dal/DefaultFeedOrder.kt @@ -24,7 +24,7 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.ui.screen.loggedIn.notifications.Card val DefaultFeedOrder: Comparator = - compareByDescending { it.event?.createdAt }.thenBy { it.idHex } + compareByDescending { it.createdAt() }.thenBy { it.idHex } val DefaultFeedOrderCard: Comparator = compareByDescending { it.createdAt() }.thenBy { it.id() } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt index b8f9daf3e..48969f3db 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/feeds/RememberForeverStates.kt @@ -46,6 +46,7 @@ object ScrollStateKeys { const val DRAFTS = "DraftsFeed" const val DISCOVER_FOLLOWS = "DiscoverFollowSetsFeed" + const val DISCOVER_READS = "DiscoverReadsFeed" const val DISCOVER_CONTENT = "DiscoverDiscoverContentFeed" const val DISCOVER_MARKETPLACE = "DiscoverMarketplaceFeed" const val DISCOVER_LIVE = "DiscoverLiveFeed" diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/LongForm.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/LongForm.kt index d02d4f42d..479b8ee5b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/LongForm.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/note/types/LongForm.kt @@ -60,7 +60,7 @@ fun RenderLongFormContent( } @Composable -private fun LongFormHeader( +fun LongFormHeader( noteEvent: LongTextNoteEvent, note: Note, accountViewModel: AccountViewModel, @@ -83,10 +83,7 @@ private fun LongFormHeader( QuoteBorder, ), ) { - val automaticallyShowUrlPreview = - remember { accountViewModel.settings.showImages.value } - - if (automaticallyShowUrlPreview) { + if (accountViewModel.settings.showImages.value) { image?.let { AsyncImage( model = it, diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt index 12aab5654..19ee69458 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/AccountFeedContentStates.kt @@ -28,6 +28,7 @@ import com.vitorpamplona.amethyst.ui.feeds.FeedContentState import com.vitorpamplona.amethyst.ui.screen.FollowListState import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.dal.ChatroomListKnownFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.chats.rooms.dal.ChatroomListNewFeedFilter +import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.DiscoverLongFormFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.DiscoverChatFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.DiscoverFollowSetsFeedFilter import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.DiscoverLiveFeedFilter @@ -55,6 +56,7 @@ class AccountFeedContentStates( val videoFeed = FeedContentState(VideoFeedFilter(accountViewModel.account), accountViewModel.viewModelScope) val discoverFollowSets = FeedContentState(DiscoverFollowSetsFeedFilter(accountViewModel.account), accountViewModel.viewModelScope) + val discoverReads = FeedContentState(DiscoverLongFormFeedFilter(accountViewModel.account), accountViewModel.viewModelScope) val discoverMarketplace = FeedContentState(DiscoverMarketplaceFeedFilter(accountViewModel.account), accountViewModel.viewModelScope) val discoverDVMs = FeedContentState(DiscoverNIP89FeedFilter(accountViewModel.account), accountViewModel.viewModelScope) val discoverLive = FeedContentState(DiscoverLiveFeedFilter(accountViewModel.account), accountViewModel.viewModelScope) @@ -84,6 +86,8 @@ class AccountFeedContentStates( videoFeed.updateFeedWith(newNotes) discoverMarketplace.updateFeedWith(newNotes) + discoverFollowSets.updateFeedWith(newNotes) + discoverReads.updateFeedWith(newNotes) discoverDVMs.updateFeedWith(newNotes) discoverLive.updateFeedWith(newNotes) discoverCommunities.updateFeedWith(newNotes) @@ -105,6 +109,8 @@ class AccountFeedContentStates( videoFeed.destroy() discoverMarketplace.destroy() + discoverFollowSets.destroy() + discoverReads.destroy() discoverDVMs.destroy() discoverLive.destroy() discoverCommunities.destroy() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/ChannelCardCompose.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/ChannelCardCompose.kt index 03e211b01..056e6d971 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/ChannelCardCompose.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/ChannelCardCompose.kt @@ -36,6 +36,7 @@ import com.vitorpamplona.amethyst.ui.note.LongPressToQuickAction import com.vitorpamplona.amethyst.ui.note.WatchNoteEvent import com.vitorpamplona.amethyst.ui.note.calculateBackgroundColor import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip23LongForm.RenderLongFormThumb import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip28Chats.RenderChannelThumb import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip51FollowSets.RenderFollowSetThumb import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip53LiveActivities.RenderLiveActivityThumb @@ -44,6 +45,7 @@ import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip90DVMs.RenderCo import com.vitorpamplona.amethyst.ui.screen.loggedIn.discover.nip99Classifieds.RenderClassifiedsThumb import com.vitorpamplona.amethyst.ui.theme.HalfPadding import com.vitorpamplona.amethyst.ui.theme.StdPadding +import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip51Lists.FollowListEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent @@ -154,6 +156,7 @@ fun InnerChannelCardWithReactions( is ClassifiedsEvent -> InnerCardBox(baseNote, accountViewModel, nav) is AppDefinitionEvent -> InnerCardRow(baseNote, accountViewModel, nav) is FollowListEvent -> InnerCardRow(baseNote, accountViewModel, nav) + is LongTextNoteEvent -> InnerCardRow(baseNote, accountViewModel, nav) } } @@ -200,20 +203,11 @@ private fun RenderNoteRow( nav: INav, ) { when (baseNote.event) { - is LiveActivitiesEvent -> { - RenderLiveActivityThumb(baseNote, accountViewModel, nav) - } - is CommunityDefinitionEvent -> { - RenderCommunitiesThumb(baseNote, accountViewModel, nav) - } - is ChannelCreateEvent -> { - RenderChannelThumb(baseNote, accountViewModel, nav) - } - is AppDefinitionEvent -> { - RenderContentDVMThumb(baseNote, accountViewModel, nav) - } - is FollowListEvent -> { - RenderFollowSetThumb(baseNote, accountViewModel, nav) - } + is LiveActivitiesEvent -> RenderLiveActivityThumb(baseNote, accountViewModel, nav) + is CommunityDefinitionEvent -> RenderCommunitiesThumb(baseNote, accountViewModel, nav) + is ChannelCreateEvent -> RenderChannelThumb(baseNote, accountViewModel, nav) + is AppDefinitionEvent -> RenderContentDVMThumb(baseNote, accountViewModel, nav) + is FollowListEvent -> RenderFollowSetThumb(baseNote, accountViewModel, nav) + is LongTextNoteEvent -> RenderLongFormThumb(baseNote, accountViewModel, nav) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/DiscoverScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/DiscoverScreen.kt index 58d41063b..003d9f78e 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/DiscoverScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/DiscoverScreen.kt @@ -81,6 +81,7 @@ import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.amethyst.ui.theme.Size26Modifier import com.vitorpamplona.amethyst.ui.theme.Size55Modifier import com.vitorpamplona.amethyst.ui.theme.TabRowHeight +import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip51Lists.FollowListEvent import com.vitorpamplona.quartz.nip53LiveActivities.streaming.LiveActivitiesEvent @@ -98,6 +99,7 @@ fun DiscoverScreen( ) { DiscoverScreen( discoveryFollowSetsFeedContentState = accountViewModel.feedStates.discoverFollowSets, + discoveryReadsFeedContentState = accountViewModel.feedStates.discoverReads, discoveryContentNIP89FeedContentState = accountViewModel.feedStates.discoverDVMs, discoveryMarketplaceFeedContentState = accountViewModel.feedStates.discoverMarketplace, discoveryLiveFeedContentState = accountViewModel.feedStates.discoverLive, @@ -112,6 +114,7 @@ fun DiscoverScreen( @Composable fun DiscoverScreen( discoveryFollowSetsFeedContentState: FeedContentState, + discoveryReadsFeedContentState: FeedContentState, discoveryContentNIP89FeedContentState: FeedContentState, discoveryMarketplaceFeedContentState: FeedContentState, discoveryLiveFeedContentState: FeedContentState, @@ -128,9 +131,16 @@ fun DiscoverScreen( R.string.discover_follows, discoveryFollowSetsFeedContentState, "DiscoverFollowSets", - ScrollStateKeys.DISCOVER_CONTENT, + ScrollStateKeys.DISCOVER_FOLLOWS, FollowListEvent.KIND, ), + TabItem( + R.string.discover_reads, + discoveryReadsFeedContentState, + "DiscoverReads", + ScrollStateKeys.DISCOVER_READS, + LongTextNoteEvent.KIND, + ), TabItem( R.string.discover_content, discoveryContentNIP89FeedContentState, @@ -175,6 +185,7 @@ fun DiscoverScreen( WatchAccountForDiscoveryScreen( discoveryFollowSetsFeedContentState = discoveryFollowSetsFeedContentState, + discoveryReadsFeedContentState = discoveryReadsFeedContentState, discoveryContentNIP89FeedContentState = discoveryContentNIP89FeedContentState, discoveryMarketplaceFeedContentState = discoveryMarketplaceFeedContentState, discoveryLiveFeedContentState = discoveryLiveFeedContentState, @@ -184,6 +195,7 @@ fun DiscoverScreen( ) WatchLifecycleAndUpdateModel(discoveryFollowSetsFeedContentState) + WatchLifecycleAndUpdateModel(discoveryReadsFeedContentState) WatchLifecycleAndUpdateModel(discoveryContentNIP89FeedContentState) WatchLifecycleAndUpdateModel(discoveryMarketplaceFeedContentState) WatchLifecycleAndUpdateModel(discoveryLiveFeedContentState) @@ -379,6 +391,7 @@ private fun RenderDiscoverFeed( @Composable fun WatchAccountForDiscoveryScreen( discoveryFollowSetsFeedContentState: FeedContentState, + discoveryReadsFeedContentState: FeedContentState, discoveryContentNIP89FeedContentState: FeedContentState, discoveryMarketplaceFeedContentState: FeedContentState, discoveryLiveFeedContentState: FeedContentState, @@ -390,6 +403,7 @@ fun WatchAccountForDiscoveryScreen( LaunchedEffect(accountViewModel, listState) { discoveryFollowSetsFeedContentState.checkKeysInvalidateDataAndSendToTop() + discoveryReadsFeedContentState.checkKeysInvalidateDataAndSendToTop() discoveryContentNIP89FeedContentState.checkKeysInvalidateDataAndSendToTop() discoveryMarketplaceFeedContentState.checkKeysInvalidateDataAndSendToTop() discoveryLiveFeedContentState.checkKeysInvalidateDataAndSendToTop() diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/datasource/DiscoveryFilterAssembler.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/datasource/DiscoveryFilterAssembler.kt index 5e12277db..565a2b908 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/datasource/DiscoveryFilterAssembler.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/datasource/DiscoveryFilterAssembler.kt @@ -30,6 +30,7 @@ import com.vitorpamplona.ammolite.relays.TypedFilter import com.vitorpamplona.ammolite.relays.datasources.Subscription import com.vitorpamplona.ammolite.relays.filters.SinceAuthorPerRelayFilter import com.vitorpamplona.ammolite.relays.filters.SincePerRelayFilter +import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelCreateEvent import com.vitorpamplona.quartz.nip28PublicChat.admin.ChannelMetadataEvent import com.vitorpamplona.quartz.nip28PublicChat.message.ChannelMessageEvent @@ -251,7 +252,26 @@ class DiscoveryFilterAssembler( SinceAuthorPerRelayFilter( authors = follows, kinds = listOf(FollowListEvent.KIND), - limit = 500, + limit = 300, + since = since(key), + ), + ), + ) + } + + fun createLongFormFilter(key: DiscoveryQueryState): List { + val follows = + key.account.liveDiscoveryListAuthorsPerRelay.value + ?.ifEmpty { null } + + return listOfNotNull( + TypedFilter( + types = setOf(FeedType.FOLLOWS), + filter = + SinceAuthorPerRelayFilter( + authors = follows, + kinds = listOf(LongTextNoteEvent.KIND), + limit = 300, since = since(key), ), ), @@ -471,6 +491,7 @@ class DiscoveryFilterAssembler( .plus(createNIP89Filter(key)) .plus(createPublicChatFilter(key)) .plus(createFollowSetFilter(key)) + .plus(createLongFormFilter(key)) .plus(createMarketplaceFilter(key)) .plus( listOfNotNull( diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/DiscoverLongFormFeedFilter.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/DiscoverLongFormFeedFilter.kt new file mode 100644 index 000000000..8c9fabd3c --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/DiscoverLongFormFeedFilter.kt @@ -0,0 +1,76 @@ +/** + * 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.screen.loggedIn.discover.nip23LongForm + +import com.vitorpamplona.amethyst.model.Account +import com.vitorpamplona.amethyst.model.LocalCache +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.ui.dal.AdditiveFeedFilter +import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder +import com.vitorpamplona.amethyst.ui.dal.FilterByListParams +import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent +import com.vitorpamplona.quartz.nip51Lists.MuteListEvent +import com.vitorpamplona.quartz.nip51Lists.PeopleListEvent + +open class DiscoverLongFormFeedFilter( + val account: Account, +) : AdditiveFeedFilter() { + override fun feedKey(): String = account.userProfile().pubkeyHex + "-" + followList() + + open fun followList(): String = account.settings.defaultDiscoveryFollowList.value + + override fun showHiddenKey(): Boolean = + followList() == PeopleListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) || + followList() == MuteListEvent.Companion.blockListFor(account.userProfile().pubkeyHex) + + override fun feed(): List { + val params = buildFilterParams(account) + + val notes = + LocalCache.addressables.filterIntoSet { _, it -> + val noteEvent = it.event + noteEvent is LongTextNoteEvent && params.match(noteEvent) + } + + return sort(notes) + } + + override fun applyFilter(collection: Set): Set = innerApplyFilter(collection) + + fun buildFilterParams(account: Account): FilterByListParams = + FilterByListParams.Companion.create( + account.userProfile().pubkeyHex, + account.settings.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 LongTextNoteEvent && params.match(noteEvent) + } + } + + override fun sort(collection: Set): List = collection.sortedWith(DefaultFeedOrder) +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormCard.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormCard.kt new file mode 100644 index 000000000..bbc00b503 --- /dev/null +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/discover/nip23LongForm/LongFormCard.kt @@ -0,0 +1,47 @@ +/** + * 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.screen.loggedIn.discover.nip23LongForm + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import com.vitorpamplona.amethyst.model.Note +import com.vitorpamplona.amethyst.service.relayClient.reqCommand.event.observeNoteEvent +import com.vitorpamplona.amethyst.ui.navigation.INav +import com.vitorpamplona.amethyst.ui.note.types.LongFormHeader +import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel +import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent + +@Composable +fun RenderLongFormThumb( + baseNote: Note, + accountViewModel: AccountViewModel, + nav: INav, +) { + val noteEvent by observeNoteEvent(baseNote, accountViewModel) + + noteEvent?.let { + LongFormHeader( + it, + baseNote, + accountViewModel, + ) + } +} diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt index 652c1128a..73eb1f32c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/threadview/ThreadFeedView.kt @@ -162,7 +162,10 @@ import com.vitorpamplona.amethyst.ui.theme.FeedPadding import com.vitorpamplona.amethyst.ui.theme.Size55dp import com.vitorpamplona.amethyst.ui.theme.Size5dp import com.vitorpamplona.amethyst.ui.theme.StdHorzSpacer +import com.vitorpamplona.amethyst.ui.theme.StdVertSpacer import com.vitorpamplona.amethyst.ui.theme.ThemeComparisonColumn +import com.vitorpamplona.amethyst.ui.theme.grayText +import com.vitorpamplona.amethyst.ui.theme.imageModifier import com.vitorpamplona.amethyst.ui.theme.lessImportantLink import com.vitorpamplona.amethyst.ui.theme.placeholderText import com.vitorpamplona.amethyst.ui.theme.selectedNote @@ -933,7 +936,7 @@ private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) { it, ), contentScale = ContentScale.FillWidth, - modifier = Modifier.fillMaxWidth(), + modifier = MaterialTheme.colorScheme.imageModifier, ) } @@ -951,11 +954,12 @@ private fun RenderLongFormHeaderForThread(noteEvent: LongTextNoteEvent) { .summary() ?.ifBlank { null } ?.let { - Spacer(modifier = DoubleVertSpacer) + Spacer(modifier = StdVertSpacer) Text( text = it, modifier = Modifier.fillMaxWidth(), - color = Color.Gray, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.grayText, ) } } diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index de1886752..5646d9b57 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -649,6 +649,7 @@ Relays Follow Packs + Reads Feed Algorithms Marketplace Live Streams