From b263d7e54712616d182ee119714b366aa3168073 Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Tue, 4 Oct 2022 19:25:53 +0300 Subject: [PATCH] android: Connection info (#1169) * android: Connection info * UI changes * Icon in text field * Alias text field * Revert "Alias text field" This reverts commit 2ac694db4d79ab925703870a4ae08e303c3a7842. * Padding * Layout changes * Bigger delay * UI changes * UI changes --- .../java/chat/simplex/app/model/ChatModel.kt | 17 +- .../java/chat/simplex/app/model/SimpleXAPI.kt | 15 ++ .../simplex/app/views/chat/ChatInfoView.kt | 22 ++- .../app/views/chatlist/ChatListNavLinkView.kt | 24 ++- .../views/chatlist/ContactConnectionView.kt | 8 +- .../views/helpers/DefaultBasicTextField.kt | 4 +- .../simplex/app/views/helpers/ModalView.kt | 2 +- .../app/views/newchat/AddContactView.kt | 20 ++- .../newchat/ContactConnectionInfoView.kt | 163 ++++++++++++++++++ .../app/views/newchat/CreateLinkView.kt | 2 +- .../app/src/main/res/values-de/strings.xml | 4 + .../app/src/main/res/values-ru/strings.xml | 4 + .../app/src/main/res/values/strings.xml | 6 +- 13 files changed, 266 insertions(+), 25 deletions(-) create mode 100644 apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt index f4e3b62861..277660d7d8 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/ChatModel.kt @@ -63,6 +63,9 @@ class ChatModel(val controller: ChatController) { val showCallView = mutableStateOf(false) val switchingCall = mutableStateOf(false) + // currently showing QR code + val connReqInv = mutableStateOf(null as String?) + // working with external intents val sharedContent = mutableStateOf(null as SharedContent?) @@ -283,6 +286,15 @@ class ChatModel(val controller: ChatController) { chats.add(index = 0, chat) } + fun dismissConnReqView(id: String) { + if (connReqInv.value == null) return + val info = getChat(id)?.chatInfo as? ChatInfo.ContactConnection ?: return + if (info.contactConnection.connReqInv == connReqInv.value) { + connReqInv.value = null + ModalManager.shared.closeModals() + } + } + fun removeChat(id: String) { chats.removeAll { it.id == id } } @@ -878,6 +890,8 @@ class PendingContactConnection( val pccConnStatus: ConnStatus, val viaContactUri: Boolean, val customUserProfileId: Long? = null, + val connReqInv: String? = null, + override val localAlias: String, override val createdAt: Instant, override val updatedAt: Instant ): SomeChat, NamedChat { @@ -889,6 +903,7 @@ class PendingContactConnection( override val ntfsEnabled get() = false override val localDisplayName get() = String.format(generalGetString(R.string.connection_local_display_name), pccConnId) override val displayName: String get() { + if (localAlias.isNotEmpty()) return localAlias val initiated = pccConnStatus.initiated return if (initiated == null) { // this should not be in the chat list @@ -902,7 +917,6 @@ class PendingContactConnection( } override val fullName get() = "" override val image get() = null - override val localAlias get() = "" val initiated get() = (pccConnStatus.initiated ?: false) && !viaContactUri @@ -927,6 +941,7 @@ class PendingContactConnection( pccAgentConnId = "abcd", pccConnStatus = status, viaContactUri = viaContactUri, + localAlias = "", customUserProfileId = null, createdAt = Clock.System.now(), updatedAt = Clock.System.now() diff --git a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt index 9c556cfa1a..f46b8b754b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/model/SimpleXAPI.kt @@ -597,6 +597,13 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a return null } + suspend fun apiSetConnectionAlias(connId: Long, localAlias: String): PendingContactConnection? { + val r = sendCmd(CC.ApiSetConnectionAlias(connId, localAlias)) + if (r is CR.ConnectionAliasUpdated) return r.toConnection + Log.e(TAG, "apiSetConnectionAlias bad response: ${r.responseType} ${r.details}") + return null + } + suspend fun apiCreateUserAddress(): String? { val r = sendCmd(CC.CreateMyAddress()) return when (r) { @@ -846,12 +853,14 @@ open class ChatController(var ctrl: ChatCtrl?, val ntfManager: NtfManager, val a } is CR.ContactConnected -> { chatModel.updateContact(r.contact) + chatModel.dismissConnReqView(r.contact.activeConn.id) chatModel.removeChat(r.contact.activeConn.id) chatModel.updateNetworkStatus(r.contact.id, Chat.NetworkStatus.Connected()) ntfManager.notifyContactConnected(r.contact) } is CR.ContactConnecting -> { chatModel.updateContact(r.contact) + chatModel.dismissConnReqView(r.contact.activeConn.id) chatModel.removeChat(r.contact.activeConn.id) } is CR.ReceivedContactRequest -> { @@ -1340,6 +1349,7 @@ sealed class CC { class ApiUpdateProfile(val profile: Profile): CC() class ApiParseMarkdown(val text: String): CC() class ApiSetContactAlias(val contactId: Long, val localAlias: String): CC() + class ApiSetConnectionAlias(val connId: Long, val localAlias: String): CC() class CreateMyAddress: CC() class DeleteMyAddress: CC() class ShowMyAddress: CC() @@ -1394,6 +1404,7 @@ sealed class CC { is ApiUpdateProfile -> "/_profile ${json.encodeToString(profile)}" is ApiParseMarkdown -> "/_parse $text" is ApiSetContactAlias -> "/_set alias @$contactId ${localAlias.trim()}" + is ApiSetConnectionAlias -> "/_set alias :$connId ${localAlias.trim()}" is CreateMyAddress -> "/address" is DeleteMyAddress -> "/delete_address" is ShowMyAddress -> "/show_address" @@ -1449,6 +1460,7 @@ sealed class CC { is ApiUpdateProfile -> "updateProfile" is ApiParseMarkdown -> "apiParseMarkdown" is ApiSetContactAlias -> "apiSetContactAlias" + is ApiSetConnectionAlias -> "apiSetConnectionAlias" is CreateMyAddress -> "createMyAddress" is DeleteMyAddress -> "deleteMyAddress" is ShowMyAddress -> "showMyAddress" @@ -1637,6 +1649,7 @@ sealed class CR { @Serializable @SerialName("userProfileNoChange") class UserProfileNoChange: CR() @Serializable @SerialName("userProfileUpdated") class UserProfileUpdated(val fromProfile: Profile, val toProfile: Profile): CR() @Serializable @SerialName("contactAliasUpdated") class ContactAliasUpdated(val toContact: Contact): CR() + @Serializable @SerialName("connectionAliasUpdated") class ConnectionAliasUpdated(val toConnection: PendingContactConnection): CR() @Serializable @SerialName("apiParsedMarkdown") class ParsedMarkdown(val formattedText: List? = null): CR() @Serializable @SerialName("userContactLink") class UserContactLink(val connReqContact: String): CR() @Serializable @SerialName("userContactLinkCreated") class UserContactLinkCreated(val connReqContact: String): CR() @@ -1725,6 +1738,7 @@ sealed class CR { is UserProfileNoChange -> "userProfileNoChange" is UserProfileUpdated -> "userProfileUpdated" is ContactAliasUpdated -> "contactAliasUpdated" + is ConnectionAliasUpdated -> "connectionAliasUpdated" is ParsedMarkdown -> "apiParsedMarkdown" is UserContactLink -> "userContactLink" is UserContactLinkCreated -> "userContactLinkCreated" @@ -1811,6 +1825,7 @@ sealed class CR { is UserProfileNoChange -> noDetails() is UserProfileUpdated -> json.encodeToString(toProfile) is ContactAliasUpdated -> json.encodeToString(toContact) + is ConnectionAliasUpdated -> json.encodeToString(toConnection) is ParsedMarkdown -> json.encodeToString(formattedText) is UserContactLink -> connReqContact is UserContactLinkCreated -> connReqContact diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt index b07a436d00..388c2f5b99 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatInfoView.kt @@ -208,21 +208,33 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) { } @Composable -private fun LocalAliasEditor(initialValue: String, updateValue: (String) -> Unit) { +fun LocalAliasEditor( + initialValue: String, + center: Boolean = true, + leadingIcon: Boolean = false, + focus: Boolean = false, + updateValue: (String) -> Unit +) { var value by rememberSaveable { mutableStateOf(initialValue) } - Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) { + val modifier = if (center) + Modifier.padding(horizontal = if (!leadingIcon) DEFAULT_PADDING else 0.dp).widthIn(min = 100.dp) + else + Modifier.padding(horizontal = if (!leadingIcon) DEFAULT_PADDING else 0.dp).fillMaxWidth() + Row(Modifier.fillMaxWidth(), horizontalArrangement = if (center) Arrangement.Center else Arrangement.Start) { DefaultBasicTextField( - Modifier.padding(horizontal = 10.dp).widthIn(min = 100.dp), + modifier, value, { Text( generalGetString(R.string.text_field_set_contact_placeholder), - textAlign = TextAlign.Center, + textAlign = if (center) TextAlign.Center else TextAlign.Start, color = HighOrLowlight ) }, + leadingIcon = if (leadingIcon) {{ Icon(Icons.Default.Edit, null, Modifier.padding(start = 7.dp)) }} else null, color = HighOrLowlight, - textStyle = TextStyle.Default.copy(textAlign = if (value.isEmpty()) TextAlign.Start else TextAlign.Center), + focus = focus, + textStyle = TextStyle.Default.copy(textAlign = if (value.isEmpty() || !center) TextAlign.Start else TextAlign.Center), keyboardActions = KeyboardActions(onDone = { updateValue(value) }) ) { value = it diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt index 464e851a5c..1f93647ea2 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt @@ -22,6 +22,7 @@ import chat.simplex.app.views.chat.group.deleteGroupDialog import chat.simplex.app.views.chat.group.leaveGroupDialog import chat.simplex.app.views.chat.item.ItemAction import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.newchat.ContactConnectionInfoView import kotlinx.coroutines.delay import kotlinx.datetime.Clock @@ -63,7 +64,11 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) { is ChatInfo.ContactConnection -> ChatListNavLinkLayout( chatLinkPreview = { ContactConnectionView(chat.chatInfo.contactConnection) }, - click = { contactConnectionAlertDialog(chat.chatInfo.contactConnection, chatModel) }, + click = { + ModalManager.shared.showModalCloseable(true) { close -> + ContactConnectionInfoView(chatModel, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, false, close) + } + }, dropdownMenuItems = { ContactConnectionMenuItems(chat.chatInfo, chatModel, showMenu) }, showMenu, stopped @@ -264,11 +269,21 @@ fun ContactRequestMenuItems(chatInfo: ChatInfo.ContactRequest, chatModel: ChatMo @Composable fun ContactConnectionMenuItems(chatInfo: ChatInfo.ContactConnection, chatModel: ChatModel, showMenu: MutableState) { + ItemAction( + stringResource(R.string.set_contact_name), + Icons.Outlined.Edit, + onClick = { + ModalManager.shared.showModalCloseable(true) { close -> + ContactConnectionInfoView(chatModel, chatInfo.contactConnection.connReqInv, chatInfo.contactConnection, true, close) + } + showMenu.value = false + }, + ) ItemAction( stringResource(R.string.delete_verb), Icons.Outlined.Delete, onClick = { - deleteContactConnectionAlert(chatInfo.contactConnection, chatModel) + deleteContactConnectionAlert(chatInfo.contactConnection, chatModel) {} showMenu.value = false }, color = Color.Red @@ -337,7 +352,7 @@ fun contactConnectionAlertDialog(connection: PendingContactConnection, chatModel ) { TextButton(onClick = { AlertManager.shared.hideAlert() - deleteContactConnectionAlert(connection, chatModel) + deleteContactConnectionAlert(connection, chatModel) {} }) { Text(stringResource(R.string.delete_verb)) } @@ -350,7 +365,7 @@ fun contactConnectionAlertDialog(connection: PendingContactConnection, chatModel ) } -fun deleteContactConnectionAlert(connection: PendingContactConnection, chatModel: ChatModel) { +fun deleteContactConnectionAlert(connection: PendingContactConnection, chatModel: ChatModel, onSuccess: () -> Unit) { AlertManager.shared.showAlertDialog( title = generalGetString(R.string.delete_pending_connection__question), text = generalGetString( @@ -363,6 +378,7 @@ fun deleteContactConnectionAlert(connection: PendingContactConnection, chatModel AlertManager.shared.hideAlert() if (chatModel.controller.apiDeleteChat(ChatType.ContactConnection, connection.apiId)) { chatModel.removeChat(connection.id) + onSuccess() } } } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt index 2ee852aeb3..06f17bcd03 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ContactConnectionView.kt @@ -4,16 +4,14 @@ import androidx.compose.foundation.layout.* import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.outlined.AddLink -import androidx.compose.material.icons.outlined.Link -import androidx.compose.runtime.Composable +import androidx.compose.material.icons.outlined.* +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.dp -import chat.simplex.app.model.PendingContactConnection -import chat.simplex.app.model.getTimestampText +import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.ProfileImage diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt index 31de2f5212..0698fd292a 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/DefaultBasicTextField.kt @@ -28,6 +28,7 @@ fun DefaultBasicTextField( modifier: Modifier, initialValue: String, placeholder: (@Composable () -> Unit)? = null, + leadingIcon: (@Composable () -> Unit)? = null, focus: Boolean = false, color: Color = MaterialTheme.colors.onBackground, textStyle: TextStyle = TextStyle.Default, @@ -44,8 +45,8 @@ fun DefaultBasicTextField( LaunchedEffect(Unit) { if (!focus) return@LaunchedEffect + delay(300) focusRequester.requestFocus() - delay(200) keyboard?.show() } val enabled = true @@ -100,6 +101,7 @@ fun DefaultBasicTextField( placeholder = placeholder, singleLine = true, enabled = enabled, + leadingIcon = leadingIcon, interactionSource = interactionSource, contentPadding = TextFieldDefaults.textFieldWithLabelPadding(start = 0.dp, end = 0.dp), visualTransformation = VisualTransformation.None, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt index 36f72c269d..ae184c1efe 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/helpers/ModalView.kt @@ -63,7 +63,7 @@ class ModalManager { } fun closeModals() { - while (modalViews.isNotEmpty()) closeModal() + while (modalCount.value > 0) closeModal() } @OptIn(ExperimentalAnimationApi::class) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt index a64a0a3356..935b4953a7 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddContactView.kt @@ -9,7 +9,7 @@ import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.TheaterComedy import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Share -import androidx.compose.runtime.Composable +import androidx.compose.runtime.* import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -24,17 +24,25 @@ import chat.simplex.app.ui.theme.* import chat.simplex.app.views.helpers.* @Composable -fun AddContactView(chatModel: ChatModel, connReqInvitation: String) { +fun AddContactView(chatModel: ChatModel, connReqInvitation: String, connIncognito: Boolean) { val cxt = LocalContext.current + LaunchedEffect(connReqInvitation) { + if (connReqInvitation.isNotEmpty()) { + chatModel.connReqInv.value = connReqInvitation + } + } + DisposableEffect(Unit) { + onDispose { chatModel.connReqInv.value = null } + } AddContactLayout( - chatModelIncognito = chatModel.incognito.value, connReq = connReqInvitation, + connIncognito = connIncognito, share = { shareText(cxt, connReqInvitation) } ) } @Composable -fun AddContactLayout(chatModelIncognito: Boolean, connReq: String, share: () -> Unit) { +fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit) { BoxWithConstraints { val screenHeight = maxHeight Column( @@ -49,7 +57,7 @@ fun AddContactLayout(chatModelIncognito: Boolean, connReq: String, share: () -> ) Row { InfoAboutIncognito( - chatModelIncognito, + connIncognito, true, generalGetString(R.string.incognito_random_profile_description), generalGetString(R.string.your_profile_will_be_sent) @@ -132,8 +140,8 @@ fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean fun PreviewAddContactView() { SimpleXTheme { AddContactLayout( - chatModelIncognito = false, connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", + connIncognito = false, share = {} ) } diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt new file mode 100644 index 0000000000..96acf498f6 --- /dev/null +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/ContactConnectionInfoView.kt @@ -0,0 +1,163 @@ +package chat.simplex.app.views.newchat + +import SectionDivider +import SectionView +import android.content.res.Configuration +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.rememberScrollState +import androidx.compose.foundation.verticalScroll +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.* +import androidx.compose.runtime.* +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import chat.simplex.app.R +import chat.simplex.app.model.* +import chat.simplex.app.ui.theme.* +import chat.simplex.app.views.chat.LocalAliasEditor +import chat.simplex.app.views.chatlist.deleteContactConnectionAlert +import chat.simplex.app.views.helpers.* +import chat.simplex.app.views.usersettings.SettingsActionItem + +@Composable +fun ContactConnectionInfoView( + chatModel: ChatModel, + connReqInvitation: String?, + contactConnection: PendingContactConnection, + focusAlias: Boolean, + close: () -> Unit +) { + /** When [AddContactView] is open, we don't need to drop [chatModel.connReqInv]. It will be managed by [AddContactView] itself + * Otherwise it will be called here AFTER [AddContactView] is launched and will clear the value too soon */ + val allowDispose = remember { mutableStateOf(true) } + LaunchedEffect(connReqInvitation) { + allowDispose.value = true + chatModel.connReqInv.value = connReqInvitation + } + DisposableEffect(Unit) { + onDispose { + if (allowDispose.value) { + chatModel.connReqInv.value = null + } + } + } + ContactConnectionInfoLayout( + connReq = connReqInvitation, + contactConnection.localAlias, + contactConnection.initiated, + contactConnection.viaContactUri, + contactConnection.incognito, + focusAlias, + deleteConnection = { deleteContactConnectionAlert(contactConnection, chatModel, close) }, + onLocalAliasChanged = { setContactAlias(contactConnection, it, chatModel) }, + showQr = { + allowDispose.value = false + ModalManager.shared.showModal { + Column( + Modifier + .fillMaxHeight() + .padding(horizontal = DEFAULT_PADDING), + verticalArrangement = Arrangement.SpaceBetween + ) { + AddContactView(chatModel, connReqInvitation ?: return@showModal, contactConnection.incognito) + } + } + } + ) +} + +@Composable +private fun ContactConnectionInfoLayout( + connReq: String?, + localAlias: String, + connectionInitiated: Boolean, + connectionViaContactUri: Boolean, + connectionIncognito: Boolean, + focusAlias: Boolean, + deleteConnection: () -> Unit, + onLocalAliasChanged: (String) -> Unit, + showQr: () -> Unit, +) { + Column( + Modifier + .verticalScroll(rememberScrollState()), + ) { + AppBarTitle( + stringResource( + if (connectionInitiated) R.string.you_invited_your_contact + else R.string.you_accepted_connection + ) + ) + Row(Modifier.padding(bottom = DEFAULT_PADDING)) { + LocalAliasEditor(localAlias, center = false, leadingIcon = true, focus = focusAlias, updateValue = onLocalAliasChanged) + } + Text( + stringResource( + if (connectionViaContactUri) R.string.you_will_be_connected_when_your_connection_request_is_accepted + else R.string.you_will_be_connected_when_your_contacts_device_is_online + ), + Modifier.padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING, bottom = DEFAULT_PADDING) + ) + SectionView { + if (!connReq.isNullOrEmpty() && connectionInitiated) { + ShowQrButton(connectionIncognito, showQr) + SectionDivider() + } + DeleteButton(deleteConnection) + } + } +} + +@Composable +fun ShowQrButton(incognito: Boolean, onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.QrCode, + stringResource(R.string.show_QR_code), + click = onClick, + textColor = if (incognito) Indigo else MaterialTheme.colors.primary, + iconColor = if (incognito) Indigo else MaterialTheme.colors.primary, + ) +} + +@Composable +fun DeleteButton(onClick: () -> Unit) { + SettingsActionItem( + Icons.Outlined.Delete, + stringResource(R.string.delete_verb), + click = onClick, + textColor = Color.Red, + iconColor = Color.Red, + ) +} + +private fun setContactAlias(contactConnection: PendingContactConnection, localAlias: String, chatModel: ChatModel) = withApi { + chatModel.controller.apiSetConnectionAlias(contactConnection.pccConnId, localAlias)?.let { + chatModel.updateContactConnection(it) + } +} + +@Preview +@Preview( + uiMode = Configuration.UI_MODE_NIGHT_YES, + showBackground = true, + name = "Dark Mode" +) +@Composable +private fun PreviewContactConnectionInfoView() { + SimpleXTheme { + ContactConnectionInfoLayout( + localAlias = "", + connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", + connectionInitiated = true, + connectionViaContactUri = true, + connectionIncognito = false, + focusAlias = false, + deleteConnection = {}, + onLocalAliasChanged = {}, + showQr = {}, + ) + } +} diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt index c0042faca8..175597935e 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/CreateLinkView.kt @@ -46,7 +46,7 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) { Column(Modifier.weight(1f)) { when (selection.value) { CreateLinkTab.ONE_TIME -> { - AddContactView(m, connReqInvitation.value) + AddContactView(m, connReqInvitation.value, m.incognito.value) } CreateLinkTab.LONG_TERM -> { UserAddressView(m) diff --git a/apps/android/app/src/main/res/values-de/strings.xml b/apps/android/app/src/main/res/values-de/strings.xml index 472525d67e..bd3fa2531c 100644 --- a/apps/android/app/src/main/res/values-de/strings.xml +++ b/apps/android/app/src/main/res/values-de/strings.xml @@ -271,6 +271,7 @@ Kontakt löschen Gruppe löschen Als gelesen markieren + Set contact name Stummschalten @@ -307,6 +308,9 @@ E-Mail Mehr + + Show QR code + Ungültiger QR-Code Dieser QR-Code beschreibt keinen Link! diff --git a/apps/android/app/src/main/res/values-ru/strings.xml b/apps/android/app/src/main/res/values-ru/strings.xml index f12840a1c4..e59f1db679 100644 --- a/apps/android/app/src/main/res/values-ru/strings.xml +++ b/apps/android/app/src/main/res/values-ru/strings.xml @@ -271,6 +271,7 @@ Удалить Удалить Прочитано + Имя контакта Без звука @@ -307,6 +308,9 @@ Email Больше + + Показать QR код + Неверный QR код Этот QR код не является ссылкой! diff --git a/apps/android/app/src/main/res/values/strings.xml b/apps/android/app/src/main/res/values/strings.xml index f3425051dc..450c435505 100644 --- a/apps/android/app/src/main/res/values/strings.xml +++ b/apps/android/app/src/main/res/values/strings.xml @@ -271,6 +271,7 @@ Delete Delete Mark read + Set contact name Mute @@ -307,6 +308,9 @@ Email More + + Show QR code + Invalid QR code This QR code is not a link! @@ -315,7 +319,7 @@ Connection request sent! You will be connected when your connection request is accepted, please wait or check later! You will be connected when your contact\'s device is online, please wait or check later! - Your contact can scan it from the app. + Your contact can scan QR code from the app. If you can\'t meet in person, show QR code in the video call, or share the link. Your chat profile will be sent\nto your contact If you cannot meet in person, you can scan QR code in the video call, or your contact can share an invitation link.