Implement hideReadFeeds preference in TimelineTab

This commit is contained in:
Shinokuni 2024-07-22 15:23:48 +02:00
parent 1e5a23b722
commit 0adf55eb02
4 changed files with 96 additions and 23 deletions

View File

@ -5,6 +5,7 @@ import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder import com.readrops.db.entities.Folder
import com.readrops.db.filters.MainFilter import com.readrops.db.filters.MainFilter
import com.readrops.db.queries.FeedUnreadCountQueryBuilder import com.readrops.db.queries.FeedUnreadCountQueryBuilder
import com.readrops.db.queries.FoldersAndFeedsQueryBuilder
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.combine
@ -15,13 +16,15 @@ class GetFoldersWithFeeds(
fun get( fun get(
accountId: Int, accountId: Int,
mainFilter: MainFilter, mainFilter: MainFilter,
useSeparateState: Boolean useSeparateState: Boolean,
hideReadFeeds: Boolean = false
): Flow<Map<Folder?, List<Feed>>> { ): Flow<Map<Folder?, List<Feed>>> {
val query = FeedUnreadCountQueryBuilder.build(accountId, mainFilter, useSeparateState) val foldersAndFeedsQuery = FoldersAndFeedsQueryBuilder.build(accountId, hideReadFeeds)
val unreadItemsCountQuery = FeedUnreadCountQueryBuilder.build(accountId, mainFilter, useSeparateState)
return combine( return combine(
flow = database.folderDao().selectFoldersAndFeeds(accountId), flow = database.folderDao().selectFoldersAndFeeds(foldersAndFeedsQuery),
flow2 = database.itemDao().selectFeedUnreadItemsCount(query) flow2 = database.itemDao().selectFeedUnreadItemsCount(unreadItemsCountQuery)
) { folders, itemCounts -> ) { folders, itemCounts ->
val foldersWithFeeds = folders.groupBy( val foldersWithFeeds = folders.groupBy(
keySelector = { keySelector = {

View File

@ -85,11 +85,15 @@ class TimelineScreenModel(
) )
} }
preferences.hideReadFeeds.flow
.flatMapLatest { hideReadFeeds ->
getFoldersWithFeeds.get( getFoldersWithFeeds.get(
account.id, accountId = account.id,
filters.mainFilter, mainFilter = filters.mainFilter,
account.config.useSeparateState useSeparateState = account.config.useSeparateState,
hideReadFeeds = hideReadFeeds
) )
}
.collect { foldersAndFeeds -> .collect { foldersAndFeeds ->
_timelineState.update { _timelineState.update {
it.copy( it.copy(

View File

@ -2,8 +2,12 @@ package com.readrops.db.dao
import androidx.room.Dao import androidx.room.Dao
import androidx.room.Query import androidx.room.Query
import androidx.room.RawQuery
import androidx.room.Transaction import androidx.room.Transaction
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.account.Account import com.readrops.db.entities.account.Account
import com.readrops.db.pojo.FolderWithFeed import com.readrops.db.pojo.FolderWithFeed
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -11,20 +15,9 @@ import kotlinx.coroutines.flow.Flow
@Dao @Dao
interface FolderDao : BaseDao<Folder> { interface FolderDao : BaseDao<Folder> {
@Query(""" // TODO react to Item changes when this table is not part of the query might be a perf issue
Select Feed.id As feedId, Feed.name As feedName, Feed.icon_url As feedIcon, Feed.url As feedUrl, @RawQuery(observedEntities = [Folder::class, Feed::class, Item::class])
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription, Feed.remoteId as feedRemoteId, Folder.id As folderId, fun selectFoldersAndFeeds(query: SupportSQLiteQuery): Flow<List<FolderWithFeed>>
Folder.name As folderName, Feed.account_id as accountId, Folder.remoteId as folderRemoteId
From Feed Left Join Folder On Folder.id = Feed.folder_id
Where Feed.folder_id is NULL OR Feed.folder_id is NOT NULL And Feed.id is NULL Or Feed.id is NOT NULL And Feed.account_id = :accountId Group By Feed.id
UNION ALL
Select Feed.id As feedId, Feed.name As feedName, Feed.icon_url As feedIcon, Feed.url As feedUrl,
Feed.siteUrl As feedSiteUrl, Feed.description as feedDescription, Feed.remoteId as feedRemoteId, Folder.id As folderId,
Folder.name As folderName, Folder.account_id as accountId, Folder.remoteId as folderRemoteId
From Folder Left Join Feed On Folder.id = Feed.folder_id
Where Feed.id is NULL And Folder.account_id = :accountId
""")
fun selectFoldersAndFeeds(accountId: Int): Flow<List<FolderWithFeed>>
@Query("Select * From Folder Where account_id = :accountId") @Query("Select * From Folder Where account_id = :accountId")
fun selectFolders(accountId: Int): Flow<List<Folder>> fun selectFolders(accountId: Int): Flow<List<Folder>>

View File

@ -0,0 +1,73 @@
package com.readrops.db.queries
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQueryBuilder
object FoldersAndFeedsQueryBuilder {
private val COLUMNS = arrayOf(
"Feed.id As feedId",
"Feed.name As feedName",
"Feed.icon_url As feedIcon",
"Feed.url As feedUrl",
"Feed.siteUrl As feedSiteUrl",
"Feed.description as feedDescription",
"Feed.remoteId as feedRemoteId",
"Folder.id As folderId",
"Folder.name As folderName",
"Feed.account_id as accountId",
"Folder.remoteId as folderRemoteId"
)
private val FEED_JOIN = """(Select * From Feed Where account_id = :accountId) Feed
Left Join Folder On Folder.id = Feed.folder_id """.trimMargin()
private const val FOLDER_JOIN = "Folder Left Join Feed On Folder.id = Feed.folder_id "
private const val ITEM_JOIN = " Inner Join Item On Item.feed_id = Feed.id "
private const val FEED_SELECTION = "Feed.folder_id is NULL OR Feed.folder_id is NOT NULL "
private const val FOLDER_SELECTION = "Feed.id is NULL And Folder.account_id = :accountId"
private const val ITEM_SELECTION = "And Item.read = 0"
fun build(accountId: Int, hideReadFeeds: Boolean = false): SupportSQLiteQuery {
return SimpleSQLiteQuery(
"""
${buildFeedQuery(accountId, hideReadFeeds).sql}
${
if (!hideReadFeeds) {
"""UNION ALL
${buildFolderQuery(accountId).sql}
""".trimIndent()
} else {
""
}
}""".trimIndent()
)
}
private fun buildFeedQuery(accountId: Int, hideReadFeeds: Boolean): SupportSQLiteQuery {
val tables = if (hideReadFeeds) FEED_JOIN + ITEM_JOIN else FEED_JOIN
val selection = if (hideReadFeeds) FEED_SELECTION + ITEM_SELECTION else FEED_SELECTION
return SupportSQLiteQueryBuilder.builder(tables.replace(":accountId", "$accountId")).run {
columns(COLUMNS)
selection(selection, null)
groupBy("Feed.id")
create()
}
}
private fun buildFolderQuery(accountId: Int): SupportSQLiteQuery {
return SupportSQLiteQueryBuilder.builder(FOLDER_JOIN).run {
columns(COLUMNS)
selection(FOLDER_SELECTION.replace(":accountId", "$accountId"), null)
create()
}
}
}