diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/PeopleListFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/PeopleListFeedFilter.kt deleted file mode 100644 index e8f741dbd..000000000 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/PeopleListFeedFilter.kt +++ /dev/null @@ -1,29 +0,0 @@ -package com.vitorpamplona.amethyst.ui.dal - -import com.vitorpamplona.amethyst.model.Account -import com.vitorpamplona.amethyst.model.LocalCache -import com.vitorpamplona.amethyst.model.Note -import com.vitorpamplona.amethyst.service.model.PeopleListEvent - -object PeopleListFeedFilter : FeedFilter() { - lateinit var account: Account - - override fun feedKey(): String { - return account.userProfile().pubkeyHex - } - - override fun feed(): List { - val privKey = account.loggedIn.privKey ?: return emptyList() - - val lists = LocalCache.addressables.values - .asSequence() - .filter { - (it.event is PeopleListEvent) - } - .toSet() - - return lists - .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) - .reversed() - } -} diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileBookmarksFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileBookmarksFeedFilter.kt index 884b5e622..0e44838c9 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileBookmarksFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileBookmarksFeedFilter.kt @@ -5,25 +5,17 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -object UserProfileBookmarksFeedFilter : FeedFilter() { - lateinit var account: Account - var user: User? = null - +class UserProfileBookmarksFeedFilter(val user: User, val account: Account) : FeedFilter() { override fun feedKey(): String { - return account.userProfile().pubkeyHex + "-" + user?.pubkeyHex - } - - fun loadUserProfile(accountLoggedIn: Account, user: User?) { - account = accountLoggedIn - this.user = user + return account.userProfile().pubkeyHex + "-" + user.pubkeyHex } override fun feed(): List { - val notes = user?.latestBookmarkList?.taggedEvents()?.mapNotNull { + val notes = user.latestBookmarkList?.taggedEvents()?.mapNotNull { LocalCache.checkGetOrCreateNote(it) }?.toSet() ?: emptySet() - val addresses = user?.latestBookmarkList?.taggedAddresses()?.map { + val addresses = user.latestBookmarkList?.taggedAddresses()?.map { LocalCache.getOrCreateAddressableNote(it) }?.toSet() ?: emptySet() diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt index c7996b985..2da4139b1 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt @@ -4,23 +4,15 @@ import com.vitorpamplona.amethyst.model.Account import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -object UserProfileConversationsFeedFilter : FeedFilter() { - var account: Account? = null - var user: User? = null - +class UserProfileConversationsFeedFilter(val user: User, val account: Account) : FeedFilter() { override fun feedKey(): String { - return account?.userProfile()?.pubkeyHex + "-" + user?.pubkeyHex - } - - fun loadUserProfile(accountLoggedIn: Account, user: User?) { - account = accountLoggedIn - this.user = user + return account.userProfile().pubkeyHex + "-" + user.pubkeyHex } override fun feed(): List { - return user?.notes - ?.filter { account?.isAcceptable(it) == true && !it.isNewThread() } - ?.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) - ?.reversed() ?: emptyList() + return user.notes + .filter { account.isAcceptable(it) == true && !it.isNewThread() } + .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) + .reversed() ?: emptyList() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt index 86e97a3ae..15eea1c1d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt @@ -8,27 +8,19 @@ import com.vitorpamplona.amethyst.service.model.AppRecommendationEvent import com.vitorpamplona.amethyst.service.model.BookmarkListEvent import com.vitorpamplona.amethyst.service.model.PeopleListEvent -object UserProfileNewThreadFeedFilter : FeedFilter() { - var account: Account? = null - var user: User? = null - +class UserProfileNewThreadFeedFilter(val user: User, val account: Account) : FeedFilter() { override fun feedKey(): String { - return account?.userProfile()?.pubkeyHex + "-" + user?.pubkeyHex - } - - fun loadUserProfile(accountLoggedIn: Account, user: User) { - account = accountLoggedIn - this.user = user + return account.userProfile().pubkeyHex + "-" + user.pubkeyHex } override fun feed(): List { val longFormNotes = LocalCache.addressables.values .filter { it.author == user && (it.event !is PeopleListEvent && it.event !is BookmarkListEvent && it.event !is AppRecommendationEvent) } - return user?.notes - ?.plus(longFormNotes) - ?.filter { account?.isAcceptable(it) == true && it.isNewThread() } - ?.sortedWith(compareBy({ it.createdAt() }, { it.idHex })) - ?.reversed() ?: emptyList() + return user.notes + .plus(longFormNotes) + .filter { account.isAcceptable(it) == true && it.isNewThread() } + .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) + .reversed() ?: emptyList() } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileReportsFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileReportsFeedFilter.kt index 920988d3b..761de219d 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileReportsFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileReportsFeedFilter.kt @@ -5,21 +5,13 @@ import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User import com.vitorpamplona.amethyst.service.model.ReportEvent -object UserProfileReportsFeedFilter : FeedFilter() { - var user: User? = null - +class UserProfileReportsFeedFilter(val user: User) : FeedFilter() { override fun feedKey(): String { - return user?.pubkeyHex ?: "" - } - - fun loadUserProfile(user: User?) { - this.user = user + return user.pubkeyHex ?: "" } override fun feed(): List { - val myUser = user ?: return emptyList() - - val reportNotes = LocalCache.notes.values.filter { (it.event as? ReportEvent)?.isTaggedUser(myUser.pubkeyHex) == true } + val reportNotes = LocalCache.notes.values.filter { (it.event as? ReportEvent)?.isTaggedUser(user.pubkeyHex) == true } return reportNotes .sortedWith(compareBy({ it.createdAt() }, { it.idHex })) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt index 377e32e6b..0cf2c9caa 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/FeedViewModel.kt @@ -81,11 +81,38 @@ class NostrThreadFeedViewModel(val noteId: String) : FeedViewModel(ThreadFeedFil } } +class NostrUserProfileNewThreadsFeedViewModel(val user: User, val account: Account) : FeedViewModel(UserProfileNewThreadFeedFilter(user, account)) { + class Factory(val user: User, val account: Account) : ViewModelProvider.Factory { + override fun create(modelClass: Class): NostrUserProfileNewThreadsFeedViewModel { + return NostrUserProfileNewThreadsFeedViewModel(user, account) as NostrUserProfileNewThreadsFeedViewModel + } + } +} +class NostrUserProfileConversationsFeedViewModel(val user: User, val account: Account) : FeedViewModel(UserProfileConversationsFeedFilter(user, account)) { + class Factory(val user: User, val account: Account) : ViewModelProvider.Factory { + override fun create(modelClass: Class): NostrUserProfileConversationsFeedViewModel { + return NostrUserProfileConversationsFeedViewModel(user, account) as NostrUserProfileConversationsFeedViewModel + } + } +} + class NostrHashtagFeedViewModel : FeedViewModel(HashtagFeedFilter) -class NostrUserProfileNewThreadsFeedViewModel : FeedViewModel(UserProfileNewThreadFeedFilter) -class NostrUserProfileConversationsFeedViewModel : FeedViewModel(UserProfileConversationsFeedFilter) -class NostrUserProfileReportFeedViewModel : FeedViewModel(UserProfileReportsFeedFilter) -class NostrUserProfileBookmarksFeedViewModel : FeedViewModel(UserProfileBookmarksFeedFilter) + +class NostrUserProfileReportFeedViewModel(val user: User) : FeedViewModel(UserProfileReportsFeedFilter(user)) { + class Factory(val user: User) : ViewModelProvider.Factory { + override fun create(modelClass: Class): NostrUserProfileReportFeedViewModel { + return NostrUserProfileReportFeedViewModel(user) as NostrUserProfileReportFeedViewModel + } + } +} +class NostrUserProfileBookmarksFeedViewModel(val user: User, val account: Account) : FeedViewModel(UserProfileBookmarksFeedFilter(user, account)) { + class Factory(val user: User, val account: Account) : ViewModelProvider.Factory { + override fun create(modelClass: Class): NostrUserProfileBookmarksFeedViewModel { + return NostrUserProfileBookmarksFeedViewModel(user, account) as NostrUserProfileBookmarksFeedViewModel + } + } +} + class NostrChatroomListKnownFeedViewModel(val account: Account) : FeedViewModel(ChatroomListKnownFeedFilter(account)) { class Factory(val account: Account) : ViewModelProvider.Factory { override fun create(modelClass: Class): NostrChatroomListKnownFeedViewModel { diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt index f1529be8c..94f9a40a3 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ProfileScreen.kt @@ -76,9 +76,6 @@ import com.vitorpamplona.amethyst.ui.components.RobohashFallbackAsyncImage import com.vitorpamplona.amethyst.ui.components.TranslatableRichTextViewer import com.vitorpamplona.amethyst.ui.components.ZoomableImageDialog import com.vitorpamplona.amethyst.ui.components.figureOutMimeType -import com.vitorpamplona.amethyst.ui.dal.UserProfileBookmarksFeedFilter -import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter -import com.vitorpamplona.amethyst.ui.dal.UserProfileNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.UserProfileReportsFeedFilter import com.vitorpamplona.amethyst.ui.navigation.ShowQRDialog import com.vitorpamplona.amethyst.ui.note.ClickableUserPicture @@ -165,33 +162,66 @@ fun PrepareViewModels(baseUser: User, accountViewModel: AccountViewModel, nav: ( ) ) + val threadsViewModel: NostrUserProfileNewThreadsFeedViewModel = viewModel( + key = baseUser.pubkeyHex + "UserProfileNewThreadsFeedViewModel", + factory = NostrUserProfileNewThreadsFeedViewModel.Factory( + baseUser, + accountViewModel.account + ) + ) + + val repliesViewModel: NostrUserProfileConversationsFeedViewModel = viewModel( + key = baseUser.pubkeyHex + "UserProfileConversationsFeedViewModel", + factory = NostrUserProfileConversationsFeedViewModel.Factory( + baseUser, + accountViewModel.account + ) + ) + + val bookmarksFeedViewModel: NostrUserProfileBookmarksFeedViewModel = viewModel( + key = baseUser.pubkeyHex + "UserProfileBookmarksFeedViewModel", + factory = NostrUserProfileBookmarksFeedViewModel.Factory( + baseUser, + accountViewModel.account + ) + ) + + val reportsFeedViewModel: NostrUserProfileReportFeedViewModel = viewModel( + key = baseUser.pubkeyHex + "UserProfileReportFeedViewModel", + factory = NostrUserProfileReportFeedViewModel.Factory( + baseUser + ) + ) + ProfileScreen( baseUser = baseUser, + threadsViewModel, + repliesViewModel, followsFeedViewModel, followersFeedViewModel, appRecommendations, zapFeedViewModel, + bookmarksFeedViewModel, + reportsFeedViewModel, accountViewModel = accountViewModel, nav = nav ) } -@OptIn(ExperimentalFoundationApi::class) @Composable fun ProfileScreen( baseUser: User, + threadsViewModel: NostrUserProfileNewThreadsFeedViewModel, + repliesViewModel: NostrUserProfileConversationsFeedViewModel, followsFeedViewModel: NostrUserProfileFollowsUserFeedViewModel, followersFeedViewModel: NostrUserProfileFollowersUserFeedViewModel, appRecommendations: NostrUserAppRecommendationsFeedViewModel, zapFeedViewModel: NostrUserProfileZapsFeedViewModel, + bookmarksFeedViewModel: NostrUserProfileBookmarksFeedViewModel, + reportsFeedViewModel: NostrUserProfileReportFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit ) { - UserProfileNewThreadFeedFilter.loadUserProfile(accountViewModel.account, baseUser) - UserProfileConversationsFeedFilter.loadUserProfile(accountViewModel.account, baseUser) - UserProfileReportsFeedFilter.loadUserProfile(baseUser) - UserProfileBookmarksFeedFilter.loadUserProfile(accountViewModel.account, baseUser) - NostrUserProfileDataSource.loadUserProfile(baseUser) val lifeCycleOwner = LocalLifecycleOwner.current @@ -223,16 +253,42 @@ fun ProfileScreen( } } - var columnSize by remember { mutableStateOf(IntSize.Zero) } - var tabsSize by remember { mutableStateOf(IntSize.Zero) } + RenderSurface( + baseUser, + threadsViewModel, + repliesViewModel, + appRecommendations, + followsFeedViewModel, + followersFeedViewModel, + zapFeedViewModel, + bookmarksFeedViewModel, + reportsFeedViewModel, + accountViewModel, + nav + ) +} +@Composable +@OptIn(ExperimentalFoundationApi::class) +private fun RenderSurface( + baseUser: User, + threadsViewModel: NostrUserProfileNewThreadsFeedViewModel, + repliesViewModel: NostrUserProfileConversationsFeedViewModel, + appRecommendations: NostrUserAppRecommendationsFeedViewModel, + followsFeedViewModel: NostrUserProfileFollowsUserFeedViewModel, + followersFeedViewModel: NostrUserProfileFollowersUserFeedViewModel, + zapFeedViewModel: NostrUserProfileZapsFeedViewModel, + bookmarksFeedViewModel: NostrUserProfileBookmarksFeedViewModel, + reportsFeedViewModel: NostrUserProfileReportFeedViewModel, + accountViewModel: AccountViewModel, + nav: (String) -> Unit +) { Surface( modifier = Modifier.fillMaxWidth(), color = MaterialTheme.colors.background ) { - val pagerState = rememberPagerState() - val coroutineScope = rememberCoroutineScope() - val scrollState = rememberScrollState() + var columnSize by remember { mutableStateOf(IntSize.Zero) } + var tabsSize by remember { mutableStateOf(IntSize.Zero) } Column( modifier = Modifier @@ -241,58 +297,110 @@ fun ProfileScreen( columnSize = it } ) { - Box( - modifier = Modifier - .verticalScroll(scrollState) - .nestedScroll(object : NestedScrollConnection { - override fun onPreScroll( - available: Offset, - source: NestedScrollSource - ): Offset { - // When scrolling vertically, scroll the container first. - return if (available.y < 0 && scrollState.canScrollForward) { - coroutineScope.launch { - scrollState.scrollBy(-available.y) - } - Offset(0f, available.y) - } else { - Offset.Zero - } - } - }) - .fillMaxHeight() - ) { - Column() { - ProfileHeader(baseUser, appRecommendations, nav, accountViewModel) - ScrollableTabRow( - backgroundColor = MaterialTheme.colors.background, - selectedTabIndex = pagerState.currentPage, - edgePadding = 8.dp, - modifier = Modifier.onSizeChanged { - tabsSize = it - } - ) { - CreateAndRenderTabs(baseUser, pagerState) - } - HorizontalPager( - pageCount = 8, - state = pagerState, - modifier = with(LocalDensity.current) { - Modifier.height((columnSize.height - tabsSize.height).toDp()) - } - ) { page -> - CreateAndRenderPages( - page, - baseUser, - followsFeedViewModel, - followersFeedViewModel, - zapFeedViewModel, - accountViewModel, - nav - ) - } + val pagerState = rememberPagerState() + val coroutineScope = rememberCoroutineScope() + val scrollState = rememberScrollState() + + val tabRowModifier = remember { + Modifier.onSizeChanged { + tabsSize = it } } + + val pagerModifier = with(LocalDensity.current) { + Modifier.height((columnSize.height - tabsSize.height).toDp()) + } + + Box( + modifier = remember { + Modifier + .verticalScroll(scrollState) + .nestedScroll(object : NestedScrollConnection { + override fun onPreScroll( + available: Offset, + source: NestedScrollSource + ): Offset { + // When scrolling vertically, scroll the container first. + return if (available.y < 0 && scrollState.canScrollForward) { + coroutineScope.launch { + scrollState.scrollBy(-available.y) + } + Offset(0f, available.y) + } else { + Offset.Zero + } + } + }) + .fillMaxHeight() + } + ) { + RenderScreen( + baseUser, + pagerState, + tabRowModifier, + pagerModifier, + threadsViewModel, + repliesViewModel, + appRecommendations, + followsFeedViewModel, + followersFeedViewModel, + zapFeedViewModel, + bookmarksFeedViewModel, + reportsFeedViewModel, + accountViewModel, + nav + ) + } + } + } +} + +@Composable +@OptIn(ExperimentalFoundationApi::class) +private fun RenderScreen( + baseUser: User, + pagerState: PagerState, + tabRowModifier: Modifier, + pagerModifier: Modifier, + threadsViewModel: NostrUserProfileNewThreadsFeedViewModel, + repliesViewModel: NostrUserProfileConversationsFeedViewModel, + appRecommendations: NostrUserAppRecommendationsFeedViewModel, + followsFeedViewModel: NostrUserProfileFollowsUserFeedViewModel, + followersFeedViewModel: NostrUserProfileFollowersUserFeedViewModel, + zapFeedViewModel: NostrUserProfileZapsFeedViewModel, + bookmarksFeedViewModel: NostrUserProfileBookmarksFeedViewModel, + reportsFeedViewModel: NostrUserProfileReportFeedViewModel, + accountViewModel: AccountViewModel, + nav: (String) -> Unit +) { + Column() { + ProfileHeader(baseUser, appRecommendations, nav, accountViewModel) + ScrollableTabRow( + backgroundColor = MaterialTheme.colors.background, + selectedTabIndex = pagerState.currentPage, + edgePadding = 8.dp, + modifier = tabRowModifier + ) { + CreateAndRenderTabs(baseUser, pagerState) + } + HorizontalPager( + pageCount = 8, + state = pagerState, + modifier = pagerModifier + ) { page -> + CreateAndRenderPages( + page, + baseUser, + threadsViewModel, + repliesViewModel, + followsFeedViewModel, + followersFeedViewModel, + zapFeedViewModel, + bookmarksFeedViewModel, + reportsFeedViewModel, + accountViewModel, + nav + ) } } } @@ -301,20 +409,24 @@ fun ProfileScreen( private fun CreateAndRenderPages( page: Int, baseUser: User, + threadsViewModel: NostrUserProfileNewThreadsFeedViewModel, + repliesViewModel: NostrUserProfileConversationsFeedViewModel, followsFeedViewModel: NostrUserProfileFollowsUserFeedViewModel, followersFeedViewModel: NostrUserProfileFollowersUserFeedViewModel, zapFeedViewModel: NostrUserProfileZapsFeedViewModel, + bookmarksFeedViewModel: NostrUserProfileBookmarksFeedViewModel, + reportsFeedViewModel: NostrUserProfileReportFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit ) { when (page) { - 0 -> TabNotesNewThreads(accountViewModel, nav) - 1 -> TabNotesConversations(accountViewModel, nav) + 0 -> TabNotesNewThreads(threadsViewModel, accountViewModel, nav) + 1 -> TabNotesConversations(repliesViewModel, accountViewModel, nav) 2 -> TabFollows(baseUser, followsFeedViewModel, accountViewModel, nav) 3 -> TabFollowers(baseUser, followersFeedViewModel, accountViewModel, nav) 4 -> TabReceivedZaps(baseUser, zapFeedViewModel, accountViewModel, nav) - 5 -> TabBookmarks(baseUser, accountViewModel, nav) - 6 -> TabReports(baseUser, accountViewModel, nav) + 5 -> TabBookmarks(bookmarksFeedViewModel, accountViewModel, nav) + 6 -> TabReports(baseUser, reportsFeedViewModel, accountViewModel, nav) 7 -> TabRelays(baseUser, accountViewModel, nav) } } @@ -367,8 +479,7 @@ private fun ReportsTabHeader(baseUser: User) { LaunchedEffect(key1 = userState) { launch(Dispatchers.IO) { - UserProfileReportsFeedFilter.user = baseUser - val newSize = UserProfileReportsFeedFilter.feed().size + val newSize = UserProfileReportsFeedFilter(baseUser).feed().size if (newSize != userReports) { userReports = newSize @@ -1125,9 +1236,7 @@ public fun DrawBanner(baseUser: User) { } @Composable -fun TabNotesNewThreads(accountViewModel: AccountViewModel, nav: (String) -> Unit) { - val feedViewModel: NostrUserProfileNewThreadsFeedViewModel = viewModel() - +fun TabNotesNewThreads(feedViewModel: NostrUserProfileNewThreadsFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit) { LaunchedEffect(Unit) { feedViewModel.invalidateData() } @@ -1148,9 +1257,7 @@ fun TabNotesNewThreads(accountViewModel: AccountViewModel, nav: (String) -> Unit } @Composable -fun TabNotesConversations(accountViewModel: AccountViewModel, nav: (String) -> Unit) { - val feedViewModel: NostrUserProfileConversationsFeedViewModel = viewModel() - +fun TabNotesConversations(feedViewModel: NostrUserProfileConversationsFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit) { LaunchedEffect(Unit) { feedViewModel.invalidateData() } @@ -1171,9 +1278,7 @@ fun TabNotesConversations(accountViewModel: AccountViewModel, nav: (String) -> U } @Composable -fun TabBookmarks(baseUser: User, accountViewModel: AccountViewModel, nav: (String) -> Unit) { - val feedViewModel: NostrUserProfileBookmarksFeedViewModel = viewModel() - +fun TabBookmarks(feedViewModel: NostrUserProfileBookmarksFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit) { LaunchedEffect(Unit) { feedViewModel.invalidateData() } @@ -1263,9 +1368,7 @@ private fun WatchZapsAndUpdateFeed( } @Composable -fun TabReports(baseUser: User, accountViewModel: AccountViewModel, nav: (String) -> Unit) { - val feedViewModel: NostrUserProfileReportFeedViewModel = viewModel() - +fun TabReports(baseUser: User, feedViewModel: NostrUserProfileReportFeedViewModel, accountViewModel: AccountViewModel, nav: (String) -> Unit) { WatchReportsAndUpdateFeed(baseUser, feedViewModel) Column(Modifier.fillMaxHeight()) {