From b8a653a407a1f483d9d3b59e583f6d60a021ecf8 Mon Sep 17 00:00:00 2001 From: ialokim <ialokim@mailbox.org> Date: Fri, 14 Jan 2022 18:13:51 +0100 Subject: [PATCH] address review comments --- .../compose/material/OutlinedTextFieldExt.kt | 3 +- .../briar/desktop/login/ErrorScreen.kt | 13 ++--- ...rrorViewHolder.kt => ErrorSubViewModel.kt} | 6 +-- .../briar/desktop/login/FormScaffold.kt | 39 ++++++++++++++ .../briar/desktop/login/LoadingView.kt | 23 +++++++++ .../briar/desktop/login/LoginScreen.kt | 21 ++++---- ...oginViewHolder.kt => LoginSubViewModel.kt} | 14 ++--- .../briar/desktop/login/RegistrationScreen.kt | 15 ++---- ...wHolder.kt => RegistrationSubViewModel.kt} | 14 ++--- .../briar/desktop/login/StartupScreen.kt | 51 ++----------------- .../briar/desktop/login/StartupViewModel.kt | 31 +++++------ .../briar/desktop/login/StrengthMeter.kt | 3 +- .../briar/desktop/settings/SettingsScreen.kt | 1 - .../briar/desktop/ui/Constants.kt | 1 + .../briar/desktop/utils/PreviewUtils.kt | 14 +++++ .../resources/strings/BriarDesktop.properties | 2 +- 16 files changed, 140 insertions(+), 111 deletions(-) rename src/main/kotlin/org/briarproject/briar/desktop/login/{ErrorViewHolder.kt => ErrorSubViewModel.kt} (59%) create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/login/FormScaffold.kt create mode 100644 src/main/kotlin/org/briarproject/briar/desktop/login/LoadingView.kt rename src/main/kotlin/org/briarproject/briar/desktop/login/{LoginViewHolder.kt => LoginSubViewModel.kt} (87%) rename src/main/kotlin/org/briarproject/briar/desktop/login/{RegistrationViewHolder.kt => RegistrationSubViewModel.kt} (87%) diff --git a/src/main/kotlin/androidx/compose/material/OutlinedTextFieldExt.kt b/src/main/kotlin/androidx/compose/material/OutlinedTextFieldExt.kt index 9f4c7373ee..e2b6fce9c9 100644 --- a/src/main/kotlin/androidx/compose/material/OutlinedTextFieldExt.kt +++ b/src/main/kotlin/androidx/compose/material/OutlinedTextFieldExt.kt @@ -108,7 +108,8 @@ fun OutlinedTextField( colors = colors ) val message = if (showError && errorMessage != null) errorMessage else helperMessage ?: "" - val color = if (showError) MaterialTheme.colors.error else LocalTextStyle.current.color.copy(alpha = ContentAlpha.medium) + val color = + if (showError) MaterialTheme.colors.error else LocalTextStyle.current.color.copy(alpha = ContentAlpha.medium) Text( text = message, style = TextStyle( diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorScreen.kt index 3744c8608d..00bfb43fa6 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorScreen.kt @@ -33,14 +33,15 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.DB_ER import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SERVICE_ERROR import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS import org.briarproject.briar.desktop.theme.Red500 +import org.briarproject.briar.desktop.ui.Constants.STARTUP_FIELDS_WIDTH import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n import org.briarproject.briar.desktop.utils.PreviewUtils.preview fun main() = preview { - var error: ErrorViewHolder.Error by remember { mutableStateOf(RegistrationViewHolder.RegistrationError) } + var error: ErrorSubViewModel.Error by remember { mutableStateOf(RegistrationSubViewModel.RegistrationError) } Row(horizontalArrangement = spacedBy(8.dp)) { - Button(onClick = { error = RegistrationViewHolder.RegistrationError }) { + Button(onClick = { error = RegistrationSubViewModel.RegistrationError }) { Text("Registration") } for (e in StartResult.values().filterNot { it in listOf(SUCCESS, ALREADY_RUNNING) }) { @@ -54,12 +55,12 @@ fun main() = preview { } @Composable -fun ErrorScreen(viewHolder: ErrorViewHolder) = +fun ErrorScreen(viewHolder: ErrorSubViewModel) = ErrorScreen(viewHolder.error, viewHolder.onBackButton) @Composable fun ErrorScreen( - error: ErrorViewHolder.Error, + error: ErrorSubViewModel.Error, onBackButton: () -> Unit, ) = Surface { IconButton(onClick = onBackButton) { @@ -81,7 +82,7 @@ fun ErrorScreen( Text(i18n("sorry"), style = MaterialTheme.typography.h5) val text = when (error) { - is RegistrationViewHolder.RegistrationError -> i18n("startup.failed.registration") + is RegistrationSubViewModel.RegistrationError -> i18n("startup.failed.registration") is StartupViewModel.StartingError -> { when (error.error) { CLOCK_ERROR -> i18n("startup.failed.clock_error") @@ -96,7 +97,7 @@ fun ErrorScreen( Text( text = text, style = MaterialTheme.typography.body1, - modifier = Modifier.widthIn(max = 400.dp) + modifier = Modifier.widthIn(max = STARTUP_FIELDS_WIDTH) ) } } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorViewHolder.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorSubViewModel.kt similarity index 59% rename from src/main/kotlin/org/briarproject/briar/desktop/login/ErrorViewHolder.kt rename to src/main/kotlin/org/briarproject/briar/desktop/login/ErrorSubViewModel.kt index 8d540501ab..498efb6e38 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorViewHolder.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/ErrorSubViewModel.kt @@ -1,11 +1,9 @@ package org.briarproject.briar.desktop.login -import org.briarproject.bramble.api.lifecycle.LifecycleManager - -class ErrorViewHolder( +class ErrorSubViewModel( private val viewModel: StartupViewModel, val error: Error, val onBackButton: () -> Unit, -) : StartupViewModel.ViewHolder { +) : StartupViewModel.SubViewModel { sealed interface Error } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/FormScaffold.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/FormScaffold.kt new file mode 100644 index 0000000000..95e8e4e664 --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/FormScaffold.kt @@ -0,0 +1,39 @@ +package org.briarproject.briar.desktop.login + +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.requiredWidth +import androidx.compose.foundation.layout.requiredWidthIn +import androidx.compose.material.Button +import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import org.briarproject.briar.desktop.ui.Constants.STARTUP_FIELDS_WIDTH +import java.util.Locale + +@Composable +fun FormScaffold( + explanationText: String?, + buttonText: String, + buttonClick: () -> Unit, + buttonEnabled: Boolean, + content: @Composable () -> Unit, +) = Column( + modifier = Modifier.requiredWidthIn(max = STARTUP_FIELDS_WIDTH), + horizontalAlignment = Alignment.CenterHorizontally +) { + if (explanationText != null) { + Spacer(Modifier.weight(0.5f)) + Text(explanationText, style = MaterialTheme.typography.body2, modifier = Modifier.requiredWidth(STARTUP_FIELDS_WIDTH)) + Spacer(Modifier.weight(0.5f)) + } else Spacer(Modifier.weight(1.0f)) + content() + Spacer(Modifier.weight(1.0f)) + Button(onClick = buttonClick, enabled = buttonEnabled, modifier = Modifier.fillMaxWidth()) { + Text(buttonText.uppercase(Locale.getDefault()), color = Color.Black) + } +} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/LoadingView.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/LoadingView.kt new file mode 100644 index 0000000000..a8cf0dc22f --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/LoadingView.kt @@ -0,0 +1,23 @@ +package org.briarproject.briar.desktop.login + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.foundation.layout.padding +import androidx.compose.material.CircularProgressIndicator +import androidx.compose.material.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp + +@Composable +fun LoadingView(text: String) = + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier.fillMaxHeight() + ) { + CircularProgressIndicator(Modifier.padding(16.dp)) + Text(text) + } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt index 008ffbe444..5a44006402 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt @@ -15,23 +15,21 @@ import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color -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.LoginViewHolder.State.COMPACTING -import org.briarproject.briar.desktop.login.LoginViewHolder.State.MIGRATING -import org.briarproject.briar.desktop.login.LoginViewHolder.State.SIGNED_OUT -import org.briarproject.briar.desktop.login.LoginViewHolder.State.STARTED -import org.briarproject.briar.desktop.login.LoginViewHolder.State.STARTING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.COMPACTING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.MIGRATING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.SIGNED_OUT +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.STARTED +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.STARTING import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @OptIn(ExperimentalMaterialApi::class) @Composable fun LoginScreen( - viewHolder: LoginViewHolder, + viewHolder: LoginSubViewModel, ) = StartupScreenScaffold(i18n("startup.title.login")) { when (viewHolder.state.value) { SIGNED_OUT -> @@ -56,8 +54,10 @@ fun LoginScreen( } if (viewHolder.decryptionFailedError.value) { - // todo: is this actually needed on Desktop? - // todo: use ErrorScreen to display this instead? + // todo: this should never be triggered, + // since we don't use any keyStrengthener for now + // when adding this, we could think about showing + // a proper error screen instead AlertDialog( onDismissRequest = viewHolder::closeDecryptionFailedDialog, title = { Text(i18n("startup.error.decryption.title")) }, @@ -90,7 +90,6 @@ fun LoginForm( singleLine = true, isError = passwordInvalidError, errorMessage = i18n("startup.error.password_wrong"), - textStyle = TextStyle(color = Color.White), visualTransformation = PasswordVisualTransformation(), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Next), modifier = Modifier.fillMaxWidth().focusRequester(initialFocusRequester), diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewHolder.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginSubViewModel.kt similarity index 87% rename from src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewHolder.kt rename to src/main/kotlin/org/briarproject/briar/desktop/login/LoginSubViewModel.kt index 8ad23db1f6..74b96432d7 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewHolder.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginSubViewModel.kt @@ -7,20 +7,20 @@ import org.briarproject.bramble.api.crypto.DecryptionException import org.briarproject.bramble.api.crypto.DecryptionResult.INVALID_PASSWORD import org.briarproject.bramble.api.crypto.DecryptionResult.KEY_STRENGTHENER_ERROR import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState -import org.briarproject.briar.desktop.login.LoginViewHolder.State.COMPACTING -import org.briarproject.briar.desktop.login.LoginViewHolder.State.MIGRATING -import org.briarproject.briar.desktop.login.LoginViewHolder.State.SIGNED_OUT -import org.briarproject.briar.desktop.login.LoginViewHolder.State.STARTED -import org.briarproject.briar.desktop.login.LoginViewHolder.State.STARTING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.COMPACTING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.MIGRATING +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.SIGNED_OUT +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.STARTED +import org.briarproject.briar.desktop.login.LoginSubViewModel.State.STARTING import org.briarproject.briar.desktop.threading.BriarExecutors import org.briarproject.briar.desktop.viewmodel.asState -class LoginViewHolder( +class LoginSubViewModel( private val viewModel: StartupViewModel, private val accountManager: AccountManager, private val briarExecutors: BriarExecutors, initialLifecycleState: LifecycleState, -) : StartupViewModel.ViewHolder { +) : StartupViewModel.SubViewModel { enum class State { SIGNED_OUT, STARTING, MIGRATING, COMPACTING, STARTED 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 b981d77398..2e534ec07a 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationScreen.kt @@ -16,22 +16,20 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalFocusManager -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.RegistrationViewHolder.State.CREATED -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.CREATING -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.INSERT_NICKNAME -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.INSERT_PASSWORD +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.CREATED +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.CREATING +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.INSERT_NICKNAME +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.INSERT_PASSWORD import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n @Composable fun RegistrationScreen( - viewHolder: RegistrationViewHolder, + viewHolder: RegistrationSubViewModel, ) = StartupScreenScaffold( title = i18n("startup.title.registration"), showBackButton = viewHolder.showBackButton.value, @@ -91,7 +89,6 @@ fun NicknameForm( singleLine = true, isError = nicknameTooLongError, errorMessage = i18n("startup.error.name_too_long"), - textStyle = TextStyle(color = Color.White), keyboardOptions = KeyboardOptions(imeAction = ImeAction.Next), modifier = Modifier.fillMaxWidth().focusRequester(initialFocusRequester), onEnter = onEnter @@ -131,7 +128,6 @@ fun PasswordForm( isError = passwordTooWeakError, showErrorWhen = AFTER_FOCUS_LOST_ONCE, errorMessage = i18n("startup.error.password_too_weak"), - textStyle = TextStyle(color = Color.White), visualTransformation = PasswordVisualTransformation(), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Next), modifier = Modifier.fillMaxWidth().focusRequester(initialFocusRequester), @@ -145,7 +141,6 @@ fun PasswordForm( isError = passwordsDontMatchError, showErrorWhen = AFTER_FIRST_FOCUSSED, errorMessage = i18n("startup.error.passwords_not_match"), - textStyle = TextStyle(color = Color.White), visualTransformation = PasswordVisualTransformation(), keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Password, imeAction = ImeAction.Done), modifier = Modifier.fillMaxWidth(), diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationViewHolder.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationSubViewModel.kt similarity index 87% rename from src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationViewHolder.kt rename to src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationSubViewModel.kt index ca2a309376..990c2ca67f 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationViewHolder.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/RegistrationSubViewModel.kt @@ -7,24 +7,24 @@ import org.briarproject.bramble.api.account.AccountManager import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK import org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.CREATING -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.INSERT_NICKNAME -import org.briarproject.briar.desktop.login.RegistrationViewHolder.State.INSERT_PASSWORD +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.CREATING +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.INSERT_NICKNAME +import org.briarproject.briar.desktop.login.RegistrationSubViewModel.State.INSERT_PASSWORD import org.briarproject.briar.desktop.threading.BriarExecutors import org.briarproject.briar.desktop.viewmodel.asState -class RegistrationViewHolder( +class RegistrationSubViewModel( private val viewModel: StartupViewModel, private val accountManager: AccountManager, private val briarExecutors: BriarExecutors, private val passwordStrengthEstimator: PasswordStrengthEstimator, -) : StartupViewModel.ViewHolder { +) : StartupViewModel.SubViewModel { companion object { private val LOG = KotlinLogging.logger {} } - object RegistrationError : ErrorViewHolder.Error + object RegistrationError : ErrorSubViewModel.Error enum class State { INSERT_NICKNAME, INSERT_PASSWORD, CREATING, CREATED @@ -59,7 +59,7 @@ class RegistrationViewHolder( val buttonEnabled = derivedStateOf { when (_state.value) { INSERT_NICKNAME -> - nickname.value.isNotEmpty() && !nicknameTooLongError.value + nickname.value.isNotBlank() && !nicknameTooLongError.value INSERT_PASSWORD -> password.value.isNotEmpty() && passwordConfirmation.value.isNotEmpty() && !passwordTooWeakError.value && !passwordMatchError.value diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/StartupScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/StartupScreen.kt index 8dead60266..24a9d8a05f 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/StartupScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/StartupScreen.kt @@ -3,16 +3,9 @@ package org.briarproject.briar.desktop.login import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredWidth -import androidx.compose.foundation.layout.requiredWidthIn import androidx.compose.foundation.layout.width -import androidx.compose.material.Button -import androidx.compose.material.CircularProgressIndicator import androidx.compose.material.Icon import androidx.compose.material.IconButton import androidx.compose.material.MaterialTheme @@ -24,21 +17,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment.Companion.CenterHorizontally import androidx.compose.ui.Alignment.Companion.CenterVertically import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import org.briarproject.briar.desktop.ui.BriarLogo import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n import org.briarproject.briar.desktop.viewmodel.viewModel -import java.util.Locale @Composable fun StartupScreen( viewModel: StartupViewModel = viewModel(), ) { - when (val holder = viewModel.mode.value) { - is LoginViewHolder -> LoginScreen(holder) - is RegistrationViewHolder -> RegistrationScreen(holder) - is ErrorViewHolder -> ErrorScreen(holder) + when (val holder = viewModel.currentSubViewModel.value) { + is LoginSubViewModel -> LoginScreen(holder) + is RegistrationSubViewModel -> RegistrationScreen(holder) + is ErrorSubViewModel -> ErrorScreen(holder) } } @@ -73,37 +64,3 @@ fun HeaderLine(title: String) = BriarLogo(Modifier.width(100.dp)) Text(title, style = MaterialTheme.typography.h4) } - -@Composable -fun LoadingView(text: String) = - Column( - horizontalAlignment = CenterHorizontally, - verticalArrangement = Arrangement.Center, - modifier = Modifier.fillMaxHeight() - ) { - CircularProgressIndicator(Modifier.padding(16.dp)) - Text(text) - } - -@Composable -fun FormScaffold( - explanationText: String?, - buttonText: String, - buttonClick: () -> Unit, - buttonEnabled: Boolean, - content: @Composable () -> Unit, -) = Column( - modifier = Modifier.requiredWidthIn(max = 400.dp), - horizontalAlignment = CenterHorizontally -) { - if (explanationText != null) { - Spacer(Modifier.weight(0.5f)) - Text(explanationText, style = MaterialTheme.typography.body2, modifier = Modifier.requiredWidth(400.dp)) - Spacer(Modifier.weight(0.5f)) - } else Spacer(Modifier.weight(1.0f)) - content() - Spacer(Modifier.weight(1.0f)) - Button(onClick = buttonClick, enabled = buttonEnabled, modifier = Modifier.fillMaxWidth()) { - Text(buttonText.uppercase(Locale.getDefault()), color = Color.Black) - } -} diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/StartupViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/StartupViewModel.kt index bf42613767..ef58597c77 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/StartupViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/StartupViewModel.kt @@ -32,45 +32,46 @@ constructor( private val LOG = KotlinLogging.logger {} } - sealed interface ViewHolder { + sealed interface SubViewModel { fun lifecycleStateChanged(s: LifecycleManager.LifecycleState) {} } - class StartingError(val error: LifecycleManager.StartResult): - ErrorViewHolder.Error + class StartingError(val error: LifecycleManager.StartResult) : + ErrorSubViewModel.Error - private val _mode = mutableStateOf(decideMode()) - val mode = _mode.asState() + private val _currentSubViewModel = mutableStateOf(decideSubViewModel()) + val currentSubViewModel = _currentSubViewModel.asState() - private fun decideMode() = + private fun decideSubViewModel() = if (accountManager.accountExists()) makeLogin() else makeRegistration() - private fun makeLogin() = LoginViewHolder( + private fun makeLogin() = LoginSubViewModel( this, accountManager, briarExecutors, lifecycleManager.lifecycleState ) fun showLogin() { - _mode.value = makeLogin() + _currentSubViewModel.value = makeLogin() } - private fun makeRegistration() = RegistrationViewHolder( + private fun makeRegistration() = RegistrationSubViewModel( this, accountManager, briarExecutors, passwordStrengthEstimator ) fun showRegistration() { - _mode.value = makeRegistration() + _currentSubViewModel.value = makeRegistration() } - private fun makeError(error: ErrorViewHolder.Error) = ErrorViewHolder( - this, error, onBackButton = { _mode.value = decideMode() } + private fun makeError(error: ErrorSubViewModel.Error) = ErrorSubViewModel( + this, error, onBackButton = { _currentSubViewModel.value = decideSubViewModel() } ) - fun showError(error: ErrorViewHolder.Error) { - _mode.value = makeError(error) + + fun showError(error: ErrorSubViewModel.Error) { + _currentSubViewModel.value = makeError(error) } override fun eventOccurred(e: Event) { - if (e is LifecycleEvent) _mode.value.lifecycleStateChanged(e.lifecycleState) + if (e is LifecycleEvent) _currentSubViewModel.value.lifecycleStateChanged(e.lifecycleState) } @IoExecutor diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt index 0207c290cf..9a834aad46 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/StrengthMeter.kt @@ -12,6 +12,7 @@ import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRON 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 import org.briarproject.briar.desktop.utils.PreviewUtils.preview val RED = Color(255, 0, 0) @@ -21,7 +22,7 @@ val LIME = Color(180, 255, 0) val GREEN = Color(0, 255, 0) fun main() = preview( - "strength" to 0f + "strength" to PreviewUtils.FloatSlider(0f, 0f, 1f) ) { StrengthMeter(getFloatParameter("strength")) } diff --git a/src/main/kotlin/org/briarproject/briar/desktop/settings/SettingsScreen.kt b/src/main/kotlin/org/briarproject/briar/desktop/settings/SettingsScreen.kt index 500fcc851a..d47c682fdb 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/settings/SettingsScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/settings/SettingsScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier -import org.briarproject.briar.desktop.viewmodel.viewModel @Composable fun SettingsScreen(viewModel: SettingsViewModel) { diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/Constants.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/Constants.kt index abd377d359..34edbf5e26 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/ui/Constants.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/Constants.kt @@ -5,5 +5,6 @@ import androidx.compose.ui.unit.dp object Constants { val HEADER_SIZE = 56.dp val COLUMN_WIDTH = 275.dp + val STARTUP_FIELDS_WIDTH = 400.dp val PARAGRAPH_WIDTH = 540.dp } 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 032a405e1a..5c0e6ef2d5 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/utils/PreviewUtils.kt @@ -8,9 +8,11 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.BasicTextField import androidx.compose.material.Icon import androidx.compose.material.MaterialTheme +import androidx.compose.material.Slider import androidx.compose.material.Surface import androidx.compose.material.Text import androidx.compose.material.icons.Icons @@ -119,6 +121,11 @@ object PreviewUtils { BasicTextField(value.value.toString(), { value.value = it.toFloat() }) } + @Composable + private fun PreviewScope.addFloatSliderParameter(name: String, initial: FloatSlider) = addParameter(name, initial.initial) { value -> + Slider(value.value, { value.value = it }, valueRange = initial.min..initial.max, modifier = Modifier.width(400.dp)) + } + /** * Open an interactive preview of the composable specified by [content]. * All [parameters] passed to this function will be changeable on the fly. @@ -142,6 +149,7 @@ object PreviewUtils { is Int -> scope.addIntParameter(name, initial) is Long -> scope.addLongParameter(name, initial) is Float -> scope.addFloatParameter(name, initial) + is FloatSlider -> scope.addFloatSliderParameter(name, initial) else -> throw IllegalArgumentException("Type ${initial::class.simpleName} is not supported for previewing.") } } @@ -157,4 +165,10 @@ object PreviewUtils { } } } + + data class FloatSlider( + val initial: Float, + val min: Float, + val max: Float, + ) } diff --git a/src/main/resources/strings/BriarDesktop.properties b/src/main/resources/strings/BriarDesktop.properties index 4f6b716a71..6c35408dc9 100644 --- a/src/main/resources/strings/BriarDesktop.properties +++ b/src/main/resources/strings/BriarDesktop.properties @@ -141,7 +141,7 @@ startup.password_forgotten.title=Lost Password startup.password_forgotten.text=Your Briar account is stored encrypted on your device, not in the cloud, so we can't reset your password. Would you like to delete your account and start again?\n\nCaution: Your identities, contacts and messages will be permanently lost. startup.failed.registration=Briar was unable to create your account.\n\nPlease upgrade to the latest version and try again. startup.failed.clock_error=Briar was unable to start because your device's clock is wrong.\n\nPlease set your device's clock to the right time and try again. -startup.failed.db_error=Briar was unable to open the database containing your account, your contacts and your messages.\n\nPlease upgrade to the latest version of the app and try again, or set up a new account by choosing 'I have forgotten my password' at the password prompt. +startup.failed.db_error=Briar was unable to open the database containing your account, your contacts and your messages.\n\nPlease check if Briar is already running on this device. Otherwise, upgrade to the latest version of the app and try again, or set up a new account by choosing 'I have forgotten my password' at the password prompt. startup.failed.data_too_old_error=Your account was created with an old version of this app and cannot be opened with this version.\n\nYou must either reinstall the old version or set up a new account by choosing 'I have forgotten my password' at the password prompt. startup.failed.data_too_new_error=Your account was created with a newer version of this app and cannot be opened with this version.\n\nPlease upgrade to the latest version and try again. startup.failed.service_error=Briar was unable to start a required component.\n\nPlease upgrade to the latest version of the app and try again. -- GitLab