优化
This commit is contained in:
@@ -1,19 +0,0 @@
|
|||||||
package io.legado.app.help
|
|
||||||
|
|
||||||
import com.script.SimpleBindings
|
|
||||||
import com.script.rhino.RhinoScriptEngine
|
|
||||||
import io.legado.app.data.entities.BaseSource
|
|
||||||
|
|
||||||
object JsEngine : JsExtensions {
|
|
||||||
|
|
||||||
override fun getSource(): BaseSource? {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
fun eval(js: String): Any? {
|
|
||||||
val bindings = SimpleBindings()
|
|
||||||
bindings["java"] = this
|
|
||||||
return RhinoScriptEngine.eval(js, bindings)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -539,9 +539,9 @@ interface JsExtensions : JsEncodeUtils {
|
|||||||
/**
|
/**
|
||||||
* 删除本地文件
|
* 删除本地文件
|
||||||
*/
|
*/
|
||||||
fun deleteFile(path: String) {
|
fun deleteFile(path: String): Boolean {
|
||||||
val file = getFile(path)
|
val file = getFile(path)
|
||||||
FileUtils.delete(file, true)
|
return FileUtils.delete(file, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -825,6 +825,15 @@ interface JsExtensions : JsEncodeUtils {
|
|||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun toURL(urlStr: String): JsURL {
|
||||||
|
return JsURL(urlStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun toURL(url: String, baseUrl: String? = null): JsURL {
|
||||||
|
return JsURL(url, baseUrl)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 弹窗提示
|
* 弹窗提示
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,40 +0,0 @@
|
|||||||
@file:Suppress("unused")
|
|
||||||
|
|
||||||
package io.legado.app.rhino
|
|
||||||
|
|
||||||
import com.script.Bindings
|
|
||||||
import org.mozilla.javascript.Context
|
|
||||||
import org.mozilla.javascript.Scriptable
|
|
||||||
import org.mozilla.javascript.ScriptableObject
|
|
||||||
import java.io.Reader
|
|
||||||
|
|
||||||
fun Context.eval(
|
|
||||||
scope: Scriptable,
|
|
||||||
source: String,
|
|
||||||
sourceName: String = "<Unknown source>",
|
|
||||||
lineno: Int = 1,
|
|
||||||
securityDomain: Any? = null
|
|
||||||
): Any? {
|
|
||||||
return evaluateString(scope, source, sourceName, lineno, securityDomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Context.eval(
|
|
||||||
scope: Scriptable,
|
|
||||||
reader: Reader,
|
|
||||||
sourceName: String = "<Unknown source>",
|
|
||||||
lineno: Int = 1,
|
|
||||||
securityDomain: Any? = null
|
|
||||||
): Any? {
|
|
||||||
return evaluateReader(scope, reader, sourceName, lineno, securityDomain)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Scriptable.putBinding(key: String, value: Any?) {
|
|
||||||
val wrappedOut = Context.javaToJS(value, this)
|
|
||||||
ScriptableObject.putProperty(this, key, wrappedOut)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Scriptable.putBindings(bindings: Bindings) {
|
|
||||||
bindings.forEach { (t, u) ->
|
|
||||||
putBinding(t, u)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,18 +10,23 @@ import android.view.*
|
|||||||
import android.webkit.*
|
import android.webkit.*
|
||||||
import androidx.activity.viewModels
|
import androidx.activity.viewModels
|
||||||
import androidx.core.view.size
|
import androidx.core.view.size
|
||||||
|
import com.script.rhino.RhinoScriptEngine
|
||||||
import io.legado.app.R
|
import io.legado.app.R
|
||||||
import io.legado.app.base.VMBaseActivity
|
import io.legado.app.base.VMBaseActivity
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.constant.AppConst.imagePathKey
|
import io.legado.app.constant.AppConst.imagePathKey
|
||||||
|
import io.legado.app.data.entities.BaseSource
|
||||||
import io.legado.app.databinding.ActivityRssReadBinding
|
import io.legado.app.databinding.ActivityRssReadBinding
|
||||||
|
import io.legado.app.help.JsExtensions
|
||||||
import io.legado.app.help.config.AppConfig
|
import io.legado.app.help.config.AppConfig
|
||||||
import io.legado.app.lib.dialogs.SelectItem
|
import io.legado.app.lib.dialogs.SelectItem
|
||||||
import io.legado.app.lib.dialogs.selector
|
import io.legado.app.lib.dialogs.selector
|
||||||
import io.legado.app.lib.theme.accentColor
|
import io.legado.app.lib.theme.accentColor
|
||||||
import io.legado.app.lib.theme.primaryTextColor
|
import io.legado.app.lib.theme.primaryTextColor
|
||||||
import io.legado.app.model.Download
|
import io.legado.app.model.Download
|
||||||
|
import io.legado.app.ui.association.AddToBookshelfDialog
|
||||||
import io.legado.app.ui.association.OnLineImportActivity
|
import io.legado.app.ui.association.OnLineImportActivity
|
||||||
|
import io.legado.app.ui.book.search.SearchActivity
|
||||||
import io.legado.app.ui.file.HandleFileContract
|
import io.legado.app.ui.file.HandleFileContract
|
||||||
import io.legado.app.ui.login.SourceLoginActivity
|
import io.legado.app.ui.login.SourceLoginActivity
|
||||||
import io.legado.app.utils.*
|
import io.legado.app.utils.*
|
||||||
@@ -39,6 +44,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
|
|
||||||
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 customWebViewCallback: WebChromeClient.CustomViewCallback? = null
|
private var customWebViewCallback: WebChromeClient.CustomViewCallback? = null
|
||||||
@@ -48,6 +54,7 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
viewModel.saveImage(it.value, uri)
|
viewModel.saveImage(it.value, uri)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private val rssJsExtensions by lazy { RssJsExtensions() }
|
||||||
|
|
||||||
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
override fun onActivityCreated(savedInstanceState: Bundle?) {
|
||||||
viewModel.upStarMenuData.observe(this) { upStarMenu() }
|
viewModel.upStarMenuData.observe(this) { upStarMenu() }
|
||||||
@@ -401,9 +408,14 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
val source = viewModel.rssSource
|
val source = viewModel.rssSource
|
||||||
val js = source?.shouldOverrideUrlLoading
|
val js = source?.shouldOverrideUrlLoading
|
||||||
if (!js.isNullOrBlank()) {
|
if (!js.isNullOrBlank()) {
|
||||||
val result = source.evalJS(js) {
|
val result = RhinoScriptEngine.runCatching {
|
||||||
|
eval(js) {
|
||||||
|
put("java", rssJsExtensions)
|
||||||
put("url", url.toString())
|
put("url", url.toString())
|
||||||
}.toString()
|
}.toString()
|
||||||
|
}.onFailure {
|
||||||
|
it.printOnDebug()
|
||||||
|
}.getOrNull()
|
||||||
if (result.isTrue()) {
|
if (result.isTrue()) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
@@ -440,4 +452,23 @@ class ReadRssActivity : VMBaseActivity<ActivityRssReadBinding, ReadRssViewModel>
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
private inner class RssJsExtensions : JsExtensions {
|
||||||
|
|
||||||
|
override fun getSource(): BaseSource? {
|
||||||
|
return viewModel.rssSource
|
||||||
|
}
|
||||||
|
|
||||||
|
fun searchBook(key: String) {
|
||||||
|
launch {
|
||||||
|
SearchActivity.start(this@ReadRssActivity, key)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addBook(bookUrl: String) {
|
||||||
|
showDialogFragment(AddToBookshelfDialog(bookUrl))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import io.legado.app.base.BaseViewModel
|
import io.legado.app.base.BaseViewModel
|
||||||
import io.legado.app.constant.AppConst
|
import io.legado.app.constant.AppConst
|
||||||
import io.legado.app.data.appDb
|
import io.legado.app.data.appDb
|
||||||
|
import io.legado.app.data.entities.BaseSource
|
||||||
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
|
||||||
import io.legado.app.data.entities.RssStar
|
import io.legado.app.data.entities.RssStar
|
||||||
import io.legado.app.exception.NoStackTraceException
|
import io.legado.app.exception.NoStackTraceException
|
||||||
|
import io.legado.app.help.JsExtensions
|
||||||
import io.legado.app.help.TTS
|
import io.legado.app.help.TTS
|
||||||
import io.legado.app.help.http.newCallResponseBody
|
import io.legado.app.help.http.newCallResponseBody
|
||||||
import io.legado.app.help.http.okHttpClient
|
import io.legado.app.help.http.okHttpClient
|
||||||
@@ -26,7 +28,7 @@ import splitties.init.appCtx
|
|||||||
import java.util.Date
|
import java.util.Date
|
||||||
|
|
||||||
|
|
||||||
class ReadRssViewModel(application: Application) : BaseViewModel(application) {
|
class ReadRssViewModel(application: Application) : BaseViewModel(application), JsExtensions {
|
||||||
var rssSource: RssSource? = null
|
var rssSource: RssSource? = null
|
||||||
var rssArticle: RssArticle? = null
|
var rssArticle: RssArticle? = null
|
||||||
var tts: TTS? = null
|
var tts: TTS? = null
|
||||||
@@ -36,6 +38,10 @@ class ReadRssViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
val upTtsMenuData = MutableLiveData<Boolean>()
|
val upTtsMenuData = MutableLiveData<Boolean>()
|
||||||
val upStarMenuData = MutableLiveData<Boolean>()
|
val upStarMenuData = MutableLiveData<Boolean>()
|
||||||
|
|
||||||
|
override fun getSource(): BaseSource? {
|
||||||
|
return rssSource
|
||||||
|
}
|
||||||
|
|
||||||
fun initData(intent: Intent) {
|
fun initData(intent: Intent) {
|
||||||
execute {
|
execute {
|
||||||
val origin = intent.getStringExtra("origin") ?: return@execute
|
val origin = intent.getStringExtra("origin") ?: return@execute
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package io.legado.app.utils
|
||||||
|
|
||||||
|
import java.net.URL
|
||||||
|
import java.net.URLDecoder
|
||||||
|
|
||||||
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
|
class JsURL(url: String, baseUrl: String? = null) {
|
||||||
|
|
||||||
|
val searchParams: Map<String, String>?
|
||||||
|
|
||||||
|
init {
|
||||||
|
val mUrl = if (!baseUrl.isNullOrEmpty()) {
|
||||||
|
val base = URL(baseUrl)
|
||||||
|
URL(base, url)
|
||||||
|
} else {
|
||||||
|
URL(url)
|
||||||
|
}
|
||||||
|
val query = mUrl.query
|
||||||
|
searchParams = query?.let { query ->
|
||||||
|
val map = hashMapOf<String, String>()
|
||||||
|
query.split("&").forEach {
|
||||||
|
val x = it.split("=")
|
||||||
|
map[x[0]] = URLDecoder.decode(x[1], "utf-8")
|
||||||
|
}
|
||||||
|
map
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -48,6 +48,12 @@ object RhinoScriptEngine : AbstractScriptEngine(), Invocable, Compilable {
|
|||||||
private val indexedProps: MutableMap<Any, Any?>
|
private val indexedProps: MutableMap<Any, Any?>
|
||||||
private val implementor: InterfaceImplementor
|
private val implementor: InterfaceImplementor
|
||||||
|
|
||||||
|
fun eval(js: String, bindingsConfig: SimpleBindings.() -> Unit = {}): Any? {
|
||||||
|
val bindings = SimpleBindings()
|
||||||
|
bindings.apply(bindingsConfig)
|
||||||
|
return eval(js, bindings)
|
||||||
|
}
|
||||||
|
|
||||||
@Throws(ScriptException::class)
|
@Throws(ScriptException::class)
|
||||||
override fun eval(reader: Reader, scope: Scriptable): Any? {
|
override fun eval(reader: Reader, scope: Scriptable): Any? {
|
||||||
val cx = Context.enter()
|
val cx = Context.enter()
|
||||||
|
|||||||
Reference in New Issue
Block a user