Эх сурвалжийг харах

Allow partially loading extensions with individually marked NSFW sources

arkon 4 жил өмнө
parent
commit
421dfb4a2d

+ 5 - 0
app/src/main/java/eu/kanade/tachiyomi/annoations/Nsfw.kt

@@ -0,0 +1,5 @@
+package eu.kanade.tachiyomi.annoations
+
+@Retention(AnnotationRetention.RUNTIME)
+@Target(AnnotationTarget.CLASS)
+annotation class Nsfw

+ 1 - 1
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt

@@ -117,7 +117,7 @@ object PreferenceKeys {
 
     const val automaticExtUpdates = "automatic_ext_updates"
 
-    const val allowNsfwSources = "allow_nsfw_sources"
+    const val allowNsfwSource = "allow_nsfw_source"
 
     const val startScreen = "start_screen"
 

+ 6 - 0
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceValues.kt

@@ -37,4 +37,10 @@ object PreferenceValues {
         VERTICAL,
         BOTH
     }
+
+    enum class NsfwAllowance {
+        ALLOWED,
+        PARTIAL,
+        BLOCKED
+    }
 }

+ 2 - 1
app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt

@@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
 import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
 import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
+import eu.kanade.tachiyomi.data.preference.PreferenceValues.NsfwAllowance
 import eu.kanade.tachiyomi.data.track.TrackService
 import eu.kanade.tachiyomi.data.track.anilist.Anilist
 import java.io.File
@@ -217,7 +218,7 @@ class PreferencesHelper(val context: Context) {
 
     fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
 
-    fun allowNsfwSources() = prefs.getBoolean(Keys.allowNsfwSources, true)
+    fun allowNsfwSource() = flowPrefs.getEnum(Keys.allowNsfwSource, NsfwAllowance.ALLOWED)
 
     fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0)
 

+ 15 - 3
app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt

@@ -5,6 +5,8 @@ import android.content.Context
 import android.content.pm.PackageInfo
 import android.content.pm.PackageManager
 import dalvik.system.PathClassLoader
+import eu.kanade.tachiyomi.annoations.Nsfw
+import eu.kanade.tachiyomi.data.preference.PreferenceValues
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.model.Extension
 import eu.kanade.tachiyomi.extension.model.LoadResult
@@ -15,7 +17,6 @@ import eu.kanade.tachiyomi.util.lang.Hash
 import kotlinx.coroutines.async
 import kotlinx.coroutines.runBlocking
 import timber.log.Timber
-import uy.kohesive.injekt.api.get
 import uy.kohesive.injekt.injectLazy
 
 /**
@@ -128,7 +129,7 @@ internal object ExtensionLoader {
         }
 
         val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1
-        if (!preferences.allowNsfwSources() && isNsfw) {
+        if (preferences.allowNsfwSource().get() == PreferenceValues.NsfwAllowance.BLOCKED && isNsfw) {
             return LoadResult.Error("NSFW extension $pkgName not allowed")
         }
 
@@ -156,10 +157,11 @@ internal object ExtensionLoader {
                     return LoadResult.Error(e)
                 }
             }
+            .filter { preferences.allowNsfwSource().get() == PreferenceValues.NsfwAllowance.ALLOWED || !isSourceNsfw(it) }
+
         val langs = sources.filterIsInstance<CatalogueSource>()
             .map { it.lang }
             .toSet()
-
         val lang = when (langs.size) {
             0 -> ""
             1 -> langs.first()
@@ -195,4 +197,14 @@ internal object ExtensionLoader {
             null
         }
     }
+
+    /**
+     * Checks whether a source is annotated with @Nsfw.
+     */
+    private fun isSourceNsfw(source: Source): Boolean {
+        // Annotations are proxied, hence this janky way of checking for them
+        return source.javaClass.annotations
+            .flatMap { it.javaClass.interfaces.map { it.simpleName } }
+            .firstOrNull { it == Nsfw::class.java.simpleName } != null
+    }
 }

+ 5 - 4
app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt

@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.ui.browse.extension
 import android.app.Application
 import android.os.Bundle
 import eu.kanade.tachiyomi.R
