Add loading screen for local account in TimelineTab

This commit is contained in:
Shinokuni 2024-03-26 19:41:35 +01:00
parent 2b1992e03a
commit 8b10864578
4 changed files with 67 additions and 14 deletions

View File

@ -81,8 +81,6 @@ class TimelineScreenModel(
} }
fun refreshTimeline() { fun refreshTimeline() {
_timelineState.update { it.copy(isRefreshing = true) }
screenModelScope.launch(dispatcher) { screenModelScope.launch(dispatcher) {
val selectedFeeds = if (currentAccount!!.isLocal) { val selectedFeeds = if (currentAccount!!.isLocal) {
when (filters.value.subFilter) { when (filters.value.subFilter) {
@ -97,9 +95,28 @@ class TimelineScreenModel(
} }
} else listOf() } else listOf()
_timelineState.update {
it.copy(
feedCount = 0,
feedMax = if (selectedFeeds.isNotEmpty())
selectedFeeds.size
else
database.newFeedDao().selectFeedCount(currentAccount!!.id)
)
}
_timelineState.update { it.copy(isRefreshing = true) }
val results = repository?.synchronize( val results = repository?.synchronize(
selectedFeeds = selectedFeeds, selectedFeeds = selectedFeeds,
onUpdate = { } onUpdate = { feed ->
_timelineState.update {
it.copy(
currentFeed = feed.name!!,
feedCount = it.feedCount + 1
)
}
}
) )
_timelineState.update { _timelineState.update {
@ -271,6 +288,9 @@ class TimelineScreenModel(
data class TimelineState( data class TimelineState(
val isRefreshing: Boolean = false, val isRefreshing: Boolean = false,
val isDrawerOpen: Boolean = false, val isDrawerOpen: Boolean = false,
val currentFeed: String = "",
val feedCount: Int = 0,
val feedMax: Int = 0,
val endSynchronizing: Boolean = false, val endSynchronizing: Boolean = false,
val synchronizationErrors: ErrorResult? = null, val synchronizationErrors: ErrorResult? = null,
val filters: QueryFilters = QueryFilters(), val filters: QueryFilters = QueryFilters(),

View File

@ -55,6 +55,7 @@ import com.readrops.app.compose.item.ItemScreen
import com.readrops.app.compose.timelime.drawer.TimelineDrawer import com.readrops.app.compose.timelime.drawer.TimelineDrawer
import com.readrops.app.compose.util.components.CenteredProgressIndicator import com.readrops.app.compose.util.components.CenteredProgressIndicator
import com.readrops.app.compose.util.components.Placeholder import com.readrops.app.compose.util.components.Placeholder
import com.readrops.app.compose.util.components.RefreshScreen
import com.readrops.app.compose.util.components.TwoChoicesDialog import com.readrops.app.compose.util.components.TwoChoicesDialog
import com.readrops.app.compose.util.theme.spacing import com.readrops.app.compose.util.theme.spacing
import com.readrops.db.filters.ListSortType import com.readrops.db.filters.ListSortType
@ -80,26 +81,25 @@ object TimelineTab : Tab {
val coroutineScope = rememberCoroutineScope() val coroutineScope = rememberCoroutineScope()
val viewModel = getScreenModel<TimelineScreenModel>() val viewModel = getScreenModel<TimelineScreenModel>()
val state by viewModel.timelineState.collectAsStateWithLifecycle() val state by viewModel.timelineState.collectAsStateWithLifecycle()
val items = state.itemState.collectAsLazyPagingItems() val items = state.itemState.collectAsLazyPagingItems()
val scrollState = rememberLazyListState() val lazyListState = rememberLazyListState()
val swipeState = rememberPullToRefreshState() val pullToRefreshState = rememberPullToRefreshState()
val snackbarHostState = remember { SnackbarHostState() } val snackbarHostState = remember { SnackbarHostState() }
LaunchedEffect(state.isRefreshing) { LaunchedEffect(state.isRefreshing) {
if (state.isRefreshing) { if (state.isRefreshing) {
swipeState.startRefresh() pullToRefreshState.startRefresh()
} else { } else {
swipeState.endRefresh() pullToRefreshState.endRefresh()
} }
} }
// Material3 pull to refresh doesn't have a onRefresh callback, // Material3 pull to refresh doesn't have a onRefresh callback,
// so we need to listen to the internal state change to trigger the refresh // so we need to listen to the internal state change to trigger the refresh
LaunchedEffect(swipeState.isRefreshing) { LaunchedEffect(pullToRefreshState.isRefreshing) {
if (swipeState.isRefreshing && !state.isRefreshing) { if (pullToRefreshState.isRefreshing && !state.isRefreshing) {
viewModel.refreshTimeline() viewModel.refreshTimeline()
} }
} }
@ -292,9 +292,15 @@ object TimelineTab : Tab {
modifier = Modifier modifier = Modifier
.padding(paddingValues) .padding(paddingValues)
.fillMaxSize() .fillMaxSize()
.nestedScroll(swipeState.nestedScrollConnection) .nestedScroll(pullToRefreshState.nestedScrollConnection)
) { ) {
when { when {
state.isRefreshing -> RefreshScreen(
currentFeed = state.currentFeed,
feedCount = state.feedCount,
feedMax = state.feedMax
)
items.isLoading() -> { items.isLoading() -> {
CenteredProgressIndicator() CenteredProgressIndicator()
} }
@ -309,7 +315,7 @@ object TimelineTab : Tab {
else -> { else -> {
if (items.itemCount > 0) { if (items.itemCount > 0) {
LazyColumn( LazyColumn(
state = scrollState, state = lazyListState,
contentPadding = PaddingValues(vertical = MaterialTheme.spacing.shortSpacing), contentPadding = PaddingValues(vertical = MaterialTheme.spacing.shortSpacing),
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing) verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing)
) { ) {
@ -335,7 +341,7 @@ object TimelineTab : Tab {
} }
PullToRefreshContainer( PullToRefreshContainer(
state = swipeState, state = pullToRefreshState,
modifier = Modifier.align(Alignment.TopCenter) modifier = Modifier.align(Alignment.TopCenter)
) )
} else { } else {
@ -346,7 +352,7 @@ object TimelineTab : Tab {
) {} ) {}
PullToRefreshContainer( PullToRefreshContainer(
state = swipeState, state = pullToRefreshState,
modifier = Modifier.align(Alignment.TopCenter) modifier = Modifier.align(Alignment.TopCenter)
) )

View File

@ -0,0 +1,25 @@
package com.readrops.app.compose.util.components
import androidx.compose.material3.LinearProgressIndicator
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import com.readrops.app.compose.util.theme.VeryShortSpacer
@Composable
fun RefreshScreen(
currentFeed: String,
feedCount: Int,
feedMax: Int
) {
CenteredColumn {
LinearProgressIndicator(
progress = { (feedCount / feedMax).toFloat() }
)
VeryShortSpacer()
Text(
text = "$currentFeed ($feedCount/$feedMax)"
)
}
}

View File

@ -33,4 +33,6 @@ abstract class NewFeedDao : NewBaseDao<Feed> {
@Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId") @Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId")
abstract fun updateFeedFields(feedId: Int, feedName: String, feedUrl: String, folderId: Int?) abstract fun updateFeedFields(feedId: Int, feedName: String, feedUrl: String, folderId: Int?)
@Query("Select count(*) from Feed Where account_id = :accountId")
abstract suspend fun selectFeedCount(accountId: Int): Int
} }