Unify NSFW flagging for sources/extensions

Since multisource extensions are no longer a thing, we now simply rely on the flag at the extension level, i.e. the per-Source/SourceFactory `@Nsfw` annotation is no longer checked.
We'll have to remove all of the annotation usages from the existing sources, which will also effectively break the setting for older versions of the app.
This commit is contained in:
arkon 2021-09-13 17:49:58 -04:00
parent 3eec207166
commit a2cf210a52
9 changed files with 8 additions and 60 deletions

View file

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.annotations package eu.kanade.tachiyomi.annotations
// TODO: remove this when no longer used in extensions
@Retention(AnnotationRetention.RUNTIME) @Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
annotation class Nsfw annotation class Nsfw

View file

@ -154,8 +154,6 @@ object PreferenceKeys {
const val automaticExtUpdates = "automatic_ext_updates" const val automaticExtUpdates = "automatic_ext_updates"
const val showNsfwSource = "show_nsfw_source" const val showNsfwSource = "show_nsfw_source"
const val showNsfwExtension = "show_nsfw_extension"
const val labelNsfwExtension = "label_nsfw_extension"
const val startScreen = "start_screen" const val startScreen = "start_screen"

View file

@ -271,8 +271,6 @@ class PreferencesHelper(val context: Context) {
fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true) fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
fun showNsfwSource() = flowPrefs.getBoolean(Keys.showNsfwSource, true) fun showNsfwSource() = flowPrefs.getBoolean(Keys.showNsfwSource, true)
fun showNsfwExtension() = flowPrefs.getBoolean(Keys.showNsfwExtension, true)
fun labelNsfwExtension() = prefs.getBoolean(Keys.labelNsfwExtension, true)
fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0) fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0)

View file

@ -6,7 +6,6 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import androidx.core.content.pm.PackageInfoCompat import androidx.core.content.pm.PackageInfoCompat
import dalvik.system.PathClassLoader import dalvik.system.PathClassLoader
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.LoadResult import eu.kanade.tachiyomi.extension.model.LoadResult
@ -154,13 +153,7 @@ internal object ExtensionLoader {
try { try {
when (val obj = Class.forName(it, false, classLoader).newInstance()) { when (val obj = Class.forName(it, false, classLoader).newInstance()) {
is Source -> listOf(obj) is Source -> listOf(obj)
is SourceFactory -> { is SourceFactory -> obj.createSources()
if (isSourceNsfw(obj)) {
emptyList()
} else {
obj.createSources()
}
}
else -> throw Exception("Unknown source class type! ${obj.javaClass}") else -> throw Exception("Unknown source class type! ${obj.javaClass}")
} }
} catch (e: Throwable) { } catch (e: Throwable) {
@ -168,7 +161,6 @@ internal object ExtensionLoader {
return LoadResult.Error(e) return LoadResult.Error(e)
} }
} }
.filter { !isSourceNsfw(it) }
val langs = sources.filterIsInstance<CatalogueSource>() val langs = sources.filterIsInstance<CatalogueSource>()
.map { it.lang } .map { it.lang }
@ -215,22 +207,4 @@ internal object ExtensionLoader {
null null
} }
} }
/**
* Checks whether a Source or SourceFactory is annotated with @Nsfw.
*/
private fun isSourceNsfw(clazz: Any): Boolean {
if (loadNsfwSource) {
return false
}
if (clazz !is Source && clazz !is SourceFactory) {
return false
}
// Annotations are proxied, hence this janky way of checking for them
return clazz.javaClass.annotations
.flatMap { it.javaClass.interfaces.map { it.simpleName } }
.firstOrNull { it == Nsfw::class.java.simpleName } != null
}
} }

View file

