Skip to content

Commit

Permalink
Reset scroll position between filters (#565)
Browse files Browse the repository at this point in the history
  • Loading branch information
jocmp authored Nov 27, 2024
1 parent 9a4cb2a commit 0758310
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 16 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,4 @@ app/gplay/release/

# Cruft
technotes/.obsidian/
.idea/runConfigurations.xml
49 changes: 37 additions & 12 deletions app/src/main/java/com/capyreader/app/ui/articles/ArticleLayout.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import androidx.compose.animation.fadeOut
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.material3.DrawerValue
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
Expand All @@ -16,6 +16,8 @@ import androidx.compose.material3.SnackbarDuration
import androidx.compose.material3.SnackbarHost
import androidx.compose.material3.SnackbarHostState
import androidx.compose.material3.TopAppBarDefaults.pinnedScrollBehavior
import androidx.compose.material3.TopAppBarScrollBehavior
import androidx.compose.material3.TopAppBarState
import androidx.compose.material3.adaptive.ExperimentalMaterial3AdaptiveApi
import androidx.compose.material3.adaptive.layout.ListDetailPaneScaffoldRole
import androidx.compose.material3.adaptive.navigation.rememberListDetailPaneScaffoldNavigator
Expand Down Expand Up @@ -113,16 +115,12 @@ fun ArticleLayout(
val coroutineScope = rememberCoroutineScope()
val scaffoldNavigator = rememberListDetailPaneScaffoldNavigator()
var isRefreshing by remember { mutableStateOf(false) }
val listState = rememberLazyListState()
val listState = rememberArticleListState(filter)
val pagingArticles = articles.collectAsLazyPagingItems(Dispatchers.IO)
val snackbarHost = remember { SnackbarHostState() }
val addFeedSuccessMessage = stringResource(R.string.add_feed_success)
val currentFeed = findCurrentFeed(filter, allFeeds)
val scrollBehavior = pinnedScrollBehavior()
val resetScrollBehaviorOffset = resetScrollBehaviorListener(
listState = listState,
scrollBehavior = scrollBehavior
)
val scrollBehavior = rememberArticleTopBar(filter)
var media by rememberSaveable(saver = Media.Saver) { mutableStateOf(null) }
val focusManager = LocalFocusManager.current
val openUpdatePasswordDialog = {
Expand All @@ -148,16 +146,21 @@ fun ArticleLayout(
}
}

val resetScrollBehaviorOffset = resetScrollBehaviorListener(
listState = listState,
scrollBehavior = scrollBehavior
)

val scrollToTop = {
coroutineScope.launch {
listState.scrollToItem(0)
resetScrollBehaviorOffset()
}
}

val resetScrollOffset = {
val refreshPagination = {
coroutineScope.launch {
pagingArticles.refresh()
delay(500)
resetScrollBehaviorOffset()
}
}
Expand All @@ -166,7 +169,7 @@ fun ArticleLayout(
isRefreshing = true
onFeedRefresh {
isRefreshing = false
resetScrollOffset()
refreshPagination()

if (!isInitialized) {
setInitialized(true)
Expand All @@ -178,7 +181,7 @@ fun ArticleLayout(
scaffoldNavigator.navigateTo(ListDetailPaneScaffoldRole.List)
delay(200)
drawerState.close()
resetScrollOffset()
refreshPagination()
}

val toggleDrawer = {
Expand Down Expand Up @@ -273,7 +276,7 @@ fun ArticleLayout(
statusCount = statusCount,
onSelectStatus = {
onSelectStatus(it)
resetScrollOffset()
refreshPagination()
}
)
},
Expand Down Expand Up @@ -463,6 +466,28 @@ fun findCurrentFeed(filter: ArticleFilter, feeds: List<Feed>): Feed? {
return null
}


@Composable
fun rememberArticleListState(filter: ArticleFilter): LazyListState {
return rememberSaveable(filter, saver = LazyListState.Saver) {
LazyListState()
}
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun rememberArticleTopBar(filter: ArticleFilter): TopAppBarScrollBehavior {
val state = rememberSaveable(filter, saver = TopAppBarState.Saver) {
TopAppBarState(
initialHeightOffsetLimit = 0f,
initialHeightOffset = 0f,
initialContentOffset = 0f
)
}

return pinnedScrollBehavior(state)
}

@Preview
@Composable
fun ArticleLayoutPreview() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import kotlinx.coroutines.launch
import org.koin.compose.koinInject
import java.time.LocalDateTime

@OptIn(FlowPreview::class)
@Composable
fun ArticleList(
articles: LazyPagingItems<Article>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ class ArticleScreenViewModel(
updateFilter(nextFilter)
}

suspend fun selectFeed(feedID: String) {
fun selectFeed(feedID: String) {
viewModelScope.launch(Dispatchers.IO) {
val feed = account.findFeed(feedID) ?: return@launch
val feedFilter = ArticleFilter.Feeds(feedID = feed.id, feedStatus = latestFilter.status)
Expand Down Expand Up @@ -152,6 +152,8 @@ class ArticleScreenViewModel(
account.markAllRead(articleIDs).onFailure {
Sync.markReadAsync(articleIDs, context)
}

updateArticlesSince()
}
}

Expand Down Expand Up @@ -253,7 +255,7 @@ class ArticleScreenViewModel(
_searchQuery.value = query
}

fun addStarAsync(articleID: String) {
fun addStarAsync(articleID: String) {
toggleCurrentStarred(articleID)
addStar(articleID)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ import androidx.compose.runtime.remember

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun resetScrollBehaviorListener(listState: LazyListState, scrollBehavior: TopAppBarScrollBehavior): () -> Unit {
fun resetScrollBehaviorListener(
listState: LazyListState,
scrollBehavior: TopAppBarScrollBehavior
): () -> Unit {
val resetContentOffset by remember {
derivedStateOf {
listState.firstVisibleItemScrollOffset == 0 &&
Expand Down

0 comments on commit 0758310

Please sign in to comment.