From d57fca35497865209ad2287e9462713392babf9d Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Sun, 19 Feb 2023 11:34:45 -0500 Subject: [PATCH] Splits profile between new threads and replies --- .../dal/UserProfileConversationsFeedFilter.kt | 24 ++++ ...r.kt => UserProfileNewThreadFeedFilter.kt} | 4 +- .../amethyst/ui/screen/FeedViewModel.kt | 6 +- .../ui/screen/loggedIn/ProfileScreen.kt | 108 +++++++++--------- 4 files changed, 87 insertions(+), 55 deletions(-) create mode 100644 app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt rename app/src/main/java/com/vitorpamplona/amethyst/ui/dal/{UserProfileNoteFeedFilter.kt => UserProfileNewThreadFeedFilter.kt} (81%) 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 new file mode 100644 index 000000000..8c0288806 --- /dev/null +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileConversationsFeedFilter.kt @@ -0,0 +1,24 @@ +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.model.User + +object UserProfileConversationsFeedFilter: FeedFilter() { + var account: Account? = null + var user: User? = null + + fun loadUserProfile(accountLoggedIn: Account, userId: String) { + account = accountLoggedIn + user = LocalCache.checkGetOrCreateUser(userId) + } + + override fun feed(): List { + return user?.notes + ?.filter { account?.isAcceptable(it) == true && !it.isNewThread() } + ?.sortedBy { it.event?.createdAt } + ?.reversed() + ?: emptyList() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNoteFeedFilter.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt similarity index 81% rename from app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNoteFeedFilter.kt rename to app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt index 7285f0725..6407840f9 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNoteFeedFilter.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/dal/UserProfileNewThreadFeedFilter.kt @@ -5,7 +5,7 @@ import com.vitorpamplona.amethyst.model.LocalCache import com.vitorpamplona.amethyst.model.Note import com.vitorpamplona.amethyst.model.User -object UserProfileNoteFeedFilter: FeedFilter() { +object UserProfileNewThreadFeedFilter: FeedFilter() { var account: Account? = null var user: User? = null @@ -16,7 +16,7 @@ object UserProfileNoteFeedFilter: FeedFilter() { override fun feed(): List { return user?.notes - ?.filter { account?.isAcceptable(it) == true } + ?.filter { account?.isAcceptable(it) == true && it.isNewThread() } ?.sortedBy { it.event?.createdAt } ?.reversed() ?: emptyList() 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 5d9d47697..064b7a6de 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 @@ -14,7 +14,8 @@ import com.vitorpamplona.amethyst.ui.dal.GlobalFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeConversationsFeedFilter import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.ThreadFeedFilter -import com.vitorpamplona.amethyst.ui.dal.UserProfileNoteFeedFilter +import com.vitorpamplona.amethyst.ui.dal.UserProfileConversationsFeedFilter +import com.vitorpamplona.amethyst.ui.dal.UserProfileNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.dal.UserProfileReportsFeedFilter import java.util.concurrent.atomic.AtomicBoolean import kotlinx.coroutines.CoroutineScope @@ -32,7 +33,8 @@ class NostrChannelFeedViewModel: FeedViewModel(ChannelFeedFilter) class NostrChatRoomFeedViewModel: FeedViewModel(ChatroomFeedFilter) class NostrGlobalFeedViewModel: FeedViewModel(GlobalFeedFilter) class NostrThreadFeedViewModel: FeedViewModel(ThreadFeedFilter) -class NostrUserProfileFeedViewModel: FeedViewModel(UserProfileNoteFeedFilter) +class NostrUserProfileNewThreadsFeedViewModel: FeedViewModel(UserProfileNewThreadFeedFilter) +class NostrUserProfileConversationsFeedViewModel: FeedViewModel(UserProfileConversationsFeedFilter) class NostrUserProfileReportFeedViewModel: FeedViewModel(UserProfileReportsFeedFilter) class NostrChatroomListKnownFeedViewModel: FeedViewModel(ChatroomListKnownFeedFilter) class NostrChatroomListNewFeedViewModel: FeedViewModel(ChatroomListNewFeedFilter) 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 dacb021ce..82dda4048 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 @@ -57,7 +57,8 @@ import com.vitorpamplona.amethyst.ui.actions.NewUserMetadataView import com.vitorpamplona.amethyst.ui.components.InvoiceRequest import com.vitorpamplona.amethyst.ui.dal.UserProfileFollowersFeedFilter import com.vitorpamplona.amethyst.ui.dal.UserProfileFollowsFeedFilter -import com.vitorpamplona.amethyst.ui.dal.UserProfileNoteFeedFilter +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.dal.UserProfileZapsFeedFilter import com.vitorpamplona.amethyst.ui.note.UserPicture @@ -65,7 +66,6 @@ import com.vitorpamplona.amethyst.ui.note.showAmount import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel import com.vitorpamplona.amethyst.ui.theme.BitcoinOrange import kotlinx.coroutines.launch -import nostr.postr.toNpub import nostr.postr.toNsec @OptIn(ExperimentalPagerApi::class) @@ -76,7 +76,8 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro if (userId == null) return - UserProfileNoteFeedFilter.loadUserProfile(account, userId) + UserProfileNewThreadFeedFilter.loadUserProfile(account, userId) + UserProfileConversationsFeedFilter.loadUserProfile(account, userId) UserProfileFollowersFeedFilter.loadUserProfile(account, userId) UserProfileFollowsFeedFilter.loadUserProfile(account, userId) UserProfileZapsFeedFilter.loadUserProfile(userId) @@ -164,62 +165,38 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro tabsSize = it } ) { - Tab( - selected = pagerState.currentPage == 0, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(0) } }, - text = { + val tabs = listOf<@Composable() (() -> Unit)?>( + { Text(text = "Notes") - } - ) - - Tab( - selected = pagerState.currentPage == 1, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(1) } }, - text = { + }, + { + Text(text = "Replies") + }, + { val userState by baseUser.live().follows.observeAsState() val userFollows = userState?.user?.follows?.size ?: "--" Text(text = "$userFollows Follows") - } - ) - - Tab( - selected = pagerState.currentPage == 2, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(2) } }, - text = { + }, + { val userState by baseUser.live().follows.observeAsState() val userFollows = userState?.user?.followers?.size ?: "--" Text(text = "$userFollows Followers") - } - ) - - Tab( - selected = pagerState.currentPage == 3, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(3) } }, - text = { + }, + { val userState by baseUser.live().zaps.observeAsState() val userZaps = userState?.user?.zappedAmount() Text(text = "${showAmount(userZaps)} Zaps") - } - ) - - Tab( - selected = pagerState.currentPage == 4, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(4) } }, - text = { + }, + { val userState by baseUser.live().reports.observeAsState() val userReports = userState?.user?.reports?.values?.flatten()?.count() Text(text = "${userReports} Reports") - } - ) - - Tab( - selected = pagerState.currentPage == 5, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(5) } }, - text = { + }, + { val userState by baseUser.live().relays.observeAsState() val userRelaysBeingUsed = userState?.user?.relaysBeingUsed?.size ?: "--" @@ -230,21 +207,30 @@ fun ProfileScreen(userId: String?, accountViewModel: AccountViewModel, navContro Text(text = "$userRelaysBeingUsed / $userRelays Relays") } ) + + tabs.forEachIndexed { index, function -> + Tab( + selected = pagerState.currentPage == index, + onClick = { coroutineScope.launch { pagerState.animateScrollToPage(index) } }, + text = function + ) + } } HorizontalPager( - count = 6, + count = 7, state = pagerState, modifier = with(LocalDensity.current) { Modifier.height((columnSize.height - tabsSize.height).toDp()) } ) { when (pagerState.currentPage) { - 0 -> TabNotes(baseUser, accountViewModel, navController) - 1 -> TabFollows(baseUser, accountViewModel, navController) - 2 -> TabFollowers(baseUser, accountViewModel, navController) - 3 -> TabReceivedZaps(baseUser, accountViewModel, navController) - 4 -> TabReports(baseUser, accountViewModel, navController) - 5 -> TabRelays(baseUser, accountViewModel, navController) + 0 -> TabNotesNewThreads(baseUser, accountViewModel, navController) + 1 -> TabNotesConversations(baseUser, accountViewModel, navController) + 2 -> TabFollows(baseUser, accountViewModel, navController) + 3 -> TabFollowers(baseUser, accountViewModel, navController) + 4 -> TabReceivedZaps(baseUser, accountViewModel, navController) + 5 -> TabReports(baseUser, accountViewModel, navController) + 6 -> TabRelays(baseUser, accountViewModel, navController) } } } @@ -465,10 +451,30 @@ private fun DrawBanner(baseUser: User) { } @Composable -fun TabNotes(user: User, accountViewModel: AccountViewModel, navController: NavController) { +fun TabNotesNewThreads(user: User, accountViewModel: AccountViewModel, navController: NavController) { val accountState by accountViewModel.accountLiveData.observeAsState() if (accountState != null) { - val feedViewModel: NostrUserProfileFeedViewModel = viewModel() + val feedViewModel: NostrUserProfileNewThreadsFeedViewModel = viewModel() + + LaunchedEffect(Unit) { + feedViewModel.refresh() + } + + Column(Modifier.fillMaxHeight()) { + Column( + modifier = Modifier.padding(vertical = 0.dp) + ) { + FeedView(feedViewModel, accountViewModel, navController, null) + } + } + } +} + +@Composable +fun TabNotesConversations(user: User, accountViewModel: AccountViewModel, navController: NavController) { + val accountState by accountViewModel.accountLiveData.observeAsState() + if (accountState != null) { + val feedViewModel: NostrUserProfileConversationsFeedViewModel = viewModel() LaunchedEffect(Unit) { feedViewModel.refresh()