From c583301dd3c7827b22a7ff6bf36de7d79af35880 Mon Sep 17 00:00:00 2001 From: Yogesh Choudhary Paliyal Date: Fri, 7 Feb 2025 00:10:43 +0530 Subject: [PATCH] Add option to enable/disable login timeout option (#1081) --- .../keypass/ui/auth/components/ButtonBar.kt | 9 ++-- .../ui/commonComponents/PreferenceItem.kt | 47 ++++++++++++------- .../keypass/ui/settings/MySettingsFragment.kt | 39 ++++++++++++++- app/src/main/res/values/strings.xml | 1 + .../yogeshpaliyal/common/data/UserSettings.kt | 1 + .../common/utils/SharedPreferenceUtils.kt | 7 +++ 6 files changed, 83 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt index 665c3317..a7baf540 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/auth/components/ButtonBar.kt @@ -52,11 +52,12 @@ fun ButtonBar( if (userSettings.isBiometricEnable && state is AuthState.Login) { OutlinedButton(onClick = { + val currentTime = System.currentTimeMillis() val lastPasswordLoginTime = userSettings.lastPasswordLoginTime ?: -1 - if (lastPasswordLoginTime > 0 && (currentTime - lastPasswordLoginTime).toDuration( + if (userSettings.biometricLoginTimeoutEnable != true || (lastPasswordLoginTime > 0 && (currentTime - lastPasswordLoginTime).toDuration( DurationUnit.MILLISECONDS - ).inWholeHours < 24 + ).inWholeHours < 24) ) { setBiometricEnable(true) } else { @@ -97,7 +98,9 @@ fun ButtonBar( coroutineScope.launch { val savedPassword = userSettings.keyPassPassword if (savedPassword == password) { - context.updateLastPasswordLoginTime(System.currentTimeMillis()) + if(userSettings.biometricLoginTimeoutEnable == true) { + context.updateLastPasswordLoginTime(System.currentTimeMillis()) + } KeyPassRedux.getLastScreen()?.let { dispatchAction(GoBackAction) } ?: dispatchAction(NavigationAction(HomeState(), true)) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/PreferenceItem.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/PreferenceItem.kt index 62bc2145..dc6e4922 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/PreferenceItem.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/commonComponents/PreferenceItem.kt @@ -23,9 +23,8 @@ import androidx.compose.ui.unit.dp @Composable fun PreferenceItem( - @StringRes title: Int? = null, - @StringRes summary: Int? = null, - summaryStr: String? = null, + title: String? = null, + summary: String? = null, icon: ImageVector? = null, painter: Painter? = null, isCategory: Boolean = false, @@ -63,33 +62,49 @@ fun PreferenceItem( PreferenceItemTitle(title = title) } } - if (summary != null || summaryStr != null) { - val summaryText = if (summary != null) { - stringResource(id = summary) - } else { - summaryStr - } - if (summaryText != null) { - Text(text = summaryText, style = MaterialTheme.typography.bodyMedium) - } + if (summary != null) { + Text(text = summary, style = MaterialTheme.typography.bodyMedium) } } } } + @Composable -private fun CategoryTitle(title: Int) { +fun PreferenceItem( + @StringRes title: Int? = null, + @StringRes summary: Int? = null, + summaryStr: String? = null, + icon: ImageVector? = null, + painter: Painter? = null, + isCategory: Boolean = false, + removeIconSpace: Boolean = false, + onClickItem: (() -> Unit)? = null +) { + PreferenceItem( + title?.let { stringResource(it) }, + summary?.let { stringResource(summary) } ?: summaryStr, + icon, + painter, + isCategory, + removeIconSpace, + onClickItem + ) +} + +@Composable +private fun CategoryTitle(title: String) { Text( - text = stringResource(id = title), + text = title, color = MaterialTheme.colorScheme.tertiary, style = MaterialTheme.typography.titleMedium ) } @Composable -private fun PreferenceItemTitle(title: Int) { +private fun PreferenceItemTitle(title: String) { Text( - text = stringResource(id = title), + text = title, style = MaterialTheme.typography.bodyLarge ) } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt index b932bc9f..5efb1f1b 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/settings/MySettingsFragment.kt @@ -19,9 +19,10 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.rounded.Feedback import androidx.compose.material.icons.rounded.Fingerprint +import androidx.compose.material.icons.rounded.LockReset import androidx.compose.material.icons.rounded.Password import androidx.compose.material.icons.rounded.Share -import androidx.compose.material3.Divider +import androidx.compose.material3.HorizontalDivider import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -35,9 +36,11 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import com.yogeshpaliyal.common.utils.email import com.yogeshpaliyal.common.utils.setBiometricEnable +import com.yogeshpaliyal.common.utils.setBiometricLoginTimeoutEnable import com.yogeshpaliyal.keypass.BuildConfig import com.yogeshpaliyal.keypass.R import com.yogeshpaliyal.keypass.ui.commonComponents.PreferenceItem @@ -119,7 +122,9 @@ fun MySettingCompose() { BiometricsOption() - Divider( + AutoDisableBiometric() + + HorizontalDivider( modifier = Modifier .fillMaxWidth(1f) .height(1.dp) @@ -246,3 +251,33 @@ fun BiometricsOption() { } } } + + +@Composable +fun AutoDisableBiometric() { + val context = LocalContext.current + val userSettings = LocalUserSettings.current + + val coroutineScope = rememberCoroutineScope() + + + val enableDisableStr = + if (userSettings.biometricLoginTimeoutEnable == true) { + R.string.enabled + } else { + R.string.disabled + } + + PreferenceItem( + title = R.string.biometric_login_timeout, + summary = enableDisableStr, + icon = Icons.Rounded.LockReset, + onClickItem = if (userSettings.isBiometricEnable) { + { + coroutineScope.launch { + context.setBiometricLoginTimeoutEnable(userSettings.biometricLoginTimeoutEnable != true) + } + } + } else null + ) +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d6ae56c9..ac317af0 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -109,6 +109,7 @@ Biometric features are currently unavailable. Setup biometric on your device. Unlock with biometric + Biometric Login Timeout (24 hrs) Please set password for your device first from phone settings Authentication Failed Authentication Error %s diff --git a/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt b/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt index 50cef38b..2bbb6360 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/data/UserSettings.kt @@ -22,6 +22,7 @@ data class UserSettings( val currentAppVersion: Int? = null, val passwordConfig: PasswordConfig = PasswordConfig.Initial, val passwordHint: String? = null, + val biometricLoginTimeoutEnable: Boolean? = null, val lastPasswordLoginTime: Long? = null, val lastKeyPhraseEnterTime: Long? = null ) { diff --git a/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt b/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt index 1ef6eeb0..836bb409 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt @@ -62,6 +62,13 @@ suspend fun Context.setBiometricEnable(isBiometricEnable: Boolean) { } } +suspend fun Context.setBiometricLoginTimeoutEnable(biometricLoginTimeoutEnable: Boolean) { + getUserSettingsDataStore().updateData { + it.copy(biometricLoginTimeoutEnable = biometricLoginTimeoutEnable) + } +} + + suspend fun Context.setBackupDirectory(backupDirectory: String) { getUserSettingsDataStore().updateData { it.copy(backupDirectory = backupDirectory)