diff options
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt | 9 | ||||
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt | 10 | ||||
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt (renamed from app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt) | 8 | ||||
-rw-r--r-- | app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt | 155 | ||||
-rw-r--r-- | app/src/main/res/values/strings.xml | 2 | ||||
-rw-r--r-- | app/src/main/res/values/strings_no_translate.xml | 1 | ||||
-rw-r--r-- | app/src/main/res/values/strings_preferences.xml | 3 | ||||
-rw-r--r-- | app/src/main/res/xml/frost_changelog.xml | 3 | ||||
-rw-r--r-- | docs/Changelog.md | 7 | ||||
-rw-r--r-- | gradle.properties | 2 |
10 files changed, 34 insertions, 166 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt index 27f959cf..1a96601d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt @@ -56,7 +56,7 @@ import com.pitchedapps.frost.fragments.WebFragment import com.pitchedapps.frost.parsers.SearchParser import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.utils.iab.FrostBilling -import com.pitchedapps.frost.utils.iab.IABMain +import com.pitchedapps.frost.utils.iab.IabMain import com.pitchedapps.frost.utils.iab.IS_FROST_PRO import com.pitchedapps.frost.views.BadgedIcon import com.pitchedapps.frost.views.FrostViewPager @@ -71,7 +71,7 @@ import java.util.concurrent.TimeUnit class MainActivity : BaseActivity(), ActivityWebContract, FileChooserContract by FileChooserDelegate(), - FrostBilling by IABMain() { + FrostBilling by IabMain() { lateinit var adapter: SectionsPagerAdapter val toolbar: Toolbar by bindView(R.id.toolbar) @@ -92,7 +92,7 @@ class MainActivity : BaseActivity(), field = value } var searchView: SearchView? = null - val searchViewCache = mutableMapOf<String, List<SearchItem>>() + private val searchViewCache = mutableMapOf<String, List<SearchItem>>() companion object { const val ACTIVITY_SETTINGS = 97 @@ -343,7 +343,8 @@ class MainActivity : BaseActivity(), else doAsync { val data = SearchParser.query(query) ?: return@doAsync - val items = data.map { SearchItem(it.href, it.title, it.description) } + val items = data.map { SearchItem(it.href, it.title, it.description) }.toMutableList() + items.add(SearchItem("${FbItem.SEARCH.url}?q=$query", string(R.string.show_all_results), iicon = null)) searchViewCache.put(query, items) uiThread { searchView?.results = items } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt index 0e0599bf..0511a74f 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt @@ -22,14 +22,14 @@ import com.pitchedapps.frost.enums.Support import com.pitchedapps.frost.settings.* import com.pitchedapps.frost.utils.* import com.pitchedapps.frost.utils.iab.FrostBilling -import com.pitchedapps.frost.utils.iab.IABSettings import com.pitchedapps.frost.utils.iab.IS_FROST_PRO +import com.pitchedapps.frost.utils.iab.IabSettings /** * Created by Allan Wang on 2017-06-06. */ -class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() { +class SettingsActivity : KPrefActivity(), FrostBilling by IabSettings() { var resultFlag = Activity.RESULT_CANCELED @@ -114,6 +114,12 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() { onClick = { _, _, _ -> startActivityForResult(AboutActivity::class.java, 9, true); true } } + plainText(R.string.help_translate) { + descRes = R.string.help_translate_desc + iicon = GoogleMaterial.Icon.gmd_translate + onClick = { _, _, _ -> startLink(R.string.translation_url); true } + } + plainText(R.string.replay_intro) { iicon = GoogleMaterial.Icon.gmd_replay onClick = { _, _, _ -> launchIntroActivity(cookies()); true } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt index 8aa3bcde..0e537f3a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IabBinder.kt @@ -37,7 +37,7 @@ interface FrostBilling : BillingProcessor.IBillingHandler { fun onActivityResultBilling(requestCode: Int, resultCode: Int, data: Intent?): Boolean } -abstract class IABBinder : FrostBilling { +abstract class IabBinder : FrostBilling { var bp: BillingProcessor? = null lateinit var activityRef: WeakReference<Activity> @@ -47,7 +47,7 @@ abstract class IABBinder : FrostBilling { override final fun Activity.onCreateBilling() { activityRef = WeakReference(this) doAsync { - bp = BillingProcessor.newBillingProcessor(this@onCreateBilling, PUBLIC_BILLING_KEY, this@IABBinder) + bp = BillingProcessor.newBillingProcessor(this@onCreateBilling, PUBLIC_BILLING_KEY, this@IabBinder) bp?.initialize() } } @@ -118,7 +118,7 @@ abstract class IABBinder : FrostBilling { } -class IABSettings : IABBinder() { +class IabSettings : IabBinder() { override fun onProductPurchased(productId: String, details: TransactionDetails?) { super.onProductPurchased(productId, details) @@ -150,7 +150,7 @@ class IABSettings : IABBinder() { } } -class IABMain : IABBinder() { +class IabMain : IabBinder() { override fun onBillingInitialized() { super.onBillingInitialized() diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt deleted file mode 100644 index d45c2cf6..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt +++ /dev/null @@ -1,155 +0,0 @@ -package com.pitchedapps.frost.web - -import android.annotation.SuppressLint -import android.content.Context -import android.webkit.JavascriptInterface -import android.webkit.WebView -import ca.allanwang.kau.searchview.SearchItem -import ca.allanwang.kau.utils.gone -import com.pitchedapps.frost.facebook.FbItem -import com.pitchedapps.frost.facebook.USER_AGENT_BASIC -import com.pitchedapps.frost.injectors.JsAssets -import com.pitchedapps.frost.injectors.JsBuilder -import com.pitchedapps.frost.utils.L -import io.reactivex.rxkotlin.subscribeBy -import io.reactivex.schedulers.Schedulers -import io.reactivex.subjects.PublishSubject -import org.jetbrains.anko.runOnUiThread -import org.jsoup.Jsoup -import java.util.concurrent.TimeUnit - -@SuppressLint("ViewConstructor") -/** - * Created by Allan Wang on 2017-06-25. - * - * A bare bone headless search view meant solely to extract search results from the web - * Having a single webview allows us to avoid loading the whole page with each query - */ -class SearchWebView(context: Context, val contract: SearchContract) : WebView(context) { - - val searchSubject = PublishSubject.create<String>()!! - - init { - 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 - */ - private var previousResult: Pair<String, Int> = Pair("", 0) - - private fun saveResultFrame(result: List<Pair<List<String>, String>>) { - synchronized(previousResult) { - previousResult = Pair(result.last().second, result.size) - } - } - - @SuppressLint("SetJavaScriptEnabled") - private fun setupWebview() { - L.i("Begin SearchWebView setup") - settings.javaScriptEnabled = true - settings.userAgentString = USER_AGENT_BASIC - webViewClient = HeadlessWebViewClient("Search", JsAssets.SEARCH) - webChromeClient = HeadlessChromeClient() - addJavascriptInterface(SearchJSI(), "Frost") - searchSubject.debounce(300, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread()) - .map { - val doc = Jsoup.parse(it) - L.d(doc.getElementById("main-search_input")?.html()) - val searchQuery = doc.getElementById("main-search-input")?.text() ?: "Null input" - L.d("Search query", searchQuery) - doc.select("a:not([rel*='keywords(']):not([href=#])[rel]").map { element -> - //split text into separate items - L.v("Search element", element.attr("href")) - val texts = element.select("div").map { it.text() }.filter { !it.isNullOrBlank() } - val pair = Pair(texts, element.attr("href")) - L.v("Search element potential", pair.toString()) - pair - }.filter { it.first.isNotEmpty() } - } - .filter { it.isNotEmpty() } - .filter { Pair(it.last().second, it.size) != previousResult } - .subscribeBy( - onNext = { content: List<Pair<List<String>, String>> -> - saveResultFrame(content) - L.d("Search element count ${content.size}") - contract.emitSearchResponse(content.map { (texts, href) -> - SearchItem(href, texts[0], texts.getOrNull(1)) - }) - }, - onError = { throwable -> - L.e(throwable, "SearchSubject error") - } - ) - reload() - } - - /** - * Toggles web activity - * Should be done in conjunction with showing/hiding the search view - */ - var pauseLoad: Boolean - get() = settings.blockNetworkLoads - set(value) { - context.runOnUiThread { settings.blockNetworkLoads = value } - } - - override fun reload() { - super.loadUrl(FbItem.SEARCH.url) - } - - /** - * Sets the input to have our given text, then dispatches the input event so the webpage recognizes it - */ - fun query(input: String) { - pauseLoad = false - L.d("Searching attempt", input) - 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),e.dispatchEvent(new Event('focus'))}else console.log('Input field not found');").build().inject(this) - } - - inner class SearchJSI { - @JavascriptInterface - fun handleHtml(html: String?) { - html ?: return - L.d("Search received response ${contract.isSearchOpened}") - if (!contract.isSearchOpened) pauseLoad = true - searchSubject.onNext(html) - } - - @JavascriptInterface - fun emit(flag: Int) { - when (flag) { - 0 -> { - L.i("Search loaded successfully") - } - 1 -> { //something is not found in the search view; this is effectively useless - L.e("Search subject error") - dispose() - contract.disposeHeadlessSearch() - } - 2 -> { - L.v("Search emission received") - } - } - } - } - - /** - * Clear up some components - */ - fun dispose() { - searchSubject.onComplete() - } - - interface SearchContract { - fun disposeHeadlessSearch() - fun emitSearchResponse(items: List<SearchItem>) - val isSearchOpened: Boolean - } -} - - - diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b3cf823e..282f1745 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,6 +46,8 @@ <string name="new_message">New Message</string> <string name="no_text">No text</string> + <string name="show_all_results">Show All Results</string> + <!--About--> <string name="frost_description">Frost is a fully themable, diff --git a/app/src/main/res/values/strings_no_translate.xml b/app/src/main/res/values/strings_no_translate.xml index 6b35ad64..b805e00d 100644 --- a/app/src/main/res/values/strings_no_translate.xml +++ b/app/src/main/res/values/strings_no_translate.xml @@ -3,4 +3,5 @@ <string name="dev_paypal" translatable="false">https://www.paypal.me/Allanw9</string> <string name="paypal" translatable="false">PayPal</string> <string name="play_store_package_id" translatable="false">com.pitchedapps.frost</string> + <string name="translation_url" translatable="false">https://crwd.in/frost-for-facebook</string> </resources> diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml index 590e8fe5..a54b95e7 100644 --- a/app/src/main/res/values/strings_preferences.xml +++ b/app/src/main/res/values/strings_preferences.xml @@ -22,6 +22,9 @@ <string name="about_frost">About Frost for Facebook</string> <string name="about_frost_desc">Version, Credits, and FAQs</string> + <string name="help_translate">Help Translate</string> + <string name="help_translate_desc">Frost is translated through crowdin. Contribute if you want it in your language!</string> + <string name="debug_frost">Frost Debugger</string> <string name="debug_frost_desc">Send html data to help with debugging.</string> diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml index 1c98aa08..16a0085b 100644 --- a/app/src/main/res/xml/frost_changelog.xml +++ b/app/src/main/res/xml/frost_changelog.xml @@ -6,6 +6,9 @@ <item text="" /> --> + <version title="Translations are opened!" /> + <item text="If you want to have Frost in your language, please consider helping translate it. Link is in settings." /> + <version title="v1.5.8" /> <item text="Fix theme for newer comments layout" /> <item text="Revert media picker to use system default" /> diff --git a/docs/Changelog.md b/docs/Changelog.md index 9cd235f2..6bbdcf39 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,5 +1,12 @@ # Changelog +## Translations are opened! +* If you want to have Frost in your language, please consider helping translate it. Link is in settings. + +## v1.5.8 +* Fix theme for newer comments layout +* Revert media picker to use system default + ## v1.5.7 * Allow hiding of composer and groups you may knnow * Theme overflow icon diff --git a/gradle.properties b/gradle.properties index 572cf6be..fcea33c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -17,7 +17,7 @@ MIN_SDK=21 TARGET_SDK=26 BUILD_TOOLS=26.0.2 -KAU=17c21ba +KAU=afc1a02 KOTLIN=1.1.51 COMMONS_TEXT=1.1 |