From a95107d0d10583bfd95495bdc84cc23022b56000 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Mon, 26 Jun 2017 13:31:37 -0700 Subject: Update dependencies --- app/src/main/assets/js/search.js | 23 +++++---- app/src/main/assets/js/search.min.js | 10 ++-- .../com/pitchedapps/frost/facebook/FbSearch.kt | 9 ++++ .../pitchedapps/frost/web/FrostWebViewSearch.kt | 58 +++++++++++++++------- 4 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt (limited to 'app/src/main') diff --git a/app/src/main/assets/js/search.js b/app/src/main/assets/js/search.js index d3b319d4..5f0f0e0a 100644 --- a/app/src/main/assets/js/search.js +++ b/app/src/main/assets/js/search.js @@ -1,13 +1,16 @@ //binds callbacks to an invisible webview to take in the search events console.log('Binding Search'); var _f_page = document.querySelector('#page'); -var _f_input = document.querySelector('#main-search-input') -if (!_f_page || !_f_input) return Frost.emit(1); -Frost.emit(0); -var x = new MutationObserver(function(mutations) { - Frost.handleHtml(page.innerHTML); -}); -x.observe(_f_page, { - childList: true, - subtree: true -}); +// var _f_input = document.querySelector('#main-search-input') +if (!_f_page) Frost.emit(1); +// else { + Frost.emit(0); + var x = new MutationObserver(function(mutations) { + Frost.handleHtml(page.innerHTML); + Frost.emit(2); + }); + x.observe(_f_page, { + childList: true, + subtree: true + }); +// } diff --git a/app/src/main/assets/js/search.min.js b/app/src/main/assets/js/search.min.js index fe93d004..c5e577d1 100644 --- a/app/src/main/assets/js/search.min.js +++ b/app/src/main/assets/js/search.min.js @@ -1,10 +1,14 @@ console.log("Binding Search") -;var page=document.querySelector("#page"),x=new MutationObserver(function(e){ -Frost.handleHtml(page.innerHTML) +;var _f_page=document.querySelector("#page") + +;_f_page||Frost.emit(1),Frost.emit(0) + +;var x=new MutationObserver(function(e){ +Frost.handleHtml(page.innerHTML),Frost.emit(2) }) -;x.observe(page,{ +;x.observe(_f_page,{ childList:!0, subtree:!0 }); \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt new file mode 100644 index 00000000..151957d3 --- /dev/null +++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt @@ -0,0 +1,9 @@ +package com.pitchedapps.frost.facebook + +/** + * Created by Allan Wang on 2017-06-26. + * + * Handles asynchronous user graph searches + */ +class FbSearch { +} \ No newline at end of file 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() 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 = Pair(null, 0) + + fun saveResultFrame(result: List, 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, String>> -> + content: List, 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") -- cgit v1.2.3