aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt58
1 files changed, 41 insertions, 17 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt
index 85dfb254..6c9ee9d5 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt
@@ -2,11 +2,11 @@ package com.pitchedapps.frost.web
import android.annotation.SuppressLint
import android.content.Context
-import android.os.Handler
import android.view.View
import android.webkit.JavascriptInterface
import android.webkit.WebView
import android.webkit.WebViewClient
+import ca.allanwang.kau.utils.gone
import com.pitchedapps.frost.facebook.FbTab
import com.pitchedapps.frost.facebook.USER_AGENT_BASIC
import com.pitchedapps.frost.injectors.JsAssets
@@ -16,7 +16,6 @@ import com.pitchedapps.frost.utils.L
import io.reactivex.schedulers.Schedulers
import io.reactivex.subjects.PublishSubject
import org.jsoup.Jsoup
-import org.jsoup.nodes.TextNode
import java.util.concurrent.TimeUnit
@SuppressLint("ViewConstructor")
@@ -25,16 +24,30 @@ import java.util.concurrent.TimeUnit
*
* A bare bone search view meant solely to extract data from the web
* This should be hidden
+ * Having a single webview allows us to avoid loading the whole page with each query
*/
class FrostWebViewSearch(context: Context, val contract: SearchContract) : WebView(context) {
val searchSubject = PublishSubject.create<String>()
init {
-// gone()
+ gone()
setupWebview()
}
+ /**
+ * Basic info of last search results, so we can check if the list has actually changed
+ * Contains the last item's href (search more) as well as the number of items found
+ * This holder is synchronized
+ */
+ var previousResult: Pair<String?, Int> = Pair(null, 0)
+
+ fun saveResultFrame(result: List<Pair<List<String>, String>>) {
+ synchronized(previousResult) {
+ previousResult = Pair(result.lastOrNull()?.second, result.size)
+ }
+ }
+
@SuppressLint("SetJavaScriptEnabled")
fun setupWebview() {
settings.javaScriptEnabled = true
@@ -42,33 +55,47 @@ class FrostWebViewSearch(context: Context, val contract: SearchContract) : WebVi
setLayerType(View.LAYER_TYPE_HARDWARE, null)
webViewClient = FrostWebViewClientSearch()
addJavascriptInterface(SearchJSI(), "Frost")
- searchSubject.debounce(200, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread())
+ searchSubject.debounce(300, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread())
.map {
Jsoup.parse(it).select("a:not([rel*='keywords(']):not([href=#])[rel]").map {
element ->
-// L.d("Search element ${element.text()} ${element.textNodes().size} ${element.attr("href")}")
- Pair(element.textNodes(), element.attr("href"))
+ //split text into separate items
+ val texts = element.select("div").map { (it.ownText()) }.filter { it.isNotBlank() }
+ Pair(texts, element.attr("href"))
}.filter { it.first.isNotEmpty() }
}
+ .filter { content -> Pair(content.lastOrNull()?.second, content.size) != previousResult }
.subscribe {
- content: List<Pair<List<TextNode>, String>> ->
+ content: List<Pair<List<String>, String>> ->
+ saveResultFrame(content)
content.forEach {
-// L.e("Search result ${it.second}")
+ (texts, href) ->
+ L.d("Search element $texts $href")
}
contract.emitSearchResponse()
}
reload()
- Handler().postDelayed({
- query("hi")
- }, 5000)
}
+ /**
+ * Toggles web activity
+ * Should be done in conjunction with showing/hiding the search view
+ */
+ var pauseLoad: Boolean
+ get() = settings.blockNetworkLoads
+ set(value) {
+ settings.blockNetworkLoads = value
+ }
+
override fun reload() {
super.loadUrl(FbTab.SEARCH.url)
}
+ /**
+ * Sets the input to have our given text, then dispatches the input event so the webpage recognizes it
+ */
fun query(input: String) {
- JsBuilder().js("var input=document.getElementById('main-search-input');input.click(),input.value='$input';").build().inject(this) {
+ JsBuilder().js("var e=document.getElementById('main-search-input');if(e){e.value='$input';var n=new Event('input',{bubbles:!0,cancelable:!0});e.dispatchEvent(n)}else console.log('Input field not found')").build().inject(this) {
L.d("Searching for $input")
}
}
@@ -90,18 +117,15 @@ class FrostWebViewSearch(context: Context, val contract: SearchContract) : WebVi
inner class SearchJSI {
@JavascriptInterface
fun handleHtml(html: String) {
-// L.d("Search received response $html")
+ L.d("Search received response")
searchSubject.onNext(html)
}
@JavascriptInterface
fun emit(flag: Int) {
- L.d("Search flag")
when (flag) {
0 -> {
- JsBuilder().js("document.getElementById('main-search-input').click()").build().inject(this@FrostWebViewSearch) {
- L.d("Search click")
- }
+ L.d("Search loaded successfully")
}
1 -> { //something is not found in the search view; this is effectively useless
L.d("Search subject error; reverting to full overlay")