Convert to use accompanist Webview

This commit is contained in:
tarsin committed 2023-06-06 21:54:25 +08:00
1 parent 816d63e432
commit cba05171af
1 file changed
+82 -86
@@ -1,121 +1,117 @@
package com.hippo.ehviewer.ui.login
import android.annotation.SuppressLint
import android.graphics.Color
import android.view.ViewGroup
import android.webkit.CookieManager
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.compose.runtime.Composable
import androidx.compose.runtime.SideEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import com.google.accompanist.web.AccompanistWebViewClient
import com.google.accompanist.web.WebView
import com.google.accompanist.web.rememberWebViewState
import com.hippo.ehviewer.client.EhCookieStore
import com.hippo.ehviewer.client.EhUrl
import com.hippo.ehviewer.client.EhUtils
import com.hippo.ehviewer.ui.FINISH_ROUTE_NAME
import com.hippo.ehviewer.ui.LocalNavController
import com.hippo.ehviewer.ui.SELECT_SITE_ROUTE_NAME
import com.hippo.ehviewer.ui.legacy.DialogWebChromeClient
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.withNonCancellableContext
import eu.kanade.tachiyomi.util.lang.withUIContext
import okhttp3.Cookie
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.HttpUrl.Companion.toHttpUrl
@SuppressLint("SetJavaScriptEnabled")
@Composable
fun WebviewSignInScreen() {
val navController = LocalNavController.current
val context = LocalContext.current
val coroutineScope = rememberCoroutineScope()
AndroidView(factory = {
EhUtils.signOut()
val state = rememberWebViewState(url = EhUrl.URL_SIGN_IN)
val client = remember {
object : AccompanistWebViewClient() {
private var present = false
fun parseCookies(url: HttpUrl?, cookieStrings: String?): List<Cookie> {
if (cookieStrings == null) {
return emptyList()
}
var cookies: MutableList<Cookie>? = null
val pieces =
cookieStrings.split(";".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()
for (piece in pieces) {
val cookie = Cookie.parse(url!!, piece) ?: continue
if (cookies == null) {
cookies = ArrayList()
}
cookies.add(cookie)
}
return cookies ?: emptyList()
}
// http://stackoverflow.com/questions/32284642/how-to-handle-an-uncatched-exception
fun addCookie(domain: String, cookie: Cookie) {
EhCookieStore.addCookie(
EhCookieStore.newCookie(
cookie,
domain,
forcePersistent = true,
forceLongLive = true,
forceNotHostOnly = true,
),
)
}
override fun onPageFinished(view: WebView, url: String?) {
if (present) {
view.destroy()
return
}
val httpUrl = url?.toHttpUrl() ?: return
val cookieString = CookieManager.getInstance().getCookie(EhUrl.HOST_E)
val cookies = parseCookies(httpUrl, cookieString)
var getId = false
var getHash = false
for (cookie in cookies) {
if (EhCookieStore.KEY_IPB_MEMBER_ID == cookie.name) {
getId = true
} else if (EhCookieStore.KEY_IPB_PASS_HASH == cookie.name) {
getHash = true
}
}
if (getId && getHash) {
present = true
coroutineScope.launchIO {
val canEx = withNonCancellableContext {
cookies.forEach {
addCookie(EhUrl.DOMAIN_EX, it)
addCookie(EhUrl.DOMAIN_E, it)
}
postLogin()
}
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
}
}
}
}
}
SideEffect {
EhUtils.signOut()
CookieManager.getInstance().apply {
flush()
removeAllCookies(null)
removeSessionCookies(null)
}
WebView(context).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
)
setBackgroundColor(Color.TRANSPARENT)
settings.run {
}
WebView(
state = state,
onCreated = {
it.settings.run {
builtInZoomControls = true
displayZoomControls = true
javaScriptEnabled = true
}
webViewClient = object : WebViewClient() {
private var present = false
fun parseCookies(url: HttpUrl?, cookieStrings: String?): List<Cookie> {
if (cookieStrings == null) {
return emptyList()
}
var cookies: MutableList<Cookie>? = null
val pieces =
cookieStrings.split(";".toRegex()).dropLastWhile { it.isEmpty() }
.toTypedArray()
for (piece in pieces) {
val cookie = Cookie.parse(url!!, piece) ?: continue
if (cookies == null) {
cookies = ArrayList()
}
cookies.add(cookie)
}
return cookies ?: emptyList()
}
fun addCookie(domain: String, cookie: Cookie) {
EhCookieStore.addCookie(
EhCookieStore.newCookie(
cookie,
domain,
forcePersistent = true,
forceLongLive = true,
forceNotHostOnly = true,
),
)
}
override fun onPageFinished(view: WebView, url: String) {
if (present) {
view.destroy()
return
}
val httpUrl = url.toHttpUrlOrNull() ?: return
val cookieString = CookieManager.getInstance().getCookie(EhUrl.HOST_E)
val cookies = parseCookies(httpUrl, cookieString)
var getId = false
var getHash = false
for (cookie in cookies) {
if (EhCookieStore.KEY_IPB_MEMBER_ID == cookie.name) {
getId = true
} else if (EhCookieStore.KEY_IPB_PASS_HASH == cookie.name) {
getHash = true
}
}
if (getId && getHash) {
present = true
coroutineScope.launchIO {
val canEx = withNonCancellableContext {
cookies.forEach {
addCookie(EhUrl.DOMAIN_EX, it)
addCookie(EhUrl.DOMAIN_E, it)
}
postLogin()
}
withUIContext { navController.navigate(if (canEx) SELECT_SITE_ROUTE_NAME else FINISH_ROUTE_NAME) }
}
}
}
}
webChromeClient = DialogWebChromeClient(context)
loadUrl(EhUrl.URL_SIGN_IN)
}
})
},
client = client,
)
}