Improve feed logic on profile detail

This commit is contained in:
Kgothatso Ngako
2026-04-22 03:25:19 +02:00
parent 2b693b832a
commit 810a690776
8 changed files with 365 additions and 267 deletions

View File

@@ -22,6 +22,9 @@ interface ConnectionDao {
@Query("SELECT * FROM Connection WHERE destinationPublicKey = :destinationPublicKey") @Query("SELECT * FROM Connection WHERE destinationPublicKey = :destinationPublicKey")
fun getPublicKeyFollowers(destinationPublicKey: String): LocalFollowers? fun getPublicKeyFollowers(destinationPublicKey: String): LocalFollowers?
@Query("SELECT * FROM Connection WHERE destinationPublicKey = :destinationPublicKey")
fun observe(destinationPublicKey: String): LocalFollowers?
@Insert @Insert
suspend fun insertPlaceholderProfile(connection: Connection) suspend fun insertPlaceholderProfile(connection: Connection)

View File

@@ -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.Profile
import ac.cord.auxiliary.compose.database.model.intermdiate.LocalProfile 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.Dao
import androidx.room.Insert import androidx.room.Insert
import androidx.room.Query import androidx.room.Query
@@ -18,6 +20,12 @@ interface ProfileDao {
@Query("SELECT * FROM Profile WHERE publicKey = :publicKey") @Query("SELECT * FROM Profile WHERE publicKey = :publicKey")
fun getProfileByPublicKey(publicKey: String): Profile? 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 @Insert
suspend fun insertPlaceholderProfile(profile: Profile) suspend fun insertPlaceholderProfile(profile: Profile)

View File

@@ -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<Profile>
)

View File

@@ -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<Profile>
)

View File

@@ -1,5 +1,7 @@
package ac.cord.auxiliary.compose.ui.composable 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.repository.NostrRepository
import ac.cord.auxiliary.compose.ui.composable.widgets.LoadingDataIndicator import ac.cord.auxiliary.compose.ui.composable.widgets.LoadingDataIndicator
import ac.cord.auxiliary.compose.ui.composable.widgets.feed.FeedListItem 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.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel import androidx.lifecycle.viewmodel.compose.viewModel
import com.vitorpamplona.quartz.nip01Core.core.HexKey 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) @OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
@Composable @Composable
@@ -56,6 +68,23 @@ fun FeedScreen(
val feedListViewModel: FeedListViewModel = viewModel( val feedListViewModel: FeedListViewModel = viewModel(
factory = FeedListViewModel.factory( factory = FeedListViewModel.factory(
initialFeedListUIState = initialFeedListUIState, 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 nostrRepository = nostrRepository
), ),
) )

View File

@@ -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.navigation.routes.Route
import ac.cord.auxiliary.compose.ui.composable.widgets.feed.ListView import ac.cord.auxiliary.compose.ui.composable.widgets.feed.ListView
import ac.cord.auxiliary.compose.ui.theme.AuxTheme 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.MetadataEventDetailType
import ac.cord.auxiliary.compose.ui.view.model.MetadataEventDetailViewModel import ac.cord.auxiliary.compose.ui.view.model.MetadataEventDetailViewModel
import ac.cord.auxiliary.compose.ui.view.model.SearchResultType import ac.cord.auxiliary.compose.ui.view.model.SearchResultType
@@ -216,81 +217,40 @@ fun MetadataEventDetail(
HorizontalPager( HorizontalPager(
state = metadataEventDetailViewModel.pagerState, state = metadataEventDetailViewModel.pagerState,
) { pageIndex -> ) { 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( feedListViewModel.RenderFeed(
modifier = Modifier.fillMaxWidth(), onNavigateToEvent = onNavigateToEvent
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
)
)
}
)
}
}
}
} MetadataEventDetailType.Following -> {
FeedListUIState.Loading -> {
Column( Text("Implementing logic to see following")
modifier = Modifier.fillMaxWidth(), }
horizontalAlignment = Alignment.CenterHorizontally MetadataEventDetailType.Followers -> {
) {
Spacer( Text("Implementing logic to see followers")
modifier = Modifier.height(50.dp) }
) }
Text(
text = "Loading ${MetadataEventDetailType.entries[pageIndex].name.lowercase()}",
textAlign = TextAlign.Center LaunchedEffect(true) {
) metadataEventDetailViewModel.updateMetadataEventDetailType(
Spacer( MetadataEventDetailType.Posts
modifier = Modifier.height(50.dp) ) {
)
LoadingIndicator()
}
}
} }
} }
} }

View File

