Fix once and for all folders and feeds query with simple read state

This commit is contained in:
Shinokuni 2024-04-26 17:08:58 +02:00
parent c55a9dc5e4
commit 6893e9a199
6 changed files with 56 additions and 95 deletions

View File

@ -4,7 +4,7 @@ import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.filters.MainFilter
import com.readrops.db.queries.FoldersAndFeedsQueriesBuilder
import com.readrops.db.queries.FeedUnreadItemsCountQueryBuilder
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
@ -13,24 +13,24 @@ class GetFoldersWithFeeds(
) {
fun get(accountId: Int, mainFilter: MainFilter): Flow<Map<Folder?, List<Feed>>> {
val foldersAndFeedsQuery =
FoldersAndFeedsQueriesBuilder.buildFoldersAndFeedsQuery(accountId, mainFilter)
val feedsWithoutFolderQuery =
FoldersAndFeedsQueriesBuilder.buildFeedsWithoutFolderQuery(accountId, mainFilter)
val query = FeedUnreadItemsCountQueryBuilder.build(accountId, mainFilter)
return combine(
flow = database.newFolderDao()
.selectFoldersAndFeeds(foldersAndFeedsQuery),
flow2 = database.newFeedDao()
.selectFeedsWithoutFolder(feedsWithoutFolderQuery)
) { folders, feedsWithoutFolder ->
flow = database.newFolderDao().selectFoldersAndFeeds(accountId),
flow2 = database.newItemDao().selectFeedUnreadItemsCount(query)
) { folders, itemCounts ->
val foldersWithFeeds = folders.groupBy(
keySelector = {
Folder(
id = it.folderId,
name = it.folderName,
accountId = it.accountId
) as Folder?
if (it.folderId != null) {
Folder(
id = it.folderId!!,
name = it.folderName,
accountId = it.accountId
)
} else {
null
}
},
valueTransform = {
Feed(
@ -40,10 +40,11 @@ class GetFoldersWithFeeds(
url = it.feedUrl,
siteUrl = it.feedSiteUrl,
description = it.feedDescription,
unreadCount = it.unreadCount
unreadCount = itemCounts[it.feedId] ?: 0
)
}
).mapValues { listEntry ->
// Empty folder case
if (listEntry.value.any { it.id == 0 }) {
listOf()
} else {
@ -51,25 +52,7 @@ class GetFoldersWithFeeds(
}
}
if (feedsWithoutFolder.isNotEmpty()) {
foldersWithFeeds + mapOf(
Pair(
null,
feedsWithoutFolder.map { feedWithoutFolder ->
Feed(
id = feedWithoutFolder.feedId,
name = feedWithoutFolder.feedName,
iconUrl = feedWithoutFolder.feedIcon,
url = feedWithoutFolder.feedUrl,
siteUrl = feedWithoutFolder.feedSiteUrl,
description = feedWithoutFolder.feedDescription,
unreadCount = feedWithoutFolder.unreadCount
)
})
)
} else {
foldersWithFeeds
}
foldersWithFeeds
}
}
}

View File

@ -2,19 +2,19 @@ package com.readrops.db.dao.newdao
import androidx.room.Dao
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.pojo.FolderWithFeed
import kotlinx.coroutines.flow.Flow
@Dao
interface NewFolderDao : NewBaseDao<Folder> {
@RawQuery(observedEntities = [Folder::class, Feed::class, Item::class])
fun selectFoldersAndFeeds(query: SupportSQLiteQuery): Flow<List<FolderWithFeed>>
@Query("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.account_id As accountId, " +
"Folder.id As folderId, Folder.name As folderName, 0 as unreadCount " +
" 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.account_id = :accountId Group By Feed.id")
fun selectFoldersAndFeeds(accountId: Int): Flow<List<FolderWithFeed>>
@Query("Select * From Folder Where account_id = :accountId")
fun selectFolders(accountId: Int): Flow<List<Folder>>

View File

@ -2,6 +2,7 @@ package com.readrops.db.dao.newdao
import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.MapColumn
import androidx.room.Query
import androidx.room.RawQuery
import androidx.sqlite.db.SupportSQLiteQuery
@ -49,4 +50,8 @@ abstract class NewItemDao : NewBaseDao<Item> {
@Query("Select count(*) From Item Inner Join Feed On Item.feed_id = Feed.id Where read = 0 and account_id = :accountId " +
"And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\")")
abstract fun selectUnreadNewItemsCount(accountId: Int): Flow<Int>
@RawQuery(observedEntities = [Item::class])
abstract fun selectFeedUnreadItemsCount(query: SupportSQLiteQuery):
Flow<Map<@MapColumn(columnName = "feed_id") Int, @MapColumn(columnName = "item_count") Int>>
}

View File

@ -13,15 +13,14 @@ data class FeedWithFolder(
) : Parcelable
data class FolderWithFeed(
val folderId: Int,
val folderName: String,
val folderId: Int?,
val folderName: String?,
val feedId: Int = 0,
val feedName: String? = null,
val feedIcon: String? = null,
val feedUrl: String? = null,
val feedDescription: String? = null,
val feedSiteUrl: String? = null,
val unreadCount: Int = 0,
val accountId: Int = 0
)

View File

@ -0,0 +1,25 @@
package com.readrops.db.queries
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.filters.MainFilter
import org.intellij.lang.annotations.Language
object FeedUnreadItemsCountQueryBuilder {
fun build(accountId: Int, mainFilter: MainFilter): SupportSQLiteQuery {
val filter = when (mainFilter) {
MainFilter.STARS -> "And Item.starred = 1"
MainFilter.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
else -> ""
}
@Language("SQL")
val query = SimpleSQLiteQuery("""
Select feed_id, count(*) AS item_count From Item Inner Join Feed On Feed.id = Item.feed_id
Where read = 0 And account_id = $accountId $filter Group By feed_id
""".trimIndent())
return query
}
}

View File

@ -1,51 +0,0 @@
package com.readrops.db.queries
import androidx.sqlite.db.SimpleSQLiteQuery
import androidx.sqlite.db.SupportSQLiteQuery
import com.readrops.db.filters.MainFilter
import org.intellij.lang.annotations.Language
object FoldersAndFeedsQueriesBuilder {
fun buildFoldersAndFeedsQuery(accountId: Int, mainFilter: MainFilter): SupportSQLiteQuery {
val filter = when (mainFilter) {
MainFilter.STARS -> "And Item.starred = 1"
MainFilter.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
else -> ""
}
@Language("SQL")
val query = SimpleSQLiteQuery("""
With main As (Select Folder.id As folderId, Folder.name As folderName, 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,
Folder.account_id As accountId, Item.read as itemRead
From Folder Left Join Feed On Folder.id = Feed.folder_id Left Join Item On Item.feed_id = Feed.id
Where Feed.folder_id is NULL OR Feed.folder_id is NOT NULL And Feed.account_id = $accountId $filter)
Select folderId, folderName, feedId, feedName, feedIcon, feedUrl, feedSiteUrl, accountId, feedDescription,
(Select count(*) From main Where (itemRead = 0)) as unreadCount
From main Group by feedId, folderId Order By folderName, feedName
""".trimIndent())
return query
}
fun buildFeedsWithoutFolderQuery(accountId: Int, mainFilter: MainFilter): SupportSQLiteQuery {
val filter = when (mainFilter) {
MainFilter.STARS -> "And Item.starred = 1 "
MainFilter.NEW -> "And DateTime(Round(Item.pub_date / 1000), 'unixepoch') Between DateTime(DateTime(\"now\"), \"-24 hour\") And DateTime(\"now\") "
else -> ""
}
@Language("SQL")
val query = SimpleSQLiteQuery("""
With main As (Select Feed.id As feedId, Feed.name As feedName, Feed.icon_url As feedIcon, feed.description as feedDescription,
Feed.url As feedUrl, Feed.siteUrl As feedSiteUrl, Feed.account_id As accountId, Item.read As itemRead
From Feed Left Join Item On Feed.id = Item.feed_id Where Feed.folder_id is Null And Feed.account_id = $accountId $filter)
Select feedId, feedName, feedIcon, feedUrl, feedSiteUrl, accountId, feedDescription,
(Select count(*) From main Where (itemRead = 0)) as unreadCount From main Group by feedId Order By feedName
""".trimIndent())
return query
}
}