Fetch FreshRSS read and star item states

This commit is contained in:
Shinokuni 2024-05-07 22:50:44 +02:00
parent df2ad13872
commit fbe14121b0
6 changed files with 220 additions and 8 deletions

View File

@ -9,8 +9,8 @@ data class SyncResult(
var starredItems: List<Item> = mutableListOf(),
var feeds: List<Feed> = listOf(),
var folders: List<Folder> = listOf(),
var unreadIds: List<String>? = null,
var readIds: List<String>? = null,
var starredIds: List<String>? = null,
var unreadIds: List<String> = listOf(),
var readIds: List<String> = listOf(),
var starredIds: List<String> = listOf(),
var isError: Boolean = false
)

View File

@ -40,8 +40,8 @@ class NewFreshRSSDataSource(private val service: NewFreshRSSService) {
feeds = async { getFeeds() }.await()
items = async { getItems(listOf(GOOGLE_READ, GOOGLE_STARRED), MAX_ITEMS, null) }.await()
starredItems = async { getStarredItems(MAX_STARRED_ITEMS) }.await()
//unreadIds = async { getItemsIds(GOOGLE_READ, GOOGLE_READING_LIST, MAX_ITEMS) }.await()
// starredIds = async { getItemsIds(null, GOOGLE_STARRED, MAX_STARRED_ITEMS) }.await()
unreadIds = async { getItemsIds(GOOGLE_READ, GOOGLE_READING_LIST, MAX_ITEMS) }.await()
starredIds = async { getItemsIds(null, GOOGLE_STARRED, MAX_STARRED_ITEMS) }.await()
}
} else {
SyncResult()
@ -59,7 +59,7 @@ class NewFreshRSSDataSource(private val service: NewFreshRSSService) {
suspend fun getStarredItems(max: Int) = service.getStarredItems(max)
suspend fun getItemsIds(excludeTarget: String, includeTarget: String, max: Int): List<String> {
suspend fun getItemsIds(excludeTarget: String?, includeTarget: String, max: Int): List<String> {
return service.getItemsIds(excludeTarget, includeTarget, max)
}

View File

@ -10,6 +10,7 @@ import com.readrops.db.Database
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.entities.account.Account
import org.koin.core.component.KoinComponent
@ -46,6 +47,8 @@ class FreshRSSRepository(
insertItems(items, false)
insertItems(starredItems, true)
insertItemsIds(unreadIds, readIds, starredIds.toMutableList())
}
return syncResult
@ -103,4 +106,56 @@ class FreshRSSRepository(
database.itemDao().insert(itemsToInsert)
}
}
private suspend fun insertItemsIds(
unreadIds: List<String>,
readIds: List<String>,
starredIds: MutableList<String> // TODO is it performance wise?
) {
database.newItemStateDao().deleteItemStates(account.id)
database.newItemStateDao().insert(unreadIds.map { id ->
val starred = starredIds.count { starredId -> starredId == id } == 1
if (starred) {
starredIds.remove(id)
}
ItemState(
id = 0,
read = false,
starred = starred,
remoteId = id,
accountId = account.id
)
})
database.newItemStateDao().insert(readIds.map { id ->
val starred = starredIds.count { starredId -> starredId == id } == 1
if (starred) {
starredIds.remove(id)
}
ItemState(
id = 0,
read = true,
starred = starred,
remoteId = id,
accountId = account.id
)
})
// insert starred items ids which are read
if (starredIds.isNotEmpty()) {
database.newItemStateDao().insert(starredIds.map { id ->
ItemState(
0,
read = true,
starred = true,
remoteId = id,
accountId = account.id
)
})
}
}
}

View File

@ -3,12 +3,23 @@ package com.readrops.db
import androidx.room.Database
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import com.readrops.db.dao.*
import com.readrops.db.dao.AccountDao
import com.readrops.db.dao.FeedDao
import com.readrops.db.dao.FolderDao
import com.readrops.db.dao.ItemDao
import com.readrops.db.dao.ItemStateChangeDao
import com.readrops.db.dao.ItemStateDao
import com.readrops.db.dao.newdao.NewAccountDao
import com.readrops.db.dao.newdao.NewFeedDao
import com.readrops.db.dao.newdao.NewFolderDao
import com.readrops.db.dao.newdao.NewItemDao
import com.readrops.db.entities.*
import com.readrops.db.dao.newdao.NewItemStateChangeDao
import com.readrops.db.dao.newdao.NewItemStateDao
import com.readrops.db.entities.Feed
import com.readrops.db.entities.Folder
import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemState
import com.readrops.db.entities.ItemStateChange
import com.readrops.db.entities.account.Account
import dev.matrix.roomigrant.GenerateRoomMigrations
@ -38,4 +49,8 @@ abstract class Database : RoomDatabase() {
abstract fun newAccountDao(): NewAccountDao
abstract fun newFolderDao(): NewFolderDao
abstract fun newItemStateDao(): NewItemStateDao
abstract fun newItemStateChangeDao(): NewItemStateChangeDao
}

View File

@ -0,0 +1,105 @@
package com.readrops.db.dao.newdao
import androidx.room.Dao
import androidx.room.Query
import com.readrops.db.entities.Item
import com.readrops.db.entities.ItemStateChange
import com.readrops.db.pojo.ItemReadStarState
@Dao
interface NewItemStateChangeDao: NewBaseDao<ItemStateChange> {
@Query("Delete From ItemStateChange Where account_id = :accountId")
suspend fun resetStateChanges(accountId: Int)
@Query("Select case When ItemState.remote_id is NULL Or ItemState.read = 1 Then 1 else 0 End read, " +
"case When ItemState.remote_id is NULL Or ItemState.starred = 1 Then 1 else 0 End starred," +
"ItemStateChange.read_change, ItemStateChange.star_change, Item.remoteId " +
"From ItemStateChange Inner Join Item On ItemStateChange.id = Item.id " +
"Left Join ItemState On ItemState.remote_id = Item.remoteId Where ItemStateChange.account_id = :accountId")
suspend fun getItemStateChanges(accountId: Int): List<ItemReadStarState>
@Query("Select Item.read, Item.starred," +
"ItemStateChange.read_change, ItemStateChange.star_change, Item.remoteId " +
"From ItemStateChange Inner Join Item On ItemStateChange.id = Item.id " +
"Where ItemStateChange.account_id = :accountId")
suspend fun getNextcloudNewsStateChanges(accountId: Int): List<ItemReadStarState>
@Query("Select Case When :itemId In (Select id From ItemStateChange Where read_change = 1) Then 1 Else 0 End")
suspend fun readStateChangeExists(itemId: Int): Boolean
@Query("Select Case When :itemId In (Select id From ItemStateChange Where star_change = 1) Then 1 Else 0 End")
suspend fun starStateChangeExists(itemId: Int): Boolean
suspend fun upsertItemReadStateChange(item: Item, accountId: Int, useSeparateState: Boolean) {
if (itemStateChangeExists(item.id, accountId)) {
val oldItemReadState = if (useSeparateState)
getItemReadState(item.remoteId!!, accountId)
else
getStandardItemReadState(item.remoteId!!, accountId)
val readChange = item.isRead != oldItemReadState
if (readChange) {
val oldItemStateChange = selectItemStateChange(item.id)
val newReadChange = !oldItemStateChange.readChange
if (!newReadChange && !oldItemStateChange.starChange) {
delete(oldItemStateChange)
} else {
updateItemReadStateChange(newReadChange, oldItemStateChange.id)
}
}
} else {
insert(ItemStateChange(id = item.id, readChange = true, accountId = accountId))
}
}
suspend fun upsertItemStarStateChange(item: Item, accountId: Int, useSeparateState: Boolean) {
if (itemStateChangeExists(item.id, accountId)) {
val oldItemStarState = if (useSeparateState)
getItemStarState(item.remoteId!!, accountId)
else
getStandardItemStarState(item.remoteId!!, accountId)
val starChange = item.isStarred != oldItemStarState
if (starChange) {
val oldItemStateChange = selectItemStateChange(item.id)
val newStarChange = !oldItemStateChange.starChange
if (!newStarChange && !oldItemStateChange.readChange) {
delete(oldItemStateChange)
} else {
updateItemStarStateChange(newStarChange, oldItemStateChange.id)
}
}
} else {
insert(ItemStateChange(id = item.id, starChange = true, accountId = accountId))
}
}
@Query("Select * From ItemStateChange Where id = :id")
fun selectItemStateChange(id: Int): ItemStateChange
@Query("Select case When Exists (Select id, account_id From ItemStateChange Where id = :id And account_id = :accountId) Then 1 else 0 End")
fun itemStateChangeExists(id: Int, accountId: Int): Boolean
@Query("Select read From ItemState Where remote_id = :remoteId And account_id = :accountId")
fun getItemReadState(remoteId: String, accountId: Int): Boolean
@Query("Select read From Item Inner Join Feed On Item.feed_id = Feed.id Where Item.remoteId = :remoteId And account_id = :accountId")
fun getStandardItemReadState(remoteId: String, accountId: Int): Boolean
@Query("Select starred From ItemState Where remote_id = :remoteId And account_id = :accountId")
fun getItemStarState(remoteId: String, accountId: Int): Boolean
@Query("Select starred From Item Inner Join Feed On Item.feed_id = Feed.id Where Item.remoteId = :remoteId And account_id = :accountId")
fun getStandardItemStarState(remoteId: String, accountId: Int): Boolean
@Query("Update ItemStateChange set read_change = :readChange Where id = :id")
fun updateItemReadStateChange(readChange: Boolean, id: Int)
@Query("Update ItemStateChange set star_change = :starChange Where id = :id")
fun updateItemStarStateChange(starChange: Boolean, id: Int)
}

View File

@ -0,0 +1,37 @@
package com.readrops.db.dao.newdao
import androidx.room.Dao
import androidx.room.Query
import com.readrops.db.entities.ItemState
@Dao
interface NewItemStateDao : NewBaseDao<ItemState> {
@Query("Delete From ItemState Where account_id = :accountId")
suspend fun deleteItemStates(accountId: Int)
@Query("Update ItemState set read = :read Where remote_id = :remoteId And account_id = :accountId")
suspend fun updateItemReadState(read: Boolean, remoteId: String, accountId: Int)
@Query("Update ItemState set starred = :star Where remote_id = :remoteId And account_id = :accountId")
suspend fun updateItemStarState(star: Boolean, remoteId: String, accountId: Int)
@Query("Select case When Exists (Select remote_id, account_id From ItemState Where remote_id = :remoteId And account_id = :accountId) Then 1 else 0 End")
suspend fun itemStateExists(remoteId: String, accountId: Int): Boolean
suspend fun upsertItemReadState(itemState: ItemState) {
if (itemStateExists(itemState.remoteId, itemState.accountId)) {
updateItemReadState(itemState.read, itemState.remoteId, itemState.accountId)
} else {
insert(itemState)
}
}
suspend fun upsertItemStarState(itemState: ItemState) {
if (itemStateExists(itemState.remoteId, itemState.accountId)) {
updateItemStarState(itemState.starred, itemState.remoteId, itemState.accountId)
} else {
insert(itemState)
}
}
}