aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2019-01-03 23:10:53 -0500
committerGitHub <noreply@github.com>2019-01-03 23:10:53 -0500
commit82f79a7d368caad4068d97051ad8deddd05b4f7e (patch)
treebfaca5c42f0ffb878c58b21b72731610f4da879a
parentbc6566bc92d073e64a8c51a681ff01ba973d7ee7 (diff)
downloadfrost-82f79a7d368caad4068d97051ad8deddd05b4f7e.tar.gz
frost-82f79a7d368caad4068d97051ad8deddd05b4f7e.tar.bz2
frost-82f79a7d368caad4068d97051ad8deddd05b4f7e.zip
Add asset preloader (#1311)
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt10
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt8
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt33
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt5
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt19
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt43
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt2
-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.kt8
11 files changed, 80 insertions, 56 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
index 3fafa2a6..37383182 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt
@@ -37,6 +37,7 @@ import com.pitchedapps.frost.utils.EXTRA_COOKIES
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.launchNewTask
+import com.pitchedapps.frost.utils.loadAssets
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -63,6 +64,7 @@ class StartActivity : KauBaseActivity() {
})
L.i { "Cookies loaded at time ${System.currentTimeMillis()}" }
L._d { "Cookies: ${cookies.joinToString("\t")}" }
+ loadAssets()
if (cookies.isNotEmpty()) {
if (Prefs.userId != -1L)
startActivity<MainActivity>(intentBuilder = {
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt
index 4aa0966c..04f67276 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/IntroActivity.kt
@@ -53,6 +53,9 @@ import com.pitchedapps.frost.intro.IntroTabTouchFragment
import com.pitchedapps.frost.utils.Prefs
import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.launchNewTask
+import com.pitchedapps.frost.utils.loadAssets
+import kotlinx.coroutines.NonCancellable
+import kotlinx.coroutines.launch
/**
* Created by Allan Wang on 2017-07-25.
@@ -166,8 +169,11 @@ class IntroActivity : KauBaseActivity(), ViewPager.PageTransformer, ViewPager.On
}
override fun finish() {
- launchNewTask<MainActivity>(cookies(), false)
- super.finish()
+ launch(NonCancellable) {
+ loadAssets()
+ launchNewTask<MainActivity>(cookies(), false)
+ super.finish()
+ }
}
override fun onBackPressed() {
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 37047448..c3089c7a 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/SettingsActivity.kt
@@ -53,8 +53,11 @@ import com.pitchedapps.frost.utils.cookies
import com.pitchedapps.frost.utils.frostChangelog
import com.pitchedapps.frost.utils.frostNavigationBar
import com.pitchedapps.frost.utils.launchNewTask
+import com.pitchedapps.frost.utils.loadAssets
import com.pitchedapps.frost.utils.materialDialogThemed
import com.pitchedapps.frost.utils.setFrostTheme
+import kotlinx.coroutines.NonCancellable
+import kotlinx.coroutines.launch
/**
* Created by Allan Wang on 2017-06-06.
@@ -206,7 +209,10 @@ class SettingsActivity : KPrefActivity() {
override fun onBackPressed() {
if (!super.backPress()) {
setResult(resultFlag)
- finishSlideOut()
+ launch(NonCancellable) {
+ loadAssets()
+ finishSlideOut()
+ }
}
}
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 de19f99c..77cb4de1 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssAssets.kt
@@ -16,6 +16,7 @@
*/
package com.pitchedapps.frost.injectors
+import android.content.Context
import android.graphics.Color
import android.webkit.WebView
import ca.allanwang.kau.kotlin.lazyContext
@@ -27,6 +28,8 @@ import ca.allanwang.kau.utils.use
import ca.allanwang.kau.utils.withAlpha
import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.utils.Prefs
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.FileNotFoundException
import java.util.Locale
@@ -36,12 +39,16 @@ import java.util.Locale
* Mapping of the available assets
* The enum name must match the css file name
*/
-enum class CssAssets(val folder: String = "themes") : InjectorContract {
+enum class CssAssets(val folder: String = THEME_FOLDER) : InjectorContract {
MATERIAL_LIGHT, MATERIAL_DARK, MATERIAL_AMOLED, MATERIAL_GLASS, CUSTOM, ROUND_ICONS("components")
;
- var file = "${name.toLowerCase(Locale.CANADA)}.css"
- var injector = lazyContext {
+ private val file = "${name.toLowerCase(Locale.CANADA)}.css"
+
+ /**
+ * Note that while this can be loaded from any thread, it is typically done through [load]
+ */
+ private val injector = lazyContext {
try {
var content = it.assets.open("css/$folder/$file").bufferedReader().use(BufferedReader::readText)
if (this == CUSTOM) {
@@ -72,11 +79,25 @@ enum class CssAssets(val folder: String = "themes") : InjectorContract {
}
}
- override fun inject(webView: WebView, callback: (() -> Unit)?) {
- injector(webView.context).inject(webView, callback)
- }
+ override fun inject(webView: WebView) =
+ injector(webView.context).inject(webView)
fun reset() {
injector.invalidate()
}
+
+ companion object {
+ // Ensures that all non themes and the selected theme are loaded
+ suspend fun load(context: Context) {
+ withContext(Dispatchers.IO) {
+ val currentTheme = Prefs.t.injector as? CssAssets
+ val (themes, others) = CssAssets.values().partition { it.folder == THEME_FOLDER }
+ themes.filter { it != currentTheme }.forEach { it.reset() }
+ currentTheme?.injector?.invoke(context)
+ others.forEach { it.injector.invoke(context) }
+ }
+ }
+ }
}
+
+private const val THEME_FOLDER = "themes"
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
index 7da6295f..4fd46ae4 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/CssHider.kt
@@ -45,7 +45,6 @@ enum class CssHider(vararg val items: String) : InjectorContract {
.single(name).build()
}
- override fun inject(webView: WebView, callback: (() -> Unit)?) {
- injector.inject(webView, callback)
- }
+ override fun inject(webView: WebView) =
+ injector.inject(webView)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
index e64d4faa..44fd01da 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsActions.kt
@@ -42,8 +42,8 @@ enum class JsActions(body: String) : InjectorContract {
val function = "(function(){$body})();"
- override fun inject(webView: WebView, callback: (() -> Unit)?) =
- JsInjector(function).inject(webView, callback)
+ override fun inject(webView: WebView) =
+ JsInjector(function).inject(webView)
}
@Suppress("NOTHING_TO_INLINE")
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
index 0dccc751..4b1bde43 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsAssets.kt
@@ -16,9 +16,12 @@
*/
package com.pitchedapps.frost.injectors
+import android.content.Context
import android.webkit.WebView
import ca.allanwang.kau.kotlin.lazyContext
import com.pitchedapps.frost.utils.L
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.FileNotFoundException
import java.util.Locale
@@ -33,8 +36,8 @@ enum class JsAssets : InjectorContract {
DOCUMENT_WATCHER
;
- var file = "${name.toLowerCase(Locale.CANADA)}.js"
- var injector = lazyContext {
+ private val file = "${name.toLowerCase(Locale.CANADA)}.js"
+ private val injector = lazyContext {
try {
val content = it.assets.open("js/$file").bufferedReader().use(BufferedReader::readText)
JsBuilder().js(content).single(name).build()
@@ -44,7 +47,15 @@ enum class JsAssets : InjectorContract {
}
}
- override fun inject(webView: WebView, callback: (() -> Unit)?) {
- injector(webView.context).inject(webView, callback)
+ override fun inject(webView: WebView) =
+ injector(webView.context).inject(webView)
+
+ companion object {
+ // Ensures that all non themes and the selected theme are loaded
+ suspend fun load(context: Context) {
+ withContext(Dispatchers.IO) {
+ JsAssets.values().forEach { it.injector.invoke(context) }
+ }
+ }
}
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
index 8ae3a2f4..00c7bcfc 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/injectors/JsInjector.kt
@@ -17,12 +17,7 @@
package com.pitchedapps.frost.injectors
import android.webkit.WebView
-import com.pitchedapps.frost.utils.L
import com.pitchedapps.frost.web.FrostWebViewClient
-import io.reactivex.Single
-import io.reactivex.android.schedulers.AndroidSchedulers
-import io.reactivex.disposables.Disposable
-import io.reactivex.subjects.SingleSubject
import org.apache.commons.text.StringEscapeUtils
import java.util.Locale
@@ -81,8 +76,7 @@ class JsBuilder {
* Contract for all injectors to allow it to interact properly with a webview
*/
interface InjectorContract {
- fun inject(webView: WebView) = inject(webView, null)
- fun inject(webView: WebView, callback: (() -> Unit)?)
+ fun inject(webView: WebView)
/**
* Toggle the injector (usually through Prefs
* If false, will fallback to an empty action
@@ -93,41 +87,18 @@ interface InjectorContract {
/**
* Helper method to inject multiple functions simultaneously with a single callback
*/
-fun WebView.jsInject(vararg injectors: InjectorContract, callback: ((Int) -> Unit)? = null): Disposable? {
- val validInjectors = injectors.filter { it != JsActions.EMPTY }
- if (validInjectors.isEmpty()) {
- callback?.invoke(0)
- return null
+fun WebView.jsInject(vararg injectors: InjectorContract) {
+ injectors.filter { it != JsActions.EMPTY }.forEach {
+ it.inject(this)
}
- L.d { "Injecting ${validInjectors.size} items" }
- if (callback == null) {
- validInjectors.forEach { it.inject(this) }
- return null
- }
- val observables = Array(validInjectors.size) { SingleSubject.create<Unit>() }
- val disposable = Single.zip<Unit, Int>(observables.asList()) { it.size }
- .observeOn(AndroidSchedulers.mainThread())
- .subscribe { res, _ ->
- callback(res)
- }
- (0 until validInjectors.size).forEach { i ->
- validInjectors[i].inject(this) {
- observables[i].onSuccess(Unit)
- }
- }
- return disposable
}
-fun FrostWebViewClient.jsInject(
- vararg injectors: InjectorContract,
- callback: ((Int) -> Unit)? = null
-) = web.jsInject(*injectors, callback = callback)
+fun FrostWebViewClient.jsInject(vararg injectors: InjectorContract) = web.jsInject(*injectors)
/**
* Wrapper class to convert a function into an injector
*/
class JsInjector(val function: String) : InjectorContract {
- override fun inject(webView: WebView, callback: (() -> Unit)?) {
- webView.evaluateJavascript(function) { callback?.invoke() }
- }
+ override fun inject(webView: WebView) =
+ webView.evaluateJavascript(function, null)
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
index 538e20f1..1b1ca796 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/settings/Appearance.kt
@@ -76,7 +76,7 @@ fun SettingsActivity.getAppearancePrefs(): KPrefAdapterBuilder.() -> Unit = {
}
fun invalidateCustomTheme() {
- CssAssets.CUSTOM.injector.invalidate()
+ CssAssets.CUSTOM.reset()
}
colorPicker(R.string.text_color, Prefs::customTextColor, {
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 303142af..add9c6cd 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Prefs.kt
@@ -68,7 +68,7 @@ object Prefs : KPref() {
private val loader = lazyResettable { Theme.values[Prefs.theme] }
- private val t: Theme by loader
+ val t: Theme by loader
val textColor: Int
get() = t.textColor
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 3f92c41d..4410b26e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Utils.kt
@@ -70,8 +70,11 @@ import com.pitchedapps.frost.facebook.FbItem
import com.pitchedapps.frost.facebook.FbUrlFormatter.Companion.VIDEO_REDIRECT
import com.pitchedapps.frost.facebook.USER_AGENT_BASIC
import com.pitchedapps.frost.facebook.formattedFbUrl
+import com.pitchedapps.frost.injectors.CssAssets
+import com.pitchedapps.frost.injectors.JsAssets
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.launch
import org.apache.commons.text.StringEscapeUtils
import org.jsoup.Jsoup
@@ -421,3 +424,8 @@ fun String.unescapeHtml(): String =
StringEscapeUtils.unescapeXml(this)
.replace("\\u003C", "<")
.replace("\\\"", "\"")
+
+suspend fun Context.loadAssets(): Unit = coroutineScope {
+ CssAssets.load(this@loadAssets)
+ JsAssets.load(this@loadAssets)
+}