From 810a69077683239f736fb8c7fa41b7f50fc60cc4 Mon Sep 17 00:00:00 2001 From: Kgothatso Ngako Date: Wed, 22 Apr 2026 03:25:19 +0200 Subject: [PATCH] Improve feed logic on profile detail --- .../compose/database/dao/ConnectionDao.kt | 3 + .../compose/database/dao/ProfileDao.kt | 8 + .../intermdiate/LocalProfileWithFollowers.kt | 29 ++ .../intermdiate/LocalProfileWithFollowing.kt | 29 ++ .../compose/ui/composable/FeedScreen.kt | 29 ++ .../widgets/detail/MetadataEventDetail.kt | 104 ++---- .../ui/view/model/FeedListViewModel.kt | 126 ++++++-- .../model/MetadataEventDetailViewModel.kt | 304 ++++++++---------- 8 files changed, 365 insertions(+), 267 deletions(-) create mode 100644 composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowers.kt create mode 100644 composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowing.kt diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ConnectionDao.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ConnectionDao.kt index 33067152..26bc08c6 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ConnectionDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ConnectionDao.kt @@ -22,6 +22,9 @@ interface ConnectionDao { @Query("SELECT * FROM Connection WHERE destinationPublicKey = :destinationPublicKey") fun getPublicKeyFollowers(destinationPublicKey: String): LocalFollowers? + @Query("SELECT * FROM Connection WHERE destinationPublicKey = :destinationPublicKey") + fun observe(destinationPublicKey: String): LocalFollowers? + @Insert suspend fun insertPlaceholderProfile(connection: Connection) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ProfileDao.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ProfileDao.kt index e4f55b46..89e9fecd 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ProfileDao.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/dao/ProfileDao.kt @@ -2,6 +2,8 @@ package ac.cord.auxiliary.compose.database.dao import ac.cord.auxiliary.compose.database.model.Profile import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfile +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfileWithFollowers +import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfileWithFollowing import androidx.room.Dao import androidx.room.Insert import androidx.room.Query @@ -18,6 +20,12 @@ interface ProfileDao { @Query("SELECT * FROM Profile WHERE publicKey = :publicKey") fun getProfileByPublicKey(publicKey: String): Profile? + @Query("SELECT * FROM NostrEvent WHERE kind = 0 AND pubKey = :publicKey") + fun observeProfileWithFollowersByPublicKey(publicKey: String): LocalProfileWithFollowers? + + @Query("SELECT * FROM NostrEvent WHERE kind = 0 AND pubKey = :publicKey") + fun observeProfileWithFollowingByPublicKey(publicKey: String): LocalProfileWithFollowing? + @Insert suspend fun insertPlaceholderProfile(profile: Profile) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowers.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowers.kt new file mode 100644 index 00000000..7509df0e --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowers.kt @@ -0,0 +1,29 @@ +package ac.cord.auxiliary.compose.database.model.intermdiate + +import ac.cord.auxiliary.compose.database.model.Connection +import ac.cord.auxiliary.compose.database.model.NostrEvent +import ac.cord.auxiliary.compose.database.model.Profile +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation + +data class LocalProfileWithFollowers( + @Embedded val nostrEvent: NostrEvent, + + @Relation( + parentColumn = "pubKey", + entityColumn = "publicKey" + ) + val profile: Profile, + + @Relation( + parentColumn = "pubKey", + entityColumn = "publicKey", + associateBy = Junction( + value = Connection::class, + parentColumn = "destinationPublicKey", + entityColumn = "sourcePublicKey" + ) + ) + val followers: List +) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowing.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowing.kt new file mode 100644 index 00000000..a6659dbd --- /dev/null +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/database/model/intermdiate/LocalProfileWithFollowing.kt @@ -0,0 +1,29 @@ +package ac.cord.auxiliary.compose.database.model.intermdiate + +import ac.cord.auxiliary.compose.database.model.Connection +import ac.cord.auxiliary.compose.database.model.NostrEvent +import ac.cord.auxiliary.compose.database.model.Profile +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation + +data class LocalProfileWithFollowing( + @Embedded val nostrEvent: NostrEvent, + + @Relation( + parentColumn = "pubKey", + entityColumn = "publicKey" + ) + val profile: Profile, + + @Relation( + parentColumn = "pubKey", + entityColumn = "publicKey", + associateBy = Junction( + value = Connection::class, + parentColumn = "sourcePublicKey", + entityColumn = "destinationPublicKey" + ) + ) + val followers: List +) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/FeedScreen.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/FeedScreen.kt index 67309154..020dc4da 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/FeedScreen.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/FeedScreen.kt @@ -1,5 +1,7 @@ package ac.cord.auxiliary.compose.ui.composable +import ac.cord.auxiliary.compose.database.model.types.SynchronizationFilter +import ac.cord.auxiliary.compose.managers.SeedManager import ac.cord.auxiliary.compose.repository.NostrRepository import ac.cord.auxiliary.compose.ui.composable.widgets.LoadingDataIndicator import ac.cord.auxiliary.compose.ui.composable.widgets.feed.FeedListItem @@ -43,6 +45,16 @@ import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.lifecycle.viewmodel.compose.viewModel import com.vitorpamplona.quartz.nip01Core.core.HexKey +import com.vitorpamplona.quartz.nip01Core.core.toHexKey +import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent +import com.vitorpamplona.quartz.nip04Dm.messages.PrivateDmEvent +import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent +import com.vitorpamplona.quartz.nip18Reposts.RepostEvent +import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent +import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent +import com.vitorpamplona.quartz.nip65RelayList.AdvertisedRelayListEvent +import com.vitorpamplona.quartz.nip96FileStorage.config.FileServersEvent +import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class) @Composable @@ -56,6 +68,23 @@ fun FeedScreen( val feedListViewModel: FeedListViewModel = viewModel( factory = FeedListViewModel.factory( initialFeedListUIState = initialFeedListUIState, + synchronizationFilter = SynchronizationFilter( + kinds = arrayOf( + TextNoteEvent.KIND, + RepostEvent.KIND, + ReactionEvent.KIND, + LnZapEvent.KIND, + ContactListEvent.KIND, + AdvertisedRelayListEvent.KIND, + PrivateDmEvent.KIND, + BlossomServersEvent.KIND, + FileServersEvent.KIND + ), + tags = mapOf( + Pair("p", listOf(SeedManager.activePublicKey().toHexKey())) + ), + limit = 50 + ), nostrRepository = nostrRepository ), ) diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt index f7ea3c55..dcd77983 100644 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/composable/widgets/detail/MetadataEventDetail.kt @@ -8,6 +8,7 @@ import ac.cord.auxiliary.compose.ui.composable.navigation.routes.NostrEventDetai import ac.cord.auxiliary.compose.ui.composable.navigation.routes.Route import ac.cord.auxiliary.compose.ui.composable.widgets.feed.ListView import ac.cord.auxiliary.compose.ui.theme.AuxTheme +import ac.cord.auxiliary.compose.ui.view.model.FeedListViewModel import ac.cord.auxiliary.compose.ui.view.model.MetadataEventDetailType import ac.cord.auxiliary.compose.ui.view.model.MetadataEventDetailViewModel import ac.cord.auxiliary.compose.ui.view.model.SearchResultType @@ -216,81 +217,40 @@ fun MetadataEventDetail( HorizontalPager( state = metadataEventDetailViewModel.pagerState, ) { pageIndex -> + when (MetadataEventDetailType.entries[pageIndex]) { + MetadataEventDetailType.Posts, MetadataEventDetailType.Replies, + MetadataEventDetailType.Articles, MetadataEventDetailType.Zaps, + MetadataEventDetailType.Photos, MetadataEventDetailType.Videos, + MetadataEventDetailType.Bookmarks, MetadataEventDetailType.Reports, MetadataEventDetailType.Relays -> { + val feedListViewModel: FeedListViewModel = viewModel( + factory = FeedListViewModel.factory( + initialFeedListUIState = FeedListUIState.Loading, + synchronizationFilter = metadataEventDetailViewModel.getSynchronizationFilter(), + nostrRepository = nostrRepository + ), + ) - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - when (val feedListUIState = metadataEventDetailViewModel.feedListUIState) { - FeedListUIState.Error -> { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer( - modifier = Modifier.height(50.dp) - ) - Text( - text = "Something went wrong", - ) - } - } - is FeedListUIState.Loaded -> { - if (feedListUIState.localNostrEvents.isEmpty()) { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer( - modifier = Modifier.height(50.dp) - ) - Text( - text = "No events were found", - ) - } - } else { - LazyColumn( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.spacedBy(10.dp) - ) { - items( - items = feedListUIState.localNostrEvents, - key = { localNostrEvent -> localNostrEvent.nostrEvent.id} - ) { localNostrEvent -> - localNostrEvent.ListView( - onNavigateToEvent = { nostrEventId -> - onNavigateToEvent.invoke( - NostrEventDetailRoute( - nostrEventId = nostrEventId - ) - ) - } - ) - } - } - } + feedListViewModel.RenderFeed( + onNavigateToEvent = onNavigateToEvent + ) + } - } - FeedListUIState.Loading -> { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally - ) { - Spacer( - modifier = Modifier.height(50.dp) - ) - Text( - text = "Loading ${MetadataEventDetailType.entries[pageIndex].name.lowercase()}", - textAlign = TextAlign.Center - ) - Spacer( - modifier = Modifier.height(50.dp) - ) + MetadataEventDetailType.Following -> { + + Text("Implementing logic to see following") + } + MetadataEventDetailType.Followers -> { + + Text("Implementing logic to see followers") + } + } + + + LaunchedEffect(true) { + metadataEventDetailViewModel.updateMetadataEventDetailType( + MetadataEventDetailType.Posts + ) { - LoadingIndicator() - } - } } } } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/FeedListViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/FeedListViewModel.kt index 38874308..177287ef 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/FeedListViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/FeedListViewModel.kt @@ -5,11 +5,29 @@ import ac.cord.auxiliary.compose.database.model.types.SynchronizationFilter import ac.cord.auxiliary.compose.managers.SeedManager import ac.cord.auxiliary.compose.nostr.Relays import ac.cord.auxiliary.compose.repository.NostrRepository +import ac.cord.auxiliary.compose.ui.composable.navigation.routes.NostrEventDetailRoute +import ac.cord.auxiliary.compose.ui.composable.navigation.routes.Route +import ac.cord.auxiliary.compose.ui.composable.widgets.feed.ListView import ac.cord.auxiliary.compose.ui.view.state.FeedListUIState +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi +import androidx.compose.material3.LoadingIndicator +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable import androidx.compose.runtime.MutableState import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewModelScope @@ -33,6 +51,7 @@ import kotlinx.coroutines.launch class FeedListViewModel( initialFeedListUIState: FeedListUIState, + val synchronizationFilter: SynchronizationFilter, val nostrRepository: NostrRepository ): ViewModel() { val logger = Logger.withTag(TAG) @@ -58,7 +77,9 @@ class FeedListViewModel( if (localProfile?.profile == null) { feedListUIState = FeedListUIState.Error } else { - nostrRepository.observeNostrFeed().collect { localNostrEvents -> + nostrRepository.observeNostrFeed( + synchronizationFilter + ).collect { localNostrEvents -> feedListUIState = FeedListUIState.Loaded( localNostrEvents = localNostrEvents ) @@ -77,23 +98,7 @@ class FeedListViewModel( SynchronizeNostrEventRequest( purpose = "feed", synchronizationFilters = arrayOf( - SynchronizationFilter( - kinds = arrayOf( - TextNoteEvent.KIND, - RepostEvent.KIND, - ReactionEvent.KIND, - LnZapEvent.KIND, - ContactListEvent.KIND, - AdvertisedRelayListEvent.KIND, - PrivateDmEvent.KIND, - BlossomServersEvent.KIND, - FileServersEvent.KIND - ), - tags = mapOf( - Pair("p", listOf(SeedManager.activePublicKey().toHexKey())) - ), - limit = 50 - ) + synchronizationFilter ), relayURL = normalizedRelay.url ) @@ -112,16 +117,101 @@ class FeedListViewModel( } } + @OptIn(ExperimentalMaterial3ExpressiveApi::class) + @Composable + fun RenderFeed( + onNavigateToEvent: (Route) -> Unit + ) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + when (val feedListUIState = feedListUIState) { + FeedListUIState.Error -> { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer( + modifier = Modifier.height(50.dp) + ) + Text( + text = "Something went wrong", + ) + } + } + is FeedListUIState.Loaded -> { + if (feedListUIState.localNostrEvents.isEmpty()) { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer( + modifier = Modifier.height(50.dp) + ) + Text( + text = "No events were found", + ) + } + } else { + LazyColumn( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(10.dp) + ) { + items( + items = feedListUIState.localNostrEvents, + key = { localNostrEvent -> localNostrEvent.nostrEvent.id} + ) { localNostrEvent -> + localNostrEvent.ListView( + onNavigateToEvent = { nostrEventId -> + onNavigateToEvent.invoke( + NostrEventDetailRoute( + nostrEventId = nostrEventId + ) + ) + } + ) + } + } + } + + } + FeedListUIState.Loading -> { + Column( + modifier = Modifier.fillMaxWidth(), + horizontalAlignment = Alignment.CenterHorizontally + ) { + Spacer( + modifier = Modifier.height(50.dp) + ) + Text( + text = "Loading", + textAlign = TextAlign.Center + ) + Spacer( + modifier = Modifier.height(50.dp) + ) + + LoadingIndicator() + } + } + } + } + } + companion object { const val TAG = "FeedListViewModel" fun factory( initialFeedListUIState: FeedListUIState = FeedListUIState.Loading, + synchronizationFilter: SynchronizationFilter, nostrRepository: NostrRepository, ): ViewModelProvider.Factory = viewModelFactory { initializer { FeedListViewModel( initialFeedListUIState = initialFeedListUIState, + synchronizationFilter = synchronizationFilter, nostrRepository = nostrRepository ) } diff --git a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/MetadataEventDetailViewModel.kt b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/MetadataEventDetailViewModel.kt index d094bedb..f9a275b3 100755 --- a/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/MetadataEventDetailViewModel.kt +++ b/composeApp/src/commonMain/kotlin/ac/cord/auxiliary/compose/ui/view/model/MetadataEventDetailViewModel.kt @@ -42,198 +42,148 @@ class MetadataEventDetailViewModel( ): ViewModel() { val logger = Logger.withTag(TAG) - - var feedJob: Job? = null - var metadataEventDetailType: MetadataEventDetailType by mutableStateOf(initialMetadataEventDetailType) private set - var feedListUIState: FeedListUIState by mutableStateOf(FeedListUIState.Loading) - private set - fun updateMetadataEventDetailType (metadataEventDetailType: MetadataEventDetailType, navigateToPage: () -> Unit) { this.metadataEventDetailType = metadataEventDetailType - initiateMetadataFeed(this.metadataEventDetailType) navigateToPage.invoke() } - fun initiateMetadataFeed(metadataEventDetailType: MetadataEventDetailType = this.metadataEventDetailType) { - feedListUIState = FeedListUIState.Loading - - logger.d("initiateMetadataFeed") - val synchronizationFilter = when (metadataEventDetailType) { - MetadataEventDetailType.Posts -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - TextNoteEvent.KIND, - RepostEvent.KIND, - ), - limit = 50 - ) - } - MetadataEventDetailType.Replies -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - TextNoteEvent.KIND, - ReactionEvent.KIND, - ), - // TODO: replyTo is set... - limit = 50 - ) - } - MetadataEventDetailType.Articles -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - LongTextNoteEvent.KIND, - ), - limit = 50 - ) - } - MetadataEventDetailType.Followers -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - ContactListEvent.KIND, - ), - // TODO: Check users with hexKey - limit = 50 - ) - } - MetadataEventDetailType.Following -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - ContactListEvent.KIND, - ), - limit = 50 - ) - } - MetadataEventDetailType.Zaps -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - LnZapEvent.KIND, - ), - // TODO: Zaps user has received... - limit = 50 - ) - } - MetadataEventDetailType.Photos -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - TextNoteEvent.KIND, - ), - // TODO: filter for tags of pictures... - limit = 50 - ) - } - MetadataEventDetailType.Videos -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - TextNoteEvent.KIND, - ), - // TODO: filter for tags of videos... - limit = 50 - ) - } - MetadataEventDetailType.Bookmarks -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - BookmarkListEvent.KIND, - ), - limit = 50 - ) - } - MetadataEventDetailType.Reports -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - ReportEvent.KIND, - ), - limit = 50 - ) - } - MetadataEventDetailType.Relays -> { - SynchronizationFilter( - authors = arrayOf( - publicKey - ), - kinds = arrayOf( - RelayFeedsListEvent.KIND, - ), - limit = 50 - ) - } + fun getSynchronizationFilter() = when (metadataEventDetailType) { + MetadataEventDetailType.Posts -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + TextNoteEvent.KIND, + RepostEvent.KIND, + ), + limit = 50 + ) } - - syncFeed(synchronizationFilter) - loadFeed(synchronizationFilter) - } - - - - private fun syncFeed(synchronizationFilter: SynchronizationFilter) { - logger.d("syncFeed") - - viewModelScope.launch(Dispatchers.IO) { - // Sync Notifications... might want to also run this in the background - nostrRepository.queueSynchronizeNostrEvent( - Relays.eventFinderRelaySet.take(1).map { normalizedRelay -> // TODO: Sync from all relays instead of 1 - SynchronizeNostrEventRequest( - purpose = "search", - synchronizationFilters = arrayOf( - synchronizationFilter - ), - relayURL = normalizedRelay.url - ) - } + MetadataEventDetailType.Replies -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + TextNoteEvent.KIND, + ReactionEvent.KIND, + ), + // TODO: replyTo is set... + limit = 50 + ) + } + MetadataEventDetailType.Articles -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + LongTextNoteEvent.KIND, + ), + limit = 50 + ) + } + MetadataEventDetailType.Followers -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + ContactListEvent.KIND, + ), + // TODO: Check users with hexKey + limit = 50 + ) + } + MetadataEventDetailType.Following -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + ContactListEvent.KIND, + ), + limit = 50 + ) + } + MetadataEventDetailType.Zaps -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + LnZapEvent.KIND, + ), + // TODO: Zaps user has received... + limit = 50 + ) + } + MetadataEventDetailType.Photos -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + TextNoteEvent.KIND, + ), + // TODO: filter for tags of pictures... + limit = 50 + ) + } + MetadataEventDetailType.Videos -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + TextNoteEvent.KIND, + ), + // TODO: filter for tags of videos... + limit = 50 + ) + } + MetadataEventDetailType.Bookmarks -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + BookmarkListEvent.KIND, + ), + limit = 50 + ) + } + MetadataEventDetailType.Reports -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + ReportEvent.KIND, + ), + limit = 50 + ) + } + MetadataEventDetailType.Relays -> { + SynchronizationFilter( + authors = arrayOf( + publicKey + ), + kinds = arrayOf( + RelayFeedsListEvent.KIND, + ), + limit = 50 ) } } - private fun loadFeed(synchronizationFilter: SynchronizationFilter) { - logger.d("loadFeed") - - feedJob?.cancel() - feedJob = viewModelScope.launch(Dispatchers.IO) { - // This is something not taking into consideration the results we are actually looking for... - nostrRepository.observeNostrFeed(synchronizationFilter).collect { localNostrEvents -> - feedListUIState = FeedListUIState.Loaded( - localNostrEvents = localNostrEvents - ) - } - } - } - companion object { - const val TAG = "SearchViewModel" + const val TAG = "MetadataEventDetailViewModel" fun factory( initialMetadataEventDetailType: MetadataEventDetailType = MetadataEventDetailType.Posts,