+import eu.kanade.tachiyomi.data.preference.PreferenceValues
 import eu.kanade.tachiyomi.data.preference.PreferencesHelper
 import eu.kanade.tachiyomi.extension.ExtensionManager
 import eu.kanade.tachiyomi.extension.model.Extension
@@ -55,14 +56,14 @@ open class ExtensionPresenter(
     private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> {
         val context = Injekt.get<Application>()
         val activeLangs = preferences.enabledLanguages().get()
-        val allowNsfw = preferences.allowNsfwSources()
+        val showNsfwExtensions = preferences.allowNsfwSource().get() != PreferenceValues.NsfwAllowance.BLOCKED
 
         val (installed, untrusted, available) = tuple
 
         val items = mutableListOf<ExtensionItem>()
 
-        val updatesSorted = installed.filter { it.hasUpdate && (allowNsfw || !it.isNsfw) }.sortedBy { it.pkgName }
-        val installedSorted = installed.filter { !it.hasUpdate && (allowNsfw || !it.isNsfw) }.sortedWith(compareBy({ !it.isObsolete }, { it.pkgName }))
+        val updatesSorted = installed.filter { it.hasUpdate && (showNsfwExtensions || !it.isNsfw) }.sortedBy { it.pkgName }
+        val installedSorted = installed.filter { !it.hasUpdate && (showNsfwExtensions || !it.isNsfw) }.sortedWith(compareBy({ !it.isObsolete }, { it.pkgName }))
         val untrustedSorted = untrusted.sortedBy { it.pkgName }
         val availableSorted = available
             // Filter out already installed extensions and disabled languages
@@ -70,7 +71,7 @@ open class ExtensionPresenter(
                 installed.none { it.pkgName == avail.pkgName } &&
                     untrusted.none { it.pkgName == avail.pkgName } &&
                     (avail.lang in activeLangs || avail.lang == "all") &&
-                    (allowNsfw || !avail.isNsfw)
+                    (showNsfwExtensions || !avail.isNsfw)
             }
             .sortedBy { it.pkgName }
 

+ 17 - 3
app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt

@@ -3,8 +3,11 @@ package eu.kanade.tachiyomi.ui.setting
 import androidx.preference.PreferenceScreen
 import eu.kanade.tachiyomi.R
 import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
+import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
 import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
 import eu.kanade.tachiyomi.util.preference.defaultValue
+import eu.kanade.tachiyomi.util.preference.entriesRes
+import eu.kanade.tachiyomi.util.preference.listPreference
 import eu.kanade.tachiyomi.util.preference.onChange
 import eu.kanade.tachiyomi.util.preference.preferenceCategory
 import eu.kanade.tachiyomi.util.preference.switchPreference
@@ -29,10 +32,21 @@ class SettingsBrowseController : SettingsController() {
                     true
                 }
             }
-            switchPreference {
-                key = Keys.allowNsfwSources
+            listPreference {
+                key = Keys.allowNsfwSource
                 titleRes = R.string.pref_allow_nsfw_sources
-                defaultValue = true
+                entriesRes = arrayOf(
+                    R.string.pref_allow_nsfw_sources_allowed,
+                    R.string.pref_allow_nsfw_sources_allowed_multisource,
+                    R.string.pref_allow_nsfw_sources_blocked
+                )
+                entryValues = arrayOf(
+                    Values.NsfwAllowance.ALLOWED.name,
+                    Values.NsfwAllowance.PARTIAL.name,
+                    Values.NsfwAllowance.BLOCKED.name
+                )
+                defaultValue = Values.NsfwAllowance.ALLOWED.name
+                summary = "%s"
             }
         }
 

+ 4 - 1
app/src/main/res/values/strings.xml

@@ -330,7 +330,10 @@
 
       <!-- Browse section -->
     <string name="pref_enable_automatic_extension_updates">Check for extension updates</string>
-    <string name="pref_allow_nsfw_sources">Allow sources with NSFW content</string>
+    <string name="pref_allow_nsfw_sources">NSFW sources</string>
+    <string name="pref_allow_nsfw_sources_allowed">Allowed</string>
+    <string name="pref_allow_nsfw_sources_allowed_multisource">Block source but show in extensions list</string>
+    <string name="pref_allow_nsfw_sources_blocked">Blocked</string>
     <string name="pref_search_pinned_sources_only">Only include pinned sources</string>
 
       <!-- Backup section -->