mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2025-01-03 09:41:51 +01:00
Option to hide NSFW extensions (closes #1312)
This commit is contained in:
parent
8bab1d9798
commit
abaca6e676
@ -117,6 +117,8 @@ object PreferenceKeys {
|
|||||||
|
|
||||||
const val automaticExtUpdates = "automatic_ext_updates"
|
const val automaticExtUpdates = "automatic_ext_updates"
|
||||||
|
|
||||||
|
const val allowNsfwSources = "allow_nsfw_sources"
|
||||||
|
|
||||||
const val startScreen = "start_screen"
|
const val startScreen = "start_screen"
|
||||||
|
|
||||||
const val useBiometricLock = "use_biometric_lock"
|
const val useBiometricLock = "use_biometric_lock"
|
||||||
|
@ -217,6 +217,8 @@ class PreferencesHelper(val context: Context) {
|
|||||||
|
|
||||||
fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
|
fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
|
||||||
|
|
||||||
|
fun allowNsfwSources() = prefs.getBoolean(Keys.allowNsfwSources, true)
|
||||||
|
|
||||||
fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0)
|
fun extensionUpdatesCount() = flowPrefs.getInt("ext_updates_count", 0)
|
||||||
|
|
||||||
fun lastExtCheck() = flowPrefs.getLong("last_ext_check", 0)
|
fun lastExtCheck() = flowPrefs.getLong("last_ext_check", 0)
|
||||||
|
@ -64,9 +64,10 @@ internal class ExtensionGithubApi {
|
|||||||
val versionName = element["version"].string
|
val versionName = element["version"].string
|
||||||
val versionCode = element["code"].int
|
val versionCode = element["code"].int
|
||||||
val lang = element["lang"].string
|
val lang = element["lang"].string
|
||||||
|
val nsfw = element["nsfw"].int == 1
|
||||||
val icon = "$REPO_URL_PREFIX/icon/${apkName.replace(".apk", ".png")}"
|
val icon = "$REPO_URL_PREFIX/icon/${apkName.replace(".apk", ".png")}"
|
||||||
|
|
||||||
Extension.Available(name, pkgName, versionName, versionCode, lang, apkName, icon)
|
Extension.Available(name, pkgName, versionName, versionCode, lang, nsfw, apkName, icon)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,14 +9,16 @@ sealed class Extension {
|
|||||||
abstract val versionName: String
|
abstract val versionName: String
|
||||||
abstract val versionCode: Int
|
abstract val versionCode: Int
|
||||||
abstract val lang: String?
|
abstract val lang: String?
|
||||||
|
abstract val isNsfw: Boolean
|
||||||
|
|
||||||
data class Installed(
|
data class Installed(
|
||||||
override val name: String,
|
override val name: String,
|
||||||
override val pkgName: String,
|
override val pkgName: String,
|
||||||
override val versionName: String,
|
override val versionName: String,
|
||||||
override val versionCode: Int,
|
override val versionCode: Int,
|
||||||
val sources: List<Source>,
|
|
||||||
override val lang: String,
|
override val lang: String,
|
||||||
|
override val isNsfw: Boolean,
|
||||||
|
val sources: List<Source>,
|
||||||
val hasUpdate: Boolean = false,
|
val hasUpdate: Boolean = false,
|
||||||
val isObsolete: Boolean = false,
|
val isObsolete: Boolean = false,
|
||||||
val isUnofficial: Boolean = false
|
val isUnofficial: Boolean = false
|
||||||
@ -28,6 +30,7 @@ sealed class Extension {
|
|||||||
override val versionName: String,
|
override val versionName: String,
|
||||||
override val versionCode: Int,
|
override val versionCode: Int,
|
||||||
override val lang: String,
|
override val lang: String,
|
||||||
|
override val isNsfw: Boolean,
|
||||||
val apkName: String,
|
val apkName: String,
|
||||||
val iconUrl: String
|
val iconUrl: String
|
||||||
) : Extension()
|
) : Extension()
|
||||||
@ -38,6 +41,7 @@ sealed class Extension {
|
|||||||
override val versionName: String,
|
override val versionName: String,
|
||||||
override val versionCode: Int,
|
override val versionCode: Int,
|
||||||
val signatureHash: String,
|
val signatureHash: String,
|
||||||
override val lang: String? = null
|
override val lang: String? = null,
|
||||||
|
override val isNsfw: Boolean = false
|
||||||
) : Extension()
|
) : Extension()
|
||||||
}
|
}
|
||||||
|
@ -15,8 +15,8 @@ import eu.kanade.tachiyomi.util.lang.Hash
|
|||||||
import kotlinx.coroutines.async
|
import kotlinx.coroutines.async
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import uy.kohesive.injekt.Injekt
|
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class that handles the loading of the extensions installed in the system.
|
* Class that handles the loading of the extensions installed in the system.
|
||||||
@ -24,8 +24,11 @@ import uy.kohesive.injekt.api.get
|
|||||||
@SuppressLint("PackageManagerGetSignatures")
|
@SuppressLint("PackageManagerGetSignatures")
|
||||||
internal object ExtensionLoader {
|
internal object ExtensionLoader {
|
||||||
|
|
||||||
|
private val preferences: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
private const val EXTENSION_FEATURE = "tachiyomi.extension"
|
private const val EXTENSION_FEATURE = "tachiyomi.extension"
|
||||||
private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
private const val METADATA_SOURCE_CLASS = "tachiyomi.extension.class"
|
||||||
|
private const val METADATA_NSFW = "tachiyomi.extension.nsfw"
|
||||||
const val LIB_VERSION_MIN = 1.2
|
const val LIB_VERSION_MIN = 1.2
|
||||||
const val LIB_VERSION_MAX = 1.2
|
const val LIB_VERSION_MAX = 1.2
|
||||||
|
|
||||||
@ -36,8 +39,7 @@ internal object ExtensionLoader {
|
|||||||
/**
|
/**
|
||||||
* List of the trusted signatures.
|
* List of the trusted signatures.
|
||||||
*/
|
*/
|
||||||
var trustedSignatures = mutableSetOf<String>() +
|
var trustedSignatures = mutableSetOf<String>() + preferences.trustedSignatures().get() + officialSignature
|
||||||
Injekt.get<PreferencesHelper>().trustedSignatures().get() + officialSignature
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a list of all the installed extensions initialized concurrently.
|
* Return a list of all the installed extensions initialized concurrently.
|
||||||
@ -125,6 +127,11 @@ internal object ExtensionLoader {
|
|||||||
return LoadResult.Untrusted(extension)
|
return LoadResult.Untrusted(extension)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1
|
||||||
|
if (!preferences.allowNsfwSources() && isNsfw) {
|
||||||
|
return LoadResult.Error("NSFW extension $pkgName not allowed")
|
||||||
|
}
|
||||||
|
|
||||||
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
val classLoader = PathClassLoader(appInfo.sourceDir, null, context.classLoader)
|
||||||
|
|
||||||
val sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
|
val sources = appInfo.metaData.getString(METADATA_SOURCE_CLASS)!!
|
||||||
@ -160,7 +167,7 @@ internal object ExtensionLoader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val extension = Extension.Installed(
|
val extension = Extension.Installed(
|
||||||
extName, pkgName, versionName, versionCode, sources, lang,
|
extName, pkgName, versionName, versionCode, lang, isNsfw, sources,
|
||||||
isUnofficial = signatureHash != officialSignature
|
isUnofficial = signatureHash != officialSignature
|
||||||
)
|
)
|
||||||
return LoadResult.Success(extension)
|
return LoadResult.Success(extension)
|
||||||
|
@ -55,20 +55,22 @@ 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 allowNsfw = preferences.allowNsfwSources()
|
||||||
|
|
||||||
val (installed, untrusted, available) = tuple
|
val (installed, untrusted, available) = tuple
|
||||||
|
|
||||||
val items = mutableListOf<ExtensionItem>()
|
val items = mutableListOf<ExtensionItem>()
|
||||||
|
|
||||||
val updatesSorted = installed.filter { it.hasUpdate }.sortedBy { it.pkgName }
|
val updatesSorted = installed.filter { it.hasUpdate && (allowNsfw || !it.isNsfw) }.sortedBy { it.pkgName }
|
||||||
val installedSorted = installed.filter { !it.hasUpdate }.sortedWith(compareBy({ !it.isObsolete }, { it.pkgName }))
|
val installedSorted = installed.filter { !it.hasUpdate && (allowNsfw || !it.isNsfw) }.sortedWith(compareBy({ !it.isObsolete }, { it.pkgName }))
|
||||||
val untrustedSorted = untrusted.sortedBy { it.pkgName }
|
val untrustedSorted = untrusted.sortedBy { it.pkgName }
|
||||||
val availableSorted = available
|
val availableSorted = available
|
||||||
// Filter out already installed extensions and disabled languages
|
// Filter out already installed extensions and disabled languages
|
||||||
.filter { avail ->
|
.filter { avail ->
|
||||||
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") &&
|
||||||
|
(allowNsfw || !avail.isNsfw)
|
||||||
}
|
}
|
||||||
.sortedBy { it.pkgName }
|
.sortedBy { it.pkgName }
|
||||||
|
|
||||||
|
@ -29,6 +29,11 @@ class SettingsBrowseController : SettingsController() {
|
|||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
switchPreference {
|
||||||
|
key = Keys.allowNsfwSources
|
||||||
|
titleRes = R.string.pref_allow_nsfw_sources
|
||||||
|
defaultValue = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
|
@ -330,6 +330,7 @@
|
|||||||
|
|
||||||
<!-- Browse section -->
|
<!-- Browse section -->
|
||||||
<string name="pref_enable_automatic_extension_updates">Check for extension updates</string>
|
<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_search_pinned_sources_only">Only include pinned sources</string>
|
<string name="pref_search_pinned_sources_only">Only include pinned sources</string>
|
||||||
|
|
||||||
<!-- Backup section -->
|
<!-- Backup section -->
|
||||||
|
Loading…
Reference in New Issue
Block a user