Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
70082090a1 | ||
|
|
dbc1a32496 | ||
|
|
e8c9ee5dd0 | ||
|
|
5c3657736b | ||
|
|
5191408d06 | ||
|
|
347ce6854d | ||
|
|
f86dec9b2e | ||
|
|
c74b128b1a | ||
|
|
8ee28a4b4f | ||
|
|
3b07b6997d | ||
|
|
f59023ed03 | ||
|
|
3fc13e61c3 | ||
|
|
ae22f448a8 | ||
|
|
450c15d51e | ||
|
|
d9e5bb4399 | ||
|
|
369904f659 | ||
|
|
96302b2344 | ||
|
|
eeffb12e3b | ||
|
|
57c12f7df0 |
No files matched your search
@@ -1,5 +1,18 @@
|
||||
# 变更日志
|
||||
|
||||
## 未发布
|
||||
|
||||
### 重大变更
|
||||
|
||||
* 由于 Apache HttpClient 5 在 Android 10 以下无法使用,后备 HTTP 引擎恢复为 OkHttp [#514](https://github.com/FooIbar/EhViewer/issues/514)
|
||||
|
||||
### Bug 修复
|
||||
|
||||
* 修复获取 pToken 失败导致无限加载 [#508](https://github.com/FooIbar/EhViewer/issues/508)
|
||||
* 修复阅读页快速滑动滑块导致下载延时过多累计 [#512](https://github.com/FooIbar/EhViewer/issues/512)
|
||||
* 修复 Android 9 以下的设备上无法退出搜索栏 [#513](https://github.com/FooIbar/EhViewer/issues/513)
|
||||
|
||||
|
||||
## 1.10.0
|
||||
|
||||
### 重大变更
|
||||
|
||||
@@ -75,7 +75,7 @@ and [Dynamic Color](https://m3.material.io/styles/color/dynamic-color/overview)
|
||||
|
||||
\* Archives and GIFs are not supported
|
||||
|
||||
** Fall back to Apache5 on devices that don't support [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine)
|
||||
** Fall back to OkHttp on devices that don't support [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine)
|
||||
|
||||
<a href="https://github.com/FooIbar/EhViewer/releases">
|
||||
<img alt="Get it on GitHub" src="https://github.com/Ehviewer-Overhauled/Art/blob/master/get-it-on-github.svg" width="200px"/>
|
||||
@@ -95,6 +95,7 @@ Here is the libraries
|
||||
- [Kotlin & KotlinX](https://kotlinlang.org/)
|
||||
- [MDC-Android](https://github.com/material-components/material-components-android)
|
||||
- [Material Icons](https://github.com/google/material-design-icons)
|
||||
- [OkHttp](https://square.github.io/okhttp/)
|
||||
- [Ktor](https://ktor.io/)
|
||||
- [Coil](https://coil-kt.github.io/coil/)
|
||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||
|
||||
@@ -64,8 +64,8 @@ android {
|
||||
applicationId = "moe.tarsin.ehviewer"
|
||||
minSdk = 28
|
||||
targetSdk = 34
|
||||
versionCode = 180047
|
||||
versionName = "1.10.0"
|
||||
versionCode = 180048
|
||||
versionName = "1.10.1"
|
||||
resourceConfigurations.addAll(
|
||||
listOf(
|
||||
"zh",
|
||||
@@ -235,6 +235,10 @@ dependencies {
|
||||
|
||||
implementation(libs.bundles.splitties)
|
||||
|
||||
// https://square.github.io/okhttp/changelogs/changelog/
|
||||
implementation(platform(libs.okhttp.bom))
|
||||
implementation(libs.bundles.okhttp)
|
||||
|
||||
implementation(libs.okio.jvm)
|
||||
|
||||
implementation(libs.diff)
|
||||
|
||||
Vendored
-8
@@ -14,14 +14,6 @@
|
||||
# Ktor logger
|
||||
-dontwarn org.slf4j.impl.StaticLoggerBinder
|
||||
|
||||
# Apache5 Http Client
|
||||
-dontwarn org.ietf.jgss.GSSContext
|
||||
-dontwarn org.ietf.jgss.GSSCredential
|
||||
-dontwarn org.ietf.jgss.GSSException
|
||||
-dontwarn org.ietf.jgss.GSSManager
|
||||
-dontwarn org.ietf.jgss.GSSName
|
||||
-dontwarn org.ietf.jgss.Oid
|
||||
|
||||
-dontwarn org.conscrypt.Conscrypt
|
||||
|
||||
-allowaccessmodification
|
||||
|
||||
@@ -139,7 +139,6 @@
|
||||
android:launchMode="singleTask"
|
||||
android:taskAffinity=""
|
||||
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
|
||||
<activity android:name=".ui.WebViewActivity" />
|
||||
|
||||
<service
|
||||
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
|
||||
|
||||
@@ -51,15 +51,22 @@ import com.hippo.ehviewer.util.FavouriteStatusRouter
|
||||
import com.hippo.ehviewer.util.FileUtils
|
||||
import com.hippo.ehviewer.util.ReadableTime
|
||||
import com.hippo.ehviewer.util.isAtLeastP
|
||||
import com.hippo.ehviewer.util.isAtLeastQ
|
||||
import com.hippo.ehviewer.util.isAtLeastS
|
||||
import com.hippo.ehviewer.util.isCronetAvailable
|
||||
import eu.kanade.tachiyomi.network.interceptor.UncaughtExceptionInterceptor
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
import eu.kanade.tachiyomi.util.lang.withUIContext
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.apache5.Apache5
|
||||
import io.ktor.client.engine.okhttp.OkHttp
|
||||
import io.ktor.client.plugins.cookies.HttpCookies
|
||||
import java.io.File
|
||||
import kotlinx.coroutines.ensureActive
|
||||
import kotlinx.coroutines.launch
|
||||
import moe.tarsin.coroutines.runSuspendCatching
|
||||
import okhttp3.AsyncDns
|
||||
import okhttp3.android.AndroidAsyncDns
|
||||
import okio.Path.Companion.toOkioPath
|
||||
import splitties.arch.room.roomDb
|
||||
import splitties.init.appCtx
|
||||
@@ -105,6 +112,22 @@ class EhApplication : Application(), SingletonImageLoader.Factory {
|
||||
launchIO {
|
||||
DownloadManager.isIdle
|
||||
}
|
||||
launchIO {
|
||||
runSuspendCatching {
|
||||
val files = mutableListOf<File>()
|
||||
AppConfig.externalCrashDir?.listFiles()?.let { files.addAll(it) }
|
||||
AppConfig.externalParseErrorDir?.listFiles()?.let { files.addAll(it) }
|
||||
files.sortByDescending { it.lastModified() }
|
||||
files.forEachIndexed { index, file ->
|
||||
ensureActive()
|
||||
if (index > 9) {
|
||||
file.delete()
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
it.printStackTrace()
|
||||
}
|
||||
}
|
||||
launchIO {
|
||||
cleanupDownload()
|
||||
}
|
||||
@@ -178,7 +201,15 @@ class EhApplication : Application(), SingletonImageLoader.Factory {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
HttpClient(Apache5) {
|
||||
HttpClient(OkHttp) {
|
||||
engine {
|
||||
config {
|
||||
if (isAtLeastQ) {
|
||||
dns(AsyncDns.toDns(AndroidAsyncDns.IPv4, AndroidAsyncDns.IPv6))
|
||||
}
|
||||
addInterceptor(UncaughtExceptionInterceptor())
|
||||
}
|
||||
}
|
||||
install(HttpCookies) {
|
||||
storage = EhCookieStore
|
||||
}
|
||||
|
||||
@@ -65,16 +65,18 @@ object EhCookieStore : CookiesStorage {
|
||||
override fun close() = Unit
|
||||
|
||||
fun load(url: Url): List<Cookie> {
|
||||
val cookies = manager.getCookie(url.toString()) ?: return emptyList()
|
||||
val cookies = manager.getCookie(url.toString())
|
||||
val checkTips = EhUrl.DOMAIN_E in url.host
|
||||
return parseClientCookiesHeader(cookies)
|
||||
.map { Cookie(it.key, it.value, maxAge = Int.MAX_VALUE) }
|
||||
.filterTo(mutableListOf()) { it.name != KEY_UTMP_NAME }.apply {
|
||||
if (checkTips) {
|
||||
removeAll { it.name == KEY_CONTENT_WARNING }
|
||||
add(sTipsCookie)
|
||||
return cookies?.let {
|
||||
parseClientCookiesHeader(cookies)
|
||||
.map { Cookie(it.key, it.value, maxAge = Int.MAX_VALUE) }
|
||||
.filterTo(mutableListOf()) { it.name != KEY_UTMP_NAME }.apply {
|
||||
if (checkTips) {
|
||||
removeAll { it.name == KEY_CONTENT_WARNING }
|
||||
add(sTipsCookie)
|
||||
}
|
||||
}
|
||||
}
|
||||
} ?: if (checkTips) listOf(sTipsCookie) else emptyList()
|
||||
}
|
||||
|
||||
override suspend fun get(requestUrl: Url) = load(requestUrl)
|
||||
|
||||
@@ -52,12 +52,10 @@ import com.hippo.ehviewer.dailycheck.showEventNotification
|
||||
import com.hippo.ehviewer.util.AppConfig
|
||||
import com.hippo.ehviewer.util.ReadableTime
|
||||
import com.hippo.ehviewer.util.StatusCodeException
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.request.forms.append
|
||||
import io.ktor.client.statement.HttpStatement
|
||||
import io.ktor.client.statement.bodyAsChannel
|
||||
import io.ktor.client.statement.bodyAsText
|
||||
import io.ktor.client.statement.request
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.utils.io.core.writeFully
|
||||
import io.ktor.utils.io.pool.DirectByteBufferPool
|
||||
@@ -79,8 +77,6 @@ import moe.tarsin.coroutines.runSuspendCatching
|
||||
import org.jsoup.Jsoup
|
||||
import splitties.init.appCtx
|
||||
|
||||
const val TAG = "EhEngine"
|
||||
|
||||
// https://ehwiki.org/wiki/API#Basics
|
||||
private const val MAX_REQUEST_SIZE = 25
|
||||
private const val MAX_SEQUENTIAL_REQUESTS = 5
|
||||
@@ -145,7 +141,6 @@ fun rethrowExactly(code: Int, body: Either<String, ByteBuffer>, e: Throwable): N
|
||||
val httpContentPool = DirectByteBufferPool(8, 0x80000)
|
||||
|
||||
suspend inline fun <T> HttpStatement.fetchUsingAsText(crossinline block: suspend String.() -> T) = execute { response ->
|
||||
logcat(tag = TAG) { response.request.url.toString() }
|
||||
val body = response.bodyAsText()
|
||||
runSuspendCatching {
|
||||
block(body)
|
||||
@@ -155,7 +150,6 @@ suspend inline fun <T> HttpStatement.fetchUsingAsText(crossinline block: suspend
|
||||
}
|
||||
|
||||
suspend inline fun <T> HttpStatement.fetchUsingAsByteBuffer(crossinline block: suspend ByteBuffer.() -> T) = execute { response ->
|
||||
logcat(tag = TAG) { response.request.url.toString() }
|
||||
httpContentPool.useInstance { buffer ->
|
||||
with(response.bodyAsChannel()) { while (!isClosedForRead) readAvailable(buffer) }
|
||||
buffer.flip()
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.hippo.ehviewer.client
|
||||
import com.hippo.ehviewer.EhApplication.Companion.ktorClient
|
||||
import com.hippo.ehviewer.EhApplication.Companion.noRedirectKtorClient
|
||||
import com.hippo.ehviewer.Settings
|
||||
import eu.kanade.tachiyomi.util.system.logcat
|
||||
import io.ktor.client.request.HttpRequestBuilder
|
||||
import io.ktor.client.request.forms.FormBuilder
|
||||
import io.ktor.client.request.forms.FormDataContent
|
||||
@@ -67,11 +68,12 @@ suspend inline fun ehRequest(
|
||||
url: String,
|
||||
referer: String? = null,
|
||||
origin: String? = null,
|
||||
verbose: Boolean = true,
|
||||
builder: HttpRequestBuilder.() -> Unit = {},
|
||||
) = ktorClient.prepareRequest(url) {
|
||||
applyEhConfig(referer, origin)
|
||||
apply(builder)
|
||||
}
|
||||
}.also { if (verbose) logcat("EhRequest") { url } }
|
||||
|
||||
suspend inline fun noRedirectEhRequest(
|
||||
url: String,
|
||||
@@ -81,7 +83,7 @@ suspend inline fun noRedirectEhRequest(
|
||||
) = noRedirectKtorClient.prepareRequest(url) {
|
||||
applyEhConfig(referer, origin)
|
||||
apply(builder)
|
||||
}
|
||||
}.also { logcat("EhRequest") { url } }
|
||||
|
||||
inline fun HttpRequestBuilder.formBody(builder: ParametersBuilder.() -> Unit) {
|
||||
method = HttpMethod.Post
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package com.hippo.ehviewer.client.exception
|
||||
|
||||
import com.hippo.ehviewer.R
|
||||
|
||||
class CloudflareBypassException : EhException(R.string.cloudflare_bypass_failed)
|
||||
@@ -25,7 +25,7 @@ class KtorHttpUriFetcher(private val data: String, private val options: Options,
|
||||
val diskCacheKey = options.diskCacheKey ?: data
|
||||
val diskCache = requireNotNull(imageLoader.diskCache)
|
||||
val snapshot = diskCache.openSnapshot(diskCacheKey) ?: run {
|
||||
val success = ehRequest(data).execute {
|
||||
val success = ehRequest(data, verbose = false).execute {
|
||||
diskCache.suspendEdit(diskCacheKey) {
|
||||
it.bodyAsChannel().copyTo(data.toFile())
|
||||
}
|
||||
|
||||
@@ -384,16 +384,16 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
galleryInfo.gid,
|
||||
galleryInfo.token!!,
|
||||
)
|
||||
return try {
|
||||
return runSuspendCatching {
|
||||
ehRequest(url, referer).fetchUsingAsText {
|
||||
GalleryMultiPageViewerPTokenParser.parse(this).forEachIndexed { index, s ->
|
||||
spiderInfo.pTokenMap[index] = s
|
||||
}
|
||||
spiderInfo.pTokenMap[index]
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
ExceptionUtils.throwIfFatal(e)
|
||||
return null
|
||||
}.getOrElse {
|
||||
it.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -416,13 +416,13 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
previewIndex,
|
||||
false,
|
||||
)
|
||||
return try {
|
||||
return runSuspendCatching {
|
||||
ehRequest(url, referer).fetchUsingAsText {
|
||||
readPreviews(this, previewIndex, spiderInfo)
|
||||
spiderInfo.pTokenMap[index]
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
ExceptionUtils.throwIfFatal(e)
|
||||
}.getOrElse {
|
||||
it.printStackTrace()
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -522,7 +522,7 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
private val mDownloadDelay = Settings.downloadDelay.milliseconds
|
||||
private val downloadTimeout = Settings.downloadTimeout.seconds
|
||||
private val delayLock = Mutex()
|
||||
private var delayedTime = TimeSource.Monotonic.markNow()
|
||||
private var lastRequestTime = TimeSource.Monotonic.markNow()
|
||||
private var isDownloadMode = false
|
||||
|
||||
fun cancelDecode(index: Int) {
|
||||
@@ -556,7 +556,7 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
val state = mPageStateArray[index]
|
||||
if (!force && state == STATE_FINISHED) return
|
||||
val currentJob = mFetcherJobMap[index]
|
||||
if (force) currentJob?.cancel()
|
||||
if (force) currentJob?.cancel(CancellationException(FORCE_RETRY))
|
||||
if (currentJob?.isActive != true) {
|
||||
mFetcherJobMap[index] = launch {
|
||||
runCatching {
|
||||
@@ -566,7 +566,9 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
}.onFailure {
|
||||
if (it is CancellationException) {
|
||||
Log.d(WORKER_DEBUG_TAG, "Download image $index cancelled")
|
||||
updatePageState(index, STATE_FAILED, "Cancelled")
|
||||
if (it.message != FORCE_RETRY) {
|
||||
updatePageState(index, STATE_FAILED, "Cancelled")
|
||||
}
|
||||
throw it
|
||||
}
|
||||
updatePageState(index, STATE_FAILED, ExceptionUtils.getReadableString(it))
|
||||
@@ -603,28 +605,23 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
}
|
||||
}
|
||||
val previousPToken: String?
|
||||
val pToken: String
|
||||
val pToken: String?
|
||||
|
||||
pTokenLock.withLock {
|
||||
pToken = getPToken(index) ?: return updatePageState(
|
||||
index,
|
||||
STATE_FAILED,
|
||||
PTOKEN_FAILED_MESSAGE,
|
||||
).also {
|
||||
// Non-local return will not release the lock
|
||||
// https://github.com/Kotlin/kotlinx.coroutines/issues/3985
|
||||
pToken = getPToken(index)
|
||||
if (pToken == null) {
|
||||
updatePageState(index, STATE_FAILED, PTOKEN_FAILED_MESSAGE)
|
||||
mSpiderInfo.pTokenMap[index] = TOKEN_FAILED
|
||||
}
|
||||
previousPToken = getPToken(index - 1)
|
||||
}
|
||||
pToken ?: return
|
||||
|
||||
delayLock.withLock {
|
||||
val new = delayedTime + mDownloadDelay
|
||||
val duration = new.elapsedNow()
|
||||
if (duration.isNegative()) {
|
||||
delayedTime = new
|
||||
delay(-duration)
|
||||
} else {
|
||||
delayedTime = TimeSource.Monotonic.markNow()
|
||||
}
|
||||
delay(mDownloadDelay - lastRequestTime.elapsedNow())
|
||||
lastRequestTime = TimeSource.Monotonic.markNow()
|
||||
}
|
||||
|
||||
var skipHathKey: String? = null
|
||||
@@ -694,7 +691,6 @@ class SpiderQueen private constructor(val galleryInfo: GalleryInfo) : CoroutineS
|
||||
referer = null
|
||||
}
|
||||
checkNotNull(targetImageUrl)
|
||||
Log.d(WORKER_DEBUG_TAG, targetImageUrl)
|
||||
|
||||
repeat(3) { times ->
|
||||
runCatching {
|
||||
@@ -782,6 +778,7 @@ private val PTOKEN_FAILED_MESSAGE = appCtx.getString(R.string.error_get_ptoken_e
|
||||
private val ERROR_TIMEOUT = appCtx.getString(R.string.error_timeout)
|
||||
private val DECODE_ERROR = appCtx.getString(R.string.error_decoding_failed)
|
||||
private val URL_509_PATTERN = Regex("\\.org/.+/509s?\\.gif")
|
||||
private const val FORCE_RETRY = "Force retry"
|
||||
private const val WORKER_DEBUG_TAG = "SpiderQueenWorker"
|
||||
|
||||
private fun check509(url: String) {
|
||||
|
||||
@@ -275,7 +275,7 @@ class MainActivity : EhActivity() {
|
||||
LaunchedEffect(Unit) {
|
||||
if (connectivityManager.isActiveNetworkMetered) {
|
||||
if (isAtLeastQ) {
|
||||
val ret = snackbarState.showSnackbar(warning, settings)
|
||||
val ret = snackbarState.showSnackbar(warning, settings, true)
|
||||
if (ret == SnackbarResult.ActionPerformed) {
|
||||
val panelIntent = Intent(android.provider.Settings.Panel.ACTION_INTERNET_CONNECTIVITY)
|
||||
startActivity(panelIntent)
|
||||
@@ -304,7 +304,7 @@ class MainActivity : EhActivity() {
|
||||
launch = { navController.navigate(ProgressScreenDestination(result2.gid, result2.pToken, result2.page)) }
|
||||
}
|
||||
launch?.let {
|
||||
val ret = snackbarState.showSnackbar(snackMessage, snackAction)
|
||||
val ret = snackbarState.showSnackbar(snackMessage, snackAction, true)
|
||||
if (ret == SnackbarResult.ActionPerformed) it()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.hippo.ehviewer.ui
|
||||
|
||||
import android.os.Bundle
|
||||
import com.hippo.ehviewer.ui.webview.WebViewScreen
|
||||
|
||||
class WebViewActivity : EhActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
val url = intent.extras?.getString(KEY_URL) ?: return
|
||||
setMD3Content {
|
||||
WebViewScreen(url = url) { finish() }
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val KEY_URL = "url"
|
||||
}
|
||||
}
|
||||
@@ -259,7 +259,7 @@ fun SignInScreen(navigator: DestinationsNavigator) {
|
||||
withStyle(
|
||||
style = SpanStyle(textDecoration = TextDecoration.Underline),
|
||||
) {
|
||||
append(stringResource(id = R.string.tourist_mode))
|
||||
append(stringResource(id = R.string.guest_mode))
|
||||
}
|
||||
},
|
||||
)
|
||||
@@ -356,7 +356,7 @@ fun SignInScreen(navigator: DestinationsNavigator) {
|
||||
withStyle(
|
||||
style = SpanStyle(textDecoration = TextDecoration.Underline),
|
||||
) {
|
||||
append(stringResource(id = R.string.tourist_mode))
|
||||
append(stringResource(id = R.string.guest_mode))
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package com.hippo.ehviewer.ui.main
|
||||
|
||||
import android.content.Intent
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
@@ -39,7 +38,6 @@ import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.clip
|
||||
import androidx.compose.ui.input.nestedscroll.nestedScroll
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.platform.LocalLayoutDirection
|
||||
import androidx.compose.ui.res.dimensionResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -51,17 +49,13 @@ import androidx.paging.compose.itemContentType
|
||||
import androidx.paging.compose.itemKey
|
||||
import com.hippo.ehviewer.R
|
||||
import com.hippo.ehviewer.Settings
|
||||
import com.hippo.ehviewer.client.EhUrl
|
||||
import com.hippo.ehviewer.client.data.BaseGalleryInfo
|
||||
import com.hippo.ehviewer.client.exception.CloudflareBypassException
|
||||
import com.hippo.ehviewer.collectAsState
|
||||
import com.hippo.ehviewer.icons.EhIcons
|
||||
import com.hippo.ehviewer.icons.big.SadAndroid
|
||||
import com.hippo.ehviewer.ui.WebViewActivity
|
||||
import com.hippo.ehviewer.ui.screen.collectDetailSizeAsState
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalGrid
|
||||
import com.hippo.ehviewer.ui.tools.FastScrollLazyVerticalStaggeredGrid
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.util.ExceptionUtils
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
@@ -81,7 +75,6 @@ fun GalleryList(
|
||||
onRefresh: suspend CoroutineScope.() -> Unit,
|
||||
onLoading: suspend CoroutineScope.() -> Unit,
|
||||
) {
|
||||
val context = LocalContext.current
|
||||
val layoutDirection = LocalLayoutDirection.current
|
||||
val marginH = dimensionResource(id = R.dimen.gallery_list_margin_h)
|
||||
val marginV = dimensionResource(id = R.dimen.gallery_list_margin_v)
|
||||
@@ -175,7 +168,6 @@ fun GalleryList(
|
||||
}
|
||||
}
|
||||
|
||||
val dialogState = LocalDialogState.current
|
||||
when (val state = data.loadState.refresh) {
|
||||
is LoadState.Loading -> if (!refreshState.isRefreshing && scrollToTopOnRefresh) {
|
||||
LaunchedEffect(Unit) {
|
||||
@@ -200,18 +192,6 @@ fun GalleryList(
|
||||
|
||||
is LoadState.Error -> {
|
||||
Surface {
|
||||
LaunchedEffect(state) {
|
||||
if (state.error.cause is CloudflareBypassException) {
|
||||
dialogState.awaitPermissionOrCancel(title = R.string.cloudflare_bypass_failed) {
|
||||
Text(text = stringResource(id = R.string.open_in_webview))
|
||||
}
|
||||
context.startActivity(
|
||||
Intent(context, WebViewActivity::class.java).apply {
|
||||
putExtra(WebViewActivity.KEY_URL, EhUrl.host)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
ErrorTip(
|
||||
modifier = Modifier.widthIn(max = 228.dp)
|
||||
.clip(ShapeDefaults.Small).clickable { data.retry() },
|
||||
|
||||
@@ -138,6 +138,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
|
||||
val labelsList = DownloadManager.labelList
|
||||
|
||||
val newLabel = stringResource(R.string.new_label_title)
|
||||
val renameLabel = stringResource(R.string.rename_label_title)
|
||||
val labelsStr = stringResource(R.string.download_labels)
|
||||
val labelEmpty = stringResource(R.string.label_text_is_empty)
|
||||
val defaultInvalid = stringResource(R.string.label_text_is_invalid)
|
||||
@@ -276,7 +277,7 @@ fun DownloadsScreen(navigator: DestinationsNavigator) {
|
||||
IconButton(
|
||||
onClick = {
|
||||
coroutineScope.launch {
|
||||
val new = dialogState.awaitInputText(title = newLabel, hint = labelsStr) { text ->
|
||||
val new = dialogState.awaitInputText(title = renameLabel, hint = labelsStr) { text ->
|
||||
when {
|
||||
text.isBlank() -> labelEmpty
|
||||
text == defaultName -> defaultInvalid
|
||||
|
||||
@@ -275,6 +275,7 @@ fun GalleryDetailScreen(args: GalleryDetailScreenArgs, navigator: DestinationsNa
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
galleryInfo?.let { info -> EhDB.putHistoryInfo(info.findBaseInfo()) }
|
||||
getDetailError = ExceptionUtils.getReadableString(it)
|
||||
}.getOrNull()
|
||||
galleryDetail?.let {
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.hippo.ehviewer.ui.screen
|
||||
import androidx.compose.animation.core.animateFloatAsState
|
||||
import androidx.compose.animation.core.tween
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.focusable
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.PaddingValues
|
||||
import androidx.compose.foundation.layout.Row
|
||||
@@ -19,6 +20,7 @@ import androidx.compose.foundation.layout.navigationBars
|
||||
import androidx.compose.foundation.layout.only
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.safeDrawingPadding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.layout.statusBarsPadding
|
||||
import androidx.compose.foundation.layout.union
|
||||
import androidx.compose.foundation.layout.windowInsetsPadding
|
||||
@@ -77,6 +79,7 @@ import com.hippo.ehviewer.ui.LocalNavDrawerState
|
||||
import com.hippo.ehviewer.ui.LockDrawer
|
||||
import com.hippo.ehviewer.ui.main.FAB_ANIMATE_TIME
|
||||
import com.hippo.ehviewer.ui.tools.LocalDialogState
|
||||
import com.hippo.ehviewer.util.isAtLeastP
|
||||
import com.jamal.composeprefs3.ui.ifNotNullThen
|
||||
import com.jamal.composeprefs3.ui.ifTrueThen
|
||||
import eu.kanade.tachiyomi.util.lang.launchIO
|
||||
@@ -233,15 +236,21 @@ fun SearchBarScreen(
|
||||
Modifier
|
||||
}
|
||||
|
||||
// Workaround IME not hiding after performing search
|
||||
// https://github.com/FooIbar/EhViewer/pull/412
|
||||
val view = LocalView.current
|
||||
val keyboardManager = remember { SoftwareKeyboardControllerCompat(view) }
|
||||
SideEffect {
|
||||
if (!active) keyboardManager.hide()
|
||||
}
|
||||
|
||||
Box(modifier = Modifier.fillMaxSize()) {
|
||||
if (isAtLeastP) {
|
||||
// Workaround IME not hiding after performing search
|
||||
// https://github.com/FooIbar/EhViewer/pull/412
|
||||
val view = LocalView.current
|
||||
val keyboardManager = remember { SoftwareKeyboardControllerCompat(view) }
|
||||
SideEffect {
|
||||
if (!active) keyboardManager.hide()
|
||||
}
|
||||
} else {
|
||||
// Workaround unable to exit search field
|
||||
// https://android.googlesource.com/platform/frameworks/support/+/8f81d46e2c3f37564d0b7515ec9411314645e187
|
||||
Box(Modifier.size(1.dp).focusable())
|
||||
}
|
||||
|
||||
Scaffold(
|
||||
topBar = {
|
||||
// Placeholder, fill immutable SearchBar padding
|
||||
@@ -289,8 +298,8 @@ fun SearchBarScreen(
|
||||
}
|
||||
active = it
|
||||
},
|
||||
title = title?.let { { Text(it, overflow = TextOverflow.Ellipsis) } },
|
||||
placeholder = searchFieldHint?.let { { Text(it) } },
|
||||
title = title.ifNotNullThen { Text(title!!, overflow = TextOverflow.Ellipsis) },
|
||||
placeholder = searchFieldHint.ifNotNullThen { Text(searchFieldHint!!) },
|
||||
leadingIcon = {
|
||||
if (active) {
|
||||
IconButton(onClick = { hideSearchView() }) {
|
||||
|
||||
@@ -142,7 +142,7 @@ fun AdvancedScreen(navigator: DestinationsNavigator) {
|
||||
var enableCronet by Settings::enableCronet.observed
|
||||
Preference(
|
||||
title = stringResource(id = R.string.settings_advanced_http_engine),
|
||||
summary = if (enableCronet) "Cronet" else "Apache 5",
|
||||
summary = if (enableCronet) "Cronet" else "OkHttp",
|
||||
) {
|
||||
coroutineScope.launch {
|
||||
dialogState.awaitPermissionOrCancel(
|
||||
@@ -156,7 +156,7 @@ fun AdvancedScreen(navigator: DestinationsNavigator) {
|
||||
onClick = { enableCronet = false },
|
||||
shape = SegmentedButtonDefaults.itemShape(index = 0, count = 2),
|
||||
) {
|
||||
Text("Apache 5")
|
||||
Text("OkHttp")
|
||||
}
|
||||
SegmentedButton(
|
||||
selected = enableCronet,
|
||||
|
||||
@@ -84,12 +84,12 @@ fun EhScreen(navigator: DestinationsNavigator) {
|
||||
},
|
||||
snackbarHost = { SnackbarHost(snackbarHostState) },
|
||||
) { paddingValues ->
|
||||
val touristMode = stringResource(id = R.string.settings_eh_identity_cookies_tourist)
|
||||
val guestMode = stringResource(id = R.string.settings_eh_identity_cookies_guest)
|
||||
val copiedToClipboard = stringResource(id = R.string.copied_to_clipboard)
|
||||
Column(modifier = Modifier.nestedScroll(scrollBehavior.nestedScrollConnection).verticalScroll(rememberScrollState()).padding(paddingValues)) {
|
||||
Preference(
|
||||
title = stringResource(id = R.string.account_name),
|
||||
summary = Settings.displayName ?: touristMode,
|
||||
summary = Settings.displayName ?: guestMode,
|
||||
) {
|
||||
val eCookies = EhCookieStore.load(Url(EhUrl.HOST_E))
|
||||
val exCookies = EhCookieStore.load(Url(EhUrl.HOST_EX))
|
||||
@@ -114,7 +114,7 @@ fun EhScreen(navigator: DestinationsNavigator) {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) launchSnackBar(copiedToClipboard)
|
||||
}
|
||||
} else {
|
||||
setMessage(touristMode)
|
||||
setMessage(guestMode)
|
||||
}
|
||||
setPositiveButton(R.string.settings_eh_sign_out) { _, _ ->
|
||||
EhUtils.signOut()
|
||||
|
||||
@@ -78,5 +78,9 @@ object Crash {
|
||||
it.printStackTrace()
|
||||
file.delete()
|
||||
}
|
||||
if (t is OutOfMemoryError) {
|
||||
val dumpFile = File(dir, "hprof-$nowString.hprof")
|
||||
Debug.dumpHprofData(dumpFile.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package eu.kanade.tachiyomi.network.interceptor
|
||||
|
||||
import java.io.IOException
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
/**
|
||||
* Catches any uncaught exceptions from later in the chain and rethrows as a non-fatal
|
||||
* IOException to avoid catastrophic failure.
|
||||
*
|
||||
* This should be the first interceptor in the client.
|
||||
*
|
||||
* See [Interceptor](https://square.github.io/okhttp/5.x/okhttp/okhttp3/-interceptor/index.html)
|
||||
*/
|
||||
class UncaughtExceptionInterceptor : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
return try {
|
||||
chain.proceed(chain.request())
|
||||
} catch (e: Exception) {
|
||||
if (e is IOException) {
|
||||
throw e
|
||||
} else {
|
||||
throw IOException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,9 +51,11 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.ModalBottomSheetFix
|
||||
import androidx.compose.material3.rememberModalBottomSheetState
|
||||
import androidx.compose.runtime.CompositionLocalProvider
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableIntStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -110,6 +112,8 @@ import eu.kanade.tachiyomi.util.system.isNightMode
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.debounce
|
||||
import kotlinx.coroutines.flow.drop
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.merge
|
||||
@@ -322,6 +326,12 @@ class ReaderActivity : EhActivity() {
|
||||
dialogState.Intercept()
|
||||
|
||||
val showSeekbar by Settings.showReaderSeekbar.collectAsState()
|
||||
val sliderValueFlow = remember { MutableStateFlow(0) }
|
||||
LaunchedEffect(sliderValueFlow) {
|
||||
sliderValueFlow.drop(1).debounce(200).collect {
|
||||
moveToPageIndex(it)
|
||||
}
|
||||
}
|
||||
ReaderAppBars(
|
||||
visible = menuVisible,
|
||||
isRtl = isRtl,
|
||||
@@ -330,7 +340,8 @@ class ReaderActivity : EhActivity() {
|
||||
totalPages = totalPage,
|
||||
onSliderValueChange = {
|
||||
isScrollingThroughPages = true
|
||||
moveToPageIndex(it)
|
||||
sliderValueFlow.value = it
|
||||
currentPage = it + 1
|
||||
},
|
||||
onClickSettings = { readerSettingSheetDialog?.show() },
|
||||
)
|
||||
|
||||
@@ -6,7 +6,6 @@ import android.content.res.Resources
|
||||
import android.graphics.Color
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.Display
|
||||
import android.view.View
|
||||
import androidx.annotation.AttrRes
|
||||
@@ -125,7 +124,3 @@ fun Context.createReaderThemeContext(): Context {
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
inline fun Any.logcat(priority: Int = Log.DEBUG, tag: String? = null, message: () -> String) {
|
||||
Log.println(priority, tag ?: javaClass.simpleName, message())
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package eu.kanade.tachiyomi.util.system
|
||||
|
||||
import android.util.Log
|
||||
|
||||
inline fun logcat(tag: String, priority: Int = Log.DEBUG, message: () -> String) {
|
||||
Log.println(priority, tag, message())
|
||||
}
|
||||
|
||||
inline fun Any.logcat(priority: Int = Log.DEBUG, message: () -> String) {
|
||||
Log.println(priority, javaClass.simpleName, message())
|
||||
}
|
||||
@@ -59,21 +59,12 @@
|
||||
<string name="gallery_list_search_bar_hint_exhentai">ExHentai durchsuchen</string>
|
||||
<string name="gallery_list_search_bar_hint_e_hentai">E-Hentai durchsuchen</string>
|
||||
<string name="gallery_list_empty_hit">Die Welt ist so groß und der Panda sitzt ganz allein</string>
|
||||
<string name="search">Suchen</string>
|
||||
<string name="keyword_search">Suche nach dem Schlüsselwort</string>
|
||||
<string name="image_search">Suche nach einem Bild</string>
|
||||
<string name="search_normal">Normale Suche</string>
|
||||
<string name="search_advance">Erweiterte Optionen</string>
|
||||
<string name="search_image">Suche nach einem Bild</string>
|
||||
<string name="search_normal_search">Normale Suche</string>
|
||||
<string name="search_subscription_search">Suche in gefolgten Etiketten</string>
|
||||
<string name="search_specify_uploader">Einen Uploader spezifizieren</string>
|
||||
<string name="search_specify_tag">Ein Etikett spezifizieren</string>
|
||||
<string name="search_enable_advance">Erweitere Optionen aktivieren</string>
|
||||
<string name="search_sh">Gelöschte Galerien anzeigen</string>
|
||||
<string name="search_sto">Nur die Galerien mit Torrentdateien anzeigen</string>
|
||||
<string name="search_sr">Mindestpunktzahl: </string>
|
||||
<string name="search_sp">Seiten: </string>
|
||||
<string name="search_sp_to">zu</string>
|
||||
<string name="search_sf">Standard-Filter deaktivieren für: </string>
|
||||
<string name="search_sfl">Sprache</string>
|
||||
@@ -231,7 +222,6 @@
|
||||
<string name="add_filter">Blocker erstellen</string>
|
||||
<string name="filter_text">Blocker-Text</string>
|
||||
<string name="filter_tip">Die blockierten Galerien wurde in EHentai nicht angezeigt.\n\nTitel-Blocker: die Galerien, deren Titel das Wort enthalten, ausschließen.\n\nUploader-Blocker: Die vom Uploader hochgeladen Galerien ausschließen.\n\nEtikett-Blocker: Die Galerien, die die Etikett haben, ausschließen. Es wird länger dauern, Galerieliste zu laden.\n\nEtikettnamensraum-Blocker: Die Galerien, die den Etikettnamensraum haben, ausschließen. Es wird länger dauern, Galerieliste zu laden.</string>
|
||||
<string name="search_tip">Normale Suche: Nur durchsuchen.\n\nSuche in gefolgten Etiketten: Nur die Galerien, die die gefolgten Etiketten haben, durchsuchen.\n\nUploader spezifizieren: Die Galerien, die vom Uploader hochgeladen sind, auflisten. Andere Optionen werden ignoriert.\n\nEtikett spezifizieren: Die Galerien, die das Etikett haben, auflisten. Nur ein Etikett kann eingegeben werden. Andere Optionen werden ignoriert.</string>
|
||||
<string name="u_config">EHentai-Einstellungen</string>
|
||||
<string name="apply_tip">Zum Speichern der Einstellungen auf Häkchen tippen</string>
|
||||
<string name="share_image">Das Bild teilen</string>
|
||||
@@ -315,7 +305,7 @@
|
||||
<string name="app_waring">Inhalt dieser App kommt aus dem Internet, von dem einige dir körperlichen oder emotionalen Schaden zufügen kann. Du hast es wirklich erfahrt und möchtest immer noch fortsetzen.</string>
|
||||
<string name="error_username_cannot_empty">Gibt den Nutzername ein</string>
|
||||
<string name="error_password_cannot_empty">Gibt das Passwort ein</string>
|
||||
<string name="tourist_mode">Anmeldung überspringen</string>
|
||||
<string name="guest_mode">Anmeldung überspringen</string>
|
||||
<string name="sign_in_failed">Anmeldung fehlgeschlagen</string>
|
||||
<string name="clipboard_gallery_url_snack_message">Ein Link von einen Galerie wurde in Zwischenablage erkennt.</string>
|
||||
<string name="clipboard_gallery_url_snack_action">Gehen</string>
|
||||
@@ -340,7 +330,7 @@
|
||||
<string name="download_reset_reading_progress">Lesefortschritte zurücksetzen</string>
|
||||
<string name="reset_reading_progress_message">Lesefortschritte aus allen heruntergeladenen Galerie zurücksetzen?</string>
|
||||
<string name="settings_eh_identity_cookies_signed">Wenn jemand die folgenden Informationen hat, kann er sich als du anmelden. <br><b>ALSO GEHEIM HALTEN!</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Du hast dich noch nicht angemeldet.</string>
|
||||
<string name="settings_eh_identity_cookies_guest">Du hast dich noch nicht angemeldet.</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Kopieren</string>
|
||||
<string name="settings_eh_show_gallery_pages">Galerieseitenzahl anzeigen</string>
|
||||
<string name="settings_eh_show_gallery_pages_summary">Die Galerieseitenzahle in der Galerieliste anzeigen</string>
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
<string name="app_waring">El contenido de esta aplicación es de Internet. Algunas de ellas pueden causarle daño psicológico. Ahora sabes los riesgos anteriormente mencionado y te gustaría asumirlos</string>
|
||||
<string name="error_username_cannot_empty">El usuario no puede estar vacío</string>
|
||||
<string name="tourist_mode">Saltar inicio de sesión</string>
|
||||
<string name="guest_mode">Saltar inicio de sesión</string>
|
||||
<string name="sign_in_failed">Inicio de sesión fallido</string>
|
||||
<string name="get_it">Entendido</string>
|
||||
|
||||
@@ -78,29 +78,17 @@
|
||||
<string name="gallery_list_search_bar_hint_e_hentai">Buscar E-Hentai</string>
|
||||
<string name="gallery_list_empty_hit">El mundo es grande y el panda está sentado solo</string>
|
||||
|
||||
<string name="search">Buscar</string>
|
||||
|
||||
<string name="keyword_search">Búsqueda por palabras clave</string>
|
||||
<string name="image_search">Búsqueda de imagen</string>
|
||||
<string name="search_normal">Búsqueda normal</string>
|
||||
<string name="search_advance">Opciones avanzadas</string>
|
||||
<string name="search_image">Búsqueda de imágenes</string>
|
||||
<string name="search_normal_search">Búsqueda general</string>
|
||||
<string name="search_specify_uploader">Uploader específicos</string>
|
||||
<string name="search_specify_tag">Etiquetas específicas</string>
|
||||
<string name="search_enable_advance">Habilitar opciones avanzadas</string>
|
||||
|
||||
<string name="search_tip">Búsqueda normal: Solo busca.\n\nBúsqueda de suscripción: Buscar etiquetas suscriptas.n\nUploader especifico: Listar de galerías subidas por el uploader. Otras opciones serán ignoradas.\n\nEtiquetas específicas: Listar las galerías que contienen la etiqueta. Solo se acepta una etiqueta. Otras opciones serán ignoradas.</string>
|
||||
|
||||
<string name="search_sh">Mostrar galerías borradas</string>
|
||||
<string name="search_sto">Mostrar solo galerías con torrents</string>
|
||||
<string name="search_sr">Valoración mínima:</string>
|
||||
<string name="search_subscription_search">Búsqueda de etiquetas suscritas</string>
|
||||
<string name="select_image">Seleccionar imagen</string>
|
||||
<string name="search_uss">Usar búsqueda similar</string>
|
||||
<string name="search_osc">Buscar solo portadas</string>
|
||||
<string name="select_image_first">Seleccione la imagen primero</string>
|
||||
<string name="search_sp">Páginas:</string>
|
||||
<string name="search_sp_to">hasta</string>
|
||||
<string name="search_sf">Deshabilitar filtros para:</string>
|
||||
<string name="search_sfl">Lenguaje</string>
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
<string name="app_waring">Le contenu de l\'application provient de l\'Internet, dont quelque chose peut vous causer le dommage physique ou mentale. Vous l\'avez bien compris et voulez continuer quand même.</string>
|
||||
<string name="error_username_cannot_empty">Nom d\'ultilisateur ne doit pas être une chaîne vide</string>
|
||||
<string name="error_password_cannot_empty">Mot de passe ne doit pas être une chaîne vide</string>
|
||||
<string name="tourist_mode">Continuer sans se connecter</string>
|
||||
<string name="guest_mode">Continuer sans se connecter</string>
|
||||
<string name="sign_in_failed">Impossible de se connecter</string>
|
||||
<string name="get_it">Compris</string>
|
||||
|
||||
@@ -81,26 +81,14 @@
|
||||
<string name="gallery_list_empty_hit">Le monde est grand et le panda s\'assied tout seul.</string>
|
||||
<string name="gallery_list_empty_hit_subscription">Vous pouvez suivre des tags à Paramètres -> EH -> Mes tags.</string>
|
||||
|
||||
<string name="search">Chercher</string>
|
||||
|
||||
<string name="keyword_search">Recherche du mot-clé</string>
|
||||
<string name="image_search">Recherche d\'une image</string>
|
||||
|
||||
<string name="search_normal">Recherche normale</string>
|
||||
<string name="search_advance">Options avancées</string>
|
||||
<string name="search_image">Recherche d\'une image</string>
|
||||
<string name="search_subscription_search">Recherche dans les tags suivis</string>
|
||||
<string name="search_normal_search">Chercher</string>
|
||||
<string name="search_specify_uploader">Spécifier un uploader</string>
|
||||
<string name="search_specify_tag">Spécifier un tag</string>
|
||||
<string name="search_enable_advance">Activer options avancées</string>
|
||||
|
||||
<string name="search_tip">Recherche normale : faire recherche.\n\nRecherche dans les tags suivis : seulement rechercher dans les tags suivis.\n\nSpécifer un uploader : faire la liste des galeries mises en ligne par l\'uploader spécifié. Autres options sont ignorées.\n\nSpécifier un tag : faire la liste des galeries qui contiennent le tag spécifié. Vous ne pouvez spécifier qu\'un tag. Autres options sont ignorées.</string>
|
||||
|
||||
<string name="search_sh">Montrer les galeries supprimées</string>
|
||||
<string name="search_sto">Seulement montrer galeries avec des fiches torrent</string>
|
||||
<string name="search_sr">Minimum note :</string>
|
||||
<string name="search_sp">Pages : </string>
|
||||
<string name="search_sp_to">à</string>
|
||||
<string name="search_sf">Désactiver le filtre par défaut pour les items suivants :</string>
|
||||
<string name="search_sfl">Langue</string>
|
||||
@@ -448,7 +436,7 @@
|
||||
<string name="settings_advanced_app_language_title">Langue de l\'app (Language)</string>
|
||||
<string name="app_language_system">Langue du système (défaut)</string>
|
||||
<string name="settings_eh_identity_cookies_signed">Tout le monde peut utiliser les cookies de ce compte pour s\'y connecter.<br><b>GARDEZ-LES BIEN !</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Vous ne vous êtes pas connecté.</string>
|
||||
<string name="settings_eh_identity_cookies_guest">Vous ne vous êtes pas connecté.</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Copier</string>
|
||||
<string name="settings_eh_show_gallery_pages">Montrer les nombres des pages des galeries</string>
|
||||
<string name="settings_eh_show_gallery_pages_summary">Montrer le nombre des pages des galerie dans la liste des galeries</string>
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<string name="app_waring">このアプリの内容はインターネットから取得したものです。その内容の一部は使用者のお体や心理に傷つける恐れがあります。それでも続行しますか?</string>
|
||||
<string name="error_username_cannot_empty">ユーザー名を入力してください。</string>
|
||||
<string name="error_password_cannot_empty">パスワードを入力してください。</string>
|
||||
<string name="tourist_mode">ログインをスキップ</string>
|
||||
<string name="guest_mode">ログインをスキップ</string>
|
||||
<string name="sign_in_failed">ログインに失敗しました。</string>
|
||||
<string name="get_it">了解</string>
|
||||
|
||||
@@ -79,26 +79,14 @@
|
||||
<string name="gallery_list_empty_hit">何も見つかりませんでした。</string>
|
||||
<string name="gallery_list_empty_hit_subscription">リストは空です。設定->EH->マイタグにてタグを購読することができます。</string>
|
||||
|
||||
<string name="search">検索</string>
|
||||
|
||||
<string name="keyword_search">キーワードで検索</string>
|
||||
<string name="image_search">画像で検索</string>
|
||||
|
||||
<string name="search_normal">検索</string>
|
||||
<string name="search_advance">その他のオプション</string>
|
||||
<string name="search_image">画像検索</string>
|
||||
<string name="search_normal_search">一般検索</string>
|
||||
<string name="search_subscription_search">購読検索</string>
|
||||
<string name="search_specify_uploader">アップローダを検索</string>
|
||||
<string name="search_specify_tag">タグを検索</string>
|
||||
<string name="search_enable_advance">その他のオプションを有効化</string>
|
||||
|
||||
<string name="search_tip">普通検索:検索します。\n\n購読検索:購読しているタグで検索します。\n\nアップローダを検索:このアップローダーがアップロードしたギャラリーをリストします。他のオプションは無視されます。\n\nタグを検索:指定したタグを含むギャラリーをリストします。他のオプションは無視されます。</string>
|
||||
|
||||
<string name="search_sh">削除済みのギャラリーを表示</string>
|
||||
<string name="search_sto">Torrentのあるギャラリーのみを表示</string>
|
||||
<string name="search_sr">評価の下限:</string>
|
||||
<string name="search_sp">ページ:</string>
|
||||
<string name="search_sp_to">から</string>
|
||||
<string name="search_sp_suffix">まで</string>
|
||||
<string name="search_sf">既定フィルターから下記のものを例外とする:</string>
|
||||
@@ -446,7 +434,7 @@
|
||||
<string name="download_service">ダウンロードサービス</string>
|
||||
|
||||
<string name="settings_eh_identity_cookies_signed">下記の情報を持つ誰でもこのアカウントにログインできますので<br><b>絶対に他人に渡さないように!</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">まだログインしていません</string>
|
||||
<string name="settings_eh_identity_cookies_guest">まだログインしていません</string>
|
||||
<string name="settings_eh_identity_cookies_copy">コピー</string>
|
||||
<string name="settings_eh_show_gallery_pages">ギャラリーページ数を表示</string>
|
||||
<string name="settings_eh_show_gallery_pages_summary">リストにギャラリーのページの数量を表示します</string>
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
<string name="app_waring">이 앱의 내용은 인터넷에서 받아옵니다. 이 앱을 사용하기 위해서는 받아온 내용 중 일부가 사용자에게 가할 수 있는 신체적 또는 정신적 피해를 감수해야 합니다.</string>
|
||||
<string name="error_username_cannot_empty">사용자 이름은 비워둘 수 없습니다.</string>
|
||||
<string name="error_password_cannot_empty">비밀번호는 비워둘 수 없습니다.</string>
|
||||
<string name="tourist_mode">로그인 없이 사용</string>
|
||||
<string name="guest_mode">로그인 없이 사용</string>
|
||||
<string name="sign_in_failed">로그인 실패</string>
|
||||
<string name="get_it">알겠습니다</string>
|
||||
|
||||
@@ -82,20 +82,10 @@
|
||||
<string name="gallery_list_search_bar_open_gallery">갤러리 열기</string>
|
||||
<string name="gallery_list_empty_hit">The World is Big and the panda sit alone</string>
|
||||
|
||||
<string name="search">검색</string>
|
||||
|
||||
<string name="keyword_search">키워드 검색</string>
|
||||
<string name="image_search">이미지 검색</string>
|
||||
|
||||
<string name="search_normal">일반 검색</string>
|
||||
<string name="search_advance">고급 옵션</string>
|
||||
<string name="search_image">이미지 검색</string>
|
||||
<string name="search_normal_search">일반 검색</string>
|
||||
<string name="search_specify_uploader">업로더 지정</string>
|
||||
<string name="search_specify_tag">태그 지정</string>
|
||||
<string name="search_enable_advance">고급 옵션 사용</string>
|
||||
|
||||
<string name="search_tip">일반 검색: 그냥 검색합니다.\n\n업로더 지정: 해당 업로더가 업로드한 갤러리를 검색합니다. 다른 옵션은 무시됩니다.\n\n태그 지정: 해당 태그를 포함한 갤러리를 검색합니다. 하나의 태그만 지정할 수 있으며, 다른 옵션은 무시됩니다.</string>
|
||||
|
||||
<string name="search_sh">Expunged 갤러리 표시</string>
|
||||
<string name="search_sto">토렌트 파일이 있는 갤러리만 검색</string>
|
||||
@@ -274,7 +264,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">로그아웃</string>
|
||||
<string name="settings_eh_identity_cookies_signed">식별용 쿠키를 사용하여 이 계정으로 로그인할 수 있습니다.<br><b>안전하게 보관하세요.</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">로그인 상태가 아닙니다.</string>
|
||||
<string name="settings_eh_identity_cookies_guest">로그인 상태가 아닙니다.</string>
|
||||
<string name="settings_eh_identity_cookies_copy">복사</string>
|
||||
<string name="settings_u_config">E-Hentai 설정</string>
|
||||
<string name="settings_u_config_summary">E-Hentai 사이트의 설정 페이지를 엽니다.</string>
|
||||
|
||||
@@ -30,24 +30,18 @@
|
||||
<string name="no_torrents">Ingen torrenter</string>
|
||||
<string name="search_sfl">Språk</string>
|
||||
<string name="search_osc">Kun søk i omslag</string>
|
||||
<string name="tourist_mode">Fortsett uten å logge inn</string>
|
||||
<string name="guest_mode">Fortsett uten å logge inn</string>
|
||||
<string name="select_scene">Hvilken galleriside vil du besøke\?</string>
|
||||
<string name="favored_times">♥ %d</string>
|
||||
<string name="torrent_count">Torrent (%d)</string>
|
||||
<string name="share">Del</string>
|
||||
<string name="gallery_list_search_bar_open_gallery">Åpne galleriet</string>
|
||||
<string name="search_normal_search">Normalt søk</string>
|
||||
<string name="search_subscription_search">Abonnementssøk</string>
|
||||
<string name="search_sp_to">til</string>
|
||||
<string name="search_sfu">Opplaster</string>
|
||||
<string name="delete">Slett</string>
|
||||
<string name="search">Søk</string>
|
||||
<string name="image_search">Bildesøk</string>
|
||||
<string name="search_normal">Normalt søk</string>
|
||||
<string name="search_cover">Søk i omslag</string>
|
||||
<string name="search_image">Bildesøk</string>
|
||||
<string name="search_specify_uploader">Angi opplaster</string>
|
||||
<string name="search_specify_tag">Angi etikett</string>
|
||||
<string name="select_image">Velg bilde</string>
|
||||
<string name="star_3">3 stjerner</string>
|
||||
<string name="read">Les</string>
|
||||
@@ -64,7 +58,6 @@
|
||||
<string name="refresh">Gjenoppfrisk</string>
|
||||
<string name="get_it">Skjønner</string>
|
||||
<string name="keyword_search">Nøkkelordssøk</string>
|
||||
<string name="search_sp">Sider:</string>
|
||||
<string name="search_sft">Etiketter</string>
|
||||
<string name="any">Ubegrenset</string>
|
||||
<plurals name="page_count">
|
||||
@@ -97,7 +90,7 @@
|
||||
<string name="key_pages">Sider</string>
|
||||
<string name="share_image">Del bilde</string>
|
||||
<string name="settings_eh_sign_out">Logg ut</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Turistmodus</string>
|
||||
<string name="settings_eh_identity_cookies_guest">Turistmodus</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Kopier informasjonskapsler</string>
|
||||
<string name="settings_about_version">Byggversjon</string>
|
||||
<string name="settings_my_tags">Mine etiketter</string>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<resources>
|
||||
<dimen name="bottom_sheet_width">480dp</dimen>
|
||||
<dimen name="screen_edge_margin">24dp</dimen>
|
||||
</resources>
|
||||
@@ -66,7 +66,7 @@
|
||||
<string name="app_waring">เนื้อหาภายในแอปพลิเคชั่นนี้มาจากอินเทอร์เน็ตทั้งหมด อาจมีเนื้อหาบางอย่างที่มีผลต่อร่างกายหรือจิตใจของคุณ คุณจะต้องยอมรับความเสี่ยงที่ดังกล่าว และดำเนินการต่อไป</string>
|
||||
<string name="error_username_cannot_empty">ชื่อผู้ใช้ห้ามเว้นว่างไว้</string>
|
||||
<string name="error_password_cannot_empty">รหัสผ่านห้ามเว้นว่างไว้</string>
|
||||
<string name="tourist_mode">ดำเนินการต่อโดยไม่ต้องลงชื่อเข้าระบบ</string>
|
||||
<string name="guest_mode">ดำเนินการต่อโดยไม่ต้องลงชื่อเข้าระบบ</string>
|
||||
<string name="sign_in_failed">การลงชื่อเข้าใช้ล้มเหลว</string>
|
||||
<string name="get_it">เข้าใจแล้ว ไม่ต้องแสดงอีก</string>
|
||||
|
||||
@@ -82,20 +82,10 @@
|
||||
<string name="gallery_list_search_bar_open_gallery">เปิดแกลเลอรี่</string>
|
||||
<string name="gallery_list_empty_hit">โลกนั้นนะมันกว้างงงงงใหญ่ไพรศาล และแพนด้านั่งโดดเดี่ยวเดียวดายในโลกกลมๆ</string>
|
||||
|
||||
<string name="search">ค้นหา</string>
|
||||
|
||||
<string name="keyword_search">คีย์เวิร์ดในการค้นหา</string>
|
||||
<string name="image_search">ค้นหาด้วยรูป</string>
|
||||
|
||||
<string name="search_normal">ค้นหาแบบธรรมดา</string>
|
||||
<string name="search_advance">ตัวเลือกขั้นสูง</string>
|
||||
<string name="search_image">ค้นหาด้วยรูปภาพ</string>
|
||||
<string name="search_normal_search">ค้นหาแบบธรรมดา</string>
|
||||
<string name="search_specify_uploader">ระบุผู้อัพโหลด</string>
|
||||
<string name="search_specify_tag">ระบุป้ายกำกับ</string>
|
||||
<string name="search_enable_advance">เปิดโหมดค้นหาขั้นสูง</string>
|
||||
|
||||
<string name="search_tip">ค้นหาแบบธรรมดา: ค้นหาแบบง๊ายง่าย\n\nระบุผู้อัพโหลด: ค้นหาแกลเลอรี่ที่อัพโหลดโดยระบุชื่อผู้ใช้ของคนอัพโหลด โดยตัวเลือกอื่นๆจะถูกข้ามไป\n\nระบุป้ายกำกับ: ค้นหาแกลเลอรี่ที่ถูกใส่ป้ายกำกับหรือแท็กไว้ในแต่ละแกลเลอรี่ ระบุได้เพียงหนึ่งป้ายกำกับ ตัวเลือกอื่นๆจะถูกข้ามไป</string>
|
||||
|
||||
<string name="search_sh">แสดงแกลเลอรี่ที่ถูกลบออก</string>
|
||||
<string name="search_sto">แสดงผลเฉพาะแกลเลอรี่ที่มีไฟล์ Torrents</string>
|
||||
@@ -289,7 +279,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">ออกจากระบบ</string>
|
||||
<string name="settings_eh_identity_cookies_signed">คุกกี๊ยืนยันตัวตนสามารถใช้ลงชื่อเข้าสู่ระบบสำหรับบัญชีนี้เท่านั้น<br><b>เก็บ รักษา ให้ ปลอดภัย</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">ยังไม่ลงชื่อเข้าสู่ระบบ</string>
|
||||
<string name="settings_eh_identity_cookies_guest">ยังไม่ลงชื่อเข้าสู่ระบบ</string>
|
||||
<string name="settings_eh_identity_cookies_copy">คัดลอก</string>
|
||||
<string name="settings_u_config">การตั้งค่า EHentai</string>
|
||||
<string name="settings_u_config_summary">การตั้งค่าบนเว็บไซต์ EHentai</string>
|
||||
|
||||
@@ -42,21 +42,13 @@
|
||||
<string name="error_invalid_number">Geçersiz numara</string>
|
||||
<string name="error_username_cannot_empty">Kullanıcı adı boş bir metin olamaz</string>
|
||||
<string name="error_password_cannot_empty">Şifre boş bir metin olamaz</string>
|
||||
<string name="tourist_mode">Giriş yapmaksızın devam et</string>
|
||||
<string name="guest_mode">Giriş yapmaksızın devam et</string>
|
||||
<string name="sign_in_failed">Giriş başarısız</string>
|
||||
<string name="get_it">Anladım</string>
|
||||
<string name="gallery_list_empty_hit">Dünya büyük olmasına rağmen pandacık yalnız oturuyor</string>
|
||||
<string name="search">Arayın</string>
|
||||
<string name="keyword_search">Anahtar Kelime Arama</string>
|
||||
<string name="image_search">Görsel Arama</string>
|
||||
<string name="search_normal">Normal Arama</string>
|
||||
<string name="search_advance">Gelişmiş Seçenekler</string>
|
||||
<string name="search_image">Görsel Arama</string>
|
||||
<string name="search_normal_search">Normal arama</string>
|
||||
<string name="search_subscription_search">Abonelik araması</string>
|
||||
<string name="search_specify_uploader">Belirli yükleyici</string>
|
||||
<string name="search_specify_tag">Belirli etiket</string>
|
||||
<string name="search_enable_advance">Gelişmiş seçenekleri etkinleştir</string>
|
||||
<string name="search_sh">Yalnızca Silinen Galerileri Gösteri</string>
|
||||
<string name="search_sto">Yalnızca Torrent\'li Galerileri Göster</string>
|
||||
<string name="search_sr">En Az Derecelendirme:</string>
|
||||
@@ -91,7 +83,6 @@
|
||||
<string name="select_scene">Hangi galeri sitesini ziyaret etmek istiyorsunuz\?</string>
|
||||
<string name="gallery_list_search_bar_hint_e_hentai">E-Hentai\'de Arayın</string>
|
||||
<string name="gallery_list_empty_hit_subscription">Etiketlere Ayarlar->EH->Etiketlerim yerinden abone olun</string>
|
||||
<string name="search_sp">Sayfa:</string>
|
||||
<string name="duplicate_quick_search">Aynı bir hızlı arama zaten var. Adı \"%s\".</string>
|
||||
<string name="search_sp_err1">Sayfa oranı en fazla 10un altında olamaz</string>
|
||||
<string name="readme">BENIOKU</string>
|
||||
|
||||
@@ -58,12 +58,10 @@
|
||||
<string name="app_waring_2">继续使用即代表您同意上述条款。</string>
|
||||
<string name="error_username_cannot_empty">用户名不可为空</string>
|
||||
<string name="error_password_cannot_empty">密码不可为空</string>
|
||||
<string name="tourist_mode">游客模式</string>
|
||||
<string name="guest_mode">游客模式</string>
|
||||
<string name="sign_in_failed">登录失败</string>
|
||||
<string name="sign_in_failed_tip">若持续出错,请尝试“通过网页登录”或“通过 Cookie 登录”。</string>
|
||||
<string name="get_it">知道了</string>
|
||||
<string name="cloudflare_bypass_failed">未能绕过 Cloudflare 验证</string>
|
||||
<string name="open_in_webview">在 WebView 中打开链接以通过验证?</string>
|
||||
<!-- Select scene -->
|
||||
<string name="select_scene">你想选择哪个画廊站点?</string>
|
||||
<string name="select_scene_explain">e-hentai:对任何人开放\nexhentai:仅对登录用户开放</string>
|
||||
@@ -74,22 +72,12 @@
|
||||
<string name="gallery_list_search_bar_open_gallery">打开画廊</string>
|
||||
<string name="gallery_list_empty_hit">什么都没有找到</string>
|
||||
<string name="gallery_list_empty_hit_subscription">请至 设置->EH->我的标签 订阅标签</string>
|
||||
<string name="search">搜索</string>
|
||||
<string name="keyword_search">关键字搜索</string>
|
||||
<string name="image_search">图片搜索</string>
|
||||
<string name="search_normal">普通搜索</string>
|
||||
<string name="search_advance">高级选项</string>
|
||||
<string name="search_image">图片搜索</string>
|
||||
<string name="search_normal_search">一般搜索</string>
|
||||
<string name="search_subscription_search">订阅搜索</string>
|
||||
<string name="search_specify_uploader">指定上传者</string>
|
||||
<string name="search_specify_tag">指定标签</string>
|
||||
<string name="search_enable_advance">启用高级选项</string>
|
||||
<string name="search_tip">一般搜索:就是搜索。\n\n订阅搜素:在订阅中搜索。\n\n指定上传者:列出该上传者上传的画廊。其他选项会被忽略。\n\n指定标签:列出含有该标签的画廊。其他选项会被忽略。</string>
|
||||
<string name="search_sh">已删除</string>
|
||||
<string name="search_sto">有种子</string>
|
||||
<string name="search_sr">最低评分:</string>
|
||||
<string name="search_sp">页数:</string>
|
||||
<string name="search_sp_to">到</string>
|
||||
<string name="search_sp_err1">页数最大值至少为 10</string>
|
||||
<string name="search_sp_err2">页数范围差至少为 20</string>
|
||||
@@ -307,7 +295,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">退出登录</string>
|
||||
<string name="settings_eh_identity_cookies_signed">身份 Cookie 可用于登录该账号。<br><b>注意数据安全</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">游客模式</string>
|
||||
<string name="settings_eh_identity_cookies_guest">游客模式</string>
|
||||
<string name="settings_eh_identity_cookies_copy">复制 Cookies</string>
|
||||
<string name="settings_u_config">EHentai 设置</string>
|
||||
<string name="settings_u_config_summary">EHentai 网站上的设置</string>
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
<string name="app_waring">本應用中內容來自互聯網,部分內容可能對您的生理及心理造成難以恢復的傷害。本應用作者不會對由本應用造成的任何後果負責。\n\n未成年人應在監護人指導下使用本應用。</string>
|
||||
<string name="error_username_cannot_empty">用户名不可為空</string>
|
||||
<string name="error_password_cannot_empty">密碼不可為空</string>
|
||||
<string name="tourist_mode">跳過登錄</string>
|
||||
<string name="guest_mode">跳過登錄</string>
|
||||
<string name="sign_in_failed">登錄失敗</string>
|
||||
<string name="sign_in_failed_tip">若持續出錯,請嘗試“通過網頁登錄”或“通過 Cookie 登錄”。</string>
|
||||
<string name="get_it">知道了</string>
|
||||
@@ -85,26 +85,14 @@
|
||||
<string name="gallery_list_empty_hit">什麼都沒有找到</string>
|
||||
<string name="gallery_list_empty_hit_subscription">請至 設置->EH->我的標籤 訂閲標籤</string>
|
||||
|
||||
<string name="search">搜索</string>
|
||||
|
||||
<string name="keyword_search">關鍵字搜索</string>
|
||||
<string name="image_search">圖片搜索</string>
|
||||
|
||||
<string name="search_normal">普通搜索</string>
|
||||
<string name="search_advance">高級選項</string>
|
||||
<string name="search_image">圖片搜索</string>
|
||||
<string name="search_normal_search">一般搜索</string>
|
||||
<string name="search_subscription_search">訂閲搜索</string>
|
||||
<string name="search_specify_uploader">指定上傳者</string>
|
||||
<string name="search_specify_tag">指定標籤</string>
|
||||
<string name="search_enable_advance">啟用高級選項</string>
|
||||
|
||||
<string name="search_tip">一般搜索:就是搜索。\n\n訂閲搜素:在訂閲中搜索。\n\n指定上傳者:列出該上傳者上傳的畫廊。其他選項會被忽略。\n\n指定標籤:列出含有該標籤的畫廊。其他選項會被忽略。</string>
|
||||
|
||||
<string name="search_sh">已刪除</string>
|
||||
<string name="search_sto">有種子</string>
|
||||
<string name="search_sr">最低評分:</string>
|
||||
<string name="search_sp">頁數:</string>
|
||||
<string name="search_sp_to">到</string>
|
||||
<string name="search_sf">禁用排除項:</string>
|
||||
<string name="search_sfl">語言</string>
|
||||
@@ -319,7 +307,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">退出登錄</string>
|
||||
<string name="settings_eh_identity_cookies_signed">身份 Cookie 可用於登錄該賬號。<br><b>注意數據安全</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">未登錄</string>
|
||||
<string name="settings_eh_identity_cookies_guest">未登錄</string>
|
||||
<string name="settings_eh_identity_cookies_copy">複製</string>
|
||||
<string name="settings_u_config">EHentai 設置</string>
|
||||
<string name="settings_u_config_summary">EHentai 網站上的設置</string>
|
||||
|
||||
@@ -58,12 +58,10 @@
|
||||
<string name="app_waring_2">繼續使用即表示您同意上述條款。</string>
|
||||
<string name="error_username_cannot_empty">使用者名稱欄位不能為空</string>
|
||||
<string name="error_password_cannot_empty">密碼欄位不能為空</string>
|
||||
<string name="tourist_mode">略過登入</string>
|
||||
<string name="guest_mode">略過登入</string>
|
||||
<string name="sign_in_failed">登入失敗</string>
|
||||
<string name="sign_in_failed_tip">若持續出錯,請嘗試“通過網頁登入”或“通過 Cookie 登入”。</string>
|
||||
<string name="get_it">知道了</string>
|
||||
<string name="cloudflare_bypass_failed">未能繞過 Cloudflare 驗證</string>
|
||||
<string name="open_in_webview">在 WebView 中開啟網址以完成驗證?</string>
|
||||
<!-- Select scene -->
|
||||
<string name="select_scene">你想選擇哪個圖庫站台?</string>
|
||||
<string name="select_scene_explain">e-hentai:對任何人開放\nexhentai:僅對登入使用者開放</string>
|
||||
@@ -74,22 +72,12 @@
|
||||
<string name="gallery_list_search_bar_open_gallery">開啟圖庫</string>
|
||||
<string name="gallery_list_empty_hit">什麼都沒找到</string>
|
||||
<string name="gallery_list_empty_hit_subscription">請至 設定->EH->我的標籤 訂閱標籤</string>
|
||||
<string name="search">搜尋</string>
|
||||
<string name="keyword_search">關鍵字搜尋</string>
|
||||
<string name="image_search">圖片搜尋</string>
|
||||
<string name="search_normal">一般搜尋</string>
|
||||
<string name="search_advance">進階選項</string>
|
||||
<string name="search_image">圖片搜尋</string>
|
||||
<string name="search_normal_search">一般搜尋</string>
|
||||
<string name="search_subscription_search">訂閱搜尋</string>
|
||||
<string name="search_specify_uploader">指定上傳者</string>
|
||||
<string name="search_specify_tag">指定標籤</string>
|
||||
<string name="search_enable_advance">啟用進階選項</string>
|
||||
<string name="search_tip">一般搜尋:就是搜尋。\n\n訂閱搜尋:在訂閱中搜尋。\n\n指定上傳者:列出該上傳者上傳的圖庫。其他選項會被忽略。\n\n指定標籤:列出含有該標籤的圖庫。其他選項會被忽略。</string>
|
||||
<string name="search_sh">已被移除</string>
|
||||
<string name="search_sto">有種子</string>
|
||||
<string name="search_sr">最低評分:</string>
|
||||
<string name="search_sp">頁數:</string>
|
||||
<string name="search_sp_to">到</string>
|
||||
<string name="search_sp_err1">頁數最大值至少為 10</string>
|
||||
<string name="search_sp_err2">頁數範圍差至少為 20</string>
|
||||
@@ -307,7 +295,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">登出</string>
|
||||
<string name="settings_eh_identity_cookies_signed">身份 Cookie 可用於登入該帳號。<br><b>請注意資料安全</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">訪客模式</string>
|
||||
<string name="settings_eh_identity_cookies_guest">訪客模式</string>
|
||||
<string name="settings_eh_identity_cookies_copy">複製 Cookies</string>
|
||||
<string name="settings_u_config">EHentai 設定</string>
|
||||
<string name="settings_u_config_summary">EHentai 網站上的設定</string>
|
||||
|
||||
@@ -56,6 +56,5 @@
|
||||
<dimen name="gallery_detail_thumb_height">192dp</dimen>
|
||||
|
||||
<dimen name="bottom_sheet_width">0dp</dimen>
|
||||
<dimen name="screen_edge_margin">16dp</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
<resources>
|
||||
|
||||
<item name="copy" type="id" />
|
||||
<item name="reader_pager" type="id" />
|
||||
|
||||
</resources>
|
||||
@@ -96,12 +96,10 @@
|
||||
<string name="app_waring_2">By continuing to use it, you agree to the above terms.</string>
|
||||
<string name="error_username_cannot_empty">Username cannot be an empty string</string>
|
||||
<string name="error_password_cannot_empty">Password cannot be an empty string</string>
|
||||
<string name="tourist_mode">Continue without signing in</string>
|
||||
<string name="guest_mode">Continue without signing in</string>
|
||||
<string name="sign_in_failed">Sign in failed</string>
|
||||
<string name="sign_in_failed_tip">If this issue continues, try \"Sign in via WebView\" or \"Sign in via cookies\".</string>
|
||||
<string name="get_it">Got it</string>
|
||||
<string name="cloudflare_bypass_failed">Failed to bypass Cloudflare challenge</string>
|
||||
<string name="open_in_webview">Open URL in WebView to finish the challenge?</string>
|
||||
<!-- Select scene -->
|
||||
<string name="select_scene">Which gallery site do you want to visit?</string>
|
||||
<string name="select_scene_explain">e-hentai: available for anyone\nexhentai: available for who has signed in</string>
|
||||
@@ -112,22 +110,12 @@
|
||||
<string name="gallery_list_search_bar_open_gallery">Open the gallery</string>
|
||||
<string name="gallery_list_empty_hit">The World is Big and the panda sit alone</string>
|
||||
<string name="gallery_list_empty_hit_subscription">Subscribe to tags in Settings->EH->My tags</string>
|
||||
<string name="search">Search</string>
|
||||
<string name="keyword_search">Keyword search</string>
|
||||
<string name="image_search">Image search</string>
|
||||
<string name="search_normal">Normal Search</string>
|
||||
<string name="search_advance">Advanced Options</string>
|
||||
<string name="search_image">Image Search</string>
|
||||
<string name="search_normal_search">Normal search</string>
|
||||
<string name="search_subscription_search">Subscription search</string>
|
||||
<string name="search_specify_uploader">Specify uploader</string>
|
||||
<string name="search_specify_tag">Specify tag</string>
|
||||
<string name="search_enable_advance">Enable advance options</string>
|
||||
<string name="search_tip">Normal search: Simply search.\n\nSubscription search: Search in subscriptions.\n\nSpecify uploader: Search for galleries uploaded by the specified uploader. All other options will be ignored.\n\nSpecify tag: Search for galleries that contain the specified tag. Only one tag accepted. Other options will be ignored.</string>
|
||||
<string name="search_sh">Expunged</string>
|
||||
<string name="search_sto">Has Torrent</string>
|
||||
<string name="search_sr">Minimum Rating:</string>
|
||||
<string name="search_sp">Pages:</string>
|
||||
<string name="search_sp_to">to</string>
|
||||
<string name="search_sp_err1">The page range maximum cannot be below 10</string>
|
||||
<string name="search_sp_err2">The page range must be at least 20</string>
|
||||
@@ -348,7 +336,7 @@
|
||||
<string name="settings_eh">EH</string>
|
||||
<string name="settings_eh_sign_out">Sign out</string>
|
||||
<string name="settings_eh_identity_cookies_signed">Identity cookies can be used to sign in to this account.<br><b>KEEP IT SAFE</b><br><br>%s</string>
|
||||
<string name="settings_eh_identity_cookies_tourist">Tourist mode</string>
|
||||
<string name="settings_eh_identity_cookies_guest">Guest mode</string>
|
||||
<string name="settings_eh_identity_cookies_copy">Copy Cookies</string>
|
||||
<string name="settings_u_config">EHentai settings</string>
|
||||
<string name="settings_u_config_summary">Settings on EHentai website</string>
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
\* 不支持压缩包和 GIF
|
||||
|
||||
** 在不支持 [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine) 的设备上回退到 Apache5
|
||||
** 在不支持 [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine) 的设备上回退到 OkHttp
|
||||
|
||||
<a href="https://github.com/FooIbar/EhViewer/releases">
|
||||
<img alt="Get it on GitHub" src="https://github.com/Ehviewer-Overhauled/Art/blob/master/get-it-on-github.svg" width="200px"/>
|
||||
@@ -94,6 +94,7 @@
|
||||
- [Kotlin & KotlinX](https://kotlinlang.org/)
|
||||
- [MDC-Android](https://github.com/material-components/material-components-android)
|
||||
- [Material Icons](https://github.com/google/material-design-icons)
|
||||
- [OkHttp](https://square.github.io/okhttp/)
|
||||
- [Ktor](https://ktor.io/)
|
||||
- [Coil](https://coil-kt.github.io/coil/)
|
||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
|
||||
\* 不支援壓縮包和 GIF
|
||||
|
||||
** 在不支援 [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine) 的裝置上回退到 Apache5
|
||||
** 在不支援 [HttpEngine](https://developer.android.com/reference/android/net/http/HttpEngine) 的裝置上回退到 OkHttp
|
||||
|
||||
<a href="https://github.com/FooIbar/EhViewer/releases">
|
||||
<img alt="Get it on GitHub" src="https://github.com/Ehviewer-Overhauled/Art/blob/master/get-it-on-github.svg" width="200px"/>
|
||||
@@ -94,6 +94,7 @@
|
||||
- [Kotlin & KotlinX](https://kotlinlang.org/)
|
||||
- [MDC-Android](https://github.com/material-components/material-components-android)
|
||||
- [Material Icons](https://github.com/google/material-design-icons)
|
||||
- [OkHttp](https://square.github.io/okhttp/)
|
||||
- [Ktor](https://ktor.io/)
|
||||
- [Coil](https://coil-kt.github.io/coil/)
|
||||
- [Compose Destinations](https://composedestinations.rafaelcosta.xyz/)
|
||||
|
||||
@@ -28,7 +28,8 @@ kotlinx-serialization = "1.6.2"
|
||||
ksp = "2.0.0-Beta1-1.0.15"
|
||||
ktlint = "1.0.1"
|
||||
ktor = "3.0.0-beta-1"
|
||||
okio = "3.6.0"
|
||||
okhttp3 = "5.0.0-alpha.12"
|
||||
okio = "3.7.0"
|
||||
splitties = "3.0.0"
|
||||
|
||||
[libraries]
|
||||
@@ -95,10 +96,12 @@ kotlinx-serialization-json-okio = { module = "org.jetbrains.kotlinx:kotlinx-seri
|
||||
# For renovate
|
||||
ktlint = { module = "com.pinterest:ktlint", version.ref = "ktlint" }
|
||||
|
||||
ktor-client-apache5 = { module = "io.ktor:ktor-client-apache5", version.ref = "ktor" }
|
||||
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
|
||||
|
||||
material = { module = "com.google.android.material:material", version.ref = "google-android-material" }
|
||||
|
||||
okhttp-android = { module = "com.squareup.okhttp3:okhttp-android" }
|
||||
okhttp-bom = { module = "com.squareup.okhttp3:okhttp-bom", version.ref = "okhttp3" }
|
||||
okio-jvm = { module = "com.squareup.okio:okio-jvm", version.ref = "okio" }
|
||||
|
||||
photoview = "com.github.chrisbanes:PhotoView:2.3.0"
|
||||
@@ -118,7 +121,8 @@ coil = ["coil-compose", "coil-gif"]
|
||||
compose = ["compose-foundation", "compose-material-icons-extended", "compose-material3", "compose-material3-windowsizeclass", "compose-ui-util"]
|
||||
cronet = ["cronet-api", "cronet-gms"]
|
||||
kotlinx-serialization = ["kotlinx-serialization-cbor", "kotlinx-serialization-json", "kotlinx-serialization-json-okio"]
|
||||
ktor = ["ktor-client-apache5"]
|
||||
ktor = ["ktor-client-okhttp"]
|
||||
okhttp = ["okhttp-android"]
|
||||
splitties = ["splitties-appctx", "splitties-arch-room", "splitties-preferences", "splitties-systemservices"]
|
||||
|
||||
[plugins]
|
||||
|
||||
Reference in new issue
Block a user