From 4dcf38c492ca1c9ef541dccfe044552224c737cd Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Mon, 8 May 2023 14:46:23 -0400 Subject: [PATCH] Fixing tab sliders from jumping from one state to the other --- .../ui/screen/loggedIn/BookmarkListScreen.kt | 4 +- .../ui/screen/loggedIn/ChatroomListScreen.kt | 168 +++++++----------- .../ui/screen/loggedIn/HiddenUsersScreen.kt | 4 +- .../amethyst/ui/screen/loggedIn/HomeScreen.kt | 53 +++--- .../ui/screen/loggedIn/ProfileScreen.kt | 4 +- 5 files changed, 102 insertions(+), 131 deletions(-) diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/BookmarkListScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/BookmarkListScreen.kt index ab92f670d..b9e79bef6 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/BookmarkListScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/BookmarkListScreen.kt @@ -72,8 +72,8 @@ fun BookmarkListScreen(accountViewModel: AccountViewModel, navController: NavCon } ) } - HorizontalPager(pageCount = 2, state = pagerState) { - when (pagerState.currentPage) { + HorizontalPager(pageCount = 2, state = pagerState) { page -> + when (page) { 0 -> FeedView(privateFeedViewModel, accountViewModel, navController, null) 1 -> FeedView(publicFeedViewModel, accountViewModel, navController, null) } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt index b86669ebc..8c7c26e02 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/ChatroomListScreen.kt @@ -24,6 +24,7 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.MutableState +import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState import androidx.compose.runtime.mutableStateOf @@ -44,6 +45,7 @@ import com.vitorpamplona.amethyst.service.NostrChatroomListDataSource import com.vitorpamplona.amethyst.ui.dal.ChatroomListKnownFeedFilter import com.vitorpamplona.amethyst.ui.dal.ChatroomListNewFeedFilter import com.vitorpamplona.amethyst.ui.screen.ChatroomListFeedView +import com.vitorpamplona.amethyst.ui.screen.FeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListKnownFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrChatroomListNewFeedViewModel import kotlinx.coroutines.launch @@ -58,6 +60,48 @@ fun ChatroomListScreen(accountViewModel: AccountViewModel, navController: NavCon val markKnownAsRead = remember { mutableStateOf(false) } val markNewAsRead = remember { mutableStateOf(false) } + val accountState by accountViewModel.accountLiveData.observeAsState() + val account = accountState?.account ?: return + + ChatroomListKnownFeedFilter.account = account + val knownFeedViewModel: NostrChatroomListKnownFeedViewModel = viewModel() + + ChatroomListNewFeedFilter.account = account + val newFeedViewModel: NostrChatroomListNewFeedViewModel = viewModel() + + LaunchedEffect(accountViewModel) { + NostrChatroomListDataSource.account = account + NostrChatroomListDataSource.start() + knownFeedViewModel.invalidateData() + newFeedViewModel.invalidateData() + } + + val lifeCycleOwner = LocalLifecycleOwner.current + DisposableEffect(accountViewModel) { + val observer = LifecycleEventObserver { _, event -> + if (event == Lifecycle.Event.ON_RESUME) { + NostrChatroomListDataSource.account = account + NostrChatroomListDataSource.start() + knownFeedViewModel.invalidateData() + newFeedViewModel.invalidateData() + } + } + + lifeCycleOwner.lifecycle.addObserver(observer) + onDispose { + lifeCycleOwner.lifecycle.removeObserver(observer) + } + } + + val tabs by remember { + derivedStateOf { + listOf( + ChatroomListTabItem(R.string.known, knownFeedViewModel, markKnownAsRead), + ChatroomListTabItem(R.string.new_requests, newFeedViewModel, markNewAsRead) + ) + } + } + Box(Modifier.fillMaxSize()) { Column(Modifier.fillMaxHeight()) { Column( @@ -68,21 +112,17 @@ fun ChatroomListScreen(accountViewModel: AccountViewModel, navController: NavCon backgroundColor = MaterialTheme.colors.background, selectedTabIndex = pagerState.currentPage ) { - Tab( - selected = pagerState.currentPage == 0, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(0) } }, - text = { - Text(text = stringResource(R.string.known)) - } - ) - - Tab( - selected = pagerState.currentPage == 1, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(1) } }, - text = { - Text(text = stringResource(R.string.new_requests)) - } - ) + tabs.forEachIndexed { index, tab -> + Tab( + selected = pagerState.currentPage == index, + text = { + Text(text = stringResource(tab.resource)) + }, + onClick = { + coroutineScope.launch { pagerState.animateScrollToPage(index) } + } + ) + } } IconButton( @@ -107,102 +147,20 @@ fun ChatroomListScreen(accountViewModel: AccountViewModel, navController: NavCon } } - HorizontalPager(pageCount = 2, state = pagerState) { - when (pagerState.currentPage) { - 0 -> TabKnown(accountViewModel, navController, markKnownAsRead) - 1 -> TabNew(accountViewModel, navController, markNewAsRead) - } + HorizontalPager(pageCount = 2, state = pagerState) { page -> + ChatroomListFeedView( + viewModel = tabs[page].viewModel, + accountViewModel = accountViewModel, + navController = navController, + markAsRead = tabs[page].markAsRead + ) } } } } } -@Composable -fun TabKnown( - accountViewModel: AccountViewModel, - navController: NavController, - markAsRead: MutableState -) { - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account ?: return - - ChatroomListKnownFeedFilter.account = account - val feedViewModel: NostrChatroomListKnownFeedViewModel = viewModel() - - LaunchedEffect(accountViewModel) { - NostrChatroomListDataSource.account = account - NostrChatroomListDataSource.start() - feedViewModel.invalidateData() - } - - val lifeCycleOwner = LocalLifecycleOwner.current - DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { _, event -> - if (event == Lifecycle.Event.ON_RESUME) { - NostrChatroomListDataSource.account = account - NostrChatroomListDataSource.start() - feedViewModel.invalidateData() - } - } - - lifeCycleOwner.lifecycle.addObserver(observer) - onDispose { - lifeCycleOwner.lifecycle.removeObserver(observer) - } - } - - Column(Modifier.fillMaxHeight()) { - Column( - modifier = Modifier.padding(vertical = 0.dp) - ) { - ChatroomListFeedView(feedViewModel, accountViewModel, navController, markAsRead) - } - } -} - -@Composable -fun TabNew( - accountViewModel: AccountViewModel, - navController: NavController, - markAsRead: MutableState -) { - val accountState by accountViewModel.accountLiveData.observeAsState() - val account = accountState?.account ?: return - - ChatroomListNewFeedFilter.account = account - val feedViewModel: NostrChatroomListNewFeedViewModel = viewModel() - - LaunchedEffect(accountViewModel) { - NostrChatroomListDataSource.account = account - NostrChatroomListDataSource.start() - feedViewModel.invalidateData() - } - - val lifeCycleOwner = LocalLifecycleOwner.current - DisposableEffect(accountViewModel) { - val observer = LifecycleEventObserver { _, event -> - if (event == Lifecycle.Event.ON_RESUME) { - NostrChatroomListDataSource.account = account - NostrChatroomListDataSource.start() - feedViewModel.invalidateData() - } - } - - lifeCycleOwner.lifecycle.addObserver(observer) - onDispose { - lifeCycleOwner.lifecycle.removeObserver(observer) - } - } - - Column(Modifier.fillMaxHeight()) { - Column( - modifier = Modifier.padding(vertical = 0.dp) - ) { - ChatroomListFeedView(feedViewModel, accountViewModel, navController, markAsRead) - } - } -} +class ChatroomListTabItem(val resource: Int, val viewModel: FeedViewModel, val markAsRead: MutableState) @Composable fun ChatroomTabMenu( diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HiddenUsersScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HiddenUsersScreen.kt index 40dfa3099..243e57289 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HiddenUsersScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HiddenUsersScreen.kt @@ -53,8 +53,8 @@ fun HiddenUsersScreen(accountViewModel: AccountViewModel, navController: NavCont } ) } - HorizontalPager(pageCount = 1, state = pagerState) { - when (pagerState.currentPage) { + HorizontalPager(pageCount = 1, state = pagerState) { page -> + when (page) { 0 -> UserFeedView(feedViewModel, accountViewModel, navController) } } diff --git a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HomeScreen.kt b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HomeScreen.kt index 658963ab4..713cafd32 100644 --- a/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HomeScreen.kt +++ b/app/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/HomeScreen.kt @@ -33,6 +33,7 @@ import com.vitorpamplona.amethyst.ui.dal.HomeNewThreadFeedFilter import com.vitorpamplona.amethyst.ui.navigation.Route import com.vitorpamplona.amethyst.ui.note.UpdateZapAmountDialog import com.vitorpamplona.amethyst.ui.screen.FeedView +import com.vitorpamplona.amethyst.ui.screen.FeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeFeedViewModel import com.vitorpamplona.amethyst.ui.screen.NostrHomeRepliesFeedViewModel import com.vitorpamplona.amethyst.ui.screen.ScrollStateKeys @@ -85,6 +86,15 @@ fun HomeScreen( } } + val tabs by remember(homeFeedViewModel, repliesFeedViewModel) { + mutableStateOf( + listOf( + TabItem(R.string.new_threads, homeFeedViewModel, Route.Home.base + "Follows", ScrollStateKeys.HOME_FOLLOWS), + TabItem(R.string.conversations, repliesFeedViewModel, Route.Home.base + "FollowsReplies", ScrollStateKeys.HOME_REPLIES) + ) + ) + } + Column(Modifier.fillMaxHeight()) { Column( modifier = Modifier.padding(vertical = 0.dp) @@ -93,28 +103,31 @@ fun HomeScreen( backgroundColor = MaterialTheme.colors.background, selectedTabIndex = pagerState.currentPage ) { - Tab( - selected = pagerState.currentPage == 0, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(0) } }, - text = { - Text(text = stringResource(R.string.new_threads)) - } - ) - - Tab( - selected = pagerState.currentPage == 1, - onClick = { coroutineScope.launch { pagerState.animateScrollToPage(1) } }, - text = { - Text(text = stringResource(R.string.conversations)) - } - ) - } - HorizontalPager(pageCount = 2, state = pagerState) { - when (pagerState.currentPage) { - 0 -> FeedView(homeFeedViewModel, accountViewModel, navController, Route.Home.base + "Follows", ScrollStateKeys.HOME_FOLLOWS, scrollToTop) - 1 -> FeedView(repliesFeedViewModel, accountViewModel, navController, Route.Home.base + "FollowsReplies", ScrollStateKeys.HOME_REPLIES, scrollToTop) + tabs.forEachIndexed { index, tab -> + Tab( + selected = pagerState.currentPage == index, + text = { + Text(text = stringResource(tab.resource)) + }, + onClick = { + coroutineScope.launch { pagerState.animateScrollToPage(index) } + } + ) } } + + HorizontalPager(pageCount = 2, state = pagerState) { page -> + FeedView( + viewModel = tabs[page].viewModel, + accountViewModel = accountViewModel, + navController = navController, + routeForLastRead = tabs[page].routeForLastRead, + scrollStateKey = tabs[page].scrollStateKey, + scrollToTop = scrollToTop + ) + } } } } + +class TabItem(val resource: Int, val viewModel: FeedViewModel, val routeForLastRead: String, val scrollStateKey: String) 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 fffd2a126..cd6379cca 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 @@ -288,8 +288,8 @@ fun ProfileScreen(user: User, accountViewModel: AccountViewModel, navController: modifier = with(LocalDensity.current) { Modifier.height((columnSize.height - tabsSize.height).toDp()) } - ) { - when (pagerState.currentPage) { + ) { page -> + when (page) { 0 -> TabNotesNewThreads(accountViewModel, navController) 1 -> TabNotesConversations(accountViewModel, navController) 2 -> TabFollows(baseUser, accountViewModel, navController)