diff --git a/app/src/main/java/com/hippo/ehviewer/ui/login/WebviewSignInScreen.kt b/app/src/main/java/com/hippo/ehviewer/ui/login/WebviewSignInScreen.kt index ca089c99c..d5bafb788 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/login/WebviewSignInScreen.kt +++ b/app/src/main/java/com/hippo/ehviewer/ui/login/WebviewSignInScreen.kt @@ -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 { + if (cookieStrings == null) { + return emptyList() + } + var cookies: MutableList? = 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 { - if (cookieStrings == null) { - return emptyList() - } - var cookies: MutableList? = 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, + ) }