-
Notifications
You must be signed in to change notification settings - Fork 10
settings: add biometric preference flow #716
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| package com.softartdev.notedelight.interactor | ||
|
|
||
| import android.app.KeyguardManager | ||
| import android.content.Context | ||
| import android.hardware.fingerprint.FingerprintManager | ||
| import android.os.Build | ||
|
|
||
| actual class BiometricInteractor(private val context: Context) { | ||
| private val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) | ||
|
|
||
| actual var biometricEnabled: Boolean | ||
| get() = prefs.getBoolean(KEY_BIOMETRIC_ENABLED, false) | ||
| set(value) { | ||
| prefs.edit().putBoolean(KEY_BIOMETRIC_ENABLED, value).apply() | ||
| } | ||
|
|
||
| actual var biometricConfirmed: Boolean | ||
| get() = prefs.getBoolean(KEY_BIOMETRIC_CONFIRMED, false) | ||
| set(value) { | ||
| prefs.edit().putBoolean(KEY_BIOMETRIC_CONFIRMED, value).apply() | ||
| } | ||
|
|
||
| actual fun capability(): BiometricCapability { | ||
| if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { | ||
| return BiometricCapability(available = false, enrolled = false) | ||
| } | ||
| val fingerprintManager = context.getSystemService(Context.FINGERPRINT_SERVICE) as? FingerprintManager | ||
| ?: return BiometricCapability(available = false, enrolled = false) | ||
| val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as? KeyguardManager | ||
| val available = fingerprintManager.isHardwareDetected && (keyguardManager?.isKeyguardSecure == true) | ||
| val enrolled = available && fingerprintManager.hasEnrolledFingerprints() | ||
|
Comment on lines
+27
to
+31
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This implementation treats biometrics as available only when a fingerprint sensor is present, which incorrectly disables the new “Enable biometrics” setting on devices that support non-fingerprint biometrics (for example, face/iris-only hardware). Since the feature is exposed as generic biometrics, capability should be checked via Useful? React with 👍 / 👎. |
||
| return BiometricCapability(available = available, enrolled = enrolled) | ||
| } | ||
|
|
||
| private companion object { | ||
| private const val PREFS_NAME = "notedelight_settings" | ||
| private const val KEY_BIOMETRIC_ENABLED = "biometric_enabled" | ||
| private const val KEY_BIOMETRIC_CONFIRMED = "biometric_confirmed" | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,12 @@ | ||
| package com.softartdev.notedelight.interactor | ||
|
|
||
| data class BiometricCapability( | ||
| val available: Boolean, | ||
| val enrolled: Boolean, | ||
| ) | ||
|
|
||
| expect class BiometricInteractor { | ||
| var biometricEnabled: Boolean | ||
| var biometricConfirmed: Boolean | ||
| fun capability(): BiometricCapability | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,27 @@ | ||
| package com.softartdev.notedelight.interactor | ||
|
|
||
| import platform.Foundation.NSUserDefaults | ||
|
|
||
| actual class BiometricInteractor { | ||
| actual var biometricEnabled: Boolean | ||
| get() = NSUserDefaults.standardUserDefaults.boolForKey(KEY_BIOMETRIC_ENABLED) | ||
| set(value) { | ||
| NSUserDefaults.standardUserDefaults.setBool(value, KEY_BIOMETRIC_ENABLED) | ||
| } | ||
|
|
||
| actual var biometricConfirmed: Boolean | ||
| get() = NSUserDefaults.standardUserDefaults.boolForKey(KEY_BIOMETRIC_CONFIRMED) | ||
| set(value) { | ||
| NSUserDefaults.standardUserDefaults.setBool(value, KEY_BIOMETRIC_CONFIRMED) | ||
| } | ||
|
|
||
| actual fun capability(): BiometricCapability = BiometricCapability( | ||
| available = false, | ||
| enrolled = false, | ||
| ) | ||
|
|
||
| private companion object { | ||
| private const val KEY_BIOMETRIC_ENABLED = "biometric_enabled" | ||
| private const val KEY_BIOMETRIC_CONFIRMED = "biometric_confirmed" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| package com.softartdev.notedelight.interactor | ||
|
|
||
| import java.util.prefs.Preferences | ||
|
|
||
| actual class BiometricInteractor { | ||
| private val preferences = Preferences.userRoot().node(PREFS_NODE) | ||
|
|
||
| actual var biometricEnabled: Boolean | ||
| get() = preferences.getBoolean(KEY_BIOMETRIC_ENABLED, false) | ||
| set(value) { | ||
| preferences.putBoolean(KEY_BIOMETRIC_ENABLED, value) | ||
| } | ||
|
|
||
| actual var biometricConfirmed: Boolean | ||
| get() = preferences.getBoolean(KEY_BIOMETRIC_CONFIRMED, false) | ||
| set(value) { | ||
| preferences.putBoolean(KEY_BIOMETRIC_CONFIRMED, value) | ||
| } | ||
|
|
||
| actual fun capability(): BiometricCapability = BiometricCapability( | ||
| available = false, | ||
| enrolled = false, | ||
| ) | ||
|
|
||
| private companion object { | ||
| private const val PREFS_NODE = "com.softartdev.notedelight.settings" | ||
| private const val KEY_BIOMETRIC_ENABLED = "biometric_enabled" | ||
| private const val KEY_BIOMETRIC_CONFIRMED = "biometric_confirmed" | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,32 @@ | ||
| package com.softartdev.notedelight.interactor | ||
|
|
||
| import kotlinx.browser.window | ||
|
|
||
| actual class BiometricInteractor { | ||
| actual var biometricEnabled: Boolean | ||
| get() = localStorageItem(KEY_BIOMETRIC_ENABLED) == TRUE_VALUE | ||
| set(value) { | ||
| setLocalStorageItem(KEY_BIOMETRIC_ENABLED, value.toString()) | ||
| } | ||
|
|
||
| actual var biometricConfirmed: Boolean | ||
| get() = localStorageItem(KEY_BIOMETRIC_CONFIRMED) == TRUE_VALUE | ||
| set(value) { | ||
| setLocalStorageItem(KEY_BIOMETRIC_CONFIRMED, value.toString()) | ||
| } | ||
|
|
||
| actual fun capability(): BiometricCapability = BiometricCapability( | ||
| available = false, | ||
| enrolled = false, | ||
| ) | ||
|
|
||
| private companion object { | ||
| private const val KEY_BIOMETRIC_ENABLED = "biometric_enabled" | ||
| private const val KEY_BIOMETRIC_CONFIRMED = "biometric_confirmed" | ||
| private const val TRUE_VALUE = "true" | ||
| } | ||
| } | ||
|
|
||
| private fun localStorageItem(key: String): String? = window.localStorage.getItem(key) | ||
|
|
||
| private fun setLocalStorageItem(key: String, value: String) = window.localStorage.setItem(key, value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
capability()callsFingerprintManager.isHardwareDetected()andhasEnrolledFingerprints()without any declared biometric/fingerprint permission in the Android manifests, so this path can raiseSecurityExceptionat runtime when settings refreshes (it runs fromupdateSwitches()on resume). Please declareUSE_BIOMETRIC/USE_FINGERPRINTin the app manifest (or use an API path that avoids this requirement) before invoking these methods.Useful? React with 👍 / 👎.