diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/AccountDeletedEvent.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/AccountDeletedEvent.kt new file mode 100644 index 0000000000000000000000000000000000000000..b1665174d84bf4b0aa0baa15ab7ee109957f95c2 --- /dev/null +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/AccountDeletedEvent.kt @@ -0,0 +1,5 @@ +package org.briarproject.briar.desktop.login + +import org.briarproject.bramble.api.event.Event + +class AccountDeletedEvent : Event() 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 475ffcb1ee1670b1482a14670ef5fc53fc1dddc1..3104a56e3a7aafb702d1ccf2ae6ef817e7b7d120 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginScreen.kt @@ -1,14 +1,16 @@ package org.briarproject.briar.desktop.login import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.width import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.material.AlertDialog -import androidx.compose.material.Button import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.OutlinedTextField import androidx.compose.material.Text +import androidx.compose.material.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester @@ -18,6 +20,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.LoginViewModel.State.COMPACTING import org.briarproject.briar.desktop.login.LoginViewModel.State.MIGRATING import org.briarproject.briar.desktop.login.LoginViewModel.State.SIGNED_OUT @@ -43,6 +46,7 @@ fun LoginScreen( viewModel.password.value, viewModel::setPassword, viewModel.passwordInvalidError.value, + viewModel::deleteAccount, viewModel::signIn ) } @@ -59,7 +63,7 @@ fun LoginScreen( title = { Text(i18n("startup.error.decryption.title")) }, text = { Text(i18n("startup.error.decryption.text")) }, confirmButton = { - Button(onClick = viewModel::closeDecryptionFailedDialog) { + TextButton(onClick = viewModel::closeDecryptionFailedDialog) { Text(i18n("ok")) } }, @@ -67,14 +71,17 @@ fun LoginScreen( } } +@OptIn(ExperimentalMaterialApi::class) @Composable fun LoginForm( password: String, setPassword: (String) -> Unit, passwordInvalidError: Boolean, + deleteAccount: () -> Unit, onEnter: () -> Unit, ) { val initialFocusRequester = remember { FocusRequester() } + val passwordForgotten = remember { mutableStateOf(false) } OutlinedTextField( value = password, @@ -89,6 +96,29 @@ fun LoginForm( modifier = Modifier.fillMaxWidth().focusRequester(initialFocusRequester), onEnter = onEnter ) + TextButton(onClick = { passwordForgotten.value = true }) { + Text(i18n("startup.password_forgotten.button")) + } + + if (passwordForgotten.value) { + val closeDialog = { passwordForgotten.value = false } + AlertDialog( + onDismissRequest = closeDialog, + title = { Text(i18n("startup.password_forgotten.title")) }, + text = { Text(i18n("startup.password_forgotten.text")) }, + confirmButton = { + TextButton(onClick = closeDialog) { + Text(i18n("cancel")) + } + }, + dismissButton = { + TextButton(onClick = { deleteAccount(); closeDialog() }) { + Text(i18n("delete")) + } + }, + modifier = Modifier.width(500.dp) + ) + } LaunchedEffect(Unit) { initialFocusRequester.requestFocus() diff --git a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewModel.kt b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewModel.kt index 5a189e6492885363cd7f7c79198a8d022d3c7e80..a7887c4281d5da9f73eb1e39fe2df033fa80622a 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewModel.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/login/LoginViewModel.kt @@ -29,7 +29,7 @@ constructor( private val accountManager: AccountManager, private val briarExecutors: BriarExecutors, private val lifecycleManager: LifecycleManager, - eventBus: EventBus, + private val eventBus: EventBus, db: TransactionManager, ) : EventListenerDbViewModel(briarExecutors, lifecycleManager, db, eventBus) { @@ -92,6 +92,11 @@ constructor( lifecycleManager.waitForStartup() } + fun deleteAccount() = briarExecutors.onIoThread { + accountManager.deleteAccount() + eventBus.broadcast(AccountDeletedEvent()) + } + fun signIn() { if (!buttonEnabled.value) return diff --git a/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt index 4ff0014735b09e26cdf12d17a07885a09e41672c..445e1a526a86395ff7e3b29a59414c9c9061e4e7 100644 --- a/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt +++ b/src/main/kotlin/org/briarproject/briar/desktop/ui/BriarUi.kt @@ -17,6 +17,7 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager import org.briarproject.bramble.api.lifecycle.LifecycleManager.LifecycleState.RUNNING import org.briarproject.bramble.api.lifecycle.event.LifecycleEvent import org.briarproject.briar.desktop.DesktopFeatureFlags +import org.briarproject.briar.desktop.login.AccountDeletedEvent import org.briarproject.briar.desktop.login.LoginScreen import org.briarproject.briar.desktop.login.RegistrationScreen import org.briarproject.briar.desktop.settings.SettingsViewModel @@ -72,6 +73,8 @@ constructor( override fun eventOccurred(e: Event?) { if (e is LifecycleEvent && e.lifecycleState == RUNNING) { screenState = MAIN + } else if (e is AccountDeletedEvent) { + screenState = REGISTRATION } } diff --git a/src/main/resources/strings/BriarDesktop.properties b/src/main/resources/strings/BriarDesktop.properties index ff3130109789bbfd691976939c20c666fcee5509..c43b7a2d57678d0c6cf4029f66dea15c4751807a 100644 --- a/src/main/resources/strings/BriarDesktop.properties +++ b/src/main/resources/strings/BriarDesktop.properties @@ -134,6 +134,9 @@ startup.error.passwords_not_match=Passwords do not match startup.error.password_wrong=Wrong password, try again startup.error.decryption.title=Cannot Check Password startup.error.decryption.text=Briar cannot check your password. Please try rebooting your device to solve this problem. +startup.password_forgotten.button=I have forgotten my password +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.database.creating=Creating Account... startup.database.opening=Decrypting Database... startup.database.migrating=Upgrading Database...