Update Voyager

This commit is contained in:
arkon 2023-10-22 15:54:31 -04:00
parent 6d1e520c6c
commit 012854dd1e
25 changed files with 136 additions and 137 deletions

View file

@ -5,7 +5,6 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.GridCells
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.outlined.HelpOutline import androidx.compose.material.icons.automirrored.outlined.HelpOutline
import androidx.compose.material.icons.outlined.HelpOutline
import androidx.compose.material.icons.outlined.Public import androidx.compose.material.icons.outlined.Public
import androidx.compose.material.icons.outlined.Refresh import androidx.compose.material.icons.outlined.Refresh
import androidx.compose.material3.SnackbarDuration import androidx.compose.material3.SnackbarDuration
@ -98,7 +97,7 @@ fun BrowseSourceContent(
), ),
EmptyScreenAction( EmptyScreenAction(
stringResId = R.string.label_help, stringResId = R.string.label_help,
icon = Icons.Outlined.HelpOutline, icon = Icons.AutoMirrored.Outlined.HelpOutline,
onClick = onHelpClick, onClick = onHelpClick,
), ),
) )

View file

@ -31,8 +31,8 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMap
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
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.core.model.screenModelScope
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.browse.components.SourceIcon import eu.kanade.presentation.browse.components.SourceIcon
@ -210,7 +210,7 @@ private class ClearDatabaseScreenModel : StateScreenModel<ClearDatabaseScreenMod
private val database: Database = Injekt.get() private val database: Database = Injekt.get()
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
getSourcesWithNonLibraryManga.subscribe() getSourcesWithNonLibraryManga.subscribe()
.collectLatest { list -> .collectLatest { list ->
mutableState.update { old -> mutableState.update { old ->

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.extension
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.extension.interactor.GetExtensionLanguages import eu.kanade.domain.extension.interactor.GetExtensionLanguages
import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
@ -29,7 +29,7 @@ class ExtensionFilterScreenModel(
val events: Flow<ExtensionFilterEvent> = _events.receiveAsFlow() val events: Flow<ExtensionFilterEvent> = _events.receiveAsFlow()
init { init {
coroutineScope.launch { screenModelScope.launch {
combine( combine(
getExtensionLanguages.subscribe(), getExtensionLanguages.subscribe(),
preferences.enabledLanguages().changes(), preferences.enabledLanguages().changes(),

View file

@ -4,7 +4,7 @@ import android.app.Application
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.extension.interactor.GetExtensionsByType import eu.kanade.domain.extension.interactor.GetExtensionsByType
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS
@ -74,7 +74,7 @@ class ExtensionsScreenModel(
} }
} }
coroutineScope.launchIO { screenModelScope.launchIO {
combine( combine(
state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS),
_currentDownloads, _currentDownloads,
@ -118,11 +118,11 @@ class ExtensionsScreenModel(
} }
} }
coroutineScope.launchIO { findAvailableExtensions() } screenModelScope.launchIO { findAvailableExtensions() }
preferences.extensionUpdatesCount().changes() preferences.extensionUpdatesCount().changes()
.onEach { mutableState.update { state -> state.copy(updates = it) } } .onEach { mutableState.update { state -> state.copy(updates = it) } }
.launchIn(coroutineScope) .launchIn(screenModelScope)
} }
fun search(query: String?) { fun search(query: String?) {
@ -132,7 +132,7 @@ class ExtensionsScreenModel(
} }
fun updateAllExtensions() { fun updateAllExtensions() {
coroutineScope.launchIO { screenModelScope.launchIO {
state.value.items.values.flatten() state.value.items.values.flatten()
.map { it.extension } .map { it.extension }
.filterIsInstance<Extension.Installed>() .filterIsInstance<Extension.Installed>()
@ -142,13 +142,13 @@ class ExtensionsScreenModel(
} }
fun installExtension(extension: Extension.Available) { fun installExtension(extension: Extension.Available) {
coroutineScope.launchIO { screenModelScope.launchIO {
extensionManager.installExtension(extension).collectToInstallUpdate(extension) extensionManager.installExtension(extension).collectToInstallUpdate(extension)
} }
} }
fun updateExtension(extension: Extension.Installed) { fun updateExtension(extension: Extension.Installed) {
coroutineScope.launchIO { screenModelScope.launchIO {
extensionManager.updateExtension(extension).collectToInstallUpdate(extension) extensionManager.updateExtension(extension).collectToInstallUpdate(extension)
} }
} }
@ -176,7 +176,7 @@ class ExtensionsScreenModel(
} }
fun findAvailableExtensions() { fun findAvailableExtensions() {
coroutineScope.launchIO { screenModelScope.launchIO {
mutableState.update { it.copy(isRefreshing = true) } mutableState.update { it.copy(isRefreshing = true) }
extensionManager.findAvailableExtensions() extensionManager.findAvailableExtensions()

View file

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.extension.details
import android.content.Context import android.content.Context
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.extension.interactor.ExtensionSourceItem import eu.kanade.domain.extension.interactor.ExtensionSourceItem
import eu.kanade.domain.extension.interactor.GetExtensionSources import eu.kanade.domain.extension.interactor.GetExtensionSources
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
@ -44,7 +44,7 @@ class ExtensionDetailsScreenModel(
val events: Flow<ExtensionDetailsEvent> = _events.receiveAsFlow() val events: Flow<ExtensionDetailsEvent> = _events.receiveAsFlow()
init { init {
coroutineScope.launch { screenModelScope.launch {
launch { launch {
extensionManager.installedExtensionsFlow extensionManager.installedExtensionsFlow
.map { it.firstOrNull { extension -> extension.pkgName == pkgName } } .map { it.firstOrNull { extension -> extension.pkgName == pkgName } }

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.manga
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -30,7 +30,7 @@ class MigrateMangaScreenModel(
val events: Flow<MigrationMangaEvent> = _events.receiveAsFlow() val events: Flow<MigrationMangaEvent> = _events.receiveAsFlow()
init { init {
coroutineScope.launch { screenModelScope.launch {
mutableState.update { state -> mutableState.update { state ->
state.copy(source = sourceManager.getOrStub(sourceId)) state.copy(source = sourceManager.getOrStub(sourceId))
} }

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.search
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import kotlinx.coroutines.flow.update import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.interactor.GetManga
@ -16,7 +16,7 @@ class MigrateSearchScreenDialogScreenModel(
) : StateScreenModel<MigrateSearchScreenDialogScreenModel.State>(State()) { ) : StateScreenModel<MigrateSearchScreenDialogScreenModel.State>(State()) {
init { init {
coroutineScope.launch { screenModelScope.launch {
val manga = getManga.await(mangaId)!! val manga = getManga.await(mangaId)!!
mutableState.update { mutableState.update {

View file

@ -1,6 +1,6 @@
package eu.kanade.tachiyomi.ui.browse.migration.search package eu.kanade.tachiyomi.ui.browse.migration.search
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchScreenModel import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SearchScreenModel
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter import eu.kanade.tachiyomi.ui.browse.source.globalsearch.SourceFilter
@ -16,7 +16,7 @@ class MigrateSearchScreenModel(
) : SearchScreenModel() { ) : SearchScreenModel() {
init { init {
coroutineScope.launch { screenModelScope.launch {
val manga = getManga.await(mangaId)!! val manga = getManga.await(mangaId)!!
mutableState.update { mutableState.update {
it.copy( it.copy(

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.migration.sources
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount import eu.kanade.domain.source.interactor.GetSourcesWithFavoriteCount
import eu.kanade.domain.source.interactor.SetMigrateSorting import eu.kanade.domain.source.interactor.SetMigrateSorting
import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.SourcePreferences
@ -30,7 +30,7 @@ class MigrateSourceScreenModel(
val channel = _channel.receiveAsFlow() val channel = _channel.receiveAsFlow()
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
getSourcesWithFavoriteCount.subscribe() getSourcesWithFavoriteCount.subscribe()
.catch { .catch {
logcat(LogPriority.ERROR, it) logcat(LogPriority.ERROR, it)
@ -48,11 +48,11 @@ class MigrateSourceScreenModel(
preferences.migrationSortingDirection().changes() preferences.migrationSortingDirection().changes()
.onEach { mutableState.update { state -> state.copy(sortingDirection = it) } } .onEach { mutableState.update { state -> state.copy(sortingDirection = it) } }
.launchIn(coroutineScope) .launchIn(screenModelScope)
preferences.migrationSortingMode().changes() preferences.migrationSortingMode().changes()
.onEach { mutableState.update { state -> state.copy(sortingMode = it) } } .onEach { mutableState.update { state -> state.copy(sortingMode = it) } }
.launchIn(coroutineScope) .launchIn(screenModelScope)
} }
fun toggleSortingMode() { fun toggleSortingMode() {

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.source.interactor.GetLanguagesWithSources import eu.kanade.domain.source.interactor.GetLanguagesWithSources
import eu.kanade.domain.source.interactor.ToggleLanguage import eu.kanade.domain.source.interactor.ToggleLanguage
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
@ -25,7 +25,7 @@ class SourcesFilterScreenModel(
) : StateScreenModel<SourcesFilterScreenModel.State>(State.Loading) { ) : StateScreenModel<SourcesFilterScreenModel.State>(State.Loading) {
init { init {
coroutineScope.launch { screenModelScope.launch {
combine( combine(
getLanguagesWithSources.subscribe(), getLanguagesWithSources.subscribe(),
preferences.enabledLanguages().changes(), preferences.enabledLanguages().changes(),

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.source
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.source.interactor.GetEnabledSources import eu.kanade.domain.source.interactor.GetEnabledSources
import eu.kanade.domain.source.interactor.ToggleSource import eu.kanade.domain.source.interactor.ToggleSource
import eu.kanade.domain.source.interactor.ToggleSourcePin import eu.kanade.domain.source.interactor.ToggleSourcePin
@ -31,7 +31,7 @@ class SourcesScreenModel(
val events = _events.receiveAsFlow() val events = _events.receiveAsFlow()
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
getEnabledSources.subscribe() getEnabledSources.subscribe()
.catch { .catch {
logcat(LogPriority.ERROR, it) logcat(LogPriority.ERROR, it)

View file

@ -12,7 +12,7 @@ import androidx.paging.cachedIn
import androidx.paging.filter import androidx.paging.filter
import androidx.paging.map import androidx.paging.map
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.domain.manga.interactor.UpdateManga import eu.kanade.domain.manga.interactor.UpdateManga
@ -72,7 +72,7 @@ class BrowseSourceScreenModel(
private val addTracks: AddTracks = Injekt.get(), private val addTracks: AddTracks = Injekt.get(),
) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) { ) : StateScreenModel<BrowseSourceScreenModel.State>(State(Listing.valueOf(listingQuery))) {
var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope)
val source = sourceManager.getOrStub(sourceId) val source = sourceManager.getOrStub(sourceId)
@ -220,7 +220,7 @@ class BrowseSourceScreenModel(
* @param manga the manga to update. * @param manga the manga to update.
*/ */
fun changeMangaFavorite(manga: Manga) { fun changeMangaFavorite(manga: Manga) {
coroutineScope.launch { screenModelScope.launch {
var new = manga.copy( var new = manga.copy(
favorite = !manga.favorite, favorite = !manga.favorite,
dateAdded = when (manga.favorite) { dateAdded = when (manga.favorite) {
@ -241,7 +241,7 @@ class BrowseSourceScreenModel(
} }
fun addFavorite(manga: Manga) { fun addFavorite(manga: Manga) {
coroutineScope.launch { screenModelScope.launch {
val categories = getCategories() val categories = getCategories()
val defaultCategoryId = libraryPreferences.defaultCategory().get() val defaultCategoryId = libraryPreferences.defaultCategory().get()
val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() } val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() }
@ -291,7 +291,7 @@ class BrowseSourceScreenModel(
} }
fun moveMangaToCategories(manga: Manga, categoryIds: List<Long>) { fun moveMangaToCategories(manga: Manga, categoryIds: List<Long>) {
coroutineScope.launchIO { screenModelScope.launchIO {
setMangaCategories.await( setMangaCategories.await(
mangaId = manga.id, mangaId = manga.id,
categoryIds = categoryIds.toList(), categoryIds = categoryIds.toList(),

View file

@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.category
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
@ -31,7 +31,7 @@ class CategoryScreenModel(
val events = _events.receiveAsFlow() val events = _events.receiveAsFlow()
init { init {
coroutineScope.launch { screenModelScope.launch {
getCategories.subscribe() getCategories.subscribe()
.collectLatest { categories -> .collectLatest { categories ->
mutableState.update { mutableState.update {
@ -44,7 +44,7 @@ class CategoryScreenModel(
} }
fun createCategory(name: String) { fun createCategory(name: String) {
coroutineScope.launch { screenModelScope.launch {
when (createCategoryWithName.await(name)) { when (createCategoryWithName.await(name)) {
is CreateCategoryWithName.Result.InternalError -> _events.send(CategoryEvent.InternalError) is CreateCategoryWithName.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
@ -53,7 +53,7 @@ class CategoryScreenModel(
} }
fun deleteCategory(categoryId: Long) { fun deleteCategory(categoryId: Long) {
coroutineScope.launch { screenModelScope.launch {
when (deleteCategory.await(categoryId = categoryId)) { when (deleteCategory.await(categoryId = categoryId)) {
is DeleteCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is DeleteCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
@ -62,7 +62,7 @@ class CategoryScreenModel(
} }
fun sortAlphabetically() { fun sortAlphabetically() {
coroutineScope.launch { screenModelScope.launch {
when (reorderCategory.sortAlphabetically()) { when (reorderCategory.sortAlphabetically()) {
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
@ -71,7 +71,7 @@ class CategoryScreenModel(
} }
fun moveUp(category: Category) { fun moveUp(category: Category) {
coroutineScope.launch { screenModelScope.launch {
when (reorderCategory.moveUp(category)) { when (reorderCategory.moveUp(category)) {
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
@ -80,7 +80,7 @@ class CategoryScreenModel(
} }
fun moveDown(category: Category) { fun moveDown(category: Category) {
coroutineScope.launch { screenModelScope.launch {
when (reorderCategory.moveDown(category)) { when (reorderCategory.moveDown(category)) {
is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is ReorderCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}
@ -89,7 +89,7 @@ class CategoryScreenModel(
} }
fun renameCategory(category: Category, name: String) { fun renameCategory(category: Category, name: String) {
coroutineScope.launch { screenModelScope.launch {
when (renameCategory.await(category, name)) { when (renameCategory.await(category, name)) {
is RenameCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError) is RenameCategory.Result.InternalError -> _events.send(CategoryEvent.InternalError)
else -> {} else -> {}

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.deeplink
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource import eu.kanade.domain.chapter.interactor.SyncChaptersWithSource
import eu.kanade.domain.manga.model.toDomainManga import eu.kanade.domain.manga.model.toDomainManga
import eu.kanade.domain.manga.model.toSManga import eu.kanade.domain.manga.model.toSManga
@ -32,7 +32,7 @@ class DeepLinkScreenModel(
) : StateScreenModel<DeepLinkScreenModel.State>(State.Loading) { ) : StateScreenModel<DeepLinkScreenModel.State>(State.Loading) {
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
val source = sourceManager.getCatalogueSources() val source = sourceManager.getCatalogueSources()
.filterIsInstance<ResolvableSource>() .filterIsInstance<ResolvableSource>()
.firstOrNull { it.getUriType(query) != UriType.Unknown } .firstOrNull { it.getUriType(query) != UriType.Unknown }

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.download
import android.view.MenuItem import android.view.MenuItem
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.screenModelScope
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadManager
import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.data.download.model.Download
@ -114,7 +114,7 @@ class DownloadQueueScreenModel(
} }
init { init {
coroutineScope.launch { screenModelScope.launch {
downloadManager.queueState downloadManager.queueState
.map { downloads -> .map { downloads ->
downloads downloads
@ -208,7 +208,7 @@ class DownloadQueueScreenModel(
* @param download the download to observe its progress. * @param download the download to observe its progress.
*/ */
private fun launchProgressJob(download: Download) { private fun launchProgressJob(download: Download) {
val job = coroutineScope.launch { val job = screenModelScope.launch {
while (download.pages == null) { while (download.pages == null) {
delay(50) delay(50)
} }

View file

@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.history
import androidx.compose.runtime.Immutable import androidx.compose.runtime.Immutable
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.util.insertSeparators import eu.kanade.core.util.insertSeparators
import eu.kanade.presentation.history.HistoryUiModel import eu.kanade.presentation.history.HistoryUiModel
import eu.kanade.tachiyomi.util.lang.toDateKey import eu.kanade.tachiyomi.util.lang.toDateKey
@ -40,7 +40,7 @@ class HistoryScreenModel(
val events: Flow<Event> = _events.receiveAsFlow() val events: Flow<Event> = _events.receiveAsFlow()
init { init {
coroutineScope.launch { screenModelScope.launch {
state.map { it.searchQuery } state.map { it.searchQuery }
.distinctUntilChanged() .distinctUntilChanged()
.flatMapLatest { query -> .flatMapLatest { query ->
@ -75,7 +75,7 @@ class HistoryScreenModel(
} }
fun getNextChapterForManga(mangaId: Long, chapterId: Long) { fun getNextChapterForManga(mangaId: Long, chapterId: Long) {
coroutineScope.launchIO { screenModelScope.launchIO {
sendNextChapterEvent(getNextChapters.await(mangaId, chapterId, onlyUnread = false)) sendNextChapterEvent(getNextChapters.await(mangaId, chapterId, onlyUnread = false))
} }
} }
@ -86,19 +86,19 @@ class HistoryScreenModel(
} }
fun removeFromHistory(history: HistoryWithRelations) { fun removeFromHistory(history: HistoryWithRelations) {
coroutineScope.launchIO { screenModelScope.launchIO {
removeHistory.await(history) removeHistory.await(history)
} }
} }
fun removeAllFromHistory(mangaId: Long) { fun removeAllFromHistory(mangaId: Long) {
coroutineScope.launchIO { screenModelScope.launchIO {
removeHistory.await(mangaId) removeHistory.await(mangaId)
} }
} }
fun removeAllHistory() { fun removeAllHistory() {
coroutineScope.launchIO { screenModelScope.launchIO {
val result = removeHistory.awaitAll() val result = removeHistory.awaitAll()
if (!result) return@launchIO if (!result) return@launchIO
_events.send(Event.HistoryCleared) _events.send(Event.HistoryCleared)

View file

@ -6,7 +6,7 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastAny
import androidx.compose.ui.util.fastMap import androidx.compose.ui.util.fastMap
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.preference.PreferenceMutableState import eu.kanade.core.preference.PreferenceMutableState
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.core.util.fastDistinctBy import eu.kanade.core.util.fastDistinctBy
@ -91,10 +91,10 @@ class LibraryScreenModel(
private val trackerManager: TrackerManager = Injekt.get(), private val trackerManager: TrackerManager = Injekt.get(),
) : StateScreenModel<LibraryScreenModel.State>(State()) { ) : StateScreenModel<LibraryScreenModel.State>(State()) {
var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(coroutineScope) var activeCategoryIndex: Int by libraryPreferences.lastUsedCategory().asState(screenModelScope)
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
combine( combine(
state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS),
getLibraryFlow(), getLibraryFlow(),
@ -139,7 +139,7 @@ class LibraryScreenModel(
) )
} }
} }
.launchIn(coroutineScope) .launchIn(screenModelScope)
combine( combine(
getLibraryItemPreferencesFlow(), getLibraryItemPreferencesFlow(),
@ -161,7 +161,7 @@ class LibraryScreenModel(
state.copy(hasActiveFilters = it) state.copy(hasActiveFilters = it)
} }
} }
.launchIn(coroutineScope) .launchIn(screenModelScope)
} }
/** /**
@ -429,7 +429,7 @@ class LibraryScreenModel(
* @param amount the amount to queue or null to queue all * @param amount the amount to queue or null to queue all
*/ */
private fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) { private fun downloadUnreadChapters(mangas: List<Manga>, amount: Int?) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
mangas.forEach { manga -> mangas.forEach { manga ->
val chapters = getNextChapters.await(manga.id) val chapters = getNextChapters.await(manga.id)
.fastFilterNot { chapter -> .fastFilterNot { chapter ->
@ -453,7 +453,7 @@ class LibraryScreenModel(
*/ */
fun markReadSelection(read: Boolean) { fun markReadSelection(read: Boolean) {
val mangas = state.value.selection.toList() val mangas = state.value.selection.toList()
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
mangas.forEach { manga -> mangas.forEach { manga ->
setReadStatus.await( setReadStatus.await(
manga = manga.manga, manga = manga.manga,
@ -472,7 +472,7 @@ class LibraryScreenModel(
* @param deleteChapters whether to delete downloaded chapters. * @param deleteChapters whether to delete downloaded chapters.
*/ */
fun removeMangas(mangaList: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) { fun removeMangas(mangaList: List<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
val mangaToDelete = mangaList.distinctBy { it.id } val mangaToDelete = mangaList.distinctBy { it.id }
if (deleteFromLibrary) { if (deleteFromLibrary) {
@ -505,7 +505,7 @@ class LibraryScreenModel(
* @param removeCategories the categories to remove in all mangas. * @param removeCategories the categories to remove in all mangas.
*/ */
fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) { fun setMangaCategories(mangaList: List<Manga>, addCategories: List<Long>, removeCategories: List<Long>) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
mangaList.forEach { manga -> mangaList.forEach { manga ->
val categoryIds = getCategories.await(manga.id) val categoryIds = getCategories.await(manga.id)
.map { it.id } .map { it.id }
@ -519,11 +519,11 @@ class LibraryScreenModel(
} }
fun getDisplayMode(): PreferenceMutableState<LibraryDisplayMode> { fun getDisplayMode(): PreferenceMutableState<LibraryDisplayMode> {
return libraryPreferences.displayMode().asState(coroutineScope) return libraryPreferences.displayMode().asState(screenModelScope)
} }
fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState<Int> { fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns()).asState(coroutineScope) return (if (isLandscape) libraryPreferences.landscapeColumns() else libraryPreferences.portraitColumns()).asState(screenModelScope)
} }
suspend fun getRandomLibraryItemForCurrentCategory(): LibraryItem? { suspend fun getRandomLibraryItemForCurrentCategory(): LibraryItem? {
@ -626,7 +626,7 @@ class LibraryScreenModel(
} }
fun openChangeCategoryDialog() { fun openChangeCategoryDialog() {
coroutineScope.launchIO { screenModelScope.launchIO {
// Create a copy of selected manga // Create a copy of selected manga
val mangaList = state.value.selection.map { it.manga } val mangaList = state.value.selection.map { it.manga }

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
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.screenModelScope
import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.base.BasePreferences
import eu.kanade.tachiyomi.data.track.TrackerManager import eu.kanade.tachiyomi.data.track.TrackerManager
import tachiyomi.core.preference.Preference import tachiyomi.core.preference.Preference
@ -43,7 +43,7 @@ class LibrarySettingsScreenModel(
} }
fun setSort(category: Category?, mode: LibrarySort.Type, direction: LibrarySort.Direction) { fun setSort(category: Category?, mode: LibrarySort.Type, direction: LibrarySort.Direction) {
coroutineScope.launchIO { screenModelScope.launchIO {
setSortModeForCategory.await(category, mode, direction) setSortModeForCategory.await(category, mode, direction)
} }
} }

View file

@ -4,7 +4,7 @@ import android.content.Context
import android.net.Uri import android.net.Uri
import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.SnackbarHostState
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import coil.imageLoader import coil.imageLoader
import coil.request.ImageRequest import coil.request.ImageRequest
import coil.size.Size import coil.size.Size
@ -40,14 +40,14 @@ class MangaCoverScreenModel(
) : StateScreenModel<Manga?>(null) { ) : StateScreenModel<Manga?>(null) {
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
getManga.subscribe(mangaId) getManga.subscribe(mangaId)
.collect { newManga -> mutableState.update { newManga } } .collect { newManga -> mutableState.update { newManga } }
} }
} }
fun saveCover(context: Context) { fun saveCover(context: Context) {
coroutineScope.launch { screenModelScope.launch {
try { try {
saveCoverInternal(context, temp = false) saveCoverInternal(context, temp = false)
snackbarHostState.showSnackbar( snackbarHostState.showSnackbar(
@ -65,7 +65,7 @@ class MangaCoverScreenModel(
} }
fun shareCover(context: Context) { fun shareCover(context: Context) {
coroutineScope.launch { screenModelScope.launch {
try { try {
val uri = saveCoverInternal(context, temp = true) ?: return@launch val uri = saveCoverInternal(context, temp = true) ?: return@launch
withUIContext { withUIContext {
@ -117,7 +117,7 @@ class MangaCoverScreenModel(
*/ */
fun editCover(context: Context, data: Uri) { fun editCover(context: Context, data: Uri) {
val manga = state.value ?: return val manga = state.value ?: return
coroutineScope.launchIO { screenModelScope.launchIO {
context.contentResolver.openInputStream(data)?.use { context.contentResolver.openInputStream(data)?.use {
try { try {
manga.editCover(Injekt.get(), it, updateManga, coverCache) manga.editCover(Injekt.get(), it, updateManga, coverCache)
@ -131,7 +131,7 @@ class MangaCoverScreenModel(
fun deleteCustomCover(context: Context) { fun deleteCustomCover(context: Context) {
val mangaId = state.value?.id ?: return val mangaId = state.value?.id ?: return
coroutineScope.launchIO { screenModelScope.launchIO {
try { try {
coverCache.deleteCustomCover(mangaId) coverCache.deleteCustomCover(mangaId)
updateManga.awaitUpdateCoverLastModified(mangaId) updateManga.awaitUpdateCoverLastModified(mangaId)
@ -143,7 +143,7 @@ class MangaCoverScreenModel(
} }
private fun notifyCoverUpdated(context: Context) { private fun notifyCoverUpdated(context: Context) {
coroutineScope.launch { screenModelScope.launch {
snackbarHostState.showSnackbar( snackbarHostState.showSnackbar(
context.getString(R.string.cover_updated), context.getString(R.string.cover_updated),
withDismissAction = true, withDismissAction = true,
@ -152,7 +152,7 @@ class MangaCoverScreenModel(
} }
private fun notifyFailedCoverUpdate(context: Context, e: Throwable) { private fun notifyFailedCoverUpdate(context: Context, e: Throwable) {
coroutineScope.launch { screenModelScope.launch {
snackbarHostState.showSnackbar( snackbarHostState.showSnackbar(
context.getString(R.string.notification_cover_update_failed), context.getString(R.string.notification_cover_update_failed),
withDismissAction = true, withDismissAction = true,

View file

@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.core.util.addOrRemove import eu.kanade.core.util.addOrRemove
import eu.kanade.domain.chapter.interactor.SetReadStatus import eu.kanade.domain.chapter.interactor.SetReadStatus
@ -126,9 +126,9 @@ class MangaScreenModel(
val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get() val chapterSwipeStartAction = libraryPreferences.swipeToEndAction().get()
val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get() val chapterSwipeEndAction = libraryPreferences.swipeToStartAction().get()
val relativeTime by uiPreferences.relativeTime().asState(coroutineScope) val relativeTime by uiPreferences.relativeTime().asState(screenModelScope)
val dateFormat by mutableStateOf(UiPreferences.dateFormat(uiPreferences.dateFormat().get())) val dateFormat by mutableStateOf(UiPreferences.dateFormat(uiPreferences.dateFormat().get()))
private val skipFiltered by readerPreferences.skipFiltered().asState(coroutineScope) private val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope)
val isUpdateIntervalEnabled = LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get() val isUpdateIntervalEnabled = LibraryPreferences.MANGA_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateMangaRestrictions().get()
@ -148,7 +148,7 @@ class MangaScreenModel(
} }
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
combine( combine(
getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(), getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(),
downloadCache.changes, downloadCache.changes,
@ -166,7 +166,7 @@ class MangaScreenModel(
observeDownloads() observeDownloads()
coroutineScope.launchIO { screenModelScope.launchIO {
val manga = getMangaAndChapters.awaitManga(mangaId) val manga = getMangaAndChapters.awaitManga(mangaId)
val chapters = getMangaAndChapters.awaitChapters(mangaId) val chapters = getMangaAndChapters.awaitChapters(mangaId)
.toChapterItems(manga) .toChapterItems(manga)
@ -194,7 +194,7 @@ class MangaScreenModel(
observeTrackers() observeTrackers()
// Fetch info-chapters when needed // Fetch info-chapters when needed
if (coroutineScope.isActive) { if (screenModelScope.isActive) {
val fetchFromSourceTasks = listOf( val fetchFromSourceTasks = listOf(
async { if (needRefreshInfo) fetchMangaFromSource() }, async { if (needRefreshInfo) fetchMangaFromSource() },
async { if (needRefreshChapter) fetchChaptersFromSource() }, async { if (needRefreshChapter) fetchChaptersFromSource() },
@ -208,7 +208,7 @@ class MangaScreenModel(
} }
fun fetchAllFromSource(manualFetch: Boolean = true) { fun fetchAllFromSource(manualFetch: Boolean = true) {
coroutineScope.launch { screenModelScope.launch {
updateSuccessState { it.copy(isRefreshingData = true) } updateSuccessState { it.copy(isRefreshingData = true) }
val fetchFromSourceTasks = listOf( val fetchFromSourceTasks = listOf(
async { fetchMangaFromSource(manualFetch) }, async { fetchMangaFromSource(manualFetch) },
@ -236,7 +236,7 @@ class MangaScreenModel(
if (e is HttpException && e.code == 103) return if (e is HttpException && e.code == 103) return
logcat(LogPriority.ERROR, e) logcat(LogPriority.ERROR, e)
coroutineScope.launch { screenModelScope.launch {
snackbarHostState.showSnackbar(message = with(context) { e.formattedMessage }) snackbarHostState.showSnackbar(message = with(context) { e.formattedMessage })
} }
} }
@ -245,7 +245,7 @@ class MangaScreenModel(
fun toggleFavorite() { fun toggleFavorite() {
toggleFavorite( toggleFavorite(
onRemoved = { onRemoved = {
coroutineScope.launch { screenModelScope.launch {
if (!hasDownloads()) return@launch if (!hasDownloads()) return@launch
val result = snackbarHostState.showSnackbar( val result = snackbarHostState.showSnackbar(
message = context.getString(R.string.delete_downloads_for_manga), message = context.getString(R.string.delete_downloads_for_manga),
@ -268,7 +268,7 @@ class MangaScreenModel(
checkDuplicate: Boolean = true, checkDuplicate: Boolean = true,
) { ) {
val state = successState ?: return val state = successState ?: return
coroutineScope.launchIO { screenModelScope.launchIO {
val manga = state.manga val manga = state.manga
if (isFavorited) { if (isFavorited) {
@ -323,7 +323,7 @@ class MangaScreenModel(
fun showChangeCategoryDialog() { fun showChangeCategoryDialog() {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
coroutineScope.launch { screenModelScope.launch {
val categories = getCategories() val categories = getCategories()
val selection = getMangaCategoryIds(manga) val selection = getMangaCategoryIds(manga)
updateSuccessState { successState -> updateSuccessState { successState ->
@ -345,7 +345,7 @@ class MangaScreenModel(
} }
fun setFetchInterval(manga: Manga, interval: Int) { fun setFetchInterval(manga: Manga, interval: Int) {
coroutineScope.launchIO { screenModelScope.launchIO {
updateManga.awaitUpdateFetchInterval( updateManga.awaitUpdateFetchInterval(
// Custom intervals are negative // Custom intervals are negative
manga.copy(fetchInterval = -interval), manga.copy(fetchInterval = -interval),
@ -395,7 +395,7 @@ class MangaScreenModel(
moveMangaToCategory(categories) moveMangaToCategory(categories)
if (manga.favorite) return if (manga.favorite) return
coroutineScope.launchIO { screenModelScope.launchIO {
updateManga.awaitUpdateFavorite(manga.id, true) updateManga.awaitUpdateFavorite(manga.id, true)
} }
} }
@ -411,7 +411,7 @@ class MangaScreenModel(
} }
private fun moveMangaToCategory(categoryIds: List<Long>) { private fun moveMangaToCategory(categoryIds: List<Long>) {
coroutineScope.launchIO { screenModelScope.launchIO {
setMangaCategories.await(mangaId, categoryIds) setMangaCategories.await(mangaId, categoryIds)
} }
} }
@ -430,7 +430,7 @@ class MangaScreenModel(
// Chapters list - start // Chapters list - start
private fun observeDownloads() { private fun observeDownloads() {
coroutineScope.launchIO { screenModelScope.launchIO {
downloadManager.statusFlow() downloadManager.statusFlow()
.filter { it.manga.id == successState?.manga?.id } .filter { it.manga.id == successState?.manga?.id }
.catch { error -> logcat(LogPriority.ERROR, error) } .catch { error -> logcat(LogPriority.ERROR, error) }
@ -441,7 +441,7 @@ class MangaScreenModel(
} }
} }
coroutineScope.launchIO { screenModelScope.launchIO {
downloadManager.progressFlow() downloadManager.progressFlow()
.filter { it.manga.id == successState?.manga?.id } .filter { it.manga.id == successState?.manga?.id }
.catch { error -> logcat(LogPriority.ERROR, error) } .catch { error -> logcat(LogPriority.ERROR, error) }
@ -523,7 +523,7 @@ class MangaScreenModel(
with(context) { e.formattedMessage } with(context) { e.formattedMessage }
} }
coroutineScope.launch { screenModelScope.launch {
snackbarHostState.showSnackbar(message = message) snackbarHostState.showSnackbar(message = message)
} }
val newManga = mangaRepository.getMangaById(mangaId) val newManga = mangaRepository.getMangaById(mangaId)
@ -535,7 +535,7 @@ class MangaScreenModel(
* @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled] * @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled]
*/ */
fun chapterSwipe(chapterItem: ChapterItem, swipeAction: LibraryPreferences.ChapterSwipeAction) { fun chapterSwipe(chapterItem: ChapterItem, swipeAction: LibraryPreferences.ChapterSwipeAction) {
coroutineScope.launch { screenModelScope.launch {
executeChapterSwipeAction(chapterItem, swipeAction) executeChapterSwipeAction(chapterItem, swipeAction)
} }
} }
@ -612,7 +612,7 @@ class MangaScreenModel(
updateSuccessState { state -> updateSuccessState { state ->
state.copy(hasPromptedToAddBefore = true) state.copy(hasPromptedToAddBefore = true)
} }
coroutineScope.launch { screenModelScope.launch {
val result = snackbarHostState.showSnackbar( val result = snackbarHostState.showSnackbar(
message = context.getString(R.string.snack_add_to_library), message = context.getString(R.string.snack_add_to_library),
actionLabel = context.getString(R.string.action_add), actionLabel = context.getString(R.string.action_add),
@ -683,7 +683,7 @@ class MangaScreenModel(
* @param read whether to mark chapters as read or unread. * @param read whether to mark chapters as read or unread.
*/ */
fun markChaptersRead(chapters: List<Chapter>, read: Boolean) { fun markChaptersRead(chapters: List<Chapter>, read: Boolean) {
coroutineScope.launchIO { screenModelScope.launchIO {
setReadStatus.await( setReadStatus.await(
read = read, read = read,
chapters = chapters.toTypedArray(), chapters = chapters.toTypedArray(),
@ -707,7 +707,7 @@ class MangaScreenModel(
* @param chapters the list of chapters to bookmark. * @param chapters the list of chapters to bookmark.
*/ */
fun bookmarkChapters(chapters: List<Chapter>, bookmarked: Boolean) { fun bookmarkChapters(chapters: List<Chapter>, bookmarked: Boolean) {
coroutineScope.launchIO { screenModelScope.launchIO {
chapters chapters
.filterNot { it.bookmark == bookmarked } .filterNot { it.bookmark == bookmarked }
.map { ChapterUpdate(id = it.id, bookmark = bookmarked) } .map { ChapterUpdate(id = it.id, bookmark = bookmarked) }
@ -722,7 +722,7 @@ class MangaScreenModel(
* @param chapters the list of chapters to delete. * @param chapters the list of chapters to delete.
*/ */
fun deleteChapters(chapters: List<Chapter>) { fun deleteChapters(chapters: List<Chapter>) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
try { try {
successState?.let { state -> successState?.let { state ->
downloadManager.deleteChapters( downloadManager.deleteChapters(
@ -738,7 +738,7 @@ class MangaScreenModel(
} }
private fun downloadNewChapters(chapters: List<Chapter>) { private fun downloadNewChapters(chapters: List<Chapter>) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
val manga = successState?.manga ?: return@launchNonCancellable val manga = successState?.manga ?: return@launchNonCancellable
val categories = getCategories.await(manga.id).map { it.id } val categories = getCategories.await(manga.id).map { it.id }
if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences)) return@launchNonCancellable if (chapters.isEmpty() || !manga.shouldDownloadNewChapters(categories, downloadPreferences)) return@launchNonCancellable
@ -758,7 +758,7 @@ class MangaScreenModel(
TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ
} }
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) setMangaChapterFlags.awaitSetUnreadFilter(manga, flag)
} }
} }
@ -776,7 +776,7 @@ class MangaScreenModel(
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED
} }
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag)
} }
} }
@ -794,7 +794,7 @@ class MangaScreenModel(
TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED
} }
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag)
} }
} }
@ -806,7 +806,7 @@ class MangaScreenModel(
fun setDisplayMode(mode: Long) { fun setDisplayMode(mode: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
setMangaChapterFlags.awaitSetDisplayMode(manga, mode) setMangaChapterFlags.awaitSetDisplayMode(manga, mode)
} }
} }
@ -818,14 +818,14 @@ class MangaScreenModel(
fun setSorting(sort: Long) { fun setSorting(sort: Long) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort)
} }
} }
fun setCurrentSettingsAsDefault(applyToExisting: Boolean) { fun setCurrentSettingsAsDefault(applyToExisting: Boolean) {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
libraryPreferences.setChapterSettingsDefault(manga) libraryPreferences.setChapterSettingsDefault(manga)
if (applyToExisting) { if (applyToExisting) {
setMangaDefaultChapterFlags.awaitAll() setMangaDefaultChapterFlags.awaitAll()
@ -929,7 +929,7 @@ class MangaScreenModel(
private fun observeTrackers() { private fun observeTrackers() {
val manga = successState?.manga ?: return val manga = successState?.manga ?: return
coroutineScope.launchIO { screenModelScope.launchIO {
getTracks.subscribe(manga.id) getTracks.subscribe(manga.id)
.catch { logcat(LogPriority.ERROR, it) } .catch { logcat(LogPriority.ERROR, it) }
.map { tracks -> .map { tracks ->

View file

@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.model.ScreenModel import cafe.adriel.voyager.core.model.ScreenModel
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
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.core.model.screenModelScope
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
@ -188,11 +188,11 @@ data class TrackInfoDialogHomeScreen(
) : StateScreenModel<Model.State>(State()) { ) : StateScreenModel<Model.State>(State()) {
init { init {
coroutineScope.launch { screenModelScope.launch {
refreshTrackers() refreshTrackers()
} }
coroutineScope.launch { screenModelScope.launch {
getTracks.subscribe(mangaId) getTracks.subscribe(mangaId)
.catch { logcat(LogPriority.ERROR, it) } .catch { logcat(LogPriority.ERROR, it) }
.distinctUntilChanged() .distinctUntilChanged()
@ -203,7 +203,7 @@ data class TrackInfoDialogHomeScreen(
fun registerEnhancedTracking(item: TrackItem) { fun registerEnhancedTracking(item: TrackItem) {
item.tracker as EnhancedTracker item.tracker as EnhancedTracker
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable val manga = Injekt.get<GetManga>().await(mangaId) ?: return@launchNonCancellable
try { try {
val matchResult = item.tracker.match(manga) ?: throw Exception() val matchResult = item.tracker.match(manga) ?: throw Exception()
@ -294,7 +294,7 @@ private data class TrackStatusSelectorScreen(
} }
fun setStatus() { fun setStatus() {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
tracker.setRemoteStatus(track.toDbTrack(), state.value.selection) tracker.setRemoteStatus(track.toDbTrack(), state.value.selection)
} }
} }
@ -353,7 +353,7 @@ private data class TrackChapterSelectorScreen(
} }
fun setChapter() { fun setChapter() {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
tracker.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection) tracker.setRemoteLastChapterRead(track.toDbTrack(), state.value.selection)
} }
} }
@ -407,7 +407,7 @@ private data class TrackScoreSelectorScreen(
} }
fun setScore() { fun setScore() {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
tracker.setRemoteScore(track.toDbTrack(), state.value.selection) tracker.setRemoteScore(track.toDbTrack(), state.value.selection)
} }
} }
@ -533,7 +533,7 @@ private data class TrackDateSelectorScreen(
fun setDate(millis: Long) { fun setDate(millis: Long) {
// Convert to local time // Convert to local time
val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault()) val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault())
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
if (start) { if (start) {
tracker.setRemoteStartDate(track.toDbTrack(), localMillis) tracker.setRemoteStartDate(track.toDbTrack(), localMillis)
} else { } else {
@ -622,7 +622,7 @@ private data class TrackDateRemoverScreen(
fun getServiceName() = tracker.name fun getServiceName() = tracker.name
fun removeDate() { fun removeDate() {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
if (start) { if (start) {
tracker.setRemoteStartDate(track.toDbTrack(), 0) tracker.setRemoteStartDate(track.toDbTrack(), 0)
} else { } else {
@ -685,7 +685,7 @@ data class TrackerSearchScreen(
} }
fun trackingSearch(query: String) { fun trackingSearch(query: String) {
coroutineScope.launch { screenModelScope.launch {
// To show loading state // To show loading state
mutableState.update { it.copy(queryResult = null, selected = null) } mutableState.update { it.copy(queryResult = null, selected = null) }
@ -707,7 +707,7 @@ data class TrackerSearchScreen(
} }
fun registerTracking(item: TrackSearch) { fun registerTracking(item: TrackSearch) {
coroutineScope.launchNonCancellable { tracker.register(item, mangaId) } screenModelScope.launchNonCancellable { tracker.register(item, mangaId) }
} }
fun updateSelection(selected: TrackSearch) { fun updateSelection(selected: TrackSearch) {
@ -812,13 +812,13 @@ private data class TrackerRemoveScreen(
fun isDeletable() = tracker is DeletableTracker fun isDeletable() = tracker is DeletableTracker
fun deleteMangaFromService() { fun deleteMangaFromService() {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
(tracker as DeletableTracker).delete(track.toDbTrack()) (tracker as DeletableTracker).delete(track.toDbTrack())
} }
} }
fun unregisterTracking(serviceId: Long) { fun unregisterTracking(serviceId: Long) {
coroutineScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) } screenModelScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) }
} }
} }
} }

View file

@ -10,8 +10,8 @@ import androidx.compose.runtime.setValue
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
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.core.model.screenModelScope
import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.LocalNavigator
import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.Navigator
import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.currentOrThrow
@ -83,15 +83,15 @@ private class MoreScreenModel(
preferences: BasePreferences = Injekt.get(), preferences: BasePreferences = Injekt.get(),
) : ScreenModel { ) : ScreenModel {
var downloadedOnly by preferences.downloadedOnly().asState(coroutineScope) var downloadedOnly by preferences.downloadedOnly().asState(screenModelScope)
var incognitoMode by preferences.incognitoMode().asState(coroutineScope) var incognitoMode by preferences.incognitoMode().asState(screenModelScope)
private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped) private var _state: MutableStateFlow<DownloadQueueState> = MutableStateFlow(DownloadQueueState.Stopped)
val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow() val downloadQueueState: StateFlow<DownloadQueueState> = _state.asStateFlow()
init { init {
// Handle running/paused status change and queue progress updating // Handle running/paused status change and queue progress updating
coroutineScope.launchIO { screenModelScope.launchIO {
combine( combine(
downloadManager.isDownloaderRunning, downloadManager.isDownloaderRunning,
downloadManager.queueState, downloadManager.queueState,

View file

@ -1,7 +1,7 @@
package eu.kanade.tachiyomi.ui.stats package eu.kanade.tachiyomi.ui.stats
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.util.fastCountNot import eu.kanade.core.util.fastCountNot
import eu.kanade.core.util.fastDistinctBy import eu.kanade.core.util.fastDistinctBy
import eu.kanade.core.util.fastFilter import eu.kanade.core.util.fastFilter
@ -39,7 +39,7 @@ class StatsScreenModel(
private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn } } private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn } }
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
val libraryManga = getLibraryManga.await() val libraryManga = getLibraryManga.await()
val distinctLibraryManga = libraryManga.fastDistinctBy { it.id } val distinctLibraryManga = libraryManga.fastDistinctBy { it.id }

View file

@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf
import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.StateScreenModel
import cafe.adriel.voyager.core.model.coroutineScope import cafe.adriel.voyager.core.model.screenModelScope
import eu.kanade.core.preference.asState import eu.kanade.core.preference.asState
import eu.kanade.core.util.addOrRemove import eu.kanade.core.util.addOrRemove
import eu.kanade.core.util.insertSeparators import eu.kanade.core.util.insertSeparators
@ -65,15 +65,15 @@ class UpdatesScreenModel(
private val _events: Channel<Event> = Channel(Int.MAX_VALUE) private val _events: Channel<Event> = Channel(Int.MAX_VALUE)
val events: Flow<Event> = _events.receiveAsFlow() val events: Flow<Event> = _events.receiveAsFlow()
val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(coroutineScope) val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(screenModelScope)
val relativeTime by uiPreferences.relativeTime().asState(coroutineScope) val relativeTime by uiPreferences.relativeTime().asState(screenModelScope)
// First and last selected index in list // First and last selected index in list
private val selectedPositions: Array<Int> = arrayOf(-1, -1) private val selectedPositions: Array<Int> = arrayOf(-1, -1)
private val selectedChapterIds: HashSet<Long> = HashSet() private val selectedChapterIds: HashSet<Long> = HashSet()
init { init {
coroutineScope.launchIO { screenModelScope.launchIO {
// Set date limit for recent chapters // Set date limit for recent chapters
val calendar = Calendar.getInstance().apply { val calendar = Calendar.getInstance().apply {
time = Date() time = Date()
@ -99,7 +99,7 @@ class UpdatesScreenModel(
} }
} }
coroutineScope.launchIO { screenModelScope.launchIO {
merge(downloadManager.statusFlow(), downloadManager.progressFlow()) merge(downloadManager.statusFlow(), downloadManager.progressFlow())
.catch { logcat(LogPriority.ERROR, it) } .catch { logcat(LogPriority.ERROR, it) }
.collect(this@UpdatesScreenModel::updateDownloadState) .collect(this@UpdatesScreenModel::updateDownloadState)
@ -131,7 +131,7 @@ class UpdatesScreenModel(
fun updateLibrary(): Boolean { fun updateLibrary(): Boolean {
val started = LibraryUpdateJob.startNow(Injekt.get<Application>()) val started = LibraryUpdateJob.startNow(Injekt.get<Application>())
coroutineScope.launch { screenModelScope.launch {
_events.send(Event.LibraryUpdateTriggered(started)) _events.send(Event.LibraryUpdateTriggered(started))
} }
return started return started
@ -163,7 +163,7 @@ class UpdatesScreenModel(
fun downloadChapters(items: List<UpdatesItem>, action: ChapterDownloadAction) { fun downloadChapters(items: List<UpdatesItem>, action: ChapterDownloadAction) {
if (items.isEmpty()) return if (items.isEmpty()) return
coroutineScope.launch { screenModelScope.launch {
when (action) { when (action) {
ChapterDownloadAction.START -> { ChapterDownloadAction.START -> {
downloadChapters(items) downloadChapters(items)
@ -203,7 +203,7 @@ class UpdatesScreenModel(
* @param read whether to mark chapters as read or unread. * @param read whether to mark chapters as read or unread.
*/ */
fun markUpdatesRead(updates: List<UpdatesItem>, read: Boolean) { fun markUpdatesRead(updates: List<UpdatesItem>, read: Boolean) {
coroutineScope.launchIO { screenModelScope.launchIO {
setReadStatus.await( setReadStatus.await(
read = read, read = read,
chapters = updates chapters = updates
@ -219,7 +219,7 @@ class UpdatesScreenModel(
* @param updates the list of chapters to bookmark. * @param updates the list of chapters to bookmark.
*/ */
fun bookmarkUpdates(updates: List<UpdatesItem>, bookmark: Boolean) { fun bookmarkUpdates(updates: List<UpdatesItem>, bookmark: Boolean) {
coroutineScope.launchIO { screenModelScope.launchIO {
updates updates
.filterNot { it.update.bookmark == bookmark } .filterNot { it.update.bookmark == bookmark }
.map { ChapterUpdate(id = it.update.chapterId, bookmark = bookmark) } .map { ChapterUpdate(id = it.update.chapterId, bookmark = bookmark) }
@ -233,7 +233,7 @@ class UpdatesScreenModel(
* @param updatesItem the list of chapters to download. * @param updatesItem the list of chapters to download.
*/ */
private fun downloadChapters(updatesItem: List<UpdatesItem>) { private fun downloadChapters(updatesItem: List<UpdatesItem>) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values
for (updates in groupedUpdates) { for (updates in groupedUpdates) {
val mangaId = updates.first().update.mangaId val mangaId = updates.first().update.mangaId
@ -252,7 +252,7 @@ class UpdatesScreenModel(
* @param updatesItem list of chapters * @param updatesItem list of chapters
*/ */
fun deleteChapters(updatesItem: List<UpdatesItem>) { fun deleteChapters(updatesItem: List<UpdatesItem>) {
coroutineScope.launchNonCancellable { screenModelScope.launchNonCancellable {
updatesItem updatesItem
.groupBy { it.update.mangaId } .groupBy { it.update.mangaId }
.entries .entries

View file

@ -5,7 +5,7 @@ shizuku_version = "12.2.0"
sqlite = "2.4.0" sqlite = "2.4.0"
sqldelight = "2.0.0" sqldelight = "2.0.0"
leakcanary = "2.12" leakcanary = "2.12"
voyager = "1.0.0-rc07" voyager = "1.0.0-rc08"
richtext = "0.17.0" richtext = "0.17.0"
[libraries] [libraries]