Add fingerprint to lock UI

Migrate login UI to conductor
Fix batch add controller not saving EditText content onResume
Prevent double-locking of lock UI
Remove back button from lock UI
Fix login preference not updating
This commit is contained in:
NerdNumber9
2017-08-24 17:11:43 -04:00
parent 32d02f9329
commit b20b3d6f5c
21 changed files with 438 additions and 109 deletions

View File

@ -0,0 +1,149 @@
package exh.ui.lock
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.content.Context
import android.os.Build
import android.support.v7.preference.SwitchPreferenceCompat
import android.support.v7.widget.LinearLayoutCompat
import android.util.AttributeSet
import android.view.Gravity
import android.view.ViewGroup
import android.widget.TextView
import com.afollestad.materialdialogs.MaterialDialog
import com.github.ajalt.reprint.core.AuthenticationResult
import com.github.ajalt.reprint.core.Reprint
import com.github.ajalt.reprint.rxjava.RxReprint
import com.mattprecious.swirl.SwirlView
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.preference.getOrDefault
import eu.kanade.tachiyomi.ui.setting.onChange
import exh.util.dpToPx
import rx.android.schedulers.AndroidSchedulers
import uy.kohesive.injekt.injectLazy
class FingerLockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
SwitchPreferenceCompat(context, attrs) {
val prefs: PreferencesHelper by injectLazy()
val fingerprintSupported
get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
&& Reprint.isHardwarePresent()
&& Reprint.hasFingerprintRegistered()
val useFingerprint
get() = fingerprintSupported
&& prefs.lockUseFingerprint().getOrDefault()
@SuppressLint("NewApi")
override fun onAttached() {
super.onAttached()
if(fingerprintSupported) {
updateSummary()
onChange {
if(it as Boolean)
tryChange()
else
prefs.lockUseFingerprint().set(false)
!it
}
} else {
title = "Fingerprint unsupported"
shouldDisableView = true
summary = if(!Reprint.hasFingerprintRegistered())
"No fingerprints enrolled!"
else
"Fingerprint unlock is unsupported on this device!"
onChange { false }
}
}
private fun updateSummary() {
isChecked = useFingerprint
title = if(isChecked)
"Fingerprint enabled"
else
"Fingerprint disabled"
}
@TargetApi(Build.VERSION_CODES.M)
fun tryChange() {
val statusTextView = TextView(context).apply {
text = "Please touch the fingerprint sensor"
val size = ViewGroup.LayoutParams.WRAP_CONTENT
layoutParams = (layoutParams ?: ViewGroup.LayoutParams(
size, size
)).apply {
width = size
height = size
setPadding(0, 0, dpToPx(context, 8), 0)
}
}
val iconView = SwirlView(context).apply {
val size = dpToPx(context, 30)
layoutParams = (layoutParams ?: ViewGroup.LayoutParams(
size, size
)).apply {
width = size
height = size
}
setState(SwirlView.State.OFF, false)
}
val linearLayout = LinearLayoutCompat(context).apply {
orientation = LinearLayoutCompat.HORIZONTAL
gravity = Gravity.CENTER_VERTICAL
val size = LinearLayoutCompat.LayoutParams.WRAP_CONTENT
layoutParams = (layoutParams ?: LinearLayoutCompat.LayoutParams(
size, size
)).apply {
width = size
height = size
val pSize = dpToPx(context, 24)
setPadding(pSize, 0, pSize, 0)
}
addView(statusTextView)
addView(iconView)
}
val dialog = MaterialDialog.Builder(context)
.title("Fingerprint verification")
.customView(linearLayout, false)
.negativeText("Cancel")
.autoDismiss(true)
.cancelable(true)
.canceledOnTouchOutside(true)
.show()
iconView.setState(SwirlView.State.ON)
val subscription = RxReprint.authenticate()
.observeOn(AndroidSchedulers.mainThread())
.subscribe { result ->
when (result.status) {
AuthenticationResult.Status.SUCCESS -> {
iconView.setState(SwirlView.State.ON)
prefs.lockUseFingerprint().set(true)
dialog.dismiss()
updateSummary()
}
AuthenticationResult.Status.NONFATAL_FAILURE -> {
iconView.setState(SwirlView.State.ERROR)
statusTextView.text = result.errorMessage
}
AuthenticationResult.Status.FATAL_FAILURE, null -> {
MaterialDialog.Builder(context)
.title("Fingerprint verification failed!")
.content(result.errorMessage)
.positiveText("Ok")
.autoDismiss(true)
.cancelable(true)
.canceledOnTouchOutside(false)
.show()
dialog.dismiss()
}
}
}
dialog.setOnDismissListener {
subscription.unsubscribe()
}
}
}