Last commit merged: 64ad25d1b5
This commit is contained in:
LuftVerbot 2023-11-25 15:09:18 +01:00
parent a60268e61c
commit 3fba4cbc2b
68 changed files with 504 additions and 347 deletions

View file

@ -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(

View file

@ -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) }

View file

@ -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,

View file

@ -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(

View file

@ -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,

View file

@ -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<MangaRepository>().resetMangaViewerFlags()
val success = Injekt.get<ResetMangaViewerFlags>().await()
withUIContext {
val message = if (success) {
R.string.pref_reset_viewer_flags_success

View file

@ -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),

View file

@ -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<ClearAnimeDatabas
private val database: AnimeDatabase = Injekt.get()
init {
coroutineScope.launchIO {
screenModelScope.launchIO {
getSourcesWithNonLibraryAnime.subscribe()
.collectLatest { list ->
mutableState.update { old ->

View file

@ -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<ClearDatabaseScreenMod
private val database: Database = Injekt.get()
init {
coroutineScope.launchIO {
screenModelScope.launchIO {
getSourcesWithNonLibraryManga.subscribe()
.collectLatest { list ->
mutableState.update { old ->

View file

@ -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

View file

@ -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)
}
}
}

View file

@ -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(),
)
}

View file

@ -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<AnimeExtensionFilterEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
combine(
getExtensionLanguages.subscribe(),
preferences.enabledLanguages().changes(),

View file

@ -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<AnimeExtension.Installed>()
@ -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()

View file

@ -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<AnimeExtensionDetailsEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
launch {
extensionManager.installedExtensionsFlow
.map { it.firstOrNull { extension -> extension.pkgName == pkgName } }

View file

@ -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<MigrationAnimeEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
mutableState.update { state ->
state.copy(source = sourceManager.getOrStub(sourceId))
}

View file

@ -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<AnimeMigrateSearchScreenDialogScreenModel.State>(State()) {
init {
coroutineScope.launch {
screenModelScope.launch {
val anime = getAnime.await(animeId)!!
mutableState.update {

View file

@ -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(

View file

@ -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() {

View file

@ -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<AnimeSourcesFilterScreenModel.State>(State.Loading) {
init {
coroutineScope.launch {
screenModelScope.launch {
combine(
getLanguagesWithSources.subscribe(),
preferences.enabledLanguages().changes(),

View file

@ -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)

View file

@ -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<BrowseAnimeSourceScreenModel.State>(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<Long>) {
coroutineScope.launchIO {
screenModelScope.launchIO {
setAnimeCategories.await(
animeId = anime.id,
categoryIds = categoryIds.toList(),

View file

@ -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<MangaExtensionFilterEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
combine(
getExtensionLanguages.subscribe(),
preferences.enabledLanguages().changes(),

View file

@ -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<MangaExtension.Installed>()
@ -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()

View file

@ -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<MangaExtensionDetailsEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
launch {
extensionManager.installedExtensionsFlow
.map { it.firstOrNull { extension -> extension.pkgName == pkgName } }

View file

@ -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<MigrationMangaEvent> = _events.receiveAsFlow()
init {
coroutineScope.launch {
screenModelScope.launch {
mutableState.update { state ->
state.copy(source = sourceManager.getOrStub(sourceId))
}

View file

@ -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<MangaMigrateSearchScreenDialogScreenModel.State>(State()) {
init {
coroutineScope.launch {
screenModelScope.launch {
val manga = getManga.await(mangaId)!!
mutableState.update {

View file

@ -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(

View file

@ -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() {

View file

@ -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<MangaSourcesFilterScreenModel.State>(State.Loading) {
init {
coroutineScope.launch {
screenModelScope.launch {
combine(
getLanguagesWithSources.subscribe(),
preferences.enabledLanguages().changes(),

View file

@ -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 <--
}

View file

@ -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<BrowseMangaSourceScreenModel.State>(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<Long>) {
coroutineScope.launchIO {
screenModelScope.launchIO {
setMangaCategories.await(
mangaId = manga.id,
categoryIds = categoryIds.toList(),

View file

@ -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,

View file

@ -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,

View file

@ -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<DeepLinkAnimeScreenModel.State>(State.Loading) {
init {
coroutineScope.launchIO {
screenModelScope.launchIO {
val source = sourceManager.getCatalogueSources()
.filterIsInstance<ResolvableAnimeSource>()
.firstOrNull { it.getUriType(query) != UriType.Unknown }

View file

@ -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<DeepLinkMangaScreenModel.State>(State.Loading) {
init {
coroutineScope.launchIO {
screenModelScope.launchIO {
val source = sourceManager.getCatalogueSources()
.filterIsInstance<ResolvableMangaSource>()
.firstOrNull { it.getUriType(query) != UriType.Unknown }

View file

@ -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

View file

@ -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)
}

View file

@ -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<Anime?>(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,

View file

@ -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<Long>) {
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<Episode>, 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<Episode>, 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<Episode>) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
try {
successState?.let { state ->
downloadManager.deleteEpisodes(
@ -775,7 +775,7 @@ class AnimeScreenModel(
}
private fun downloadNewEpisodes(episodes: List<Episode>) {
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 ->

View file

@ -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<Model.State>(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<GetAnime>().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) }
}
}
}

View file

@ -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<Manga?>(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,

View file

@ -186,6 +186,7 @@ class MangaScreen(
onSortModeChanged = screenModel::setSorting,
onDisplayModeChanged = screenModel::setDisplayMode,
onSetAsDefault = screenModel::setCurrentSettingsAsDefault,
onResetToDefault = screenModel::resetToDefaultSettings,
)
MangaScreenModel.Dialog.TrackSheet -> {
NavigatorAdaptiveSheet(

View file

@ -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<Long>) {
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<Chapter>, 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<Chapter>, 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<Chapter>) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
try {
successState?.let { state ->
downloadManager.deleteChapters(
@ -761,7 +761,7 @@ class MangaScreenModel(
}
private fun downloadNewChapters(chapters: List<Chapter>) {
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 ->

View file

@ -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<Model.State>(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<GetManga>().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) }
}
}
}

View file

@ -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<String?> = _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)

View file

@ -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<String?> = _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)

View file

@ -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<AnimeLibraryScreenModel.State>(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<Anime>, 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<Anime>, deleteFromLibrary: Boolean, deleteEpisodes: Boolean) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
val animeToDelete = animeList.distinctBy { it.id }
if (deleteFromLibrary) {
@ -523,7 +523,7 @@ class AnimeLibraryScreenModel(
addCategories: List<Long>,
removeCategories: List<Long>,
) {
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<LibraryDisplayMode> {
return libraryPreferences.displayMode().asState(coroutineScope)
return libraryPreferences.displayMode().asState(screenModelScope)
}
fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
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 }

View file

@ -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)
}
}

View file

@ -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<MangaLibraryScreenModel.State>(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<Manga>, 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<Manga>, deleteFromLibrary: Boolean, deleteChapters: Boolean) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
val mangaToDelete = mangaList.distinctBy { it.id }
if (deleteFromLibrary) {
@ -515,7 +515,7 @@ class MangaLibraryScreenModel(
addCategories: List<Long>,
removeCategories: List<Long>,
) {
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<LibraryDisplayMode> {
return libraryPreferences.displayMode().asState(coroutineScope)
return libraryPreferences.displayMode().asState(screenModelScope)
}
fun getColumnsPreferenceForCurrentOrientation(isLandscape: Boolean): PreferenceMutableState<Int> {
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 }

View file

@ -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)
}
}

View file

@ -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<DownloadQueueState> = 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,

View file

@ -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 -> {

View file

@ -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

View file

@ -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)

View file

@ -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
}
}

View file

@ -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<Nothing> { continuation ->
@ -234,6 +234,7 @@ class WebtoonPageHolder(
*/
private fun onImageDecoded() {
progressContainer.isVisible = false
removeErrorLayout()
}
/**

View file

@ -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 }

View file

@ -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 }

View file

@ -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<T>(
private val selectedCategory = MutableStateFlow(AllCategory)
init {
coroutineScope.launchIO {
screenModelScope.launchIO {
val hideHiddenCategories = libraryPreferences.hideHiddenCategoriesSettings().get()
combine(

View file

@ -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

View file

@ -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

View file

@ -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<Event> = Channel(Int.MAX_VALUE)
val events: Flow<Event> = _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<Long> = 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<Application>())
coroutineScope.launch {
screenModelScope.launch {
_events.send(Event.LibraryUpdateTriggered(started))
}
return started
@ -167,7 +167,7 @@ class AnimeUpdatesScreenModel(
fun downloadEpisodes(items: List<AnimeUpdatesItem>, 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<AnimeUpdatesItem>, 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<AnimeUpdatesItem>, 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<AnimeUpdatesItem>, 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<AnimeUpdatesItem>) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
updatesItem
.groupBy { it.update.animeId }
.entries

View file

@ -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<Event> = Channel(Int.MAX_VALUE)
val events: Flow<Event> = _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<Int> = arrayOf(-1, -1)
private val selectedChapterIds: HashSet<Long> = 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<Application>())
coroutineScope.launch {
screenModelScope.launch {
_events.send(Event.LibraryUpdateTriggered(started))
}
return started
@ -163,7 +163,7 @@ class MangaUpdatesScreenModel(
fun downloadChapters(items: List<MangaUpdatesItem>, 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<MangaUpdatesItem>, 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<MangaUpdatesItem>, 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<MangaUpdatesItem>) {
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<MangaUpdatesItem>) {
coroutineScope.launchNonCancellable {
screenModelScope.launchNonCancellable {
updatesItem
.groupBy { it.update.mangaId }
.entries

View file

@ -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)

View file

@ -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]

View file

@ -332,6 +332,8 @@
<string name="pref_double_tap_zoom">Double tap to zoom</string>
<string name="pref_cutout_short">Show content in cutout area</string>
<string name="pref_page_transitions">Animate page transitions</string>
<string name="pref_flash_page">Flash white on page change</string>
<string name="pref_flash_page_summ">Reduces ghosting on e-ink displays</string>
<string name="pref_double_tap_anim_speed">Double tap animation speed</string>
<string name="pref_show_page_number">Show page number</string>
<string name="pref_show_reading_mode">Show reading mode</string>

View file

@ -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<Float>(
durationMillis = ViewConfiguration.getScrollBarFadeDuration(),