Compare commits

...

20 Commits

Author SHA1 Message Date
c87ba6231d Release 0.10.7 2020-12-13 21:02:28 -05:00
c5ca739b49 Fix loading fallback thumbnails in browse view (closes #4127) 2020-12-13 20:47:48 -05:00
00fe4cdf2d Minor code cleanup 2020-12-13 18:11:18 -05:00
69be3e1e87 Complete migration off of Kotlin synthetics 2020-12-13 18:01:51 -05:00
2cb3984d68 Show MAL relogin message on update, localize error message 2020-12-13 17:52:21 -05:00
5901978889 Use view binding for date headers 2020-12-13 17:47:29 -05:00
8bf1cf3cc5 Update to coroutines 1.4.2
Should fix crashes on some devices. See https://github.com/Kotlin/kotlinx.coroutines/issues/2371
2020-12-13 17:18:59 -05:00
f6af1184bc Reword NSFW settings section 2020-12-13 17:18:38 -05:00
4880741b8b More crash fixes 2020-12-13 17:18:28 -05:00
e8627800fe Remove bundled fallback file picker 2020-12-13 12:42:10 -05:00
907fbb94a2 Require WebView 86+ 2020-12-13 11:27:05 -05:00
fd2028557e Some crash fixes 2020-12-13 11:00:46 -05:00
91fa1ec6b2 Suppress some deprecation warnings 2020-12-12 23:50:28 -05:00
628c525599 Disable release postprocessing (Proguard)
Caused the following error for someone:

Detected problmes with app native libraries (please consult log for detail):
libavcoded.so: text relocations
libswresample.so:test relocations
2020-12-12 23:50:05 -05:00
bbc00768f0 Note that toggling NSFW sources requires a restart 2020-12-12 17:27:11 -05:00
5b09461ccf Break out NSFW hiding/labeling into separate settings 2020-12-12 17:20:54 -05:00
1a439ecece Remove source overwrite logic since built-in sources no longer exist 2020-12-12 16:15:18 -05:00
836aec4396 Flip left/right key events for Webtoon viewer (fixes #4111) 2020-12-12 15:50:56 -05:00
0b5dec9bab Revert "Hide incomplete NSFW source labelling settings"
This reverts commit a3b1690d38.
2020-12-12 11:32:55 -05:00
fd56123267 [SKIP CI] Update issue templates 2020-12-12 11:32:44 -05:00
85 changed files with 214 additions and 337 deletions

View File

@ -2,7 +2,7 @@
I acknowledge that: I acknowledge that:
- I have updated to the latest version of the app (stable is v0.10.5) - I have updated to the latest version of the app (stable is v0.10.7)
- I have updated all extensions - I have updated all extensions
- If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions

View File

@ -9,7 +9,7 @@ labels: "bug"
I acknowledge that: I acknowledge that:
- I have updated to the latest version of the app (stable is v0.10.5) - I have updated to the latest version of the app (stable is v0.10.7)
- I have updated all extensions - I have updated all extensions
- If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions

View File

@ -9,7 +9,7 @@ labels: "feature"
I acknowledge that: I acknowledge that:
- I have updated to the latest version of the app (stable is v0.10.5) - I have updated to the latest version of the app (stable is v0.10.7)
- I have updated all extensions - I have updated all extensions
- If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions

View File

@ -58,7 +58,7 @@ DON'T: https://github.com/inorichi/tachiyomi/issues/75
* Write a detailed issue, explaining what it should do or how. Avoid writing just "like X app does" * Write a detailed issue, explaining what it should do or how. Avoid writing just "like X app does"
* Include screenshot (if needed) * Include screenshot (if needed)
Catalogue requests should be created at https://github.com/inorichi/tachiyomi-extensions, they do not belong in this repository. Source requests should be created at https://github.com/inorichi/tachiyomi-extensions, they do not belong in this repository.
</details> </details>
## FAQ ## FAQ

View File

@ -5,8 +5,8 @@ import java.text.SimpleDateFormat
apply plugin: 'com.android.application' apply plugin: 'com.android.application'
apply plugin: 'com.mikepenz.aboutlibraries.plugin' apply plugin: 'com.mikepenz.aboutlibraries.plugin'
apply plugin: 'kotlin-android' apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-kapt'
apply plugin: 'kotlin-parcelize'
apply plugin: 'kotlinx-serialization' apply plugin: 'kotlinx-serialization'
apply plugin: 'com.github.zellius.shortcut-helper' apply plugin: 'com.github.zellius.shortcut-helper'
@ -42,8 +42,8 @@ android {
minSdkVersion AndroidConfig.minSdk minSdkVersion AndroidConfig.minSdk
targetSdkVersion AndroidConfig.targetSdk targetSdkVersion AndroidConfig.targetSdk
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
versionCode 52 versionCode 53
versionName "0.10.6" versionName "0.10.7"
buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\""
buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\""
@ -67,13 +67,13 @@ android {
applicationIdSuffix ".debug" applicationIdSuffix ".debug"
} }
release { release {
postprocessing { // postprocessing {
obfuscate false // obfuscate false
optimizeCode true // optimizeCode true
removeUnusedCode false // removeUnusedCode false
removeUnusedResources true // removeUnusedResources true
proguardFiles 'proguard-rules.pro' // proguardFiles 'proguard-rules.pro'
} // }
} }
} }
@ -123,10 +123,6 @@ android {
} }
} }
androidExtensions {
experimental = true
}
dependencies { dependencies {
// Source models and interfaces from Tachiyomi 1.x // Source models and interfaces from Tachiyomi 1.x
@ -239,7 +235,6 @@ dependencies {
implementation 'com.github.dmytrodanylyk.android-process-button:library:1.0.4' implementation 'com.github.dmytrodanylyk.android-process-button:library:1.0.4'
implementation 'eu.davidea:flexible-adapter:5.1.0' implementation 'eu.davidea:flexible-adapter:5.1.0'
implementation 'eu.davidea:flexible-adapter-ui:1.0.0' implementation 'eu.davidea:flexible-adapter-ui:1.0.0'
implementation 'com.nononsenseapps:filepicker:2.5.2'
implementation 'com.nightlynexus.viewstatepageradapter:viewstatepageradapter:1.1.0' implementation 'com.nightlynexus.viewstatepageradapter:viewstatepageradapter:1.1.0'
implementation 'com.github.chrisbanes:PhotoView:2.3.0' implementation 'com.github.chrisbanes:PhotoView:2.3.0'
implementation 'com.github.carlosesco:DirectionalViewPager:a844dbca0a' implementation 'com.github.carlosesco:DirectionalViewPager:a844dbca0a'
@ -280,7 +275,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-reflect:$BuildPluginsVersion.KOTLIN" implementation "org.jetbrains.kotlin:kotlin-reflect:$BuildPluginsVersion.KOTLIN"
final coroutines_version = '1.4.1' final coroutines_version = '1.4.2'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$coroutines_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version" implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"

View File

@ -80,10 +80,6 @@
<activity <activity
android:name=".ui.webview.WebViewActivity" android:name=".ui.webview.WebViewActivity"
android:configChanges="uiMode|orientation|screenSize" /> android:configChanges="uiMode|orientation|screenSize" />
<activity
android:name=".widget.CustomLayoutPickerActivity"
android:label="@string/app_name"
android:theme="@style/FilePickerTheme" />
<activity <activity
android:name=".ui.setting.track.AnilistLoginActivity" android:name=".ui.setting.track.AnilistLoginActivity"
android:label="Anilist"> android:label="Anilist">

View File

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.data.updater.UpdaterJob
import eu.kanade.tachiyomi.extension.ExtensionUpdateJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob
import eu.kanade.tachiyomi.ui.library.LibrarySort import eu.kanade.tachiyomi.ui.library.LibrarySort
import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.ExtendedNavigationView
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -92,6 +93,7 @@ object Migrations {
} }
if (oldVersion < 44) { if (oldVersion < 44) {
// Reset sorting preference if using removed sort by source // Reset sorting preference if using removed sort by source
@Suppress("DEPRECATION")
if (preferences.librarySortingMode().get() == LibrarySort.SOURCE) { if (preferences.librarySortingMode().get() == LibrarySort.SOURCE) {
preferences.librarySortingMode().set(LibrarySort.ALPHA) preferences.librarySortingMode().set(LibrarySort.ALPHA)
} }
@ -117,7 +119,10 @@ object Migrations {
// Force MAL log out due to login flow change // Force MAL log out due to login flow change
val trackManager = Injekt.get<TrackManager>() val trackManager = Injekt.get<TrackManager>()
if (trackManager.myAnimeList.isLogged) {
trackManager.myAnimeList.logout() trackManager.myAnimeList.logout()
context.toast(R.string.myanimelist_relogin)
}
} }
return true return true
} }

View File

@ -146,7 +146,7 @@ class BackupNotifier(private val context: Context) {
val uri = destFile.getUriCompat(context) val uri = destFile.getUriCompat(context)
addAction( addAction(
R.drawable.nnf_ic_file_folder, R.drawable.ic_folder_24dp,
context.getString(R.string.action_open_log), context.getString(R.string.action_open_log),
NotificationReceiver.openErrorLogPendingActivity(context, uri) NotificationReceiver.openErrorLogPendingActivity(context, uri)
) )

View File

@ -137,7 +137,7 @@ class DownloadPendingDeleter(context: Context) {
val id: Long, val id: Long,
val url: String, val url: String,
val name: String, val name: String,
val scanlator: String? val scanlator: String? = null
) )
/** /**

View File

@ -109,7 +109,7 @@ class LibraryUpdateNotifier(private val context: Context) {
setContentIntent(errorLogIntent) setContentIntent(errorLogIntent)
addAction( addAction(
R.drawable.nnf_ic_file_folder, R.drawable.ic_folder_24dp,
context.getString(R.string.action_open_log), context.getString(R.string.action_open_log),
errorLogIntent errorLogIntent
) )

View File

@ -121,7 +121,9 @@ object PreferenceKeys {
const val automaticExtUpdates = "automatic_ext_updates" const val automaticExtUpdates = "automatic_ext_updates"
const val allowNsfwSource = "allow_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

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

View File

@ -10,7 +10,6 @@ import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode 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.TrackService
import eu.kanade.tachiyomi.data.track.anilist.Anilist import eu.kanade.tachiyomi.data.track.anilist.Anilist
import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.ExtendedNavigationView
@ -225,7 +224,9 @@ class PreferencesHelper(val context: Context) {
fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true) fun automaticExtUpdates() = flowPrefs.getBoolean(Keys.automaticExtUpdates, true)
fun allowNsfwSource() = flowPrefs.getEnum(Keys.allowNsfwSource, NsfwAllowance.ALLOWED) 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

@ -63,7 +63,7 @@ data class ALUserManga(
"DROPPED" -> Anilist.DROPPED "DROPPED" -> Anilist.DROPPED
"PLANNING" -> Anilist.PLANNING "PLANNING" -> Anilist.PLANNING
"REPEATING" -> Anilist.REPEATING "REPEATING" -> Anilist.REPEATING
else -> throw NotImplementedError("Unknown status") else -> throw NotImplementedError("Unknown status: $list_status")
} }
} }
@ -74,7 +74,7 @@ fun Track.toAnilistStatus() = when (status) {
Anilist.DROPPED -> "DROPPED" Anilist.DROPPED -> "DROPPED"
Anilist.PLANNING -> "PLANNING" Anilist.PLANNING -> "PLANNING"
Anilist.REPEATING -> "REPEATING" Anilist.REPEATING -> "REPEATING"
else -> throw NotImplementedError("Unknown status") else -> throw NotImplementedError("Unknown status: $status")
} }
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
@ -102,5 +102,5 @@ fun Track.toAnilistScore(): String = when (preferences.anilistScoreType().get())
} }
// 10 point decimal // 10 point decimal
"POINT_10_DECIMAL" -> (score / 10).toString() "POINT_10_DECIMAL" -> (score / 10).toString()
else -> throw Exception("Unknown score type") else -> throw NotImplementedError("Unknown score type")
} }

View File

@ -8,7 +8,7 @@ fun Track.toBangumiStatus() = when (status) {
Bangumi.ON_HOLD -> "on_hold" Bangumi.ON_HOLD -> "on_hold"
Bangumi.DROPPED -> "dropped" Bangumi.DROPPED -> "dropped"
Bangumi.PLANNING -> "wish" Bangumi.PLANNING -> "wish"
else -> throw NotImplementedError("Unknown status") else -> throw NotImplementedError("Unknown status: $status")
} }
fun toTrackStatus(status: String) = when (status) { fun toTrackStatus(status: String) = when (status) {
@ -17,6 +17,5 @@ fun toTrackStatus(status: String) = when (status) {
"on_hold" -> Bangumi.ON_HOLD "on_hold" -> Bangumi.ON_HOLD
"dropped" -> Bangumi.DROPPED "dropped" -> Bangumi.DROPPED
"wish" -> Bangumi.PLANNING "wish" -> Bangumi.PLANNING
else -> throw NotImplementedError("Unknown status: $status")
else -> throw Exception("Unknown status")
} }

View File

@ -111,7 +111,7 @@ class MyAnimeList(private val context: Context, id: Int) : TrackService(id) {
fun ensureLoggedIn() { fun ensureLoggedIn() {
if (isAuthorized) return if (isAuthorized) return
if (!isLogged) throw Exception("MAL login credentials not found") if (!isLogged) throw Exception(context.getString(R.string.myanimelist_creds_missing))
} }
override fun logout() { override fun logout() {

View File

@ -9,7 +9,7 @@ fun Track.toShikimoriStatus() = when (status) {
Shikimori.DROPPED -> "dropped" Shikimori.DROPPED -> "dropped"
Shikimori.PLANNING -> "planned" Shikimori.PLANNING -> "planned"
Shikimori.REPEATING -> "rewatching" Shikimori.REPEATING -> "rewatching"
else -> throw NotImplementedError("Unknown status") else -> throw NotImplementedError("Unknown status: $status")
} }
fun toTrackStatus(status: String) = when (status) { fun toTrackStatus(status: String) = when (status) {
@ -19,6 +19,5 @@ fun toTrackStatus(status: String) = when (status) {
"dropped" -> Shikimori.DROPPED "dropped" -> Shikimori.DROPPED
"planned" -> Shikimori.PLANNING "planned" -> Shikimori.PLANNING
"rewatching" -> Shikimori.REPEATING "rewatching" -> Shikimori.REPEATING
else -> throw NotImplementedError("Unknown status: $status")
else -> throw Exception("Unknown status")
} }

View File

@ -124,8 +124,7 @@ class ExtensionManager(
.map { it.extension } .map { it.extension }
installedExtensions installedExtensions
.flatMap { it.sources } .flatMap { it.sources }
// overwrite is needed until the bundled sources are removed .forEach { sourceManager.registerSource(it) }
.forEach { sourceManager.registerSource(it, true) }
untrustedExtensions = extensions untrustedExtensions = extensions
.filterIsInstance<LoadResult.Untrusted>() .filterIsInstance<LoadResult.Untrusted>()

View File

@ -6,7 +6,6 @@ import android.content.pm.PackageInfo
import android.content.pm.PackageManager import android.content.pm.PackageManager
import dalvik.system.PathClassLoader import dalvik.system.PathClassLoader
import eu.kanade.tachiyomi.annotations.Nsfw import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.data.preference.PreferenceValues
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
@ -26,8 +25,8 @@ import uy.kohesive.injekt.injectLazy
internal object ExtensionLoader { internal object ExtensionLoader {
private val preferences: PreferencesHelper by injectLazy() private val preferences: PreferencesHelper by injectLazy()
private val allowNsfwSource by lazy { private val loadNsfwSource by lazy {
preferences.allowNsfwSource().get() preferences.showNsfwSource().get()
} }
private const val EXTENSION_FEATURE = "tachiyomi.extension" private const val EXTENSION_FEATURE = "tachiyomi.extension"
@ -133,7 +132,7 @@ internal object ExtensionLoader {
} }
val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1 val isNsfw = appInfo.metaData.getInt(METADATA_NSFW) == 1
if (allowNsfwSource == PreferenceValues.NsfwAllowance.BLOCKED && isNsfw) { if (!loadNsfwSource && isNsfw) {
return LoadResult.Error("NSFW extension $pkgName not allowed") return LoadResult.Error("NSFW extension $pkgName not allowed")
} }
@ -218,7 +217,7 @@ internal object ExtensionLoader {
* Checks whether a Source or SourceFactory is annotated with @Nsfw. * Checks whether a Source or SourceFactory is annotated with @Nsfw.
*/ */
private fun isSourceNsfw(clazz: Any): Boolean { private fun isSourceNsfw(clazz: Any): Boolean {
if (allowNsfwSource == PreferenceValues.NsfwAllowance.ALLOWED) { if (loadNsfwSource) {
return false return false
} }

View File

@ -62,14 +62,18 @@ interface Source : tachiyomi.source.Source {
/** /**
* [1.x API] Get the updated details for a manga. * [1.x API] Get the updated details for a manga.
*/ */
@Suppress("DEPRECATION")
override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo { override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo {
return fetchMangaDetails(manga.toSManga()).awaitSingle() val sManga = manga.toSManga()
.toMangaInfo() val networkManga = fetchMangaDetails(sManga).awaitSingle()
sManga.copyFrom(networkManga)
return sManga.toMangaInfo()
} }
/** /**
* [1.x API] Get all the available chapters for a manga. * [1.x API] Get all the available chapters for a manga.
*/ */
@Suppress("DEPRECATION")
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> { override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
return fetchChapterList(manga.toSManga()).awaitSingle() return fetchChapterList(manga.toSManga()).awaitSingle()
.map { it.toChapterInfo() } .map { it.toChapterInfo() }
@ -78,6 +82,7 @@ interface Source : tachiyomi.source.Source {
/** /**
* [1.x API] Get the list of pages a chapter has. * [1.x API] Get the list of pages a chapter has.
*/ */
@Suppress("DEPRECATION")
override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> { override suspend fun getPageList(chapter: ChapterInfo): List<tachiyomi.source.model.Page> {
return fetchPageList(chapter.toSChapter()).awaitSingle() return fetchPageList(chapter.toSChapter()).awaitSingle()
.map { it.toPageUrl() } .map { it.toPageUrl() }

View File

@ -32,11 +32,11 @@ open class SourceManager(private val context: Context) {
fun getCatalogueSources() = sourcesMap.values.filterIsInstance<CatalogueSource>() fun getCatalogueSources() = sourcesMap.values.filterIsInstance<CatalogueSource>()
internal fun registerSource(source: Source, overwrite: Boolean = false) { internal fun registerSource(source: Source) {
if (overwrite || !sourcesMap.containsKey(source.id)) { if (!sourcesMap.containsKey(source.id)) {
sourcesMap[source.id] = source sourcesMap[source.id] = source
} }
if (overwrite || !stubSourcesMap.containsKey(source.id)) { if (!stubSourcesMap.containsKey(source.id)) {
stubSourcesMap[source.id] = StubSource(source.id) stubSourcesMap[source.id] = StubSource(source.id)
} }
} }

View File

@ -12,7 +12,6 @@ import com.bluelinelabs.conductor.ControllerChangeHandler
import com.bluelinelabs.conductor.ControllerChangeType import com.bluelinelabs.conductor.ControllerChangeType
import com.bluelinelabs.conductor.RestoreViewOnCreateController import com.bluelinelabs.conductor.RestoreViewOnCreateController
import kotlinx.android.extensions.LayoutContainer import kotlinx.android.extensions.LayoutContainer
import kotlinx.android.synthetic.clearFindViewByIdCache
import timber.log.Timber import timber.log.Timber
abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) : abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
@ -54,11 +53,6 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
return inflateView(inflater, container) return inflateView(inflater, container)
} }
override fun onDestroyView(view: View) {
super.onDestroyView(view)
clearFindViewByIdCache()
}
abstract fun inflateView(inflater: LayoutInflater, container: ViewGroup): View abstract fun inflateView(inflater: LayoutInflater, container: ViewGroup): View
open fun onViewCreated(view: View) {} open fun onViewCreated(view: View) {}

View File

@ -4,16 +4,23 @@ import android.view.View
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.glide.GlideApp import eu.kanade.tachiyomi.data.glide.GlideApp
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
class ExtensionHolder(view: View, val adapter: ExtensionAdapter) : class ExtensionHolder(view: View, val adapter: ExtensionAdapter) :
FlexibleViewHolder(view, adapter) { FlexibleViewHolder(view, adapter) {
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)
@ -30,7 +37,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.isObsolete -> itemView.context.getString(R.string.ext_obsolete) extension is Extension.Installed && extension.isObsolete -> itemView.context.getString(R.string.ext_obsolete)
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.isNsfw -> itemView.context.getString(R.string.ext_nsfw_short) extension.isNsfw && shouldLabelNsfw -> itemView.context.getString(R.string.ext_nsfw_short)
else -> "" else -> ""
}.toUpperCase() }.toUpperCase()

View File

@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.browse.extension
import android.app.Application import android.app.Application
import android.os.Bundle import android.os.Bundle
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferenceValues
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.extension.ExtensionManager
import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.Extension
@ -56,7 +55,7 @@ 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.allowNsfwSource().get() != PreferenceValues.NsfwAllowance.BLOCKED val showNsfwExtensions = preferences.showNsfwExtension().get()
val (installed, untrusted, available) = tuple val (installed, untrusted, available) = tuple

View File

@ -459,7 +459,6 @@ open class BrowseSourceController(bundle: Bundle) :
val adapter = adapter ?: return val adapter = adapter ?: return
preferences.sourceDisplayMode().set(mode) preferences.sourceDisplayMode().set(mode)
presenter.refreshDisplayMode()
activity?.invalidateOptionsMenu() activity?.invalidateOptionsMenu()
setupRecycler(view) setupRecycler(view)

View File

@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
import android.os.Bundle import android.os.Bundle
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.cache.CoverCache
import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
@ -34,10 +33,13 @@ import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.removeCovers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.isActive
import rx.Observable import rx.Observable
import rx.Subscription import rx.Subscription
import rx.android.schedulers.AndroidSchedulers import rx.android.schedulers.AndroidSchedulers
@ -106,11 +108,6 @@ open class BrowseSourcePresenter(
*/ */
private var pageSubscription: Subscription? = null private var pageSubscription: Subscription? = null
/**
* Job to initialize manga details.
*/
private var initializerJob: Job? = null
override fun onCreate(savedState: Bundle?) { override fun onCreate(savedState: Bundle?) {
super.onCreate(savedState) super.onCreate(savedState)
@ -140,8 +137,6 @@ open class BrowseSourcePresenter(
this.query = query this.query = query
this.appliedFilters = filters this.appliedFilters = filters
initializeManga()
// Create a new pager. // Create a new pager.
pager = createPager(query, filters) pager = createPager(query, filters)
@ -193,27 +188,6 @@ open class BrowseSourcePresenter(
return pager.hasNextPage return pager.hasNextPage
} }
/**
* Subscribes to the initializer of manga details and updates the view if needed.
*/
private fun initializeManga() {
initializerJob?.cancel()
initializerJob = launchIO {
mangaDetailsFlow
.onEach { mangas ->
if (!isActive) return@onEach
try {
mangas.filter { it.thumbnail_url == null && !it.initialized }
.map { getMangaDetails(it) }
.forEach { launchUI { view?.onMangaInitialized(it) } }
} catch (error: Exception) {
launchUI { Timber.e(error) }
}
}
}
}
/** /**
* Returns a manga from the database for the given manga from network. It creates a new entry * Returns a manga from the database for the given manga from network. It creates a new entry
* if the manga is not yet in the database. * if the manga is not yet in the database.
@ -239,7 +213,19 @@ open class BrowseSourcePresenter(
* @param mangas the list of manga to initialize. * @param mangas the list of manga to initialize.
*/ */
fun initializeMangas(mangas: List<Manga>) { fun initializeMangas(mangas: List<Manga>) {
launchIO { mangaDetailsFlow.emit(mangas) } launchIO {
mangas.asFlow()
.filter { it.thumbnail_url == null && !it.initialized }
.map { getMangaDetails(it) }
.onEach {
launchUI {
@Suppress("DEPRECATION")
view?.onMangaInitialized(it)
}
}
.catch { e -> Timber.e(e) }
.collect()
}
} }
/** /**
@ -249,17 +235,15 @@ open class BrowseSourcePresenter(
* @return the initialized manga * @return the initialized manga
*/ */
private suspend fun getMangaDetails(manga: Manga): Manga { private suspend fun getMangaDetails(manga: Manga): Manga {
return try { try {
source.getMangaDetails(manga.toMangaInfo()) val networkManga = source.getMangaDetails(manga.toMangaInfo())
.let { networkManga ->
manga.copyFrom(networkManga.toSManga()) manga.copyFrom(networkManga.toSManga())
manga.initialized = true manga.initialized = true
db.insertManga(manga).executeAsBlocking() db.insertManga(manga).executeAsBlocking()
manga
}
} catch (e: Exception) { } catch (e: Exception) {
manga Timber.e(e)
} }
return manga
} }
/** /**
@ -283,13 +267,6 @@ open class BrowseSourcePresenter(
db.insertManga(manga).executeAsBlocking() db.insertManga(manga).executeAsBlocking()
} }
/**
* Refreshes the active display mode.
*/
fun refreshDisplayMode() {
initializeManga()
}
/** /**
* Set the filter states for the current source. * Set the filter states for the current source.
* *
@ -321,7 +298,7 @@ open class BrowseSourcePresenter(
is Filter.Text -> TextSectionItem(it) is Filter.Text -> TextSectionItem(it)
is Filter.Select<*> -> SelectSectionItem(it) is Filter.Select<*> -> SelectSectionItem(it)
else -> null else -> null
} as? ISectionable<*, *> }
} }
subItems.forEach { it.header = group } subItems.forEach { it.header = group }
group.subItems = subItems group.subItems = subItems

View File

@ -1,9 +1,10 @@
package eu.kanade.tachiyomi.ui.library package eu.kanade.tachiyomi.ui.library
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.database.models.Category
import eu.kanade.tachiyomi.databinding.LibraryCategoryBinding
import eu.kanade.tachiyomi.util.view.inflate import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.widget.RecyclerViewPagerAdapter import eu.kanade.tachiyomi.widget.RecyclerViewPagerAdapter
@ -34,8 +35,9 @@ class LibraryAdapter(private val controller: LibraryController) : RecyclerViewPa
* @return a new view. * @return a new view.
*/ */
override fun createView(container: ViewGroup): View { override fun createView(container: ViewGroup): View {
val view = container.inflate(R.layout.library_category) as LibraryCategoryView val binding = LibraryCategoryBinding.inflate(LayoutInflater.from(container.context), container, false)
view.onCreate(controller) val view: LibraryCategoryView = binding.root
view.onCreate(controller, binding)
return view return view
} }

View File

@ -14,12 +14,11 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.databinding.LibraryCategoryBinding
import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.lang.plusAssign
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import eu.kanade.tachiyomi.util.view.inflate import eu.kanade.tachiyomi.util.view.inflate
import eu.kanade.tachiyomi.widget.AutofitRecyclerView import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import kotlinx.android.synthetic.main.library_category.view.fast_scroller
import kotlinx.android.synthetic.main.library_category.view.swipe_refresh
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
@ -70,15 +69,15 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
private var lastClickPosition = -1 private var lastClickPosition = -1
fun onCreate(controller: LibraryController) { fun onCreate(controller: LibraryController, binding: LibraryCategoryBinding) {
this.controller = controller this.controller = controller
recycler = if (preferences.libraryDisplayMode().get() == DisplayMode.LIST) { recycler = if (preferences.libraryDisplayMode().get() == DisplayMode.LIST) {
(swipe_refresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply { (binding.swipeRefresh.inflate(R.layout.library_list_recycler) as RecyclerView).apply {
layoutManager = LinearLayoutManager(context) layoutManager = LinearLayoutManager(context)
} }
} else { } else {
(swipe_refresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply { (binding.swipeRefresh.inflate(R.layout.library_grid_recycler) as AutofitRecyclerView).apply {
spanCount = controller.mangaPerRow spanCount = controller.mangaPerRow
} }
} }
@ -87,28 +86,28 @@ class LibraryCategoryView @JvmOverloads constructor(context: Context, attrs: Att
recycler.setHasFixedSize(true) recycler.setHasFixedSize(true)
recycler.adapter = adapter recycler.adapter = adapter
swipe_refresh.addView(recycler) binding.swipeRefresh.addView(recycler)
adapter.fastScroller = fast_scroller adapter.fastScroller = binding.fastScroller
recycler.scrollStateChanges() recycler.scrollStateChanges()
.onEach { .onEach {
// Disable swipe refresh when view is not at the top // Disable swipe refresh when view is not at the top
val firstPos = (recycler.layoutManager as LinearLayoutManager) val firstPos = (recycler.layoutManager as LinearLayoutManager)
.findFirstCompletelyVisibleItemPosition() .findFirstCompletelyVisibleItemPosition()
swipe_refresh.isEnabled = firstPos <= 0 binding.swipeRefresh.isEnabled = firstPos <= 0
} }
.launchIn(scope) .launchIn(scope)
// Double the distance required to trigger sync // Double the distance required to trigger sync
swipe_refresh.setDistanceToTriggerSync((2 * 64 * resources.displayMetrics.density).toInt()) binding.swipeRefresh.setDistanceToTriggerSync((2 * 64 * resources.displayMetrics.density).toInt())
swipe_refresh.refreshes() binding.swipeRefresh.refreshes()
.onEach { .onEach {
if (LibraryUpdateService.start(context, category)) { if (LibraryUpdateService.start(context, category)) {
context.toast(R.string.updating_category) context.toast(R.string.updating_category)
} }
// It can be a very long operation, so we disable swipe refresh and show a toast. // It can be a very long operation, so we disable swipe refresh and show a toast.
swipe_refresh.isRefreshing = false binding.swipeRefresh.isRefreshing = false
} }
.launchIn(scope) .launchIn(scope)
} }

View File

@ -143,7 +143,7 @@ class LibraryController(
if (preferences.categoryTabs().get()) { if (preferences.categoryTabs().get()) {
currentTitle = resources?.getString(R.string.label_library) currentTitle = resources?.getString(R.string.label_library)
} else { } else {
adapter?.categories?.get(binding.libraryPager.currentItem)?.let { adapter?.categories?.getOrNull(binding.libraryPager.currentItem)?.let {
currentTitle = it.name currentTitle = it.name
} }
} }

View File

@ -923,7 +923,7 @@ class MangaController :
private fun markPreviousAsRead(chapters: List<ChapterItem>) { private fun markPreviousAsRead(chapters: List<ChapterItem>) {
val adapter = chaptersAdapter ?: return val adapter = chaptersAdapter ?: return
val prevChapters = if (presenter.sortDescending()) adapter.items.reversed() else adapter.items val prevChapters = if (presenter.sortDescending()) adapter.items.reversed() else adapter.items
val chapterPos = prevChapters.indexOf(chapters.last()) val chapterPos = prevChapters.indexOf(chapters.lastOrNull())
if (chapterPos != -1) { if (chapterPos != -1) {
markAsRead(prevChapters.take(chapterPos)) markAsRead(prevChapters.take(chapterPos))
} }

View File

@ -33,9 +33,6 @@ import java.util.TimeZone
class AboutController : SettingsController() { class AboutController : SettingsController() {
/**
* Checks for new releases
*/
private val updateChecker by lazy { GithubUpdateChecker() } private val updateChecker by lazy { GithubUpdateChecker() }
private val dateFormat: DateFormat = preferences.dateFormat() private val dateFormat: DateFormat = preferences.dateFormat()

View File

@ -20,7 +20,7 @@ class DirectoryPageLoader(val file: File) : PageLoader() {
override fun getPages(): Observable<List<ReaderPage>> { override fun getPages(): Observable<List<ReaderPage>> {
return file.listFiles() return file.listFiles()
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } } .filter { !it.isDirectory && ImageUtil.isImage(it.name) { FileInputStream(it) } }
.sortedWith(Comparator<File> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }) .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
.mapIndexed { i, file -> .mapIndexed { i, file ->
val streamFn = { FileInputStream(file) } val streamFn = { FileInputStream(file) }
ReaderPage(i).apply { ReaderPage(i).apply {

View File

@ -8,7 +8,6 @@ import eu.kanade.tachiyomi.util.system.ImageUtil
import rx.Observable import rx.Observable
import java.io.File import java.io.File
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.util.zip.ZipEntry
import java.util.zip.ZipFile import java.util.zip.ZipFile
/** /**
@ -40,7 +39,7 @@ class ZipPageLoader(file: File) : PageLoader() {
override fun getPages(): Observable<List<ReaderPage>> { override fun getPages(): Observable<List<ReaderPage>> {
return zip.entries().toList() return zip.entries().toList()
.filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } } .filter { !it.isDirectory && ImageUtil.isImage(it.name) { zip.getInputStream(it) } }
.sortedWith(Comparator<ZipEntry> { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }) .sortedWith { f1, f2 -> f1.name.compareToCaseInsensitiveNaturalOrder(f2.name) }
.mapIndexed { i, entry -> .mapIndexed { i, entry ->
val streamFn = { zip.getInputStream(entry) } val streamFn = { zip.getInputStream(entry) }
ReaderPage(i).apply { ReaderPage(i).apply {

View File

@ -185,7 +185,7 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer {
* activity of the change and requests the preload of the next chapter if this is the last page. * activity of the change and requests the preload of the next chapter if this is the last page.
*/ */
private fun onReaderPageSelected(page: ReaderPage, allowPreload: Boolean) { private fun onReaderPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages!! // Won't be null because it's the loaded chapter val pages = page.chapter.pages ?: return
Timber.d("onReaderPageSelected: ${page.number}/${pages.size}") Timber.d("onReaderPageSelected: ${page.number}/${pages.size}")
activity.onPageSelected(page) activity.onPageSelected(page)

View File

@ -185,7 +185,7 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
* activity of the change and requests the preload of the next chapter if this is the last page. * activity of the change and requests the preload of the next chapter if this is the last page.
*/ */
private fun onPageSelected(page: ReaderPage, allowPreload: Boolean) { private fun onPageSelected(page: ReaderPage, allowPreload: Boolean) {
val pages = page.chapter.pages!! // Won't be null because it's the loaded chapter val pages = page.chapter.pages ?: return
Timber.d("onPageSelected: ${page.number}/${pages.size}") Timber.d("onPageSelected: ${page.number}/${pages.size}")
activity.onPageSelected(page) activity.onPageSelected(page)
@ -293,11 +293,11 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr
} }
KeyEvent.KEYCODE_MENU -> if (isUp) activity.toggleMenu() KeyEvent.KEYCODE_MENU -> if (isUp) activity.toggleMenu()
KeyEvent.KEYCODE_DPAD_RIGHT, KeyEvent.KEYCODE_DPAD_LEFT,
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_UP,
KeyEvent.KEYCODE_PAGE_UP -> if (isUp) scrollUp() KeyEvent.KEYCODE_PAGE_UP -> if (isUp) scrollUp()
KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_DOWN,
KeyEvent.KEYCODE_PAGE_DOWN -> if (isUp) scrollDown() KeyEvent.KEYCODE_PAGE_DOWN -> if (isUp) scrollDown()
else -> return false else -> return false

View File

@ -2,26 +2,26 @@ package eu.kanade.tachiyomi.ui.recent
import android.text.format.DateUtils import android.text.format.DateUtils
import android.view.View import android.view.View
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.FlexibleAdapter
import eu.davidea.flexibleadapter.items.AbstractHeaderItem import eu.davidea.flexibleadapter.items.AbstractHeaderItem
import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.viewholders.FlexibleViewHolder import eu.davidea.viewholders.FlexibleViewHolder
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.databinding.RecentSectionItemBinding
import java.util.Date import java.util.Date
class DateSectionItem(val date: Date) : AbstractHeaderItem<DateSectionItem.Holder>() { class DateSectionItem(val date: Date) : AbstractHeaderItem<DateSectionItem.DateSectionItemHolder>() {
override fun getLayoutRes(): Int { override fun getLayoutRes(): Int {
return R.layout.recent_section_item return R.layout.recent_section_item
} }
override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): Holder { override fun createViewHolder(view: View, adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>): DateSectionItemHolder {
return Holder(view, adapter) return DateSectionItemHolder(view, adapter)
} }
override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: Holder, position: Int, payloads: List<Any?>?) { override fun bindViewHolder(adapter: FlexibleAdapter<IFlexible<RecyclerView.ViewHolder>>, holder: DateSectionItemHolder, position: Int, payloads: List<Any?>?) {
holder.bind(this) holder.bind(this)
} }
@ -37,14 +37,14 @@ class DateSectionItem(val date: Date) : AbstractHeaderItem<DateSectionItem.Holde
return date.hashCode() return date.hashCode()
} }
class Holder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter, true) { inner class DateSectionItemHolder(view: View, adapter: FlexibleAdapter<*>) : FlexibleViewHolder(view, adapter, true) {
private val binding = RecentSectionItemBinding.bind(view)
private val now = Date().time private val now = Date().time
val section_text: TextView = view.findViewById(R.id.section_text)
fun bind(item: DateSectionItem) { fun bind(item: DateSectionItem) {
section_text.text = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS) binding.sectionText.text = DateUtils.getRelativeTimeSpanString(item.date.time, now, DateUtils.DAY_IN_MILLIS)
} }
} }
} }

View File

@ -122,7 +122,7 @@ class SettingsAdvancedController : SettingsController() {
switchPreference { switchPreference {
key = Keys.enableDoh key = Keys.enableDoh
titleRes = R.string.pref_dns_over_https titleRes = R.string.pref_dns_over_https
summaryRes = R.string.pref_dns_over_https_summary summaryRes = R.string.requires_app_restart
defaultValue = false defaultValue = false
} }
} }

View File

@ -39,7 +39,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 eu.kanade.tachiyomi.util.system.getFilePicker
import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
@ -125,13 +124,11 @@ class SettingsBackupController : SettingsController() {
titleRes = R.string.pref_backup_directory titleRes = R.string.pref_backup_directory
onClick { onClick {
val currentDir = preferences.backupsDirectory().get()
try { try {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
startActivityForResult(intent, CODE_BACKUP_DIR) startActivityForResult(intent, CODE_BACKUP_DIR)
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
// Fall back to custom picker on error activity?.toast(R.string.file_picker_error)
startActivityForResult(preferences.context.getFilePicker(currentDir), CODE_BACKUP_DIR)
} }
} }
@ -205,7 +202,7 @@ class SettingsBackupController : SettingsController() {
) )
} }
CODE_BACKUP_RESTORE -> { CODE_BACKUP_RESTORE -> {
uri?.path?.let { path -> uri?.path?.let {
val fileName = DocumentFile.fromSingleUri(activity, uri)!!.name!! val fileName = DocumentFile.fromSingleUri(activity, uri)!!.name!!
when { when {
fileName.endsWith(".proto.gz") -> { fileName.endsWith(".proto.gz") -> {
@ -258,7 +255,6 @@ class SettingsBackupController : SettingsController() {
fun createBackup(flags: Int, type: Int) { fun createBackup(flags: Int, type: Int) {
backupFlags = flags backupFlags = flags
val currentDir = preferences.backupsDirectory().get()
val code = when (type) { val code = when (type) {
BackupConst.BACKUP_TYPE_FULL -> CODE_FULL_BACKUP_CREATE BackupConst.BACKUP_TYPE_FULL -> CODE_FULL_BACKUP_CREATE
else -> CODE_LEGACY_BACKUP_CREATE else -> CODE_LEGACY_BACKUP_CREATE
@ -277,8 +273,7 @@ class SettingsBackupController : SettingsController() {
startActivityForResult(intent, code) startActivityForResult(intent, code)
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
// Handle errors where the Android ROM doesn't support the built in picker activity?.toast(R.string.file_picker_error)
startActivityForResult(preferences.context.getFilePicker(currentDir), code)
} }
} }

View File

@ -2,12 +2,16 @@ 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.onChange import eu.kanade.tachiyomi.util.preference.onChange
import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.preferenceCategory
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() {
@ -41,27 +45,29 @@ class SettingsBrowseController : SettingsController() {
} }
} }
// preferenceCategory { preferenceCategory {
// titleRes = R.string.pref_category_nsfw_content titleRes = R.string.pref_category_nsfw_content
//
// listPreference { switchPreference {
// key = Keys.allowNsfwSource key = Keys.showNsfwSource
// titleRes = R.string.pref_allow_nsfw_sources titleRes = R.string.pref_show_nsfw_source
// entriesRes = arrayOf( summaryRes = R.string.requires_app_restart
// R.string.pref_allow_nsfw_sources_allowed, defaultValue = true
// R.string.pref_allow_nsfw_sources_allowed_multisource, }
// R.string.pref_allow_nsfw_sources_blocked switchPreference {
// ) key = Keys.showNsfwExtension
// entryValues = arrayOf( titleRes = R.string.pref_show_nsfw_extension
// PreferenceValues.NsfwAllowance.ALLOWED.name, defaultValue = true
// PreferenceValues.NsfwAllowance.PARTIAL.name, }
// PreferenceValues.NsfwAllowance.BLOCKED.name switchPreference {
// ) key = Keys.labelNsfwExtension
// defaultValue = PreferenceValues.NsfwAllowance.ALLOWED.name titleRes = R.string.pref_label_nsfw_extension
// summary = "%s" defaultValue = true
// }
// preferences.showNsfwExtension().asImmediateFlow { isVisible = it }.launchIn(scope)
// infoPreference(R.string.parental_controls_info) }
// }
infoPreference(R.string.parental_controls_info)
}
} }
} }

View File

@ -27,7 +27,7 @@ import eu.kanade.tachiyomi.util.preference.preference
import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.preferenceCategory
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 eu.kanade.tachiyomi.util.system.getFilePicker import eu.kanade.tachiyomi.util.system.toast
import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
@ -155,12 +155,12 @@ class SettingsDownloadController : SettingsController() {
preferences.downloadsDirectory().set(path.toString()) preferences.downloadsDirectory().set(path.toString())
} }
fun customDirectorySelected(currentDir: String) { fun customDirectorySelected() {
val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE) val intent = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
try { try {
startActivityForResult(intent, DOWNLOAD_DIR) startActivityForResult(intent, DOWNLOAD_DIR)
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
startActivityForResult(preferences.context.getFilePicker(currentDir), DOWNLOAD_DIR) activity?.toast(R.string.file_picker_error)
} }
} }
@ -181,7 +181,7 @@ class SettingsDownloadController : SettingsController() {
) { _, position, text -> ) { _, position, text ->
val target = targetController as? SettingsDownloadController val target = targetController as? SettingsDownloadController
if (position == externalDirs.lastIndex) { if (position == externalDirs.lastIndex) {
target?.customDirectorySelected(currentDir) target?.customDirectorySelected()
} else { } else {
target?.predefinedDirectorySelected(text.toString()) target?.predefinedDirectorySelected(text.toString())
} }

View File

@ -101,7 +101,7 @@ object SettingsSearchHelper {
(pref.title != null) -> { (pref.title != null) -> {
// Is an actual preference // Is an actual preference
val title = pref.title.toString() val title = pref.title.toString()
val summary = if (pref.summary != null) pref.summary.toString() else "" val summary = pref.summary?.toString() ?: ""
val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}") val breadcrumbsStr = addLocalizedBreadcrumb(breadcrumbs, "${pref.title}")
prefSearchResultList.add( prefSearchResultList.add(

View File

@ -31,15 +31,17 @@ open class BaseWebViewActivity : BaseActivity<WebviewActivityBinding>() {
if (!WebViewUtil.supportsWebView(this)) { if (!WebViewUtil.supportsWebView(this)) {
toast(R.string.information_webview_required, Toast.LENGTH_LONG) toast(R.string.information_webview_required, Toast.LENGTH_LONG)
finish() finish()
return
} }
try { try {
binding = WebviewActivityBinding.inflate(layoutInflater) binding = WebviewActivityBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
} catch (e: Exception) { } catch (e: Throwable) {
// Potentially throws errors like "Error inflating class android.webkit.WebView" // Potentially throws errors like "Error inflating class android.webkit.WebView"
toast(R.string.information_webview_required, Toast.LENGTH_LONG) toast(R.string.information_webview_required, Toast.LENGTH_LONG)
finish() finish()
return
} }
title = intent.extras?.getString(TITLE_KEY) title = intent.extras?.getString(TITLE_KEY)

View File

@ -29,10 +29,8 @@ import androidx.core.graphics.green
import androidx.core.graphics.red import androidx.core.graphics.red
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.localbroadcastmanager.content.LocalBroadcastManager import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.nononsenseapps.filepicker.FilePickerActivity
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.lang.truncateCenter import eu.kanade.tachiyomi.util.lang.truncateCenter
import eu.kanade.tachiyomi.widget.CustomLayoutPickerActivity
import kotlin.math.roundToInt import kotlin.math.roundToInt
/** /**
@ -98,19 +96,6 @@ fun Context.notification(channelId: String, block: (NotificationCompat.Builder.(
return builder.build() return builder.build()
} }
/**
* Helper method to construct an Intent to use a custom file picker.
* @param currentDir the path the file picker will open with.
* @return an Intent to start the file picker activity.
*/
fun Context.getFilePicker(currentDir: String): Intent {
return Intent(this, CustomLayoutPickerActivity::class.java)
.putExtra(FilePickerActivity.EXTRA_ALLOW_MULTIPLE, false)
.putExtra(FilePickerActivity.EXTRA_ALLOW_CREATE_DIR, true)
.putExtra(FilePickerActivity.EXTRA_MODE, FilePickerActivity.MODE_DIR)
.putExtra(FilePickerActivity.EXTRA_START_PATH, currentDir)
}
/** /**
* Checks if the give permission is granted. * Checks if the give permission is granted.
* *

View File

@ -13,7 +13,7 @@ object WebViewUtil {
const val REQUESTED_WITH = "com.android.browser" const val REQUESTED_WITH = "com.android.browser"
const val MINIMUM_WEBVIEW_VERSION = 84 const val MINIMUM_WEBVIEW_VERSION = 86
fun supportsWebView(context: Context): Boolean { fun supportsWebView(context: Context): Boolean {
try { try {

View File

@ -1,33 +0,0 @@
package eu.kanade.tachiyomi.widget
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.nononsenseapps.filepicker.AbstractFilePickerFragment
import com.nononsenseapps.filepicker.FilePickerActivity
import com.nononsenseapps.filepicker.FilePickerFragment
import com.nononsenseapps.filepicker.LogicHandler
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.view.inflate
import java.io.File
class CustomLayoutPickerActivity : FilePickerActivity() {
override fun getFragment(startPath: String?, mode: Int, allowMultiple: Boolean, allowCreateDir: Boolean):
AbstractFilePickerFragment<File> {
val fragment = CustomLayoutFilePickerFragment()
fragment.setArgs(startPath, mode, allowMultiple, allowCreateDir)
return fragment
}
}
class CustomLayoutFilePickerFragment : FilePickerFragment() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
LogicHandler.VIEWTYPE_DIR -> {
val view = parent.inflate(R.layout.common_listitem_dir)
DirViewHolder(view)
}
else -> super.onCreateViewHolder(parent, viewType)
}
}
}

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#FF000000"
android:pathData="M10,4H4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V8c0,-1.1 -0.9,-2 -2,-2h-8l-2,-2z" />
</vector>

View File

@ -1,38 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/nnf_item_container"
android:layout_width="match_parent"
android:layout_height="?android:listPreferredItemHeight"
android:background="?selectableItemBackground"
android:focusable="true"
android:minHeight="?android:listPreferredItemHeight"
android:nextFocusLeft="@+id/nnf_button_cancel"
android:nextFocusRight="@+id/nnf_button_ok"
android:orientation="horizontal">
<ImageView
android:id="@+id/item_icon"
android:layout_width="?android:listPreferredItemHeight"
android:layout_height="?android:listPreferredItemHeight"
android:adjustViewBounds="true"
android:scaleType="center"
android:src="@drawable/nnf_ic_file_folder"
android:visibility="visible"
app:tint="?attr/colorAccent"
tools:ignore="ContentDescription" />
<TextView
android:id="@android:id/text1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:ellipsize="end"
android:gravity="center_vertical"
android:maxLines="1"
android:padding="8dp"
android:singleLine="true"
android:text="@string/nnf_name" />
</LinearLayout>

View File

@ -601,7 +601,7 @@
<string name="action_start">ابدأ</string> <string name="action_start">ابدأ</string>
<string name="action_sort_date_added">تاريخ الاضافة</string> <string name="action_sort_date_added">تاريخ الاضافة</string>
<string name="whats_new">ما الجديد</string> <string name="whats_new">ما الجديد</string>
<string name="pref_dns_over_https_summary">يتطلب إعادة تشغيل التطبيق ليتم تفعيله</string> <string name="requires_app_restart">يتطلب إعادة تشغيل التطبيق ليتم تفعيله</string>
<string name="label_network">شبكة الاتصال</string> <string name="label_network">شبكة الاتصال</string>
<string name="backup_restore_missing_trackers">أجهزة التتبع التي لم يتم تسجيل الدخول إليها:</string> <string name="backup_restore_missing_trackers">أجهزة التتبع التي لم يتم تسجيل الدخول إليها:</string>
<string name="pref_remove_bookmarked_chapters">حذف الفصول ذات العلامة المرجعية</string> <string name="pref_remove_bookmarked_chapters">حذف الفصول ذات العلامة المرجعية</string>

View File

@ -375,7 +375,7 @@
<string name="pref_clear_chapter_cache">Borrar caché de los capítulos</string> <string name="pref_clear_chapter_cache">Borrar caché de los capítulos</string>
<string name="label_data">Datos</string> <string name="label_data">Datos</string>
<string name="cookies_cleared">Cookies borradas</string> <string name="cookies_cleared">Cookies borradas</string>
<string name="pref_dns_over_https_summary">Requiere el reinicio de la aplicación para que surta efecto</string> <string name="requires_app_restart">Requiere el reinicio de la aplicación para que surta efecto</string>
<string name="battery_optimization_disabled">La optimización de la batería ya está desactivada</string> <string name="battery_optimization_disabled">La optimización de la batería ya está desactivada</string>
<string name="pref_disable_battery_optimization_summary">Ayuda con las actualizaciones y las copias de seguridad de biblioteca en segundo plano</string> <string name="pref_disable_battery_optimization_summary">Ayuda con las actualizaciones y las copias de seguridad de biblioteca en segundo plano</string>
<string name="pref_disable_battery_optimization">Desactivar optimización de batería</string> <string name="pref_disable_battery_optimization">Desactivar optimización de batería</string>

View File

@ -581,7 +581,7 @@
<string name="tabs_header">Раздели</string> <string name="tabs_header">Раздели</string>
<string name="badges_header">Значки</string> <string name="badges_header">Значки</string>
<string name="label_data">Данни</string> <string name="label_data">Данни</string>
<string name="pref_dns_over_https_summary">Изисква рестартиране на приложението, за да влезе в сила</string> <string name="requires_app_restart">Изисква рестартиране на приложението, за да влезе в сила</string>
<string name="label_network">Мрежа</string> <string name="label_network">Мрежа</string>
<string name="backup_restore_missing_sources">Липсващи източници:</string> <string name="backup_restore_missing_sources">Липсващи източници:</string>
<string name="invalid_backup_file_missing_manga">Резервното копие не съдържа манга.</string> <string name="invalid_backup_file_missing_manga">Резервното копие не съдържа манга.</string>

View File

@ -464,7 +464,7 @@
<string name="set_chapter_settings_as_default">প্রকৃত হিসেবে সংরক্ষণ করুন</string> <string name="set_chapter_settings_as_default">প্রকৃত হিসেবে সংরক্ষণ করুন</string>
<string name="confirm_set_chapter_settings">আপনি কি নিশ্চিত সেটিংসগুলো প্রকৃত হিসেবে সংরক্ষণ করবেন\?</string> <string name="confirm_set_chapter_settings">আপনি কি নিশ্চিত সেটিংসগুলো প্রকৃত হিসেবে সংরক্ষণ করবেন\?</string>
<string name="label_data">তথ্য</string> <string name="label_data">তথ্য</string>
<string name="pref_dns_over_https_summary">কার্যকর করতে অ্যাপ পুনরারম্ভ করতে হবে</string> <string name="requires_app_restart">কার্যকর করতে অ্যাপ পুনরারম্ভ করতে হবে</string>
<string name="label_network">নেটওয়ার্ক</string> <string name="label_network">নেটওয়ার্ক</string>
<string name="restoring_backup_canceled">পুনরুদ্ধার বাতিল করা হয়েছে</string> <string name="restoring_backup_canceled">পুনরুদ্ধার বাতিল করা হয়েছে</string>
<string name="restoring_backup_error">ব্যাকআপ পুনরুদ্ধার ব্যর্থ হয়েছে</string> <string name="restoring_backup_error">ব্যাকআপ পুনরুদ্ধার ব্যর্থ হয়েছে</string>

View File

@ -573,7 +573,7 @@
<string name="action_global_search_query">Cerca \"%1$s\" globalment</string> <string name="action_global_search_query">Cerca \"%1$s\" globalment</string>
<string name="updated_version">S\'ha actualitzat a la v%1$s</string> <string name="updated_version">S\'ha actualitzat a la v%1$s</string>
<string name="whats_new">Novetats</string> <string name="whats_new">Novetats</string>
<string name="pref_dns_over_https_summary">Cal reiniciar l\'aplicació perquè s\'apliqui</string> <string name="requires_app_restart">Cal reiniciar l\'aplicació perquè s\'apliqui</string>
<string name="label_network">Xarxa</string> <string name="label_network">Xarxa</string>
<string name="pref_category_reading_mode">Mode de lectura</string> <string name="pref_category_reading_mode">Mode de lectura</string>
<string name="pref_show_reading_mode_summary">Mostra breument el mode actual en obrir el lector</string> <string name="pref_show_reading_mode_summary">Mostra breument el mode actual en obrir el lector</string>

View File

@ -558,7 +558,7 @@
<string name="cache_deleted">Кеша тастнӑ. %1$d файла катертнӗ</string> <string name="cache_deleted">Кеша тастнӑ. %1$d файла катертнӗ</string>
<string name="pref_clear_chapter_cache">Сыпӑксен кешне тасат</string> <string name="pref_clear_chapter_cache">Сыпӑксен кешне тасат</string>
<string name="label_data">Пӗлӗмсем</string> <string name="label_data">Пӗлӗмсем</string>
<string name="pref_dns_over_https_summary">Вӑя кӗрес тесен хушӑма сӳнтерсе ҫутмалла</string> <string name="requires_app_restart">Вӑя кӗрес тесен хушӑма сӳнтерсе ҫутмалла</string>
<string name="restoring_backup_canceled">Тавӑрнине пӑрахӑҫланӑ</string> <string name="restoring_backup_canceled">Тавӑрнине пӑрахӑҫланӑ</string>
<string name="restoring_backup_error">Янтӑв тавӑрни йӑнӑшӗ</string> <string name="restoring_backup_error">Янтӑв тавӑрни йӑнӑшӗ</string>
<string name="restoring_backup">Янтӑв тавӑрни</string> <string name="restoring_backup">Янтӑв тавӑрни</string>

View File

@ -568,7 +568,7 @@
<item quantity="other">%1$s Kapitel</item> <item quantity="other">%1$s Kapitel</item>
</plurals> </plurals>
<string name="action_open_in_settings">In den Einstellungen öffnen</string> <string name="action_open_in_settings">In den Einstellungen öffnen</string>
<string name="pref_dns_over_https_summary">App muss neu gestartet werden, um die Einstellung zu übernehmen</string> <string name="requires_app_restart">App muss neu gestartet werden, um die Einstellung zu übernehmen</string>
<string name="pref_dns_over_https" translatable="false">DNS über HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS über HTTPS (Cloudflare)</string>
<string name="label_network">Netzwerk</string> <string name="label_network">Netzwerk</string>
<string name="pref_jump_to_chapters">Beim Öffnen zu den Kapiteln springen</string> <string name="pref_jump_to_chapters">Beim Öffnen zu den Kapiteln springen</string>

View File

@ -568,7 +568,7 @@
<item quantity="other">%1$s κεφάλαια</item> <item quantity="other">%1$s κεφάλαια</item>
</plurals> </plurals>
<string name="action_open_in_settings">Άνοιγμα στις Ρυθμίσεις</string> <string name="action_open_in_settings">Άνοιγμα στις Ρυθμίσεις</string>
<string name="pref_dns_over_https_summary">Απαιτείται επανεκκίνηση της εφαρμογής για να τεθεί σε ισχύ</string> <string name="requires_app_restart">Απαιτείται επανεκκίνηση της εφαρμογής για να τεθεί σε ισχύ</string>
<string name="pref_dns_over_https" translatable="false">DNS μέσω HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS μέσω HTTPS (Cloudflare)</string>
<string name="label_network">Δίκτυο</string> <string name="label_network">Δίκτυο</string>
<string name="pref_jump_to_chapters">Μετάβαση στα κεφάλαια κατά το άνοιγμα</string> <string name="pref_jump_to_chapters">Μετάβαση στα κεφάλαια κατά το άνοιγμα</string>

View File

@ -599,7 +599,7 @@
<string name="action_sort_descending">Descendente</string> <string name="action_sort_descending">Descendente</string>
<string name="action_disable">Desactivar</string> <string name="action_disable">Desactivar</string>
<string name="action_open_in_settings">Abrir en Configuración</string> <string name="action_open_in_settings">Abrir en Configuración</string>
<string name="pref_dns_over_https_summary">Requiere el reinicio de la aplicación para que surta efecto</string> <string name="requires_app_restart">Requiere el reinicio de la aplicación para que surta efecto</string>
<string name="pref_dns_over_https" translatable="false">DNS sobre HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS sobre HTTPS (Cloudflare)</string>
<string name="label_network">Red</string> <string name="label_network">Red</string>
<string name="pref_jump_to_chapters">Saltar a los capítulos abiertos</string> <string name="pref_jump_to_chapters">Saltar a los capítulos abiertos</string>

View File

@ -581,7 +581,7 @@
<string name="no_pinned_sources">شما هیچ منبع پین‌شده‌ای ندارید</string> <string name="no_pinned_sources">شما هیچ منبع پین‌شده‌ای ندارید</string>
<string name="action_global_search_query">«%1$s» در همه منابع جستجو شود</string> <string name="action_global_search_query">«%1$s» در همه منابع جستجو شود</string>
<string name="whats_new">اخبار</string> <string name="whats_new">اخبار</string>
<string name="pref_dns_over_https_summary">برای اعمال تغییرات برنامه نیاز به راه اندازی مجدد دارد</string> <string name="requires_app_restart">برای اعمال تغییرات برنامه نیاز به راه اندازی مجدد دارد</string>
<string name="label_network">شبکه</string> <string name="label_network">شبکه</string>
<string name="backup_restore_missing_trackers">ردیابی‌هایی که به سیستم وارد نشده اند:</string> <string name="backup_restore_missing_trackers">ردیابی‌هایی که به سیستم وارد نشده اند:</string>
<string name="pref_category_reading_mode">حالت خواندن</string> <string name="pref_category_reading_mode">حالت خواندن</string>

View File

@ -568,7 +568,7 @@
<item quantity="other">%1$s lukua</item> <item quantity="other">%1$s lukua</item>
</plurals> </plurals>
<string name="action_open_in_settings">Avaa Asetuksissa</string> <string name="action_open_in_settings">Avaa Asetuksissa</string>
<string name="pref_dns_over_https_summary">Edellyttää sovelluksen käynnistämistä uudelleen</string> <string name="requires_app_restart">Edellyttää sovelluksen käynnistämistä uudelleen</string>
<string name="pref_dns_over_https" translatable="false">DNS HTTPS:n kautta (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS HTTPS:n kautta (Cloudflare)</string>
<string name="label_network">Verkko</string> <string name="label_network">Verkko</string>
<string name="pref_jump_to_chapters">Siirry lukuihin avatessa</string> <string name="pref_jump_to_chapters">Siirry lukuihin avatessa</string>

View File

@ -568,7 +568,7 @@
<string name="pref_clear_chapter_cache">Linisin ang cache ng kabanata</string> <string name="pref_clear_chapter_cache">Linisin ang cache ng kabanata</string>
<string name="label_data">Data</string> <string name="label_data">Data</string>
<string name="cookies_cleared">Nalinis na ang mga cookie</string> <string name="cookies_cleared">Nalinis na ang mga cookie</string>
<string name="pref_dns_over_https_summary">Nangangailangang buksan muli ang app para gumana</string> <string name="requires_app_restart">Nangangailangang buksan muli ang app para gumana</string>
<string name="pref_clear_cookies">Linisin ang mga cookie</string> <string name="pref_clear_cookies">Linisin ang mga cookie</string>
<string name="label_network">Network</string> <string name="label_network">Network</string>
<string name="restoring_backup_error">Pumalya sa pagbalik sa backup</string> <string name="restoring_backup_error">Pumalya sa pagbalik sa backup</string>

View File

@ -602,7 +602,7 @@
<string name="action_sort_descending">Décroissant</string> <string name="action_sort_descending">Décroissant</string>
<string name="action_disable">Désactiver</string> <string name="action_disable">Désactiver</string>
<string name="action_open_in_settings">Ouvrir dans les paramètres</string> <string name="action_open_in_settings">Ouvrir dans les paramètres</string>
<string name="pref_dns_over_https_summary">Nécessite un redémarrage de l\'application pour prendre effet</string> <string name="requires_app_restart">Nécessite un redémarrage de l\'application pour prendre effet</string>
<string name="pref_dns_over_https" translatable="false">DNS sur HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS sur HTTPS (Cloudflare)</string>
<string name="label_network">Réseau</string> <string name="label_network">Réseau</string>
<string name="tapping_inverted_both">Les deux</string> <string name="tapping_inverted_both">Les deux</string>

View File

@ -578,7 +578,7 @@
<string name="pref_read_with_tapping_inverted">उलटा दोहन</string> <string name="pref_read_with_tapping_inverted">उलटा दोहन</string>
<string name="unknown_status">अज्ञात स्थिति</string> <string name="unknown_status">अज्ञात स्थिति</string>
<string name="unknown_author">अज्ञात लेखक</string> <string name="unknown_author">अज्ञात लेखक</string>
<string name="pref_dns_over_https_summary">प्रभावी होने के लिए ऐप पुनः आरंभ करने की आवश्यकता है</string> <string name="requires_app_restart">प्रभावी होने के लिए ऐप पुनः आरंभ करने की आवश्यकता है</string>
<string name="action_download_unread">अपठित अध्याय डाउनलोड करें</string> <string name="action_download_unread">अपठित अध्याय डाउनलोड करें</string>
<string name="whats_new">नया क्या है</string> <string name="whats_new">नया क्या है</string>
<string name="download_insufficient_space">कम डिस्क स्पेस के कारण अध्याय डाउनलोड नहीं कर सका</string> <string name="download_insufficient_space">कम डिस्क स्पेस के कारण अध्याय डाउनलोड नहीं कर सका</string>

View File

@ -578,7 +578,7 @@
<item quantity="few">%1$s poglavlja</item> <item quantity="few">%1$s poglavlja</item>
<item quantity="other">%1$s poglavlja</item> <item quantity="other">%1$s poglavlja</item>
</plurals> </plurals>
<string name="pref_dns_over_https_summary">Za preuzimanje postavke, ponovo pokreni program</string> <string name="requires_app_restart">Za preuzimanje postavke, ponovo pokreni program</string>
<string name="pref_dns_over_https" translatable="false">DNS preko HTTPS-a (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS preko HTTPS-a (Cloudflare)</string>
<string name="label_network">Mreža</string> <string name="label_network">Mreža</string>
<string name="tapping_inverted_both">Oboje</string> <string name="tapping_inverted_both">Oboje</string>

View File

@ -555,7 +555,7 @@
<plurals name="manga_num_chapters"> <plurals name="manga_num_chapters">
<item quantity="other">%1$s bab</item> <item quantity="other">%1$s bab</item>
</plurals> </plurals>
<string name="pref_dns_over_https_summary">Mulai ulang aplikasi untuk menerapkan pengaturan</string> <string name="requires_app_restart">Mulai ulang aplikasi untuk menerapkan pengaturan</string>
<string name="pref_dns_over_https" translatable="false">DNS melalui HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS melalui HTTPS (Cloudflare)</string>
<string name="label_network">Jaringan</string> <string name="label_network">Jaringan</string>
<string name="pref_jump_to_chapters">Lompat ke bab saat dibuka</string> <string name="pref_jump_to_chapters">Lompat ke bab saat dibuka</string>

View File

@ -604,7 +604,7 @@
<string name="unknown_author">Autore sconosciuto</string> <string name="unknown_author">Autore sconosciuto</string>
<string name="updated_version">Aggiornato verso v%1$s</string> <string name="updated_version">Aggiornato verso v%1$s</string>
<string name="whats_new">Le novità</string> <string name="whats_new">Le novità</string>
<string name="pref_dns_over_https_summary">Richiede il riavvio dell\'applicazione per avere effetto</string> <string name="requires_app_restart">Richiede il riavvio dell\'applicazione per avere effetto</string>
<string name="pref_dns_over_https" translatable="false">DNS via HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS via HTTPS (Cloudflare)</string>
<string name="label_network">Rete</string> <string name="label_network">Rete</string>
<string name="pref_show_reading_mode_summary">Mostra brevemente la modalità corrente all\'apertura del lettore</string> <string name="pref_show_reading_mode_summary">Mostra brevemente la modalità corrente all\'apertura del lettore</string>

View File

@ -564,7 +564,7 @@
<string name="tapping_inverted_none">なし</string> <string name="tapping_inverted_none">なし</string>
<string name="unknown_status">不明なステータス</string> <string name="unknown_status">不明なステータス</string>
<string name="unknown_author">作者不明</string> <string name="unknown_author">作者不明</string>
<string name="pref_dns_over_https_summary">変更を適用するためには再起動してください</string> <string name="requires_app_restart">変更を適用するためには再起動してください</string>
<string name="label_network">ネットワーク</string> <string name="label_network">ネットワーク</string>
<string name="pref_jump_to_chapters">起動時にチャプターを表示</string> <string name="pref_jump_to_chapters">起動時にチャプターを表示</string>
<string name="pref_read_with_tapping_inverted">タップでのページめくりを反転</string> <string name="pref_read_with_tapping_inverted">タップでのページめくりを反転</string>

View File

@ -563,7 +563,7 @@
</plurals> </plurals>
<string name="updated_version">განახლებულია v%1$s-მდე</string> <string name="updated_version">განახლებულია v%1$s-მდე</string>
<string name="whats_new">რა არის ახალი</string> <string name="whats_new">რა არის ახალი</string>
<string name="pref_dns_over_https_summary">ასამოქმედებლად საჭიროა აპლიკაციის გადატვირთვა</string> <string name="requires_app_restart">ასამოქმედებლად საჭიროა აპლიკაციის გადატვირთვა</string>
<string name="label_network">ქსელი</string> <string name="label_network">ქსელი</string>
<plurals name="restore_completed_message"> <plurals name="restore_completed_message">
<item quantity="one">გაკეთებულია %1$s %2$s შეცდომით</item> <item quantity="one">გაკეთებულია %1$s %2$s შეცდომით</item>

View File

@ -578,7 +578,7 @@
<string name="action_global_search_query">\"%1$s\" ಅನ್ನು ಗ್ಲೋಬಲ್ ಸರ್ಚ್ ಮಾಡಿ</string> <string name="action_global_search_query">\"%1$s\" ಅನ್ನು ಗ್ಲೋಬಲ್ ಸರ್ಚ್ ಮಾಡಿ</string>
<string name="updated_version">v%1$s ಗೆ ಅಪ್ಡೇಟ್ ಆಗಿದೆ</string> <string name="updated_version">v%1$s ಗೆ ಅಪ್ಡೇಟ್ ಆಗಿದೆ</string>
<string name="whats_new">ಹೊಸತೇನಿದೆ</string> <string name="whats_new">ಹೊಸತೇನಿದೆ</string>
<string name="pref_dns_over_https_summary">ಜಾರಿಗೆ ಬರಲು ಅಪ್ಲಿಕೇಶನ್ ಮರುಪ್ರಾರಂಭದ ಅಗತ್ಯವಿದೆ</string> <string name="requires_app_restart">ಜಾರಿಗೆ ಬರಲು ಅಪ್ಲಿಕೇಶನ್ ಮರುಪ್ರಾರಂಭದ ಅಗತ್ಯವಿದೆ</string>
<string name="label_network">ಅಡ್ವಾನ್ಸ್ಡ್ ಸೆಕ್ಷನ್</string> <string name="label_network">ಅಡ್ವಾನ್ಸ್ಡ್ ಸೆಕ್ಷನ್</string>
<string name="pref_category_reading_mode">ಓದುವ ಮೊಡ್</string> <string name="pref_category_reading_mode">ಓದುವ ಮೊಡ್</string>
<string name="pref_jump_to_chapters">ಓಪನ್ ಮಾಡಿದ ಮೇಲೆ ಅಧ್ಯಯಕ್ಕೆ ಹೋಗಿ</string> <string name="pref_jump_to_chapters">ಓಪನ್ ಮಾಡಿದ ಮೇಲೆ ಅಧ್ಯಯಕ್ಕೆ ಹೋಗಿ</string>

View File

@ -558,7 +558,7 @@
</plurals> </plurals>
<string name="action_sort_descending">Menurun</string> <string name="action_sort_descending">Menurun</string>
<string name="action_disable">Matikan</string> <string name="action_disable">Matikan</string>
<string name="pref_dns_over_https_summary">Mula semula diperlukan untuk berkesan</string> <string name="requires_app_restart">Mula semula diperlukan untuk berkesan</string>
<string name="pref_dns_over_https" translatable="false">DNS melalui HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS melalui HTTPS (Cloudflare)</string>
<string name="label_network">Rangkaian</string> <string name="label_network">Rangkaian</string>
<string name="pref_jump_to_chapters">Terus ke bab bila buka</string> <string name="pref_jump_to_chapters">Terus ke bab bila buka</string>

View File

@ -523,7 +523,7 @@
<string name="battery_optimization_disabled">Batterioptimalisering er allerede deaktivert</string> <string name="battery_optimization_disabled">Batterioptimalisering er allerede deaktivert</string>
<string name="pref_disable_battery_optimization">Deaktiver batterioptimalisering</string> <string name="pref_disable_battery_optimization">Deaktiver batterioptimalisering</string>
<string name="label_data">Data</string> <string name="label_data">Data</string>
<string name="pref_dns_over_https_summary">Krever omstart for å tre i kraft</string> <string name="requires_app_restart">Krever omstart for å tre i kraft</string>
<string name="label_network">Nettverk</string> <string name="label_network">Nettverk</string>
<string name="restoring_backup_canceled">Avbrutt gjenoppretting</string> <string name="restoring_backup_canceled">Avbrutt gjenoppretting</string>
<string name="restore_in_progress">Gjenoppretting er allerede i gang</string> <string name="restore_in_progress">Gjenoppretting er allerede i gang</string>

View File

@ -568,7 +568,7 @@
</plurals> </plurals>
<string name="action_sort_descending">Aflopend</string> <string name="action_sort_descending">Aflopend</string>
<string name="action_open_in_settings">In Instellingen openen</string> <string name="action_open_in_settings">In Instellingen openen</string>
<string name="pref_dns_over_https_summary">Herstart van de app nodig om van kracht te worden</string> <string name="requires_app_restart">Herstart van de app nodig om van kracht te worden</string>
<string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
<string name="label_network">Netwerk</string> <string name="label_network">Netwerk</string>
<string name="pref_jump_to_chapters">Ga naar de hoofdstukken bij openen</string> <string name="pref_jump_to_chapters">Ga naar de hoofdstukken bij openen</string>

View File

@ -581,7 +581,7 @@
<string name="action_disable">Wyłącz</string> <string name="action_disable">Wyłącz</string>
<string name="action_open_in_settings">Otwórz w ustawieniach</string> <string name="action_open_in_settings">Otwórz w ustawieniach</string>
<string name="action_start">Start</string> <string name="action_start">Start</string>
<string name="pref_dns_over_https_summary">Wymaga ponownego uruchomienia aplikacji</string> <string name="requires_app_restart">Wymaga ponownego uruchomienia aplikacji</string>
<string name="pref_dns_over_https" translatable="false">DNS przez HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS przez HTTPS (Cloudflare)</string>
<string name="label_network">Sieć</string> <string name="label_network">Sieć</string>
<string name="pref_jump_to_chapters">Przeskocz do rozdziałów przy otwarciu</string> <string name="pref_jump_to_chapters">Przeskocz do rozdziałów przy otwarciu</string>

View File

@ -568,7 +568,7 @@
<item quantity="other">%1$s capítulos</item> <item quantity="other">%1$s capítulos</item>
</plurals> </plurals>
<string name="action_open_in_settings">Abrir nas Configurações</string> <string name="action_open_in_settings">Abrir nas Configurações</string>
<string name="pref_dns_over_https_summary">Requer o reinício do aplicativo para ter efeito</string> <string name="requires_app_restart">Requer o reinício do aplicativo para ter efeito</string>
<string name="pref_dns_over_https" translatable="false">DNS sob HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS sob HTTPS (Cloudflare)</string>
<string name="label_network">Rede</string> <string name="label_network">Rede</string>
<string name="pref_jump_to_chapters">Pular para os capítulos ao abrir</string> <string name="pref_jump_to_chapters">Pular para os capítulos ao abrir</string>

View File

@ -606,7 +606,7 @@
</plurals> </plurals>
<string name="unknown_status">Estado desconhecido</string> <string name="unknown_status">Estado desconhecido</string>
<string name="unknown_author">Autor desconhecido</string> <string name="unknown_author">Autor desconhecido</string>
<string name="pref_dns_over_https_summary">Requer reinício da app para ter efeito</string> <string name="requires_app_restart">Requer reinício da app para ter efeito</string>
<string name="label_network">Rede</string> <string name="label_network">Rede</string>
<string name="pref_dns_over_https" translatable="false">DNS por HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS por HTTPS (Cloudflare)</string>
<string name="updated_version">Atualizado para v%1$s</string> <string name="updated_version">Atualizado para v%1$s</string>

View File

@ -575,7 +575,7 @@
<item quantity="few">%1$s capitole</item> <item quantity="few">%1$s capitole</item>
<item quantity="other">%1$s de capitole</item> <item quantity="other">%1$s de capitole</item>
</plurals> </plurals>
<string name="pref_dns_over_https_summary">Necesită restartarea aplicației pentru a avea efect</string> <string name="requires_app_restart">Necesită restartarea aplicației pentru a avea efect</string>
<string name="pref_dns_over_https" translatable="false">DNS prin HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS prin HTTPS (Cloudflare)</string>
<string name="action_sort_descending">Descrescător</string> <string name="action_sort_descending">Descrescător</string>
<string name="action_disable">Dezactivați</string> <string name="action_disable">Dezactivați</string>

View File

@ -586,7 +586,7 @@
<item quantity="other">%1$s глав</item> <item quantity="other">%1$s глав</item>
</plurals> </plurals>
<string name="action_sort_descending">По убыванию</string> <string name="action_sort_descending">По убыванию</string>
<string name="pref_dns_over_https_summary">Требуется перезапуск приложения для вступления в силу</string> <string name="requires_app_restart">Требуется перезапуск приложения для вступления в силу</string>
<string name="pref_dns_over_https" translatable="false">DNS по HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS по HTTPS (Cloudflare)</string>
<string name="label_network">Сеть</string> <string name="label_network">Сеть</string>
<string name="pref_jump_to_chapters">Переходить к главам при запуске</string> <string name="pref_jump_to_chapters">Переходить к главам при запуске</string>

View File

@ -345,7 +345,7 @@
<string name="pref_remove_after_marked_as_read">Ааҕыллыбыт диэн суруллубутун кэннэ</string> <string name="pref_remove_after_marked_as_read">Ааҕыллыбыт диэн суруллубутун кэннэ</string>
<string name="pref_download_only_over_wifi">Wi-Fi эрэ баар буоллаҕына хачайдаа</string> <string name="pref_download_only_over_wifi">Wi-Fi эрэ баар буоллаҕына хачайдаа</string>
<string name="pref_download_directory">Хачайдааһын сурунаала</string> <string name="pref_download_directory">Хачайдааһын сурунаала</string>
<string name="pref_dns_over_https_summary">Уларыйыы киирэрин гына эбилиги хос холбоо</string> <string name="requires_app_restart">Уларыйыы киирэрин гына эбилиги хос холбоо</string>
<string name="cache_delete_error">Кээс сотторуутугар сыыһааһын буолла</string> <string name="cache_delete_error">Кээс сотторуутугар сыыһааһын буолла</string>
<string name="cache_deleted">Кээс ыраастанна. %1$d билэ сотторуллубут этэ</string> <string name="cache_deleted">Кээс ыраастанна. %1$d билэ сотторуллубут этэ</string>
<string name="used_cache">Туттуллубут: %1$s</string> <string name="used_cache">Туттуллубут: %1$s</string>

View File

@ -568,7 +568,7 @@
<item quantity="one">1 capìtulu</item> <item quantity="one">1 capìtulu</item>
<item quantity="other">%1$s capìtulos</item> <item quantity="other">%1$s capìtulos</item>
</plurals> </plurals>
<string name="pref_dns_over_https_summary">Tenet bisòngiu chi torres a allùghere s\'aplicatzione pro tènnere efetu</string> <string name="requires_app_restart">Tenet bisòngiu chi torres a allùghere s\'aplicatzione pro tènnere efetu</string>
<string name="pref_dns_over_https" translatable="false">DNS pro mèdiu de HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS pro mèdiu de HTTPS (Cloudflare)</string>
<string name="label_network">Retza</string> <string name="label_network">Retza</string>
<string name="pref_jump_to_chapters">Brinca a sos capìtulos a s\'abertura</string> <string name="pref_jump_to_chapters">Brinca a sos capìtulos a s\'abertura</string>

View File

@ -572,7 +572,7 @@
</plurals> </plurals>
<string name="unknown_status">Okänd status</string> <string name="unknown_status">Okänd status</string>
<string name="unknown_author">Okänd författare</string> <string name="unknown_author">Okänd författare</string>
<string name="pref_dns_over_https_summary">Kräver omstart av appen för att börja gälla</string> <string name="requires_app_restart">Kräver omstart av appen för att börja gälla</string>
<string name="pref_dns_over_https" translatable="false">DNS över HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS över HTTPS (Cloudflare)</string>
<string name="label_network">Nätverk</string> <string name="label_network">Nätverk</string>
<string name="pref_jump_to_chapters">Hoppa till kapitel vid öppning</string> <string name="pref_jump_to_chapters">Hoppa till kapitel vid öppning</string>

View File

@ -568,7 +568,7 @@
<item quantity="other">%1$s bölüm</item> <item quantity="other">%1$s bölüm</item>
</plurals> </plurals>
<string name="action_open_in_settings">Ayarlarda aç</string> <string name="action_open_in_settings">Ayarlarda aç</string>
<string name="pref_dns_over_https_summary">Etkili olması için uygulama yeniden başlatılmalıdır</string> <string name="requires_app_restart">Etkili olması için uygulama yeniden başlatılmalıdır</string>
<string name="pref_dns_over_https" translatable="false">HTTPS ile DNS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">HTTPS ile DNS (Cloudflare)</string>
<string name="label_network"></string> <string name="label_network"></string>
<string name="pref_jump_to_chapters">ınca bölümlere git</string> <string name="pref_jump_to_chapters">ınca bölümlere git</string>

View File

@ -591,7 +591,7 @@
<string name="pref_read_with_tapping_inverted">Інвертувати тицяння</string> <string name="pref_read_with_tapping_inverted">Інвертувати тицяння</string>
<string name="unknown_status">Невідомий статус</string> <string name="unknown_status">Невідомий статус</string>
<string name="unknown_author">Невідомий автор</string> <string name="unknown_author">Невідомий автор</string>
<string name="pref_dns_over_https_summary">Потрібен перезапуск, щоб зміни вступили в дію</string> <string name="requires_app_restart">Потрібен перезапуск, щоб зміни вступили в дію</string>
<string name="pref_dns_over_https" translatable="false">DNS понад HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS понад HTTPS (Cloudflare)</string>
<string name="label_network">Мережа</string> <string name="label_network">Мережа</string>
<string name="pref_jump_to_chapters">Перейти до глав при відкритті</string> <string name="pref_jump_to_chapters">Перейти до глав при відкритті</string>

View File

@ -558,7 +558,7 @@
<item quantity="other">%1$s 个章节</item> <item quantity="other">%1$s 个章节</item>
</plurals> </plurals>
<string name="action_open_in_settings">在设置中打开</string> <string name="action_open_in_settings">在设置中打开</string>
<string name="pref_dns_over_https_summary">需要重启应用才能生效</string> <string name="requires_app_restart">需要重启应用才能生效</string>
<string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
<string name="label_network">网络</string> <string name="label_network">网络</string>
<string name="pref_jump_to_chapters">打开时跳转到阅读章节</string> <string name="pref_jump_to_chapters">打开时跳转到阅读章节</string>

View File

@ -525,7 +525,7 @@
<plurals name="num_categories"> <plurals name="num_categories">
<item quantity="other">%d 個分類</item> <item quantity="other">%d 個分類</item>
</plurals> </plurals>
<string name="pref_dns_over_https_summary">需要重新啟動應用程式以套用</string> <string name="requires_app_restart">需要重新啟動應用程式以套用</string>
<string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
<string name="label_network">網路</string> <string name="label_network">網路</string>
<string name="tapping_inverted_both">全部</string> <string name="tapping_inverted_both">全部</string>

View File

@ -172,11 +172,10 @@
<string name="secure_screen_summary">Hide app contents when switching apps and block screenshots</string> <string name="secure_screen_summary">Hide app contents when switching apps and block screenshots</string>
<string name="hide_notification_content">Hide notification content</string> <string name="hide_notification_content">Hide notification content</string>
<string name="pref_category_nsfw_content">18+ content</string> <string name="pref_category_nsfw_content">NSFW (18+) sources</string>
<string name="pref_allow_nsfw_sources">18+ sources</string> <string name="pref_show_nsfw_source">Show in sources list</string>
<string name="pref_allow_nsfw_sources_allowed">Show</string> <string name="pref_show_nsfw_extension">Show in extensions list</string>
<string name="pref_allow_nsfw_sources_allowed_multisource">Hide in sources but show in extensions list</string> <string name="pref_label_nsfw_extension">Label in extensions list</string>
<string name="pref_allow_nsfw_sources_blocked">Hide</string>
<string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing 18+ content within the app.</string> <string name="parental_controls_info">This does not prevent unofficial or potentially incorrectly flagged extensions from surfacing 18+ content within the app.</string>
<!-- Library section --> <!-- Library section -->
@ -390,7 +389,7 @@
<string name="label_network">Network</string> <string name="label_network">Network</string>
<string name="pref_clear_cookies">Clear cookies</string> <string name="pref_clear_cookies">Clear cookies</string>
<string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string> <string name="pref_dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
<string name="pref_dns_over_https_summary">Requires app restart to take effect</string> <string name="requires_app_restart">Requires app restart to take effect</string>
<string name="cookies_cleared">Cookies cleared</string> <string name="cookies_cleared">Cookies cleared</string>
<string name="label_data">Data</string> <string name="label_data">Data</string>
<string name="pref_clear_chapter_cache">Clear chapter cache</string> <string name="pref_clear_chapter_cache">Clear chapter cache</string>
@ -570,6 +569,8 @@
<string name="track_type">Type</string> <string name="track_type">Type</string>
<string name="track_author">Author</string> <string name="track_author">Author</string>
<string name="error_invalid_date_supplied">Invalid date supplied</string> <string name="error_invalid_date_supplied">Invalid date supplied</string>
<string name="myanimelist_creds_missing">MAL login credentials not found</string>
<string name="myanimelist_relogin">Please login to MAL again</string>
<!-- Category activity --> <!-- Category activity -->
<string name="error_category_exists">A category with this name already exists!</string> <string name="error_category_exists">A category with this name already exists!</string>
@ -666,6 +667,7 @@
<!-- File Picker Titles --> <!-- File Picker Titles -->
<string name="file_select_cover">Select cover image</string> <string name="file_select_cover">Select cover image</string>
<string name="file_select_backup">Select backup file</string> <string name="file_select_backup">Select backup file</string>
<string name="file_picker_error">No file picker app found</string>
<!--UpdateCheck--> <!--UpdateCheck-->
<string name="update_check_confirm">Download</string> <string name="update_check_confirm">Download</string>

View File

@ -325,22 +325,4 @@
<item name="android:textSize">15sp</item> <item name="android:textSize">15sp</item>
</style> </style>
<!--===-->
<!--OLD-->
<!--===-->
<style name="FilePickerTheme" parent="NNF_BaseTheme.Light">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimary</item>
<item name="colorAccent">@color/colorAccentLight</item>
<item name="colorButtonNormal">@color/colorPrimary</item>
<item name="android:textSize">14sp</item>
<item name="alertDialogTheme">@style/FilePickerAlertDialogTheme</item>
<item name="nnf_toolbarTheme">@style/ThemeOverlay.AppCompat.Dark.ActionBar</item>
</style>
<style name="FilePickerAlertDialogTheme" parent="Theme.MaterialComponents.Light.Dialog.Alert" />
</resources> </resources>

View File

@ -27,7 +27,7 @@ buildscript {
dependencies { dependencies {
classpath("com.github.zellius:android-shortcut-gradle-plugin:0.1.2") classpath("com.github.zellius:android-shortcut-gradle-plugin:0.1.2")
classpath("com.google.gms:google-services:4.3.4") classpath("com.google.gms:google-services:4.3.4")
classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:" + BuildPluginsVersion.ABOUTLIB_PLUGIN) classpath("com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${BuildPluginsVersion.ABOUTLIB_PLUGIN}")
classpath(kotlin("serialization", version = BuildPluginsVersion.KOTLIN)) classpath(kotlin("serialization", version = BuildPluginsVersion.KOTLIN))
} }
repositories { repositories {