aboutsummaryrefslogtreecommitdiff
path: root/app/src
diff options
context:
space:
mode:
Diffstat (limited to 'app/src')
-rw-r--r--app/src/main/assets/js/search.js23
-rw-r--r--app/src/main/assets/js/search.min.js10
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt9
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt58
4 files changed, 70 insertions, 30 deletions
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<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")