Clean up ServiceButton related code
This commit is contained in:
@@ -31,14 +31,12 @@ import android.nfc.NfcAdapter
|
||||
import android.os.Bundle
|
||||
import android.os.SystemClock
|
||||
import android.support.customtabs.CustomTabsIntent
|
||||
import android.support.design.widget.FloatingActionButton
|
||||
import android.support.design.widget.Snackbar
|
||||
import android.support.v4.content.ContextCompat
|
||||
import android.support.v7.app.AlertDialog
|
||||
import android.support.v7.app.AppCompatActivity
|
||||
import android.support.v7.content.res.AppCompatResources
|
||||
import android.support.v7.preference.PreferenceDataStore
|
||||
import android.support.v7.widget.TooltipCompat
|
||||
import android.util.Log
|
||||
import android.view.View
|
||||
import android.widget.TextView
|
||||
@@ -87,8 +85,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
|
||||
}
|
||||
|
||||
// UI
|
||||
private lateinit var fab: FloatingActionButton
|
||||
private val fabHelper by lazy { ServiceButton(fab) }
|
||||
private lateinit var fab: ServiceButton
|
||||
internal var crossfader: Crossfader<CrossFadeSlidingPaneLayout>? = null
|
||||
internal lateinit var drawer: Drawer
|
||||
private var previousSelectedDrawer: Long = 0 // it's actually lateinit
|
||||
@@ -110,9 +107,6 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
|
||||
} catch (_: ActivityNotFoundException) { } // ignore
|
||||
fun launchUrl(uri: String) = launchUrl(Uri.parse(uri))
|
||||
|
||||
private val greyTint by lazy { ContextCompat.getColorStateList(this, R.color.material_primary_500) }
|
||||
private val greenTint by lazy { ContextCompat.getColorStateList(this, R.color.material_green_700) }
|
||||
|
||||
// service
|
||||
var state = BaseService.IDLE
|
||||
override val serviceCallback: IShadowsocksServiceCallback.Stub by lazy {
|
||||
@@ -130,7 +124,7 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
|
||||
}
|
||||
|
||||
fun changeState(state: Int, msg: String? = null, animate: Boolean = false) {
|
||||
fabHelper.changeState(state, animate)
|
||||
fab.changeState(state, animate)
|
||||
when (state) {
|
||||
BaseService.CONNECTING -> statusText.setText(R.string.connecting)
|
||||
BaseService.CONNECTED -> statusText.setText(R.string.vpn_connected)
|
||||
@@ -145,20 +139,12 @@ class MainActivity : AppCompatActivity(), ShadowsocksConnection.Interface, Drawe
|
||||
}
|
||||
}
|
||||
this.state = state
|
||||
if (state == BaseService.CONNECTED) {
|
||||
fab.backgroundTintList = greenTint
|
||||
TooltipCompat.setTooltipText(fab, getString(R.string.stop))
|
||||
} else {
|
||||
fab.backgroundTintList = greyTint
|
||||
TooltipCompat.setTooltipText(fab, getString(R.string.connect))
|
||||
if (state != BaseService.CONNECTED) {
|
||||
updateTraffic(-1, 0, 0, 0, 0)
|
||||
testCount += 1 // suppress previous test messages
|
||||
}
|
||||
ProfilesFragment.instance?.profilesAdapter?.notifyDataSetChanged() // refresh button enabled state
|
||||
stateListener?.invoke(state)
|
||||
fab.isEnabled = false
|
||||
if (state == BaseService.CONNECTED || state == BaseService.STOPPED) app.handler.postDelayed(
|
||||
{ fab.isEnabled = state == BaseService.CONNECTED || state == BaseService.STOPPED }, 1000)
|
||||
}
|
||||
fun updateTraffic(profileId: Int, txRate: Long, rxRate: Long, txTotal: Long, rxTotal: Long) {
|
||||
txText.text = TrafficMonitor.formatTraffic(txTotal)
|
||||
|
||||
@@ -20,19 +20,38 @@
|
||||
|
||||
package com.github.shadowsocks.widget
|
||||
|
||||
import android.content.Context
|
||||
import android.graphics.drawable.Drawable
|
||||
import android.support.annotation.DrawableRes
|
||||
import android.support.design.widget.FloatingActionButton
|
||||
import android.support.graphics.drawable.Animatable2Compat
|
||||
import android.support.graphics.drawable.AnimatedVectorDrawableCompat
|
||||
import android.support.v7.widget.TooltipCompat
|
||||
import android.util.AttributeSet
|
||||
import android.view.View
|
||||
import com.github.shadowsocks.App
|
||||
import com.github.shadowsocks.R
|
||||
import com.github.shadowsocks.bg.BaseService
|
||||
import java.util.*
|
||||
|
||||
class ServiceButton(private val fab: FloatingActionButton) : Animatable2Compat.AnimationCallback() {
|
||||
class ServiceButton @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
|
||||
FloatingActionButton(context, attrs, defStyleAttr) {
|
||||
private val callback = object : Animatable2Compat.AnimationCallback() {
|
||||
override fun onAnimationEnd(drawable: Drawable) {
|
||||
super.onAnimationEnd(drawable)
|
||||
var next = animationQueue.peek() ?: return
|
||||
if (next.current == drawable) {
|
||||
animationQueue.pop()
|
||||
next = animationQueue.peek() ?: return
|
||||
}
|
||||
setImageDrawable(next)
|
||||
next.start()
|
||||
}
|
||||
}
|
||||
|
||||
private fun createIcon(@DrawableRes resId: Int): AnimatedVectorDrawableCompat {
|
||||
val result = AnimatedVectorDrawableCompat.create(fab.context, resId)!!
|
||||
result.registerAnimationCallback(this)
|
||||
val result = AnimatedVectorDrawableCompat.create(context, resId)!!
|
||||
result.registerAnimationCallback(callback)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -42,6 +61,14 @@ class ServiceButton(private val fab: FloatingActionButton) : Animatable2Compat.A
|
||||
private val iconStopping by lazy { createIcon(R.drawable.ic_service_stopping) }
|
||||
private val animationQueue = ArrayDeque<AnimatedVectorDrawableCompat>()
|
||||
|
||||
private var checked = false
|
||||
|
||||
override fun onCreateDrawableState(extraSpace: Int): IntArray {
|
||||
val drawableState = super.onCreateDrawableState(extraSpace + 1)
|
||||
if (checked) View.mergeDrawableStates(drawableState, intArrayOf(android.R.attr.state_checked))
|
||||
return drawableState
|
||||
}
|
||||
|
||||
fun changeState(state: Int, animate: Boolean) {
|
||||
when (state) {
|
||||
BaseService.CONNECTING -> changeState(iconConnecting, animate)
|
||||
@@ -49,6 +76,17 @@ class ServiceButton(private val fab: FloatingActionButton) : Animatable2Compat.A
|
||||
BaseService.STOPPING -> changeState(iconStopping, animate)
|
||||
else -> changeState(iconStopped, animate)
|
||||
}
|
||||
if (state == BaseService.CONNECTED) {
|
||||
checked = true
|
||||
TooltipCompat.setTooltipText(this, context.getString(R.string.stop))
|
||||
} else {
|
||||
checked = false
|
||||
TooltipCompat.setTooltipText(this, context.getString(R.string.connect))
|
||||
}
|
||||
refreshDrawableState()
|
||||
isEnabled = false
|
||||
if (state == BaseService.CONNECTED || state == BaseService.STOPPED) App.app.handler.postDelayed(
|
||||
{ isEnabled = state == BaseService.CONNECTED || state == BaseService.STOPPED }, 1000)
|
||||
}
|
||||
|
||||
private fun counters(a: AnimatedVectorDrawableCompat, b: AnimatedVectorDrawableCompat): Boolean =
|
||||
@@ -62,26 +100,15 @@ class ServiceButton(private val fab: FloatingActionButton) : Animatable2Compat.A
|
||||
if (animationQueue.size < 2 || !counters(animationQueue.last, icon)) {
|
||||
animationQueue.add(icon)
|
||||
if (animationQueue.size == 1) {
|
||||
fab.setImageDrawable(icon)
|
||||
setImageDrawable(icon)
|
||||
icon.start()
|
||||
}
|
||||
} else animationQueue.removeLast()
|
||||
} else {
|
||||
animationQueue.peekFirst()?.stop()
|
||||
animationQueue.clear()
|
||||
fab.setImageDrawable(icon)
|
||||
setImageDrawable(icon)
|
||||
icon.stop()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onAnimationEnd(drawable: Drawable) {
|
||||
super.onAnimationEnd(drawable)
|
||||
var next = animationQueue.peek() ?: return
|
||||
if (next.current == drawable) {
|
||||
animationQueue.pop()
|
||||
next = animationQueue.peek() ?: return
|
||||
}
|
||||
fab.setImageDrawable(next)
|
||||
next.start()
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user