mirror of
https://github.com/aniyomiorg/aniyomi.git
synced 2024-11-24 13:48:55 +03:00
commit
afffe462ef
75 changed files with 2184 additions and 464 deletions
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
|
@ -1,2 +1 @@
|
|||
github: inorichi
|
||||
ko_fi: inorichi
|
||||
|
|
2
.github/ISSUE_TEMPLATE.md
vendored
2
.github/ISSUE_TEMPLATE.md
vendored
|
@ -3,7 +3,7 @@
|
|||
I acknowledge that:
|
||||
|
||||
- I have updated:
|
||||
- To the latest version of the app (stable is v0.10.10)
|
||||
- To the latest version of the app (stable is v0.10.11)
|
||||
- All extensions
|
||||
- I have tried the troubleshooting guide: https://tachiyomi.org/help/guides/troubleshooting-problems/
|
||||
- If this is an issue with an extension, that I should be opening an issue in https://github.com/tachiyomiorg/tachiyomi-extensions
|
||||
|
|
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
2
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -10,7 +10,7 @@ labels: "bug"
|
|||
I acknowledge that:
|
||||
|
||||
- I have updated:
|
||||
- To the latest version of the app (stable is v0.10.10)
|
||||
- To the latest version of the app (stable is v0.10.11)
|
||||
- All extensions
|
||||
- I have tried the troubleshooting guide: https://tachiyomi.org/help/guides/troubleshooting-problems/
|
||||
- If this is an issue with an extension, that I should be opening an issue in https://github.com/tachiyomiorg/tachiyomi-extensions
|
||||
|
|
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
2
.github/ISSUE_TEMPLATE/feature_request.md
vendored
|
@ -10,7 +10,7 @@ labels: "feature"
|
|||
I acknowledge that:
|
||||
|
||||
- I have updated:
|
||||
- To the latest version of the app (stable is v0.10.10)
|
||||
- To the latest version of the app (stable is v0.10.11)
|
||||
- All extensions
|
||||
- If this is an issue with an extension, that I should be opening an issue in https://github.com/tachiyomiorg/tachiyomi-extensions
|
||||
- I have searched the existing issues and this is new ticket **NOT** a duplicate or related to another open issue
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
### r2903
|
||||
- The MyAnimeList tracker was rewritten. You will need to log out and log in again.
|
||||
|
||||
### r1810
|
||||
- Background jobs were migrated to a new system. You may need to toggle the settings to ensure they
|
||||
run properly. This includes app updates, library updates, and automatic backups.
|
||||
|
||||
### r1340
|
||||
- A new screen for managing extensions was added. If you previously installed extensions from FDroid,
|
||||
you will have to uninstall all of them first (tap on the extension then uninstall), otherwise you won't be able
|
||||
to update them due to signature mismatch. You won't lose anything in this process as the extensions themselves
|
||||
don't store anything.
|
||||
|
||||
### r959
|
||||
- The download manager has been rewritten and it's possible some of your downloads
|
||||
aren't recognized anymore. You may have to check your downloads folder and manually delete those.
|
||||
- You can now download to any folder in your SD card.
|
||||
- The download directory setting has been reset.
|
||||
|
||||
### r857
|
||||
- **Important!** Delete after read has been updated.
|
||||
This means the value has been reset set to disabled.
|
||||
This can be changed in Settings > Downloads
|
||||
|
||||
### r736
|
||||
- **Important!** Now chapters follow the order of the sources. **It's required that you update your entire library
|
||||
before reading in order for them to be synced.** Old behavior can be restored for a manga in the overflow menu of the chapters tab.
|
||||
|
||||
### r724
|
||||
- Kissmanga covers may not load anymore. The only workaround is to update the details of the manga
|
||||
from the info tab, or clearing the database (the latter won't fix covers from library manga).
|
|
@ -29,8 +29,8 @@ android {
|
|||
minSdkVersion(AndroidConfig.minSdk)
|
||||
targetSdkVersion(AndroidConfig.targetSdk)
|
||||
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
|
||||
versionCode = 57
|
||||
versionName = "0.10.10"
|
||||
versionCode = 58
|
||||
versionName = "0.10.11"
|
||||
|
||||
buildConfigField("String", "COMMIT_COUNT", "\"${getCommitCount()}\"")
|
||||
buildConfigField("String", "COMMIT_SHA", "\"${getGitSha()}\"")
|
||||
|
@ -265,7 +265,7 @@ dependencies {
|
|||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutinesVersion")
|
||||
|
||||
// For detecting memory leaks; see https://square.github.io/leakcanary/
|
||||
// debugImplementation("com.squareup.leakcanary:leakcanary-android:2.6")
|
||||
// debugImplementation("com.squareup.leakcanary:leakcanary-android:2.7")
|
||||
}
|
||||
|
||||
tasks {
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
android:largeHeap="true"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:theme="@style/Theme.Tachiyomi.Light"
|
||||
android:theme="@style/Theme.Base"
|
||||
android:networkSecurityConfig="@xml/network_security_config">
|
||||
<activity
|
||||
android:name=".ui.main.MainActivity"
|
||||
|
@ -84,7 +84,7 @@
|
|||
</activity>
|
||||
<activity
|
||||
android:name=".ui.security.BiometricUnlockActivity"
|
||||
android:theme="@style/Theme.Splash" />
|
||||
android:theme="@style/Theme.Base" />
|
||||
<activity
|
||||
android:name=".ui.webview.WebViewActivity"
|
||||
android:configChanges="uiMode|orientation|screenSize" />
|
||||
|
|
|
@ -2,17 +2,17 @@ package eu.kanade.tachiyomi.data.cache
|
|||
|
||||
import android.content.Context
|
||||
import android.text.format.Formatter
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.Gson
|
||||
import com.jakewharton.disklrucache.DiskLruCache
|
||||
import eu.kanade.tachiyomi.data.database.models.Chapter
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.util.storage.DiskUtil
|
||||
import eu.kanade.tachiyomi.util.storage.saveTo
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.encodeToString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Response
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
@ -42,8 +42,7 @@ class ChapterCache(private val context: Context) {
|
|||
const val PARAMETER_CACHE_SIZE = 100L * 1024 * 1024
|
||||
}
|
||||
|
||||
/** Google Json class used for parsing JSON files. */
|
||||
private val gson: Gson by injectLazy()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
/** Cache class used for cache management. */
|
||||
private val diskCache = DiskLruCache.open(
|
||||
|
@ -56,7 +55,7 @@ class ChapterCache(private val context: Context) {
|
|||
/**
|
||||
* Returns directory of cache.
|
||||
*/
|
||||
val cacheDir: File
|
||||
private val cacheDir: File
|
||||
get() = diskCache.directory
|
||||
|
||||
/**
|
||||
|
@ -71,43 +70,19 @@ class ChapterCache(private val context: Context) {
|
|||
val readableSize: String
|
||||
get() = Formatter.formatFileSize(context, realSize)
|
||||
|
||||
/**
|
||||
* Remove file from cache.
|
||||
*
|
||||
* @param file name of file "md5.0".
|
||||
* @return status of deletion for the file.
|
||||
*/
|
||||
fun removeFileFromCache(file: String): Boolean {
|
||||
// Make sure we don't delete the journal file (keeps track of cache).
|
||||
if (file == "journal" || file.startsWith("journal.")) {
|
||||
return false
|
||||
}
|
||||
|
||||
return try {
|
||||
// Remove the extension from the file to get the key of the cache
|
||||
val key = file.substringBeforeLast(".")
|
||||
// Remove file from cache.
|
||||
diskCache.remove(key)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get page list from cache.
|
||||
*
|
||||
* @param chapter the chapter.
|
||||
* @return an observable of the list of pages.
|
||||
* @return the list of pages.
|
||||
*/
|
||||
fun getPageListFromCache(chapter: Chapter): Observable<List<Page>> {
|
||||
return Observable.fromCallable {
|
||||
// Get the key for the chapter.
|
||||
val key = DiskUtil.hashKeyForDisk(getKey(chapter))
|
||||
fun getPageListFromCache(chapter: Chapter): List<Page> {
|
||||
// Get the key for the chapter.
|
||||
val key = DiskUtil.hashKeyForDisk(getKey(chapter))
|
||||
|
||||
// Convert JSON string to list of objects. Throws an exception if snapshot is null
|
||||
diskCache.get(key).use {
|
||||
gson.fromJson<List<Page>>(it.getString(0))
|
||||
}
|
||||
// Convert JSON string to list of objects. Throws an exception if snapshot is null
|
||||
return diskCache.get(key).use {
|
||||
json.decodeFromString(it.getString(0))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,7 +94,7 @@ class ChapterCache(private val context: Context) {
|
|||
*/
|
||||
fun putPageListToCache(chapter: Chapter, pages: List<Page>) {
|
||||
// Convert list of pages to json string.
|
||||
val cachedValue = gson.toJson(pages)
|
||||
val cachedValue = json.encodeToString(pages)
|
||||
|
||||
// Initialize the editor (edits the values for an entry).
|
||||
var editor: DiskLruCache.Editor? = null
|
||||
|
@ -199,6 +174,38 @@ class ChapterCache(private val context: Context) {
|
|||
}
|
||||
}
|
||||
|
||||
fun clear(): Int {
|
||||
var deletedFiles = 0
|
||||
cacheDir.listFiles()?.forEach {
|
||||
if (removeFileFromCache(it.name)) {
|
||||
deletedFiles++
|
||||
}
|
||||
}
|
||||
return deletedFiles
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove file from cache.
|
||||
*
|
||||
* @param file name of file "md5.0".
|
||||
* @return status of deletion for the file.
|
||||
*/
|
||||
private fun removeFileFromCache(file: String): Boolean {
|
||||
// Make sure we don't delete the journal file (keeps track of cache).
|
||||
if (file == "journal" || file.startsWith("journal.")) {
|
||||
return false
|
||||
}
|
||||
|
||||
return try {
|
||||
// Remove the extension from the file to get the key of the cache
|
||||
val key = file.substringBeforeLast(".")
|
||||
// Remove file from cache.
|
||||
diskCache.remove(key)
|
||||
} catch (e: Exception) {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
private fun getKey(chapter: Chapter): String {
|
||||
return "${chapter.manga_id}${chapter.url}"
|
||||
}
|
||||
|
|
|
@ -163,7 +163,7 @@ internal object ExtensionLoader {
|
|||
else -> throw Exception("Unknown source class type! ${obj.javaClass}")
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
Timber.w(e, "Extension load error: $extName ($it)")
|
||||
Timber.e(e, "Extension load error: $extName ($it)")
|
||||
return LoadResult.Error(e)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,65 +1,39 @@
|
|||
package eu.kanade.tachiyomi.ui.base.activity
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Build
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_MASK
|
||||
import android.content.res.Configuration.UI_MODE_NIGHT_YES
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DarkThemeVariant
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.LightThemeVariant
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.ThemeMode
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values
|
||||
|
||||
abstract class BaseThemedActivity : AppCompatActivity() {
|
||||
|
||||
val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
private val isDarkMode: Boolean by lazy {
|
||||
val themeMode = preferences.themeMode().get()
|
||||
(themeMode == Values.ThemeMode.dark) ||
|
||||
(
|
||||
themeMode == Values.ThemeMode.system &&
|
||||
(resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES)
|
||||
)
|
||||
}
|
||||
|
||||
private val lightTheme: Int by lazy {
|
||||
when (preferences.themeLight().get()) {
|
||||
Values.LightThemeVariant.blue -> R.style.Theme_Tachiyomi_LightBlue
|
||||
else -> {
|
||||
when {
|
||||
// Light status + navigation bar
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1 -> {
|
||||
R.style.Theme_Tachiyomi_Light_Api27
|
||||
}
|
||||
// Light status bar + fallback gray navigation bar
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.M -> {
|
||||
R.style.Theme_Tachiyomi_Light_Api23
|
||||
}
|
||||
// Fallback gray status + navigation bar
|
||||
else -> {
|
||||
R.style.Theme_Tachiyomi_Light
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val darkTheme: Int by lazy {
|
||||
when (preferences.themeDark().get()) {
|
||||
Values.DarkThemeVariant.blue -> R.style.Theme_Tachiyomi_DarkBlue
|
||||
Values.DarkThemeVariant.amoled -> R.style.Theme_Tachiyomi_Amoled
|
||||
else -> R.style.Theme_Tachiyomi_Dark
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
setTheme(
|
||||
when {
|
||||
isDarkMode -> darkTheme
|
||||
else -> lightTheme
|
||||
val isDarkMode = when (preferences.themeMode().get()) {
|
||||
ThemeMode.light -> false
|
||||
ThemeMode.dark -> true
|
||||
ThemeMode.system -> resources.configuration.uiMode and UI_MODE_NIGHT_MASK == UI_MODE_NIGHT_YES
|
||||
}
|
||||
val themeId = if (isDarkMode) {
|
||||
when (preferences.themeDark().get()) {
|
||||
DarkThemeVariant.default -> R.style.Theme_Tachiyomi_Dark
|
||||
DarkThemeVariant.blue -> R.style.Theme_Tachiyomi_Dark_Blue
|
||||
DarkThemeVariant.amoled -> R.style.Theme_Tachiyomi_Dark_Amoled
|
||||
}
|
||||
)
|
||||
|
||||
} else {
|
||||
when (preferences.themeLight().get()) {
|
||||
LightThemeVariant.default -> R.style.Theme_Tachiyomi_Light
|
||||
LightThemeVariant.blue -> R.style.Theme_Tachiyomi_Light_Blue
|
||||
}
|
||||
}
|
||||
setTheme(themeId)
|
||||
super.onCreate(savedInstanceState)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,8 @@ import timber.log.Timber
|
|||
abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
|
||||
RestoreViewOnCreateController(bundle) {
|
||||
|
||||
lateinit var binding: VB
|
||||
protected lateinit var binding: VB
|
||||
private set
|
||||
|
||||
lateinit var viewScope: CoroutineScope
|
||||
|
||||
|
@ -51,11 +52,12 @@ abstract class BaseController<VB : ViewBinding>(bundle: Bundle? = null) :
|
|||
)
|
||||
}
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
|
||||
return inflateView(inflater, container)
|
||||
}
|
||||
abstract fun createBinding(inflater: LayoutInflater): VB
|
||||
|
||||
abstract fun inflateView(inflater: LayoutInflater, container: ViewGroup): View
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedViewState: Bundle?): View {
|
||||
binding = createBinding(inflater)
|
||||
return binding.root
|
||||
}
|
||||
|
||||
open fun onViewCreated(view: View) {}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.browse
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import com.bluelinelabs.conductor.Controller
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
|
@ -50,10 +49,7 @@ class BrowseController :
|
|||
return resources!!.getString(R.string.browse)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = PagerControllerBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = PagerControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.bluelinelabs.conductor.ControllerChangeHandler
|
||||
|
@ -57,18 +56,16 @@ open class ExtensionController :
|
|||
return ExtensionPresenter()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = ExtensionControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = ExtensionControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.swipeRefresh.isRefreshing = true
|
||||
binding.swipeRefresh.refreshes()
|
||||
|
|
|
@ -12,7 +12,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.preference.Preference
|
||||
|
@ -65,15 +64,9 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
override fun createBinding(inflater: LayoutInflater): ExtensionDetailControllerBinding {
|
||||
val themedInflater = inflater.cloneInContext(getPreferenceThemeContext())
|
||||
binding = ExtensionDetailControllerBinding.inflate(themedInflater)
|
||||
binding.extensionPrefsRecycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
return ExtensionDetailControllerBinding.inflate(themedInflater)
|
||||
}
|
||||
|
||||
override fun createPresenter(): ExtensionDetailsPresenter {
|
||||
|
@ -88,6 +81,12 @@ class ExtensionDetailsController(bundle: Bundle? = null) :
|
|||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.extensionPrefsRecycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
|
||||
val extension = presenter.extension ?: return
|
||||
val context = view.context
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.os.Bundle
|
|||
import android.util.TypedValue
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.view.ContextThemeWrapper
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.preference.DialogPreference
|
||||
|
@ -45,10 +44,9 @@ class SourcePreferencesController(bundle: Bundle? = null) :
|
|||
bundleOf(SOURCE_ID to sourceId)
|
||||
)
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
override fun createBinding(inflater: LayoutInflater): SourcePreferencesControllerBinding {
|
||||
val themedInflater = inflater.cloneInContext(getPreferenceThemeContext())
|
||||
binding = SourcePreferencesControllerBinding.inflate(themedInflater)
|
||||
return binding.root
|
||||
return SourcePreferencesControllerBinding.inflate(themedInflater)
|
||||
}
|
||||
|
||||
override fun createPresenter(): SourcePreferencesPresenter {
|
||||
|
|
|
@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.browse.migration.manga
|
|||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
|
@ -45,18 +44,16 @@ class MigrationMangaController :
|
|||
return MigrationMangaPresenter(sourceId)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = MigrationMangaControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = MigrationMangaControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
adapter = MigrationMangaAdapter(this)
|
||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
|
|
|
@ -104,23 +104,22 @@ class SearchPresenter(
|
|||
val prevMangaChapters = db.getChapters(prevManga).executeAsBlocking()
|
||||
val maxChapterRead = prevMangaChapters
|
||||
.filter { it.read }
|
||||
.maxOfOrNull { it.chapter_number }
|
||||
if (maxChapterRead != null) {
|
||||
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
||||
for (chapter in dbChapters) {
|
||||
if (chapter.isRecognizedNumber) {
|
||||
val prevChapter = prevMangaChapters
|
||||
.find { it.isRecognizedNumber && it.chapter_number == chapter.chapter_number }
|
||||
if (prevChapter != null) {
|
||||
chapter.date_fetch = prevChapter.date_fetch
|
||||
chapter.bookmark = prevChapter.bookmark
|
||||
} else if (chapter.chapter_number <= maxChapterRead) {
|
||||
chapter.read = true
|
||||
}
|
||||
.maxOfOrNull { it.chapter_number } ?: 0f
|
||||
val dbChapters = db.getChapters(manga).executeAsBlocking()
|
||||
for (chapter in dbChapters) {
|
||||
if (chapter.isRecognizedNumber) {
|
||||
val prevChapter = prevMangaChapters
|
||||
.find { it.isRecognizedNumber && it.chapter_number == chapter.chapter_number }
|
||||
if (prevChapter != null) {
|
||||
chapter.date_fetch = prevChapter.date_fetch
|
||||
chapter.bookmark = prevChapter.bookmark
|
||||
}
|
||||
if (chapter.chapter_number <= maxChapterRead) {
|
||||
chapter.read = true
|
||||
}
|
||||
}
|
||||
db.insertChapters(dbChapters).executeAsBlocking()
|
||||
}
|
||||
db.insertChapters(dbChapters).executeAsBlocking()
|
||||
}
|
||||
|
||||
// Update categories
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
|
@ -30,18 +29,16 @@ class MigrationSourcesController :
|
|||
return MigrationSourcesPresenter()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = MigrationSourcesControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = MigrationSourcesControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
adapter = SourceAdapter(this)
|
||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
|
|
|
@ -8,7 +8,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItems
|
||||
|
@ -67,25 +66,16 @@ class SourceController :
|
|||
return SourcePresenter()
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the view with [R.layout.source_main_controller].
|
||||
*
|
||||
* @param inflater used to load the layout xml.
|
||||
* @param container containing parent views.
|
||||
* @return inflated view.
|
||||
*/
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = SourceMainControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = SourceMainControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
adapter = SourceAdapter(this)
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import com.jakewharton.rxrelay.PublishRelay
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import rx.Observable
|
||||
|
||||
/**
|
||||
* A general pager for source requests (latest updates, popular, search)
|
||||
*/
|
||||
abstract class AnimePager(var currentPage: Int = 1) {
|
||||
|
||||
var hasNextPage = true
|
||||
private set
|
||||
|
||||
protected val results: PublishRelay<Pair<Int, List<SAnime>>> = PublishRelay.create()
|
||||
|
||||
fun results(): Observable<Pair<Int, List<SAnime>>> {
|
||||
return results.asObservable()
|
||||
}
|
||||
|
||||
abstract fun requestNext(): Observable<AnimesPage>
|
||||
|
||||
fun onPageReceived(animesPage: AnimesPage) {
|
||||
val page = currentPage
|
||||
currentPage++
|
||||
hasNextPage = animesPage.hasNextPage && animesPage.animes.isNotEmpty()
|
||||
results.call(Pair(page, animesPage.animes))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.source.model.AnimesPage
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
|
||||
open class AnimeSourcePager(val source: AnimeCatalogueSource, val query: String, val filters: FilterList) : AnimePager() {
|
||||
|
||||
override fun requestNext(): Observable<AnimesPage> {
|
||||
val page = currentPage
|
||||
|
||||
val observable = if (query.isBlank() && filters.isEmpty()) {
|
||||
source.fetchPopularAnime(page)
|
||||
} else {
|
||||
source.fetchSearchAnime(page, query, filters)
|
||||
}
|
||||
|
||||
return observable
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnNext {
|
||||
if (it.animes.isNotEmpty()) {
|
||||
onPageReceived(it)
|
||||
} else {
|
||||
throw NoResultsException()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,620 @@
|
|||
package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import android.content.res.Configuration
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.Menu
|
||||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.core.view.updatePadding
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.list.listItems
|
||||
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import com.tfcporciuncula.flow.Preference
|
||||
import dev.chrisbanes.insetter.applyInsetter
|
||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.data.preference.asImmediateFlow
|
||||
import eu.kanade.tachiyomi.databinding.AnimeSourceControllerBinding
|
||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.source.LocalAnimeSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.online.AnimeHttpSource
|
||||
import eu.kanade.tachiyomi.ui.anime.AnimeController
|
||||
import eu.kanade.tachiyomi.ui.animelib.ChangeAnimeCategoriesDialog
|
||||
import eu.kanade.tachiyomi.ui.base.controller.FabController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.SearchableNucleusController
|
||||
import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchController
|
||||
import eu.kanade.tachiyomi.ui.main.MainActivity
|
||||
import eu.kanade.tachiyomi.ui.more.MoreController
|
||||
import eu.kanade.tachiyomi.ui.webview.WebViewActivity
|
||||
import eu.kanade.tachiyomi.util.system.connectivityManager
|
||||
import eu.kanade.tachiyomi.util.system.openInBrowser
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import eu.kanade.tachiyomi.util.view.inflate
|
||||
import eu.kanade.tachiyomi.util.view.shrinkOnScroll
|
||||
import eu.kanade.tachiyomi.util.view.snack
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import eu.kanade.tachiyomi.widget.EmptyView
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
/**
|
||||
* Controller to manage the catalogues available in the app.
|
||||
*/
|
||||
open class BrowseAnimeSourceController(bundle: Bundle) :
|
||||
SearchableNucleusController<AnimeSourceControllerBinding, BrowseAnimeSourcePresenter>(bundle),
|
||||
FabController,
|
||||
FlexibleAdapter.OnItemClickListener,
|
||||
FlexibleAdapter.OnItemLongClickListener,
|
||||
FlexibleAdapter.EndlessScrollListener,
|
||||
ChangeAnimeCategoriesDialog.Listener {
|
||||
|
||||
constructor(source: AnimeCatalogueSource, searchQuery: String? = null) : this(
|
||||
Bundle().apply {
|
||||
putLong(SOURCE_ID_KEY, source.id)
|
||||
|
||||
if (searchQuery != null) {
|
||||
putString(SEARCH_QUERY_KEY, searchQuery)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
private val preferences: PreferencesHelper by injectLazy()
|
||||
|
||||
/**
|
||||
* Adapter containing the list of anime from the catalogue.
|
||||
*/
|
||||
protected var adapter: FlexibleAdapter<IFlexible<*>>? = null
|
||||
|
||||
private var actionFab: ExtendedFloatingActionButton? = null
|
||||
private var actionFabScrollListener: RecyclerView.OnScrollListener? = null
|
||||
|
||||
/**
|
||||
* Snackbar containing an error message when a request fails.
|
||||
*/
|
||||
private var snack: Snackbar? = null
|
||||
|
||||
/**
|
||||
* Sheet containing filter items.
|
||||
*/
|
||||
private var filterSheet: SourceFilterSheet? = null
|
||||
|
||||
/**
|
||||
* Recycler view with the list of results.
|
||||
*/
|
||||
private var recycler: RecyclerView? = null
|
||||
|
||||
/**
|
||||
* Subscription for the number of anime per row.
|
||||
*/
|
||||
private var numColumnsJob: Job? = null
|
||||
|
||||
/**
|
||||
* Endless loading item.
|
||||
*/
|
||||
private var progressItem: ProgressItem? = null
|
||||
|
||||
init {
|
||||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return presenter.source.name
|
||||
}
|
||||
|
||||
override fun createPresenter(): BrowseAnimeSourcePresenter {
|
||||
return BrowseAnimeSourcePresenter(args.getLong(SOURCE_ID_KEY), args.getString(SEARCH_QUERY_KEY))
|
||||
}
|
||||
|
||||
override fun createBinding(inflater: LayoutInflater) = AnimeSourceControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
// Prepare filter sheet
|
||||
initFilterSheet()
|
||||
|
||||
// Initialize adapter, scroll listener and recycler views
|
||||
adapter = FlexibleAdapter(null, this)
|
||||
setupRecycler(view)
|
||||
|
||||
binding.progress.isVisible = true
|
||||
}
|
||||
|
||||
open fun initFilterSheet() {
|
||||
if (presenter.sourceFilters.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
filterSheet = SourceFilterSheet(
|
||||
activity!!,
|
||||
onFilterClicked = {
|
||||
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
|
||||
showProgressBar()
|
||||
adapter?.clear()
|
||||
presenter.setSourceFilter(if (allDefault) FilterList() else presenter.sourceFilters)
|
||||
},
|
||||
onResetClicked = {
|
||||
presenter.appliedFilters = FilterList()
|
||||
val newFilters = presenter.source.getFilterList()
|
||||
presenter.sourceFilters = newFilters
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
}
|
||||
)
|
||||
filterSheet?.setFilters(presenter.filterItems)
|
||||
|
||||
// TODO: [ExtendedFloatingActionButton] hide/show methods don't work properly
|
||||
filterSheet?.setOnShowListener { actionFab?.isVisible = false }
|
||||
filterSheet?.setOnDismissListener { actionFab?.isVisible = true }
|
||||
|
||||
actionFab?.setOnClickListener { filterSheet?.show() }
|
||||
|
||||
actionFab?.isVisible = true
|
||||
}
|
||||
|
||||
override fun configureFab(fab: ExtendedFloatingActionButton) {
|
||||
actionFab = fab
|
||||
|
||||
// Controlled by initFilterSheet()
|
||||
fab.isVisible = false
|
||||
|
||||
fab.setText(R.string.action_filter)
|
||||
fab.setIconResource(R.drawable.ic_filter_list_24dp)
|
||||
}
|
||||
|
||||
override fun cleanupFab(fab: ExtendedFloatingActionButton) {
|
||||
fab.setOnClickListener(null)
|
||||
actionFabScrollListener?.let { recycler?.removeOnScrollListener(it) }
|
||||
actionFab = null
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
numColumnsJob?.cancel()
|
||||
numColumnsJob = null
|
||||
adapter = null
|
||||
snack = null
|
||||
recycler = null
|
||||
super.onDestroyView(view)
|
||||
}
|
||||
|
||||
private fun setupRecycler(view: View) {
|
||||
numColumnsJob?.cancel()
|
||||
|
||||
var oldPosition = RecyclerView.NO_POSITION
|
||||
val oldRecycler = binding.catalogueView.getChildAt(1)
|
||||
if (oldRecycler is RecyclerView) {
|
||||
oldPosition = (oldRecycler.layoutManager as LinearLayoutManager).findFirstVisibleItemPosition()
|
||||
oldRecycler.adapter = null
|
||||
|
||||
binding.catalogueView.removeView(oldRecycler)
|
||||
}
|
||||
|
||||
val recycler = if (preferences.sourceDisplayMode().get() == DisplayMode.LIST) {
|
||||
RecyclerView(view.context).apply {
|
||||
id = R.id.recycler
|
||||
layoutManager = LinearLayoutManager(context)
|
||||
layoutParams = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
|
||||
}
|
||||
} else {
|
||||
(binding.catalogueView.inflate(R.layout.source_recycler_autofit) as AutofitRecyclerView).apply {
|
||||
numColumnsJob = getColumnsPreferenceForCurrentOrientation().asImmediateFlow { spanCount = it }
|
||||
.drop(1)
|
||||
// Set again the adapter to recalculate the covers height
|
||||
.onEach { adapter = this@BrowseAnimeSourceController.adapter }
|
||||
.launchIn(viewScope)
|
||||
|
||||
(layoutManager as GridLayoutManager).spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
return when (adapter?.getItemViewType(position)) {
|
||||
R.layout.source_compact_grid_item, R.layout.source_comfortable_grid_item, null -> 1
|
||||
else -> spanCount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (filterSheet != null) {
|
||||
// Add bottom padding if filter FAB is visible
|
||||
recycler.updatePadding(bottom = view.resources.getDimensionPixelOffset(R.dimen.fab_list_padding))
|
||||
recycler.clipToPadding = false
|
||||
|
||||
actionFab?.shrinkOnScroll(recycler)
|
||||
}
|
||||
|
||||
recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
recycler.setHasFixedSize(true)
|
||||
recycler.adapter = adapter
|
||||
|
||||
binding.catalogueView.addView(recycler, 1)
|
||||
|
||||
if (oldPosition != RecyclerView.NO_POSITION) {
|
||||
recycler.layoutManager?.scrollToPosition(oldPosition)
|
||||
}
|
||||
this.recycler = recycler
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu, inflater: MenuInflater) {
|
||||
createOptionsMenu(menu, inflater, R.menu.source_browse, R.id.action_search)
|
||||
val searchItem = menu.findItem(R.id.action_search)
|
||||
|
||||
searchItem.fixExpand(
|
||||
onExpand = { invalidateMenuOnExpand() },
|
||||
onCollapse = {
|
||||
if (router.backstackSize >= 2 && router.backstack[router.backstackSize - 2].controller() is GlobalSearchController) {
|
||||
router.popController(this)
|
||||
} else {
|
||||
nonSubmittedQuery = ""
|
||||
searchWithQuery("")
|
||||
}
|
||||
|
||||
true
|
||||
}
|
||||
)
|
||||
|
||||
val displayItem = when (preferences.sourceDisplayMode().get()) {
|
||||
DisplayMode.COMPACT_GRID -> R.id.action_compact_grid
|
||||
DisplayMode.COMFORTABLE_GRID -> R.id.action_comfortable_grid
|
||||
DisplayMode.LIST -> R.id.action_list
|
||||
}
|
||||
menu.findItem(displayItem).isChecked = true
|
||||
}
|
||||
|
||||
override fun onSearchViewQueryTextSubmit(query: String?) {
|
||||
searchWithQuery(query ?: "")
|
||||
}
|
||||
|
||||
override fun onPrepareOptionsMenu(menu: Menu) {
|
||||
super.onPrepareOptionsMenu(menu)
|
||||
|
||||
val isHttpSource = presenter.source is AnimeHttpSource
|
||||
menu.findItem(R.id.action_open_in_web_view).isVisible = isHttpSource
|
||||
|
||||
val isLocalSource = presenter.source is LocalAnimeSource
|
||||
menu.findItem(R.id.action_local_source_help).isVisible = isLocalSource
|
||||
}
|
||||
|
||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||
when (item.itemId) {
|
||||
R.id.action_search -> expandActionViewFromInteraction = true
|
||||
R.id.action_compact_grid -> setDisplayMode(DisplayMode.COMPACT_GRID)
|
||||
R.id.action_comfortable_grid -> setDisplayMode(DisplayMode.COMFORTABLE_GRID)
|
||||
R.id.action_list -> setDisplayMode(DisplayMode.LIST)
|
||||
R.id.action_open_in_web_view -> openInWebView()
|
||||
R.id.action_local_source_help -> openLocalSourceHelpGuide()
|
||||
}
|
||||
return super.onOptionsItemSelected(item)
|
||||
}
|
||||
|
||||
private fun openInWebView() {
|
||||
val source = presenter.source as? AnimeHttpSource ?: return
|
||||
|
||||
val activity = activity ?: return
|
||||
val intent = WebViewActivity.newIntent(activity, source.baseUrl, source.id, presenter.source.name)
|
||||
startActivity(intent)
|
||||
}
|
||||
|
||||
private fun openLocalSourceHelpGuide() {
|
||||
activity?.openInBrowser(LocalAnimeSource.HELP_URL)
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the request with a new query.
|
||||
*
|
||||
* @param newQuery the new query.
|
||||
*/
|
||||
fun searchWithQuery(newQuery: String) {
|
||||
// If text didn't change, do nothing
|
||||
if (presenter.query == newQuery) {
|
||||
return
|
||||
}
|
||||
|
||||
showProgressBar()
|
||||
adapter?.clear()
|
||||
|
||||
presenter.restartPager(newQuery)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when the network request is received.
|
||||
*
|
||||
* @param page the current page.
|
||||
* @param animes the list of anime of the page.
|
||||
*/
|
||||
fun onAddPage(page: Int, animes: List<AnimeSourceItem>) {
|
||||
val adapter = adapter ?: return
|
||||
hideProgressBar()
|
||||
if (page == 1) {
|
||||
adapter.clear()
|
||||
resetProgressItem()
|
||||
}
|
||||
adapter.onLoadMoreComplete(animes)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when the network request fails.
|
||||
*
|
||||
* @param error the error received.
|
||||
*/
|
||||
fun onAddPageError(error: Throwable) {
|
||||
Timber.e(error)
|
||||
val adapter = adapter ?: return
|
||||
adapter.onLoadMoreComplete(null)
|
||||
hideProgressBar()
|
||||
|
||||
snack?.dismiss()
|
||||
|
||||
val message = getErrorMessage(error)
|
||||
val retryAction = View.OnClickListener {
|
||||
// If not the first page, show bottom progress bar.
|
||||
if (adapter.mainItemCount > 0 && progressItem != null) {
|
||||
adapter.addScrollableFooterWithDelay(progressItem!!, 0, true)
|
||||
} else {
|
||||
showProgressBar()
|
||||
}
|
||||
presenter.requestNext()
|
||||
}
|
||||
|
||||
if (adapter.isEmpty) {
|
||||
val actions = if (presenter.source is LocalAnimeSource) {
|
||||
listOf(
|
||||
EmptyView.Action(R.string.local_source_help_guide, R.drawable.ic_help_24dp) { openLocalSourceHelpGuide() }
|
||||
)
|
||||
} else {
|
||||
listOf(
|
||||
EmptyView.Action(R.string.action_retry, R.drawable.ic_refresh_24dp, retryAction),
|
||||
EmptyView.Action(R.string.action_open_in_web_view, R.drawable.ic_public_24dp) { openInWebView() },
|
||||
EmptyView.Action(R.string.label_help, R.drawable.ic_help_24dp) { activity?.openInBrowser(MoreController.URL_HELP) }
|
||||
)
|
||||
}
|
||||
|
||||
binding.emptyView.show(message, actions)
|
||||
} else {
|
||||
snack = (activity as? MainActivity)?.binding?.rootCoordinator?.snack(message, Snackbar.LENGTH_INDEFINITE) {
|
||||
setAction(R.string.action_retry, retryAction)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun getErrorMessage(error: Throwable): String {
|
||||
if (error is NoResultsException) {
|
||||
return binding.catalogueView.context.getString(R.string.no_results_found)
|
||||
}
|
||||
|
||||
return when {
|
||||
error.message == null -> ""
|
||||
error.message!!.startsWith("HTTP error") -> "${error.message}: ${binding.catalogueView.context.getString(R.string.http_error_hint)}"
|
||||
else -> error.message!!
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new progress item and reenables the scroll listener.
|
||||
*/
|
||||
private fun resetProgressItem() {
|
||||
progressItem = ProgressItem()
|
||||
adapter?.endlessTargetCount = 0
|
||||
adapter?.setEndlessScrollListener(this, progressItem!!)
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the adapter when scrolled near the bottom.
|
||||
*/
|
||||
override fun onLoadMore(lastPosition: Int, currentPage: Int) {
|
||||
if (presenter.hasNextPage()) {
|
||||
presenter.requestNext()
|
||||
} else {
|
||||
adapter?.onLoadMoreComplete(null)
|
||||
adapter?.endlessTargetCount = 1
|
||||
}
|
||||
}
|
||||
|
||||
override fun noMoreLoad(newItemsSize: Int) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the presenter when a anime is initialized.
|
||||
*
|
||||
* @param anime the anime initialized
|
||||
*/
|
||||
fun onAnimeInitialized(anime: Anime) {
|
||||
getHolder(anime)?.setImage(anime)
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the current display mode.
|
||||
*
|
||||
* @param mode the mode to change to
|
||||
*/
|
||||
private fun setDisplayMode(mode: DisplayMode) {
|
||||
val view = view ?: return
|
||||
val adapter = adapter ?: return
|
||||
|
||||
preferences.sourceDisplayMode().set(mode)
|
||||
activity?.invalidateOptionsMenu()
|
||||
setupRecycler(view)
|
||||
|
||||
// Initialize animes if not on a metered connection
|
||||
if (!view.context.connectivityManager.isActiveNetworkMetered) {
|
||||
val animes = (0 until adapter.itemCount).mapNotNull {
|
||||
(adapter.getItem(it) as? AnimeSourceItem)?.anime
|
||||
}
|
||||
presenter.initializeAnimes(animes)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a preference for the number of anime per row based on the current orientation.
|
||||
*
|
||||
* @return the preference.
|
||||
*/
|
||||
private fun getColumnsPreferenceForCurrentOrientation(): Preference<Int> {
|
||||
return if (resources?.configuration?.orientation == Configuration.ORIENTATION_PORTRAIT) {
|
||||
preferences.portraitColumns()
|
||||
} else {
|
||||
preferences.landscapeColumns()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view holder for the given anime.
|
||||
*
|
||||
* @param anime the anime to find.
|
||||
* @return the holder of the anime or null if it's not bound.
|
||||
*/
|
||||
private fun getHolder(anime: Anime): AnimeSourceHolder<*>? {
|
||||
val adapter = adapter ?: return null
|
||||
|
||||
adapter.allBoundViewHolders.forEach { holder ->
|
||||
val item = adapter.getItem(holder.bindingAdapterPosition) as? AnimeSourceItem
|
||||
if (item != null && item.anime.id!! == anime.id!!) {
|
||||
return holder as AnimeSourceHolder<*>
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the progress bar.
|
||||
*/
|
||||
private fun showProgressBar() {
|
||||
binding.emptyView.hide()
|
||||
binding.progress.isVisible = true
|
||||
snack?.dismiss()
|
||||
snack = null
|
||||
}
|
||||
|
||||
/**
|
||||
* Hides active progress bars.
|
||||
*/
|
||||
private fun hideProgressBar() {
|
||||
binding.emptyView.hide()
|
||||
binding.progress.isVisible = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a anime is clicked.
|
||||
*
|
||||
* @param position the position of the element clicked.
|
||||
* @return true if the item should be selected, false otherwise.
|
||||
*/
|
||||
override fun onItemClick(view: View, position: Int): Boolean {
|
||||
val item = adapter?.getItem(position) as? AnimeSourceItem ?: return false
|
||||
router.pushController(AnimeController(item.anime, true).withFadeTransaction())
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a anime is long clicked.
|
||||
*
|
||||
* Adds the anime to the default category if none is set it shows a list of categories for the user to put the anime
|
||||
* in, the list consists of the default category plus the user's categories. The default category is preselected on
|
||||
* new anime, and on already favorited anime the anime's categories are preselected.
|
||||
*
|
||||
* @param position the position of the element clicked.
|
||||
*/
|
||||
override fun onItemLongClick(position: Int) {
|
||||
val activity = activity ?: return
|
||||
val anime = (adapter?.getItem(position) as? AnimeSourceItem?)?.anime ?: return
|
||||
|
||||
if (anime.favorite) {
|
||||
MaterialDialog(activity)
|
||||
.listItems(
|
||||
items = listOf(activity.getString(R.string.remove_from_library)),
|
||||
waitForPositiveButton = false
|
||||
) { _, which, _ ->
|
||||
when (which) {
|
||||
0 -> {
|
||||
presenter.changeAnimeFavorite(anime)
|
||||
adapter?.notifyItemChanged(position)
|
||||
activity.toast(activity.getString(R.string.manga_removed_library))
|
||||
}
|
||||
}
|
||||
}
|
||||
.show()
|
||||
} else {
|
||||
val categories = presenter.getCategories()
|
||||
val defaultCategoryId = preferences.defaultCategory()
|
||||
val defaultCategory = categories.find { it.id == defaultCategoryId }
|
||||
|
||||
when {
|
||||
// Default category set
|
||||
defaultCategory != null -> {
|
||||
presenter.moveAnimeToCategory(anime, defaultCategory)
|
||||
|
||||
presenter.changeAnimeFavorite(anime)
|
||||
adapter?.notifyItemChanged(position)
|
||||
activity.toast(activity.getString(R.string.manga_added_library))
|
||||
}
|
||||
|
||||
// Automatic 'Default' or no categories
|
||||
defaultCategoryId == 0 || categories.isEmpty() -> {
|
||||
presenter.moveAnimeToCategory(anime, null)
|
||||
|
||||
presenter.changeAnimeFavorite(anime)
|
||||
adapter?.notifyItemChanged(position)
|
||||
activity.toast(activity.getString(R.string.manga_added_library))
|
||||
}
|
||||
|
||||
// Choose a category
|
||||
else -> {
|
||||
val ids = presenter.getAnimeCategoryIds(anime)
|
||||
val preselected = ids.mapNotNull { id ->
|
||||
categories.indexOfFirst { it.id == id }.takeIf { it != -1 }
|
||||
}.toTypedArray()
|
||||
|
||||
ChangeAnimeCategoriesDialog(this, listOf(anime), categories, preselected)
|
||||
.showDialog(router)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update anime to use selected categories.
|
||||
*
|
||||
* @param animes The list of anime to move to categories.
|
||||
* @param categories The list of categories where anime will be placed.
|
||||
*/
|
||||
override fun updateCategoriesForAnimes(animes: List<Anime>, categories: List<Category>) {
|
||||
val anime = animes.firstOrNull() ?: return
|
||||
|
||||
presenter.changeAnimeFavorite(anime)
|
||||
presenter.updateAnimeCategories(anime, categories)
|
||||
|
||||
val position = adapter?.currentItems?.indexOfFirst { it -> (it as AnimeSourceItem).anime.id == anime.id }
|
||||
if (position != null) {
|
||||
adapter?.notifyItemChanged(position)
|
||||
}
|
||||
activity?.toast(activity?.getString(R.string.manga_added_library))
|
||||
}
|
||||
|
||||
protected companion object {
|
||||
const val SOURCE_ID_KEY = "sourceId"
|
||||
const val SEARCH_QUERY_KEY = "searchQuery"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
package eu.kanade.tachiyomi.ui.browse.source.browse
|
||||
|
||||
import android.os.Bundle
|
||||
import eu.davidea.flexibleadapter.items.IFlexible
|
||||
import eu.kanade.tachiyomi.data.cache.AnimeCoverCache
|
||||
import eu.kanade.tachiyomi.data.database.AnimeDatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Anime
|
||||
import eu.kanade.tachiyomi.data.database.models.AnimeCategory
|
||||
import eu.kanade.tachiyomi.data.database.models.Category
|
||||
import eu.kanade.tachiyomi.data.database.models.toAnimeInfo
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.AnimeCatalogueSource
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.SAnime
|
||||
import eu.kanade.tachiyomi.source.model.toSAnime
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.CheckboxSectionItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.GroupItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.HeaderItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.SelectItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.SelectSectionItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.SeparatorItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.SortGroup
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.SortItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.TextItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.TextSectionItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
|
||||
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
|
||||
import eu.kanade.tachiyomi.util.episode.EpisodeSettingsHelper
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.removeCovers
|
||||
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 rx.Observable
|
||||
import rx.Subscription
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.util.Date
|
||||
|
||||
/**
|
||||
* Presenter of [BrowseSourceController].
|
||||
*/
|
||||
open class BrowseAnimeSourcePresenter(
|
||||
private val sourceId: Long,
|
||||
searchQuery: String? = null,
|
||||
private val sourceManager: SourceManager = Injekt.get(),
|
||||
private val db: AnimeDatabaseHelper = Injekt.get(),
|
||||
private val prefs: PreferencesHelper = Injekt.get(),
|
||||
private val coverCache: AnimeCoverCache = Injekt.get()
|
||||
) : BasePresenter<BrowseAnimeSourceController>() {
|
||||
|
||||
/**
|
||||
* Selected source.
|
||||
*/
|
||||
lateinit var source: AnimeCatalogueSource
|
||||
|
||||
/**
|
||||
* Modifiable list of filters.
|
||||
*/
|
||||
var sourceFilters = FilterList()
|
||||
set(value) {
|
||||
field = value
|
||||
filterItems = value.toItems()
|
||||
}
|
||||
|
||||
var filterItems: List<IFlexible<*>> = emptyList()
|
||||
|
||||
/**
|
||||
* List of filters used by the [Pager]. If empty alongside [query], the popular query is used.
|
||||
*/
|
||||
var appliedFilters = FilterList()
|
||||
|
||||
/**
|
||||
* Pager containing a list of anime results.
|
||||
*/
|
||||
private lateinit var pager: AnimePager
|
||||
|
||||
/**
|
||||
* Flow of anime list to initialize.
|
||||
*/
|
||||
private val animeDetailsFlow = MutableStateFlow<List<Anime>>(emptyList())
|
||||
|
||||
/**
|
||||
* Subscription for the pager.
|
||||
*/
|
||||
private var pagerSubscription: Subscription? = null
|
||||
|
||||
/**
|
||||
* Subscription for one request from the pager.
|
||||
*/
|
||||
private var pageSubscription: Subscription? = null
|
||||
|
||||
init {
|
||||
query = searchQuery ?: ""
|
||||
}
|
||||
|
||||
override fun onCreate(savedState: Bundle?) {
|
||||
super.onCreate(savedState)
|
||||
|
||||
source = sourceManager.get(sourceId) as? AnimeCatalogueSource ?: return
|
||||
|
||||
sourceFilters = source.getFilterList()
|
||||
|
||||
if (savedState != null) {
|
||||
query = savedState.getString(::query.name, "")
|
||||
}
|
||||
|
||||
restartPager()
|
||||
}
|
||||
|
||||
override fun onSave(state: Bundle) {
|
||||
state.putString(::query.name, query)
|
||||
super.onSave(state)
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts the pager for the active source with the provided query and filters.
|
||||
*
|
||||
* @param query the query.
|
||||
* @param filters the current state of the filters (for search mode).
|
||||
*/
|
||||
fun restartPager(query: String = this.query, filters: FilterList = this.appliedFilters) {
|
||||
this.query = query
|
||||
this.appliedFilters = filters
|
||||
|
||||
// Create a new pager.
|
||||
pager = createPager(query, filters)
|
||||
|
||||
val sourceId = source.id
|
||||
|
||||
val sourceDisplayMode = prefs.sourceDisplayMode()
|
||||
|
||||
// Prepare the pager.
|
||||
pagerSubscription?.let { remove(it) }
|
||||
pagerSubscription = pager.results()
|
||||
.observeOn(Schedulers.io())
|
||||
.map { (first, second) -> first to second.map { networkToLocalAnime(it, sourceId) } }
|
||||
.doOnNext { initializeAnimes(it.second) }
|
||||
.map { (first, second) -> first to second.map { AnimeSourceItem(it, sourceDisplayMode) } }
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribeReplay(
|
||||
{ view, (page, animes) ->
|
||||
view.onAddPage(page, animes)
|
||||
},
|
||||
{ _, error ->
|
||||
Timber.e(error)
|
||||
}
|
||||
)
|
||||
|
||||
// Request first page.
|
||||
requestNext()
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests the next page for the active pager.
|
||||
*/
|
||||
fun requestNext() {
|
||||
if (!hasNextPage()) return
|
||||
|
||||
pageSubscription?.let { remove(it) }
|
||||
pageSubscription = Observable.defer { pager.requestNext() }
|
||||
.subscribeFirst(
|
||||
{ _, _ ->
|
||||
// Nothing to do when onNext is emitted.
|
||||
},
|
||||
BrowseAnimeSourceController::onAddPageError
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the last fetched page has a next page.
|
||||
*/
|
||||
fun hasNextPage(): Boolean {
|
||||
return pager.hasNextPage
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a anime from the database for the given anime from network. It creates a new entry
|
||||
* if the anime is not yet in the database.
|
||||
*
|
||||
* @param sAnime the anime from the source.
|
||||
* @return a anime from the database.
|
||||
*/
|
||||
private fun networkToLocalAnime(sAnime: SAnime, sourceId: Long): Anime {
|
||||
var localAnime = db.getAnime(sAnime.url, sourceId).executeAsBlocking()
|
||||
if (localAnime == null) {
|
||||
val newAnime = Anime.create(sAnime.url, sAnime.title, sourceId)
|
||||
newAnime.copyFrom(sAnime)
|
||||
val result = db.insertAnime(newAnime).executeAsBlocking()
|
||||
newAnime.id = result.insertedId()
|
||||
localAnime = newAnime
|
||||
}
|
||||
return localAnime
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a list of anime.
|
||||
*
|
||||
* @param animes the list of anime to initialize.
|
||||
*/
|
||||
fun initializeAnimes(animes: List<Anime>) {
|
||||
presenterScope.launchIO {
|
||||
animes.asFlow()
|
||||
.filter { it.thumbnail_url == null && !it.initialized }
|
||||
.map { getAnimeDetails(it) }
|
||||
.onEach {
|
||||
withUIContext {
|
||||
@Suppress("DEPRECATION")
|
||||
view?.onAnimeInitialized(it)
|
||||
}
|
||||
}
|
||||
.catch { e -> Timber.e(e) }
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialized anime.
|
||||
*
|
||||
* @param anime the anime to initialize.
|
||||
* @return the initialized anime
|
||||
*/
|
||||
private suspend fun getAnimeDetails(anime: Anime): Anime {
|
||||
try {
|
||||
val networkAnime = source.getAnimeDetails(anime.toAnimeInfo())
|
||||
anime.copyFrom(networkAnime.toSAnime())
|
||||
anime.initialized = true
|
||||
db.insertAnime(anime).executeAsBlocking()
|
||||
} catch (e: Exception) {
|
||||
Timber.e(e)
|
||||
}
|
||||
return anime
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or removes a anime from the library.
|
||||
*
|
||||
* @param anime the anime to update.
|
||||
*/
|
||||
fun changeAnimeFavorite(anime: Anime) {
|
||||
anime.favorite = !anime.favorite
|
||||
anime.date_added = when (anime.favorite) {
|
||||
true -> Date().time
|
||||
false -> 0
|
||||
}
|
||||
|
||||
if (!anime.favorite) {
|
||||
anime.removeCovers(coverCache)
|
||||
} else {
|
||||
EpisodeSettingsHelper.applySettingDefaults(anime)
|
||||
}
|
||||
|
||||
db.insertAnime(anime).executeAsBlocking()
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the filter states for the current source.
|
||||
*
|
||||
* @param filters a list of active filters.
|
||||
*/
|
||||
fun setSourceFilter(filters: FilterList) {
|
||||
restartPager(filters = filters)
|
||||
}
|
||||
|
||||
open fun createPager(query: String, filters: FilterList): AnimePager {
|
||||
return AnimeSourcePager(source, query, filters)
|
||||
}
|
||||
|
||||
private fun FilterList.toItems(): List<IFlexible<*>> {
|
||||
return mapNotNull { filter ->
|
||||
when (filter) {
|
||||
is Filter.Header -> HeaderItem(filter)
|
||||
is Filter.Separator -> SeparatorItem(filter)
|
||||
is Filter.CheckBox -> CheckboxItem(filter)
|
||||
is Filter.TriState -> TriStateItem(filter)
|
||||
is Filter.Text -> TextItem(filter)
|
||||
is Filter.Select<*> -> SelectItem(filter)
|
||||
is Filter.Group<*> -> {
|
||||
val group = GroupItem(filter)
|
||||
val subItems = filter.state.mapNotNull {
|
||||
when (it) {
|
||||
is Filter.CheckBox -> CheckboxSectionItem(it)
|
||||
is Filter.TriState -> TriStateSectionItem(it)
|
||||
is Filter.Text -> TextSectionItem(it)
|
||||
is Filter.Select<*> -> SelectSectionItem(it)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
subItems.forEach { it.header = group }
|
||||
group.subItems = subItems
|
||||
group
|
||||
}
|
||||
is Filter.Sort -> {
|
||||
val group = SortGroup(filter)
|
||||
val subItems = filter.values.map {
|
||||
SortItem(it, group)
|
||||
}
|
||||
group.subItems = subItems
|
||||
group
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user categories.
|
||||
*
|
||||
* @return List of categories, not including the default category
|
||||
*/
|
||||
fun getCategories(): List<Category> {
|
||||
return db.getCategories().executeAsBlocking()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the category id's the anime is in, if the anime is not in a category, returns the default id.
|
||||
*
|
||||
* @param anime the anime to get categories from.
|
||||
* @return Array of category ids the anime is in, if none returns default id
|
||||
*/
|
||||
fun getAnimeCategoryIds(anime: Anime): Array<Int?> {
|
||||
val categories = db.getCategoriesForAnime(anime).executeAsBlocking()
|
||||
return categories.mapNotNull { it.id }.toTypedArray()
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the given anime to categories.
|
||||
*
|
||||
* @param categories the selected categories.
|
||||
* @param anime the anime to move.
|
||||
*/
|
||||
private fun moveAnimeToCategories(anime: Anime, categories: List<Category>) {
|
||||
val mc = categories.filter { it.id != 0 }.map { AnimeCategory.create(anime, it) }
|
||||
db.setAnimeCategories(mc, listOf(anime))
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the given anime to the category.
|
||||
*
|
||||
* @param category the selected category.
|
||||
* @param anime the anime to move.
|
||||
*/
|
||||
fun moveAnimeToCategory(anime: Anime, category: Category?) {
|
||||
moveAnimeToCategories(anime, listOfNotNull(category))
|
||||
}
|
||||
|
||||
/**
|
||||
* Update anime to use selected categories.
|
||||
*
|
||||
* @param anime needed to change
|
||||
* @param selectedCategories selected categories
|
||||
*/
|
||||
fun updateAnimeCategories(anime: Anime, selectedCategories: List<Category>) {
|
||||
if (!anime.favorite) {
|
||||
changeAnimeFavorite(anime)
|
||||
}
|
||||
|
||||
moveAnimeToCategories(anime, selectedCategories)
|
||||
}
|
||||
}
|
|
@ -124,10 +124,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
|||
return BrowseSourcePresenter(args.getLong(SOURCE_ID_KEY), args.getString(SEARCH_QUERY_KEY))
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = SourceControllerBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = SourceControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
@ -269,6 +266,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
|||
if (router.backstackSize >= 2 && router.backstack[router.backstackSize - 2].controller() is GlobalSearchController) {
|
||||
router.popController(this)
|
||||
} else {
|
||||
nonSubmittedQuery = ""
|
||||
searchWithQuery("")
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -50,22 +49,7 @@ open class GlobalSearchController(
|
|||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the view with [R.layout.global_search_controller].
|
||||
*
|
||||
* @param inflater used to load the layout xml.
|
||||
* @param container containing parent views.
|
||||
* @return inflated view
|
||||
*/
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = GlobalSearchControllerBinding.inflate(inflater)
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = GlobalSearchControllerBinding.inflate(inflater)
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return presenter.query
|
||||
|
@ -142,6 +126,12 @@ open class GlobalSearchController(
|
|||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
|
||||
adapter = GlobalSearchAdapter(this)
|
||||
|
||||
// Create recycler and set adapter.
|
||||
|
|
|
@ -4,7 +4,6 @@ import android.view.LayoutInflater
|
|||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -68,21 +67,7 @@ class CategoryController :
|
|||
return resources?.getString(R.string.action_edit_categories)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view of this controller.
|
||||
*
|
||||
* @param inflater The layout inflater to create the view from XML.
|
||||
* @param container The parent view for this one.
|
||||
*/
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = CategoriesControllerBinding.inflate(inflater)
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = CategoriesControllerBinding.inflate(inflater)
|
||||
|
||||
/**
|
||||
* Called after view inflation. Used to initialize the view.
|
||||
|
@ -92,6 +77,12 @@ class CategoryController :
|
|||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
|
||||
adapter = CategoryAdapter(this@CategoryController)
|
||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
binding.recycler.setHasFixedSize(true)
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
|
@ -55,15 +54,7 @@ class DownloadController :
|
|||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = DownloadControllerBinding.inflate(inflater)
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = DownloadControllerBinding.inflate(inflater)
|
||||
|
||||
override fun createPresenter(): DownloadPresenter {
|
||||
return DownloadPresenter()
|
||||
|
@ -76,6 +67,12 @@ class DownloadController :
|
|||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
|
||||
// Check if download queue is empty and update information accordingly.
|
||||
setInformationView()
|
||||
|
||||
|
|
|
@ -131,6 +131,15 @@ class MainActivity : BaseViewBindingActivity<MainActivityBinding>() {
|
|||
tabAnimator = ViewHeightAnimator(binding.tabs, 0L)
|
||||
bottomNavAnimator = ViewHeightAnimator(binding.bottomNav)
|
||||
|
||||
// If bottom nav is hidden, make it visible again when the app bar is expanded
|
||||
binding.appbar.addOnOffsetChangedListener(
|
||||
AppBarLayout.OnOffsetChangedListener { _, verticalOffset ->
|
||||
if (verticalOffset == 0) {
|
||||
showBottomNav(true)
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Set behavior of bottom nav
|
||||
preferences.hideBottomBar()
|
||||
.asImmediateFlow { setBottomNavBehaviorOnScroll() }
|
||||
|
|
|
@ -11,7 +11,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.core.graphics.blue
|
||||
|
@ -199,8 +198,11 @@ class MangaController :
|
|||
)
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = MangaControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = MangaControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
|
@ -211,11 +213,6 @@ class MangaController :
|
|||
margin(bottom = true)
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
if (manga == null || source == null) return
|
||||
|
||||
|
@ -1007,11 +1004,17 @@ class MangaController :
|
|||
|
||||
// OVERFLOW MENU DIALOGS
|
||||
|
||||
private fun getUnreadChaptersSorted() = presenter.chapters
|
||||
.sortedWith(presenter.getChapterSort())
|
||||
.filter { !it.read && it.status == Download.State.NOT_DOWNLOADED }
|
||||
.distinctBy { it.name }
|
||||
.reversed()
|
||||
private fun getUnreadChaptersSorted(): List<ChapterItem> {
|
||||
val chapters = presenter.chapters
|
||||
.sortedWith(presenter.getChapterSort())
|
||||
.filter { !it.read && it.status == Download.State.NOT_DOWNLOADED }
|
||||
.distinctBy { it.name }
|
||||
return if (presenter.sortDescending()) {
|
||||
chapters.reversed()
|
||||
} else {
|
||||
chapters
|
||||
}
|
||||
}
|
||||
|
||||
private fun downloadChapters(choice: Int) {
|
||||
val chaptersToDownload = when (choice) {
|
||||
|
|
|
@ -474,7 +474,12 @@ class MangaPresenter(
|
|||
* Returns the next unread chapter or null if everything is read.
|
||||
*/
|
||||
fun getNextUnreadChapter(): ChapterItem? {
|
||||
return chapters.sortedWith(getChapterSort()).findLast { !it.read }
|
||||
val chapters = chapters.sortedWith(getChapterSort())
|
||||
return if (sortDescending()) {
|
||||
return chapters.findLast { !it.read }
|
||||
} else {
|
||||
chapters.find { !it.read }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -78,15 +78,6 @@ class AboutController : SettingsController() {
|
|||
openInBrowser(url)
|
||||
}
|
||||
}
|
||||
if (BuildConfig.DEBUG) {
|
||||
preference {
|
||||
key = "pref_about_notices"
|
||||
titleRes = R.string.notices
|
||||
onClick {
|
||||
openInBrowser("https://github.com/tachiyomiorg/tachiyomi/blob/master/PREVIEW_RELEASE_NOTES.md")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
preference {
|
||||
|
@ -97,6 +88,14 @@ class AboutController : SettingsController() {
|
|||
onClick { openInBrowser(it) }
|
||||
}
|
||||
}
|
||||
preference {
|
||||
key = "pref_about_facebook"
|
||||
title = "Facebook"
|
||||
"https://facebook.com/tachiyomiorg".also {
|
||||
summary = it
|
||||
onClick { openInBrowser(it) }
|
||||
}
|
||||
}
|
||||
preference {
|
||||
key = "pref_about_twitter"
|
||||
title = "Twitter"
|
||||
|
@ -116,15 +115,7 @@ class AboutController : SettingsController() {
|
|||
preference {
|
||||
key = "pref_about_github"
|
||||
title = "GitHub"
|
||||
"https://github.com/tachiyomiorg/tachiyomi".also {
|
||||
summary = it
|
||||
onClick { openInBrowser(it) }
|
||||
}
|
||||
}
|
||||
preference {
|
||||
key = "pref_about_label_extensions"
|
||||
titleRes = R.string.label_extensions
|
||||
"https://github.com/tachiyomiorg/tachiyomi-extensions".also {
|
||||
"https://github.com/tachiyomiorg".also {
|
||||
summary = it
|
||||
onClick { openInBrowser(it) }
|
||||
}
|
||||
|
|
|
@ -85,8 +85,7 @@ class HttpPageLoader(
|
|||
* the local cache, otherwise fallbacks to network.
|
||||
*/
|
||||
override fun getPages(): Observable<List<ReaderPage>> {
|
||||
return chapterCache
|
||||
.getPageListFromCache(chapter.chapter)
|
||||
return Observable.fromCallable { chapterCache.getPageListFromCache(chapter.chapter) }
|
||||
.onErrorResumeNext { source.fetchPageList(chapter.chapter) }
|
||||
.map { pages ->
|
||||
pages.mapIndexed { index, page ->
|
||||
|
|
|
@ -7,7 +7,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
|
@ -72,18 +71,16 @@ class HistoryController :
|
|||
return HistoryPresenter()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = HistoryControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = HistoryControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
|
||||
// Initialize adapter
|
||||
binding.recycler.layoutManager = LinearLayoutManager(view.context)
|
||||
|
|
|
@ -5,7 +5,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.appcompat.view.ActionMode
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
|
@ -69,8 +68,10 @@ class UpdatesController :
|
|||
return UpdatesPresenter()
|
||||
}
|
||||
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = UpdatesControllerBinding.inflate(inflater)
|
||||
override fun createBinding(inflater: LayoutInflater) = UpdatesControllerBinding.inflate(inflater)
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
binding.recycler.applyInsetter {
|
||||
type(navigationBars = true) {
|
||||
padding()
|
||||
|
@ -81,11 +82,7 @@ class UpdatesController :
|
|||
margin(bottom = true)
|
||||
}
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View) {
|
||||
super.onViewCreated(view)
|
||||
view.context.notificationManager.cancel(Notifications.ID_NEW_CHAPTERS)
|
||||
|
||||
// Init RecyclerView and adapter
|
||||
|
|
|
@ -1,22 +1,19 @@
|
|||
package eu.kanade.tachiyomi.ui.security
|
||||
|
||||
import android.os.Bundle
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.base.activity.BaseThemedActivity
|
||||
import eu.kanade.tachiyomi.util.system.BiometricUtil
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.Date
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
/**
|
||||
* Blank activity with a BiometricPrompt.
|
||||
*/
|
||||
class BiometricUnlockActivity : AppCompatActivity() {
|
||||
class BiometricUnlockActivity : BaseThemedActivity() {
|
||||
|
||||
private val preferences: PreferencesHelper by injectLazy()
|
||||
private val executor = Executors.newSingleThreadExecutor()
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
|
|
@ -20,6 +20,8 @@ import eu.kanade.tachiyomi.network.PREF_DOH_CLOUDFLARE
|
|||
import eu.kanade.tachiyomi.network.PREF_DOH_GOOGLE
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||
import eu.kanade.tachiyomi.util.preference.intListPreference
|
||||
import eu.kanade.tachiyomi.util.preference.onChange
|
||||
|
@ -31,9 +33,6 @@ import eu.kanade.tachiyomi.util.preference.switchPreference
|
|||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.powerManager
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import rx.Observable
|
||||
import rx.android.schedulers.AndroidSchedulers
|
||||
import rx.schedulers.Schedulers
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys
|
||||
|
||||
|
@ -171,27 +170,18 @@ class SettingsAdvancedController : SettingsController() {
|
|||
|
||||
private fun clearChapterCache() {
|
||||
if (activity == null) return
|
||||
val files = chapterCache.cacheDir.listFiles() ?: return
|
||||
|
||||
var deletedFiles = 0
|
||||
|
||||
Observable.defer { Observable.from(files) }
|
||||
.doOnNext { file ->
|
||||
if (chapterCache.removeFileFromCache(file.name)) {
|
||||
deletedFiles++
|
||||
launchIO {
|
||||
try {
|
||||
val deletedFiles = chapterCache.clear()
|
||||
withUIContext {
|
||||
activity?.toast(resources?.getString(R.string.cache_deleted, deletedFiles))
|
||||
findPreference(CLEAR_CACHE_KEY)?.summary =
|
||||
resources?.getString(R.string.used_cache, chapterCache.readableSize)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
withUIContext { activity?.toast(R.string.cache_delete_error) }
|
||||
}
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.doOnError {
|
||||
activity?.toast(R.string.cache_delete_error)
|
||||
}
|
||||
.doOnCompleted {
|
||||
activity?.toast(resources?.getString(R.string.cache_deleted, deletedFiles))
|
||||
findPreference(CLEAR_CACHE_KEY)?.summary =
|
||||
resources?.getString(R.string.used_cache, chapterCache.readableSize)
|
||||
}
|
||||
.subscribe()
|
||||
}
|
||||
}
|
||||
|
||||
class ClearDatabaseDialogController : DialogController() {
|
||||
|
|
|
@ -32,6 +32,7 @@ abstract class SettingsController : PreferenceController() {
|
|||
var preferenceKey: String? = null
|
||||
val preferences: PreferencesHelper = Injekt.get()
|
||||
val viewScope = MainScope()
|
||||
private var themedContext: Context? = null
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup, savedInstanceState: Bundle?): View {
|
||||
val view = super.onCreateView(inflater, container, savedInstanceState)
|
||||
|
@ -76,20 +77,23 @@ abstract class SettingsController : PreferenceController() {
|
|||
super.onChangeStarted(handler, type)
|
||||
}
|
||||
|
||||
override fun onDestroyView(view: View) {
|
||||
super.onDestroyView(view)
|
||||
themedContext = null
|
||||
}
|
||||
|
||||
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
|
||||
val screen = preferenceManager.createPreferenceScreen(getThemedContext())
|
||||
val tv = TypedValue()
|
||||
activity!!.theme.resolveAttribute(R.attr.preferenceTheme, tv, true)
|
||||
themedContext = ContextThemeWrapper(activity, tv.resourceId)
|
||||
|
||||
val screen = preferenceManager.createPreferenceScreen(themedContext)
|
||||
preferenceScreen = screen
|
||||
setupPreferenceScreen(screen)
|
||||
}
|
||||
|
||||
abstract fun setupPreferenceScreen(screen: PreferenceScreen): PreferenceScreen
|
||||
|
||||
private fun getThemedContext(): Context {
|
||||
val tv = TypedValue()
|
||||
activity!!.theme.resolveAttribute(R.attr.preferenceTheme, tv, true)
|
||||
return ContextThemeWrapper(activity, tv.resourceId)
|
||||
}
|
||||
|
||||
private fun animatePreferenceHighlight(view: View) {
|
||||
ValueAnimator
|
||||
.ofObject(ArgbEvaluator(), Color.TRANSPARENT, view.context.getResourceColor(R.attr.rippleColor))
|
||||
|
|
|
@ -6,7 +6,6 @@ import android.view.Menu
|
|||
import android.view.MenuInflater
|
||||
import android.view.MenuItem
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.appcompat.widget.SearchView
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import eu.kanade.tachiyomi.R
|
||||
|
@ -33,17 +32,7 @@ class SettingsSearchController :
|
|||
setHasOptionsMenu(true)
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiate the view with [R.layout.settings_search_controller].
|
||||
*
|
||||
* @param inflater used to load the layout xml.
|
||||
* @param container containing parent views.
|
||||
* @return inflated view
|
||||
*/
|
||||
override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View {
|
||||
binding = SettingsSearchControllerBinding.inflate(inflater)
|
||||
return binding.root
|
||||
}
|
||||
override fun createBinding(inflater: LayoutInflater) = SettingsSearchControllerBinding.inflate(inflater)
|
||||
|
||||
override fun getTitle(): String? {
|
||||
return presenter.query
|
||||
|
|
38
app/src/main/res/layout/anime_source_controller.xml
Normal file
38
app/src/main/res/layout/anime_source_controller.xml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/catalogue_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".ui.browse.source.browse.BrowseSourceController">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/progress"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible">
|
||||
|
||||
<com.google.android.material.progressindicator.CircularProgressIndicator
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:indeterminate="true" />
|
||||
|
||||
</FrameLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<eu.kanade.tachiyomi.widget.EmptyView
|
||||
android:id="@+id/empty_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:visibility="gone" />
|
||||
|
||||
</FrameLayout>
|
14
app/src/main/res/layout/animelib_grid_recycler.xml
Normal file
14
app/src/main/res/layout/animelib_grid_recycler.xml
Normal file
|
@ -0,0 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eu.kanade.tachiyomi.widget.AutofitRecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/animelib_grid"
|
||||
style="@style/Theme.Widget.GridView.Source"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:columnWidth="140dp"
|
||||
android:paddingStart="5dp"
|
||||
android:paddingTop="5dp"
|
||||
android:paddingEnd="5dp"
|
||||
android:paddingBottom="@dimen/action_toolbar_list_padding"
|
||||
tools:listitem="@layout/source_compact_grid_item" />
|
9
app/src/main/res/layout/animelib_list_recycler.xml
Normal file
9
app/src/main/res/layout/animelib_list_recycler.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.recyclerview.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:id="@+id/animelib_list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipToPadding="false"
|
||||
android:paddingBottom="@dimen/action_toolbar_list_padding"
|
||||
tools:listitem="@layout/source_list_item" />
|
249
app/src/main/res/layout/watcher_color_filter_settings.xml
Normal file
249
app/src/main/res/layout/watcher_color_filter_settings.xml
Normal file
|
@ -0,0 +1,249 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="16dp">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<!-- Color filter -->
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/switch_color_filter"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_custom_color_filter"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- Red filter -->
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_red"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_red_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/switch_color_filter" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_red_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_r_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_red_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_red"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<!-- Green filter -->
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_green"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_green_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_red" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_green_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_g_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_green_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_green"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<!-- Blue filter -->
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_blue"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_blue_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_green" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_blue_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_b_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_blue_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_blue"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<!-- Alpha filter -->
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/seekbar_color_filter_alpha"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:max="255"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_color_filter_alpha_value"
|
||||
app:layout_constraintStart_toEndOf="@id/color_filter_symbols_barrier"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_blue" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_alpha_symbol"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/color_filter_a_value"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_color_filter_alpha_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/seekbar_color_filter_alpha"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/seekbar_color_filter_alpha" />
|
||||
|
||||
<!-- Filter mode -->
|
||||
|
||||
<TextView
|
||||
android:id="@+id/color_filter_mode_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/pref_color_filter_mode"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/color_filter_mode"
|
||||
app:layout_constraintEnd_toStartOf="@id/color_filter_mode"
|
||||
app:layout_constraintStart_toStartOf="parent" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatSpinner
|
||||
android:id="@+id/color_filter_mode"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:entries="@array/color_filter_modes"
|
||||
app:layout_constraintEnd_toStartOf="@id/spinner_end"
|
||||
app:layout_constraintStart_toEndOf="@id/verticalcenter"
|
||||
app:layout_constraintTop_toBottomOf="@id/seekbar_color_filter_alpha" />
|
||||
|
||||
<!-- Brightness -->
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/custom_brightness"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="@string/pref_custom_brightness"
|
||||
app:layout_constraintTop_toBottomOf="@id/color_filter_mode_text" />
|
||||
|
||||
<!-- Brightness value -->
|
||||
|
||||
<eu.kanade.tachiyomi.widget.NegativeSeekBar
|
||||
android:id="@+id/brightness_seekbar"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:padding="@dimen/material_component_text_fields_floating_label_padding_between_label_and_input_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/txt_brightness_seekbar_value"
|
||||
app:layout_constraintStart_toEndOf="@id/txt_brightness_seekbar_icon"
|
||||
app:layout_constraintTop_toBottomOf="@id/custom_brightness"
|
||||
app:max_seek="100"
|
||||
app:min_seek="-75" />
|
||||
|
||||
<androidx.appcompat.widget.AppCompatImageView
|
||||
android:id="@+id/txt_brightness_seekbar_icon"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
android:tint="?attr/colorOnBackground"
|
||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar"
|
||||
app:srcCompat="@drawable/ic_brightness_5_24dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/txt_brightness_seekbar_value"
|
||||
android:layout_width="30dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.Medium.SubHeading"
|
||||
app:layout_constraintBottom_toBottomOf="@id/brightness_seekbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/brightness_seekbar" />
|
||||
|
||||
<androidx.constraintlayout.widget.Barrier
|
||||
android:id="@+id/color_filter_symbols_barrier"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:barrierDirection="end"
|
||||
app:constraint_referenced_ids="txt_color_filter_alpha_symbol,txt_color_filter_blue_symbol,txt_color_filter_red_symbol,txt_color_filter_green_symbol" />
|
||||
|
||||
<androidx.constraintlayout.widget.Guideline
|
||||
android:id="@+id/verticalcenter"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<android.widget.Space
|
||||
android:id="@+id/spinner_end"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintStart_toEndOf="parent"
|
||||
tools:ignore="MissingConstraints" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
94
app/src/main/res/layout/watcher_general_settings.xml
Normal file
94
app/src/main/res/layout/watcher_general_settings.xml
Normal file
|
@ -0,0 +1,94 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<eu.kanade.tachiyomi.widget.MaterialSpinnerView
|
||||
android:id="@+id/rotation_mode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:entries="@array/rotation_type"
|
||||
app:title="@string/pref_rotation_type" />
|
||||
|
||||
<eu.kanade.tachiyomi.widget.MaterialSpinnerView
|
||||
android:id="@+id/background_color"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:entries="@array/reader_themes"
|
||||
app:title="@string/pref_reader_theme" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/show_page_number"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_show_page_number" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/fullscreen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_fullscreen" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/cutout_short"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_cutout_short"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/keepscreen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_keep_screen_on" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/long_tap"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_read_with_long_tap" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/always_show_episode_transition"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_always_show_chapter_transition" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/page_transitions"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
android:text="@string/pref_page_transitions" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
40
app/src/main/res/layout/watcher_reading_mode_settings.xml
Normal file
40
app/src/main/res/layout/watcher_reading_mode_settings.xml
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<eu.kanade.tachiyomi.widget.MaterialSpinnerView
|
||||
android:id="@+id/viewer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:entries="@array/viewers_selector"
|
||||
app:title="@string/pref_category_for_this_series" />
|
||||
|
||||
<!-- Pager preferences -->
|
||||
<include
|
||||
android:id="@+id/pager_prefs_group"
|
||||
layout="@layout/reader_pager_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<!-- Webtoon preferences -->
|
||||
<include
|
||||
android:id="@+id/webtoon_prefs_group"
|
||||
layout="@layout/reader_webtoon_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.core.widget.NestedScrollView>
|
49
app/src/main/res/layout/watcher_transition_view.xml
Normal file
49
app/src/main/res/layout/watcher_transition_view.xml
Normal file
|
@ -0,0 +1,49 @@
|
|||
<?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:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/upper_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:textSize="17.5sp"
|
||||
tools:text="Top" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:scaleType="fitCenter"
|
||||
app:srcCompat="@drawable/ic_warning_white_24dp"
|
||||
app:tint="?attr/colorOnBackground"
|
||||
tools:ignore="ContentDescription" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warning_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
tools:text="Warning" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lower_text"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="17.5sp"
|
||||
tools:text="Bottom" />
|
||||
|
||||
</LinearLayout>
|
40
app/src/main/res/menu/animelib_selection.xml
Normal file
40
app/src/main/res/menu/animelib_selection.xml
Normal file
|
@ -0,0 +1,40 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_move_to_category"
|
||||
android:icon="@drawable/ic_label_24dp"
|
||||
android:title="@string/action_move_category"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_download_unread"
|
||||
android:icon="@drawable/ic_get_app_24dp"
|
||||
android:title="@string/action_download_unread"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_mark_as_read"
|
||||
android:icon="@drawable/ic_done_24dp"
|
||||
android:title="@string/action_mark_as_read"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_mark_as_unread"
|
||||
android:icon="@drawable/ic_done_outline_24dp"
|
||||
android:title="@string/action_mark_as_unread"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
<item
|
||||
android:id="@+id/action_delete"
|
||||
android:icon="@drawable/ic_delete_24dp"
|
||||
android:title="@string/action_delete"
|
||||
app:iconTint="?attr/colorOnPrimary"
|
||||
app:showAsAction="always" />
|
||||
|
||||
</menu>
|
|
@ -630,7 +630,7 @@
|
|||
<string name="action_disable_all">Zakázat vše</string>
|
||||
<string name="action_enable_all">Povolit vše</string>
|
||||
<string name="action_search_settings">Nastavení vyhledávání</string>
|
||||
<string name="action_sort_date_added">Data přidání</string>
|
||||
<string name="action_sort_date_added">Datum přidání</string>
|
||||
<string name="action_sort_last_checked">Naposledy zkontrolováno</string>
|
||||
<string name="action_filter_tracked">Sledováno</string>
|
||||
<string name="confirm_exit">Opětovným stisknutím tlačítka aplikaci opustíte</string>
|
||||
|
@ -668,4 +668,15 @@
|
|||
<string name="pref_category_display">Zobrazení</string>
|
||||
<string name="action_display_show_tabs">Zobrazovat karty kategorií</string>
|
||||
<string name="action_display_unread_badge">Odznáček u nepřečtených</string>
|
||||
<string name="update_check_eol">Tato verze systému Android již není podporována</string>
|
||||
<string name="clipboard_copy_error">Kopírování do schránky se nezdařilo</string>
|
||||
<string name="tracker_not_logged_in">Nejsi přihlášen/a: %1$s</string>
|
||||
<string name="vertical_plus_viewer">Průběžné vertikální</string>
|
||||
<string name="edge_nav">Okraj</string>
|
||||
<string name="pref_read_with_tapping_inverted">Převrátit klepnutí</string>
|
||||
<string name="pref_dual_page_split">Rozdělení na dvě stránky</string>
|
||||
<string name="pref_show_navigation_mode_summary">Ukázat oblast klepnutí když je čtečka otevřená</string>
|
||||
<string name="theme_system">Systém sledování</string>
|
||||
<string name="action_show_errors">Zobrazit chyby</string>
|
||||
<string name="action_sort_chapter_fetch_date">Datum načtení</string>
|
||||
</resources>
|
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_download_new_categories_details">Manga in ausgeschlossenen Kategorien werden nicht heruntergeladen, auch wenn sie in eingeschlossenen Kategorien vorhanden sind.</string>
|
||||
<string name="pref_category_auto_download">Automatisches Herunterladen</string>
|
||||
<string name="pref_library_update_categories_details">Manga in ausgeschlossenen Kategorien werden nicht aktualisiert, auch wenn sie in eingeschlossenen Kategorien vorhanden sind.</string>
|
||||
<string name="action_show_errors">Fehler anzeigen</string>
|
||||
<string name="update_check_eol">Diese Android-Version wird nicht mehr unterstützt</string>
|
||||
<string name="clipboard_copy_error">Kopieren in die Zwischenablage fehlgeschlagen</string>
|
||||
</resources>
|
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_download_new_categories_details">Τα Manga σε εξαιρούμενες κατηγορίες δεν θα ληφθούν ακόμα κι αν ανήκουν και σε κατηγορίες που περιλαμβάνονται.</string>
|
||||
<string name="pref_category_auto_download">Αυτόματη λήψη</string>
|
||||
<string name="pref_library_update_categories_details">Τα manga στις αποκλεισμένες κατηγορίες δεν θα ενημερώνονται ακόμη και αν βρίσκονται επίσης στις συμπεριλαμβανόμενες κατηγορίες.</string>
|
||||
<string name="action_show_errors">Εμφάνιση σφαλμάτων</string>
|
||||
<string name="update_check_eol">Αυτή η έκδοση Android δεν υποστηρίζεται πλέον</string>
|
||||
<string name="clipboard_copy_error">Απέτυχε η αντιγραφή στο πρόχειρο</string>
|
||||
</resources>
|
|
@ -4,15 +4,15 @@
|
|||
<string name="label_recent_manga">Historio</string>
|
||||
<string name="label_recent_updates">Ĝisdatigoj</string>
|
||||
<string name="label_library">Biblioteko</string>
|
||||
<string name="label_download_queue">Elŝutos</string>
|
||||
<string name="label_download_queue">Elŝutoj</string>
|
||||
<string name="label_settings">Agordoj</string>
|
||||
<string name="label_more">Plu</string>
|
||||
<string name="label_more">Pli</string>
|
||||
<string name="name">Nomo</string>
|
||||
<string name="information_no_recent">Neniuj ĝisdatigoj</string>
|
||||
<string name="information_no_downloads">Neniu elŝuto</string>
|
||||
<string name="label_help">Asistado</string>
|
||||
<string name="label_extension_info">Konektprogramaro Informaĵo</string>
|
||||
<string name="label_extensions">Konektoprogramaro</string>
|
||||
<string name="label_extensions">Aldonaĵoj</string>
|
||||
<string name="label_migration">Migri</string>
|
||||
<string name="label_backup">Arĥivo</string>
|
||||
<string name="website">Retejo</string>
|
||||
|
@ -162,4 +162,114 @@
|
|||
<string name="ext_nsfw_short">18+</string>
|
||||
<string name="ext_language_info">Lingvo: %1$s</string>
|
||||
<string name="ext_version_info">Versio: %1$s</string>
|
||||
<string name="nav_zone_next">Sekv\'</string>
|
||||
<string name="nav_zone_prev">Antaŭ\'</string>
|
||||
<string name="browse">Foliumi</string>
|
||||
<string name="manga_chapters_tab">Ĉapitroj</string>
|
||||
<plurals name="manga_num_chapters">
|
||||
<item quantity="one">1 ĉapitro</item>
|
||||
<item quantity="other">%1$s ĉapitroj</item>
|
||||
</plurals>
|
||||
<string name="downloaded_chapters">Elŝutitaj ĉapitroj</string>
|
||||
<string name="in_library">En biblioteko</string>
|
||||
<string name="library_search_hint">Titolo aŭ aŭtoro…</string>
|
||||
<string name="manga_added_library">Aldonita al biblioteko</string>
|
||||
<string name="add_to_library">Aldoni al biblioteko</string>
|
||||
<string name="custom_dir">Propra dosierujo</string>
|
||||
<string name="pref_remove_after_read">Post legi ilin</string>
|
||||
<string name="pref_download_only_over_wifi">Elŝuti nur per Vifio</string>
|
||||
<string name="webtoon_side_padding_25">25%</string>
|
||||
<string name="webtoon_side_padding_20">20%</string>
|
||||
<string name="webtoon_side_padding_15">15%</string>
|
||||
<string name="webtoon_side_padding_10">10%</string>
|
||||
<string name="webtoon_side_padding_0">Neniu</string>
|
||||
<string name="pref_category_reading">Legada</string>
|
||||
<string name="pref_category_reading_mode">Legada reĝimo</string>
|
||||
<string name="color_filter_a_value">Vid</string>
|
||||
<string name="color_filter_b_value">Blu</string>
|
||||
<string name="color_filter_g_value">Verd</string>
|
||||
<string name="color_filter_r_value">Ruĝ</string>
|
||||
<string name="rotation_lock">Ŝlosita</string>
|
||||
<string name="rotation_free">Libera</string>
|
||||
<string name="pref_rotation_type">Orientiĝo</string>
|
||||
<string name="double_tap_anim_speed_fast">Rapida</string>
|
||||
<string name="double_tap_anim_speed_normal">Normala</string>
|
||||
<string name="zoom_start_automatic">Aŭtomate</string>
|
||||
<string name="scale_type_smart_fit">Ŝaĝa adapto</string>
|
||||
<string name="scale_type_fit_height">Adapti al alto</string>
|
||||
<string name="scale_type_fit_width">Adapti al larĝo</string>
|
||||
<string name="vertical_plus_viewer">Seninterrompe vertikale</string>
|
||||
<string name="vertical_viewer">Vertikale</string>
|
||||
<string name="nav_zone_right">Dekstra</string>
|
||||
<string name="nav_zone_left">Maldekstra</string>
|
||||
<string name="right_and_left_nav">Dekstra kaj Maldekstra</string>
|
||||
<string name="l_nav">En formo kiel \"L\"</string>
|
||||
<string name="default_nav">Defaŭlte</string>
|
||||
<string name="default_viewer">Defaŭlte</string>
|
||||
<string name="tapping_inverted_both">Ambaŭ</string>
|
||||
<string name="tapping_inverted_vertical">Vertikala</string>
|
||||
<string name="tapping_inverted_horizontal">Horizontala</string>
|
||||
<string name="tapping_inverted_none">Nenio</string>
|
||||
<string name="pref_reader_navigation">Navigo</string>
|
||||
<string name="pref_skip_read_chapters">Preterpasi ĉapitrojn markitajn kiel legitaj</string>
|
||||
<string name="pref_keep_screen_on">Ne malŝalti ekranon</string>
|
||||
<string name="filter_mode_screen">Ekranado</string>
|
||||
<string name="filter_mode_multiply">Obligado</string>
|
||||
<string name="filter_mode_overlay">Plustavolo</string>
|
||||
<string name="filter_mode_default">Defaŭlta</string>
|
||||
<string name="pref_custom_brightness">Adaptita lumeco</string>
|
||||
<string name="pref_crop_borders">Stuci borderojn</string>
|
||||
<string name="pref_true_color">32-bitaj koloroj</string>
|
||||
<string name="pref_show_reading_mode">Legada reĝimo</string>
|
||||
<string name="pref_show_page_number">Montri numero de paĝo</string>
|
||||
<string name="pref_lock_orientation">Ŝlosi orientiĝon</string>
|
||||
<string name="pref_fullscreen">Plenekrano</string>
|
||||
<string name="obsolete_extension_message">Ĉi tiu aldonaĵo ne estas plu disponebla.</string>
|
||||
<string name="all_lang">Ĉiuj</string>
|
||||
<string name="all">Ĉio</string>
|
||||
<string name="pref_library_update_prioritization">Ĝisdatiga ordigo</string>
|
||||
<string name="update_48hour">Po unu fojon 2 tage</string>
|
||||
<string name="update_12hour">Po unu fojon 12 hore</string>
|
||||
<string name="update_8hour">Po unu fojon 8 hore</string>
|
||||
<string name="update_6hour">Po unu fojon 6 hore</string>
|
||||
<string name="update_4hour">Po unu fojon 4 hore</string>
|
||||
<string name="update_3hour">Po unu fojon 3 hore</string>
|
||||
<string name="update_2hour">Po unu fojon 2 hore</string>
|
||||
<string name="update_1hour">Po unu fojon hore</string>
|
||||
<string name="update_never">Mana</string>
|
||||
<string name="pref_library_update_interval">Ofteco de ĝisdatigoj</string>
|
||||
<string name="pref_category_library_update">Ĝisdatigoj</string>
|
||||
<string name="default_columns">Defaŭlte</string>
|
||||
<string name="landscape">Horizontale</string>
|
||||
<string name="portrait">Vertikale</string>
|
||||
<string name="pref_category_display">Montrado</string>
|
||||
<string name="pref_show_nsfw_extension">Montri en aldonaĵlisto</string>
|
||||
<string name="pref_show_nsfw_source">Montri en fontlisto</string>
|
||||
<string name="pref_category_nsfw_content">MPL/NSFW (18+) fontoj</string>
|
||||
<string name="pref_confirm_exit">Konfirmi eliron</string>
|
||||
<string name="theme_dark_amoled">AMOLED-a nigra</string>
|
||||
<string name="pref_category_locale">Lingvo</string>
|
||||
<string name="pref_category_general">Ĝenerala</string>
|
||||
<string name="app_not_available">Apo maldisponebla</string>
|
||||
<string name="action_restore">Restaŭro</string>
|
||||
<string name="action_show_errors">Montri erarojn</string>
|
||||
<string name="action_reset">Restartigi</string>
|
||||
<string name="action_sort_descending">Malkreskante</string>
|
||||
<string name="action_display_show_number_of_items">Montri nombro de elementoj</string>
|
||||
<string name="action_display_show_tabs">Montri kategoriajn langetojn</string>
|
||||
<string name="action_display_unread_badge">Nelegitajsignoj</string>
|
||||
<string name="action_display_download_badge">Elŝutosignoj</string>
|
||||
<string name="action_display_grid">Kompakta krado</string>
|
||||
<string name="action_display">Montrado</string>
|
||||
<string name="action_display_mode">Montrada reĝimo</string>
|
||||
<string name="action_open_in_web_view">Malfermi per WebView</string>
|
||||
<string name="action_move">Movi</string>
|
||||
<string name="action_resume">Daŭrigi</string>
|
||||
<string name="action_pause">Paŭzigi</string>
|
||||
<string name="action_next_unread">Sekva nelegita</string>
|
||||
<string name="action_sort_down">Ordigi malkreskante</string>
|
||||
<string name="action_sort_up">Ordigi kreskante</string>
|
||||
<string name="action_edit_cover">Redakti kovrilon</string>
|
||||
<string name="action_move_category">Aldoni al kategorioj</string>
|
||||
<string name="action_global_search">Serĉi ĉie</string>
|
||||
</resources>
|
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_download_new_categories_details">Poissuljettuihin kategorioihin kuuluvia mangoja ei ladata, vaikka ne olisivat myös sisällytetyissä kategorioissa.</string>
|
||||
<string name="pref_category_auto_download">Automaattinen lataus</string>
|
||||
<string name="pref_library_update_categories_details">Poissuljettuihin kategorioihin sisältyvää mangaa ei päivitetä, vaikka ne olisivat myös sisällytetyissä kategorioissa.</string>
|
||||
<string name="action_show_errors">Näytä virheet</string>
|
||||
<string name="update_check_eol">Tätä Android-versiota ei enää tueta</string>
|
||||
<string name="clipboard_copy_error">Kopiointi leikepöydälle epäonnistui</string>
|
||||
</resources>
|
|
@ -254,7 +254,7 @@
|
|||
<string name="all_lang">Lahat</string>
|
||||
<string name="all">Lahat</string>
|
||||
<plurals name="num_categories">
|
||||
<item quantity="one">1 kategorya</item>
|
||||
<item quantity="one">%d kategorya</item>
|
||||
<item quantity="other">%d (na) kategorya</item>
|
||||
</plurals>
|
||||
<string name="default_category_summary">Palaging tanungin</string>
|
||||
|
@ -526,7 +526,7 @@
|
|||
<string name="username">Sagisag (username)</string>
|
||||
<string name="login_title">Mag-login sa %1$s</string>
|
||||
<plurals name="download_queue_summary">
|
||||
<item quantity="one">Isa na lang</item>
|
||||
<item quantity="one">1 na lang</item>
|
||||
<item quantity="other">%1$s na lang</item>
|
||||
</plurals>
|
||||
<string name="downloaded_only_summary">Isalâ ang Aklatan</string>
|
||||
|
@ -672,4 +672,5 @@
|
|||
<string name="none">Wala</string>
|
||||
<string name="pref_library_update_categories_details">Di ia-update ang mga manga na nasa di kasamang kategorya kahit na nasa kasamang kategorya ang mga ito.</string>
|
||||
<string name="action_sort_chapter_fetch_date">Petsa kinuha</string>
|
||||
<string name="action_show_errors">Ipakita ang mga error</string>
|
||||
</resources>
|
|
@ -706,4 +706,7 @@
|
|||
<string name="pref_library_update_categories_details">Les mangas dans les catégories exclus ne seront pas mises a jour meme s\'ils sont aussi dans les catégories inlcus.</string>
|
||||
<string name="pref_download_new_categories_details">Les mangas dans les catégories exclus ne seront pas mise a jour meme s\'ils sont aussi dans les catégories inclus.</string>
|
||||
<string name="pref_category_auto_download">Téléchargement Automatique</string>
|
||||
<string name="action_show_errors">Afficher les erreurs</string>
|
||||
<string name="update_check_eol">Cette version d\'Android n\'est plus supportée</string>
|
||||
<string name="clipboard_copy_error">Échec de la copie dans le presse-papiers</string>
|
||||
</resources>
|
|
@ -684,4 +684,5 @@
|
|||
<string name="include">Uključi: %s</string>
|
||||
<string name="pref_library_update_categories_details">Manga u isključenim kategorijama neće se ažurirati čak niti ako se također nalaze u uključenim kategorijama.</string>
|
||||
<string name="action_sort_chapter_fetch_date">Datum preuzimanja</string>
|
||||
<string name="action_show_errors">Prikaži greške</string>
|
||||
</resources>
|
|
@ -80,7 +80,7 @@
|
|||
<string name="portrait">Tegak</string>
|
||||
<string name="landscape">Menyamping</string>
|
||||
<string name="default_columns">Asali</string>
|
||||
<string name="pref_library_update_interval">Frekuensi pembaruan perpustakaan</string>
|
||||
<string name="pref_library_update_interval">Frekuensi pembaruan</string>
|
||||
<string name="update_never">Manual</string>
|
||||
<string name="update_1hour">Tiap jam</string>
|
||||
<string name="update_2hour">Tiap 2 jam</string>
|
||||
|
@ -91,7 +91,7 @@
|
|||
<string name="update_48hour">Tiap 2 hari</string>
|
||||
<string name="update_weekly">Tiap minggu</string>
|
||||
<string name="all">Semua</string>
|
||||
<string name="pref_library_update_restriction">Pembatasan pembaruan perpustakaan</string>
|
||||
<string name="pref_library_update_restriction">Pembatasan pembaruan</string>
|
||||
<string name="pref_library_update_restriction_summary">Perbaharui hanya ketika kondisi terpenuhi</string>
|
||||
<string name="charging">Sedang mengisi daya</string>
|
||||
<string name="pref_update_only_non_completed">Perbarui manga yang masih belum tamat saja</string>
|
||||
|
@ -376,7 +376,7 @@
|
|||
<string name="filter_mode_lighten">Dodge / Cerahkan</string>
|
||||
<string name="filter_mode_darken">Burn / Gelapkan</string>
|
||||
<string name="label_help">Bantuan</string>
|
||||
<string name="pref_library_update_prioritization">Urutan perbarui perpustakaan</string>
|
||||
<string name="pref_library_update_prioritization">Urutan pembaruan</string>
|
||||
<string name="no_results_found">Hasil tidak ditemukan</string>
|
||||
<string name="migration_selection_prompt">Pilih sumber untuk migrasi dari</string>
|
||||
<string name="action_webview_back">Kembali</string>
|
||||
|
@ -639,4 +639,7 @@
|
|||
<string name="action_display_show_number_of_items">Tampilkan jumlah item</string>
|
||||
<string name="update_8hour">Setiap 8 jam</string>
|
||||
<string name="update_4hour">Setiap 4 jam</string>
|
||||
<string name="none">Kosong</string>
|
||||
<string name="action_show_errors">Tampilkan error</string>
|
||||
<string name="action_sort_chapter_fetch_date">Tanggal diambil</string>
|
||||
</resources>
|
|
@ -594,7 +594,7 @@
|
|||
</plurals>
|
||||
<string name="unknown_status">Stato sconosciuto</string>
|
||||
<string name="unknown_author">Autore sconosciuto</string>
|
||||
<string name="updated_version">Aggiornato verso v%1$s</string>
|
||||
<string name="updated_version">Aggiornato a v%1$s</string>
|
||||
<string name="whats_new">Le novità</string>
|
||||
<string name="requires_app_restart">Richiesto riavvio dell\'app per applicare le modifiche</string>
|
||||
<string name="label_network">Rete</string>
|
||||
|
@ -702,4 +702,8 @@
|
|||
<string name="nav_zone_right">Destra</string>
|
||||
<string name="nav_zone_left">Sinistra</string>
|
||||
<string name="pref_library_update_categories_details">Manga che si trovano in categorie escluse non saranno aggiornati anche se si trovano in categorie incluse.</string>
|
||||
<string name="pref_dns_over_https">DNS via HTTPS</string>
|
||||
<string name="pref_show_navigation_mode">Mostra schema di navigazione</string>
|
||||
<string name="pref_show_navigation_mode_summary">Mostra zone di tocco quando il lettore viene aperto</string>
|
||||
<string name="action_show_errors">Mostra errori</string>
|
||||
</resources>
|
|
@ -70,7 +70,7 @@
|
|||
<string name="portrait">縦向き</string>
|
||||
<string name="landscape">横向き</string>
|
||||
<string name="default_columns">デフォルト</string>
|
||||
<string name="pref_library_update_interval">ライブラリ更新頻度</string>
|
||||
<string name="pref_library_update_interval">更新頻度</string>
|
||||
<string name="update_never">マニュアル</string>
|
||||
<string name="update_1hour">毎時間</string>
|
||||
<string name="update_2hour">2時間ごと</string>
|
||||
|
@ -81,7 +81,7 @@
|
|||
<string name="update_48hour">2日ごと</string>
|
||||
<string name="update_weekly">毎週</string>
|
||||
<string name="all">すべて</string>
|
||||
<string name="pref_library_update_restriction">ライブラリ更新制限</string>
|
||||
<string name="pref_library_update_restriction">更新制限</string>
|
||||
<string name="pref_library_update_restriction_summary">条件が満たされた場合にのみ更新する</string>
|
||||
<string name="charging">充電中</string>
|
||||
<string name="pref_update_only_non_completed">連載中のマンガのみ更新</string>
|
||||
|
@ -369,7 +369,7 @@
|
|||
<string name="filter_mode_default">既定</string>
|
||||
<string name="filter_mode_overlay">オーバーレイ</string>
|
||||
<string name="filter_mode_screen">スクリーン</string>
|
||||
<string name="pref_library_update_prioritization">ライブラリ更新の順</string>
|
||||
<string name="pref_library_update_prioritization">更新の順</string>
|
||||
<string name="no_results_found">結果が見つかりませんでした</string>
|
||||
<string name="migration_selection_prompt">移行元を選択</string>
|
||||
<string name="action_webview_back">前へ</string>
|
||||
|
@ -380,7 +380,7 @@
|
|||
<string name="ext_obsolete">廃止済み</string>
|
||||
<string name="obsolete_extension_message">この拡張機能は利用不可になりました。</string>
|
||||
<string name="pref_date_format">日付形式</string>
|
||||
<string name="pref_category_library_update">更新</string>
|
||||
<string name="pref_category_library_update">グローバルアップデート</string>
|
||||
<string name="logout_title">%1$sからログアウトしますか?</string>
|
||||
<string name="logout">ログアウト</string>
|
||||
<string name="logout_success">ログアウトしました</string>
|
||||
|
@ -402,7 +402,7 @@
|
|||
<string name="theme_dark_amoled">AMOLEDブラック</string>
|
||||
<string name="pref_manage_notifications">通知設定</string>
|
||||
<string name="pref_category_security">セキュリティ</string>
|
||||
<string name="lock_with_biometrics">生体認証</string>
|
||||
<string name="lock_with_biometrics">アンロックを必要とする</string>
|
||||
<string name="lock_when_idle">タイムアウトロック</string>
|
||||
<string name="lock_always">常時</string>
|
||||
<string name="lock_never">しない</string>
|
||||
|
@ -650,6 +650,15 @@
|
|||
<string name="nav_zone_left">左</string>
|
||||
<string name="nav_zone_next">次へ</string>
|
||||
<string name="nav_zone_prev">前へ</string>
|
||||
<string name="pref_show_navigation_mode_summary">ビューアが立ち上がるとタップゾーンをしばらく表示します</string>
|
||||
<string name="pref_show_navigation_mode_summary">ビューアが立ち上がるとタップゾーンを表示します</string>
|
||||
<string name="pref_show_navigation_mode">ナビゲーションレイアウトオーバーレイを表示</string>
|
||||
<string name="pref_dns_over_https">DNS over HTTPS</string>
|
||||
<string name="pref_download_new_categories_details">含まれているカテゴリーに入っていても、除外対象カテゴリーにあるマンガは更新されません。</string>
|
||||
<string name="pref_category_auto_download">自動ダウンロード</string>
|
||||
<string name="exclude">下記を除外:%s</string>
|
||||
<string name="include">下記を含む:%s</string>
|
||||
<string name="none">なし</string>
|
||||
<string name="pref_library_update_categories_details">含まれているカテゴリーに入っていても、除外対象カテゴリーにあるマンガは更新されません。</string>
|
||||
<string name="action_show_errors">エラーを表示</string>
|
||||
<string name="action_sort_chapter_fetch_date">日付を取得しました</string>
|
||||
</resources>
|
|
@ -14,7 +14,7 @@
|
|||
<string name="lock_never">ಎಂದಿಗೂ ಇಲ್ಲ</string>
|
||||
<string name="lock_always">ಯಾವಾಗಲೂ</string>
|
||||
<string name="lock_when_idle">ನಿಷ್ಕ್ರಿಯವಾಗಿದ್ದಾಗ ಲಾಕ್ ಮಾಡಿ</string>
|
||||
<string name="lock_with_biometrics">"ಬೆರಳಚ್ಚ ಬದ್ರತೆ"</string>
|
||||
<string name="lock_with_biometrics">ಅನ್ ಲಾಕ್ ಅಗತ್ಯವಿದೆ</string>
|
||||
<string name="pref_category_security">ಭದ್ರತೆ</string>
|
||||
<string name="pref_manage_notifications">ಸೂಚನೆಗಳನ್ನು ನಿರ್ವಹಿಸಿ</string>
|
||||
<string name="pref_confirm_exit">ನಿರ್ಗಮನವನ್ನು ಖಚಿತಪಡಿಸಿ</string>
|
||||
|
@ -281,8 +281,8 @@
|
|||
<string name="pref_update_only_non_completed">ಚಾಲ್ತಿಯಿರುವ ಮಾಂಗಾವನ್ನು ಮಾತ್ರ ನವೀಕರಿಸಿ</string>
|
||||
<string name="charging">ಚಾರ್ಜಿಂಗ್</string>
|
||||
<string name="pref_library_update_restriction_summary">ಷರತ್ತುಗಳನ್ನು ಪೂರೈಸಿದಾಗ ಮಾತ್ರ ನವೀಕರಿಸಿ</string>
|
||||
<string name="pref_library_update_restriction">ಗ್ರಂಥಾಲಯ ನವೀಕರಣ ನಿರ್ಬಂಧಗಳು</string>
|
||||
<string name="pref_library_update_prioritization">ಗ್ರಂಥಾಲಯ ನವೀಕರಣ ಪಾಳಿ</string>
|
||||
<string name="pref_library_update_restriction">ನವೀಕರಣ ನಿರ್ಬಂಧಗಳು</string>
|
||||
<string name="pref_library_update_prioritization">ನವೀಕರಣ ಪಾಳಿ</string>
|
||||
<string name="update_weekly">ವಾರಕ್ಕೊಮ್ಮೆ</string>
|
||||
<string name="update_48hour">ಪ್ರತಿ 2 ದಿನಗಳಿಗೊಮ್ಮೆ</string>
|
||||
<string name="update_24hour">ಪ್ರತಿದಿನ</string>
|
||||
|
@ -292,7 +292,7 @@
|
|||
<string name="update_2hour">ಪ್ರತಿ 2 ಗಂಟೆಗಳಿಗೊಮ್ಮೆ</string>
|
||||
<string name="update_1hour">ಗಂಟೆ</string>
|
||||
<string name="update_never">ಸ್ವಂತ ಮಾಡು</string>
|
||||
<string name="pref_library_update_interval">ಗ್ರಂಥಾಲಯ ನವೀಕರಣ ಆವರ್ತನ</string>
|
||||
<string name="pref_library_update_interval">ನವೀಕರಣ ಆವರ್ತನ</string>
|
||||
<string name="pref_category_library_update">ನವೀಕರಣಗಳು</string>
|
||||
<string name="default_columns">ಡೀಫಾಲ್ಟ್</string>
|
||||
<string name="source_requires_login">ಈ ಮೂಲದ ಬಳಕೆಗೆ ಲಾಗಿನ್ ಆಗುವ ಅಗತ್ಯವಿದೆ</string>
|
||||
|
@ -607,7 +607,7 @@
|
|||
<string name="backup_restore_missing_trackers">ಟ್ರ್ಯಾಕರ್ ಗಳು ಲಾಗಿನ್ ಆಗಿಲ್ಲ:</string>
|
||||
<string name="pref_remove_bookmarked_chapters">ಬುಕ್ ಮಾರ್ಕ್ ಮಾಡಿದ ಅಧ್ಯಾಯಗಳನ್ನು ಅಳಿಸಿ</string>
|
||||
<string name="pref_category_delete_chapters">ಅಧ್ಯಾಯಗಳನ್ನು ಅಳಿಸಿ</string>
|
||||
<string name="ext_nsfw_warning">18+ ವಿಷಯವನ್ನು ಹೊಂದಿರಬಹುದು</string>
|
||||
<string name="ext_nsfw_warning">NSFW (18+) ವಿಷಯವನ್ನು ಹೊಂದಿರಬಹುದು</string>
|
||||
<string name="ext_nsfw_short">18+</string>
|
||||
<string name="pref_hide_bottom_bar_on_scroll">ಸ್ಕ್ರಾಲ್ ಮಾಡಿದಾಗ ಕೆಳಗಿನ ಪಟ್ಟಿಯನ್ನು ಮರೆಮಾಡಿ</string>
|
||||
<string name="action_search_settings">ಸಂಯೋಜನೆಗಳಲ್ಲಿ ಹುಡುಕಿ</string>
|
||||
|
@ -622,7 +622,8 @@
|
|||
<string name="pref_clear_history">ಇತಿಹಾಸವನ್ನು ತೆರವುಗೊಳಿಸಿ</string>
|
||||
<string name="clear_history_confirmation">ನೀವು ಖಚಿತವಾಗಿರುವಿರಾ\? ಎಲ್ಲಾ ಇತಿಹಾಸವೂ ಕಳೆದುಹೋಗುತ್ತದೆ.</string>
|
||||
<string name="clear_history_completed">ಇತಿಹಾಸವನ್ನು ಅಳಿಸಲಾಗಿದೆ</string>
|
||||
<string name="invalid_backup_file_type">ಅಮಾನ್ಯ ಬ್ಯಾಕಪ್ ಫೈಲ್:%1$s</string>
|
||||
<string name="invalid_backup_file_type">ಅಮಾನ್ಯ ಬ್ಯಾಕಪ್ ಫೈಲ್ ಪ್ರಕಾರ:%1$s
|
||||
\nಫೈಲ್ ಪ್ರಕಾರ .proto.gz ಅಥವಾ .json ನೊಂದಿಗೆ ಕೊನೆಗೊಳ್ಳಬೇಕು.</string>
|
||||
<string name="pref_backup_auto_create_legacy">ಹಳೆಯ ಪ್ರಕಾರದ ಬ್ಯಾಕಪ್ ಅನ್ನು ಸಹ ರಚಿಸಿ</string>
|
||||
<string name="pref_create_legacy_backup_summary">ತಚಿಯೋಮಿಯ ಹಳೆಯ ಆವೃತ್ತಿಗಳಲ್ಲಿ ಬಳಸಬಹುದು</string>
|
||||
<string name="pref_create_legacy_backup">ಹಳೆಯ ಪ್ರಕಾರದ ಬ್ಯಾಕಪ್ ರಚಿಸಿ</string>
|
||||
|
@ -635,8 +636,41 @@
|
|||
<string name="update_4hour">ಪ್ರತಿ ೪ ಗಂಟೆಗೆ</string>
|
||||
<string name="action_desc">ಮೊದಲು ಚಿಕ್ಕದು</string>
|
||||
<string name="action_asc">ಮೊದಲ ಸಾಣ್ಣದ್ದು</string>
|
||||
<string name="action_order_by_chapter_number">ಅಧ್ಯಾಯ ಸಾಂಖ್ಯಯಂತೆ</string>
|
||||
<string name="action_order_by_upload_date">ದಿನಾಂಕ ದಂತೆ</string>
|
||||
<string name="action_display_show_number_of_items">"ವಸ್ತುವಿನ ಸಾಂಖ್ಯ ತೋರಿಸಿ"</string>
|
||||
<string name="action_sort_chapter_fetch_date">ಪಡೆಯುಲಾದ ಮಾಹಿತಿ</string>
|
||||
<string name="action_order_by_chapter_number">ಅಧ್ಯಾಯ ಸಂಖ್ಯೆಯಿಂದ</string>
|
||||
<string name="action_order_by_upload_date">ಅಪ್ಲೋಡ್ ದಿನಾಂಕ ದಂತೆ</string>
|
||||
<string name="action_display_show_number_of_items">ವಸ್ತುಗಳ ಸಂಖ್ಯೆಯನ್ನು ತೋರಿಸಿ</string>
|
||||
<string name="action_sort_chapter_fetch_date">ಸಿಕ್ಕ ಮಾಹಿತಿ</string>
|
||||
<string name="channel_crash_logs">ಕ್ರ್ಯಾಶ್ ಲಾಗ್ ಗಳು</string>
|
||||
<string name="track_finished_reading_date">ಓದಿ ಮುಗಿಸಿದ ದಿನಾಂಕ</string>
|
||||
<string name="track_started_reading_date">ಓದಲು ಪ್ರಾರಂಭಿಸಿದ ದಿನಾಂಕ</string>
|
||||
<string name="crash_log_saved">ಕ್ರ್ಯಾಶ್ ಲಾಗ್ಗಳನ್ನು ಉಳಿಸಲಾಗಿದೆ</string>
|
||||
<string name="pref_dump_crash_logs_summary">ಡೆವಲಪರ್ಗಳೊಂದಿಗೆ ಹಂಚಿಕೊಳ್ಳಲು ದೋಷದೆ ಲಾಗ್ಗಳನ್ನು ಫೈಲ್ಗೆ ಸೇರಿಸಿ</string>
|
||||
<string name="pref_dump_crash_logs">ಕ್ರ್ಯಾಶ್ ಲಾಗ್ಗಳನ್ನು ಡಂಪ್ ಮಾಡಿ</string>
|
||||
<string name="pref_dns_over_https">HTTPS ಮೇಲೆ DNS ಬಳಸಿ</string>
|
||||
<string name="backup_restore_content_full">ಬ್ಯಾಕಪ್ ಫೈಲ್ನಿಂದ ಡೇಟಾವನ್ನು ಮರುಸ್ಥಾಪಿಸಲಾಗುತ್ತದೆ.
|
||||
\n
|
||||
\nಕಾಣೆಯಾದ ಯಾವುದೇ ವಿಸ್ತರಣೆಗಳನ್ನು ನೀವು ಪುನಃ ಸ್ಥಾಪಿಸಬೇಕಾಗುತ್ತದೆ ಮತ್ತು ಅವುಗಳನ್ನು ಬಳಸಲು ಟ್ರ್ಯಾಕಿಂಗ್ ಸೇವೆಗಳಿಗೆ ಲಾಗ್ ಇನ್ ಮಾಡಬೇಕಾಗುತ್ತದೆ.</string>
|
||||
<string name="pref_download_new_categories_details">ಹೊರಗಿಡಲಾದ ವಿಭಾಗಗಳಲ್ಲಿ ಮಾಂಗಾವನ್ನು ಸೇರಿಸಿದ ವಿಭಾಗಗಳಲ್ಲಿದ್ದರೂ ಅವುಗಳನ್ನು ಡೌನ್ಲೋಡ್ ಮಾಡಲಾಗುವುದಿಲ್ಲ.</string>
|
||||
<string name="pref_category_auto_download">ಸ್ವಯಂ ಡೌನ್ಲೋಡ್</string>
|
||||
<string name="pref_viewer_nav">ನ್ಯಾವಿಗೇಶನ್ ಲೇಔಟ್</string>
|
||||
<string name="nav_zone_right">ಬಲಕ್ಕೆ</string>
|
||||
<string name="nav_zone_left">ಎಡಕ್ಕೆ</string>
|
||||
<string name="nav_zone_next">ಮುಂದಿನ</string>
|
||||
<string name="nav_zone_prev">ಹಿಂದಿನ</string>
|
||||
<string name="right_and_left_nav">ಬಲ ಮತ್ತು ಎಡ</string>
|
||||
<string name="edge_nav">ಅಂಚು</string>
|
||||
<string name="kindlish_nav">ಕಿಂಡಲ್-ಇಶ್</string>
|
||||
<string name="l_nav">L ಆಕಾರದ</string>
|
||||
<string name="default_nav">ಪೂರ್ವನಿಯೋಜಿತ</string>
|
||||
<string name="pref_dual_page_invert_summary">ಡ್ಯುಯಲ್ ಪೇಜ್ ಸ್ಪ್ಲಿಟ್ ನ ಪ್ಲೇಸ್ ಮೆಂಟ್ ಓದುವ ದಿಕ್ಕಿಗೆ ಹೊಂದಿಕೆಯಾಗದಿದ್ದರೆ</string>
|
||||
<string name="pref_dual_page_invert">ಡ್ಯುಯಲ್ ಪೇಜ್ ಸ್ಪ್ಲಿಟ್ ಪ್ಲೇಸ್ಮೆಂಟ್ ಅನ್ನು ತಿರುಗಿಸಿ</string>
|
||||
<string name="pref_dual_page_split">ಡ್ಯುಯಲ್ ಪುಟ ವಿಭಜನೆ</string>
|
||||
<string name="pref_show_navigation_mode_summary">ರೀಡರ್ ತೆರೆದಾಗ ಟ್ಯಾಪ್ ವಲಯಗಳನ್ನು ತೋರಿಸಿ</string>
|
||||
<string name="pref_show_navigation_mode">ನ್ಯಾವಿಗೇಶನ್ ಲೇಔಟ್ ಓವರ್ ಲೇ ತೋರಿಸಿ</string>
|
||||
<string name="exclude">ಹೊರಗಿಡಿ: %s</string>
|
||||
<string name="include">ಸೇರಿಸಿ: %s</string>
|
||||
<string name="none">ಯಾವುದು ಅಲ್ಲ</string>
|
||||
<string name="pref_library_update_categories_details">ಹೊರಗಿಡಲಾದ ವರ್ಗಗಳಲ್ಲಿನ ಮಾಂಗಾ ಸೇರಿಸಿದ ವಿಭಾಗಗಳಲ್ಲಿದ್ದರೂ ನವೀಕರಿಸಲಾಗುವುದಿಲ್ಲ.</string>
|
||||
<string name="network_unmetered">ಅಳತೆಯಿಲ್ಲದ ನೆಟ್ವರ್ಕ್</string>
|
||||
<string name="action_show_errors">ದೋಷಗಳನ್ನು ತೋರಿಸು</string>
|
||||
</resources>
|
|
@ -101,7 +101,7 @@
|
|||
<string name="pref_auto_update_manga_sync">Kemas kini bab selepas dibaca</string>
|
||||
<string name="pref_start_screen">Skrin permulaan</string>
|
||||
<string name="pref_language">Bahasa</string>
|
||||
<string name="system_default">Lalai</string>
|
||||
<string name="system_default">Sistem asal</string>
|
||||
<string name="default_category">Kategori lalai</string>
|
||||
<string name="default_category_summary">Sentiasa tanya</string>
|
||||
<string name="pref_fullscreen">Skrin penuh</string>
|
||||
|
@ -152,7 +152,7 @@
|
|||
<string name="pref_remove_after_marked_as_read">Selepas ditandakan sebagai dibaca secara manual</string>
|
||||
<string name="pref_remove_after_read">Setelah membaca</string>
|
||||
<string name="custom_dir">Lokasi tersuai</string>
|
||||
<string name="disabled">Dinyahaktifkan</string>
|
||||
<string name="disabled">Di nyahkan</string>
|
||||
<string name="last_read_chapter">Bab terakhir dibaca</string>
|
||||
<string name="second_to_last">Bab kedua terakhir</string>
|
||||
<string name="third_to_last">Bab ketiga terakhir</string>
|
||||
|
@ -212,7 +212,7 @@
|
|||
<string name="local_source">Sumber lokal</string>
|
||||
<string name="other_source">Lain</string>
|
||||
<string name="invalid_combination">Lalai tidak boleh dipilih bersama kategori lain</string>
|
||||
<string name="added_to_library">Manga ini telah ditambahkan ke pustaka anda</string>
|
||||
<string name="added_to_library">Ditambah ke pustaka</string>
|
||||
<string name="action_global_search_hint">Carian keseluruhan…</string>
|
||||
<string name="latest">Terkini</string>
|
||||
<string name="browse">Semak imbas</string>
|
||||
|
@ -232,7 +232,7 @@
|
|||
<string name="chapter_downloading">Muat turun dalam progres</string>
|
||||
<string name="chapter_downloading_progress">Memuat turun (%1$d/%2$d)</string>
|
||||
<string name="chapter_error">Ralat</string>
|
||||
<string name="chapter_paused">Dihenti sebentar</string>
|
||||
<string name="chapter_paused">Ditangguh</string>
|
||||
<string name="fetch_chapters_error">Tidak berhasil mendapatkan bab</string>
|
||||
<string name="show_title">Tajuk sumber</string>
|
||||
<string name="show_chapter_number">Nombor bab</string>
|
||||
|
@ -244,7 +244,7 @@
|
|||
<string name="download_5">5 bab seterusnya</string>
|
||||
<string name="download_10">10 bab seterusnya</string>
|
||||
<string name="download_all">Semua</string>
|
||||
<string name="download_unread">Belum dibaca</string>
|
||||
<string name="download_unread">Muat turun yang belum di baca</string>
|
||||
<string name="confirm_delete_chapters">Adakah anda pasti ingin memadamkan bab yang dipilih\?</string>
|
||||
<string name="manga_tracking_tab">Penjejakan</string>
|
||||
<string name="reading">Sedang baca</string>
|
||||
|
@ -274,7 +274,7 @@
|
|||
<string name="chapter_subtitle">Bab %1$s</string>
|
||||
<string name="no_next_chapter">Bab seterusnya tidak dijumpai</string>
|
||||
<string name="no_previous_chapter">Bab sebelumnya tidak dijumpai</string>
|
||||
<string name="decode_image_error">Imej tidak dapat dimuatkan</string>
|
||||
<string name="decode_image_error">Imej tidak dapat di muatkan</string>
|
||||
<string name="confirm_set_image_as_cover">Guna imej ini sebagai muka hadapan\?</string>
|
||||
<string name="download_queue_error">Memuat turun bab tidak berjaya. Anda boleh mencuba lagi di bahagian muat turun</string>
|
||||
<string name="notification_update_progress">Progres kemas kini: %1$d/%2$d</string>
|
||||
|
@ -319,7 +319,7 @@
|
|||
<string name="ext_update">Kemaskini</string>
|
||||
<string name="ext_install">Pasang</string>
|
||||
<string name="ext_pending">Masih menunggu</string>
|
||||
<string name="ext_downloading">Muat turun dalam progres</string>
|
||||
<string name="ext_downloading">Menuat turun</string>
|
||||
<string name="ext_installing">Memasang</string>
|
||||
<string name="ext_installed">Dipasang</string>
|
||||
<string name="ext_trust">Dipercayai</string>
|
||||
|
@ -391,9 +391,9 @@
|
|||
<string name="logout_title">Log keluar daripada %1$s\?</string>
|
||||
<string name="logout">Log keluar</string>
|
||||
<string name="logout_success">Anda telah log keluar</string>
|
||||
<string name="currently_reading">Sedang baca</string>
|
||||
<string name="currently_reading">Sedang di baca</string>
|
||||
<string name="paused">Ditangguh</string>
|
||||
<string name="want_to_read">Ingin baca</string>
|
||||
<string name="want_to_read">Hendak di baca</string>
|
||||
<string name="label_more">Lain-lain</string>
|
||||
<string name="action_sort_latest_chapter">Bab terkini</string>
|
||||
<string name="action_view_chapters">Buka bab</string>
|
||||
|
@ -408,7 +408,7 @@
|
|||
<string name="theme_dark_amoled">AMOLED</string>
|
||||
<string name="pref_manage_notifications">Uruskan pemberitahuan</string>
|
||||
<string name="pref_category_security">Keselamatan</string>
|
||||
<string name="lock_with_biometrics">Memerlukan buka kunci</string>
|
||||
<string name="lock_with_biometrics">Kunci dengan biometrik</string>
|
||||
<string name="lock_when_idle">Kunci apabila terbiar</string>
|
||||
<string name="lock_always">Selalu</string>
|
||||
<string name="lock_never">Tidak</string>
|
||||
|
@ -474,8 +474,8 @@
|
|||
<string name="add_tracking">Tambah penjejakan</string>
|
||||
<string name="manga_info_collapse">Tutup</string>
|
||||
<string name="manga_info_expand">Buka</string>
|
||||
<string name="in_library">Dalam pustaka</string>
|
||||
<string name="add_to_library">Tambah ke pustaka</string>
|
||||
<string name="in_library">Dalam Pustaka</string>
|
||||
<string name="add_to_library">Tambah ke Pustaka</string>
|
||||
<string name="pinned_sources">Disematkan</string>
|
||||
<string name="licenses">Lesen perisian sumber terbuka</string>
|
||||
<string name="website">Laman web</string>
|
||||
|
@ -660,4 +660,7 @@
|
|||
<string name="pref_library_update_categories_details">Manga di dalam kategori berkecuali tidak akan dikemaskini walaupun ianya ada di dalam kategori hanya.</string>
|
||||
<string name="pref_download_new_categories_details">Manga di dalam kategori berkecuali tidak akan dimuat turun walaupun ianya ada di dalam kategori hanya.</string>
|
||||
<string name="pref_category_auto_download">Muat turun automatik</string>
|
||||
<string name="action_show_errors">Tunjuk ralat</string>
|
||||
<string name="update_check_eol">Versi Android ini tidak lagi disokong</string>
|
||||
<string name="clipboard_copy_error">Gagal menyalin ke papan keratan</string>
|
||||
</resources>
|
|
@ -122,8 +122,8 @@
|
|||
<string name="pref_category_tracking">Sporing</string>
|
||||
<string name="portrait">Stående</string>
|
||||
<string name="landscape">Liggende</string>
|
||||
<string name="pref_library_update_interval">Frekvens for oppdatering av bibliotek</string>
|
||||
<string name="pref_library_update_restriction">Restriksjoner for oppdatering av bibliotek</string>
|
||||
<string name="pref_library_update_interval">Oppdateringsfrekvens</string>
|
||||
<string name="pref_library_update_restriction">Oppdateringsrestriksjoner</string>
|
||||
<string name="pref_library_update_restriction_summary">Kun oppdater når disse vilkårene oppfylles</string>
|
||||
<string name="pref_update_only_non_completed">Kun oppdater pågående manga</string>
|
||||
<string name="pref_auto_update_manga_sync">Oppdater kapittelfremdrift etter lesing</string>
|
||||
|
@ -376,7 +376,7 @@
|
|||
<string name="filter_mode_multiply">Multiplisere</string>
|
||||
<string name="filter_mode_lighten">Unngå / lysne</string>
|
||||
<string name="filter_mode_darken">Brenn / mørkere</string>
|
||||
<string name="pref_library_update_prioritization">Rekkefølge for biblioteksoppdatering</string>
|
||||
<string name="pref_library_update_prioritization">Oppdateringsrekkefølge</string>
|
||||
<string name="no_results_found">Resultatløst</string>
|
||||
<string name="migration_selection_prompt">Velg en kilde å migrere fra</string>
|
||||
<string name="action_webview_back">Tilbake</string>
|
||||
|
@ -387,7 +387,7 @@
|
|||
<string name="ext_obsolete">Foreldet</string>
|
||||
<string name="obsolete_extension_message">Denne utvidelsen er ikke lenger tilgjengelig.</string>
|
||||
<string name="pref_date_format">Datoformat</string>
|
||||
<string name="pref_category_library_update">Oppdateringer</string>
|
||||
<string name="pref_category_library_update">Global oppdatering</string>
|
||||
<string name="logout_title">Logg ut fra %1$s\?</string>
|
||||
<string name="logout">Logg ut</string>
|
||||
<string name="logout_success">Du er utlogget</string>
|
||||
|
@ -669,4 +669,8 @@
|
|||
<string name="update_8hour">Hver 8 time</string>
|
||||
<string name="update_4hour">Hver 4 time</string>
|
||||
<string name="action_sort_chapter_fetch_date">Dato hentet</string>
|
||||
<string name="pref_download_new_categories_details">Manga i utelukkede kategorier vil ikke bli nedlastet selv om de også er i inkluderte kategorier.</string>
|
||||
<string name="pref_category_auto_download">Last ned automatisk</string>
|
||||
<string name="pref_library_update_categories_details">Manga i utelukkede kategorier vil ikke bli oppdatert selv om de også er i inkluderte kategorier.</string>
|
||||
<string name="action_show_errors">Vis feil</string>
|
||||
</resources>
|
|
@ -672,4 +672,5 @@
|
|||
<string name="pref_library_update_categories_details">Manga in uitgesloten categorieën worden niet bijgewerkt, zelfs niet als ze onder opgenomen categorieën vallen.</string>
|
||||
<string name="action_sort_chapter_fetch_date">Datum opgehaald</string>
|
||||
<string name="none">Geen</string>
|
||||
<string name="action_show_errors">Fouten weergeven</string>
|
||||
</resources>
|
|
@ -641,7 +641,7 @@
|
|||
<string name="track_started_reading_date">Data de início da leitura</string>
|
||||
<string name="crash_log_saved">Registros de travamento salvos</string>
|
||||
<string name="pref_dump_crash_logs_summary">Salva os registros de erro em um arquivo para o compartilhamento com os desenvolvedores</string>
|
||||
<string name="pref_dump_crash_logs">Limpar os registros de travamentos</string>
|
||||
<string name="pref_dump_crash_logs">Exportar os registros de travamentos</string>
|
||||
<string name="network_unmetered">Rede ilimitada</string>
|
||||
<string name="action_desc">Decrescente</string>
|
||||
<string name="action_asc">Crescente</string>
|
||||
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_library_update_categories_details">Os mangás nas categorias excluídas não serão atualizados mesmo que eles também estejam nas categorias incluídas.</string>
|
||||
<string name="pref_download_new_categories_details">Os mangás nas categorias excluídas não serão disponibilizados offline mesmo que eles também estejam nas categorias incluídas.</string>
|
||||
<string name="pref_category_auto_download">Disponibilizar offline automaticamente</string>
|
||||
<string name="action_show_errors">Mostrar erros</string>
|
||||
<string name="update_check_eol">Esta versão do Android não é mais suportada</string>
|
||||
<string name="clipboard_copy_error">Erro ao copiar para a área de transferência</string>
|
||||
</resources>
|
|
@ -59,7 +59,7 @@
|
|||
<string name="portrait">Retrato</string>
|
||||
<string name="landscape">Paisagem</string>
|
||||
<string name="default_columns">Padrão</string>
|
||||
<string name="pref_library_update_interval">Frequência de atualização da biblioteca</string>
|
||||
<string name="pref_library_update_interval">Frequência de atualização</string>
|
||||
<string name="update_never">Manual</string>
|
||||
<string name="update_1hour">Hora à hora</string>
|
||||
<string name="update_2hour">A cada 2 horas</string>
|
||||
|
@ -69,7 +69,7 @@
|
|||
<string name="update_24hour">Diariamente</string>
|
||||
<string name="update_48hour">A cada 2 dias</string>
|
||||
<string name="all">Tudo</string>
|
||||
<string name="pref_library_update_restriction">Restrições sobre a atualização da biblioteca</string>
|
||||
<string name="pref_library_update_restriction">Restrições sobre a atualização</string>
|
||||
<string name="pref_library_update_restriction_summary">Atualizar apenas quando se cumprem as condições</string>
|
||||
<string name="charging">A carregar</string>
|
||||
<string name="pref_update_only_non_completed">Atualizar apenas mangás a decorrer</string>
|
||||
|
@ -181,7 +181,7 @@
|
|||
<string name="sort_by_source">Por fonte</string>
|
||||
<string name="sort_by_number">Por número de capítulo</string>
|
||||
<string name="manga_download">Transferir</string>
|
||||
<string name="download_1">Próximo capítulo</string>
|
||||
<string name="download_1">Capítulo seguinte</string>
|
||||
<string name="download_5">Próximos 5 capítulos</string>
|
||||
<string name="download_10">Próximos 10 capítulos</string>
|
||||
<string name="download_all">Tudo</string>
|
||||
|
@ -406,7 +406,7 @@
|
|||
<string name="pref_color_filter_mode">Modo de mistura do filtro de cores</string>
|
||||
<string name="filter_mode_lighten">Sub-exposição / Clarear</string>
|
||||
<string name="label_help">Ajuda</string>
|
||||
<string name="pref_library_update_prioritization">Ordem de atualização da biblioteca</string>
|
||||
<string name="pref_library_update_prioritization">Ordem de atualização</string>
|
||||
<string name="no_results_found">Nenhum resultado encontrado</string>
|
||||
<string name="migration_selection_prompt">Selecione uma fonte da qual migrar</string>
|
||||
<string name="action_webview_back">Voltar</string>
|
||||
|
@ -417,7 +417,7 @@
|
|||
<string name="ext_obsolete">Obsoleto</string>
|
||||
<string name="obsolete_extension_message">Esta extensão já não está disponível.</string>
|
||||
<string name="pref_date_format">Formato da data</string>
|
||||
<string name="pref_category_library_update">Atualizações</string>
|
||||
<string name="pref_category_library_update">Atualização global</string>
|
||||
<string name="logout_title">Terminar sessão em %1$s\?</string>
|
||||
<string name="logout">Terminar sessão</string>
|
||||
<string name="logout_success">Sua sessão está agora encerrada</string>
|
||||
|
@ -438,7 +438,7 @@
|
|||
<string name="theme_dark_amoled">Preto AMOLED</string>
|
||||
<string name="pref_manage_notifications">Gerir notificações</string>
|
||||
<string name="pref_category_security">Segurança</string>
|
||||
<string name="lock_with_biometrics">Bloqueio com biometria</string>
|
||||
<string name="lock_with_biometrics">Requerer desbloqueio</string>
|
||||
<string name="lock_when_idle">Bloquear automaticamente</string>
|
||||
<string name="lock_always">Sempre</string>
|
||||
<string name="lock_never">Nunca</string>
|
||||
|
@ -690,8 +690,19 @@
|
|||
<string name="nav_zone_left">Esquerda</string>
|
||||
<string name="nav_zone_next">Seguinte</string>
|
||||
<string name="nav_zone_prev">Anterior</string>
|
||||
<string name="pref_show_navigation_mode_summary">Brevemente mostrar zonas de toque quando o leitor é aberto</string>
|
||||
<string name="pref_show_navigation_mode_summary">Mostrar zonas de toque quando o leitor é aberto</string>
|
||||
<string name="pref_show_navigation_mode">Mostrar sobreposição da disposição de navegação</string>
|
||||
<string name="update_8hour">A cada 8 horas</string>
|
||||
<string name="update_4hour">A cada 4 horas</string>
|
||||
<string name="none">Nenhum</string>
|
||||
<string name="pref_dns_over_https">DNS por HTTPS</string>
|
||||
<string name="pref_category_auto_download">Transferir automaticamente</string>
|
||||
<string name="update_check_eol">Esta versão do Android não é mais suportada</string>
|
||||
<string name="clipboard_copy_error">Falha ao copiar para a área de transferência</string>
|
||||
<string name="pref_download_new_categories_details">Mangá nas categorias excluídas não será transferida mesmo que também esteja em categorias incluídas.</string>
|
||||
<string name="exclude">Excluir: %s</string>
|
||||
<string name="include">Incluir: %s</string>
|
||||
<string name="pref_library_update_categories_details">Mangá em categorias excluídas não será atualizada mesmo que também estejam nas categorias incluídas.</string>
|
||||
<string name="action_show_errors">Mostrar erros</string>
|
||||
<string name="action_sort_chapter_fetch_date">Data de procura</string>
|
||||
</resources>
|
|
@ -83,7 +83,7 @@
|
|||
<string name="pref_library_columns">Elemente pe rând</string>
|
||||
<string name="portrait">Portret</string>
|
||||
<string name="default_columns">Prestabilit</string>
|
||||
<string name="pref_library_update_interval">Frecvența actualizării bibliotecii</string>
|
||||
<string name="pref_library_update_interval">Frecvență de actualizare</string>
|
||||
<string name="update_never">Manual</string>
|
||||
<string name="update_1hour">La fiecare oră</string>
|
||||
<string name="update_2hour">La fiecare 2 ore</string>
|
||||
|
@ -94,7 +94,7 @@
|
|||
<string name="update_48hour">La fiecare 2 zile</string>
|
||||
<string name="update_weekly">Săptămânal</string>
|
||||
<string name="all">Toate</string>
|
||||
<string name="pref_library_update_restriction">Restricții actualizare bibliotecă</string>
|
||||
<string name="pref_library_update_restriction">Restricții de actualizare</string>
|
||||
<string name="pref_library_update_restriction_summary">Actualizează doar când condițiile sunt împlinite</string>
|
||||
<string name="charging">Se încarcă</string>
|
||||
<string name="pref_update_only_non_completed">Actualizați doar manga în desfășurare</string>
|
||||
|
@ -108,7 +108,7 @@
|
|||
<string name="ext_update">Actualizează</string>
|
||||
<string name="ext_install">Instalează</string>
|
||||
<string name="ext_pending">În așteptare</string>
|
||||
<string name="ext_downloading">În curs de descărcare</string>
|
||||
<string name="ext_downloading">Se descarcă</string>
|
||||
<string name="ext_installing">În curs de instalare</string>
|
||||
<string name="ext_installed">Instalată</string>
|
||||
<string name="ext_trust">Ai încredere</string>
|
||||
|
@ -275,7 +275,7 @@
|
|||
<string name="sort_by_number">După numărul capitolului</string>
|
||||
<string name="manga_download">Descarcă</string>
|
||||
<string name="custom_download">Descarcă cantitate personalizată</string>
|
||||
<string name="download_1">Următorul capitol</string>
|
||||
<string name="download_1">Capitolul următor</string>
|
||||
<string name="download_5">Următoarele 5 capitole</string>
|
||||
<string name="download_10">Următoarele 10 capitole</string>
|
||||
<string name="download_custom">Personalizat</string>
|
||||
|
@ -286,7 +286,7 @@
|
|||
<string name="reading">Citind</string>
|
||||
<string name="completed">Terminată</string>
|
||||
<string name="dropped">Abandonată</string>
|
||||
<string name="on_hold">In așteptare</string>
|
||||
<string name="on_hold">În așteptare</string>
|
||||
<string name="plan_to_read">Planificat pentru citit</string>
|
||||
<string name="repeating">Recitind</string>
|
||||
<string name="score">Scor</string>
|
||||
|
@ -305,10 +305,10 @@
|
|||
<string name="saving_picture">Imaginea se salvează</string>
|
||||
<string name="options">Opțiuni</string>
|
||||
<string name="custom_filter">Filtru personalizat</string>
|
||||
<string name="set_as_cover">Stabilește că și copertă</string>
|
||||
<string name="set_as_cover">Stabilește ca și copertă</string>
|
||||
<string name="cover_updated">Copertă actualizată</string>
|
||||
<string name="page_downloaded">Pagină copiată în %1$s</string>
|
||||
<string name="downloading">Se descărcă…</string>
|
||||
<string name="downloading">Se descarcă…</string>
|
||||
<string name="download_progress">Descărcat %1$d%%</string>
|
||||
<string name="chapter_progress">Pagina: %1$d</string>
|
||||
<string name="chapter_subtitle">Capitolul %1$s</string>
|
||||
|
@ -376,7 +376,7 @@
|
|||
<string name="pref_skip_read_chapters">Treci peste capitolele marcate ca Citit</string>
|
||||
<string name="pref_read_with_long_tap">Dialog prin apăsare lunga</string>
|
||||
<string name="label_help">Ajutor</string>
|
||||
<string name="pref_library_update_prioritization">Ordinea actualizării bibliotecii</string>
|
||||
<string name="pref_library_update_prioritization">Ordinea actualizărilor</string>
|
||||
<string name="no_results_found">Nici un rezultat găsit</string>
|
||||
<string name="migration_selection_prompt">Selectați o sursă din care să migrați</string>
|
||||
<string name="action_webview_back">Înapoi</string>
|
||||
|
@ -387,7 +387,7 @@
|
|||
<string name="ext_obsolete">Învechit</string>
|
||||
<string name="obsolete_extension_message">Această extensie nu mai este disponibilă.</string>
|
||||
<string name="pref_date_format">Formatul datei</string>
|
||||
<string name="pref_category_library_update">Actualizări</string>
|
||||
<string name="pref_category_library_update">Actualizare globală</string>
|
||||
<string name="logout_title">Deconectează-te de la %1$s\?</string>
|
||||
<string name="logout">Deconectează-te</string>
|
||||
<string name="logout_success">Acum ești deconectat</string>
|
||||
|
@ -407,7 +407,7 @@
|
|||
<string name="theme_dark_amoled">Negru AMOLED</string>
|
||||
<string name="pref_manage_notifications">Setări notificări</string>
|
||||
<string name="pref_category_security">Securitate</string>
|
||||
<string name="lock_with_biometrics">Blocare cu amprentă</string>
|
||||
<string name="lock_with_biometrics">Necesită deblocare</string>
|
||||
<string name="unlock_app">Deblochează Tachiyomi</string>
|
||||
<string name="action_sort_latest_chapter">Ultimul capitol</string>
|
||||
<string name="lock_when_idle">Blocați când este inactiv</string>
|
||||
|
@ -525,7 +525,7 @@
|
|||
</plurals>
|
||||
<string name="battery_optimization_setting_activity_not_found">Imposibil de deschis setările dispozitivului</string>
|
||||
<plurals name="restore_completed_message">
|
||||
<item quantity="one">Gata în %1$s cu %2$s eroare</item>
|
||||
<item quantity="one">Gata în %1$s cu eroarea %2$s</item>
|
||||
<item quantity="few">Gata în %1$s cu %2$s erori</item>
|
||||
<item quantity="other">Gata în %1$s cu %2$s erori</item>
|
||||
</plurals>
|
||||
|
@ -631,7 +631,8 @@
|
|||
<string name="spen_next_page">Pagina următoare</string>
|
||||
<string name="spen_previous_page">Pagina anterioară</string>
|
||||
<string name="migration_help_guide">Ghid de migrare a sursei</string>
|
||||
<string name="invalid_backup_file_type">Fișierul copiei de rezervă este nevalid: %1$s</string>
|
||||
<string name="invalid_backup_file_type">Tip de fișier de restaurare nevalid: %1$s
|
||||
\nAr trebui să se termine cu .proto.gz sau .json.</string>
|
||||
<string name="pref_backup_auto_create_legacy">De asemenea, creați copii de rezervă de moștenire</string>
|
||||
<string name="pref_create_legacy_backup_summary">Poate fi utilizat în versiuni mai vechi de Tachiyomi</string>
|
||||
<string name="pref_create_legacy_backup">Crează copie de rezervă de moștenire</string>
|
||||
|
@ -644,7 +645,7 @@
|
|||
<string name="myanimelist_creds_missing">Datele de conectare la site-ul MAL nu au fost găsite</string>
|
||||
<string name="pref_dual_page_invert">Inversează plasamentul paginilor duble despărțite</string>
|
||||
<string name="pref_dual_page_split">împărțirea paginilor duble</string>
|
||||
<string name="pref_show_navigation_mode_summary">Afișați scurt zonele de atingere când cititorul este deschis</string>
|
||||
<string name="pref_show_navigation_mode_summary">Afișați zonele de atingere atunci când cititorul este deschis</string>
|
||||
<string name="pref_show_navigation_mode">Afișați suprapunerea aspectului de navigare</string>
|
||||
<string name="network_unmetered">Rețea nemăsurată</string>
|
||||
<string name="update_8hour">O dată la 8 ore</string>
|
||||
|
@ -653,4 +654,37 @@
|
|||
<string name="action_asc">Ascendent</string>
|
||||
<string name="action_order_by_chapter_number">După numărul capitolului</string>
|
||||
<string name="action_order_by_upload_date">După data postării</string>
|
||||
<string name="exclude">Excludeți: %s</string>
|
||||
<string name="include">Includeți: %s</string>
|
||||
<string name="pref_library_update_categories_details">Manga din categoriile excluse nu vor fi actualizate, chiar dacă se află și în categoriile incluse.</string>
|
||||
<string name="action_show_errors">Afișați erorile</string>
|
||||
<string name="action_display_show_number_of_items">Afișare număr de elemente</string>
|
||||
<string name="none">Nici unul</string>
|
||||
<string name="pref_dns_over_https">DNS peste HTTPS</string>
|
||||
<string name="channel_crash_logs">Jurnale de erori fatale</string>
|
||||
<string name="track_finished_reading_date">Data încheierii citirii</string>
|
||||
<string name="track_started_reading_date">Data începerii citirii</string>
|
||||
<string name="crash_log_saved">Jurnalele de erori fatale salvate</string>
|
||||
<string name="pref_dump_crash_logs">Aruncați jurnalele de erori fatale</string>
|
||||
<string name="pref_dump_crash_logs_summary">Salvează jurnalele de erori într-un fișier pentru partajarea cu dezvoltatorii</string>
|
||||
<string name="pref_viewer_nav">Aspect de navigare</string>
|
||||
<string name="edge_nav">Margine</string>
|
||||
<string name="kindlish_nav">Similar unui Kindle</string>
|
||||
<string name="l_nav">În formă de L</string>
|
||||
<string name="default_nav">Implicită</string>
|
||||
<string name="action_sort_chapter_fetch_date">Data preluată</string>
|
||||
<string name="action_filter_tracked">Urmărit</string>
|
||||
<string name="backup_restore_content_full">Datele din fișierul de rezervă vor fi restaurate.
|
||||
\n
|
||||
\nVa trebui să instalați toate extensiile lipsă și să vă conectați ulterior la serviciile de urmărire pentru a le utiliza.</string>
|
||||
<string name="pref_download_new_categories_details">Manga din categoriile excluse nu vor fi descărcate, chiar dacă se află și în categoriile incluse.</string>
|
||||
<string name="pref_category_auto_download">Descărcare automată</string>
|
||||
<string name="nav_zone_right">Dreapta</string>
|
||||
<string name="nav_zone_left">Stânga</string>
|
||||
<string name="nav_zone_next">Următorul</string>
|
||||
<string name="nav_zone_prev">Anterior</string>
|
||||
<string name="right_and_left_nav">Dreapta și stânga</string>
|
||||
<string name="pref_dual_page_invert_summary">Dacă amplasarea divizării duble a paginii nu corespunde cu direcția de citire</string>
|
||||
<string name="update_check_eol">Această versiune Android nu mai este suportată</string>
|
||||
<string name="clipboard_copy_error">Nu s-a reușit copierea în clipboard</string>
|
||||
</resources>
|
|
@ -99,13 +99,13 @@
|
|||
<string name="download_notifier_unknown_error">Не могу скачать главу из-за непревиденной ошибки</string>
|
||||
<string name="download_progress">Загружен(о) %1$d%%</string>
|
||||
<string name="download_queue_error">Невозможно скачать главы. Можете попробовать еще раз в разделе загрузок</string>
|
||||
<string name="download_unread">Не прочитано</string>
|
||||
<string name="downloading">Загрузка…</string>
|
||||
<string name="download_unread">Непрочитано</string>
|
||||
<string name="downloading">Загружается…</string>
|
||||
<string name="dropped">Заброшено</string>
|
||||
<string name="error_category_exists">Категория с таким именем уже существует!</string>
|
||||
<string name="fetch_chapters_error">Не могу получить главы</string>
|
||||
<string name="fifth_to_last">Пятая от прочитанной главы</string>
|
||||
<string name="file_select_backup">Выбрать файл бэкапа</string>
|
||||
<string name="file_select_backup">Выбрать файл резервной копии</string>
|
||||
<string name="file_select_cover">Выбрать обложку</string>
|
||||
<string name="fourth_to_last">Четвёртая от прочитанной главы</string>
|
||||
<string name="information_empty_library">Ваша библиотека пуста. Добавьте тайтлы в библиотеку из Поиска.</string>
|
||||
|
@ -262,7 +262,7 @@
|
|||
<string name="action_restore">Восстановить</string>
|
||||
<string name="action_undo">Отменить</string>
|
||||
<string name="added_to_library">Манга была добавлена в библиотеку</string>
|
||||
<string name="backup_choice">Что вы хотите бэкапить\?</string>
|
||||
<string name="backup_choice">Что вы хотите резервировать\?</string>
|
||||
<string name="backup_created">Резевная копия создана</string>
|
||||
<string name="backup_restore_content">При восстановлении используются данные из источников, что может вызвать большой расход трафика.
|
||||
\n
|
||||
|
@ -279,17 +279,17 @@
|
|||
<string name="local_source">Локальная манга</string>
|
||||
<string name="manga">Манга</string>
|
||||
<string name="no_more_results">Больше нет результатов</string>
|
||||
<string name="pref_backup_directory">Каталог бэкапа</string>
|
||||
<string name="pref_backup_interval">Частота бэкапов</string>
|
||||
<string name="pref_backup_service_category">Автоматические бэкапы</string>
|
||||
<string name="pref_backup_slots">Максимальное количество бэкапов</string>
|
||||
<string name="pref_create_backup">Создать бэкап</string>
|
||||
<string name="pref_backup_directory">Каталог резервной копии</string>
|
||||
<string name="pref_backup_interval">Частота резервных копий</string>
|
||||
<string name="pref_backup_service_category">Автоматические резервные копии</string>
|
||||
<string name="pref_backup_slots">Максимальное количество резервных копий</string>
|
||||
<string name="pref_create_backup">Создать резервную копию</string>
|
||||
<string name="pref_create_backup_summ">Можно использовать для восстановления текущей библиотеки</string>
|
||||
<string name="pref_crop_borders">Обрезать поля</string>
|
||||
<string name="pref_refresh_library_tracking">Обновить отслеживание</string>
|
||||
<string name="pref_refresh_library_tracking_summary">Обновляет статус, оценку и последнюю прочитанную главу из сервисов отслеживания</string>
|
||||
<string name="pref_restore_backup">Восстановить из бэкапа</string>
|
||||
<string name="pref_restore_backup_summ">Восстановить библиотеку из бэкапа</string>
|
||||
<string name="pref_restore_backup">Восстановить из резервной копии</string>
|
||||
<string name="pref_restore_backup_summ">Восстановить библиотеку из резервной копии</string>
|
||||
<string name="restore_completed">Восстановление завершено</string>
|
||||
<string name="restoring_backup">Восстановление из резервной копии</string>
|
||||
<string name="short_recent_updates">Обновления</string>
|
||||
|
@ -449,7 +449,7 @@
|
|||
<string name="updating_library">Обновление библиотеки</string>
|
||||
<string name="http_error_hint">Проверить страницу в WebView</string>
|
||||
<string name="battery_optimization_disabled">Оптимизация батареи уже выключена</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Помогает с фоновым обновлением библиотеки и бэкапом</string>
|
||||
<string name="pref_disable_battery_optimization_summary">Помогает с фоновым обновлением библиотеки и резевной копии</string>
|
||||
<string name="pref_disable_battery_optimization">Выключить оптимизацию батареи</string>
|
||||
<string name="theme_light_default">По умолчанию</string>
|
||||
<plurals name="update_check_notification_ext_updates">
|
||||
|
@ -506,10 +506,10 @@
|
|||
<string name="downloaded_only_summary">Фильтрует всю мангу в вашей библиотеке</string>
|
||||
<string name="check_for_updates">Проверить обновления</string>
|
||||
<string name="restoring_backup_canceled">Восстановление отменено</string>
|
||||
<string name="restoring_backup_error">Ошибка восстановления из бэкапа</string>
|
||||
<string name="restoring_backup_error">Ошибка восстановления из резервной копии</string>
|
||||
<string name="restore_in_progress">Восстановление уже выполняется</string>
|
||||
<string name="creating_backup_error">Ошибка бэкапа</string>
|
||||
<string name="backup_in_progress">Бэкап уже выполняется</string>
|
||||
<string name="creating_backup_error">Не удалось создать резервную копию</string>
|
||||
<string name="backup_in_progress">Резервная копия уже выполняется</string>
|
||||
<string name="restore_duration">%02d мин, %02d сек</string>
|
||||
<string name="pref_search_pinned_sources_only">Включать только закрепленные источники</string>
|
||||
<plurals name="download_queue_summary">
|
||||
|
@ -605,7 +605,7 @@
|
|||
</plurals>
|
||||
<string name="no_pinned_sources">У вас нет закрепленных источников</string>
|
||||
<string name="download_notifier_download_finish">Загрузка завершена</string>
|
||||
<string name="group_backup_restore">Бэкап и восстановление</string>
|
||||
<string name="group_backup_restore">Резервирование и восстановление</string>
|
||||
<string name="group_downloader">Загрузки</string>
|
||||
<string name="channel_complete">Завершение</string>
|
||||
<string name="channel_progress">Прогресс</string>
|
||||
|
@ -673,8 +673,8 @@
|
|||
<string name="action_display_show_number_of_items">Показать число объектов</string>
|
||||
<string name="right_and_left_nav">Справа и слева</string>
|
||||
<string name="pref_dual_page_split">Двухстраничное разделение</string>
|
||||
<string name="pref_dual_page_invert">Инвертировать двухстраничное размещение разделения</string>
|
||||
<string name="pref_dual_page_invert_summary">Если двухстраничное размещение разделения не соответствует направлению чтения</string>
|
||||
<string name="pref_dual_page_invert">Инвертировать двухстраничное разделение</string>
|
||||
<string name="pref_dual_page_invert_summary">Если двухстраничное разделение не соответствует направлению чтения</string>
|
||||
<string name="backup_restore_content_full">Данные из файла резевной копии будут восстановлены.
|
||||
\n
|
||||
\nВам будет нужно установить все недостающие расширения, и после этого войти в сервисы отслеживания для их использования.</string>
|
||||
|
@ -685,7 +685,7 @@
|
|||
<string name="nav_zone_next">Следующая</string>
|
||||
<string name="nav_zone_prev">Предыдущая</string>
|
||||
<string name="pref_show_navigation_mode_summary">Показывать зоны касания когда читалка открыта</string>
|
||||
<string name="pref_show_navigation_mode">Показывать наложение схемы навигации</string>
|
||||
<string name="pref_show_navigation_mode">Показывать наложение макета навигации</string>
|
||||
<string name="pref_dns_over_https">DNS по HTTPS</string>
|
||||
<string name="none">Нет</string>
|
||||
<string name="exclude">Исключать: %s</string>
|
||||
|
@ -694,4 +694,7 @@
|
|||
<string name="pref_download_new_categories_details">Манга в исключенных категориях не будет загруженна, даже если она также находится во включенных категориях.</string>
|
||||
<string name="pref_library_update_categories_details">Манга в исключенных категориях не будет обновляться, даже если она также находится во включенных категориях.</string>
|
||||
<string name="pref_category_auto_download">Автозагрузка</string>
|
||||
<string name="action_show_errors">Показать ошибки</string>
|
||||
<string name="update_check_eol">Эта версия Андроида больше не поддерживается</string>
|
||||
<string name="clipboard_copy_error">Не удалось скопировать в буфер обмена</string>
|
||||
</resources>
|
|
@ -87,7 +87,7 @@
|
|||
<string name="portrait">Orientamentu verticale</string>
|
||||
<string name="landscape">Orientamentu orizontale</string>
|
||||
<string name="default_columns">Predefinidu</string>
|
||||
<string name="pref_library_update_interval">Frecuèntzia de agiornamentu de sa biblioteca</string>
|
||||
<string name="pref_library_update_interval">Frecuèntzia de agiornamentu</string>
|
||||
<string name="update_never">Manuale</string>
|
||||
<string name="update_1hour">Cada ora</string>
|
||||
<string name="update_2hour">Cada 2 oras</string>
|
||||
|
@ -98,7 +98,7 @@
|
|||
<string name="update_48hour">Cada 2 dies</string>
|
||||
<string name="update_weekly">Cada chida</string>
|
||||
<string name="all">Totus</string>
|
||||
<string name="pref_library_update_restriction">Restritziones a s\'agiornamentu de sa biblioteca</string>
|
||||
<string name="pref_library_update_restriction">Restritziones a s\'agiornamentu</string>
|
||||
<string name="pref_library_update_restriction_summary">Agiorna petzi cando sas cunditziones benint rispetadas</string>
|
||||
<string name="charging">Carrighende</string>
|
||||
<string name="pref_update_only_non_completed">Agiorna sos manga in cursu ebbia</string>
|
||||
|
@ -376,7 +376,7 @@
|
|||
<string name="filter_mode_lighten">Istransi / Acrari</string>
|
||||
<string name="filter_mode_darken">Brùsia / Iscuri</string>
|
||||
<string name="label_help">Agiudu</string>
|
||||
<string name="pref_library_update_prioritization">Òrdine de agiornamentu de sa biblioteca</string>
|
||||
<string name="pref_library_update_prioritization">Òrdine de agiornamentu</string>
|
||||
<string name="no_results_found">Perunu resultadu agadadu</string>
|
||||
<string name="migration_selection_prompt">Ischerta una mitza dae sa cale tramudare</string>
|
||||
<string name="action_webview_back">In segus</string>
|
||||
|
@ -387,7 +387,7 @@
|
|||
<string name="ext_obsolete">Obsoleta</string>
|
||||
<string name="obsolete_extension_message">Cust\'estensione no est prus a disponimentu.</string>
|
||||
<string name="pref_date_format">Formadu de sa data</string>
|
||||
<string name="pref_category_library_update">Agiornamentos</string>
|
||||
<string name="pref_category_library_update">Agiornamentu globale</string>
|
||||
<string name="logout_title">Essire dae %1$s\?</string>
|
||||
<string name="logout">Essi</string>
|
||||
<string name="logout_success">Ses essidu</string>
|
||||
|
@ -669,4 +669,10 @@
|
|||
<string name="include">Include: %s</string>
|
||||
<string name="none">Perunu</string>
|
||||
<string name="action_sort_chapter_fetch_date">Data recuperada</string>
|
||||
</resources>
|
||||
<string name="pref_download_new_categories_details">Sos manga in sas categorias esclùdidas non s\'ant a iscarrigare nemmancu si sunt fintzas in categorias inclùdidas.</string>
|
||||
<string name="pref_category_auto_download">Iscarrigamentu automàticu</string>
|
||||
<string name="pref_library_update_categories_details">Sos manga in sas categorias esclùdidas non s\'ant a agiornare nemmancu si sunt fintzas in categorias inclùdidas.</string>
|
||||
<string name="action_show_errors">Ammustra sos errores</string>
|
||||
<string name="clipboard_copy_error">Còpia in punta de billete fallida</string>
|
||||
<string name="update_check_eol">Custa versione de Android no est prus suportada</string>
|
||||
</resources>
|
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_download_new_categories_details">Manga i uteslutna kategorier laddas inte ner även om de också ingår i inkluderade kategorier.</string>
|
||||
<string name="pref_category_auto_download">Ladda ned automatiskt</string>
|
||||
<string name="pref_library_update_categories_details">Manga i uteslutna kategorier uppdateras inte även om de också ingår i inkluderade kategorier.</string>
|
||||
<string name="action_show_errors">Visa fel</string>
|
||||
<string name="update_check_eol">Denna Android-version stöds inte längre</string>
|
||||
<string name="clipboard_copy_error">Kunde inte kopiera till urklipp</string>
|
||||
</resources>
|
|
@ -318,7 +318,7 @@
|
|||
<string name="confirm_set_image_as_cover">Bu görsel kapak resmi olarak kullanılsın mı\?</string>
|
||||
<string name="migration_info">Taşınılacak kaynağı seçmek için dokunun</string>
|
||||
<string name="migration_dialog_what_to_include">Eklenecek veriyi seç</string>
|
||||
<string name="migrate">Taşın</string>
|
||||
<string name="migrate">Geçiş yap</string>
|
||||
<string name="copy">Kopyala</string>
|
||||
<string name="download_queue_error">Bölümler indirilemedi. İndirmeler bölümünden yeniden deneyebilirsiniz</string>
|
||||
<string name="notification_update_progress">Güncelleme ilerlemesi: %1$d/%2$d</string>
|
||||
|
@ -672,4 +672,7 @@
|
|||
<string name="pref_download_new_categories_details">Hariç tutulan kategorilerdeki manga, dahil edilen kategorilerde olsa bile indirilmeyecektir.</string>
|
||||
<string name="pref_category_auto_download">Otomatik indir</string>
|
||||
<string name="pref_library_update_categories_details">Hariç tutulan kategorilerdeki manga, dahil edilen kategorilerde olsa bile güncellenmeyecektir.</string>
|
||||
<string name="action_show_errors">Hataları göster</string>
|
||||
<string name="update_check_eol">Bu Android sürümü artık desteklenmiyor</string>
|
||||
<string name="clipboard_copy_error">Panoya kopyalanamadı</string>
|
||||
</resources>
|
|
@ -692,4 +692,5 @@
|
|||
<string name="none">Ніхто</string>
|
||||
<string name="pref_library_update_categories_details">Мангу в виключених категоріях не буде оновлено, навіть якщо вона також знаходиться у включених категоріях.</string>
|
||||
<string name="action_sort_chapter_fetch_date">Дата отримання</string>
|
||||
<string name="action_show_errors">Показати помилки</string>
|
||||
</resources>
|
|
@ -1,9 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Tachiyomi.Light.Api23">
|
||||
<item name="android:statusBarColor">@color/md_white_1000</item>
|
||||
<style name="Base.V23.Theme.Tachiyomi.Light" parent="Base.Theme.Tachiyomi.Light">
|
||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Tachiyomi.Light" parent="Base.V23.Theme.Tachiyomi.Light" />
|
||||
</resources>
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<style name="Theme.Tachiyomi.Light.Api27">
|
||||
<item name="android:statusBarColor">@color/md_white_1000</item>
|
||||
<item name="android:windowLightStatusBar">true</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/md_white_1000</item>
|
||||
<style name="Base.V27.Theme.Tachiyomi.Light" parent="Base.V23.Theme.Tachiyomi.Light">
|
||||
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:windowLightNavigationBar">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Tachiyomi.Light" parent="Base.V27.Theme.Tachiyomi.Light" />
|
||||
</resources>
|
||||
|
|
|
@ -180,7 +180,7 @@
|
|||
<string name="pref_remove_after_marked_as_read">手动标记为已读后</string>
|
||||
<string name="pref_remove_after_read">阅毕</string>
|
||||
<string name="custom_dir">自定义路径</string>
|
||||
<string name="disabled">关闭</string>
|
||||
<string name="disabled">已禁用</string>
|
||||
<string name="last_read_chapter">最后阅读的章节</string>
|
||||
<string name="second_to_last">倒数第二章</string>
|
||||
<string name="third_to_last">倒数第三章</string>
|
||||
|
@ -393,7 +393,7 @@
|
|||
<string name="logout_success">你已登出</string>
|
||||
<string name="paused">已暂停</string>
|
||||
<string name="currently_reading">正在阅读</string>
|
||||
<string name="want_to_read">想要阅读</string>
|
||||
<string name="want_to_read">想读</string>
|
||||
<string name="label_more">更多</string>
|
||||
<string name="action_sort_latest_chapter">最新章节</string>
|
||||
<string name="action_view_chapters">查看章节</string>
|
||||
|
@ -660,4 +660,7 @@
|
|||
<string name="pref_library_update_categories_details">应用不会更新位于排除分类中的漫画,即使它们同样位于包括的分类中。</string>
|
||||
<string name="pref_download_new_categories_details">应用不会下载位于排除分类中的漫画,即使它们同样位于包括的分类中。</string>
|
||||
<string name="pref_category_auto_download">自动下载</string>
|
||||
<string name="action_show_errors">显示错误</string>
|
||||
<string name="update_check_eol">英勇不再支持此 Android 版本</string>
|
||||
<string name="clipboard_copy_error">未能复制到剪贴板</string>
|
||||
</resources>
|
|
@ -451,7 +451,6 @@
|
|||
<string name="version">Version</string>
|
||||
<string name="build_time">Build time</string>
|
||||
<string name="whats_new">What\'s new</string>
|
||||
<string name="notices">Preview build notices</string>
|
||||
<string name="licenses">Open source licenses</string>
|
||||
<string name="check_for_updates">Check for updates</string>
|
||||
<string name="updated_version">Updated to v%1$s</string>
|
||||
|
|
|
@ -47,8 +47,9 @@
|
|||
<item name="android:textDirection">locale</item>
|
||||
|
||||
<!-- Themes -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:statusBarColor">@color/md_black_1000</item>
|
||||
<item name="android:navigationBarColor">@color/md_black_1000</item>
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">@null</item>
|
||||
<item name="android:enforceNavigationBarContrast" tools:targetApi="Q">false</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="elevationOverlayEnabled">false</item>
|
||||
|
@ -84,28 +85,24 @@
|
|||
<!-- Custom Attributes-->
|
||||
<item name="colorLibrarySelection">?attr/colorAccent</item>
|
||||
<item name="colorLibrarySelectionActive">@color/selectorColorLight</item>
|
||||
<item name="colorFilterActive">@color/filterColorDark</item>
|
||||
<item name="colorFilterActive">@color/filterColorLight</item>
|
||||
</style>
|
||||
|
||||
<!--===========-->
|
||||
<!-- Main Theme-->
|
||||
<!--===========-->
|
||||
<style name="Theme.Tachiyomi.Light" parent="Theme.Base">
|
||||
<item name="android:statusBarColor">@color/md_black_1000</item>
|
||||
<item name="android:navigationBarColor">@color/md_black_1000_54</item>
|
||||
<style name="Base.Theme.Tachiyomi.Light" parent="Theme.Base" />
|
||||
<style name="Theme.Tachiyomi.Light" parent="Base.Theme.Tachiyomi.Light" />
|
||||
|
||||
<item name="colorFilterActive">@color/filterColorLight</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Tachiyomi.LightBlue" parent="Theme.Base">
|
||||
<style name="Theme.Tachiyomi.Light.Blue">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorOnPrimary">@color/textColorPrimaryDark</item>
|
||||
<item name="colorAccentOnPrimary">@color/textColorPrimaryDark</item>
|
||||
<item name="colorPrimaryVariant">@color/colorPrimaryDark</item>
|
||||
|
||||
<item name="colorFilterActive">@color/filterColorDark</item>
|
||||
<item name="actionBarTheme">@style/Theme.Toolbar.Light</item>
|
||||
|
||||
<item name="android:navigationBarColor">@color/colorPrimary_70</item>
|
||||
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
|
||||
<item name="android:windowLightNavigationBar" tools:targetApi="o_mr1">false</item>
|
||||
</style>
|
||||
|
||||
<!--=============-->
|
||||
|
@ -145,6 +142,7 @@
|
|||
<!-- Themes -->
|
||||
<item name="android:statusBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:navigationBarColor">?attr/colorPrimary</item>
|
||||
<item name="android:navigationBarDividerColor" tools:targetApi="o_mr1">@null</item>
|
||||
<item name="android:enforceNavigationBarContrast" tools:targetApi="Q">false</item>
|
||||
<item name="windowActionModeOverlay">true</item>
|
||||
<item name="elevationOverlayEnabled">false</item>
|
||||
|
@ -184,16 +182,15 @@
|
|||
<item name="colorFilterActive">@color/filterColorDark</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Tachiyomi.Dark" parent="Theme.Base.Dark">
|
||||
</style>
|
||||
<style name="Theme.Tachiyomi.Dark" parent="Theme.Base.Dark" />
|
||||
|
||||
<style name="Theme.Tachiyomi.DarkBlue" parent="Theme.Base.Dark">
|
||||
<style name="Theme.Tachiyomi.Dark.Blue">
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorAccentOnPrimary">@color/textColorPrimaryDark</item>
|
||||
<item name="colorPrimaryVariant">@color/colorPrimary</item>
|
||||
</style>
|
||||
|
||||
<style name="Theme.Tachiyomi.Amoled" parent="Theme.Base.Dark">
|
||||
<style name="Theme.Tachiyomi.Dark.Amoled">
|
||||
<item name="colorPrimary">@color/colorAmoledPrimary</item>
|
||||
<item name="colorPrimaryVariant">@color/colorAmoledPrimary</item>
|
||||
<item name="colorSurface">@color/colorAmoledPrimary</item>
|
||||
|
@ -255,7 +252,7 @@
|
|||
<!--===============-->
|
||||
<!-- Launch Screen -->
|
||||
<!--===============-->
|
||||
<style name="Theme.Splash" parent="Theme.Tachiyomi.LightBlue">
|
||||
<style name="Theme.Splash" parent="Theme.Tachiyomi.Light.Blue">
|
||||
<item name="colorBackgroundSplash">@color/colorPrimary</item>
|
||||
|
||||
<item name="android:windowBackground">@drawable/splash_background</item>
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
# The setting is particularly useful for tweaking memory settings.
|
||||
# Default value: -Xmx10248m -XX:MaxPermSize=256m
|
||||
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
org.gradle.jvmargs=-Xmx3072m
|
||||
|
||||
# When configured, Gradle will run in incubating parallel mode.
|
||||
# This option should only be used with decoupled projects. More details, visit
|
||||
|
|
Loading…
Reference in a new issue