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:
parent
3eec207166
commit
a2cf210a52
@ -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
|
||||||
|
@ -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"
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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()
|
||||||
|
|
||||||
|
@ -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 }
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user