diff --git a/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineScreenModel.kt b/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineScreenModel.kt index 8f080f22..a3b7462c 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineScreenModel.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineScreenModel.kt @@ -81,8 +81,6 @@ class TimelineScreenModel( } fun refreshTimeline() { - _timelineState.update { it.copy(isRefreshing = true) } - screenModelScope.launch(dispatcher) { val selectedFeeds = if (currentAccount!!.isLocal) { when (filters.value.subFilter) { @@ -97,9 +95,28 @@ class TimelineScreenModel( } } 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( selectedFeeds = selectedFeeds, - onUpdate = { } + onUpdate = { feed -> + _timelineState.update { + it.copy( + currentFeed = feed.name!!, + feedCount = it.feedCount + 1 + ) + } + } ) _timelineState.update { @@ -271,6 +288,9 @@ class TimelineScreenModel( data class TimelineState( val isRefreshing: Boolean = false, val isDrawerOpen: Boolean = false, + val currentFeed: String = "", + val feedCount: Int = 0, + val feedMax: Int = 0, val endSynchronizing: Boolean = false, val synchronizationErrors: ErrorResult? = null, val filters: QueryFilters = QueryFilters(), diff --git a/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineTab.kt b/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineTab.kt index 991fa6f6..36303d88 100644 --- a/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineTab.kt +++ b/appcompose/src/main/java/com/readrops/app/compose/timelime/TimelineTab.kt @@ -55,6 +55,7 @@ import com.readrops.app.compose.item.ItemScreen import com.readrops.app.compose.timelime.drawer.TimelineDrawer import com.readrops.app.compose.util.components.CenteredProgressIndicator 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.theme.spacing import com.readrops.db.filters.ListSortType @@ -80,26 +81,25 @@ object TimelineTab : Tab { val coroutineScope = rememberCoroutineScope() val viewModel = getScreenModel() - val state by viewModel.timelineState.collectAsStateWithLifecycle() val items = state.itemState.collectAsLazyPagingItems() - val scrollState = rememberLazyListState() - val swipeState = rememberPullToRefreshState() + val lazyListState = rememberLazyListState() + val pullToRefreshState = rememberPullToRefreshState() val snackbarHostState = remember { SnackbarHostState() } LaunchedEffect(state.isRefreshing) { if (state.isRefreshing) { - swipeState.startRefresh() + pullToRefreshState.startRefresh() } else { - swipeState.endRefresh() + pullToRefreshState.endRefresh() } } // Material3 pull to refresh doesn't have a onRefresh callback, // so we need to listen to the internal state change to trigger the refresh - LaunchedEffect(swipeState.isRefreshing) { - if (swipeState.isRefreshing && !state.isRefreshing) { + LaunchedEffect(pullToRefreshState.isRefreshing) { + if (pullToRefreshState.isRefreshing && !state.isRefreshing) { viewModel.refreshTimeline() } } @@ -292,9 +292,15 @@ object TimelineTab : Tab { modifier = Modifier .padding(paddingValues) .fillMaxSize() - .nestedScroll(swipeState.nestedScrollConnection) + .nestedScroll(pullToRefreshState.nestedScrollConnection) ) { when { + state.isRefreshing -> RefreshScreen( + currentFeed = state.currentFeed, + feedCount = state.feedCount, + feedMax = state.feedMax + ) + items.isLoading() -> { CenteredProgressIndicator() } @@ -309,7 +315,7 @@ object TimelineTab : Tab { else -> { if (items.itemCount > 0) { LazyColumn( - state = scrollState, + state = lazyListState, contentPadding = PaddingValues(vertical = MaterialTheme.spacing.shortSpacing), verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing) ) { @@ -335,7 +341,7 @@ object TimelineTab : Tab { } PullToRefreshContainer( - state = swipeState, + state = pullToRefreshState, modifier = Modifier.align(Alignment.TopCenter) ) } else { @@ -346,7 +352,7 @@ object TimelineTab : Tab { ) {} PullToRefreshContainer( - state = swipeState, + state = pullToRefreshState, modifier = Modifier.align(Alignment.TopCenter) ) diff --git a/appcompose/src/main/java/com/readrops/app/compose/util/components/RefreshScreen.kt b/appcompose/src/main/java/com/readrops/app/compose/util/components/RefreshScreen.kt new file mode 100644 index 00000000..6d705116 --- /dev/null +++ b/appcompose/src/main/java/com/readrops/app/compose/util/components/RefreshScreen.kt @@ -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)" + ) + } +} \ No newline at end of file diff --git a/db/src/main/java/com/readrops/db/dao/newdao/NewFeedDao.kt b/db/src/main/java/com/readrops/db/dao/newdao/NewFeedDao.kt index 47b1182a..5dcd3a9d 100644 --- a/db/src/main/java/com/readrops/db/dao/newdao/NewFeedDao.kt +++ b/db/src/main/java/com/readrops/db/dao/newdao/NewFeedDao.kt @@ -33,4 +33,6 @@ abstract class NewFeedDao : NewBaseDao { @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?) + @Query("Select count(*) from Feed Where account_id = :accountId") + abstract suspend fun selectFeedCount(accountId: Int): Int } \ No newline at end of file