diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryListingScreen.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryListingScreen.kt index 378e5fb..a840dba 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryListingScreen.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryListingScreen.kt @@ -53,16 +53,22 @@ import kotlin.math.roundToInt @Composable fun DirectoryScreen(directoryViewModel: DirectoryViewModel) { val state = directoryViewModel.state - directoryViewModel.ObserveEvents() - LifecycleEffect( - onStart = { directoryViewModel.start() }, - onStop = { directoryViewModel.stop() } + + val listState: LazyListState = rememberLazyListState( + initialFirstVisibleItemIndex = 0, ) val toolbarHeight = 72.dp val toolbarHeightPx = with(LocalDensity.current) { toolbarHeight.roundToPx().toFloat() } val toolbarOffsetHeightPx = remember { mutableStateOf(0f) } + directoryViewModel.ObserveEvents(listState, toolbarOffsetHeightPx) + + LifecycleEffect( + onStart = { directoryViewModel.start() }, + onStop = { directoryViewModel.stop() } + ) + val nestedScrollConnection = remember { object : NestedScrollConnection { override fun onPreScroll(available: Offset, source: NestedScrollSource): Offset { @@ -80,7 +86,7 @@ fun DirectoryScreen(directoryViewModel: DirectoryViewModel) { ) { when (state) { is Content -> { - Content(state) + Content(listState, state) } EmptyLoading -> CenteredLoading() is Error -> { @@ -99,7 +105,7 @@ fun DirectoryScreen(directoryViewModel: DirectoryViewModel) { } @Composable -private fun DirectoryViewModel.ObserveEvents() { +private fun DirectoryViewModel.ObserveEvents(listState: LazyListState, toolbarPosition: MutableState) { val context = LocalContext.current StartObserving { this@ObserveEvents.events.launch { @@ -107,21 +113,22 @@ private fun DirectoryViewModel.ObserveEvents() { is OpenDownloadUrl -> { context.startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(it.url))) } + DirectoryEvent.ScrollToTop -> { + toolbarPosition.value = 0f + listState.scrollToItem(0) + } } } } } @Composable -private fun Content(state: Content) { +private fun Content(listState: LazyListState, state: Content) { val context = LocalContext.current val navigateToRoom = { roomId: RoomId -> context.startActivity(MessengerActivity.newInstance(context, roomId)) } val clock = Clock.systemUTC() - val listState: LazyListState = rememberLazyListState( - initialFirstVisibleItemIndex = 0, - ) val scope = rememberCoroutineScope() LaunchedEffect(key1 = state.overviewState) { diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryState.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryState.kt index d52fb1d..6b1879e 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryState.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryState.kt @@ -10,5 +10,6 @@ sealed interface DirectoryScreenState { sealed interface DirectoryEvent { data class OpenDownloadUrl(val url: String) : DirectoryEvent + object ScrollToTop : DirectoryEvent } diff --git a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryViewModel.kt b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryViewModel.kt index 44a68ad..0bd06d4 100644 --- a/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryViewModel.kt +++ b/features/directory/src/main/kotlin/app/dapk/st/directory/DirectoryViewModel.kt @@ -36,5 +36,9 @@ class DirectoryViewModel( fun stop() { syncJob?.cancel() } + + fun scrollToTopOfMessages() { + _events.tryEmit(DirectoryEvent.ScrollToTop) + } } diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt b/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt index 62b7605..250265c 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/HomeScreen.kt @@ -25,6 +25,7 @@ fun HomeScreen(homeViewModel: HomeViewModel) { homeViewModel.start() } + when (val state = homeViewModel.state) { Loading -> CenteredLoading() is SignedIn -> { @@ -66,7 +67,12 @@ private fun BottomBar(state: SignedIn, homeViewModel: HomeViewModel) { Directory -> BottomNavigationItem( icon = { Icon(page.icon, contentDescription = null) }, selected = state.page == page, - onClick = { homeViewModel.changePage(page) }, + onClick = { + when { + state.page == page -> homeViewModel.scrollToTopOfMessages() + else -> homeViewModel.changePage(page) + } + }, ) Profile -> BottomNavigationItem( icon = { diff --git a/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt b/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt index 5a4d7e5..877314a 100644 --- a/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt +++ b/features/home/src/main/kotlin/app/dapk/st/home/HomeViewModel.kt @@ -55,6 +55,10 @@ class HomeViewModel( } } + fun scrollToTopOfMessages() { + directoryViewModel.scrollToTopOfMessages() + } + fun changePage(page: Page) { state = when (val current = state) { Loading -> current