Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(greader): incrementally fetch the unread items by last sync time #569

Merged
merged 1 commit into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 44 additions & 2 deletions app/src/main/java/me/ash/reader/domain/repository/ArticleDao.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,59 @@
package me.ash.reader.domain.repository

import androidx.paging.PagingSource
import androidx.room.*
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.RewriteQueriesToDropUnusedColumns
import androidx.room.Transaction
import androidx.room.Update
import kotlinx.coroutines.flow.Flow
import me.ash.reader.domain.model.article.Article
import me.ash.reader.domain.model.article.ArticleMeta
import me.ash.reader.domain.model.article.ArticleWithFeed
import me.ash.reader.domain.model.feed.ImportantNum
import java.util.*
import java.util.Date

@Dao
interface ArticleDao {

@Transaction
@RewriteQueriesToDropUnusedColumns
@Query(
"""
SELECT count(1)
FROM article
WHERE feedId = :feedId
AND isStarred = :isStarred
AND accountId = :accountId
"""
)
fun countByFeedIdWhenIsStarred(
accountId: Int,
feedId: String,
isStarred: Boolean,
): Int

@Transaction
@RewriteQueriesToDropUnusedColumns
@Query(
"""
SELECT count(1)
FROM article AS a
LEFT JOIN feed AS b ON b.id = a.feedId
LEFT JOIN `group` AS c ON c.id = b.groupId
WHERE c.id = :groupId
AND a.isStarred = :isStarred
AND a.accountId = :accountId
"""
)
fun countByGroupIdWhenIsStarred(
accountId: Int,
groupId: String,
isStarred: Boolean,
): Int

@Transaction
@Query(
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ import me.ash.reader.infrastructure.rss.RssHelper
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.decodeHTML
import me.ash.reader.ui.ext.spacerDollar
import java.util.*
import java.util.Date
import java.util.UUID

abstract class AbstractRssRepository(
private val context: Context,
Expand Down Expand Up @@ -311,13 +312,24 @@ abstract class AbstractRssRepository(
feedDao.update(feed)
}

open suspend fun deleteGroup(group: Group) {
open suspend fun deleteGroup(group: Group, onlyDeleteNoStarred: Boolean? = false) {
val accountId = context.currentAccountId
if (onlyDeleteNoStarred == true
&& articleDao.countByGroupIdWhenIsStarred(accountId, group.id, true) > 0
) {
return
}
deleteArticles(group = group)
feedDao.deleteByGroupId(context.currentAccountId, group.id)
feedDao.deleteByGroupId(accountId, group.id)
groupDao.delete(group)
}

open suspend fun deleteFeed(feed: Feed) {
open suspend fun deleteFeed(feed: Feed, onlyDeleteNoStarred: Boolean? = false) {
if (onlyDeleteNoStarred == true
&& articleDao.countByFeedIdWhenIsStarred(context.currentAccountId, feed.id, true) > 0
) {
return
}
deleteArticles(feed = feed)
feedDao.delete(feed)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import me.ash.reader.domain.repository.AccountDao
import me.ash.reader.domain.repository.ArticleDao
import me.ash.reader.domain.repository.FeedDao
import me.ash.reader.domain.repository.GroupDao
import me.ash.reader.ui.ext.*
import me.ash.reader.ui.ext.DataStoreKeys
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.dataStore
import me.ash.reader.ui.ext.getDefaultGroupId
import me.ash.reader.ui.ext.put
import me.ash.reader.ui.ext.showToast
import javax.inject.Inject

class AccountService @Inject constructor(
Expand Down Expand Up @@ -72,6 +77,7 @@ class AccountService @Inject constructor(
Looper.loop()
return
}
rssService.get().cancelSync()
accountDao.queryById(accountId)?.let {
articleDao.deleteByAccountId(accountId)
feedDao.deleteByAccountId(accountId)
Expand Down
45 changes: 25 additions & 20 deletions app/src/main/java/me/ash/reader/domain/service/FeverRssService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,18 @@ import me.ash.reader.infrastructure.android.NotificationHelper
import me.ash.reader.infrastructure.di.DefaultDispatcher
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.di.MainDispatcher
import me.ash.reader.infrastructure.html.Readability
import me.ash.reader.infrastructure.rss.RssHelper
import me.ash.reader.infrastructure.rss.provider.fever.FeverAPI
import me.ash.reader.infrastructure.rss.provider.fever.FeverDTO
import me.ash.reader.ui.ext.*
import net.dankito.readability4j.extended.Readability4JExtended
import java.util.*
import me.ash.reader.ui.ext.currentAccountId
import me.ash.reader.ui.ext.decodeHTML
import me.ash.reader.ui.ext.dollarLast
import me.ash.reader.ui.ext.showToast
import me.ash.reader.ui.ext.spacerDollar
import java.util.Date
import javax.inject.Inject
import kotlin.collections.set

class FeverRssService @Inject constructor(
@ApplicationContext
Expand Down Expand Up @@ -96,11 +101,11 @@ class FeverRssService @Inject constructor(
throw Exception("Unsupported")
}

override suspend fun deleteGroup(group: Group) {
override suspend fun deleteGroup(group: Group, onlyDeleteNoStarred: Boolean?) {
throw Exception("Unsupported")
}

override suspend fun deleteFeed(feed: Feed) {
override suspend fun deleteFeed(feed: Feed, onlyDeleteNoStarred: Boolean?) {
throw Exception("Unsupported")
}

Expand Down Expand Up @@ -144,12 +149,6 @@ class FeverRssService @Inject constructor(
)
} ?: emptyList()
groupDao.insertOrUpdate(groups)
val groupIds = groups.map { it.id }
groupDao.queryAll(accountId).forEach {
if (!groupIds.contains(it.id)) {
super.deleteGroup(it)
}
}

// 2. Fetch the Fever feeds
val feedsBody = feverAPI.getFeeds()
Expand All @@ -161,11 +160,6 @@ class FeverRssService @Inject constructor(
}
}
}
feedDao.queryAll(accountId).forEach {
if (!feedsGroupsMap.contains(it.id.dollarLast())) {
super.deleteFeed(it)
}
}

// Fetch the Fever favicons
val faviconsById = feverAPI.getFavicons().favicons?.associateBy { it.id } ?: emptyMap()
Expand Down Expand Up @@ -201,10 +195,7 @@ class FeverRssService @Inject constructor(
title = it.title.decodeHTML() ?: context.getString(R.string.empty),
author = it.author,
rawDescription = it.html ?: "",
shortDescription = (Readability4JExtended("", it.html ?: "")
.parse().textContent ?: "")
.take(110)
.trim(),
shortDescription = Readability.parseToText(it.html, it.url).take(110),
fullContent = it.html,
img = rssHelper.findImg(it.html ?: ""),
link = it.url ?: "",
Expand Down Expand Up @@ -241,6 +232,20 @@ class FeverRssService @Inject constructor(
}
}

// Remove orphaned groups and feeds, after synchronizing the starred/un-starred
val groupIds = groups.map { it.id }
groupDao.queryAll(accountId).forEach {
if (!groupIds.contains(it.id)) {
super.deleteGroup(it, true)
}
}

feedDao.queryAll(accountId).forEach {
if (!feedsGroupsMap.contains(it.id.dollarLast())) {
super.deleteFeed(it, true)
}
}


Log.i("RLog", "onCompletion: ${System.currentTimeMillis() - preTime}")
accountDao.update(account.apply {
Expand Down
Loading
Loading