Add profile details
This commit is contained in:
@@ -4,6 +4,7 @@ import ac.aux.compose.database.model.NostrEvent
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.intermdiate.LocalNostrEvent
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.composable.navigation.routes.Route
|
||||
import ac.aux.compose.ui.composable.widgets.LoadingDataIndicator
|
||||
import ac.aux.compose.ui.composable.widgets.detail.MetadataEventDetail
|
||||
import ac.aux.compose.ui.composable.widgets.detail.TextNoteEventDetail
|
||||
@@ -37,6 +38,7 @@ fun NostrEventDetailScreen(
|
||||
nostrEventId: HexKey,
|
||||
nostrRepository: NostrRepository,
|
||||
onNavigateBack: () -> Unit,
|
||||
onNavigateToEvent: (Route) -> Unit,
|
||||
onNavigateToWriteAReply: (String) -> Unit
|
||||
) {
|
||||
val nostrEventDetailViewModel: NostrEventDetailViewModel = viewModel(
|
||||
@@ -64,6 +66,8 @@ fun NostrEventDetailScreen(
|
||||
MetadataEventDetail(
|
||||
localNostrEvent = feedListUIState.localNostrEvent,
|
||||
onNavigateBack = onNavigateBack,
|
||||
onNavigateToEvent = onNavigateToEvent,
|
||||
nostrRepository = nostrRepository
|
||||
)
|
||||
}
|
||||
TextNoteEvent.KIND -> {
|
||||
@@ -155,6 +159,7 @@ It has survived not only five centuries, but also the leap into electronic types
|
||||
nostrEventId = "",
|
||||
nostrRepository = NostrRepository.NO_OP_NOSTR_REPOSITORY,
|
||||
onNavigateBack = {},
|
||||
onNavigateToEvent = {},
|
||||
onNavigateToWriteAReply = {}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -206,37 +206,72 @@ fun SearchResultScreen(
|
||||
Text("Posts")
|
||||
}
|
||||
SearchResultType.Articles -> {
|
||||
Text("Posts")
|
||||
Text("Articles")
|
||||
}
|
||||
SearchResultType.Profiles -> {
|
||||
Text("Posts")
|
||||
Text("Profiles")
|
||||
}
|
||||
SearchResultType.Photos -> {
|
||||
|
||||
Text("Posts")
|
||||
Text("Photos")
|
||||
}
|
||||
SearchResultType.Videos -> {
|
||||
|
||||
Text("Posts")
|
||||
Text("Videos")
|
||||
}
|
||||
}
|
||||
|
||||
when (val searchResultListUIState = searchViewModel.searchResultListUIState) {
|
||||
SearchResultListUIState.Error -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
Text(
|
||||
text = "Something went wrong",
|
||||
)
|
||||
SearchResultListUIState.Error -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
Text(
|
||||
text = "Something went wrong",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
is SearchResultListUIState.Loaded -> {
|
||||
if (searchResultListUIState.localNostrEvents.isEmpty()) {
|
||||
is SearchResultListUIState.Loaded -> {
|
||||
if (searchResultListUIState.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 = searchResultListUIState.localNostrEvents,
|
||||
key = { localNostrEvent -> localNostrEvent.nostrEvent.id}
|
||||
) { localNostrEvent ->
|
||||
localNostrEvent.ListView(
|
||||
onNavigateToEvent = { nostrEventId ->
|
||||
onNavigateToEvent.invoke(
|
||||
NostrEventDetailRoute(
|
||||
nostrEventId = nostrEventId
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
SearchResultListUIState.Loading -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
@@ -245,66 +280,19 @@ fun SearchResultScreen(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
Text(
|
||||
text = "No events were found",
|
||||
text = "Searching for ${searchViewModel.searchResultType.name.lowercase()} on \"${searchQuery.lowercase()}\"",
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
|
||||
LoadingIndicator()
|
||||
}
|
||||
} else {
|
||||
|
||||
LazyColumn(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||
) {
|
||||
items(
|
||||
items = searchResultListUIState.localNostrEvents,
|
||||
key = { localNostrEvent -> localNostrEvent.nostrEvent.id}
|
||||
) { localNostrEvent ->
|
||||
localNostrEvent.ListView(
|
||||
onNavigateToEvent = { nostrEventId ->
|
||||
onNavigateToEvent.invoke(
|
||||
NostrEventDetailRoute(
|
||||
nostrEventId = nostrEventId
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
SearchResultListUIState.Loading -> {
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
Text(
|
||||
text = "Searching for ${searchViewModel.searchResultType.name.lowercase()} on \"${searchQuery.lowercase()}\"",
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
Spacer(
|
||||
modifier = Modifier.height(50.dp)
|
||||
)
|
||||
|
||||
LoadingIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +376,11 @@ fun AuxNavHost(
|
||||
onNavigateBack = {
|
||||
navController.popBackStack()
|
||||
},
|
||||
onNavigateToEvent = { route ->
|
||||
navController.navigate(
|
||||
route = route
|
||||
)
|
||||
},
|
||||
onNavigateToWriteAReply = { nostrEventId ->
|
||||
navController.navigate(
|
||||
route = WriteNewNoteRoute(
|
||||
|
||||
@@ -3,49 +3,53 @@ package ac.aux.compose.ui.composable.widgets.detail
|
||||
import ac.aux.compose.database.model.NostrEvent
|
||||
import ac.aux.compose.database.model.Profile
|
||||
import ac.aux.compose.database.model.intermdiate.LocalNostrEvent
|
||||
import ac.aux.compose.extensions.toFormattedTimeAndDateString
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.composable.navigation.routes.NostrEventDetailRoute
|
||||
import ac.aux.compose.ui.composable.navigation.routes.Route
|
||||
import ac.aux.compose.ui.composable.widgets.feed.ListView
|
||||
import ac.aux.compose.ui.theme.AuxTheme
|
||||
import ac.aux.compose.ui.view.model.MetadataEventDetailType
|
||||
import ac.aux.compose.ui.view.model.MetadataEventDetailViewModel
|
||||
import ac.aux.compose.ui.view.model.SearchResultType
|
||||
import ac.aux.compose.ui.view.state.FeedListUIState
|
||||
import ac.aux.compose.ui.view.state.SearchResultListUIState
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.WindowInsets
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.pager.HorizontalPager
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.AddReaction
|
||||
import androidx.compose.material.icons.filled.ArrowBackIosNew
|
||||
import androidx.compose.material.icons.filled.Bolt
|
||||
import androidx.compose.material.icons.filled.ChatBubble
|
||||
import androidx.compose.material.icons.filled.CurrencyBitcoin
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Repeat
|
||||
import androidx.compose.material3.BottomAppBar
|
||||
import androidx.compose.material3.Button
|
||||
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||
import androidx.compose.material3.ExtendedFloatingActionButton
|
||||
import androidx.compose.material3.HorizontalDivider
|
||||
import androidx.compose.material3.ExperimentalMaterial3ExpressiveApi
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.IconButton
|
||||
import androidx.compose.material3.LargeTopAppBar
|
||||
import androidx.compose.material3.LoadingIndicator
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.PrimaryScrollableTabRow
|
||||
import androidx.compose.material3.PrimaryTabRow
|
||||
import androidx.compose.material3.Scaffold
|
||||
import androidx.compose.material3.Surface
|
||||
import androidx.compose.material3.Tab
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TopAppBar
|
||||
import androidx.compose.material3.TopAppBarDefaults
|
||||
import androidx.compose.material3.rememberTopAppBarState
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
@@ -55,21 +59,32 @@ import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.text.style.TextOverflow
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.navigation.compose.ComposeNavigator
|
||||
import androidx.navigation.compose.DialogNavigator
|
||||
import androidx.navigation.compose.rememberNavController
|
||||
import androidx.lifecycle.viewmodel.compose.viewModel
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
@OptIn(ExperimentalMaterial3Api::class)
|
||||
@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterial3ExpressiveApi::class)
|
||||
@Composable
|
||||
fun MetadataEventDetail(
|
||||
localNostrEvent: LocalNostrEvent,
|
||||
onNavigateBack: () -> Unit,
|
||||
onNavigateToEvent: (Route) -> Unit,
|
||||
nostrRepository: NostrRepository
|
||||
) {
|
||||
val scope = rememberCoroutineScope()
|
||||
|
||||
val profile = localNostrEvent.profile
|
||||
val scrollBehavior = TopAppBarDefaults.exitUntilCollapsedScrollBehavior(rememberTopAppBarState())
|
||||
|
||||
val metadataEventDetailViewModel: MetadataEventDetailViewModel = viewModel(
|
||||
factory = MetadataEventDetailViewModel.factory(
|
||||
initialMetadataEventDetailType = MetadataEventDetailType.Posts,
|
||||
publicKey = localNostrEvent.nostrEvent.pubKey,
|
||||
nostrRepository = nostrRepository,
|
||||
pagerState = rememberPagerState { SearchResultType.entries.size }
|
||||
),
|
||||
)
|
||||
|
||||
Scaffold(
|
||||
modifier = Modifier.fillMaxSize().nestedScroll(scrollBehavior.nestedScrollConnection),
|
||||
topBar = {
|
||||
@@ -173,27 +188,25 @@ fun MetadataEventDetail(
|
||||
}
|
||||
|
||||
item {
|
||||
val destinations = arrayOf("Notes", "Replies", "Articles", "Follows", "Following", "Photos", "Videos")
|
||||
|
||||
val startDestination = 0
|
||||
var selectedDestination by rememberSaveable {
|
||||
mutableIntStateOf(startDestination)
|
||||
}
|
||||
|
||||
PrimaryScrollableTabRow(
|
||||
modifier = Modifier.padding(10.dp),
|
||||
edgePadding = 10.dp,
|
||||
selectedTabIndex = selectedDestination,
|
||||
selectedTabIndex = metadataEventDetailViewModel.pagerState.currentPage,
|
||||
) {
|
||||
destinations.forEachIndexed { index, destination ->
|
||||
MetadataEventDetailType.entries.forEachIndexed { index, destination ->
|
||||
Tab(
|
||||
selected = selectedDestination == index,
|
||||
selected = metadataEventDetailViewModel.pagerState.currentPage == index,
|
||||
onClick = {
|
||||
selectedDestination = index
|
||||
|
||||
metadataEventDetailViewModel.updateMetadataEventDetailType(destination) {
|
||||
scope.launch {
|
||||
metadataEventDetailViewModel.pagerState.animateScrollToPage(destination.ordinal)
|
||||
}
|
||||
}
|
||||
},
|
||||
text = {
|
||||
Text(
|
||||
text = destination,
|
||||
text = destination.name,
|
||||
maxLines = 1,
|
||||
overflow = TextOverflow.Ellipsis
|
||||
)
|
||||
@@ -203,15 +216,99 @@ fun MetadataEventDetail(
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.Center
|
||||
modifier = Modifier.fillParentMaxSize()
|
||||
) {
|
||||
Spacer(
|
||||
modifier = Modifier.height(30.dp)
|
||||
)
|
||||
Text("Profile Feed Nav Host Goes here...")
|
||||
HorizontalPager(
|
||||
state = metadataEventDetailViewModel.pagerState,
|
||||
) { pageIndex ->
|
||||
|
||||
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
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
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)
|
||||
)
|
||||
|
||||
LoadingIndicator()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LaunchedEffect(true) {
|
||||
metadataEventDetailViewModel.updateMetadataEventDetailType(
|
||||
MetadataEventDetailType.Posts
|
||||
) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -245,6 +342,8 @@ private fun MetadataEventEventDetailPreview() {
|
||||
)
|
||||
),
|
||||
onNavigateBack = {},
|
||||
onNavigateToEvent = {},
|
||||
nostrRepository = NostrRepository.NO_OP_NOSTR_REPOSITORY
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,256 @@
|
||||
package ac.aux.compose.ui.view.model
|
||||
|
||||
import ac.aux.compose.database.model.SynchronizeNostrEventRequest
|
||||
import ac.aux.compose.database.model.types.SynchronizationFilter
|
||||
import ac.aux.compose.nostr.Relays
|
||||
import ac.aux.compose.repository.NostrRepository
|
||||
import ac.aux.compose.ui.view.state.FeedListUIState
|
||||
import ac.aux.compose.ui.view.state.SearchResultListUIState
|
||||
import androidx.compose.foundation.pager.PagerState
|
||||
import androidx.compose.foundation.pager.rememberPagerState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import androidx.lifecycle.viewmodel.initializer
|
||||
import androidx.lifecycle.viewmodel.viewModelFactory
|
||||
import co.touchlab.kermit.Logger
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip02FollowList.ContactListEvent
|
||||
import com.vitorpamplona.quartz.nip10Notes.TextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip18Reposts.RepostEvent
|
||||
import com.vitorpamplona.quartz.nip23LongContent.LongTextNoteEvent
|
||||
import com.vitorpamplona.quartz.nip25Reactions.ReactionEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.bookmarkList.BookmarkListEvent
|
||||
import com.vitorpamplona.quartz.nip51Lists.relayLists.RelayFeedsListEvent
|
||||
import com.vitorpamplona.quartz.nip56Reports.ReportEvent
|
||||
import com.vitorpamplona.quartz.nip57Zaps.LnZapEvent
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.IO
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
enum class MetadataEventDetailType {
|
||||
Posts, Replies, Articles, Followers, Following, Zaps, Photos, Videos, Bookmarks, Reports, Relays
|
||||
}
|
||||
|
||||
class MetadataEventDetailViewModel(
|
||||
initialMetadataEventDetailType: MetadataEventDetailType,
|
||||
val publicKey: HexKey,
|
||||
val nostrRepository: NostrRepository,
|
||||
val pagerState: PagerState
|
||||
): 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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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.map { normalizedRelay ->
|
||||
SynchronizeNostrEventRequest(
|
||||
purpose = "search",
|
||||
synchronizationFilters = arrayOf(
|
||||
synchronizationFilter
|
||||
),
|
||||
relayURL = normalizedRelay.url
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
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"
|
||||
|
||||
fun factory(
|
||||
initialMetadataEventDetailType: MetadataEventDetailType = MetadataEventDetailType.Posts,
|
||||
publicKey: HexKey,
|
||||
nostrRepository: NostrRepository,
|
||||
pagerState: PagerState
|
||||
): ViewModelProvider.Factory = viewModelFactory {
|
||||
initializer {
|
||||
MetadataEventDetailViewModel(
|
||||
initialMetadataEventDetailType = initialMetadataEventDetailType,
|
||||
nostrRepository = nostrRepository,
|
||||
pagerState = pagerState,
|
||||
publicKey = publicKey
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user