aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt70
1 files changed, 45 insertions, 25 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
index dd73209f..2d067e44 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
@@ -3,7 +3,7 @@ package com.pitchedapps.frost.injectors
import android.webkit.WebView
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.web.FrostWebViewClient
-import io.reactivex.Observable
+import io.reactivex.Single
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.subjects.SingleSubject
import org.apache.commons.text.StringEscapeUtils
@@ -26,30 +26,35 @@ class JsBuilder {
}
fun single(tag: String): JsBuilder {
- this.tag = tag
+ this.tag = "_frost_${tag.toLowerCase(Locale.CANADA)}"
return this
}
fun build() = JsInjector(toString())
override fun toString(): String {
- val builder = StringBuilder().append("!function(){")
- if (css.isNotBlank()) {
- val cssMin = css.replace(Regex("\\s*\n\\s*"), "")
- builder.append("var a=document.createElement('style');a.innerHTML='$cssMin';document.head.appendChild(a);")
+ val tag = this.tag
+ val builder = StringBuilder().apply {
+ append("!function(){")
+ if (css.isNotBlank()) {
+ val cssMin = css.replace(Regex("\\s*\n\\s*"), "")
+ append("var a=document.createElement('style');")
+ append("a.innerHTML='$cssMin';")
+ if (tag != null) append("a.id='$tag';")
+ append("document.head.appendChild(a);")
+ }
+ if (js.isNotBlank())
+ append(js)
}
- if (js.isNotBlank())
- builder.append(js)
var content = builder.append("}()").toString()
- if (tag != null) content = singleInjector(tag!!, content)
+ if (tag != null) content = singleInjector(tag, content)
return content
}
private fun singleInjector(tag: String, content: String) = StringBuilder().apply {
- val name = "_frost_${tag.toLowerCase(Locale.CANADA)}"
- append("if (!window.hasOwnProperty(\"$name\")) {")
- append("console.log(\"Registering $name\");")
- append("window.$name = true;")
+ append("if (!window.hasOwnProperty(\"$tag\")) {")
+ append("console.log(\"Registering $tag\");")
+ append("window.$tag = true;")
append(content)
append("}")
}.toString()
@@ -60,7 +65,7 @@ class JsBuilder {
*/
interface InjectorContract {
fun inject(webView: WebView) = inject(webView, null)
- fun inject(webView: WebView, callback: ((String) -> Unit)?)
+ fun inject(webView: WebView, callback: (() -> Unit)?)
/**
* Toggle the injector (usually through Prefs
* If false, will fallback to an empty action
@@ -71,24 +76,39 @@ interface InjectorContract {
/**
* Helper method to inject multiple functions simultaneously with a single callback
*/
-fun WebView.jsInject(vararg injectors: InjectorContract, callback: ((Array<String>) -> Unit) = {}) {
+fun WebView.jsInject(vararg injectors: InjectorContract, callback: ((Int) -> Unit)? = null) {
val validInjectors = injectors.filter { it != JsActions.EMPTY }
- if (validInjectors.isEmpty()) return callback(emptyArray())
- val observables = Array(validInjectors.size, { SingleSubject.create<String>() })
- L.d { "Injecting ${observables.size} items" }
- Observable.zip<String, Array<String>>(observables.map(SingleSubject<String>::toObservable),
- { it.map(Any::toString).toTypedArray() })
- .subscribeOn(AndroidSchedulers.mainThread()).subscribe({ callback(it) })
- (0 until validInjectors.size).forEach { i -> validInjectors[i].inject(this, { observables[i].onSuccess(it) }) }
+ if (validInjectors.isEmpty()) {
+ callback?.invoke(0)
+ return
+ }
+ L.d { "Injecting ${validInjectors.size} items" }
+ if (callback == null) {
+ validInjectors.forEach { it.inject(this) }
+ return
+ }
+ val observables = Array(validInjectors.size, { SingleSubject.create<Unit>() })
+ Single.zip<Unit, Int>(observables.asList(), { it.size })
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe { res, _ ->
+ callback(res)
+ }
+ (0 until validInjectors.size).forEach { i ->
+ validInjectors[i].inject(this, {
+ observables[i].onSuccess(Unit)
+ })
+ }
}
-fun FrostWebViewClient.jsInject(vararg injectors: InjectorContract, callback: ((Array<String>) -> Unit) = {}) = web.jsInject(*injectors, callback = callback)
+fun FrostWebViewClient.jsInject(vararg injectors: InjectorContract,
+ callback: ((Int) -> Unit)? = null)
+ = web.jsInject(*injectors, callback = callback)
/**
* Wrapper class to convert a function into an injector
*/
class JsInjector(val function: String) : InjectorContract {
- override fun inject(webView: WebView, callback: ((String) -> Unit)?) {
- webView.evaluateJavascript(function, { value -> callback?.invoke(value) })
+ override fun inject(webView: WebView, callback: (() -> Unit)?) {
+ webView.evaluateJavascript(function, { callback?.invoke() })
}
} \ No newline at end of file