diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 34c8d8ac5..7e0631a2b 100755
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -135,6 +135,8 @@
android:launchMode="singleTask"
android:taskAffinity=""
android:theme="@android:style/Theme.Translucent.NoTitleBar" />
+
{
binding.tip.text = ExceptionUtils.getReadableString(state.error)
transition.showView(2)
+ if (state.error.cause is CloudflareBypassException) {
+ dialogState.awaitPermissionOrCancel(
+ android.R.string.ok,
+ android.R.string.cancel,
+ R.string.cloudflare_bypass_failed,
+ ) {
+ Text(text = stringResource(id = R.string.open_in_webview))
+ }
+ navAnimated(R.id.webView, bundleOf(WebViewActivity.KEY_URL to EhUrl.host))
+ }
}
is LoadState.NotLoading -> {
delay(500)
diff --git a/app/src/main/java/com/hippo/ehviewer/ui/webview/WebViewScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/webview/WebViewScreen.kt
new file mode 100644
index 000000000..9a83c4ec0
--- /dev/null
+++ b/app/src/main/java/com/hippo/ehviewer/ui/webview/WebViewScreen.kt
@@ -0,0 +1,46 @@
+package com.hippo.ehviewer.ui.webview
+
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.padding
+import androidx.compose.material.icons.Icons
+import androidx.compose.material.icons.filled.Close
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.Scaffold
+import androidx.compose.material3.Text
+import androidx.compose.material3.TopAppBar
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.DisposableEffect
+import androidx.compose.ui.Modifier
+import com.google.accompanist.web.WebView
+import com.google.accompanist.web.rememberWebViewState
+import com.hippo.ehviewer.client.EhCookieStore
+import com.hippo.ehviewer.util.setDefaultSettings
+
+@Composable
+fun WebViewScreen(url: String, onNavigateUp: () -> Unit) {
+ val state = rememberWebViewState(url = url)
+ Scaffold(
+ topBar = {
+ TopAppBar(
+ title = { Text(text = state.pageTitle ?: url) },
+ navigationIcon = {
+ IconButton(onClick = onNavigateUp) {
+ Icon(imageVector = Icons.Default.Close, contentDescription = null)
+ }
+ },
+ )
+ },
+ ) { paddingValues ->
+ WebView(
+ state = state,
+ modifier = Modifier.padding(top = paddingValues.calculateTopPadding()).fillMaxSize(),
+ onCreated = { it.setDefaultSettings() },
+ )
+ DisposableEffect(Unit) {
+ onDispose {
+ EhCookieStore.flush()
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/hippo/ehviewer/util/WebViewExtensions.kt b/app/src/main/java/com/hippo/ehviewer/util/WebViewExtensions.kt
index d68fb01b5..98a08608c 100644
--- a/app/src/main/java/com/hippo/ehviewer/util/WebViewExtensions.kt
+++ b/app/src/main/java/com/hippo/ehviewer/util/WebViewExtensions.kt
@@ -2,10 +2,12 @@ package com.hippo.ehviewer.util
import android.annotation.SuppressLint
import android.webkit.WebView
+import com.hippo.ehviewer.client.CHROME_USER_AGENT
@SuppressLint("SetJavaScriptEnabled")
fun WebView.setDefaultSettings() = settings.run {
builtInZoomControls = true
displayZoomControls = false
javaScriptEnabled = true
+ userAgentString = CHROME_USER_AGENT
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt
index 235b3f7e8..63d75e2ec 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/CloudflareInterceptor.kt
@@ -51,7 +51,7 @@ class CloudflareInterceptor(context: Context) : WebViewInterceptor(context) {
val headers = parseHeaders(originalRequest.headers)
executor.execute {
- webview = createWebView(originalRequest)
+ webview = createWebView()
webview?.webViewClient = object : WebViewClient() {
override fun onPageFinished(view: WebView, url: String) {
@@ -102,7 +102,6 @@ class CloudflareInterceptor(context: Context) : WebViewInterceptor(context) {
// Throw exception if we failed to bypass Cloudflare
if (!cloudflareBypassed) {
- // TODO: Prompt user to open url in WebView and finish the challenge manually
throw CloudflareBypassException()
}
}
diff --git a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt b/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt
index 5eef8000d..26a6eda2c 100644
--- a/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt
+++ b/app/src/main/java/eu/kanade/tachiyomi/network/interceptor/WebViewInterceptor.kt
@@ -56,11 +56,9 @@ abstract class WebViewInterceptor(private val context: Context) : Interceptor {
await(30, TimeUnit.SECONDS)
}
- fun createWebView(request: Request): WebView {
+ fun createWebView(): WebView {
return WebView(context).apply {
setDefaultSettings()
- // Avoid sending empty User-Agent, Chromium WebView will reset to default if empty
- settings.userAgentString = request.header("User-Agent")
}
}
}
diff --git a/app/src/main/res/navigation/nav_graph.xml b/app/src/main/res/navigation/nav_graph.xml
index 15ff2324e..76d913c8f 100644
--- a/app/src/main/res/navigation/nav_graph.xml
+++ b/app/src/main/res/navigation/nav_graph.xml
@@ -76,4 +76,13 @@
android:id="@+id/progressScene"
android:name="com.hippo.ehviewer.ui.scene.ProgressScene"
android:label="ProgressScene" />
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml
index 4b1e98026..b20b277ad 100644
--- a/app/src/main/res/values-zh-rCN/strings.xml
+++ b/app/src/main/res/values-zh-rCN/strings.xml
@@ -64,6 +64,8 @@
登录失败
若持续出错,请尝试“通过网页登录”或“通过 Cookie 登录”。
知道了
+ 未能绕过 Cloudflare 验证
+ 在 WebView 中打开链接以通过验证?
你想选择哪个画廊站点?
e-hentai:对任何人开放\nexhentai:仅对登录用户开放
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 1240f8d86..88c1e814f 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -103,6 +103,8 @@
Sign in failed
If this issue continues, try \"Sign in via WebView\" or \"Sign in via cookies\".
Got it
+ Failed to bypass Cloudflare challenge
+ Open URL in WebView to finish the challenge?
Which gallery site do you want to visit?
e-hentai: available for anyone\nexhentai: available for who has signed in