From 7003463bac69b5a17167c66abce57cbbcdba316a Mon Sep 17 00:00:00 2001 From: Koitharu Date: Thu, 20 Mar 2025 07:52:08 +0200 Subject: [PATCH] Option to use disabled sources for suggestions --- .../koitharu/kotatsu/core/model/MangaSource.kt | 3 +++ .../koitharu/kotatsu/core/prefs/AppSettings.kt | 4 ++++ .../explore/data/MangaSourcesRepository.kt | 3 +-- .../suggestions/ui/SuggestionsWorker.kt | 18 ++++++++++++++++-- app/src/main/res/values/strings.xml | 3 +++ app/src/main/res/xml/pref_suggestions.xml | 8 ++++++++ 6 files changed, 35 insertions(+), 4 deletions(-) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt index 0abf3138d..7305386b0 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/model/MangaSource.kt @@ -22,6 +22,7 @@ import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.util.splitTwoParts +import java.util.Locale import com.google.android.material.R as materialR data object LocalMangaSource : MangaSource { @@ -79,6 +80,8 @@ tailrec fun MangaSource.unwrap(): MangaSource = if (this is MangaSourceInfo) { this } +fun MangaSource.getLocale(): Locale? = (unwrap() as? MangaParserSource)?.locale?.toLocale() + fun MangaSource.getSummary(context: Context): String? = when (val source = unwrap()) { is MangaParserSource -> { val type = context.getString(source.contentType.titleResId) diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt index 85d73cee6..7cec0067e 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/core/prefs/AppSettings.kt @@ -359,6 +359,9 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { val isSuggestionsExcludeNsfw: Boolean get() = prefs.getBoolean(KEY_SUGGESTIONS_EXCLUDE_NSFW, false) + val isSuggestionsIncludeDisabledSources: Boolean + get() = prefs.getBoolean(KEY_SUGGESTIONS_DISABLED_SOURCES, false) + val isSuggestionsNotificationAvailable: Boolean get() = prefs.getBoolean(KEY_SUGGESTIONS_NOTIFICATIONS, false) @@ -658,6 +661,7 @@ class AppSettings @Inject constructor(@ApplicationContext context: Context) { const val KEY_SUGGESTIONS_WIFI_ONLY = "suggestions_wifi" const val KEY_SUGGESTIONS_EXCLUDE_NSFW = "suggestions_exclude_nsfw" const val KEY_SUGGESTIONS_EXCLUDE_TAGS = "suggestions_exclude_tags" + const val KEY_SUGGESTIONS_DISABLED_SOURCES = "suggestions_disabled_sources" const val KEY_SUGGESTIONS_NOTIFICATIONS = "suggestions_notifications" const val KEY_SHIKIMORI = "shikimori" const val KEY_ANILIST = "anilist" diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/explore/data/MangaSourcesRepository.kt b/app/src/main/kotlin/org/koitharu/kotatsu/explore/data/MangaSourcesRepository.kt index 770890500..24726e457 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/explore/data/MangaSourcesRepository.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/explore/data/MangaSourcesRepository.kt @@ -6,7 +6,6 @@ import android.content.Intent import android.content.IntentFilter import androidx.core.content.ContextCompat import androidx.room.withTransaction -import dagger.hilt.android.qualifiers.ApplicationContext import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.trySendBlocking import kotlinx.coroutines.flow.Flow @@ -354,7 +353,7 @@ class MangaSourcesRepository @Inject constructor( .conflate() } - private fun getExternalSources() = context.packageManager.queryIntentContentProviders( + fun getExternalSources(): List = context.packageManager.queryIntentContentProviders( Intent("app.kotatsu.parser.PROVIDE_MANGA"), 0, ).map { resolveInfo -> ExternalMangaSource( diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt index 199c17735..d6ed0368d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/suggestions/ui/SuggestionsWorker.kt @@ -48,11 +48,13 @@ import org.koitharu.kotatsu.R import org.koitharu.kotatsu.browser.cloudflare.CaptchaNotifier import org.koitharu.kotatsu.core.exceptions.CloudFlareProtectedException import org.koitharu.kotatsu.core.model.distinctById +import org.koitharu.kotatsu.core.model.getLocale import org.koitharu.kotatsu.core.model.isNsfw import org.koitharu.kotatsu.core.nav.AppRouter import org.koitharu.kotatsu.core.nav.ReaderIntent import org.koitharu.kotatsu.core.parser.MangaRepository import org.koitharu.kotatsu.core.prefs.AppSettings +import org.koitharu.kotatsu.core.util.LocaleComparator import org.koitharu.kotatsu.core.util.ext.asArrayList import org.koitharu.kotatsu.core.util.ext.awaitUniqueWorkInfoByName import org.koitharu.kotatsu.core.util.ext.awaitWorkInfosByTag @@ -179,7 +181,7 @@ class SuggestionsWorker @AssistedInject constructor( historyRepository.getList(0, 20) + favouritesRepository.getLastManga(20) ).distinctById() - val sources = sourcesRepository.getEnabledSources() + val sources = getSources() if (seed.isEmpty() || sources.isEmpty()) { return 0 } @@ -188,7 +190,7 @@ class SuggestionsWorker @AssistedInject constructor( val semaphore = Semaphore(MAX_PARALLELISM) val producer = channelFlow { - for (it in sources.shuffled()) { + for (it in sources) { if (it.isNsfw() && (appSettings.isSuggestionsExcludeNsfw || appSettings.isNsfwContentDisabled)) { continue } @@ -243,6 +245,18 @@ class SuggestionsWorker @AssistedInject constructor( return suggestions.size } + private suspend fun getSources(): List { + if (appSettings.isSuggestionsIncludeDisabledSources) { + val result = sourcesRepository.allMangaSources.toMutableList() + result.addAll(sourcesRepository.getExternalSources()) + result.shuffle() + result.sortWith(compareBy(nullsLast(LocaleComparator())) { it.getLocale() }) + return result + } else { + return sourcesRepository.getEnabledSources().shuffled() + } + } + private suspend fun getList( source: MangaSource, tags: List, diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b37edda5e..ca880912c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -819,4 +819,7 @@ Clear browser data Clear browser data such as cache and cookies. Warning: Authorization in manga sources may become invalid Does not have permission to write a file + Adult manga will not be shown in suggestions. This option may work inaccurate with some sources + Include disabled sources + Show suggestions from all manga sources, including disabled ones diff --git a/app/src/main/res/xml/pref_suggestions.xml b/app/src/main/res/xml/pref_suggestions.xml index b88b19b99..ceb0b1127 100644 --- a/app/src/main/res/xml/pref_suggestions.xml +++ b/app/src/main/res/xml/pref_suggestions.xml @@ -17,6 +17,13 @@ android:summary="@string/suggestions_wifi_only_summary" android:title="@string/only_using_wifi" /> + +