From c8f76b5aa406f84f49789a50871c68a1a95a232d Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Thu, 15 Jun 2017 19:25:17 -0700 Subject: Only animate webview when explicitly asked --- app/src/main/assets/js/menu_click.js | 2 +- app/src/main/assets/js/menu_click.min.js | 2 +- .../main/kotlin/com/pitchedapps/frost/FrostApp.kt | 1 - .../kotlin/com/pitchedapps/frost/LoginActivity.kt | 3 - .../kotlin/com/pitchedapps/frost/StartActivity.kt | 3 + .../com/pitchedapps/frost/views/AccountItem.kt | 1 + .../com/pitchedapps/frost/views/AnimUtils.kt | 119 --------------------- .../com/pitchedapps/frost/views/ViewUtils.kt | 39 ------- .../kotlin/com/pitchedapps/frost/web/FrostJSI.kt | 4 +- .../com/pitchedapps/frost/web/FrostWebView.kt | 4 +- .../pitchedapps/frost/web/FrostWebViewClient.kt | 16 +-- .../frost/web/FrostWebViewClientMenu.kt | 6 +- .../com/pitchedapps/frost/web/FrostWebViewCore.kt | 40 ++++++- .../com/pitchedapps/frost/web/LoginWebView.kt | 4 +- 14 files changed, 54 insertions(+), 190 deletions(-) delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt delete mode 100644 app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt diff --git a/app/src/main/assets/js/menu_click.js b/app/src/main/assets/js/menu_click.js index 65c1c401..3e23617a 100644 --- a/app/src/main/assets/js/menu_click.js +++ b/app/src/main/assets/js/menu_click.js @@ -10,7 +10,7 @@ document.onclick = function(e) { console.log(url); if (url !== "https://m.facebook.com/settings" && url !== "https://m.facebook.com/settings#" && url !== "https://m.facebook.com/settings#!/settings?soft=bookmarks") { Frost.loadUrl(url); - Frost.reloadBaseUrl(); //temporary workaround + Frost.reloadBaseUrl(false); //reinject base view } } }; diff --git a/app/src/main/assets/js/menu_click.min.js b/app/src/main/assets/js/menu_click.min.js index 14ac7e76..580f0467 100644 --- a/app/src/main/assets/js/menu_click.min.js +++ b/app/src/main/assets/js/menu_click.min.js @@ -1 +1 @@ -document.onclick=function(c){c=c||window.event;var b=c.target||c.srcElement;if(b.tagName!=="A"){b=b.parentNode}if(b.tagName==="A"){var a=b.href;console.log("Click Intercept");console.log(a);if(a!=="https://m.facebook.com/settings"&&a!=="https://m.facebook.com/settings#"&&a!=="https://m.facebook.com/settings#!/settings?soft=bookmarks"){Frost.loadUrl(a);Frost.reloadBaseUrl()}}}; \ No newline at end of file +document.onclick=function(c){c=c||window.event;var b=c.target||c.srcElement;if(b.tagName!=="A"){b=b.parentNode}if(b.tagName==="A"){var a=b.href;console.log("Click Intercept");console.log(a);if(a!=="https://m.facebook.com/settings"&&a!=="https://m.facebook.com/settings#"&&a!=="https://m.facebook.com/settings#!/settings?soft=bookmarks"){Frost.loadUrl(a);Frost.reloadBaseUrl(false)}}}; \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt index 09a54444..c18c007a 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/FrostApp.kt @@ -48,7 +48,6 @@ class FrostApp : Application() { Prefs.initialize(this, "${com.pitchedapps.frost.BuildConfig.APPLICATION_ID}.prefs") FbCookie() super.onCreate() - requestNotifications(Prefs.userId) //Drawer profile loading logic DrawerImageLoader.init(object : AbstractDrawerImageLoader() { override fun set(imageView: ImageView, uri: Uri, placeholder: Drawable, tag: String) { diff --git a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt index c4cf7a97..c3dad579 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/LoginActivity.kt @@ -23,9 +23,6 @@ import com.pitchedapps.frost.facebook.PROFILE_PICTURE_URL import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.launchNewTask -import com.pitchedapps.frost.views.fadeIn -import com.pitchedapps.frost.views.fadeOut -import com.pitchedapps.frost.views.setTextWithFade import com.pitchedapps.frost.web.LoginWebView import io.reactivex.Observable import io.reactivex.android.schedulers.AndroidSchedulers diff --git a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt index 751658e9..bdac366e 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/StartActivity.kt @@ -3,6 +3,7 @@ package com.pitchedapps.frost import android.os.Bundle import android.support.v7.app.AppCompatActivity import com.pitchedapps.frost.dbflow.loadFbCookiesAsync +import com.pitchedapps.frost.services.requestNotifications import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.launchNewTask @@ -17,6 +18,8 @@ class StartActivity : AppCompatActivity() { L.d("Load cookies ${System.currentTimeMillis()}") loadFbCookiesAsync { cookies -> + cookies.forEach { requestNotifications(it.id) } + L.d("Cookies loaded ${System.currentTimeMillis()} $cookies") if (cookies.isNotEmpty()) launchNewTask(if (Prefs.userId != -1L) MainActivity::class.java else SelectorActivity::class.java, ArrayList(cookies)) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt index 8cb189e7..244c1388 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AccountItem.kt @@ -6,6 +6,7 @@ import android.support.v7.widget.RecyclerView import android.view.View import android.widget.ImageView import ca.allanwang.kau.utils.bindView +import ca.allanwang.kau.utils.fadeIn import ca.allanwang.kau.utils.toDrawable import com.bumptech.glide.Glide import com.bumptech.glide.load.DataSource diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt deleted file mode 100644 index 3d212cc0..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt +++ /dev/null @@ -1,119 +0,0 @@ -package com.pitchedapps.frost.views - -import android.animation.Animator -import android.animation.AnimatorListenerAdapter -import android.support.annotation.StringRes -import android.view.View -import android.view.ViewAnimationUtils -import android.view.animation.Animation -import android.view.animation.AnimationUtils -import android.view.animation.DecelerateInterpolator -import android.widget.TextView - - -/** - * Created by Allan Wang on 2017-06-01. - */ - -fun View.rootCircularReveal(x: Int = 0, y: Int = 0, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { - this.addOnLayoutChangeListener(object : View.OnLayoutChangeListener { - override fun onLayoutChange(v: View, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, - oldRight: Int, oldBottom: Int) { - v.removeOnLayoutChangeListener(this) - var x2 = x - var y2 = y - if (x2 > right) x2 = 0 - if (y2 > bottom) y2 = 0 - val radius = Math.hypot(Math.max(x2, right - x2).toDouble(), Math.max(y2, bottom - y2).toDouble()).toInt() - val reveal = ViewAnimationUtils.createCircularReveal(v, x2, y2, 0f, radius.toFloat()) - reveal.interpolator = DecelerateInterpolator(1f) - reveal.duration = duration - reveal.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { - visibility = View.VISIBLE - onStart?.invoke() - } - - override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit - override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit - }) - reveal.start() - } - }) -} - -fun View.circularReveal(x: Int = 0, y: Int = 0, offset: Long = 0L, radius: Float = -1.0f, duration: Long = 500L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { - if (!isAttachedToWindow) { - visibility = View.VISIBLE - return - } - var r = radius - if (r < 0.0f) { - r = Math.max(Math.hypot(x.toDouble(), y.toDouble()), Math.hypot((width - x.toDouble()), (height - y.toDouble()))).toFloat() - } - val anim = ViewAnimationUtils.createCircularReveal(this, x, y, 0f, r).setDuration(duration) - anim.startDelay = offset - anim.addListener(object : AnimatorListenerAdapter() { - override fun onAnimationStart(animation: Animator?) { - visibility = View.VISIBLE - onStart?.invoke() - } - - override fun onAnimationEnd(animation: Animator?) = onFinish?.invoke() ?: Unit - override fun onAnimationCancel(animation: Animator?) = onFinish?.invoke() ?: Unit - }) - anim.start() -} - -fun View.fadeIn(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { - if (!isAttachedToWindow) { - visibility = View.VISIBLE - return - } - if (isAttachedToWindow) { - val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_in) - anim.startOffset = offset - anim.duration = duration - anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) {} - override fun onAnimationEnd(animation: Animation?) = onFinish?.invoke() ?: Unit - override fun onAnimationStart(animation: Animation?) { - visibility = View.VISIBLE - onStart?.invoke() - } - }) - startAnimation(anim) - } -} - -fun View.fadeOut(offset: Long = 0L, duration: Long = 200L, onStart: (() -> Unit)? = null, onFinish: (() -> Unit)? = null) { - if (!isAttachedToWindow) { - visibility = View.INVISIBLE - return - } - val anim = AnimationUtils.loadAnimation(context, android.R.anim.fade_out) - anim.startOffset = offset - anim.duration = duration - anim.setAnimationListener(object : Animation.AnimationListener { - override fun onAnimationRepeat(animation: Animation?) {} - override fun onAnimationEnd(animation: Animation?) { - visibility = View.INVISIBLE - onFinish?.invoke() - } - - override fun onAnimationStart(animation: Animation?) { - onStart?.invoke() - } - }) - startAnimation(anim) -} - -fun TextView.setTextWithFade(text: String, duration: Long = 200, onFinish: (() -> Unit)? = null) { - fadeOut(duration = duration, onFinish = { - setText(text) - fadeIn(duration = duration, onFinish = onFinish) - }) -} - -fun TextView.setTextWithFade(@StringRes textId: Int, duration: Long = 200, onFinish: (() -> Unit)? = null) = setTextWithFade(context.getString(textId), duration, onFinish) - diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt deleted file mode 100644 index 8dc3f01f..00000000 --- a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt +++ /dev/null @@ -1,39 +0,0 @@ -package com.pitchedapps.frost.views - -import android.content.res.ColorStateList -import android.support.annotation.ColorInt -import android.support.annotation.ColorRes -import android.support.annotation.StringRes -import android.support.design.widget.Snackbar -import android.support.v4.content.ContextCompat -import android.view.View -import android.view.ViewGroup -import android.widget.ProgressBar - - -/** - * Created by Allan Wang on 2017-05-31. - */ -fun View.matchParent() { - with(layoutParams) { - height = ViewGroup.LayoutParams.MATCH_PARENT - width = ViewGroup.LayoutParams.MATCH_PARENT - } -} - -fun ProgressBar.tintRes(@ColorRes id: Int) = tint(ContextCompat.getColor(context, id)) - -fun ProgressBar.tint(@ColorInt color: Int) { - val sl = ColorStateList.valueOf(color) - progressTintList = sl - secondaryProgressTintList = sl - indeterminateTintList = sl -} - -fun View.snackbar(text: String, duration: Int = Snackbar.LENGTH_LONG) { - Snackbar.make(this, text, duration).show() -} - -fun View.snackbar(@StringRes textId: Int, duration: Int = Snackbar.LENGTH_LONG) { - Snackbar.make(this, textId, duration).show() -} \ No newline at end of file diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt index 14ea4df8..bb482c3c 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostJSI.kt @@ -23,11 +23,11 @@ class FrostJSI(val context: Context, val webView: FrostWebViewCore) { fun loadUrl(url: String) = context.launchWebOverlay(url) @JavascriptInterface - fun reloadBaseUrl() { + fun reloadBaseUrl(animate: Boolean) { L.d("FrostJSI reload") webView.post { webView.stopLoading() - webView.loadBaseUrl() + webView.loadBaseUrl(animate) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt index c99feaf5..a600489d 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt @@ -50,8 +50,8 @@ class FrostWebView @JvmOverloads constructor(context: Context, attrs: AttributeS //Some urls have postJavascript injections so make sure we load the base url override fun onRefresh() { when (web.baseUrl) { - FbTab.MENU.url -> web.loadBaseUrl() - else -> web.reload() + FbTab.MENU.url -> web.loadBaseUrl(true) + else -> web.reload(true) } } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt index c3eb0a1f..e4ff4e10 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt @@ -4,7 +4,6 @@ import android.content.Context import android.graphics.Bitmap import android.view.KeyEvent import android.webkit.* -import ca.allanwang.kau.utils.isVisible import com.pitchedapps.frost.LoginActivity import com.pitchedapps.frost.MainActivity import com.pitchedapps.frost.SelectorActivity @@ -18,9 +17,6 @@ import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs import com.pitchedapps.frost.utils.cookies import com.pitchedapps.frost.utils.launchNewTask -import com.pitchedapps.frost.views.circularReveal -import com.pitchedapps.frost.views.fadeIn -import com.pitchedapps.frost.views.fadeOut import io.reactivex.subjects.Subject /** @@ -36,7 +32,6 @@ open class FrostWebViewClient(val refreshObservable: Subject) : WebView 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) }) - view.fadeOut(duration = 200L) } fun launchLogin(c: Context) { @@ -50,19 +45,18 @@ open class FrostWebViewClient(val refreshObservable: Subject) : WebView super.onPageFinished(view, url) if (!url.contains(FACEBOOK_COM)) { refreshObservable.onNext(false) - if (!view.isVisible()) view.fadeIn(duration = 200L) return } L.i("Page finished $url") JsActions.LOGIN_CHECK.inject(view) - onPageFinishedReveal(view as FrostWebViewCore, url) + onPageFinishedActions(view as FrostWebViewCore, url) } - open internal fun onPageFinishedReveal(view: FrostWebViewCore, url: String?) { - onPageFinishedReveal(view, true) + open internal fun onPageFinishedActions(view: FrostWebViewCore, url: String?) { + onPageFinishedActions(view) } - internal fun onPageFinishedReveal(view: FrostWebViewCore, animate: Boolean) { + internal fun onPageFinishedActions(view: FrostWebViewCore) { L.d("Page finished reveal") view.jsInject(CssHider.HEADER, Prefs.themeInjector, @@ -70,8 +64,6 @@ open class FrostWebViewClient(val refreshObservable: Subject) : WebView callback = { L.d("Finished ${it.contentToString()}") refreshObservable.onNext(false) - if (animate) view.circularReveal(offset = 150L) - else view.fadeIn(duration = 100L) }) } diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClientMenu.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClientMenu.kt index 3b032f62..f299b840 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClientMenu.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClientMenu.kt @@ -45,18 +45,18 @@ class FrostWebViewClientMenu(refreshObservable: Subject) : FrostWebView override fun emit(flag: Int) { super.emit(flag) - if (view != null) super.onPageFinishedReveal(view!!, true) + if (view != null) super.onPageFinishedActions(view!!) view = null } - override fun onPageFinishedReveal(view: FrostWebViewCore, url: String?) { + override fun onPageFinishedActions(view: FrostWebViewCore, url: String?) { when (url) { "https://m.facebook.com/settings", "https://m.facebook.com/settings#", "https://m.facebook.com/settings#!/settings?soft=bookmarks" -> { //do nothing; we will further inject before revealing } - else -> super.onPageFinishedReveal(view, false) + else -> super.onPageFinishedActions(view) } } 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 db5f877d..86d88e47 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt @@ -12,8 +12,13 @@ import android.view.MotionEvent import android.view.View import android.view.animation.DecelerateInterpolator import android.webkit.WebView +import ca.allanwang.kau.utils.circularReveal +import ca.allanwang.kau.utils.fadeIn +import ca.allanwang.kau.utils.fadeOut +import ca.allanwang.kau.utils.isVisible import com.pitchedapps.frost.facebook.FbTab import com.pitchedapps.frost.facebook.USER_AGENT_BASIC +import com.pitchedapps.frost.utils.L import io.reactivex.Scheduler import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable @@ -65,13 +70,38 @@ class FrostWebViewCore @JvmOverloads constructor( setBackgroundColor(Color.TRANSPARENT) } - override fun loadUrl(url: String?) { - if (url != null) - super.loadUrl(url) + fun loadUrl(url: String?, animate: Boolean) { + if (url == null) return + registerTransition(animate) + super.loadUrl(url) } - fun loadBaseUrl() { - loadUrl(baseUrl) + fun reload(animate: Boolean) { + registerTransition(animate) + super.reload() + } + + /** + * Hook onto the refresh observable for one cycle + * Note that this is a behaviour subject so the first 'false' emission should be ignored + */ + fun registerTransition(animate: Boolean) { + var dispose: Disposable? = null + var loading = false + dispose = refreshObservable.subscribeOn(AndroidSchedulers.mainThread()).subscribe { + if (it) { + loading = true + if (isVisible()) fadeOut(duration = 200L) + } else if (loading) { + dispose?.dispose() + if (animate) circularReveal(offset = 150L) + else fadeIn(duration = 100L) + } + } + } + + fun loadBaseUrl(animate: Boolean = true) { + loadUrl(baseUrl, animate) } fun addTitleListener(subscriber: (title: String) -> Unit, scheduler: Scheduler = AndroidSchedulers.mainThread()): Disposable 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 aa10e602..8265f429 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/web/LoginWebView.kt @@ -5,6 +5,8 @@ import android.content.Context import android.util.AttributeSet import android.view.View import android.webkit.* +import ca.allanwang.kau.utils.fadeIn +import ca.allanwang.kau.utils.snackbar import com.pitchedapps.frost.dbflow.CookieModel import com.pitchedapps.frost.facebook.FACEBOOK_COM import com.pitchedapps.frost.facebook.FbCookie @@ -12,8 +14,6 @@ import com.pitchedapps.frost.injectors.CssHider import com.pitchedapps.frost.injectors.jsInject import com.pitchedapps.frost.utils.L import com.pitchedapps.frost.utils.Prefs -import com.pitchedapps.frost.views.fadeIn -import com.pitchedapps.frost.views.snackbar import io.reactivex.subjects.PublishSubject import io.reactivex.subjects.SingleSubject import io.reactivex.subjects.Subject -- cgit v1.2.3