Implement androidx Paging and unify TimeLineViewModel state
This commit is contained in:
parent
16ed0ef05e
commit
36f768044a
@ -3,10 +3,10 @@ package com.readrops.app.compose.timelime
|
|||||||
import androidx.activity.compose.BackHandler
|
import androidx.activity.compose.BackHandler
|
||||||
import androidx.compose.foundation.layout.Arrangement
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
import androidx.compose.foundation.layout.Column
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.PaddingValues
|
||||||
import androidx.compose.foundation.layout.fillMaxSize
|
import androidx.compose.foundation.layout.fillMaxSize
|
||||||
import androidx.compose.foundation.layout.padding
|
import androidx.compose.foundation.layout.padding
|
||||||
import androidx.compose.foundation.lazy.LazyColumn
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
import androidx.compose.foundation.lazy.items
|
|
||||||
import androidx.compose.foundation.lazy.rememberLazyListState
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
||||||
import androidx.compose.foundation.rememberScrollState
|
import androidx.compose.foundation.rememberScrollState
|
||||||
import androidx.compose.foundation.verticalScroll
|
import androidx.compose.foundation.verticalScroll
|
||||||
@ -31,6 +31,7 @@ import androidx.compose.ui.Alignment
|
|||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
import androidx.lifecycle.compose.collectAsStateWithLifecycle
|
||||||
|
import androidx.paging.compose.collectAsLazyPagingItems
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import cafe.adriel.voyager.navigator.tab.Tab
|
import cafe.adriel.voyager.navigator.tab.Tab
|
||||||
@ -48,27 +49,22 @@ object TimelineTab : Tab {
|
|||||||
|
|
||||||
override val options: TabOptions
|
override val options: TabOptions
|
||||||
@Composable
|
@Composable
|
||||||
get() {
|
get() = TabOptions(
|
||||||
return TabOptions(
|
|
||||||
index = 1u,
|
index = 1u,
|
||||||
title = "Timeline",
|
title = "Timeline",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ExperimentalMaterial3Api::class)
|
@OptIn(ExperimentalMaterial3Api::class)
|
||||||
@Composable
|
@Composable
|
||||||
override fun Content() {
|
override fun Content() {
|
||||||
val viewModel = getViewModel<TimelineViewModel>()
|
val viewModel = getViewModel<TimelineViewModel>()
|
||||||
|
|
||||||
val state by viewModel.timelineState.collectAsStateWithLifecycle()
|
val state by viewModel.timelineState.collectAsStateWithLifecycle()
|
||||||
val drawerState by viewModel.drawerState.collectAsStateWithLifecycle()
|
|
||||||
val isRefreshing by viewModel.isRefreshing.collectAsStateWithLifecycle()
|
|
||||||
|
|
||||||
val navigator = LocalNavigator.currentOrThrow
|
val navigator = LocalNavigator.currentOrThrow
|
||||||
|
|
||||||
val scrollState = rememberLazyListState()
|
val scrollState = rememberLazyListState()
|
||||||
val swipeState = rememberSwipeRefreshState(isRefreshing)
|
val swipeState = rememberSwipeRefreshState(state.isRefreshing)
|
||||||
val drawerUIState = rememberDrawerState(
|
val drawerState = rememberDrawerState(
|
||||||
initialValue = DrawerValue.Closed,
|
initialValue = DrawerValue.Closed,
|
||||||
confirmStateChange = {
|
confirmStateChange = {
|
||||||
if (it == DrawerValue.Closed) {
|
if (it == DrawerValue.Closed) {
|
||||||
@ -82,23 +78,23 @@ object TimelineTab : Tab {
|
|||||||
)
|
)
|
||||||
|
|
||||||
BackHandler(
|
BackHandler(
|
||||||
enabled = drawerState.isOpen,
|
enabled = state.isDrawerOpen,
|
||||||
onBack = { viewModel.closeDrawer() }
|
onBack = { viewModel.closeDrawer() }
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(drawerState.isOpen) {
|
LaunchedEffect(state.isDrawerOpen) {
|
||||||
if (drawerState.isOpen) {
|
if (state.isDrawerOpen) {
|
||||||
drawerUIState.open()
|
drawerState.open()
|
||||||
} else {
|
} else {
|
||||||
drawerUIState.close()
|
drawerState.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ModalNavigationDrawer(
|
ModalNavigationDrawer(
|
||||||
drawerState = drawerUIState,
|
drawerState = drawerState,
|
||||||
drawerContent = {
|
drawerContent = {
|
||||||
TimelineDrawer(
|
TimelineDrawer(
|
||||||
state = drawerState,
|
state = state,
|
||||||
onClickDefaultItem = {
|
onClickDefaultItem = {
|
||||||
viewModel.updateDrawerDefaultItem(it)
|
viewModel.updateDrawerDefaultItem(it)
|
||||||
},
|
},
|
||||||
@ -156,8 +152,8 @@ object TimelineTab : Tab {
|
|||||||
onRefresh = { viewModel.refreshTimeline() },
|
onRefresh = { viewModel.refreshTimeline() },
|
||||||
modifier = Modifier.padding(paddingValues)
|
modifier = Modifier.padding(paddingValues)
|
||||||
) {
|
) {
|
||||||
when (state) {
|
when (val itemState = state.items) {
|
||||||
is TimelineState.Loading -> {
|
is ItemState.Loading -> {
|
||||||
Column(
|
Column(
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
horizontalAlignment = Alignment.CenterHorizontally,
|
||||||
verticalArrangement = Arrangement.Center,
|
verticalArrangement = Arrangement.Center,
|
||||||
@ -167,25 +163,22 @@ object TimelineTab : Tab {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is TimelineState.Error -> {
|
is ItemState.Error -> TODO()
|
||||||
|
is ItemState.Loaded -> {
|
||||||
|
val items = itemState.items.collectAsLazyPagingItems()
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
is TimelineState.Loaded -> {
|
|
||||||
val items = (state as TimelineState.Loaded).items
|
|
||||||
|
|
||||||
if (items.isNotEmpty()) {
|
|
||||||
LazyColumn(
|
LazyColumn(
|
||||||
state = scrollState,
|
state = scrollState,
|
||||||
|
contentPadding = PaddingValues(vertical = MaterialTheme.spacing.shortSpacing),
|
||||||
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing)
|
verticalArrangement = Arrangement.spacedBy(MaterialTheme.spacing.shortSpacing)
|
||||||
) {
|
) {
|
||||||
items(
|
items(
|
||||||
items = items,
|
count = items.itemCount,
|
||||||
key = { it.item.id },
|
key = { items[it]!!.item.id },
|
||||||
contentType = { "item_with_feed" }
|
contentType = { "item_with_feed" }
|
||||||
) { itemWithFeed ->
|
) { itemCount ->
|
||||||
TimelineItem(
|
TimelineItem(
|
||||||
itemWithFeed = itemWithFeed,
|
itemWithFeed = items[itemCount]!!,
|
||||||
onClick = { navigator.push(ItemScreen()) },
|
onClick = { navigator.push(ItemScreen()) },
|
||||||
onFavorite = {},
|
onFavorite = {},
|
||||||
onReadLater = {},
|
onReadLater = {},
|
||||||
@ -193,9 +186,6 @@ object TimelineTab : Tab {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
NoItemPlaceholder()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,23 +2,26 @@ package com.readrops.app.compose.timelime
|
|||||||
|
|
||||||
import androidx.compose.runtime.Immutable
|
import androidx.compose.runtime.Immutable
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import androidx.paging.Pager
|
||||||
|
import androidx.paging.PagingConfig
|
||||||
|
import androidx.paging.PagingData
|
||||||
|
import androidx.paging.cachedIn
|
||||||
import com.readrops.app.compose.base.TabViewModel
|
import com.readrops.app.compose.base.TabViewModel
|
||||||
import com.readrops.app.compose.repositories.GetFoldersWithFeeds
|
import com.readrops.app.compose.repositories.GetFoldersWithFeeds
|
||||||
import com.readrops.app.compose.timelime.drawer.DrawerDefaultItemsSelection
|
|
||||||
import com.readrops.db.Database
|
import com.readrops.db.Database
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
import com.readrops.db.entities.Folder
|
import com.readrops.db.entities.Folder
|
||||||
|
import com.readrops.db.filters.FilterType
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
import com.readrops.db.queries.ItemsQueryBuilder
|
import com.readrops.db.queries.ItemsQueryBuilder
|
||||||
import com.readrops.db.queries.QueryFilters
|
import com.readrops.db.queries.QueryFilters
|
||||||
import kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.CoroutineDispatcher
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.awaitAll
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.catch
|
|
||||||
import kotlinx.coroutines.flow.collectLatest
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.consumeAsFlow
|
import kotlinx.coroutines.flow.consumeAsFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@ -29,108 +32,128 @@ class TimelineViewModel(
|
|||||||
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
|
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
|
||||||
) : TabViewModel(database) {
|
) : TabViewModel(database) {
|
||||||
|
|
||||||
private val _timelineState = MutableStateFlow<TimelineState>(TimelineState.Loading)
|
private val _timelineState = MutableStateFlow(TimelineState())
|
||||||
val timelineState = _timelineState.asStateFlow()
|
val timelineState = _timelineState.asStateFlow()
|
||||||
|
|
||||||
private var _isRefreshing = MutableStateFlow(false)
|
private val filters = MutableStateFlow(_timelineState.value.filters)
|
||||||
val isRefreshing = _isRefreshing.asStateFlow()
|
|
||||||
|
|
||||||
private val _drawerState = MutableStateFlow(DrawerState())
|
|
||||||
val drawerState = _drawerState.asStateFlow()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch(dispatcher) {
|
viewModelScope.launch(dispatcher) {
|
||||||
accountEvent.consumeAsFlow().collectLatest { account ->
|
combine(
|
||||||
val query = ItemsQueryBuilder.buildItemsQuery(QueryFilters(accountId = account.id))
|
accountEvent.consumeAsFlow(),
|
||||||
|
filters
|
||||||
|
) { account, filters ->
|
||||||
|
Pair(account, filters)
|
||||||
|
}.collectLatest { (account, filters) ->
|
||||||
|
val query = ItemsQueryBuilder.buildItemsQuery(filters.copy(accountId = account.id))
|
||||||
|
|
||||||
val items = async {
|
_timelineState.update {
|
||||||
database.newItemDao().selectAll(query)
|
|
||||||
.catch { _timelineState.value = TimelineState.Error(Exception(it)) }
|
|
||||||
.collect {
|
|
||||||
_timelineState.value = TimelineState.Loaded(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val drawer = async {
|
|
||||||
_drawerState.update {
|
|
||||||
it.copy(
|
it.copy(
|
||||||
foldersAndFeeds = getFoldersWithFeeds.get(account.id)
|
foldersAndFeeds = getFoldersWithFeeds.get(account.id),
|
||||||
|
items = ItemState.Loaded(
|
||||||
|
items = Pager(
|
||||||
|
config = PagingConfig(
|
||||||
|
pageSize = 100,
|
||||||
|
prefetchDistance = 150
|
||||||
|
),
|
||||||
|
pagingSourceFactory = {
|
||||||
|
database.newItemDao().selectAll(query)
|
||||||
|
},
|
||||||
|
).flow
|
||||||
|
.cachedIn(viewModelScope)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
awaitAll(items, drawer)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun refreshTimeline() {
|
fun refreshTimeline() {
|
||||||
_isRefreshing.value = true
|
_timelineState.update { it.copy(isRefreshing = true) }
|
||||||
viewModelScope.launch(dispatcher) {
|
viewModelScope.launch(dispatcher) {
|
||||||
repository?.synchronize(null) {
|
repository?.synchronize(null) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_isRefreshing.value = false
|
_timelineState.update { it.copy(isRefreshing = false) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun openDrawer() {
|
fun openDrawer() {
|
||||||
_drawerState.update { it.copy(isOpen = true) }
|
_timelineState.update { it.copy(isDrawerOpen = true) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun closeDrawer() {
|
fun closeDrawer() {
|
||||||
_drawerState.update { it.copy(isOpen = false) }
|
_timelineState.update { it.copy(isDrawerOpen = false) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDrawerDefaultItem(selection: DrawerDefaultItemsSelection) {
|
fun updateDrawerDefaultItem(selection: FilterType) {
|
||||||
_drawerState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
isOpen = false,
|
filters = updateFilters {
|
||||||
selection = selection,
|
it.filters.copy(
|
||||||
selectedFolderId = 0,
|
filterType = selection
|
||||||
selectedFeedId = 0,
|
)
|
||||||
|
},
|
||||||
|
isDrawerOpen = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDrawerFolderSelection(folderId: Int) {
|
fun updateDrawerFolderSelection(folderId: Int) {
|
||||||
_drawerState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
isOpen = false,
|
filters = updateFilters {
|
||||||
selectedFolderId = folderId,
|
it.filters.copy(
|
||||||
selectedFeedId = 0
|
filterType = FilterType.FOLDER_FILER,
|
||||||
|
filterFolderId = folderId,
|
||||||
|
filterFeedId = 0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isDrawerOpen = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun updateDrawerFeedSelection(feedId: Int) {
|
fun updateDrawerFeedSelection(feedId: Int) {
|
||||||
_drawerState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
isOpen = false,
|
filters = updateFilters {
|
||||||
selectedFeedId = feedId,
|
it.filters.copy(
|
||||||
selectedFolderId = 0
|
filterType = FilterType.FEED_FILTER,
|
||||||
|
filterFeedId = feedId,
|
||||||
|
filterFolderId = 0
|
||||||
|
)
|
||||||
|
},
|
||||||
|
isDrawerOpen = false
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sealed class TimelineState {
|
private fun updateFilters(block: () -> QueryFilters): QueryFilters {
|
||||||
object Loading : TimelineState()
|
val filter = block()
|
||||||
|
filters.update { filter }
|
||||||
|
|
||||||
@Immutable
|
return filter
|
||||||
data class Error(val exception: Exception) : TimelineState()
|
}
|
||||||
|
|
||||||
@Immutable
|
|
||||||
data class Loaded(val items: List<ItemWithFeed>) : TimelineState()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Immutable
|
@Immutable
|
||||||
data class DrawerState(
|
data class TimelineState(
|
||||||
val isOpen: Boolean = false,
|
val isRefreshing: Boolean = false,
|
||||||
val selection: DrawerDefaultItemsSelection = DrawerDefaultItemsSelection.ARTICLES,
|
val isDrawerOpen: Boolean = false,
|
||||||
val selectedFolderId: Int = 0,
|
val filters: QueryFilters = QueryFilters(),
|
||||||
val selectedFeedId: Int = 0,
|
val foldersAndFeeds: Map<Folder?, List<Feed>> = emptyMap(),
|
||||||
val foldersAndFeeds: Map<Folder?, List<Feed>> = emptyMap()
|
val items: ItemState = ItemState.Loading
|
||||||
)
|
)
|
||||||
|
|
||||||
|
sealed class ItemState {
|
||||||
|
@Immutable
|
||||||
|
object Loading : ItemState()
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class Error(val exception: Exception) : ItemState()
|
||||||
|
|
||||||
|
@Immutable
|
||||||
|
data class Loaded(val items: Flow<PagingData<ItemWithFeed>>) : ItemState()
|
||||||
|
}
|
||||||
|
@ -23,20 +23,14 @@ import androidx.compose.ui.text.style.TextOverflow
|
|||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import coil.compose.AsyncImage
|
import coil.compose.AsyncImage
|
||||||
import com.readrops.app.compose.R
|
import com.readrops.app.compose.R
|
||||||
import com.readrops.app.compose.timelime.DrawerState
|
import com.readrops.app.compose.timelime.TimelineState
|
||||||
import com.readrops.app.compose.util.theme.spacing
|
import com.readrops.app.compose.util.theme.spacing
|
||||||
|
import com.readrops.db.filters.FilterType
|
||||||
enum class DrawerDefaultItemsSelection {
|
|
||||||
ARTICLES,
|
|
||||||
NEW,
|
|
||||||
FAVORITES,
|
|
||||||
READ_LATER
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun TimelineDrawer(
|
fun TimelineDrawer(
|
||||||
state: DrawerState,
|
state: TimelineState,
|
||||||
onClickDefaultItem: (DrawerDefaultItemsSelection) -> Unit,
|
onClickDefaultItem: (FilterType) -> Unit,
|
||||||
onFolderClick: (Int) -> Unit,
|
onFolderClick: (Int) -> Unit,
|
||||||
onFeedClick: (Int) -> Unit,
|
onFeedClick: (Int) -> Unit,
|
||||||
) {
|
) {
|
||||||
@ -50,7 +44,7 @@ fun TimelineDrawer(
|
|||||||
Spacer(modifier = Modifier.size(MaterialTheme.spacing.drawerSpacing))
|
Spacer(modifier = Modifier.size(MaterialTheme.spacing.drawerSpacing))
|
||||||
|
|
||||||
DrawerDefaultItems(
|
DrawerDefaultItems(
|
||||||
selectedItem = state.selection,
|
selectedItem = state.filters.filterType,
|
||||||
onClick = { onClickDefaultItem(it) }
|
onClick = { onClickDefaultItem(it) }
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -78,10 +72,10 @@ fun TimelineDrawer(
|
|||||||
badge = {
|
badge = {
|
||||||
Text(folderEntry.value.sumOf { it.unreadCount }.toString())
|
Text(folderEntry.value.sumOf { it.unreadCount }.toString())
|
||||||
},
|
},
|
||||||
selected = state.selectedFolderId == folder.id,
|
selected = state.filters.filterFolderId == folder.id,
|
||||||
onClick = { onFolderClick(folder.id) },
|
onClick = { onFolderClick(folder.id) },
|
||||||
feeds = folderEntry.value,
|
feeds = folderEntry.value,
|
||||||
selectedFeed = state.selectedFeedId,
|
selectedFeed = state.filters.filterFeedId,
|
||||||
onFeedClick = { onFeedClick(it) },
|
onFeedClick = { onFeedClick(it) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
@ -106,7 +100,7 @@ fun TimelineDrawer(
|
|||||||
)
|
)
|
||||||
},
|
},
|
||||||
badge = { Text(feed.unreadCount.toString()) },
|
badge = { Text(feed.unreadCount.toString()) },
|
||||||
selected = feed.id == state.selectedFeedId,
|
selected = feed.id == state.filters.filterFeedId,
|
||||||
onClick = { onFeedClick(feed.id) },
|
onClick = { onFeedClick(feed.id) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
@ -119,8 +113,8 @@ fun TimelineDrawer(
|
|||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun DrawerDefaultItems(
|
fun DrawerDefaultItems(
|
||||||
selectedItem: DrawerDefaultItemsSelection,
|
selectedItem: FilterType,
|
||||||
onClick: (DrawerDefaultItemsSelection) -> Unit,
|
onClick: (FilterType) -> Unit,
|
||||||
) {
|
) {
|
||||||
NavigationDrawerItem(
|
NavigationDrawerItem(
|
||||||
label = { Text("Articles") },
|
label = { Text("Articles") },
|
||||||
@ -130,8 +124,8 @@ fun DrawerDefaultItems(
|
|||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
selected = selectedItem == DrawerDefaultItemsSelection.ARTICLES,
|
selected = selectedItem == FilterType.NO_FILTER,
|
||||||
onClick = { onClick(DrawerDefaultItemsSelection.ARTICLES) },
|
onClick = { onClick(FilterType.NO_FILTER) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -143,8 +137,8 @@ fun DrawerDefaultItems(
|
|||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
selected = selectedItem == DrawerDefaultItemsSelection.NEW,
|
selected = selectedItem == FilterType.NEW,
|
||||||
onClick = { onClick(DrawerDefaultItemsSelection.NEW) },
|
onClick = { onClick(FilterType.NEW) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -156,8 +150,8 @@ fun DrawerDefaultItems(
|
|||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
selected = selectedItem == DrawerDefaultItemsSelection.FAVORITES,
|
selected = selectedItem == FilterType.STARS_FILTER,
|
||||||
onClick = { onClick(DrawerDefaultItemsSelection.FAVORITES) },
|
onClick = { onClick(FilterType.STARS_FILTER) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -169,8 +163,8 @@ fun DrawerDefaultItems(
|
|||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
selected = selectedItem == DrawerDefaultItemsSelection.READ_LATER,
|
selected = selectedItem == FilterType.READ_IT_LATER_FILTER,
|
||||||
onClick = { onClick(DrawerDefaultItemsSelection.READ_LATER) },
|
onClick = { onClick(FilterType.READ_IT_LATER_FILTER) },
|
||||||
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
modifier = Modifier.padding(NavigationDrawerItemDefaults.ItemPadding)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,7 @@ dependencies {
|
|||||||
kapt "androidx.room:room-compiler:$room_version"
|
kapt "androidx.room:room-compiler:$room_version"
|
||||||
implementation "androidx.room:room-rxjava2:$room_version"
|
implementation "androidx.room:room-rxjava2:$room_version"
|
||||||
androidTestImplementation "androidx.room:room-testing:$room_version"
|
androidTestImplementation "androidx.room:room-testing:$room_version"
|
||||||
|
implementation "androidx.room:room-paging:$room_version"
|
||||||
|
|
||||||
implementation 'com.github.MatrixDev.Roomigrant:RoomigrantLib:0.3.4'
|
implementation 'com.github.MatrixDev.Roomigrant:RoomigrantLib:0.3.4'
|
||||||
kapt 'com.github.MatrixDev.Roomigrant:RoomigrantCompiler:0.3.4'
|
kapt 'com.github.MatrixDev.Roomigrant:RoomigrantCompiler:0.3.4'
|
||||||
@ -98,4 +99,7 @@ dependencies {
|
|||||||
|
|
||||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4"
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4'
|
||||||
|
|
||||||
|
api "androidx.paging:paging-runtime:3.1.1"
|
||||||
|
api "androidx.paging:paging-compose:1.0.0-alpha18"
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ import io.reactivex.Completable
|
|||||||
interface ItemDao : BaseDao<Item> {
|
interface ItemDao : BaseDao<Item> {
|
||||||
|
|
||||||
@RawQuery(observedEntities = [Item::class, Folder::class, Feed::class, ItemState::class])
|
@RawQuery(observedEntities = [Item::class, Folder::class, Feed::class, ItemState::class])
|
||||||
fun selectAll(query: SupportSQLiteQuery): DataSource.Factory<Int?, ItemWithFeed>
|
fun selectAll(query: SupportSQLiteQuery): DataSource.Factory<Int, ItemWithFeed>
|
||||||
|
|
||||||
@Query("Select * From Item Where id = :itemId")
|
@Query("Select * From Item Where id = :itemId")
|
||||||
fun select(itemId: Int): Item
|
fun select(itemId: Int): Item
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.readrops.db.dao.newdao
|
package com.readrops.db.dao.newdao
|
||||||
|
|
||||||
|
import androidx.paging.PagingSource
|
||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import androidx.room.RawQuery
|
import androidx.room.RawQuery
|
||||||
@ -9,13 +10,12 @@ import com.readrops.db.entities.Folder
|
|||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import com.readrops.db.entities.ItemState
|
import com.readrops.db.entities.ItemState
|
||||||
import com.readrops.db.pojo.ItemWithFeed
|
import com.readrops.db.pojo.ItemWithFeed
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class NewItemDao : NewBaseDao<Item> {
|
abstract class NewItemDao : NewBaseDao<Item> {
|
||||||
|
|
||||||
@RawQuery(observedEntities = [Item::class, Feed::class, Folder::class, ItemState::class])
|
@RawQuery(observedEntities = [Item::class, Feed::class, Folder::class, ItemState::class])
|
||||||
abstract fun selectAll(query: SupportSQLiteQuery): Flow<List<ItemWithFeed>>
|
abstract fun selectAll(query: SupportSQLiteQuery): PagingSource<Int, ItemWithFeed>
|
||||||
|
|
||||||
@Query("Select count(*) From Item Where feed_id = :feedId And read = 0")
|
@Query("Select count(*) From Item Where feed_id = :feedId And read = 0")
|
||||||
abstract fun selectUnreadCount(feedId: Int): Int
|
abstract fun selectUnreadCount(feedId: Int): Int
|
||||||
|
@ -5,5 +5,6 @@ enum class FilterType {
|
|||||||
FOLDER_FILER,
|
FOLDER_FILER,
|
||||||
READ_IT_LATER_FILTER,
|
READ_IT_LATER_FILTER,
|
||||||
STARS_FILTER,
|
STARS_FILTER,
|
||||||
NO_FILTER
|
NO_FILTER,
|
||||||
|
NEW
|
||||||
}
|
}
|
@ -81,7 +81,7 @@ object ItemsQueryBuilder {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class QueryFilters(
|
data class QueryFilters(
|
||||||
var showReadItems: Boolean = true,
|
var showReadItems: Boolean = true,
|
||||||
var filterFeedId: Int = 0,
|
var filterFeedId: Int = 0,
|
||||||
var filterFolderId: Int = 0,
|
var filterFolderId: Int = 0,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user