aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/kotlin/com
diff options
context:
space:
mode:
authorAllan Wang <me@allanwang.ca>2017-06-01 17:45:42 -0700
committerAllan Wang <me@allanwang.ca>2017-06-01 17:45:42 -0700
commit266569a14f3b1dea9002de58cef40b4149384ef6 (patch)
tree2f5bd5d01396359d6b43fbc7e3b0ba446eb167fd /app/src/main/kotlin/com
parentd924fd96dd3dff3b13af3a1ea112e0e784ce65bb (diff)
downloadfrost-266569a14f3b1dea9002de58cef40b4149384ef6.tar.gz
frost-266569a14f3b1dea9002de58cef40b4149384ef6.tar.bz2
frost-266569a14f3b1dea9002de58cef40b4149384ef6.zip
add progressbar and remove tab indicator
Diffstat (limited to 'app/src/main/kotlin/com')
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt35
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt29
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt4
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt55
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/IIconUtils.kt12
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/utils/Interfaces.kt2
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt107
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt18
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt16
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebEnums.kt13
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt167
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt45
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt137
-rw-r--r--app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt30
14 files changed, 443 insertions, 227 deletions
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt
index 2cf8cd5b..c167dfdb 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/MainActivity.kt
@@ -11,6 +11,7 @@ import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import android.view.Menu
import android.view.MenuItem
+import android.view.ViewTreeObserver
import butterknife.ButterKnife
import com.mikepenz.materialdrawer.Drawer
import com.pitchedapps.frost.dbflow.loadFbTabs
@@ -18,9 +19,7 @@ import com.pitchedapps.frost.dbflow.saveAsync
import com.pitchedapps.frost.facebook.FbTab
import com.pitchedapps.frost.fragments.BaseFragment
import com.pitchedapps.frost.fragments.WebFragment
-import com.pitchedapps.frost.utils.Changelog
-import com.pitchedapps.frost.utils.bindView
-import com.pitchedapps.frost.utils.toDrawable
+import com.pitchedapps.frost.utils.*
class MainActivity : AppCompatActivity() {
@@ -33,6 +32,8 @@ class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+// SwipeBackHelper.onCreate(this)
+// SwipeBackHelper.getCurrentPage(this).setSwipeBackEnable(false)
setContentView(R.layout.activity_main)
ButterKnife.bind(this)
setSupportActionBar(toolbar)
@@ -40,6 +41,20 @@ class MainActivity : AppCompatActivity() {
adapter = SectionsPagerAdapter(supportFragmentManager, loadFbTabs())
viewPager.adapter = adapter
viewPager.offscreenPageLimit = 5
+ viewPager.addOnPageChangeListener(object : ViewPager.SimpleOnPageChangeListener() {
+ override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
+ super.onPageScrolled(position, positionOffset, positionOffsetPixels)
+ val delta: Float by lazy { positionOffset * (255 - 128).toFloat() }
+ (0 until tabs.tabCount).asSequence().forEach {
+ i ->
+ tabs.getTabAt(i)?.icon?.alpha = when (i) {
+ position -> (255.0 - delta).toInt()
+ position + 1 -> (128.0 + delta).toInt()
+ else -> 128
+ }
+ }
+ }
+ })
setupTabs()
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
@@ -47,6 +62,17 @@ class MainActivity : AppCompatActivity() {
}
}
+
+ override fun onPostCreate(savedInstanceState: Bundle?) {
+ super.onPostCreate(savedInstanceState)
+// SwipeBackHelper.onPostCreate(this)
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+// SwipeBackHelper.onDestroy(this)
+ }
+
fun setupTabs() {
viewPager.addOnPageChangeListener(TabLayout.TabLayoutOnPageChangeListener(tabs))
@@ -72,8 +98,7 @@ class MainActivity : AppCompatActivity() {
// finish()
}
R.id.action_changelog -> Changelog.show(this)
- R.id.action_call -> {
- }
+ R.id.action_call -> WebOverlayActivity.newInstance(this, "https://www.google.ca")
R.id.action_db -> adapter.pages.saveAsync(this)
R.id.action_restart -> {
finish();
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt
index 25c20594..fafcf7ae 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/WebOverlayActivity.kt
@@ -3,12 +3,17 @@ package com.pitchedapps.frost
import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.support.v4.app.ActivityOptionsCompat
+import android.support.v4.content.ContextCompat
import android.support.v4.widget.SwipeRefreshLayout
import android.support.v7.app.AppCompatActivity
import android.support.v7.widget.Toolbar
import butterknife.ButterKnife
+import com.jude.swipbackhelper.SwipeBackHelper
import com.pitchedapps.frost.utils.bindView
import com.pitchedapps.frost.web.FrostWebView
+import com.pitchedapps.frost.web.FrostWebViewCore
+
/**
* Created by Allan Wang on 2017-06-01.
@@ -16,15 +21,15 @@ import com.pitchedapps.frost.web.FrostWebView
class WebOverlayActivity : AppCompatActivity() {
val toolbar: Toolbar by bindView(R.id.toolbar)
- val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
- val web: FrostWebView by bindView(R.id.frost_webview)
+ val frostWeb:FrostWebView by bindView(R.id.frost_webview)
companion object {
private const val ARG_URL = "arg_url"
fun newInstance(context: Context, url: String) {
val intent = Intent(context, WebOverlayActivity::class.java)
intent.putExtra(ARG_URL, url)
- context.startActivity(intent)
+ val bundle = ActivityOptionsCompat.makeCustomAnimation(context, R.anim.slide_in_right, R.anim.slide_out_right).toBundle()
+ ContextCompat.startActivity(context, intent, bundle)
}
}
@@ -33,5 +38,23 @@ class WebOverlayActivity : AppCompatActivity() {
setContentView(R.layout.activity_web_overlay)
ButterKnife.bind(this)
setSupportActionBar(toolbar)
+ frostWeb.baseUrl = intent.extras.getString(ARG_URL)
+ SwipeBackHelper.onCreate(this)
+ SwipeBackHelper.getCurrentPage(this)
+ .setSwipeBackEnable(true)
+ .setSwipeSensitivity(0.5f)
+ .setSwipeRelateEnable(true)
+ .setSwipeRelateOffset(300)
+ }
+
+ override fun onPostCreate(savedInstanceState: Bundle?) {
+ super.onPostCreate(savedInstanceState)
+ SwipeBackHelper.onPostCreate(this)
}
+
+ override fun onDestroy() {
+ super.onDestroy()
+ SwipeBackHelper.onDestroy(this)
+ }
+
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt b/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt
index 64c91955..a2eb6907 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/events/WebEvent.kt
@@ -1,6 +1,6 @@
package com.pitchedapps.frost.events
-import com.pitchedapps.frost.web.FrostWebView
+import com.pitchedapps.frost.web.FrostWebViewCore
/**
* Created by Allan Wang on 2017-05-31.
@@ -12,7 +12,7 @@ class WebEvent(val key: Int, val urlMatch: String? = null) {
const val REFRESH_BASE = 1
}
- fun execute(webView: FrostWebView) {
+ fun execute(webView: FrostWebViewCore) {
if (urlMatch != null && !webView.url.contains(urlMatch)) return
when (key) {
REFRESH -> webView.reload()
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt
index f55579e0..21d019e7 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/fragments/WebFragment.kt
@@ -5,34 +5,26 @@ import android.support.v4.widget.SwipeRefreshLayout
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import butterknife.ButterKnife
-import butterknife.Unbinder
-import com.pitchedapps.frost.R
-import com.pitchedapps.frost.utils.bindView
import com.pitchedapps.frost.utils.putString
import com.pitchedapps.frost.web.FrostWebView
-import com.pitchedapps.frost.web.WebStatus
+import com.pitchedapps.frost.web.FrostWebViewCore
/**
* Created by Allan Wang on 2017-05-29.
*/
-class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
-
- override fun onRefresh() {
- web.reload()
- }
+class WebFragment : BaseFragment() {
companion object {
private const val ARG_URL = "arg_url"
fun newInstance(position: Int, url: String) = BaseFragment.newInstance(WebFragment(), position).putString(ARG_URL, url)
}
- val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
- val web: FrostWebView by bindView(R.id.frost_webview)
+ val refresh: SwipeRefreshLayout by lazy { frostWebView.refresh }
+ val web: FrostWebViewCore by lazy { frostWebView.web }
lateinit var url: String
- private lateinit var unbinder: Unbinder
+ lateinit private var frostWebView: FrostWebView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -41,39 +33,10 @@ class WebFragment : BaseFragment(), SwipeRefreshLayout.OnRefreshListener {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
super.onCreateView(inflater, container, savedInstanceState)
- val view = inflater.inflate(R.layout.swipe_webview, container, false)
- unbinder = ButterKnife.bind(this, view)
- return view
- }
-
- override fun onViewCreated(view: View?, savedInstanceState: Bundle?) {
- super.onViewCreated(view, savedInstanceState)
- web.baseUrl = url
- web.observable.subscribe {
- t: WebStatus ->
- when (t) {
- WebStatus.LOADED, WebStatus.ERROR -> refresh.isRefreshing = false
- WebStatus.LOADING -> refresh.isRefreshing = true
- }
- }
- refresh.setOnRefreshListener(this)
-// refresh.shouldSwipe = {
-// L.e("Y ${web.scrollY}")
-// SwipeRefreshBase.shouldScroll(web)
-// }
- web.loadUrl(url)
+ frostWebView = FrostWebView(context)
+ frostWebView.baseUrl = url
+ return frostWebView
}
- override fun onDestroyView() {
- super.onDestroyView()
- unbinder.unbind()
- }
-
- override fun onBackPressed(): Boolean {
- if (web.canGoBack()) {
- web.goBack()
- return true
- }
- return false
- }
+ override fun onBackPressed() = frostWebView.onBackPressed()
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/IIconUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/IIconUtils.kt
index cc645d93..2e0a44c1 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/IIconUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/IIconUtils.kt
@@ -1,13 +1,19 @@
package com.pitchedapps.frost.utils
import android.content.Context
+import android.content.res.ColorStateList
+import android.graphics.Color
import android.graphics.drawable.Drawable
-import android.support.annotation.ColorRes
+import android.support.annotation.ColorInt
import com.mikepenz.iconics.IconicsDrawable
import com.mikepenz.iconics.typeface.IIcon
/**
* Created by Allan Wang on 2017-05-29.
*/
-fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorRes color: Int = android.R.color.white): Drawable
- = IconicsDrawable(c).icon(this).colorRes(color).sizeDp(sizeDp) \ No newline at end of file
+fun IIcon.toDrawable(c: Context, sizeDp: Int = 24, @ColorInt color: Int = Color.WHITE): Drawable {
+ val state = ColorStateList.valueOf(color)
+ val icon = IconicsDrawable(c).icon(this).sizeDp(sizeDp)
+ icon.setTintList(state)
+ return icon
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Interfaces.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Interfaces.kt
index 79904c6e..1e42f59f 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Interfaces.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Interfaces.kt
@@ -6,7 +6,7 @@ import io.reactivex.subjects.Subject
* Created by Allan Wang on 2017-05-29.
*/
interface ObservableContainer<T> {
- val observable: Subject<T>
+ val progressObservable: Subject<T>
}
interface KeyPairObservable : ObservableContainer<Pair<Int, Int>> \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt
new file mode 100644
index 00000000..a2a0dcff
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/AnimUtils.kt
@@ -0,0 +1,107 @@
+package com.pitchedapps.frost.views
+
+import android.animation.Animator
+import android.animation.AnimatorListenerAdapter
+import android.view.View
+import android.view.ViewAnimationUtils
+import android.view.animation.Animation
+import android.view.animation.AnimationUtils
+import android.view.animation.DecelerateInterpolator
+
+
+/**
+ * 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)
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt
index 513287ef..01a49f7e 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/views/ViewUtils.kt
@@ -1,14 +1,30 @@
package com.pitchedapps.frost.views
+import android.content.res.ColorStateList
+import android.graphics.PorterDuff
+import android.support.annotation.ColorInt
+import android.support.annotation.ColorRes
+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) {
+ 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
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt
index 8367255a..4cd90d7b 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostChromeClient.kt
@@ -2,14 +2,28 @@ package com.pitchedapps.frost.web
import android.webkit.ConsoleMessage
import android.webkit.WebChromeClient
+import android.webkit.WebView
import com.pitchedapps.frost.utils.L
+import io.reactivex.subjects.Subject
/**
* Created by Allan Wang on 2017-05-31.
*/
-class FrostChromeClient:WebChromeClient() {
+class FrostChromeClient(val progressObservable: Subject<Int>) : WebChromeClient() {
override fun onConsoleMessage(consoleMessage: ConsoleMessage): Boolean {
L.d("Console ${consoleMessage.lineNumber()}: ${consoleMessage.message()}")
return super.onConsoleMessage(consoleMessage)
}
+
+ override fun onReceivedTitle(view: WebView?, title: String?) {
+ super.onReceivedTitle(view, title)
+ L.d("Title $title")
+ }
+
+ override fun onProgressChanged(view: WebView, newProgress: Int) {
+ super.onProgressChanged(view, newProgress)
+ progressObservable.onNext(newProgress)
+ }
+
+
} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebEnums.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebEnums.kt
new file mode 100644
index 00000000..17e44785
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebEnums.kt
@@ -0,0 +1,13 @@
+package com.pitchedapps.frost.web
+
+enum class FrostWebEnums {
+ LOADING, LOADED, ERROR
+}
+
+enum class FrostWebOverlay(val match: String) {
+ STORY("story.php?story_fbid");
+
+ companion object {
+ val values = values()
+ }
+} \ No newline at end of file
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 de7860da..a9cf0559 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebView.kt
@@ -1,141 +1,62 @@
package com.pitchedapps.frost.web
-import android.annotation.SuppressLint
import android.content.Context
-import android.support.v4.view.MotionEventCompat
-import android.support.v4.view.NestedScrollingChild
-import android.support.v4.view.NestedScrollingChildHelper
-import android.support.v4.view.ViewCompat
+import android.os.Build
+import android.support.v4.widget.SwipeRefreshLayout
import android.util.AttributeSet
-import android.view.MotionEvent
import android.view.View
-import android.webkit.WebView
-import com.pitchedapps.frost.events.WebEvent
-import com.pitchedapps.frost.utils.ObservableContainer
-import io.reactivex.subjects.BehaviorSubject
-import io.reactivex.subjects.Subject
-import org.greenrobot.eventbus.EventBus
-import org.greenrobot.eventbus.Subscribe
-
-enum class WebStatus {
- LOADING, LOADED, ERROR
-}
+import android.widget.FrameLayout
+import android.widget.ProgressBar
+import butterknife.ButterKnife
+import com.pitchedapps.frost.R
+import com.pitchedapps.frost.utils.L
+import com.pitchedapps.frost.utils.bindView
+import io.reactivex.android.schedulers.AndroidSchedulers
/**
- * Created by Allan Wang on 2017-05-29.
- *
- * Courtesy of takahirom
- *
- * https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
+ * Created by Allan Wang on 2017-06-01.
*/
-class FrostWebView @JvmOverloads constructor(
- context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
-) : WebView(context, attrs, defStyleAttr), NestedScrollingChild, ObservableContainer<WebStatus> {
-
- private val childHelper = NestedScrollingChildHelper(this)
- private var lastY: Int = 0
- private val scrollOffset = IntArray(2)
- private val scrollConsumed = IntArray(2)
- private var nestedOffsetY: Int = 0
- override val observable: Subject<WebStatus> //TODO see if we need this
- var baseUrl: String? = null
+class FrostWebView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, defStyleRes: Int = 0)
+ : FrameLayout(context, attrs, defStyleAttr, defStyleRes), SwipeRefreshLayout.OnRefreshListener {
+ var baseUrl: String?
+ get() = web.baseUrl
+ set(value) {
+ web.baseUrl = value
+ if (value != null) web.loadUrl(value)
+ }
+ val refresh: SwipeRefreshLayout by bindView(R.id.swipe_refresh)
+ val web: FrostWebViewCore by bindView(R.id.frost_webview_core)
+ val progress: ProgressBar by bindView(R.id.progressBar)
init {
- isNestedScrollingEnabled = true
- observable = BehaviorSubject.create<WebStatus>()
- setupWebview()
- }
-
- @SuppressLint("SetJavaScriptEnabled")
- fun setupWebview() {
- settings.javaScriptEnabled = true
- settings.domStorageEnabled = true
- setLayerType(View.LAYER_TYPE_HARDWARE, null)
- setWebViewClient(FrostWebViewClient(observable))
- setWebChromeClient(FrostChromeClient())
- }
-
- override fun loadUrl(url: String?) {
- if (url != null)
- super.loadUrl(url)
- }
-
- override fun onTouchEvent(ev: MotionEvent): Boolean {
- val event = MotionEvent.obtain(ev)
- val action = MotionEventCompat.getActionMasked(event)
- if (action == MotionEvent.ACTION_DOWN)
- nestedOffsetY = 0
- val eventY = event.y.toInt()
- event.offsetLocation(0f, nestedOffsetY.toFloat())
- val returnValue: Boolean
- when (action) {
- MotionEvent.ACTION_MOVE -> {
- var deltaY = lastY - eventY
- // NestedPreScroll
- if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
- deltaY -= scrollConsumed[1]
- event.offsetLocation(0f, -scrollOffset[1].toFloat())
- nestedOffsetY += scrollOffset[1]
- }
- lastY = eventY - scrollOffset[1]
- returnValue = super.onTouchEvent(event)
- // NestedScroll
- if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) {
- event.offsetLocation(0f, scrollOffset[1].toFloat())
- nestedOffsetY += scrollOffset[1]
- lastY -= scrollOffset[1]
- }
- }
- MotionEvent.ACTION_DOWN -> {
- returnValue = super.onTouchEvent(event)
- lastY = eventY
- startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
- }
- MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
- returnValue = super.onTouchEvent(event)
- stopNestedScroll()
- }
- else -> return false
+ inflate(getContext(), R.layout.swipe_webview, this)
+ ButterKnife.bind(this)
+ web.progressObservable.observeOn(AndroidSchedulers.mainThread()).subscribe {
+ val loaded = it == 100
+ refresh.isRefreshing = !loaded
+ progress.visibility = if (loaded) View.INVISIBLE else View.VISIBLE
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) progress.setProgress(it, true)
+ else progress.progress = it
}
- return returnValue
- }
+ refresh.setOnRefreshListener(this)
+ addOnAttachStateChangeListener(object : OnAttachStateChangeListener {
+ override fun onViewDetachedFromWindow(v: View) {
+ web.visibility = View.VISIBLE
+ }
- override fun onAttachedToWindow() {
- super.onAttachedToWindow()
- EventBus.getDefault().register(this);
+ override fun onViewAttachedToWindow(v: View) {}
+ })
}
- override fun onDetachedFromWindow() {
- EventBus.getDefault().unregister(this)
- super.onDetachedFromWindow()
+ override fun onRefresh() {
+ web.reload()
}
- @Subscribe
- fun webEvent(event: WebEvent) = event.execute(this)
-
- // Nested Scroll implements
- override fun setNestedScrollingEnabled(enabled: Boolean) {
- childHelper.isNestedScrollingEnabled = enabled
+ fun onBackPressed(): Boolean {
+ if (web.canGoBack()) {
+ web.goBack()
+ return true
+ }
+ return false
}
-
- override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
-
- override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
-
- override fun stopNestedScroll() = childHelper.stopNestedScroll()
-
- override fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
-
- override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
- = childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
-
- override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
- = childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
-
- override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
- = childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
-
- override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
- = childHelper.dispatchNestedPreFling(velocityX, velocityY)
-
} \ No newline at end of file
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 379bb22d..143c9f5a 100644
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewClient.kt
@@ -1,18 +1,20 @@
package com.pitchedapps.frost.web
import android.graphics.Bitmap
-import android.view.View
+import android.view.KeyEvent
import android.webkit.*
import com.pitchedapps.frost.facebook.FACEBOOK_COM
import com.pitchedapps.frost.facebook.FbCookie
import com.pitchedapps.frost.injectors.CssAssets
import com.pitchedapps.frost.utils.L
+import com.pitchedapps.frost.views.circularReveal
+import com.pitchedapps.frost.views.fadeOut
import io.reactivex.subjects.Subject
/**
* Created by Allan Wang on 2017-05-31.
*/
-class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() {
+class FrostWebViewClient : WebViewClient() {
companion object {
//Collections of jewels mapped with url match -> id
@@ -23,31 +25,50 @@ class FrostWebViewClient(val observable: Subject<WebStatus>) : WebViewClient() {
}
}
- override fun onReceivedError(view: WebView?, request: WebResourceRequest?, error: WebResourceError?) {
- super.onReceivedError(view, request, error)
- observable.onNext(WebStatus.ERROR)
- L.e("FWV Error ${request}")
- }
-
override fun onPageStarted(view: WebView, url: String, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
- observable.onNext(WebStatus.LOADING)
L.d("FWV Loading $url")
if (!url.contains(FACEBOOK_COM)) return
if (url.contains("logout.php")) FbCookie.logout()
- view.visibility = View.INVISIBLE
+ view.fadeOut(duration = 200L)
}
override fun onPageFinished(view: WebView, url: String) {
super.onPageFinished(view, url)
if (!url.contains(FACEBOOK_COM)) return
- observable.onNext(WebStatus.LOADED)
FbCookie.checkUserId(url, CookieManager.getInstance().getCookie(url))
CssAssets.BASE.inject(view, {
- view.visibility = View.VISIBLE
+ view.circularReveal(offset = 150L)
})
}
+ override fun shouldOverrideKeyEvent(view: WebView, event: KeyEvent): Boolean {
+ L.d("Key event ${event.keyCode}")
+ return super.shouldOverrideKeyEvent(view, event)
+ }
+
+ override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
+ L.d("Hi")
+ L.d("Url Loading ${request.url?.path}")
+ return super.shouldOverrideUrlLoading(view, request)
+ }
+
+ override fun shouldInterceptRequest(view: WebView, request: WebResourceRequest): WebResourceResponse? {
+ if (!request.url.host.contains(FACEBOOK_COM)) return super.shouldInterceptRequest(view, request)
+ L.d("Url intercept ${request.url.path}")
+ return super.shouldInterceptRequest(view, request)
+ }
+
+ override fun onLoadResource(view: WebView, url: String) {
+ if (!url.contains(FACEBOOK_COM)) return super.onLoadResource(view, url)
+ L.d("Resource $url")
+ FrostWebOverlay.values.forEach {
+ if (url.contains(it.match))
+ L.d("Loaded $it")
+ }
+ super.onLoadResource(view, url)
+ }
+
fun logout() {
}
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt
new file mode 100644
index 00000000..03659908
--- /dev/null
+++ b/app/src/main/kotlin/com/pitchedapps/frost/web/FrostWebViewCore.kt
@@ -0,0 +1,137 @@
+package com.pitchedapps.frost.web
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.support.v4.view.MotionEventCompat
+import android.support.v4.view.NestedScrollingChild
+import android.support.v4.view.NestedScrollingChildHelper
+import android.support.v4.view.ViewCompat
+import android.util.AttributeSet
+import android.view.MotionEvent
+import android.view.View
+import android.webkit.WebView
+import com.pitchedapps.frost.events.WebEvent
+import com.pitchedapps.frost.utils.ObservableContainer
+import io.reactivex.subjects.BehaviorSubject
+import io.reactivex.subjects.Subject
+import org.greenrobot.eventbus.EventBus
+import org.greenrobot.eventbus.Subscribe
+
+/**
+ * Created by Allan Wang on 2017-05-29.
+ *
+ * Courtesy of takahirom
+ *
+ * https://github.com/takahirom/webview-in-coordinatorlayout/blob/master/app/src/main/java/com/github/takahirom/webview_in_coodinator_layout/NestedWebView.java
+ */
+class FrostWebViewCore @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
+) : WebView(context, attrs, defStyleAttr), NestedScrollingChild, ObservableContainer<Int> {
+
+ private val childHelper = NestedScrollingChildHelper(this)
+ private var lastY: Int = 0
+ private val scrollOffset = IntArray(2)
+ private val scrollConsumed = IntArray(2)
+ private var nestedOffsetY: Int = 0
+ override val progressObservable: Subject<Int> //TODO see if we need this
+ var baseUrl: String? = null
+
+ init {
+ isNestedScrollingEnabled = true
+ progressObservable = BehaviorSubject.create<Int>()
+ setupWebview()
+ }
+
+ @SuppressLint("SetJavaScriptEnabled")
+ fun setupWebview() {
+ settings.javaScriptEnabled = true
+ settings.domStorageEnabled = true
+ setLayerType(View.LAYER_TYPE_HARDWARE, null)
+ setWebViewClient(FrostWebViewClient())
+ setWebChromeClient(FrostChromeClient(progressObservable))
+ }
+
+ override fun loadUrl(url: String?) {
+ if (url != null)
+ super.loadUrl(url)
+ }
+
+ override fun onTouchEvent(ev: MotionEvent): Boolean {
+ val event = MotionEvent.obtain(ev)
+ val action = MotionEventCompat.getActionMasked(event)
+ if (action == MotionEvent.ACTION_DOWN)
+ nestedOffsetY = 0
+ val eventY = event.y.toInt()
+ event.offsetLocation(0f, nestedOffsetY.toFloat())
+ val returnValue: Boolean
+ when (action) {
+ MotionEvent.ACTION_MOVE -> {
+ var deltaY = lastY - eventY
+ // NestedPreScroll
+ if (dispatchNestedPreScroll(0, deltaY, scrollConsumed, scrollOffset)) {
+ deltaY -= scrollConsumed[1]
+ event.offsetLocation(0f, -scrollOffset[1].toFloat())
+ nestedOffsetY += scrollOffset[1]
+ }
+ lastY = eventY - scrollOffset[1]
+ returnValue = super.onTouchEvent(event)
+ // NestedScroll
+ if (dispatchNestedScroll(0, scrollOffset[1], 0, deltaY, scrollOffset)) {
+ event.offsetLocation(0f, scrollOffset[1].toFloat())
+ nestedOffsetY += scrollOffset[1]
+ lastY -= scrollOffset[1]
+ }
+ }
+ MotionEvent.ACTION_DOWN -> {
+ returnValue = super.onTouchEvent(event)
+ lastY = eventY
+ startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL)
+ }
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+ returnValue = super.onTouchEvent(event)
+ stopNestedScroll()
+ }
+ else -> return false
+ }
+ return returnValue
+ }
+
+ override fun onAttachedToWindow() {
+ super.onAttachedToWindow()
+ EventBus.getDefault().register(this);
+ }
+
+ override fun onDetachedFromWindow() {
+ EventBus.getDefault().unregister(this)
+ super.onDetachedFromWindow()
+ }
+
+ @Subscribe
+ fun webEvent(event: WebEvent) = event.execute(this)
+
+ // Nested Scroll implements
+ override fun setNestedScrollingEnabled(enabled: Boolean) {
+ childHelper.isNestedScrollingEnabled = enabled
+ }
+
+ override fun isNestedScrollingEnabled() = childHelper.isNestedScrollingEnabled
+
+ override fun startNestedScroll(axes: Int) = childHelper.startNestedScroll(axes)
+
+ override fun stopNestedScroll() = childHelper.stopNestedScroll()
+
+ override fun hasNestedScrollingParent() = childHelper.hasNestedScrollingParent()
+
+ override fun dispatchNestedScroll(dxConsumed: Int, dyConsumed: Int, dxUnconsumed: Int, dyUnconsumed: Int, offsetInWindow: IntArray?)
+ = childHelper.dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, offsetInWindow)
+
+ override fun dispatchNestedPreScroll(dx: Int, dy: Int, consumed: IntArray?, offsetInWindow: IntArray?)
+ = childHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow)
+
+ override fun dispatchNestedFling(velocityX: Float, velocityY: Float, consumed: Boolean)
+ = childHelper.dispatchNestedFling(velocityX, velocityY, consumed)
+
+ override fun dispatchNestedPreFling(velocityX: Float, velocityY: Float)
+ = childHelper.dispatchNestedPreFling(velocityX, velocityY)
+
+} \ No newline at end of file
diff --git a/app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt b/app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt
deleted file mode 100644
index 0e303e49..00000000
--- a/app/src/main/kotlin/com/pitchedapps/frost/web/SwipeRefreshBase.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package com.pitchedapps.frost.web
-
-import android.content.Context
-import android.support.v4.widget.SwipeRefreshLayout
-import android.util.AttributeSet
-import android.view.MotionEvent
-import android.webkit.WebView
-import com.pitchedapps.frost.utils.Utils
-
-
-/**
- * Created by Allan Wang on 2017-05-28.
- */
-class SwipeRefreshBase @JvmOverloads constructor(
- context: Context?, attrs: AttributeSet? = null
-) : SwipeRefreshLayout(context, attrs) {
-
- lateinit var shouldSwipe: (ev: MotionEvent) -> Boolean
-
- companion object {
- private val SCROLL_BUFFER by lazy { Utils.dpToPx(5) }
- fun shouldScroll(webview: WebView) = webview.scrollY <= SCROLL_BUFFER
- }
-
-// override fun onInterceptTouchEvent(ev: MotionEvent):Boolean {
-// val b = shouldSwipe.invoke(ev) && super.onInterceptTouchEvent(ev)
-// L.e("Should swipe $b")
-// return b
-// }
-} \ No newline at end of file