diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 0b2ad12fd..07a76c223 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -340,7 +340,11 @@
+
+
-
-
diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt
index b002aacb0..8d0f7ffb1 100644
--- a/app/src/main/java/io/legado/app/help/JsExtensions.kt
+++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt
@@ -1,6 +1,5 @@
package io.legado.app.help
-import android.content.Intent
import android.net.Uri
import android.webkit.WebSettings
import androidx.annotation.Keep
@@ -22,7 +21,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.ui.association.OpenUrlConfirmActivity
import io.legado.app.utils.ArchiveUtils
import io.legado.app.utils.ChineseUtils
import io.legado.app.utils.EncoderUtils
@@ -45,6 +44,7 @@ import io.legado.app.utils.longToastOnUi
import io.legado.app.utils.readBytes
import io.legado.app.utils.readText
import io.legado.app.utils.stackTraceStr
+import io.legado.app.utils.startActivity
import io.legado.app.utils.toStringArray
import io.legado.app.utils.toastOnUi
import kotlinx.coroutines.Dispatchers.IO
@@ -966,23 +966,12 @@ interface JsExtensions : JsEncodeUtils {
// 新增 mimeType 参数,默认为 null(保持兼容性)
fun openUrl(url: String, mimeType: String? = null) {
- try {
- val intent = Intent(appCtx, ConfirmationDialogActivity::class.java).apply {
- // 同时设置 Data 和 Type(避免单独设置 data/type 导致冲突)
- if (mimeType != null) {
- setDataAndType(Uri.parse(url), mimeType)
- } else {
- data = Uri.parse(url)
- }
- putExtra("sourceTag", getSource()?.getTag() ?: "")
- // 可选:添加 MIME 类型到 Extra 供后续逻辑使用
- putExtra("mimeType", mimeType)
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
- appCtx.startActivity(intent)
- } catch (e: Exception) {
- AppLog.put("启动跳转对话框失败", e)
- appCtx.toastOnUi("启动跳转确认失败")
+ val source = getSource() ?: throw NoStackTraceException("openUrl source cannot be null")
+ appCtx.startActivity {
+ putExtra("uri", url)
+ putExtra("mimeType", mimeType)
+ putExtra("sourceOrigin", source.getKey())
+ putExtra("sourceName", source.getTag())
}
}
diff --git a/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmActivity.kt b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmActivity.kt
new file mode 100644
index 000000000..ceb0978b1
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmActivity.kt
@@ -0,0 +1,23 @@
+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 OpenUrlConfirmActivity :
+ BaseActivity() {
+
+ override val binding by viewBinding(ActivityTranslucenceBinding::inflate)
+
+ override fun onActivityCreated(savedInstanceState: Bundle?) {
+ intent.getStringExtra("uri")?.let {
+ val mimeType = intent.getStringExtra("mimeType")
+ val sourceOrigin = intent.getStringExtra("sourceOrigin")
+ val sourceName = intent.getStringExtra("sourceName")
+ showDialogFragment(OpenUrlConfirmDialog(it, mimeType, sourceOrigin, sourceName))
+ } ?: finish()
+ }
+
+}
diff --git a/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmDialog.kt b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmDialog.kt
new file mode 100644
index 000000000..dbf3d443b
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmDialog.kt
@@ -0,0 +1,130 @@
+package io.legado.app.ui.association
+
+import android.content.Intent
+import android.os.Bundle
+import android.view.MenuItem
+import android.view.View
+import android.view.ViewGroup
+import androidx.appcompat.widget.Toolbar
+import androidx.core.net.toUri
+import androidx.fragment.app.viewModels
+import io.legado.app.R
+import io.legado.app.base.BaseDialogFragment
+import io.legado.app.constant.AppLog
+import io.legado.app.databinding.DialogOpenUrlConfirmBinding
+import io.legado.app.lib.dialogs.alert
+import io.legado.app.lib.theme.primaryColor
+import io.legado.app.utils.applyTint
+import io.legado.app.utils.setLayout
+import io.legado.app.utils.toastOnUi
+import io.legado.app.utils.viewbindingdelegate.viewBinding
+import splitties.init.appCtx
+
+class OpenUrlConfirmDialog() : BaseDialogFragment(R.layout.dialog_open_url_confirm),
+ Toolbar.OnMenuItemClickListener {
+
+ constructor(
+ uri: String,
+ mimeType: String?,
+ sourceOrigin: String? = null,
+ sourceName: String? = null
+ ) : this() {
+ arguments = Bundle().apply {
+ putString("uri", uri)
+ putString("mimeType", mimeType)
+ putString("sourceOrigin", sourceOrigin)
+ putString("sourceName", sourceName)
+ }
+ }
+
+ val binding by viewBinding(DialogOpenUrlConfirmBinding::bind)
+ val viewModel by viewModels()
+
+ override fun onStart() {
+ super.onStart()
+ setLayout(1f, ViewGroup.LayoutParams.WRAP_CONTENT)
+ }
+
+ override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
+ initMenu()
+ val arguments = arguments ?: return
+ viewModel.initData(arguments)
+ if (viewModel.uri.isBlank()) {
+ dismiss()
+ return
+ }
+ binding.toolBar.setBackgroundColor(primaryColor)
+ binding.toolBar.subtitle = viewModel.sourceName
+ initView()
+ }
+
+ private fun initMenu() {
+ binding.toolBar.setOnMenuItemClickListener(this)
+ binding.toolBar.inflateMenu(R.menu.open_url_confirm)
+ binding.toolBar.menu.applyTint(requireContext())
+ }
+
+ private fun initView() {
+ binding.message.text = "${viewModel.sourceName} 正在请求跳转链接/应用,是否跳转?"
+ binding.btnNegative.setOnClickListener { dismiss() }
+ binding.btnPositive.setOnClickListener {
+ openUrl()
+ dismiss()
+ }
+ }
+
+ private fun openUrl() {
+ try {
+ val uri = viewModel.uri.toUri()
+ val mimeType = viewModel.mimeType
+ // 创建目标 Intent 并设置类型
+ val targetIntent = Intent(Intent.ACTION_VIEW).apply {
+ // 同时设置 Data 和 Type
+ if (!mimeType.isNullOrBlank()) {
+ setDataAndType(uri, mimeType)
+ } else {
+ data = uri
+ }
+ addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ }
+
+ // 验证是否有应用可以处理
+ if (targetIntent.resolveActivity(appCtx.packageManager) != null) {
+ startActivity(targetIntent)
+ } else {
+ toastOnUi(R.string.can_not_open)
+ }
+ } catch (e: Exception) {
+ AppLog.put("打开链接失败", e, true)
+ }
+ }
+
+ override fun onMenuItemClick(item: MenuItem): Boolean {
+ when (item.itemId) {
+ R.id.menu_disable_source -> {
+ viewModel.disableSource {
+ dismiss()
+ }
+ }
+
+ R.id.menu_delete_source -> {
+ alert(R.string.draw) {
+ setMessage(getString(R.string.sure_del) + "\n" + viewModel.sourceName)
+ noButton()
+ yesButton {
+ viewModel.deleteSource {
+ dismiss()
+ }
+ }
+ }
+ }
+ }
+ return false
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ activity?.finish()
+ }
+
+}
diff --git a/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmViewModel.kt b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmViewModel.kt
new file mode 100644
index 000000000..e677fb683
--- /dev/null
+++ b/app/src/main/java/io/legado/app/ui/association/OpenUrlConfirmViewModel.kt
@@ -0,0 +1,38 @@
+package io.legado.app.ui.association
+
+import android.app.Application
+import android.os.Bundle
+import io.legado.app.base.BaseViewModel
+import io.legado.app.data.appDb
+
+class OpenUrlConfirmViewModel(app: Application): BaseViewModel(app) {
+
+ var uri = ""
+ var mimeType: String? = null
+ var sourceOrigin = ""
+ var sourceName = ""
+
+ fun initData(arguments: Bundle) {
+ uri = arguments.getString("uri") ?: ""
+ mimeType = arguments.getString("mimeType")
+ sourceName = arguments.getString("sourceName") ?: ""
+ sourceOrigin = arguments.getString("sourceOrigin") ?: ""
+ }
+
+ fun disableSource(block: () -> Unit) {
+ execute {
+ appDb.bookSourceDao.enable(sourceOrigin, false)
+ }.onSuccess {
+ block.invoke()
+ }
+ }
+
+ fun deleteSource(block: () -> Unit) {
+ execute {
+ appDb.bookSourceDao.delete(sourceOrigin)
+ }.onSuccess {
+ block.invoke()
+ }
+ }
+
+}
diff --git a/app/src/main/java/io/legado/app/ui/javascript/ConfirmationDialogActivity.kt b/app/src/main/java/io/legado/app/ui/javascript/ConfirmationDialogActivity.kt
deleted file mode 100644
index e212ba2f6..000000000
--- a/app/src/main/java/io/legado/app/ui/javascript/ConfirmationDialogActivity.kt
+++ /dev/null
@@ -1,72 +0,0 @@
-package io.legado.app.ui.javascript
-
-import android.content.ActivityNotFoundException
-import android.content.Intent
-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(R.id.message)
- val toolbar = findViewById(R.id.tool_bar)
- val btnNegative = findViewById(R.id.btn_negative)
- val btnPositive = findViewById(R.id.btn_positive)
-
- // 获取原始 Intent 的数据和 MIME 类型
- val uri = intent?.data
- val mimeType = intent?.getStringExtra("mimeType")
- if (uri == null) {
- finish()
- return
- }
-
- // 处理来源标签显示
- val sourceTag = intent.getStringExtra("sourceTag").takeIf { !it.isNullOrBlank() } ?: "当前来源"
- messageView.text = "$sourceTag 正在请求跳转外部链接/应用,是否跳转?"
-
- toolbar.setNavigationOnClickListener { finish() }
- btnNegative.setOnClickListener { finish() }
- btnPositive.setOnClickListener {
- try {
- // 创建目标 Intent 并设置类型
- val targetIntent = Intent(Intent.ACTION_VIEW).apply {
- // 同时设置 Data 和 Type
- if (!mimeType.isNullOrBlank()) {
- setDataAndType(uri, mimeType)
- } else {
- data = uri
- }
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
- }
-
- // 验证是否有应用可以处理
- if (targetIntent.resolveActivity(packageManager) != null) {
- startActivity(targetIntent)
- } else {
- toastOnUi(R.string.can_not_open)
- }
- } 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()
- }
-}
diff --git a/app/src/main/res/layout/confirmation_dialog.xml b/app/src/main/res/layout/confirmation_dialog.xml
deleted file mode 100644
index b8b0b36d1..000000000
--- a/app/src/main/res/layout/confirmation_dialog.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/dialog_open_url_confirm.xml b/app/src/main/res/layout/dialog_open_url_confirm.xml
new file mode 100644
index 000000000..f6e5d147b
--- /dev/null
+++ b/app/src/main/res/layout/dialog_open_url_confirm.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/menu/open_url_confirm.xml b/app/src/main/res/menu/open_url_confirm.xml
new file mode 100644
index 000000000..e85dbaf20
--- /dev/null
+++ b/app/src/main/res/menu/open_url_confirm.xml
@@ -0,0 +1,17 @@
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 00bf22601..a67ff259a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1185,6 +1185,4 @@
主题配置
Download the chapter after
Download all chapter
- 打开失败
- %s正在请求跳转外部链接/应用,是否跳转?
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 7f736e1b6..4bc8faa05 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -127,21 +127,4 @@
- wrap_content
-
-
-
-
-
-
-
-