From 1a61130f0b46addef036687b6c98f930e13147f8 Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 26 Mar 2023 13:12:32 -0400 Subject: [PATCH] Don't attempt to initialize manga details from BrowseSource or Search screens This was effectively DDoSing sources as it does a request for every entry to get the details (primarily a cover image). The expectation now is that users have to open individual entries to load the details/cover if needed. This isn't necessary for most sources, which are able to provide covers as part of the listing normally. --- .../presentation/browse/GlobalSearchScreen.kt | 6 ++-- .../browse/MigrateSearchScreen.kt | 6 ++-- .../migration/search/MigrateSearchScreen.kt | 4 +-- .../source/browse/BrowseSourceScreenModel.kt | 25 -------------- .../source/globalsearch/GlobalSearchScreen.kt | 7 +--- .../source/globalsearch/SearchScreenModel.kt | 34 ++----------------- 6 files changed, 10 insertions(+), 72 deletions(-) diff --git a/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt index 8bcccfb65c..9735e75361 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/GlobalSearchScreen.kt @@ -29,7 +29,7 @@ fun GlobalSearchScreen( navigateUp: () -> Unit, onChangeSearchQuery: (String?) -> Unit, onSearch: (String) -> Unit, - getManga: @Composable (CatalogueSource, Manga) -> State, + getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit, @@ -62,7 +62,7 @@ fun GlobalSearchScreen( private fun GlobalSearchContent( items: Map, contentPadding: PaddingValues, - getManga: @Composable (CatalogueSource, Manga) -> State, + getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit, @@ -96,7 +96,7 @@ private fun GlobalSearchContent( GlobalSearchCardRow( titles = result.result, - getManga = { getManga(source, it) }, + getManga = { getManga(it) }, onClick = onClickItem, onLongClick = onLongClickItem, ) diff --git a/app/src/main/java/eu/kanade/presentation/browse/MigrateSearchScreen.kt b/app/src/main/java/eu/kanade/presentation/browse/MigrateSearchScreen.kt index e33da5742d..a424de8091 100644 --- a/app/src/main/java/eu/kanade/presentation/browse/MigrateSearchScreen.kt +++ b/app/src/main/java/eu/kanade/presentation/browse/MigrateSearchScreen.kt @@ -21,7 +21,7 @@ import tachiyomi.presentation.core.components.material.Scaffold fun MigrateSearchScreen( navigateUp: () -> Unit, state: MigrateSearchState, - getManga: @Composable (CatalogueSource, Manga) -> State, + getManga: @Composable (Manga) -> State, onChangeSearchQuery: (String?) -> Unit, onSearch: (String) -> Unit, onClickSource: (CatalogueSource) -> Unit, @@ -58,7 +58,7 @@ private fun MigrateSearchContent( sourceId: Long, items: Map, contentPadding: PaddingValues, - getManga: @Composable (CatalogueSource, Manga) -> State, + getManga: @Composable (Manga) -> State, onClickSource: (CatalogueSource) -> Unit, onClickItem: (Manga) -> Unit, onLongClickItem: (Manga) -> Unit, @@ -85,7 +85,7 @@ private fun MigrateSearchContent( GlobalSearchCardRow( titles = result.result, - getManga = { getManga(source, it) }, + getManga = { getManga(it) }, onClick = onClickItem, onLongClick = onLongClickItem, ) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt index 639c1eb74b..73ad967800 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/MigrateSearchScreen.kt @@ -22,9 +22,7 @@ class MigrateSearchScreen(private val mangaId: Long) : Screen() { MigrateSearchScreen( navigateUp = navigator::pop, state = state, - getManga = { source, manga -> - screenModel.getManga(source = source, initialManga = manga) - }, + getManga = { screenModel.getManga(it) }, onChangeSearchQuery = screenModel::updateSearchQuery, onSearch = screenModel::search, onClickSource = { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt index cc7246b4a1..e4ee7aebb2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreenModel.kt @@ -16,9 +16,7 @@ import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.core.preference.asState import eu.kanade.domain.chapter.interactor.SyncChaptersWithTrackServiceTwoWay import eu.kanade.domain.manga.interactor.UpdateManga -import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.toDomainManga -import eu.kanade.domain.manga.model.toSManga import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.track.model.toDomainTrack import eu.kanade.tachiyomi.data.cache.CoverCache @@ -36,7 +34,6 @@ import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.map -import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.flow.update import kotlinx.coroutines.launch @@ -45,7 +42,6 @@ import tachiyomi.core.preference.CheckboxState import tachiyomi.core.preference.mapAsCheckboxState import tachiyomi.core.util.lang.launchIO import tachiyomi.core.util.lang.withIOContext -import tachiyomi.core.util.lang.withNonCancellableContext import tachiyomi.core.util.system.logcat import tachiyomi.domain.category.interactor.GetCategories import tachiyomi.domain.category.interactor.SetMangaCategories @@ -133,7 +129,6 @@ class BrowseSourceScreenModel( .filter { localManga -> !sourcePreferences.hideInLibraryItems().get() || !localManga.favorite } - .onEach(::initializeManga) .stateIn(coroutineScope) } } @@ -234,26 +229,6 @@ class BrowseSourceScreenModel( } } - /** - * Initialize a manga. - * - * @param manga to initialize. - */ - private suspend fun initializeManga(manga: Manga) { - if (manga.thumbnailUrl != null || manga.initialized) return - withNonCancellableContext { - try { - val networkManga = source.getMangaDetails(manga.toSManga()) - val updatedManga = manga.copyFrom(networkManga) - .copy(initialized = true) - - updateManga.await(updatedManga.toMangaUpdate()) - } catch (e: Exception) { - logcat(LogPriority.ERROR, e) - } - } - } - /** * Adds or removes a manga from the library. * diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt index 698d46b777..151e750444 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchScreen.kt @@ -33,12 +33,7 @@ class GlobalSearchScreen( navigateUp = navigator::pop, onChangeSearchQuery = screenModel::updateSearchQuery, onSearch = screenModel::search, - getManga = { source, manga -> - screenModel.getManga( - source = source, - initialManga = manga, - ) - }, + getManga = { screenModel.getManga(it) }, onClickSource = { if (!screenModel.incognitoMode.get()) { screenModel.lastUsedSourceId.set(it.id) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt index 96a549d42b..4979ac72bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/SearchScreenModel.kt @@ -6,9 +6,7 @@ import androidx.compose.runtime.produceState import cafe.adriel.voyager.core.model.StateScreenModel import cafe.adriel.voyager.core.model.coroutineScope import eu.kanade.domain.manga.interactor.UpdateManga -import eu.kanade.domain.manga.model.copyFrom import eu.kanade.domain.manga.model.toDomainManga -import eu.kanade.domain.manga.model.toSManga import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.source.CatalogueSource @@ -18,15 +16,11 @@ import kotlinx.coroutines.awaitAll import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.launch import kotlinx.coroutines.withContext -import logcat.LogPriority import tachiyomi.core.util.lang.awaitSingle import tachiyomi.core.util.lang.withIOContext -import tachiyomi.core.util.lang.withNonCancellableContext -import tachiyomi.core.util.system.logcat import tachiyomi.domain.manga.interactor.GetManga import tachiyomi.domain.manga.interactor.NetworkToLocalManga import tachiyomi.domain.manga.model.Manga -import tachiyomi.domain.manga.model.toMangaUpdate import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.util.concurrent.Executors @@ -57,43 +51,19 @@ abstract class SearchScreenModel( } @Composable - fun getManga(source: CatalogueSource, initialManga: Manga): State { + fun getManga(initialManga: Manga): State { return produceState(initialValue = initialManga) { getManga.subscribe(initialManga.url, initialManga.source) .collectLatest { manga -> if (manga == null) return@collectLatest - withIOContext { - initializeManga(source, manga) - } value = manga } } } - /** - * Initialize a manga. - * - * @param source to interact with - * @param manga to initialize. - */ - private suspend fun initializeManga(source: CatalogueSource, manga: Manga) { - if (manga.thumbnailUrl != null || manga.initialized) return - withNonCancellableContext { - try { - val networkManga = source.getMangaDetails(manga.toSManga()) - val updatedManga = manga.copyFrom(networkManga) - .copy(initialized = true) - - updateManga.await(updatedManga.toMangaUpdate()) - } catch (e: Exception) { - logcat(LogPriority.ERROR, e) - } - } - } - abstract fun getEnabledSources(): List - fun getSelectedSources(): List { + private fun getSelectedSources(): List { val filter = extensionFilter val enabledSources = getEnabledSources()