Skip to content
Snippets Groups Projects

Handle errors in AddContactDialog

Merged Sebastian requested to merge 81-version1 into main
7 files
+ 267
41
Compare changes
  • Side-by-side
  • Inline

Files

@@ -24,65 +24,126 @@ import androidx.compose.foundation.layout.Row
@@ -24,65 +24,126 @@ import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.width
 
import androidx.compose.foundation.layout.widthIn
import androidx.compose.material.AlertDialog
import androidx.compose.material.AlertDialog
import androidx.compose.material.Button
import androidx.compose.material.Button
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ExperimentalMaterialApi
 
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TextButton
import androidx.compose.material.TextField
import androidx.compose.material.TextField
 
import androidx.compose.material.icons.Icons
 
import androidx.compose.material.icons.filled.Error
 
import androidx.compose.material.icons.filled.Warning
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.unit.sp
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.AddContactError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.AliasInvalidError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.ContactAlreadyExistsError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.LinkInvalidError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.OwnLinkError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.PendingAlreadyExistsError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.PublicKeyInvalidError
 
import org.briarproject.briar.desktop.contact.add.remote.AddContactViewModel.RemoteInvalidError
 
import org.briarproject.briar.desktop.dialogs.DialogType.ERROR
 
import org.briarproject.briar.desktop.dialogs.DialogType.WARNING
 
import org.briarproject.briar.desktop.theme.Orange500
 
import org.briarproject.briar.desktop.theme.Red500
 
import org.briarproject.briar.desktop.ui.Constants.DIALOG_WIDTH
 
import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18n
 
import org.briarproject.briar.desktop.utils.InternationalizationUtils.i18nF
 
import org.briarproject.briar.desktop.utils.PreviewUtils
import org.briarproject.briar.desktop.utils.PreviewUtils.preview
import org.briarproject.briar.desktop.utils.PreviewUtils.preview
import org.briarproject.briar.desktop.viewmodel.viewModel
import org.briarproject.briar.desktop.viewmodel.viewModel
 
const val link = "briar://ady23gvb2r76afe5zhxh5kvnh4b22zrcnxibn63tfknrdcwrw7zrs"
 
fun main() = preview(
fun main() = preview(
"visible" to true,
"visible" to true,
"remote link" to "",
"remote link" to "",
"local link" to "briar://ady23gvb2r76afe5zhxh5kvnh4b22zrcnxibn63tfknrdcwrw7zrs",
"local link" to link,
"alias" to "Alice",
"alias" to "Alice",
) {
"error visible" to false,
if (getBooleanParameter("visible")) {
"error type" to PreviewUtils.DropDownValues(
AddContactDialog(
0,
onClose = { setBooleanParameter("visible", false) },
listOf(
remoteHandshakeLink = getStringParameter("remote link"),
OwnLinkError::class.simpleName!!,
setRemoteHandshakeLink = { link -> setStringParameter("remote link", link) },
RemoteInvalidError::class.simpleName!!,
alias = getStringParameter("alias"),
AliasInvalidError::class.simpleName!!,
setAddContactAlias = { alias -> setStringParameter("alias", alias) },
LinkInvalidError::class.simpleName!!,
handshakeLink = getStringParameter("local link"),
PublicKeyInvalidError::class.simpleName!!,
onSubmitAddContactDialog = {}
ContactAlreadyExistsError::class.simpleName!!,
 
PendingAlreadyExistsError::class.simpleName!!,
)
)
}
),
 
) {
 
val localLink = getStringParameter("local link")
 
AddContactDialog(
 
onClose = { setBooleanParameter("visible", false) },
 
visible = getBooleanParameter("visible"),
 
remoteHandshakeLink = getStringParameter("remote link"),
 
setRemoteHandshakeLink = { link -> setStringParameter("remote link", link) },
 
alias = getStringParameter("alias"),
 
setAddContactAlias = { alias -> setStringParameter("alias", alias) },
 
handshakeLink = localLink,
 
onSubmitAddContactDialog = { setBooleanParameter("error visible", true) },
 
error = if (getBooleanParameter("error visible")) mapErrors(getStringParameter("error type")) else null,
 
onErrorDialogDismissed = { setBooleanParameter("error visible", false) },
 
)
 
}
 
 
private fun PreviewUtils.PreviewScope.mapErrors(name: String?): AddContactError? = when (name) {
 
OwnLinkError::class.simpleName!! -> OwnLinkError(link)
 
RemoteInvalidError::class.simpleName!! -> RemoteInvalidError(link)
 
AliasInvalidError::class.simpleName!! -> AliasInvalidError(link, "")
 
LinkInvalidError::class.simpleName!! -> LinkInvalidError(link)
 
PublicKeyInvalidError::class.simpleName!! -> PublicKeyInvalidError(link)
 
ContactAlreadyExistsError::class.simpleName!! -> ContactAlreadyExistsError(
 
link, "David", getStringParameter("alias")
 
)
 
PendingAlreadyExistsError::class.simpleName!! -> PendingAlreadyExistsError(
 
link, "Frank", getStringParameter("alias")
 
)
 
else -> null
}
}
@Composable
@Composable
fun AddContactDialog(
fun AddContactDialog(
onClose: () -> Unit,
viewModel: AddContactViewModel = viewModel(),
viewModel: AddContactViewModel = viewModel(),
) = AddContactDialog(
) = AddContactDialog(
onClose = onClose,
viewModel::dismissDialog,
 
viewModel.visible.value,
viewModel.remoteHandshakeLink.value,
viewModel.remoteHandshakeLink.value,
viewModel::setRemoteHandshakeLink,
viewModel::setRemoteHandshakeLink,
viewModel.alias.value,
viewModel.alias.value,
viewModel::setAddContactAlias,
viewModel::setAddContactAlias,
viewModel.handshakeLink.value,
viewModel.handshakeLink.value,
viewModel::onSubmitAddContactDialog,
viewModel::onSubmitAddContactDialog,
 
viewModel.error.value,
 
viewModel::clearError,
)
)
@OptIn(ExperimentalMaterialApi::class)
@OptIn(ExperimentalMaterialApi::class)
@Composable
@Composable
fun AddContactDialog(
fun AddContactDialog(
onClose: () -> Unit,
onClose: () -> Unit,
 
visible: Boolean,
remoteHandshakeLink: String,
remoteHandshakeLink: String,
setRemoteHandshakeLink: (String) -> Unit,
setRemoteHandshakeLink: (String) -> Unit,
alias: String,
alias: String,
setAddContactAlias: (String) -> Unit,
setAddContactAlias: (String) -> Unit,
handshakeLink: String,
handshakeLink: String,
onSubmitAddContactDialog: () -> Unit,
onSubmitAddContactDialog: () -> Unit,
 
error: AddContactError?,
 
onErrorDialogDismissed: () -> Unit,
) {
) {
 
if (!visible) {
 
return
 
}
AlertDialog(
AlertDialog(
onDismissRequest = onClose,
onDismissRequest = onClose,
text = {
text = {
@@ -130,7 +191,11 @@ fun AddContactDialog(
@@ -130,7 +191,11 @@ fun AddContactDialog(
}
}
},
},
confirmButton = {
confirmButton = {
Button(onClick = { onSubmitAddContactDialog(); onClose() }) {
Button(
 
onClick = {
 
onSubmitAddContactDialog()
 
}
 
) {
Text("Add")
Text("Add")
}
}
},
},
@@ -142,4 +207,55 @@ fun AddContactDialog(
@@ -142,4 +207,55 @@ fun AddContactDialog(
}
}
},
},
)
)
 
