diff --git a/app/src/main/java/eu/kanade/domain/entries/manga/interactor/SetMangaViewerFlags.kt b/app/src/main/java/eu/kanade/domain/entries/manga/interactor/SetMangaViewerFlags.kt index 106bf2fc7..399638589 100644 --- a/app/src/main/java/eu/kanade/domain/entries/manga/interactor/SetMangaViewerFlags.kt +++ b/app/src/main/java/eu/kanade/domain/entries/manga/interactor/SetMangaViewerFlags.kt @@ -9,7 +9,7 @@ class SetMangaViewerFlags( private val mangaRepository: MangaRepository, ) { - suspend fun awaitSetMangaReadingMode(id: Long, flag: Long) { + suspend fun awaitSetReadingMode(id: Long, flag: Long) { val manga = mangaRepository.getMangaById(id) mangaRepository.updateManga( MangaUpdate( @@ -19,7 +19,7 @@ class SetMangaViewerFlags( ) } - suspend fun awaitSetOrientationType(id: Long, flag: Long) { + suspend fun awaitSetOrientation(id: Long, flag: Long) { val manga = mangaRepository.getMangaById(id) mangaRepository.updateManga( MangaUpdate( diff --git a/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt b/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt index 28b36e501..0294201e5 100644 --- a/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/entries/anime/EpisodeOptionsDialogScreen.kt @@ -47,8 +47,8 @@ import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp 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.screenModelScope import cafe.adriel.voyager.core.screen.Screen import eu.kanade.core.util.asFlow import eu.kanade.presentation.components.TabbedDialogPaddings @@ -116,7 +116,7 @@ class EpisodeOptionsDialogScreenModel( private val sourceManager: AnimeSourceManager = Injekt.get() init { - coroutineScope.launch { + screenModelScope.launch { // To show loading state mutableState.update { it.copy(episode = null, anime = null, resultList = null) } diff --git a/app/src/main/java/eu/kanade/presentation/entries/anime/components/AnimeInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/entries/anime/components/AnimeInfoHeader.kt index e60949426..255d580de 100644 --- a/app/src/main/java/eu/kanade/presentation/entries/anime/components/AnimeInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/entries/anime/components/AnimeInfoHeader.kt @@ -25,8 +25,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Brush import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.HourglassEmpty +import androidx.compose.material.icons.filled.PersonOutline import androidx.compose.material.icons.outlined.AttachMoney import androidx.compose.material.icons.outlined.Block import androidx.compose.material.icons.outlined.Close @@ -473,6 +475,7 @@ private fun AnimeAndSourceTitlesSmall( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, top = appBarPadding + 16.dp, end = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically, ) { ItemCover.Book( @@ -483,7 +486,9 @@ private fun AnimeAndSourceTitlesSmall( contentDescription = stringResource(R.string.manga_cover), onClick = onCoverClick, ) - Column(modifier = Modifier.padding(start = 16.dp)) { + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { Text( text = title.ifBlank { stringResource(R.string.unknown_title) }, style = MaterialTheme.typography.titleLarge, @@ -499,40 +504,63 @@ private fun AnimeAndSourceTitlesSmall( onClick = { if (title.isNotBlank()) doSearch(title, true) }, ), ) + Spacer(modifier = Modifier.height(2.dp)) - Text( - text = author?.takeIf { it.isNotBlank() } - ?: stringResource(R.string.unknown_studio), - style = MaterialTheme.typography.titleSmall, - modifier = Modifier - .secondaryItemAlpha() - .padding(top = 2.dp) - .clickableNoIndication( - onLongClick = { - if (!author.isNullOrBlank()) { - context.copyToClipboard( - author, - author, - ) - } - }, - onClick = { if (!author.isNullOrBlank()) doSearch(author, true) }, - ), - ) - if (!artist.isNullOrBlank() && author != artist) { + + Row( + modifier = Modifier.secondaryItemAlpha(), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = Icons.Filled.PersonOutline, + contentDescription = null, + modifier = Modifier.size(16.dp), + ) Text( - text = artist, + text = author?.takeIf { it.isNotBlank() } + ?: stringResource(R.string.unknown_author), style = MaterialTheme.typography.titleSmall, modifier = Modifier - .secondaryItemAlpha() - .padding(top = 2.dp) .clickableNoIndication( - onLongClick = { context.copyToClipboard(artist, artist) }, - onClick = { doSearch(artist, true) }, + onLongClick = { + if (!author.isNullOrBlank()) { + context.copyToClipboard( + author, + author, + ) + } + }, + onClick = { if (!author.isNullOrBlank()) doSearch(author, true) }, ), ) } - Spacer(modifier = Modifier.height(4.dp)) + + if (!artist.isNullOrBlank() && author != artist) { + Row( + modifier = Modifier.secondaryItemAlpha(), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = Icons.Filled.Brush, + contentDescription = null, + modifier = Modifier.size(16.dp), + ) + Text( + text = artist, + style = MaterialTheme.typography.titleSmall, + modifier = Modifier + .clickableNoIndication( + onLongClick = { context.copyToClipboard(artist, artist) }, + onClick = { doSearch(artist, true) }, + ), + ) + } + } + + Spacer(modifier = Modifier.height(2.dp)) + Row( modifier = Modifier.secondaryItemAlpha(), verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/java/eu/kanade/presentation/entries/manga/ChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/presentation/entries/manga/ChapterSettingsDialog.kt index f7a937507..3767e93ca 100644 --- a/app/src/main/java/eu/kanade/presentation/entries/manga/ChapterSettingsDialog.kt +++ b/app/src/main/java/eu/kanade/presentation/entries/manga/ChapterSettingsDialog.kt @@ -39,6 +39,7 @@ fun ChapterSettingsDialog( onSortModeChanged: (Long) -> Unit, onDisplayModeChanged: (Long) -> Unit, onSetAsDefault: (applyToExistingManga: Boolean) -> Unit, + onResetToDefault: () -> Unit, ) { var showSetAsDefaultDialog by rememberSaveable { mutableStateOf(false) } if (showSetAsDefaultDialog) { @@ -63,6 +64,13 @@ fun ChapterSettingsDialog( closeMenu() }, ) + DropdownMenuItem( + text = { Text(stringResource(R.string.action_reset)) }, + onClick = { + onResetToDefault() + closeMenu() + }, + ) }, ) { page -> Column( diff --git a/app/src/main/java/eu/kanade/presentation/entries/manga/components/MangaInfoHeader.kt b/app/src/main/java/eu/kanade/presentation/entries/manga/components/MangaInfoHeader.kt index 6ed4833bb..ca83c65c9 100644 --- a/app/src/main/java/eu/kanade/presentation/entries/manga/components/MangaInfoHeader.kt +++ b/app/src/main/java/eu/kanade/presentation/entries/manga/components/MangaInfoHeader.kt @@ -25,8 +25,10 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.text.selection.SelectionContainer import androidx.compose.material.LocalMinimumInteractiveComponentEnforcement import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Brush import androidx.compose.material.icons.filled.Favorite import androidx.compose.material.icons.filled.HourglassEmpty +import androidx.compose.material.icons.filled.PersonOutline import androidx.compose.material.icons.filled.Warning import androidx.compose.material.icons.outlined.AttachMoney import androidx.compose.material.icons.outlined.Block @@ -473,6 +475,7 @@ private fun MangaAndSourceTitlesSmall( modifier = Modifier .fillMaxWidth() .padding(start = 16.dp, top = appBarPadding + 16.dp, end = 16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), verticalAlignment = Alignment.CenterVertically, ) { ItemCover.Book( @@ -483,7 +486,9 @@ private fun MangaAndSourceTitlesSmall( contentDescription = stringResource(R.string.manga_cover), onClick = onCoverClick, ) - Column(modifier = Modifier.padding(start = 16.dp)) { + Column( + verticalArrangement = Arrangement.spacedBy(2.dp), + ) { Text( text = title.ifBlank { stringResource(R.string.unknown_title) }, style = MaterialTheme.typography.titleLarge, @@ -499,40 +504,62 @@ private fun MangaAndSourceTitlesSmall( onClick = { if (title.isNotBlank()) doSearch(title, true) }, ), ) + Spacer(modifier = Modifier.height(2.dp)) - Text( - text = author?.takeIf { it.isNotBlank() } - ?: stringResource(R.string.unknown_author), - style = MaterialTheme.typography.titleSmall, - modifier = Modifier - .secondaryItemAlpha() - .padding(top = 2.dp) - .clickableNoIndication( - onLongClick = { - if (!author.isNullOrBlank()) { - context.copyToClipboard( - author, - author, - ) - } - }, - onClick = { if (!author.isNullOrBlank()) doSearch(author, true) }, - ), - ) - if (!artist.isNullOrBlank() && author != artist) { + Row( + modifier = Modifier.secondaryItemAlpha(), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = Icons.Filled.PersonOutline, + contentDescription = null, + modifier = Modifier.size(16.dp), + ) Text( - text = artist, + text = author?.takeIf { it.isNotBlank() } + ?: stringResource(R.string.unknown_author), style = MaterialTheme.typography.titleSmall, modifier = Modifier - .secondaryItemAlpha() - .padding(top = 2.dp) .clickableNoIndication( - onLongClick = { context.copyToClipboard(artist, artist) }, - onClick = { doSearch(artist, true) }, + onLongClick = { + if (!author.isNullOrBlank()) { + context.copyToClipboard( + author, + author, + ) + } + }, + onClick = { if (!author.isNullOrBlank()) doSearch(author, true) }, ), ) } - Spacer(modifier = Modifier.height(4.dp)) + + if (!artist.isNullOrBlank() && author != artist) { + Row( + modifier = Modifier.secondaryItemAlpha(), + horizontalArrangement = Arrangement.spacedBy(4.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = Icons.Filled.Brush, + contentDescription = null, + modifier = Modifier.size(16.dp), + ) + Text( + text = artist, + style = MaterialTheme.typography.titleSmall, + modifier = Modifier + .clickableNoIndication( + onLongClick = { context.copyToClipboard(artist, artist) }, + onClick = { doSearch(artist, true) }, + ), + ) + } + } + + Spacer(modifier = Modifier.height(2.dp)) + Row( modifier = Modifier.secondaryItemAlpha(), verticalAlignment = Alignment.CenterVertically, diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt index e54b8a89f..03c58007e 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsAdvancedScreen.kt @@ -65,7 +65,7 @@ import okhttp3.Headers import tachiyomi.core.util.lang.launchNonCancellable import tachiyomi.core.util.lang.withUIContext import tachiyomi.core.util.system.logcat -import tachiyomi.domain.entries.manga.repository.MangaRepository +import tachiyomi.domain.entries.manga.interactor.ResetMangaViewerFlags import tachiyomi.presentation.core.util.collectAsState import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -336,7 +336,7 @@ object SettingsAdvancedScreen : SearchableSettings { subtitle = stringResource(R.string.pref_reset_viewer_flags_summary), onClick = { scope.launchNonCancellable { - val success = Injekt.get().resetMangaViewerFlags() + val success = Injekt.get().await() withUIContext { val message = if (success) { R.string.pref_reset_viewer_flags_success diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt index 8acb536c3..21be0053e 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/SettingsReaderScreen.kt @@ -64,6 +64,11 @@ object SettingsReaderScreen : SearchableSettings { pref = readerPref.pageTransitions(), title = stringResource(R.string.pref_page_transitions), ), + Preference.PreferenceItem.SwitchPreference( + pref = readerPref.flashOnPageChange(), + title = stringResource(R.string.pref_flash_page), + subtitle = stringResource(R.string.pref_flash_page_summ), + ), getDisplayGroup(readerPreferences = readerPref), getReadingGroup(readerPreferences = readerPref), getPagedGroup(readerPreferences = readerPref), diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearAnimeDatabaseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearAnimeDatabaseScreen.kt index dd6c9e6f3..5e746a8cc 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearAnimeDatabaseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearAnimeDatabaseScreen.kt @@ -31,8 +31,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastMap 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.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.anime.components.AnimeSourceIcon @@ -216,7 +216,7 @@ private class ClearAnimeDatabaseScreenModel : StateScreenModel mutableState.update { old -> diff --git a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt index 860378b9d..b1d8ca71f 100644 --- a/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/more/settings/screen/advanced/ClearDatabaseScreen.kt @@ -31,8 +31,8 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.compose.ui.util.fastMap 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.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import eu.kanade.presentation.browse.manga.components.MangaSourceIcon @@ -216,7 +216,7 @@ private class ClearDatabaseScreenModel : StateScreenModel mutableState.update { old -> diff --git a/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt b/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt index 144b8ea27..b945906a4 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/BrightnessOverlay.kt @@ -1,5 +1,6 @@ package eu.kanade.presentation.reader +import androidx.annotation.IntRange import androidx.compose.foundation.Canvas import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable @@ -10,7 +11,7 @@ import kotlin.math.abs @Composable fun BrightnessOverlay( - value: Int, + @IntRange(from = -100, to = 100) value: Int, ) { if (value >= 0) return diff --git a/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt b/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt new file mode 100644 index 000000000..018dbb948 --- /dev/null +++ b/app/src/main/java/eu/kanade/presentation/reader/DisplayRefreshHost.kt @@ -0,0 +1,45 @@ +package eu.kanade.presentation.reader + +import androidx.compose.foundation.Canvas +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.setValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import kotlinx.coroutines.delay + +@Stable +class DisplayRefreshHost { + + internal var currentDisplayRefresh by mutableStateOf(false) + + fun flash() { + currentDisplayRefresh = true + } +} + +@Composable +fun DisplayRefreshHost( + hostState: DisplayRefreshHost, + modifier: Modifier = Modifier, +) { + val currentDisplayRefresh = hostState.currentDisplayRefresh + LaunchedEffect(currentDisplayRefresh) { + if (currentDisplayRefresh) { + delay(200) + hostState.currentDisplayRefresh = false + } + } + + if (currentDisplayRefresh) { + Canvas( + modifier = modifier.fillMaxSize(), + ) { + drawRect(Color.White) + } + } +} diff --git a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt index 8d165ec76..5fe65eb2f 100644 --- a/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt +++ b/app/src/main/java/eu/kanade/presentation/reader/settings/GeneralSettingsPage.kt @@ -68,4 +68,9 @@ internal fun ColumnScope.GeneralPage(screenModel: ReaderSettingsScreenModel) { label = stringResource(R.string.pref_page_transitions), pref = screenModel.preferences.pageTransitions(), ) + + CheckboxItem( + label = stringResource(R.string.pref_flash_page), + pref = screenModel.preferences.flashOnPageChange(), + ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionFilterScreenModel.kt index c5283ce07..068a22794 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionFilterScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.extension import androidx.compose.runtime.Immutable 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.anime.interactor.GetAnimeExtensionLanguages import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.ToggleLanguage @@ -29,7 +29,7 @@ class AnimeExtensionFilterScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { combine( getExtensionLanguages.subscribe(), preferences.enabledLanguages().changes(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsScreenModel.kt index 919e4523a..41b902f75 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/AnimeExtensionsScreenModel.kt @@ -4,7 +4,7 @@ import android.app.Application import androidx.annotation.StringRes import androidx.compose.runtime.Immutable 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.anime.interactor.GetAnimeExtensionsByType import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS @@ -84,7 +84,7 @@ class AnimeExtensionsScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { combine( state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), _currentDownloads, @@ -136,11 +136,11 @@ class AnimeExtensionsScreenModel( } } } - coroutineScope.launchIO { findAvailableExtensions() } + screenModelScope.launchIO { findAvailableExtensions() } preferences.animeExtensionUpdatesCount().changes() .onEach { mutableState.update { state -> state.copy(updates = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } fun search(query: String?) { @@ -150,7 +150,7 @@ class AnimeExtensionsScreenModel( } fun updateAllExtensions() { - coroutineScope.launchIO { + screenModelScope.launchIO { state.value.items.values.flatten() .map { it.extension } .filterIsInstance() @@ -160,13 +160,13 @@ class AnimeExtensionsScreenModel( } fun installExtension(extension: AnimeExtension.Available) { - coroutineScope.launchIO { + screenModelScope.launchIO { extensionManager.installExtension(extension).collectToInstallUpdate(extension) } } fun updateExtension(extension: AnimeExtension.Installed) { - coroutineScope.launchIO { + screenModelScope.launchIO { extensionManager.updateExtension(extension).collectToInstallUpdate(extension) } } @@ -194,7 +194,7 @@ class AnimeExtensionsScreenModel( } fun findAvailableExtensions() { - coroutineScope.launchIO { + screenModelScope.launchIO { mutableState.update { it.copy(isRefreshing = true) } extensionManager.findAvailableExtensions() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/details/AnimeExtensionDetailsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/details/AnimeExtensionDetailsScreenModel.kt index 58bfbc95c..5d9a5e68f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/details/AnimeExtensionDetailsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/extension/details/AnimeExtensionDetailsScreenModel.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.extension.details import android.content.Context import androidx.compose.runtime.Immutable 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.anime.interactor.AnimeExtensionSourceItem import eu.kanade.domain.extension.anime.interactor.GetAnimeExtensionSources import eu.kanade.domain.source.anime.interactor.ToggleAnimeSource @@ -44,7 +44,7 @@ class AnimeExtensionDetailsScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { launch { extensionManager.installedExtensionsFlow .map { it.firstOrNull { extension -> extension.pkgName == pkgName } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/anime/MigrateAnimeScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/anime/MigrateAnimeScreenModel.kt index f334a73ac..d408a6df9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/anime/MigrateAnimeScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/anime/MigrateAnimeScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.migration.anime import androidx.compose.runtime.Immutable 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.animesource.AnimeSource import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow @@ -30,7 +30,7 @@ class MigrateAnimeScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { mutableState.update { state -> state.copy(source = sourceManager.getOrStub(sourceId)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/AnimeMigrateSearchScreenDialogScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/AnimeMigrateSearchScreenDialogScreenModel.kt index 83bd3e3fc..105905027 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/AnimeMigrateSearchScreenDialogScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/AnimeMigrateSearchScreenDialogScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.migration.search import androidx.compose.runtime.Immutable 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.launch import tachiyomi.domain.entries.anime.interactor.GetAnime @@ -16,7 +16,7 @@ class AnimeMigrateSearchScreenDialogScreenModel( ) : StateScreenModel(State()) { init { - coroutineScope.launch { + screenModelScope.launch { val anime = getAnime.await(animeId)!! mutableState.update { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/MigrateAnimeSearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/MigrateAnimeSearchScreenModel.kt index 79ae7cad0..a1b1d005b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/MigrateAnimeSearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/search/MigrateAnimeSearchScreenModel.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.anime.migration.search -import cafe.adriel.voyager.core.model.coroutineScope +import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.tachiyomi.animesource.AnimeCatalogueSource import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.AnimeSearchScreenModel import eu.kanade.tachiyomi.ui.browse.anime.source.globalsearch.AnimeSourceFilter @@ -18,7 +18,7 @@ class MigrateAnimeSearchScreenModel( init { extensionFilter = initialExtensionFilter - coroutineScope.launch { + screenModelScope.launch { val anime = getAnime.await(animeId)!! mutableState.update { it.copy( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/sources/MigrateAnimeSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/sources/MigrateAnimeSourceScreenModel.kt index b975573aa..4088003f0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/sources/MigrateAnimeSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/migration/sources/MigrateAnimeSourceScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.migration.sources import androidx.compose.runtime.Immutable 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.anime.interactor.GetAnimeSourcesWithFavoriteCount import eu.kanade.domain.source.service.SetMigrateSorting import eu.kanade.domain.source.service.SourcePreferences @@ -30,7 +30,7 @@ class MigrateAnimeSourceScreenModel( val channel = _channel.receiveAsFlow() init { - coroutineScope.launchIO { + screenModelScope.launchIO { getSourcesWithFavoriteCount.subscribe() .catch { logcat(LogPriority.ERROR, it) @@ -48,11 +48,11 @@ class MigrateAnimeSourceScreenModel( preferences.migrationSortingDirection().changes() .onEach { mutableState.update { state -> state.copy(sortingDirection = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) preferences.migrationSortingMode().changes() .onEach { mutableState.update { state -> state.copy(sortingMode = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } fun toggleSortingMode() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesFilterScreenModel.kt index 113ca7d44..73bd9f924 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesFilterScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.source import androidx.compose.runtime.Immutable 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.anime.interactor.GetLanguagesWithAnimeSources import eu.kanade.domain.source.anime.interactor.ToggleAnimeSource import eu.kanade.domain.source.service.SourcePreferences @@ -25,7 +25,7 @@ class AnimeSourcesFilterScreenModel( ) : StateScreenModel(State.Loading) { init { - coroutineScope.launch { + screenModelScope.launch { combine( getLanguagesWithSources.subscribe(), preferences.enabledLanguages().changes(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesScreenModel.kt index 64f3777c5..6900bc7f1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/AnimeSourcesScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.anime.source import androidx.compose.runtime.Immutable 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.base.BasePreferences import eu.kanade.domain.source.anime.interactor.GetEnabledAnimeSources import eu.kanade.domain.source.anime.interactor.ToggleAnimeSource @@ -37,7 +37,7 @@ class AnimeSourcesScreenModel( val events = _events.receiveAsFlow() init { - coroutineScope.launchIO { + screenModelScope.launchIO { getEnabledAnimeSources.subscribe() .catch { logcat(LogPriority.ERROR, it) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/browse/BrowseAnimeSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/browse/BrowseAnimeSourceScreenModel.kt index 86d9c83f6..f28ad5873 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/browse/BrowseAnimeSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/anime/source/browse/BrowseAnimeSourceScreenModel.kt @@ -12,7 +12,7 @@ import androidx.paging.cachedIn import androidx.paging.filter import androidx.paging.map 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.domain.base.BasePreferences import eu.kanade.domain.entries.anime.interactor.UpdateAnime @@ -72,7 +72,7 @@ class BrowseAnimeSourceScreenModel( private val addTracks: AddAnimeTracks = Injekt.get(), ) : StateScreenModel(State(Listing.valueOf(listingQuery))) { - var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) + var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope) val source = sourceManager.getOrStub(sourceId) @@ -219,7 +219,7 @@ class BrowseAnimeSourceScreenModel( * @param anime the anime to update. */ fun changeAnimeFavorite(anime: Anime) { - coroutineScope.launch { + screenModelScope.launch { var new = anime.copy( favorite = !anime.favorite, dateAdded = when (anime.favorite) { @@ -240,7 +240,7 @@ class BrowseAnimeSourceScreenModel( } fun addFavorite(anime: Anime) { - coroutineScope.launch { + screenModelScope.launch { val categories = getCategories() val defaultCategoryId = libraryPreferences.defaultAnimeCategory().get() val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() } @@ -294,7 +294,7 @@ class BrowseAnimeSourceScreenModel( } fun moveAnimeToCategories(anime: Anime, categoryIds: List) { - coroutineScope.launchIO { + screenModelScope.launchIO { setAnimeCategories.await( animeId = anime.id, categoryIds = categoryIds.toList(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionFilterScreenModel.kt index 5a82a6b46..2eeeb956a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionFilterScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.extension import androidx.compose.runtime.Immutable 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.manga.interactor.GetMangaExtensionLanguages import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.source.service.ToggleLanguage @@ -29,7 +29,7 @@ class MangaExtensionFilterScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { combine( getExtensionLanguages.subscribe(), preferences.enabledLanguages().changes(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsScreenModel.kt index f60b5fceb..43fe291e2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/MangaExtensionsScreenModel.kt @@ -4,7 +4,7 @@ import android.app.Application import androidx.annotation.StringRes import androidx.compose.runtime.Immutable 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.manga.interactor.GetMangaExtensionsByType import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.presentation.components.SEARCH_DEBOUNCE_MILLIS @@ -84,7 +84,7 @@ class MangaExtensionsScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { combine( state.map { it.searchQuery }.distinctUntilChanged().debounce(SEARCH_DEBOUNCE_MILLIS), _currentDownloads, @@ -137,11 +137,11 @@ class MangaExtensionsScreenModel( } } - coroutineScope.launchIO { findAvailableExtensions() } + screenModelScope.launchIO { findAvailableExtensions() } preferences.mangaExtensionUpdatesCount().changes() .onEach { mutableState.update { state -> state.copy(updates = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } fun search(query: String?) { @@ -151,7 +151,7 @@ class MangaExtensionsScreenModel( } fun updateAllExtensions() { - coroutineScope.launchIO { + screenModelScope.launchIO { state.value.items.values.flatten() .map { it.extension } .filterIsInstance() @@ -161,13 +161,13 @@ class MangaExtensionsScreenModel( } fun installExtension(extension: MangaExtension.Available) { - coroutineScope.launchIO { + screenModelScope.launchIO { extensionManager.installExtension(extension).collectToInstallUpdate(extension) } } fun updateExtension(extension: MangaExtension.Installed) { - coroutineScope.launchIO { + screenModelScope.launchIO { extensionManager.updateExtension(extension).collectToInstallUpdate(extension) } } @@ -195,7 +195,7 @@ class MangaExtensionsScreenModel( } fun findAvailableExtensions() { - coroutineScope.launchIO { + screenModelScope.launchIO { mutableState.update { it.copy(isRefreshing = true) } extensionManager.findAvailableExtensions() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/details/MangaExtensionDetailsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/details/MangaExtensionDetailsScreenModel.kt index 2a2ba1cb1..77d0f04ed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/details/MangaExtensionDetailsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/extension/details/MangaExtensionDetailsScreenModel.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.extension.details import android.content.Context import androidx.compose.runtime.Immutable 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.manga.interactor.GetExtensionSources import eu.kanade.domain.extension.manga.interactor.MangaExtensionSourceItem import eu.kanade.domain.source.manga.interactor.ToggleMangaSource @@ -44,7 +44,7 @@ class MangaExtensionDetailsScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { launch { extensionManager.installedExtensionsFlow .map { it.firstOrNull { extension -> extension.pkgName == pkgName } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/manga/MigrateMangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/manga/MigrateMangaScreenModel.kt index 2406a7ba9..2be87fd13 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/manga/MigrateMangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/manga/MigrateMangaScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.migration.manga import androidx.compose.runtime.Immutable 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.MangaSource import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow @@ -30,7 +30,7 @@ class MigrateMangaScreenModel( val events: Flow = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { mutableState.update { state -> state.copy(source = sourceManager.getOrStub(sourceId)) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MangaMigrateSearchScreenDialogScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MangaMigrateSearchScreenDialogScreenModel.kt index fa9267434..dbe51aaa0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MangaMigrateSearchScreenDialogScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MangaMigrateSearchScreenDialogScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.migration.search import androidx.compose.runtime.Immutable 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.launch import tachiyomi.domain.entries.manga.interactor.GetManga @@ -16,7 +16,7 @@ class MangaMigrateSearchScreenDialogScreenModel( ) : StateScreenModel(State()) { init { - coroutineScope.launch { + screenModelScope.launch { val manga = getManga.await(mangaId)!! mutableState.update { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MigrateMangaSearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MigrateMangaSearchScreenModel.kt index 0eaf37a35..f92ddd254 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MigrateMangaSearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/search/MigrateMangaSearchScreenModel.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.manga.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.ui.browse.manga.source.globalsearch.MangaSearchScreenModel import eu.kanade.tachiyomi.ui.browse.manga.source.globalsearch.MangaSourceFilter @@ -18,7 +18,7 @@ class MigrateMangaSearchScreenModel( init { extensionFilter = initialExtensionFilter - coroutineScope.launch { + screenModelScope.launch { val manga = getManga.await(mangaId)!! mutableState.update { it.copy( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/sources/MigrateMangaSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/sources/MigrateMangaSourceScreenModel.kt index ce8b0463f..03bfc4082 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/sources/MigrateMangaSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/migration/sources/MigrateMangaSourceScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.migration.sources import androidx.compose.runtime.Immutable 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.manga.interactor.GetMangaSourcesWithFavoriteCount import eu.kanade.domain.source.service.SetMigrateSorting import eu.kanade.domain.source.service.SourcePreferences @@ -30,7 +30,7 @@ class MigrateMangaSourceScreenModel( val channel = _channel.receiveAsFlow() init { - coroutineScope.launchIO { + screenModelScope.launchIO { getSourcesWithFavoriteCount.subscribe() .catch { logcat(LogPriority.ERROR, it) @@ -48,11 +48,11 @@ class MigrateMangaSourceScreenModel( preferences.migrationSortingDirection().changes() .onEach { mutableState.update { state -> state.copy(sortingDirection = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) preferences.migrationSortingMode().changes() .onEach { mutableState.update { state -> state.copy(sortingMode = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } fun toggleSortingMode() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesFilterScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesFilterScreenModel.kt index 84d2505ad..61d650e1d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesFilterScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesFilterScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.source import androidx.compose.runtime.Immutable 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.manga.interactor.GetLanguagesWithMangaSources import eu.kanade.domain.source.manga.interactor.ToggleMangaSource import eu.kanade.domain.source.service.SourcePreferences @@ -25,7 +25,7 @@ class MangaSourcesFilterScreenModel( ) : StateScreenModel(State.Loading) { init { - coroutineScope.launch { + screenModelScope.launch { combine( getLanguagesWithSources.subscribe(), preferences.enabledLanguages().changes(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesScreenModel.kt index 13b14bfcd..2774b8a58 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/MangaSourcesScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.browse.manga.source import androidx.compose.runtime.Immutable 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.base.BasePreferences import eu.kanade.domain.source.manga.interactor.GetEnabledMangaSources import eu.kanade.domain.source.manga.interactor.ToggleExcludeFromMangaDataSaver @@ -44,7 +44,7 @@ class MangaSourcesScreenModel( val events = _events.receiveAsFlow() init { - coroutineScope.launchIO { + screenModelScope.launchIO { getEnabledSources.subscribe() .catch { logcat(LogPriority.ERROR, it) @@ -61,7 +61,7 @@ class MangaSourcesScreenModel( ) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) // SY <-- } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/browse/BrowseMangaSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/browse/BrowseMangaSourceScreenModel.kt index bdb635886..4aadba7c0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/browse/BrowseMangaSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/manga/source/browse/BrowseMangaSourceScreenModel.kt @@ -12,7 +12,7 @@ import androidx.paging.cachedIn import androidx.paging.filter import androidx.paging.map 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.domain.base.BasePreferences import eu.kanade.domain.entries.manga.interactor.UpdateManga @@ -72,7 +72,7 @@ class BrowseMangaSourceScreenModel( private val addTracks: AddMangaTracks = Injekt.get(), ) : StateScreenModel(State(Listing.valueOf(listingQuery))) { - var displayMode by sourcePreferences.sourceDisplayMode().asState(coroutineScope) + var displayMode by sourcePreferences.sourceDisplayMode().asState(screenModelScope) val source = sourceManager.getOrStub(sourceId) @@ -220,7 +220,7 @@ class BrowseMangaSourceScreenModel( * @param manga the manga to update. */ fun changeMangaFavorite(manga: Manga) { - coroutineScope.launch { + screenModelScope.launch { var new = manga.copy( favorite = !manga.favorite, dateAdded = when (manga.favorite) { @@ -241,7 +241,7 @@ class BrowseMangaSourceScreenModel( } fun addFavorite(manga: Manga) { - coroutineScope.launch { + screenModelScope.launch { val categories = getCategories() val defaultCategoryId = libraryPreferences.defaultMangaCategory().get() val defaultCategory = categories.find { it.id == defaultCategoryId.toLong() } @@ -296,7 +296,7 @@ class BrowseMangaSourceScreenModel( } fun moveMangaToCategories(manga: Manga, categoryIds: List) { - coroutineScope.launchIO { + screenModelScope.launchIO { setMangaCategories.await( mangaId = manga.id, categoryIds = categoryIds.toList(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/anime/AnimeCategoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/anime/AnimeCategoryScreenModel.kt index bf26c5cab..7743bdfb6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/anime/AnimeCategoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/anime/AnimeCategoryScreenModel.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.category.anime import androidx.annotation.StringRes import androidx.compose.runtime.Immutable 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 kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest @@ -37,7 +37,7 @@ class AnimeCategoryScreenModel( val events = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { val allCategories = if (libraryPreferences.hideHiddenCategoriesSettings().get()) { getVisibleCategories.subscribe() } else { @@ -55,7 +55,7 @@ class AnimeCategoryScreenModel( } fun createCategory(name: String) { - coroutineScope.launch { + screenModelScope.launch { when (createCategoryWithName.await(name)) { is CreateAnimeCategoryWithName.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, @@ -67,7 +67,7 @@ class AnimeCategoryScreenModel( } fun hideCategory(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (hideCategory.await(category)) { is HideAnimeCategory.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, @@ -78,7 +78,7 @@ class AnimeCategoryScreenModel( } fun deleteCategory(categoryId: Long) { - coroutineScope.launch { + screenModelScope.launch { when (deleteCategory.await(categoryId = categoryId)) { is DeleteAnimeCategory.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, @@ -89,7 +89,7 @@ class AnimeCategoryScreenModel( } fun sortAlphabetically() { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.sortAlphabetically()) { is ReorderAnimeCategory.Result.InternalError -> _events.send(AnimeCategoryEvent.InternalError) else -> {} @@ -98,7 +98,7 @@ class AnimeCategoryScreenModel( } fun moveUp(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.moveUp(category)) { is ReorderAnimeCategory.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, @@ -109,7 +109,7 @@ class AnimeCategoryScreenModel( } fun moveDown(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.moveDown(category)) { is ReorderAnimeCategory.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, @@ -120,7 +120,7 @@ class AnimeCategoryScreenModel( } fun renameCategory(category: Category, name: String) { - coroutineScope.launch { + screenModelScope.launch { when (renameCategory.await(category, name)) { is RenameAnimeCategory.Result.InternalError -> _events.send( AnimeCategoryEvent.InternalError, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/manga/MangaCategoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/manga/MangaCategoryScreenModel.kt index 92cf95607..fee4f6b90 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/manga/MangaCategoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/manga/MangaCategoryScreenModel.kt @@ -3,7 +3,7 @@ package eu.kanade.tachiyomi.ui.category.manga import androidx.annotation.StringRes import androidx.compose.runtime.Immutable 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 kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.collectLatest @@ -37,7 +37,7 @@ class MangaCategoryScreenModel( val events = _events.receiveAsFlow() init { - coroutineScope.launch { + screenModelScope.launch { val allCategories = if (libraryPreferences.hideHiddenCategoriesSettings().get()) { getVisibleCategories.subscribe() } else { @@ -55,7 +55,7 @@ class MangaCategoryScreenModel( } fun createCategory(name: String) { - coroutineScope.launch { + screenModelScope.launch { when (createCategoryWithName.await(name)) { is CreateMangaCategoryWithName.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, @@ -67,7 +67,7 @@ class MangaCategoryScreenModel( } fun hideCategory(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (hideCategory.await(category)) { is HideMangaCategory.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, @@ -78,7 +78,7 @@ class MangaCategoryScreenModel( } fun deleteCategory(categoryId: Long) { - coroutineScope.launch { + screenModelScope.launch { when (deleteCategory.await(categoryId = categoryId)) { is DeleteMangaCategory.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, @@ -89,7 +89,7 @@ class MangaCategoryScreenModel( } fun sortAlphabetically() { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.sortAlphabetically()) { is ReorderMangaCategory.Result.InternalError -> _events.send(MangaCategoryEvent.InternalError) else -> {} @@ -98,7 +98,7 @@ class MangaCategoryScreenModel( } fun moveUp(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.moveUp(category)) { is ReorderMangaCategory.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, @@ -109,7 +109,7 @@ class MangaCategoryScreenModel( } fun moveDown(category: Category) { - coroutineScope.launch { + screenModelScope.launch { when (reorderCategory.moveDown(category)) { is ReorderMangaCategory.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, @@ -120,7 +120,7 @@ class MangaCategoryScreenModel( } fun renameCategory(category: Category, name: String) { - coroutineScope.launch { + screenModelScope.launch { when (renameCategory.await(category, name)) { is RenameMangaCategory.Result.InternalError -> _events.send( MangaCategoryEvent.InternalError, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/anime/DeepLinkAnimeScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/anime/DeepLinkAnimeScreenModel.kt index 01738e3bd..a26b2c278 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/anime/DeepLinkAnimeScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/anime/DeepLinkAnimeScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.deeplink.anime import androidx.compose.runtime.Immutable 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.entries.anime.model.toDomainAnime import eu.kanade.domain.entries.anime.model.toSAnime import eu.kanade.domain.items.episode.interactor.SyncEpisodesWithSource @@ -32,7 +32,7 @@ class DeepLinkAnimeScreenModel( ) : StateScreenModel(State.Loading) { init { - coroutineScope.launchIO { + screenModelScope.launchIO { val source = sourceManager.getCatalogueSources() .filterIsInstance() .firstOrNull { it.getUriType(query) != UriType.Unknown } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/manga/DeepLinkMangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/manga/DeepLinkMangaScreenModel.kt index dbec6812c..fad594a5a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/manga/DeepLinkMangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/deeplink/manga/DeepLinkMangaScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.deeplink.manga import androidx.compose.runtime.Immutable 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.entries.manga.model.toDomainManga import eu.kanade.domain.entries.manga.model.toSManga import eu.kanade.domain.items.chapter.interactor.SyncChaptersWithSource @@ -32,7 +32,7 @@ class DeepLinkMangaScreenModel( ) : StateScreenModel(State.Loading) { init { - coroutineScope.launchIO { + screenModelScope.launchIO { val source = sourceManager.getCatalogueSources() .filterIsInstance() .firstOrNull { it.getUriType(query) != UriType.Unknown } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/anime/AnimeDownloadQueueScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/anime/AnimeDownloadQueueScreenModel.kt index 61a6aeae5..ad7fdb6f4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/anime/AnimeDownloadQueueScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/anime/AnimeDownloadQueueScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.download.anime import android.view.MenuItem 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.data.download.anime.AnimeDownloadManager import eu.kanade.tachiyomi.data.download.anime.model.AnimeDownload @@ -108,7 +108,7 @@ class AnimeDownloadQueueScreenModel( } init { - coroutineScope.launch { + screenModelScope.launch { downloadManager.queueState .map { downloads -> downloads diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/manga/MangaDownloadQueueScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/manga/MangaDownloadQueueScreenModel.kt index a866ba778..e0ad3607d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/manga/MangaDownloadQueueScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/manga/MangaDownloadQueueScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.download.manga import android.view.MenuItem 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.data.download.manga.MangaDownloadManager import eu.kanade.tachiyomi.data.download.manga.model.MangaDownload @@ -114,7 +114,7 @@ class MangaDownloadQueueScreenModel( } init { - coroutineScope.launch { + screenModelScope.launch { downloadManager.queueState .map { downloads -> downloads @@ -211,7 +211,7 @@ class MangaDownloadQueueScreenModel( * @param download the download to observe its progress. */ private fun launchProgressJob(download: MangaDownload) { - val job = coroutineScope.launch { + val job = screenModelScope.launch { while (download.pages == null) { delay(50) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeCoverScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeCoverScreenModel.kt index f843d5baf..80457c28f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeCoverScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeCoverScreenModel.kt @@ -4,7 +4,7 @@ import android.content.Context import android.net.Uri import androidx.compose.material3.SnackbarHostState 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.request.ImageRequest import coil.size.Size @@ -40,14 +40,14 @@ class AnimeCoverScreenModel( ) : StateScreenModel(null) { init { - coroutineScope.launchIO { + screenModelScope.launchIO { getAnime.subscribe(animeId) .collect { newAnime -> mutableState.update { newAnime } } } } fun saveCover(context: Context) { - coroutineScope.launch { + screenModelScope.launch { try { saveCoverInternal(context, temp = false) snackbarHostState.showSnackbar( @@ -65,7 +65,7 @@ class AnimeCoverScreenModel( } fun shareCover(context: Context) { - coroutineScope.launch { + screenModelScope.launch { try { val uri = saveCoverInternal(context, temp = true) ?: return@launch withUIContext { @@ -117,7 +117,7 @@ class AnimeCoverScreenModel( */ fun editCover(context: Context, data: Uri) { val anime = state.value ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { context.contentResolver.openInputStream(data)?.use { try { anime.editCover(Injekt.get(), it, updateAnime, coverCache) @@ -131,7 +131,7 @@ class AnimeCoverScreenModel( fun deleteCustomCover(context: Context) { val animeId = state.value?.id ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { try { coverCache.deleteCustomCover(animeId) updateAnime.awaitUpdateCoverLastModified(animeId) @@ -143,7 +143,7 @@ class AnimeCoverScreenModel( } private fun notifyCoverUpdated(context: Context) { - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar( context.getString(R.string.cover_updated), withDismissAction = true, @@ -152,7 +152,7 @@ class AnimeCoverScreenModel( } private fun notifyFailedCoverUpdate(context: Context, e: Throwable) { - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar( context.getString(R.string.notification_cover_update_failed), withDismissAction = true, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreenModel.kt index 27f4c1da2..0aaebf0b8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/AnimeScreenModel.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf 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.util.addOrRemove import eu.kanade.domain.entries.anime.interactor.SetAnimeViewerFlags @@ -135,7 +135,7 @@ class AnimeScreenModel( val alwaysUseExternalPlayer = playerPreferences.alwaysUseExternalPlayer().get() val useExternalDownloader = downloadPreferences.useExternalDownloader().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 isUpdateIntervalEnabled = LibraryPreferences.ENTRY_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateItemRestrictions().get() @@ -161,7 +161,7 @@ class AnimeScreenModel( } init { - coroutineScope.launchIO { + screenModelScope.launchIO { combine( getAnimeAndEpisodes.subscribe(animeId).distinctUntilChanged(), downloadCache.changes, @@ -179,7 +179,7 @@ class AnimeScreenModel( observeDownloads() - coroutineScope.launchIO { + screenModelScope.launchIO { val anime = getAnimeAndEpisodes.awaitAnime(animeId) val episodes = getAnimeAndEpisodes.awaitEpisodes(animeId) .toEpisodeItems(anime) @@ -206,7 +206,7 @@ class AnimeScreenModel( observeTrackers() // Fetch info-episodes when needed - if (coroutineScope.isActive) { + if (screenModelScope.isActive) { val fetchFromSourceTasks = listOf( async { if (needRefreshInfo) fetchAnimeFromSource() }, async { if (needRefreshEpisode) fetchEpisodesFromSource() }, @@ -220,7 +220,7 @@ class AnimeScreenModel( } fun fetchAllFromSource(manualFetch: Boolean = true) { - coroutineScope.launch { + screenModelScope.launch { updateSuccessState { it.copy(isRefreshingData = true) } val fetchFromSourceTasks = listOf( async { fetchAnimeFromSource(manualFetch) }, @@ -249,7 +249,7 @@ class AnimeScreenModel( if (e is HttpException && e.code == 103) return logcat(LogPriority.ERROR, e) - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar(message = with(context) { e.formattedMessage }) } } @@ -258,7 +258,7 @@ class AnimeScreenModel( fun toggleFavorite() { toggleFavorite( onRemoved = { - coroutineScope.launch { + screenModelScope.launch { if (!hasDownloads()) return@launch val result = snackbarHostState.showSnackbar( message = context.getString(R.string.delete_downloads_for_anime), @@ -281,7 +281,7 @@ class AnimeScreenModel( checkDuplicate: Boolean = true, ) { val state = successState ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { val anime = state.anime if (isFavorited) { @@ -345,7 +345,7 @@ class AnimeScreenModel( fun showChangeCategoryDialog() { val anime = successState?.anime ?: return - coroutineScope.launch { + screenModelScope.launch { val categories = getCategories() val selection = getAnimeCategoryIds(anime) updateSuccessState { successState -> @@ -367,7 +367,7 @@ class AnimeScreenModel( } fun setFetchInterval(anime: Anime, interval: Int) { - coroutineScope.launchIO { + screenModelScope.launchIO { updateAnime.awaitUpdateFetchInterval( // Custom intervals are negative anime.copy(fetchInterval = -interval), @@ -417,7 +417,7 @@ class AnimeScreenModel( moveAnimeToCategory(categories) if (anime.favorite) return - coroutineScope.launchIO { + screenModelScope.launchIO { updateAnime.awaitUpdateFavorite(anime.id, true) } } @@ -433,7 +433,7 @@ class AnimeScreenModel( } private fun moveAnimeToCategory(categoryIds: List) { - coroutineScope.launchIO { + screenModelScope.launchIO { setAnimeCategories.await(animeId, categoryIds) } } @@ -452,7 +452,7 @@ class AnimeScreenModel( // Episodes list - start private fun observeDownloads() { - coroutineScope.launchIO { + screenModelScope.launchIO { downloadManager.statusFlow() .filter { it.anime.id == successState?.anime?.id } .catch { error -> logcat(LogPriority.ERROR, error) } @@ -463,7 +463,7 @@ class AnimeScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { downloadManager.progressFlow() .filter { it.anime.id == successState?.anime?.id } .catch { error -> logcat(LogPriority.ERROR, error) } @@ -550,7 +550,7 @@ class AnimeScreenModel( with(context) { e.formattedMessage } } - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar(message = message) } val newAnime = animeRepository.getAnimeById(animeId) @@ -562,7 +562,7 @@ class AnimeScreenModel( * @throws IllegalStateException if the swipe action is [LibraryPreferences.EpisodeSwipeAction.Disabled] */ fun episodeSwipe(episodeItem: EpisodeItem, swipeAction: LibraryPreferences.EpisodeSwipeAction) { - coroutineScope.launch { + screenModelScope.launch { executeEpisodeSwipeAction(episodeItem, swipeAction) } } @@ -640,7 +640,7 @@ class AnimeScreenModel( updateSuccessState { state -> state.copy(hasPromptedToAddBefore = true) } - coroutineScope.launch { + screenModelScope.launch { val result = snackbarHostState.showSnackbar( message = context.getString(R.string.snack_add_to_anime_library), actionLabel = context.getString(R.string.action_add), @@ -716,7 +716,7 @@ class AnimeScreenModel( * @param seen whether to mark episodes as seen or unseen. */ fun markEpisodesSeen(episodes: List, seen: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { setSeenStatus.await( seen = seen, episodes = episodes.toTypedArray(), @@ -744,7 +744,7 @@ class AnimeScreenModel( * @param episodes the list of episodes to bookmark. */ fun bookmarkEpisodes(episodes: List, bookmarked: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { episodes .filterNot { it.bookmark == bookmarked } .map { EpisodeUpdate(id = it.id, bookmark = bookmarked) } @@ -759,7 +759,7 @@ class AnimeScreenModel( * @param episodes the list of episodes to delete. */ fun deleteEpisodes(episodes: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { try { successState?.let { state -> downloadManager.deleteEpisodes( @@ -775,7 +775,7 @@ class AnimeScreenModel( } private fun downloadNewEpisodes(episodes: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val anime = successState?.anime ?: return@launchNonCancellable val categories = getCategories.await(anime.id).map { it.id } if (episodes.isEmpty() || !anime.shouldDownloadNewEpisodes( @@ -801,7 +801,7 @@ class AnimeScreenModel( TriState.ENABLED_IS -> Anime.EPISODE_SHOW_UNSEEN TriState.ENABLED_NOT -> Anime.EPISODE_SHOW_SEEN } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setAnimeEpisodeFlags.awaitSetUnseenFilter(anime, flag) } } @@ -819,7 +819,7 @@ class AnimeScreenModel( TriState.ENABLED_NOT -> Anime.EPISODE_SHOW_NOT_DOWNLOADED } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setAnimeEpisodeFlags.awaitSetDownloadedFilter(anime, flag) } } @@ -837,7 +837,7 @@ class AnimeScreenModel( TriState.ENABLED_NOT -> Anime.EPISODE_SHOW_NOT_BOOKMARKED } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setAnimeEpisodeFlags.awaitSetBookmarkFilter(anime, flag) } } @@ -849,7 +849,7 @@ class AnimeScreenModel( fun setDisplayMode(mode: Long) { val anime = successState?.anime ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setAnimeEpisodeFlags.awaitSetDisplayMode(anime, mode) } } @@ -861,14 +861,14 @@ class AnimeScreenModel( fun setSorting(sort: Long) { val anime = successState?.anime ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setAnimeEpisodeFlags.awaitSetSortingModeOrFlipOrder(anime, sort) } } fun setCurrentSettingsAsDefault(applyToExisting: Boolean) { val anime = successState?.anime ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { libraryPreferences.setEpisodeSettingsDefault(anime) if (applyToExisting) { setAnimeDefaultEpisodeFlags.awaitAll() @@ -973,7 +973,7 @@ class AnimeScreenModel( private fun observeTrackers() { val anime = successState?.anime ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { getTracks.subscribe(anime.id) .catch { logcat(LogPriority.ERROR, it) } .map { tracks -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/track/AnimeTrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/track/AnimeTrackInfoDialog.kt index 6def96491..32b62588c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/track/AnimeTrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/anime/track/AnimeTrackInfoDialog.kt @@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.model.ScreenModel 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.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -193,11 +193,11 @@ data class AnimeTrackInfoDialogHomeScreen( ) : StateScreenModel(State()) { init { - coroutineScope.launch { + screenModelScope.launch { refreshTrackers() } - coroutineScope.launch { + screenModelScope.launch { getTracks.subscribe(animeId) .catch { logcat(LogPriority.ERROR, it) } .distinctUntilChanged() @@ -214,7 +214,7 @@ data class AnimeTrackInfoDialogHomeScreen( fun registerEnhancedTracking(item: AnimeTrackItem) { item.tracker as EnhancedAnimeTracker - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val anime = Injekt.get().await(animeId) ?: return@launchNonCancellable try { val matchResult = item.tracker.match(anime) ?: throw Exception() @@ -307,7 +307,7 @@ private data class TrackStatusSelectorScreen( } fun setStatus() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.animeService.setRemoteAnimeStatus(track.toDbTrack(), state.value.selection) } } @@ -367,7 +367,7 @@ private data class TrackEpisodeSelectorScreen( } fun setEpisode() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.animeService.setRemoteLastEpisodeSeen( track.toDbTrack(), state.value.selection, @@ -424,7 +424,7 @@ private data class TrackScoreSelectorScreen( } fun setScore() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.animeService.setRemoteScore(track.toDbTrack(), state.value.selection) } } @@ -552,7 +552,7 @@ private data class TrackDateSelectorScreen( // Convert to local time val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault()) - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { if (start) { tracker.animeService.setRemoteStartDate(track.toDbTrack(), localMillis) } else { @@ -644,7 +644,7 @@ private data class TrackDateRemoverScreen( fun getName() = tracker.name fun removeDate() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { if (start) { tracker.animeService.setRemoteStartDate(track.toDbTrack(), 0) } else { @@ -707,7 +707,7 @@ data class TrackServiceSearchScreen( } fun trackingSearch(query: String) { - coroutineScope.launch { + screenModelScope.launch { // To show loading state mutableState.update { it.copy(queryResult = null, selected = null) } @@ -729,7 +729,7 @@ data class TrackServiceSearchScreen( } fun registerTracking(item: AnimeTrackSearch) { - coroutineScope.launchNonCancellable { tracker.animeService.register(item, animeId) } + screenModelScope.launchNonCancellable { tracker.animeService.register(item, animeId) } } fun updateSelection(selected: AnimeTrackSearch) { @@ -833,13 +833,13 @@ private data class TrackerAnimeRemoveScreen( fun isDeletable() = tracker is DeletableAnimeTracker fun deleteAnimeFromService() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { (tracker as DeletableAnimeTracker).delete(track.toDbTrack()) } } fun unregisterTracking(serviceId: Long) { - coroutineScope.launchNonCancellable { deleteTrack.await(animeId, serviceId) } + screenModelScope.launchNonCancellable { deleteTrack.await(animeId, serviceId) } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaCoverScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaCoverScreenModel.kt index 09fd6ad4d..652e3c3cb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaCoverScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaCoverScreenModel.kt @@ -4,7 +4,7 @@ import android.content.Context import android.net.Uri import androidx.compose.material3.SnackbarHostState 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.request.ImageRequest import coil.size.Size @@ -40,14 +40,14 @@ class MangaCoverScreenModel( ) : StateScreenModel(null) { init { - coroutineScope.launchIO { + screenModelScope.launchIO { getManga.subscribe(mangaId) .collect { newManga -> mutableState.update { newManga } } } } fun saveCover(context: Context) { - coroutineScope.launch { + screenModelScope.launch { try { saveCoverInternal(context, temp = false) snackbarHostState.showSnackbar( @@ -65,7 +65,7 @@ class MangaCoverScreenModel( } fun shareCover(context: Context) { - coroutineScope.launch { + screenModelScope.launch { try { val uri = saveCoverInternal(context, temp = true) ?: return@launch withUIContext { @@ -117,7 +117,7 @@ class MangaCoverScreenModel( */ fun editCover(context: Context, data: Uri) { val manga = state.value ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { context.contentResolver.openInputStream(data)?.use { try { manga.editCover(Injekt.get(), it, updateManga, coverCache) @@ -131,7 +131,7 @@ class MangaCoverScreenModel( fun deleteCustomCover(context: Context) { val mangaId = state.value?.id ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { try { coverCache.deleteCustomCover(mangaId) updateManga.awaitUpdateCoverLastModified(mangaId) @@ -143,7 +143,7 @@ class MangaCoverScreenModel( } private fun notifyCoverUpdated(context: Context) { - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar( context.getString(R.string.cover_updated), withDismissAction = true, @@ -152,7 +152,7 @@ class MangaCoverScreenModel( } private fun notifyFailedCoverUpdate(context: Context, e: Throwable) { - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar( context.getString(R.string.notification_cover_update_failed), withDismissAction = true, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreen.kt index 9e42d892d..1ecd2f158 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreen.kt @@ -186,6 +186,7 @@ class MangaScreen( onSortModeChanged = screenModel::setSorting, onDisplayModeChanged = screenModel::setDisplayMode, onSetAsDefault = screenModel::setCurrentSettingsAsDefault, + onResetToDefault = screenModel::resetToDefaultSettings, ) MangaScreenModel.Dialog.TrackSheet -> { NavigatorAdaptiveSheet( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreenModel.kt index 63dc19896..8c7e4e4ad 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/MangaScreenModel.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf 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.util.addOrRemove import eu.kanade.domain.entries.manga.interactor.UpdateManga @@ -129,9 +129,9 @@ class MangaScreenModel( val chapterSwipeStartAction = libraryPreferences.swipeChapterEndAction().get() val chapterSwipeEndAction = libraryPreferences.swipeChapterStartAction().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 skipFiltered by readerPreferences.skipFiltered().asState(coroutineScope) + val skipFiltered by readerPreferences.skipFiltered().asState(screenModelScope) val isUpdateIntervalEnabled = LibraryPreferences.ENTRY_OUTSIDE_RELEASE_PERIOD in libraryPreferences.autoUpdateItemRestrictions().get() @@ -156,7 +156,7 @@ class MangaScreenModel( } init { - coroutineScope.launchIO { + screenModelScope.launchIO { combine( getMangaAndChapters.subscribe(mangaId).distinctUntilChanged(), downloadCache.changes, @@ -174,7 +174,7 @@ class MangaScreenModel( observeDownloads() - coroutineScope.launchIO { + screenModelScope.launchIO { val manga = getMangaAndChapters.awaitManga(mangaId) val chapters = getMangaAndChapters.awaitChapters(mangaId) .toChapterItems(manga) @@ -202,7 +202,7 @@ class MangaScreenModel( observeTrackers() // Fetch info-chapters when needed - if (coroutineScope.isActive) { + if (screenModelScope.isActive) { val fetchFromSourceTasks = listOf( async { if (needRefreshInfo) fetchMangaFromSource() }, async { if (needRefreshChapter) fetchChaptersFromSource() }, @@ -216,7 +216,7 @@ class MangaScreenModel( } fun fetchAllFromSource(manualFetch: Boolean = true) { - coroutineScope.launch { + screenModelScope.launch { updateSuccessState { it.copy(isRefreshingData = true) } val fetchFromSourceTasks = listOf( async { fetchMangaFromSource(manualFetch) }, @@ -244,7 +244,7 @@ class MangaScreenModel( if (e is HttpException && e.code == 103) return logcat(LogPriority.ERROR, e) - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar(message = with(context) { e.formattedMessage }) } } @@ -253,7 +253,7 @@ class MangaScreenModel( fun toggleFavorite() { toggleFavorite( onRemoved = { - coroutineScope.launch { + screenModelScope.launch { if (!hasDownloads()) return@launch val result = snackbarHostState.showSnackbar( message = context.getString(R.string.delete_downloads_for_manga), @@ -276,7 +276,7 @@ class MangaScreenModel( checkDuplicate: Boolean = true, ) { val state = successState ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { val manga = state.manga if (isFavorited) { @@ -341,7 +341,7 @@ class MangaScreenModel( fun showChangeCategoryDialog() { val manga = successState?.manga ?: return - coroutineScope.launch { + screenModelScope.launch { val categories = getCategories() val selection = getMangaCategoryIds(manga) updateSuccessState { successState -> @@ -363,7 +363,7 @@ class MangaScreenModel( } fun setFetchInterval(manga: Manga, interval: Int) { - coroutineScope.launchIO { + screenModelScope.launchIO { updateManga.awaitUpdateFetchInterval( // Custom intervals are negative manga.copy(fetchInterval = -interval), @@ -413,7 +413,7 @@ class MangaScreenModel( moveMangaToCategory(categories) if (manga.favorite) return - coroutineScope.launchIO { + screenModelScope.launchIO { updateManga.awaitUpdateFavorite(manga.id, true) } } @@ -429,7 +429,7 @@ class MangaScreenModel( } private fun moveMangaToCategory(categoryIds: List) { - coroutineScope.launchIO { + screenModelScope.launchIO { setMangaCategories.await(mangaId, categoryIds) } } @@ -448,7 +448,7 @@ class MangaScreenModel( // Chapters list - start private fun observeDownloads() { - coroutineScope.launchIO { + screenModelScope.launchIO { downloadManager.statusFlow() .filter { it.manga.id == successState?.manga?.id } .catch { error -> logcat(LogPriority.ERROR, error) } @@ -459,7 +459,7 @@ class MangaScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { downloadManager.progressFlow() .filter { it.manga.id == successState?.manga?.id } .catch { error -> logcat(LogPriority.ERROR, error) } @@ -546,7 +546,7 @@ class MangaScreenModel( with(context) { e.formattedMessage } } - coroutineScope.launch { + screenModelScope.launch { snackbarHostState.showSnackbar(message = message) } val newManga = mangaRepository.getMangaById(mangaId) @@ -558,7 +558,7 @@ class MangaScreenModel( * @throws IllegalStateException if the swipe action is [LibraryPreferences.ChapterSwipeAction.Disabled] */ fun chapterSwipe(chapterItem: ChapterItem, swipeAction: LibraryPreferences.ChapterSwipeAction) { - coroutineScope.launch { + screenModelScope.launch { executeChapterSwipeAction(chapterItem, swipeAction) } } @@ -634,7 +634,7 @@ class MangaScreenModel( updateSuccessState { state -> state.copy(hasPromptedToAddBefore = true) } - coroutineScope.launch { + screenModelScope.launch { val result = snackbarHostState.showSnackbar( message = context.getString(R.string.snack_add_to_manga_library), actionLabel = context.getString(R.string.action_add), @@ -706,7 +706,7 @@ class MangaScreenModel( * @param read whether to mark chapters as read or unread. */ fun markChaptersRead(chapters: List, read: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { setReadStatus.await( read = read, chapters = chapters.toTypedArray(), @@ -730,7 +730,7 @@ class MangaScreenModel( * @param chapters the list of chapters to bookmark. */ fun bookmarkChapters(chapters: List, bookmarked: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { chapters .filterNot { it.bookmark == bookmarked } .map { ChapterUpdate(id = it.id, bookmark = bookmarked) } @@ -745,7 +745,7 @@ class MangaScreenModel( * @param chapters the list of chapters to delete. */ fun deleteChapters(chapters: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { try { successState?.let { state -> downloadManager.deleteChapters( @@ -761,7 +761,7 @@ class MangaScreenModel( } private fun downloadNewChapters(chapters: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val manga = successState?.manga ?: return@launchNonCancellable val categories = getCategories.await(manga.id).map { it.id } if (chapters.isEmpty() || !manga.shouldDownloadNewChapters( @@ -787,7 +787,7 @@ class MangaScreenModel( TriState.ENABLED_IS -> Manga.CHAPTER_SHOW_UNREAD TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_READ } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setMangaChapterFlags.awaitSetUnreadFilter(manga, flag) } } @@ -805,7 +805,7 @@ class MangaScreenModel( TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_DOWNLOADED } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setMangaChapterFlags.awaitSetDownloadedFilter(manga, flag) } } @@ -823,7 +823,7 @@ class MangaScreenModel( TriState.ENABLED_NOT -> Manga.CHAPTER_SHOW_NOT_BOOKMARKED } - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setMangaChapterFlags.awaitSetBookmarkFilter(manga, flag) } } @@ -835,7 +835,7 @@ class MangaScreenModel( fun setDisplayMode(mode: Long) { val manga = successState?.manga ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setMangaChapterFlags.awaitSetDisplayMode(manga, mode) } } @@ -847,14 +847,14 @@ class MangaScreenModel( fun setSorting(sort: Long) { val manga = successState?.manga ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { setMangaChapterFlags.awaitSetSortingModeOrFlipOrder(manga, sort) } } fun setCurrentSettingsAsDefault(applyToExisting: Boolean) { val manga = successState?.manga ?: return - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { libraryPreferences.setChapterSettingsDefault(manga) if (applyToExisting) { setMangaDefaultChapterFlags.awaitAll() @@ -865,6 +865,13 @@ class MangaScreenModel( } } + fun resetToDefaultSettings() { + val manga = successState?.manga ?: return + screenModelScope.launchNonCancellable { + setMangaDefaultChapterFlags.await(manga) + } + } + fun toggleSelection( item: ChapterItem, selected: Boolean, @@ -960,7 +967,7 @@ class MangaScreenModel( private fun observeTrackers() { val manga = successState?.manga ?: return - coroutineScope.launchIO { + screenModelScope.launchIO { getTracks.subscribe(manga.id) .catch { logcat(LogPriority.ERROR, it) } .map { tracks -> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/track/MangaTrackInfoDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/track/MangaTrackInfoDialog.kt index 63e9600f0..7a9fb5efe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/track/MangaTrackInfoDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/entries/manga/track/MangaTrackInfoDialog.kt @@ -34,8 +34,8 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import cafe.adriel.voyager.core.model.ScreenModel 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.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -193,11 +193,11 @@ data class MangaTrackInfoDialogHomeScreen( ) : StateScreenModel(State()) { init { - coroutineScope.launch { + screenModelScope.launch { refreshTrackers() } - coroutineScope.launch { + screenModelScope.launch { getTracks.subscribe(mangaId) .catch { logcat(LogPriority.ERROR, it) } .distinctUntilChanged() @@ -214,7 +214,7 @@ data class MangaTrackInfoDialogHomeScreen( fun registerEnhancedTracking(item: MangaTrackItem) { item.tracker as EnhancedMangaTracker - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val manga = Injekt.get().await(mangaId) ?: return@launchNonCancellable try { val matchResult = item.tracker.match(manga) ?: throw Exception() @@ -307,7 +307,7 @@ private data class TrackStatusSelectorScreen( } fun setStatus() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.mangaService.setRemoteMangaStatus(track.toDbTrack(), state.value.selection) } } @@ -367,7 +367,7 @@ private data class TrackChapterSelectorScreen( } fun setChapter() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.mangaService.setRemoteLastChapterRead( track.toDbTrack(), state.value.selection, @@ -424,7 +424,7 @@ private data class TrackScoreSelectorScreen( } fun setScore() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { tracker.mangaService.setRemoteScore(track.toDbTrack(), state.value.selection) } } @@ -552,7 +552,7 @@ private data class TrackDateSelectorScreen( // Convert to local time val localMillis = millis.convertEpochMillisZone(ZoneOffset.UTC, ZoneOffset.systemDefault()) - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { if (start) { tracker.mangaService.setRemoteStartDate(track.toDbTrack(), localMillis) } else { @@ -644,7 +644,7 @@ private data class TrackDateRemoverScreen( fun getName() = tracker.name fun removeDate() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { if (start) { tracker.mangaService.setRemoteStartDate(track.toDbTrack(), 0) } else { @@ -707,7 +707,7 @@ data class TrackServiceSearchScreen( } fun trackingSearch(query: String) { - coroutineScope.launch { + screenModelScope.launch { // To show loading state mutableState.update { it.copy(queryResult = null, selected = null) } @@ -729,7 +729,7 @@ data class TrackServiceSearchScreen( } fun registerTracking(item: MangaTrackSearch) { - coroutineScope.launchNonCancellable { tracker.mangaService.register(item, mangaId) } + screenModelScope.launchNonCancellable { tracker.mangaService.register(item, mangaId) } } fun updateSelection(selected: MangaTrackSearch) { @@ -833,13 +833,13 @@ private data class TrackerMangaRemoveScreen( fun isDeletable() = tracker is DeletableMangaTracker fun deleteMangaFromService() { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { (tracker as DeletableMangaTracker).delete(track.toDbTrack()) } } fun unregisterTracking(serviceId: Long) { - coroutineScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) } + screenModelScope.launchNonCancellable { deleteTrack.await(mangaId, serviceId) } } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryScreenModel.kt index d635e4a2c..760661801 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/anime/AnimeHistoryScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.history.anime import androidx.compose.runtime.Immutable 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.presentation.history.anime.AnimeHistoryUiModel import eu.kanade.tachiyomi.util.lang.toDateKey @@ -46,7 +46,7 @@ class AnimeHistoryScreenModel( val query: StateFlow = _query.asStateFlow() init { - coroutineScope.launch { + screenModelScope.launch { _query.collectLatest { query -> getHistory.subscribe(query ?: "") .distinctUntilChanged() @@ -62,7 +62,7 @@ class AnimeHistoryScreenModel( } fun search(query: String?) { - coroutineScope.launchIO { + screenModelScope.launchIO { _query.emit(query) } } @@ -87,7 +87,7 @@ class AnimeHistoryScreenModel( } fun getNextEpisodeForAnime(animeId: Long, episodeId: Long) { - coroutineScope.launchIO { + screenModelScope.launchIO { sendNextEpisodeEvent(getNextEpisodes.await(animeId, episodeId, onlyUnseen = false)) } } @@ -98,19 +98,19 @@ class AnimeHistoryScreenModel( } fun removeFromHistory(history: AnimeHistoryWithRelations) { - coroutineScope.launchIO { + screenModelScope.launchIO { removeHistory.await(history) } } fun removeAllFromHistory(animeId: Long) { - coroutineScope.launchIO { + screenModelScope.launchIO { removeHistory.await(animeId) } } fun removeAllHistory() { - coroutineScope.launchIO { + screenModelScope.launchIO { val result = removeHistory.awaitAll() if (!result) return@launchIO _events.send(Event.HistoryCleared) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/history/manga/MangaHistoryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/history/manga/MangaHistoryScreenModel.kt index dcf9f2020..281edfa45 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/history/manga/MangaHistoryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/history/manga/MangaHistoryScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.history.manga import androidx.compose.runtime.Immutable 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.presentation.history.manga.MangaHistoryUiModel import eu.kanade.tachiyomi.util.lang.toDateKey @@ -46,7 +46,7 @@ class MangaHistoryScreenModel( val query: StateFlow = _query.asStateFlow() init { - coroutineScope.launch { + screenModelScope.launch { _query.collectLatest { query -> getHistory.subscribe(query ?: "") .distinctUntilChanged() @@ -62,7 +62,7 @@ class MangaHistoryScreenModel( } fun search(query: String?) { - coroutineScope.launchIO { + screenModelScope.launchIO { _query.emit(query) } } @@ -87,7 +87,7 @@ class MangaHistoryScreenModel( } fun getNextChapterForManga(mangaId: Long, chapterId: Long) { - coroutineScope.launchIO { + screenModelScope.launchIO { sendNextChapterEvent(getNextChapters.await(mangaId, chapterId, onlyUnread = false)) } } @@ -98,19 +98,19 @@ class MangaHistoryScreenModel( } fun removeFromHistory(history: MangaHistoryWithRelations) { - coroutineScope.launchIO { + screenModelScope.launchIO { removeHistory.await(history) } } fun removeAllFromHistory(mangaId: Long) { - coroutineScope.launchIO { + screenModelScope.launchIO { removeHistory.await(mangaId) } } fun removeAllHistory() { - coroutineScope.launchIO { + screenModelScope.launchIO { val result = removeHistory.awaitAll() if (!result) return@launchIO _events.send(Event.HistoryCleared) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryScreenModel.kt index f4519b8df..2e36a522c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibraryScreenModel.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastMap 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.asState import eu.kanade.core.util.fastDistinctBy @@ -93,11 +93,11 @@ class AnimeLibraryScreenModel( ) : StateScreenModel(State()) { var activeCategoryIndex: Int by libraryPreferences.lastUsedAnimeCategory().asState( - coroutineScope, + screenModelScope, ) init { - coroutineScope.launchIO { + screenModelScope.launchIO { combine( state.map { it.searchQuery }.debounce(SEARCH_DEBOUNCE_MILLIS), getLibraryFlow(), @@ -142,7 +142,7 @@ class AnimeLibraryScreenModel( ) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) combine( getAnimelibItemPreferencesFlow(), @@ -164,7 +164,7 @@ class AnimeLibraryScreenModel( state.copy(hasActiveFilters = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } /** @@ -443,7 +443,7 @@ class AnimeLibraryScreenModel( * @param amount the amount to queue or null to queue all */ private fun downloadUnseenEpisodes(animes: List, amount: Int?) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { animes.forEach { anime -> val episodes = getNextEpisodes.await(anime.id) .fastFilterNot { episode -> @@ -467,7 +467,7 @@ class AnimeLibraryScreenModel( */ fun markSeenSelection(seen: Boolean) { val animes = state.value.selection.toList() - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { animes.forEach { anime -> setSeenStatus.await( anime = anime.anime, @@ -486,7 +486,7 @@ class AnimeLibraryScreenModel( * @param deleteEpisodes whether to delete downloaded episodes. */ fun removeAnimes(animeList: List, deleteFromLibrary: Boolean, deleteEpisodes: Boolean) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val animeToDelete = animeList.distinctBy { it.id } if (deleteFromLibrary) { @@ -523,7 +523,7 @@ class AnimeLibraryScreenModel( addCategories: List, removeCategories: List, ) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { animeList.forEach { anime -> val categoryIds = getCategories.await(anime.id) .map { it.id } @@ -537,12 +537,12 @@ class AnimeLibraryScreenModel( } fun getDisplayMode(): PreferenceMutableState { - return libraryPreferences.displayMode().asState(coroutineScope) + return libraryPreferences.displayMode().asState(screenModelScope) } fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState { return (if (isLandscape) libraryPreferences.animeLandscapeColumns() else libraryPreferences.animePortraitColumns()).asState( - coroutineScope, + screenModelScope, ) } @@ -646,7 +646,7 @@ class AnimeLibraryScreenModel( } fun openChangeCategoryDialog() { - coroutineScope.launchIO { + screenModelScope.launchIO { // Create a copy of selected anime val animeList = state.value.selection.map { it.anime } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibrarySettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibrarySettingsScreenModel.kt index 0cebe8077..7407284f2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibrarySettingsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/anime/AnimeLibrarySettingsScreenModel.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.library.anime 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.tachiyomi.data.track.TrackerManager import tachiyomi.core.preference.Preference @@ -47,7 +47,7 @@ class AnimeLibrarySettingsScreenModel( mode: AnimeLibrarySort.Type, direction: AnimeLibrarySort.Direction, ) { - coroutineScope.launchIO { + screenModelScope.launchIO { setSortModeForCategory.await(category, mode, direction) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibraryScreenModel.kt index 3da5e8b90..c0c613409 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibraryScreenModel.kt @@ -6,7 +6,7 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.util.fastAny import androidx.compose.ui.util.fastMap 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.asState import eu.kanade.core.util.fastDistinctBy @@ -93,11 +93,11 @@ class MangaLibraryScreenModel( ) : StateScreenModel(State()) { var activeCategoryIndex: Int by libraryPreferences.lastUsedMangaCategory().asState( - coroutineScope, + screenModelScope, ) init { - coroutineScope.launchIO { + screenModelScope.launchIO { combine( state.map { it.searchQuery }.debounce(SEARCH_DEBOUNCE_MILLIS), getLibraryFlow(), @@ -142,7 +142,7 @@ class MangaLibraryScreenModel( ) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) combine( getLibraryItemPreferencesFlow(), @@ -164,7 +164,7 @@ class MangaLibraryScreenModel( state.copy(hasActiveFilters = it) } } - .launchIn(coroutineScope) + .launchIn(screenModelScope) } /** @@ -435,7 +435,7 @@ class MangaLibraryScreenModel( * @param amount the amount to queue or null to queue all */ private fun downloadUnreadChapters(mangas: List, amount: Int?) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { mangas.forEach { manga -> val chapters = getNextChapters.await(manga.id) .fastFilterNot { chapter -> @@ -459,7 +459,7 @@ class MangaLibraryScreenModel( */ fun markReadSelection(read: Boolean) { val mangas = state.value.selection.toList() - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { mangas.forEach { manga -> setReadStatus.await( manga = manga.manga, @@ -478,7 +478,7 @@ class MangaLibraryScreenModel( * @param deleteChapters whether to delete downloaded chapters. */ fun removeMangas(mangaList: List, deleteFromLibrary: Boolean, deleteChapters: Boolean) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val mangaToDelete = mangaList.distinctBy { it.id } if (deleteFromLibrary) { @@ -515,7 +515,7 @@ class MangaLibraryScreenModel( addCategories: List, removeCategories: List, ) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { mangaList.forEach { manga -> val categoryIds = getCategories.await(manga.id) .map { it.id } @@ -529,12 +529,12 @@ class MangaLibraryScreenModel( } fun getDisplayMode(): PreferenceMutableState { - return libraryPreferences.displayMode().asState(coroutineScope) + return libraryPreferences.displayMode().asState(screenModelScope) } fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState { return (if (isLandscape) libraryPreferences.mangaLandscapeColumns() else libraryPreferences.mangaPortraitColumns()).asState( - coroutineScope, + screenModelScope, ) } @@ -638,7 +638,7 @@ class MangaLibraryScreenModel( } fun openChangeCategoryDialog() { - coroutineScope.launchIO { + screenModelScope.launchIO { // Create a copy of selected manga val mangaList = state.value.selection.map { it.manga } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibrarySettingsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibrarySettingsScreenModel.kt index e4f2937af..09301b02f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibrarySettingsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/manga/MangaLibrarySettingsScreenModel.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.library.manga 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.tachiyomi.data.track.TrackerManager import tachiyomi.core.preference.Preference @@ -47,7 +47,7 @@ class MangaLibrarySettingsScreenModel( mode: MangaLibrarySort.Type, direction: MangaLibrarySort.Direction, ) { - coroutineScope.launchIO { + screenModelScope.launchIO { setSortModeForCategory.await(category, mode, direction) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt index 00ae44045..4c6cbd055 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreTab.kt @@ -10,8 +10,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource 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.screenModelScope import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.Navigator import cafe.adriel.voyager.navigator.currentOrThrow @@ -104,8 +104,8 @@ private class MoreScreenModel( preferences: BasePreferences = Injekt.get(), ) : ScreenModel { - var downloadedOnly by preferences.downloadedOnly().asState(coroutineScope) - var incognitoMode by preferences.incognitoMode().asState(coroutineScope) + var downloadedOnly by preferences.downloadedOnly().asState(screenModelScope) + var incognitoMode by preferences.incognitoMode().asState(screenModelScope) private var _state: MutableStateFlow = MutableStateFlow( DownloadQueueState.Stopped, @@ -114,7 +114,7 @@ private class MoreScreenModel( init { // Handle running/paused status change and queue progress updating - coroutineScope.launchIO { + screenModelScope.launchIO { combine( downloadManager.isDownloaderRunning, downloadManager.queueState, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 56a4d7a79..edb00ce3b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -42,6 +42,7 @@ import com.google.android.material.transition.platform.MaterialContainerTransfor import dev.chrisbanes.insetter.applyInsetter import eu.kanade.domain.base.BasePreferences import eu.kanade.presentation.reader.BrightnessOverlay +import eu.kanade.presentation.reader.DisplayRefreshHost import eu.kanade.presentation.reader.OrientationModeSelectDialog import eu.kanade.presentation.reader.PageIndicatorText import eu.kanade.presentation.reader.ReaderPageActionsDialog @@ -122,6 +123,7 @@ class ReaderActivity : BaseActivity() { private var menuToggleToast: Toast? = null private var readingModeToast: Toast? = null + private val displayRefreshHost = DisplayRefreshHost() private val windowInsetsController by lazy { WindowInsetsControllerCompat(window, binding.root) } @@ -203,6 +205,9 @@ class ReaderActivity : BaseActivity() { ReaderViewModel.Event.ReloadViewerChapters -> { viewModel.state.value.viewerChapters?.let(::setChapters) } + ReaderViewModel.Event.PageChanged -> { + displayRefreshHost.flash() + } is ReaderViewModel.Event.SetOrientation -> { setOrientation(event.orientation) } @@ -329,6 +334,7 @@ class ReaderActivity : BaseActivity() { val isHttpSource = viewModel.getSource() is HttpSource val isFullscreen by readerPreferences.fullscreen().collectAsState() + val flashOnPageChange by readerPreferences.flashOnPageChange().collectAsState() val cropBorderPaged by readerPreferences.cropBorders().collectAsState() val cropBorderWebtoon by readerPreferences.cropBordersWebtoon().collectAsState() @@ -382,6 +388,12 @@ class ReaderActivity : BaseActivity() { value = state.brightnessOverlayValue, ) + if (flashOnPageChange) { + DisplayRefreshHost( + hostState = displayRefreshHost, + ) + } + val onDismissRequest = viewModel::closeDialog when (state.dialog) { is ReaderViewModel.Dialog.Loading -> { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt index 29f802faa..b668fdea8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderViewModel.kt @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.ui.reader import android.app.Application import android.net.Uri +import androidx.annotation.IntRange import androidx.compose.runtime.Immutable import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel @@ -449,6 +450,8 @@ class ReaderViewModel @JvmOverloads constructor( if (inDownloadRange) { downloadNextChapters() } + + eventChannel.trySend(Event.PageChanged) } private fun downloadNextChapters() { @@ -650,7 +653,7 @@ class ReaderViewModel @JvmOverloads constructor( fun setMangaReadingMode(readingModeType: ReadingModeType) { val manga = manga ?: return runBlocking(Dispatchers.IO) { - setMangaViewerFlags.awaitSetMangaReadingMode( + setMangaViewerFlags.awaitSetReadingMode( manga.id, readingModeType.flagValue.toLong(), ) @@ -689,7 +692,7 @@ class ReaderViewModel @JvmOverloads constructor( fun setMangaOrientationType(rotationType: OrientationType) { val manga = manga ?: return viewModelScope.launchIO { - setMangaViewerFlags.awaitSetOrientationType(manga.id, rotationType.flagValue.toLong()) + setMangaViewerFlags.awaitSetOrientation(manga.id, rotationType.flagValue.toLong()) val currChapters = state.value.viewerChapters if (currChapters != null) { // Save current page @@ -926,7 +929,7 @@ class ReaderViewModel @JvmOverloads constructor( val viewer: Viewer? = null, val dialog: Dialog? = null, val menuVisible: Boolean = false, - val brightnessOverlayValue: Int = 0, + @IntRange(from = -100, to = 100) val brightnessOverlayValue: Int = 0, ) { val currentChapter: ReaderChapter? get() = viewerChapters?.currChapter @@ -945,6 +948,7 @@ class ReaderViewModel @JvmOverloads constructor( sealed interface Event { data object ReloadViewerChapters : Event + data object PageChanged : Event data class SetOrientation(val orientation: Int) : Event data class SetCoverResult(val result: SetAsCoverResult) : Event diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt index c63695eae..138ea1966 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/setting/ReaderPreferences.kt @@ -13,6 +13,8 @@ class ReaderPreferences( fun pageTransitions() = preferenceStore.getBoolean("pref_enable_transitions_key", true) + fun flashOnPageChange() = preferenceStore.getBoolean("pref_reader_flash", false) + fun doubleTapAnimSpeed() = preferenceStore.getInt("pref_double_tap_anim_speed", 500) fun showPageNumber() = preferenceStore.getBoolean("pref_show_page_number_key", true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 2454b96ec..14828640f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -111,7 +111,7 @@ class PagerPageHolder( */ private fun setQueued() { progressIndicator.show() - errorLayout?.root?.isVisible = false + removeErrorLayout() } /** @@ -119,7 +119,7 @@ class PagerPageHolder( */ private fun setLoading() { progressIndicator.show() - errorLayout?.root?.isVisible = false + removeErrorLayout() } /** @@ -127,7 +127,7 @@ class PagerPageHolder( */ private fun setDownloading() { progressIndicator.show() - errorLayout?.root?.isVisible = false + removeErrorLayout() } /** @@ -135,7 +135,6 @@ class PagerPageHolder( */ private suspend fun setImage() { progressIndicator.setProgress(0) - errorLayout?.root?.isVisible = false val streamFn = page.stream ?: return @@ -172,6 +171,7 @@ class PagerPageHolder( pageBackground = background } } + removeErrorLayout() } } @@ -282,4 +282,12 @@ class PagerPageHolder( errorLayout?.root?.isVisible = true return errorLayout!! } + + /** + * Removes the decode error layout from the holder, if found. + */ + private fun removeErrorLayout() { + errorLayout?.root?.isVisible = false + errorLayout = null + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt index c2c688a02..c9a87e420 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonPageHolder.kt @@ -181,7 +181,6 @@ class WebtoonPageHolder( */ private suspend fun setImage() { progressIndicator.setProgress(0) - removeErrorLayout() val streamFn = page?.stream ?: return @@ -202,6 +201,7 @@ class WebtoonPageHolder( cropBorders = viewer.config.imageCropBorders, ), ) + removeErrorLayout() } // Suspend the coroutine to close the input stream only when the WebtoonPageHolder is recycled suspendCancellableCoroutine { continuation -> @@ -234,6 +234,7 @@ class WebtoonPageHolder( */ private fun onImageDecoded() { progressContainer.isVisible = false + removeErrorLayout() } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/anime/AnimeStatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/anime/AnimeStatsScreenModel.kt index 680638995..596637ff2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/anime/AnimeStatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/anime/AnimeStatsScreenModel.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.stats.anime 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.fastDistinctBy import eu.kanade.core.util.fastFilter @@ -40,7 +40,7 @@ class AnimeStatsScreenModel( private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn && it is AnimeTracker } } init { - coroutineScope.launchIO { + screenModelScope.launchIO { val animelibAnime = getAnimelibAnime.await() val distinctLibraryAnime = animelibAnime.fastDistinctBy { it.id } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/manga/MangaStatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/manga/MangaStatsScreenModel.kt index a3ffd2567..f391e8b39 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/manga/MangaStatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/manga/MangaStatsScreenModel.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.ui.stats.manga 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.fastDistinctBy import eu.kanade.core.util.fastFilter @@ -40,7 +40,7 @@ class MangaStatsScreenModel( private val loggedInTrackers by lazy { trackerManager.trackers.fastFilter { it.isLoggedIn && it is MangaTracker } } init { - coroutineScope.launchIO { + screenModelScope.launchIO { val libraryManga = getLibraryManga.await() val distinctLibraryManga = libraryManga.fastDistinctBy { it.id } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/CommonStorageScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/CommonStorageScreenModel.kt index 9d2a0ba9c..173c0a82f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/CommonStorageScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/CommonStorageScreenModel.kt @@ -2,7 +2,7 @@ package eu.kanade.tachiyomi.ui.storage import androidx.compose.ui.graphics.Color import cafe.adriel.voyager.core.model.StateScreenModel -import cafe.adriel.voyager.core.model.coroutineScope +import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.presentation.more.storage.StorageItem import eu.kanade.presentation.more.storage.StorageScreenState import kotlinx.coroutines.flow.Flow @@ -36,7 +36,7 @@ abstract class CommonStorageScreenModel( private val selectedCategory = MutableStateFlow(AllCategory) init { - coroutineScope.launchIO { + screenModelScope.launchIO { val hideHiddenCategories = libraryPreferences.hideHiddenCategoriesSettings().get() combine( diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/anime/AnimeStorageScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/anime/AnimeStorageScreenModel.kt index 71f0a7696..87f825a34 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/anime/AnimeStorageScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/anime/AnimeStorageScreenModel.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.ui.storage.anime -import cafe.adriel.voyager.core.model.coroutineScope +import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadCache import eu.kanade.tachiyomi.data.download.anime.AnimeDownloadManager import eu.kanade.tachiyomi.ui.storage.CommonStorageScreenModel @@ -39,7 +39,7 @@ class AnimeStorageScreenModel( getThumbnail = { anime.thumbnailUrl }, ) { override fun deleteEntry(id: Long) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val anime = getLibraries.await().find { it.id == id }?.anime ?: return@launchNonCancellable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/manga/MangaStorageScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/manga/MangaStorageScreenModel.kt index c42b41421..d5ff2e1d9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/storage/manga/MangaStorageScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/storage/manga/MangaStorageScreenModel.kt @@ -1,6 +1,6 @@ package eu.kanade.tachiyomi.ui.storage.manga -import cafe.adriel.voyager.core.model.coroutineScope +import cafe.adriel.voyager.core.model.screenModelScope import eu.kanade.tachiyomi.data.download.manga.MangaDownloadCache import eu.kanade.tachiyomi.data.download.manga.MangaDownloadManager import eu.kanade.tachiyomi.ui.storage.CommonStorageScreenModel @@ -39,7 +39,7 @@ class MangaStorageScreenModel( getThumbnail = { manga.thumbnailUrl }, ) { override fun deleteEntry(id: Long) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val manga = getLibraries.await().find { it.id == id }?.manga ?: return@launchNonCancellable diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesScreenModel.kt index 06fa6be83..80c98e577 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/anime/AnimeUpdatesScreenModel.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf 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.util.addOrRemove import eu.kanade.core.util.insertSeparators @@ -67,8 +67,8 @@ class AnimeUpdatesScreenModel( private val _events: Channel = Channel(Int.MAX_VALUE) val events: Flow = _events.receiveAsFlow() - val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(coroutineScope) - val relativeTime by uiPreferences.relativeTime().asState(coroutineScope) + val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(screenModelScope) + val relativeTime by uiPreferences.relativeTime().asState(screenModelScope) val useExternalDownloader = downloadPreferences.useExternalDownloader().get() @@ -77,7 +77,7 @@ class AnimeUpdatesScreenModel( private val selectedEpisodeIds: HashSet = HashSet() init { - coroutineScope.launchIO { + screenModelScope.launchIO { // Set date limit for recent episodes val calendar = Calendar.getInstance().apply { time = Date() @@ -103,7 +103,7 @@ class AnimeUpdatesScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { merge(downloadManager.statusFlow(), downloadManager.progressFlow()) .catch { logcat(LogPriority.ERROR, it) } .collect(this@AnimeUpdatesScreenModel::updateDownloadState) @@ -135,7 +135,7 @@ class AnimeUpdatesScreenModel( fun updateLibrary(): Boolean { val started = AnimeLibraryUpdateJob.startNow(Injekt.get()) - coroutineScope.launch { + screenModelScope.launch { _events.send(Event.LibraryUpdateTriggered(started)) } return started @@ -167,7 +167,7 @@ class AnimeUpdatesScreenModel( fun downloadEpisodes(items: List, action: EpisodeDownloadAction) { if (items.isEmpty()) return - coroutineScope.launch { + screenModelScope.launch { when (action) { EpisodeDownloadAction.START -> { downloadEpisodes(items) @@ -211,7 +211,7 @@ class AnimeUpdatesScreenModel( * @param seen whether to mark episodes as seen or unseen. */ fun markUpdatesSeen(updates: List, seen: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { setSeenStatus.await( seen = seen, episodes = updates @@ -227,7 +227,7 @@ class AnimeUpdatesScreenModel( * @param updates the list of episodes to bookmark. */ fun bookmarkUpdates(updates: List, bookmark: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { updates .filterNot { it.update.bookmark == bookmark } .map { EpisodeUpdate(id = it.update.episodeId, bookmark = bookmark) } @@ -241,7 +241,7 @@ class AnimeUpdatesScreenModel( * @param updatesItem the list of episodes to download. */ private fun downloadEpisodes(updatesItem: List, alt: Boolean = false) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val groupedUpdates = updatesItem.groupBy { it.update.animeId }.values for (updates in groupedUpdates) { val animeId = updates.first().update.animeId @@ -260,7 +260,7 @@ class AnimeUpdatesScreenModel( * @param updatesItem list of episodes */ fun deleteEpisodes(updatesItem: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { updatesItem .groupBy { it.update.animeId } .entries diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/manga/MangaUpdatesScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/manga/MangaUpdatesScreenModel.kt index fb0d96c5c..8ce3e0b23 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/updates/manga/MangaUpdatesScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/updates/manga/MangaUpdatesScreenModel.kt @@ -7,7 +7,7 @@ import androidx.compose.runtime.Immutable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf 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.util.addOrRemove import eu.kanade.core.util.insertSeparators @@ -65,15 +65,15 @@ class MangaUpdatesScreenModel( private val _events: Channel = Channel(Int.MAX_VALUE) val events: Flow = _events.receiveAsFlow() - val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(coroutineScope) - val relativeTime by uiPreferences.relativeTime().asState(coroutineScope) + val lastUpdated by libraryPreferences.lastUpdatedTimestamp().asState(screenModelScope) + val relativeTime by uiPreferences.relativeTime().asState(screenModelScope) // First and last selected index in list private val selectedPositions: Array = arrayOf(-1, -1) private val selectedChapterIds: HashSet = HashSet() init { - coroutineScope.launchIO { + screenModelScope.launchIO { // Set date limit for recent chapters val calendar = Calendar.getInstance().apply { time = Date() @@ -99,7 +99,7 @@ class MangaUpdatesScreenModel( } } - coroutineScope.launchIO { + screenModelScope.launchIO { merge(downloadManager.statusFlow(), downloadManager.progressFlow()) .catch { logcat(LogPriority.ERROR, it) } .collect(this@MangaUpdatesScreenModel::updateDownloadState) @@ -131,7 +131,7 @@ class MangaUpdatesScreenModel( fun updateLibrary(): Boolean { val started = MangaLibraryUpdateJob.startNow(Injekt.get()) - coroutineScope.launch { + screenModelScope.launch { _events.send(Event.LibraryUpdateTriggered(started)) } return started @@ -163,7 +163,7 @@ class MangaUpdatesScreenModel( fun downloadChapters(items: List, action: ChapterDownloadAction) { if (items.isEmpty()) return - coroutineScope.launch { + screenModelScope.launch { when (action) { ChapterDownloadAction.START -> { downloadChapters(items) @@ -203,7 +203,7 @@ class MangaUpdatesScreenModel( * @param read whether to mark chapters as read or unread. */ fun markUpdatesRead(updates: List, read: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { setReadStatus.await( read = read, chapters = updates @@ -219,7 +219,7 @@ class MangaUpdatesScreenModel( * @param updates the list of chapters to bookmark. */ fun bookmarkUpdates(updates: List, bookmark: Boolean) { - coroutineScope.launchIO { + screenModelScope.launchIO { updates .filterNot { it.update.bookmark == bookmark } .map { ChapterUpdate(id = it.update.chapterId, bookmark = bookmark) } @@ -233,7 +233,7 @@ class MangaUpdatesScreenModel( * @param updatesItem the list of chapters to download. */ private fun downloadChapters(updatesItem: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { val groupedUpdates = updatesItem.groupBy { it.update.mangaId }.values for (updates in groupedUpdates) { val mangaId = updates.first().update.mangaId @@ -252,7 +252,7 @@ class MangaUpdatesScreenModel( * @param updatesItem list of chapters */ fun deleteChapters(updatesItem: List) { - coroutineScope.launchNonCancellable { + screenModelScope.launchNonCancellable { updatesItem .groupBy { it.update.mangaId } .entries diff --git a/data/src/main/sqldelight/data/mangas.sq b/data/src/main/sqldelight/data/mangas.sq index 01df11f98..3c2047dbd 100644 --- a/data/src/main/sqldelight/data/mangas.sq +++ b/data/src/main/sqldelight/data/mangas.sq @@ -57,7 +57,8 @@ WHERE _id = :id; getMangaByUrlAndSource: SELECT * FROM mangas -WHERE url = :url AND source = :source +WHERE url = :url +AND source = :source LIMIT 1; getFavorites: @@ -107,7 +108,8 @@ GROUP BY source; deleteMangasNotInLibraryBySourceIds: DELETE FROM mangas -WHERE favorite = 0 AND source IN :sourceIds; +WHERE favorite = 0 +AND source IN :sourceIds; insert: INSERT INTO mangas(source, url, artist, author, description, genre, title, status, thumbnail_url, favorite, last_update, next_update, initialized, viewer, chapter_flags, cover_last_modified, date_added, update_strategy, calculate_interval, last_modified_at) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ed47fdf7c..89425f767 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,7 +5,7 @@ shizuku_version = "12.2.0" sqlite = "2.4.0" sqldelight = "2.0.0" leakcanary = "2.12" -voyager = "1.0.0-rc07" +voyager = "1.0.0-rc08" richtext = "0.17.0" [libraries] diff --git a/i18n/src/main/res/values/strings.xml b/i18n/src/main/res/values/strings.xml index d564f1165..97a73ae37 100644 --- a/i18n/src/main/res/values/strings.xml +++ b/i18n/src/main/res/values/strings.xml @@ -332,6 +332,8 @@ Double tap to zoom Show content in cutout area Animate page transitions + Flash white on page change + Reduces ghosting on e-ink displays Double tap animation speed Show page number Show reading mode diff --git a/presentation-core/src/main/java/tachiyomi/presentation/core/components/VerticalFastScroller.kt b/presentation-core/src/main/java/tachiyomi/presentation/core/components/VerticalFastScroller.kt index b68714371..23d6d9296 100644 --- a/presentation-core/src/main/java/tachiyomi/presentation/core/components/VerticalFastScroller.kt +++ b/presentation-core/src/main/java/tachiyomi/presentation/core/components/VerticalFastScroller.kt @@ -359,7 +359,6 @@ fun VerticalGridFastScroller( }, ) .height(ThumbLength) - .padding(horizontal = 8.dp) .padding(end = endContentPadding) .width(ThumbThickness) .alpha(alpha.value) @@ -436,7 +435,7 @@ object Scroller { } private val ThumbLength = 48.dp -private val ThumbThickness = 8.dp +private val ThumbThickness = 12.dp private val ThumbShape = RoundedCornerShape(ThumbThickness / 2) private val FadeOutAnimationSpec = tween( durationMillis = ViewConfiguration.getScrollBarFadeDuration(),