From 3610f4a6f20dfc9b701a088845337e59af55576b Mon Sep 17 00:00:00 2001 From: Cuong-Tran Date: Fri, 8 Nov 2024 22:29:37 +0700 Subject: [PATCH] Revert "Cleanup some code" This reverts commit ee81c3e9058e40c4a23bbc522f142f7d5594e26b. --- .../eu/kanade/core/util/CollectionUtils.kt | 61 ++++++++++++++++++- .../migration/search/SourceSearchScreen.kt | 3 +- .../source/browse/BrowseSourceScreen.kt | 4 +- .../source/browse/BrowseSourceScreenModel.kt | 9 ++- .../eu/kanade/tachiyomi/ui/home/HomeScreen.kt | 2 +- .../ui/library/LibraryScreenModel.kt | 6 +- .../tachiyomi/ui/stats/StatsScreenModel.kt | 6 +- .../exh/md/follows/MangaDexFollowsScreen.kt | 4 +- .../exh/md/similar/MangaDexSimilarScreen.kt | 4 +- .../main/java/exh/recs/RecommendsScreen.kt | 4 +- 10 files changed, 86 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt index e8eed9d3d..baf369e39 100644 --- a/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt +++ b/app/src/main/java/eu/kanade/core/util/CollectionUtils.kt @@ -1,6 +1,5 @@ package eu.kanade.core.util -import androidx.compose.ui.util.fastFilter import androidx.compose.ui.util.fastForEach import kotlin.contracts.ExperimentalContracts import kotlin.contracts.contract @@ -46,6 +45,21 @@ fun HashSet.addOrRemove(value: E, shouldAdd: Boolean) { } } +/** + * Returns a list containing only elements matching the given [predicate]. + * + * **Do not use for collections that come from public APIs**, since they may not support random + * access in an efficient way, and this method may actually be a lot slower. Only use for + * collections that are created by code we control and are known to support random access. + */ +@OptIn(ExperimentalContracts::class) +inline fun List.fastFilter(predicate: (T) -> Boolean): List { + contract { callsInPlace(predicate) } + val destination = ArrayList() + fastForEach { if (predicate(it)) destination.add(it) } + return destination +} + /** * Returns a list containing all elements not matching the given [predicate]. * @@ -56,7 +70,27 @@ fun HashSet.addOrRemove(value: E, shouldAdd: Boolean) { @OptIn(ExperimentalContracts::class) inline fun List.fastFilterNot(predicate: (T) -> Boolean): List { contract { callsInPlace(predicate) } - return fastFilter { !predicate(it) } + val destination = ArrayList() + fastForEach { if (!predicate(it)) destination.add(it) } + return destination +} + +/** + * Returns a list containing only the non-null results of applying the + * given [transform] function to each element in the original collection. + * + * **Do not use for collections that come from public APIs**, since they may not support random + * access in an efficient way, and this method may actually be a lot slower. Only use for + * collections that are created by code we control and are known to support random access. + */ +@OptIn(ExperimentalContracts::class) +inline fun List.fastMapNotNull(transform: (T) -> R?): List { + contract { callsInPlace(transform) } + val destination = ArrayList() + fastForEach { element -> + transform(element)?.let(destination::add) + } + return destination } /** @@ -97,3 +131,26 @@ inline fun List.fastCountNot(predicate: (T) -> Boolean): Int { fastForEach { if (predicate(it)) --count } return count } + +/** + * Returns a list containing only elements from the given collection + * having distinct keys returned by the given [selector] function. + * + * Among elements of the given collection with equal keys, only the first one will be present in the resulting list. + * The elements in the resulting list are in the same order as they were in the source collection. + * + * **Do not use for collections that come from public APIs**, since they may not support random + * access in an efficient way, and this method may actually be a lot slower. Only use for + * collections that are created by code we control and are known to support random access. + */ +@OptIn(ExperimentalContracts::class) +inline fun List.fastDistinctBy(selector: (T) -> K): List { + contract { callsInPlace(selector) } + val set = HashSet() + val list = ArrayList() + fastForEach { + val key = selector(it) + if (set.add(key)) list.add(it) + } + return list +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt index 312ecfa9b..a3e8807a1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SourceSearchScreen.kt @@ -123,6 +123,7 @@ data class SourceSearchScreen( }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, ) { paddingValues -> + val pagingFlow by screenModel.mangaPagerFlowFlow.collectAsState() val openMigrateDialog: (Manga) -> Unit = { // SY --> navigator.items @@ -134,7 +135,7 @@ data class SourceSearchScreen( } BrowseSourceContent( source = screenModel.source, - mangaList = screenModel.mangaPagerFlow.collectAsLazyPagingItems(), + mangaList = pagingFlow.collectAsLazyPagingItems(), columns = screenModel.getColumnsPreference(LocalConfiguration.current.orientation), // SY --> ehentaiBrowseDisplayMode = screenModel.ehentaiBrowseDisplayMode, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt index 5b71d8484..853004a72 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceScreen.kt @@ -312,9 +312,11 @@ data class BrowseSourceScreen( }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, ) { paddingValues -> + val pagingFlow by screenModel.mangaPagerFlowFlow.collectAsState() + BrowseSourceContent( source = screenModel.source, - mangaList = screenModel.mangaPagerFlow.collectAsLazyPagingItems(), + mangaList = pagingFlow.collectAsLazyPagingItems(), columns = screenModel.getColumnsPreference(LocalConfiguration.current.orientation), // SY --> ehentaiBrowseDisplayMode = screenModel.ehentaiBrowseDisplayMode, 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 c77b56beb..147657523 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 @@ -37,7 +37,9 @@ import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.delay import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.distinctUntilChanged +import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filterNotNull import kotlinx.coroutines.flow.firstOrNull import kotlinx.coroutines.flow.flatMapLatest @@ -201,9 +203,9 @@ open class BrowseSourceScreenModel( * Flow of Pager flow tied to [State.listing] */ private val hideInLibraryItems = sourcePreferences.hideInLibraryItems().get() - val mangaPagerFlow = state.map { it.listing } + val mangaPagerFlowFlow = state.map { it.listing } .distinctUntilChanged() - .flatMapLatest { listing -> + .map { listing -> Pager(PagingConfig(pageSize = 25)) { // SY --> createSourcePagingSource(listing.query ?: "", listing.filters) @@ -220,8 +222,9 @@ open class BrowseSourceScreenModel( } .filter { !hideInLibraryItems || !it.value.first.favorite } } + .cachedIn(ioCoroutineScope) } - .cachedIn(ioCoroutineScope) + .stateIn(ioCoroutineScope, SharingStarted.Lazily, emptyFlow()) fun getColumnsPreference(orientation: Int): GridCells { val isLandscape = orientation == Configuration.ORIENTATION_LANDSCAPE diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt index 333ea9973..1de9b5a27 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/home/HomeScreen.kt @@ -30,13 +30,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.semantics.contentDescription import androidx.compose.ui.semantics.semantics import androidx.compose.ui.text.style.TextOverflow -import androidx.compose.ui.util.fastFilter import androidx.compose.ui.util.fastForEach import cafe.adriel.voyager.navigator.LocalNavigator import cafe.adriel.voyager.navigator.currentOrThrow import cafe.adriel.voyager.navigator.tab.LocalTabNavigator import cafe.adriel.voyager.navigator.tab.TabNavigator import eu.kanade.core.preference.asState +import eu.kanade.core.util.fastFilter import eu.kanade.domain.source.service.SourcePreferences import eu.kanade.domain.ui.UiPreferences import eu.kanade.presentation.util.Screen diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt index f0ffdacc0..df454f095 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryScreenModel.kt @@ -7,16 +7,16 @@ import androidx.compose.runtime.getValue import androidx.compose.runtime.setValue import androidx.compose.ui.util.fastAll import androidx.compose.ui.util.fastAny -import androidx.compose.ui.util.fastDistinctBy -import androidx.compose.ui.util.fastFilter import androidx.compose.ui.util.fastForEach import androidx.compose.ui.util.fastMap -import androidx.compose.ui.util.fastMapNotNull import cafe.adriel.voyager.core.model.StateScreenModel 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 +import eu.kanade.core.util.fastFilter import eu.kanade.core.util.fastFilterNot +import eu.kanade.core.util.fastMapNotNull import eu.kanade.core.util.fastPartition import eu.kanade.domain.base.BasePreferences import eu.kanade.domain.chapter.interactor.SetReadStatus diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt index f5726e82f..5889ea0ab 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/stats/StatsScreenModel.kt @@ -1,12 +1,12 @@ package eu.kanade.tachiyomi.ui.stats -import androidx.compose.ui.util.fastDistinctBy -import androidx.compose.ui.util.fastFilter -import androidx.compose.ui.util.fastMapNotNull import cafe.adriel.voyager.core.model.StateScreenModel 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 import eu.kanade.core.util.fastFilterNot +import eu.kanade.core.util.fastMapNotNull import eu.kanade.presentation.more.stats.StatsScreenState import eu.kanade.presentation.more.stats.data.StatsData import eu.kanade.tachiyomi.data.download.DownloadManager diff --git a/app/src/main/java/exh/md/follows/MangaDexFollowsScreen.kt b/app/src/main/java/exh/md/follows/MangaDexFollowsScreen.kt index 20f0aef5f..7ebdbb194 100644 --- a/app/src/main/java/exh/md/follows/MangaDexFollowsScreen.kt +++ b/app/src/main/java/exh/md/follows/MangaDexFollowsScreen.kt @@ -102,9 +102,11 @@ class MangaDexFollowsScreen(private val sourceId: Long) : Screen() { SnackbarHost(hostState = snackbarHostState) }, ) { paddingValues -> + val pagingFlow by screenModel.mangaPagerFlowFlow.collectAsState() + BrowseSourceContent( source = screenModel.source, - mangaList = screenModel.mangaPagerFlow.collectAsLazyPagingItems(), + mangaList = pagingFlow.collectAsLazyPagingItems(), columns = screenModel.getColumnsPreference(LocalConfiguration.current.orientation), // SY --> ehentaiBrowseDisplayMode = screenModel.ehentaiBrowseDisplayMode, diff --git a/app/src/main/java/exh/md/similar/MangaDexSimilarScreen.kt b/app/src/main/java/exh/md/similar/MangaDexSimilarScreen.kt index dd5bcebd0..9dc9d2cdc 100644 --- a/app/src/main/java/exh/md/similar/MangaDexSimilarScreen.kt +++ b/app/src/main/java/exh/md/similar/MangaDexSimilarScreen.kt @@ -96,9 +96,11 @@ class MangaDexSimilarScreen(val mangaId: Long, val sourceId: Long) : Screen() { }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, ) { paddingValues -> + val pagingFlow by screenModel.mangaPagerFlowFlow.collectAsState() + BrowseSourceContent( source = screenModel.source, - mangaList = screenModel.mangaPagerFlow.collectAsLazyPagingItems(), + mangaList = pagingFlow.collectAsLazyPagingItems(), columns = screenModel.getColumnsPreference(LocalConfiguration.current.orientation), // SY --> ehentaiBrowseDisplayMode = false, diff --git a/app/src/main/java/exh/recs/RecommendsScreen.kt b/app/src/main/java/exh/recs/RecommendsScreen.kt index b656a4b9e..944fb6003 100644 --- a/app/src/main/java/exh/recs/RecommendsScreen.kt +++ b/app/src/main/java/exh/recs/RecommendsScreen.kt @@ -95,9 +95,11 @@ class RecommendsScreen(val mangaId: Long, val sourceId: Long) : Screen() { }, snackbarHost = { SnackbarHost(hostState = snackbarHostState) }, ) { paddingValues -> + val pagingFlow by screenModel.mangaPagerFlowFlow.collectAsState() + BrowseSourceContent( source = screenModel.source, - mangaList = screenModel.mangaPagerFlow.collectAsLazyPagingItems(), + mangaList = pagingFlow.collectAsLazyPagingItems(), columns = screenModel.getColumnsPreference(LocalConfiguration.current.orientation), // SY --> ehentaiBrowseDisplayMode = false,