diff options
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.kt | 70 |
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 |