mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-22 07:21:51 +01:00
Use IO dispatcher for some screen model work
Not sure if this is an ideal approach. If it is, we could migrate more usages to this.
This commit is contained in:
parent
d1bf857079
commit
18f9e5ba6b
@ -31,11 +31,11 @@ import androidx.lifecycle.asFlow
|
|||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkQuery
|
import androidx.work.WorkQuery
|
||||||
import cafe.adriel.voyager.core.model.ScreenModel
|
import cafe.adriel.voyager.core.model.ScreenModel
|
||||||
import cafe.adriel.voyager.core.model.coroutineScope
|
|
||||||
import cafe.adriel.voyager.core.model.rememberScreenModel
|
import cafe.adriel.voyager.core.model.rememberScreenModel
|
||||||
import cafe.adriel.voyager.navigator.LocalNavigator
|
import cafe.adriel.voyager.navigator.LocalNavigator
|
||||||
import cafe.adriel.voyager.navigator.currentOrThrow
|
import cafe.adriel.voyager.navigator.currentOrThrow
|
||||||
import eu.kanade.presentation.util.Screen
|
import eu.kanade.presentation.util.Screen
|
||||||
|
import eu.kanade.presentation.util.ioCoroutineScope
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.util.system.workManager
|
import eu.kanade.tachiyomi.util.system.workManager
|
||||||
import kotlinx.coroutines.flow.SharingStarted
|
import kotlinx.coroutines.flow.SharingStarted
|
||||||
@ -128,19 +128,19 @@ object WorkerInfoScreen : Screen() {
|
|||||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
|
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.SUCCEEDED, WorkInfo.State.FAILED, WorkInfo.State.CANCELLED))
|
||||||
.asFlow()
|
.asFlow()
|
||||||
.map(::constructString)
|
.map(::constructString)
|
||||||
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
|
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||||
|
|
||||||
val running = workManager
|
val running = workManager
|
||||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.RUNNING))
|
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.RUNNING))
|
||||||
.asFlow()
|
.asFlow()
|
||||||
.map(::constructString)
|
.map(::constructString)
|
||||||
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
|
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||||
|
|
||||||
val enqueued = workManager
|
val enqueued = workManager
|
||||||
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.ENQUEUED))
|
.getWorkInfosLiveData(WorkQuery.fromStates(WorkInfo.State.ENQUEUED))
|
||||||
.asFlow()
|
.asFlow()
|
||||||
.map(::constructString)
|
.map(::constructString)
|
||||||
.stateIn(coroutineScope, SharingStarted.WhileSubscribed(), "")
|
.stateIn(ioCoroutineScope, SharingStarted.WhileSubscribed(), "")
|
||||||
|
|
||||||
private fun constructString(list: List<WorkInfo>) = buildString {
|
private fun constructString(list: List<WorkInfo>) = buildString {
|
||||||
if (list.isEmpty()) {
|
if (list.isEmpty()) {
|
||||||
|
@ -3,12 +3,20 @@ package eu.kanade.presentation.util
|
|||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.runtime.ProvidableCompositionLocal
|
import androidx.compose.runtime.ProvidableCompositionLocal
|
||||||
import androidx.compose.runtime.staticCompositionLocalOf
|
import androidx.compose.runtime.staticCompositionLocalOf
|
||||||
|
import cafe.adriel.voyager.core.model.ScreenModel
|
||||||
|
import cafe.adriel.voyager.core.model.ScreenModelStore
|
||||||
import cafe.adriel.voyager.core.screen.Screen
|
import cafe.adriel.voyager.core.screen.Screen
|
||||||
import cafe.adriel.voyager.core.screen.ScreenKey
|
import cafe.adriel.voyager.core.screen.ScreenKey
|
||||||
import cafe.adriel.voyager.core.screen.uniqueScreenKey
|
import cafe.adriel.voyager.core.screen.uniqueScreenKey
|
||||||
import cafe.adriel.voyager.core.stack.StackEvent
|
import cafe.adriel.voyager.core.stack.StackEvent
|
||||||
import cafe.adriel.voyager.navigator.Navigator
|
import cafe.adriel.voyager.navigator.Navigator
|
||||||
import cafe.adriel.voyager.transitions.ScreenTransition
|
import cafe.adriel.voyager.transitions.ScreenTransition
|
||||||
|
import kotlinx.coroutines.CoroutineName
|
||||||
|
import kotlinx.coroutines.CoroutineScope
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.SupervisorJob
|
||||||
|
import kotlinx.coroutines.cancel
|
||||||
|
import kotlinx.coroutines.plus
|
||||||
import soup.compose.material.motion.animation.materialSharedAxisX
|
import soup.compose.material.motion.animation.materialSharedAxisX
|
||||||
import soup.compose.material.motion.animation.rememberSlideDistance
|
import soup.compose.material.motion.animation.rememberSlideDistance
|
||||||
|
|
||||||
@ -28,6 +36,18 @@ abstract class Screen : Screen {
|
|||||||
override val key: ScreenKey = uniqueScreenKey
|
override val key: ScreenKey = uniqueScreenKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A variant of ScreenModel.coroutineScope except with the IO dispatcher instead of the
|
||||||
|
* main dispatcher.
|
||||||
|
*/
|
||||||
|
val ScreenModel.ioCoroutineScope: CoroutineScope
|
||||||
|
get() = ScreenModelStore.getOrPutDependency(
|
||||||
|
screenModel = this,
|
||||||
|
name = "ScreenModelIoCoroutineScope",
|
||||||
|
factory = { key -> CoroutineScope(Dispatchers.IO + SupervisorJob()) + CoroutineName(key) },
|
||||||
|
onDispose = { scope -> scope.cancel() },
|
||||||
|
)
|
||||||
|
|
||||||
interface AssistContentScreen {
|
interface AssistContentScreen {
|
||||||
fun onProvideAssistUrl(): String?
|
fun onProvideAssistUrl(): String?
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import eu.kanade.domain.manga.interactor.UpdateManga
|
|||||||
import eu.kanade.domain.manga.model.toDomainManga
|
import eu.kanade.domain.manga.model.toDomainManga
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
import eu.kanade.domain.track.model.toDomainTrack
|
import eu.kanade.domain.track.model.toDomainTrack
|
||||||
|
import eu.kanade.presentation.util.ioCoroutineScope
|
||||||
import eu.kanade.tachiyomi.data.cache.CoverCache
|
import eu.kanade.tachiyomi.data.cache.CoverCache
|
||||||
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
import eu.kanade.tachiyomi.data.track.EnhancedTrackService
|
||||||
import eu.kanade.tachiyomi.data.track.TrackManager
|
import eu.kanade.tachiyomi.data.track.TrackManager
|
||||||
@ -125,12 +126,12 @@ class BrowseSourceScreenModel(
|
|||||||
.filter { localManga ->
|
.filter { localManga ->
|
||||||
!sourcePreferences.hideInLibraryItems().get() || !localManga.favorite
|
!sourcePreferences.hideInLibraryItems().get() || !localManga.favorite
|
||||||
}
|
}
|
||||||
.stateIn(coroutineScope)
|
.stateIn(ioCoroutineScope)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.cachedIn(coroutineScope)
|
.cachedIn(ioCoroutineScope)
|
||||||
}
|
}
|
||||||
.stateIn(coroutineScope, SharingStarted.Lazily, emptyFlow())
|
.stateIn(ioCoroutineScope, SharingStarted.Lazily, emptyFlow())
|
||||||
|
|
||||||
fun getColumnsPreference(orientation: Int): GridCells {
|
fun getColumnsPreference(orientation: Int): GridCells {
|
||||||
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
|
val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE
|
||||||
|
@ -4,10 +4,10 @@ import androidx.compose.runtime.Composable
|
|||||||
import androidx.compose.runtime.State
|
import androidx.compose.runtime.State
|
||||||
import androidx.compose.runtime.produceState
|
import androidx.compose.runtime.produceState
|
||||||
import cafe.adriel.voyager.core.model.StateScreenModel
|
import cafe.adriel.voyager.core.model.StateScreenModel
|
||||||
import cafe.adriel.voyager.core.model.coroutineScope
|
|
||||||
import eu.kanade.domain.manga.interactor.UpdateManga
|
import eu.kanade.domain.manga.interactor.UpdateManga
|
||||||
import eu.kanade.domain.manga.model.toDomainManga
|
import eu.kanade.domain.manga.model.toDomainManga
|
||||||
import eu.kanade.domain.source.service.SourcePreferences
|
import eu.kanade.domain.source.service.SourcePreferences
|
||||||
|
import eu.kanade.presentation.util.ioCoroutineScope
|
||||||
import eu.kanade.tachiyomi.extension.ExtensionManager
|
import eu.kanade.tachiyomi.extension.ExtensionManager
|
||||||
import eu.kanade.tachiyomi.source.CatalogueSource
|
import eu.kanade.tachiyomi.source.CatalogueSource
|
||||||
import kotlinx.coroutines.asCoroutineDispatcher
|
import kotlinx.coroutines.asCoroutineDispatcher
|
||||||
@ -17,7 +17,6 @@ import kotlinx.coroutines.flow.collectLatest
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import tachiyomi.core.util.lang.awaitSingle
|
import tachiyomi.core.util.lang.awaitSingle
|
||||||
import tachiyomi.core.util.lang.withIOContext
|
|
||||||
import tachiyomi.domain.manga.interactor.GetManga
|
import tachiyomi.domain.manga.interactor.GetManga
|
||||||
import tachiyomi.domain.manga.interactor.NetworkToLocalManga
|
import tachiyomi.domain.manga.interactor.NetworkToLocalManga
|
||||||
import tachiyomi.domain.manga.model.Manga
|
import tachiyomi.domain.manga.model.Manga
|
||||||
@ -94,7 +93,7 @@ abstract class SearchScreenModel<T>(
|
|||||||
|
|
||||||
abstract fun getItems(): Map<CatalogueSource, SearchItemResult>
|
abstract fun getItems(): Map<CatalogueSource, SearchItemResult>
|
||||||
|
|
||||||
fun getAndUpdateItems(function: (Map<CatalogueSource, SearchItemResult>) -> Map<CatalogueSource, SearchItemResult>) {
|
private fun getAndUpdateItems(function: (Map<CatalogueSource, SearchItemResult>) -> Map<CatalogueSource, SearchItemResult>) {
|
||||||
updateItems(function(getItems()))
|
updateItems(function(getItems()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,7 +105,7 @@ abstract class SearchScreenModel<T>(
|
|||||||
val initialItems = getSelectedSources().associateWith { SearchItemResult.Loading }
|
val initialItems = getSelectedSources().associateWith { SearchItemResult.Loading }
|
||||||
updateItems(initialItems)
|
updateItems(initialItems)
|
||||||
|
|
||||||
coroutineScope.launch {
|
ioCoroutineScope.launch {
|
||||||
sources
|
sources
|
||||||
.map { source ->
|
.map { source ->
|
||||||
async {
|
async {
|
||||||
@ -115,11 +114,9 @@ abstract class SearchScreenModel<T>(
|
|||||||
source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle()
|
source.fetchSearchManga(1, query, source.getFilterList()).awaitSingle()
|
||||||
}
|
}
|
||||||
|
|
||||||
val titles = withIOContext {
|
val titles = page.mangas.map {
|
||||||
page.mangas.map {
|
|
||||||
networkToLocalManga.await(it.toDomainManga(source.id))
|
networkToLocalManga.await(it.toDomainManga(source.id))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
getAndUpdateItems { items ->
|
getAndUpdateItems { items ->
|
||||||
val mutableMap = items.toMutableMap()
|
val mutableMap = items.toMutableMap()
|
||||||
@ -129,7 +126,7 @@ abstract class SearchScreenModel<T>(
|
|||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
getAndUpdateItems { items ->
|
getAndUpdateItems { items ->
|
||||||
val mutableMap = items.toMutableMap()
|
val mutableMap = items.toMutableMap()
|
||||||
mutableMap[source] = SearchItemResult.Error(throwable = e)
|
mutableMap[source] = SearchItemResult.Error(e)
|
||||||
mutableMap.toSortedMap(sortComparator(mutableMap))
|
mutableMap.toSortedMap(sortComparator(mutableMap))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user