Made almost all the strings SY uses translatable! If people would like to help translate, feel free to join the Tachiyomi discord server (https://discord.gg/tachiyomi), and jump in the tachiyomi-az-sy channel and I can give you a rundown on how to do it
This commit is contained in:
parent
0ca87a3763
commit
362f0a6671
@ -286,7 +286,7 @@ class BackupRestoreService : Service() {
|
||||
backupManager.restoreSavedSearches(savedSearchesJson)
|
||||
|
||||
restoreProgress += 1
|
||||
showRestoreProgress(restoreProgress, restoreAmount, getString(R.string.eh_saved_searches))
|
||||
showRestoreProgress(restoreProgress, restoreAmount, getString(R.string.saved_searches))
|
||||
}
|
||||
// SY <--
|
||||
|
||||
|
@ -98,7 +98,7 @@ open class SourceManager(private val context: Context) {
|
||||
XLog.d("[EXH] Delegating source: %s -> %s!", sourceQName, delegate.newSourceClass.qualifiedName)
|
||||
val enhancedSource = EnhancedHttpSource(
|
||||
source,
|
||||
delegate.newSourceClass.constructors.find { it.parameters.size == 1 }!!.call(source)
|
||||
delegate.newSourceClass.constructors.find { it.parameters.size == 2 }!!.call(source, context)
|
||||
)
|
||||
val map = listOf(DelegatedSource(enhancedSource.originalSource.name, enhancedSource.originalSource.id, enhancedSource.originalSource::class.qualifiedName ?: delegate.originalSourceQualifiedClassName, (enhancedSource.enhancedSource as DelegatedHttpSource)::class, delegate.factory)).associateBy { it.originalSourceQualifiedClassName }
|
||||
currentDelegatedSources.plusAssign(map)
|
||||
@ -132,12 +132,12 @@ open class SourceManager(private val context: Context) {
|
||||
if (prefs.enableExhentai().get()) {
|
||||
exSrcs += EHentai(EXH_SOURCE_ID, true, context)
|
||||
}
|
||||
exSrcs += PervEden(PERV_EDEN_EN_SOURCE_ID, PervEdenLang.en)
|
||||
exSrcs += PervEden(PERV_EDEN_IT_SOURCE_ID, PervEdenLang.it)
|
||||
exSrcs += PervEden(PERV_EDEN_EN_SOURCE_ID, PervEdenLang.en, context)
|
||||
exSrcs += PervEden(PERV_EDEN_IT_SOURCE_ID, PervEdenLang.it, context)
|
||||
exSrcs += NHentai(context)
|
||||
exSrcs += Hitomi()
|
||||
exSrcs += EightMuses()
|
||||
exSrcs += HBrowse()
|
||||
exSrcs += Hitomi(context)
|
||||
exSrcs += EightMuses(context)
|
||||
exSrcs += HBrowse(context)
|
||||
return exSrcs
|
||||
}
|
||||
// SY <--
|
||||
|
@ -271,7 +271,7 @@ class EHentai(
|
||||
|
||||
// Support direct URL importing
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
|
||||
urlImportFetchSearchManga(query) {
|
||||
urlImportFetchSearchManga(context, query) {
|
||||
searchMangaRequestObservable(page, query, filters).flatMap {
|
||||
client.newCall(it).asObservableSuccess()
|
||||
}.map { response ->
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.all
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import com.github.salomonbrys.kotson.array
|
||||
@ -41,7 +42,7 @@ import uy.kohesive.injekt.injectLazy
|
||||
/**
|
||||
* Man, I hate this source :(
|
||||
*/
|
||||
class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImportableSource {
|
||||
class Hitomi(val context: Context) : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImportableSource {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
override val id = HITOMI_SOURCE_ID
|
||||
@ -185,7 +186,7 @@ class Hitomi : HttpSource(), LewdSource<HitomiSearchMetadata, Document>, UrlImpo
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = throw UnsupportedOperationException()
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
return urlImportFetchSearchManga(query) {
|
||||
return urlImportFetchSearchManga(context, query) {
|
||||
val splitQuery = query.split(" ")
|
||||
|
||||
val positive = splitQuery.filter { !it.startsWith('-') }.toMutableList()
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.all
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
@ -11,7 +12,7 @@ import exh.source.DelegatedHttpSource
|
||||
import exh.util.urlImportFetchSearchManga
|
||||
import rx.Observable
|
||||
|
||||
class MangaDex(delegate: HttpSource) :
|
||||
class MangaDex(delegate: HttpSource, val context: Context) :
|
||||
DelegatedHttpSource(delegate),
|
||||
ConfigurableSource,
|
||||
UrlImportableSource {
|
||||
@ -19,7 +20,7 @@ class MangaDex(delegate: HttpSource) :
|
||||
override val matchingHosts: List<String> = listOf("mangadex.org", "www.mangadex.org")
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> =
|
||||
urlImportFetchSearchManga(query) {
|
||||
urlImportFetchSearchManga(context, query) {
|
||||
super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ import rx.Observable
|
||||
* NHentai source
|
||||
*/
|
||||
|
||||
class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata, Response>, UrlImportableSource {
|
||||
class NHentai(val context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata, Response>, UrlImportableSource {
|
||||
override val metaClass = NHentaiSearchMetadata::class
|
||||
|
||||
override fun fetchPopularManga(page: Int): Observable<MangasPage> {
|
||||
@ -57,7 +57,7 @@ class NHentai(context: Context) : HttpSource(), LewdSource<NHentaiSearchMetadata
|
||||
"$baseUrl/g/$trimmedIdQuery/"
|
||||
} else query
|
||||
|
||||
return urlImportFetchSearchManga(newQuery) {
|
||||
return urlImportFetchSearchManga(context, newQuery) {
|
||||
searchMangaRequestObservable(page, query, filters).flatMap {
|
||||
client.newCall(it).asObservableSuccess()
|
||||
}.map { response ->
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.all
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
@ -33,7 +34,7 @@ import org.jsoup.nodes.TextNode
|
||||
import rx.Observable
|
||||
|
||||
// TODO Transform into delegated source
|
||||
class PervEden(override val id: Long, val pvLang: PervEdenLang) :
|
||||
class PervEden(override val id: Long, val pvLang: PervEdenLang, val context: Context) :
|
||||
ParsedHttpSource(),
|
||||
LewdSource<PervEdenSearchMetadata, Document>,
|
||||
UrlImportableSource {
|
||||
@ -64,7 +65,7 @@ class PervEden(override val id: Long, val pvLang: PervEdenLang) :
|
||||
|
||||
// Support direct URL importing
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
|
||||
urlImportFetchSearchManga(query) {
|
||||
urlImportFetchSearchManga(context, query) {
|
||||
super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.kizitonwose.time.hours
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
@ -41,7 +42,7 @@ import rx.schedulers.Schedulers
|
||||
|
||||
typealias SiteMap = NakedTrie<Unit>
|
||||
|
||||
class EightMuses :
|
||||
class EightMuses(val context: Context) :
|
||||
HttpSource(),
|
||||
LewdSource<EightMusesSearchMetadata, Document>,
|
||||
UrlImportableSource {
|
||||
@ -177,7 +178,7 @@ class EightMuses :
|
||||
override fun fetchPopularManga(page: Int) = fetchListing(popularMangaRequest(page), false) // TODO Dig
|
||||
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
return urlImportFetchSearchManga(query) {
|
||||
return urlImportFetchSearchManga(context, query) {
|
||||
fetchListing(searchMangaRequest(page, query, filters), false)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.github.salomonbrys.kotson.array
|
||||
import com.github.salomonbrys.kotson.string
|
||||
@ -43,7 +44,7 @@ import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import rx.schedulers.Schedulers
|
||||
|
||||
class HBrowse : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlImportableSource {
|
||||
class HBrowse(val context: Context) : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlImportableSource {
|
||||
/**
|
||||
* An ISO 639-1 compliant language code (two letters in lower case).
|
||||
*/
|
||||
@ -110,7 +111,7 @@ class HBrowse : HttpSource(), LewdSource<HBrowseSearchMetadata, Document>, UrlIm
|
||||
* @param filters the list of filters to apply.
|
||||
*/
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||
return urlImportFetchSearchManga(query) {
|
||||
return urlImportFetchSearchManga(context, query) {
|
||||
fetchSearchMangaInternal(page, query, filters)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
@ -19,7 +20,7 @@ import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import org.jsoup.nodes.Document
|
||||
import rx.Observable
|
||||
|
||||
class HentaiCafe(delegate: HttpSource) :
|
||||
class HentaiCafe(delegate: HttpSource, val context: Context) :
|
||||
DelegatedHttpSource(delegate),
|
||||
LewdSource<HentaiCafeSearchMetadata, Document>,
|
||||
UrlImportableSource {
|
||||
@ -34,7 +35,7 @@ class HentaiCafe(delegate: HttpSource) :
|
||||
|
||||
// Support direct URL importing
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
|
||||
urlImportFetchSearchManga(query) {
|
||||
urlImportFetchSearchManga(context, query) {
|
||||
super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
@ -18,7 +19,7 @@ import exh.util.urlImportFetchSearchManga
|
||||
import org.jsoup.nodes.Document
|
||||
import rx.Observable
|
||||
|
||||
class Pururin(delegate: HttpSource) :
|
||||
class Pururin(delegate: HttpSource, val context: Context) :
|
||||
DelegatedHttpSource(delegate),
|
||||
LewdSource<PururinSearchMetadata, Document>,
|
||||
UrlImportableSource {
|
||||
@ -38,7 +39,7 @@ class Pururin(delegate: HttpSource) :
|
||||
"$baseUrl/gallery/$trimmedIdQuery/-"
|
||||
} else query
|
||||
|
||||
return urlImportFetchSearchManga(newQuery) {
|
||||
return urlImportFetchSearchManga(context, newQuery) {
|
||||
super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
package eu.kanade.tachiyomi.source.online.english
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
@ -19,7 +20,7 @@ import java.util.Locale
|
||||
import org.jsoup.nodes.Document
|
||||
import rx.Observable
|
||||
|
||||
class Tsumino(delegate: HttpSource) :
|
||||
class Tsumino(delegate: HttpSource, val context: Context) :
|
||||
DelegatedHttpSource(delegate),
|
||||
LewdSource<TsuminoSearchMetadata, Document>,
|
||||
UrlImportableSource {
|
||||
@ -28,7 +29,7 @@ class Tsumino(delegate: HttpSource) :
|
||||
|
||||
// Support direct URL importing
|
||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList) =
|
||||
urlImportFetchSearchManga(query) {
|
||||
urlImportFetchSearchManga(context, query) {
|
||||
super.fetchSearchManga(page, query, filters)
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,6 @@ import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import reactivecircus.flowbinding.appcompat.QueryTextEvent
|
||||
import reactivecircus.flowbinding.appcompat.queryTextEvents
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
/**
|
||||
@ -193,7 +192,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
|
||||
if (presenter.sourceFilters.isEmpty()) {
|
||||
// SY -->
|
||||
actionFab?.text = activity!!.getString(R.string.eh_saved_searches)
|
||||
actionFab?.text = activity!!.getString(R.string.saved_searches)
|
||||
// SY <--
|
||||
}
|
||||
|
||||
@ -218,8 +217,8 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
onSaveClicked = {
|
||||
filterSheet?.context?.let {
|
||||
MaterialDialog(it)
|
||||
.title(text = "Save current search query?")
|
||||
.input("My search name", hintRes = null) { _, searchName ->
|
||||
.title(R.string.save_search)
|
||||
.input(hintRes = R.string.save_search_hint) { _, searchName ->
|
||||
val oldSavedSearches = presenter.loadSearches()
|
||||
if (searchName.isNotBlank() &&
|
||||
oldSavedSearches.size < MAX_SAVED_SEARCHES
|
||||
@ -248,8 +247,8 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
if (search == null) {
|
||||
filterSheet?.context?.let {
|
||||
MaterialDialog(it)
|
||||
.title(text = "Failed to load saved searches!")
|
||||
.message(text = "An error occurred while loading your saved searches.")
|
||||
.title(R.string.save_search_failed_to_load)
|
||||
.message(R.string.save_search_failed_to_load_message)
|
||||
.cancelable(true)
|
||||
.cancelOnTouchOutside(true)
|
||||
.show()
|
||||
@ -275,8 +274,8 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
if (search == null || search.name != name) {
|
||||
filterSheet?.context?.let {
|
||||
MaterialDialog(it)
|
||||
.title(text = "Failed to delete saved search!")
|
||||
.message(text = "An error occurred while deleting the search.")
|
||||
.title(R.string.save_search_failed_to_delete)
|
||||
.message(R.string.save_search_failed_to_delete_message)
|
||||
.cancelable(true)
|
||||
.cancelOnTouchOutside(true)
|
||||
.show()
|
||||
@ -286,10 +285,10 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
|
||||
filterSheet?.context?.let {
|
||||
MaterialDialog(it)
|
||||
.title(text = "Delete saved search query?")
|
||||
.message(text = "Are you sure you wish to delete your saved search query: '${search.name}'?")
|
||||
.title(R.string.save_search_delete)
|
||||
.message(text = it.getString(R.string.save_search_delete_message, search.name))
|
||||
.positiveButton(R.string.action_cancel)
|
||||
.negativeButton(text = "Confirm") {
|
||||
.negativeButton(android.R.string.yes) {
|
||||
val newSearches = savedSearches.filterIndexed { index, _ ->
|
||||
index != indexToDelete
|
||||
}
|
||||
|
@ -696,7 +696,7 @@ class LibraryController(
|
||||
private fun showSyncProgressDialog() {
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title(text = "Favorites syncing")
|
||||
?.title(R.string.favorites_syncing)
|
||||
?.cancelable(false)
|
||||
// ?.progress(true, 0)
|
||||
favSyncDialog?.show()
|
||||
@ -723,15 +723,15 @@ class LibraryController(
|
||||
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title(text = "Favorites sync error")
|
||||
?.message(text = status.message + " Sync will not start until the gallery is in only one category.")
|
||||
?.title(R.string.favorites_sync_error)
|
||||
?.message(text = activity!!.getString(R.string.favorites_sync_bad_library_state, status.message))
|
||||
?.cancelable(false)
|
||||
?.positiveButton(text = "Show gallery") {
|
||||
?.positiveButton(R.string.show_gallery) {
|
||||
openManga(status.manga)
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle(activity!!))
|
||||
}
|
||||
?.negativeButton(android.R.string.ok) {
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle(activity!!))
|
||||
}
|
||||
favSyncDialog?.show()
|
||||
}
|
||||
@ -740,11 +740,11 @@ class LibraryController(
|
||||
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title(text = "Favorites sync error")
|
||||
?.message(text = "An error occurred during the sync process: ${status.message}")
|
||||
?.title(R.string.favorites_sync_error)
|
||||
?.message(text = activity!!.getString(R.string.favorites_sync_error_string, status.message))
|
||||
?.cancelable(false)
|
||||
?.positiveButton(android.R.string.ok) {
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle(activity!!))
|
||||
}
|
||||
favSyncDialog?.show()
|
||||
}
|
||||
@ -753,11 +753,11 @@ class LibraryController(
|
||||
|
||||
favSyncDialog?.dismiss()
|
||||
favSyncDialog = buildDialog()
|
||||
?.title(text = "Favorites sync complete with errors")
|
||||
?.message(text = "Errors occurred during the sync process that were ignored:\n${status.message}")
|
||||
?.title(R.string.favorites_sync_done_errors)
|
||||
?.message(text = activity!!.getString(R.string.favorites_sync_done_errors_message, status.message))
|
||||
?.cancelable(false)
|
||||
?.positiveButton(android.R.string.ok) {
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle())
|
||||
presenter.favoritesSync.status.onNext(FavoritesSyncStatus.Idle(activity!!))
|
||||
}
|
||||
favSyncDialog?.show()
|
||||
}
|
||||
|
@ -548,7 +548,7 @@ class MangaController :
|
||||
startActivityForResult(
|
||||
Intent.createChooser(
|
||||
intent,
|
||||
resources?.getString(R.string.select_cover_image)
|
||||
resources?.getString(R.string.action_edit_cover)
|
||||
),
|
||||
REQUEST_EDIT_MANGA_COVER
|
||||
)
|
||||
@ -750,7 +750,7 @@ class MangaController :
|
||||
presenter.editCoverWithStream(uri)
|
||||
}
|
||||
} catch (error: IOException) {
|
||||
activity.toast(R.string.failed_to_update_cover)
|
||||
activity.toast(R.string.notification_cover_update_failed)
|
||||
Timber.e(error)
|
||||
}
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ class MangaInfoHeaderAdapter(
|
||||
binding.btnSmartSearch.clicks()
|
||||
.onEach { controller.openSmartSearch() }
|
||||
.launchIn(scope)
|
||||
binding.btnSmartSearch.setTooltip(R.string.eh_merge_with_another_source)
|
||||
binding.btnSmartSearch.setTooltip(R.string.merge_with_another_source)
|
||||
}
|
||||
// SY <--
|
||||
|
||||
|
@ -146,12 +146,12 @@ class SettingsAdvancedController : SettingsController() {
|
||||
|
||||
// --> EXH
|
||||
preferenceCategory {
|
||||
title = "Developer tools"
|
||||
titleRes = R.string.developer_tools
|
||||
isPersistent = false
|
||||
|
||||
switchPreference {
|
||||
title = "Enable integrated hentai features"
|
||||
summary = "This is a experimental feature that will disable all hentai features if toggled off"
|
||||
titleRes = R.string.toggle_hentai_features
|
||||
summaryRes = R.string.toggle_hentai_features_summary
|
||||
key = Keys.eh_is_hentai_enabled
|
||||
defaultValue = true
|
||||
|
||||
@ -212,35 +212,35 @@ class SettingsAdvancedController : SettingsController() {
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
title = "Enable delegated sources"
|
||||
titleRes = R.string.toggle_delegated_sources
|
||||
key = Keys.eh_delegateSources
|
||||
defaultValue = true
|
||||
summary = "Apply ${context.getString(R.string.app_name)} enhancements to the following sources if they are installed: ${DELEGATED_SOURCES.values.map { it.sourceName }.distinct().joinToString()}"
|
||||
summary = context.getString(R.string.toggle_delegated_sources_summary, context.getString(R.string.app_name), DELEGATED_SOURCES.values.map { it.sourceName }.distinct().joinToString())
|
||||
}
|
||||
|
||||
intListPreference {
|
||||
key = Keys.eh_logLevel
|
||||
title = "Log level"
|
||||
titleRes = R.string.log_level
|
||||
|
||||
entries = EHLogLevel.values().map {
|
||||
"${it.name.toLowerCase().capitalize()} (${it.description})"
|
||||
"${context.getString(it.nameRes)} (${context.getString(it.description)})"
|
||||
}.toTypedArray()
|
||||
entryValues = EHLogLevel.values().mapIndexed { index, _ -> "$index" }.toTypedArray()
|
||||
defaultValue = "0"
|
||||
|
||||
summary = "Changing this can impact app performance. Force-restart app after changing. Current value: %s"
|
||||
summaryRes = R.string.log_level_summary
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
title = "Enable source blacklist"
|
||||
titleRes = R.string.enable_source_blacklist
|
||||
key = Keys.eh_enableSourceBlacklist
|
||||
defaultValue = true
|
||||
summary = "Hide extensions/sources that are incompatible with ${context.getString(R.string.app_name)}. Force-restart app after changing."
|
||||
summary = context.getString(R.string.enable_source_blacklist_summary, context.getString(R.string.app_name))
|
||||
}
|
||||
|
||||
preference {
|
||||
title = "Open debug menu"
|
||||
summary = HtmlCompat.fromHtml("DO NOT TOUCH THIS MENU UNLESS YOU KNOW WHAT YOU ARE DOING! <font color='red'>IT CAN CORRUPT YOUR LIBRARY!</font>", HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
titleRes = R.string.open_debug_menu
|
||||
summary = HtmlCompat.fromHtml(context.getString(R.string.open_debug_menu_summary), HtmlCompat.FROM_HTML_MODE_LEGACY)
|
||||
onClick { router.pushController(SettingsDebugController().withFadeTransaction()) }
|
||||
}
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ import eu.kanade.tachiyomi.util.preference.preference
|
||||
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
import exh.EH_SOURCE_ID
|
||||
import exh.EXH_SOURCE_ID
|
||||
@ -143,14 +144,14 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||
title = "E-Hentai"
|
||||
titleRes = R.string.pref_category_eh
|
||||
|
||||
preferenceCategory {
|
||||
title = "E-Hentai Website Account Settings"
|
||||
titleRes = R.string.ehentai_prefs_account_settings
|
||||
|
||||
switchPreference {
|
||||
title = "Enable ExHentai"
|
||||
summaryOff = "Requires login"
|
||||
titleRes = R.string.enable_exhentai
|
||||
summaryOff = context.getString(R.string.requires_login)
|
||||
key = PreferenceKeys.eh_enableExHentai
|
||||
isPersistent = false
|
||||
defaultValue = false
|
||||
@ -178,33 +179,23 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
intListPreference {
|
||||
title = "Use Hentai@Home Network"
|
||||
titleRes = R.string.use_hentai_at_home
|
||||
|
||||
key = PreferenceKeys.eh_enable_hah
|
||||
if (preferences.eh_hathPerksCookies().get().isBlank()) {
|
||||
summary = "Do you wish to load images through the Hentai@Home Network, if available? Disabling this option will reduce the amount of pages you are able to view\nOptions:\n - Any client (Recommended)\n - Default port clients only (Can be slower. Enable if behind firewall/proxy that blocks outgoing non-standard ports.)"
|
||||
entries = arrayOf(
|
||||
"Any client (Recommended)",
|
||||
"Default port clients only"
|
||||
)
|
||||
entryValues = arrayOf("0", "1")
|
||||
} else {
|
||||
summary = "Do you wish to load images through the Hentai@Home Network, if available? Disabling this option will reduce the amount of pages you are able to view\nOptions:\n - Any client (Recommended)\n - Default port clients only (Can be slower. Enable if behind firewall/proxy that blocks outgoing non-standard ports.)\n - No (Donator only. You will not be able to browse as many pages, enable only if having severe problems.)"
|
||||
entries = arrayOf(
|
||||
"Any client (Recommended)",
|
||||
"Default port clients only",
|
||||
"No(will select Default port clients only if you are not a donator)"
|
||||
)
|
||||
entryValues = arrayOf("0", "1", "2")
|
||||
}
|
||||
summaryRes = R.string.use_hentai_at_home_summary
|
||||
entriesRes = arrayOf(
|
||||
R.string.use_hentai_at_home_option_1,
|
||||
R.string.use_hentai_at_home_option_2
|
||||
)
|
||||
entryValues = arrayOf("0", "1")
|
||||
|
||||
onChange { preferences.useHentaiAtHome().reconfigure() }
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
switchPreference {
|
||||
title = "Show Japanese titles in search results"
|
||||
summaryOn = "Currently showing Japanese titles in search results. Clear the chapter cache after changing this (in the Advanced section)"
|
||||
summaryOff = "Currently showing English/Romanized titles in search results. Clear the chapter cache after changing this (in the Advanced section)"
|
||||
titleRes = R.string.show_japanese_titles
|
||||
summaryOn = context.getString(R.string.show_japanese_titles_option_1)
|
||||
summaryOff = context.getString(R.string.show_japanese_titles_option_2)
|
||||
key = "use_jp_title"
|
||||
defaultValue = false
|
||||
|
||||
@ -212,9 +203,9 @@ class SettingsEhController : SettingsController() {
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
switchPreference {
|
||||
title = "Use original images"
|
||||
summaryOn = "Currently using original images"
|
||||
summaryOff = "Currently using resampled images"
|
||||
titleRes = R.string.use_original_images
|
||||
summaryOn = context.getString(R.string.use_original_images_on)
|
||||
summaryOff = context.getString(R.string.use_original_images_off)
|
||||
key = PreferenceKeys.eh_useOrigImages
|
||||
defaultValue = false
|
||||
|
||||
@ -222,28 +213,28 @@ class SettingsEhController : SettingsController() {
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
preference {
|
||||
title = "Watched Tags"
|
||||
summary = "Opens a webview to your E/ExHentai watched tags page"
|
||||
titleRes = R.string.watched_tags
|
||||
summaryRes = R.string.watched_tags_summary
|
||||
onClick {
|
||||
val intent = if (preferences.enableExhentai().get()) {
|
||||
WebViewActivity.newIntent(activity!!, url = "https://exhentai.org/mytags", title = "ExHentai Watched Tags")
|
||||
WebViewActivity.newIntent(activity!!, url = "https://exhentai.org/mytags", title = context.getString(R.string.watched_tags_exh))
|
||||
} else {
|
||||
WebViewActivity.newIntent(activity!!, url = "https://e-hentai.org/mytags", title = "E-Hentai Watched Tags")
|
||||
WebViewActivity.newIntent(activity!!, url = "https://e-hentai.org/mytags", title = context.getString(R.string.watched_tags_eh))
|
||||
}
|
||||
startActivity(intent)
|
||||
}
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
preference {
|
||||
title = "Tag Filtering Threshold"
|
||||
titleRes = R.string.tag_filtering_threshold
|
||||
key = PreferenceKeys.eh_tag_filtering_value
|
||||
defaultValue = 0
|
||||
|
||||
summary = "You can soft filter tags by adding them to the \"My Tags\" E/ExHentai page with a negative weight. If a gallery has tags that add up to weight below this value, it is filtered from view. This threshold can be set between -9999 and 0. Currently: ${preferences.ehTagFilterValue().get()}"
|
||||
summaryRes = R.string.tag_filtering_threshhold_summary
|
||||
|
||||
onClick {
|
||||
MaterialDialog(activity!!)
|
||||
.title(text = "Tag Filtering Threshold")
|
||||
.title(R.string.tag_filtering_threshold)
|
||||
.input(
|
||||
inputType = InputType.TYPE_NUMBER_FLAG_SIGNED,
|
||||
waitForPositiveButton = false,
|
||||
@ -255,14 +246,13 @@ class SettingsEhController : SettingsController() {
|
||||
if (value != null && value in -9999..0) {
|
||||
inputField.error = null
|
||||
} else {
|
||||
inputField.error = "Must be between -9999 and 0!"
|
||||
inputField.error = context.getString(R.string.tag_filtering_threshhold_error)
|
||||
}
|
||||
dialog.setActionButtonEnabled(WhichButton.POSITIVE, value != null && value in -9999..0)
|
||||
}
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val value = it.getInputField().text.toString().toInt()
|
||||
preferences.ehTagFilterValue().set(value)
|
||||
summary = "You can soft filter tags by adding them to the \"My Tags\" E/ExHentai page with a negative weight. If a gallery has tags that add up to weight below this value, it is filtered from view. This threshold can be set between 0 and -9999. Currently: $value"
|
||||
preferences.ehTagFilterValue().reconfigure()
|
||||
}
|
||||
.show()
|
||||
@ -270,15 +260,15 @@ class SettingsEhController : SettingsController() {
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
preference {
|
||||
title = "Tag Watching Threshold"
|
||||
titleRes = R.string.tag_watching_threshhold
|
||||
key = PreferenceKeys.eh_tag_watching_value
|
||||
defaultValue = 0
|
||||
|
||||
summary = "Recently uploaded galleries will be included on the watched screen if it has at least one watched tag with positive weight, and the sum of weights on its watched tags add up to this value or higher. This threshold can be set between 0 and 9999. Currently: ${preferences.ehTagWatchingValue().get()}"
|
||||
summaryRes = R.string.tag_watching_threshhold_summary
|
||||
|
||||
onClick {
|
||||
MaterialDialog(activity!!)
|
||||
.title(text = "Tag Watching Threshold")
|
||||
.title(R.string.tag_watching_threshhold)
|
||||
.input(
|
||||
inputType = InputType.TYPE_NUMBER_FLAG_SIGNED,
|
||||
maxLength = 4,
|
||||
@ -291,14 +281,13 @@ class SettingsEhController : SettingsController() {
|
||||
if (value != null && value in 0..9999) {
|
||||
inputField.error = null
|
||||
} else {
|
||||
inputField.error = "Must be between 0 and 9999!"
|
||||
inputField.error = context.getString(R.string.tag_watching_threshhold_error)
|
||||
}
|
||||
dialog.setActionButtonEnabled(WhichButton.POSITIVE, value != null && value in 0..9999)
|
||||
}
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val value = it.getInputField().text.toString().toInt()
|
||||
preferences.ehTagWatchingValue().set(value)
|
||||
summary = "Recently uploaded galleries will be included on the watched screen if it has at least one watched tag with positive weight, and the sum of weights on its watched tags add up to this value or higher. This threshold can be set between 0 and 9999. Currently: $value"
|
||||
preferences.ehTagWatchingValue().reconfigure()
|
||||
}
|
||||
.show()
|
||||
@ -306,13 +295,13 @@ class SettingsEhController : SettingsController() {
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
preference {
|
||||
title = "Language Filtering"
|
||||
summary = "If you wish to hide galleries in certain languages from the gallery list and searches, select them in the dialog that will popup.\nNote that matching galleries will never appear regardless of your search query.\nTldr checkmarked = exclude"
|
||||
titleRes = R.string.language_filtering
|
||||
summaryRes = R.string.language_filtering_summary
|
||||
|
||||
onClick {
|
||||
MaterialDialog(activity!!)
|
||||
.title(text = "Language Filtering")
|
||||
.message(text = "If you wish to hide galleries in certain languages from the gallery list and searches, select them in the dialog that will popup.\nNote that matching galleries will never appear regardless of your search query.\nTldr checkmarked = exclude")
|
||||
.title(R.string.language_filtering)
|
||||
.message(R.string.language_filtering_summary)
|
||||
.customView(R.layout.eh_dialog_languages, scrollable = true)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
val customView = it.view.contentLayout.customView!!
|
||||
@ -444,13 +433,13 @@ class SettingsEhController : SettingsController() {
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
preference {
|
||||
title = "Front Page Categories"
|
||||
summary = "What categories would you like to show by default on the front page and in searches? They can still be enabled by enabling their filters"
|
||||
titleRes = R.string.frong_page_categories
|
||||
summaryRes = R.string.fromt_page_categories_summary
|
||||
|
||||
onClick {
|
||||
MaterialDialog(activity!!)
|
||||
.title(text = "Front Page Categories")
|
||||
.message(text = "What categories would you like to show by default on the front page and in searches? They can still be enabled by enabling their filters")
|
||||
.title(R.string.frong_page_categories)
|
||||
.message(R.string.fromt_page_categories_summary)
|
||||
.customView(R.layout.eh_dialog_categories, scrollable = true)
|
||||
.positiveButton {
|
||||
val customView = it.view.contentLayout.customView!!
|
||||
@ -497,22 +486,22 @@ class SettingsEhController : SettingsController() {
|
||||
switchPreference {
|
||||
defaultValue = false
|
||||
key = PreferenceKeys.eh_watched_list_default_state
|
||||
title = "Watched List Filter Default State"
|
||||
summary = "When browsing ExHentai/E-Hentai should the watched list filter be enabled by default"
|
||||
}
|
||||
titleRes = R.string.watched_list_default
|
||||
summaryRes = R.string.watched_list_state_summary
|
||||
}.dependency = PreferenceKeys.eh_enableExHentai
|
||||
|
||||
listPreference {
|
||||
defaultValue = "auto"
|
||||
key = PreferenceKeys.eh_ehentai_quality
|
||||
summary = "The quality of the downloaded images"
|
||||
title = "Image quality"
|
||||
entries = arrayOf(
|
||||
"Auto",
|
||||
"2400x",
|
||||
"1600x",
|
||||
"1280x",
|
||||
"980x",
|
||||
"780x"
|
||||
summaryRes = R.string.eh_image_quality_summary
|
||||
titleRes = R.string.eh_image_quality
|
||||
entriesRes = arrayOf(
|
||||
R.string.eh_image_quality_auto,
|
||||
R.string.eh_image_quality_2400,
|
||||
R.string.eh_image_quality_1600,
|
||||
R.string.eh_image_quality_1280,
|
||||
R.string.eh_image_quality_980,
|
||||
R.string.eh_image_quality_780
|
||||
)
|
||||
entryValues = arrayOf(
|
||||
"auto",
|
||||
@ -528,18 +517,18 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
title = "Favorites sync"
|
||||
titleRes = R.string.favorites_sync
|
||||
|
||||
switchPreference {
|
||||
title = "Disable favorites uploading"
|
||||
summary = "Favorites are only downloaded from ExHentai. Any changes to favorites in the app will not be uploaded. Prevents accidental loss of favorites on ExHentai. Note that removals will still be downloaded (if you remove a favorites on ExHentai, it will be removed in the app as well)."
|
||||
titleRes = R.string.disable_favorites_uploading
|
||||
summaryRes = R.string.disable_favorites_uploading_summary
|
||||
key = PreferenceKeys.eh_readOnlySync
|
||||
defaultValue = false
|
||||
}
|
||||
|
||||
preference {
|
||||
title = "Show favorites sync notes"
|
||||
summary = "Show some information regarding the favorites sync feature"
|
||||
titleRes = R.string.show_favorite_sync_notes
|
||||
summaryRes = R.string.show_favorite_sync_notes_summary
|
||||
|
||||
onClick {
|
||||
activity?.let {
|
||||
@ -549,21 +538,21 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
title = "Ignore sync errors when possible"
|
||||
summary = "Do not abort immediately when encountering errors during the sync process. Errors will still be displayed when the sync is complete. Can cause loss of favorites in some cases. Useful when syncing large libraries."
|
||||
titleRes = R.string.ignore_sync_errors
|
||||
summaryRes = R.string.ignore_sync_errors_summary
|
||||
key = PreferenceKeys.eh_lenientSync
|
||||
defaultValue = false
|
||||
}
|
||||
|
||||
preference {
|
||||
title = "Force sync state reset"
|
||||
summary = "Performs a full resynchronization on the next sync. Removals will not be synced. All favorites in the app will be re-uploaded to ExHentai and all favorites on ExHentai will be re-downloaded into the app. Useful for repairing sync after sync has been interrupted."
|
||||
titleRes = R.string.force_sync_state_reset
|
||||
summaryRes = R.string.force_sync_state_reset_summary
|
||||
|
||||
onClick {
|
||||
activity?.let { activity ->
|
||||
MaterialDialog(activity)
|
||||
.title(R.string.eh_force_sync_reset_title)
|
||||
.message(R.string.eh_force_sync_reset_message)
|
||||
.title(R.string.favorites_sync_reset)
|
||||
.message(R.string.favorites_sync_reset_message)
|
||||
.positiveButton(android.R.string.yes) {
|
||||
LocalFavoritesStorage().apply {
|
||||
getRealm().use {
|
||||
@ -572,7 +561,7 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
}
|
||||
}
|
||||
activity.toast("Sync state reset", Toast.LENGTH_LONG)
|
||||
activity.toast(context.getString(R.string.sync_state_reset), Toast.LENGTH_LONG)
|
||||
}
|
||||
.negativeButton(android.R.string.no)
|
||||
.cancelable(false)
|
||||
@ -583,20 +572,20 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
preferenceCategory {
|
||||
title = "Gallery update checker"
|
||||
titleRes = R.string.gallery_update_checker
|
||||
|
||||
intListPreference {
|
||||
key = PreferenceKeys.eh_autoUpdateFrequency
|
||||
title = "Time between update batches"
|
||||
entries = arrayOf(
|
||||
"Never update galleries",
|
||||
"1 hour",
|
||||
"2 hours",
|
||||
"3 hours",
|
||||
"6 hours",
|
||||
"12 hours",
|
||||
"24 hours",
|
||||
"48 hours"
|
||||
titleRes = R.string.time_between_batches
|
||||
entriesRes = arrayOf(
|
||||
R.string.time_between_batches_never,
|
||||
R.string.time_between_batches_1_hour,
|
||||
R.string.time_between_batches_2_hours,
|
||||
R.string.time_between_batches_3_hours,
|
||||
R.string.time_between_batches_6_hours,
|
||||
R.string.time_between_batches_12_hours,
|
||||
R.string.time_between_batches_24_hours,
|
||||
R.string.time_between_batches_48_hours
|
||||
)
|
||||
entryValues = arrayOf("0", "1", "2", "3", "6", "12", "24", "48")
|
||||
defaultValue = "0"
|
||||
@ -604,11 +593,9 @@ class SettingsEhController : SettingsController() {
|
||||
preferences.eh_autoUpdateFrequency().asFlow()
|
||||
.onEach { newVal ->
|
||||
summary = if (newVal == 0) {
|
||||
"${context.getString(R.string.app_name)} will currently never check galleries in your library for updates."
|
||||
context.getString(R.string.time_between_batches_summary_1, context.getString(R.string.app_name))
|
||||
} else {
|
||||
"${context.getString(R.string.app_name)} checks/updates galleries in batches. " +
|
||||
"This means it will wait $newVal hour(s), check ${EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION} galleries," +
|
||||
" wait $newVal hour(s), check ${EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION} and so on..."
|
||||
context.getString(R.string.time_between_batches_summary_2, context.getString(R.string.app_name), newVal, EHentaiUpdateWorkerConstants.UPDATES_PER_ITERATION)
|
||||
}
|
||||
}
|
||||
.launchIn(scope)
|
||||
@ -622,7 +609,7 @@ class SettingsEhController : SettingsController() {
|
||||
|
||||
multiSelectListPreference {
|
||||
key = PreferenceKeys.eh_autoUpdateRestrictions
|
||||
title = "Auto update restrictions"
|
||||
titleRes = R.string.auto_update_restrictions
|
||||
entriesRes = arrayOf(R.string.wifi, R.string.charging)
|
||||
entryValues = arrayOf("wifi", "ac")
|
||||
summaryRes = R.string.pref_library_update_restriction_summary
|
||||
@ -639,11 +626,11 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
preference {
|
||||
title = "Show updater statistics"
|
||||
titleRes = R.string.show_updater_statistics
|
||||
|
||||
onClick {
|
||||
val progress = MaterialDialog(context)
|
||||
.message(R.string.eh_show_update_statistics_dialog)
|
||||
.message(R.string.gallery_updater_statistics_collection)
|
||||
.cancelable(false)
|
||||
progress.show()
|
||||
|
||||
@ -655,8 +642,8 @@ class SettingsEhController : SettingsController() {
|
||||
}
|
||||
|
||||
val statsText = if (stats != null) {
|
||||
"The updater last ran ${Humanize.naturalTime(Date(stats.startTime))}, and checked ${stats.updateCount} out of the ${stats.possibleUpdates} galleries that were ready for checking."
|
||||
} else "The updater has not ran yet."
|
||||
context.getString(R.string.gallery_updater_stats_text, Humanize.naturalTime(Date(stats.startTime)), stats.updateCount, stats.possibleUpdates)
|
||||
} else context.getString(R.string.gallery_updater_not_ran_yet)
|
||||
|
||||
val allMeta = db.getFavoriteMangaWithMetadata().await().filter {
|
||||
it.source == EH_SOURCE_ID || it.source == EXH_SOURCE_ID
|
||||
@ -672,26 +659,24 @@ class SettingsEhController : SettingsController() {
|
||||
}.count()
|
||||
}
|
||||
|
||||
"""
|
||||
$statsText
|
||||
|
||||
Galleries that were checked in the last:
|
||||
- hour: ${metaInRelativeDuration(1.hours)}
|
||||
- 6 hours: ${metaInRelativeDuration(6.hours)}
|
||||
- 12 hours: ${metaInRelativeDuration(12.hours)}
|
||||
- day: ${metaInRelativeDuration(1.days)}
|
||||
- 2 days: ${metaInRelativeDuration(2.days)}
|
||||
- week: ${metaInRelativeDuration(7.days)}
|
||||
- month: ${metaInRelativeDuration(30.days)}
|
||||
- year: ${metaInRelativeDuration(365.days)}
|
||||
""".trimIndent()
|
||||
statsText + "\n\n" + context.getString(
|
||||
R.string.gallery_updater_stats_time,
|
||||
metaInRelativeDuration(1.hours),
|
||||
metaInRelativeDuration(6.hours),
|
||||
metaInRelativeDuration(12.hours),
|
||||
metaInRelativeDuration(1.days),
|
||||
metaInRelativeDuration(2.days),
|
||||
metaInRelativeDuration(7.days),
|
||||
metaInRelativeDuration(30.days),
|
||||
metaInRelativeDuration(365.days)
|
||||
)
|
||||
} finally {
|
||||
progress.dismiss()
|
||||
}
|
||||
|
||||
withContext(Dispatchers.Main) {
|
||||
MaterialDialog(context)
|
||||
.title(text = "Gallery updater statistics")
|
||||
.title(R.string.gallery_updater_statistics)
|
||||
.message(text = updateInfo)
|
||||
.positiveButton(android.R.string.ok)
|
||||
.show()
|
||||
|
@ -16,6 +16,7 @@ import eu.kanade.tachiyomi.util.preference.onChange
|
||||
import eu.kanade.tachiyomi.util.preference.onClick
|
||||
import eu.kanade.tachiyomi.util.preference.preference
|
||||
import eu.kanade.tachiyomi.util.preference.preferenceCategory
|
||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
import eu.kanade.tachiyomi.util.system.LocaleHelper
|
||||
@ -252,19 +253,18 @@ class SettingsGeneralController : SettingsController() {
|
||||
}
|
||||
// --> EXH
|
||||
preferenceCategory {
|
||||
titleRes = R.string.eh_settings_category
|
||||
titleRes = R.string.pref_category_fork
|
||||
|
||||
switchPreference {
|
||||
key = Keys.eh_expandFilters
|
||||
title = "Expand all search filters by default"
|
||||
titleRes = R.string.toggle_expand_search_filters
|
||||
defaultValue = false
|
||||
}
|
||||
|
||||
switchPreference {
|
||||
key = Keys.eh_autoSolveCaptchas
|
||||
title = "Automatically solve captcha"
|
||||
summary =
|
||||
"Use HIGHLY EXPERIMENTAL automatic ReCAPTCHA solver. Will be grayed out if unsupported by your device."
|
||||
titleRes = R.string.auto_solve_captchas
|
||||
summaryRes = R.string.auto_solve_captchas_summary
|
||||
defaultValue = false
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
|
||||
/**
|
||||
* hitomi.la Settings fragment
|
||||
@ -11,11 +14,11 @@ import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
|
||||
class SettingsHlController : SettingsController() {
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||
title = "hitomi.la"
|
||||
titleRes = R.string.pref_category_hl
|
||||
|
||||
switchPreference {
|
||||
title = "Use high-quality thumbnails"
|
||||
summary = "May slow down search results"
|
||||
titleRes = R.string.high_quality_thumbnails
|
||||
summaryRes = R.string.high_quality_thumbnails_summary
|
||||
key = PreferenceKeys.eh_hl_useHighQualityThumbs
|
||||
defaultValue = false
|
||||
}
|
||||
|
@ -219,11 +219,11 @@ class SettingsLibraryController : SettingsController() {
|
||||
.isNotEmpty()
|
||||
) {
|
||||
preferenceCategory {
|
||||
title = "Migration"
|
||||
titleRes = R.string.migration
|
||||
|
||||
switchPreference {
|
||||
key = Keys.skipPreMigration
|
||||
titleRes = R.string.pref_skip_pre_migration
|
||||
titleRes = R.string.skip_pre_migration
|
||||
summaryRes = R.string.pref_skip_pre_migration_summary
|
||||
defaultValue = false
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
package eu.kanade.tachiyomi.ui.setting
|
||||
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||
import eu.kanade.tachiyomi.util.preference.defaultValue
|
||||
import eu.kanade.tachiyomi.util.preference.summaryRes
|
||||
import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
import eu.kanade.tachiyomi.util.preference.titleRes
|
||||
|
||||
/**
|
||||
* nhentai Settings fragment
|
||||
@ -11,11 +14,11 @@ import eu.kanade.tachiyomi.util.preference.switchPreference
|
||||
|
||||
class SettingsNhController : SettingsController() {
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) = with(screen) {
|
||||
title = "nhentai"
|
||||
titleRes = R.string.pref_category_nh
|
||||
|
||||
switchPreference {
|
||||
title = "Use high-quality thumbnails"
|
||||
summary = "May slow down search results"
|
||||
titleRes = R.string.high_quality_thumbnails
|
||||
summaryRes = R.string.high_quality_thumbnails_summary
|
||||
key = PreferenceKeys.eh_nh_useHighQualityThumbs
|
||||
defaultValue = false
|
||||
}
|
||||
|
@ -140,34 +140,31 @@ class SettingsReaderController : SettingsController() {
|
||||
|
||||
// EXH -->
|
||||
preferenceCategory {
|
||||
titleRes = R.string.eh_settings_category
|
||||
titleRes = R.string.pref_category_fork
|
||||
|
||||
intListPreference {
|
||||
key = Keys.eh_readerThreads
|
||||
title = "Download threads"
|
||||
titleRes = R.string.download_threads
|
||||
entries = arrayOf("1", "2", "3", "4", "5")
|
||||
entryValues = entries
|
||||
defaultValue = "2"
|
||||
summary =
|
||||
"Higher values can speed up image downloading significantly, but can also trigger bans. Recommended value is 2 or 3. Current value is: %s"
|
||||
summaryRes = R.string.download_threads_summary
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.eh_aggressivePageLoading
|
||||
title = "Aggressively load pages"
|
||||
summary =
|
||||
"Slowly download the entire gallery while reading instead of just loading the pages you are viewing."
|
||||
titleRes = R.string.aggressively_load_pages
|
||||
summaryRes = R.string.aggressively_load_pages_summary
|
||||
defaultValue = false
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.eh_readerInstantRetry
|
||||
title = "Skip queue on retry"
|
||||
summary =
|
||||
"Normally, pressing the retry button on a failed download will wait until the downloader has finished downloading the last page before beginning to re-download the failed page. Enabling this will force the downloader to begin re-downloading the failed page as soon as you press the retry button."
|
||||
titleRes = R.string.skip_queue_on_retry
|
||||
summaryRes = R.string.skip_queue_on_retry_summary
|
||||
defaultValue = true
|
||||
}
|
||||
intListPreference {
|
||||
key = Keys.eh_preload_size
|
||||
title = "Reader Preload amount"
|
||||
titleRes = R.string.reader_preload_amount
|
||||
entryValues = arrayOf(
|
||||
"1",
|
||||
"2",
|
||||
@ -180,25 +177,24 @@ class SettingsReaderController : SettingsController() {
|
||||
"14",
|
||||
"16"
|
||||
)
|
||||
entries = arrayOf(
|
||||
"1 Page",
|
||||
"2 Pages",
|
||||
"3 Pages",
|
||||
"4 Pages",
|
||||
"6 Pages",
|
||||
"8 Pages",
|
||||
"10 Pages",
|
||||
"12 Pages",
|
||||
"14 Pages",
|
||||
"16 Pages"
|
||||
entriesRes = arrayOf(
|
||||
R.string.reader_preload_amount_1_page,
|
||||
R.string.reader_preload_amount_2_pages,
|
||||
R.string.reader_preload_amount_3_pages,
|
||||
R.string.reader_preload_amount_4_pages,
|
||||
R.string.reader_preload_amount_6_pages,
|
||||
R.string.reader_preload_amount_8_pages,
|
||||
R.string.reader_preload_amount_10_pages,
|
||||
R.string.reader_preload_amount_12_pages,
|
||||
R.string.reader_preload_amount_14_pages,
|
||||
R.string.reader_preload_amount_16_pages
|
||||
)
|
||||
defaultValue = "4"
|
||||
summary =
|
||||
"The amount of pages to preload when reading. Higher values will result in a smoother reading experience, at the cost of higher cache usage, it is recommended to increase the amount of cache you allocate when using larger values"
|
||||
summaryRes = R.string.reader_preload_amount_summary
|
||||
}
|
||||
listPreference {
|
||||
key = Keys.eh_cacheSize
|
||||
title = "Reader cache size"
|
||||
titleRes = R.string.reader_cache_size
|
||||
entryValues = arrayOf(
|
||||
"50",
|
||||
"75",
|
||||
@ -236,18 +232,17 @@ class SettingsReaderController : SettingsController() {
|
||||
"5 GB"
|
||||
)
|
||||
defaultValue = "75"
|
||||
summary =
|
||||
"The amount of images to save on device while reading. Higher values will result in a smoother reading experience, at the cost of higher disk space usage"
|
||||
summaryRes = R.string.reader_cache_size_summary
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.eh_preserveReadingPosition
|
||||
title = "Preserve reading position on read manga"
|
||||
titleRes = R.string.preserve_reading_position
|
||||
defaultValue = false
|
||||
}
|
||||
switchPreference {
|
||||
key = Keys.eh_use_auto_webtoon
|
||||
title = "Auto Webtoon Mode"
|
||||
summary = "Use auto webtoon mode for manga that are detected to likely use the long strip format"
|
||||
titleRes = R.string.auto_webtoon_mode
|
||||
summaryRes = R.string.auto_webtoon_mode_summary
|
||||
defaultValue = true
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,6 @@ import android.content.Context
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Filter
|
||||
import android.widget.Filterable
|
||||
import timber.log.Timber
|
||||
|
||||
class AutoCompleteAdapter(context: Context, resource: Int, var objects: List<String>, val excludePrefix: String?) :
|
||||
ArrayAdapter<String>(context, resource, objects),
|
||||
@ -35,8 +34,6 @@ class AutoCompleteAdapter(context: Context, resource: Int, var objects: List<Str
|
||||
mOriginalValues = objects
|
||||
}
|
||||
|
||||
Timber.d("$prefix ")
|
||||
|
||||
if (prefix == null || prefix.isEmpty()) {
|
||||
val list = mOriginalValues!!
|
||||
results.values = list
|
||||
@ -44,7 +41,6 @@ class AutoCompleteAdapter(context: Context, resource: Int, var objects: List<Str
|
||||
} else {
|
||||
val prefixString = prefix.toString()
|
||||
val containsPrefix: Boolean = excludePrefix?.let { prefixString.startsWith(it) } ?: false
|
||||
Timber.d(prefixString)
|
||||
val filterResults = mOriginalValues!!.filter { it.contains(if (excludePrefix != null) prefixString.removePrefix(excludePrefix) else prefixString, true) }
|
||||
results.values = if (containsPrefix) filterResults.map { excludePrefix + it } else filterResults
|
||||
results.count = filterResults.size
|
||||
|
@ -1,7 +1,9 @@
|
||||
package exh
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import com.elvishew.xlog.XLog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.database.DatabaseHelper
|
||||
import eu.kanade.tachiyomi.data.database.models.Manga
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
@ -18,12 +20,13 @@ class GalleryAdder {
|
||||
private val sourceManager: SourceManager by injectLazy()
|
||||
|
||||
fun addGallery(
|
||||
context: Context,
|
||||
url: String,
|
||||
fav: Boolean = false,
|
||||
forceSource: UrlImportableSource? = null,
|
||||
throttleFunc: () -> Unit = {}
|
||||
): GalleryAddEvent {
|
||||
XLog.d("Importing gallery (url: %s, fav: %s, forceSource: %s)...", url, fav, forceSource)
|
||||
XLog.d(context.getString(R.string.gallery_adder_importing_gallery, url, fav.toString(), forceSource))
|
||||
try {
|
||||
val uri = Uri.parse(url)
|
||||
|
||||
@ -31,10 +34,10 @@ class GalleryAdder {
|
||||
val source = if (forceSource != null) {
|
||||
try {
|
||||
if (forceSource.matchesUri(uri)) forceSource
|
||||
else return GalleryAddEvent.Fail.UnknownType(url)
|
||||
else return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||
} catch (e: Exception) {
|
||||
XLog.e("Source URI match check error!", e)
|
||||
return GalleryAddEvent.Fail.UnknownType(url)
|
||||
XLog.e(context.getString(R.string.gallery_adder_source_uri_must_match), e)
|
||||
return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||
}
|
||||
} else {
|
||||
sourceManager.getVisibleCatalogueSources()
|
||||
@ -43,7 +46,7 @@ class GalleryAdder {
|
||||
try {
|
||||
it.matchesUri(uri)
|
||||
} catch (e: Exception) {
|
||||
XLog.e("Source URI match check error!", e)
|
||||
XLog.e(context.getString(R.string.gallery_adder_source_uri_must_match), e)
|
||||
false
|
||||
}
|
||||
} ?: sourceManager.getDelegatedCatalogueSources()
|
||||
@ -52,27 +55,27 @@ class GalleryAdder {
|
||||
try {
|
||||
it.matchesUri(uri)
|
||||
} catch (e: Exception) {
|
||||
XLog.e("Source URI match check error!", e)
|
||||
XLog.e(context.getString(R.string.gallery_adder_source_uri_must_match), e)
|
||||
false
|
||||
}
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url)
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||
}
|
||||
|
||||
// Map URL to manga URL
|
||||
val realUrl = try {
|
||||
source.mapUrlToMangaUrl(uri)
|
||||
} catch (e: Exception) {
|
||||
XLog.e("Source URI map-to-manga error!", e)
|
||||
XLog.e(context.getString(R.string.gallery_adder_uri_map_to_manga_error), e)
|
||||
null
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url)
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||
|
||||
// Clean URL
|
||||
val cleanedUrl = try {
|
||||
source.cleanMangaUrl(realUrl)
|
||||
} catch (e: Exception) {
|
||||
XLog.e("Source URI clean error!", e)
|
||||
XLog.e(context.getString(R.string.gallery_adder_uri_clean_error), e)
|
||||
null
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url)
|
||||
} ?: return GalleryAddEvent.Fail.UnknownType(url, context)
|
||||
|
||||
// Use manga in DB if possible, otherwise, make a new manga
|
||||
val manga = db.getManga(cleanedUrl, source.id).executeAsBlocking()
|
||||
@ -112,16 +115,16 @@ class GalleryAdder {
|
||||
syncChaptersWithSource(db, it, manga, source)
|
||||
}.toBlocking().first()
|
||||
} catch (e: Exception) {
|
||||
XLog.w("Failed to update chapters for gallery: ${manga.title}!", e)
|
||||
return GalleryAddEvent.Fail.Error(url, "Failed to update chapters for gallery: $url")
|
||||
XLog.w(context.getString(R.string.gallery_adder_chapter_fetch_error, manga.title), e)
|
||||
return GalleryAddEvent.Fail.Error(url, context.getString(R.string.gallery_adder_chapter_fetch_error, url))
|
||||
}
|
||||
|
||||
return GalleryAddEvent.Success(url, manga)
|
||||
return GalleryAddEvent.Success(url, manga, context)
|
||||
} catch (e: Exception) {
|
||||
XLog.w("Could not add gallery (url: $url)!", e)
|
||||
XLog.w(context.getString(R.string.gallery_adder_could_not_add_gallery, url), e)
|
||||
|
||||
if (e is EHentai.GalleryNotFoundException) {
|
||||
return GalleryAddEvent.Fail.NotFound(url)
|
||||
return GalleryAddEvent.Fail.NotFound(url, context)
|
||||
}
|
||||
|
||||
return GalleryAddEvent.Fail.Error(
|
||||
@ -139,15 +142,16 @@ sealed class GalleryAddEvent {
|
||||
|
||||
class Success(
|
||||
override val galleryUrl: String,
|
||||
val manga: Manga
|
||||
val manga: Manga,
|
||||
val context: Context
|
||||
) : GalleryAddEvent() {
|
||||
override val galleryTitle = manga.title
|
||||
override val logMessage = "Added gallery: $galleryTitle"
|
||||
override val logMessage = context.getString(R.string.batch_add_success_log_message, galleryTitle)
|
||||
}
|
||||
|
||||
sealed class Fail : GalleryAddEvent() {
|
||||
class UnknownType(override val galleryUrl: String) : Fail() {
|
||||
override val logMessage = "Unknown gallery type for gallery: $galleryUrl"
|
||||
class UnknownType(override val galleryUrl: String, val context: Context) : Fail() {
|
||||
override val logMessage = context.getString(R.string.batch_add_unknown_type_log_message, galleryUrl)
|
||||
}
|
||||
|
||||
open class Error(
|
||||
@ -155,7 +159,7 @@ sealed class GalleryAddEvent {
|
||||
override val logMessage: String
|
||||
) : Fail()
|
||||
|
||||
class NotFound(galleryUrl: String) :
|
||||
Error(galleryUrl, "Gallery does not exist: $galleryUrl")
|
||||
class NotFound(galleryUrl: String, context: Context) :
|
||||
Error(galleryUrl, context.getString(R.string.batch_add_not_exist_log_message, galleryUrl))
|
||||
}
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ package exh.favorites
|
||||
import android.content.Context
|
||||
import androidx.core.text.HtmlCompat
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
@ -10,26 +11,11 @@ class FavoritesIntroDialog {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
|
||||
fun show(context: Context) = MaterialDialog(context)
|
||||
.title(text = "IMPORTANT FAVORITES SYNC NOTES")
|
||||
.message(text = HtmlCompat.fromHtml(FAVORITES_INTRO_TEXT, HtmlCompat.FROM_HTML_MODE_LEGACY))
|
||||
.title(R.string.favorites_sync_notes)
|
||||
.message(text = HtmlCompat.fromHtml(context.getString(R.string.favorites_sync_notes_message), HtmlCompat.FROM_HTML_MODE_LEGACY))
|
||||
.positiveButton(android.R.string.ok) {
|
||||
prefs.eh_showSyncIntro().set(false)
|
||||
}
|
||||
.cancelable(false)
|
||||
.show()
|
||||
|
||||
private val FAVORITES_INTRO_TEXT =
|
||||
"""
|
||||
1. Changes to category names in the app are <b>NOT</b> synced! Please <i>change the category names on ExHentai instead</i>. The category names will be copied from the ExHentai servers every sync.
|
||||
<br><br>
|
||||
2. The favorite categories on ExHentai correspond to the <b>first 10 categories in the app</b> (excluding the 'Default' category). <i>Galleries in other categories will <b>NOT</b> be synced!</i>
|
||||
<br><br>
|
||||
3. <font color='red'><b>ENSURE YOU HAVE A STABLE INTERNET CONNECTION WHEN SYNC IS IN PROGRESS!</b></font> If the internet disconnects while the app is syncing, your favorites may be left in a <i>partially-synced state</i>.
|
||||
<br><br>
|
||||
4. Keep the app open while favorites are syncing. Android will close apps that are in the background sometimes and that could be bad if it happens while the app is syncing.
|
||||
<br><br>
|
||||
5. <b>Do NOT put favorites in multiple categories</b> (the app supports this). This can confuse the sync algorithm as ExHentai only allows each favorite to be in one category.
|
||||
<br><br>
|
||||
This dialog will only popup once. You can read these notes again by going to 'Settings > E-Hentai > Show favorites sync notes'.
|
||||
""".trimIndent()
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.net.wifi.WifiManager
|
||||
import android.os.PowerManager
|
||||
import com.elvishew.xlog.XLog
|
||||
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.database.models.Manga
|
||||
@ -52,7 +53,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
private val logger = XLog.tag("EHFavSync").build()
|
||||
|
||||
val status = BehaviorSubject.create<FavoritesSyncStatus>(FavoritesSyncStatus.Idle())
|
||||
val status = BehaviorSubject.create<FavoritesSyncStatus>(FavoritesSyncStatus.Idle(context))
|
||||
|
||||
@Synchronized
|
||||
fun runSync() {
|
||||
@ -60,7 +61,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
return
|
||||
}
|
||||
|
||||
status.onNext(FavoritesSyncStatus.Initializing())
|
||||
status.onNext(FavoritesSyncStatus.Initializing(context))
|
||||
|
||||
thread { beginSync() }
|
||||
}
|
||||
@ -68,12 +69,12 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
private fun beginSync() {
|
||||
// Check if logged in
|
||||
if (!prefs.enableExhentai().get()) {
|
||||
status.onNext(FavoritesSyncStatus.Error("Please log in!"))
|
||||
status.onNext(FavoritesSyncStatus.Error(context.getString(R.string.please_login)))
|
||||
return
|
||||
}
|
||||
|
||||
// Validate library state
|
||||
status.onNext(FavoritesSyncStatus.Processing("Verifying local library"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_verifying_library), context = context))
|
||||
val libraryManga = db.getLibraryMangas().executeAsBlocking()
|
||||
val seenManga = HashSet<Long>(libraryManga.size)
|
||||
libraryManga.forEach {
|
||||
@ -83,9 +84,9 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
val inCategories = db.getCategoriesForManga(it).executeAsBlocking()
|
||||
status.onNext(
|
||||
FavoritesSyncStatus.BadLibraryState
|
||||
.MangaInMultipleCategories(it, inCategories)
|
||||
.MangaInMultipleCategories(it, inCategories, context)
|
||||
)
|
||||
logger.w("Manga %s is in multiple categories!", it.id)
|
||||
logger.w(context.getString(R.string.favorites_sync_manga_multiple_categories_error, it.id))
|
||||
return
|
||||
} else {
|
||||
seenManga += it.id!!
|
||||
@ -94,11 +95,11 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
// Download remote favorites
|
||||
val favorites = try {
|
||||
status.onNext(FavoritesSyncStatus.Processing("Downloading favorites from remote server"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_downloading), context = context))
|
||||
exh.fetchFavorites()
|
||||
} catch (e: Exception) {
|
||||
status.onNext(FavoritesSyncStatus.Error("Failed to fetch favorites from remote server!"))
|
||||
logger.e("Could not fetch favorites!", e)
|
||||
status.onNext(FavoritesSyncStatus.Error(context.getString(R.string.favorites_sync_failed_to_featch)))
|
||||
logger.e(context.getString(R.string.favorites_sync_could_not_fetch), e)
|
||||
return
|
||||
}
|
||||
|
||||
@ -127,17 +128,17 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
storage.getRealm().use { realm ->
|
||||
realm.trans {
|
||||
db.inTransaction {
|
||||
status.onNext(FavoritesSyncStatus.Processing("Calculating remote changes"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_calculating_remote_changes), context = context))
|
||||
val remoteChanges = storage.getChangedRemoteEntries(realm, favorites.first)
|
||||
val localChanges = if (prefs.eh_readOnlySync().get()) {
|
||||
null // Do not build local changes if they are not going to be applied
|
||||
} else {
|
||||
status.onNext(FavoritesSyncStatus.Processing("Calculating local changes"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_calculating_local_changes), context = context))
|
||||
storage.getChangedDbEntries(realm)
|
||||
}
|
||||
|
||||
// Apply remote categories
|
||||
status.onNext(FavoritesSyncStatus.Processing("Updating category names"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_syncing_category_names), context = context))
|
||||
applyRemoteCategories(favorites.second)
|
||||
|
||||
// Apply change sets
|
||||
@ -146,7 +147,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
applyChangeSetToRemote(errorList, localChanges)
|
||||
}
|
||||
|
||||
status.onNext(FavoritesSyncStatus.Processing("Cleaning up"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_cleaning_up), context = context))
|
||||
storage.snapshotEntries(realm)
|
||||
}
|
||||
}
|
||||
@ -154,15 +155,15 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
val theContext = context
|
||||
launchUI {
|
||||
theContext.toast("Sync complete!")
|
||||
theContext.toast(context.getString(R.string.favorites_sync_complete))
|
||||
}
|
||||
} catch (e: IgnoredException) {
|
||||
// Do not display error as this error has already been reported
|
||||
logger.w("Ignoring exception!", e)
|
||||
logger.w(context.getString(R.string.favorites_sync_ignoring_exception), e)
|
||||
return
|
||||
} catch (e: Exception) {
|
||||
status.onNext(FavoritesSyncStatus.Error("Unknown error: ${e.message}"))
|
||||
logger.e("Sync error!", e)
|
||||
status.onNext(FavoritesSyncStatus.Error(context.getString(R.string.favorites_sync_unknown_error, e.message)))
|
||||
logger.e(context.getString(R.string.favorites_sync_sync_error), e)
|
||||
return
|
||||
} finally {
|
||||
// Release wake + wifi locks
|
||||
@ -180,7 +181,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
}
|
||||
|
||||
if (errorList.isEmpty()) {
|
||||
status.onNext(FavoritesSyncStatus.Idle())
|
||||
status.onNext(FavoritesSyncStatus.Idle(context))
|
||||
} else {
|
||||
status.onNext(FavoritesSyncStatus.CompleteWithErrors(errorList))
|
||||
}
|
||||
@ -268,7 +269,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
break
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.w("Sync network error!", e)
|
||||
logger.w(context.getString(R.string.favorites_sync_network_error), e)
|
||||
}
|
||||
}
|
||||
|
||||
@ -278,7 +279,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
private fun applyChangeSetToRemote(errorList: MutableList<String>, changeSet: ChangeSet) {
|
||||
// Apply removals
|
||||
if (changeSet.removed.isNotEmpty()) {
|
||||
status.onNext(FavoritesSyncStatus.Processing("Removing ${changeSet.removed.size} galleries from remote server"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_removing_galleries, changeSet.removed.size), context = context))
|
||||
|
||||
val formBody = FormBody.Builder()
|
||||
.add("ddact", "delete")
|
||||
@ -295,7 +296,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
.build()
|
||||
|
||||
if (!explicitlyRetryExhRequest(10, request)) {
|
||||
val errorString = "Unable to delete galleries from the remote servers!"
|
||||
val errorString = context.getString(R.string.favorites_sync_unable_to_delete)
|
||||
|
||||
if (prefs.eh_lenientSync().get()) {
|
||||
errorList += errorString
|
||||
@ -311,8 +312,9 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
changeSet.added.forEachIndexed { index, it ->
|
||||
status.onNext(
|
||||
FavoritesSyncStatus.Processing(
|
||||
"Adding gallery ${index + 1} of ${changeSet.added.size} to remote server",
|
||||
needWarnThrottle()
|
||||
context.getString(R.string.favorites_sync_adding_to_remote, index + 1, changeSet.added.size),
|
||||
needWarnThrottle(),
|
||||
context
|
||||
)
|
||||
)
|
||||
|
||||
@ -327,7 +329,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
// Apply removals
|
||||
changeSet.removed.forEachIndexed { index, it ->
|
||||
status.onNext(FavoritesSyncStatus.Processing("Removing gallery ${index + 1} of ${changeSet.removed.size} from local library"))
|
||||
status.onNext(FavoritesSyncStatus.Processing(context.getString(R.string.favorites_sync_remove_from_local, index + 1, changeSet.removed.size), context = context))
|
||||
val url = it.getUrl()
|
||||
|
||||
// Consider both EX and EH sources
|
||||
@ -359,8 +361,9 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
changeSet.added.forEachIndexed { index, it ->
|
||||
status.onNext(
|
||||
FavoritesSyncStatus.Processing(
|
||||
"Adding gallery ${index + 1} of ${changeSet.added.size} to local library",
|
||||
needWarnThrottle()
|
||||
context.getString(R.string.favorites_sync_add_to_local, index + 1, changeSet.added.size),
|
||||
needWarnThrottle(),
|
||||
context
|
||||
)
|
||||
)
|
||||
|
||||
@ -368,6 +371,7 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
// Import using gallery adder
|
||||
val result = galleryAdder.addGallery(
|
||||
context,
|
||||
"${exh.baseUrl}${it.getUrl()}",
|
||||
true,
|
||||
exh,
|
||||
@ -376,14 +380,14 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
|
||||
if (result is GalleryAddEvent.Fail) {
|
||||
if (result is GalleryAddEvent.Fail.NotFound) {
|
||||
XLog.e("Remote gallery does not exist, skipping: %s!", it.getUrl())
|
||||
XLog.e(context.getString(R.string.favorites_sync_remote_not_exist, it.getUrl()))
|
||||
// Skip this gallery, it no longer exists
|
||||
return@forEachIndexed
|
||||
}
|
||||
|
||||
val errorString = "Failed to add gallery to local database: " + when (result) {
|
||||
is GalleryAddEvent.Fail.Error -> "'${it.title}' ${result.logMessage}"
|
||||
is GalleryAddEvent.Fail.UnknownType -> "'${it.title}' (${result.galleryUrl}) is not a valid gallery!"
|
||||
val errorString = context.getString(R.string.favorites_sync_failed_to_add_to_local) + when (result) {
|
||||
is GalleryAddEvent.Fail.Error -> context.getString(R.string.favorites_sync_failed_to_add_to_local_error, it.title, result.logMessage)
|
||||
is GalleryAddEvent.Fail.UnknownType -> context.getString(R.string.favorites_sync_failed_to_add_to_local_unknown_type, it.title, result.galleryUrl)
|
||||
}
|
||||
|
||||
if (prefs.eh_lenientSync().get()) {
|
||||
@ -418,20 +422,22 @@ class FavoritesSyncHelper(val context: Context) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO String resources
|
||||
sealed class FavoritesSyncStatus(val message: String) {
|
||||
class Error(message: String) : FavoritesSyncStatus(message)
|
||||
class Idle : FavoritesSyncStatus("Waiting for sync to start")
|
||||
class Idle(context: Context) : FavoritesSyncStatus(context.getString(R.string.favorites_sync_waiting_for_start))
|
||||
sealed class BadLibraryState(message: String) : FavoritesSyncStatus(message) {
|
||||
class MangaInMultipleCategories(
|
||||
val manga: Manga,
|
||||
val categories: List<Category>
|
||||
val categories: List<Category>,
|
||||
context: Context
|
||||
) :
|
||||
BadLibraryState("The gallery: ${manga.title} is in more than one category (${categories.joinToString { it.name }})!")
|
||||
BadLibraryState(context.getString(R.string.favorites_sync_manga_in_multiple_categories, manga.title, categories.joinToString { it.name }))
|
||||
}
|
||||
class Initializing : FavoritesSyncStatus("Initializing sync")
|
||||
class Processing(message: String, isThrottle: Boolean = false) : FavoritesSyncStatus(
|
||||
class Initializing(context: Context) : FavoritesSyncStatus(context.getString(R.string.favorites_sync_initializing))
|
||||
class Processing(message: String, isThrottle: Boolean = false, context: Context) : FavoritesSyncStatus(
|
||||
if (isThrottle) {
|
||||
"$message\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete."
|
||||
context.getString(R.string.favorites_sync_processing_throttle, message)
|
||||
} else {
|
||||
message
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
package exh.log
|
||||
|
||||
import android.content.Context
|
||||
import androidx.annotation.StringRes
|
||||
import androidx.preference.PreferenceManager
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
||||
|
||||
enum class EHLogLevel(val description: String) {
|
||||
MINIMAL("critical errors only"),
|
||||
EXTRA("log everything"),
|
||||
EXTREME("network inspection mode");
|
||||
enum class EHLogLevel(@StringRes val nameRes: Int, @StringRes val description: Int) {
|
||||
MINIMAL(R.string.log_minimal, R.string.log_minimal_desc),
|
||||
EXTRA(R.string.log_extra, R.string.log_extra_desc),
|
||||
EXTREME(R.string.log_extreme, R.string.log_extreme_desc);
|
||||
|
||||
companion object {
|
||||
private var curLogLevel: Int? = null
|
||||
|
@ -4,6 +4,7 @@ import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
||||
import eu.kanade.tachiyomi.util.system.toast
|
||||
@ -17,16 +18,16 @@ class ConfiguringDialogController : DialogController() {
|
||||
if (savedViewState == null) {
|
||||
thread {
|
||||
try {
|
||||
EHConfigurator().configureAll()
|
||||
EHConfigurator(activity!!).configureAll()
|
||||
launchUI {
|
||||
activity?.toast("Settings successfully uploaded!")
|
||||
activity?.toast(activity?.getString(R.string.eh_settings_successfully_uploaded))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
activity?.let {
|
||||
it.runOnUiThread {
|
||||
MaterialDialog(it)
|
||||
.title(text = "Configuration failed!")
|
||||
.message(text = "An error occurred during the configuration process: " + e.message)
|
||||
.title(R.string.eh_settings_configuration_failed)
|
||||
.message(text = it.getString(R.string.eh_settings_configuration_failed_message, e.message))
|
||||
.positiveButton(android.R.string.ok)
|
||||
.show()
|
||||
}
|
||||
@ -40,8 +41,8 @@ class ConfiguringDialogController : DialogController() {
|
||||
}
|
||||
|
||||
return MaterialDialog(activity!!)
|
||||
.title(text = "Uploading settings to server")
|
||||
.message(text = "Please wait, this may take some time...")
|
||||
.title(R.string.eh_settings_uploading_to_server)
|
||||
.message(R.string.eh_settings_uploading_to_server_message)
|
||||
.cancelable(false)
|
||||
.also {
|
||||
materialDialog = it
|
||||
|
@ -1,5 +1,7 @@
|
||||
package exh.uconfig
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.source.SourceManager
|
||||
import eu.kanade.tachiyomi.source.online.all.EHentai
|
||||
@ -13,7 +15,7 @@ import okhttp3.Request
|
||||
import timber.log.Timber
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class EHConfigurator {
|
||||
class EHConfigurator(val context: Context) {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
private val sources: SourceManager by injectLazy()
|
||||
|
||||
@ -104,7 +106,7 @@ class EHConfigurator {
|
||||
|
||||
// No profile slots left :(
|
||||
if (availableProfiles.isEmpty()) {
|
||||
throw IllegalStateException("You are out of profile slots on ${source.name}, please delete a profile!")
|
||||
throw IllegalStateException(context.getString(R.string.eh_settings_out_of_slots_error, source.name))
|
||||
}
|
||||
// Create profile in available slot
|
||||
|
||||
|
@ -4,6 +4,7 @@ import android.app.Dialog
|
||||
import android.os.Bundle
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||
import uy.kohesive.injekt.Injekt
|
||||
@ -14,15 +15,8 @@ class WarnConfigureDialogController : DialogController() {
|
||||
private val prefs: PreferencesHelper by injectLazy()
|
||||
override fun onCreateDialog(savedViewState: Bundle?): Dialog {
|
||||
return MaterialDialog(activity!!)
|
||||
.title(text = "Settings profile note")
|
||||
.message(
|
||||
text =
|
||||
"""
|
||||
The app will now add a new settings profile on E-Hentai and ExHentai to optimize app performance. Please ensure that you have less than three profiles on both sites.
|
||||
|
||||
If you have no idea what settings profiles are, then it probably doesn't matter, just hit 'OK'.
|
||||
""".trimIndent()
|
||||
)
|
||||
.title(R.string.settings_profile_note)
|
||||
.message(R.string.settings_profile_note_message)
|
||||
.positiveButton(android.R.string.ok) {
|
||||
prefs.eh_showSettingsUploadWarning().set(false)
|
||||
ConfiguringDialogController().showDialog(router)
|
||||
|
@ -5,6 +5,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.TextView
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.EhFragmentBatchAddBinding
|
||||
import eu.kanade.tachiyomi.ui.base.controller.NucleusController
|
||||
import eu.kanade.tachiyomi.util.lang.combineLatest
|
||||
@ -26,7 +27,7 @@ class BatchAddController : NucleusController<EhFragmentBatchAddBinding, BatchAdd
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun getTitle() = "Batch add"
|
||||
override fun getTitle() = activity!!.getString(R.string.batch_add)
|
||||
|
||||
override fun createPresenter() = BatchAddPresenter()
|
||||
|
||||
@ -145,14 +146,14 @@ class BatchAddController : NucleusController<EhFragmentBatchAddBinding, BatchAdd
|
||||
return
|
||||
}
|
||||
|
||||
presenter.addGalleries(galleries)
|
||||
presenter.addGalleries(activity!!, galleries)
|
||||
}
|
||||
|
||||
private fun noGalleriesSpecified() {
|
||||
activity?.let {
|
||||
MaterialDialog(it)
|
||||
.title(text = "No galleries to add!")
|
||||
.message(text = "You must specify at least one gallery to add!")
|
||||
.title(R.string.batch_add_no_valid_galleries)
|
||||
.message(R.string.batch_add_no_valid_galleries_message)
|
||||
.positiveButton(android.R.string.ok) { materialDialog -> materialDialog.dismiss() }
|
||||
.cancelable(true)
|
||||
.cancelOnTouchOutside(true)
|
||||
|
@ -1,7 +1,9 @@
|
||||
package exh.ui.batchadd
|
||||
|
||||
import android.content.Context
|
||||
import com.jakewharton.rxrelay.BehaviorRelay
|
||||
import com.jakewharton.rxrelay.ReplayRelay
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
|
||||
import exh.GalleryAddEvent
|
||||
@ -20,7 +22,7 @@ class BatchAddPresenter : BasePresenter<BatchAddController>() {
|
||||
var eventRelay: ReplayRelay<String>? = null
|
||||
val currentlyAddingRelay = BehaviorRelay.create(STATE_IDLE)!!
|
||||
|
||||
fun addGalleries(galleries: String) {
|
||||
fun addGalleries(context: Context, galleries: String) {
|
||||
eventRelay = ReplayRelay.create()
|
||||
val regex =
|
||||
"""[0-9]*?\.[a-z0-9]*?:""".toRegex()
|
||||
@ -53,7 +55,7 @@ class BatchAddPresenter : BasePresenter<BatchAddController>() {
|
||||
val failed = mutableListOf<String>()
|
||||
|
||||
splitGalleries.forEachIndexed { i, s ->
|
||||
val result = galleryAdder.addGallery(s, true)
|
||||
val result = galleryAdder.addGallery(context, s, true)
|
||||
if (result is GalleryAddEvent.Success) {
|
||||
succeeded.add(s)
|
||||
} else {
|
||||
@ -63,15 +65,15 @@ class BatchAddPresenter : BasePresenter<BatchAddController>() {
|
||||
eventRelay?.call(
|
||||
(
|
||||
when (result) {
|
||||
is GalleryAddEvent.Success -> "[OK]"
|
||||
is GalleryAddEvent.Fail -> "[ERROR]"
|
||||
is GalleryAddEvent.Success -> context.getString(R.string.batch_add_ok)
|
||||
is GalleryAddEvent.Fail -> context.getString(R.string.batch_add_error)
|
||||
}
|
||||
) + " " + result.logMessage
|
||||
)
|
||||
}
|
||||
|
||||
// Show report
|
||||
val summary = "\nSummary:\nAdded: ${succeeded.size} gallerie(s)\nFailed: ${failed.size} gallerie(s)"
|
||||
val summary = context.getString(R.string.batch_add_summary, succeeded.size, failed.size)
|
||||
eventRelay?.call(summary)
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
@ -180,8 +181,8 @@ class BrowserActionActivity : AppCompatActivity() {
|
||||
runOnUiThread {
|
||||
webview.evaluateJavascript(SOLVE_UI_SCRIPT_HIDE, null)
|
||||
MaterialDialog(this)
|
||||
.title(text = "Captcha solve failure")
|
||||
.message(text = "Failed to auto-solve the captcha!")
|
||||
.title(R.string.captcha_solve_failure)
|
||||
.message(R.string.captcha_solve_failure_message)
|
||||
.cancelable(true)
|
||||
.cancelOnTouchOutside(true)
|
||||
.positiveButton(android.R.string.ok)
|
||||
|
@ -61,7 +61,7 @@ class InterceptActivity : BaseActivity<EhActivityInterceptBinding>() {
|
||||
when (it) {
|
||||
is InterceptResult.Success -> {
|
||||
binding.interceptProgress.gone()
|
||||
binding.interceptStatus.text = "Launching app..."
|
||||
binding.interceptStatus.setText(R.string.launching_app)
|
||||
onBackPressed()
|
||||
startActivity(
|
||||
Intent(this, MainActivity::class.java)
|
||||
@ -72,10 +72,10 @@ class InterceptActivity : BaseActivity<EhActivityInterceptBinding>() {
|
||||
}
|
||||
is InterceptResult.Failure -> {
|
||||
binding.interceptProgress.gone()
|
||||
binding.interceptStatus.text = "Error: ${it.reason}"
|
||||
binding.interceptStatus.text = this.getString(R.string.error_with_reason, it.reason)
|
||||
MaterialDialog(this)
|
||||
.title(text = "Error")
|
||||
.message(text = "Could not open this gallery:\n\n${it.reason}")
|
||||
.title(R.string.chapter_error)
|
||||
.message(text = this.getString(R.string.could_not_open_gallery, it.reason))
|
||||
.cancelable(true)
|
||||
.cancelOnTouchOutside(true)
|
||||
.positiveButton(android.R.string.ok)
|
||||
@ -104,13 +104,13 @@ class InterceptActivity : BaseActivity<EhActivityInterceptBinding>() {
|
||||
|
||||
// Load gallery async
|
||||
thread {
|
||||
val result = galleryAdder.addGallery(gallery)
|
||||
val result = galleryAdder.addGallery(this, gallery)
|
||||
|
||||
status.onNext(
|
||||
when (result) {
|
||||
is GalleryAddEvent.Success -> result.manga.id?.let {
|
||||
InterceptResult.Success(it)
|
||||
} ?: InterceptResult.Failure("Manga ID is null!")
|
||||
} ?: InterceptResult.Failure(this.getString(R.string.manga_id_is_null))
|
||||
is GalleryAddEvent.Fail -> InterceptResult.Failure(result.logMessage)
|
||||
}
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
package exh.util
|
||||
|
||||
import android.content.Context
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
import eu.kanade.tachiyomi.source.online.UrlImportableSource
|
||||
import exh.GalleryAddEvent
|
||||
@ -13,11 +14,11 @@ private val galleryAdder by lazy {
|
||||
/**
|
||||
* A version of fetchSearchManga that supports URL importing
|
||||
*/
|
||||
fun UrlImportableSource.urlImportFetchSearchManga(query: String, fail: () -> Observable<MangasPage>) =
|
||||
fun UrlImportableSource.urlImportFetchSearchManga(context: Context, query: String, fail: () -> Observable<MangasPage>) =
|
||||
when {
|
||||
query.startsWith("http://") || query.startsWith("https://") -> {
|
||||
Observable.fromCallable {
|
||||
val res = galleryAdder.addGallery(query, false, this)
|
||||
val res = galleryAdder.addGallery(context, query, false, this)
|
||||
MangasPage(
|
||||
(
|
||||
if (res is GalleryAddEvent.Success) {
|
||||
|
@ -192,7 +192,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:contentDescription="@string/eh_merge_with_another_source"
|
||||
android:contentDescription="@string/merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
app:icon="@drawable/eh_ic_find_replace_white_24dp"
|
||||
tools:visibility="visible" />
|
||||
@ -289,7 +289,7 @@
|
||||
android:layout_marginTop="4dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="4dp"
|
||||
android:text="@string/eh_merge_with_another_source"
|
||||
android:text="@string/merge_with_another_source"
|
||||
android:visibility="gone"
|
||||
tools:visibility="visible" />
|
||||
|
||||
|
@ -194,7 +194,7 @@
|
||||
android:id="@+id/auto_webtoon_mode"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/eh_auto_webtoon_mode"
|
||||
android:text="@string/auto_webtoon_mode"
|
||||
android:textColor="?android:attr/textColorSecondary"
|
||||
app:layout_constraintTop_toBottomOf="@id/always_show_chapter_transition" />
|
||||
|
||||
|
@ -14,7 +14,7 @@
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:visibility="visible"
|
||||
android:text="@string/eh_saved_searches" />
|
||||
android:text="@string/saved_searches" />
|
||||
|
||||
<com.google.android.material.chip.ChipGroup
|
||||
android:id="@+id/saved_searches"
|
||||
|
@ -28,7 +28,7 @@
|
||||
<item
|
||||
android:id="@+id/action_sync_favorites"
|
||||
android:icon="@drawable/ic_cloud_24dp"
|
||||
android:title="@string/eh_sync_favorites"
|
||||
android:title="@string/sync_favorites"
|
||||
app:showAsAction="never"/>
|
||||
|
||||
|
||||
|
@ -1,147 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Activities and fragments labels (toolbar title) -->
|
||||
<string name="label_reorganize_by">Reorder</string>
|
||||
<string name="label_alpha_reverse">Alpha. (descending)</string>
|
||||
<string name="label_hide_title">Hide title</string>
|
||||
<string name="label_show_title">Show title</string>
|
||||
|
||||
<!-- Actions -->
|
||||
<string name="action_sort_first_checked">First checked</string>
|
||||
<string name="action_sort_drag_and_drop">Drag & Drop</string>
|
||||
<string name="action_sort_enabled">Enabled</string>
|
||||
<string name="action_skip_manga">Don\'t migrate</string>
|
||||
<string name="action_search_manually">Search manually</string>
|
||||
<string name="action_migrate_now">Migrate now</string>
|
||||
<string name="action_copy_now">Copy now</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<!-- Filter -->
|
||||
<string name="tracked">Tracked</string>
|
||||
<string name="lewd">Lewd</string>
|
||||
|
||||
<!-- Subsections -->
|
||||
<string name="pref_category_all_sources">All Sources</string>
|
||||
|
||||
<!-- Library section -->
|
||||
<string name="pref_skip_pre_migration">Skip pre-migration</string>
|
||||
<string name="pref_skip_pre_migration_summary">Use last saved pre-migration preferences
|
||||
and sources to mass migrate</string>
|
||||
|
||||
<!-- Extension section -->
|
||||
<string name="ext_redundant">Redundant</string>
|
||||
<string name="redundant_extension_message">This extension is redundant and will not be used inside this version of Tachiyomi.</string>
|
||||
|
||||
<!-- Library update service notifications -->
|
||||
<string name="notification_new_chapters_text_old">For %1$d titles</string>
|
||||
|
||||
|
||||
<!-- Migration -->
|
||||
<string name="select_sources">Select sources</string>
|
||||
<string name="select_none">Select none</string>
|
||||
<string name="source_migration">Source migration</string>
|
||||
<string name="migration">Migration</string>
|
||||
<string name="skip_pre_migration">Skip pre-migration</string>
|
||||
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
|
||||
<string name="select_a_source_to_migrate_from">Select a source to migrate from</string>
|
||||
<string name="use_intelligent_search">Search title + keywords of title</string>
|
||||
<string name="data_to_include_in_migration">Data to include in migration</string>
|
||||
<string name="search_parameter_eg">Search parameter (e.g. language:english)</string>
|
||||
<string name="include_extra_search_parameter">Include extra search parameter when searching</string>
|
||||
<string name="use_most_chapters">Use source with the most chapters (slower)</string>
|
||||
<string name="use_first_source">Use first source with alternative</string>
|
||||
<string name="skip_this_step_next_time">Skip this step next time</string>
|
||||
<string name="search_parameter">Search parameter (e.g. language:english)</string>
|
||||
<string name="to_show_again_setting_library">To show this screen again, go to Settings -> Library.</string>
|
||||
<string name="latest_">Latest: %1$s</string>
|
||||
<string name="migrating_to">migrating to</string>
|
||||
<string name="dont_migrate">Don\'t migrate</string>
|
||||
<string name="search_manually">Search manually</string>
|
||||
<string name="migrate_now">Migrate now</string>
|
||||
<string name="copy_now">Copy now</string>
|
||||
<!--<string name="select">Select</string>-->
|
||||
<!--<string name="migrate">Migrate</string>-->
|
||||
<string name="migrate_">Migrate %1$s</string>
|
||||
<string name="copy_value">Copy</string>
|
||||
<string name="match_pinned_sources">Match pinned sources</string>
|
||||
<string name="match_enabled_sources">Match enabled sources</string>
|
||||
<string name="no_chapters_found_for_migration">No chapters found, this manga cannot be used for
|
||||
migration</string>
|
||||
<string name="no_alternatives_found">No Alternatives Found</string>
|
||||
<string name="stop_migrating">Stop migrating?</string>
|
||||
<plurals name="migrate_manga">
|
||||
<item quantity="one">Migrate %1$d%2$s manga?</item>
|
||||
<item quantity="other">Migrate %1$d%2$s manga?</item>
|
||||
</plurals>
|
||||
<plurals name="copy_manga">
|
||||
<item quantity="one">Copy %1$d%2$s manga?</item>
|
||||
<item quantity="other">Copy %1$d%2$s manga?</item>
|
||||
</plurals>
|
||||
<string name="skipping_">(skipping %1$d)</string>
|
||||
<plurals name="manga_migrated">
|
||||
<item quantity="one">%d manga migrated</item>
|
||||
<item quantity="other">%d manga migrated</item>
|
||||
</plurals>
|
||||
|
||||
<!-- EXH -->
|
||||
<string name="label_login">Login</string>
|
||||
<string name="pref_category_eh">E-Hentai</string>
|
||||
<string name="pref_category_nh">nhentai</string>
|
||||
<string name="pref_category_hl">hitomi.la</string>
|
||||
<string name="eh_batch_add">Batch Add</string>
|
||||
<string name="eh_settings_category">Fork Settings</string>
|
||||
<string name="eh_sync_favorites">Sync favorites</string>
|
||||
<string name="eh_find_in_another_source">Find in another source</string>
|
||||
<string name="eh_autoscroll">Autoscroll</string>
|
||||
<string name="eh_retry_all">Retry all</string>
|
||||
<string name="eh_boost_page">Boost page</string>
|
||||
<string name="merge">Merge with current</string>
|
||||
<string name="eh_merge_with_another_source">Merge With Another</string>
|
||||
<string name="eh_autoscroll_help">Autoscroll help</string>
|
||||
<string name="eh_autoscroll_help_message">Automatically scroll to the next page in the specified interval. Interval is specified in seconds.</string>
|
||||
<string name="eh_retry_all_help">Retry all help</string>
|
||||
<string name="eh_retry_all_help_message">Re-add all failed pages to the download queue.</string>
|
||||
<string name="eh_boost_page_help">Boost page help</string>
|
||||
<string name="eh_boost_page_help_message">Normally the downloader can only download a specific amount of pages at the same time. This means you can be waiting for a page to download but the downloader will not start downloading the page until it has a free download slot. Pressing \'Boost page\' will force the downloader to begin downloading the current page, regardless of whether or not there is an available slot.</string>
|
||||
<string name="eh_force_sync_reset_title">Are you sure?</string>
|
||||
<string name="eh_force_sync_reset_message">Resetting the sync state can cause your next sync to be extremely slow.</string>
|
||||
<string name="eh_show_update_statistics_dialog">Collecting statistics…</string>
|
||||
<string name="eh_saved_searches">Saved Searches</string>
|
||||
<string name="eh_batch_add_description">Example:\n\nhttp://e-hentai.org/g/12345/1a2b3c4e\nhttp://g.e-hentai.org/g/67890/6f7g8h9i\nhttp://exhentai.org/g/13579/1a3b5c7e\nhttps://exhentai.org/g/24680/2f4g6h8i\n\nIt also supports E-H Visited exported data\n</string>
|
||||
<string name="eh_batch_add_title">Enter the galleries to add (separated by a new line):</string>
|
||||
<string name="eh_batch_add_button">Add Galleries</string>
|
||||
<string name="eh_batch_add_adding_galleries">Adding galleries…</string>
|
||||
<string name="eh_batch_add_finish">Finish</string>
|
||||
<string name="eh_auto_webtoon_mode">Auto Webtoon Mode Detection</string>
|
||||
<string name="eh_auto_webtoon_snack">Reading webtoon style</string>
|
||||
<string name="loading_gallery">Loading gallery…</string>
|
||||
<string name="watch">Watch</string>
|
||||
<string name="unwatch">Unwatch</string>
|
||||
<string name="pref_latest_position">Latest tab position</string>
|
||||
<string name="pref_latest_position_summery">Do you want the latest tab to be the first tab in browse? This will make it the default tab when opening browse, not recommended if your on data or a metered network</string>
|
||||
<string name="too_many_watched">Too many watched sources, cannot add more then 5</string>
|
||||
<string name="latest_tab_empty">You don\'t have any watched sources, go to the sources tab and long press a source to watch it</string>
|
||||
<string name="pref_latest_tab_language_code">Display language code next to name</string>
|
||||
<string name="no_source_categories">No source categories available</string>
|
||||
<string name="invalid_category_name">Invalid category name</string>
|
||||
<string name="add_tag">Add Tag</string>
|
||||
<string name="cover_reset_toast">The cover will be updated when you exit manga info edit</string>
|
||||
<string name="select_cover_image">Select cover image</string>
|
||||
<string name="failed_to_update_cover">Failed to update cover</string>
|
||||
|
||||
<!-- AZ -->
|
||||
<string name="az_recommends">See Recommendations</string>
|
||||
|
||||
<!-- Manga Type -->
|
||||
<!--<string name="manga">Manga</string>-->
|
||||
<string name="manhwa">Manhwa</string>
|
||||
<string name="manhua">Manhua</string>
|
||||
<string name="comic">Comic</string>
|
||||
<string name="webtoon">Webtoon</string>
|
||||
|
||||
<!-- SY -->
|
||||
<string name="reset_tags">Reset Tags</string>
|
||||
<string name="reset_cover">Reset Cover</string>
|
||||
|
||||
</resources>
|
341
app/src/main/res/values/strings_sy.xml
Normal file
341
app/src/main/res/values/strings_sy.xml
Normal file
@ -0,0 +1,341 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<!-- Activities and fragments labels (toolbar title) -->
|
||||
<string name="label_reorganize_by">Reorder</string>
|
||||
<string name="label_alpha_reverse">Alpha. (descending)</string>
|
||||
|
||||
<!-- Actions -->
|
||||
<string name="action_sort_first_checked">First checked</string>
|
||||
<string name="action_sort_drag_and_drop">Drag & Drop</string>
|
||||
<string name="action_sort_enabled">Enabled</string>
|
||||
<string name="action_skip_manga">Don\'t migrate</string>
|
||||
<string name="action_search_manually">Search manually</string>
|
||||
<string name="action_migrate_now">Migrate now</string>
|
||||
<string name="action_copy_now">Copy now</string>
|
||||
|
||||
<!-- Manga Type -->
|
||||
<string name="manhwa">Manhwa</string>
|
||||
<string name="manhua">Manhua</string>
|
||||
<string name="comic">Comic</string>
|
||||
<string name="webtoon">Webtoon</string>
|
||||
|
||||
<!-- Captcha -->
|
||||
<string name="captcha_solve_failure">Captcha solve failure</string>
|
||||
<string name="captcha_solve_failure_message">Failed to auto-solve the captcha!</string>
|
||||
<string name="please_login">Please log in!</string>
|
||||
|
||||
<!-- Preferences -->
|
||||
<!-- Subsections -->
|
||||
<string name="pref_category_all_sources">All Sources</string>
|
||||
<string name="pref_category_eh">E-Hentai</string>
|
||||
<string name="pref_category_nh">nhentai</string>
|
||||
<string name="pref_category_hl">hitomi.la</string>
|
||||
<string name="pref_category_fork">Fork Settings</string>
|
||||
|
||||
<!-- EH Settings -->
|
||||
<string name="ehentai_prefs_account_settings">E-Hentai Website Account Settings</string>
|
||||
<string name="enable_exhentai">Enable ExHentai</string>
|
||||
<string name="requires_login">Requires login</string>
|
||||
<string name="use_hentai_at_home">Use Hentai@Home Network</string>
|
||||
<string name="use_hentai_at_home_summary">Do you wish to load images through the Hentai@Home Network, if available? Disabling this option will reduce the amount of pages you are able to view\nOptions:\n- Any client (Recommended)\n- Default port clients only (Can be slower. Enable if behind firewall/proxy that blocks outgoing non-standard ports.)</string>
|
||||
<string name="use_hentai_at_home_option_1">Any client (Recommended)</string>
|
||||
<string name="use_hentai_at_home_option_2">Default port clients only</string>
|
||||
<string name="show_japanese_titles">Show Japanese titles in search results</string>
|
||||
<string name="show_japanese_titles_option_1">Currently showing Japanese titles in search results. Clear the chapter cache after changing this (in the Advanced section)</string>
|
||||
<string name="show_japanese_titles_option_2">Currently showing English/Romanized titles in search results. Clear the chapter cache after changing this (in the Advanced section)</string>
|
||||
<string name="use_original_images">Use original images</string>
|
||||
<string name="use_original_images_on">Currently using original images</string>
|
||||
<string name="use_original_images_off">Currently using resampled images</string>
|
||||
<string name="watched_tags">Watched Tags</string>
|
||||
<string name="watched_tags_summary">Opens a webview to your E/ExHentai watched tags page</string>
|
||||
<string name="watched_tags_exh">ExHentai Watched Tags</string>
|
||||
<string name="watched_tags_eh">E-Hentai Watched Tags</string>
|
||||
<string name="tag_filtering_threshold">Tag Filtering Threshold</string>
|
||||
<string name="tag_filtering_threshhold_error">Must be between -9999 and 0!</string>
|
||||
<string name="tag_filtering_threshhold_summary">You can soft filter tags by adding them to the "My Tags" E/ExHentai page with a negative weight. If a gallery has tags that add up to weight below this value, it is filtered from view. This threshold can be set between -9999 and 0. Currently: %s</string>
|
||||
<string name="tag_watching_threshhold">Tag Watching Threshold</string>
|
||||
<string name="tag_watching_threshhold_error">Must be between 0 and 9999!</string>
|
||||
<string name="tag_watching_threshhold_summary">Recently uploaded galleries will be included on the watched screen if it has at least one watched tag with positive weight, and the sum of weights on its watched tags add up to this value or higher. This threshold can be set between 0 and 9999. Currently: %s</string>
|
||||
<string name="language_filtering">Language Filtering</string>
|
||||
<string name="language_filtering_summary">If you wish to hide galleries in certain languages from the gallery list and searches, select them in the dialog that will popup.\nNote that matching galleries will never appear regardless of your search query.\nTldr checkmarked = exclude</string>
|
||||
<string name="frong_page_categories">Front Page Categories</string>
|
||||
<string name="fromt_page_categories_summary">What categories would you like to show by default on the front page and in searches? They can still be enabled by enabling their filters</string>
|
||||
<string name="watched_list_default">Watched List Filter Default State</string>
|
||||
<string name="watched_list_state_summary">When browsing ExHentai/E-Hentai should the watched list filter be enabled by default</string>
|
||||
<string name="eh_image_quality_summary">The quality of the downloaded images</string>
|
||||
<string name="eh_image_quality">Image quality</string>
|
||||
<string name="eh_image_quality_auto">Auto</string>
|
||||
<string name="eh_image_quality_2400">2400x</string>
|
||||
<string name="eh_image_quality_1600">1600x</string>
|
||||
<string name="eh_image_quality_1280">1280x</string>
|
||||
<string name="eh_image_quality_980">980x</string>
|
||||
<string name="eh_image_quality_780">780x</string>
|
||||
<string name="favorites_sync">Favorites sync</string>
|
||||
<string name="disable_favorites_uploading">Disable favorites uploading</string>
|
||||
<string name="disable_favorites_uploading_summary">Favorites are only downloaded from ExHentai. Any changes to favorites in the app will not be uploaded. Prevents accidental loss of favorites on ExHentai. Note that removals will still be downloaded (if you remove a favorites on ExHentai, it will be removed in the app as well).</string>
|
||||
<string name="show_favorite_sync_notes">Show favorites sync notes</string>
|
||||
<string name="show_favorite_sync_notes_summary">Show some information regarding the favorites sync feature</string>
|
||||
<string name="ignore_sync_errors">Ignore sync errors when possible</string>
|
||||
<string name="ignore_sync_errors_summary">Do not abort immediately when encountering errors during the sync process. Errors will still be displayed when the sync is complete. Can cause loss of favorites in some cases. Useful when syncing large libraries.</string>
|
||||
<string name="force_sync_state_reset">Force sync state reset</string>
|
||||
<string name="force_sync_state_reset_summary">Performs a full resynchronization on the next sync. Removals will not be synced. All favorites in the app will be re-uploaded to ExHentai and all favorites on ExHentai will be re-downloaded into the app. Useful for repairing sync after sync has been interrupted.</string>
|
||||
<string name="sync_state_reset">Sync state reset</string>
|
||||
<string name="gallery_update_checker">Gallery update checker</string>
|
||||
<string name="auto_update_restrictions">Auto update restrictions</string>
|
||||
<string name="time_between_batches">Time between update batches</string>
|
||||
<string name="time_between_batches_never">Never update galleries</string>
|
||||
<string name="time_between_batches_1_hour">1 hour</string>
|
||||
<string name="time_between_batches_2_hours">2 hours</string>
|
||||
<string name="time_between_batches_3_hours">3 hours</string>
|
||||
<string name="time_between_batches_6_hours">6 hours</string>
|
||||
<string name="time_between_batches_12_hours">12 hours</string>
|
||||
<string name="time_between_batches_24_hours">24 hours</string>
|
||||
<string name="time_between_batches_48_hours">48 hours</string>
|
||||
<string name="time_between_batches_summary_1">%1$s will currently never check galleries in your library for updates.</string>
|
||||
<string name="time_between_batches_summary_2">%1$s checks/updates galleries in batches. This means it will wait %2$d hour(s), check %3$d galleries, wait %2$d hour(s), check %3$d and so on…</string>
|
||||
<string name="show_updater_statistics">Show updater statistics</string>
|
||||
<string name="gallery_updater_statistics_collection">Collecting statistics…</string>
|
||||
<string name="gallery_updater_statistics">Gallery updater statistics</string>
|
||||
<string name="gallery_updater_stats_text">The updater last ran %1$s, and checked %2$d out of the %3$d galleries that were ready for checking.</string>
|
||||
<string name="gallery_updater_not_ran_yet">The updater has not ran yet.</string>
|
||||
<string name="gallery_updater_stats_time">\nGalleries that were checked in the last:\n- hour: %1$d\n- 6 hours: %2$d\n- 12 hours: %3$d\n- day: %4$d\n- 2 days: %5$d\n- week: %6$d\n- month: %7$d\n- year: %8$d</string>
|
||||
|
||||
<!-- EH Settings Upload Dialogs -->
|
||||
<string name="settings_profile_note">Settings profile note</string>
|
||||
<string name="settings_profile_note_message">The app will now add a new settings profile on E-Hentai and ExHentai to optimize app performance. Please ensure that you have less than three profiles on both sites.\n\nIf you have no idea what settings profiles are, then it probably doesn\'t matter, just hit \'OK\'.</string>
|
||||
<string name="eh_settings_successfully_uploaded">Settings successfully uploaded!</string>
|
||||
<string name="eh_settings_configuration_failed">Configuration failed!</string>
|
||||
<string name="eh_settings_configuration_failed_message">An error occurred during the configuration process: %1$s</string>
|
||||
<string name="eh_settings_uploading_to_server">Uploading settings to server</string>
|
||||
<string name="eh_settings_uploading_to_server_message">Please wait, this may take some time…</string>
|
||||
<string name="eh_settings_out_of_slots_error">You are out of profile slots on %1$s, please delete a profile!</string>
|
||||
|
||||
<!-- Advanced Settings -->
|
||||
<string name="developer_tools">Developer tools</string>
|
||||
<string name="toggle_hentai_features">Enable integrated hentai features</string>
|
||||
<string name="toggle_hentai_features_summary">This is a experimental feature that will disable all hentai features if toggled off</string>
|
||||
<string name="toggle_delegated_sources">Enable delegated sources</string>
|
||||
<string name="toggle_delegated_sources_summary">Apply %1$s enhancements to the following sources if they are installed: %2$s</string>
|
||||
<string name="log_level">Log level</string>
|
||||
<string name="log_level_summary">Changing this can impact app performance. Force-restart app after changing. Current value: %s</string>
|
||||
<string name="enable_source_blacklist">Enable source blacklist</string>
|
||||
<string name="enable_source_blacklist_summary">Hide extensions/sources that are incompatible with %1$s. Force-restart app after changing.</string>
|
||||
<string name="open_debug_menu">Open debug menu</string>
|
||||
<string name="open_debug_menu_summary"><![CDATA[DO NOT TOUCH THIS MENU UNLESS YOU KNOW WHAT YOU ARE DOING! <font color=\'red\'>IT CAN CORRUPT YOUR LIBRARY!</font>]]></string>
|
||||
|
||||
<!-- Log Level -->
|
||||
<string name="log_minimal">Minimal</string>
|
||||
<string name="log_extra">Extra</string>
|
||||
<string name="log_extreme">Extreme</string>
|
||||
<string name="log_minimal_desc">critical errors only</string>
|
||||
<string name="log_extra_desc">log everything</string>
|
||||
<string name="log_extreme_desc">network inspection mode</string>
|
||||
|
||||
<!-- General Settings -->
|
||||
<string name="toggle_expand_search_filters">Expand all search filters by default</string>
|
||||
<string name="auto_solve_captchas">Automatically solve captcha</string>
|
||||
<string name="auto_solve_captchas_summary">Use HIGHLY EXPERIMENTAL automatic ReCAPTCHA solver. Will be grayed out if unsupported by your device.</string>
|
||||
|
||||
<!-- Library settings -->
|
||||
<string name="pref_skip_pre_migration_summary">Use last saved pre-migration preferences and sources to mass migrate</string>
|
||||
|
||||
<!-- Other Settings -->
|
||||
<string name="high_quality_thumbnails">Use high-quality thumbnails</string>
|
||||
<string name="high_quality_thumbnails_summary">May slow down search results</string>
|
||||
|
||||
<!-- Reader Settings -->
|
||||
<string name="download_threads">Download threads</string>
|
||||
<string name="download_threads_summary">Higher values can speed up image downloading significantly, but can also trigger bans. Recommended value is 2 or 3. Current value is: %s</string>
|
||||
<string name="aggressively_load_pages">Aggressively load pages</string>
|
||||
<string name="aggressively_load_pages_summary">Slowly download the entire gallery while reading instead of just loading the pages you are viewing.</string>
|
||||
<string name="skip_queue_on_retry">Skip queue on retry</string>
|
||||
<string name="skip_queue_on_retry_summary">Normally, pressing the retry button on a failed download will wait until the downloader has finished downloading the last page before beginning to re-download the failed page. Enabling this will force the downloader to begin re-downloading the failed page as soon as you press the retry button.</string>
|
||||
<string name="reader_preload_amount">Reader Preload amount</string>
|
||||
<string name="reader_preload_amount_1_page">1 Page</string>
|
||||
<string name="reader_preload_amount_2_pages">2 Pages</string>
|
||||
<string name="reader_preload_amount_3_pages">3 Pages</string>
|
||||
<string name="reader_preload_amount_4_pages">4 Pages</string>
|
||||
<string name="reader_preload_amount_6_pages">6 Pages</string>
|
||||
<string name="reader_preload_amount_8_pages">8 Pages</string>
|
||||
<string name="reader_preload_amount_10_pages">10 Pages</string>
|
||||
<string name="reader_preload_amount_12_pages">12 Pages</string>
|
||||
<string name="reader_preload_amount_14_pages">14 Pages</string>
|
||||
<string name="reader_preload_amount_16_pages">16 Pages</string>
|
||||
<string name="reader_preload_amount_summary">The amount of pages to preload when reading. Higher values will result in a smoother reading experience, at the cost of higher cache usage, it is recommended to increase the amount of cache you allocate when using larger values</string>
|
||||
<string name="reader_cache_size">Reader cache size</string>
|
||||
<string name="reader_cache_size_summary">The amount of images to save on device while reading. Higher values will result in a smoother reading experience, at the cost of higher disk space usage</string>
|
||||
<string name="preserve_reading_position">Preserve reading position on read manga</string>
|
||||
<string name="auto_webtoon_mode">Auto Webtoon Mode</string>
|
||||
<string name="auto_webtoon_mode_summary">Use auto webtoon mode for manga that are detected to likely use the long strip format</string>
|
||||
|
||||
<!-- Reader -->
|
||||
<!-- Reader Actions -->
|
||||
<string name="eh_autoscroll">Autoscroll</string>
|
||||
<string name="eh_retry_all">Retry all</string>
|
||||
<string name="eh_boost_page">Boost page</string>
|
||||
<string name="eh_autoscroll_help">Autoscroll help</string>
|
||||
<string name="eh_autoscroll_help_message">Automatically scroll to the next page in the specified interval. Interval is specified in seconds.</string>
|
||||
<string name="eh_retry_all_help">Retry all help</string>
|
||||
<string name="eh_retry_all_help_message">Re-add all failed pages to the download queue.</string>
|
||||
<string name="eh_boost_page_help">Boost page help</string>
|
||||
<string name="eh_boost_page_help_message">Normally the downloader can only download a specific amount of pages at the same time. This means you can be waiting for a page to download but the downloader will not start downloading the page until it has a free download slot. Pressing \'Boost page\' will force the downloader to begin downloading the current page, regardless of whether or not there is an available slot.</string>
|
||||
|
||||
<!-- Auto Webtoon Mode -->
|
||||
<string name="eh_auto_webtoon_snack">Reading webtoon style</string>
|
||||
|
||||
<!-- Manga Page -->
|
||||
<!-- Manga Info -->
|
||||
<string name="az_recommends">See Recommendations</string>
|
||||
<string name="merge_with_another_source">Merge With Another</string>
|
||||
|
||||
<!-- Manga Info Edit -->
|
||||
<string name="reset_tags">Reset Tags</string>
|
||||
<string name="reset_cover">Reset Cover</string>
|
||||
<string name="add_tag">Add Tag</string>
|
||||
<string name="cover_reset_toast">The cover will be updated when you exit manga info edit</string>
|
||||
|
||||
<!-- Browse -->
|
||||
<!-- Saved Searches -->
|
||||
<string name="saved_searches">Saved Searches</string>
|
||||
<string name="save_search">Save current search query?</string>
|
||||
<string name="save_search_hint">My search name</string>
|
||||
<string name="save_search_failed_to_load">Failed to load saved searches!</string>
|
||||
<string name="save_search_failed_to_load_message">An error occurred while loading your saved searches.</string>
|
||||
<string name="save_search_failed_to_delete">Failed to delete saved search!</string>
|
||||
<string name="save_search_failed_to_delete_message">An error occurred while deleting the search.</string>
|
||||
<string name="save_search_delete">Delete saved search query?</string>
|
||||
<string name="save_search_delete_message">Are you sure you wish to delete your saved search query: \'%1$s\'?</string>
|
||||
|
||||
<!-- Source Categories -->
|
||||
<string name="no_source_categories">No source categories available</string>
|
||||
<string name="invalid_category_name">Invalid category name</string>
|
||||
|
||||
<!-- Latest Tab -->
|
||||
<string name="watch">Watch</string>
|
||||
<string name="unwatch">Unwatch</string>
|
||||
<string name="too_many_watched">Too many watched sources, cannot add more then 5</string>
|
||||
<string name="latest_tab_empty">You don\'t have any watched sources, go to the sources tab and long press a source to watch it</string>
|
||||
<string name="pref_latest_tab_language_code">Display language code next to name</string>
|
||||
<string name="pref_latest_position">Latest tab position</string>
|
||||
<string name="pref_latest_position_summery">Do you want the latest tab to be the first tab in browse? This will make it the default tab when opening browse, not recommended if your on data or a metered network</string>
|
||||
|
||||
<!-- Extension section -->
|
||||
<string name="ext_redundant">Redundant</string>
|
||||
<string name="redundant_extension_message">This extension is redundant and will not be used inside this version of Tachiyomi.</string>
|
||||
|
||||
<!-- Migration -->
|
||||
<string name="select_sources">Select sources</string>
|
||||
<string name="select_none">Select none</string>
|
||||
<string name="source_migration">Source migration</string>
|
||||
<string name="migration">Migration</string>
|
||||
<string name="skip_pre_migration">Skip pre-migration</string>
|
||||
<string name="pre_migration_skip_toast">To show this screen again, go to Settings -> Library.</string>
|
||||
<string name="select_a_source_to_migrate_from">Select a source to migrate from</string>
|
||||
<string name="use_intelligent_search">Search title + keywords of title</string>
|
||||
<string name="data_to_include_in_migration">Data to include in migration</string>
|
||||
<string name="include_extra_search_parameter">Include extra search parameter when searching</string>
|
||||
<string name="use_most_chapters">Use source with the most chapters (slower)</string>
|
||||
<string name="use_first_source">Use first source with alternative</string>
|
||||
<string name="skip_this_step_next_time">Skip this step next time</string>
|
||||
<string name="search_parameter">Search parameter (e.g. language:english)</string>
|
||||
<string name="latest_">Latest: %1$s</string>
|
||||
<string name="migrating_to">migrating to</string>
|
||||
<string name="match_pinned_sources">Match pinned sources</string>
|
||||
<string name="match_enabled_sources">Match enabled sources</string>
|
||||
<string name="no_chapters_found_for_migration">No chapters found, this manga cannot be used for
|
||||
migration</string>
|
||||
<string name="no_alternatives_found">No Alternatives Found</string>
|
||||
<string name="stop_migrating">Stop migrating?</string>
|
||||
<plurals name="migrate_manga">
|
||||
<item quantity="one">Migrate %1$d%2$s manga?</item>
|
||||
<item quantity="other">Migrate %1$d%2$s manga?</item>
|
||||
</plurals>
|
||||
<plurals name="copy_manga">
|
||||
<item quantity="one">Copy %1$d%2$s manga?</item>
|
||||
<item quantity="other">Copy %1$d%2$s manga?</item>
|
||||
</plurals>
|
||||
<string name="skipping_">(skipping %1$d)</string>
|
||||
<plurals name="manga_migrated">
|
||||
<item quantity="one">%d manga migrated</item>
|
||||
<item quantity="other">%d manga migrated</item>
|
||||
</plurals>
|
||||
|
||||
<!-- Library -->
|
||||
<!-- Library Sheet -->
|
||||
<string name="tracked">Tracked</string>
|
||||
<string name="lewd">Lewd</string>
|
||||
|
||||
<!-- Favorites Sync -->
|
||||
<string name="sync_favorites">Sync favorites</string>
|
||||
<string name="favorites_sync_error">Favorites sync error</string>
|
||||
<string name="show_gallery">Show Gallery</string>
|
||||
<string name="favorites_sync_bad_library_state">%1$s Sync will not start until the gallery is in only one category.</string>
|
||||
<string name="favorites_syncing">Favorites syncing</string>
|
||||
<string name="favorites_sync_error_string">An error occurred during the sync process: %1$s</string>
|
||||
<string name="favorites_sync_done_errors">Favorites sync complete with errors</string>
|
||||
<string name="favorites_sync_done_errors_message">Errors occurred during the sync process that were ignored:\n%1$s</string>
|
||||
<string name="favorites_sync_verifying_library">Verifying local library</string>
|
||||
<string name="favorites_sync_manga_multiple_categories_error">Manga %1$d is in multiple categories!</string>
|
||||
<string name="favorites_sync_downloading">Downloading favorites from remote server</string>
|
||||
<string name="favorites_sync_failed_to_featch">Failed to fetch favorites from remote server!</string>
|
||||
<string name="favorites_sync_could_not_fetch">Could not fetch favorites!</string>
|
||||
<string name="favorites_sync_calculating_remote_changes">Calculating remote changes</string>
|
||||
<string name="favorites_sync_calculating_local_changes">Calculating local changes</string>
|
||||
<string name="favorites_sync_syncing_category_names">Updating category names</string>
|
||||
<string name="favorites_sync_cleaning_up">Cleaning up</string>
|
||||
<string name="favorites_sync_complete">Sync complete!</string>
|
||||
<string name="favorites_sync_ignoring_exception">Ignoring exception!</string>
|
||||
<string name="favorites_sync_sync_error">Sync error!</string>
|
||||
<string name="favorites_sync_unknown_error">Unknown error: %1$s</string>
|
||||
<string name="favorites_sync_network_error">Sync network error!</string>
|
||||
<string name="favorites_sync_removing_galleries">Removing %1$d galleries from remote server</string>
|
||||
<string name="favorites_sync_unable_to_delete">Unable to delete galleries from the remote servers!</string>
|
||||
<string name="favorites_sync_adding_to_remote">Adding gallery %1$d of %2$d to remote server</string>
|
||||
<string name="favorites_sync_remove_from_local">Removing gallery %1$d of %2$d from local library</string>
|
||||
<string name="favorites_sync_add_to_local">Adding gallery %1$d of %2$d to local library</string>
|
||||
<string name="favorites_sync_remote_not_exist">Remote gallery does not exist, skipping: %1$s!</string>
|
||||
<string name="favorites_sync_failed_to_add_to_local">Failed to add gallery to local database: </string>
|
||||
<string name="favorites_sync_failed_to_add_to_local_error">\'%1$s\' %2$s</string>
|
||||
<string name="favorites_sync_failed_to_add_to_local_unknown_type">\'%1$s\' (%2$s) is not a valid gallery!</string>
|
||||
<string name="favorites_sync_waiting_for_start">Waiting for sync to start</string>
|
||||
<string name="favorites_sync_manga_in_multiple_categories">The gallery: %1$s is in more than one category (%2$s)!</string>
|
||||
<string name="favorites_sync_initializing">Initializing sync</string>
|
||||
<string name="favorites_sync_processing_throttle">%1$s\n\nSync is currently throttling (to avoid being banned from ExHentai) and may take a long time to complete.</string>
|
||||
<string name="favorites_sync_notes">IMPORTANT FAVORITES SYNC NOTES</string>
|
||||
<string name="favorites_sync_notes_message"><![CDATA[1. Changes to category names in the app are <b>NOT</b> synced! Please <i>change the category names on ExHentai instead</i>. The category names will be copied from the ExHentai servers every sync.<br><br>2. The favorite categories on ExHentai correspond to the <b>first 10 categories in the app</b> (excluding the \'Default\' category). <i>Galleries in other categories will <b>NOT</b> be synced!</i><br><br>3. <font color=\'red\'><b>ENSURE YOU HAVE A STABLE INTERNET CONNECTION WHEN SYNC IS IN PROGRESS!</b></font> If the internet disconnects while the app is syncing, your favorites may be left in a <i>partially-synced state</i>.<br><br>4. Keep the app open while favorites are syncing. Android will close apps that are in the background sometimes and that could be bad if it happens while the app is syncing.<br><br>5. <b>Do NOT put favorites in multiple categories</b> (the app supports this). This can confuse the sync algorithm as ExHentai only allows each favorite to be in one category.<br><br>This dialog will only popup once. You can read these notes again by going to \'Settings > E-Hentai > Show favorites sync notes\'.]]></string>
|
||||
<string name="favorites_sync_reset">Are you sure?</string>
|
||||
<string name="favorites_sync_reset_message">Resetting the sync state can cause your next sync to be extremely slow.</string>
|
||||
|
||||
<!-- Gallery Adder -->
|
||||
<!-- Batch Add -->
|
||||
<string name="eh_batch_add">Batch Add</string>
|
||||
<string name="eh_batch_add_description">Example:\n\nhttp://e-hentai.org/g/12345/1a2b3c4e\nhttp://g.e-hentai.org/g/67890/6f7g8h9i\nhttp://exhentai.org/g/13579/1a3b5c7e\nhttps://exhentai.org/g/24680/2f4g6h8i\n\nIt also supports E-H Visited exported data\n</string>
|
||||
<string name="eh_batch_add_title">Enter the galleries to add (separated by a new line):</string>
|
||||
<string name="eh_batch_add_button">Add Galleries</string>
|
||||
<string name="eh_batch_add_adding_galleries">Adding galleries…</string>
|
||||
<string name="eh_batch_add_finish">Finish</string>
|
||||
<string name="batch_add_no_valid_galleries">No galleries to add!</string>
|
||||
<string name="batch_add_no_valid_galleries_message">You must specify at least one gallery to add!</string>
|
||||
<string name="batch_add">Batch add</string>
|
||||
<string name="batch_add_ok">[OK]</string>
|
||||
<string name="batch_add_error">[ERROR]</string>
|
||||
<string name="batch_add_summary">\nSummary:\nAdded: %1$d gallerie(s)\nFailed: %2$d gallerie(s)</string>
|
||||
<string name="batch_add_success_log_message">Added gallery: %1$s</string>
|
||||
<string name="batch_add_unknown_type_log_message">Unknown gallery type for gallery: %1$s</string>
|
||||
<string name="batch_add_not_exist_log_message">Gallery does not exist: %1$s</string>
|
||||
<string name="gallery_adder_importing_gallery">Importing gallery (url: %1$s, fav: %2$s, forceSource: %3$s)…</string>
|
||||
<string name="gallery_adder_source_uri_must_match">Source URI match check error!</string>
|
||||
<string name="gallery_adder_uri_map_to_manga_error">Source URI map-to-manga error!</string>
|
||||
<string name="gallery_adder_uri_clean_error">Source URI clean error!</string>
|
||||
<string name="gallery_adder_chapter_fetch_error">Failed to update chapters for gallery: %1$s!</string>
|
||||
<string name="gallery_adder_could_not_add_gallery">Could not add gallery (url: %1$s)!</string>
|
||||
|
||||
<!-- Intercept Activity -->
|
||||
<string name="launching_app">Launching app…</string>
|
||||
<string name="error_with_reason">Error: %1$s</string>
|
||||
<string name="could_not_open_gallery">Could not open this gallery:\n\n%1$s</string>
|
||||
<string name="manga_id_is_null">Manga ID is null!</string>
|
||||
<string name="loading_gallery">Loading gallery…</string>
|
||||
|
||||
</resources>
|
Loading…
x
Reference in New Issue
Block a user