mirror of
https://github.com/readrops/Readrops.git
synced 2025-02-08 16:08:44 +01:00
Improve logic to build drawer folders and feeds list
* db requests down to 2 * react to changes when feeds/folders/items read state are modified
This commit is contained in:
parent
36f768044a
commit
03ee5deab9
@ -3,35 +3,43 @@ package com.readrops.app.compose.repositories
|
|||||||
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 kotlinx.coroutines.CoroutineDispatcher
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
|
|
||||||
class GetFoldersWithFeeds(
|
class GetFoldersWithFeeds(
|
||||||
private val database: Database,
|
private val database: Database,
|
||||||
private val dispatcher: CoroutineDispatcher = Dispatchers.IO
|
|
||||||
) {
|
) {
|
||||||
|
|
||||||
suspend fun get(accountId: Int): Map<Folder?, List<Feed>> = withContext(dispatcher) {
|
fun get(accountId: Int): Flow<Map<Folder?, List<Feed>>> {
|
||||||
val foldersWithFeeds = mutableMapOf<Folder?, List<Feed>>()
|
return combine(
|
||||||
val folders = database.newFolderDao().selectFoldersByAccount(accountId)
|
flow = database.newFolderDao()
|
||||||
|
.selectFoldersAndFeeds(accountId),
|
||||||
for (folder in folders) {
|
flow2 = database.newFeedDao()
|
||||||
val feeds = database.newFeedDao().selectFeedsByFolder(folder.id)
|
.selectFeedsWithoutFolder(accountId)
|
||||||
|
) { folders, feedsWithoutFolder ->
|
||||||
for (feed in feeds) {
|
val foldersWithFeeds = folders.groupBy(
|
||||||
feed.unreadCount = database.newItemDao().selectUnreadCount(feed.id)
|
keySelector = { Folder(id = it.folderId, name = it.folderName) },
|
||||||
|
valueTransform = {
|
||||||
|
Feed(
|
||||||
|
id = it.feedId,
|
||||||
|
name = it.feedName,
|
||||||
|
iconUrl = it.feedIcon,
|
||||||
|
unreadCount = it.unreadCount
|
||||||
|
)
|
||||||
|
}
|
||||||
|
).mapValues { listEntry ->
|
||||||
|
if (listEntry.value.any { it.id == 0 }) {
|
||||||
|
listOf()
|
||||||
|
} else {
|
||||||
|
listEntry.value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foldersWithFeeds[folder] = feeds
|
foldersWithFeeds + mapOf(
|
||||||
|
Pair(
|
||||||
|
null,
|
||||||
|
feedsWithoutFolder.map { it.feed.apply { unreadCount = it.unreadCount } })
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val feedsAlone = database.newFeedDao().selectFeedsAlone(accountId)
|
|
||||||
for (feed in feedsAlone) {
|
|
||||||
feed.unreadCount = database.newItemDao().selectUnreadCount(feed.id)
|
|
||||||
}
|
|
||||||
|
|
||||||
foldersWithFeeds[null] = feedsAlone
|
|
||||||
foldersWithFeeds.toSortedMap(nullsLast())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -49,7 +49,6 @@ class TimelineViewModel(
|
|||||||
|
|
||||||
_timelineState.update {
|
_timelineState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
foldersAndFeeds = getFoldersWithFeeds.get(account.id),
|
|
||||||
items = ItemState.Loaded(
|
items = ItemState.Loaded(
|
||||||
items = Pager(
|
items = Pager(
|
||||||
config = PagingConfig(
|
config = PagingConfig(
|
||||||
@ -64,6 +63,15 @@ class TimelineViewModel(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getFoldersWithFeeds.get(account.id)
|
||||||
|
.collect { foldersAndFeeds ->
|
||||||
|
_timelineState.update {
|
||||||
|
it.copy(
|
||||||
|
foldersAndFeeds = foldersAndFeeds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,7 @@ package com.readrops.db.dao.newdao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
|
import com.readrops.db.pojo.FeedWithCount
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
@ -20,9 +21,8 @@ abstract class NewFeedDao : NewBaseDao<Feed> {
|
|||||||
@Query("Select case When :feedUrl In (Select url from Feed Where account_id = :accountId) Then 1 else 0 end")
|
@Query("Select case When :feedUrl In (Select url from Feed Where account_id = :accountId) Then 1 else 0 end")
|
||||||
abstract suspend fun feedExists(feedUrl: String, accountId: Int): Boolean
|
abstract suspend fun feedExists(feedUrl: String, accountId: Int): Boolean
|
||||||
|
|
||||||
@Query("Select * From Feed Where folder_id = :folderId")
|
@Query("Select *, count(*) as unreadCount From Feed Inner Join Item On Feed.id = Item.feed_id " +
|
||||||
abstract suspend fun selectFeedsByFolder(folderId: Int): List<Feed>
|
"Where Feed.folder_id is Null And Item.read = 0 And Feed.account_id = :accountId Group by Feed.id")
|
||||||
|
abstract fun selectFeedsWithoutFolder(accountId: Int): Flow<List<FeedWithCount>>
|
||||||
|
|
||||||
@Query("Select * From Feed Where account_id = :accountId And folder_id Is Null")
|
|
||||||
abstract suspend fun selectFeedsAlone(accountId: Int): List<Feed>
|
|
||||||
}
|
}
|
@ -3,12 +3,16 @@ package com.readrops.db.dao.newdao
|
|||||||
import androidx.room.Dao
|
import androidx.room.Dao
|
||||||
import androidx.room.Query
|
import androidx.room.Query
|
||||||
import com.readrops.db.entities.Folder
|
import com.readrops.db.entities.Folder
|
||||||
|
import com.readrops.db.pojo.FolderWithFeed
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
@Dao
|
@Dao
|
||||||
abstract class NewFolderDao : NewBaseDao<Folder> {
|
abstract class NewFolderDao : NewBaseDao<Folder> {
|
||||||
|
|
||||||
@Query("Select * From Folder Where account_id = :accountId Order By name ASC")
|
@Query("Select Folder.id As folderId, Folder.name as folderName, Feed.id As feedId, Feed.name AS feedName, " +
|
||||||
abstract suspend fun selectFoldersByAccount(accountId: Int): List<Folder>
|
"Feed.icon_url As feedIcon, count(*) As unreadCount 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 Item.read = 0 " +
|
||||||
|
"And Feed.account_id = :accountId Group By Feed.id, Folder.id Order By Folder.id")
|
||||||
|
abstract fun selectFoldersAndFeeds(accountId: Int): Flow<List<FolderWithFeed>>
|
||||||
}
|
}
|
@ -8,6 +8,20 @@ import kotlinx.parcelize.Parcelize
|
|||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data class FeedWithFolder(
|
data class FeedWithFolder(
|
||||||
@Embedded(prefix = "feed_") val feed: Feed,
|
@Embedded(prefix = "feed_") val feed: Feed,
|
||||||
@Embedded(prefix = "folder_") val folder: Folder,
|
@Embedded(prefix = "folder_") val folder: Folder,
|
||||||
) : Parcelable
|
) : Parcelable
|
||||||
|
|
||||||
|
data class FolderWithFeed(
|
||||||
|
val folderId: Int,
|
||||||
|
val folderName: String,
|
||||||
|
val feedId: Int = 0,
|
||||||
|
val feedName: String? = null,
|
||||||
|
val feedIcon: String? = null,
|
||||||
|
val unreadCount: Int = 0
|
||||||
|
)
|
||||||
|
|
||||||
|
data class FeedWithCount(
|
||||||
|
@Embedded val feed: Feed,
|
||||||
|
val unreadCount: Int
|
||||||
|
)
|
Loading…
x
Reference in New Issue
Block a user