fix(greader): mark all as read (#582)

This commit is contained in:
Ash 2024-02-06 00:47:21 +08:00 committed by GitHub
parent f14aecb2a9
commit 9327a2734f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 144 additions and 65 deletions

View File

@ -286,11 +286,13 @@ interface ArticleDao {
before: Date,
)
@Transaction
@Query(
"""
UPDATE article SET isUnread = :isUnread
WHERE accountId = :accountId
AND date < :before
AND isUnread != :isUnread
"""
)
suspend fun markAllAsRead(
@ -299,6 +301,7 @@ interface ArticleDao {
before: Date,
)
@Transaction
@Query(
"""
UPDATE article SET isUnread = :isUnread
@ -307,6 +310,7 @@ interface ArticleDao {
WHERE groupId = :groupId
)
AND accountId = :accountId
AND isUnread != :isUnread
AND date < :before
"""
)
@ -317,11 +321,13 @@ interface ArticleDao {
before: Date,
)
@Transaction
@Query(
"""
UPDATE article SET isUnread = :isUnread
WHERE feedId = :feedId
AND accountId = :accountId
AND isUnread != :isUnread
AND date < :before
"""
)
@ -332,6 +338,7 @@ interface ArticleDao {
before: Date,
)
@Transaction
@Query(
"""
UPDATE article SET isUnread = :isUnread
@ -632,6 +639,17 @@ interface ArticleDao {
)
fun queryMetadataAll(accountId: Int): List<ArticleMeta>
@Transaction
@Query(
"""
SELECT id, isUnread, isStarred FROM article
WHERE accountId = :accountId
AND isUnread = :isUnread
ORDER BY date DESC
"""
)
fun queryMetadataAll(accountId: Int, isUnread: Boolean): List<ArticleMeta>
@Transaction
@Query(
"""
@ -648,11 +666,12 @@ interface ArticleDao {
"""
SELECT id, isUnread, isStarred FROM article
WHERE accountId = :accountId
AND feedId = :feedId
AND isUnread = :isUnread
AND date < :before
ORDER BY date DESC
"""
)
fun queryMetadataByFeedId(accountId: Int, feedId: String): List<ArticleMeta>
fun queryMetadataAll(accountId: Int, isUnread: Boolean, before: Date): List<ArticleMeta>
@Transaction
@Query(
@ -660,11 +679,24 @@ interface ArticleDao {
SELECT id, isUnread, isStarred FROM article
WHERE accountId = :accountId
AND feedId = :feedId
AND isUnread = :isUnread
ORDER BY date DESC
"""
)
fun queryMetadataByFeedId(accountId: Int, feedId: String, isUnread: Boolean): List<ArticleMeta>
@Transaction
@Query(
"""
SELECT id, isUnread, isStarred FROM article
WHERE accountId = :accountId
AND feedId = :feedId
AND isUnread = :isUnread
AND date < :before
ORDER BY date DESC
"""
)
fun queryMetadataByFeedId(accountId: Int, feedId: String, before: Date): List<ArticleMeta>
fun queryMetadataByFeedId(accountId: Int, feedId: String, isUnread: Boolean, before: Date): List<ArticleMeta>
@Transaction
@Query(
@ -675,10 +707,11 @@ interface ArticleDao {
LEFT JOIN `group` AS c ON c.id = b.groupId
WHERE c.id = :groupId
AND a.accountId = :accountId
AND a.isUnread = :isUnread
ORDER BY a.date DESC
"""
)
fun queryMetadataByGroupId(accountId: Int, groupId: String): List<ArticleMeta>
fun queryMetadataByGroupIdWhenIsUnread(accountId: Int, groupId: String, isUnread: Boolean): List<ArticleMeta>
@Transaction
@Query(
@ -689,11 +722,12 @@ interface ArticleDao {
LEFT JOIN `group` AS c ON c.id = b.groupId
WHERE c.id = :groupId
AND a.accountId = :accountId
AND a.isUnread = :isUnread
AND a.date < :before
ORDER BY a.date DESC
"""
)
fun queryMetadataByGroupId(accountId: Int, groupId: String, before: Date): List<ArticleMeta>
fun queryMetadataByGroupIdWhenIsUnread(accountId: Int, groupId: String, isUnread: Boolean, before: Date): List<ArticleMeta>
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insert(vararg article: Article)

View File

@ -140,7 +140,7 @@ abstract class AbstractRssRepository(
)
}
feedId != null && articleId == null -> {
feedId != null -> {
articleDao.markAllAsReadByFeedId(
accountId = accountId,
feedId = feedId,

View File

@ -184,16 +184,16 @@ class GoogleReaderRssService @Inject constructor(
}
/**
* This is a reference to Reeder's synchronization logic,
* This is improved from Reeder's synchronization strategy,
* which syncs well across multiple devices.
*
* 1. Fetch tags (not supported yet)
* 2. Fetch folder and subscription list
* 3. Fetch all unread item id list
* 4. Fetch all starred item id list
* 5. Fetch unread contents of items with differences
* 5. Fetch unread contents of items with differences (up to 10k items per sync process)
* 6. Fetch starred contents of items with differences
* 7. Fetch read contents of items with differences
* 7. Fetch read contents of items with differences (up to one month old)
* 8. Remove orphaned groups and feeds, after synchronizing the starred/un-starred
*
* The following link contains other great synchronization logic,
@ -277,16 +277,16 @@ class GoogleReaderRssService @Inject constructor(
googleReaderAPI.getUnreadItemIds(continuationId = it)
}.toSet()
Log.i("RLog", "sync unreadIds size: ${unreadIds.size}")
val toBeUnread = unreadIds - localUnreadIds
val toBeUnread = (unreadIds - localUnreadIds).run {
if (size > 10000) take(10000).toSet() else this
}
Log.i("RLog", "sync toBeUnread size: ${toBeUnread.size}")
if (toBeUnread.isNotEmpty()) {
toBeUnread.chunked(999).forEach {
articleDao.markAsReadByIdSet(
accountId = accountId,
ids = it.toSet(),
isUnread = true,
)
}
toBeUnread.takeIf { it.isNotEmpty() }?.chunked(500)?.forEach {
articleDao.markAsReadByIdSet(
accountId = accountId,
ids = it.toSet(),
isUnread = true,
)
}
// 4. Fetch all starred item id list
@ -296,17 +296,15 @@ class GoogleReaderRssService @Inject constructor(
Log.i("RLog", "sync starredIds size: ${starredIds.size}")
val toBeStarred = starredIds - localStarredIds
Log.i("RLog", "sync toBeStarred size: ${toBeStarred.size}")
if (toBeStarred.isNotEmpty()) {
toBeStarred.chunked(999).forEach {
articleDao.markAsStarredByIdSet(
accountId = accountId,
ids = it.toSet(),
isStarred = true,
)
}
toBeStarred.takeIf { it.isNotEmpty() }?.chunked(500)?.forEach {
articleDao.markAsStarredByIdSet(
accountId = accountId,
ids = it.toSet(),
isStarred = true,
)
}
// 5. Fetch unread contents of items with differences
// 5. Fetch unread contents of items with differences (up to 10k items per sync process)
fetchItemsContents(
itemIds = toBeUnread,
googleReaderAPI = googleReaderAPI,
@ -328,14 +326,14 @@ class GoogleReaderRssService @Inject constructor(
preDate = preDate,
)
// 7. Fetch read contents of items with differences
// 7. Fetch read contents of items with differences (up to one month old)
val readIds = fetchItemIdsAndContinue {
googleReaderAPI.getReadItemIds(since = lastMonthAt, continuationId = it)
}.toSet()
Log.i("RLog", "sync readIds size: ${readIds.size}")
val localReadIds = articleDao.queryMetadataAll(accountId).filter { !it.isUnread }
.map { it.id.dollarLast() }.toSet()
val toBeRead = readIds - unreadIds - localReadIds
var toBeRead = readIds - unreadIds - localReadIds
Log.i("RLog", "sync toBeRead size: ${toBeRead.size}")
if (toBeRead.isNotEmpty()) {
fetchItemsContents(
@ -348,6 +346,16 @@ class GoogleReaderRssService @Inject constructor(
preDate = preDate,
)
}
// Sync the read status of articles prior to last month
toBeRead = localUnreadIds - unreadIds
Log.i("RLog", "sync toBeRead (last month) size: ${toBeRead.size}")
toBeRead.takeIf { it.isNotEmpty() }?.chunked(500)?.forEach {
articleDao.markAsReadByIdSet(
accountId = accountId,
ids = it.toSet(),
isUnread = false,
)
}
// 8. Remove orphaned groups and feeds, after synchronizing the starred/un-starred
groupDao.queryAll(accountId)
@ -428,23 +436,25 @@ class GoogleReaderRssService @Inject constructor(
before: Date?,
isUnread: Boolean,
) {
super.markAsRead(groupId, feedId, articleId, before, isUnread)
val accountId = context.currentAccountId
val googleReaderAPI = getGoogleReaderAPI()
val markList: List<String> = when {
groupId != null -> {
if (before == null) {
articleDao.queryMetadataByGroupId(accountId, groupId)
articleDao.queryMetadataByGroupIdWhenIsUnread(accountId, groupId, !isUnread)
} else {
articleDao.queryMetadataByGroupId(accountId, groupId, before)
articleDao.queryMetadataByGroupIdWhenIsUnread(accountId,
groupId,
!isUnread,
before)
}.map { it.id.dollarLast() }
}
feedId != null -> {
if (before == null) {
articleDao.queryMetadataByFeedId(accountId, feedId)
articleDao.queryMetadataByFeedId(accountId, feedId, !isUnread)
} else {
articleDao.queryMetadataByFeedId(accountId, feedId, before)
articleDao.queryMetadataByFeedId(accountId, feedId, !isUnread, before)
}.map { it.id.dollarLast() }
}
@ -454,17 +464,21 @@ class GoogleReaderRssService @Inject constructor(
else -> {
if (before == null) {
articleDao.queryMetadataAll(accountId)
articleDao.queryMetadataAll(accountId, !isUnread)
} else {
articleDao.queryMetadataAll(accountId, before)
articleDao.queryMetadataAll(accountId, !isUnread, before)
}.map { it.id.dollarLast() }
}
}
if (markList.isNotEmpty()) googleReaderAPI.editTag(
itemIds = markList,
mark = if (!isUnread) GoogleReaderAPI.Stream.READ.tag else null,
unmark = if (isUnread) GoogleReaderAPI.Stream.READ.tag else null,
)
super.markAsRead(groupId, feedId, articleId, before, isUnread)
markList.takeIf { it.isNotEmpty() }?.chunked(500)?.forEach {
Log.d("RLog", "sync markAsRead: ${it.size} num")
googleReaderAPI.editTag(
itemIds = it,
mark = if (!isUnread) GoogleReaderAPI.Stream.READ.tag else null,
unmark = if (isUnread) GoogleReaderAPI.Stream.READ.tag else null,
)
}
}
override suspend fun markAsStarred(articleId: String, isStarred: Boolean) {

View File

@ -256,7 +256,7 @@ class GoogleReaderAPI private constructor(
retryablePostRequest<String>(
query = "reader/api/0/edit-tag",
form = mutableListOf<Pair<String, String>>().apply {
itemIds.forEach { add(Pair("i", it.ofItemIdToStreamId())) }
itemIds.forEach { add(Pair("i", it.ofItemIdToHexId())) }
mark?.let { add(Pair("a", mark)) }
unmark?.let { add(Pair("r", unmark)) }
}

View File

@ -1,7 +1,6 @@
package me.ash.reader.ui.page.home
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
@ -10,7 +9,13 @@ import androidx.work.WorkManager
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import me.ash.reader.domain.model.article.ArticleFlowItem
import me.ash.reader.domain.model.article.mapPagingFlowItem
@ -18,8 +23,8 @@ import me.ash.reader.domain.model.feed.Feed
import me.ash.reader.domain.model.general.Filter
import me.ash.reader.domain.model.group.Group
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.android.AndroidStringsHelper
import me.ash.reader.domain.service.SyncWorker
import me.ash.reader.infrastructure.android.AndroidStringsHelper
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.IODispatcher
import javax.inject.Inject
@ -44,7 +49,7 @@ class HomeViewModel @Inject constructor(
val syncWorkLiveData = workManager.getWorkInfosByTagLiveData(SyncWorker.WORK_NAME)
fun sync() {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
rssService.get().doSync()
}
}

View File

@ -17,6 +17,7 @@ import kotlinx.coroutines.withContext
import me.ash.reader.domain.model.feed.Feed
import me.ash.reader.domain.model.group.Group
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.di.MainDispatcher
import javax.inject.Inject
@ -29,6 +30,8 @@ class FeedOptionViewModel @Inject constructor(
private val mainDispatcher: CoroutineDispatcher,
@IODispatcher
private val ioDispatcher: CoroutineDispatcher,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _feedOptionUiState = MutableStateFlow(FeedOptionUiState())
@ -87,7 +90,7 @@ class FeedOptionViewModel @Inject constructor(
fun addNewGroup() {
if (_feedOptionUiState.value.newGroupContent.isNotBlank()) {
viewModelScope.launch {
applicationScope.launch {
selectedGroup(rssService.get().addGroup(
destFeed = _feedOptionUiState.value.feed,
newGroupName = _feedOptionUiState.value.newGroupContent))
@ -97,7 +100,7 @@ class FeedOptionViewModel @Inject constructor(
}
fun selectedGroup(groupId: String) {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
_feedOptionUiState.value.feed?.let {
rssService.get().moveFeed(
originGroupId = it.groupId,
@ -128,7 +131,7 @@ class FeedOptionViewModel @Inject constructor(
fun delete(callback: () -> Unit = {}) {
_feedOptionUiState.value.feed?.let {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
rssService.get().deleteFeed(it)
withContext(mainDispatcher) {
callback()
@ -166,7 +169,7 @@ class FeedOptionViewModel @Inject constructor(
fun renameFeed() {
_feedOptionUiState.value.feed?.let {
viewModelScope.launch {
applicationScope.launch {
rssService.get().renameFeed(it.copy(name = _feedOptionUiState.value.newName))
_feedOptionUiState.update { it.copy(renameDialogVisible = false) }
}
@ -219,7 +222,7 @@ class FeedOptionViewModel @Inject constructor(
fun changeFeedUrl() {
_feedOptionUiState.value.feed?.let {
viewModelScope.launch {
applicationScope.launch {
rssService.get().changeFeedUrl(it.copy(url = _feedOptionUiState.value.newUrl))
_feedOptionUiState.update { it.copy(changeUrlDialogVisible = false) }
}

View File

@ -16,6 +16,7 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import me.ash.reader.domain.model.group.Group
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.di.MainDispatcher
import javax.inject.Inject
@ -28,6 +29,8 @@ class GroupOptionViewModel @Inject constructor(
private val mainDispatcher: CoroutineDispatcher,
@IODispatcher
private val ioDispatcher: CoroutineDispatcher,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _groupOptionUiState = MutableStateFlow(GroupOptionUiState())
@ -92,7 +95,7 @@ class GroupOptionViewModel @Inject constructor(
fun delete(callback: () -> Unit = {}) {
_groupOptionUiState.value.group?.let {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
rssService.get().deleteGroup(it)
withContext(mainDispatcher) {
callback()
@ -161,7 +164,7 @@ class GroupOptionViewModel @Inject constructor(
fun rename() {
_groupOptionUiState.value.group?.let {
viewModelScope.launch {
applicationScope.launch {
rssService.get().renameGroup(it.copy(name = _groupOptionUiState.value.newName))
_groupOptionUiState.update { it.copy(renameDialogVisible = false) }
}

View File

@ -5,14 +5,21 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.rometools.rome.feed.synd.SyndFeed
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import me.ash.reader.R
import me.ash.reader.domain.model.group.Group
import me.ash.reader.domain.service.OpmlService
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.android.AndroidStringsHelper
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.rss.RssHelper
import me.ash.reader.ui.ext.formatUrl
import java.io.InputStream
@ -24,6 +31,8 @@ class SubscribeViewModel @Inject constructor(
val rssService: RssService,
private val rssHelper: RssHelper,
private val androidStringsHelper: AndroidStringsHelper,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _subscribeUiState = MutableStateFlow(SubscribeUiState())
@ -48,7 +57,7 @@ class SubscribeViewModel @Inject constructor(
}
fun importFromInputStream(inputStream: InputStream) {
viewModelScope.launch {
applicationScope.launch {
try {
opmlService.saveToDatabase(inputStream)
rssService.get().doSync()
@ -64,7 +73,7 @@ class SubscribeViewModel @Inject constructor(
fun addNewGroup() {
if (_subscribeUiState.value.newGroupContent.isNotBlank()) {
viewModelScope.launch {
applicationScope.launch {
// TODO: How to add a single group without no feeds via Google Reader API?
selectedGroup(rssService.get().addGroup(null, _subscribeUiState.value.newGroupContent))
hideNewGroupDialog()
@ -141,7 +150,7 @@ class SubscribeViewModel @Inject constructor(
}
fun subscribe() {
viewModelScope.launch {
applicationScope.launch {
rssService.get().subscribe(
searchedFeed = _subscribeUiState.value.searchedFeed ?: return@launch,
feedLink = _subscribeUiState.value.linkContent,

View File

@ -2,15 +2,16 @@ package me.ash.reader.ui.page.home.flow
import androidx.compose.foundation.lazy.LazyListState
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import me.ash.reader.domain.model.general.MarkAsReadConditions
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.IODispatcher
import javax.inject.Inject
@ -19,13 +20,15 @@ class FlowViewModel @Inject constructor(
private val rssService: RssService,
@IODispatcher
private val ioDispatcher: CoroutineDispatcher,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _flowUiState = MutableStateFlow(FlowUiState())
val flowUiState: StateFlow<FlowUiState> = _flowUiState.asStateFlow()
fun sync() {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
rssService.get().doSync()
}
}
@ -36,7 +39,7 @@ class FlowViewModel @Inject constructor(
articleId: String?,
conditions: MarkAsReadConditions,
) {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
rssService.get().markAsRead(
groupId = groupId,
feedId = feedId,

View File

@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
import androidx.paging.ItemSnapshotList
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
@ -17,9 +18,10 @@ import me.ash.reader.domain.model.article.ArticleFlowItem
import me.ash.reader.domain.model.article.ArticleWithFeed
import me.ash.reader.domain.model.feed.Feed
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.rss.RssHelper
import java.util.*
import java.util.Date
import javax.inject.Inject
@HiltViewModel
@ -28,6 +30,8 @@ class ReadingViewModel @Inject constructor(
private val rssHelper: RssHelper,
@IODispatcher
private val ioDispatcher: CoroutineDispatcher,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _readingUiState = MutableStateFlow(ReadingUiState())
@ -110,7 +114,7 @@ class ReadingViewModel @Inject constructor(
fun updateReadStatus(isUnread: Boolean) {
currentArticle?.run {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
_readingUiState.update { it.copy(isUnread = isUnread) }
rssService.get().markAsRead(
groupId = null,
@ -128,7 +132,7 @@ class ReadingViewModel @Inject constructor(
fun markAsUnread() = updateReadStatus(isUnread = true)
fun updateStarredStatus(isStarred: Boolean) {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
_readingUiState.update { it.copy(isStarred = isStarred) }
currentArticle?.let {
rssService.get().markAsStarred(

View File

@ -5,6 +5,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
@ -18,6 +19,7 @@ import me.ash.reader.domain.model.account.Account
import me.ash.reader.domain.service.AccountService
import me.ash.reader.domain.service.OpmlService
import me.ash.reader.domain.service.RssService
import me.ash.reader.infrastructure.di.ApplicationScope
import me.ash.reader.infrastructure.di.DefaultDispatcher
import me.ash.reader.infrastructure.di.IODispatcher
import me.ash.reader.infrastructure.di.MainDispatcher
@ -34,6 +36,8 @@ class AccountViewModel @Inject constructor(
private val defaultDispatcher: CoroutineDispatcher,
@MainDispatcher
private val mainDispatcher: CoroutineDispatcher,
@ApplicationScope
private val applicationScope: CoroutineScope,
) : ViewModel() {
private val _accountUiState = MutableStateFlow(AccountUiState())
@ -48,7 +52,7 @@ class AccountViewModel @Inject constructor(
}
fun update(accountId: Int, block: Account.() -> Unit) {
viewModelScope.launch(ioDispatcher) {
applicationScope.launch(ioDispatcher) {
accountService.update(accountId, block)
rssService.get(accountId).clearAuthorization()
}
@ -101,7 +105,7 @@ class AccountViewModel @Inject constructor(
fun addAccount(account: Account, callback: (account: Account?, exception: Exception?) -> Unit) {
setLoading(true)
addAccountJob = viewModelScope.launch(ioDispatcher) {
addAccountJob = applicationScope.launch(ioDispatcher) {
val addAccount = accountService.addAccount(account)
try {
if (rssService.get(addAccount.type.id).validCredentials(account)) {