实现JS方法(openUrl),能够弹窗提示用户是否跳转外部链接 (#4649)

* feat(ui): 添加外部链接跳转确认对话框

- 新增 ConfirmationDialogActivity 用于显示跳转确认对话框
- 在 AndroidManifest.xml 中注册新活动
- 添加 confirmation_dialog.xml 布局文件- 在 JsExtensions.kt 中实现 openUrl 函数以启动对话框
- 更新 styles.xml 添加透明主题样式
- 在 strings.xml 中添加新的错误提示字符串

* feat(dialog): 优化外部链接/应用跳转确认对话框

- 更新对话框布局,增加文本大小设置
- 添加来源标签显示,提高用户识别度
- 优化对话框逻辑,正确处理视图初始化顺序
- 更新字符串资源,支持来源标签显示

---------

Co-authored-by: SunQAQ <sunqi87c6@gmail.com>
This commit is contained in:
Sun-QAQ
2025-02-11 19:49:08 +08:00
committed by GitHub
co-authored by SunQAQ
parent 7bad3e3967
commit f25e885b48
6 changed files with 158 additions and 0 deletions
@@ -2,6 +2,8 @@ package io.legado.app.help
import android.net.Uri
import android.webkit.WebSettings
import android.app.AlertDialog
import android.content.Intent
import androidx.annotation.Keep
import cn.hutool.core.codec.Base64
import cn.hutool.core.util.HexUtil
@@ -21,6 +23,7 @@ import io.legado.app.help.source.SourceVerificationHelp
import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.analyzeRule.QueryTTF
import io.legado.app.ui.javascript.ConfirmationDialogActivity
import io.legado.app.utils.ArchiveUtils
import io.legado.app.utils.ChineseUtils
import io.legado.app.utils.EncoderUtils
@@ -45,9 +48,11 @@ import io.legado.app.utils.readText
import io.legado.app.utils.stackTraceStr
import io.legado.app.utils.toStringArray
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.async
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import okio.use
import org.jsoup.Connection
import org.jsoup.Jsoup
@@ -958,4 +963,17 @@ interface JsExtensions : JsEncodeUtils {
return AppConst.androidId
}
fun openUrl(url: String) {
try {
val intent = Intent(appCtx, ConfirmationDialogActivity::class.java).apply {
data = Uri.parse(url)
putExtra("sourceTag", getSource()?.getTag() ?: "") // 添加来源标签参数
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
appCtx.startActivity(intent)
} catch (e: Exception) {
AppLog.put("启动跳转对话框失败", e)
appCtx.toastOnUi("启动跳转确认失败")
}
}
}
@@ -0,0 +1,63 @@
package io.legado.app.ui.javascript
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.widget.Toolbar
import androidx.appcompat.app.AppCompatActivity
import io.legado.app.R
import io.legado.app.constant.AppLog
import io.legado.app.ui.widget.text.AccentTextView
import io.legado.app.utils.toastOnUi
class ConfirmationDialogActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 必须先设置布局再获取控件
setContentView(R.layout.confirmation_dialog)
// 正确顺序:先设置布局再获取视图
val messageView = findViewById<TextView>(R.id.message)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
val btnNegative = findViewById<AccentTextView>(R.id.btn_negative)
val btnPositive = findViewById<AccentTextView>(R.id.btn_positive)
val url = intent?.dataString
if (url.isNullOrBlank()) {
finish()
return
}
// 处理来源标签显示
val sourceTag = intent.getStringExtra("sourceTag").takeIf { !it.isNullOrBlank() } ?: "当前来源"
messageView.text = "$sourceTag 正在请求跳转外部链接/应用,是否跳转?"
// 设置其他组件
toolbar.setNavigationOnClickListener { finish() }
btnNegative.setOnClickListener { finish() }
btnPositive.setOnClickListener {
try {
startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(url)).apply {
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
)
} catch (e: ActivityNotFoundException) {
toastOnUi(R.string.can_not_open)
} catch (e: Exception) {
AppLog.put("打开链接失败", e)
toastOnUi(R.string.error_occurred)
}
finish()
}
}
override fun onBackPressed() {
super.onBackPressed()
finish()
}
}