Convert EhLoginActivity to compose
This commit is contained in:
parent
f28342601b
commit
3807fb0607
@ -0,0 +1,197 @@
|
|||||||
|
package eu.kanade.presentation.webview
|
||||||
|
|
||||||
|
import android.content.pm.ApplicationInfo
|
||||||
|
import android.webkit.CookieManager
|
||||||
|
import android.webkit.WebView
|
||||||
|
import androidx.compose.animation.core.animateFloatAsState
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.Arrangement
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Column
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxWidth
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.Close
|
||||||
|
import androidx.compose.material3.LinearProgressIndicator
|
||||||
|
import androidx.compose.material3.ProgressIndicatorDefaults
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.produceState
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Dialog
|
||||||
|
import com.google.accompanist.web.AccompanistWebViewClient
|
||||||
|
import com.google.accompanist.web.LoadingState
|
||||||
|
import com.google.accompanist.web.WebContent
|
||||||
|
import com.google.accompanist.web.WebView
|
||||||
|
import com.google.accompanist.web.rememberWebViewNavigator
|
||||||
|
import com.google.accompanist.web.rememberWebViewState
|
||||||
|
import eu.kanade.presentation.components.AppBar
|
||||||
|
import eu.kanade.presentation.components.Button
|
||||||
|
import eu.kanade.presentation.components.Scaffold
|
||||||
|
import eu.kanade.tachiyomi.BuildConfig
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun EhLoginWebViewScreen(
|
||||||
|
onUp: () -> Unit,
|
||||||
|
onPageFinished: (view: WebView, url: String) -> Unit,
|
||||||
|
onClickRecheckLoginStatus: (loadUrl: (String) -> Unit) -> Unit,
|
||||||
|
onClickAlternateLoginPage: (loadUrl: (String) -> Unit) -> Unit,
|
||||||
|
onClickSkipPageRestyling: (loadUrl: (String) -> Unit) -> Unit,
|
||||||
|
onClickCustomIgneousCookie: () -> Unit,
|
||||||
|
) {
|
||||||
|
val state = rememberWebViewState(
|
||||||
|
url = "https://forums.e-hentai.org/index.php?act=Login",
|
||||||
|
)
|
||||||
|
val navigator = rememberWebViewNavigator()
|
||||||
|
val loading by produceState(true) {
|
||||||
|
CookieManager.getInstance().removeAllCookies {
|
||||||
|
value = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Scaffold(
|
||||||
|
topBar = {
|
||||||
|
Box {
|
||||||
|
AppBar(
|
||||||
|
title = "ExHentai login",
|
||||||
|
navigateUp = onUp,
|
||||||
|
navigationIcon = Icons.Default.Close,
|
||||||
|
)
|
||||||
|
when (val loadingState = state.loadingState) {
|
||||||
|
is LoadingState.Initializing -> LinearProgressIndicator(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.BottomCenter),
|
||||||
|
)
|
||||||
|
is LoadingState.Loading -> {
|
||||||
|
val animatedProgress by animateFloatAsState(
|
||||||
|
(loadingState as? LoadingState.Loading)?.progress ?: 1f,
|
||||||
|
animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec,
|
||||||
|
)
|
||||||
|
LinearProgressIndicator(
|
||||||
|
progress = animatedProgress,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.align(Alignment.BottomCenter),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
) { contentPadding ->
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return@Scaffold
|
||||||
|
}
|
||||||
|
|
||||||
|
val webClient = remember {
|
||||||
|
object : AccompanistWebViewClient() {
|
||||||
|
override fun onPageFinished(view: WebView?, url: String?) {
|
||||||
|
super.onPageFinished(view, url)
|
||||||
|
onPageFinished(view ?: return, url ?: return)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var showAdvancedOptions by remember {
|
||||||
|
mutableStateOf(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(Modifier.padding(contentPadding)) {
|
||||||
|
Box {
|
||||||
|
WebView(
|
||||||
|
state = state,
|
||||||
|
navigator = navigator,
|
||||||
|
modifier = Modifier.padding(bottom = 48.dp),
|
||||||
|
onCreated = { webView ->
|
||||||
|
webView.setDefaultSettings()
|
||||||
|
|
||||||
|
// Debug mode (chrome://inspect/#devices)
|
||||||
|
if (BuildConfig.DEBUG &&
|
||||||
|
0 != webView.context.applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE
|
||||||
|
) {
|
||||||
|
WebView.setWebContentsDebuggingEnabled(true)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
client = webClient,
|
||||||
|
)
|
||||||
|
Row(
|
||||||
|
Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.height(48.dp)
|
||||||
|
.align(Alignment.BottomCenter),
|
||||||
|
horizontalArrangement = Arrangement.SpaceBetween,
|
||||||
|
) {
|
||||||
|
Button(onClick = onUp, Modifier.weight(0.5F)) {
|
||||||
|
Text(text = stringResource(android.R.string.cancel))
|
||||||
|
}
|
||||||
|
Button(onClick = { showAdvancedOptions = true }, Modifier.weight(0.5F)) {
|
||||||
|
Text(text = stringResource(R.string.pref_category_advanced))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (showAdvancedOptions) {
|
||||||
|
Box(Modifier.background(Color(0xb5000000))) {
|
||||||
|
Dialog(onDismissRequest = { showAdvancedOptions = false }) {
|
||||||
|
fun loadUrl(url: String) {
|
||||||
|
state.content = WebContent.Url(url)
|
||||||
|
}
|
||||||
|
Column(Modifier.fillMaxWidth(0.8F)) {
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onClickRecheckLoginStatus(::loadUrl)
|
||||||
|
showAdvancedOptions = false
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.recheck_login_status))
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onClickAlternateLoginPage(::loadUrl)
|
||||||
|
showAdvancedOptions = false
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.alternative_login_page))
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onClickSkipPageRestyling(::loadUrl)
|
||||||
|
showAdvancedOptions = false
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.skip_page_restyling))
|
||||||
|
}
|
||||||
|
Button(
|
||||||
|
onClick = {
|
||||||
|
onClickCustomIgneousCookie()
|
||||||
|
showAdvancedOptions = false
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(),
|
||||||
|
) {
|
||||||
|
Text(text = stringResource(R.string.custom_igneous_cookie))
|
||||||
|
}
|
||||||
|
Button(onClick = { showAdvancedOptions = false }, Modifier.fillMaxWidth()) {
|
||||||
|
Text(text = stringResource(android.R.string.cancel))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,33 +2,21 @@ package exh.ui.login
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.ApplicationInfo
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.webkit.CookieManager
|
import android.webkit.CookieManager
|
||||||
import android.webkit.WebChromeClient
|
|
||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.view.isInvisible
|
|
||||||
import androidx.core.view.isVisible
|
|
||||||
import androidx.lifecycle.lifecycleScope
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import eu.kanade.tachiyomi.BuildConfig
|
import eu.kanade.presentation.webview.EhLoginWebViewScreen
|
||||||
import eu.kanade.tachiyomi.R
|
import eu.kanade.tachiyomi.R
|
||||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||||
import eu.kanade.tachiyomi.databinding.EhActivityLoginBinding
|
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
|
||||||
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
import eu.kanade.tachiyomi.ui.base.activity.BaseActivity
|
||||||
import eu.kanade.tachiyomi.util.lang.launchUI
|
|
||||||
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
import eu.kanade.tachiyomi.util.system.WebViewUtil
|
||||||
import eu.kanade.tachiyomi.util.system.setDefaultSettings
|
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
import eu.kanade.tachiyomi.util.view.setComposeContent
|
||||||
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
import eu.kanade.tachiyomi.widget.materialdialogs.setTextInput
|
||||||
import exh.log.xLogD
|
import exh.log.xLogD
|
||||||
import kotlinx.coroutines.flow.launchIn
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
|
||||||
import reactivecircus.flowbinding.appcompat.navigationClicks
|
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.net.HttpCookie
|
import java.net.HttpCookie
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
@ -37,13 +25,7 @@ import java.util.Locale
|
|||||||
* LoginController
|
* LoginController
|
||||||
*/
|
*/
|
||||||
class EhLoginActivity : BaseActivity() {
|
class EhLoginActivity : BaseActivity() {
|
||||||
lateinit var binding: EhActivityLoginBinding
|
private val preferenceManager: PreferencesHelper by injectLazy()
|
||||||
|
|
||||||
val preferenceManager: PreferencesHelper by injectLazy()
|
|
||||||
|
|
||||||
val sourceManager: SourceManager by injectLazy()
|
|
||||||
|
|
||||||
private var bundle: Bundle? = null
|
|
||||||
|
|
||||||
private var igneous: String? = null
|
private var igneous: String? = null
|
||||||
|
|
||||||
@ -56,95 +38,28 @@ class EhLoginActivity : BaseActivity() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
setComposeContent {
|
||||||
binding = EhActivityLoginBinding.inflate(layoutInflater)
|
EhLoginWebViewScreen(
|
||||||
setContentView(binding.root)
|
onUp = { finish() },
|
||||||
} catch (e: Throwable) {
|
onPageFinished = ::onPageFinished,
|
||||||
// Potentially throws errors like "Error inflating class android.webkit.WebView"
|
onClickRecheckLoginStatus = ::recheckLoginStatus,
|
||||||
toast(R.string.information_webview_required, Toast.LENGTH_LONG)
|
onClickAlternateLoginPage = ::alternateLoginPage,
|
||||||
finish()
|
onClickSkipPageRestyling = ::skipPageRestyling,
|
||||||
return
|
onClickCustomIgneousCookie = ::openIgneousDialog,
|
||||||
}
|
)
|
||||||
|
|
||||||
title = "ExHentai login"
|
|
||||||
|
|
||||||
setSupportActionBar(binding.toolbar)
|
|
||||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
|
||||||
|
|
||||||
binding.toolbar.navigationClicks()
|
|
||||||
.onEach { finish() }
|
|
||||||
.launchIn(lifecycleScope)
|
|
||||||
|
|
||||||
onViewCreated()
|
|
||||||
|
|
||||||
if (bundle == null) {
|
|
||||||
binding.webview.setDefaultSettings()
|
|
||||||
|
|
||||||
// Debug mode (chrome://inspect/#devices)
|
|
||||||
if (BuildConfig.DEBUG && 0 != applicationInfo.flags and ApplicationInfo.FLAG_DEBUGGABLE) {
|
|
||||||
WebView.setWebContentsDebuggingEnabled(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.webview.webChromeClient = object : WebChromeClient() {
|
|
||||||
override fun onProgressChanged(view: WebView?, newProgress: Int) {
|
|
||||||
binding.progressBar.isVisible = true
|
|
||||||
binding.progressBar.progress = newProgress
|
|
||||||
if (newProgress == 100) {
|
|
||||||
binding.progressBar.isInvisible = true
|
|
||||||
}
|
|
||||||
super.onProgressChanged(view, newProgress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
binding.webview.restoreState(bundle!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bundle == null) {
|
|
||||||
startWebview()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onViewCreated() {
|
private fun recheckLoginStatus(loadUrl: (String) -> Unit) {
|
||||||
binding.btnCancel.setOnClickListener { finish() }
|
loadUrl("https://exhentai.org/")
|
||||||
|
}
|
||||||
|
|
||||||
binding.btnAdvanced.setOnClickListener {
|
private fun alternateLoginPage(loadUrl: (String) -> Unit) {
|
||||||
binding.advancedOptions.isVisible = true
|
loadUrl("https://e-hentai.org/bounce_login.php")
|
||||||
binding.webview.isVisible = false
|
}
|
||||||
binding.btnAdvanced.isEnabled = false
|
|
||||||
binding.btnCancel.isEnabled = false
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnClose.setOnClickListener {
|
private fun skipPageRestyling(loadUrl: (String) -> Unit) {
|
||||||
hideAdvancedOptions()
|
loadUrl("https://forums.e-hentai.org/index.php?act=Login&$PARAM_SKIP_INJECT=true")
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnRecheck.setOnClickListener {
|
|
||||||
hideAdvancedOptions()
|
|
||||||
binding.webview.loadUrl("https://exhentai.org/")
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnAltLogin.setOnClickListener {
|
|
||||||
hideAdvancedOptions()
|
|
||||||
binding.webview.loadUrl("https://e-hentai.org/bounce_login.php")
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnSkipRestyle.setOnClickListener {
|
|
||||||
hideAdvancedOptions()
|
|
||||||
binding.webview.loadUrl("https://forums.e-hentai.org/index.php?act=Login&$PARAM_SKIP_INJECT=true")
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.btnIgneousCookie.setOnClickListener {
|
|
||||||
hideAdvancedOptions()
|
|
||||||
openIgneousDialog()
|
|
||||||
}
|
|
||||||
|
|
||||||
CookieManager.getInstance().removeAllCookies {
|
|
||||||
launchUI {
|
|
||||||
if (bundle == null) {
|
|
||||||
startWebview()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun openIgneousDialog() {
|
private fun openIgneousDialog() {
|
||||||
@ -164,54 +79,33 @@ class EhLoginActivity : BaseActivity() {
|
|||||||
.show()
|
.show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideAdvancedOptions() {
|
private fun onPageFinished(view: WebView, url: String) {
|
||||||
binding.advancedOptions.isVisible = false
|
xLogD(url)
|
||||||
binding.webview.isVisible = true
|
val parsedUrl = Uri.parse(url)
|
||||||
binding.btnAdvanced.isEnabled = true
|
if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
|
||||||
binding.btnCancel.isEnabled = true
|
// Hide distracting content
|
||||||
}
|
if (!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT)) {
|
||||||
|
view.evaluateJavascript(HIDE_JS, null)
|
||||||
|
}
|
||||||
|
// Check login result
|
||||||
|
|
||||||
private fun startWebview() {
|
if (parsedUrl.getQueryParameter("code")?.toInt() != 0) {
|
||||||
binding.webview.setDefaultSettings()
|
if (checkLoginCookies(url)) view.loadUrl("https://exhentai.org/")
|
||||||
|
}
|
||||||
binding.webview.loadUrl("https://forums.e-hentai.org/index.php?act=Login")
|
} else if (parsedUrl.host.equals("exhentai.org", ignoreCase = true)) {
|
||||||
|
// At ExHentai, check that everything worked out...
|
||||||
binding.webview.webViewClient = object : WebViewClient() {
|
if (applyExHentaiCookies(url)) {
|
||||||
override fun onPageFinished(view: WebView, url: String) {
|
preferenceManager.enableExhentai().set(true)
|
||||||
super.onPageFinished(view, url)
|
setResult(RESULT_OK)
|
||||||
xLogD(url)
|
finish()
|
||||||
val parsedUrl = Uri.parse(url)
|
|
||||||
if (parsedUrl.host.equals("forums.e-hentai.org", ignoreCase = true)) {
|
|
||||||
// Hide distracting content
|
|
||||||
if (!parsedUrl.queryParameterNames.contains(PARAM_SKIP_INJECT)) {
|
|
||||||
view.evaluateJavascript(HIDE_JS, null)
|
|
||||||
}
|
|
||||||
// Check login result
|
|
||||||
|
|
||||||
if (parsedUrl.getQueryParameter("code")?.toInt() != 0) {
|
|
||||||
if (checkLoginCookies(url)) view.loadUrl("https://exhentai.org/")
|
|
||||||
}
|
|
||||||
} else if (parsedUrl.host.equals("exhentai.org", ignoreCase = true)) {
|
|
||||||
// At ExHentai, check that everything worked out...
|
|
||||||
if (applyExHentaiCookies(url)) {
|
|
||||||
preferenceManager.enableExhentai().set(true)
|
|
||||||
setResult(RESULT_OK)
|
|
||||||
finish()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
binding.webview?.destroy()
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if we are logged in
|
* Check if we are logged in
|
||||||
*/
|
*/
|
||||||
fun checkLoginCookies(url: String): Boolean {
|
private fun checkLoginCookies(url: String): Boolean {
|
||||||
getCookies(url)?.let { parsed ->
|
getCookies(url)?.let { parsed ->
|
||||||
return parsed.count {
|
return parsed.count {
|
||||||
(
|
(
|
||||||
@ -227,7 +121,7 @@ class EhLoginActivity : BaseActivity() {
|
|||||||
/**
|
/**
|
||||||
* Parse cookies at ExHentai
|
* Parse cookies at ExHentai
|
||||||
*/
|
*/
|
||||||
fun applyExHentaiCookies(url: String): Boolean {
|
private fun applyExHentaiCookies(url: String): Boolean {
|
||||||
getCookies(url)?.let { parsed ->
|
getCookies(url)?.let { parsed ->
|
||||||
|
|
||||||
var memberId: String? = null
|
var memberId: String? = null
|
||||||
|
Loading…
x
Reference in New Issue
Block a user