diff --git a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt
index c9b75fd73..5dd49a44b 100644
--- a/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/core/prefs/AppSettings.kt
@@ -125,6 +125,10 @@ class AppSettings(context: Context) {
get() = prefs.getString(KEY_APP_PASSWORD, null)
set(value) = prefs.edit { if (value != null) putString(KEY_APP_PASSWORD, value) else remove(KEY_APP_PASSWORD) }
+ var isBiometricProtectionEnabled: Boolean
+ get() = prefs.getBoolean(KEY_PROTECT_APP_BIOMETRIC, true)
+ set(value) = prefs.edit { putBoolean(KEY_PROTECT_APP_BIOMETRIC, value) }
+
var sourcesOrder: List
get() = prefs.getString(KEY_SOURCES_ORDER, null)
?.split('|')
@@ -293,6 +297,7 @@ class AppSettings(context: Context) {
const val KEY_READER_MODE_DETECT = "reader_mode_detect"
const val KEY_APP_PASSWORD = "app_password"
const val KEY_PROTECT_APP = "protect_app"
+ const val KEY_PROTECT_APP_BIOMETRIC = "protect_app_bio"
const val KEY_APP_VERSION = "app_version"
const val KEY_ZOOM_MODE = "zoom_mode"
const val KEY_BACKUP = "backup"
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
index 953991baa..0da2ee55f 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectActivity.kt
@@ -96,6 +96,9 @@ class ProtectActivity :
}
private fun useFingerprint(): Boolean {
+ if (!viewModel.isBiometricEnabled) {
+ return false
+ }
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_WEAK) != BIOMETRIC_SUCCESS) {
return false
}
diff --git a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
index 69e671c01..85ffe23cb 100644
--- a/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/main/ui/protect/ProtectViewModel.kt
@@ -19,6 +19,9 @@ class ProtectViewModel(
val onUnlockSuccess = SingleLiveEvent()
+ val isBiometricEnabled
+ get() = settings.isBiometricProtectionEnabled
+
fun tryUnlock(password: String) {
if (job?.isActive == true) {
return
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt
index a0145362a..f88a8dad9 100644
--- a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupActivity.kt
@@ -1,5 +1,7 @@
package org.koitharu.kotatsu.settings.protect
+import android.content.pm.PackageManager
+import android.os.Build
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
@@ -7,9 +9,11 @@ import android.view.KeyEvent
import android.view.View
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
+import android.widget.CompoundButton
import android.widget.TextView
import androidx.core.graphics.Insets
import androidx.core.view.isGone
+import androidx.core.view.isVisible
import org.koin.androidx.viewmodel.ext.android.viewModel
import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.base.ui.BaseActivity
@@ -18,7 +22,7 @@ import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
private const val MIN_PASSWORD_LENGTH = 4
class ProtectSetupActivity : BaseActivity(), TextWatcher,
- View.OnClickListener, TextView.OnEditorActionListener {
+ View.OnClickListener, TextView.OnEditorActionListener, CompoundButton.OnCheckedChangeListener {
private val viewModel by viewModel()
@@ -31,6 +35,9 @@ class ProtectSetupActivity : BaseActivity(), TextWa
binding.buttonNext.setOnClickListener(this)
binding.buttonCancel.setOnClickListener(this)
+ binding.switchBiometric.isChecked = viewModel.isBiometricEnabled
+ binding.switchBiometric.setOnCheckedChangeListener(this)
+
viewModel.isSecondStep.observe(this, this::onStepChanged)
viewModel.onPasswordSet.observe(this) {
finishAfterTransition()
@@ -62,6 +69,10 @@ class ProtectSetupActivity : BaseActivity(), TextWa
}
}
+ override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
+ viewModel.setBiometricEnabled(isChecked)
+ }
+
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) {
binding.buttonNext.performClick()
@@ -85,6 +96,7 @@ class ProtectSetupActivity : BaseActivity(), TextWa
private fun onStepChanged(isSecondStep: Boolean) {
binding.buttonCancel.isGone = isSecondStep
+ binding.switchBiometric.isVisible = isSecondStep && isBiometricAvailable()
if (isSecondStep) {
binding.layoutPassword.helperText = getString(R.string.repeat_password)
binding.buttonNext.setText(R.string.confirm)
@@ -93,4 +105,9 @@ class ProtectSetupActivity : BaseActivity(), TextWa
binding.buttonNext.setText(R.string.next)
}
}
+
+ private fun isBiometricAvailable(): Boolean {
+ return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
+ packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt
index 1244c836e..c9013d23d 100644
--- a/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt
+++ b/app/src/main/java/org/koitharu/kotatsu/settings/protect/ProtectSetupViewModel.kt
@@ -22,6 +22,9 @@ class ProtectSetupViewModel(
val onPasswordMismatch = SingleLiveEvent()
val onClearText = SingleLiveEvent()
+ val isBiometricEnabled
+ get() = settings.isBiometricProtectionEnabled
+
fun onNextClick(password: String) {
if (firstPassword.value == null) {
firstPassword.value = password
@@ -35,4 +38,8 @@ class ProtectSetupViewModel(
}
}
}
+
+ fun setBiometricEnabled(isEnabled: Boolean) {
+ settings.isBiometricProtectionEnabled = isEnabled
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_setup_protect.xml b/app/src/main/res/layout/activity_setup_protect.xml
index 8fbd925a7..78c0e8e02 100644
--- a/app/src/main/res/layout/activity_setup_protect.xml
+++ b/app/src/main/res/layout/activity_setup_protect.xml
@@ -62,6 +62,19 @@
+
+
Something went wrong. Please submit a bug report to the developers to help us fix it.
Send
Disable all
+ Use fingerprint if available
\ No newline at end of file
diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml
index 16b847cc8..691c50251 100644
--- a/app/src/main/res/values/themes.xml
+++ b/app/src/main/res/values/themes.xml
@@ -72,6 +72,7 @@
- @style/Widget.Material3.CardView.Filled
- @style/Widget.Kotatsu.RecyclerView
- @style/Widget.Kotatsu.ListItemTextView
+ - @style/Widget.Material3.CompoundButton.MaterialSwitch
- @style/TextAppearance.Kotatsu.Menu