diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 133dd9c3b..36fcceec4 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -2,7 +2,7 @@ I acknowledge that: -- I have updated to the latest version of the app (stable is v0.10.4) +- I have updated to the latest version of the app (stable is v0.10.5) - I have updated all extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 8b0162363..c3d809092 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ labels: "bug" I acknowledge that: -- I have updated to the latest version of the app (stable is v0.10.4) +- I have updated to the latest version of the app (stable is v0.10.5) - I have updated all extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index 5c0b5d084..0179a75d2 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -9,7 +9,7 @@ labels: "feature" I acknowledge that: -- I have updated to the latest version of the app (stable is v0.10.4) +- I have updated to the latest version of the app (stable is v0.10.5) - I have updated all extensions - If this is an issue with an extension, that I should be opening an issue in https://github.com/inorichi/tachiyomi-extensions diff --git a/README.md b/README.md index f46d30475..fdeeb25f9 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ | Build | Stable | Weekly Preview | Contribute | Support Server | |-------|----------|---------|------------|---------| -| [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=download)](https://github.com/inorichi/tachiyomi/releases) | [![latest weekly build](https://img.shields.io/badge/download-latest%20build-blue.svg)](http://tachiyomi.kanade.eu/latest) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/tachiyomi) | +| [![Travis](https://img.shields.io/travis/inorichi/tachiyomi.svg)](https://travis-ci.org/inorichi/tachiyomi) | [![stable release](https://img.shields.io/github/release/inorichi/tachiyomi.svg?maxAge=3600&label=download)](https://github.com/inorichi/tachiyomi/releases) | [![latest weekly build](https://img.shields.io/github/v/release/tachiyomiorg/android-app-preview.svg?maxAge=3600&label=download)](https://github.com/tachiyomiorg/android-app-preview/releases) | [![Translation status](https://hosted.weblate.org/widgets/tachiyomi/-/svg-badge.svg)](https://hosted.weblate.org/engage/tachiyomi/?utm_source=widget) | [![Discord](https://img.shields.io/discord/349436576037732353.svg)](https://discord.gg/tachiyomi) | # ![app icon](./.github/readme-images/app-icon.png)Tachiyomi @@ -23,7 +23,7 @@ Features include: ## Download Get the app from our [releases page](https://github.com/inorichi/tachiyomi/releases). -If you want to try new features before they get to the stable release, you can download the preview version [here](http://tachiyomi.kanade.eu/latest). +If you want to try new features before they get to the stable release, you can download the preview version [here](https://github.com/tachiyomiorg/android-app-preview/releases). ## Issues, Feature Requests and Contributing diff --git a/app/build.gradle b/app/build.gradle index 0223a0054..bc98d4048 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -40,8 +40,8 @@ android { minSdkVersion AndroidConfig.minSdk targetSdkVersion AndroidConfig.targetSdk testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" - versionCode 50 - versionName "0.10.4" + versionCode 51 + versionName "0.10.5" buildConfigField "String", "COMMIT_COUNT", "\"${getCommitCount()}\"" buildConfigField "String", "COMMIT_SHA", "\"${getGitSha()}\"" @@ -133,7 +133,7 @@ dependencies { implementation 'androidx.biometric:biometric:1.1.0-alpha02' implementation 'androidx.browser:browser:1.2.0' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:2.0.0' + implementation 'androidx.constraintlayout:constraintlayout:2.0.1' implementation 'androidx.coordinatorlayout:coordinatorlayout:1.1.0' implementation 'androidx.core:core-ktx:1.4.0-alpha01' implementation 'androidx.multidex:multidex:2.0.1' @@ -163,14 +163,14 @@ dependencies { implementation 'com.github.pwittchen:reactivenetwork:0.13.0' // Network client - final okhttp_version = '4.8.1' + final okhttp_version = '4.9.0' implementation "com.squareup.okhttp3:okhttp:$okhttp_version" implementation "com.squareup.okhttp3:logging-interceptor:$okhttp_version" implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:$okhttp_version" - implementation 'com.squareup.okio:okio:2.7.0' + implementation 'com.squareup.okio:okio:2.8.0' // TLS 1.3 support for Android < 10 - implementation 'org.conscrypt:conscrypt-android:2.4.0' + implementation 'org.conscrypt:conscrypt-android:2.5.1' // REST final retrofit_version = '2.9.0' @@ -281,10 +281,6 @@ dependencies { // For detecting memory leaks; see https://square.github.io/leakcanary/ // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.4' - - // Debug tool; see https://fbflipper.com/ -// debugImplementation 'com.facebook.flipper:flipper:0.50.0' -// debugImplementation 'com.facebook.soloader:soloader:0.9.0' } buildscript { @@ -312,7 +308,7 @@ task copyResources(type: Copy) { include '**/*' } -preBuild.dependsOn(ktlintFormat, copyResources) +preBuild.dependsOn(formatKotlin, copyResources) if (getGradle().getStartParameter().getTaskRequests().toString().contains("Standard")) { apply plugin: 'com.google.gms.google-services' diff --git a/app/src/main/java/eu/kanade/tachiyomi/App.kt b/app/src/main/java/eu/kanade/tachiyomi/App.kt index 91c49c136..762b324f3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/App.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/App.kt @@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.util.system.LocaleHelper -import java.security.Security import org.acra.ACRA import org.acra.annotation.AcraCore import org.acra.annotation.AcraHttpSender @@ -24,6 +23,7 @@ import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.InjektScope import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.registry.default.DefaultRegistrar +import java.security.Security @AcraCore( buildConfigClass = BuildConfig::class, diff --git a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt index 3b748d77a..204ca4edf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/Migrations.kt @@ -1,11 +1,15 @@ package eu.kanade.tachiyomi +import androidx.core.content.edit +import androidx.preference.PreferenceManager import eu.kanade.tachiyomi.data.backup.BackupCreatorJob import eu.kanade.tachiyomi.data.library.LibraryUpdateJob +import eu.kanade.tachiyomi.data.preference.PreferenceKeys import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.updater.UpdaterJob import eu.kanade.tachiyomi.extension.ExtensionUpdateJob import eu.kanade.tachiyomi.ui.library.LibrarySort +import eu.kanade.tachiyomi.widget.ExtendedNavigationView import java.io.File object Migrations { @@ -89,6 +93,25 @@ object Migrations { preferences.librarySortingMode().set(LibrarySort.ALPHA) } } + if (oldVersion < 52) { + // Migrate library filters to tri-state versions + val prefs = PreferenceManager.getDefaultSharedPreferences(context) + fun convertBooleanPrefToTriState(key: String): Int { + val oldPrefValue = prefs.getBoolean(key, false) + return if (oldPrefValue) ExtendedNavigationView.Item.TriStateGroup.STATE_INCLUDE + else ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE + } + prefs.edit { + putInt(PreferenceKeys.filterDownloaded, convertBooleanPrefToTriState("pref_filter_downloaded_key")) + remove("pref_filter_downloaded_key") + + putInt(PreferenceKeys.filterUnread, convertBooleanPrefToTriState("pref_filter_unread_key")) + remove("pref_filter_unread_key") + + putInt(PreferenceKeys.filterCompleted, convertBooleanPrefToTriState("pref_filter_completed_key")) + remove("pref_filter_completed_key") + } + } return true } return false diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt index 8c62e9476..c78f87011 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupCreatorJob.kt @@ -8,9 +8,9 @@ import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import java.util.concurrent.TimeUnit import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit class BackupCreatorJob(private val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { @@ -36,8 +36,10 @@ class BackupCreatorJob(private val context: Context, workerParams: WorkerParamet val interval = prefInterval ?: preferences.backupInterval().get() if (interval > 0) { val request = PeriodicWorkRequestBuilder( - interval.toLong(), TimeUnit.HOURS, - 10, TimeUnit.MINUTES + interval.toLong(), + TimeUnit.HOURS, + 10, + TimeUnit.MINUTES ) .addTag(TAG) .build() diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt index 8761f0a7f..66a7e55d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupManager.kt @@ -50,10 +50,10 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import kotlin.math.max import rx.Observable import timber.log.Timber import uy.kohesive.injekt.injectLazy +import kotlin.math.max class BackupManager(val context: Context, version: Int = CURRENT_VERSION) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt index e48f2d334..d7e24e6eb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupNotifier.kt @@ -11,9 +11,9 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationManager +import uy.kohesive.injekt.injectLazy import java.io.File import java.util.concurrent.TimeUnit -import uy.kohesive.injekt.injectLazy internal class BackupNotifier(private val context: Context) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt index bf832a8fc..df51b1a99 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/backup/BackupRestoreService.kt @@ -32,12 +32,9 @@ import eu.kanade.tachiyomi.data.database.models.TrackImpl import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.Source +import eu.kanade.tachiyomi.util.chapter.NoChaptersException import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning -import java.io.File -import java.text.SimpleDateFormat -import java.util.Date -import java.util.Locale import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.Job @@ -45,6 +42,10 @@ import kotlinx.coroutines.launch import rx.Observable import timber.log.Timber import uy.kohesive.injekt.injectLazy +import java.io.File +import java.text.SimpleDateFormat +import java.util.Date +import java.util.Locale /** * Restores backup from a JSON file. @@ -398,7 +399,12 @@ class BackupRestoreService : Service() { return backupManager.restoreChapterFetchObservable(source, manga, chapters) // If there's any error, return empty update and continue. .onErrorReturn { - errors.add(Date() to "${manga.title} - ${it.message}") + val errorMessage = if (it is NoChaptersException) { + getString(R.string.no_chapters_error) + } else { + it.message + } + errors.add(Date() to "${manga.title} - $errorMessage") Pair(emptyList(), emptyList()) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt index bb63a8225..fab8a2b31 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/cache/ChapterCache.kt @@ -9,13 +9,13 @@ 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 java.io.File -import java.io.IOException 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 /** * Class used to create chapter cache diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt index d5d20d87a..99ae7cbb8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/queries/MangaQueries.kt @@ -83,6 +83,11 @@ interface MangaQueries : DbProvider { .withPutResolver(MangaFlagsPutResolver()) .prepare() + fun updateFlags(mangas: List) = db.put() + .objects(mangas) + .withPutResolver(MangaFlagsPutResolver(true)) + .prepare() + fun updateLastUpdated(manga: Manga) = db.put() .`object`(manga) .withPutResolver(MangaLastUpdatedPutResolver()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt index 0a30da7da..2a8e08383 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/database/resolvers/MangaFlagsPutResolver.kt @@ -9,7 +9,7 @@ import eu.kanade.tachiyomi.data.database.inTransactionReturn import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.tables.MangaTable -class MangaFlagsPutResolver : PutResolver() { +class MangaFlagsPutResolver(private val updateAll: Boolean = false) : PutResolver() { override fun performPut(db: StorIOSQLite, manga: Manga) = db.inTransactionReturn { val updateQuery = mapToUpdateQuery(manga) @@ -19,11 +19,21 @@ class MangaFlagsPutResolver : PutResolver() { PutResult.newUpdateResult(numberOfRowsUpdated, updateQuery.table()) } - fun mapToUpdateQuery(manga: Manga) = UpdateQuery.builder() - .table(MangaTable.TABLE) - .where("${MangaTable.COL_ID} = ?") - .whereArgs(manga.id) - .build() + fun mapToUpdateQuery(manga: Manga): UpdateQuery { + val builder = UpdateQuery.builder() + + return if (updateAll) { + builder + .table(MangaTable.TABLE) + .build() + } else { + builder + .table(MangaTable.TABLE) + .where("${MangaTable.COL_ID} = ?") + .whereArgs(manga.id) + .build() + } + } fun mapToContentValues(manga: Manga) = ContentValues(1).apply { put(MangaTable.COL_CHAPTER_FLAGS, manga.chapter_flags) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt index f51578c43..edf719e74 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadCache.kt @@ -7,10 +7,10 @@ import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.source.SourceManager -import java.util.concurrent.TimeUnit import kotlinx.coroutines.flow.onEach import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit /** * Cache where we dump the downloads directory from the filesystem. This class is needed because diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt index f2136e7c1..16bcee8de 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/DownloadNotifier.kt @@ -12,8 +12,8 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationManager -import java.util.regex.Pattern import uy.kohesive.injekt.injectLazy +import java.util.regex.Pattern /** * DownloadNotifier is used to show notifications when downloading one or multiple chapters. @@ -107,7 +107,9 @@ internal class DownloadNotifier(private val context: Context) { } val downloadingProgressText = context.getString( - R.string.chapter_downloading_progress, download.downloadedImages, download.pages!!.size + R.string.chapter_downloading_progress, + download.downloadedImages, + download.pages!!.size ) if (preferences.hideNotificationContent()) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt index 4382333d8..d107f4cde 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/Downloader.kt @@ -22,7 +22,6 @@ import eu.kanade.tachiyomi.util.lang.plusAssign import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.saveTo import eu.kanade.tachiyomi.util.system.ImageUtil -import java.io.File import kotlinx.coroutines.async import okhttp3.Response import rx.Observable @@ -31,6 +30,7 @@ import rx.schedulers.Schedulers import rx.subscriptions.CompositeSubscription import timber.log.Timber import uy.kohesive.injekt.injectLazy +import java.io.File /** * This class is the one in charge of downloading chapters. diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt index 79dde6a6e..90207b9e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/download/model/DownloadQueue.kt @@ -5,9 +5,9 @@ import eu.kanade.tachiyomi.data.database.models.Chapter import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.DownloadStore import eu.kanade.tachiyomi.source.model.Page -import java.util.concurrent.CopyOnWriteArrayList import rx.Observable import rx.subjects.PublishSubject +import java.util.concurrent.CopyOnWriteArrayList class DownloadQueue( private val store: DownloadStore, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/FileFetcher.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/FileFetcher.kt index 91da7c558..a54c3cede 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/glide/FileFetcher.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/FileFetcher.kt @@ -5,12 +5,12 @@ import android.util.Log import com.bumptech.glide.Priority import com.bumptech.glide.load.DataSource import com.bumptech.glide.load.data.DataFetcher +import timber.log.Timber import java.io.File import java.io.FileInputStream import java.io.FileNotFoundException import java.io.IOException import java.io.InputStream -import timber.log.Timber open class FileFetcher(private val filePath: String = "") : DataFetcher { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaThumbnailModelLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaThumbnailModelLoader.kt index ca478cc74..b3cf79a15 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaThumbnailModelLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/MangaThumbnailModelLoader.kt @@ -14,10 +14,10 @@ import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.util.isLocal -import java.io.InputStream import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import java.io.InputStream /** * A class for loading a cover associated with a [Manga] that can be present in our own cache. diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt index 2182fa868..dca2e0879 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/glide/TachiGlideModule.kt @@ -14,9 +14,9 @@ import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions import com.bumptech.glide.module.AppGlideModule import com.bumptech.glide.request.RequestOptions import eu.kanade.tachiyomi.network.NetworkHelper -import java.io.InputStream import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.io.InputStream /** * Class used to update Glide module settings diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt index 9e9731030..f2055a654 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateJob.kt @@ -9,9 +9,9 @@ import androidx.work.WorkManager import androidx.work.Worker import androidx.work.WorkerParameters import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import java.util.concurrent.TimeUnit import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit class LibraryUpdateJob(private val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { @@ -45,8 +45,10 @@ class LibraryUpdateJob(private val context: Context, workerParams: WorkerParamet .build() val request = PeriodicWorkRequestBuilder( - interval.toLong(), TimeUnit.HOURS, - 10, TimeUnit.MINUTES + interval.toLong(), + TimeUnit.HOURS, + 10, + TimeUnit.MINUTES ) .addTag(TAG) .setConstraints(constraints) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt index 8982730e0..697d76b3f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateNotifier.kt @@ -22,9 +22,9 @@ import eu.kanade.tachiyomi.util.lang.chop import eu.kanade.tachiyomi.util.system.notification import eu.kanade.tachiyomi.util.system.notificationBuilder import eu.kanade.tachiyomi.util.system.notificationManager +import uy.kohesive.injekt.injectLazy import java.text.DecimalFormat import java.text.DecimalFormatSymbols -import uy.kohesive.injekt.injectLazy class LibraryUpdateNotifier(private val context: Context) { @@ -198,18 +198,23 @@ class LibraryUpdateNotifier(private val context: Context) { // Mark chapters as read action addAction( - R.drawable.ic_glasses_black_24dp, context.getString(R.string.action_mark_as_read), + R.drawable.ic_glasses_black_24dp, + context.getString(R.string.action_mark_as_read), NotificationReceiver.markAsReadPendingBroadcast( context, - manga, chapters, Notifications.ID_NEW_CHAPTERS + manga, + chapters, + Notifications.ID_NEW_CHAPTERS ) ) // View chapters action addAction( - R.drawable.ic_book_24dp, context.getString(R.string.action_view_chapters), + R.drawable.ic_book_24dp, + context.getString(R.string.action_view_chapters), NotificationReceiver.openChapterPendingActivity( context, - manga, Notifications.ID_NEW_CHAPTERS + manga, + Notifications.ID_NEW_CHAPTERS ) ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt index 597376e5a..49d64db7c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/library/LibraryUpdateService.kt @@ -6,6 +6,7 @@ import android.content.Intent import android.os.Build import android.os.IBinder import android.os.PowerManager +import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.cache.CoverCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category @@ -21,20 +22,21 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.SManga +import eu.kanade.tachiyomi.util.chapter.NoChaptersException import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning -import java.io.File -import java.util.concurrent.atomic.AtomicInteger import rx.Observable import rx.Subscription import rx.schedulers.Schedulers import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.io.File +import java.util.concurrent.atomic.AtomicInteger /** * This class will take care of updating the chapters of the manga from the library. It can be @@ -268,7 +270,12 @@ class LibraryUpdateService( updateManga(manga) // If there's any error, return empty update and continue. .onErrorReturn { - failedUpdates.add(Pair(manga, it.message)) + val errorMessage = if (it is NoChaptersException) { + getString(R.string.no_chapters_error) + } else { + it.message + } + failedUpdates.add(Pair(manga, errorMessage)) Pair(emptyList(), emptyList()) } // Filter out mangas without new chapters (or failed). diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt index 695b608bb..4960327b9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/NotificationReceiver.kt @@ -7,7 +7,6 @@ import android.content.Intent import android.net.Uri import android.os.Build import android.os.Handler -import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.backup.BackupRestoreService import eu.kanade.tachiyomi.data.database.DatabaseHelper @@ -26,10 +25,11 @@ import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.system.notificationManager import eu.kanade.tachiyomi.util.system.toast -import java.io.File import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import java.io.File +import eu.kanade.tachiyomi.BuildConfig.APPLICATION_ID as ID /** * Global [BroadcastReceiver] that runs on UI thread @@ -56,19 +56,22 @@ class NotificationReceiver : BroadcastReceiver() { // Launch share activity and dismiss notification ACTION_SHARE_IMAGE -> shareImage( - context, intent.getStringExtra(EXTRA_FILE_LOCATION), + context, + intent.getStringExtra(EXTRA_FILE_LOCATION), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1) ) // Delete image from path and dismiss notification ACTION_DELETE_IMAGE -> deleteImage( - context, intent.getStringExtra(EXTRA_FILE_LOCATION), + context, + intent.getStringExtra(EXTRA_FILE_LOCATION), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1) ) // Share backup file ACTION_SHARE_BACKUP -> shareBackup( - context, intent.getParcelableExtra(EXTRA_URI), + context, + intent.getParcelableExtra(EXTRA_URI), intent.getIntExtra(EXTRA_NOTIFICATION_ID, -1) ) ACTION_CANCEL_RESTORE -> cancelRestore( @@ -80,7 +83,8 @@ class NotificationReceiver : BroadcastReceiver() { // Open reader activity ACTION_OPEN_CHAPTER -> { openChapter( - context, intent.getLongExtra(EXTRA_MANGA_ID, -1), + context, + intent.getLongExtra(EXTRA_MANGA_ID, -1), intent.getLongExtra(EXTRA_CHAPTER_ID, -1) ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt index 0bd84af86..b55b53fed 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/notification/Notifications.kt @@ -82,53 +82,62 @@ object Notifications { listOf( NotificationChannel( - CHANNEL_COMMON, context.getString(R.string.channel_common), + CHANNEL_COMMON, + context.getString(R.string.channel_common), NotificationManager.IMPORTANCE_LOW ), NotificationChannel( - CHANNEL_LIBRARY, context.getString(R.string.channel_library), + CHANNEL_LIBRARY, + context.getString(R.string.channel_library), NotificationManager.IMPORTANCE_LOW ).apply { setShowBadge(false) }, NotificationChannel( - CHANNEL_DOWNLOADER_PROGRESS, context.getString(R.string.channel_progress), + CHANNEL_DOWNLOADER_PROGRESS, + context.getString(R.string.channel_progress), NotificationManager.IMPORTANCE_LOW ).apply { group = GROUP_DOWNLOADER setShowBadge(false) }, NotificationChannel( - CHANNEL_DOWNLOADER_COMPLETE, context.getString(R.string.channel_complete), + CHANNEL_DOWNLOADER_COMPLETE, + context.getString(R.string.channel_complete), NotificationManager.IMPORTANCE_LOW ).apply { group = GROUP_DOWNLOADER setShowBadge(false) }, NotificationChannel( - CHANNEL_DOWNLOADER_ERROR, context.getString(R.string.channel_errors), + CHANNEL_DOWNLOADER_ERROR, + context.getString(R.string.channel_errors), NotificationManager.IMPORTANCE_LOW ).apply { group = GROUP_DOWNLOADER setShowBadge(false) }, NotificationChannel( - CHANNEL_NEW_CHAPTERS, context.getString(R.string.channel_new_chapters), + CHANNEL_NEW_CHAPTERS, + context.getString(R.string.channel_new_chapters), NotificationManager.IMPORTANCE_DEFAULT ), NotificationChannel( - CHANNEL_UPDATES_TO_EXTS, context.getString(R.string.channel_ext_updates), + CHANNEL_UPDATES_TO_EXTS, + context.getString(R.string.channel_ext_updates), NotificationManager.IMPORTANCE_DEFAULT ), NotificationChannel( - CHANNEL_BACKUP_RESTORE_PROGRESS, context.getString(R.string.channel_progress), + CHANNEL_BACKUP_RESTORE_PROGRESS, + context.getString(R.string.channel_progress), NotificationManager.IMPORTANCE_LOW ).apply { group = GROUP_BACKUP_RESTORE setShowBadge(false) }, NotificationChannel( - CHANNEL_BACKUP_RESTORE_COMPLETE, context.getString(R.string.channel_complete), + CHANNEL_BACKUP_RESTORE_COMPLETE, + context.getString(R.string.channel_complete), NotificationManager.IMPORTANCE_HIGH ).apply { group = GROUP_BACKUP_RESTORE diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt index 2c7f66dcf..0d3d974ec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferenceKeys.kt @@ -109,11 +109,11 @@ object PreferenceKeys { const val downloadedOnly = "pref_downloaded_only" - const val filterDownloaded = "pref_filter_downloaded_key" + const val filterDownloaded = "pref_filter_library_downloaded" - const val filterUnread = "pref_filter_unread_key" + const val filterUnread = "pref_filter_library_unread" - const val filterCompleted = "pref_filter_completed_key" + const val filterCompleted = "pref_filter_library_completed" const val librarySortingMode = "library_sorting_mode" @@ -165,6 +165,18 @@ object PreferenceKeys { const val enableDoh = "enable_doh" + const val defaultChapterFilterByRead = "default_chapter_filter_by_read" + + const val defaultChapterFilterByDownloaded = "default_chapter_filter_by_downloaded" + + const val defaultChapterFilterByBookmarked = "default_chapter_filter_by_bookmarked" + + const val defaultChapterSortBySourceOrNumber = "default_chapter_sort_by_source_or_number" // and upload date + + const val defaultChapterSortByAscendingOrDescending = "default_chapter_sort_by_ascending_or_descending" + + const val defaultChapterDisplayByNameOrNumber = "default_chapter_display_by_name_or_number" + fun trackUsername(syncId: Int) = "pref_mangasync_username_$syncId" fun trackPassword(syncId: Int) = "pref_mangasync_password_$syncId" diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 9a83794ca..62a98904b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -8,19 +8,21 @@ import androidx.preference.PreferenceManager import com.tfcporciuncula.flow.FlowSharedPreferences import com.tfcporciuncula.flow.Preference import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys -import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values +import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode import eu.kanade.tachiyomi.data.preference.PreferenceValues.NsfwAllowance import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.anilist.Anilist +import eu.kanade.tachiyomi.widget.ExtendedNavigationView +import kotlinx.coroutines.ExperimentalCoroutinesApi +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.onEach import java.io.File import java.text.DateFormat import java.text.SimpleDateFormat import java.util.Locale -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.onEach +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys +import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values @OptIn(ExperimentalCoroutinesApi::class) fun Preference.asImmediateFlow(block: (value: T) -> Unit): Flow { @@ -209,11 +211,11 @@ class PreferencesHelper(val context: Context) { fun categoryTabs() = flowPrefs.getBoolean(Keys.categoryTabs, true) - fun filterDownloaded() = flowPrefs.getBoolean(Keys.filterDownloaded, false) + fun filterDownloaded() = flowPrefs.getInt(Keys.filterDownloaded, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE) - fun filterUnread() = flowPrefs.getBoolean(Keys.filterUnread, false) + fun filterUnread() = flowPrefs.getInt(Keys.filterUnread, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE) - fun filterCompleted() = flowPrefs.getBoolean(Keys.filterCompleted, false) + fun filterCompleted() = flowPrefs.getInt(Keys.filterCompleted, ExtendedNavigationView.Item.TriStateGroup.STATE_IGNORE) fun librarySortingMode() = flowPrefs.getInt(Keys.librarySortingMode, 0) @@ -254,4 +256,27 @@ class PreferencesHelper(val context: Context) { fun lastSearchQuerySearchSettings() = prefs.getString("last_search_query", "") fun lastSearchQuerySearchSettings(query: String) = prefs.edit { putString("last_search_query", query) } + + fun filterChapterByRead() = prefs.getInt(Keys.defaultChapterFilterByRead, Manga.SHOW_ALL) + + fun filterChapterByDownloaded() = prefs.getInt(Keys.defaultChapterFilterByDownloaded, Manga.SHOW_ALL) + + fun filterChapterByBookmarked() = prefs.getInt(Keys.defaultChapterFilterByBookmarked, Manga.SHOW_ALL) + + fun sortChapterBySourceOrNumber() = prefs.getInt(Keys.defaultChapterSortBySourceOrNumber, Manga.SORTING_SOURCE) + + fun displayChapterByNameOrNumber() = prefs.getInt(Keys.defaultChapterDisplayByNameOrNumber, Manga.DISPLAY_NAME) + + fun sortChapterByAscendingOrDescending() = prefs.getInt(Keys.defaultChapterSortByAscendingOrDescending, Manga.SORT_DESC) + + fun setChapterSettingsDefault(manga: Manga) { + prefs.edit { + putInt(Keys.defaultChapterFilterByRead, manga.readFilter) + putInt(Keys.defaultChapterFilterByDownloaded, manga.downloadedFilter) + putInt(Keys.defaultChapterFilterByBookmarked, manga.bookmarkedFilter) + putInt(Keys.defaultChapterSortBySourceOrNumber, manga.sorting) + putInt(Keys.defaultChapterDisplayByNameOrNumber, manga.displayMode) + putInt(Keys.defaultChapterSortByAscendingOrDescending, if (manga.sortDescending()) Manga.SORT_DESC else Manga.SORT_ASC) + } + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt index 5f0afdf4e..125867750 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistApi.kt @@ -13,12 +13,12 @@ import com.google.gson.JsonParser import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.network.asObservableSuccess -import java.util.Calendar import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import rx.Observable +import java.util.Calendar class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { @@ -271,9 +271,14 @@ class AnilistApi(val client: OkHttpClient, interceptor: AnilistInterceptor) { } return ALManga( - struct["id"].asInt, struct["title"]["romaji"].asString, struct["coverImage"]["large"].asString, - struct["description"].nullString.orEmpty(), struct["type"].asString, struct["status"].nullString.orEmpty(), - date, struct["chapters"].nullInt ?: 0 + struct["id"].asInt, + struct["title"]["romaji"].asString, + struct["coverImage"]["large"].asString, + struct["description"].nullString.orEmpty(), + struct["type"].asString, + struct["status"].nullString.orEmpty(), + date, + struct["chapters"].nullInt ?: 0 ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt index 8c8cfd576..f589e3b4d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/anilist/AnilistModels.kt @@ -4,9 +4,9 @@ import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.model.TrackSearch +import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Locale -import uy.kohesive.injekt.injectLazy data class ALManga( val media_id: Int, diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt index 24d95c78b..fedb1a956 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/bangumi/BangumiApi.kt @@ -12,13 +12,13 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.asObservableSuccess -import java.net.URLEncoder import okhttp3.CacheControl import okhttp3.FormBody import okhttp3.OkHttpClient import okhttp3.Request import rx.Observable import uy.kohesive.injekt.injectLazy +import java.net.URLEncoder class BangumiApi(private val client: OkHttpClient, interceptor: BangumiInterceptor) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt index 8b5ef74f1..412f04b55 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/kitsu/Kitsu.kt @@ -7,10 +7,10 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.model.TrackSearch -import java.text.DecimalFormat import rx.Completable import rx.Observable import uy.kohesive.injekt.injectLazy +import java.text.DecimalFormat class Kitsu(private val context: Context, id: Int) : TrackService(id) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt index 0939726b2..39ae21125 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/myanimelist/MyAnimeListApi.kt @@ -11,13 +11,6 @@ import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.util.lang.toCalendar import eu.kanade.tachiyomi.util.selectInt import eu.kanade.tachiyomi.util.selectText -import java.io.BufferedReader -import java.io.InputStreamReader -import java.text.SimpleDateFormat -import java.util.Calendar -import java.util.GregorianCalendar -import java.util.Locale -import java.util.zip.GZIPInputStream import okhttp3.FormBody import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.OkHttpClient @@ -30,6 +23,13 @@ import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.jsoup.parser.Parser import rx.Observable +import java.io.BufferedReader +import java.io.InputStreamReader +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.GregorianCalendar +import java.util.Locale +import java.util.zip.GZIPInputStream class MyAnimeListApi(private val client: OkHttpClient, interceptor: MyAnimeListInterceptor) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateChecker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateChecker.kt deleted file mode 100644 index 9f1e8eac1..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdateChecker.kt +++ /dev/null @@ -1,23 +0,0 @@ -package eu.kanade.tachiyomi.data.updater - -import eu.kanade.tachiyomi.BuildConfig -import eu.kanade.tachiyomi.data.updater.devrepo.DevRepoUpdateChecker -import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker - -abstract class UpdateChecker { - - companion object { - fun getUpdateChecker(): UpdateChecker { - return if (BuildConfig.DEBUG) { - DevRepoUpdateChecker() - } else { - GithubUpdateChecker() - } - } - } - - /** - * Returns observable containing release information - */ - abstract suspend fun checkForUpdate(): UpdateResult -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt index f786afc10..fd8d96521 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterJob.kt @@ -13,9 +13,10 @@ import androidx.work.Worker import androidx.work.WorkerParameters import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.notification.Notifications +import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker import eu.kanade.tachiyomi.util.system.notificationManager -import java.util.concurrent.TimeUnit import kotlinx.coroutines.runBlocking +import java.util.concurrent.TimeUnit class UpdaterJob(private val context: Context, workerParams: WorkerParameters) : Worker(context, workerParams) { @@ -23,7 +24,7 @@ class UpdaterJob(private val context: Context, workerParams: WorkerParameters) : override fun doWork(): Result { return runBlocking { try { - val result = UpdateChecker.getUpdateChecker().checkForUpdate() + val result = GithubUpdateChecker().checkForUpdate() if (result is UpdateResult.NewUpdate<*>) { val url = result.release.downloadLink @@ -65,8 +66,10 @@ class UpdaterJob(private val context: Context, workerParams: WorkerParameters) : .build() val request = PeriodicWorkRequestBuilder( - 3, TimeUnit.DAYS, - 3, TimeUnit.HOURS + 3, + TimeUnit.DAYS, + 3, + TimeUnit.HOURS ) .addTag(TAG) .setConstraints(constraints) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt index 39596ea22..81103643e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/UpdaterService.kt @@ -20,9 +20,9 @@ import eu.kanade.tachiyomi.util.storage.getUriCompat import eu.kanade.tachiyomi.util.storage.saveTo import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.isServiceRunning -import java.io.File import timber.log.Timber import uy.kohesive.injekt.injectLazy +import java.io.File class UpdaterService : Service() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoRelease.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoRelease.kt deleted file mode 100644 index 0f2b1ac75..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoRelease.kt +++ /dev/null @@ -1,13 +0,0 @@ -package eu.kanade.tachiyomi.data.updater.devrepo - -import eu.kanade.tachiyomi.data.updater.Release - -class DevRepoRelease(override val info: String) : Release { - - override val downloadLink: String - get() = LATEST_URL - - companion object { - const val LATEST_URL = "https://tachiyomi.kanade.eu/latest" - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateChecker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateChecker.kt deleted file mode 100644 index c224ba457..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateChecker.kt +++ /dev/null @@ -1,41 +0,0 @@ -package eu.kanade.tachiyomi.data.updater.devrepo - -import eu.kanade.tachiyomi.BuildConfig -import eu.kanade.tachiyomi.data.updater.UpdateChecker -import eu.kanade.tachiyomi.data.updater.UpdateResult -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.network.NetworkHelper -import eu.kanade.tachiyomi.network.await -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.withContext -import okhttp3.OkHttpClient -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -class DevRepoUpdateChecker : UpdateChecker() { - - private val client: OkHttpClient by lazy { - Injekt.get().client.newBuilder() - .followRedirects(false) - .build() - } - - private val versionRegex: Regex by lazy { - Regex("tachiyomi-r(\\d+).apk") - } - - override suspend fun checkForUpdate(): UpdateResult { - val response = withContext(Dispatchers.IO) { - client.newCall(GET(DevRepoRelease.LATEST_URL)).await() - } - - // Get latest repo version number from header in format "Location: tachiyomi-r1512.apk" - val latestVersionNumber: String = versionRegex.find(response.header("Location")!!)!!.groupValues[1] - - return if (latestVersionNumber.toInt() > BuildConfig.COMMIT_COUNT.toInt()) { - DevRepoUpdateResult.NewUpdate(DevRepoRelease("v$latestVersionNumber")) - } else { - DevRepoUpdateResult.NoNewUpdate() - } - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateResult.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateResult.kt deleted file mode 100644 index 1b62201a8..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/devrepo/DevRepoUpdateResult.kt +++ /dev/null @@ -1,9 +0,0 @@ -package eu.kanade.tachiyomi.data.updater.devrepo - -import eu.kanade.tachiyomi.data.updater.UpdateResult - -sealed class DevRepoUpdateResult : UpdateResult() { - - class NewUpdate(release: DevRepoRelease) : UpdateResult.NewUpdate(release) - class NoNewUpdate : UpdateResult.NoNewUpdate() -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubRelease.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubRelease.kt index 09f1b37d0..ec20699af 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubRelease.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubRelease.kt @@ -28,5 +28,5 @@ class GithubRelease( * Assets class containing download url. * @param downloadLink download url. */ - inner class Assets(@SerializedName("browser_download_url") val downloadLink: String) + class Assets(@SerializedName("browser_download_url") val downloadLink: String) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubService.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubService.kt index 88a9eb37c..e64a19d5e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubService.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubService.kt @@ -4,11 +4,12 @@ import eu.kanade.tachiyomi.network.NetworkHelper import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET +import retrofit2.http.Path import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get /** - * Used to connect with the GitHub API. + * Used to connect with the GitHub API to get the latest release version from a repo. */ interface GithubService { @@ -24,6 +25,6 @@ interface GithubService { } } - @GET("/repos/inorichi/tachiyomi/releases/latest") - suspend fun getLatestVersion(): GithubRelease + @GET("/repos/{repo}/releases/latest") + suspend fun getLatestVersion(@Path("repo", encoded = true) repo: String): GithubRelease } diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateChecker.kt b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateChecker.kt index 20ab5de5c..aa01b68e3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateChecker.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/updater/github/GithubUpdateChecker.kt @@ -1,23 +1,43 @@ package eu.kanade.tachiyomi.data.updater.github import eu.kanade.tachiyomi.BuildConfig -import eu.kanade.tachiyomi.data.updater.UpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateResult -class GithubUpdateChecker : UpdateChecker() { +class GithubUpdateChecker { private val service: GithubService = GithubService.create() - override suspend fun checkForUpdate(): UpdateResult { - val release = service.getLatestVersion() + private val repo: String by lazy { + if (BuildConfig.DEBUG) { + "tachiyomiorg/android-app-preview" + } else { + "inorichi/tachiyomi" + } + } - val newVersion = release.version.replace("[^\\d.]".toRegex(), "") + suspend fun checkForUpdate(): UpdateResult { + val release = service.getLatestVersion(repo) // Check if latest version is different from current version - return if (newVersion != BuildConfig.VERSION_NAME) { + return if (isNewVersion(release.version)) { GithubUpdateResult.NewUpdate(release) } else { GithubUpdateResult.NoNewUpdate() } } + + private fun isNewVersion(versionTag: String): Boolean { + // Removes prefixes like "r" or "v" + val newVersion = versionTag.replace("[^\\d.]".toRegex(), "") + + return if (BuildConfig.DEBUG) { + // Preview builds: based on releases in "tachiyomiorg/android-app-preview" repo + // tagged as something like "r1234" + newVersion.toInt() > BuildConfig.COMMIT_COUNT.toInt() + } else { + // Release builds: based on releases in "inorichi/tachiyomi" repo + // tagged as something like "v0.1.2" + newVersion != BuildConfig.VERSION_NAME + } + } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt index d9d2ed398..974b42827 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/ExtensionUpdateJob.kt @@ -16,10 +16,10 @@ import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.extension.api.ExtensionGithubApi import eu.kanade.tachiyomi.util.system.notification -import java.util.concurrent.TimeUnit import kotlinx.coroutines.coroutineScope import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParameters) : CoroutineWorker(context, workerParams) { @@ -73,8 +73,10 @@ class ExtensionUpdateJob(private val context: Context, workerParams: WorkerParam .build() val request = PeriodicWorkRequestBuilder( - 12, TimeUnit.HOURS, - 1, TimeUnit.HOURS + 12, + TimeUnit.HOURS, + 1, + TimeUnit.HOURS ) .addTag(TAG) .setConstraints(constraints) diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt index 2b989efc0..6b991f2b9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/api/ExtensionGithubApi.kt @@ -9,10 +9,10 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.LoadResult import eu.kanade.tachiyomi.extension.util.ExtensionLoader -import java.util.Date import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import uy.kohesive.injekt.injectLazy +import java.util.Date internal class ExtensionGithubApi { diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt index 7b698ee15..02ae9ae9f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt @@ -13,11 +13,11 @@ import com.jakewharton.rxrelay.PublishRelay import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.util.storage.getUriCompat -import java.io.File -import java.util.concurrent.TimeUnit import rx.Observable import rx.android.schedulers.AndroidSchedulers import timber.log.Timber +import java.io.File +import java.util.concurrent.TimeUnit /** * The installer which installs, updates and uninstalls the extensions. diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt index a2f51c731..f84a2337d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionLoader.kt @@ -178,7 +178,13 @@ internal object ExtensionLoader { } val extension = Extension.Installed( - extName, pkgName, versionName, versionCode, lang, isNsfw, sources, + extName, + pkgName, + versionName, + versionCode, + lang, + isNsfw, + sources, isUnofficial = signatureHash != officialSignature ) return LoadResult.Success(extension) diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt index 5b2cccde2..de143801b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/CloudflareInterceptor.kt @@ -16,15 +16,15 @@ import eu.kanade.tachiyomi.util.system.WebViewUtil import eu.kanade.tachiyomi.util.system.isOutdated import eu.kanade.tachiyomi.util.system.setDefaultSettings import eu.kanade.tachiyomi.util.system.toast -import java.io.IOException -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit import okhttp3.Cookie import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Interceptor import okhttp3.Request import okhttp3.Response import uy.kohesive.injekt.injectLazy +import java.io.IOException +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit class CloudflareInterceptor(private val context: Context) : Interceptor { diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt index aeb7ce5cd..0f31ee10b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/NetworkHelper.kt @@ -3,15 +3,15 @@ package eu.kanade.tachiyomi.network import android.content.Context import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import java.io.File -import java.net.InetAddress -import java.util.concurrent.TimeUnit import okhttp3.Cache import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.dnsoverhttps.DnsOverHttps import okhttp3.logging.HttpLoggingInterceptor import uy.kohesive.injekt.injectLazy +import java.io.File +import java.net.InetAddress +import java.util.concurrent.TimeUnit class NetworkHelper(context: Context) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt index 8d86629cf..5e8b660d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/OkHttpExtensions.kt @@ -1,9 +1,5 @@ package eu.kanade.tachiyomi.network -import java.io.IOException -import java.util.concurrent.atomic.AtomicBoolean -import kotlin.coroutines.resume -import kotlin.coroutines.resumeWithException import kotlinx.coroutines.suspendCancellableCoroutine import okhttp3.Call import okhttp3.Callback @@ -13,6 +9,10 @@ import okhttp3.Response import rx.Observable import rx.Producer import rx.Subscription +import java.io.IOException +import java.util.concurrent.atomic.AtomicBoolean +import kotlin.coroutines.resume +import kotlin.coroutines.resumeWithException fun Call.asObservable(): Observable { return Observable.unsafeCreate { subscriber -> @@ -54,22 +54,24 @@ fun Call.asObservable(): Observable { // Based on https://github.com/gildor/kotlin-coroutines-okhttp suspend fun Call.await(assertSuccess: Boolean = false): Response { return suspendCancellableCoroutine { continuation -> - enqueue(object : Callback { - override fun onResponse(call: Call, response: Response) { - if (assertSuccess && !response.isSuccessful) { - continuation.resumeWithException(Exception("HTTP error ${response.code}")) - return + enqueue( + object : Callback { + override fun onResponse(call: Call, response: Response) { + if (assertSuccess && !response.isSuccessful) { + continuation.resumeWithException(Exception("HTTP error ${response.code}")) + return + } + + continuation.resume(response) } - continuation.resume(response) + override fun onFailure(call: Call, e: IOException) { + // Don't bother with resuming the continuation if it is already cancelled. + if (continuation.isCancelled) return + continuation.resumeWithException(e) + } } - - override fun onFailure(call: Call, e: IOException) { - // Don't bother with resuming the continuation if it is already cancelled. - if (continuation.isCancelled) return - continuation.resumeWithException(e) - } - }) + ) continuation.invokeOnCancellation { try { diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt b/app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt index 53799e9ca..ff56520b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/ProgressResponseBody.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.network -import java.io.IOException import okhttp3.MediaType import okhttp3.ResponseBody import okio.Buffer @@ -8,6 +7,7 @@ import okio.BufferedSource import okio.ForwardingSource import okio.Source import okio.buffer +import java.io.IOException class ProgressResponseBody(private val responseBody: ResponseBody, private val progressListener: ProgressListener) : ResponseBody() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt b/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt index 8fc2b9a6f..3d3b88b54 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/network/Requests.kt @@ -1,11 +1,11 @@ package eu.kanade.tachiyomi.network -import java.util.concurrent.TimeUnit.MINUTES import okhttp3.CacheControl import okhttp3.FormBody import okhttp3.Headers import okhttp3.Request import okhttp3.RequestBody +import java.util.concurrent.TimeUnit.MINUTES private val DEFAULT_CACHE_CONTROL = CacheControl.Builder().maxAge(10, MINUTES).build() private val DEFAULT_HEADERS = Headers.Builder().build() diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt index 23d0f00b4..9ab3c2ae1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/LocalSource.kt @@ -14,6 +14,10 @@ import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.storage.EpubFile import eu.kanade.tachiyomi.util.system.ImageUtil +import junrar.Archive +import junrar.rarfile.FileHeader +import rx.Observable +import timber.log.Timber import java.io.File import java.io.FileInputStream import java.io.InputStream @@ -21,10 +25,6 @@ import java.util.Locale import java.util.concurrent.TimeUnit import java.util.zip.ZipEntry import java.util.zip.ZipFile -import junrar.Archive -import junrar.rarfile.FileHeader -import rx.Observable -import timber.log.Timber class LocalSource(private val context: Context) : CatalogueSource { companion object { diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt index 438662c6d..23b15ff47 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/HttpSource.kt @@ -10,15 +10,15 @@ import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga -import java.net.URI -import java.net.URISyntaxException -import java.security.MessageDigest import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import rx.Observable import uy.kohesive.injekt.injectLazy +import java.net.URI +import java.net.URISyntaxException +import java.security.MessageDigest /** * A simple implementation for sources from a website. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt index 0ecde8b1d..7635f07bb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/activity/BaseActivity.kt @@ -7,11 +7,11 @@ import androidx.appcompat.app.AppCompatActivity import androidx.lifecycle.lifecycleScope import androidx.viewbinding.ViewBinding import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.security.SecureActivityDelegate import eu.kanade.tachiyomi.util.system.LocaleHelper import uy.kohesive.injekt.injectLazy +import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values abstract class BaseActivity : AppCompatActivity() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt index f1e980a7d..8d4fea215 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/BaseController.kt @@ -22,27 +22,29 @@ abstract class BaseController(bundle: Bundle? = null) : lateinit var binding: VB init { - addLifecycleListener(object : LifecycleListener() { - override fun postCreateView(controller: Controller, view: View) { - onViewCreated(view) - } + addLifecycleListener( + object : LifecycleListener() { + override fun postCreateView(controller: Controller, view: View) { + onViewCreated(view) + } - override fun preCreateView(controller: Controller) { - Timber.d("Create view for ${controller.instance()}") - } + override fun preCreateView(controller: Controller) { + Timber.d("Create view for ${controller.instance()}") + } - override fun preAttach(controller: Controller, view: View) { - Timber.d("Attach view for ${controller.instance()}") - } + override fun preAttach(controller: Controller, view: View) { + Timber.d("Attach view for ${controller.instance()}") + } - override fun preDetach(controller: Controller, view: View) { - Timber.d("Detach view for ${controller.instance()}") - } + override fun preDetach(controller: Controller, view: View) { + Timber.d("Detach view for ${controller.instance()}") + } - override fun preDestroyView(controller: Controller, view: View) { - Timber.d("Destroy view for ${controller.instance()}") + override fun preDestroyView(controller: Controller, view: View) { + Timber.d("Destroy view for ${controller.instance()}") + } } - }) + ) } override val containerView: View? @@ -98,17 +100,19 @@ abstract class BaseController(bundle: Bundle? = null) : var expandActionViewFromInteraction = false fun MenuItem.fixExpand(onExpand: ((MenuItem) -> Boolean)? = null, onCollapse: ((MenuItem) -> Boolean)? = null) { - setOnActionExpandListener(object : MenuItem.OnActionExpandListener { - override fun onMenuItemActionExpand(item: MenuItem): Boolean { - return onExpand?.invoke(item) ?: true - } + setOnActionExpandListener( + object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem): Boolean { + return onExpand?.invoke(item) ?: true + } - override fun onMenuItemActionCollapse(item: MenuItem): Boolean { - activity?.invalidateOptionsMenu() + override fun onMenuItemActionCollapse(item: MenuItem): Boolean { + activity?.invalidateOptionsMenu() - return onCollapse?.invoke(item) ?: true + return onCollapse?.invoke(item) ?: true + } } - }) + ) if (expandActionViewFromInteraction) { expandActionViewFromInteraction = false diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt index f9ca2b386..6c892ffe0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/ExtensionPresenter.kt @@ -10,12 +10,12 @@ import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.util.system.LocaleHelper -import java.util.concurrent.TimeUnit import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit private typealias ExtensionTuple = Triple, List, List> diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsController.kt index 2fb7f7a64..b5ff00290 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/ExtensionDetailsController.kt @@ -20,8 +20,6 @@ import androidx.preference.PreferenceManager import androidx.preference.PreferenceScreen import androidx.preference.SwitchPreferenceCompat import androidx.recyclerview.widget.ConcatAdapter -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL import androidx.recyclerview.widget.LinearLayoutManager import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore @@ -92,7 +90,6 @@ class ExtensionDetailsController(bundle: Bundle? = null) : ExtensionDetailsHeaderAdapter(presenter), initPreferencesAdapter(context, extension) ) - binding.extensionPrefsRecycler.addItemDecoration(DividerItemDecoration(context, VERTICAL)) } private fun initPreferencesAdapter(context: Context, extension: Extension.Installed): PreferenceGroupAdapter { @@ -112,7 +109,7 @@ class ExtensionDetailsController(bundle: Bundle? = null) : .forEach { val preferenceBlock = { it.value - .sortedWith(compareBy({ !it.isEnabled() }, { it.name })) + .sortedWith(compareBy({ !it.isEnabled() }, { it.name.toLowerCase() })) .forEach { source -> val sourcePrefs = mutableListOf() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/SourcePreferencesController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/SourcePreferencesController.kt index 7867f6c1d..fa26cd208 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/SourcePreferencesController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/extension/details/SourcePreferencesController.kt @@ -19,8 +19,6 @@ import androidx.preference.Preference import androidx.preference.PreferenceGroupAdapter import androidx.preference.PreferenceManager import androidx.preference.PreferenceScreen -import androidx.recyclerview.widget.DividerItemDecoration -import androidx.recyclerview.widget.DividerItemDecoration.VERTICAL import androidx.recyclerview.widget.LinearLayoutManager import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.EmptyPreferenceDataStore @@ -86,7 +84,6 @@ class SourcePreferencesController(bundle: Bundle? = null) : binding.recycler.layoutManager = LinearLayoutManager(context) binding.recycler.adapter = PreferenceGroupAdapter(screen) - binding.recycler.addItemDecoration(DividerItemDecoration(context, VERTICAL)) } override fun onDestroyView(view: View) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt index 910cf148f..277ec7529 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/search/SearchPresenter.kt @@ -13,10 +13,10 @@ import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchCardItem import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchItem import eu.kanade.tachiyomi.ui.browse.source.globalsearch.GlobalSearchPresenter import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource -import java.util.Date import rx.Observable import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import java.util.Date class SearchPresenter( initialQuery: String? = "", diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt index 1d724d2f8..72a3a2526 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/migration/sources/MigrationSourcesPresenter.kt @@ -29,7 +29,7 @@ class MigrationSourcesPresenter( val header = SelectionHeader() return library.map { it.source }.toSet() .mapNotNull { if (it != LocalSource.ID) sourceManager.getOrStub(it) else null } - .sortedBy { it.name } + .sortedBy { it.name.toLowerCase() } .map { SourceItem(it, header) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt index 2b11f7550..4781db7f1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourceFilterController.kt @@ -16,9 +16,9 @@ import eu.kanade.tachiyomi.util.preference.onChange import eu.kanade.tachiyomi.util.preference.switchPreferenceCategory import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.LocaleHelper -import java.util.TreeMap import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.TreeMap class SourceFilterController : SettingsController() { @@ -42,7 +42,7 @@ class SourceFilterController : SettingsController() { ) orderedLangs.forEach { lang -> - val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name } + val sources = sourcesByLang[lang].orEmpty().sortedBy { it.name.toLowerCase() } // Create a preference group and set initial state and change listener switchPreferenceCategory { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt index c39c14254..eeee195c5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/SourcePresenter.kt @@ -6,7 +6,6 @@ import eu.kanade.tachiyomi.source.CatalogueSource import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import java.util.TreeMap import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job @@ -21,6 +20,7 @@ import rx.Observable import rx.Subscription import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.TreeMap /** * Presenter of [SourceController] @@ -128,7 +128,7 @@ class SourcePresenter( return sourceManager.getCatalogueSources() .filter { it.lang in languages } .filterNot { it.id.toString() in disabledSourceIds } - .sortedBy { "(${it.lang}) ${it.name}" } + + .sortedBy { "(${it.lang}) ${it.name.toLowerCase()}" } + sourceManager.get(LocalSource.ID) as LocalSource } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt index 118d9106f..5b82616fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourceController.kt @@ -10,7 +10,6 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.widget.SearchView import androidx.core.view.isVisible -import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView @@ -216,7 +215,6 @@ open class BrowseSourceController(bundle: Bundle) : id = R.id.recycler layoutManager = LinearLayoutManager(context) layoutParams = RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) - addItemDecoration(DividerItemDecoration(context, DividerItemDecoration.VERTICAL)) } } else { (binding.catalogueView.inflate(R.layout.source_recycler_autofit) as AutofitRecyclerView).apply { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt index 7a75b0f5a..d406ca3fb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/BrowseSourcePresenter.kt @@ -28,9 +28,8 @@ 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.chapter.ChapterSettingsHelper import eu.kanade.tachiyomi.util.removeCovers -import java.util.Date -import kotlinx.coroutines.flow.subscribe import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -39,6 +38,7 @@ import rx.subjects.PublishSubject import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.Date /** * Presenter of [BrowseSourceController]. @@ -268,6 +268,8 @@ open class BrowseSourcePresenter( if (!manga.favorite) { manga.removeCovers(coverCache) + } else { + ChapterSettingsHelper.applySettingDefaults(manga) } db.insertManga(manga).executeAsBlocking() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt index 5ee0bb61a..8fefce9e0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt @@ -38,10 +38,13 @@ class SourceItem(val manga: Manga, private val displayMode: Preference) : AbstractFlexibleItem( holder.itemView.context, - android.R.layout.simple_spinner_item, filter.values + android.R.layout.simple_spinner_item, + filter.values ).apply { setDropDownViewResource(R.layout.common_spinner_item) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt index 1c8feb830..9bc93ee7f 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/filter/TriStateItem.kt @@ -9,10 +9,10 @@ import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.items.AbstractFlexibleItem import eu.davidea.flexibleadapter.items.IFlexible import eu.davidea.viewholders.FlexibleViewHolder -import eu.kanade.tachiyomi.R as TR import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.util.system.getResourceColor +import eu.kanade.tachiyomi.R as TR open class TriStateItem(val filter: Filter.TriState) : AbstractFlexibleItem() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt index 04ba78da0..64bbb04c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchController.kt @@ -108,17 +108,19 @@ open class GlobalSearchController( val searchView = searchItem.actionView as SearchView searchView.maxWidth = Int.MAX_VALUE - searchItem.setOnActionExpandListener(object : MenuItem.OnActionExpandListener { - override fun onMenuItemActionExpand(item: MenuItem?): Boolean { - searchView.onActionViewExpanded() // Required to show the query in the view - searchView.setQuery(presenter.query, false) - return true - } + searchItem.setOnActionExpandListener( + object : MenuItem.OnActionExpandListener { + override fun onMenuItemActionExpand(item: MenuItem?): Boolean { + searchView.onActionViewExpanded() // Required to show the query in the view + searchView.setQuery(presenter.query, false) + return true + } - override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { - return true + override fun onMenuItemActionCollapse(item: MenuItem?): Boolean { + return true + } } - }) + ) searchView.queryTextEvents() .filterIsInstance() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt index bedf58add..7042dcb57 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchPresenter.kt @@ -108,7 +108,7 @@ open class GlobalSearchPresenter( return sourceManager.getCatalogueSources() .filter { it.lang in languages } .filterNot { it.id.toString() in disabledSourceIds } - .sortedWith(compareBy({ it.id.toString() !in pinnedSourceIds }, { "${it.name} (${it.lang})" })) + .sortedWith(compareBy({ it.id.toString() !in pinnedSourceIds }, { "${it.name.toLowerCase()} (${it.lang})" })) } private fun getSourcesToQuery(): List { @@ -188,7 +188,7 @@ open class GlobalSearchPresenter( { it.results.isNullOrEmpty() }, // Same as initial sort, i.e. pinned first then alphabetically { it.source.id.toString() !in pinnedSourceIds }, - { "${it.source.name} (${it.source.lang})" } + { "${it.source.name.toLowerCase()} (${it.source.lang})" } ) ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryController.kt index 5a5c27928..e1fac83de 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/category/CategoryController.kt @@ -198,8 +198,11 @@ class CategoryController : R.id.action_delete -> { undoHelper = UndoHelper(adapter, this) undoHelper?.start( - adapter.selectedPositions, activity!!.root_coordinator, - R.string.snack_categories_deleted, R.string.action_undo, 3000 + adapter.selectedPositions, + activity!!.root_coordinator, + R.string.snack_categories_deleted, + R.string.action_undo, + 3000 ) mode.finish() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadController.kt index eba0cba6b..5fb2d934a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/download/DownloadController.kt @@ -18,13 +18,13 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.base.controller.FabController import eu.kanade.tachiyomi.ui.base.controller.NucleusController import eu.kanade.tachiyomi.util.view.shrinkOnScroll -import java.util.concurrent.TimeUnit import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import reactivecircus.flowbinding.android.view.clicks import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers +import java.util.concurrent.TimeUnit /** * Controller that shows the currently active downloads. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt index 9ecefbd02..60cdfb936 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryController.kt @@ -183,7 +183,7 @@ class LibraryController( createActionModeIfNeeded() } - settingsSheet = LibrarySettingsSheet(activity!!) { group -> + settingsSheet = LibrarySettingsSheet(router) { group -> when (group) { is LibrarySettingsSheet.Filter.FilterGroup -> onFilterChanged() is LibrarySettingsSheet.Sort.SortGroup -> onSortChanged() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index a246c2d6b..8c4176f96 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -45,7 +45,9 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe view.apply { card.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight) gradient.layoutParams = FrameLayout.LayoutParams( - MATCH_PARENT, coverHeight / 2, Gravity.BOTTOM + MATCH_PARENT, + coverHeight / 2, + Gravity.BOTTOM ) } LibraryCompactGridHolder(view, adapter) @@ -55,7 +57,8 @@ class LibraryItem(val manga: LibraryManga, private val libraryDisplayMode: Prefe val coverHeight = parent.itemWidth / 3 * 4 view.apply { card.layoutParams = ConstraintLayout.LayoutParams( - MATCH_PARENT, coverHeight + MATCH_PARENT, + coverHeight ) } LibraryComfortableGridHolder(view, adapter) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt index 578aece21..e94530c14 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryPresenter.kt @@ -19,14 +19,16 @@ import eu.kanade.tachiyomi.util.lang.combineLatest import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.removeCovers -import java.util.Collections -import java.util.Comparator +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.Collections +import java.util.Comparator /** * Class containing library information. @@ -110,34 +112,45 @@ class LibraryPresenter( * @param map the map to filter. */ private fun applyFilters(map: LibraryMap): LibraryMap { - val filterDownloaded = preferences.downloadedOnly().get() || preferences.filterDownloaded().get() + val downloadedOnly = preferences.downloadedOnly().get() + val filterDownloaded = preferences.filterDownloaded().get() val filterUnread = preferences.filterUnread().get() val filterCompleted = preferences.filterCompleted().get() - val filterFn: (LibraryItem) -> Boolean = f@{ item -> - // Filter when there isn't unread chapters. - if (filterUnread && item.manga.unread == 0) { - return@f false + val filterFnUnread: (LibraryItem) -> Boolean = unread@{ item -> + if (filterUnread == STATE_IGNORE) return@unread true + val isUnread = item.manga.unread != 0 + + return@unread if (filterUnread == STATE_INCLUDE) isUnread + else !isUnread + } + + val filterFnCompleted: (LibraryItem) -> Boolean = completed@{ item -> + if (filterCompleted == STATE_IGNORE) return@completed true + val isCompleted = item.manga.status == SManga.COMPLETED + + return@completed if (filterCompleted == STATE_INCLUDE) isCompleted + else !isCompleted + } + + val filterFnDownloaded: (LibraryItem) -> Boolean = downloaded@{ item -> + if (!downloadedOnly && filterDownloaded == STATE_IGNORE) return@downloaded true + val isDownloaded = when { + item.manga.isLocal() -> true + item.downloadCount != -1 -> item.downloadCount > 0 + else -> downloadManager.getDownloadCount(item.manga) > 0 } - if (filterCompleted && item.manga.status != SManga.COMPLETED) { - return@f false - } + return@downloaded if (downloadedOnly || filterDownloaded == STATE_INCLUDE) isDownloaded + else !isDownloaded + } - // Filter when there are no downloads. - if (filterDownloaded) { - // Local manga are always downloaded - if (item.manga.isLocal()) { - return@f true - } - // Don't bother with directory checking if download count has been set. - if (item.downloadCount != -1) { - return@f item.downloadCount > 0 - } - - return@f downloadManager.getDownloadCount(item.manga) > 0 - } - true + val filterFn: (LibraryItem) -> Boolean = filter@{ item -> + return@filter !( + !filterFnUnread(item) || + !filterFnCompleted(item) || + !filterFnDownloaded(item) + ) } return map.mapValues { entry -> entry.value.filter(filterFn) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt index d4b3d3af5..87587b937 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibrarySettingsSheet.kt @@ -1,33 +1,36 @@ package eu.kanade.tachiyomi.ui.library -import android.app.Activity import android.content.Context import android.util.AttributeSet import android.view.View +import com.bluelinelabs.conductor.Router import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferenceValues.DisplayMode import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.widget.ExtendedNavigationView +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_EXCLUDE +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_IGNORE +import eu.kanade.tachiyomi.widget.ExtendedNavigationView.Item.TriStateGroup.Companion.STATE_INCLUDE import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog import uy.kohesive.injekt.injectLazy class LibrarySettingsSheet( - activity: Activity, + router: Router, onGroupClickListener: (ExtendedNavigationView.Group) -> Unit -) : TabbedBottomSheetDialog(activity) { +) : TabbedBottomSheetDialog(router) { val filters: Filter private val sort: Sort private val display: Display init { - filters = Filter(activity) + filters = Filter(router.activity!!) filters.onGroupClicked = onGroupClickListener - sort = Sort(activity) + sort = Sort(router.activity!!) sort.onGroupClicked = onGroupClickListener - display = Display(activity) + display = Display(router.activity!!) display.onGroupClicked = onGroupClickListener } @@ -59,33 +62,43 @@ class LibrarySettingsSheet( * Returns true if there's at least one filter from [FilterGroup] active. */ fun hasActiveFilters(): Boolean { - return filterGroup.items.any { it.checked } + return filterGroup.items.any { it.state != Item.TriStateGroup.STATE_IGNORE } } inner class FilterGroup : Group { - private val downloaded = Item.CheckboxGroup(R.string.action_filter_downloaded, this) - private val unread = Item.CheckboxGroup(R.string.action_filter_unread, this) - private val completed = Item.CheckboxGroup(R.string.completed, this) + private val downloaded = Item.TriStateGroup(R.string.action_filter_downloaded, this) + private val unread = Item.TriStateGroup(R.string.action_filter_unread, this) + private val completed = Item.TriStateGroup(R.string.completed, this) override val header = null override val items = listOf(downloaded, unread, completed) override val footer = null override fun initModels() { - downloaded.checked = preferences.downloadedOnly().get() || preferences.filterDownloaded().get() - downloaded.enabled = !preferences.downloadedOnly().get() - unread.checked = preferences.filterUnread().get() - completed.checked = preferences.filterCompleted().get() + if (preferences.downloadedOnly().get()) { + downloaded.state = STATE_INCLUDE + downloaded.enabled = false + } else { + downloaded.state = preferences.filterDownloaded().get() + } + unread.state = preferences.filterUnread().get() + completed.state = preferences.filterCompleted().get() } override fun onItemClicked(item: Item) { - item as Item.CheckboxGroup - item.checked = !item.checked + item as Item.TriStateGroup + val newState = when (item.state) { + STATE_IGNORE -> STATE_INCLUDE + STATE_INCLUDE -> STATE_EXCLUDE + STATE_EXCLUDE -> STATE_IGNORE + else -> throw Exception("Unknown State") + } + item.state = newState when (item) { - downloaded -> preferences.filterDownloaded().set(item.checked) - unread -> preferences.filterUnread().set(item.checked) - completed -> preferences.filterCompleted().set(item.checked) + downloaded -> preferences.filterDownloaded().set(newState) + unread -> preferences.filterUnread().set(newState) + completed -> preferences.filterCompleted().set(newState) } adapter.notifyItemChanged(item) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt index a5829b6a7..4c02134a9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/main/MainActivity.kt @@ -44,13 +44,13 @@ import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController import eu.kanade.tachiyomi.util.lang.launchIO import eu.kanade.tachiyomi.util.lang.launchUI import eu.kanade.tachiyomi.util.system.toast -import java.util.Date -import java.util.concurrent.TimeUnit import kotlinx.android.synthetic.main.main_activity.appbar import kotlinx.android.synthetic.main.main_activity.tabs import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import timber.log.Timber +import java.util.Date +import java.util.concurrent.TimeUnit class MainActivity : BaseActivity() { @@ -126,26 +126,28 @@ class MainActivity : BaseActivity() { onBackPressed() } - router.addChangeListener(object : ControllerChangeHandler.ControllerChangeListener { - override fun onChangeStarted( - to: Controller?, - from: Controller?, - isPush: Boolean, - container: ViewGroup, - handler: ControllerChangeHandler - ) { - syncActivityViewWithController(to, from) - } + router.addChangeListener( + object : ControllerChangeHandler.ControllerChangeListener { + override fun onChangeStarted( + to: Controller?, + from: Controller?, + isPush: Boolean, + container: ViewGroup, + handler: ControllerChangeHandler + ) { + syncActivityViewWithController(to, from) + } - override fun onChangeCompleted( - to: Controller?, - from: Controller?, - isPush: Boolean, - container: ViewGroup, - handler: ControllerChangeHandler - ) { + override fun onChangeCompleted( + to: Controller?, + from: Controller?, + isPush: Boolean, + container: ViewGroup, + handler: ControllerChangeHandler + ) { + } } - }) + ) syncActivityViewWithController(router.backstack.lastOrNull()?.controller()) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt index f9f6a1f2b..0e46fb393 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaController.kt @@ -52,7 +52,6 @@ import eu.kanade.tachiyomi.ui.library.ChangeMangaCoverDialog import eu.kanade.tachiyomi.ui.library.LibraryController import eu.kanade.tachiyomi.ui.main.MainActivity import eu.kanade.tachiyomi.ui.main.offsetAppbarHeight -import eu.kanade.tachiyomi.ui.manga.chapter.ChapterDividerItemDecoration import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersAdapter import eu.kanade.tachiyomi.ui.manga.chapter.ChaptersSettingsSheet @@ -65,13 +64,13 @@ import eu.kanade.tachiyomi.ui.reader.ReaderActivity import eu.kanade.tachiyomi.ui.recent.history.HistoryController import eu.kanade.tachiyomi.ui.recent.updates.UpdatesController import eu.kanade.tachiyomi.ui.webview.WebViewActivity +import eu.kanade.tachiyomi.util.chapter.NoChaptersException import eu.kanade.tachiyomi.util.hasCustomCover import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.toast import eu.kanade.tachiyomi.util.view.getCoordinates import eu.kanade.tachiyomi.util.view.shrinkOnScroll import eu.kanade.tachiyomi.util.view.snack -import kotlin.math.min import kotlinx.android.synthetic.main.main_activity.root_coordinator import kotlinx.android.synthetic.main.main_activity.toolbar import kotlinx.coroutines.flow.launchIn @@ -83,6 +82,7 @@ import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import kotlin.math.min class MangaController : NucleusController, @@ -207,7 +207,6 @@ class MangaController : binding.recycler.adapter = ConcatAdapter(mangaInfoAdapter, chaptersHeaderAdapter, chaptersAdapter) binding.recycler.layoutManager = LinearLayoutManager(view.context) - binding.recycler.addItemDecoration(ChapterDividerItemDecoration(view.context)) binding.recycler.setHasFixedSize(true) chaptersAdapter?.fastScroller = binding.fastScroller @@ -238,7 +237,7 @@ class MangaController : binding.actionToolbar.offsetAppbarHeight(activity!!) - settingsSheet = ChaptersSettingsSheet(activity!!, presenter) { group -> + settingsSheet = ChaptersSettingsSheet(router, presenter) { group -> if (group is ChaptersSettingsSheet.Filter.FilterGroup) { updateFilterIconState() chaptersAdapter?.notifyDataSetChanged() @@ -292,10 +291,10 @@ class MangaController : // Get coordinates and start animation actionFab?.getCoordinates()?.let { coordinates -> if (!binding.revealView.showRevealEffect( - coordinates.x, - coordinates.y, - revealAnimationListener - ) + coordinates.x, + coordinates.y, + revealAnimationListener + ) ) { openChapter(item.chapter) } @@ -343,7 +342,8 @@ class MangaController : } override fun onPrepareOptionsMenu(menu: Menu) { - // Hide download options for local manga + // Hide options for local manga + menu.findItem(R.id.action_share).isVisible = !isLocalSource menu.findItem(R.id.download_group).isVisible = !isLocalSource // Hide options for non-library manga @@ -354,6 +354,7 @@ class MangaController : override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { + R.id.action_share -> shareManga() R.id.download_next, R.id.download_next_5, R.id.download_next_10, R.id.download_custom, R.id.download_unread, R.id.download_all -> downloadChapters(item.itemId) @@ -694,7 +695,11 @@ class MangaController : fun onFetchChaptersError(error: Throwable) { isRefreshingChapters = false updateRefreshing() - activity?.toast(error.message) + if (error is NoChaptersException) { + activity?.toast(activity?.getString(R.string.no_chapters_error)) + } else { + activity?.toast(error.message) + } } fun onChapterStatusChange(download: Download) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt index 95ee65ce3..24002f7fe 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/MangaPresenter.kt @@ -18,6 +18,7 @@ import eu.kanade.tachiyomi.source.LocalSource import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.manga.chapter.ChapterItem +import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.isLocal import eu.kanade.tachiyomi.util.lang.isNullOrUnsubscribed @@ -26,7 +27,6 @@ import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.removeCovers import eu.kanade.tachiyomi.util.shouldDownloadNewChapters import eu.kanade.tachiyomi.util.updateCoverLastModified -import java.util.Date import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -34,6 +34,7 @@ import rx.schedulers.Schedulers import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.Date class MangaPresenter( val manga: Manga, @@ -82,6 +83,10 @@ class MangaPresenter( override fun onCreate(savedState: Bundle?) { super.onCreate(savedState) + if (!manga.favorite) { + ChapterSettingsHelper.applySettingDefaults(manga) + } + // Manga info - start getMangaObservable() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDividerItemDecoration.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDividerItemDecoration.kt deleted file mode 100644 index 0a66f401b..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterDividerItemDecoration.kt +++ /dev/null @@ -1,59 +0,0 @@ -package eu.kanade.tachiyomi.ui.manga.chapter - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Rect -import android.graphics.drawable.Drawable -import android.view.View -import androidx.core.view.forEach -import androidx.core.view.marginBottom -import androidx.recyclerview.widget.RecyclerView - -/** - * Mimics a DividerItemDecoration that doesn't draw between the first two items. - * - * Used in MangaController since the manga info header and chapters header are the first two - * items in the list using a ConcatAdapter. - */ -class ChapterDividerItemDecoration(context: Context) : RecyclerView.ItemDecoration() { - - private val divider: Drawable - - init { - val a = context.obtainStyledAttributes(intArrayOf(android.R.attr.listDivider)) - divider = a.getDrawable(0)!! - a.recycle() - } - - override fun onDraw(canvas: Canvas, parent: RecyclerView, state: RecyclerView.State) { - if (parent.layoutManager == null) { - return - } - - canvas.save() - parent.forEach { - val top = it.bottom + it.marginBottom - val bottom = top + divider.intrinsicHeight - val left = parent.paddingStart - val right = parent.width - parent.paddingEnd - divider.setBounds(left, top, right, bottom) - divider.draw(canvas) - } - canvas.restore() - } - - override fun getItemOffsets( - outRect: Rect, - view: View, - parent: RecyclerView, - state: RecyclerView.State - ) { - val position = parent.getChildAdapterPosition(view) - - if (position == 0) { - outRect.setEmpty() - } else { - outRect.set(0, 0, 0, divider.intrinsicHeight) - } - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt index d57ef6e0a..7dd16b7fd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChapterHolder.kt @@ -9,11 +9,11 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.download.model.Download import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder -import java.util.Date import kotlinx.android.synthetic.main.chapters_item.bookmark_icon import kotlinx.android.synthetic.main.chapters_item.chapter_description import kotlinx.android.synthetic.main.chapters_item.chapter_title import kotlinx.android.synthetic.main.chapters_item.download_text +import java.util.Date class ChapterHolder( view: View, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt index 9ead9cde9..f78047d02 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersAdapter.kt @@ -6,10 +6,10 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.manga.MangaController import eu.kanade.tachiyomi.util.system.getResourceColor +import uy.kohesive.injekt.injectLazy import java.text.DateFormat import java.text.DecimalFormat import java.text.DecimalFormatSymbols -import uy.kohesive.injekt.injectLazy class ChaptersAdapter( controller: MangaController, diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt index af34bfbf5..321369039 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt @@ -1,34 +1,39 @@ package eu.kanade.tachiyomi.ui.manga.chapter -import android.app.Activity import android.content.Context import android.util.AttributeSet import android.view.View +import androidx.core.view.isVisible +import com.bluelinelabs.conductor.Router import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.ui.manga.MangaPresenter +import eu.kanade.tachiyomi.util.view.popupMenu import eu.kanade.tachiyomi.widget.ExtendedNavigationView import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog class ChaptersSettingsSheet( - activity: Activity, + private val router: Router, private val presenter: MangaPresenter, onGroupClickListener: (ExtendedNavigationView.Group) -> Unit -) : TabbedBottomSheetDialog(activity) { +) : TabbedBottomSheetDialog(router) { val filters: Filter private val sort: Sort private val display: Display init { - filters = Filter(activity) + filters = Filter(router.activity!!) filters.onGroupClicked = onGroupClickListener - sort = Sort(activity) + sort = Sort(router.activity!!) sort.onGroupClicked = onGroupClickListener - display = Display(activity) + display = Display(router.activity!!) display.onGroupClicked = onGroupClickListener + + binding.menu.isVisible = true + binding.menu.setOnClickListener { it.post { showPopupMenu(it) } } } override fun getTabViews(): List = listOf( @@ -43,6 +48,23 @@ class ChaptersSettingsSheet( R.string.action_display ) + private fun showPopupMenu(view: View) { + view.popupMenu( + R.menu.default_chapter_filter, + { + }, + { + when (this.itemId) { + R.id.set_as_default -> { + SetChapterSettingsDialog(presenter.manga).showDialog(router) + true + } + else -> true + } + } + ) + } + /** * Filters group (unread, downloaded, ...). */ diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/MangaChaptersHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/MangaChaptersHeaderAdapter.kt index 067b1e953..db09d9597 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/MangaChaptersHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/MangaChaptersHeaderAdapter.kt @@ -66,7 +66,7 @@ class MangaChaptersHeaderAdapter( } else { view.context.getResourceColor(R.attr.colorOnPrimary) } - DrawableCompat.setTint(binding.btnChaptersFilter.icon, filterColor) + DrawableCompat.setTint(binding.btnChaptersFilter.drawable, filterColor) merge(view.clicks(), binding.btnChaptersFilter.clicks()) .onEach { controller.showSettingsSheet() } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt new file mode 100644 index 000000000..323034536 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/SetChapterSettingsDialog.kt @@ -0,0 +1,48 @@ +package eu.kanade.tachiyomi.ui.manga.chapter + +import android.app.Dialog +import android.os.Bundle +import com.afollestad.materialdialogs.MaterialDialog +import com.afollestad.materialdialogs.customview.customView +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.ui.base.controller.DialogController +import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper +import eu.kanade.tachiyomi.util.system.toast +import eu.kanade.tachiyomi.widget.DialogCheckboxView + +class SetChapterSettingsDialog(bundle: Bundle? = null) : DialogController(bundle) { + + constructor(manga: Manga) : this( + Bundle().apply { + putSerializable(MANGA_KEY, manga) + } + ) + + override fun onCreateDialog(savedViewState: Bundle?): Dialog { + val view = DialogCheckboxView(activity!!).apply { + setDescription(R.string.confirm_set_chapter_settings) + setOptionDescription(R.string.also_set_chapter_settings_for_library) + } + + return MaterialDialog(activity!!) + .title(R.string.chapter_settings) + .customView( + view = view, + horizontalPadding = true + ) + .positiveButton(android.R.string.ok) { + ChapterSettingsHelper.setGlobalSettings(args.getSerializable(MANGA_KEY)!! as Manga) + if (view.isChecked()) { + ChapterSettingsHelper.updateAllMangasWithGlobalDefaults() + } + + activity?.toast(activity!!.getString(R.string.chapter_settings_updated)) + } + .negativeButton(android.R.string.cancel) + } + + private companion object { + const val MANGA_KEY = "manga" + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt index 6138026f3..88b1eeca2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/info/MangaInfoHeaderAdapter.kt @@ -105,13 +105,27 @@ class MangaInfoHeaderAdapter( isVisible = true if (trackCount > 0) { - setIconResource(R.drawable.ic_done_24dp) - text = view.context.resources.getQuantityString(R.plurals.num_trackers, trackCount, trackCount) - isChecked = true + setCompoundDrawablesWithIntrinsicBounds( + null, + ContextCompat.getDrawable(context, R.drawable.ic_done_24dp), + null, + null + ) + text = view.context.resources.getQuantityString( + R.plurals.num_trackers, + trackCount, + trackCount + ) + isSelected = true } else { - setIconResource(R.drawable.ic_sync_24dp) + setCompoundDrawablesWithIntrinsicBounds( + null, + ContextCompat.getDrawable(context, R.drawable.ic_sync_24dp), + null, + null + ) text = view.context.getString(R.string.manga_tracking_tab) - isChecked = false + isSelected = false } clicks() @@ -128,12 +142,6 @@ class MangaInfoHeaderAdapter( .onEach { controller.openMangaInWebView() } .launchIn(scope) binding.btnWebview.setTooltip(R.string.action_open_in_web_view) - - binding.btnShare.isVisible = true - binding.btnShare.clicks() - .onEach { controller.shareManga() } - .launchIn(scope) - binding.btnShare.setTooltip(R.string.action_share) } binding.mangaFullTitle.longClicks() @@ -285,14 +293,24 @@ class MangaInfoHeaderAdapter( // Update genres list if (!manga.genre.isNullOrBlank()) { - binding.mangaGenresTagsCompactChips.setChips(manga.getGenres(), controller::performSearch) - binding.mangaGenresTagsFullChips.setChips(manga.getGenres(), controller::performSearch) + binding.mangaGenresTagsCompactChips.setChips( + manga.getGenres(), + controller::performSearch + ) + binding.mangaGenresTagsFullChips.setChips( + manga.getGenres(), + controller::performSearch + ) } else { binding.mangaGenresTagsWrapper.isVisible = false } // Handle showing more or less info - merge(binding.mangaSummarySection.clicks(), binding.mangaSummaryText.clicks(), binding.mangaInfoToggle.clicks()) + merge( + binding.mangaSummarySection.clicks(), + binding.mangaSummaryText.clicks(), + binding.mangaInfoToggle.clicks() + ) .onEach { toggleMangaInfo(view.context) } .launchIn(scope) @@ -310,20 +328,22 @@ class MangaInfoHeaderAdapter( private fun toggleMangaInfo(context: Context) { val isExpanded = - binding.mangaInfoToggle.text == context.getString(R.string.manga_info_collapse) + binding.mangaInfoToggle.contentDescription == context.getString(R.string.manga_info_collapse) with(binding.mangaInfoToggle) { - text = if (isExpanded) { + contentDescription = if (isExpanded) { context.getString(R.string.manga_info_expand) } else { context.getString(R.string.manga_info_collapse) } - icon = if (isExpanded) { - context.getDrawable(R.drawable.ic_baseline_expand_more_24dp) - } else { - context.getDrawable(R.drawable.ic_baseline_expand_less_24dp) - } + setImageDrawable( + if (isExpanded) { + context.getDrawable(R.drawable.ic_baseline_expand_more_24dp) + } else { + context.getDrawable(R.drawable.ic_baseline_expand_less_24dp) + } + ) } with(binding.mangaSummaryText) { @@ -355,13 +375,18 @@ class MangaInfoHeaderAdapter( // Set the Favorite drawable to the correct one. // Border drawable if false, filled drawable if true. binding.btnFavorite.apply { - icon = ContextCompat.getDrawable( - context, - if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp + setCompoundDrawablesWithIntrinsicBounds( + null, + ContextCompat.getDrawable( + context, + if (isFavorite) R.drawable.ic_favorite_24dp else R.drawable.ic_favorite_border_24dp + ), + null, + null ) text = context.getString(if (isFavorite) R.string.in_library else R.string.add_to_library) - isChecked = isFavorite + isSelected = isFavorite } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt index 00aed713b..a5d60509a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/SetTrackReadingDatesDialog.kt @@ -9,9 +9,9 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.ui.base.controller.DialogController -import java.util.Calendar import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.Calendar class SetTrackReadingDatesDialog : DialogController where T : Controller, T : SetTrackReadingDatesDialog.Listener { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt index a35353e04..1279335aa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackHolder.kt @@ -5,8 +5,8 @@ import androidx.core.view.isVisible import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.databinding.TrackItemBinding import eu.kanade.tachiyomi.ui.base.holder.BaseViewHolder -import java.text.DateFormat import uy.kohesive.injekt.injectLazy +import java.text.DateFormat class TrackHolder(private val binding: TrackItemBinding, adapter: TrackAdapter) : BaseViewHolder(binding.root) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt index e949ab29e..2671042b5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/track/TrackSearchDialog.kt @@ -13,7 +13,6 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.model.TrackSearch import eu.kanade.tachiyomi.ui.base.controller.DialogController -import java.util.concurrent.TimeUnit import kotlinx.android.synthetic.main.track_search_dialog.view.progress import kotlinx.android.synthetic.main.track_search_dialog.view.track_search import kotlinx.android.synthetic.main.track_search_dialog.view.track_search_list @@ -26,6 +25,7 @@ import reactivecircus.flowbinding.android.widget.itemClicks import reactivecircus.flowbinding.android.widget.textChanges import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.TimeUnit class TrackSearchDialog : DialogController { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt index 0bd61bbcd..75d0aa6e9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/AboutController.kt @@ -10,9 +10,9 @@ import com.afollestad.materialdialogs.MaterialDialog import com.mikepenz.aboutlibraries.LibsBuilder import eu.kanade.tachiyomi.BuildConfig import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.updater.UpdateChecker import eu.kanade.tachiyomi.data.updater.UpdateResult import eu.kanade.tachiyomi.data.updater.UpdaterService +import eu.kanade.tachiyomi.data.updater.github.GithubUpdateChecker import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.setting.SettingsController import eu.kanade.tachiyomi.util.lang.launchNow @@ -23,19 +23,19 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.copyToClipboard import eu.kanade.tachiyomi.util.system.toast +import timber.log.Timber import java.text.DateFormat import java.text.ParseException import java.text.SimpleDateFormat import java.util.Locale import java.util.TimeZone -import timber.log.Timber class AboutController : SettingsController() { /** * Checks for new releases */ - private val updateChecker by lazy { UpdateChecker.getUpdateChecker() } + private val updateChecker by lazy { GithubUpdateChecker() } private val dateFormat: DateFormat = preferences.dateFormat() @@ -234,7 +234,9 @@ class AboutController : SettingsController() { val buildTime = inputDf.parse(BuildConfig.BUILD_TIME) val outputDf = DateFormat.getDateTimeInstance( - DateFormat.MEDIUM, DateFormat.SHORT, Locale.getDefault() + DateFormat.MEDIUM, + DateFormat.SHORT, + Locale.getDefault() ) outputDf.timeZone = TimeZone.getDefault() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt index 7f357e727..aa839a9ec 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/more/MoreController.kt @@ -7,7 +7,6 @@ import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.data.download.DownloadService -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.ui.base.controller.NoToolbarElevationController import eu.kanade.tachiyomi.ui.base.controller.RootController import eu.kanade.tachiyomi.ui.base.controller.withFadeTransaction @@ -28,6 +27,7 @@ import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.util.system.openInBrowser import rx.android.schedulers.AndroidSchedulers import uy.kohesive.injekt.injectLazy +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class MoreController : SettingsController(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 6439071e5..9a6687f8c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -21,6 +21,7 @@ import android.view.animation.Animation import android.view.animation.AnimationUtils import android.widget.SeekBar import androidx.core.view.ViewCompat +import androidx.core.view.WindowInsetsCompat import androidx.core.view.isVisible import androidx.core.view.setPadding import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView @@ -56,8 +57,6 @@ import eu.kanade.tachiyomi.util.view.showBar import eu.kanade.tachiyomi.util.view.snack import eu.kanade.tachiyomi.widget.SimpleAnimationListener import eu.kanade.tachiyomi.widget.SimpleSeekBarListener -import java.io.File -import kotlin.math.abs import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.delay import kotlinx.coroutines.flow.drop @@ -67,6 +66,8 @@ import kotlinx.coroutines.flow.sample import nucleus.factory.RequiresPresenter import timber.log.Timber import uy.kohesive.injekt.injectLazy +import java.io.File +import kotlin.math.abs /** * Activity containing the reader of Tachiyomi. This activity is mostly a container of the @@ -290,24 +291,27 @@ class ReaderActivity : BaseRxActivity() ViewCompat.setOnApplyWindowInsetsListener(binding.readerMenu) { _, insets -> if (!window.isDefaultBar()) { + val systemInsets = insets.getInsets(WindowInsetsCompat.Type.systemBars()) binding.readerMenu.setPadding( - insets.systemWindowInsetLeft, - insets.systemWindowInsetTop, - insets.systemWindowInsetRight, - insets.systemWindowInsetBottom + systemInsets.left, + systemInsets.top, + systemInsets.right, + systemInsets.bottom ) } insets } // Init listeners on bottom menu - binding.pageSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (viewer != null && fromUser) { - moveToPageIndex(value) + binding.pageSeekbar.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (viewer != null && fromUser) { + moveToPageIndex(value) + } } } - }) + ) binding.leftChapter.setOnClickListener { if (viewer != null) { if (viewer is R2LPagerViewer) { @@ -347,12 +351,14 @@ class ReaderActivity : BaseRxActivity() if (animate) { val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_top) - toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { - override fun onAnimationStart(animation: Animation) { - // Fix status bar being translucent the first time it's opened. - window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + toolbarAnimation.setAnimationListener( + object : SimpleAnimationListener() { + override fun onAnimationStart(animation: Animation) { +// Fix status bar being translucent the first time it's opened. + window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) + } } - }) + ) binding.toolbar.startAnimation(toolbarAnimation) val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.enter_from_bottom) @@ -371,11 +377,13 @@ class ReaderActivity : BaseRxActivity() if (animate) { val toolbarAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_top) - toolbarAnimation.setAnimationListener(object : SimpleAnimationListener() { - override fun onAnimationEnd(animation: Animation) { - binding.readerMenu.isVisible = false + toolbarAnimation.setAnimationListener( + object : SimpleAnimationListener() { + override fun onAnimationEnd(animation: Animation) { + binding.readerMenu.isVisible = false + } } - }) + ) binding.toolbar.startAnimation(toolbarAnimation) val bottomAnimation = AnimationUtils.loadAnimation(this, R.anim.exit_to_bottom) @@ -572,9 +580,13 @@ class ReaderActivity : BaseRxActivity() * Called from the presenter when a page is ready to be shared. It shows Android's default * sharing tool. */ - fun onShareImageResult(file: File) { + fun onShareImageResult(file: File, page: ReaderPage) { + val manga = presenter.manga ?: return + val chapter = page.chapter.chapter + val stream = file.getUriCompat(this) val intent = Intent(Intent.ACTION_SEND).apply { + putExtra(Intent.EXTRA_TEXT, getString(R.string.share_page_info, manga.title, chapter.name, page.number)) putExtra(Intent.EXTRA_STREAM, stream) flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION type = "image/*" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt index 7fe1a4609..8dee52cb5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderColorFilterSheet.kt @@ -74,45 +74,55 @@ class ReaderColorFilterSheet(private val activity: ReaderActivity) : BottomSheet } binding.colorFilterMode.setSelection(preferences.colorFilterMode().get(), false) - binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (fromUser) { - setColorValue(value, ALPHA_MASK, 24) + binding.seekbarColorFilterAlpha.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (fromUser) { + setColorValue(value, ALPHA_MASK, 24) + } } } - }) + ) - binding.seekbarColorFilterRed.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (fromUser) { - setColorValue(value, RED_MASK, 16) + binding.seekbarColorFilterRed.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (fromUser) { + setColorValue(value, RED_MASK, 16) + } } } - }) + ) - binding.seekbarColorFilterGreen.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (fromUser) { - setColorValue(value, GREEN_MASK, 8) + binding.seekbarColorFilterGreen.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (fromUser) { + setColorValue(value, GREEN_MASK, 8) + } } } - }) + ) - binding.seekbarColorFilterBlue.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (fromUser) { - setColorValue(value, BLUE_MASK, 0) + binding.seekbarColorFilterBlue.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (fromUser) { + setColorValue(value, BLUE_MASK, 0) + } } } - }) + ) - binding.brightnessSeekbar.setOnSeekBarChangeListener(object : SimpleSeekBarListener() { - override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { - if (fromUser) { - preferences.customBrightnessValue().set(value) + binding.brightnessSeekbar.setOnSeekBarChangeListener( + object : SimpleSeekBarListener() { + override fun onProgressChanged(seekBar: SeekBar, value: Int, fromUser: Boolean) { + if (fromUser) { + preferences.customBrightnessValue().set(value) + } } } - }) + ) } override fun onStart() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt index 83aac83d6..85b2ee797 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderPresenter.kt @@ -27,9 +27,6 @@ import eu.kanade.tachiyomi.util.lang.takeBytes import eu.kanade.tachiyomi.util.storage.DiskUtil import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.updateCoverLastModified -import java.io.File -import java.util.Date -import java.util.concurrent.TimeUnit import rx.Completable import rx.Observable import rx.Subscription @@ -38,6 +35,9 @@ import rx.schedulers.Schedulers import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.io.File +import java.util.Date +import java.util.concurrent.TimeUnit /** * Presenter used by the activity to perform background operations. @@ -569,7 +569,7 @@ class ReaderPresenter( .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribeFirst( - { view, file -> view.onShareImageResult(file) }, + { view, file -> view.onShareImageResult(file, page) }, { _, _ -> /* Empty */ } ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DirectoryPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DirectoryPageLoader.kt index 95e7c6e5e..71671b6fc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DirectoryPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/DirectoryPageLoader.kt @@ -4,9 +4,9 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder import eu.kanade.tachiyomi.util.system.ImageUtil +import rx.Observable import java.io.File import java.io.FileInputStream -import rx.Observable /** * Loader used to load a chapter from a directory given on [file]. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt index 00895e901..99764ac7b 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/EpubPageLoader.kt @@ -3,8 +3,8 @@ package eu.kanade.tachiyomi.ui.reader.loader import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.storage.EpubFile -import java.io.File import rx.Observable +import java.io.File /** * Loader used to load a chapter from a .epub file. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt index 1cc6df6ba..81481a266 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/HttpPageLoader.kt @@ -6,9 +6,6 @@ import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.lang.plusAssign -import java.util.concurrent.PriorityBlockingQueue -import java.util.concurrent.atomic.AtomicInteger -import kotlin.math.min import rx.Completable import rx.Observable import rx.schedulers.Schedulers @@ -18,6 +15,9 @@ import rx.subscriptions.CompositeSubscription import timber.log.Timber import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.concurrent.PriorityBlockingQueue +import java.util.concurrent.atomic.AtomicInteger +import kotlin.math.min /** * Loader used to load chapters from an online source. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt index 37b35a97c..9a6a6b88c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/RarPageLoader.kt @@ -4,14 +4,14 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder import eu.kanade.tachiyomi.util.system.ImageUtil +import junrar.Archive +import junrar.rarfile.FileHeader +import rx.Observable import java.io.File import java.io.InputStream import java.io.PipedInputStream import java.io.PipedOutputStream import java.util.concurrent.Executors -import junrar.Archive -import junrar.rarfile.FileHeader -import rx.Observable /** * Loader used to load a chapter from a .rar or .cbr file. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt index f65ebc594..a48c404a6 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/loader/ZipPageLoader.kt @@ -5,11 +5,11 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.util.lang.compareToCaseInsensitiveNaturalOrder import eu.kanade.tachiyomi.util.system.ImageUtil +import rx.Observable import java.io.File import java.nio.charset.StandardCharsets import java.util.zip.ZipEntry import java.util.zip.ZipFile -import rx.Observable /** * Loader used to load a chapter from a .zip or .cbz file. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt new file mode 100644 index 000000000..4ee2543ea --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/MissingChapters.kt @@ -0,0 +1,15 @@ +package eu.kanade.tachiyomi.ui.reader.viewer + +import eu.kanade.tachiyomi.data.database.models.Chapter +import kotlin.math.floor + +object MissingChapters { + + fun hasMissingChapters(higher: Chapter, lower: Chapter): Boolean { + return hasMissingChapters(higher.chapter_number, lower.chapter_number) + } + + fun hasMissingChapters(higherChapterNumber: Float, lowerChapterNumber: Float): Boolean { + return floor(higherChapterNumber) - floor(lowerChapterNumber) - 1f > 0f + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressBar.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressBar.kt index 4161bf4f0..3afc4da31 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressBar.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderProgressBar.kt @@ -63,9 +63,12 @@ class ReaderProgressBar @JvmOverloads constructor( */ private val rotationAnimation by lazy { RotateAnimation( - 0f, 360f, - Animation.RELATIVE_TO_SELF, 0.5f, - Animation.RELATIVE_TO_SELF, 0.5f + 0f, + 360f, + Animation.RELATIVE_TO_SELF, + 0.5f, + Animation.RELATIVE_TO_SELF, + 0.5f ).apply { interpolator = LinearInterpolator() repeatCount = Animation.INFINITE diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt new file mode 100644 index 000000000..13394c87b --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/ReaderTransitionView.kt @@ -0,0 +1,103 @@ +package eu.kanade.tachiyomi.ui.reader.viewer + +import android.content.Context +import android.util.AttributeSet +import android.widget.LinearLayout +import androidx.core.text.bold +import androidx.core.text.buildSpannedString +import androidx.core.view.isVisible +import eu.kanade.tachiyomi.R +import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition +import kotlinx.android.synthetic.main.reader_transition_view.view.lower_text +import kotlinx.android.synthetic.main.reader_transition_view.view.upper_text +import kotlinx.android.synthetic.main.reader_transition_view.view.warning +import kotlinx.android.synthetic.main.reader_transition_view.view.warning_text +import kotlin.math.floor + +class ReaderTransitionView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : + LinearLayout(context, attrs) { + + init { + inflate(context, R.layout.reader_transition_view, this) + } + + fun bind(transition: ChapterTransition) { + when (transition) { + is ChapterTransition.Prev -> bindPrevChapterTransition(transition) + is ChapterTransition.Next -> bindNextChapterTransition(transition) + } + + missingChapterWarning(transition) + } + + /** + * Binds a previous chapter transition on this view and subscribes to the page load status. + */ + private fun bindPrevChapterTransition(transition: ChapterTransition) { + val prevChapter = transition.to + + val hasPrevChapter = prevChapter != null + lower_text.isVisible = hasPrevChapter + if (hasPrevChapter) { + upper_text.textAlignment = TEXT_ALIGNMENT_TEXT_START + upper_text.text = buildSpannedString { + bold { append(context.getString(R.string.transition_current)) } + append("\n${transition.from.chapter.name}") + } + lower_text.text = buildSpannedString { + bold { append(context.getString(R.string.transition_previous)) } + append("\n${prevChapter!!.chapter.name}") + } + } else { + upper_text.textAlignment = TEXT_ALIGNMENT_CENTER + upper_text.text = context.getString(R.string.transition_no_previous) + } + } + + /** + * Binds a next chapter transition on this view and subscribes to the load status. + */ + private fun bindNextChapterTransition(transition: ChapterTransition) { + val nextChapter = transition.to + + val hasNextChapter = nextChapter != null + lower_text.isVisible = hasNextChapter + if (hasNextChapter) { + upper_text.textAlignment = TEXT_ALIGNMENT_TEXT_START + upper_text.text = buildSpannedString { + bold { append(context.getString(R.string.transition_finished)) } + append("\n${transition.from.chapter.name}") + } + lower_text.text = buildSpannedString { + bold { append(context.getString(R.string.transition_next)) } + append("\n${nextChapter!!.chapter.name}") + } + } else { + upper_text.textAlignment = TEXT_ALIGNMENT_CENTER + upper_text.text = context.getString(R.string.transition_no_next) + } + } + + private fun missingChapterWarning(transition: ChapterTransition) { + if (transition.to == null) { + warning.isVisible = false + return + } + + val fromChapterNumber: Float = floor(transition.from.chapter.chapter_number) + val toChapterNumber: Float = floor(transition.to!!.chapter.chapter_number) + + val chapterDifference = when (transition) { + is ChapterTransition.Prev -> fromChapterNumber - toChapterNumber - 1f + is ChapterTransition.Next -> toChapterNumber - fromChapterNumber - 1f + } + + val hasMissingChapters = when (transition) { + is ChapterTransition.Prev -> MissingChapters.hasMissingChapters(fromChapterNumber, toChapterNumber) + is ChapterTransition.Next -> MissingChapters.hasMissingChapters(toChapterNumber, fromChapterNumber) + } + + warning_text.text = resources.getQuantityString(R.plurals.missing_chapters_warning, chapterDifference.toInt(), chapterDifference.toInt()) + warning.isVisible = hasMissingChapters + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt index 1d4242a41..1443ab19c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerPageHolder.kt @@ -35,12 +35,12 @@ import eu.kanade.tachiyomi.ui.webview.WebViewActivity import eu.kanade.tachiyomi.util.system.ImageUtil import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.widget.ViewPagerAdapter -import java.io.InputStream -import java.util.concurrent.TimeUnit import rx.Observable import rx.Subscription import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers +import java.io.InputStream +import java.util.concurrent.TimeUnit /** * View of the ViewPager that contains a page of a chapter. @@ -307,20 +307,22 @@ class PagerPageHolder( setMinimumDpi(90) setMinimumTileDpi(180) setCropBorders(config.imageCropBorders) - setOnImageEventListener(object : SubsamplingScaleImageView.DefaultOnImageEventListener() { - override fun onReady() { - when (config.imageZoomType) { - ZoomType.Left -> setScaleAndCenter(scale, PointF(0f, 0f)) - ZoomType.Right -> setScaleAndCenter(scale, PointF(sWidth.toFloat(), 0f)) - ZoomType.Center -> setScaleAndCenter(scale, center.also { it?.y = 0f }) + setOnImageEventListener( + object : SubsamplingScaleImageView.DefaultOnImageEventListener() { + override fun onReady() { + when (config.imageZoomType) { + ZoomType.Left -> setScaleAndCenter(scale, PointF(0f, 0f)) + ZoomType.Right -> setScaleAndCenter(scale, PointF(sWidth.toFloat(), 0f)) + ZoomType.Center -> setScaleAndCenter(scale, center.also { it?.y = 0f }) + } + onImageDecoded() } - onImageDecoded() - } - override fun onImageLoadError(e: Exception) { - onImageDecodeError() + override fun onImageLoadError(e: Exception) { + onImageDecodeError() + } } - }) + ) } addView(subsamplingImageView) return subsamplingImageView!! @@ -338,16 +340,18 @@ class PagerPageHolder( setZoomTransitionDuration(viewer.config.doubleTapAnimDuration) setScaleLevels(1f, 2f, 3f) // Force 2 scale levels on double tap - setOnDoubleTapListener(object : GestureDetector.SimpleOnGestureListener() { - override fun onDoubleTap(e: MotionEvent): Boolean { - if (scale > 1f) { - setScale(1f, e.x, e.y, true) - } else { - setScale(2f, e.x, e.y, true) + setOnDoubleTapListener( + object : GestureDetector.SimpleOnGestureListener() { + override fun onDoubleTap(e: MotionEvent): Boolean { + if (scale > 1f) { + setScale(1f, e.x, e.y, true) + } else { + setScale(2f, e.x, e.y, true) + } + return true } - return true } - }) + ) } addView(imageView) return imageView!! @@ -437,31 +441,33 @@ class PagerPageHolder( .skipMemoryCache(true) .diskCacheStrategy(DiskCacheStrategy.NONE) .transition(DrawableTransitionOptions.with(NoTransition.getFactory())) - .listener(object : RequestListener { - override fun onLoadFailed( - e: GlideException?, - model: Any?, - target: Target?, - isFirstResource: Boolean - ): Boolean { - onImageDecodeError() - return false - } - - override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, - isFirstResource: Boolean - ): Boolean { - if (resource is GifDrawable) { - resource.setLoopCount(GifDrawable.LOOP_INTRINSIC) + .listener( + object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + onImageDecodeError() + return false + } + + override fun onResourceReady( + resource: Drawable?, + model: Any?, + target: Target?, + dataSource: DataSource?, + isFirstResource: Boolean + ): Boolean { + if (resource is GifDrawable) { + resource.setLoopCount(GifDrawable.LOOP_INTRINSIC) + } + onImageDecoded() + return false } - onImageDecoded() - return false } - }) + ) .into(this) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt index f116b2600..5c3d556f4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerTransitionHolder.kt @@ -8,13 +8,11 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.LinearLayout import android.widget.ProgressBar -import android.widget.TextView import androidx.appcompat.widget.AppCompatTextView -import androidx.core.text.bold -import androidx.core.text.buildSpannedString import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter +import eu.kanade.tachiyomi.ui.reader.viewer.ReaderTransitionView import eu.kanade.tachiyomi.util.system.dpToPx import eu.kanade.tachiyomi.widget.ViewPagerAdapter import rx.Subscription @@ -40,14 +38,6 @@ class PagerTransitionHolder( */ private var statusSubscription: Subscription? = null - /** - * Text view used to display the text of the current and next/prev chapters. - */ - private var textView = TextView(context).apply { - textSize = 17.5F - wrapContent() - } - /** * View container of the current status of the transition page. Child views will be added * dynamically. @@ -63,13 +53,14 @@ class PagerTransitionHolder( gravity = Gravity.CENTER val sidePadding = 64.dpToPx setPadding(sidePadding, 0, sidePadding, 0) - addView(textView) + + val transitionView = ReaderTransitionView(context) + addView(transitionView) addView(pagesContainer) - when (transition) { - is ChapterTransition.Prev -> bindPrevChapterTransition() - is ChapterTransition.Next -> bindNextChapterTransition() - } + transitionView.bind(transition) + + transition.to?.let { observeStatus(it) } } /** @@ -81,50 +72,6 @@ class PagerTransitionHolder( statusSubscription = null } - /** - * Binds a next chapter transition on this view and subscribes to the load status. - */ - private fun bindNextChapterTransition() { - val nextChapter = transition.to - - textView.text = if (nextChapter != null) { - buildSpannedString { - bold { append(context.getString(R.string.transition_finished)) } - append("\n${transition.from.chapter.name}\n\n") - bold { append(context.getString(R.string.transition_next)) } - append("\n${nextChapter.chapter.name}\n\n") - } - } else { - context.getString(R.string.transition_no_next) - } - - if (nextChapter != null) { - observeStatus(nextChapter) - } - } - - /** - * Binds a previous chapter transition on this view and subscribes to the page load status. - */ - private fun bindPrevChapterTransition() { - val prevChapter = transition.to - - textView.text = if (prevChapter != null) { - buildSpannedString { - bold { append(context.getString(R.string.transition_current)) } - append("\n${transition.from.chapter.name}\n\n") - bold { append(context.getString(R.string.transition_previous)) } - append("\n${prevChapter.chapter.name}\n\n") - } - } else { - context.getString(R.string.transition_no_previous) - } - - if (prevChapter != null) { - observeStatus(prevChapter) - } - } - /** * Observes the status of the page list of the next/previous chapter. Whenever there's a new * state, the pages container is cleaned up before setting the new state. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt index a4f5a3e95..373401ac0 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewer.kt @@ -71,15 +71,17 @@ abstract class PagerViewer(val activity: ReaderActivity) : BaseViewer { pager.offscreenPageLimit = 1 pager.id = R.id.reader_pager pager.adapter = adapter - pager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() { - override fun onPageSelected(position: Int) { - onPageChange(position) - } + pager.addOnPageChangeListener( + object : ViewPager.SimpleOnPageChangeListener() { + override fun onPageSelected(position: Int) { + onPageChange(position) + } - override fun onPageScrollStateChanged(state: Int) { - isIdle = state == ViewPager.SCROLL_STATE_IDLE + override fun onPageScrollStateChanged(state: Int) { + isIdle = state == ViewPager.SCROLL_STATE_IDLE + } } - }) + ) pager.tapListener = f@{ event -> if (!config.tappingEnabled) { activity.toggleMenu() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt index 720171e4e..fe2244cfb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/pager/PagerViewerAdapter.kt @@ -6,6 +6,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters +import eu.kanade.tachiyomi.ui.reader.viewer.MissingChapters import eu.kanade.tachiyomi.widget.ViewPagerAdapter import timber.log.Timber @@ -33,6 +34,10 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() { fun setChapters(chapters: ViewerChapters, forceTransition: Boolean) { val newItems = mutableListOf() + // Forces chapter transition if there is missing chapters + val prevHasMissingChapters = if (chapters.prevChapter != null) MissingChapters.hasMissingChapters(chapters.currChapter.chapter, chapters.prevChapter.chapter) else false + val nextHasMissingChapters = if (chapters.nextChapter != null) MissingChapters.hasMissingChapters(chapters.nextChapter.chapter, chapters.currChapter.chapter) else false + // Add previous chapter pages and transition. if (chapters.prevChapter != null) { // We only need to add the last few pages of the previous chapter, because it'll be @@ -44,7 +49,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() { } // Skip transition page if the chapter is loaded & current page is not a transition page - if (forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) { + if (prevHasMissingChapters || forceTransition || chapters.prevChapter?.state !is ReaderChapter.State.Loaded) { newItems.add(ChapterTransition.Prev(chapters.currChapter, chapters.prevChapter)) } @@ -59,7 +64,7 @@ class PagerViewerAdapter(private val viewer: PagerViewer) : ViewPagerAdapter() { // Add next chapter transition and pages. nextTransition = ChapterTransition.Next(chapters.currChapter, chapters.nextChapter) .also { - if (forceTransition || + if (nextHasMissingChapters || forceTransition || chapters.nextChapter?.state !is ReaderChapter.State.Loaded ) { newItems.add(it) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt index 92cb5192c..0aa19a2f1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonAdapter.kt @@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters +import eu.kanade.tachiyomi.ui.reader.viewer.MissingChapters /** * RecyclerView Adapter used by this [viewer] to where [ViewerChapters] updates are posted. @@ -29,6 +30,10 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter() + // Forces chapter transition if there is missing chapters + val prevHasMissingChapters = if (chapters.prevChapter != null) MissingChapters.hasMissingChapters(chapters.currChapter.chapter, chapters.prevChapter.chapter) else false + val nextHasMissingChapters = if (chapters.nextChapter != null) MissingChapters.hasMissingChapters(chapters.nextChapter.chapter, chapters.currChapter.chapter) else false + // Add previous chapter pages and transition. if (chapters.prevChapter != null) { // We only need to add the last few pages of the previous chapter, because it'll be @@ -40,7 +45,7 @@ class WebtoonAdapter(val viewer: WebtoonViewer) : RecyclerView.Adapter { - override fun onLoadFailed( - e: GlideException?, - model: Any?, - target: Target?, - isFirstResource: Boolean - ): Boolean { - onImageDecodeError() - return false - } - - override fun onResourceReady( - resource: Drawable?, - model: Any?, - target: Target?, - dataSource: DataSource?, - isFirstResource: Boolean - ): Boolean { - if (resource is GifDrawable) { - resource.setLoopCount(GifDrawable.LOOP_INTRINSIC) + .listener( + object : RequestListener { + override fun onLoadFailed( + e: GlideException?, + model: Any?, + target: Target?, + isFirstResource: Boolean + ): Boolean { + onImageDecodeError() + return false + } + + override fun onResourceReady( + resource: Drawable?, + model: Any?, + target: Target?, + dataSource: DataSource?, + isFirstResource: Boolean + ): Boolean { + if (resource is GifDrawable) { + resource.setLoopCount(GifDrawable.LOOP_INTRINSIC) + } + onImageDecoded() + return false } - onImageDecoded() - return false } - }) + ) .into(this) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt index e220b0680..16f08654c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonTransitionHolder.kt @@ -5,16 +5,14 @@ import android.view.ViewGroup.LayoutParams.MATCH_PARENT import android.view.ViewGroup.LayoutParams.WRAP_CONTENT import android.widget.LinearLayout import android.widget.ProgressBar -import android.widget.TextView import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatTextView -import androidx.core.text.bold -import androidx.core.text.buildSpannedString import androidx.core.view.isNotEmpty import androidx.core.view.isVisible import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderChapter +import eu.kanade.tachiyomi.ui.reader.viewer.ReaderTransitionView import eu.kanade.tachiyomi.util.system.dpToPx import rx.Subscription import rx.android.schedulers.AndroidSchedulers @@ -32,13 +30,7 @@ class WebtoonTransitionHolder( */ private var statusSubscription: Subscription? = null - /** - * Text view used to display the text of the current and next/prev chapters. - */ - private var textView = TextView(context).apply { - textSize = 17.5F - wrapContent() - } + private val transitionView = ReaderTransitionView(context) /** * View container of the current status of the transition page. Child views will be added @@ -63,7 +55,7 @@ class WebtoonTransitionHolder( setMargins(0, childMargins, 0, childMargins) } - layout.addView(textView, childParams) + layout.addView(transitionView) layout.addView(pagesContainer, childParams) } @@ -71,10 +63,9 @@ class WebtoonTransitionHolder( * Binds the given [transition] with this view holder, subscribing to its state. */ fun bind(transition: ChapterTransition) { - when (transition) { - is ChapterTransition.Prev -> bindPrevChapterTransition(transition) - is ChapterTransition.Next -> bindNextChapterTransition(transition) - } + transitionView.bind(transition) + + transition.to?.let { observeStatus(it, transition) } } /** @@ -84,50 +75,6 @@ class WebtoonTransitionHolder( unsubscribeStatus() } - /** - * Binds a next chapter transition on this view and subscribes to the load status. - */ - private fun bindNextChapterTransition(transition: ChapterTransition.Next) { - val nextChapter = transition.to - - textView.text = if (nextChapter != null) { - buildSpannedString { - bold { append(context.getString(R.string.transition_finished)) } - append("\n${transition.from.chapter.name}\n\n") - bold { append(context.getString(R.string.transition_next)) } - append("\n${nextChapter.chapter.name}\n\n") - } - } else { - context.getString(R.string.transition_no_next) - } - - if (nextChapter != null) { - observeStatus(nextChapter, transition) - } - } - - /** - * Binds a previous chapter transition on this view and subscribes to the page load status. - */ - private fun bindPrevChapterTransition(transition: ChapterTransition.Prev) { - val prevChapter = transition.to - - textView.text = if (prevChapter != null) { - buildSpannedString { - bold { append(context.getString(R.string.transition_current)) } - append("\n${transition.from.chapter.name}\n\n") - bold { append(context.getString(R.string.transition_previous)) } - append("\n${prevChapter.chapter.name}\n\n") - } - } else { - context.getString(R.string.transition_no_previous) - } - - if (prevChapter != null) { - observeStatus(prevChapter, transition) - } - } - /** * Observes the status of the page list of the next/previous chapter. Whenever there's a new * state, the pages container is cleaned up before setting the new state. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt index bb927f923..e2a449236 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/viewer/webtoon/WebtoonViewer.kt @@ -15,10 +15,10 @@ import eu.kanade.tachiyomi.ui.reader.model.ChapterTransition import eu.kanade.tachiyomi.ui.reader.model.ReaderPage import eu.kanade.tachiyomi.ui.reader.model.ViewerChapters import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer -import kotlin.math.max -import kotlin.math.min import rx.subscriptions.CompositeSubscription import timber.log.Timber +import kotlin.math.max +import kotlin.math.min /** * Implementation of a [BaseViewer] to display pages with a [RecyclerView]. @@ -71,28 +71,30 @@ class WebtoonViewer(val activity: ReaderActivity, val isContinuous: Boolean = tr recycler.itemAnimator = null recycler.layoutManager = layoutManager recycler.adapter = adapter - recycler.addOnScrollListener(object : RecyclerView.OnScrollListener() { - override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { - val position = layoutManager.findLastEndVisibleItemPosition() - val item = adapter.items.getOrNull(position) - val allowPreload = checkAllowPreload(item as? ReaderPage) - if (item != null && currentPage != item) { - currentPage = item - when (item) { - is ReaderPage -> onPageSelected(item, allowPreload) - is ChapterTransition -> onTransitionSelected(item) + recycler.addOnScrollListener( + object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + val position = layoutManager.findLastEndVisibleItemPosition() + val item = adapter.items.getOrNull(position) + val allowPreload = checkAllowPreload(item as? ReaderPage) + if (item != null && currentPage != item) { + currentPage = item + when (item) { + is ReaderPage -> onPageSelected(item, allowPreload) + is ChapterTransition -> onTransitionSelected(item) + } } - } - if (dy < 0) { - val firstIndex = layoutManager.findFirstVisibleItemPosition() - val firstItem = adapter.items.getOrNull(firstIndex) - if (firstItem is ChapterTransition.Prev && firstItem.to != null) { - activity.requestPreloadChapter(firstItem.to) + if (dy < 0) { + val firstIndex = layoutManager.findFirstVisibleItemPosition() + val firstItem = adapter.items.getOrNull(firstIndex) + if (firstItem is ChapterTransition.Prev && firstItem.to != null) { + activity.requestPreloadChapter(firstItem.to) + } } } } - }) + ) recycler.tapListener = f@{ event -> if (!config.tappingEnabled) { activity.toggleMenu() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt index 98f2f4245..d5c19f32d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryAdapter.kt @@ -2,9 +2,9 @@ package eu.kanade.tachiyomi.ui.recent.history import eu.davidea.flexibleadapter.FlexibleAdapter import eu.kanade.tachiyomi.source.SourceManager +import uy.kohesive.injekt.injectLazy import java.text.DecimalFormat import java.text.DecimalFormatSymbols -import uy.kohesive.injekt.injectLazy /** * Adapter of HistoryHolder. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt index cd9a4799d..595bf640c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryHolder.kt @@ -8,13 +8,13 @@ import eu.kanade.tachiyomi.data.glide.GlideApp import eu.kanade.tachiyomi.data.glide.toMangaThumbnail import eu.kanade.tachiyomi.ui.base.holder.BaseFlexibleViewHolder import eu.kanade.tachiyomi.util.lang.toTimestampString -import java.util.Date import kotlinx.android.synthetic.main.history_item.cover import kotlinx.android.synthetic.main.history_item.holder import kotlinx.android.synthetic.main.history_item.manga_subtitle import kotlinx.android.synthetic.main.history_item.manga_title import kotlinx.android.synthetic.main.history_item.remove import kotlinx.android.synthetic.main.history_item.resume +import java.util.Date /** * Holder that contains recent manga item diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt index b8b5506a1..b75a1dafd 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/history/HistoryPresenter.kt @@ -9,13 +9,13 @@ import eu.kanade.tachiyomi.data.database.models.MangaChapterHistory import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.recent.DateSectionItem import eu.kanade.tachiyomi.util.lang.toDateKey +import rx.Observable +import rx.android.schedulers.AndroidSchedulers +import uy.kohesive.injekt.injectLazy import java.util.Calendar import java.util.Comparator import java.util.Date import java.util.TreeMap -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import uy.kohesive.injekt.injectLazy /** * Presenter of HistoryFragment. diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt index 0b113f134..4e69be628 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesController.kt @@ -8,7 +8,6 @@ import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.view.ActionMode -import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.LinearLayoutManager import eu.davidea.flexibleadapter.FlexibleAdapter import eu.davidea.flexibleadapter.SelectableAdapter @@ -89,7 +88,6 @@ class UpdatesController : // Init RecyclerView and adapter val layoutManager = LinearLayoutManager(view.context) binding.recycler.layoutManager = layoutManager - binding.recycler.addItemDecoration(DividerItemDecoration(view.context, DividerItemDecoration.VERTICAL)) binding.recycler.setHasFixedSize(true) adapter = UpdatesAdapter(this@UpdatesController) binding.recycler.adapter = adapter diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt index 86a75cd2d..84b1c87e1 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/recent/updates/UpdatesPresenter.kt @@ -10,15 +10,15 @@ import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter import eu.kanade.tachiyomi.ui.recent.DateSectionItem import eu.kanade.tachiyomi.util.lang.toDateKey -import java.util.Calendar -import java.util.Date -import java.util.TreeMap import rx.Observable 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.Calendar +import java.util.Date +import java.util.TreeMap class UpdatesPresenter( val preferences: PreferencesHelper = Injekt.get(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/security/BiometricUnlockActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/security/BiometricUnlockActivity.kt index 9ab2cb267..92a7d778a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/security/BiometricUnlockActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/security/BiometricUnlockActivity.kt @@ -5,9 +5,9 @@ import androidx.appcompat.app.AppCompatActivity import androidx.biometric.BiometricPrompt import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import uy.kohesive.injekt.injectLazy import java.util.Date import java.util.concurrent.Executors -import uy.kohesive.injekt.injectLazy /** * Blank activity with a BiometricPrompt. @@ -21,7 +21,8 @@ class BiometricUnlockActivity : AppCompatActivity() { super.onCreate(savedInstanceState) val biometricPrompt = BiometricPrompt( - this, executor, + this, + executor, object : BiometricPrompt.AuthenticationCallback() { override fun onAuthenticationError(errorCode: Int, errString: CharSequence) { super.onAuthenticationError(errorCode, errString) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt index a34a13819..5549ae2fb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/security/SecureActivityDelegate.kt @@ -6,10 +6,10 @@ import androidx.biometric.BiometricManager import androidx.fragment.app.FragmentActivity import androidx.lifecycle.lifecycleScope import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import java.util.Date import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import uy.kohesive.injekt.injectLazy +import java.util.Date class SecureActivityDelegate(private val activity: FragmentActivity) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt index 87b114268..036896b24 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsAdvancedController.kt @@ -15,7 +15,6 @@ import eu.kanade.tachiyomi.data.cache.ChapterCache import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.library.LibraryUpdateService import eu.kanade.tachiyomi.data.library.LibraryUpdateService.Target -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.util.preference.defaultValue @@ -31,6 +30,7 @@ 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 class SettingsAdvancedController : SettingsController() { private val network: NetworkHelper by injectLazy() diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt index 459384fdb..dd1ef0bf9 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBackupController.kt @@ -19,7 +19,6 @@ import eu.kanade.tachiyomi.data.backup.BackupCreatorJob import eu.kanade.tachiyomi.data.backup.BackupRestoreService import eu.kanade.tachiyomi.data.backup.BackupRestoreValidator import eu.kanade.tachiyomi.data.backup.models.Backup -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.ui.base.controller.DialogController import eu.kanade.tachiyomi.ui.base.controller.requestPermissionsSafe @@ -36,6 +35,7 @@ import eu.kanade.tachiyomi.util.system.getFilePicker import eu.kanade.tachiyomi.util.system.toast import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsBackupController : SettingsController() { @@ -92,9 +92,12 @@ class SettingsBackupController : SettingsController() { key = Keys.backupInterval titleRes = R.string.pref_backup_interval entriesRes = arrayOf( - R.string.update_never, R.string.update_6hour, - R.string.update_12hour, R.string.update_24hour, - R.string.update_48hour, R.string.update_weekly + R.string.update_never, + R.string.update_6hour, + R.string.update_12hour, + R.string.update_24hour, + R.string.update_48hour, + R.string.update_weekly ) entryValues = arrayOf("0", "6", "12", "24", "48", "168") defaultValue = "0" @@ -213,8 +216,11 @@ class SettingsBackupController : SettingsController() { override fun onCreateDialog(savedViewState: Bundle?): Dialog { val activity = activity!! val options = arrayOf( - R.string.manga, R.string.categories, R.string.chapters, - R.string.track, R.string.history + R.string.manga, + R.string.categories, + R.string.chapters, + R.string.track, + R.string.history ) .map { activity.getString(it) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt index 7212095c3..61defdcfb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsBrowseController.kt @@ -2,13 +2,13 @@ package eu.kanade.tachiyomi.ui.setting import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.extension.ExtensionUpdateJob import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.onChange import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsBrowseController : SettingsController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt index 76ff9f196..d11d8dea8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsDownloadController.kt @@ -15,7 +15,6 @@ import com.hippo.unifile.UniFile import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.ui.base.controller.DialogController @@ -29,12 +28,13 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.getFilePicker -import java.io.File import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy +import java.io.File +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsDownloadController : SettingsController() { @@ -76,8 +76,11 @@ class SettingsDownloadController : SettingsController() { key = Keys.removeAfterReadSlots titleRes = R.string.pref_remove_after_read entriesRes = arrayOf( - R.string.disabled, R.string.last_read_chapter, - R.string.second_to_last, R.string.third_to_last, R.string.fourth_to_last, + R.string.disabled, + R.string.last_read_chapter, + R.string.second_to_last, + R.string.third_to_last, + R.string.fourth_to_last, R.string.fifth_to_last ) entryValues = arrayOf("-1", "0", "1", "2", "3", "4") diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt index b28d74af2..473254905 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsGeneralController.kt @@ -5,8 +5,6 @@ import android.os.Build import android.provider.Settings import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys -import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.entriesRes @@ -19,8 +17,10 @@ import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.LocaleHelper -import java.util.Date import kotlinx.coroutines.flow.launchIn +import java.util.Date +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys +import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values class SettingsGeneralController : SettingsController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt index 4d83eaf83..46f2d2136 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsLibraryController.kt @@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.DatabaseHelper import eu.kanade.tachiyomi.data.database.models.Category import eu.kanade.tachiyomi.data.library.LibraryUpdateJob -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.ui.base.controller.DialogController @@ -35,6 +34,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsLibraryController : SettingsController() { @@ -123,9 +123,14 @@ class SettingsLibraryController : SettingsController() { key = Keys.libraryUpdateInterval titleRes = R.string.pref_library_update_interval entriesRes = arrayOf( - R.string.update_never, R.string.update_1hour, - R.string.update_2hour, R.string.update_3hour, R.string.update_6hour, - R.string.update_12hour, R.string.update_24hour, R.string.update_48hour + R.string.update_never, + R.string.update_1hour, + R.string.update_2hour, + R.string.update_3hour, + R.string.update_6hour, + R.string.update_12hour, + R.string.update_24hour, + R.string.update_48hour ) entryValues = arrayOf("0", "1", "2", "3", "6", "12", "24", "48") defaultValue = "24" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt index 42708094a..58859bdc8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsParentalControlsController.kt @@ -2,14 +2,14 @@ package eu.kanade.tachiyomi.ui.setting import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys -import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.entriesRes import eu.kanade.tachiyomi.util.preference.infoPreference import eu.kanade.tachiyomi.util.preference.listPreference import eu.kanade.tachiyomi.util.preference.preferenceCategory import eu.kanade.tachiyomi.util.preference.titleRes +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys +import eu.kanade.tachiyomi.data.preference.PreferenceValues as Values class SettingsParentalControlsController : SettingsController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt index fbbcd9056..f4162958e 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsReaderController.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.setting import android.os.Build import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.PreferenceValues.TappingInvertMode import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.util.preference.defaultValue @@ -16,6 +15,7 @@ import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.hasDisplayCutout import kotlinx.coroutines.flow.launchIn +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsReaderController : SettingsController() { @@ -26,8 +26,11 @@ class SettingsReaderController : SettingsController() { key = Keys.defaultViewer titleRes = R.string.pref_viewer_type entriesRes = arrayOf( - R.string.left_to_right_viewer, R.string.right_to_left_viewer, - R.string.vertical_viewer, R.string.webtoon_viewer, R.string.vertical_plus_viewer + R.string.left_to_right_viewer, + R.string.right_to_left_viewer, + R.string.vertical_viewer, + R.string.webtoon_viewer, + R.string.vertical_plus_viewer ) entryValues = arrayOf("1", "2", "3", "4", "5") defaultValue = "2" @@ -68,8 +71,10 @@ class SettingsReaderController : SettingsController() { key = Keys.rotation titleRes = R.string.pref_rotation_type entriesRes = arrayOf( - R.string.rotation_free, R.string.rotation_lock, - R.string.rotation_force_portrait, R.string.rotation_force_landscape + R.string.rotation_free, + R.string.rotation_lock, + R.string.rotation_force_portrait, + R.string.rotation_force_landscape ) entryValues = arrayOf("1", "2", "3", "4") defaultValue = "1" @@ -136,9 +141,12 @@ class SettingsReaderController : SettingsController() { key = Keys.imageScaleType titleRes = R.string.pref_image_scale_type entriesRes = arrayOf( - R.string.scale_type_fit_screen, R.string.scale_type_stretch, - R.string.scale_type_fit_width, R.string.scale_type_fit_height, - R.string.scale_type_original_size, R.string.scale_type_smart_fit + R.string.scale_type_fit_screen, + R.string.scale_type_stretch, + R.string.scale_type_fit_width, + R.string.scale_type_fit_height, + R.string.scale_type_original_size, + R.string.scale_type_smart_fit ) entryValues = arrayOf("1", "2", "3", "4", "5", "6") defaultValue = "1" @@ -148,8 +156,10 @@ class SettingsReaderController : SettingsController() { key = Keys.zoomStart titleRes = R.string.pref_zoom_start entriesRes = arrayOf( - R.string.zoom_start_automatic, R.string.zoom_start_left, - R.string.zoom_start_right, R.string.zoom_start_center + R.string.zoom_start_automatic, + R.string.zoom_start_left, + R.string.zoom_start_right, + R.string.zoom_start_center ) entryValues = arrayOf("1", "2", "3", "4") defaultValue = "1" diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt index bf1bb76fd..ba8e9a650 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsSecurityController.kt @@ -3,7 +3,6 @@ package eu.kanade.tachiyomi.ui.setting import androidx.biometric.BiometricManager import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.util.preference.defaultValue import eu.kanade.tachiyomi.util.preference.intListPreference @@ -11,6 +10,7 @@ import eu.kanade.tachiyomi.util.preference.summaryRes import eu.kanade.tachiyomi.util.preference.switchPreference import eu.kanade.tachiyomi.util.preference.titleRes import kotlinx.coroutines.flow.launchIn +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsSecurityController : SettingsController() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt index dbe4e5ad9..ffb2daee8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/setting/SettingsTrackingController.kt @@ -5,7 +5,6 @@ import android.content.Intent import androidx.browser.customtabs.CustomTabsIntent import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackService import eu.kanade.tachiyomi.data.track.anilist.AnilistApi @@ -23,6 +22,7 @@ import eu.kanade.tachiyomi.util.preference.titleRes import eu.kanade.tachiyomi.util.system.getResourceColor import eu.kanade.tachiyomi.widget.preference.LoginPreference import uy.kohesive.injekt.injectLazy +import eu.kanade.tachiyomi.data.preference.PreferenceKeys as Keys class SettingsTrackingController : SettingsController(), diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt new file mode 100644 index 000000000..cccb214d6 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSettingsHelper.kt @@ -0,0 +1,60 @@ +package eu.kanade.tachiyomi.util.chapter + +import eu.kanade.tachiyomi.data.database.DatabaseHelper +import eu.kanade.tachiyomi.data.database.models.Manga +import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.util.lang.launchIO +import uy.kohesive.injekt.injectLazy + +object ChapterSettingsHelper { + + private val prefs: PreferencesHelper by injectLazy() + private val db: DatabaseHelper by injectLazy() + + /** + * Updates the global Chapter Settings in Preferences. + */ + fun setGlobalSettings(manga: Manga?) { + manga?.let { + prefs.setChapterSettingsDefault(it) + db.updateFlags(it).executeAsBlocking() + } + } + + /** + * Updates a single manga's Chapter Settings to match what's set in Preferences. + */ + fun applySettingDefaults(manga: Manga) { + with(manga) { + readFilter = prefs.filterChapterByRead() + downloadedFilter = prefs.filterChapterByDownloaded() + bookmarkedFilter = prefs.filterChapterByBookmarked() + sorting = prefs.sortChapterBySourceOrNumber() + displayMode = prefs.displayChapterByNameOrNumber() + setChapterOrder(prefs.sortChapterByAscendingOrDescending()) + } + + db.updateFlags(manga).executeAsBlocking() + } + + /** + * Updates all mangas in library with global Chapter Settings. + */ + fun updateAllMangasWithGlobalDefaults() { + launchIO { + val updatedMangas = db.getMangas().executeAsBlocking().map { manga -> + with(manga) { + readFilter = prefs.filterChapterByRead() + downloadedFilter = prefs.filterChapterByDownloaded() + bookmarkedFilter = prefs.filterChapterByBookmarked() + sorting = prefs.sortChapterBySourceOrNumber() + displayMode = prefs.displayChapterByNameOrNumber() + setChapterOrder(prefs.sortChapterByAscendingOrDescending()) + } + manga + } + + db.updateFlags(updatedMangas).executeAsBlocking() + } + } +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt index be4a87dc8..308ba27fa 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/ChapterSourceSync.kt @@ -7,10 +7,10 @@ import eu.kanade.tachiyomi.data.download.DownloadManager import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.online.HttpSource -import java.util.Date -import java.util.TreeSet import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get +import java.util.Date +import java.util.TreeSet /** * Helper method for syncing the list of chapters from the source with the ones from the database. @@ -28,7 +28,7 @@ fun syncChaptersWithSource( source: Source ): Pair, List> { if (rawSourceChapters.isEmpty()) { - throw Exception("No chapters found") + throw NoChaptersException() } val downloadManager: DownloadManager = Injekt.get() diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/chapter/NoChaptersException.kt b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/NoChaptersException.kt new file mode 100644 index 000000000..180179248 --- /dev/null +++ b/app/src/main/java/eu/kanade/tachiyomi/util/chapter/NoChaptersException.kt @@ -0,0 +1,3 @@ +package eu.kanade.tachiyomi.util.chapter + +class NoChaptersException : Exception() diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/RetryWithDelay.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/RetryWithDelay.kt index a14825a4b..bc1d9a801 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/RetryWithDelay.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/RetryWithDelay.kt @@ -1,10 +1,10 @@ package eu.kanade.tachiyomi.util.lang -import java.util.concurrent.TimeUnit.MILLISECONDS import rx.Observable import rx.Scheduler import rx.functions.Func1 import rx.schedulers.Schedulers +import java.util.concurrent.TimeUnit.MILLISECONDS class RetryWithDelay( private val maxRetries: Int = 1, diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt index 1ae62a62e..74d98276c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/lang/StringExtensions.kt @@ -1,7 +1,7 @@ package eu.kanade.tachiyomi.util.lang -import kotlin.math.floor import net.greypanther.natsort.CaseInsensitiveSimpleNaturalComparator +import kotlin.math.floor /** * Replaces the given string to have at most [count] characters using [replacement] at its end. diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt b/app/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt index 8d6c3a59b..656467850 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/storage/EpubFile.kt @@ -2,6 +2,8 @@ package eu.kanade.tachiyomi.util.storage import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga +import org.jsoup.Jsoup +import org.jsoup.nodes.Document import java.io.Closeable import java.io.File import java.io.InputStream @@ -10,8 +12,6 @@ import java.text.SimpleDateFormat import java.util.Locale import java.util.zip.ZipEntry import java.util.zip.ZipFile -import org.jsoup.Jsoup -import org.jsoup.nodes.Document /** * Wrapper over ZipFile to load files in epub format. diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/storage/OkioExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/storage/OkioExtensions.kt index 0eac12d48..c3f72c866 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/storage/OkioExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/storage/OkioExtensions.kt @@ -1,10 +1,10 @@ package eu.kanade.tachiyomi.util.storage -import java.io.File -import java.io.OutputStream import okio.BufferedSource import okio.buffer import okio.sink +import java.io.File +import java.io.OutputStream /** * Saves the given source to a file and closes it. Directories will be created if needed. diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt index 5ae9383fa..059facb3a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/LocaleHelper.kt @@ -8,8 +8,8 @@ import android.view.ContextThemeWrapper import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.ui.browse.source.SourcePresenter -import java.util.Locale import uy.kohesive.injekt.injectLazy +import java.util.Locale /** * Utility class to change the application's language in runtime. diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt index d32cc1141..8d2eea7cf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/system/WebViewClientCompat.kt @@ -61,8 +61,11 @@ abstract class WebViewClientCompat : WebViewClient() { error: WebResourceError ) { onReceivedErrorCompat( - view, error.errorCode, error.description?.toString(), - request.url.toString(), request.isForMainFrame + view, + error.errorCode, + error.description?.toString(), + request.url.toString(), + request.isForMainFrame ) } @@ -82,7 +85,9 @@ abstract class WebViewClientCompat : WebViewClient() { error: WebResourceResponse ) { onReceivedErrorCompat( - view, error.statusCode, error.reasonPhrase, + view, + error.statusCode, + error.reasonPhrase, request.url .toString(), request.isForMainFrame diff --git a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt index a215ea01d..c50f111bf 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/util/view/ViewExtensions.kt @@ -64,7 +64,7 @@ inline fun View.popupMenu( @MenuRes menuRes: Int, noinline initMenu: (Menu.() -> Unit)? = null, noinline onMenuItemClick: MenuItem.() -> Boolean -) { +): PopupMenu { val popup = PopupMenu(context, this, Gravity.NO_GRAVITY, R.attr.actionOverflowMenuStyle, 0) popup.menuInflater.inflate(menuRes, popup.menu) @@ -74,6 +74,7 @@ inline fun View.popupMenu( popup.setOnMenuItemClickListener { it.onMenuItemClick() } popup.show() + return popup } /** diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/ActionToolbar.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/ActionToolbar.kt index eb6f70c93..4b825cfd8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/ActionToolbar.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/ActionToolbar.kt @@ -59,11 +59,13 @@ class ActionToolbar @JvmOverloads constructor(context: Context, attrs: Attribute */ fun hide() { val bottomAnimation = AnimationUtils.loadAnimation(context, R.anim.exit_to_bottom) - bottomAnimation.setAnimationListener(object : SimpleAnimationListener() { - override fun onAnimationEnd(animation: Animation) { - common_action_toolbar.isVisible = false + bottomAnimation.setAnimationListener( + object : SimpleAnimationListener() { + override fun onAnimationEnd(animation: Animation) { + common_action_toolbar.isVisible = false + } } - }) + ) common_action_toolbar.startAnimation(bottomAnimation) } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/EmptyView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/EmptyView.kt index 3d56b942e..05bb89d6c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/EmptyView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/EmptyView.kt @@ -8,10 +8,10 @@ import androidx.annotation.StringRes import androidx.appcompat.widget.AppCompatButton import androidx.core.view.isVisible import eu.kanade.tachiyomi.R -import kotlin.random.Random import kotlinx.android.synthetic.main.common_view_empty.view.actions_container import kotlinx.android.synthetic.main.common_view_empty.view.text_face import kotlinx.android.synthetic.main.common_view_empty.view.text_label +import kotlin.random.Random class EmptyView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : RelativeLayout(context, attrs) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt index 44b7bd791..be59f618d 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/ExtendedNavigationView.kt @@ -4,6 +4,7 @@ import android.content.Context import android.graphics.drawable.Drawable import android.util.AttributeSet import android.view.ViewGroup +import androidx.annotation.AttrRes import androidx.annotation.CallSuper import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat @@ -45,20 +46,20 @@ open class ExtendedNavigationView @JvmOverloads constructor( /** * A checkbox belonging to a group. The group must handle selections and restrictions. */ - class CheckboxGroup(resTitle: Int, override val group: Group, checked: Boolean = false) : - Checkbox(resTitle, checked), GroupedItem + class CheckboxGroup(resTitle: Int, override val group: Group, checked: Boolean = false, enabled: Boolean = true) : + Checkbox(resTitle, checked, enabled), GroupedItem /** * A radio belonging to a group (a sole radio makes no sense). The group must handle * selections and restrictions. */ - class Radio(val resTitle: Int, override val group: Group, var checked: Boolean = false) : + class Radio(val resTitle: Int, override val group: Group, var checked: Boolean = false, var enabled: Boolean = true) : Item(), GroupedItem /** * An item with which needs more than two states (selected/deselected). */ - abstract class MultiState(val resTitle: Int, var state: Int = 0) : Item() { + abstract class MultiState(val resTitle: Int, var state: Int = 0, var enabled: Boolean = true) : Item() { /** * Returns the drawable associated to every possible each state. @@ -71,9 +72,9 @@ open class ExtendedNavigationView @JvmOverloads constructor( * @param context any context. * @param resId the vector resource to load and tint */ - fun tintVector(context: Context, resId: Int): Drawable { + fun tintVector(context: Context, resId: Int, @AttrRes colorAttrRes: Int = R.attr.colorAccent): Drawable { return AppCompatResources.getDrawable(context, resId)!!.apply { - setTint(context.getResourceColor(R.attr.colorAccent)) + setTint(context.getResourceColor(if (enabled) colorAttrRes else R.attr.colorControlNormal)) } } } @@ -82,8 +83,8 @@ open class ExtendedNavigationView @JvmOverloads constructor( * An item with which needs more than two states (selected/deselected) belonging to a group. * The group must handle selections and restrictions. */ - abstract class MultiStateGroup(resTitle: Int, override val group: Group, state: Int = 0) : - MultiState(resTitle, state), GroupedItem + abstract class MultiStateGroup(resTitle: Int, override val group: Group, state: Int = 0, enabled: Boolean = true) : + MultiState(resTitle, state, enabled), GroupedItem /** * A multistate item for sorting lists (unselected, ascending, descending). @@ -105,6 +106,27 @@ open class ExtendedNavigationView @JvmOverloads constructor( } } } + + /** + * A checkbox with 3 states (unselected, checked, explicitly unchecked). + */ + class TriStateGroup(resId: Int, group: Group) : MultiStateGroup(resId, group) { + + companion object { + const val STATE_IGNORE = 0 + const val STATE_INCLUDE = 1 + const val STATE_EXCLUDE = 2 + } + + override fun getStateDrawable(context: Context): Drawable? { + return when (state) { + STATE_IGNORE -> tintVector(context, R.drawable.ic_check_box_outline_blank_24dp, R.attr.colorControlNormal) + STATE_INCLUDE -> tintVector(context, R.drawable.ic_check_box_24dp) + STATE_EXCLUDE -> tintVector(context, R.drawable.ic_check_box_x_24dp) + else -> throw Exception("Unknown state") + } + } + } } /** @@ -213,13 +235,15 @@ open class ExtendedNavigationView @JvmOverloads constructor( val item = items[position] as Item.Radio holder.radio.setText(item.resTitle) holder.radio.isChecked = item.checked + + holder.itemView.isClickable = item.enabled + holder.radio.isEnabled = item.enabled } is CheckboxHolder -> { val item = items[position] as Item.CheckboxGroup holder.check.setText(item.resTitle) holder.check.isChecked = item.checked - // Allow disabling the holder holder.itemView.isClickable = item.enabled holder.check.isEnabled = item.enabled } @@ -228,6 +252,12 @@ open class ExtendedNavigationView @JvmOverloads constructor( val drawable = item.getStateDrawable(context) holder.text.setText(item.resTitle) holder.text.setCompoundDrawablesWithIntrinsicBounds(drawable, null, null, null) + + holder.itemView.isClickable = item.enabled + holder.text.isEnabled = item.enabled + + // Mimics checkbox/radio button + holder.text.alpha = if (item.enabled) 1f else 0.4f } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt index 3f6778089..60549d302 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/MaterialFastScroll.kt @@ -12,7 +12,9 @@ class MaterialFastScroll @JvmOverloads constructor(context: Context, attrs: Attr init { setViewsToUse( - R.layout.material_fastscroll, R.id.fast_scroller_bubble, R.id.fast_scroller_handle + R.layout.material_fastscroll, + R.id.fast_scroller_bubble, + R.id.fast_scroller_handle ) autoHideEnabled = true ignoreTouchesOutsideHandle = true diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/NegativeSeekBar.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/NegativeSeekBar.kt index 10f4f1296..36f5a7a6c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/NegativeSeekBar.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/NegativeSeekBar.kt @@ -18,7 +18,9 @@ class NegativeSeekBar @JvmOverloads constructor(context: Context, attrs: Attribu init { val styledAttributes = context.obtainStyledAttributes( attrs, - R.styleable.NegativeSeekBar, 0, 0 + R.styleable.NegativeSeekBar, + 0, + 0 ) try { @@ -28,19 +30,21 @@ class NegativeSeekBar @JvmOverloads constructor(context: Context, attrs: Attribu styledAttributes.recycle() } - super.setOnSeekBarChangeListener(object : OnSeekBarChangeListener { - override fun onProgressChanged(seekBar: SeekBar?, value: Int, fromUser: Boolean) { - listener?.onProgressChanged(seekBar, minValue + value, fromUser) - } + super.setOnSeekBarChangeListener( + object : OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar?, value: Int, fromUser: Boolean) { + listener?.onProgressChanged(seekBar, minValue + value, fromUser) + } - override fun onStartTrackingTouch(p0: SeekBar?) { - listener?.onStartTrackingTouch(p0) - } + override fun onStartTrackingTouch(p0: SeekBar?) { + listener?.onStartTrackingTouch(p0) + } - override fun onStopTrackingTouch(p0: SeekBar?) { - listener?.onStopTrackingTouch(p0) + override fun onStopTrackingTouch(p0: SeekBar?) { + listener?.onStopTrackingTouch(p0) + } } - }) + ) } override fun setProgress(progress: Int) { diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt index 69dcde091..8201d3b4a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/RevealAnimationView.kt @@ -25,7 +25,11 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att // Create the animation (the final radius is zero). val anim = ViewAnimationUtils.createCircularReveal( - this, centerX, centerY, initialRadius.toFloat(), 0f + this, + centerX, + centerY, + initialRadius.toFloat(), + 0f ) // Set duration of animation. @@ -55,7 +59,11 @@ class RevealAnimationView @JvmOverloads constructor(context: Context, attrs: Att // Create animation val anim = ViewAnimationUtils.createCircularReveal( - this, centerX, centerY, 0f, height.toFloat() + this, + centerX, + centerY, + 0f, + height.toFloat() ) // Set duration of animation diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleNavigationView.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleNavigationView.kt index 1d91b7b76..af0cdcfe4 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleNavigationView.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/SimpleNavigationView.kt @@ -18,8 +18,8 @@ import androidx.recyclerview.widget.RecyclerView import com.google.android.material.R import com.google.android.material.internal.ScrimInsetsFrameLayout import com.google.android.material.textfield.TextInputLayout -import eu.kanade.tachiyomi.R as TR import eu.kanade.tachiyomi.util.view.inflate +import eu.kanade.tachiyomi.R as TR @Suppress("LeakingThis") @SuppressLint("PrivateResource", "RestrictedApi") @@ -37,20 +37,24 @@ open class SimpleNavigationView @JvmOverloads constructor( init { // Custom attributes val a = TintTypedArray.obtainStyledAttributes( - context, attrs, - R.styleable.NavigationView, defStyleAttr, + context, + attrs, + R.styleable.NavigationView, + defStyleAttr, R.style.Widget_Design_NavigationView ) ViewCompat.setBackground( - this, a.getDrawable(R.styleable.NavigationView_android_background) + this, + a.getDrawable(R.styleable.NavigationView_android_background) ) if (a.hasValue(R.styleable.NavigationView_elevation)) { ViewCompat.setElevation( this, a.getDimensionPixelSize( - R.styleable.NavigationView_elevation, 0 + R.styleable.NavigationView_elevation, + 0 ).toFloat() ) } diff --git a/app/src/main/java/eu/kanade/tachiyomi/widget/TabbedBottomSheetDialog.kt b/app/src/main/java/eu/kanade/tachiyomi/widget/TabbedBottomSheetDialog.kt index 80b196f3e..8b840ac29 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/widget/TabbedBottomSheetDialog.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/widget/TabbedBottomSheetDialog.kt @@ -1,16 +1,16 @@ package eu.kanade.tachiyomi.widget -import android.app.Activity import android.view.View import android.view.ViewGroup +import com.bluelinelabs.conductor.Router import com.google.android.material.bottomsheet.BottomSheetDialog import eu.kanade.tachiyomi.databinding.CommonTabbedSheetBinding -abstract class TabbedBottomSheetDialog(private val activity: Activity) : BottomSheetDialog(activity) { +abstract class TabbedBottomSheetDialog(private val router: Router) : BottomSheetDialog(router.activity!!) { + + val binding: CommonTabbedSheetBinding = CommonTabbedSheetBinding.inflate(router.activity!!.layoutInflater) init { - val binding: CommonTabbedSheetBinding = CommonTabbedSheetBinding.inflate(activity.layoutInflater) - val adapter = LibrarySettingsSheetAdapter() binding.pager.offscreenPageLimit = 2 binding.pager.adapter = adapter @@ -34,7 +34,7 @@ abstract class TabbedBottomSheetDialog(private val activity: Activity) : BottomS } override fun getPageTitle(position: Int): CharSequence { - return activity.resources!!.getString(getTabTitles()[position]) + return router.activity!!.resources!!.getString(getTabTitles()[position]) } } } diff --git a/app/src/main/res/color/outlined_button_stroke.xml b/app/src/main/res/color/outlined_button_stroke.xml deleted file mode 100644 index 0702ae4c0..000000000 --- a/app/src/main/res/color/outlined_button_stroke.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/app/src/main/res/drawable/ic_warning_white_24dp.xml b/app/src/main/res/drawable/ic_warning_white_24dp.xml new file mode 100644 index 000000000..c0cd523f5 --- /dev/null +++ b/app/src/main/res/drawable/ic_warning_white_24dp.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/drawable/list_item_selector_background.xml b/app/src/main/res/drawable/list_item_selector_background.xml new file mode 100644 index 000000000..e1b1ed5db --- /dev/null +++ b/app/src/main/res/drawable/list_item_selector_background.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/categories_item.xml b/app/src/main/res/layout/categories_item.xml index 12a0e39a0..2bbd5b8d1 100644 --- a/app/src/main/res/layout/categories_item.xml +++ b/app/src/main/res/layout/categories_item.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="@dimen/material_component_lists_single_line_with_avatar_height" - android:background="@drawable/list_item_selector"> + android:background="@drawable/list_item_selector_background"> diff --git a/app/src/main/res/layout/common_tabbed_sheet.xml b/app/src/main/res/layout/common_tabbed_sheet.xml index 22904a734..8c9cba869 100644 --- a/app/src/main/res/layout/common_tabbed_sheet.xml +++ b/app/src/main/res/layout/common_tabbed_sheet.xml @@ -1,17 +1,44 @@ - + android:layout_height="wrap_content"> + + + + + + diff --git a/app/src/main/res/layout/manga_chapters_header.xml b/app/src/main/res/layout/manga_chapters_header.xml index 8da2f17dd..5f580b13c 100644 --- a/app/src/main/res/layout/manga_chapters_header.xml +++ b/app/src/main/res/layout/manga_chapters_header.xml @@ -23,16 +23,16 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> - + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_filter_list_24dp" + app:tint="?attr/colorOnPrimary" /> diff --git a/app/src/main/res/layout/manga_info_header.xml b/app/src/main/res/layout/manga_info_header.xml index 87277aa30..80ceb2b4e 100644 --- a/app/src/main/res/layout/manga_info_header.xml +++ b/app/src/main/res/layout/manga_info_header.xml @@ -15,6 +15,7 @@ android:id="@+id/backdrop" android:layout_width="0dp" android:layout_height="0dp" + android:layout_marginBottom="?attr/actionBarSize" android:alpha="0.2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" @@ -25,6 +26,7 @@ @@ -33,7 +35,10 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" - android:padding="16dp" + android:paddingStart="16dp" + android:paddingTop="64dp" + android:paddingEnd="16dp" + android:paddingBottom="16dp" app:layout_constraintTop_toTopOf="parent"> + android:layout_marginBottom="16dp" + android:orientation="vertical"> @@ -84,91 +88,93 @@ android:textIsSelectable="false" tools:text="Artist" /> - + android:layout_marginTop="4dp"> - + + + + + + + - + + + + + android:checkable="true" + android:text="@string/add_to_library" + app:drawableTopCompat="@drawable/ic_favorite_border_24dp" + app:layout_constraintEnd_toStartOf="@+id/btn_tracking" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + - - - - - - - - - - - + @@ -176,6 +182,7 @@ android:id="@+id/manga_summary_section" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_marginTop="8dp" android:background="?attr/selectableItemBackground" android:orientation="vertical"> @@ -185,31 +192,18 @@ android:paddingStart="16dp" android:paddingEnd="16dp"> - - - + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_baseline_expand_more_24dp" + app:tint="?attr/colorOnPrimary" /> diff --git a/app/src/main/res/layout/migration_sources_controller.xml b/app/src/main/res/layout/migration_sources_controller.xml index 4f94ddbdb..f52be48e9 100644 --- a/app/src/main/res/layout/migration_sources_controller.xml +++ b/app/src/main/res/layout/migration_sources_controller.xml @@ -10,6 +10,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" + android:paddingTop="8dp" android:paddingBottom="@dimen/action_toolbar_list_padding" /> + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/source_main_controller.xml b/app/src/main/res/layout/source_main_controller.xml index 9ec606cf0..b9706bf4b 100644 --- a/app/src/main/res/layout/source_main_controller.xml +++ b/app/src/main/res/layout/source_main_controller.xml @@ -10,6 +10,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" + android:paddingTop="8dp" android:paddingBottom="@dimen/action_toolbar_list_padding" tools:listitem="@layout/source_main_controller_card_header" /> diff --git a/app/src/main/res/layout/updates_item.xml b/app/src/main/res/layout/updates_item.xml index 858356cdd..36c533b59 100644 --- a/app/src/main/res/layout/updates_item.xml +++ b/app/src/main/res/layout/updates_item.xml @@ -4,7 +4,7 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="@dimen/material_component_lists_two_line_height" - android:background="@drawable/list_item_selector" + android:background="@drawable/list_item_selector_background" android:paddingEnd="16dp"> + + + + + diff --git a/app/src/main/res/menu/manga.xml b/app/src/main/res/menu/manga.xml index a3837c201..8bbd39205 100644 --- a/app/src/main/res/menu/manga.xml +++ b/app/src/main/res/menu/manga.xml @@ -2,6 +2,13 @@ + + مؤثرات الانتقال بين الصفحات عرض رقم الصفحة اقتصاص الحدود - سطوع مخصص - فلتر ألوان مخصص + سطوع مُخصّص + مرشح لون مخصص ابقاء الشاشة مفتوحة التنقل بأزرار الصوت @@ -147,8 +147,8 @@ الوضع الرأسي اﻹجباري مسار التحميلات التحميل عبر الواي فاي فقط - الحذف عند التحديد كمقروءة - الحذف بعد إكمال القراءة + وضع علامة \"مقروءة\" يدويًا + بعد القراءة مجلد مخصص معطل آخر فصل مقروء @@ -293,7 +293,6 @@ الاتصال غير متوفر اختر صورة الغلاف اختر ملف النسخ الاحتياطي - اختر أيقونة الاختصار تحميل تجاهل لا تتوفر تحديثات جديدة @@ -364,7 +363,7 @@ اختر بيانات لتضمينها ترحيل نسخ - لا توجد لديك أي فئات. اضغط زر اﻹضافة لإنشاء واحدة لتنظيم المكتبة الخاصة بك. + ليس لديك أيّة فئات. اضغط زر اﻹضافة لإنشاء واحدة تنظيماً للمكتبة الخاصة بك. تمَّ الانتهاء من: الحالي: التّالي: @@ -513,8 +512,8 @@ متوقّف تقرأ حالياً إضافة تتبع - إظهار معلومات أقل - إظهار المزيد من المعلومات + أقل + المزيد حول في المكتبة إضافة إلى المكتبة @@ -566,7 +565,7 @@ ملف النسخ الاحتياطي غير صالح لم يتم تسجيل الدخول: %1$s لم يتم العثور على المصدر: s$1% - مزامنة أحاديّة لتحديث تقدم الفصول في خدمات التتبع. نظّم التتبع الخاص بمانجا محدّدة من قائمة التتبع الخاصة بها. + مزامنة أحاديّة لتحديث تقدم الفصول في خدمات التتبع. قم بإعداد التتبع الخاص بمانجا محدّدة من زر التتبع الخاص بها. هذه الإضافة ليست من قائمة إضافات Tachiyomi الرسميّة. غير رسمي عرض إشعارات أخطاء التحديث @@ -600,4 +599,71 @@ تعطيل الكل إظهار الوضع الحالي لفترةٍ وجيزةٍ عند فتح القارئ إظهار وضع القراءة + الرقابة الأبوية + السمة + تنازلياً + تعطيل + ابدأ + تاريخ الاضافه + ما الجديد + يتطلب إعادة تشغيل التطبيق ليتم تفعيله + شبكة الاتصال + أجهزة التتبع التي لم يتم تسجيل الدخول إليها: + حذف فصول المفضلة + حذف الفصول + وضع القراءة + قد يحتوى محتوى للبالغين + محتوى غير لائق + الذهاب إلى الفصول المفتوحة + هذا لا يمنع الإضافات الغير رسمية أو التي تم وضع علامة عليها بشكل غير صحيح من اظهار محتوى غير لائق داخل التطبيق. + محجوب + منع مصادر التصفح ولكن تظهر في قائمة الملحقات + مَسموح + مصادر +18 + محلي + افتح في الإعدادات + تنزيل الفصول غير المقروءة + كليهما + عمودي + أفقي + لا شيء + عكس جهة النقر + النسخ الاحتياطي والاستعادة + تحميلات + أخطاء + مُكتمل + التقدّم + إكتمل التحميل + تعذّر تحميل الفصول بسبب انخفاض مساحة التخزين + لم يتم العثور على المصدر + + لا متتبّع + متتبّع واحد + متتبعين + بضعة متتبّعات (%d) + عدّة متتبّعات (%d) + %d متتبّعاً + + + لا فصول + فصل واحد + فصلين + بضعة فصول (%1$s) + عدّة فصول (%1$s) + %1$s فصلاً + + حالة غير معروفة + مؤلّف غير معروف + لا تمتلك أيّة مصادر مثبّتة + إبحث عن \"%1$s\" بشكلٍ شامل + حُدِّث إلى الإصدار v%1$s + + لا توجد فصول مفقودة + هناك فصل واحد مفقود + هناك فصلان مفقودتان + هناك %d فصول مفقودة + هناك %d فصول مفقودة + هناك %d فصول مفقودة + + لم يتم العثور على فصول \ No newline at end of file diff --git a/app/src/main/res/values-b+es+419/strings.xml b/app/src/main/res/values-b+es+419/strings.xml index e7e9aa9b8..e910b3e04 100644 --- a/app/src/main/res/values-b+es+419/strings.xml +++ b/app/src/main/res/values-b+es+419/strings.xml @@ -67,7 +67,7 @@ Leído No leído Marcado - Cola de descarga + Lista de descargas Más Siguiendo Deshacer @@ -103,7 +103,7 @@ Copia de seguridad Solamente incluir fuentes fijados Buscar actualizaciones de extensiones - Sincronización unidireccional para actualizar el progreso del capítulo en los servicios de rastreo. Configura el seguimiento de las entradas de manga individuales desde sus pestañas de seguimiento. + Sincronización unidireccional para actualizar el progreso del capítulo en los servicios de seguimiento. Configure el seguimiento de las entradas de manga individuales desde su botón de seguimiento. Servicios Actualizar el progreso del capítulo después de la lectura Categorías a incluir en la descarga @@ -115,8 +115,8 @@ Último capítulo leído Deshabilitado Directorio personalizado - Eliminar después de leer - Eliminar cuando se marque como leído + Despues de leer + Después de marcar manualmente como leído Sólo descargar con Wi-Fi Ubicación de descargas 25% @@ -505,7 +505,6 @@ No hay nuevas actualizaciones disponibles Ignorar Descargar - Seleccionar icono de acceso directo Seleccione el archivo de copia de seguridad Seleccione la imagen de portada Conexión no disponible @@ -589,7 +588,7 @@ Lo quiero leer Local Buscar \"%1$s\" Globalmente - Fecha de añadido + Fecha de agregado No se pudieron descargar capítulos debido al poco espacio en el disco Modo de lectura Tema @@ -604,4 +603,15 @@ Descarga completada Respaldar y restaurar No tienes fuentes fijadas + Páginas de seguimiento donde no has iniciado sesion: + Eliminar capítulos marcados + Eliminar capítulos + Puede contener contenido para mayores de 18 años + 18+ + Esto no evita que las extensiones no oficiales o potencialmente marcadas incorrectamente muestren contenido para mayores de 18 años dentro de la aplicación. + Bloquear + Bloquear fuente, mostrar en la lista de extensiones + Permitidas + Fuentes +18 + Controles parentales \ No newline at end of file diff --git a/app/src/main/res/values-bg/strings.xml b/app/src/main/res/values-bg/strings.xml index 4c0c9c575..b6f75dad7 100644 --- a/app/src/main/res/values-bg/strings.xml +++ b/app/src/main/res/values-bg/strings.xml @@ -50,8 +50,8 @@ Продължи Отвори в браузър Режим на показване - Показване - Решетка + Покажи + Компактна решетка Списък Отмени Сортирай @@ -141,7 +141,7 @@ Директория на изтеглянията Тегли само с Wi-Fi Изтрий, щом маркирам като прочетено - Изтривай след прочитане + След прочитане Персонализирана директория Изключено Последно прочетена глава @@ -161,7 +161,7 @@ Бисквитки изчистени Рестартирай диалогичните избори Изчисти базата данни - Изтрий манга и глави, които не са в библиотеката ми + Изтрий историята на манги, които не са запазени в библиотеката Сигурни ли сте\? Прочетените глави и напредъкът на манги, които не са в библиотеката Ви, ще бъдат изгубени Базата данни изчистена @@ -272,7 +272,6 @@ Изберете корица Изберете резервно копие - Изберете икона за пряк път Изтегли Игнорирай @@ -290,7 +289,7 @@ Нямате изтегляния Нямате нови глави Не сте чели нищо наскоро - Библиотеката Ви е празна, напълнете я от менюто Търсене. + Библиотеката Ви е празна. Добавете поредици в библиотеката чрез Търсене. Изтегли Грешка @@ -352,7 +351,7 @@ Търсене Общи Библиотека - Изтегляне на значки + Значка за изтеглени глави Локална Нямате категории. Натиснете плюса, за да създадете такава и да организирате библиотеката си. Мигриране @@ -470,8 +469,8 @@ Крайна дата Начална дата Добави проследяване - Покажи по-малко - Покажи повече + По-малко + Повече Инфо В библиотеката Добави към библиотеката @@ -530,14 +529,14 @@ AMOLED черно Тъмносин По подразбиране - Тъмен вариант + Тъмна тема Светлосин По подразбиране - Светъл вариант + Светла тема Система на абонаментите - Тъмна - Светла - Цветова тема + Включено + Изключено + Тъмен режим Премести най-горе Премести най-долу Най-стари @@ -563,14 +562,14 @@ Направено за %1$s с %2$s грешка Направено за %1$s с %2$s грешки - Еднопосочна синхронизация на прочетените глави. Установи проследяване за отделни манги от индивидуалния раздел за проследяване. + Еднопосочна синхронизация на прочетените глави. Установи проследяване за отделни манги от индивидуалния бутон за проследяване. Сиво Намалява бандинга, но се отразява на производителността %d категория %d категории - Покажи непрочетени + Значка за непрочетени глави Мигрирай 1 актуализация не бе успешна @@ -589,23 +588,67 @@ Изисква рестартиране на приложението, за да влезе в сила Мрежа Липсващи източници: - Резервно копие не съдържа никаква манга. - Във файла липсват метаданни. + Резервното копие не съдържа манга. + Във файла липсват данни. Невалиден резервен файл Източник не е открит: %1$s Накратко показване на текущия режим при отваряне на четеца Покажи режим на четене - Това разширение не е от официалния списък с разширения на Tachiyomi. + Това разширение не е част от официалните разширения на Тачийоми. Неофициален Показване на известия за грешки при актуализиране Провери за нова корица и подробности при актуализиране на библиотеката Автоматично обновяване на метаданните Низходящ - Деактивиране + Деактивирай Показване на раздели за категории Удобна решетка Отваряне в \"Настройки\" Започни Деактивирай всички Активира всички + Без + Език + И двете + Вертикално + Хоризонтално + Резервно копие и възстановяване + Изтегляния + Грешки + Готово + Прогрес + Изтеглянето е завършено + Главите не можаха да бъдат изтеглени поради недостатъчно място + + 1 тракер + %d тракери + + Неизвестен статус + Неизвестен автор + Нямате отметнати източници + Търси „%1$s“ глобално + Обновена до v%1$s + Какво е ново + Не сте влезли като потребител в: + Не сте влезли като потребител: %1$s + Изтрий главите с отметки + Изтрий глави + Режим на четене + Може да има съдържание 18+ + 18+ + Отиди до глави при отваряне + Тази настройка няма да спре неофициални или потенциално неправилно маркирани разширения да позволяват достъп до съдържание за възрастни в апликацията. + Блокирани + Блокирай разглеждането на източници, но ги показвай в списъка с разширения + Позволено + Източници 18+ + Родителски контрол + Тема + Изтегли непрочетените глави + Добавено на + Не са намерени глави + + Има %d липсваща глава + Има %d липсващи глави + \ No newline at end of file diff --git a/app/src/main/res/values-bn-rBD/strings.xml b/app/src/main/res/values-bn-rBD/strings.xml new file mode 100644 index 000000000..be08827a0 --- /dev/null +++ b/app/src/main/res/values-bn-rBD/strings.xml @@ -0,0 +1,4 @@ + + + নাম + \ No newline at end of file diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 9be0745b9..1a42ff294 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -4,7 +4,7 @@ ধরণ মাংগা অধ্যায়গুলো - অনুসরণকরণ + অনুসরণ করে রাখা ইতিহাস সেটিংস ডাউনলোড @@ -15,19 +15,19 @@ ব্যাকআপ সেটিংস বিশোধন - ডাউনলোডেড - পঠিত নিশানা + ডাউনলোড করা + বুকমার্ক অপঠিত পড়ুন - ফিল্টার সরান - বর্ণানুক্রমে + বাছাইকৃতগুলো সরান + বর্ণানুসারে মোট অধ্যায় - শেষ পঠিত + শেষ পড়া খোঁজ সর্বত্র খোঁজ সব নির্বাচন - পড়া হয়েছে - পড়া হয়েছে + পঠিত হিসেবে চিহ্নিত করুন + অপঠিত হিসাবে চিহ্নিত আগেরগুলো পড়া হয়েছে ডাউনলোড বুকমার্ক @@ -40,11 +40,11 @@ ধরণ যোগ করুন ধরন সম্পাদন ধরণ নামান্তর - ধরণে সরান + ধরণগুলো সেট করুন কভার ছবি সম্পাদন সাজান বাছাই করুন - ডাউনলোডেড + ডাউনলোড করা অপঠিত পরবর্তি থামুন বিরতি @@ -55,10 +55,10 @@ সরান পুনরারম্ভ সরান - ব্রাউজারে খুলুন - দেখার ধরণ পরিবর্তন করুন + ব্রাউজারে ডোকুন + প্রদর্শন মোড প্রদর্শন - গ্রিড + কমপ্যাক্ট গ্রিড তালিকা ব্যাজ ডাউনলোড বাতিল @@ -82,7 +82,7 @@ অনুসরিত অগ্রবর্তী সম্বন্ধে - সারিক্রমে মাংগাশালা + সারি প্রতি আইটেম ঘুরান আড়াআড়ি ভাবে ডিফল্ট @@ -107,7 +107,7 @@ পড়ার পর অধ্যায়গুলো সুসংগত করুন আরম্ভ স্ক্রিন ভাষা - প্রথম অবস্থা + ডিফল্ট নির্ধারিত ধরণ সর্বদা জিজ্ঞাসা করুন সম্পূর্ণ স্ক্রিন @@ -231,7 +231,7 @@ চলমান অজানা লাইসেন্সকৃত - মাংগাশালা থেকে সরিয়ে ফেলুন + মাংগাশালা থেকে সরিয়ে ফেলা হয়ছে ডাউনলোডকৃত অধ্যায়গুলো মুছে ফেলতে চান? অধ্যায়গুলো শিরোনামহীন @@ -295,7 +295,6 @@ যোগাযোগ নেই কভার ছবি নির্বাচন করুন ব্যাকআপ ফাইল নির্বাচন করুন - শর্টকাট আইকন নির্বাচন করুন ডাউনলোড এড়িয়ে যান নতুন কোন আপডেট নেই @@ -307,9 +306,9 @@ আপডেট এসেছে! মাংগার কভার ডাউনলোড নেই - কোন সাম্প্রতিক অধ্যায় নেই + কোন নতুন অধ্যায় নেই কোন সাম্প্রতিক পড়া মাংগা নেই - আপনার মাংগাশালা খালি, চাইলে মাংগাশালায় ক্যাটালগস থেকে মাংগা যোগ করতে পারেন। + আপনার মাংগাশালা খালি, চাইলে মাংগাশালায় ক্যাটালগস অংশ থেকে মাংগা যোগ করতে পারেন। আপনার কোন ধরণ নেই। যোগ চিহ্ন বাটনে ক্লিক করে একটি ধরণ তৈরী করুন এবং আপনার মাংগাশালা সাজান। ডাউনলোডার ত্রুটি @@ -322,7 +321,7 @@ সাধারণ মাংগাশালা উৎস পরিবর্তন - সংযোজিত অংশ + দরকারি অংশ সংযোজিত অংশ তথ্য সব আপডেট @@ -350,7 +349,8 @@ শিরোনাম মাংগাশালায় যোগ করা হয়েছে মাংগাশালা থেকে সরিয়ে ফেলা হয়েছে - %1$s ক্লিপবোর্ডে কপি হয়েছে + ক্লিপবোর্ডে কপি হয়েছে: +\n%1$s কাস্টম পরিমাণ ডাউনলোড করুন কাস্টম সরিয়ে নেয়ার জন্য উৎস নির্বাচন করুন @@ -373,7 +373,7 @@ পৃষ্ঠা লোড হচ্ছে … পৃষ্ঠা লোড করতে ব্যর্থ হয়েছে: %1$s দীর্ঘক্ষণ ট্যাপ ডায়ালগ - ওয়েব দর্শনে খুলুন + ওয়েবভিউ খুলুন ৩২-বিট রঙ পঠিত অধ্যায়গুলো এড়িয়ে যান রঙ ফিল্টার মিশ্রন মোড @@ -395,4 +395,66 @@ অপ্রচলিত এই এক্সটেনশন আর পাওয়া যাচ্ছে না । ইমেল ঠিকানা + লাইব্রেরিতে + মাংগাশালায় যোগ করা হয়েছে + আরও + পরিচয় + কম + বিপরীত নির্বাচন কর + তারিখ যোগ করা হয়েছে + সর্বশেষ অধ্যায় + সর্বশেষ চেক করা হয়েছে + তালিকা + বাইরে যেতে আবার ফিরে টিপুন + তাছিয়ুমি খুলা + মাধ্যম + আরও + প্রদর্শন + এটি অ্যাপ্লিকেশনটিতে 18+ সামগ্রীতে স্ফেসিং থেকে অনানুষ্ঠানিক বা সম্ভাব্যভাবে ভুলভাবে চিহ্নিত ফ্ল্যাগগুলি আটকাবে না। + অবরুদ্ধ + ব্রাউজিং উত্স অবরুদ্ধ করুন কিন্তু এক্সটেনশান তালিকায় দেখান + মঞ্জুরিপ্রাপ্ত + ১৮+ উৎস + বিজ্ঞপ্তি সামগ্রী লুকান + সুরক্ষিত পর্দা + কখনো না + সর্বদা + বায়োমেট্রিকস দিয়ে লক করুন + নিরাপত্তা + বিজ্ঞপ্তিগুলি পরিচালনা করুন + বের হতে নিশ্চিত করুন + তারিখ বিন্যাস + অ্যামোলেড কালো + গাঢ় নীল + ডিফল্ট + কালো থিম + হালকা নীল + ডিফল্ট + সাদা থিম + চালু + বন্ধ + সিস্টেম এর মতো চলুন + অন্ধকার মোড + স্থান + থিমসস + নীচে সরান + শীর্ষে স্থানে যান + পুরাতন + মাত্র নতুন + অনুসারে পুনঃক্রম করুন + উল্লটা সাজানো + সব বাতিল + আনপিন + পিন + অক্ষম + বিভাগের ট্যাবগুলি দেখান + অপঠিত ব্যাজ + ঠিকঠাক গ্রিড + মাইগ্রেট + সেটিংসে প্রবেশ করুন + শুরু + অধ্যায়গুলি দেখুন + সব বিকল করে দাও + সব সক্ষম করুন + অপঠিত অধ্যায়গুলি ডাউনলোড করুন \ No newline at end of file diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index f8b29e0c7..bfcb76c7b 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -181,8 +181,8 @@ A Ubicació de les baixades Baixa només amb Wi-Fi - Elimina en marcar com a llegit - Elimina després de llegir + Després de marcar-los manualment com a llegits + Després de llegir-los Velocitat de l\'animació del doble toc Ubicació personalitzada Desactivat @@ -347,7 +347,6 @@ Connexió no disponible Seleccioneu la imatge de portada Seleccioneu el fitxer de còpia de seguretat - Seleccioneu la icona de la drecera Baixa Ignora No hi ha cap nova actualització disponible @@ -535,7 +534,7 @@ %d categories Icones de no llegit - Sincronització unidireccional per a actualitzar el progrés dels capítols als serveis de seguiment. Configureu el seguiment d\'entrades individuals de manga a les seves pestanyes de seguiment. + Sincronització unidireccional per a actualitzar el progrés dels capítols als serveis de seguiment. Configureu el seguiment d\'entrades individuals de manga al seu botó de seguiment. Refresca les portades del manga de la biblioteca Ha fallat 1 actualització @@ -604,4 +603,19 @@ Progrés Errors Seguidors sense sessió iniciada: + Suprimeix els capítols preferits + Suprimeix capítols + Pot contenir contingut +18 + +18 + Això no evita que les extensions no oficials o possiblement mal etiquetades puguin mostrar contingut +18 a l\'aplicació. + Blocat + Bloca la navegació de les fonts però les mostra a la llista d\'extensions + Permès + Fonts +18 + Control parental + + Hi manca 1 capítol + Hi manquen %d capítols + + No s\'ha trobat cap capítol \ No newline at end of file diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index d69b05628..998af9f87 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -187,7 +187,6 @@ Synchronizace zrušena Připojení není k dispozici Vybrat záložní soubor - Vybrat ikonu zástupce Stáhnout Ignorovat Žádné nové aktualizace diff --git a/app/src/main/res/values-cv/strings.xml b/app/src/main/res/values-cv/strings.xml index 51e615792..d4c3fdc80 100644 --- a/app/src/main/res/values-cv/strings.xml +++ b/app/src/main/res/values-cv/strings.xml @@ -249,7 +249,7 @@ Ҫук ҫӑл куҫсем: Ҫакнӑ ҫӑл куҫсене ҫеҫ кӗрт Хушмасем валли ҫӗнетӳ пуррине тӗрӗслемелле - Сӑнану сервиссенче сыпӑкӑн ӳсӗмне ҫӗнетме пӗр енлӗ пӗрлӗхлени пур. Манкӑн уйрӑм ҫыравӗсемпе вӗсен сӑнану кантӑксем валли сӑнану ӗнерле. + Сӑнану сервиссенче сыпӑкӑн ӳсӗмне ҫӗнетме пӗр енлӗ пӗрлӗхлени. Манкӑн уйрӑм ҫыравӗсемпе вӗсен сӑнану пускӑчсем валли сӑнану ӗнерле. Вуланӑ хыҫҫӑн сыпӑксен ӳсӗме ҫӗнет Тиенекенсем патне кӗртмелли пухмӑшсем Вуланӑ сыпӑкран пиллӗкмӗшӗ @@ -328,7 +328,7 @@ %1$s,%2$s йӑнӑшпа тӑвӑннӑ %1$s, %2$s йӑнӑшпа тӑвӑннӑ - Пӗлӗмсене тавӑрнӑ чух ҫӑл куҫсем усӑ курӑнаҫҫӗ, ҫакӑ вара пысӑк трафик тӑкакӗсене кӳме пултарать. + Пӗлӗмсене тавӑрнӑ чух ҫӑл куҫсем усӑ курӑнаҫҫӗ, ҫакӑ вара пысӑк траффик тӑкакӗсене кӳме пултарать. \n \nТавӑрас умӗн кирлӗ хушмасене тата сӑнану сервиссене лартнине, тата вӗсене кӗнине тӗрӗсле. Сӑнану хуш @@ -371,7 +371,6 @@ Ҫӗнетӳсем шырани… Ҫӗнетӳсем тупӑнман Тиесе ил - Ярлӑк суйла Хуплашка суйла Ҫыхӑну кӗме май ҫук Пӗрлӗхлени пӑрахӑҫланӑ @@ -571,7 +570,7 @@ Янтӑвлани йӑнӑшӗ Янтӑв тӑвӑнать Мӗн эсӗ янтӑвласшӑн\? - Янтӑв пурнӑҫланать ӗнтӗ + Янтӑ пурнӑҫланать ӗнтӗ Тавӑрни вӗҫленнӗ Кӗмен: %1$s Хальхи вулавăша тавӑрма усӑ курма пулать @@ -606,10 +605,19 @@ Тиев вӗҫленӗ Йӑнӑшсем Кӗмен сӑнанусем: - Ҫӑл куҫа чарса ларт, анчах хушмасен ят-йышӗнче кӑтарт - NSFW ҫӑл куҫсем + Ҫӑл куҫа пӑхма чарса ларт, анчах хушмасен ят-йышӗнче кӑтарт + 18+ ҫӑл куҫсем Ирӗк панӑ Чарса лартнӑ Картнӑ сыпӑксене катерт Сыпӑксене катерт + 18+ шалаш пулма пултарать + 18+ + Ҫакӑ хушӑмӑн официаллӑ мар е тӗрӗс мар палӑртнӑ хушмасен 18+ шалашне кӑтартма чӑрмантармасть. + Атте-анне тӗрӗслевӗ + + 1 сыпӑк ҫук + %d сыпӑк ҫук + + Сыпӑксем ҫук \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 644fa496e..7266f8363 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -10,7 +10,7 @@ Bibliothek Verlauf Kategorien - Sicherung + Backup Einstellungen Filter Heruntergeladen @@ -161,23 +161,23 @@ Neue Kapitel herunterladen Kategorien, die heruntergeladen werden sollen Anbieter - Sicherung - Sicherung erstellen + Backup + Backup erstellen Kann benutzt werden, um die aktuelle Bibliothek wiederherzustellen - Sicherung wiederherstellen - Bibliothek mit Hilfe einer Sicherung wiederherstellen - Sicherung-Speicherort - Automatische Sicherungen - Sicherunghäufigkeit - Maximale Sicherungen - Sicherung erstellt + Backup wiederherstellen + Bibliothek mit Hilfe eines Backups wiederherstellen + Backup-Speicherort + Automatische Backups + Backuphäufigkeit + Maximale Backups + Backup erstellt Wiederherstellen abgeschlossen - Beim Wiederherstellen eines Backups werden Daten von den Quellen abgerufen, wodurch Mobilfunkkosten enstehen können. -\n -\nVergewissern Sie sich zudem, dass Sie alle benötigen Seitenlogins bereitgestellt haben, bevor Sie mit dem Wiederherstellen beginnen. + Beim Wiederherstellen eines Backups werden Daten von den Quellen abgerufen, wodurch Mobilfunkkosten enstehen können. +\n +\nVergewissere dich zudem, dass du alle benötigten Seitenlogins bereitgestellt hast, bevor du mit dem Wiederherstellen beginnst. Was möchtest du sichern\? - Sicherung wird wiederhergestellt - Erstelle Sicherung + Backup wird wiederhergestellt + Erstelle Backup Kapitel-Zwischenspeicher leeren Belegt: %1$s Zwischenspeicher geleert. %1$d Dateien wurden gelöscht @@ -283,8 +283,7 @@ Synchronisation abgebrochen Keine Verbindung möglich Wähle ein Vorschaubild - Wähle eine Sicherungsdatei - Wähle ein Verknüpfungssymbol + Wähle eine Backup-Datei Herunterladen Ignorieren Kein neues Update verfügbar @@ -449,7 +448,7 @@ Benachrichtigungsinhalt verbergen Überprüfe auf neue Kapitel Akkuverbrauch-Optimierung deaktivieren - Hilft bei Bibliotheksaktualisierungen und Sicherungen im Hintergrund + Hilft bei Bibliotheksaktualisierungen und Backups im Hintergrund Akkuverbrauch-Optimierung ist bereits deaktiviert E-Mail-Adresse Kapitelübergang immer anzeigen @@ -503,11 +502,11 @@ Beenden bestätigen Nur Heruntergeladenes Kap. %1$s - %2$s - Sicherungswiederherstellung fehlgeschlagen - Sicherung fehlgeschlagen + Backup-Wiederherstellung fehlgeschlagen + Backup fehlgeschlagen Wiederherstellung abgebrochen Wiederherstellung wird bereits durchgeführt - Sicherung wird bereits durchgeführt + Backup wird bereits durchgeführt Ungültiges Datum angegeben Datum des Leseendes Datum des Lesebeginns @@ -535,7 +534,7 @@ Erledigt in %1$s mit %2$s Fehlern Ungelesenzähler - Einweg-Synchronisation zum Aktualisieren der Kapitelfortschritte in den Trackingdiensten. Richte Tracking für einzelne Manga über deren jeweiligen Tracking-Reiter ein. + Einweg-Synchronisation zum Aktualisieren der Kapitelfortschritte in den Trackingdiensten. Richte Tracking für einzelne Manga über deren jeweiligen Tracking-Button ein. Bibliotheksmangacover aktualisieren Eine Aktualisierung fehlgeschlagen @@ -546,9 +545,9 @@ Nach Uploaddatum Daten Fehlende Quellen: - Sicherung beinhaltet keinerlei Manga. + Backup beinhaltet keinerlei Manga. Der Datei fehlen Daten. - Ungültige Sicherungdatei + Ungültige Backupdatei Nicht angemeldet: %1$s Quelle nicht gefunden: %1$s Aktualisierungsfehler-Benachrichtigungen anzeigen @@ -605,12 +604,19 @@ Fortschritt Fehler Nicht-eingeloggte Tracker: - NSFW-Quellen + 18+ Quellen Blockiert - Quelle blockieren, aber in der Erweiterungsliste anzeigen + Stöbern der Quelle blockieren, aber in der Erweiterungsliste anzeigen Erlaubt Mit Lesezeichen versehene Kapitel löschen Kapitel löschen Kann 18+ Inhalte enthalten 18+ + Dies verhindert nicht, dass inoffizielle oder möglicherweise falsch gekennzeichnete Erweiterungen 18+ Inhalte in der App anzeigen. + Kindersicherung + + Es gibt 1 fehlendes Kapitel + Es gibt %d fehlende Kapitel + + Keine Kapitel gefunden \ No newline at end of file diff --git a/app/src/main/res/values-el/strings.xml b/app/src/main/res/values-el/strings.xml index 33050bb64..d188c6741 100644 --- a/app/src/main/res/values-el/strings.xml +++ b/app/src/main/res/values-el/strings.xml @@ -182,8 +182,8 @@ A Τοποθεσία λήψεων Λήψη μόνο μέσω Wi-Fi - Διαγραφή αν σημειώνεται ως αναγνωσμένο - Διαγραφή μετά την ανάγνωση + Μετά από χειροκίνητη επισήμανση ως αναγνωσμένο + Μετά την ανάγνωση Προσαρμοσμένη τοποθεσία Απενεργοποιημένο Τελευταίο αναγνωσμένο κεφάλαιο @@ -347,7 +347,6 @@ Η σύνδεση δεν είναι διαθέσιμη Επιλέξτε εικόνα εξωφύλλου Επιλέξτε αρχείο αντιγράφου ασφαλείας - Επιλέξτε εικονίδιο συντόμευσης Λήψη Παράλειψη Δεν υπάρχουν διαθέσιμες νέες ενημερώσεις @@ -535,7 +534,7 @@ Έγινε σε %1$s με %2$s σφάλματα Μη αναγνωσμένα σήματα - Μονόδρομος συγχρονισμός για ενημέρωση των υπηρεσιών παρακολούθησης προόδου κεφαλαίων. Ρυθμίστε την παρακολούθηση για μεμονωμένες καταχωρήσεις manga από τις καρτέλες παρακολούθησης. + Μονόδρομος συγχρονισμός για ενημέρωση των υπηρεσιών παρακολούθησης προόδου κεφαλαίων. Ρυθμίστε την παρακολούθηση για μεμονωμένες καταχωρήσεις manga από το κουμπί παρακολούθησης τους. Ανανέωση εξώφυλλων manga της βιβλιοθήκης 1 ενημέρωση απέτυχε @@ -606,10 +605,18 @@ Σφάλματα Ιχνηλάτες που δεν έχουν συνδεθεί: Αποκλείστηκε - Αποκλεισμός πηγής αλλά εμφάνιση στη λίστα επεκτάσεων + Αποκλεισμός περιήγησης πηγών αλλά εμφάνιση στη λίστα επεκτάσεων Επιτρέπεται - Πηγές NSFW + 18+ πηγές Διαγραφή κεφαλαίων Μπορεί να περιέχει 18+ περιεχόμενο 18+ + Διαγραφή κεφαλαίων με σελιδοδείκτη + Αυτό δεν εμποδίζει τις ανεπίσημες ή ενδεχομένως εσφαλμένα επισημασμένες επεκτάσεις να εμφανίζουν περιεχόμενο 18+ περιεχόμενο στην εφαρμογή. + Γονικοί ελέγχοι + + Λείπει 1 κεφάλαιο + Λείπουν %d κεφάλαια + + Δεν βρέθηκαν κεφάλαια \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index b353d7588..6115a5bd8 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -81,7 +81,7 @@ Bloquear orientación Animar las transiciones de página Mostrar el número de página - Brillo personalizado + Utilizar brillo personalizado Mantener la pantalla encendida Navegación Teclas de volumen @@ -238,7 +238,7 @@ No hay descargas No hay actualizaciones recientes - Nada leeído recientemente + Nada leído recientemente La biblioteca está vacía. Añádale series a partir de la Busqueda. Error @@ -338,7 +338,6 @@ Cubierta actualizada Página copiada a %1$s Error al actualizar la portada - Seleccionar icono de acceso directo Descargador Predefinido no puede ser seleccionada con otras categorías Búsqueda global @@ -567,7 +566,7 @@ Hecho %1$s con %2$s error Hecho %1$s con %2$s errores - Sincronización unidireccional para actualizar el progreso del capítulo en los servicios de rastreo. Configurar el seguimiento de las entradas de manga individuales desde sus pestañas de seguimiento. + Sincronización unidireccional para actualizar el progreso del capítulo en los servicios de rastreo. Configurar el seguimiento de las entradas de manga individuales desde sus botones de seguimiento. Icono de no leídas 1 actualización fallida @@ -636,12 +635,19 @@ Progreso Errores Rastreadores no conectados: - Fuentes NSFW + Fuentes 18+ Bloqueado - Bloquear fuente pero mostrarlo en la lista de extensiones + Bloquear fuentes de navegación pero mostrarlas en la lista de extensiones Permitido Borrar capítulos marcados Borrar capítulos Puede contener contenido 18+ 18+ + Esto no evita que las extensiones no oficiales o potencialmente marcadas incorrectamente muestren contenido para mayores de 18 años dentro de la aplicación. + Controles parentales + + Falta 1 capítulo + Faltan %d capítulos + + No hay capítulos \ No newline at end of file diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index 7b4584822..59e1c3304 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -14,7 +14,6 @@ هیچ آپدیت جدیدی موجود نیست نادیده گرفتن دانلود - آیکون میانبر را انتخاب کنید فایل پشتیبان را انتخاب کنید عکس روی جلد را انتخاب کنید اتصال در دسترس نیست diff --git a/app/src/main/res/values-fi/strings.xml b/app/src/main/res/values-fi/strings.xml index 3d0000f72..699c6da62 100644 --- a/app/src/main/res/values-fi/strings.xml +++ b/app/src/main/res/values-fi/strings.xml @@ -64,7 +64,6 @@ Yhteyttä ei ole saatavilla Valitse kansikuva Valitse varmuuskopio-tiedosto - Valitse pikakuvakkeen ikoni Lataa Ohita Ei päivityksiä saatavilla @@ -535,7 +534,7 @@ Näytä lukemattomien määrä Lukutila Laiteasetuksia ei voitu avata - Yksisuuntainen synkronointi lukujen seurantapalveluiden päivittämiseksi. Määritä yksittäisten mangamerkintöjen seuranta seurantavälilehdistä. + Yksisuuntainen synkronointi lukujen seurantapalveluiden päivittämiseksi. Määritä yksittäisten mangamerkintöjen seuranta seurantapainikkeesta. Päivitä kirjaston manga-kannet 1 päivitys epäonnistui @@ -606,11 +605,18 @@ Virheet Seurantapalvelimet joihin et ole kirjautunut sisään: Estetty - Estä lähde, mutta näytä laajennusluettelossa + Estä selaaminen lähteistä, mutta näytä laajennusluettelossa Sallittu - NSFW-lähteet + 18+ lähteet Poista kirjanmerkityt luvut Poista luvut Voi sisältää 18+ sisältöä 18+ + Tämä ei estä epävirallisia tai mahdollisesti väärin merkittyjä laajennuksia näyttämästä 18+ sisältöä sovelluksessa. + Lapsilukko + + 1 puuttuva luku + %d puuttuvaa lukua + + Lukuja ei löytynyt \ No newline at end of file diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 32934db75..ea29da7ff 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -313,7 +313,7 @@ Pag-backup Isama lamang ang mga naka-pin Tumingin ng update sa dugtong - Isahang pagsabay (sync) para ma-update ang bilang ng nabásang kabanata sa mga tagasubaybay (tracking services). Isaayos ang Pagsubaybay para sa mga manga sa kanilang mga tab ng Pagsubaybay. + Isahang pagsabay (sync) para ma-update ang bilang ng nabásang kabanata sa mga tagasubaybay (tracking services). Isaayos ang pagsubaybay sa mga ito sa Pagsubaybay na makikita sa iskrin nila. Mga Serbisyo I-update ang bahagdang nabása pagkabása Mga kategoryang kasama sa download @@ -359,7 +359,6 @@ Walang bagong update Balewalain I-download - Pumili ng shortcut icon Pumili ng backup Pumili ng pabalat Walang koneksyon @@ -605,10 +604,19 @@ Takbo Tapos na sa pag-download Di naka-login sa (mga) tagasubaybay: - Harangan pero ipakita sa Mga Dugtong + Harangan ang mga pinagkukunan pero ipakita sa Mga Dugtong Harangan Payagan - Mga NSFW + Pinagkukunang 18+ Burahin ang mga tinandaan Magbura ng kabanata + Hindi naiiwasan nito ang pagpakita ng mga 18+ ng mga di-opisyal o posibleng maling naka-flag na dugtong sa loob ng app. + Maaaring maglaman ng pang-18+ + 18+ + Kontrol ng Magulang + + May isang nawawalang kabanata + May %d (na) nawawalang kabanata + + Walang nakitang kabanata \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index d94c777c7..9977a4be7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -137,7 +137,7 @@ Répertoire de téléchargement Télécharger uniquement via Wi-Fi - Supprimer après avoir lu + Après avoir lu Désactivé Dernier chapitre lu Avant-dernier chapitre lu @@ -255,7 +255,6 @@ Sélectionner l\'image de couverture Sélectionner fichier de sauvegarde - Sélectionner une icône de raccourci Télécharger Ignorer @@ -292,7 +291,7 @@ Pas de titre Synchronisation annulée Effacer le cache des chapitres - Supprimer quand marqué comme lu + Après avoir été marqué comme lu Par source Par défaut Mise à jour de la catégorie @@ -570,7 +569,7 @@ Impossible d\'ouvrir les paramètres de l\'appareil Badges des non lus Actualiser les couvertures des séries de la bibliothèque - Permet de synchroniser automatiquement les chapitres lus avec les services externes proposés. Allez dans l\'onglet « Suivi » d\'une série pour activer son suivi. + Permet de synchroniser automatiquement les chapitres lus avec les services externes proposés. Allez dans le bouton « Suivi » d\'une série pour activer son suivi. Cette extension ne fait pas partie de la liste des extensions officielles de Tachiyomi. Non officiel @@ -632,9 +631,26 @@ %d traqueurs Vous n\'avez aucune source épinglée - Téléchargés + Téléchargement Sauvegarde et restauration Compléter Progression Téléchargement terminé + Bloquer les sources de navigation mais afficher dans la liste des extensions + Erreurs + Trackers non connectés: + Supprimer les chapitres favoris + Supprimer des chapitres + Peut contenir du contenus +18 + 18+ + Cela n\'empêche pas les extensions non officielles ou potentiellement incorrectement signalées de faire apparaître du contenu 18+ dans l\'application. + Bloqué + Autorisé + Sources 18+ + contrôle parental + + Il manque 1 chapitre + Il manque %d chapitres + + Aucun chapitre trouvé \ No newline at end of file diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index e6012cfdd..dbcdd5be7 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -31,7 +31,6 @@ אין עדכונים חדשים זמינים התעלם הורד - בחר סמל קיצור דרך בחר קובץ גיבוי בחר תמונת כריכה החיבור אינו זמין diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 16bad2e10..b25612c70 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -155,8 +155,8 @@ A डाउनलोड निर्देशिका वाई - फाई पर ही डाउनलोड करे - पढ़ा जाने चिह्नित होने पर हटाएं - पढ़ने के बाद हटा दें + मैन्युअल रूप से चिह्नित के रूप में पढ़ने के बाद + पढ़ने के बाद इच्छा अनुसार निर्देशिका बंद करें अंतिम पढ़ा अध्याय @@ -295,7 +295,6 @@ कनेक्शन उपलब्ध नहीं है कवर छवि का चयन करें बैकअप फ़ाइल का चयन करें - शॉर्टकट आइकन चुनें डाउनलोड नज़रअंदाज़ करे कोई नया अद्यतन उपलब्ध नहीं है @@ -535,7 +534,7 @@ %1$s में %2$s त्रुटियों के साथ किया गया अपठित बैज - अध्याय ट्रैकिंग सेवाओं को अपडेट करने के लिए वन-वे सिंक। उनके ट्रैकिंग टैब से व्यक्तिगत मंगा प्रविष्टियों के लिए ट्रैकिंग स्थापित करें। + ट्रैकिंग सेवाओं में अध्याय की प्रगति को अद्यतन करने के लिए एकतरफा सिंक। अपने ट्रैकिंग बटन से व्यक्तिगत मंगा प्रविष्टियों के लिए ट्रैकिंग सेट अप करें। रिफ्रेश पुस्तकालय मंगा कवर 1 अद्यतन विफल हुआ @@ -604,4 +603,19 @@ प्रगती डाउनलोड सम्पन्न हुआ त्रुटियाँ + ट्रैकर्स में लॉग इन नहीं किया गया: + बुकमार्क अध्यायों को हटाएं + अध्यायों को हटाएं + 18+ सामग्री हो सकती है + 18+ + अवरुद्ध + ब्राउज़िंग स्रोतों को ब्लॉक करें लेकिन एक्सटेंशन सूची में दिखाएं + 18+ स्रोत + अनुमति + पैतृक नियंत्रण + यह अनौपचारिक या संभावित रूप से फ़्लैग किए गए एक्सटेंशन को ऐप के भीतर 18+ सामग्री के सामने आने से नहीं रोकता है। + + 1 लापता अध्याय है + %d लापता अध्याय हैं + \ No newline at end of file diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index 59f004771..940685bf2 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -224,8 +224,8 @@ Zadnje pročitano poglavlje Isključeno Prilagođeno mjesto - Ukloni nakon čitanja - Ukloni kad se označi kao pročitano + Nakon čitanja + Nakon ručnog označivanja kao pročitano Preuzimaj samo putem Wi-Fi veze Mjesto preuzimanja 25 % @@ -307,7 +307,6 @@ Nema novih ažuriranja Zanemari Preuzimanje - Odabir ikone prečaca Odaberi datoteku sigurnosne kopije Odaberi sliku naslovnice Veza nije dostupna @@ -551,7 +550,7 @@ Neispravna datoteka sigurnosne kopije Neprijavljeno: %1$s Izvor nije pronađen: %1$s - Jednosmjerna sinkronizacija za ažuriranje napretka poglavlja u usluzi praćenja. Postavi praćenje pojedinačnih unosa manga na karticama praćenja. + Jednosmjerna sinkronizacija za ažuriranje napretka poglavlja u usluzi praćenja. Postavi praćenje pojedinačnih unosa manga putem gumba za praćenje. Ovo proširenje nije sa službenog tachiyomi popisa proširenja. Neslužbeno Pokaži obavijesti o greškama pri ažuriranju @@ -614,4 +613,22 @@ Gotovo Napredak Preuzimanje gotovo + Greške + Izbriši označena poglavlja + Izbriši poglavlja + Može sadržavati 18+ sadržaj + 18+ + Blokirano + Blokiraj izvore pregledavanja, ali prikaži u popisu proširenja + Dopušteno + 18+ izvori + Roditeljski nadzor + Praćenja bez prijave: + To ne sprečava neslužbena ili potencijalno krivo označena proširenje prikazati sadržaj 18+ unutar aplikacije. + + Nedostaje jedno poglavlje + Nedostaju %d poglavlja + Nedostaje %d poglavlja + + Nema poglavlja \ No newline at end of file diff --git a/app/src/main/res/values-in/strings.xml b/app/src/main/res/values-in/strings.xml index a776ea9cb..de2e59964 100644 --- a/app/src/main/res/values-in/strings.xml +++ b/app/src/main/res/values-in/strings.xml @@ -151,8 +151,8 @@ A Lokasi unduhan Hanya unduh melalui Wi-Fi - Hapus ketika ditandai telah dibaca - Hapus semua bab yang telah dibaca sebelum + Setelah ditandai telah dibaca secara manual + Setelah dibaca Tempat kustom Tidak aktif Bab terakhir @@ -286,7 +286,6 @@ Koneksi tidak tersedia Pilih gambar sampul Pilih file cadangan - Pilih ikon pintasan Unduh Abaikan Anda telah memiliki versi yang terbaru @@ -473,7 +472,7 @@ Terdapat perbaharuan ekstensi Bab. %1$s - %2$s - Memperbaharui koleksi perpustakaan + Memperbarui koleksi perpustakaan Tambahkan pelacak Lebih sedikit Selengkapnya @@ -528,7 +527,7 @@ Selesai dalam %1$s dengan %2$s kesalahan - Sinkronisasi satu arah untuk memperbarui perkembangan bab dalam layanan pelacakan. Siapkan pelacakan untuk entri manga individual dari tab pelacakan mereka. + Sinkronisasi satu arah untuk memperbarui jejak bab dalam pelacakan. Siapkan pelacakan untuk entri manga individual dari tombol pelacakan. %1$d pembaruan gagal @@ -595,5 +594,17 @@ error Pelacakan tidak tersinkronisasi di: Diizinkan - Sumber NSFW + Sumber 18+ + Mungkin berisi konten 18+ + 18+ + Pengawasan orang tua + Diblokir + Hapus bab yang ditandai + Hapus bab + Ini tidak mencegah ekstensi yang tidak dilabeli konten 18+ di dalam aplikasi. + Blokir sumber tetapi ekstensi masih ditampilkan + + Ada %d bab yang hilang + + Bab tidak ditemukan \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 5040b20b1..8446e4b90 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -136,8 +136,8 @@ Posizione dello scaricamento Scarica solo tramite Wi-Fi - Rimuovi quando indicato come letto - Rimuovi dopo lettura + Dopo aver contrassegnato manualmente come letto + Dopo la lettura Posizione personalizzata Disabilitato Ultimo capitolo letto @@ -262,7 +262,6 @@ Seleziona immagine copertina Seleziona il file di backup - Seleziona l\'icona della scorciatoia Scarica Ignora @@ -562,7 +561,7 @@ %02d min %02d sec Includi solo le fonti fissate - Sincronizzazione a senso unico per aggiornare l\'avanzamento del capitolo sui servizi di monitoraggio. Imposta il monitoraggio per le singole voci del manga dalle loro schede di monitoraggio. + Sincronizzazione a senso unico per aggiornare l\'avanzamento del capitolo sui servizi di monitoraggio. Imposta il monitoraggio per le singole voci del manga dai loro pulsanti di monitoraggio. Riduce l\'uso della banda, ma influisce sulle prestazioni %d categoria @@ -631,4 +630,26 @@ %d tracciatori Progresso + Permesso + Backup e ripristino + Scaricamenti + Errori + Completo + Scaricamento completato + Non hai fonti fissate + Elimina capitoli contrassegnati + Elimina capitoli + Potrebbe contenere materiale 18+ + 18+ + Fonti 18+ + Filtro famiglia + + C\'è un capitolo mancante + Ci sono %d capitoli mancanti + + Trackers non collegati: + Nessun capitolo trovato + Questo non impedisce a estensioni non ufficiali o potenzialmente segnalate in modo errato di far mostrare contenuti 18+ all\'interno dell\'app. + Bloccato + Blocca le fonti di navigazione ma mostrale nell\'elenco delle estensioni \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index b8e47e174..bb6a31bd2 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -2,7 +2,7 @@ 名前 カテゴリ - 漫画 + マンガ 履歴 設定 @@ -21,7 +21,7 @@ フィルタを削除 アルファベット順 章の数順 - 最後に読んだ日時順 + 最後に読んだ順 検索 グローバル検索 すべて選択 @@ -36,7 +36,7 @@ 拡張機能の情報 移行 既読にする - 未読としてマーク + 未読にする 削除する 更新 ライブラリを更新する @@ -49,7 +49,7 @@ 前の章 次の章 リトライ - 続きから読む + 再開 ブラウザで開く 表示モード 表示 @@ -74,7 +74,7 @@ デフォルト ライブラリ更新頻度 マニュアル - 毎時 + 毎時間 2時間ごと 3時間ごと 6時間ごと @@ -132,7 +132,7 @@ ページの表示 画像デコーダ スケールの種類 - フィット画面 + 画面サイズに合わせる ストレッチ 幅に合わせる オリジナルサイズ @@ -149,13 +149,13 @@ ロック 横向き画面を強制 R - ジー + G B A ダウンロードフォルダ Wi-Fi経由でのみダウンロード - 既読の章を自動で削除 - 読んだ後に削除 + 既読とマークした後 + 読んだ後 カスタムディレクトリ 無効 最後に読んだ章の2番目 @@ -185,17 +185,17 @@ ログイン ログインしました 追加 - カテゴリー名を変更 + カテゴリー名を編集 カテゴリーを設定 昇順に並べ替え 降順に並べ替え - ダウンロード終了 + ダウンロード完了 停止 削除 インストール 取り消し ヘルプ - 前に読んだ章を既読にする + 前の章を既読にする 次の未読 移動 WebViewで開く @@ -276,7 +276,7 @@ ソースタイトル 章の数 並べ替えモード - ソース順 + ソースに基づいた順 章番号順 ダウンロード カスタムの数でダウンロード @@ -289,7 +289,7 @@ 選択した章を削除してもよろしいですか? 同期 読書中 - 読書済み + 完結済み 放棄済み 保留中 計画済み @@ -335,7 +335,6 @@ 接続していません カバー画像を選択 バックアップファイルを選択 - ショートカットアイコンを選択 ダウンロード 無視 新しいバージョンがありません @@ -346,7 +345,7 @@ ダウンロード中にエラー発生 アップデート利用可能! マンガカバー - ダウンロードタスクなし + ダウンロードタスクが空です 最近の章なし 最近に読んだマンガなし ライブラリは空です。「ブラウズ」から新しいマンガシリーズを追加してください。 @@ -363,7 +362,7 @@ ライブラリ 読み直している 未インストールのソース:%1$s - 読み終わった: + 読み終わりました: 読んでいます: 次: 前: @@ -374,7 +373,7 @@ コンテキストメニュー(長押し) 32ビットカラー 読み終わった章をスキップ - カラー フィルター ブレンド モード + カラーフィルターブレンドモード 既定 オーバーレイ スクリーン @@ -399,7 +398,7 @@ 読みたい その他 - 最新章の更新日付順 + 最新章の更新順 章を見る 全てキャンセル ダークモード @@ -420,7 +419,7 @@ 後%1$s分 セキュア画面 - Tachiyomiを開ける + Tachiyomiのロックを解除する %1$d新しい章 @@ -464,7 +463,7 @@ ソース%1$sが見つかりません ピン留め済みのソースのみで検索 拡張機能の更新を確認 - 一方に同期して追跡サービスにある章の読書進捗を更新します。個別のマンガの「同期」タブで追跡サービスを設定してください。 + 一方同期の追跡サービスにある章の読書進捗を更新します。個別のマンガの「同期」ボタンで追跡サービスを設定してください。 25% 20% 15% @@ -490,7 +489,7 @@ 更新エラーを通知で表示 ライブラリを更新時、新しい表紙と情報を確認します メタデータを自動で更新 - 行毎のアイテム数 + 行あたりのアイテム数 画面 通知コンテンツを非表示 スクリーンショットを無効化し、「最近使ったアプリ」画面にアプリの内容を非表示します @@ -511,7 +510,7 @@ 全て無効にする 全て有効にする 選択を反転 - 最近のアクセス日付順 + 最近のアクセス順 メニュー もう一度押して終了します 章の更新 @@ -541,7 +540,7 @@ 第%1$s章 - %2$s ページが見つかりません - このシリーズについて + このシリーズでは 読み終わった日付 追跡サービスを追加 紹介 @@ -593,4 +592,19 @@ テーマ ライブラリへの追加日付順 エラー + ペアレンタル‐コントロール + ログインしていないトラッカー: + ブックマークした章を削除 + 章を削除 + 成人向けのコンテンツをが含まれる可能性があります + 18禁 + 非公式や誤ってフラグ付けされた可能性のある拡張機能の18禁コンテンツはこれからも表示される恐れがあります。 + ブロック済み + ソースのブラウズをブロックするが、拡張機能リストに表示する + 許可済み + 18禁ソース + + %d章が欠けています + + 章が見つかりません \ No newline at end of file diff --git a/app/src/main/res/values-ka-rGE/strings.xml b/app/src/main/res/values-ka-rGE/strings.xml index a830f1017..6d13e434d 100644 --- a/app/src/main/res/values-ka-rGE/strings.xml +++ b/app/src/main/res/values-ka-rGE/strings.xml @@ -435,7 +435,6 @@ კავშირი არ არის ხელმისაწვდომი ამოირჩიე ყდის სურათი ამოირჩიე რეზერვის ფაილი - ამოირჩიე მალსახმობის ნიშნაკი გადმოწერა დაიგნორება განახლება ვერ მოიძებნა diff --git a/app/src/main/res/values-kn/strings.xml b/app/src/main/res/values-kn/strings.xml index 0c5447793..1a71cf139 100644 --- a/app/src/main/res/values-kn/strings.xml +++ b/app/src/main/res/values-kn/strings.xml @@ -334,7 +334,6 @@ ಹೊಸ ನವೀಕರಣಗಳು ಲಭ್ಯವಿಲ್ಲ ನಿರ್ಲಕ್ಷಿಸಿ ಡೌನ್‌ಲೋಡ್ ಮಾಡಿ - ಶಾರ್ಟ್ಕಟ್ ಐಕಾನ್ ಆಯ್ಕೆಮಾಡಿ ಬ್ಯಾಕಪ್ ಫೈಲ್ ಆಯ್ಕೆಮಾಡಿ ಕವರ್ ಇಮೇಜ್ ಆಯ್ಕೆಮಾಡಿ ಸಂಪರ್ಕ ಲಭ್ಯವಿಲ್ಲ diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index e68e54941..e0c582675 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -279,7 +279,6 @@ 연결되지 않음 표지 이미지 선택 백업 파일 선택 - 바로가기 아이콘 선택 다운로드 무시 새로운 업데이트 없음 diff --git a/app/src/main/res/values-lv/strings.xml b/app/src/main/res/values-lv/strings.xml index 2529a7714..d100446cb 100644 --- a/app/src/main/res/values-lv/strings.xml +++ b/app/src/main/res/values-lv/strings.xml @@ -203,4 +203,9 @@ Pārvietot uz leju Pārvietot uz augšu Vecākais + Lejuplādes žetoni + Nelasīti žetoni + Atļauti + 18+ avoti + Vecāku kontrole \ No newline at end of file diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index f1b788f98..6b22dd65a 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -295,7 +295,6 @@ Sambungan tidak tersedia Pilih imej muka hadapan Pilih fail sandaran - Pilih ikon pintasan Muat turun Abaikan Tiada versi baharu tersedia @@ -527,7 +526,7 @@ Selesai dalam %1$s dengan %2$s ralat Penanda tidak dibaca - Sinkron satu hala untuk kemas kini bab kemajuan dalam sistem penjejakan. Sediakan penjejakan untuk penyertaan manga persendirian dari tab penjejakan mereka. + Sinkron satu hala untuk kemas kini bab kemajuan dalam sistem penjejakan. Sediakan penjejakan untuk penyertaan manga persendirian dari butang penjejakan mereka. Segar semula muka hadapan manga pustaka %1$d gagal kemas kini @@ -594,12 +593,18 @@ Selesai Ralat Penjejak yang tidak dilog masuk: - Sumber NSFW + Sumber 18+ tahun keatas Disekat - Sekat sumber tetapi tunjuk dalam senarai sambungan + Sekat melayari sumber tetapi tunjuk dalam senarai sambungan Dibenarkan Padam bab yang ditanda Padam bab Mungkin mengandungi kandungan 18+ tahun keatas 18+ + Kawalan ibu bapa + Ini tidak menghalang sambungan yang tidak rasmi atau berpotensi tidak menggunakan tetapan yang betul daripada menayangkan kandungan 18+ tahun keatas dalam aplikasi. + + Ada %d bab yang hilang + + Tiada bab dijumpai \ No newline at end of file diff --git a/app/src/main/res/values-nb-rNO/strings.xml b/app/src/main/res/values-nb-rNO/strings.xml index dd59001a2..7f4ab4a66 100644 --- a/app/src/main/res/values-nb-rNO/strings.xml +++ b/app/src/main/res/values-nb-rNO/strings.xml @@ -357,7 +357,6 @@ Tilkobling ikke tilgjengelig Velg omslagsbilde Velg sikkerhetskopifil - Velg snarveisikon Ingen nye oppdateringer tilgjengelige Ser etter oppdateringer… Last ned oppdatering @@ -572,4 +571,16 @@ Fullført Kapittel %1$s og %2$s til Du har ingen festede kilder + Framdrift + Nedlastet + Slett bokmerkede kapittel + Slett kapittel + Kan inneholde innhold for 18+ + 18+ + Dette forhindrer ikke uoffisielle eller potensielt feilaktig kategoriserte tillegg fra å vise innhold for 18+ i programmet. + Blokkert + Blokker surfing av kilder, men vis i tilleggslisten + Tillatt + Kilder for 18+ + Foreldrekontroll \ No newline at end of file diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index b6d437123..ac1a35762 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -296,7 +296,6 @@ Niet aangesloten op netstroom Synchronisatie geannuleerd Verbinding niet beschikbaar - Selecteer icoon voor snelkoppeling Zoeken naar updates… Download update Downloaden… @@ -536,7 +535,7 @@ Ongelezen badges Omslagen van manga in bibliotheek bijwerken - Eenzijdige synchronisatie om voortang van hoofdstukken bij te werken bij trackingdiensten. Stel tracking in bij individuele manga op het tabblad Tracking. + Eenzijdige synchronisatie om voortang van hoofdstukken bij te werken bij trackingdiensten. Stel tracking in bij individuele manga via de \"Tracking\"-knop. 1 update mislukt %1$d updates mislukt @@ -606,9 +605,18 @@ Fouten Niet-ingelogde trackers: Geblokkeerd - Blokkeer bron, maar laat wel zien in lijst van extensies + Blokkeer bladeren door bronnen, maar laat wel zien in lijst van extensies Toegestaan - NSFW-bronnen + 18+-bronnen Verwijder hoofdstukken met bladwijzers Hoofdstukken verwijderen + Kan 18+-inhoud bevatten + 18+ + Dit voorkomt niet dat onofficiële of mogelijk incorrect gemarkeerde extensies 18+-inhoud kunnen laten zien in de app. + Ouderlijk toezicht + + Er is 1 missend hoofdstuk + Er zijn %d missende hoofstukken + + Geen hoofdstukken gevonden \ No newline at end of file diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index d8c538434..8689c35f7 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -299,7 +299,6 @@ Nie udało się zaktualizować okładki Zanim to zrobisz, dodaj tę mangę do biblioteki Wybierz plik kopii zapasowej - Wybierz ikonę skrótu Okładka mangi Brak pobieranych rozdziałów Brak ostatnio zaktualizowanych @@ -612,4 +611,8 @@ Motyw Pobierz nieprzeczytane rozdziały Dane dodane + Zablokuj przeglądanie ale wyświetlaj na liście rozszerzeń + Dozwolone + Źródła 18+ + Kontrola rodzicielska \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index ee94b19cf..d2c771c92 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -109,7 +109,7 @@ Tela cheia Bloquear a orientação Animar as transições de página - Mostrar o número de página + Mostrar o número da página Aparar as bordas Brilho personalizado Filtro de cor personalizado @@ -229,7 +229,7 @@ Disponível offline Na fila Download em andamento - Download em andamento (%1$d/%2$d) + Fazendo download (%1$d/%2$d) Erro Pausado Não foi possível obter os capítulos @@ -266,8 +266,8 @@ Usar como capa Capa atualizada Página copiada para %1$s - Download em andamento… - Fazendo download (%1$d%%) + Fazendo download… + %1$d%% disponível offline Página: %1$d Capítulo %1$s Próximo capítulo não encontrado @@ -285,13 +285,12 @@ Conexão indisponível Selecionar imagem de capa Selecionar arquivo de backup - Selecionar ícone do atalho Fazer download Ignorar Sem atualizações disponíveis Procurando por atualizações… Fazer download da atualização - Download em andamento… + Fazendo download… Download concluído Erro ao fazer download Nova versão disponível! @@ -331,7 +330,7 @@ Fazendo download Instalando Instalada - Confiabilidade + Confiar Não confiável Desinstalar Disponível @@ -390,7 +389,7 @@ Avançar Recarregar Biblioteca - Obsoleto + Obsoleta Esta extensão não está mais disponível. Nenhum resultado encontrado Selecione uma fonte da qual migrar @@ -407,7 +406,7 @@ Mais Último capítulo Visualizar os capítulos - Cancelar tudo + Cancelar todos Modo noturno Desligado Ligado @@ -467,7 +466,7 @@ Mais antigos Mover para o topo Mover para o final - Último verificado + Verificado por último Procurar por atualizações de extensão Atualização de extensão disponível @@ -498,7 +497,7 @@ Sobre Confirmar ao sair Pressione voltar novamente para sair - O WebView é necessário para o Tachiyomi + A WebView é necessária para o Tachiyomi Licenças de código aberto Site Somente disponíveis offline @@ -507,7 +506,7 @@ A restauração já está em andamento Cap. %1$s - %2$s Restauração cancelada - Falha na restauração do backup + Falha ao restaurar o backup Data de término da leitura Data de início da leitura Data inválida fornecida @@ -535,7 +534,7 @@ Concluído em %1$s com %2$s erros Selos de não lido - Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços de monitoramento. Configure o monitoramento para entradas individuais dos mangás em suas abas de monitoramento. + Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços de monitoramento. Configure o monitoramento para entradas individuais dos mangás a partir de seus botões de monitoramento. Atualizar as capas dos mangás da biblioteca 1 atualização falhou @@ -547,7 +546,7 @@ Dados Fontes faltando: O backup não possui nenhum mangá. - Dados faltando no arquivo. + Faltam dados no arquivo. Arquivo de backup inválido Login não realizado: %1$s Fonte não encontrada: %1$s @@ -560,8 +559,8 @@ Mostrar abas de categoria Abas Nenhuma página encontrada - Desativar todos - Ativar todos + Desativar todas + Ativar todas Mostra de forma resumida o modo atual quando o leitor for aberto Mostrar o modo de leitura Iniciar @@ -605,12 +604,19 @@ Concluído Erros Monitoradores sem login realizado: - Fontes NSFW - Bloquear fonte, mas exibi-la na lista de extensões + Fontes +18 + Bloquear a navegação nas fontes, mas exibi-las na lista de extensões Bloqueado Permitido Excluir capítulos favoritos Excluir capítulos - Pode haver conteúdo para maiores de 18 anos - 18+ + Pode haver conteúdo +18 + +18 + Controles parentais + Isso não impede que extensões não oficiais ou potencialmente sinalizadas de maneira incorreta apresentem conteúdo +18 no aplicativo. + + Há 1 capítulo faltando + Há %d capítulos faltando + + Nenhum capítulo encontrado \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index af690c02f..1643ad5c6 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -118,8 +118,8 @@ Localização das Transferências Apenas transferir por Wi-Fi - Eliminar ao marcar como lido - Eliminar depois de ler + Depois de marcado como lido + Depois de lido Localização personalizada Desativado Último capítulo @@ -400,7 +400,6 @@ Migrar Copiar Erro ao atualizar a capa - Selecionar ícone do atalho Não tem nenhuma categoria. Pressione o botão (+) para criar uma e organizar a sua biblioteca. Gestor de transferências Conexão à rede indisponível @@ -566,7 +565,7 @@ Concluído em %1$s com %2$s erros Atualizar capas das mangás da biblioteca - Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços de monitorização. Defina a monitorização para entradas individuais das mangás nas suas abas de monitorização. + Sincronização unidirecional para atualizar o progresso dos capítulos nos serviços de monitorização. Defina a monitorização para entradas individuais das mangás no seu botão de monitorização. Esta extensão não vem da lista oficial de extensões do Tachiyomi. Mostra brevemente o modo atual quando o leitor é aberto Nenhuma página encontrada @@ -635,4 +634,19 @@ Transferência concluída Erros Monitorizadores sem sessão iniciada: + Eliminar capítulos marcados + Eliminar capítulos + Pode conter conteúdo 18+ + 18+ + Isto não impede que extensões não oficiais ou potencialmente marcadas de forma incorreta surjam com conteúdos de 18+ dentro da aplicação. + Bloqueado + Bloquear fontes de navegação mas mostrar na lista de extensões + Permitido + fontes 18+ + Controlos parentais + + Há 1 capítulo em falta + Há %d capítulos em falta + + Nenhum capítulo encontrado \ No newline at end of file diff --git a/app/src/main/res/values-ro/strings.xml b/app/src/main/res/values-ro/strings.xml index f2d365b36..7413235c4 100644 --- a/app/src/main/res/values-ro/strings.xml +++ b/app/src/main/res/values-ro/strings.xml @@ -182,8 +182,8 @@ A Locația descărcărilor Descarcă doar prin Wi-Fi - Elimina când este marcat ca citit - Elimină după ce a fost citit + După ce a fost marcat manual ca citit + După citit Locație personalizată Deactivat Ultimul capitol citit @@ -347,7 +347,6 @@ Conexiune indisponibilă Selectează imagine de copertă Selectează fișierul de rezervă - Selectează pictogramă pentru scurtătură Descarcă Ignoră Nu sunt exista actualizări noi @@ -543,7 +542,7 @@ Gata în %1$s cu %2$s erori Insigne pentru necitite - Sincronizare într-un singur sens pentru a actualiza progresul capitolului în serviciile de urmărire. Configurați urmărirea pentru intrările manga individuale din filele lor de urmărire. + Sincronizare unidirecțională pentru a actualiza progresul capitolului în serviciile de urmărire. Configurați urmărirea pentru intrările individuale de manga din butonul lor de urmărire. Actualizează coperțile manga-urilor din bibliotecă După data încărcării Surse lipsă: @@ -603,4 +602,33 @@ Local Temă Data adăugării + Creează copie de rezervă și restaurează + Descărcări + Erori + Terminat + Progresul + Descărcare terminată + + Un tracker + Câteva trackere + Câteva trackere + + Trackerele nu sunt conectate la: + Ștergeți capitolele marcate + Ștergeți capitole + Poate conține conținut 18+ + Peste 18 + Acest lucru nu împiedică extensiile neoficiale sau potențial semnalizate incorect să iasă la suprafață cu conținut 18+ în cadrul aplicației. + Blocat + Blocați sursele de navigare, dar se afișează în lista de extensii + Permis + Surse 18+ + Control parental + Nu aveți surse fixate + Nu a fost găsit niciun capitol + + Lipsește un capitol + Lipsesc %d capitole + Lipsesc %d capitole + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index a2a5455c1..bd3b2cd7f 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -8,10 +8,10 @@ Отобразить Компактная сетка Список - Изменить отображение + Режим отображения Загрузить Изменить - Изменить категорию + Изменить категории Изменить обложку Фильтр Закладка @@ -46,14 +46,14 @@ По убыванию Последняя прочитанная По возрастанию - Стоп + Остановить Обновить Обновить библиотеку Все Резервная копия Черный Дата сборки - Возникла ошибка при удалении кэша + Возникла ошибка при очистке кэша Кэш очищен. %1$d файл(ов/а) был(о) удален(о) Загружено Загружается @@ -64,8 +64,8 @@ Глава %1$s Главы Заряжается - Опции выбора сбросятся - Данные удалены + Сбросить выборы в диалоговых окнах + Записи удалены Вы уверены\? Прочитанные главы и прогресс не-библиотечной манги будет потерян А R @@ -73,7 +73,7 @@ B Завершено Вы уверены что хотите удалить выбранн(ые/ую) глав(ы/у)\? - Вы уверены что хотите удалить выбранную мангу\? + Вы уверены, что хотите удалить выбранную мангу\? Использовать эту картинку как обложку\? Куки удалены Обложка обновлена @@ -100,16 +100,15 @@ Ошибка Не могу скачать главу из-за непревиденной ошибки Загружен(о) %1$d%% - Невозможно скачать главы. Можете попробовать еще раз в разделе загрузки + Невозможно скачать главы. Можете попробовать еще раз в разделе загрузок Не прочитано Загрузка… Заброшено Категория с таким именем уже существует! - Не могу извлечь главы + Не могу получить главы Пятая от прочитанной главы Выбрать файл бэкапа Выбрать обложку - Выбрать ярлык Четвёртая от прочитанной главы Ваша библиотека пуста. Добавьте тайтлы в библиотеку из Поиска. Нет загрузок @@ -123,7 +122,7 @@ История Обновления Настройки - Горизонтальная + Ландшафтный режим Последняя прочитанная глава Слева направо Название или автор… @@ -136,15 +135,15 @@ Главы Информация Загрузить - Эта манга удалена из базы данных. - Отслеживать + Эта манга была удалена из базы данных. + Отслеживание Название Следующая глава не найдена Предыдущая глава не найдена - Пожалуйста включите хотя бы один источник + Пожалуйста, включите хотя бы один источник Не удалось обновить обложку - Пожалуйста добавьте мангу в свою библиотеку, перед тем как делать это - Новые главы найдены + Пожалуйста, добавьте мангу в свою библиотеку, перед тем как делать это + Найдены новые главы Соединение не доступно Синхронизация отменена Не заряжается @@ -157,7 +156,7 @@ Пароль Картинка сохранена Планирую прочитать - Вертикальная + Портретный режим Помогает исправлять любые баги. Личные данные не передаются Обновлять прогресс глав после прочтения Информация @@ -182,11 +181,11 @@ Масштабирование Держать экран включенным Язык - Элементы в ряд - Категории, включенные в глобальный поиск + Количество элементов в строке + Категории, включенные в глобальное обновление Частота обновления библиотеки Ограничения обновления библиотеки - Обновлять, когда выполнены условия + Обновлять только когда выполнены условия Блокировать ориентацию Нажатие Клавиши громкости @@ -209,7 +208,7 @@ Заблокированная Сохраняю картинку По высоте - По экрану + Уместить в экран По ширине Исходный размер Умное @@ -225,7 +224,7 @@ Добавить мангу в библиотеку? По номеру главы По источнику - Метод сортировки + Режим сортировки Этот источник требует входа Статус По умолчанию @@ -247,8 +246,8 @@ Загрузка завершена Ошибка загрузки Загрузка… - Обновление загрузки - Доступно обновление! + Загрузить обновление + Доступна новая версия! Вручную Обновление категории Использовано: %1$s @@ -267,13 +266,13 @@ Переместить Восстановить Отменить - Эта манга уже добавлена в библиотеку - Так же удалить загруженные главы + Манга была добавлена в библиотеку + Также удалить загруженные главы Что вы хотите бэкапить\? Бэкап создан - При восстановлении используются данные из источников, что может вызвать большой расход трафика. -\n -\nТакже убедитесь, что установили и авторизировались во всех нужных расширениях и сервисах отслеживания, перед восстановлением. + При восстановлении используются данные из источников, что может вызвать большой расход трафика. +\n +\nУбедитесь, что установили и авторизовались во всех нужных расширениях и сервисах отслеживания перед восстановлением. Категории Пауза Создаем бэкап @@ -287,19 +286,19 @@ Манга Больше нет результатов Каталог бэкапа - Частота бэкапа + Частота бэкапов Автоматические бэкапы - Максимально бэкапов + Максимальное количество бэкапов Создать бэкап Можно использовать для восстановления текущей библиотеки - Границы обрезки + Обрезать поля Категории для включения в загружаемые Обновить отслеживание - Обновить статус, счет и последнюю прочитанную главу от отслеживаемых сервисов - Восстановить бэкап + Обновляет статус, оценку и последнюю прочитанную главу из сервисов отслеживания + Восстановить из бэкапа Восстановить библиотеку из бэкапа Восстановление закончено - Восстановление бэкапа + Восстановление из бэкапа Обновления Категории удалены Отслеживание @@ -310,15 +309,15 @@ Приложение недоступно Инвертировать клавиши громкости Глобальный поиск - Значок загруженных + Значки загруженных Открыть - Логин + Войти Локальная Другие Глобальный поиск… Последняя Поиск - Обычный + Общий Библиотека У вас нет категорий. Нажмите кнопку + чтобы создать категорию для организации вашей библиотеки. Мигрировать @@ -335,10 +334,10 @@ Удалить Доступно Ненадёжное расширение - Это расширение было подписано ненадёжным сертификатом и не было активировано. -\n -\nВредоносное расширение может считывать любые учетные данные для входа, хранящиеся в Tachiyomi, или выполнять произвольный код. -\n + Это расширение подписано ненадёжным сертификатом и не было активировано. +\n +\nВредоносное расширение может считывать любые учетные данные, хранящиеся в Tachiyomi, или выполнять произвольный код. +\n \nДоверяя этому сертификату, вы принимаете эти риски. Версия: %1$s Язык: %1$s @@ -347,8 +346,8 @@ Нормальная Быстрая Заголовок - Добавить в библиотеку - Удалить из библиотеки + Добавлено в библиотеку + Удалено из библиотеки Скопированно в буфер обмена: \n\"%1$s\" Загрузить определенное количество @@ -369,8 +368,8 @@ Текущий: Следующий: Предыдущий: - Следующей части нет - Предыдущей части нет + Следующей главы нет + Предыдущей главы нет Идёт загрузка страниц… Не удалось загрузить страницы: %1$s Диалог при долгом нажатии @@ -396,13 +395,13 @@ Устарело Это расширение больше недоступно. Формат даты - Обновить + Обновление Категории Выйти из %1$s\? Выйти - Вы вышли из системы + Вы успешно вышли Сейчас читаю - Пауза + Приостановлено Хочу почитать Еще Последняя глава @@ -418,7 +417,7 @@ AMOLED черный Управлять уведомлениями Безопасность - Блокировать отпечатком + Блокировать биометрией Блокировать в режиме ожидания Всегда Никогда @@ -427,8 +426,8 @@ После %1$s минут После %1$s минут - Экран безопасности - Обновления ожидаются + Защита экрана + Доступны обновления Отображать содержимое в вырезанной области Не удалось обойти Cloudflare Пожалуйста, обновите WebView для лучшей совместимости @@ -443,36 +442,38 @@ Глава %1$s Отобразить - Найденна новая глава - Найденны %1$d новые главы - Найденно %1$d новых глав + 1 новая глава + %1$d новые главы + %1$d новых глав + %1$d новых глав - Найденны новые главы для тайтла - Найденны новые главы для %d тайтлов - Найденны новые главы для %d тайтлов + Для 1 тайтла + Для %d тайтлов + Для %d тайтлов + Для %d тайтлов - Заметка о ранних версиях + Примечания к предварительной сборке Проверка наличия новых глав - Обновления библиотеки + Обновление библиотеки Проверить страницу в WebView - Оптимизация батареи уже выключенна + Оптимизация батареи уже выключена Помогает с фоновым обновлением библиотеки и бэкапом Выключить оптимизацию батареи По умолчанию Доступно обновление для расширения - Доступно %d обновления для расширений - Доступнo %d обновлений для расширений - Доступнo %d обновлений для расширений + Доступны обновления для %d расширений + Доступны обновления для %d расширений + Доступны обновления для %d расширений Адрес почты - Всегда показывать главу перехода + Всегда показывать переход между главами Проверять обновления для расширений - Скрыть содержимое уведомления - Скрыть содержимое приложения, при переключении на другие приложения, и блокировании скриншотов + Скрыть содержимое уведомлений + Скрывать содержимое приложения при переключении на другие приложения и блокировать скриншоты Бело-синяя - Белая тема + Светлая тема Старейший Новейший В начало @@ -485,7 +486,7 @@ Источники Чтение Пропускать фильтрованные главы - Выбрать наоборот + Инвертировать выбор Непрерывно вертикально Боковой отступ 25% @@ -493,31 +494,31 @@ 15% 10% Без отступа - Закрепленно + Закреплено Открепить Закрепить Добавить отслеживание - Нажмите назад, ещё раз, чтобы выйти + Нажмите назад ещё раз, чтобы выйти Только загруженное - WebView требуется для Tachiyomi + Для Tachiyomi необходим WebView Меньше Больше - Содержимое + Описание В библиотеке Добавить в библиотеку - Лицензии с открытым кодом + Лицензии открытого кода Вебсайт Подтвердить выход Гл. %1$s - %2$s - Неправильная указанная дата - Дата окончания прочтения - Дата начала прочтения - Локальное руководство источника + Неправильно указана дата + Дата окончания чтения + Дата начала чтения + Руководство по локальным источникам Последний использованный - Фильтровать всю мангу в вашей библиотеке + Фильтрует всю мангу в вашей библиотеке Проверить обновления Восстановление отменено - Ошибка восстановления бэкапа + Ошибка восстановления из бэкапа Восстановление уже выполняется Ошибка бэкапа Бэкап уже выполняется @@ -542,18 +543,18 @@ Не удалось открыть настройки устройства Обновить обложки библиотечной манги - Сделано %1$s с %2$s ошибкой - Сделано %1$s с %2$s ошибками - Сделано %1$s с %2$s ошибками - Сделано %1$s с %2$s ошибками + Выполнено за %1$s с %2$s ошибкой + Выполнено за %1$s с %2$s ошибками + Выполнено за %1$s с %2$s ошибками + Выполнено за %1$s с %2$s ошибками - Односторонняя синхронизация для обновления прогресса глав в отслеживаемых сервисов. Настройте отслеживание для отдельных записей манги с их вкладками отслеживания. - Значок непрочитанных + Односторонняя синхронизация для обновления прогресса глав в сервисах отслеживания. Настройте отслеживание отдельных записей манги при помощи их кнопок отслеживания. + Значки непрочитанных - 1 ошибка обновления - %1$d ошибки обновления - %1$d ошибок обновления - %1$d ошибок обновления + 1 неудачное обновление + %1$d неудачных обновления + %1$d неудачных обновлений + %1$d неудачных обновлений Это расширение не входит в официальный список расширений Tachiyomi. Неофициальное @@ -563,10 +564,10 @@ Бэпап не содержит мангу. В файле отсутствуют данные. Неверный файл бэкапа - Не зарегистрирован в: %1$s + Не выполнен вход в: %1$s Источник не найден: %1$s Показывать уведомления об ошибках обновления - Проверка на наличие новой обложки и деталей при обновлении библиотеки + Проверять наличие новой обложки и описания при обновлении библиотеки Автоматически обновлять метаданные Удобная сетка Мигрировать @@ -576,7 +577,7 @@ Страницы не найдены Включить всё Выключить всё - Кратко отобразить текущий режим когда читалка открыта + Ненадолго отобразить текущий режим при открытии читалки Показать режим чтения Начать Источник не найден @@ -592,7 +593,7 @@ Требуется перезапуск приложения для вступления в силу DNS по HTTPS (Cloudflare) Сеть - Перейти к открытым главам + Переходить к главам при запуске Оба Вертикально Горизонтально @@ -604,9 +605,9 @@ Обновлено до v%1$s Что нового Невозможно загрузить главы из-за нехватки места на диске - Искать для \"%1$s\" глобально + Искать \"%1$s\" глобально Режим чтения - Местоположение + Локаль Тема Дата добавления @@ -619,16 +620,25 @@ Загрузка завершена Бэкап и восстановление Загрузки - Завершено + Завершение Прогресс Ошибки - Трекеры не авторизованы: - NSFW источники + Не выполнен вход в трекеры: + Источники 18+ Заблокировано - Блокировать источник, но отображать его в списке расширений + Блокировать просмотр источников, но отображать их в списке расширений Разрешено - Удалить главы с закладками - Удалить главы + Удалять главы с закладками + Удаление глав Может содержать контент 18+ 18+ + Это не предотвращает появление внутри приложения контента 18+ из неофициальных или потенциально неправильно помеченных расширений. + Родительский контроль + + Отсутствует 1 глава + Отсутствуют %d главы + Отсутствуют %d глав + Отсутствуют %d глав + + Нет глав \ No newline at end of file diff --git a/app/src/main/res/values-sah/strings.xml b/app/src/main/res/values-sah/strings.xml index 0af421912..268dc8285 100644 --- a/app/src/main/res/values-sah/strings.xml +++ b/app/src/main/res/values-sah/strings.xml @@ -4,7 +4,7 @@ Уларыт Барытын араар Барытын холбоо - Библиотеканы саҥардыы + Бэбэлэтиэкэ саҥардыы Саҥардыы Сотон кэбис Кыбытыыны хомуй @@ -39,8 +39,8 @@ Түһүмэхтэр Маанга Бөлөхтөр - Эйиэхэ бөлөхтөр суохтар. Эбэр бэлиэни батта, библиотекаҕа саҥа бөлөҕү оҥорорго. - Эн библиотекан кураанах. Библиотекаҕа айымньыыларыы көрдөөһүнтэн эп. + Эйиэхэ бөлөхтөр суохтар. Эбэр бэлиэни батта, бэбэлэтиэкэҕэ саҥа бөлөҕү оҥорорго. + Эн бэбэлэтиэкэн кураанах. Бэбэлэтиэкэҕэ айымньыыларыы көрдөөһүнтэн эп. Бүтэһик кэмҥэ тугу да аахпатын Саҥардыылар суохтар Хачаайдааһын суох @@ -48,15 +48,15 @@ Кэҥэтии туһунан Кэҥэтии Көһүү - Резервнай куопуйа + Хаппаас куопуйа Бөлөхтөр Төрүттэр Остуоруйа Саҥардыылар - Библиотека + Бэбэлэтиэкэ Хачаайдааһын уочарата Түстэл - Өссө + Эбии Аат Tachiyomi @@ -72,8 +72,8 @@ Иитиллэр Wi-Fi Усулуобуйалар толоруллубутугар эрэ, саҥарт - Библиотека саҥардыытын хааччахтааһын - Библиотека саҥардыытын бэрээдэгэ + Бэбэлэтиэкэ саҥардыытын хааччахтааһын + Бэбэлэтиэкэ саҥардыытын бэрээдэгэ Ый аайы Нэдиэлэ аайы Икки күн аайы @@ -84,7 +84,7 @@ Икки чаас аайы Чаас аайы Илиинэн - Библиотека саҥардыытын түргэнэ + Бэбэлэтиэкэ саҥардыытын түргэнэ Саҥардыылар Аһаҕас түһүмэххэ көһүү Куолутунан @@ -127,10 +127,10 @@ Кэтээһин Хачайдаммыттар Ааҕааччы - Библиотека + Бэбэлэтиэкэ Сүрүн Саҥардыылар - Сыһыарыы кыаллыбат + Эбилик кыаллыбат Холбонуу… Чэбдигирт Инники @@ -161,7 +161,7 @@ Ааҕыллыбатахтар бэлиэлэрэ Бэлиэлэри хачайдаа Табыгастаах илим - испииһэк + Испииһэк Биир кэлим илим Көрдөр Көрүнүн уларыт @@ -292,13 +292,13 @@ Кукины ырааста Ситим Төнүҥнэри тохтоото - Резервнай куопуйа төнүҥнэриитэ туолбата - Резервнай куопуйаны төнүҥнэри туола турар + Хаппаас куопуйа төнүҥнэриитэ туолбата + Хаппаас куопуйаны төнүҥнэри туола турар Төнүҥнэрии туола турар - Резервнай куопуйа оҥоһуллубата - Резервнай куопуйа оҥоһуута + Хаппаас куопуйа оҥоһуллубата + Хаппаас куопуйа оҥоһуута Тугу куопуйалаары гынннын\? - Резервнай куопуйа оҥоруута туола турар + Хаппаас куопуйа оҥоруута туола турар Туолла %1$sҕа %2$s сыаһалаах @@ -309,29 +309,28 @@ \nУонна төнүҥнэрии иннигэр, көрүҥ, туох баар наадалах кэтээһин кэҥэтиилэригэр уонна өҥөтүгэр киирдиҥ диэн. Трэкэрдар киирбэтилэр: Суох төрүттэр: - Резервнай куопуйа маангата суох. + Хаппаас куопуйа маангата суох. Биликкэ дааннайдар суохтар. - Резервнай куопуйа алдьаммыт билэтэ - Резервнай куопуйа оҥоһуллунна + Хаппаас куопуйа алдьаммыт билэтэ + Хаппаас куопуйа оҥоһуллунна Киирбэтэх: %1$s Төрүт булуллубата: %$1s - Муҥутугар дылы резервнай куопуйалар - Резервнай куопуйа оҥоһуутун түргэнэ - Автоматическай резервнай куопуйалар - Резервнай куопуйа сурунаала - Библиотеканы резервнай куопуйа билэтиттэн төнүҥнэрии - Резервнай куопуйаны куолутунан туруоруу + Муҥутугар дылы хаппаас куопуйалар + Хаппаас куопуйа оҥоһуутун түргэнэ + Автоматическай Хаппаас куопуйалар + Хаппаас куопуйа сурунаала + Бэбэлэтиэкэни хаппаас куопуйа билэтиттэн төнүҥнэрии + Хаппаас куопуйаны куолутунан туруоруу Билиҥни бибилиотеканы төнүннэрэргэ туттуохха сөп - Резервнай куопуйаны оҥоруу + Хаппаас куопуйаны оҥоруу Хаамнаммыт - Төрүтү хаамна, ол да буоллар кэҥэтии испииһигэр көрдөр + Көрүллүбүт төрүттэри хаамна, ол да буоллар кэҥэтии испииһигэр көрдөр Көҥүллэммит - NSFW төрүттэр - Резервнай куопуйа + 18+ төрүттэр + Хаппаас куопуйа Сыһыарыллыбыт эрэ төрүттэри киллэр Кэҥэтии саҥардыыларын баар буолутун бэрэбиэркэлээһин - Биир өттүттэн мэнэйдэһии, кэтээһин өҥөлөргө баар түһүмэхтэр туруктарын саҥардыыга. Маанга туспа суругун кэтээһинин -\nтүстэлгэ уларыт. + Биир өттүттэн мэнэйдэһии, кэтээһин өҥөлөргө баар түһүмэхтэр туруктарын саҥардыыга. Маанга туспа суругун уонна талкыйын кэтээһинин түстэлгэ уларыт. Өҥөлөр Түһүмэх туругун ааҕы кэннэ саҥарт Хачайдааһыҥҥа киирбит бөлөхтөр @@ -347,27 +346,27 @@ Ааҕыллыбыт диэн суруллубутун кэннэ Wi-Fi эрэ баар буоллаҕына хачайдаа Хачайдааһын сурунаала - Уларыйыы киирэрин гына сыһыарыыны хос холбоо + Уларыйыы киирэрин гына эбилиги хос холбоо Кээс сотторуутугар сыыһааһын буолла Кээс ыраастанна. %1$d билэ сотторуллубут этэ Туттуллубут: %1$s Түһүмэх кээһин ыраастааһын Билим Куки ыраастанна - Эрэллэххин дуо\? Ааҕыллыбыт түһүмэхтэр уонна библиотекаҕа суох маанга туруга сүтүө - Эн библиотекаҕар суох маанга остуоруйатын сотторуу + Эрэллэххин дуо\? Ааҕыллыбыт түһүмэхтэр уонна бэбэлэтиэкэҕэ суох маанга туруга сүтүө + Эн бэбэлэтиэкэҕэр суох маанга остуоруйатын сотторуу Билим олоҕо ыраастааһына Кэпсэтии түстэлэ ыраастанна Батарея тупсарыытын араарыы Туругу, ахсааны уонна бүтэһик ааҕыллыбыт түһүмэҕи кэтээн көрөр өҥөлөртөн саҥардыы Кэтээһини чэбдигирии - Библиотекаҕа баар маанга таһын чэбдигирии + Бэбэлэтиэкэҕэ баар маанга таһын чэбдигирии Дааннайдар сотуллубуттар - Библиотека уонна резервнай куопуйатыгар кэннинээҕи саҥардыытыгар көмөлөһөр + Бэбэлэтиэкэ уонна хаппаас куопуйатыгар кэннинээҕи саҥардыытыгар көмөлөһөр Устройства түстэлэ сатаан арыллыбата Батарея тупсуруута араарыллынна - Резервнай куопуйаны оҥоруу уонна төнүҥнэрии - Резервнай куопуйа билимин талыы + Хаппаас куопуйаны оҥоруу уонна төнүҥнэрии + Хаппаас куопуйа билэтин талыы Инники биэрсиялар бэлиэтэ Туох саҥа баарый Тахсыбыт кэмэ @@ -377,7 +376,7 @@ v%1$s дылы саҥарданна Саҥардыы баар буолуутун бэрэбиэркэлээһин Толору көрдөөһүн… - Бу маанга библиотекаҕа киирбитэ + Бу маанга бэбэлэтиэкэҕэ киирбитэ Куолунунан сылдьар бөлөх ураты бөлөҕү кытта талыллыбат Иҥиннэриллибит Бүтэһигинэн туттуллубут @@ -411,7 +410,7 @@ %1$s хаалла - Библиотекаҕа баар маанганы барытын биилтирдээһин + Бэбэлэтиэкэҕэ баар маанганы барытын биилтирдээһин Хачайдаммыт эрэ Ханнык баҕар сыаһалары көннөрөргө көмөлөһөр. Бэйэ дааннайдар ылыллыбаттар Охтуу туһунан отчуоту ыытыы @@ -422,12 +421,12 @@ Кырата Эбии Маанга туһунан - Библиотекаттан ылылынна - Библиотекаҕа киирдэ + Бэбэлэтиэкэттэн ылылынна + Бэбэлэтиэкэҕэ киирдэ Айымньы аата - Библиотекаттан ыл - Библиотекаҕа - Библиотекаҕа киллэр + Бэбэлэтиэкэттэн ыл + Бэбэлэтиэкэҕэ + Бэбэлэтиэкэҕэ киллэрии Лицензиялаах Биллибэт турук Биллибэт @@ -444,4 +443,82 @@ \"%1$s\" толору көрдөө Кыбытыылах түһүмэхтэри соттор Түһүмэхтэри соттор + Кэтээһин + Хачайдааһыҥна барсыбат ыйдарыы + Талыллыбыт түһүмэхтэри сотторорго эрэллээххин дуу\? + Ааҕыллыбата + Барыта + Атын ахсаан + Аныгыскы 10 түһүмэх + Аныгыскы 5 түһүмэх + Аныгыскы түһүмэх + Тустаах ахсааны хачайдаа + Хачайдаа + Хачайдааһын кэминэн + Түһүмэх нүөмэринэн + Төрүттэринэн + Суортуур эрэһиимэ + Түһүмэх нүөмэрэ + Төрүт аата + Түһүмэхтэри кыайан таһаарбатым + Тохтотулунна + Сыыһааһын + Хачайдааһын (%1$d/%2$d) + Хачайдааһын + Уочаракка + Хачайдаммыт + Түһүмэх %1$s + Аата cуох + Түһүмэхтэр + Маанганы Бэбэлэтиэкэҕэ киллэрэбит дуу\? + Төрүт туруоруллубатах: %1$s + Хоспоххо куопуйаланна: +\n %1$s + 18+ контент баар буолуон сөп + 18+ + Ити официальнайа суох эбэтэр сыыһа бэлиэтэммит 18+ контенны эбиликкж киирэрин тохтоппот. + Төрөппүт хонтуруола + Хачайдааһын бүттэ + Туттааччы биилтирэ + Түстэл + Хартыыҥканы оннунан хааллара турабын + Хартыыҥка оннунан хаалла + Бу маанга бары түһүмэхтэрин түһэрии + Бу дьайыы түһүмэх ааҕыллыбыт кэмин сотторуо. Эрэллээххин дуо\? + Бөлөхтөр соттороллубуттар + Оннук ааттах бөлөх уруккуттан баар! + Табыллыбат кэм ыйылынна + Көрүҥ + Ааҕы бүппүт кэмэ + Ааҕы саҕаламмыт кэмэ + Саҕаланна + Турук + Турук + Айымньы аата + Сыанабыл + Саҥаттаан ааҕабын + Ааҕыахпын баҕарабын + Ааҕаары гынабын + Тохтотулунна + Тохтообут + Быраҕыллыбыт + Бүппүт + Билигин ааҕабын + Ааҕабын + эбии кэтээһини киллэрии + + %d трэкэр + + Бу сиэриэҕэ + Бу ойууну тас курдук туттаҕын дуо\? + Ойуу кыайан хачайдаммата + Ааспыттааҥҥы түһүмэх булуллубата + Аныгыскы түһүмэх булуллубата + Түһүмэх %1$s + Сирэй: %1$d + %1$d%% хачайданна + Хачайдааһын… + Сирэй манна копуйаланна: %1$s + Тас саҥардыллыбыт + Тас курдук туруор \ No newline at end of file diff --git a/app/src/main/res/values-sc/strings.xml b/app/src/main/res/values-sc/strings.xml index fb77d146d..2de855aeb 100644 --- a/app/src/main/res/values-sc/strings.xml +++ b/app/src/main/res/values-sc/strings.xml @@ -183,8 +183,8 @@ A Cartella de sos iscarrigamentos Iscàrriga petzi impreende su WiFi - Iscantzella cando est marcadu comente non lèghidu - Iscantzella a pustis de sa leghidura + A pustis de l\'àere marcadu comente lèghidu + A pustis de sa leghidura Cartella personalizada Disabilitadu Leghe s\'ùrtimu capìtulu @@ -335,7 +335,7 @@ Carrigamentu de pàginas fallidu: %1$s Toca pro ischertare sa mitza dae sa cale migrare Ischerta sos datos de incluire - Mìgra + Tràmuda Còpia Iscarrigamentu de sos capìtulos fallidu. Podes torrare a proare in sa setzione de sos iscarrigamentos Progressu de s\'agiornamentu: %1$d/%2$d @@ -348,7 +348,6 @@ Connessione non disponìbile Ischerta s\'immàgine de cobertedda Ischerta sa còpia de seguresa - Ischerta s\'icona de s\'incurtzadura Iscàrriga Ignora Non bi sunt agiornamentos disponìbiles noos @@ -394,7 +393,7 @@ Biblioteca Cartella de iscarrigamentu non vàlida Obsoleta - Cust\'estensione no est prus disponìbile. + Cust\'estensione no est prus a disponimentu. Formadu de sa data Agiornamentos Categorias @@ -534,7 +533,7 @@ Fatu in %1$s cun %2$s errore Fatu in %1$s cun %2$s errores - Sincronizatzione a una diretzione ebbia pro agiornare su progressu in sos capìtulos in su servìtziu de arrastamentu. Imposta s\'arrastamentu pro sos elementos de sos manga dae s\'ischeda de arrastamentu issoro. + Sincronizatzione a una diretzione ebbia pro agiornare su progressu in sos capìtulos in su servìtziu de arrastamentu. Imposta s\'arrastamentu pro sos elementos de sos manga dae su butone de arrastamentu issoro. Iconas de sos non lèghidos Annoa sas coberteddas de sos manga de sa biblioteca @@ -605,4 +604,19 @@ Iscarrigamentu acabadu Errores Arrastadores a sos cales no as fatu atzessu: + Iscantzella sos capìtulos sinnados + Iscantzella capìtulos + Diat pòdere cuntènnere cuntenutos 18+ + 18+ + Custu no impedit a estensiones no ufitziales o potentzialmente non curretas de ammustrare cuntenutos 18+ in s\'aplicatzione. + Blocadas + Bloca s\'esploratzione de sas mitzas ma ammustra·las in sa lista de sas estensiones + Permìtidas + Mitzas 18+ + Controllos pro sos genitores + + Mancat 1 capìtulu + Mancant %d capìtulos + + Perunu capìtulu agatadu \ No newline at end of file diff --git a/app/src/main/res/values-sk/strings.xml b/app/src/main/res/values-sk/strings.xml index 2b49decae..59f7d0d43 100644 --- a/app/src/main/res/values-sk/strings.xml +++ b/app/src/main/res/values-sk/strings.xml @@ -283,7 +283,7 @@ Odstránené z knižnice Odstrániť stiahnuté kapitoly\? %1$s bol skopírovaný do schránky - Zdroj nie je nainštalovaný + Zdroj nie je nainštalovaný: %1$s Kapitoly Bez názvu Kapitola %1$s @@ -365,7 +365,6 @@ Pripojenie nie je k dispozícii Vyberte obrázok obalu Vyberte záložný súbor - Vyberte ikonu zástupca Stiahnuť Ignorovať Žiadné nové aktualizácie diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index aff5fe46d..f0d698901 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -490,7 +490,6 @@ Nisu dostupne nove ispravke Ignoriši Preuzmi - Izaberite ikonu prečice Izaberite datoteku rezervne kopije Izaberite naslovnu sliku Veza nije dostupna diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 52d02bb47..fe56a28e6 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -347,7 +347,6 @@ Anslutningen är inte tillänglig Välj omslagsbild Välj säkerhetskopia - Välj genvägsikon Ladda ner Ignorera Inga nya uppdateringar tillgängliga @@ -536,7 +535,7 @@ Det gick inte att öppna enhetsinställningarna Olästa märken Uppdatera bibliotekets manga omslag - Envägssynkronisering för att uppdatera kapitelförloppet i spårningstjänster. Ställ in spårning för enskilda manga från deras spårningsflikar. + Envägssynkronisering för att uppdatera kapitelförloppet i spårningstjänster. Ställ in spårning för enskilda manga från spårningsknappen under manga info. 1 uppdatering misslyckades %1$d uppdateringar misslyckades @@ -604,12 +603,15 @@ Du har inga fästa källor Blockerad - Blockera källan men visa i tilläggslistan + Blockera att bläddra källor men visa i tilläggslistan Tillåtet - NSFW källor + 18+ källor Ta bort bokmärkta kapitel Ta bort kapitel Kan innehålla 18+ innehåll 18+ Trackers som inte har loggats in: + Detta förhindrar inte inofficiella eller potentiellt felaktigt flaggade tillägg från att visa 18+ innehåll i appen. + Föräldrakontroll + Fel \ No newline at end of file diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 2206ab022..7fa6be2f8 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -357,7 +357,6 @@ การเชื่อมต่อไม่พร้อม เลือกภาพหน้าปก เลือกไฟล์สำรองข้อมูล - เลือกไอคอนทางลัด ดาวน์โหลด ไม่สนใจ ไม่มีการอัปเดตใหม่ diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 1e5d39288..0518af8d1 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -339,7 +339,6 @@ Bağlantı yok Kapak görselini seç Yedek dosyasını seç - Kısayol simgesi seç İndir Yok say Yeni güncelleme yok @@ -535,7 +534,7 @@ %1$s içinde %2$s hatayla tamamlandı Okunmamış rozetler - Bölüm ilerlemesini, izleme hizmetlerinde güncellemek için tek yönlü eşitleme. Her manga girdisinin izleme sekmesinden, izlemeyi ayarlayın. + Bölüm ilerlemesini, izleme hizmetlerinde güncellemek için tek yönlü eşitleme. Her manga girdisinin izleme düğmesinden, izlemeyi ayarlayın. Kitaplık manga kapaklarını yenile 1 güncelleme başarısız @@ -606,9 +605,18 @@ Hatalar İzleyiciler giriş yapmadı: Engelli - Kaynağı engelle, ancak uzantılar listesinde göster + Kaynaklara göz atmayı engelle, ancak uzantılar listesinde göster İzinli - Uygunsuz kaynaklar + 18+ kaynaklar İşaretli bölümleri sil Bölümleri sil + 18+ içerik içerebilir + 18+ + Bu, resmi olmayan veya yanlış işaretlenmiş uzantıların, uygulama içinde 18+ içeriği göstermesini engellemez. + Ebeveyn denetimleri + + 1 eksik bölüm var + %d eksik bölüm var + + Bölüm bulunamadı \ No newline at end of file diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 224b519d6..d69c8841e 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -182,8 +182,8 @@ A Директорія завантаження Завантажувати лише через Wi-Fi - Видалити коли відмічено як прочитано - Видаляти після прочитання + Після того, як було відміченим як прочитане + Після прочитання Користувацька директорія Відключено Остання прочитана глава @@ -347,7 +347,6 @@ З`єднання не доступне Вибрати обкладинку Виберіть файл резервної копії - Вибрати ярлик Завантажити Ігнорувати Оновлень не виявлено @@ -558,7 +557,7 @@ Не зареєстровано в: %1$s Джерело не знайдено %1$s Включати тільки закріплені джерела - Одностороння синхронізація для оновлення прогресу глави в службах відстеження. Налаштуйте відстеження для окремих записів манги з їх вкладок відстеження. + Одностороння синхронізація для оновлення прогресу глави в службах відстеження. Налаштуйте відстеження для окремих записів манги з їх кнопками відстеження. Показувати вкладки категорій Зручна сітка Дата завершення читання @@ -621,4 +620,22 @@ Завершено Поступ Завантаження завершено + Трекери не авторизовано: + Видалити глави з закладок + Видалити глави + Може містити контент 18+ + 18+ + Це не заважає неофіційним або потенційно невірним розширенням розміщувати вміст 18+ у додатку. + Заблоковано + Блокувати переглянуті джерела, але показувати в списку розширень + Дозволено + 18+ джерела + Батьківський контроль + + Відсутня 1 глава + Відсутні %d глави + Відсутні %d глав + Відсутні %d глав + + Немає глав \ No newline at end of file diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 23e4ebaca..eeda756f8 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -6,8 +6,8 @@ Hàng chờ tải xuống Thư Viện Lịch Sử - Mới Cập Nhật - Hạng mục + Mới + Danh mục Sao lưu Cài đặt @@ -273,7 +273,6 @@ Chọn ảnh bìa Chọn file sao lưu - Chọn biểu tượng phím tắt Tải xuống Bỏ qua @@ -306,8 +305,8 @@ Theo dõi Lịch sử Di chuyển - Tiện ích bổ sung - Thông tin về tiện ích bổ sung + Phần mở rộng + Thông tin về phần mở rộng Toàn bộ các chương tìm kiếm toàn cầu Đóng @@ -541,4 +540,14 @@ Backup không chứa manga nào. File backup không hợp lệ Thêm vào thư viện + Có thể chứa nội dung 18+ + 18+ + Tự động làm mới metadata + Chuyển đến các chương khi mở + Điều này không ngăn các tiện ích không chính thức hoặc có khả năng bị gắn cờ không chính xác hiển thị nội dung 18+ trong ứng dụng. + Đã chặn + Đã cho phép + Nguồn 18+ + Kiểm soát của phụ huynh + Chỉ hiện truyện đã tải \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 578fd439c..34a266a80 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -51,7 +51,7 @@ 下一章 重试 移除 - 继续阅读 + 继续 移动 在浏览器中打开 显示模式 @@ -347,7 +347,6 @@ 连接不可用 选择封面图片 选择备份文件 - 选择快捷方式图标 下载 忽略 没有可用的更新 @@ -528,7 +527,7 @@ 减少色彩带,但会降低性能 未读标记 刷新书架漫画封面 - 单向同步以更新同步服务中的章节进度。在「同步」选项卡中为单个漫画设置同步。 + 单向同步以更新跟踪服务的章节进度。通过跟踪按钮设置对单个漫画条目的跟踪。 %1$d 本漫画更新失败 @@ -595,9 +594,17 @@ 错误 未登录的同步源: 拦截的 - 拦截源但显示在扩展列表中 + 阻止浏览源但显示在扩展列表中 允许的 - NSFW 源 + 仅适合18岁以上人士的源 删除添加为书签的章节 删除章节 + 可能包含仅适合18岁以上人士的内容 + 18+ + 这不会阻止非官方的或可能被错误标记的扩展程序在应用程序中显示仅适合18岁以上人士的内容。 + 家长控制 + + 有 %d 章缺失 + + 未找到章节 \ No newline at end of file diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index ee173f66f..da02ad540 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -139,7 +139,7 @@ A 下載位置 僅透過 Wi-Fi 下載 - 刪除標示為已讀的章節 + 手動標示為已讀後 自訂位置 停用 自動下載新章節 @@ -303,7 +303,6 @@ 尚未接上電源 已取消同步 選擇備份檔案 - 選擇捷徑圖示 漫畫封面 尚無任何分類,輕觸新增按鈕即可建立分類以組織你的書櫃。 下載管理員 @@ -333,7 +332,7 @@ 接下來: 發現新章節 略過已讀的章節 - 閱畢後刪除 + 翻閱過後 已複製頁面至「%1$s」 以下空白 已達盡頭 @@ -424,7 +423,7 @@ 立即 閒置時鎖定 解除鎖定 Tachiyomi - 使用生物辨識鎖定 + 生物特徵辨識鎖定 在切換應用程式時隱藏預覽,並禁止擷取螢幕畫面 防窺畫面 隱私 @@ -526,7 +525,7 @@ 共 %1$s 章 - 將章節進度單向同步至閱讀歷程平台,請逕行前往個別作品的「歷程」頁籤以設置。 + 將章節進度單向同步至閱讀歷程平台,請逕行前往個別作品的「歷程」頁面以設置。 %d 個分類 @@ -586,9 +585,18 @@ 尚未登入至歷程平台: 進度 錯誤 - 完成 - 已封鎖 - 已允許 + 作業完成 + 禁止顯示 + 允許顯示 下載完成 下載 + 18+ + 監護 + 即使啟用監護限制,還是可能有漏網之魚。使用者仍可藉由非官方或未正確標幟的擴充套件在本應用程式中瀏覽未滿十八歲之人不宜觀賞的內容。 + 可能包含未滿十八歲之人不宜觀賞的內容 + 未滿十八歲之人不宜瀏覽的來源 + 禁止顯示,但仍可見於擴充套件清單 + 備份檔並未包含任何漫畫 + 刪除有書籤的章節 + 刪除章節 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 94172f369..7c8a5a8bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -84,6 +84,7 @@ Move Open in browser Open in WebView + WebView Open in Settings Migrate Display mode @@ -487,7 +488,6 @@ Title Added to library Removed from library - About More Less @@ -526,6 +526,11 @@ Unread Are you sure you want to delete the selected chapters? Invalid download location + Chapter settings + Are you sure you want to save these settings as default? + Also apply to all manga in my library + Set as default + No chapters found Tracking @@ -571,6 +576,7 @@ Custom filter Set as cover Cover updated + %1$s: %2$s, page %3$d Page copied to %1$s Downloading… Downloaded %1$d%% @@ -592,6 +598,10 @@ Failed to load pages: %1$s No pages found Source not found + + There is 1 missing chapter + There are %d missing chapters + Updating library @@ -643,7 +653,6 @@ Select cover image Select backup file - Select shortcut icon Download @@ -676,6 +685,7 @@ Failed to bypass Cloudflare WebView is required for Tachiyomi Please update the WebView app for better compatibility + Updated default chapter settings Downloader diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 9a3845cba..51874a7af 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -96,15 +96,7 @@ - - - - - - - diff --git a/build.gradle.kts b/build.gradle.kts index 26bec1e91..63f349094 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,7 +2,7 @@ plugins { id("com.android.application") version BuildPluginsVersion.AGP apply false id("com.android.library") version BuildPluginsVersion.AGP apply false kotlin("android") version BuildPluginsVersion.KOTLIN apply false - id("org.jlleitschuh.gradle.ktlint") version BuildPluginsVersion.KTLINT + id("org.jmailen.kotlinter") version BuildPluginsVersion.KOTLINTER id("com.github.ben-manes.versions") version BuildPluginsVersion.VERSIONS_PLUGIN } @@ -16,22 +16,10 @@ allprojects { } subprojects { - apply { - plugin("org.jlleitschuh.gradle.ktlint") - } + apply(plugin = "org.jmailen.kotlinter") - ktlint { - debug.set(false) - version.set(Versions.KTLINT) - verbose.set(true) - android.set(false) - outputToConsole.set(true) - ignoreFailures.set(false) - enableExperimentalRules.set(true) - filter { - exclude("**/generated/**") - include("**/kotlin/**") - } + kotlinter { + experimentalRules = true } } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 6b9c1f921..3e170e2d7 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -1,10 +1,6 @@ -object Versions { - const val KTLINT = "0.36.0" -} - object BuildPluginsVersion { const val AGP = "4.0.1" - const val KOTLIN = "1.4.0" - const val KTLINT = "9.2.1" + const val KOTLIN = "1.4.10" + const val KOTLINTER = "3.0.2" const val VERSIONS_PLUGIN = "0.28.0" }