diff options
-rw-r--r-- | .idea/misc.xml | 2 | ||||
-rw-r--r-- | app/build.gradle | 12 | ||||
-rw-r--r-- | app/src/main/assets/js/search.js | 23 | ||||
-rw-r--r-- | app/src/main/assets/js/search.min.js | 10 | ||||
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/facebook/FbSearch.kt | 9 | ||||
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewSearch.kt | 58 | ||||
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | gradle.properties | 11 |
8 files changed, 74 insertions, 53 deletions
diff --git a/.idea/misc.xml b/.idea/misc.xml index 085136f8..7319f021 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -53,7 +53,7 @@ <ConfirmationsSetting value="0" id="Add" /> <ConfirmationsSetting value="0" id="Remove" /> </component> - <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> + <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <output url="file://$PROJECT_DIR$/build/classes" /> </component> <component name="ProjectType"> diff --git a/app/build.gradle b/app/build.gradle index 5bc879ca..099174be 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -100,23 +100,13 @@ dependencies { annotationProcessor "com.github.Raizlabs.DBFlow:dbflow-processor:${DBFLOW}" kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${DBFLOW}" compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${DBFLOW}" - -// compile "org.greenrobot:eventbus:${EVENTBUS}" - + //Icons - compile "com.mikepenz:google-material-typeface:${IICON_GOOGLE}.original@aar" compile "com.mikepenz:material-design-iconic-typeface:${IICON_MATERIAL}@aar" compile "com.mikepenz:community-material-typeface:${IICON_COMMUNITY}@aar" - compile "io.reactivex.rxjava2:rxjava:${RX_JAVA}" - compile "io.reactivex.rxjava2:rxandroid:${RX_ANDROID}" -// compile "com.jakewharton.rxbinding2:rxbinding:${RX_BINDING}" -// compile "com.jakewharton.rxbinding2:rxbinding-appcompat-v7:${RX_BINDING}" - compile "org.jsoup:jsoup:${JSOUP}" - compile "org.jetbrains.anko:anko:${ANKO}" - compile "com.github.bumptech.glide:glide:${GLIDE}" annotationProcessor "com.github.bumptech.glide:compiler:${GLIDE}" 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") diff --git a/build.gradle b/build.gradle index df3b344f..083ca65f 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { - ext.kotlin_version = '1.1.2-5' + ext.kotlin_version = '1.1.3' repositories { jcenter() maven { url 'https://maven.fabric.io/public' } diff --git a/gradle.properties b/gradle.properties index b7db5d91..8f76b8d1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,25 +19,16 @@ BUILD_TOOLS=26.0.0 VERSION_CODE=5 VERSION_NAME=0.5 -# wait for jitpack to fix itself -KAU=9e31fdd4f1 +KAU=c9302a7b0f MATERIAL_DRAWER=5.9.2 MATERIAL_DRAWER_KT=1.0.2 -IICON_GOOGLE=3.0.1.0 IICON_MATERIAL=2.2.0.2 IICON_COMMUNITY=1.9.32.1 -SEARCH_VIEW=4.0 -RX_JAVA=2.1.0 -RX_ANDROID=2.0.1 -RX_BINDING=2.0.0 JSOUP=1.10.2 -ANKO=0.10.1 GLIDE=4.0.0-RC0 RETROFIT=2.2.0 -EVENTBUS=3.0.0 DBFLOW=4.0.2 ROBOELECTRIC=3.3.2 -RX_PREFS=2.0.0-RC2 PAPER_PARCEL=2.0.1 SWIPE_BACK=3.1.2 CRASHLYTICS=2.6.8 |