Fixed auto sync
This commit is contained in:
parent
582e0f8148
commit
c7c708d92a
|
@ -54,6 +54,7 @@ dependencies {
|
||||||
implementation("com.google.accompanist:accompanist-navigation-animation:0.24.3-alpha")
|
implementation("com.google.accompanist:accompanist-navigation-animation:0.24.3-alpha")
|
||||||
implementation "androidx.datastore:datastore-preferences:1.0.0"
|
implementation "androidx.datastore:datastore-preferences:1.0.0"
|
||||||
implementation "com.airbnb.android:lottie-compose:4.2.2"
|
implementation "com.airbnb.android:lottie-compose:4.2.2"
|
||||||
|
implementation "androidx.hilt:hilt-work:1.0.0"
|
||||||
implementation "androidx.work:work-runtime-ktx:2.8.0-alpha01"
|
implementation "androidx.work:work-runtime-ktx:2.8.0-alpha01"
|
||||||
implementation "net.dankito.readability4j:readability4j:1.0.8"
|
implementation "net.dankito.readability4j:readability4j:1.0.8"
|
||||||
implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
|
implementation "androidx.navigation:navigation-compose:2.5.0-alpha01"
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
package="me.ash.reader">
|
package="me.ash.reader">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
@ -23,6 +24,11 @@
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
<provider
|
||||||
|
android:name="androidx.startup.InitializationProvider"
|
||||||
|
android:authorities="${applicationId}.androidx-startup"
|
||||||
|
tools:node="remove">
|
||||||
|
</provider>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
|
@ -1,22 +1,32 @@
|
||||||
package me.ash.reader
|
package me.ash.reader
|
||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
|
import androidx.hilt.work.HiltWorkerFactory
|
||||||
|
import androidx.work.*
|
||||||
import dagger.hilt.android.HiltAndroidApp
|
import dagger.hilt.android.HiltAndroidApp
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.Dispatchers
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.data.repository.*
|
import me.ash.reader.data.repository.*
|
||||||
import me.ash.reader.data.source.OpmlLocalDataSource
|
import me.ash.reader.data.source.OpmlLocalDataSource
|
||||||
import me.ash.reader.data.source.ReaderDatabase
|
import me.ash.reader.data.source.ReaderDatabase
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
import me.ash.reader.data.source.RssNetworkDataSource
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@DelicateCoroutinesApi
|
@DelicateCoroutinesApi
|
||||||
@HiltAndroidApp
|
@HiltAndroidApp
|
||||||
class App : Application() {
|
class App : Application(), Configuration.Provider {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var readerDatabase: ReaderDatabase
|
lateinit var readerDatabase: ReaderDatabase
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var workerFactory: HiltWorkerFactory
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
lateinit var workManager: WorkManager
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var opmlLocalDataSource: OpmlLocalDataSource
|
lateinit var opmlLocalDataSource: OpmlLocalDataSource
|
||||||
|
|
||||||
|
@ -44,15 +54,43 @@ class App : Application() {
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var rssRepository: RssRepository
|
lateinit var rssRepository: RssRepository
|
||||||
|
|
||||||
|
private val applicationScope = CoroutineScope(Dispatchers.IO)
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
GlobalScope.launch {
|
applicationScope.launch {
|
||||||
|
accountInit()
|
||||||
|
workerInit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private suspend fun accountInit() {
|
||||||
if (accountRepository.isNoAccount()) {
|
if (accountRepository.isNoAccount()) {
|
||||||
val account = accountRepository.addDefaultAccount()
|
val account = accountRepository.addDefaultAccount()
|
||||||
applicationContext.dataStore.put(DataStoreKeys.CurrentAccountId, account.id!!)
|
applicationContext.dataStore.put(DataStoreKeys.CurrentAccountId, account.id!!)
|
||||||
applicationContext.dataStore.put(DataStoreKeys.CurrentAccountType, account.type)
|
applicationContext.dataStore.put(DataStoreKeys.CurrentAccountType, account.type)
|
||||||
}
|
}
|
||||||
rssRepository.get().doSync(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun workerInit() {
|
||||||
|
val repeatingRequest = PeriodicWorkRequestBuilder<SyncWorker>(
|
||||||
|
15, TimeUnit.MINUTES
|
||||||
|
).setConstraints(
|
||||||
|
Constraints.Builder()
|
||||||
|
.setRequiredNetworkType(NetworkType.CONNECTED)
|
||||||
|
.build()
|
||||||
|
).addTag(SyncWorker.WORK_NAME).build()
|
||||||
|
|
||||||
|
workManager.enqueueUniquePeriodicWork(
|
||||||
|
SyncWorker.WORK_NAME,
|
||||||
|
ExistingPeriodicWorkPolicy.REPLACE,
|
||||||
|
repeatingRequest
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getWorkManagerConfiguration(): Configuration =
|
||||||
|
Configuration.Builder()
|
||||||
|
.setWorkerFactory(workerFactory)
|
||||||
|
.setMinimumLoggingLevel(android.util.Log.DEBUG)
|
||||||
|
.build()
|
||||||
}
|
}
|
|
@ -2,11 +2,18 @@ package me.ash.reader.data.repository
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
|
import androidx.hilt.work.HiltWorker
|
||||||
import androidx.paging.PagingSource
|
import androidx.paging.PagingSource
|
||||||
import androidx.work.*
|
import androidx.work.CoroutineWorker
|
||||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
import androidx.work.WorkManager
|
||||||
|
import androidx.work.WorkerParameters
|
||||||
|
import dagger.assisted.Assisted
|
||||||
|
import dagger.assisted.AssistedInject
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.StateFlow
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.asStateFlow
|
||||||
|
import kotlinx.coroutines.flow.update
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
import me.ash.reader.DataStoreKeys
|
import me.ash.reader.DataStoreKeys
|
||||||
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
|
||||||
|
@ -18,12 +25,9 @@ import me.ash.reader.data.feed.FeedDao
|
||||||
import me.ash.reader.data.group.Group
|
import me.ash.reader.data.group.Group
|
||||||
import me.ash.reader.data.group.GroupDao
|
import me.ash.reader.data.group.GroupDao
|
||||||
import me.ash.reader.data.group.GroupWithFeed
|
import me.ash.reader.data.group.GroupWithFeed
|
||||||
import me.ash.reader.data.source.ReaderDatabase
|
|
||||||
import me.ash.reader.data.source.RssNetworkDataSource
|
import me.ash.reader.data.source.RssNetworkDataSource
|
||||||
import me.ash.reader.dataStore
|
import me.ash.reader.dataStore
|
||||||
import me.ash.reader.get
|
import me.ash.reader.get
|
||||||
import java.util.concurrent.TimeUnit
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
abstract class AbstractRssRepository constructor(
|
abstract class AbstractRssRepository constructor(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
|
@ -43,19 +47,11 @@ abstract class AbstractRssRepository constructor(
|
||||||
val isNotSyncing: Boolean = !isSyncing
|
val isNotSyncing: Boolean = !isSyncing
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract fun getSyncState(): StateFlow<SyncState>
|
|
||||||
|
|
||||||
abstract suspend fun updateArticleInfo(article: Article)
|
abstract suspend fun updateArticleInfo(article: Article)
|
||||||
|
|
||||||
abstract suspend fun subscribe(feed: Feed, articles: List<Article>)
|
abstract suspend fun subscribe(feed: Feed, articles: List<Article>)
|
||||||
|
|
||||||
abstract suspend fun sync(
|
abstract suspend fun sync()
|
||||||
context: Context,
|
|
||||||
accountDao: AccountDao,
|
|
||||||
articleDao: ArticleDao,
|
|
||||||
feedDao: FeedDao,
|
|
||||||
rssNetworkDataSource: RssNetworkDataSource
|
|
||||||
)
|
|
||||||
|
|
||||||
fun pullGroups(): Flow<MutableList<Group>> {
|
fun pullGroups(): Flow<MutableList<Group>> {
|
||||||
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId) ?: 0
|
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId) ?: 0
|
||||||
|
@ -135,46 +131,32 @@ abstract class AbstractRssRepository constructor(
|
||||||
return workManager.getWorkInfosByTag("sync").get().size.toString()
|
return workManager.getWorkInfosByTag("sync").get().size.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun doSync(isWork: Boolean? = false) {
|
companion object {
|
||||||
if (isWork == true) {
|
val mutex = Mutex()
|
||||||
workManager.cancelAllWork()
|
|
||||||
val syncWorkerRequest: WorkRequest =
|
private val _syncState = MutableStateFlow(SyncState())
|
||||||
PeriodicWorkRequestBuilder<SyncWorker>(
|
val syncState = _syncState.asStateFlow()
|
||||||
15, TimeUnit.MINUTES
|
|
||||||
).setConstraints(
|
fun updateSyncState(function: (SyncState) -> SyncState) {
|
||||||
Constraints.Builder()
|
_syncState.update(function)
|
||||||
.setRequiredNetworkType(NetworkType.CONNECTED)
|
|
||||||
.build()
|
|
||||||
).addTag("sync").build()
|
|
||||||
workManager.enqueue(syncWorkerRequest)
|
|
||||||
} else {
|
|
||||||
sync(context, accountDao, articleDao, feedDao, rssNetworkDataSource)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@DelicateCoroutinesApi
|
@HiltWorker
|
||||||
class SyncWorker(
|
class SyncWorker @AssistedInject constructor(
|
||||||
context: Context,
|
@Assisted context: Context,
|
||||||
workerParams: WorkerParameters,
|
@Assisted workerParams: WorkerParameters,
|
||||||
|
private val rssRepository: RssRepository,
|
||||||
) : CoroutineWorker(context, workerParams) {
|
) : CoroutineWorker(context, workerParams) {
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var rssRepository: RssRepository
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
lateinit var rssNetworkDataSource: RssNetworkDataSource
|
|
||||||
|
|
||||||
override suspend fun doWork(): Result {
|
override suspend fun doWork(): Result {
|
||||||
Log.i("RLog", "doWork: ")
|
Log.i("RLog", "doWork: ")
|
||||||
val db = ReaderDatabase.getInstance(applicationContext)
|
rssRepository.get().sync()
|
||||||
rssRepository.get().sync(
|
|
||||||
applicationContext,
|
|
||||||
db.accountDao(),
|
|
||||||
db.articleDao(),
|
|
||||||
db.feedDao(),
|
|
||||||
rssNetworkDataSource
|
|
||||||
)
|
|
||||||
return Result.success()
|
return Result.success()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val WORK_NAME = "article.sync"
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -4,9 +4,6 @@ import android.content.Context
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.flow.MutableStateFlow
|
|
||||||
import kotlinx.coroutines.flow.update
|
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import me.ash.reader.DataStoreKeys
|
import me.ash.reader.DataStoreKeys
|
||||||
import me.ash.reader.data.account.AccountDao
|
import me.ash.reader.data.account.AccountDao
|
||||||
|
@ -33,18 +30,13 @@ class FeverRssRepository @Inject constructor(
|
||||||
private val groupDao: GroupDao,
|
private val groupDao: GroupDao,
|
||||||
private val rssHelper: RssHelper,
|
private val rssHelper: RssHelper,
|
||||||
private val feverApiDataSource: FeverApiDataSource,
|
private val feverApiDataSource: FeverApiDataSource,
|
||||||
|
private val accountDao: AccountDao,
|
||||||
rssNetworkDataSource: RssNetworkDataSource,
|
rssNetworkDataSource: RssNetworkDataSource,
|
||||||
accountDao: AccountDao,
|
|
||||||
workManager: WorkManager,
|
workManager: WorkManager,
|
||||||
) : AbstractRssRepository(
|
) : AbstractRssRepository(
|
||||||
context, accountDao, articleDao, groupDao,
|
context, accountDao, articleDao, groupDao,
|
||||||
feedDao, rssNetworkDataSource, workManager,
|
feedDao, rssNetworkDataSource, workManager,
|
||||||
) {
|
) {
|
||||||
private val mutex = Mutex()
|
|
||||||
private val syncState = MutableStateFlow(SyncState())
|
|
||||||
|
|
||||||
override fun getSyncState() = syncState
|
|
||||||
|
|
||||||
override suspend fun updateArticleInfo(article: Article) {
|
override suspend fun updateArticleInfo(article: Article) {
|
||||||
articleDao.update(article)
|
articleDao.update(article)
|
||||||
}
|
}
|
||||||
|
@ -56,18 +48,12 @@ class FeverRssRepository @Inject constructor(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sync(
|
override suspend fun sync() {
|
||||||
context: Context,
|
|
||||||
accountDao: AccountDao,
|
|
||||||
articleDao: ArticleDao,
|
|
||||||
feedDao: FeedDao,
|
|
||||||
rssNetworkDataSource: RssNetworkDataSource
|
|
||||||
) {
|
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId)
|
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId)
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
syncState.update {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
feedCount = 1,
|
feedCount = 1,
|
||||||
syncedCount = 1,
|
syncedCount = 1,
|
||||||
|
@ -140,7 +126,7 @@ class FeverRssRepository @Inject constructor(
|
||||||
accountDao.update(accountDao.queryById(accountId)!!.apply {
|
accountDao.update(accountDao.queryById(accountId)!!.apply {
|
||||||
updateAt = Date()
|
updateAt = Date()
|
||||||
})
|
})
|
||||||
syncState.update {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
feedCount = 0,
|
feedCount = 0,
|
||||||
syncedCount = 0,
|
syncedCount = 0,
|
||||||
|
|
|
@ -13,7 +13,6 @@ import androidx.core.content.ContextCompat.getSystemService
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import dagger.hilt.android.qualifiers.ApplicationContext
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import kotlinx.coroutines.flow.*
|
import kotlinx.coroutines.flow.*
|
||||||
import kotlinx.coroutines.sync.Mutex
|
|
||||||
import kotlinx.coroutines.sync.withLock
|
import kotlinx.coroutines.sync.withLock
|
||||||
import me.ash.reader.*
|
import me.ash.reader.*
|
||||||
import me.ash.reader.data.account.AccountDao
|
import me.ash.reader.data.account.AccountDao
|
||||||
|
@ -34,19 +33,14 @@ class LocalRssRepository @Inject constructor(
|
||||||
private val articleDao: ArticleDao,
|
private val articleDao: ArticleDao,
|
||||||
private val feedDao: FeedDao,
|
private val feedDao: FeedDao,
|
||||||
private val rssHelper: RssHelper,
|
private val rssHelper: RssHelper,
|
||||||
rssNetworkDataSource: RssNetworkDataSource,
|
private val rssNetworkDataSource: RssNetworkDataSource,
|
||||||
|
private val accountDao: AccountDao,
|
||||||
groupDao: GroupDao,
|
groupDao: GroupDao,
|
||||||
accountDao: AccountDao,
|
|
||||||
workManager: WorkManager,
|
workManager: WorkManager,
|
||||||
) : AbstractRssRepository(
|
) : AbstractRssRepository(
|
||||||
context, accountDao, articleDao, groupDao,
|
context, accountDao, articleDao, groupDao,
|
||||||
feedDao, rssNetworkDataSource, workManager,
|
feedDao, rssNetworkDataSource, workManager,
|
||||||
) {
|
) {
|
||||||
private val mutex = Mutex()
|
|
||||||
private val syncState = MutableStateFlow(SyncState())
|
|
||||||
|
|
||||||
override fun getSyncState() = syncState
|
|
||||||
|
|
||||||
override suspend fun updateArticleInfo(article: Article) {
|
override suspend fun updateArticleInfo(article: Article) {
|
||||||
articleDao.update(article)
|
articleDao.update(article)
|
||||||
}
|
}
|
||||||
|
@ -58,13 +52,7 @@ class LocalRssRepository @Inject constructor(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun sync(
|
override suspend fun sync() {
|
||||||
context: Context,
|
|
||||||
accountDao: AccountDao,
|
|
||||||
articleDao: ArticleDao,
|
|
||||||
feedDao: FeedDao,
|
|
||||||
rssNetworkDataSource: RssNetworkDataSource
|
|
||||||
) {
|
|
||||||
mutex.withLock {
|
mutex.withLock {
|
||||||
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId)
|
val accountId = context.dataStore.get(DataStoreKeys.CurrentAccountId)
|
||||||
?: return
|
?: return
|
||||||
|
@ -98,10 +86,10 @@ class LocalRssRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
syncState.update {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
feedCount = feeds.size,
|
feedCount = feeds.size,
|
||||||
syncedCount = syncState.value.syncedCount + 1,
|
syncedCount = it.syncedCount + 1,
|
||||||
currentFeedName = feed.name
|
currentFeedName = feed.name
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -173,7 +161,7 @@ class LocalRssRepository @Inject constructor(
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
syncState.update {
|
updateSyncState {
|
||||||
it.copy(
|
it.copy(
|
||||||
feedCount = 0,
|
feedCount = 0,
|
||||||
syncedCount = 0,
|
syncedCount = 0,
|
||||||
|
|
|
@ -16,7 +16,6 @@ import androidx.navigation.NavHostController
|
||||||
import com.google.accompanist.pager.ExperimentalPagerApi
|
import com.google.accompanist.pager.ExperimentalPagerApi
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import me.ash.reader.ui.page.common.NotificationGroupName
|
|
||||||
import me.ash.reader.ui.extension.collectAsStateValue
|
import me.ash.reader.ui.extension.collectAsStateValue
|
||||||
import me.ash.reader.ui.extension.findActivity
|
import me.ash.reader.ui.extension.findActivity
|
||||||
import me.ash.reader.ui.page.common.ExtraName
|
import me.ash.reader.ui.page.common.ExtraName
|
||||||
|
@ -46,9 +45,9 @@ fun HomePage(
|
||||||
intent.extras?.get(ExtraName.ARTICLE_ID)?.let {
|
intent.extras?.get(ExtraName.ARTICLE_ID)?.let {
|
||||||
readViewModel.dispatch(ReadViewAction.ScrollToItem(2))
|
readViewModel.dispatch(ReadViewAction.ScrollToItem(2))
|
||||||
scope.launch {
|
scope.launch {
|
||||||
val article =
|
val article = readViewModel
|
||||||
readViewModel.rssRepository.get().findArticleById(it.toString().toInt())
|
.rssRepository.get()
|
||||||
?: return@launch
|
.findArticleById(it.toString().toInt()) ?: return@launch
|
||||||
readViewModel.dispatch(ReadViewAction.InitData(article))
|
readViewModel.dispatch(ReadViewAction.InitData(article))
|
||||||
if (article.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
if (article.feed.isFullContent) readViewModel.dispatch(ReadViewAction.RenderFullContent)
|
||||||
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
else readViewModel.dispatch(ReadViewAction.RenderDescriptionContent)
|
||||||
|
|
|
@ -15,6 +15,7 @@ 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
|
||||||
|
import me.ash.reader.data.repository.AbstractRssRepository
|
||||||
import me.ash.reader.data.repository.RssRepository
|
import me.ash.reader.data.repository.RssRepository
|
||||||
import me.ash.reader.ui.extension.animateScrollToPage
|
import me.ash.reader.ui.extension.animateScrollToPage
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
@ -31,7 +32,7 @@ class HomeViewModel @Inject constructor(
|
||||||
private val _filterState = MutableStateFlow(FilterState())
|
private val _filterState = MutableStateFlow(FilterState())
|
||||||
val filterState = _filterState.asStateFlow()
|
val filterState = _filterState.asStateFlow()
|
||||||
|
|
||||||
val syncState = rssRepository.get().getSyncState()
|
val syncState = AbstractRssRepository.syncState
|
||||||
|
|
||||||
fun dispatch(action: HomeViewAction) {
|
fun dispatch(action: HomeViewAction) {
|
||||||
when (action) {
|
when (action) {
|
||||||
|
@ -47,7 +48,7 @@ class HomeViewModel @Inject constructor(
|
||||||
|
|
||||||
private fun sync(callback: () -> Unit = {}) {
|
private fun sync(callback: () -> Unit = {}) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
rssRepository.get().doSync()
|
rssRepository.get().sync()
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ class FeedsViewModel @Inject constructor(
|
||||||
private fun addFromFile(inputStream: InputStream) {
|
private fun addFromFile(inputStream: InputStream) {
|
||||||
viewModelScope.launch(Dispatchers.IO) {
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
opmlRepository.saveToDatabase(inputStream)
|
opmlRepository.saveToDatabase(inputStream)
|
||||||
pullFeeds(isStarred = false, isUnread = false)
|
rssRepository.get().sync()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,6 @@ class FeedsViewModel @Inject constructor(
|
||||||
isStarred = filterState.filter.isStarred(),
|
isStarred = filterState.filter.isStarred(),
|
||||||
isUnread = filterState.filter.isUnread(),
|
isUnread = filterState.filter.isUnread(),
|
||||||
)
|
)
|
||||||
_viewState
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package me.ash.reader.ui.page.home.flow
|
package me.ash.reader.ui.page.home.flow
|
||||||
|
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.compose.foundation.ExperimentalFoundationApi
|
import androidx.compose.foundation.ExperimentalFoundationApi
|
||||||
import androidx.compose.foundation.background
|
import androidx.compose.foundation.background
|
||||||
import androidx.compose.foundation.layout.fillMaxWidth
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
@ -77,7 +78,11 @@ fun FlowPage(
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions = {
|
actions = {
|
||||||
IconButton(onClick = {}) {
|
IconButton(onClick = {
|
||||||
|
viewModel.dispatch(FlowViewAction.PeekSyncWork)
|
||||||
|
Toast.makeText(context, viewState.syncWorkInfo.length.toString(), Toast.LENGTH_SHORT)
|
||||||
|
.show()
|
||||||
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Rounded.DoneAll,
|
imageVector = Icons.Rounded.DoneAll,
|
||||||
contentDescription = stringResource(R.string.mark_all_as_read),
|
contentDescription = stringResource(R.string.mark_all_as_read),
|
||||||
|
|
|
@ -21,9 +21,3 @@ kotlin.code.style=official
|
||||||
# resources declared in the library itself and none from the library's dependencies,
|
# resources declared in the library itself and none from the library's dependencies,
|
||||||
# thereby reducing the size of the R class for that library
|
# thereby reducing the size of the R class for that library
|
||||||
android.nonTransitiveRClass=true
|
android.nonTransitiveRClass=true
|
||||||
|
|
||||||
# Custom
|
|
||||||
org.gradle.daemon=true
|
|
||||||
org.gradle.parallel=true
|
|
||||||
org.gradle.configureondemand=true
|
|
||||||
org.gradle.caching = true
|
|
Loading…
Reference in New Issue
Block a user