订阅源网页重定向功能 #171
This commit is contained in:
14 files changed
+2066
-7
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -65,7 +65,7 @@ val appDb by lazy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Database(
|
@Database(
|
||||||
version = 77,
|
version = 78,
|
||||||
exportSchema = true,
|
exportSchema = true,
|
||||||
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
entities = [Book::class, BookGroup::class, BookSource::class, BookChapter::class,
|
||||||
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
|
||||||
@@ -107,7 +107,8 @@ val appDb by lazy {
|
|||||||
AutoMigration(from = 73, to = 74),
|
AutoMigration(from = 73, to = 74),
|
||||||
AutoMigration(from = 74, to = 75),
|
AutoMigration(from = 74, to = 75),
|
||||||
AutoMigration(from = 75, to = 76),
|
AutoMigration(from = 75, to = 76),
|
||||||
AutoMigration(from = 76, to = 77)
|
AutoMigration(from = 76, to = 77),
|
||||||
|
AutoMigration(from = 77, to = 78)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
abstract class AppDatabase : RoomDatabase() {
|
abstract class AppDatabase : RoomDatabase() {
|
||||||
|
|||||||
@@ -128,6 +128,9 @@ interface RssSourceDao {
|
|||||||
@Query("update rssSources set enabled = :enable where sourceUrl = :sourceUrl")
|
@Query("update rssSources set enabled = :enable where sourceUrl = :sourceUrl")
|
||||||
fun enable(sourceUrl: String, enable: Boolean)
|
fun enable(sourceUrl: String, enable: Boolean)
|
||||||
|
|
||||||
|
@Query("UPDATE rssSources SET redirectPolicy = :redirectPolicy WHERE sourceUrl = :sourceUrl")
|
||||||
|
suspend fun updateRedirectPolicy(sourceUrl: String, redirectPolicy: String)
|
||||||
|
|
||||||
private fun dealGroups(list: List<String>): List<String> {
|
private fun dealGroups(list: List<String>): List<String> {
|
||||||
val groups = linkedSetOf<String>()
|
val groups = linkedSetOf<String>()
|
||||||
list.forEach {
|
list.forEach {
|
||||||
|
|||||||
@@ -91,7 +91,10 @@ data class RssSource(
|
|||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
var lastUpdateTime: Long = 0,
|
var lastUpdateTime: Long = 0,
|
||||||
@ColumnInfo(defaultValue = "0")
|
@ColumnInfo(defaultValue = "0")
|
||||||
var customOrder: Int = 0
|
var customOrder: Int = 0,
|
||||||
|
//用户控制的重定向
|
||||||
|
@ColumnInfo(defaultValue = "ASK_CROSS_ORIGIN")
|
||||||
|
var redirectPolicy: String = "ASK_CROSS_ORIGIN"
|
||||||
) : Parcelable, BaseSource {
|
) : Parcelable, BaseSource {
|
||||||
|
|
||||||
override fun getTag(): String {
|
override fun getTag(): String {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ package io.legado.app.ui.rss.article
|
|||||||
import android.graphics.Color
|
import android.graphics.Color
|
||||||
import android.graphics.drawable.GradientDrawable
|
import android.graphics.drawable.GradientDrawable
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
@@ -19,6 +20,7 @@ import io.legado.app.base.VMBaseActivity
|
|||||||
import io.legado.app.databinding.ActivityRssArtivlesBinding
|
import io.legado.app.databinding.ActivityRssArtivlesBinding
|
||||||
import io.legado.app.help.source.sortUrls
|
import io.legado.app.help.source.sortUrls
|
||||||
import io.legado.app.ui.login.SourceLoginActivity
|
import io.legado.app.ui.login.SourceLoginActivity
|
||||||
|
import io.legado.app.ui.rss.read.ReadRssActivity.RedirectPolicy
|
||||||
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
|
import io.legado.app.ui.rss.source.edit.RssSourceEditActivity
|
||||||
import io.legado.app.ui.widget.dialog.VariableDialog
|
import io.legado.app.ui.widget.dialog.VariableDialog
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
@@ -45,16 +47,19 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var redirectPolicy: RedirectPolicy = RedirectPolicy.ALLOW_ALL
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
setSupportActionBar(binding.topBar)
|
setSupportActionBar(binding.topBar)
|
||||||
|
|
||||||
viewModel.titleLiveData.observe(this) {
|
viewModel.titleLiveData.observe(this) {
|
||||||
binding.topBar.title = it
|
binding.ctlBar.title = it
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.initData(intent) {
|
viewModel.initData(intent) {
|
||||||
upFragments()
|
upFragments()
|
||||||
|
redirectPolicy = RedirectPolicy.fromString(viewModel.rssSource?.redirectPolicy)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.titleBar.addOnOffsetChangedListener({ appBarLayout, verticalOffset ->
|
binding.titleBar.addOnOffsetChangedListener({ appBarLayout, verticalOffset ->
|
||||||
@@ -98,7 +103,8 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
|||||||
putExtra("sourceUrl", it)
|
putExtra("sourceUrl", it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
R.id.menu_redirect_policy ->
|
||||||
|
showRedirectPolicySubMenu()
|
||||||
R.id.menu_clear -> {
|
R.id.menu_clear -> {
|
||||||
viewModel.url?.let {
|
viewModel.url?.let {
|
||||||
viewModel.clearArticles()
|
viewModel.clearArticles()
|
||||||
@@ -117,6 +123,49 @@ class RssSortActivity : VMBaseActivity<ActivityRssArtivlesBinding, RssSortViewMo
|
|||||||
return super.onCompatOptionsItemSelected(item)
|
return super.onCompatOptionsItemSelected(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showRedirectPolicySubMenu() {
|
||||||
|
val popup = PopupMenu(this, binding.titleBar, Gravity.END)
|
||||||
|
popup.menuInflater.inflate(R.menu.menu_redirect_policy_submenu, popup.menu)
|
||||||
|
setCurrentRedirectPolicyChecked(popup.menu)
|
||||||
|
popup.setOnMenuItemClickListener { menuItem ->
|
||||||
|
handleRedirectPolicySelection(menuItem)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
popup.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setCurrentRedirectPolicyChecked(menu: Menu) {
|
||||||
|
val currentPolicy = redirectPolicy
|
||||||
|
val menuItemId = when (currentPolicy) {
|
||||||
|
RedirectPolicy.ALLOW_ALL -> R.id.menu_redirect_allow_all
|
||||||
|
RedirectPolicy.ASK_ALWAYS -> R.id.menu_redirect_ask_always
|
||||||
|
RedirectPolicy.ASK_CROSS_ORIGIN -> R.id.menu_redirect_ask_cross_origin
|
||||||
|
RedirectPolicy.BLOCK_CROSS_ORIGIN -> R.id.menu_redirect_block_cross_origin
|
||||||
|
}
|
||||||
|
menu.findItem(menuItemId)?.isChecked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRedirectPolicySelection(menuItem: MenuItem) {
|
||||||
|
val selectedPolicy = when (menuItem.itemId) {
|
||||||
|
R.id.menu_redirect_allow_all -> RedirectPolicy.ALLOW_ALL
|
||||||
|
R.id.menu_redirect_ask_always -> RedirectPolicy.ASK_ALWAYS
|
||||||
|
R.id.menu_redirect_ask_cross_origin -> RedirectPolicy.ASK_CROSS_ORIGIN
|
||||||
|
R.id.menu_redirect_block_cross_origin -> RedirectPolicy.BLOCK_CROSS_ORIGIN
|
||||||
|
else -> RedirectPolicy.ALLOW_ALL
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRedirectPolicy(selectedPolicy)
|
||||||
|
toastOnUi("重定向策略已更新")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun updateRedirectPolicy(policy: RedirectPolicy) {
|
||||||
|
viewModel.rssSource?.let { source ->
|
||||||
|
source.redirectPolicy = policy.name
|
||||||
|
redirectPolicy = policy
|
||||||
|
viewModel.updateRssSourceRedirectPolicy(source.sourceUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun upFragments() {
|
private fun upFragments() {
|
||||||
lifecycleScope.launch {
|
lifecycleScope.launch {
|
||||||
val sorts = viewModel.rssSource?.sortUrls().orEmpty()
|
val sorts = viewModel.rssSource?.sortUrls().orEmpty()
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import io.legado.app.data.entities.RssArticle
|
|||||||
import io.legado.app.data.entities.RssReadRecord
|
import io.legado.app.data.entities.RssReadRecord
|
||||||
import io.legado.app.data.entities.RssSource
|
import io.legado.app.data.entities.RssSource
|
||||||
import io.legado.app.help.source.removeSortCache
|
import io.legado.app.help.source.removeSortCache
|
||||||
|
import io.legado.app.utils.toastOnUi
|
||||||
|
import splitties.init.appCtx
|
||||||
|
|
||||||
|
|
||||||
class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
||||||
@@ -92,4 +94,14 @@ class RssSortViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateRssSourceRedirectPolicy(redirectPolicy: String) {
|
||||||
|
execute {
|
||||||
|
val source = rssSource ?: return@execute
|
||||||
|
source.redirectPolicy = redirectPolicy
|
||||||
|
appDb.rssSourceDao.updateRedirectPolicy(source.sourceUrl, redirectPolicy)
|
||||||
|
}.onError {
|
||||||
|
appCtx.toastOnUi("保存失败: ${it.localizedMessage}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,7 @@ import android.net.Uri
|
|||||||
import android.net.http.SslError
|
import android.net.http.SslError
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
|
import android.view.Gravity
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -22,6 +23,8 @@ import android.webkit.WebView
|
|||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import androidx.activity.addCallback
|
import androidx.activity.addCallback
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.app.AlertDialog
|
||||||
|
import androidx.appcompat.widget.PopupMenu
|
||||||
import androidx.core.net.toUri
|
import androidx.core.net.toUri
|
||||||
import androidx.core.view.WindowInsetsCompat
|
import androidx.core.view.WindowInsetsCompat
|
||||||
import androidx.core.view.size
|
import androidx.core.view.size
|
||||||
@@ -73,11 +76,28 @@ import java.util.regex.PatternSyntaxException
|
|||||||
class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>(),
|
class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>(),
|
||||||
RssFavoritesDialog.Callback {
|
RssFavoritesDialog.Callback {
|
||||||
|
|
||||||
|
enum class RedirectPolicy {
|
||||||
|
ALLOW_ALL,
|
||||||
|
ASK_ALWAYS,
|
||||||
|
ASK_CROSS_ORIGIN,
|
||||||
|
BLOCK_CROSS_ORIGIN;
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun fromString(value: String?): RedirectPolicy {
|
||||||
|
return entries.find { it.name.equals(value, ignoreCase = true) } ?: ALLOW_ALL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var redirectPolicy: RedirectPolicy = RedirectPolicy.ALLOW_ALL
|
||||||
|
|
||||||
override val binding by viewBinding(ActivityRssReadBinding::inflate)
|
override val binding by viewBinding(ActivityRssReadBinding::inflate)
|
||||||
override val viewModel by viewModels<ReadRssViewModel>()
|
override val viewModel by viewModels<ReadRssViewModel>()
|
||||||
|
|
||||||
private var starMenuItem: MenuItem? = null
|
private var starMenuItem: MenuItem? = null
|
||||||
private var ttsMenuItem: MenuItem? = null
|
private var ttsMenuItem: MenuItem? = null
|
||||||
|
private var redirectPolicyMenu: MenuItem? = null
|
||||||
private var isFullScreen = false
|
private var isFullScreen = false
|
||||||
private var customWebViewCallback: WebChromeClient.CustomViewCallback? = null
|
private var customWebViewCallback: WebChromeClient.CustomViewCallback? = null
|
||||||
private val rssJsExtensions by lazy { RssJsExtensions(this) }
|
private val rssJsExtensions by lazy { RssJsExtensions(this) }
|
||||||
@@ -138,6 +158,11 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
override fun onPrepareOptionsMenu(menu: Menu): Boolean {
|
||||||
starMenuItem = menu.findItem(R.id.menu_rss_star)
|
starMenuItem = menu.findItem(R.id.menu_rss_star)
|
||||||
ttsMenuItem = menu.findItem(R.id.menu_aloud)
|
ttsMenuItem = menu.findItem(R.id.menu_aloud)
|
||||||
|
redirectPolicyMenu = menu.findItem(R.id.menu_redirect_policy)
|
||||||
|
redirectPolicyMenu?.setOnMenuItemClickListener {
|
||||||
|
showRedirectPolicySubMenu()
|
||||||
|
true
|
||||||
|
}
|
||||||
upStarMenu()
|
upStarMenu()
|
||||||
return super.onPrepareOptionsMenu(menu)
|
return super.onPrepareOptionsMenu(menu)
|
||||||
}
|
}
|
||||||
@@ -160,7 +185,6 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
showDialogFragment(RssFavoritesDialog(it))
|
showDialogFragment(RssFavoritesDialog(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
R.id.menu_share_it -> {
|
R.id.menu_share_it -> {
|
||||||
binding.webView.url?.let {
|
binding.webView.url?.let {
|
||||||
share(it)
|
share(it)
|
||||||
@@ -203,6 +227,41 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
return AppConfig.isNightTheme
|
return AppConfig.isNightTheme
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun showRedirectPolicySubMenu() {
|
||||||
|
val popup = PopupMenu(this, binding.titleBar, Gravity.END)
|
||||||
|
popup.menuInflater.inflate(R.menu.menu_redirect_policy_submenu, popup.menu)
|
||||||
|
setCurrentRedirectPolicyChecked(popup.menu)
|
||||||
|
popup.setOnMenuItemClickListener { menuItem ->
|
||||||
|
handleRedirectPolicySelection(menuItem)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
popup.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setCurrentRedirectPolicyChecked(menu: Menu) {
|
||||||
|
val currentPolicy = redirectPolicy
|
||||||
|
val menuItemId = when (currentPolicy) {
|
||||||
|
RedirectPolicy.ALLOW_ALL -> R.id.menu_redirect_allow_all
|
||||||
|
RedirectPolicy.ASK_ALWAYS -> R.id.menu_redirect_ask_always
|
||||||
|
RedirectPolicy.ASK_CROSS_ORIGIN -> R.id.menu_redirect_ask_cross_origin
|
||||||
|
RedirectPolicy.BLOCK_CROSS_ORIGIN -> R.id.menu_redirect_block_cross_origin
|
||||||
|
}
|
||||||
|
menu.findItem(menuItemId)?.isChecked = true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRedirectPolicySelection(menuItem: MenuItem) {
|
||||||
|
val selectedPolicy = when (menuItem.itemId) {
|
||||||
|
R.id.menu_redirect_allow_all -> RedirectPolicy.ALLOW_ALL
|
||||||
|
R.id.menu_redirect_ask_always -> RedirectPolicy.ASK_ALWAYS
|
||||||
|
R.id.menu_redirect_ask_cross_origin -> RedirectPolicy.ASK_CROSS_ORIGIN
|
||||||
|
R.id.menu_redirect_block_cross_origin -> RedirectPolicy.BLOCK_CROSS_ORIGIN
|
||||||
|
else -> RedirectPolicy.ALLOW_ALL
|
||||||
|
}
|
||||||
|
|
||||||
|
updateRedirectPolicy(selectedPolicy)
|
||||||
|
toastOnUi("重定向策略已更新")
|
||||||
|
}
|
||||||
|
|
||||||
private fun toggleFullScreen() {
|
private fun toggleFullScreen() {
|
||||||
isFullScreen = !isFullScreen
|
isFullScreen = !isFullScreen
|
||||||
|
|
||||||
@@ -277,6 +336,9 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
private fun initLiveData() {
|
private fun initLiveData() {
|
||||||
viewModel.contentLiveData.observe(this) { content ->
|
viewModel.contentLiveData.observe(this) { content ->
|
||||||
viewModel.rssArticle?.let {
|
viewModel.rssArticle?.let {
|
||||||
|
if (viewModel.rssSource != null) {
|
||||||
|
redirectPolicy = RedirectPolicy.fromString(viewModel.rssSource?.redirectPolicy)
|
||||||
|
}
|
||||||
upJavaScriptEnable()
|
upJavaScriptEnable()
|
||||||
val url = NetworkUtils.getAbsoluteURL(it.origin, it.link)
|
val url = NetworkUtils.getAbsoluteURL(it.origin, it.link)
|
||||||
val html = viewModel.clHtml(content)
|
val html = viewModel.clHtml(content)
|
||||||
@@ -306,6 +368,14 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateRedirectPolicy(policy: RedirectPolicy) {
|
||||||
|
viewModel.rssSource?.let { source ->
|
||||||
|
source.redirectPolicy = policy.name
|
||||||
|
redirectPolicy = policy
|
||||||
|
viewModel.updateRssSourceRedirectPolicy(source.sourceUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun upStarMenu() {
|
private fun upStarMenu() {
|
||||||
starMenuItem?.isVisible = viewModel.rssArticle != null
|
starMenuItem?.isVisible = viewModel.rssArticle != null
|
||||||
if (viewModel.rssStar != null) {
|
if (viewModel.rssStar != null) {
|
||||||
@@ -382,19 +452,74 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
}
|
}
|
||||||
|
|
||||||
inner class CustomWebViewClient : WebViewClient() {
|
inner class CustomWebViewClient : WebViewClient() {
|
||||||
|
private var lastUrl: String? = null
|
||||||
override fun shouldOverrideUrlLoading(
|
override fun shouldOverrideUrlLoading(
|
||||||
view: WebView,
|
view: WebView,
|
||||||
request: WebResourceRequest
|
request: WebResourceRequest
|
||||||
): Boolean {
|
): Boolean {
|
||||||
|
val currentUrl = lastUrl ?: view.url
|
||||||
|
val targetUrl = request.url.toString()
|
||||||
|
lastUrl = targetUrl
|
||||||
|
if (!request.isForMainFrame) return false
|
||||||
|
if (handleRedirect(view, currentUrl, targetUrl)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return shouldOverrideUrlLoading(request.url)
|
return shouldOverrideUrlLoading(request.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION", "KotlinRedundantDiagnosticSuppress")
|
@Suppress("DEPRECATION", "OVERRIDE_DEPRECATION", "KotlinRedundantDiagnosticSuppress")
|
||||||
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
override fun shouldOverrideUrlLoading(view: WebView, url: String): Boolean {
|
||||||
|
val currentUrl = lastUrl ?: view.url
|
||||||
|
val targetUrl = url
|
||||||
|
lastUrl = targetUrl
|
||||||
|
if (handleRedirect(view, currentUrl, targetUrl)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
return shouldOverrideUrlLoading(url.toUri())
|
return shouldOverrideUrlLoading(url.toUri())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun handleRedirect(view: WebView, fromUrl: String?, toUrl: String): Boolean {
|
||||||
|
val fromHost = fromUrl?.toUri()?.host
|
||||||
|
val toHost = toUrl.toUri().host
|
||||||
|
val crossOrigin = fromHost != null && toHost != null && fromHost != toHost
|
||||||
|
|
||||||
|
return when (redirectPolicy) {
|
||||||
|
RedirectPolicy.ALLOW_ALL -> false
|
||||||
|
RedirectPolicy.ASK_ALWAYS -> {
|
||||||
|
askUser(fromUrl, toUrl) { if (it) view.loadUrl(toUrl) }
|
||||||
|
true
|
||||||
|
}
|
||||||
|
RedirectPolicy.ASK_CROSS_ORIGIN -> {
|
||||||
|
if (crossOrigin) {
|
||||||
|
askUser(fromUrl, toUrl) { if (it) view.loadUrl(toUrl) }
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RedirectPolicy.BLOCK_CROSS_ORIGIN -> {
|
||||||
|
if (crossOrigin) {
|
||||||
|
toastOnUi("已阻止跨域重定向")
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun askUser(fromUrl: String?, toUrl: String, onResult: (Boolean) -> Unit) {
|
||||||
|
AlertDialog.Builder(this@ReadRssActivity)
|
||||||
|
.setTitle("重定向请求")
|
||||||
|
.setMessage("是否允许页面跳转?\n\n来源:${fromUrl ?: "未知"}\n目标:$toUrl")
|
||||||
|
.setPositiveButton("允许") { _, _ -> onResult(true) }
|
||||||
|
.setNegativeButton("拒绝") { _, _ -> onResult(false) }
|
||||||
|
.setCancelable(true)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果有黑名单,黑名单匹配返回空白,
|
* 如果有黑名单,黑名单匹配返回空白,
|
||||||
* 没有黑名单再判断白名单,在白名单中的才通过,
|
* 没有黑名单再判断白名单,在白名单中的才通过,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import androidx.lifecycle.MutableLiveData
|
|||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.script.rhino.runScriptWithContext
|
import com.script.rhino.runScriptWithContext
|
||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
|
import io.legado.app.constant.AppLog
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
import io.legado.app.data.entities.RssArticle
|
import io.legado.app.data.entities.RssArticle
|
||||||
import io.legado.app.data.entities.RssSource
|
import io.legado.app.data.entities.RssSource
|
||||||
@@ -242,6 +243,16 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
tts?.speak(text)
|
tts?.speak(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun updateRssSourceRedirectPolicy(redirectPolicy: String) {
|
||||||
|
execute {
|
||||||
|
val source = rssSource ?: return@execute
|
||||||
|
source.redirectPolicy = redirectPolicy
|
||||||
|
appDb.rssSourceDao.updateRedirectPolicy(source.sourceUrl, redirectPolicy)
|
||||||
|
}.onError {
|
||||||
|
appCtx.toastOnUi("保存失败: ${it.localizedMessage}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onCleared() {
|
override fun onCleared() {
|
||||||
super.onCleared()
|
super.onCleared()
|
||||||
tts?.clearTts()
|
tts?.clearTts()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
android:stateListAnimator="@null">
|
android:stateListAnimator="@null">
|
||||||
|
|
||||||
<com.google.android.material.appbar.CollapsingToolbarLayout
|
<com.google.android.material.appbar.CollapsingToolbarLayout
|
||||||
|
android:id="@+id/ctl_bar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
|
android:layout_height="?attr/collapsingToolbarLayoutMediumSize"
|
||||||
style="?attr/collapsingToolbarLayoutMediumStyle"
|
style="?attr/collapsingToolbarLayoutMediumStyle"
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<group android:checkableBehavior="single">
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_allow_all"
|
||||||
|
android:title="@string/redirect_allow_all" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_ask_always"
|
||||||
|
android:title="@string/redirect_ask_always" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_ask_cross_origin"
|
||||||
|
android:title="@string/redirect_ask_cross_origin" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_block_cross_origin"
|
||||||
|
android:title="@string/redirect_block_cross_origin" />
|
||||||
|
</group>
|
||||||
|
</menu>
|
||||||
@@ -37,4 +37,9 @@
|
|||||||
android:title="@string/clear"
|
android:title="@string/clear"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_policy"
|
||||||
|
android:title="@string/redirect_policy"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
</menu>
|
</menu>
|
||||||
@@ -38,6 +38,11 @@
|
|||||||
android:title="@string/login"
|
android:title="@string/login"
|
||||||
app:showAsAction="never" />
|
app:showAsAction="never" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_redirect_policy"
|
||||||
|
android:title="@string/redirect_policy"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/menu_browser_open"
|
android:id="@+id/menu_browser_open"
|
||||||
android:title="@string/open_in_browser"
|
android:title="@string/open_in_browser"
|
||||||
|
|||||||
@@ -1313,4 +1313,9 @@
|
|||||||
<string name="screen_settings">屏幕显示与亮度</string>
|
<string name="screen_settings">屏幕显示与亮度</string>
|
||||||
<string name="reading_behavior">阅读行为</string>
|
<string name="reading_behavior">阅读行为</string>
|
||||||
<string name="page_control">翻页控制</string>
|
<string name="page_control">翻页控制</string>
|
||||||
|
<string name="redirect_policy">网页重定向策略</string>
|
||||||
|
<string name="redirect_allow_all">允许所有重定向</string>
|
||||||
|
<string name="redirect_ask_always">总是询问</string>
|
||||||
|
<string name="redirect_ask_cross_origin">跨域时询问</string>
|
||||||
|
<string name="redirect_block_cross_origin">阻止跨域重定向</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -1314,4 +1314,9 @@
|
|||||||
<string name="screen_settings">屏幕显示与亮度</string>
|
<string name="screen_settings">屏幕显示与亮度</string>
|
||||||
<string name="reading_behavior">阅读行为</string>
|
<string name="reading_behavior">阅读行为</string>
|
||||||
<string name="page_control">翻页控制</string>
|
<string name="page_control">翻页控制</string>
|
||||||
|
<string name="redirect_policy">网页重定向策略</string>
|
||||||
|
<string name="redirect_allow_all">允许所有重定向</string>
|
||||||
|
<string name="redirect_ask_always">总是询问</string>
|
||||||
|
<string name="redirect_ask_cross_origin">跨域时询问</string>
|
||||||
|
<string name="redirect_block_cross_origin">阻止跨域重定向</string>
|
||||||
</resources>
|
</resources>
|
||||||
Reference in new issue
Block a user