@@ -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.managers.SeedManager
import ac.cord.auxiliary.compose.nostr.Relays import ac.cord.auxiliary.compose.nostr.Relays
import ac.cord.auxiliary.compose.repository.NostrRepository 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 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.MutableState
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue 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.ViewModel
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
@@ -33,6 +51,7 @@ import kotlinx.coroutines.launch
class FeedListViewModel( class FeedListViewModel(
initialFeedListUIState: FeedListUIState, initialFeedListUIState: FeedListUIState,
val synchronizationFilter: SynchronizationFilter,
val nostrRepository: NostrRepository val nostrRepository: NostrRepository
): ViewModel() { ): ViewModel() {
val logger = Logger.withTag(TAG) val logger = Logger.withTag(TAG)
@@ -58,7 +77,9 @@ class FeedListViewModel(
if (localProfile?.profile == null) { if (localProfile?.profile == null) {
feedListUIState = FeedListUIState.Error feedListUIState = FeedListUIState.Error
} else { } else {
nostrRepository.observeNostrFeed().collect { localNostrEvents -> nostrRepository.observeNostrFeed(
synchronizationFilter
).collect { localNostrEvents ->
feedListUIState = FeedListUIState.Loaded( feedListUIState = FeedListUIState.Loaded(
localNostrEvents = localNostrEvents localNostrEvents = localNostrEvents
) )
@@ -77,23 +98,7 @@ class FeedListViewModel(
SynchronizeNostrEventRequest( SynchronizeNostrEventRequest(
purpose = "feed", purpose = "feed",
synchronizationFilters = arrayOf( synchronizationFilters = arrayOf(
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
)
), ),
relayURL = normalizedRelay.url 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 { companion object {
const val TAG = "FeedListViewModel" const val TAG = "FeedListViewModel"
fun factory( fun factory(
initialFeedListUIState: FeedListUIState = FeedListUIState.Loading, initialFeedListUIState: FeedListUIState = FeedListUIState.Loading,
synchronizationFilter: SynchronizationFilter,
nostrRepository: NostrRepository, nostrRepository: NostrRepository,
): ViewModelProvider.Factory = viewModelFactory { ): ViewModelProvider.Factory = viewModelFactory {
initializer { initializer {
FeedListViewModel( FeedListViewModel(
initialFeedListUIState = initialFeedListUIState, initialFeedListUIState = initialFeedListUIState,
synchronizationFilter = synchronizationFilter,
nostrRepository = nostrRepository nostrRepository = nostrRepository
) )
} }

View File

@@ -42,198 +42,148 @@ class MetadataEventDetailViewModel(
): ViewModel() { ): ViewModel() {
val logger = Logger.withTag(TAG) val logger = Logger.withTag(TAG)
var feedJob: Job? = null
var metadataEventDetailType: MetadataEventDetailType by mutableStateOf(initialMetadataEventDetailType) var metadataEventDetailType: MetadataEventDetailType by mutableStateOf(initialMetadataEventDetailType)
private set private set
var feedListUIState: FeedListUIState by mutableStateOf(FeedListUIState.Loading)
private set
fun updateMetadataEventDetailType (metadataEventDetailType: MetadataEventDetailType, navigateToPage: () -> Unit) { fun updateMetadataEventDetailType (metadataEventDetailType: MetadataEventDetailType, navigateToPage: () -> Unit) {
this.metadataEventDetailType = metadataEventDetailType this.metadataEventDetailType = metadataEventDetailType
initiateMetadataFeed(this.metadataEventDetailType)
navigateToPage.invoke() navigateToPage.invoke()
} }
fun initiateMetadataFeed(metadataEventDetailType: MetadataEventDetailType = this.metadataEventDetailType) { fun getSynchronizationFilter() = when (metadataEventDetailType) {
feedListUIState = FeedListUIState.Loading MetadataEventDetailType.Posts -> {
SynchronizationFilter(
logger.d("initiateMetadataFeed") authors = arrayOf(
val synchronizationFilter = when (metadataEventDetailType) { publicKey
MetadataEventDetailType.Posts -> { ),
SynchronizationFilter( kinds = arrayOf(
authors = arrayOf( TextNoteEvent.KIND,
publicKey RepostEvent.KIND,
), ),
kinds = arrayOf( limit = 50
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
)
}
} }
MetadataEventDetailType.Replies -> {
syncFeed(synchronizationFilter) SynchronizationFilter(
loadFeed(synchronizationFilter) authors = arrayOf(
} publicKey
),
kinds = arrayOf(
TextNoteEvent.KIND,
private fun syncFeed(synchronizationFilter: SynchronizationFilter) { ReactionEvent.KIND,
logger.d("syncFeed") ),
// TODO: replyTo is set...
viewModelScope.launch(Dispatchers.IO) { limit = 50
// 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 MetadataEventDetailType.Articles -> {
SynchronizeNostrEventRequest( SynchronizationFilter(
purpose = "search", authors = arrayOf(
synchronizationFilters = arrayOf( publicKey
synchronizationFilter ),
), kinds = arrayOf(
relayURL = normalizedRelay.url 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 { companion object {
const val TAG = "SearchViewModel" const val TAG = "MetadataEventDetailViewModel"
fun factory( fun factory(
initialMetadataEventDetailType: MetadataEventDetailType = MetadataEventDetailType.Posts, initialMetadataEventDetailType: MetadataEventDetailType = MetadataEventDetailType.Posts,