Option to disable fingerprint authentication
This commit is contained in:
@@ -125,6 +125,10 @@ class AppSettings(context: Context) {
|
|||||||
get() = prefs.getString(KEY_APP_PASSWORD, null)
|
get() = prefs.getString(KEY_APP_PASSWORD, null)
|
||||||
set(value) = prefs.edit { if (value != null) putString(KEY_APP_PASSWORD, value) else remove(KEY_APP_PASSWORD) }
|
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<String>
|
var sourcesOrder: List<String>
|
||||||
get() = prefs.getString(KEY_SOURCES_ORDER, null)
|
get() = prefs.getString(KEY_SOURCES_ORDER, null)
|
||||||
?.split('|')
|
?.split('|')
|
||||||
@@ -293,6 +297,7 @@ class AppSettings(context: Context) {
|
|||||||
const val KEY_READER_MODE_DETECT = "reader_mode_detect"
|
const val KEY_READER_MODE_DETECT = "reader_mode_detect"
|
||||||
const val KEY_APP_PASSWORD = "app_password"
|
const val KEY_APP_PASSWORD = "app_password"
|
||||||
const val KEY_PROTECT_APP = "protect_app"
|
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_APP_VERSION = "app_version"
|
||||||
const val KEY_ZOOM_MODE = "zoom_mode"
|
const val KEY_ZOOM_MODE = "zoom_mode"
|
||||||
const val KEY_BACKUP = "backup"
|
const val KEY_BACKUP = "backup"
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ class ProtectActivity :
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun useFingerprint(): Boolean {
|
private fun useFingerprint(): Boolean {
|
||||||
|
if (!viewModel.isBiometricEnabled) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_WEAK) != BIOMETRIC_SUCCESS) {
|
if (BiometricManager.from(this).canAuthenticate(BIOMETRIC_WEAK) != BIOMETRIC_SUCCESS) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ class ProtectViewModel(
|
|||||||
|
|
||||||
val onUnlockSuccess = SingleLiveEvent<Unit>()
|
val onUnlockSuccess = SingleLiveEvent<Unit>()
|
||||||
|
|
||||||
|
val isBiometricEnabled
|
||||||
|
get() = settings.isBiometricProtectionEnabled
|
||||||
|
|
||||||
fun tryUnlock(password: String) {
|
fun tryUnlock(password: String) {
|
||||||
if (job?.isActive == true) {
|
if (job?.isActive == true) {
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.koitharu.kotatsu.settings.protect
|
package org.koitharu.kotatsu.settings.protect
|
||||||
|
|
||||||
|
import android.content.pm.PackageManager
|
||||||
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.text.Editable
|
import android.text.Editable
|
||||||
import android.text.TextWatcher
|
import android.text.TextWatcher
|
||||||
@@ -7,9 +9,11 @@ import android.view.KeyEvent
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.widget.CompoundButton
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.graphics.Insets
|
import androidx.core.graphics.Insets
|
||||||
import androidx.core.view.isGone
|
import androidx.core.view.isGone
|
||||||
|
import androidx.core.view.isVisible
|
||||||
import org.koin.androidx.viewmodel.ext.android.viewModel
|
import org.koin.androidx.viewmodel.ext.android.viewModel
|
||||||
import org.koitharu.kotatsu.R
|
import org.koitharu.kotatsu.R
|
||||||
import org.koitharu.kotatsu.base.ui.BaseActivity
|
import org.koitharu.kotatsu.base.ui.BaseActivity
|
||||||
@@ -18,7 +22,7 @@ import org.koitharu.kotatsu.databinding.ActivitySetupProtectBinding
|
|||||||
private const val MIN_PASSWORD_LENGTH = 4
|
private const val MIN_PASSWORD_LENGTH = 4
|
||||||
|
|
||||||
class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWatcher,
|
class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWatcher,
|
||||||
View.OnClickListener, TextView.OnEditorActionListener {
|
View.OnClickListener, TextView.OnEditorActionListener, CompoundButton.OnCheckedChangeListener {
|
||||||
|
|
||||||
private val viewModel by viewModel<ProtectSetupViewModel>()
|
private val viewModel by viewModel<ProtectSetupViewModel>()
|
||||||
|
|
||||||
@@ -31,6 +35,9 @@ class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWa
|
|||||||
binding.buttonNext.setOnClickListener(this)
|
binding.buttonNext.setOnClickListener(this)
|
||||||
binding.buttonCancel.setOnClickListener(this)
|
binding.buttonCancel.setOnClickListener(this)
|
||||||
|
|
||||||
|
binding.switchBiometric.isChecked = viewModel.isBiometricEnabled
|
||||||
|
binding.switchBiometric.setOnCheckedChangeListener(this)
|
||||||
|
|
||||||
viewModel.isSecondStep.observe(this, this::onStepChanged)
|
viewModel.isSecondStep.observe(this, this::onStepChanged)
|
||||||
viewModel.onPasswordSet.observe(this) {
|
viewModel.onPasswordSet.observe(this) {
|
||||||
finishAfterTransition()
|
finishAfterTransition()
|
||||||
@@ -62,6 +69,10 @@ class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) {
|
||||||
|
viewModel.setBiometricEnabled(isChecked)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
|
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
|
||||||
return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) {
|
return if (actionId == EditorInfo.IME_ACTION_DONE && binding.buttonNext.isEnabled) {
|
||||||
binding.buttonNext.performClick()
|
binding.buttonNext.performClick()
|
||||||
@@ -85,6 +96,7 @@ class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWa
|
|||||||
|
|
||||||
private fun onStepChanged(isSecondStep: Boolean) {
|
private fun onStepChanged(isSecondStep: Boolean) {
|
||||||
binding.buttonCancel.isGone = isSecondStep
|
binding.buttonCancel.isGone = isSecondStep
|
||||||
|
binding.switchBiometric.isVisible = isSecondStep && isBiometricAvailable()
|
||||||
if (isSecondStep) {
|
if (isSecondStep) {
|
||||||
binding.layoutPassword.helperText = getString(R.string.repeat_password)
|
binding.layoutPassword.helperText = getString(R.string.repeat_password)
|
||||||
binding.buttonNext.setText(R.string.confirm)
|
binding.buttonNext.setText(R.string.confirm)
|
||||||
@@ -93,4 +105,9 @@ class ProtectSetupActivity : BaseActivity<ActivitySetupProtectBinding>(), TextWa
|
|||||||
binding.buttonNext.setText(R.string.next)
|
binding.buttonNext.setText(R.string.next)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isBiometricAvailable(): Boolean {
|
||||||
|
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
|
||||||
|
packageManager.hasSystemFeature(PackageManager.FEATURE_FINGERPRINT)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -22,6 +22,9 @@ class ProtectSetupViewModel(
|
|||||||
val onPasswordMismatch = SingleLiveEvent<Unit>()
|
val onPasswordMismatch = SingleLiveEvent<Unit>()
|
||||||
val onClearText = SingleLiveEvent<Unit>()
|
val onClearText = SingleLiveEvent<Unit>()
|
||||||
|
|
||||||
|
val isBiometricEnabled
|
||||||
|
get() = settings.isBiometricProtectionEnabled
|
||||||
|
|
||||||
fun onNextClick(password: String) {
|
fun onNextClick(password: String) {
|
||||||
if (firstPassword.value == null) {
|
if (firstPassword.value == null) {
|
||||||
firstPassword.value = password
|
firstPassword.value = password
|
||||||
@@ -35,4 +38,8 @@ class ProtectSetupViewModel(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun setBiometricEnabled(isEnabled: Boolean) {
|
||||||
|
settings.isBiometricProtectionEnabled = isEnabled
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -62,6 +62,19 @@
|
|||||||
|
|
||||||
</com.google.android.material.textfield.TextInputLayout>
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.materialswitch.MaterialSwitch
|
||||||
|
android:id="@+id/switch_biometric"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="16dp"
|
||||||
|
android:checked="true"
|
||||||
|
android:text="@string/use_fingerprint"
|
||||||
|
android:visibility="gone"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/layout_password"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<com.google.android.material.button.MaterialButton
|
||||||
android:id="@+id/button_cancel"
|
android:id="@+id/button_cancel"
|
||||||
style="@style/Widget.Material3.Button.OutlinedButton"
|
style="@style/Widget.Material3.Button.OutlinedButton"
|
||||||
|
|||||||
@@ -301,4 +301,5 @@
|
|||||||
<string name="crash_text">Something went wrong. Please submit a bug report to the developers to help us fix it.</string>
|
<string name="crash_text">Something went wrong. Please submit a bug report to the developers to help us fix it.</string>
|
||||||
<string name="send">Send</string>
|
<string name="send">Send</string>
|
||||||
<string name="disable_all">Disable all</string>
|
<string name="disable_all">Disable all</string>
|
||||||
|
<string name="use_fingerprint">Use fingerprint if available</string>
|
||||||
</resources>
|
</resources>
|
||||||
@@ -72,6 +72,7 @@
|
|||||||
<item name="materialCardViewStyle">@style/Widget.Material3.CardView.Filled</item>
|
<item name="materialCardViewStyle">@style/Widget.Material3.CardView.Filled</item>
|
||||||
<item name="recyclerViewStyle">@style/Widget.Kotatsu.RecyclerView</item>
|
<item name="recyclerViewStyle">@style/Widget.Kotatsu.RecyclerView</item>
|
||||||
<item name="listItemTextViewStyle">@style/Widget.Kotatsu.ListItemTextView</item>
|
<item name="listItemTextViewStyle">@style/Widget.Kotatsu.ListItemTextView</item>
|
||||||
|
<item name="materialSwitchStyle">@style/Widget.Material3.CompoundButton.MaterialSwitch</item>
|
||||||
|
|
||||||
<!-- Text appearance -->
|
<!-- Text appearance -->
|
||||||
<item name="actionMenuTextAppearance">@style/TextAppearance.Kotatsu.Menu</item>
|
<item name="actionMenuTextAppearance">@style/TextAppearance.Kotatsu.Menu</item>
|
||||||
|
|||||||
Reference in New Issue
Block a user