commit
1cc6999e5b
@ -0,0 +1,69 @@ |
|||||||
|
package io.legado.app.help |
||||||
|
|
||||||
|
import io.legado.app.utils.startActivity |
||||||
|
import io.legado.app.constant.AppLog |
||||||
|
import io.legado.app.exception.NoStackTraceException |
||||||
|
import io.legado.app.data.entities.BaseSource |
||||||
|
import io.legado.app.ui.browser.WebViewActivity |
||||||
|
import io.legado.app.ui.association.VerificationCodeActivity |
||||||
|
import splitties.init.appCtx |
||||||
|
import kotlinx.coroutines.runBlocking |
||||||
|
|
||||||
|
|
||||||
|
object SourceVerificationHelp { |
||||||
|
|
||||||
|
/** |
||||||
|
* 获取书源验证结果 |
||||||
|
* 图片验证码 防爬 滑动验证码 点击字符 等等 |
||||||
|
*/ |
||||||
|
fun getVerificationResult(source: BaseSource?, url: String, title: String, useBrowser: Boolean): String { |
||||||
|
source ?: throw NoStackTraceException("getVerificationResult parameter source cannot be null") |
||||||
|
return runBlocking { |
||||||
|
val key = "${source?.getKey() ?: ""}_verificationResult" |
||||||
|
CacheManager.delete(key) |
||||||
|
|
||||||
|
if (!useBrowser) { |
||||||
|
appCtx.startActivity<VerificationCodeActivity> { |
||||||
|
putExtra("imageUrl", url) |
||||||
|
putExtra("sourceOrigin", source?.getKey()) |
||||||
|
} |
||||||
|
} else { |
||||||
|
startBrowser(source, url, title, true) |
||||||
|
} |
||||||
|
|
||||||
|
var waitUserInput: Boolean = false |
||||||
|
while(CacheManager.get(key) == null) { |
||||||
|
if (!waitUserInput) { |
||||||
|
AppLog.putDebug("等待返回验证结果...") |
||||||
|
waitUserInput = true |
||||||
|
} |
||||||
|
} |
||||||
|
CacheManager.get(key)!!.let { |
||||||
|
if (it.isBlank()) { |
||||||
|
throw NoStackTraceException("验证结果为空") |
||||||
|
} else { |
||||||
|
it |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* 启动内置浏览器 |
||||||
|
@param saveResult 保存网页源代码到数据库 |
||||||
|
*/ |
||||||
|
fun startBrowser(source: BaseSource?, url: String, title: String, saveResult: Boolean? = false) { |
||||||
|
source ?: throw NoStackTraceException("startBrowser parameter source cannot be null") |
||||||
|
appCtx.startActivity<WebViewActivity> { |
||||||
|
putExtra("title", title) |
||||||
|
putExtra("url", url) |
||||||
|
putExtra("sourceOrigin", source?.getKey()) |
||||||
|
putExtra("sourceVerificationEnable", saveResult) |
||||||
|
IntentData.put(url, source?.getHeaderMap(true)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
private fun checkActivityStatus(): Boolean { |
||||||
|
return true |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,26 @@ |
|||||||
|
package io.legado.app.ui.association |
||||||
|
|
||||||
|
import android.os.Bundle |
||||||
|
import io.legado.app.base.BaseActivity |
||||||
|
import io.legado.app.databinding.ActivityTranslucenceBinding |
||||||
|
import io.legado.app.utils.showDialogFragment |
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding |
||||||
|
|
||||||
|
/** |
||||||
|
* 验证码 |
||||||
|
*/ |
||||||
|
class VerificationCodeActivity : |
||||||
|
BaseActivity<ActivityTranslucenceBinding>() { |
||||||
|
|
||||||
|
override val binding by viewBinding(ActivityTranslucenceBinding::inflate) |
||||||
|
|
||||||
|
override fun onActivityCreated(savedInstanceState: Bundle?) { |
||||||
|
intent.getStringExtra("imageUrl")?.let { |
||||||
|
val sourceOrigin = intent.getStringExtra("sourceOrigin") |
||||||
|
showDialogFragment( |
||||||
|
VerificationCodeDialog(it, sourceOrigin) |
||||||
|
) |
||||||
|
} ?: finish() |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,84 @@ |
|||||||
|
package io.legado.app.ui.association |
||||||
|
|
||||||
|
import android.os.Bundle |
||||||
|
import android.view.View |
||||||
|
import android.view.ViewGroup |
||||||
|
import android.net.Uri |
||||||
|
import com.bumptech.glide.request.RequestOptions |
||||||
|
import io.legado.app.R |
||||||
|
import io.legado.app.base.BaseDialogFragment |
||||||
|
import io.legado.app.databinding.DialogVerificationCodeViewBinding |
||||||
|
import io.legado.app.help.CacheManager |
||||||
|
import io.legado.app.help.glide.ImageLoader |
||||||
|
import io.legado.app.help.glide.OkHttpModelLoader |
||||||
|
import io.legado.app.lib.theme.primaryColor |
||||||
|
import io.legado.app.ui.widget.dialog.PhotoDialog |
||||||
|
import io.legado.app.utils.setLayout |
||||||
|
import io.legado.app.utils.showDialogFragment |
||||||
|
import io.legado.app.utils.viewbindingdelegate.viewBinding |
||||||
|
|
||||||
|
/** |
||||||
|
* 图片验证码对话框 |
||||||
|
* 结果保存在数据库中 |
||||||
|
* val key = "${sourceOrigin ?: ""}_verificationResult" |
||||||
|
* CacheManager.get(key) |
||||||
|
*/ |
||||||
|
class VerificationCodeDialog() : BaseDialogFragment(R.layout.dialog_verification_code_view) { |
||||||
|
|
||||||
|
constructor(imageUrl: String, sourceOrigin: String? = null) : this() { |
||||||
|
arguments = Bundle().apply { |
||||||
|
putString("sourceOrigin", sourceOrigin) |
||||||
|
putString("imageUrl", imageUrl) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
val binding by viewBinding(DialogVerificationCodeViewBinding::bind) |
||||||
|
|
||||||
|
override fun onStart() { |
||||||
|
super.onStart() |
||||||
|
setLayout(1f, ViewGroup.LayoutParams.WRAP_CONTENT) |
||||||
|
} |
||||||
|
|
||||||
|
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) { |
||||||
|
binding.run { |
||||||
|
toolBar.setBackgroundColor(primaryColor) |
||||||
|
val sourceOrigin = arguments?.getString("sourceOrigin") |
||||||
|
val key = "${sourceOrigin ?: ""}_verificationResult" |
||||||
|
arguments?.getString("imageUrl")?.let { imageUrl -> |
||||||
|
ImageLoader.load(requireContext(), imageUrl).apply { |
||||||
|
sourceOrigin?.let { |
||||||
|
apply( |
||||||
|
RequestOptions().set( |
||||||
|
OkHttpModelLoader.sourceOriginOption, |
||||||
|
it |
||||||
|
) |
||||||
|
) |
||||||
|
} |
||||||
|
}.error(R.drawable.image_loading_error) |
||||||
|
.into(ivImage) |
||||||
|
ivImage.setOnClickListener { |
||||||
|
showDialogFragment(PhotoDialog(imageUrl, sourceOrigin)) |
||||||
|
} |
||||||
|
} |
||||||
|
tvOk.setOnClickListener { |
||||||
|
val verificationCode = binding.verificationCode.text.toString() |
||||||
|
verificationCode?.let { |
||||||
|
CacheManager.put(key, it) |
||||||
|
dismiss() |
||||||
|
} |
||||||
|
} |
||||||
|
tvCancel.setOnClickListener { |
||||||
|
dismiss() |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
override fun onDestroy() { |
||||||
|
val sourceOrigin = arguments?.getString("sourceOrigin") |
||||||
|
val key = "${sourceOrigin ?: ""}_verificationResult" |
||||||
|
CacheManager.get(key) ?: CacheManager.put(key, "") |
||||||
|
super.onDestroy() |
||||||
|
activity?.finish() |
||||||
|
} |
||||||
|
|
||||||
|
} |
@ -0,0 +1,70 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
xmlns:tools="http://schemas.android.com/tools" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:orientation="vertical"> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.Toolbar |
||||||
|
android:id="@+id/tool_bar" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:theme="?attr/actionBarStyle" |
||||||
|
app:title="@string/input_verification_code" |
||||||
|
app:popupTheme="@style/AppTheme.PopupOverlay" |
||||||
|
app:titleTextAppearance="@style/ToolbarTitle" /> |
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatImageView |
||||||
|
android:id="@+id/iv_image" |
||||||
|
android:scaleType="fitXY" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="50dp" |
||||||
|
android:paddingLeft="12dp" |
||||||
|
android:paddingRight="12dp" |
||||||
|
android:paddingTop="3dp" |
||||||
|
android:background="?android:attr/selectableItemBackgroundBorderless" |
||||||
|
tools:ignore="UnusedAttribute" /> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.TextInputLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:paddingLeft="12dp" |
||||||
|
android:paddingRight="12dp" |
||||||
|
android:paddingTop="3dp"> |
||||||
|
|
||||||
|
<io.legado.app.lib.theme.view.ThemeEditText |
||||||
|
android:id="@+id/verification_code" |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:hint="@string/verification_code" |
||||||
|
tools:ignore="SpeakableTextPresentCheck,TouchTargetSizeCheck" /> |
||||||
|
|
||||||
|
</io.legado.app.ui.widget.text.TextInputLayout> |
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.flexbox.FlexboxLayout |
||||||
|
android:layout_width="match_parent" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:paddingLeft="12dp" |
||||||
|
android:paddingRight="12dp" |
||||||
|
app:justifyContent="flex_end"> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView |
||||||
|
android:id="@+id/tv_cancel" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:padding="12dp" |
||||||
|
android:text="@string/cancel" |
||||||
|
tools:ignore="RtlHardcoded" /> |
||||||
|
|
||||||
|
<io.legado.app.ui.widget.text.AccentTextView |
||||||
|
android:id="@+id/tv_ok" |
||||||
|
android:layout_width="wrap_content" |
||||||
|
android:layout_height="wrap_content" |
||||||
|
android:padding="12dp" |
||||||
|
android:text="@string/ok" |
||||||
|
tools:ignore="RtlHardcoded" /> |
||||||
|
|
||||||
|
</com.google.android.flexbox.FlexboxLayout> |
||||||
|
</LinearLayout> |
@ -0,0 +1,13 @@ |
|||||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||||
|
<menu xmlns:tools="http://schemas.android.com/tools" |
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android" |
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto" |
||||||
|
tools:ignore="AlwaysShowAction"> |
||||||
|
|
||||||
|
<item |
||||||
|
android:id="@+id/menu_ok" |
||||||
|
android:icon="@drawable/ic_check" |
||||||
|
android:title="@string/ok" |
||||||
|
app:showAsAction="always" /> |
||||||
|
|
||||||
|
</menu> |
Loading…
Reference in new issue