aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/build.gradle5
-rw-r--r--app/src/main/assets/js/menu.js18
-rw-r--r--app/src/main/assets/js/menu.min.js23
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt43
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt19
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt47
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt6
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt17
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/iab/IABBinder.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt29
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt72
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/WebStates.kt11
-rw-r--r--app/src/main/res/values/strings_pref_networks.xml4
-rw-r--r--app/src/main/res/values/strings_pref_notifications.xml1
-rw-r--r--app/src/main/res/values/strings_preferences.xml3
-rw-r--r--app/src/main/res/values/strings_temp.xml6
-rw-r--r--app/src/main/res/xml/frost_changelog.xml8
-rw-r--r--docs/Changelog.md1
-rw-r--r--gradle.properties5
29 files changed, 245 insertions, 123 deletions
diff --git a/app/build.gradle b/app/build.gradle
index 671e8471..6227423b 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -177,7 +177,8 @@ dependencies {
implementation "com.sothree.slidinguppanel:library:${SLIDING_PANEL}"
//Reactive Libs
- compile "io.reactivex.rxjava2:rxkotlin:${RX_KOTLIN}"
- compile "io.reactivex.rxjava2:rxandroid:${RX_ANDROID}"
+ implementation "io.reactivex.rxjava2:rxkotlin:${RX_KOTLIN}"
+ implementation "io.reactivex.rxjava2:rxandroid:${RX_ANDROID}"
+ implementation "com.github.pwittchen:reactivenetwork-rx2:${RX_NETWORK}"
} \ No newline at end of file
diff --git a/app/src/main/assets/js/menu.js b/app/src/main/assets/js/menu.js
index 7394c824..a43b1820 100644
--- a/app/src/main/assets/js/menu.js
+++ b/app/src/main/assets/js/menu.js
@@ -4,6 +4,8 @@ if (!window.hasOwnProperty('frost_menu')) {
window.frost_menu = true;
var viewport = document.querySelector('#viewport');
var root = document.querySelector('#root');
+ if (!viewport) console.log('Menu.js: viewport is null');
+ if (!root) console.log('Menu.js: root is null');
var y = new MutationObserver(function(mutations) {
viewport.removeAttribute('style');
root.removeAttribute('style');
@@ -21,18 +23,24 @@ if (!window.hasOwnProperty('frost_menu')) {
console.log('Found side menu');
while (root.firstChild)
root.removeChild(root.firstChild);
- while (menu.childNodes.length)
- root.appendChild(menu.childNodes[0]);
- Frost.emit(0);
+ while (menu.childNodes.length) {
+ console.log('append');
+ viewport.appendChild(menu.childNodes[0]);
+ }
+ if (typeof Frost !== 'undefined') Frost.emit(0);
setTimeout(function() {
y.disconnect();
console.log('Unhook styler');
}, 500);
}
});
- x.observe(document.querySelector('#mJewelNav'), {
+ var jewel = document.querySelector('#mJewelNav');
+ if (!jewel) console.log('Menu.js: jewel is null');
+ x.observe(jewel, {
childList: true,
subtree: true
});
- document.querySelector('#bookmarks_jewel').querySelector('a').click();
+ var menuA = document.querySelector('#bookmarks_jewel').querySelector('a');
+ if (!menuA) console.log('Menu.js: jewel is null')
+ menuA.click();
}
diff --git a/app/src/main/assets/js/menu.min.js b/app/src/main/assets/js/menu.min.js
index 5403e03a..5b65ac9b 100644
--- a/app/src/main/assets/js/menu.min.js
+++ b/app/src/main/assets/js/menu.min.js
@@ -1,8 +1,10 @@
if(!window.hasOwnProperty("frost_menu")){
console.log("Registering frost_menu"),window.frost_menu=!0
-;var viewport=document.querySelector("#viewport"),root=document.querySelector("#root"),y=new MutationObserver(function(e){
-viewport.removeAttribute("style"),
-root.removeAttribute("style")
+;var viewport=document.querySelector("#viewport"),root=document.querySelector("#root")
+;viewport||console.log("Menu.js: viewport is null"),
+root||console.log("Menu.js: root is null")
+;var y=new MutationObserver(function(e){
+viewport.removeAttribute("style"),root.removeAttribute("style")
})
;y.observe(viewport,{
attributes:!0
@@ -13,14 +15,19 @@ attributes:!0
var o=document.querySelector(".mSideMenu")
;if(null!==o){
for(x.disconnect(),console.log("Found side menu");root.firstChild;)root.removeChild(root.firstChild)
-;for(;o.childNodes.length;)root.appendChild(o.childNodes[0])
-;Frost.emit(0),setTimeout(function(){
+;for(;o.childNodes.length;)console.log("append"),
+viewport.appendChild(o.childNodes[0])
+;"undefined"!=typeof Frost&&Frost.emit(0),setTimeout(function(){
y.disconnect(),console.log("Unhook styler")
},500)
}
-})
-;x.observe(document.querySelector("#mJewelNav"),{
+}),jewel=document.querySelector("#mJewelNav")
+;jewel||console.log("Menu.js: jewel is null"),
+x.observe(jewel,{
childList:!0,
subtree:!0
-}),document.querySelector("#bookmarks_jewel").querySelector("a").click()
+})
+;var menuA=document.querySelector("#bookmarks_jewel").querySelector("a")
+;menuA||console.log("Menu.js: jewel is null"),
+menuA.click()
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
index 77a20d04..c7ca5ec7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/BaseActivity.kt
@@ -2,10 +2,16 @@ package com.pitchedapps.frost.activities
import android.os.Bundle
import ca.allanwang.kau.internal.KauBaseActivity
+import com.github.pwittchen.reactivenetwork.library.rx2.Connectivity
+import com.github.pwittchen.reactivenetwork.library.rx2.ReactiveNetwork
import com.pitchedapps.frost.R
+import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.materialDialogThemed
import com.pitchedapps.frost.utils.setFrostTheme
+import io.reactivex.android.schedulers.AndroidSchedulers
+import io.reactivex.disposables.Disposable
+import io.reactivex.schedulers.Schedulers
/**
* Created by Allan Wang on 2017-06-12.
@@ -29,4 +35,41 @@ abstract class BaseActivity : KauBaseActivity() {
setFrostTheme()
}
+ private var networkDisposable: Disposable? = null
+ private var networkConsumer: ((Connectivity) -> Unit)? = null
+
+ fun setNetworkObserver(consumer: (connectivity: Connectivity) -> Unit) {
+ this.networkConsumer = consumer
+ }
+
+ fun observeNetworkConnectivity() {
+ val consumer = networkConsumer ?: return
+ networkDisposable = ReactiveNetwork.observeNetworkConnectivity(applicationContext)
+ .subscribeOn(Schedulers.io())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe {
+ connectivity: Connectivity ->
+ connectivity.apply {
+ L.d("Network connectivity changed: isAvailable: $isAvailable isRoaming: $isRoaming")
+ consumer(connectivity)
+ }
+ }
+ }
+
+ fun disposeNetworkConnectivity() {
+ if (!(networkDisposable?.isDisposed ?: true))
+ networkDisposable?.dispose()
+ networkDisposable = null
+ }
+
+ override fun onResume() {
+ super.onResume()
+ disposeNetworkConnectivity()
+ observeNetworkConnectivity()
+ }
+
+ override fun onPause() {
+ super.onPause()
+ disposeNetworkConnectivity()
+ }
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
index 47c286fa..eb991599 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/LoginActivity.kt
@@ -79,7 +79,7 @@ class LoginActivity : BaseActivity() {
refresh = false
if (!foundImage) {
L.eThrow("Could not get profile photo; Invalid userId?")
- L.i("-\t$cookie")
+ L.i(null, cookie.toString())
}
textview.text = String.format(getString(R.string.welcome), name)
textview.fadeIn()
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 58c7b121..af7db2f0 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/MainActivity.kt
@@ -60,6 +60,7 @@ import com.pitchedapps.frost.utils.iab.IS_FROST_PRO
import com.pitchedapps.frost.views.BadgedIcon
import com.pitchedapps.frost.views.FrostViewPager
import com.pitchedapps.frost.web.SearchWebView
+import com.pitchedapps.frost.web.shouldLoadImages
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
@@ -160,14 +161,10 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract,
// }
setFrostColors(toolbar, themeWindow = false, headers = arrayOf(tabs, appBar), backgrounds = arrayOf(viewPager))
onCreateBilling()
- if (Prefs.installDate < 1501454310304 && Showcase.intro)
- materialDialogThemed {
- title(R.string.intro_title)
- content(R.string.intro_desc)
- positiveText(R.string.kau_yes)
- negativeText(R.string.kau_no)
- onPositive { _, _ -> launchIntroActivity(cookies()) }
- }
+ setNetworkObserver {
+ connectivity ->
+ shouldLoadImages = !connectivity.isRoaming
+ }
}
fun tabsForEachView(action: (position: Int, view: BadgedIcon) -> Unit) {
@@ -370,11 +367,7 @@ class MainActivity : BaseActivity(), SearchWebView.SearchContract,
if (Prefs.searchBar) {
if (firstLoadFinished && hiddenSearchView == null) hiddenSearchView = SearchWebView(this, this)
if (searchView == null) searchView = bindSearchView(menu, R.id.action_search, Prefs.iconColor) {
- textCallback = {
- query, _ ->
- hiddenSearchView?.query(query)
- }
- textDebounceInterval = 200L
+ textCallback = { query, _ -> runOnUiThread { hiddenSearchView?.query(query) } }
foregroundColor = Prefs.textColor
backgroundColor = Prefs.bgColor.withMinAlpha(200)
openListener = { hiddenSearchView?.pauseLoad = false }
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 200c5fa4..3fd3e3b5 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
@@ -67,6 +67,11 @@ class SettingsActivity : KPrefActivity(), FrostBilling by IABSettings() {
iicon = GoogleMaterial.Icon.gmd_notifications
}
+ subItems(R.string.network, getNetworkPrefs()) {
+ descRes = R.string.network_desc
+ iicon = GoogleMaterial.Icon.gmd_network_cell
+ }
+
subItems(R.string.experimental, getExperimentalPrefs()) {
descRes = R.string.experimental_desc
iicon = CommunityMaterial.Icon.cmd_flask_outline
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt
index 7cd93d14..69b2ba41 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/facebook/FbUrlFormatter.kt
@@ -33,7 +33,7 @@ class FbUrlFormatter(url: String) {
if (cleanedUrl.startsWith("#!/")) cleanedUrl = cleanedUrl.substring(2)
if (cleanedUrl.startsWith("/")) cleanedUrl = FB_URL_BASE + cleanedUrl.substring(1)
cleanedUrl = cleanedUrl.replaceFirst(".facebook.com//", ".facebook.com/") //sometimes we are given a bad url
- L.v("Formatted url from $url to $cleanedUrl")
+ L.v(null, "Formatted url from $url to $cleanedUrl")
cleaned = cleanedUrl
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
index 0992a9cb..b9b35956 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
@@ -3,7 +3,9 @@ package com.pitchedapps.frost.injectors
import android.graphics.Color
import android.webkit.WebView
import ca.allanwang.kau.utils.*
+import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
+import java.io.FileNotFoundException
/**
* Created by Allan Wang on 2017-05-31.
@@ -19,28 +21,33 @@ enum class CssAssets(val folder: String = "themes") : InjectorContract {
override fun inject(webView: WebView, callback: ((String) -> Unit)?) {
if (injector == null) {
- var content = webView.context.assets.open("css/$folder/$file").bufferedReader().use { it.readText() }
- if (this == CUSTOM) {
- var bbt = Prefs.bgColor
- val bt: String
- if (Color.alpha(bbt) == 255) {
- bbt = bbt.adjustAlpha(0.2f).colorToForeground(0.35f)
- bt = Prefs.bgColor.toRgbaString()
- } else {
- bbt = bbt.adjustAlpha(0.05f).colorToForeground(0.5f)
- bt = "transparent"
+ try {
+ var content = webView.context.assets.open("css/$folder/$file").bufferedReader().use { it.readText() }
+ if (this == CUSTOM) {
+ var bbt = Prefs.bgColor
+ val bt: String
+ if (Color.alpha(bbt) == 255) {
+ bbt = bbt.adjustAlpha(0.2f).colorToForeground(0.35f)
+ bt = Prefs.bgColor.toRgbaString()
+ } else {
+ bbt = bbt.adjustAlpha(0.05f).colorToForeground(0.5f)
+ bt = "transparent"
+ }
+ content = content
+ .replace("\$T\$", Prefs.textColor.toRgbaString())
+ .replace("\$TT\$", Prefs.textColor.colorToBackground(0.05f).toRgbaString())
+ .replace("\$B\$", Prefs.bgColor.toRgbaString())
+ .replace("\$BT\$", bt)
+ .replace("\$BBT\$", bbt.toRgbaString())
+ .replace("\$O\$", Prefs.bgColor.withAlpha(255).toRgbaString())
+ .replace("\$OO\$", Prefs.bgColor.colorToForeground(0.35f).withAlpha(255).toRgbaString())
+ .replace("\$D\$", Prefs.textColor.adjustAlpha(0.3f).toRgbaString())
}
- content = content
- .replace("\$T\$", Prefs.textColor.toRgbaString())
- .replace("\$TT\$", Prefs.textColor.colorToBackground(0.05f).toRgbaString())
- .replace("\$B\$", Prefs.bgColor.toRgbaString())
- .replace("\$BT\$", bt)
- .replace("\$BBT\$", bbt.toRgbaString())
- .replace("\$O\$", Prefs.bgColor.withAlpha(255).toRgbaString())
- .replace("\$OO\$", Prefs.bgColor.colorToForeground(0.35f).withAlpha(255).toRgbaString())
- .replace("\$D\$", Prefs.textColor.adjustAlpha(0.3f).toRgbaString())
+ injector = JsBuilder().css(content).build()
+ } catch (e: FileNotFoundException) {
+ L.e(e, "CssAssets file not found")
+ injector = JsInjector(JsActions.EMPTY.function)
}
- injector = JsBuilder().css(content).build()
}
injector!!.inject(webView, callback)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
index 2453d3b0..52a1a5f9 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/FrostNotifications.kt
@@ -99,7 +99,7 @@ data class NotificationContent(val data: CookieModel,
.setGroup(group)
if (timestamp != -1L) notifBuilder.setWhen(timestamp * 1000)
- L.v("Notif load $this")
+ L.v("Notif load", this.toString())
NotificationManagerCompat.from(context).notify(group, notifId, notifBuilder.withBigText.build().frostConfig())
if (profileUrl.isNotBlank()) {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
index fe7758cc..972014a3 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/services/NotificationService.kt
@@ -96,7 +96,7 @@ class NotificationService : JobService() {
}
fun fetchGeneralNotifications(data: CookieModel) {
- L.i("Notif fetch for $data")
+ L.i("Notif fetch", data.toString())
val doc = Jsoup.connect(FbTab.NOTIFICATIONS.url).cookie(FACEBOOK_COM, data.cookie).userAgent(USER_AGENT_BASIC).get()
//aclb for unread, acw for read
val unreadNotifications = (doc.getElementById("notifications_list") ?: return L.eThrow("Notification list not found")).getElementsByClass("aclb")
@@ -139,7 +139,7 @@ class NotificationService : JobService() {
}
fun fetchMessageNotifications(data: CookieModel, content: String) {
- L.i("Notif IM fetch for $data")
+ L.i("Notif IM fetch", data.toString())
val doc = Jsoup.parseBodyFragment(content)
val unreadNotifications = (doc.getElementById("threadlist_rows") ?: return L.eThrow("Notification messages not found")).getElementsByClass("aclb")
var notifCount = 0
@@ -175,7 +175,7 @@ class NotificationService : JobService() {
//fetch convo pic
val p = element.select("i.img[style*=url]")
val pUrl = profMatcher.find(p.attr("style"))?.groups?.get(1)?.value ?: ""
- L.v("url ${a.attr("href")}")
+ L.v("url", a.attr("href"))
return NotificationContent(data, notifId.toInt(), a.attr("href"), a.text(), text, epoch, pUrl.formattedFbUrl)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt
new file mode 100644
index 00000000..30ab2579
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Network.kt
@@ -0,0 +1,17 @@
+package com.pitchedapps.frost.settings
+
+import ca.allanwang.kau.kpref.activity.KPrefAdapterBuilder
+import com.pitchedapps.frost.R
+import com.pitchedapps.frost.activities.SettingsActivity
+import com.pitchedapps.frost.utils.Prefs
+
+/**
+ * Created by Allan Wang on 2017-08-08.
+ */
+fun SettingsActivity.getNetworkPrefs(): KPrefAdapterBuilder.() -> Unit = {
+
+ checkbox(R.string.network_media_on_metered, { Prefs.loadMediaOnMeteredNetwork }, { Prefs.loadMediaOnMeteredNetwork = it }) {
+ descRes = R.string.network_media_on_metered_desc
+ }
+
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
index b053b9dd..e52109c4 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
@@ -128,4 +128,6 @@ object Prefs : KPref() {
var viewpagerSwipe: Boolean by kpref("viewpager_swipe", true)
+ var loadMediaOnMeteredNetwork: Boolean by kpref("media_on_metered_network", true)
+
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
index 496a6b5b..91c5ca23 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
@@ -56,8 +56,8 @@ fun Activity.cookies(): ArrayList<CookieModel> {
fun Context.launchWebOverlay(url: String) {
val argUrl = url.formattedFbUrl
- L.v("Launch received $url")
- L.i("Launch web overlay: $argUrl")
+ L.v("Launch received", url)
+ L.i("Launch web overlay", argUrl)
startActivity(WebOverlayActivity::class.java, false, intentBuilder = {
putExtra(ARG_URL, argUrl)
})
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 47331833..b4dc2294 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
@@ -57,13 +57,13 @@ abstract class IABBinder : FrostBilling {
activityRef.clear()
}
- override fun onBillingInitialized() = L.d("IAB initialized")
+ override fun onBillingInitialized() = L.i("IAB initialized")
override fun onPurchaseHistoryRestored() = L.d("IAB restored")
override fun onProductPurchased(productId: String, details: TransactionDetails?) {
bp.doAsync {
- L.d("IAB $productId purchased")
+ L.i("IAB $productId purchased")
val listing = weakRef.get()?.getPurchaseListingDetails(productId) ?: return@doAsync
val currency = try {
Currency.getInstance(listing.currency)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt
index 6bc27256..61711092 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClients.kt
@@ -34,15 +34,9 @@ class FrostChromeClient(webCore: FrostWebViewCore) : WebChromeClient() {
val activityContract = (webCore.context as? ActivityWebContract)
val context = webCore.context!!
- companion object {
- val consoleBlacklist = setOf(
- "edge-chat"
- )
- }
-
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
if (consoleBlacklist.any { consoleMessage.message().contains(it) }) return true
- L.i("Chrome Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}")
+ L.d("Chrome Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}")
return true
}
@@ -63,10 +57,10 @@ class FrostChromeClient(webCore: FrostWebViewCore) : WebChromeClient() {
}
override fun onGeolocationPermissionsShowPrompt(origin: String, callback: GeolocationPermissions.Callback) {
- L.d("Requesting geolocation")
+ L.i("Requesting geolocation")
context.kauRequestPermissions(PERMISSION_ACCESS_FINE_LOCATION) {
granted, _ ->
- L.d("Geolocation response received; ${if (granted) "granted" else "denied"}")
+ L.i("Geolocation response received; ${if (granted) "granted" else "denied"}")
callback(origin, granted, true)
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt
index 3f2891d0..1a907f7f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostRequestInterceptor.kt
@@ -5,6 +5,7 @@ import android.webkit.WebResourceResponse
import android.webkit.WebView
import ca.allanwang.kau.utils.use
import com.pitchedapps.frost.utils.L
+import com.pitchedapps.frost.utils.Prefs
import okhttp3.HttpUrl
import java.io.ByteArrayInputStream
@@ -15,17 +16,17 @@ import java.io.ByteArrayInputStream
* Handler to decide when a request should be done by us
* This is the crux of Frost's optimizations for the web browser
*/
-val blankResource: WebResourceResponse by lazy { WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray())) }
+private val blankResource: WebResourceResponse by lazy { WebResourceResponse("text/plain", "utf-8", ByteArrayInputStream("".toByteArray())) }
//these hosts will redirect to a blank resource
-val blacklistHost: Set<String> by lazy {
+private val blacklistHost: Set<String> by lazy {
setOf(
"edge-chat.facebook.com"
)
}
//these hosts will return null and skip logging
-val whitelistHost: Set<String> by lazy {
+private val whitelistHost: Set<String> by lazy {
setOf(
"static.xx.fbcdn.net",
"m.facebook.com",
@@ -35,13 +36,13 @@ val whitelistHost: Set<String> by lazy {
//these hosts will skip ad inspection
//this list does not have to include anything from the two above
-val adWhitelistHost: Set<String> by lazy {
+private val adWhitelistHost: Set<String> by lazy {
setOf(
"scontent-sea1-1.xx.fbcdn.net"
)
}
-var adblock: Set<String>? = null
+private var adblock: Set<String>? = null
fun shouldFrostInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
val httpUrl = HttpUrl.parse(request.url?.toString() ?: return null) ?: return null
@@ -53,7 +54,8 @@ fun shouldFrostInterceptRequest(view: WebView, request: WebResourceRequest): Web
if (adblock == null) adblock = view.context.assets.open("adblock.txt").bufferedReader().use { it.readLines().toSet() }
if (adblock?.any { url.contains(it) } ?: false) return blankResource
}
- L.v("Intercept Request ${host} ${url}")
+ if (!shouldLoadImages && !Prefs.loadMediaOnMeteredNetwork && request.isMedia) return blankResource
+ L.v("Intercept Request", "$host $url")
return null
}
@@ -64,16 +66,25 @@ fun WebResourceRequest.query(action: (url: String) -> Boolean): Boolean {
return action(url?.path ?: return false)
}
+val WebResourceRequest.isImage: Boolean
+ get() = query { it.contains(".jpg") || it.contains(".png") }
+
+val WebResourceRequest.isMedia: Boolean
+ get() = query { it.contains(".jpg") || it.contains(".png") || it.contains("video") }
+
/**
* Generic filter passthrough
* If Resource is already nonnull, pass it, otherwise check if filter is met and override the response accordingly
*/
-fun WebResourceResponse?.filter(request: WebResourceRequest, filter: (url: String) -> Boolean): WebResourceResponse?
- = this ?: if (request.query { filter(it) }) blankResource else null
+fun WebResourceResponse?.filter(request: WebResourceRequest, filter: (url: String) -> Boolean)
+ = filter(request.query { filter(it) })
+
+fun WebResourceResponse?.filter(filter: Boolean): WebResourceResponse?
+ = this ?: if (filter) blankResource else null
fun WebResourceResponse?.filterCss(request: WebResourceRequest): WebResourceResponse?
= filter(request) { it.endsWith(".css") }
fun WebResourceResponse?.filterImage(request: WebResourceRequest): WebResourceResponse?
- = filter(request) { it.contains(".jpg") || it.contains(".png") }
+ = filter(request.isImage)
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
index f3068c43..3c08fda9 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClients.kt
@@ -2,6 +2,7 @@ package com.pitchedapps.frost.web
import android.content.Context
import android.graphics.Bitmap
+import android.graphics.Color
import android.webkit.WebResourceRequest
import android.webkit.WebResourceResponse
import android.webkit.WebView
@@ -17,6 +18,7 @@ import com.pitchedapps.frost.injectors.*
import com.pitchedapps.frost.utils.*
import com.pitchedapps.frost.utils.iab.IS_FROST_PRO
import io.reactivex.subjects.Subject
+import org.jetbrains.anko.withAlpha
/**
* Created by Allan Wang on 2017-05-31.
@@ -41,18 +43,19 @@ open class BaseWebViewClient : WebViewClient() {
open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient() {
val refreshObservable: Subject<Boolean> = webCore.refreshObservable
+ val isMain = webCore.baseEnum != null
override fun onPageStarted(view: WebView, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
if (url == null) return
- L.i("FWV Loading $url")
-// L.v("Cookies ${CookieManager.getInstance().getCookie(url)}")
+ L.i("FWV Loading", url)
refreshObservable.onNext(true)
if (!url.contains(FACEBOOK_COM)) return
if (url.contains("logout.php")) FbCookie.logout(Prefs.userId, { launchLogin(view.context) })
else if (url.contains("login.php")) FbCookie.reset({ launchLogin(view.context) })
}
+
fun launchLogin(c: Context) {
if (c is MainActivity && c.cookies().isNotEmpty())
c.launchNewTask(SelectorActivity::class.java, c.cookies())
@@ -60,19 +63,28 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
c.launchNewTask(LoginActivity::class.java)
}
+ fun injectBackgroundColor()
+ = webCore.setBackgroundColor(if (isMain) Color.TRANSPARENT else Prefs.bgColor.withAlpha(255))
+
+
+ override fun onPageCommitVisible(view: WebView, url: String?) {
+ super.onPageCommitVisible(view, url)
+ injectBackgroundColor()
+ view.jsInject(
+ CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons),
+ CssHider.HEADER,
+ CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO),
+ Prefs.themeInjector,
+ CssHider.NON_RECENT.maybe(webCore.url?.contains("?sk=h_chr") ?: false))
+ }
+
override fun onPageFinished(view: WebView, url: String?) {
- super.onPageFinished(view, url)
- if (url == null) return
- L.i("Page finished $url")
+ url ?: return
+ L.i("Page finished", url)
if (!url.contains(FACEBOOK_COM)) {
refreshObservable.onNext(false)
return
}
- view.jsInject(
- CssAssets.ROUND_ICONS.maybe(Prefs.showRoundedIcons),
- CssHider.PEOPLE_YOU_MAY_KNOW.maybe(!Prefs.showSuggestedFriends && IS_FROST_PRO),
- CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO)
- )
onPageFinishedActions(url)
}
@@ -82,19 +94,16 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
internal fun injectAndFinish() {
L.d("Page finished reveal")
- webCore.jsInject(CssHider.HEADER,
- CssHider.NON_RECENT.maybe(webCore.url.contains("?sk=h_chr")),
- Prefs.themeInjector,
- callback = {
- refreshObservable.onNext(false)
- webCore.jsInject(
- JsActions.LOGIN_CHECK,
- JsAssets.CLICK_A.maybe(webCore.baseEnum != null && Prefs.overlayEnabled),
- JsAssets.TEXTAREA_LISTENER,
- JsAssets.CONTEXT_A,
- JsAssets.HEADER_BADGES.maybe(webCore.baseEnum != null)
- )
- })
+ refreshObservable.onNext(false)
+ injectBackgroundColor()
+ webCore.jsInject(
+ JsActions.LOGIN_CHECK,
+ JsAssets.CLICK_A.maybe(webCore.baseEnum != null && Prefs.overlayEnabled),
+ JsAssets.TEXTAREA_LISTENER,
+ CssHider.ADS.maybe(!Prefs.showFacebookAds && IS_FROST_PRO),
+ JsAssets.CONTEXT_A,
+ JsAssets.HEADER_BADGES.maybe(webCore.baseEnum != null)
+ )
}
open fun handleHtml(html: String?) {
@@ -111,26 +120,26 @@ open class FrostWebViewClient(val webCore: FrostWebViewCore) : BaseWebViewClient
* returns false if we are already in an overlaying activity
*/
private fun launchRequest(request: WebResourceRequest): Boolean {
- L.d("Launching Url", request.url.toString())
+ L.d("Launching Url", request.url?.toString() ?: "null")
if (webCore.context is WebOverlayActivity) return false
webCore.context.launchWebOverlay(request.url.toString())
return true
}
- private fun launchImage(request: WebResourceRequest, text: String? = null): Boolean {
- L.d("Launching Image", request.url.toString())
- webCore.context.launchImageActivity(request.url.toString(), text)
+ private fun launchImage(url: String, text: String? = null): Boolean {
+ L.d("Launching Image", url)
+ webCore.context.launchImageActivity(url, text)
if (webCore.canGoBack()) webCore.goBack()
return true
}
override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
- L.i("Url Loading ${request.url}")
- val path = request.url.path ?: return super.shouldOverrideUrlLoading(view, request)
- L.v("Url Loading Path $path")
+ L.i("Url Loading", request.url?.toString())
+ val path = request.url?.path ?: return super.shouldOverrideUrlLoading(view, request)
+ L.v("Url Loading Path", path)
if (path.startsWith("/composer/")) return launchRequest(request)
if (request.url.toString().contains("scontent-sea1-1.xx.fbcdn.net") && (path.endsWith(".jpg") || path.endsWith(".png")))
- return launchImage(request)
+ return launchImage(request.url.toString())
if (view.context.resolveActivityForUri(request.url)) return true
return super.shouldOverrideUrlLoading(view, request)
}
@@ -162,6 +171,7 @@ class FrostWebViewClientMenu(webCore: FrostWebViewCore) : FrostWebViewClient(web
}
override fun onPageFinishedActions(url: String) {
+ L.d("Should inject ${url.shouldInjectMenu}")
if (!url.shouldInjectMenu) injectAndFinish()
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt
index d8edc15c..390055cd 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt
@@ -76,7 +76,7 @@ class FrostWebViewCore @JvmOverloads constructor(
if (isVisible) fadeOut(duration = 200L)
} else if (loading) {
dispose?.dispose()
- if (animate && Prefs.animate) circularReveal(offset = 150L)
+ if (animate && Prefs.animate) circularReveal(offset = WEB_LOAD_DELAY)
else fadeIn(duration = 100L)
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
index 31be4450..aea25337 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt
@@ -60,7 +60,7 @@ class LoginWebView @JvmOverloads constructor(
view.jsInject(CssHider.HEADER.maybe(containsFacebook),
CssHider.CORE.maybe(containsFacebook),
Prefs.themeInjector.maybe(containsFacebook),
- callback = { if (!view.isVisible) view.fadeIn(offset = 150L) })
+ callback = { if (!view.isVisible) view.fadeIn(offset = WEB_LOAD_DELAY) })
}
fun checkForLogin(url: String?, onFound: (id: Long, cookie: String) -> Unit) {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt
index fb4e5bf7..f63f4fdc 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/SearchWebView.kt
@@ -56,13 +56,17 @@ class SearchWebView(context: Context, val contract: SearchContract) : WebView(co
addJavascriptInterface(SearchJSI(), "Frost")
searchSubject.debounce(300, TimeUnit.MILLISECONDS).subscribeOn(Schedulers.newThread())
.map {
- Jsoup.parse(it).select("a:not([rel*='keywords(']):not([href=#])[rel]").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")}")
+ 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")
+ L.v("Search element potential", pair.toString())
pair
}.filter { it.first.isNotEmpty() }
}
@@ -124,6 +128,9 @@ class SearchWebView(context: Context, val contract: SearchContract) : WebView(co
searchSubject.onComplete()
contract.searchOverlayDispose()
}
+ 2 -> {
+ L.v("Search emission received")
+ }
}
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/WebStates.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/WebStates.kt
new file mode 100644
index 00000000..ad1fe467
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/WebStates.kt
@@ -0,0 +1,11 @@
+package com.pitchedapps.frost.web
+
+/**
+ * Created by Allan Wang on 2017-08-08.
+ *
+ * Global variables that are define states or constants for web contents
+ */
+const val WEB_LOAD_DELAY = 50L
+var shouldLoadImages = false
+
+val consoleBlacklist = setOf("edge-chat") \ No newline at end of file
diff --git a/app/src/main/res/values/strings_pref_networks.xml b/app/src/main/res/values/strings_pref_networks.xml
new file mode 100644
index 00000000..29eca24a
--- /dev/null
+++ b/app/src/main/res/values/strings_pref_networks.xml
@@ -0,0 +1,4 @@
+<resources>
+ <string name="network_media_on_metered">Load images on metered network.</string>
+ <string name="network_media_on_metered_desc">If a metered network is detected, Frost will automatically stop all images and videos from loading.</string>
+</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/strings_pref_notifications.xml b/app/src/main/res/values/strings_pref_notifications.xml
index 00c30b57..3cd953f6 100644
--- a/app/src/main/res/values/strings_pref_notifications.xml
+++ b/app/src/main/res/values/strings_pref_notifications.xml
@@ -19,5 +19,4 @@
<string name="notification_vibrate">Notification vibration</string>
<string name="notification_lights">Notification lights</string>
-
</resources> \ No newline at end of file
diff --git a/app/src/main/res/values/strings_preferences.xml b/app/src/main/res/values/strings_preferences.xml
index c2ba0b36..3cacf684 100644
--- a/app/src/main/res/values/strings_preferences.xml
+++ b/app/src/main/res/values/strings_preferences.xml
@@ -10,6 +10,9 @@
<string name="behaviour">Behaviour</string>
<string name="behaviour_desc">Define how the app interacts in certain settings</string>
+ <string name="network">Network</string>
+ <string name="network_desc">Define options that affect metered networks</string>
+
<string name="experimental">Experimental</string>
<string name="experimental_desc">Enable early access to potentially unstable features</string>
diff --git a/app/src/main/res/values/strings_temp.xml b/app/src/main/res/values/strings_temp.xml
deleted file mode 100644
index 526b102d..00000000
--- a/app/src/main/res/values/strings_temp.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<resources>
- <string name="intro_title">Frost now has an intro screen</string>
- <string name="intro_desc">Would you like to see it? You can always replay it under settings</string>
-
-</resources> \ No newline at end of file
diff --git a/app/src/main/res/xml/frost_changelog.xml b/app/src/main/res/xml/frost_changelog.xml
index ddaa6312..8f0c90a8 100644
--- a/app/src/main/res/xml/frost_changelog.xml
+++ b/app/src/main/res/xml/frost_changelog.xml
@@ -11,9 +11,13 @@
<!--<version title="Beta Updates" />-->
<version title="Beta Updates"/>
- <item text="Fixed notification titles" />
- <item text="Added support for downloading videos" />
+ <item text="Fix notification titles" />
+ <item text="ALPHA: Add support for downloading videos (hit the download button)" />
<item text="Deny intents for login so the page loads properly (thank you @Zenexer)" />
+ <item text="Reduce injection offset and move injectors to an earlier method" />
+ <item text="Add option to disable media loading on metered network" />
+ <item text="Fix menu section" />
+ <item text="Add more background setters to help transparent themes" />
<item text="" />
<item text="" />
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 50154ff5..a7a855f7 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -4,6 +4,7 @@
* Fixed notification titles
* Added support for downloading videos
* Deny intents for login so the page loads properly (thank you @Zenexer)
+* Reduce injection offset and move injectors to an earlier method
## v1.5.0
* Experimental: Add notifications for messages; report to me if this drains your battery
diff --git a/gradle.properties b/gradle.properties
index a1c9cab9..c0cc3b0a 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -17,12 +17,12 @@ MIN_SDK=21
TARGET_SDK=26
BUILD_TOOLS=26.0.1
-KAU=3.3.0
+KAU=c2dd5d6
KOTLIN=1.1.3-2
CRASHLYTICS=2.6.8
DBFLOW=4.0.5
-IAB=1.0.43
+IAB=1.0.44
IICON_COMMUNITY=1.9.32.2
IICON_MATERIAL=2.2.0.3
JSOUP=1.10.3
@@ -35,5 +35,6 @@ RX_ANDROID=2.0.1
RX_BINDING=2.0.0
RX_JAVA=2.1.2
RX_KOTLIN=2.1.0
+RX_NETWORK=0.11.0
SCALE_IMAGE_VIEW=3.6.0
SLIDING_PANEL=3.3.1 \ No newline at end of file