@ -11,7 +11,6 @@ import rx.Observable
open class SourceManager(private val context: Context) { open class SourceManager(private val context: Context) {
private val sourcesMap = mutableMapOf<Long, Source>() private val sourcesMap = mutableMapOf<Long, Source>()
private val stubSourcesMap = mutableMapOf<Long, StubSource>() private val stubSourcesMap = mutableMapOf<Long, StubSource>()
init { init {

View file

@ -5,12 +5,10 @@ import coil.clear
import coil.load import coil.load
import eu.davidea.viewholders.FlexibleViewHolder import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.ExtensionCardItemBinding import eu.kanade.tachiyomi.databinding.ExtensionCardItemBinding
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.extension.model.InstallStep
import eu.kanade.tachiyomi.util.system.LocaleHelper import eu.kanade.tachiyomi.util.system.LocaleHelper
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
class ExtensionHolder(view: View, val adapter: ExtensionAdapter) : class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
@ -18,10 +16,6 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
private val binding = ExtensionCardItemBinding.bind(view) private val binding = ExtensionCardItemBinding.bind(view)
private val shouldLabelNsfw by lazy {
Injekt.get<PreferencesHelper>().labelNsfwExtension()
}
init { init {
binding.extButton.setOnClickListener { binding.extButton.setOnClickListener {
adapter.buttonClickListener.onButtonClick(bindingAdapterPosition) adapter.buttonClickListener.onButtonClick(bindingAdapterPosition)
@ -38,7 +32,7 @@ class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
extension is Extension.Untrusted -> itemView.context.getString(R.string.ext_untrusted) extension is Extension.Untrusted -> itemView.context.getString(R.string.ext_untrusted)
extension is Extension.Installed && extension.isUnofficial -> itemView.context.getString(R.string.ext_unofficial) extension is Extension.Installed && extension.isUnofficial -> itemView.context.getString(R.string.ext_unofficial)
extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.ext_obsolete) extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.ext_obsolete)
extension.isNsfw && shouldLabelNsfw -> itemView.context.getString(R.string.ext_nsfw_short) extension.isNsfw -> itemView.context.getString(R.string.ext_nsfw_short)
else -> "" else -> ""
}.uppercase() }.uppercase()

View file

@ -55,14 +55,14 @@ open class ExtensionPresenter(
private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> { private fun toItems(tuple: ExtensionTuple): List<ExtensionItem> {
val context = Injekt.get<Application>() val context = Injekt.get<Application>()
val activeLangs = preferences.enabledLanguages().get() val activeLangs = preferences.enabledLanguages().get()
val showNsfwExtensions = preferences.showNsfwExtension().get() val showNsfwSources = preferences.showNsfwSource().get()
val (installed, untrusted, available) = tuple val (installed, untrusted, available) = tuple
val items = mutableListOf<ExtensionItem>() val items = mutableListOf<ExtensionItem>()
val updatesSorted = installed.filter { it.hasUpdate && (showNsfwExtensions || !it.isNsfw) }.sortedBy { it.name } val updatesSorted = installed.filter { it.hasUpdate && (showNsfwSources || !it.isNsfw) }.sortedBy { it.name }
val installedSorted = installed.filter { !it.hasUpdate && (showNsfwExtensions || !it.isNsfw) }.sortedWith(compareBy({ !it.isObsolete }, { it.name })) val installedSorted = installed.filter { !it.hasUpdate && (showNsfwSources || !it.isNsfw) }.sortedWith(compareBy({ !it.isObsolete }, { it.name }))
val untrustedSorted = untrusted.sortedBy { it.name } val untrustedSorted = untrusted.sortedBy { it.name }
val availableSorted = available val availableSorted = available
// Filter out already installed extensions and disabled languages // Filter out already installed extensions and disabled languages
@ -70,7 +70,7 @@ open class ExtensionPresenter(
installed.none { it.pkgName == avail.pkgName } && installed.none { it.pkgName == avail.pkgName } &&
untrusted.none { it.pkgName == avail.pkgName } && untrusted.none { it.pkgName == avail.pkgName } &&
(avail.lang in activeLangs || avail.lang == "all") && (avail.lang in activeLangs || avail.lang == "all") &&
(showNsfwExtensions || !avail.isNsfw) (showNsfwSources || !avail.isNsfw)
} }
.sortedBy { it.name } .sortedBy { it.name }

View file

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.setting
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.defaultValue
import eu.kanade.tachiyomi.util.preference.infoPreference import eu.kanade.tachiyomi.util.preference.infoPreference
@ -11,7 +10,6 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory
import eu.kanade.tachiyomi.util.preference.summaryRes import eu.kanade.tachiyomi.util.preference.summaryRes
import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.switchPreference
import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.preference.titleRes
import kotlinx.coroutines.flow.launchIn
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
class SettingsBrowseController : SettingsController() { class SettingsBrowseController : SettingsController() {
@ -54,18 +52,6 @@ class SettingsBrowseController : SettingsController() {
summaryRes = R.string.requires_app_restart summaryRes = R.string.requires_app_restart
defaultValue = true defaultValue = true
} }
switchPreference {
key = Keys.showNsfwExtension
titleRes = R.string.pref_show_nsfw_extension
defaultValue = true
}
switchPreference {
key = Keys.labelNsfwExtension
titleRes = R.string.pref_label_nsfw_extension
defaultValue = true
preferences.showNsfwExtension().asImmediateFlow { isVisible = it }.launchIn(viewScope)
}
infoPreference(R.string.parental_controls_info) infoPreference(R.string.parental_controls_info)
} }

View file

@ -189,9 +189,7 @@
<string name="hide_notification_content">Hide notification content</string> <string name="hide_notification_content">Hide notification content</string>
<string name="pref_category_nsfw_content">NSFW (18+) sources</string> <string name="pref_category_nsfw_content">NSFW (18+) sources</string>
<string name="pref_show_nsfw_source">Show in sources list</string> <string name="pref_show_nsfw_source">Show in sources and extensions lists</string>
<string name="pref_show_nsfw_extension">Show in extensions list</string>
<string name="pref_label_nsfw_extension">Label in extensions list</string>
<string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app.</string> <string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing NSFW (18+) content within the app.</string>
<string name="recently">Recently</string> <string name="recently">Recently</string>