Improve coroutines
This commit is contained in:
parent
435eb67c55
commit
77974c1d8b
|
@ -58,7 +58,7 @@ class App : Application(), Configuration.Provider {
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
applicationScope.launch {
|
applicationScope.launch(Dispatchers.IO) {
|
||||||
accountInit()
|
accountInit()
|
||||||
workerInit()
|
workerInit()
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ class Filter(
|
||||||
companion object {
|
companion object {
|
||||||
val Starred = Filter(
|
val Starred = Filter(
|
||||||
index = 0,
|
index = 0,
|
||||||
important = 13,
|
important = 666,
|
||||||
icon = Icons.Rounded.StarOutline,
|
icon = Icons.Rounded.StarOutline,
|
||||||
filledIcon = Icons.Rounded.Star,
|
filledIcon = Icons.Rounded.Star,
|
||||||
)
|
)
|
||||||
|
|
|
@ -10,7 +10,6 @@ import dagger.assisted.AssistedInject
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import me.ash.reader.currentAccountId
|
import me.ash.reader.currentAccountId
|
||||||
import me.ash.reader.data.account.AccountDao
|
import me.ash.reader.data.account.AccountDao
|
||||||
import me.ash.reader.data.article.Article
|
import me.ash.reader.data.article.Article
|
||||||
|
@ -104,24 +103,22 @@ abstract class AbstractRssRepository constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun pullImportant(
|
fun pullImportant(
|
||||||
isStarred: Boolean = false,
|
isStarred: Boolean = false,
|
||||||
isUnread: Boolean = false,
|
isUnread: Boolean = false,
|
||||||
): Flow<List<ImportantCount>> {
|
): Flow<List<ImportantCount>> {
|
||||||
return withContext(Dispatchers.IO) {
|
|
||||||
Log.i("RLog", "thread:pullImportant ${Thread.currentThread().name}")
|
Log.i("RLog", "thread:pullImportant ${Thread.currentThread().name}")
|
||||||
val accountId = context.currentAccountId
|
val accountId = context.currentAccountId
|
||||||
Log.i(
|
Log.i(
|
||||||
"RLog",
|
"RLog",
|
||||||
"pullImportant: accountId: ${accountId}, isStarred: ${isStarred}, isUnread: ${isUnread}"
|
"pullImportant: accountId: ${accountId}, isStarred: ${isStarred}, isUnread: ${isUnread}"
|
||||||
)
|
)
|
||||||
when {
|
return when {
|
||||||
isStarred -> articleDao
|
isStarred -> articleDao
|
||||||
.queryImportantCountWhenIsStarred(accountId, isStarred)
|
.queryImportantCountWhenIsStarred(accountId, isStarred)
|
||||||
isUnread -> articleDao
|
isUnread -> articleDao
|
||||||
.queryImportantCountWhenIsUnread(accountId, isUnread)
|
.queryImportantCountWhenIsUnread(accountId, isUnread)
|
||||||
else -> articleDao.queryImportantCountWhenIsAll(accountId)
|
else -> articleDao.queryImportantCountWhenIsAll(accountId)
|
||||||
}
|
|
||||||
}.flowOn(Dispatchers.IO)
|
}.flowOn(Dispatchers.IO)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,11 +151,9 @@ abstract class AbstractRssRepository constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun deleteFeed(feed: Feed) {
|
suspend fun deleteFeed(feed: Feed) {
|
||||||
withContext(Dispatchers.IO) {
|
|
||||||
articleDao.deleteByFeedId(context.currentAccountId, feed.id)
|
articleDao.deleteByFeedId(context.currentAccountId, feed.id)
|
||||||
feedDao.delete(feed)
|
feedDao.delete(feed)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val mutex = Mutex()
|
val mutex = Mutex()
|
||||||
|
|
|
@ -17,7 +17,9 @@ import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import me.ash.reader.*
|
import me.ash.reader.MainActivity
|
||||||
|
import me.ash.reader.R
|
||||||
|
import me.ash.reader.currentAccountId
|
||||||
import me.ash.reader.data.account.AccountDao
|
import me.ash.reader.data.account.AccountDao
|
||||||
import me.ash.reader.data.article.Article
|
import me.ash.reader.data.article.Article
|
||||||
import me.ash.reader.data.article.ArticleDao
|
import me.ash.reader.data.article.ArticleDao
|
||||||
|
@ -89,25 +91,28 @@ class LocalRssRepository @Inject constructor(
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
val preTime = System.currentTimeMillis()
|
val preTime = System.currentTimeMillis()
|
||||||
val accountId = context.currentAccountId
|
val accountId = context.currentAccountId
|
||||||
val feeds = async { feedDao.queryAll(accountId) }
|
val articles = mutableListOf<Article>()
|
||||||
val articles = feeds.await().also { feed ->
|
feedDao.queryAll(accountId).also { feed ->
|
||||||
updateSyncState {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
feedCount = feed.size,
|
feedCount = feed.size,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Log.i("RLog", "thread:sync ${Thread.currentThread().name}")
|
|
||||||
}.map { feed ->
|
}.map { feed ->
|
||||||
async {
|
async {
|
||||||
val articles = syncFeed(accountId, feed)
|
syncFeed(accountId, feed)
|
||||||
articles
|
|
||||||
}
|
}
|
||||||
|
}.awaitAll().forEach {
|
||||||
|
if (it.isNotify) {
|
||||||
|
notify(it.articles)
|
||||||
|
}
|
||||||
|
articles.addAll(it.articles)
|
||||||
}
|
}
|
||||||
|
|
||||||
articles.awaitAll().sumOf { it.size }.let { count ->
|
articleDao.insertList(articles)
|
||||||
Log.i(
|
Log.i(
|
||||||
"RlOG",
|
"RlOG",
|
||||||
"[${count}] onCompletion: ${System.currentTimeMillis() - preTime}"
|
"onCompletion: ${System.currentTimeMillis() - preTime}"
|
||||||
)
|
)
|
||||||
accountDao.queryById(accountId)?.let { account ->
|
accountDao.queryById(accountId)?.let { account ->
|
||||||
accountDao.update(
|
accountDao.update(
|
||||||
|
@ -126,12 +131,16 @@ class LocalRssRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
data class ArticleNotify(
|
||||||
|
val articles: List<Article>,
|
||||||
|
val isNotify: Boolean,
|
||||||
|
)
|
||||||
|
|
||||||
private suspend fun syncFeed(
|
private suspend fun syncFeed(
|
||||||
accountId: Int,
|
accountId: Int,
|
||||||
feed: Feed
|
feed: Feed
|
||||||
): List<Article> {
|
): ArticleNotify {
|
||||||
val latest = articleDao.queryLatestByFeedId(accountId, feed.id)
|
val latest = articleDao.queryLatestByFeedId(accountId, feed.id)
|
||||||
val articles = rssHelper.queryRssXml(
|
val articles = rssHelper.queryRssXml(
|
||||||
rssNetworkDataSource,
|
rssNetworkDataSource,
|
||||||
|
@ -143,21 +152,16 @@ class LocalRssRepository @Inject constructor(
|
||||||
rssHelper.queryRssIcon(feedDao, feed, it.first().link)
|
rssHelper.queryRssIcon(feedDao, feed, it.first().link)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.i("RLog", "thread:syncFeed ${Thread.currentThread().name}")
|
|
||||||
updateSyncState {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
syncedCount = it.syncedCount + 1,
|
syncedCount = it.syncedCount + 1,
|
||||||
currentFeedName = feed.name
|
currentFeedName = feed.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (articles.isNotEmpty()) {
|
return ArticleNotify(
|
||||||
articleDao.insertList(articles)
|
articles = articles,
|
||||||
if (feed.isNotification) {
|
isNotify = articles.isNotEmpty() && feed.isNotification
|
||||||
notify(articles)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
return articles
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun notify(
|
private fun notify(
|
||||||
|
|
|
@ -1,17 +1,14 @@
|
||||||
package me.ash.reader.ui.page.home
|
package me.ash.reader.ui.page.home
|
||||||
|
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
import com.google.accompanist.pager.PagerState
|
import com.google.accompanist.pager.PagerState
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import me.ash.reader.data.constant.Filter
|
import me.ash.reader.data.constant.Filter
|
||||||
import me.ash.reader.data.feed.Feed
|
import me.ash.reader.data.feed.Feed
|
||||||
import me.ash.reader.data.group.Group
|
import me.ash.reader.data.group.Group
|
||||||
|
@ -36,7 +33,7 @@ class HomeViewModel @Inject constructor(
|
||||||
|
|
||||||
fun dispatch(action: HomeViewAction) {
|
fun dispatch(action: HomeViewAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is HomeViewAction.Sync -> sync(action.callback)
|
is HomeViewAction.Sync -> sync()
|
||||||
is HomeViewAction.ChangeFilter -> changeFilter(action.filterState)
|
is HomeViewAction.ChangeFilter -> changeFilter(action.filterState)
|
||||||
is HomeViewAction.ScrollToPage -> scrollToPage(
|
is HomeViewAction.ScrollToPage -> scrollToPage(
|
||||||
action.scope,
|
action.scope,
|
||||||
|
@ -46,11 +43,8 @@ class HomeViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun sync(callback: () -> Unit = {}) {
|
private fun sync() {
|
||||||
viewModelScope.launch {
|
|
||||||
rssRepository.get().doSync()
|
rssRepository.get().doSync()
|
||||||
callback()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeFilter(filterState: FilterState) {
|
private fun changeFilter(filterState: FilterState) {
|
||||||
|
@ -80,9 +74,7 @@ data class HomeViewState(
|
||||||
)
|
)
|
||||||
|
|
||||||
sealed class HomeViewAction {
|
sealed class HomeViewAction {
|
||||||
data class Sync(
|
object Sync : HomeViewAction()
|
||||||
val callback: () -> Unit = {},
|
|
||||||
) : HomeViewAction()
|
|
||||||
|
|
||||||
data class ChangeFilter(
|
data class ChangeFilter(
|
||||||
val filterState: FilterState
|
val filterState: FilterState
|
||||||
|
|
|
@ -49,7 +49,7 @@ fun DeleteFeedDialog(
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
viewModel.dispatch(FeedOptionViewAction.Delete(){
|
viewModel.dispatch(FeedOptionViewAction.Delete {
|
||||||
viewModel.dispatch(FeedOptionViewAction.HideDeleteDialog)
|
viewModel.dispatch(FeedOptionViewAction.HideDeleteDialog)
|
||||||
viewModel.dispatch(FeedOptionViewAction.Hide(scope))
|
viewModel.dispatch(FeedOptionViewAction.Hide(scope))
|
||||||
Toast.makeText(context, deletedTip, Toast.LENGTH_SHORT).show()
|
Toast.makeText(context, deletedTip, Toast.LENGTH_SHORT).show()
|
||||||
|
|
|
@ -8,11 +8,13 @@ import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
import kotlinx.coroutines.flow.update
|
import kotlinx.coroutines.flow.update
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
import kotlinx.coroutines.withContext
|
||||||
import me.ash.reader.data.feed.Feed
|
import me.ash.reader.data.feed.Feed
|
||||||
import me.ash.reader.data.group.Group
|
import me.ash.reader.data.group.Group
|
||||||
import me.ash.reader.data.repository.RssRepository
|
import me.ash.reader.data.repository.RssRepository
|
||||||
|
@ -30,7 +32,7 @@ class FeedOptionViewModel @Inject constructor(
|
||||||
val viewState: StateFlow<FeedOptionViewState> = _viewState.asStateFlow()
|
val viewState: StateFlow<FeedOptionViewState> = _viewState.asStateFlow()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
rssRepository.get().pullGroups().collect { groups ->
|
rssRepository.get().pullGroups().collect { groups ->
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
@ -88,7 +90,7 @@ class FeedOptionViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun selectedGroup(groupId: String) {
|
private fun selectedGroup(groupId: String) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.value.feed?.let {
|
_viewState.value.feed?.let {
|
||||||
rssRepository.get().updateFeed(
|
rssRepository.get().updateFeed(
|
||||||
it.copy(
|
it.copy(
|
||||||
|
@ -109,7 +111,7 @@ class FeedOptionViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeParseFullContentPreset() {
|
private fun changeParseFullContentPreset() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.value.feed?.let {
|
_viewState.value.feed?.let {
|
||||||
rssRepository.get().updateFeed(
|
rssRepository.get().updateFeed(
|
||||||
it.copy(
|
it.copy(
|
||||||
|
@ -122,7 +124,7 @@ class FeedOptionViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun changeAllowNotificationPreset() {
|
private fun changeAllowNotificationPreset() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.value.feed?.let {
|
_viewState.value.feed?.let {
|
||||||
rssRepository.get().updateFeed(
|
rssRepository.get().updateFeed(
|
||||||
it.copy(
|
it.copy(
|
||||||
|
@ -136,13 +138,14 @@ class FeedOptionViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun delete(callback: () -> Unit = {}) {
|
private fun delete(callback: () -> Unit = {}) {
|
||||||
_viewState.value.feed?.let {
|
_viewState.value.feed?.let {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
rssRepository.get().deleteFeed(it)
|
rssRepository.get().deleteFeed(it)
|
||||||
}.invokeOnCompletion {
|
withContext(Dispatchers.Main) {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun hideDeleteDialog() {
|
private fun hideDeleteDialog() {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
|
@ -201,6 +204,6 @@ sealed class FeedOptionViewAction {
|
||||||
val callback: () -> Unit = {}
|
val callback: () -> Unit = {}
|
||||||
) : FeedOptionViewAction()
|
) : FeedOptionViewAction()
|
||||||
|
|
||||||
object ShowDeleteDialog: FeedOptionViewAction()
|
object ShowDeleteDialog : FeedOptionViewAction()
|
||||||
object HideDeleteDialog: FeedOptionViewAction()
|
object HideDeleteDialog : FeedOptionViewAction()
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ fun FeedsPage(
|
||||||
)
|
)
|
||||||
|
|
||||||
LaunchedEffect(Unit) {
|
LaunchedEffect(Unit) {
|
||||||
viewModel.dispatch(FeedsViewAction.FetchAccount())
|
viewModel.dispatch(FeedsViewAction.FetchAccount)
|
||||||
}
|
}
|
||||||
|
|
||||||
LaunchedEffect(homeViewModel.filterState) {
|
LaunchedEffect(homeViewModel.filterState) {
|
||||||
|
@ -89,7 +89,7 @@ fun FeedsPage(
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = {
|
IconButton(onClick = {
|
||||||
if (syncState.isSyncing) return@IconButton
|
if (syncState.isSyncing) return@IconButton
|
||||||
homeViewModel.dispatch(HomeViewAction.Sync())
|
homeViewModel.dispatch(HomeViewAction.Sync)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
modifier = Modifier.rotate(if (syncState.isSyncing) angle else 0f),
|
modifier = Modifier.rotate(if (syncState.isSyncing) angle else 0f),
|
||||||
|
@ -135,7 +135,7 @@ fun FeedsPage(
|
||||||
Banner(
|
Banner(
|
||||||
title = filterState.filter.getName(),
|
title = filterState.filter.getName(),
|
||||||
desc = filterState.filter.getDesc(),
|
desc = filterState.filter.getDesc(),
|
||||||
icon = viewState.filter.icon,
|
icon = filterState.filter.icon,
|
||||||
action = {
|
action = {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Outlined.KeyboardArrowRight,
|
imageVector = Icons.Outlined.KeyboardArrowRight,
|
||||||
|
|
|
@ -29,33 +29,32 @@ class FeedsViewModel @Inject constructor(
|
||||||
|
|
||||||
fun dispatch(action: FeedsViewAction) {
|
fun dispatch(action: FeedsViewAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
is FeedsViewAction.FetchAccount -> fetchAccount(action.callback)
|
is FeedsViewAction.FetchAccount -> fetchAccount()
|
||||||
is FeedsViewAction.FetchData -> fetchData(action.filterState)
|
is FeedsViewAction.FetchData -> fetchData(action.filterState)
|
||||||
is FeedsViewAction.AddFromFile -> addFromFile(action.inputStream)
|
is FeedsViewAction.AddFromFile -> addFromFile(action.inputStream)
|
||||||
is FeedsViewAction.ScrollToItem -> scrollToItem(action.index)
|
is FeedsViewAction.ScrollToItem -> scrollToItem(action.index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchAccount(callback: () -> Unit = {}) {
|
private fun fetchAccount() {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
account = accountRepository.getCurrentAccount()
|
account = accountRepository.getCurrentAccount()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
callback()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun addFromFile(inputStream: InputStream) {
|
private fun addFromFile(inputStream: InputStream) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
opmlRepository.saveToDatabase(inputStream)
|
opmlRepository.saveToDatabase(inputStream)
|
||||||
rssRepository.get().doSync()
|
rssRepository.get().doSync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchData(filterState: FilterState) {
|
private fun fetchData(filterState: FilterState) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
pullFeeds(
|
pullFeeds(
|
||||||
isStarred = filterState.filter.isStarred(),
|
isStarred = filterState.filter.isStarred(),
|
||||||
isUnread = filterState.filter.isUnread(),
|
isUnread = filterState.filter.isUnread(),
|
||||||
|
@ -144,9 +143,7 @@ sealed class FeedsViewAction {
|
||||||
val filterState: FilterState,
|
val filterState: FilterState,
|
||||||
) : FeedsViewAction()
|
) : FeedsViewAction()
|
||||||
|
|
||||||
data class FetchAccount(
|
object FetchAccount: FeedsViewAction()
|
||||||
val callback: () -> Unit = {},
|
|
||||||
) : FeedsViewAction()
|
|
||||||
|
|
||||||
data class AddFromFile(
|
data class AddFromFile(
|
||||||
val inputStream: InputStream
|
val inputStream: InputStream
|
||||||
|
|
|
@ -5,11 +5,8 @@ import androidx.lifecycle.viewModelScope
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
import com.google.accompanist.pager.PagerState
|
import com.google.accompanist.pager.PagerState
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.*
|
||||||
import kotlinx.coroutines.Job
|
|
||||||
import kotlinx.coroutines.async
|
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import me.ash.reader.R
|
import me.ash.reader.R
|
||||||
import me.ash.reader.data.article.Article
|
import me.ash.reader.data.article.Article
|
||||||
import me.ash.reader.data.feed.Feed
|
import me.ash.reader.data.feed.Feed
|
||||||
|
@ -73,7 +70,7 @@ class SubscribeViewModel @Inject constructor(
|
||||||
private fun subscribe() {
|
private fun subscribe() {
|
||||||
val feed = _viewState.value.feed ?: return
|
val feed = _viewState.value.feed ?: return
|
||||||
val articles = _viewState.value.articles
|
val articles = _viewState.value.articles
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
val groupId = async {
|
val groupId = async {
|
||||||
if (
|
if (
|
||||||
_viewState.value.newGroupSelected &&
|
_viewState.value.newGroupSelected &&
|
||||||
|
@ -129,7 +126,7 @@ class SubscribeViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun search(scope: CoroutineScope) {
|
private fun search(scope: CoroutineScope) {
|
||||||
searchJob?.cancel()
|
searchJob?.cancel()
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
try {
|
try {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
|
|
|
@ -42,7 +42,7 @@ class FlowViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun fetchData(filterState: FilterState) {
|
private fun fetchData(filterState: FilterState) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch(Dispatchers.Default) {
|
||||||
rssRepository.get().pullImportant(filterState.filter.isStarred(), true)
|
rssRepository.get().pullImportant(filterState.filter.isStarred(), true)
|
||||||
.collect { importantList ->
|
.collect { importantList ->
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import androidx.compose.foundation.lazy.LazyListState
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
import kotlinx.coroutines.flow.asStateFlow
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
@ -65,46 +66,44 @@ class ReadViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun markUnread(isUnread: Boolean) {
|
private fun markUnread(isUnread: Boolean) {
|
||||||
_viewState.value.articleWithFeed?.let {
|
val articleWithFeed = _viewState.value.articleWithFeed ?: return
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
articleWithFeed = it.articleWithFeed?.copy(
|
articleWithFeed = articleWithFeed.copy(
|
||||||
article = it.articleWithFeed.article.copy(
|
article = articleWithFeed.article.copy(
|
||||||
isUnread = isUnread
|
isUnread = isUnread
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
viewModelScope.launch {
|
|
||||||
rssRepository.get().updateArticleInfo(
|
rssRepository.get().updateArticleInfo(
|
||||||
it.article.copy(
|
articleWithFeed.article.copy(
|
||||||
isUnread = isUnread
|
isUnread = isUnread
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun markStarred(isStarred: Boolean) {
|
private fun markStarred(isStarred: Boolean) {
|
||||||
_viewState.value.articleWithFeed?.let {
|
val articleWithFeed = _viewState.value.articleWithFeed ?: return
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
_viewState.update {
|
_viewState.update {
|
||||||
it.copy(
|
it.copy(
|
||||||
articleWithFeed = it.articleWithFeed?.copy(
|
articleWithFeed = articleWithFeed.copy(
|
||||||
article = it.articleWithFeed.article.copy(
|
article = articleWithFeed.article.copy(
|
||||||
isStarred = isStarred
|
isStarred = isStarred
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
viewModelScope.launch {
|
|
||||||
rssRepository.get().updateArticleInfo(
|
rssRepository.get().updateArticleInfo(
|
||||||
it.article.copy(
|
articleWithFeed.article.copy(
|
||||||
isStarred = isStarred
|
isStarred = isStarred
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private fun scrollToItem(index: Int) {
|
private fun scrollToItem(index: Int) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user