From 29383d10e45151a02102a91ff40279c81d8f39df Mon Sep 17 00:00:00 2001 From: ialokim <ialokim@mailbox.org> Date: Mon, 10 Jan 2022 16:02:19 +0100 Subject: [PATCH] add visual indication of password strength --- .../briar/desktop/login/RegistrationScreen.kt | 11 ++++ .../briar/desktop/login/StrengthMeter.kt | 51 +++++++++++++++++++ .../briar/desktop/utils/PreviewUtils.kt | 10 ++++ 3 files changed, 72 insertions(+) create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt index 2666f779f8..50b275f76f 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt @@ -1,6 +1,8 @@ package org.briarproject.briar.desktop.login +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.InitialFocusState.AFTER_FIRST_FOCUSSED import androidx.compose.material.InitialFocusState.AFTER_FOCUS_LOST_ONCE @@ -9,6 +11,7 @@ import androidx.compose.material.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment.Companion.Center import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusRequester @@ -19,6 +22,7 @@ import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.text.input.PasswordVisualTransformation +import androidx.compose.ui.unit.dp import org.briarproject.briar.desktop.login.RegistrationViewModel.State.CREATED import org.briarproject.briar.desktop.login.RegistrationViewModel.State.CREATING import org.briarproject.briar.desktop.login.RegistrationViewModel.State.INSERT_NICKNAME @@ -113,6 +117,13 @@ fun PasswordForm( val initialFocusRequester = remember { FocusRequester() } val focusManager = LocalFocusManager.current + Box( + modifier = Modifier.fillMaxWidth().requiredHeight(24.dp), + contentAlignment = Center + ) { + if (password.isNotEmpty()) + StrengthMeter(passwordStrength, Modifier.fillMaxWidth()) + } OutlinedTextField( value = password, onValueChange = setPassword, diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt new file mode 100644 index 0000000000..0207c290cf --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt @@ -0,0 +1,51 @@ +package org.briarproject.briar.desktop.login + +import androidx.compose.animation.animateColorAsState +import androidx.compose.animation.core.animateFloatAsState +import androidx.compose.material.LinearProgressIndicator +import androidx.compose.material.ProgressIndicatorDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG +import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK +import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG +import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK +import org.briarproject.briar.desktop.utils.PreviewUtils.preview + +val RED = Color(255, 0, 0) +val ORANGE = Color(255, 160, 0) +val YELLOW = Color(255, 255, 0) +val LIME = Color(180, 255, 0) +val GREEN = Color(0, 255, 0) + +fun main() = preview( + "strength" to 0f +) { + StrengthMeter(getFloatParameter("strength")) +} + +@Composable +fun StrengthMeter( + strength: Float, + modifier: Modifier = Modifier +) { + val color = when { + strength < WEAK -> RED + strength < QUITE_WEAK -> ORANGE + strength < QUITE_STRONG -> YELLOW + strength < STRONG -> GREEN + else -> LIME + } + val animatedProgress by animateFloatAsState( + targetValue = strength, + animationSpec = ProgressIndicatorDefaults.ProgressAnimationSpec + ) + val animatedColor by animateColorAsState(color) + LinearProgressIndicator( + progress = animatedProgress, + color = animatedColor, + modifier = modifier + ) +} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt b/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt index 967b0e4bb6..032a405e1a 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt @@ -64,6 +64,10 @@ object PreviewUtils { fun setLongParameter(name: String, value: Long) = setDatatype(name, value) + fun getFloatParameter(name: String) = getDatatype<Float>(name) + + fun setFloatParameter(name: String, value: Float) = setDatatype(name, value) + fun getRandomId() = random.nextBytes(UniqueId.LENGTH) @Composable @@ -110,6 +114,11 @@ object PreviewUtils { BasicTextField(value.value.toString(), { value.value = it.toLong() }) } + @Composable + private fun PreviewScope.addFloatParameter(name: String, initial: Float) = addParameter(name, initial) { value -> + BasicTextField(value.value.toString(), { value.value = it.toFloat() }) + } + /** * Open an interactive preview of the composable specified by [content]. * All [parameters] passed to this function will be changeable on the fly. @@ -132,6 +141,7 @@ object PreviewUtils { is Boolean -> scope.addBooleanParameter(name, initial) is Int -> scope.addIntParameter(name, initial) is Long -> scope.addLongParameter(name, initial) + is Float -> scope.addFloatParameter(name, initial) else -> throw IllegalArgumentException("Type ${initial::class.simpleName} is not supported for previewing.") } } -- GitLab