if (error != null) {
 
val (type, title, message) = errorMessage(error)
 
val (icon, color) = when (type) {
 
WARNING -> Icons.Filled.Warning to Orange500
 
ERROR -> Icons.Filled.Error to Red500
 
}
 
AlertDialog(
 
onDismissRequest = onErrorDialogDismissed,
 
confirmButton = {
 
TextButton(onErrorDialogDismissed) {
 
Text(i18n("ok"))
 
}
 
},
 
modifier = Modifier.widthIn(min = DIALOG_WIDTH),
 
title = {
 
Row(
 
verticalAlignment = Alignment.CenterVertically,
 
horizontalArrangement = Arrangement.spacedBy(8.dp)
 
) {
 
Icon(
 
imageVector = icon,
 
contentDescription = title,
 
tint = color
 
)
 
Text(title)
 
}
 
},
 
text = { Text(message) }
 
)
 
}
 
}
 
 
fun errorMessage(error: AddContactError) = when (error) {
 
is OwnLinkError -> Triple(ERROR, i18n("error"), i18n("introduction.error.own_link"))
 
is RemoteInvalidError -> Triple(ERROR, i18n("error"), i18n("introduction.error.remote_invalid"))
 
is AliasInvalidError -> Triple(ERROR, i18n("error"), i18n("introduction.error.alias_invalid"))
 
is LinkInvalidError -> Triple(ERROR, i18n("error"), i18nF("introduction.error.link_invalid", error.link))
 
is PublicKeyInvalidError -> Triple(
 
ERROR, i18n("error"),
 
i18nF("introduction.error.public_key_invalid", error.link)
 
)
 
is ContactAlreadyExistsError -> {
 
val intro = i18nF("introduction.error.contact_already_exists", error.existingName)
 
var explanation = i18nF("introduction.error.duplicate_contact_explainer", error.existingName, error.alias)
 
Triple(WARNING, i18n("introduction.error.adding_failed"), (intro + "\n\n" + explanation))
 
}
 
is PendingAlreadyExistsError -> {
 
val intro = i18nF("introduction.error.pending_contact_already_exists", error.existingAlias)
 
var explanation = i18nF("introduction.error.duplicate_contact_explainer", error.existingAlias, error.alias)
 
Triple(WARNING, i18n("introduction.error.adding_failed"), (intro + "\n\n" + explanation))
 
}
}
}
Loading