From ef3f4c2e17db202623cb4704b90ac0738cc29721 Mon Sep 17 00:00:00 2001 From: arkon Date: Sun, 10 May 2020 11:42:46 -0400 Subject: [PATCH] Convert rotation to FlowPreference, remove some unused subscriptions code Also remove EH lock code(was broken because of RxController changes) (cherry picked from commit d46a742a43d23c62aecf203e21a5221a06195131) # Conflicts: # app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt --- .../data/preference/PreferencesHelper.kt | 2 +- .../ui/base/controller/RxController.kt | 62 +------ .../tachiyomi/ui/reader/ReaderActivity.kt | 29 +--- .../java/exh/ui/lock/FingerLockPreference.kt | 158 ------------------ .../java/exh/ui/lock/LockActivityDelegate.kt | 51 ------ .../java/exh/ui/lock/LockChangeHandler.kt | 39 ----- .../main/java/exh/ui/lock/LockController.kt | 142 ---------------- .../main/java/exh/ui/lock/LockPreference.kt | 91 ---------- .../main/java/exh/ui/lock/LockPresenter.kt | 18 -- app/src/main/java/exh/ui/lock/LockUtils.kt | 101 ----------- 10 files changed, 11 insertions(+), 682 deletions(-) delete mode 100644 app/src/main/java/exh/ui/lock/FingerLockPreference.kt delete mode 100644 app/src/main/java/exh/ui/lock/LockActivityDelegate.kt delete mode 100644 app/src/main/java/exh/ui/lock/LockChangeHandler.kt delete mode 100755 app/src/main/java/exh/ui/lock/LockController.kt delete mode 100755 app/src/main/java/exh/ui/lock/LockPreference.kt delete mode 100644 app/src/main/java/exh/ui/lock/LockPresenter.kt delete mode 100755 app/src/main/java/exh/ui/lock/LockUtils.kt diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt index 3358eb947..7c789c5b8 100755 --- a/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/preference/PreferencesHelper.kt @@ -92,7 +92,7 @@ class PreferencesHelper(val context: Context) { fun themeDark() = flowPrefs.getString(Keys.themeDark, Values.THEME_DARK_DEFAULT) - fun rotation() = rxPrefs.getInteger(Keys.rotation, 1) + fun rotation() = flowPrefs.getInt(Keys.rotation, 1) fun pageTransitions() = flowPrefs.getBoolean(Keys.enableTransitions, true) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt index 2c3d7e9b3..493504aeb 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/base/controller/RxController.kt @@ -10,25 +10,7 @@ import rx.subscriptions.CompositeSubscription abstract class RxController(bundle: Bundle? = null) : BaseController(bundle) { - var untilDetachSubscriptions = CompositeSubscription() - private set - - var untilDestroySubscriptions = CompositeSubscription() - private set - - @CallSuper - override fun onAttach(view: View) { - super.onAttach(view) - if (untilDetachSubscriptions.isUnsubscribed) { - untilDetachSubscriptions = CompositeSubscription() - } - } - - @CallSuper - override fun onDetach(view: View) { - super.onDetach(view) - untilDetachSubscriptions.unsubscribe() - } + private var untilDestroySubscriptions = CompositeSubscription() @CallSuper override fun onViewCreated(view: View) { @@ -43,49 +25,7 @@ abstract class RxController(bundle: Bundle? = null) : BaseCont untilDestroySubscriptions.unsubscribe() } - fun Observable.subscribeUntilDetach(): Subscription { - return subscribe().also { untilDetachSubscriptions.add(it) } - } - - fun Observable.subscribeUntilDetach(onNext: (T) -> Unit): Subscription { - return subscribe(onNext).also { untilDetachSubscriptions.add(it) } - } - - fun Observable.subscribeUntilDetach( - onNext: (T) -> Unit, - onError: (Throwable) -> Unit - ): Subscription { - return subscribe(onNext, onError).also { untilDetachSubscriptions.add(it) } - } - - fun Observable.subscribeUntilDetach( - onNext: (T) -> Unit, - onError: (Throwable) -> Unit, - onCompleted: () -> Unit - ): Subscription { - return subscribe(onNext, onError, onCompleted).also { untilDetachSubscriptions.add(it) } - } - - fun Observable.subscribeUntilDestroy(): Subscription { - return subscribe().also { untilDestroySubscriptions.add(it) } - } - fun Observable.subscribeUntilDestroy(onNext: (T) -> Unit): Subscription { return subscribe(onNext).also { untilDestroySubscriptions.add(it) } } - - fun Observable.subscribeUntilDestroy( - onNext: (T) -> Unit, - onError: (Throwable) -> Unit - ): Subscription { - return subscribe(onNext, onError).also { untilDestroySubscriptions.add(it) } - } - - fun Observable.subscribeUntilDestroy( - onNext: (T) -> Unit, - onError: (Throwable) -> Unit, - onCompleted: () -> Unit - ): Subscription { - return subscribe(onNext, onError, onCompleted).also { untilDestroySubscriptions.add(it) } - } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt index 30e49f696..db5c2b73c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/reader/ReaderActivity.kt @@ -30,6 +30,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.notification.NotificationReceiver import eu.kanade.tachiyomi.data.notification.Notifications import eu.kanade.tachiyomi.data.preference.PreferencesHelper +import eu.kanade.tachiyomi.data.preference.asImmediateFlow import eu.kanade.tachiyomi.databinding.ReaderActivityBinding import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.source.model.Page @@ -64,6 +65,7 @@ import java.io.File import java.util.concurrent.TimeUnit import kotlin.math.abs import kotlin.math.roundToLong +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.drop import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.observeOn @@ -226,7 +228,6 @@ class ReaderActivity : BaseRxActivity() super.onDestroy() viewer?.destroy() viewer = null - config?.destroy() config = null progressDialog?.dismiss() progressDialog = null @@ -852,22 +853,17 @@ class ReaderActivity : BaseRxActivity() */ private inner class ReaderConfig { - /** - * List of subscriptions to keep while the reader is alive. - */ - private val subscriptions = CompositeSubscription() - /** * Initializes the reader subscriptions. */ init { - val sharedRotation = preferences.rotation().asObservable().share() - val initialRotation = sharedRotation.take(1) - val rotationUpdates = sharedRotation.skip(1) - .delay(250, TimeUnit.MILLISECONDS, AndroidSchedulers.mainThread()) - - subscriptions += Observable.merge(initialRotation, rotationUpdates) - .subscribe { setOrientation(it) } + preferences.rotation().asImmediateFlow { setOrientation(it) } + .drop(1) + .onEach { + delay(250) + setOrientation(it) + } + .launchIn(scope) preferences.readerTheme().asFlow() .drop(1) // We only care about updates @@ -905,13 +901,6 @@ class ReaderActivity : BaseRxActivity() .launchIn(scope) } - /** - * Called when the reader is being destroyed. It cleans up all the subscriptions. - */ - fun destroy() { - subscriptions.unsubscribe() - } - /** * Forces the user preferred [orientation] on the activity. */ diff --git a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt b/app/src/main/java/exh/ui/lock/FingerLockPreference.kt deleted file mode 100644 index f14aef554..000000000 --- a/app/src/main/java/exh/ui/lock/FingerLockPreference.kt +++ /dev/null @@ -1,158 +0,0 @@ -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.afollestad.materialdialogs.customview.customView -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.R -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(context) - .title(text = "Fingerprint verification") - .customView(view = linearLayout) - .negativeButton(R.string.action_cancel) - .cancelable(true) - .cancelOnTouchOutside(true) - dialog.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(context) - .title(text = "Fingerprint verification failed!") - .message(text = result.errorMessage) - .positiveButton(android.R.string.ok) - .cancelable(true) - .cancelOnTouchOutside(false) - .show() - dialog.dismiss() - } - } - } - dialog.setOnDismissListener { - subscription.unsubscribe() - } - } -} diff --git a/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt b/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt deleted file mode 100644 index c50c5ff35..000000000 --- a/app/src/main/java/exh/ui/lock/LockActivityDelegate.kt +++ /dev/null @@ -1,51 +0,0 @@ -package exh.ui.lock - -import android.view.WindowManager -import androidx.fragment.app.FragmentActivity -import com.bluelinelabs.conductor.Router -import com.bluelinelabs.conductor.RouterTransaction -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.flow.launchIn -import kotlinx.coroutines.flow.onEach -import uy.kohesive.injekt.injectLazy - -object LockActivityDelegate { - private val preferences by injectLazy() - - var willLock: Boolean = true - - private val uiScope = CoroutineScope(Dispatchers.Main) - - fun doLock(router: Router, animate: Boolean = false) { - router.pushController( - RouterTransaction.with(LockController()) - .popChangeHandler(LockChangeHandler(animate)) - ) - } - - fun onCreate(activity: FragmentActivity) { - preferences.secureScreen().asFlow() - .onEach { - if (it) { - activity.window.setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE) - } else { - activity.window.clearFlags(WindowManager.LayoutParams.FLAG_SECURE) - } - } - .launchIn(uiScope) - } - - fun onResume(activity: FragmentActivity, router: Router) { - if (lockEnabled() && !isAppLocked(router) && willLock && !preferences.eh_lockManually().getOrDefault()) { - doLock(router) - willLock = false - } - } - - private fun isAppLocked(router: Router): Boolean { - return router.backstack.lastOrNull()?.controller() is LockController - } -} diff --git a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt b/app/src/main/java/exh/ui/lock/LockChangeHandler.kt deleted file mode 100644 index b9c3dd5c1..000000000 --- a/app/src/main/java/exh/ui/lock/LockChangeHandler.kt +++ /dev/null @@ -1,39 +0,0 @@ -package exh.ui.lock - -import android.animation.Animator -import android.animation.AnimatorSet -import android.animation.ObjectAnimator -import android.view.View -import android.view.ViewGroup -import com.bluelinelabs.conductor.ControllerChangeHandler -import com.bluelinelabs.conductor.changehandler.AnimatorChangeHandler -import java.util.ArrayList - -class LockChangeHandler : AnimatorChangeHandler { - constructor() : super() - - constructor(removesFromViewOnPush: Boolean) : super(removesFromViewOnPush) - - constructor(duration: Long) : super(duration) - - constructor(duration: Long, removesFromViewOnPush: Boolean) : super(duration, removesFromViewOnPush) - - override fun getAnimator(container: ViewGroup, from: View?, to: View?, isPush: Boolean, toAddedToContainer: Boolean): Animator { - val animator = AnimatorSet() - val viewAnimators = ArrayList() - - if (!isPush && from != null) { - viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_X, 3f)) - viewAnimators.add(ObjectAnimator.ofFloat(from, View.SCALE_Y, 3f)) - viewAnimators.add(ObjectAnimator.ofFloat(from, View.ALPHA, 0f)) - } - - animator.playTogether(viewAnimators) - return animator - } - - override fun resetFromView(from: View) {} - - override fun copy(): ControllerChangeHandler = - LockChangeHandler(animationDuration, removesFromViewOnPush()) -} diff --git a/app/src/main/java/exh/ui/lock/LockController.kt b/app/src/main/java/exh/ui/lock/LockController.kt deleted file mode 100755 index 4e5b62d7c..000000000 --- a/app/src/main/java/exh/ui/lock/LockController.kt +++ /dev/null @@ -1,142 +0,0 @@ -package exh.ui.lock - -import android.annotation.SuppressLint -import android.util.TypedValue -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.afollestad.materialdialogs.MaterialDialog -import com.andrognito.pinlockview.PinLockListener -import com.github.ajalt.reprint.core.AuthenticationResult -import com.github.ajalt.reprint.rxjava.RxReprint -import com.mattprecious.swirl.SwirlView -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.databinding.ActivityLockBinding -import eu.kanade.tachiyomi.ui.base.controller.NucleusController -import exh.util.dpToPx -import kotlinx.android.synthetic.main.activity_lock.view.swirl_container -import uy.kohesive.injekt.injectLazy - -class LockController : NucleusController() { - - val prefs: PreferencesHelper by injectLazy() - - override fun inflateView(inflater: LayoutInflater, container: ViewGroup): View { - binding = ActivityLockBinding.inflate(inflater) - return binding.root - } - override fun createPresenter() = LockPresenter() - - override fun getTitle() = "Application locked" - - override fun onViewCreated(view: View) { - super.onViewCreated(view) - - if (!lockEnabled(prefs)) { - closeLock() - return - } - - with(view) { - // Setup pin lock - binding.pinLockView.attachIndicatorDots(binding.indicatorDots) - - binding.pinLockView.pinLength = prefs.eh_lockLength().getOrDefault() - binding.pinLockView.setPinLockListener(object : PinLockListener { - override fun onEmpty() {} - - override fun onComplete(pin: String) { - if (sha512(pin, prefs.eh_lockSalt().get()!!) == prefs.eh_lockHash().get()) { - // Yay! - closeLock() - } else { - MaterialDialog(context) - .title(text = "PIN code incorrect") - .message(text = "The PIN code you entered is incorrect. Please try again.") - .cancelable(true) - .cancelOnTouchOutside(true) - .positiveButton(android.R.string.ok) - .show() - binding.pinLockView.resetPinLockView() - } - } - - override fun onPinChange(pinLength: Int, intermediatePin: String?) {} - }) - } - } - - @SuppressLint("NewApi") - override fun onAttach(view: View) { - super.onAttach(view) - - with(view) { - // Fingerprint - if (presenter.useFingerprint) { - binding.swirlContainer.visibility = View.VISIBLE - binding.swirlContainer.removeAllViews() - val icon = SwirlView(context).apply { - val size = dpToPx(context, 60) - layoutParams = ( - layoutParams ?: ViewGroup.LayoutParams( - size, size - ) - ).apply { - width = size - height = size - - val pSize = dpToPx(context, 8) - setPadding(pSize, pSize, pSize, pSize) - } - val lockColor = resolvColor(android.R.attr.windowBackground) - setBackgroundColor(lockColor) - val bgColor = resolvColor(android.R.attr.colorBackground) - // Disable elevation if lock color is same as background color - if (lockColor == bgColor) { - this@with.swirl_container.cardElevation = 0f - } - setState(SwirlView.State.OFF, true) - } - binding.swirlContainer.addView(icon) - icon.setState(SwirlView.State.ON) - RxReprint.authenticate() - .subscribeUntilDetach { - when (it.status) { - AuthenticationResult.Status.SUCCESS -> closeLock() - AuthenticationResult.Status.NONFATAL_FAILURE -> icon.setState(SwirlView.State.ERROR) - AuthenticationResult.Status.FATAL_FAILURE, null -> { - MaterialDialog(context) - .title(text = "Fingerprint error!") - .message(text = it.errorMessage) - .cancelable(false) - .cancelOnTouchOutside(false) - .positiveButton(android.R.string.ok) - .show() - icon.setState(SwirlView.State.OFF) - } - } - } - } else { - binding.swirlContainer.visibility = View.GONE - } - } - } - - private fun resolvColor(color: Int): Int { - val typedVal = TypedValue() - activity!!.theme!!.resolveAttribute(color, typedVal, true) - return typedVal.data - } - - override fun onDetach(view: View) { - super.onDetach(view) - } - - fun closeLock() { - router.popCurrentController() - } - - override fun handleBack() = true -} diff --git a/app/src/main/java/exh/ui/lock/LockPreference.kt b/app/src/main/java/exh/ui/lock/LockPreference.kt deleted file mode 100755 index c527df819..000000000 --- a/app/src/main/java/exh/ui/lock/LockPreference.kt +++ /dev/null @@ -1,91 +0,0 @@ -package exh.ui.lock - -import android.content.Context -import android.text.InputType -import android.util.AttributeSet -import androidx.preference.SwitchPreferenceCompat -import com.afollestad.materialdialogs.MaterialDialog -import com.afollestad.materialdialogs.input.input -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.util.preference.onChange -import java.math.BigInteger -import java.security.SecureRandom -import rx.Observable -import rx.android.schedulers.AndroidSchedulers -import rx.schedulers.Schedulers -import uy.kohesive.injekt.injectLazy - -class LockPreference @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) : - SwitchPreferenceCompat(context, attrs) { - - private val secureRandom by lazy { SecureRandom() } - - val prefs: PreferencesHelper by injectLazy() - - override fun onAttached() { - super.onAttached() - updateSummary() - onChange { - tryChange() - false - } - } - - private fun updateSummary() { - isChecked = lockEnabled(prefs) - if (isChecked) { - title = "Lock enabled" - summary = "Tap to disable or change pin code" - } else { - title = "Lock disabled" - summary = "Tap to enable" - } - } - - fun tryChange() { - if (!notifyLockSecurity(context)) { - MaterialDialog(context) - .title(text = "Lock application") - .message(text = "Enter a pin to lock the application. Enter nothing to disable the pin lock.") - // .inputRangeRes(0, 10, R.color.material_red_500) - // .inputType(InputType.TYPE_CLASS_NUMBER) - .input(maxLength = 10, inputType = InputType.TYPE_CLASS_NUMBER, allowEmpty = true) { _, c -> - val progressDialog = MaterialDialog(context) - .title(text = "Saving password") - .cancelable(false) - progressDialog.show() - Observable.fromCallable { - savePassword(c.toString()) - }.subscribeOn(Schedulers.computation()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe { - progressDialog.dismiss() - updateSummary() - } - } - .negativeButton(R.string.action_cancel) - .cancelable(true) - .cancelOnTouchOutside(true) - .show() - } - } - - private fun savePassword(password: String) { - val salt: String? - val hash: String? - val length: Int - if (password.isEmpty()) { - salt = null - hash = null - length = -1 - } else { - salt = BigInteger(130, secureRandom).toString(32) - hash = sha512(password, salt) - length = password.length - } - prefs.eh_lockSalt().set(salt) - prefs.eh_lockHash().set(hash) - prefs.eh_lockLength().set(length) - } -} diff --git a/app/src/main/java/exh/ui/lock/LockPresenter.kt b/app/src/main/java/exh/ui/lock/LockPresenter.kt deleted file mode 100644 index cb33a8f3c..000000000 --- a/app/src/main/java/exh/ui/lock/LockPresenter.kt +++ /dev/null @@ -1,18 +0,0 @@ -package exh.ui.lock - -import android.os.Build -import com.github.ajalt.reprint.core.Reprint -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter -import uy.kohesive.injekt.injectLazy - -class LockPresenter : BasePresenter() { - val prefs: PreferencesHelper by injectLazy() - - val useFingerprint - get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && - Reprint.isHardwarePresent() && - Reprint.hasFingerprintRegistered() && - prefs.eh_lockUseFingerprint().getOrDefault() -} diff --git a/app/src/main/java/exh/ui/lock/LockUtils.kt b/app/src/main/java/exh/ui/lock/LockUtils.kt deleted file mode 100755 index 8710587e7..000000000 --- a/app/src/main/java/exh/ui/lock/LockUtils.kt +++ /dev/null @@ -1,101 +0,0 @@ -package exh.ui.lock - -import android.app.AppOpsManager -import android.content.ActivityNotFoundException -import android.content.Context -import android.content.Intent -import android.content.pm.PackageManager -import android.provider.Settings -import com.afollestad.materialdialogs.MaterialDialog -import com.elvishew.xlog.XLog -import eu.kanade.tachiyomi.R -import eu.kanade.tachiyomi.data.preference.PreferencesHelper -import eu.kanade.tachiyomi.data.preference.getOrDefault -import java.security.MessageDigest -import kotlin.experimental.and -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get - -/** - * Password hashing utils - */ - -/** - * Yes, I know SHA512 is fast, but bcrypt on mobile devices is too slow apparently - */ -fun sha512(passwordToHash: String, salt: String): String { - val md = MessageDigest.getInstance("SHA-512") - md.update(salt.toByteArray(charset("UTF-8"))) - val bytes = md.digest(passwordToHash.toByteArray(charset("UTF-8"))) - val sb = StringBuilder() - for (i in bytes.indices) { - sb.append(Integer.toString((bytes[i] and 0xff.toByte()) + 0x100, 16).substring(1)) - } - return sb.toString() -} - -/** - * Check if lock is enabled - */ -fun lockEnabled(prefs: PreferencesHelper = Injekt.get()) = - prefs.eh_lockHash().get() != null && - prefs.eh_lockSalt().get() != null && - prefs.eh_lockLength().getOrDefault() != -1 - -/** - * Check if the lock will function properly - * - * @return true if action is required, false if lock is working properly - */ -fun notifyLockSecurity( - context: Context, - prefs: PreferencesHelper = Injekt.get() -): Boolean { - return false - if (!prefs.eh_lockManually().getOrDefault() && - !hasAccessToUsageStats(context) - ) { - MaterialDialog(context) - .title(text = "Permission required") - .message( - text = "${context.getString(R.string.app_name)} requires the usage stats permission to detect when you leave the app. " + - "This is required for the application lock to function properly. " + - "Press OK to grant this permission now." - ) - .negativeButton(R.string.action_cancel) - .positiveButton(android.R.string.ok) { - try { - context.startActivity(Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)) - } catch (e: ActivityNotFoundException) { - XLog.e("Device does not support USAGE_ACCESS_SETTINGS shortcut!") - MaterialDialog(context) - .title(text = "Grant permission manually") - .message( - text = "Failed to launch the window used to grant the usage stats permission. " + - "You can still grant this permission manually: go to your phone's settings and search for 'usage access'." - ) - .positiveButton(android.R.string.ok) { it.dismiss() } - .cancelable(true) - .cancelOnTouchOutside(false) - .show() - } - } - .cancelable(false) - .show() - return true - } else { - return false - } -} - -fun hasAccessToUsageStats(context: Context): Boolean { - return try { - val packageManager = context.packageManager - val applicationInfo = packageManager.getApplicationInfo(context.packageName, 0) - val appOpsManager = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager - val mode = appOpsManager.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS, applicationInfo.uid, applicationInfo.packageName) - (mode == AppOpsManager.MODE_ALLOWED) - } catch (e: PackageManager.NameNotFoundException) { - false - } -}