diff --git a/.github/workflows/pr-check.yaml b/.github/workflows/pr-check.yaml index 76480baa..b5e3b9aa 100644 --- a/.github/workflows/pr-check.yaml +++ b/.github/workflows/pr-check.yaml @@ -34,7 +34,7 @@ jobs: - name: 🏗 Build APK run: bash ./gradlew assembleProductionDebug - - name: 🚀 Upload APK to Artifiacts 📱 + - name: 🚀 Upload APK to Artifacts 📱 uses: actions/upload-artifact@v3 with: name: app diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt new file mode 100644 index 00000000..ac1e5269 --- /dev/null +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthScreen.kt @@ -0,0 +1,106 @@ +package com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.rounded.ArrowBackIosNew +import androidx.compose.material.icons.rounded.Done +import androidx.compose.material3.BottomAppBar +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.rememberVectorPainter +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.testTag +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.lifecycle.viewmodel.compose.viewModel +import com.yogeshpaliyal.keypass.ui.generate.ui.components.PasswordLengthInput +import com.yogeshpaliyal.keypass.ui.redux.actions.Action +import com.yogeshpaliyal.keypass.ui.redux.actions.GoBackAction +import com.yogeshpaliyal.keypass.ui.redux.states.ChangeDefaultPasswordLengthState +import org.reduxkotlin.TypedDispatcher +import org.reduxkotlin.compose.rememberTypedDispatcher + +@Composable +fun ChangeDefaultPasswordLengthScreen( + viewModel: ChangeDefaultPasswordLengthViewModel = viewModel() +) { + viewModel.retrieveSavedPasswordLength(LocalContext.current) + val dispatchAction = rememberTypedDispatcher() + val state by viewModel.viewState.collectAsState() + + Scaffold(bottomBar = { BottomBar(dispatchAction, viewModel) }) { contentPadding -> + Surface( + modifier = Modifier + .padding(contentPadding) + .fillMaxWidth() + ) { + ChangeDefaultPasswordLengthContent(state = state, viewModel = viewModel) + } + } +} + +@Composable +private fun ChangeDefaultPasswordLengthContent( + state: ChangeDefaultPasswordLengthState, + viewModel: ChangeDefaultPasswordLengthViewModel +) { + Column( + modifier = Modifier + .fillMaxSize() + .padding(32.dp), + verticalArrangement = Arrangement.spacedBy(8.dp) + ) { + PasswordLengthInput(length = state.length, viewModel::onPasswordLengthChanged) + } +} + +@Composable +private fun BottomBar( + dispatchAction: TypedDispatcher, + viewModel: ChangeDefaultPasswordLengthViewModel +) { + val context = LocalContext.current + BottomAppBar( + actions = { + IconButton(onClick = { dispatchAction(GoBackAction) }) { + Icon( + painter = rememberVectorPainter(image = Icons.Rounded.ArrowBackIosNew), + contentDescription = "Go Back", + tint = MaterialTheme.colorScheme.onSurface + ) + } + }, + floatingActionButton = { + FloatingActionButton(modifier = Modifier.testTag("save"), onClick = { + // Save new password length + viewModel.updatePasswordLength(context) { + // Close screen + dispatchAction(GoBackAction) + } + }) { + Icon( + painter = rememberVectorPainter(image = Icons.Rounded.Done), + contentDescription = "Save Changes" + ) + } + } + ) +} + +@Preview(name = "ChangeDefaultPasswordLength", showBackground = true, showSystemUi = true) +@Composable +fun ChangeDefaultPasswordLengthPreview() { + ChangeDefaultPasswordLengthScreen() +} diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthViewModel.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthViewModel.kt new file mode 100644 index 00000000..3cc1aeda --- /dev/null +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/changeDefaultPasswordLength/ChangeDefaultPasswordLengthViewModel.kt @@ -0,0 +1,53 @@ +package com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength + +import android.content.Context +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.yogeshpaliyal.common.utils.getKeyPassPasswordLength +import com.yogeshpaliyal.common.utils.setKeyPassPasswordLength +import com.yogeshpaliyal.keypass.ui.generate.ui.components.DEFAULT_PASSWORD_LENGTH +import com.yogeshpaliyal.keypass.ui.redux.states.ChangeDefaultPasswordLengthState +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch + +class ChangeDefaultPasswordLengthViewModel : ViewModel() { + + private val _viewState = MutableStateFlow(ChangeDefaultPasswordLengthState()) + val viewState = _viewState.asStateFlow() + + /** + * Initial [ChangeDefaultPasswordLengthState] with previously saved length + * */ + fun retrieveSavedPasswordLength(context: Context) { + viewModelScope.launch { + _viewState.update { + val oldPasswordLength = + context.getKeyPassPasswordLength() ?: DEFAULT_PASSWORD_LENGTH + ChangeDefaultPasswordLengthState(length = oldPasswordLength) + } + } + } + + /** + * Stores the new password length from [_viewState] in the data store [Context.setKeyPassPasswordLength] + * */ + fun updatePasswordLength(context: Context, callback: () -> Unit) { + viewModelScope.launch { + _viewState.value.length.let { length -> + context.setKeyPassPasswordLength(length) + callback.invoke() + } + } + } + + /** + * Updates the state after changing the value of the slider + * */ + fun onPasswordLengthChanged(value: Float) { + _viewState.update { + _viewState.value.copy(length = value) + } + } +} diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordActivity.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordActivity.kt index 5b15a798..c8506bd2 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordActivity.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordActivity.kt @@ -14,6 +14,7 @@ class GeneratePasswordActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + viewModel.retrieveSavedPasswordLength(baseContext) setContent { Mdc3Theme { GeneratePasswordScreen(viewModel) diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewModel.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewModel.kt index 130d0c4a..3050b525 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewModel.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewModel.kt @@ -1,24 +1,49 @@ package com.yogeshpaliyal.keypass.ui.generate +import android.content.Context import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope import com.yogeshpaliyal.common.utils.PasswordGenerator +import com.yogeshpaliyal.common.utils.getKeyPassPasswordLength +import com.yogeshpaliyal.common.utils.setKeyPassPasswordLength +import com.yogeshpaliyal.keypass.ui.generate.ui.components.DEFAULT_PASSWORD_LENGTH import dagger.hilt.android.lifecycle.HiltViewModel +import dagger.hilt.android.qualifiers.ApplicationContext +import kotlinx.coroutines.FlowPreview import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.asStateFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.flow.debounce import kotlinx.coroutines.flow.update +import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel -class GeneratePasswordViewModel @Inject constructor() : ViewModel() { +class GeneratePasswordViewModel @Inject constructor( + @ApplicationContext context: Context +) : ViewModel() { private val _viewState = MutableStateFlow(GeneratePasswordViewState.Initial) val viewState = _viewState.asStateFlow() + init { + observeState(context) + } + + fun retrieveSavedPasswordLength(context: Context) { + viewModelScope.launch { + val savedPasswordLength = context.getKeyPassPasswordLength() ?: DEFAULT_PASSWORD_LENGTH + _viewState.update { + _viewState.value.copy(length = savedPasswordLength) + } + } + } + fun generatePassword() { val currentViewState = _viewState.value val passwordGenerator = PasswordGenerator( - length = currentViewState.length, + length = currentViewState.length.toInt(), includeUpperCaseLetters = currentViewState.includeUppercaseLetters, includeLowerCaseLetters = currentViewState.includeLowercaseLetters, includeSymbols = currentViewState.includeSymbols, @@ -33,7 +58,7 @@ class GeneratePasswordViewModel @Inject constructor() : ViewModel() { fun onPasswordLengthSliderChange(value: Float) { _viewState.update { - it.copy(length = value.toInt()) + it.copy(length = value) } } @@ -60,4 +85,16 @@ class GeneratePasswordViewModel @Inject constructor() : ViewModel() { it.copy(includeSymbols = checked) } } + + @OptIn(FlowPreview::class) + private fun observeState(context: Context) { + viewModelScope.launch { + // Save every changed value from password length with a delay + _viewState + .debounce(400) + .collectLatest { state -> + context.setKeyPassPasswordLength(state.length) + } + } + } } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewState.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewState.kt index 596d0786..35ce7c68 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewState.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/GeneratePasswordViewState.kt @@ -1,7 +1,9 @@ package com.yogeshpaliyal.keypass.ui.generate +import com.yogeshpaliyal.keypass.ui.generate.ui.components.DEFAULT_PASSWORD_LENGTH + data class GeneratePasswordViewState( - val length: Int, + val length: Float, val includeUppercaseLetters: Boolean, val includeLowercaseLetters: Boolean, val includeSymbols: Boolean, @@ -10,7 +12,7 @@ data class GeneratePasswordViewState( ) { companion object { val Initial = GeneratePasswordViewState( - length = 10, + length = DEFAULT_PASSWORD_LENGTH, includeUppercaseLetters = true, includeLowercaseLetters = true, includeSymbols = true, diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/GeneratePasswordContent.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/GeneratePasswordContent.kt index 97224407..ab4b19e1 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/GeneratePasswordContent.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/GeneratePasswordContent.kt @@ -17,7 +17,6 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.OutlinedCard import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Scaffold -import androidx.compose.material3.Slider import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier @@ -26,6 +25,7 @@ import androidx.compose.ui.unit.dp import com.google.accompanist.themeadapter.material3.Mdc3Theme import com.yogeshpaliyal.keypass.ui.generate.GeneratePasswordViewState import com.yogeshpaliyal.keypass.ui.generate.ui.components.CheckboxWithLabel +import com.yogeshpaliyal.keypass.ui.generate.ui.components.PasswordLengthInput @Composable fun GeneratePasswordContent( @@ -135,21 +135,6 @@ private fun PasswordTextField( ) } -@Composable -private fun PasswordLengthInput( - length: Int, - onPasswordLengthChange: (Float) -> Unit -) { - Text(text = "Password Length: $length") - - Slider( - value = length.toFloat(), - onValueChange = onPasswordLengthChange, - valueRange = 7f..50f, - steps = 43 - ) -} - @Composable private fun UppercaseAlphabetInput( includeUppercaseLetters: Boolean, diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/components/PasswordLengthInput.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/components/PasswordLengthInput.kt new file mode 100644 index 00000000..c91f3193 --- /dev/null +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/generate/ui/components/PasswordLengthInput.kt @@ -0,0 +1,22 @@ +package com.yogeshpaliyal.keypass.ui.generate.ui.components + +import androidx.compose.material3.Slider +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable + +const val DEFAULT_PASSWORD_LENGTH = 10f + +@Composable +fun PasswordLengthInput( + length: Float, + onPasswordLengthChange: (Float) -> Unit +) { + Text(text = "Password Length: ${length.toInt()}") + + Slider( + value = length, + onValueChange = onPasswordLengthChange, + valueRange = 7f..50f, + steps = 43 + ) +} diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt index 5ab3ecf3..ea8cf817 100644 --- a/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/nav/DashboardComposeActivity.kt @@ -51,6 +51,7 @@ import androidx.compose.ui.unit.dp import com.yogeshpaliyal.keypass.BuildConfig import com.yogeshpaliyal.keypass.ui.auth.AuthScreen import com.yogeshpaliyal.keypass.ui.backup.BackupScreen +import com.yogeshpaliyal.keypass.ui.changeDefaultPasswordLength.ChangeDefaultPasswordLengthScreen import com.yogeshpaliyal.keypass.ui.changePassword.ChangePassword import com.yogeshpaliyal.keypass.ui.detail.AccountDetailPage import com.yogeshpaliyal.keypass.ui.home.Homepage @@ -64,6 +65,7 @@ import com.yogeshpaliyal.keypass.ui.redux.states.AuthState import com.yogeshpaliyal.keypass.ui.redux.states.BackupScreenState import com.yogeshpaliyal.keypass.ui.redux.states.BottomSheetState import com.yogeshpaliyal.keypass.ui.redux.states.ChangeAppPasswordState +import com.yogeshpaliyal.keypass.ui.redux.states.ChangeDefaultPasswordLengthState import com.yogeshpaliyal.keypass.ui.redux.states.HomeState import com.yogeshpaliyal.keypass.ui.redux.states.KeyPassState import com.yogeshpaliyal.keypass.ui.redux.states.ScreenState @@ -163,6 +165,11 @@ fun CurrentPage() { is ChangeAppPasswordState -> { ChangePassword(it) } + + is ChangeDefaultPasswordLengthState -> { + ChangeDefaultPasswordLengthScreen() + } + is TotpDetailState -> { } } diff --git a/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/states/ChangeDefaultPasswordLengthState.kt b/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/states/ChangeDefaultPasswordLengthState.kt new file mode 100644 index 00000000..38439747 --- /dev/null +++ b/app/src/main/java/com/yogeshpaliyal/keypass/ui/redux/states/ChangeDefaultPasswordLengthState.kt @@ -0,0 +1,7 @@ +package com.yogeshpaliyal.keypass.ui.redux.states + +import com.yogeshpaliyal.keypass.ui.generate.ui.components.DEFAULT_PASSWORD_LENGTH + +data class ChangeDefaultPasswordLengthState( + val length: Float = DEFAULT_PASSWORD_LENGTH +) : ScreenState(false) 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 9103854e..f1ac8731 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 @@ -34,9 +34,11 @@ import androidx.compose.material3.Text import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.vector.ImageVector @@ -48,9 +50,11 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.yogeshpaliyal.common.utils.BACKUP_KEY_LENGTH import com.yogeshpaliyal.common.utils.email +import com.yogeshpaliyal.common.utils.getKeyPassPasswordLength import com.yogeshpaliyal.common.utils.isBiometricEnable import com.yogeshpaliyal.common.utils.setBiometricEnable import com.yogeshpaliyal.keypass.R +import com.yogeshpaliyal.keypass.ui.generate.ui.components.DEFAULT_PASSWORD_LENGTH import com.yogeshpaliyal.keypass.ui.home.DashboardViewModel import com.yogeshpaliyal.keypass.ui.redux.actions.Action import com.yogeshpaliyal.keypass.ui.redux.actions.IntentNavigation @@ -58,6 +62,7 @@ import com.yogeshpaliyal.keypass.ui.redux.actions.NavigationAction import com.yogeshpaliyal.keypass.ui.redux.actions.ToastAction import com.yogeshpaliyal.keypass.ui.redux.states.BackupScreenState import com.yogeshpaliyal.keypass.ui.redux.states.ChangeAppPasswordState +import com.yogeshpaliyal.keypass.ui.redux.states.ChangeDefaultPasswordLengthState import kotlinx.coroutines.launch import org.reduxkotlin.compose.rememberTypedDispatcher @@ -153,6 +158,12 @@ fun MySettingCompose() { ) } + // Retrieving saved password length + var savedPasswordLength by remember { mutableStateOf(DEFAULT_PASSWORD_LENGTH) } + LaunchedEffect(key1 = Unit) { + context.getKeyPassPasswordLength()?.let { value -> savedPasswordLength = value } + } + Column { PreferenceItem(title = R.string.security, isCategory = true) PreferenceItem( @@ -174,6 +185,13 @@ fun MySettingCompose() { ) { dispatchAction(NavigationAction(ChangeAppPasswordState())) } + val changePasswordLengthSummary = context.getString(R.string.default_password_length) + PreferenceItem( + title = R.string.change_password_length, + summaryStr = "$changePasswordLengthSummary: ${savedPasswordLength.toInt()}" + ) { + dispatchAction(NavigationAction(ChangeDefaultPasswordLengthState())) + } BiometricsOption() diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index f4e3b86d..ad9b406f 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -95,4 +95,6 @@ مجلد النسخ الاحتياطي دعم قم بتشغيل النسخ الاحتياطية + تغيير طول كلمة المرور + الطول الافتراضي لكلمة المرور \ No newline at end of file diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index a502fa32..728361bb 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -95,4 +95,6 @@ ফোন সেটিংস থেকে প্রথমে আপনার ডিভাইসের জন্য পাসওয়ার্ড সেট করুন প্রমাণীকরণ ব্যর্থ হয়েছে প্রমাণীকরণ ত্রুটি %s + পাসওয়ার্ডের দৈর্ঘ্য পরিবর্তন করুন + ডিফল্ট পাসওয়ার্ড দৈর্ঘ্য \ No newline at end of file diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 54d77c2c..472e993e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -95,4 +95,6 @@ Passwort eingeben Weitermachen Absteigend + Passwortlänge ändern + Standardlänge des Passworts \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index fcf2ae85..d9818682 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -95,4 +95,6 @@ Contraseña antigua Por favor, introduzca su contraseña anterior Desbloqueo con biométrico + Cambiar la longitud de la contraseña + Longitud de contraseña predeterminada \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 3104532c..85cdd250 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -95,4 +95,6 @@ Authentification échouée Erreur d\'authentification %s Es-tu sûr \? + Modifier la longueur du mot de passe + Longueur du mot de passe par défaut \ No newline at end of file diff --git a/app/src/main/res/values-gu-rIN/strings.xml b/app/src/main/res/values-gu-rIN/strings.xml index fa0a3f98..3450174e 100644 --- a/app/src/main/res/values-gu-rIN/strings.xml +++ b/app/src/main/res/values-gu-rIN/strings.xml @@ -95,4 +95,6 @@ કૃપા કરીને ફોન સેટિંગ્સમાંથી પહેલા તમારા ઉપકરણ માટે પાસવર્ડ સેટ કરો પ્રમાણીકરણ નિષ્ફળ થયું પ્રમાણીકરણ ભૂલ %s + પાસવર્ડ લંબાઈ બદલો + ડિફૉલ્ટ પાસવર્ડ લંબાઈ \ No newline at end of file diff --git a/app/src/main/res/values-gu/strings.xml b/app/src/main/res/values-gu/strings.xml index 77431346..136ea03b 100644 --- a/app/src/main/res/values-gu/strings.xml +++ b/app/src/main/res/values-gu/strings.xml @@ -95,4 +95,6 @@ કૃપા કરીને ફોન સેટિંગ્સમાંથી પહેલા તમારા ઉપકરણ માટે પાસવર્ડ સેટ કરો પ્રમાણીકરણ નિષ્ફળ થયું પ્રમાણીકરણ ભૂલ %s + પાસવર્ડ લંબાઈ બદલો + ડિફૉલ્ટ પાસવર્ડ લંબાઈ \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 77b3c3b7..25f48a7f 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -96,4 +96,6 @@ कृपया पुष्टि पासवर्ड दर्ज करें पासवर्ड सफलतापूर्वक बदला गया प्रमाणीकरण त्रुटि %s + पासवर्ड की लंबाई बदलें + डिफ़ॉल्ट पासवर्ड लंबाई \ No newline at end of file diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index fde03bd0..2fffb0a1 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -95,4 +95,6 @@ Si prega di impostare la password per il dispositivo prima dalle impostazioni del telefono Autenticazione non riuscita Errore di autenticazione %s + Modifica la lunghezza della password + Lunghezza password predefinita \ No newline at end of file diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1aede4d9..25bfda9f 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -95,4 +95,6 @@ パスワードの長さ パスワード 大文字のアルファベット + パスワードの長さを変更する + デフォルトのパスワードの長さ \ No newline at end of file diff --git a/app/src/main/res/values-mr/strings.xml b/app/src/main/res/values-mr/strings.xml index 49219437..25501099 100644 --- a/app/src/main/res/values-mr/strings.xml +++ b/app/src/main/res/values-mr/strings.xml @@ -95,4 +95,6 @@ कृपया फोन सेटिंग्जमधून प्रथम तुमच्या डिव्हाइससाठी पासवर्ड सेट करा प्रमाणीकरण अयशस्वी प्रमाणीकरण त्रुटी %s + पासवर्डची लांबी बदला + डीफॉल्ट पासवर्ड लांबी \ No newline at end of file diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index a0d0b9f3..5cb27243 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -96,4 +96,6 @@ Por favor, digite a senha de confirmação Senha alterada com sucesso Erro de autenticação %s + Alterar tamanho da senha + Comprimento da senha padrão \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index ba431649..84f829ac 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -96,4 +96,6 @@ Пожалуйста, сначала установите пароль для вашего устройства в настройках телефона Ошибка проверки подлинности Ошибка аутентификации %s + Изменить длину пароля + Длина пароля по умолчанию \ No newline at end of file diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index d536d0f5..a56876e4 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -95,4 +95,6 @@ கடவுச்சொல் வெற்றிகரமாக மாற்றப்பட்டது இந்தச் சாதனத்தில் பயோமெட்ரிக் அம்சங்கள் எதுவும் இல்லை. பயோமெட்ரிக் அம்சங்கள் தற்போது கிடைக்கவில்லை. + கடவுச்சொல் நீளத்தை மாற்றவும் + இயல்புநிலை கடவுச்சொல் நீளம் \ No newline at end of file diff --git a/app/src/main/res/values-te/strings.xml b/app/src/main/res/values-te/strings.xml index 0d5542f2..516273a6 100644 --- a/app/src/main/res/values-te/strings.xml +++ b/app/src/main/res/values-te/strings.xml @@ -95,4 +95,6 @@ దయచేసి ముందుగా ఫోన్ సెట్టింగ్‌ల నుండి మీ పరికరానికి పాస్‌వర్డ్‌ని సెట్ చేయండి ప్రామాణీకరణ విఫలమైంది ప్రమాణీకరణ లోపం %s + పాస్వర్డ్ పొడవు మార్చండి + డిఫాల్ట్ పాస్‌వర్డ్ పొడవు \ No newline at end of file diff --git a/app/src/main/res/values-ur-rIN/strings.xml b/app/src/main/res/values-ur-rIN/strings.xml index dc3f6f2b..7bb9dfde 100644 --- a/app/src/main/res/values-ur-rIN/strings.xml +++ b/app/src/main/res/values-ur-rIN/strings.xml @@ -95,4 +95,6 @@ براہ کرم فون کی ترتیبات سے پہلے اپنے آلے کے لیے پاس ورڈ سیٹ کریں تصدیق میں ناکام رہے تصدیق کی خرابی %s + پاس ورڈ کی لمبائی تبدیل کریں۔ + پہلے سے طے شدہ پاس ورڈ کی لمبائی \ No newline at end of file diff --git a/app/src/main/res/values-ur-rPK/strings.xml b/app/src/main/res/values-ur-rPK/strings.xml index 26ecdf50..3ab81db2 100644 --- a/app/src/main/res/values-ur-rPK/strings.xml +++ b/app/src/main/res/values-ur-rPK/strings.xml @@ -95,4 +95,6 @@ براہ کرم فون کی ترتیبات سے پہلے اپنے آلے کے لیے پاس ورڈ سیٹ کریں تصدیق میں ناکام رہے تصدیق کی خرابی %s + پاس ورڈ کی لمبائی تبدیل کریں۔ + پہلے سے طے شدہ پاس ورڈ کی لمبائی \ No newline at end of file diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 20e952dc..9aaaeb99 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -95,4 +95,6 @@ بائیو میٹرک فیچرز فی الحال دستیاب نہیں ہیں۔ اپنے آلے پر بائیو میٹرک سیٹ اپ کریں۔ بائیو میٹرک کے ساتھ انلاک کریں + پاس ورڈ کی لمبائی تبدیل کریں۔ + پہلے سے طے شدہ پاس ورڈ کی لمبائی \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index a8ac3db6..c987c499 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -96,4 +96,6 @@ 请输入确认密码 密码修改成功 身份验证错误 %s + 更改密码长度 + 默认密码长度 \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d4f30189..5b893afd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -105,5 +105,7 @@ Please set password for your device first from phone settings Authentication Failed Authentication Error %s + Change password length + Default password length diff --git a/build.gradle.kts b/build.gradle.kts index be3559aa..6ee1d5fb 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -44,7 +44,7 @@ subprojects { targetExclude("$buildDir/**/*.kt") targetExclude("bin/**/*.kt") - val map = HashMap(); + val map = HashMap() ktlint("0.46.0").userData(map) // licenseHeaderFile rootProject.file('spotless/copyright.kt') } diff --git a/buildSrc/src/main/kotlin/Dependencies.kt b/buildSrc/src/main/kotlin/Dependencies.kt index 68f87d57..d5d24b37 100644 --- a/buildSrc/src/main/kotlin/Dependencies.kt +++ b/buildSrc/src/main/kotlin/Dependencies.kt @@ -16,8 +16,6 @@ object Deps { val runtimeCompose by lazy { "androidx.lifecycle:lifecycle-runtime-compose:${Versions.lifecycle}" } } - object ComposeAndroidTest { - - } + object ComposeAndroidTest } diff --git a/common/build.gradle.kts b/common/build.gradle.kts index f9a36523..8b2aa3f9 100644 --- a/common/build.gradle.kts +++ b/common/build.gradle.kts @@ -46,7 +46,6 @@ dependencies { api("androidx.documentfile:documentfile:1.0.1") api("androidx.room:room-runtime:${Versions.room}") - androidTestApi("androidx.test:rules:1.5.0") kapt("androidx.room:room-compiler:${Versions.room}") api("androidx.room:room-ktx:${Versions.room}") @@ -67,4 +66,8 @@ dependencies { api("androidx.datastore:datastore-preferences:1.0.0") + // Test + implementation("androidx.test.ext:junit-ktx:1.1.5") + androidTestApi("androidx.test:rules:1.5.0") + } diff --git a/common/src/androidTest/java/com/yogeshpaliyal/keypass/SharedPreferenceUtilsTest.kt b/common/src/androidTest/java/com/yogeshpaliyal/keypass/SharedPreferenceUtilsTest.kt new file mode 100644 index 00000000..34779548 --- /dev/null +++ b/common/src/androidTest/java/com/yogeshpaliyal/keypass/SharedPreferenceUtilsTest.kt @@ -0,0 +1,49 @@ +package com.yogeshpaliyal.keypass + +import android.content.Context +import androidx.datastore.preferences.core.edit +import androidx.test.core.app.ApplicationProvider +import androidx.test.ext.junit.runners.AndroidJUnit4 +import com.yogeshpaliyal.common.utils.dataStore +import com.yogeshpaliyal.common.utils.getKeyPassPasswordLength +import com.yogeshpaliyal.common.utils.setKeyPassPasswordLength +import kotlinx.coroutines.runBlocking +import org.junit.After +import org.junit.Assert.assertEquals +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(AndroidJUnit4::class) +class SharedPreferenceUtilsTest { + + private lateinit var context: Context + + @Before + fun setup() { + context = ApplicationProvider.getApplicationContext() + } + + @Test + fun getKeyPassPasswordLength_test() = runBlocking { + val result = context.getKeyPassPasswordLength() + assertEquals(null, result) + } + + @Test + fun setKeyPassPasswordLength_test() = runBlocking { + val expectedLength = 8f + context.setKeyPassPasswordLength(expectedLength) + val result = context.getKeyPassPasswordLength() + assertEquals(expectedLength, result) + } + + @After + fun clear() { + runBlocking { + context.dataStore.edit { preferences -> + preferences.clear() + } + } + } +} diff --git a/common/src/main/java/com/yogeshpaliyal/common/CommonMyApplication.kt b/common/src/main/java/com/yogeshpaliyal/common/CommonMyApplication.kt index c5d2833e..7b5bd29b 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/CommonMyApplication.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/CommonMyApplication.kt @@ -31,7 +31,7 @@ abstract class CommonMyApplication : Application(), Configuration.Provider { override fun getWorkManagerConfiguration(): Configuration { return Configuration.Builder() - .setMinimumLoggingLevel(android.util.Log.INFO) + .setMinimumLoggingLevel(Log.INFO) .setWorkerFactory(workerFactory) .build() } diff --git a/common/src/main/java/com/yogeshpaliyal/common/constants/AccountType.kt b/common/src/main/java/com/yogeshpaliyal/common/constants/AccountType.kt index 916ff281..571f4ebb 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/constants/AccountType.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/constants/AccountType.kt @@ -1,6 +1,6 @@ package com.yogeshpaliyal.common.constants -annotation class AccountType() { +annotation class AccountType { companion object { const val DEFAULT = 1 // used to store password and user information const val TOTP = 2 // used to store Time base - One time Password diff --git a/common/src/main/java/com/yogeshpaliyal/common/utils/FormatCalendar.kt b/common/src/main/java/com/yogeshpaliyal/common/utils/FormatCalendar.kt index 8c33c9d0..7b0f86bd 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/utils/FormatCalendar.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/utils/FormatCalendar.kt @@ -15,5 +15,5 @@ fun Long.formatCalendar(dateTimeFormat: String?): String? { val calendar: Calendar = Calendar.getInstance() calendar.timeInMillis = this val simpleDateFormat = SimpleDateFormat(dateTimeFormat, Locale.US) - return simpleDateFormat.format(calendar.getTime()) + return simpleDateFormat.format(calendar.time) } diff --git a/common/src/main/java/com/yogeshpaliyal/common/utils/PasswordGenerator.kt b/common/src/main/java/com/yogeshpaliyal/common/utils/PasswordGenerator.kt index ce39101f..607ffcdf 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/utils/PasswordGenerator.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/utils/PasswordGenerator.kt @@ -15,7 +15,7 @@ class PasswordGenerator( private val NUMBERS = 2 private val SYMBOLS = 3 - public fun generatePassword(): String { + fun generatePassword(): String { var password = "" val list = ArrayList() if (includeUpperCaseLetters) { 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 5c53a08e..b1e53980 100644 --- a/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt +++ b/common/src/main/java/com/yogeshpaliyal/common/utils/SharedPreferenceUtils.kt @@ -3,6 +3,7 @@ package com.yogeshpaliyal.common.utils import android.content.Context import androidx.datastore.preferences.core.booleanPreferencesKey import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.floatPreferencesKey import androidx.datastore.preferences.core.longPreferencesKey import androidx.datastore.preferences.core.stringPreferencesKey import androidx.datastore.preferences.preferencesDataStore @@ -53,6 +54,16 @@ suspend fun Context.setKeyPassPassword(password: String?) { } } +suspend fun Context.getKeyPassPasswordLength(): Float? { + return dataStore.data.first()[KEYPASS_PASSWORD_LENGTH] +} + +suspend fun Context.setKeyPassPasswordLength(length: Float) { + dataStore.edit { + it[KEYPASS_PASSWORD_LENGTH] = length + } +} + suspend fun Context.isKeyPresent(): Boolean { val sp = dataStore.data.first() return sp.contains(BACKUP_KEY) @@ -123,6 +134,7 @@ suspend fun Context?.getBackupTime(): Long { private val BACKUP_KEY = stringPreferencesKey("backup_key") private val BIOMETRIC_ENABLE = booleanPreferencesKey("biometric_enable") private val KEYPASS_PASSWORD = stringPreferencesKey("keypass_password") +private val KEYPASS_PASSWORD_LENGTH = floatPreferencesKey("keypass_password_length") private val BACKUP_DIRECTORY = stringPreferencesKey("backup_directory") private val BACKUP_DATE_TIME = longPreferencesKey("backup_date_time") private val AUTO_BACKUP = booleanPreferencesKey("auto_backup")