package exh.ui.lock import android.annotation.SuppressLint import android.annotation.TargetApi import android.content.Context import android.os.Build import android.util.AttributeSet import android.view.Gravity import android.view.ViewGroup import android.widget.TextView import androidx.appcompat.widget.LinearLayoutCompat import androidx.preference.SwitchPreferenceCompat 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.util.preference.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.eh_lockUseFingerprint().getOrDefault() @SuppressLint("NewApi") override fun onAttached() { super.onAttached() if(fingerprintSupported) { updateSummary() onChange { if(it as Boolean) tryChange() else prefs.eh_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.eh_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() } } }