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 3b02db61e1..b6c4470576 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
@@ -290,6 +290,7 @@ class ChatModel(val controller: ChatController) {
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()
}
}
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 1e3b7f0d2e..ccf936860f 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,21 @@ fun ChatInfoHeader(cInfo: ChatInfo, contact: Contact) {
}
@Composable
-fun LocalAliasEditor(initialValue: String, updateValue: (String) -> Unit) {
+fun LocalAliasEditor(initialValue: String, center: Boolean = true, updateValue: (String) -> Unit) {
var value by rememberSaveable { mutableStateOf(initialValue) }
- Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center) {
+ Row(Modifier.fillMaxWidth(), horizontalArrangement = if (center) Arrangement.Center else Arrangement.Start) {
DefaultBasicTextField(
- Modifier.padding(horizontal = 10.dp).widthIn(min = 100.dp),
+ Modifier.padding(horizontal = DEFAULT_PADDING).widthIn(min = 100.dp),
value,
{
Text(
generalGetString(R.string.text_field_set_contact_placeholder),
- textAlign = TextAlign.Center,
+ textAlign = if (center) TextAlign.Center else TextAlign.Start,
color = HighOrLowlight
)
},
color = HighOrLowlight,
- textStyle = TextStyle.Default.copy(textAlign = if (value.isEmpty()) TextAlign.Start else TextAlign.Center),
+ 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 1173528854..d85c930bd0 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,10 +64,11 @@ fun ChatListNavLinkView(chat: Chat, chatModel: ChatModel) {
is ChatInfo.ContactConnection ->
ChatListNavLinkLayout(
chatLinkPreview = { ContactConnectionView(chat.chatInfo.contactConnection) },
- click = { chat.chatInfo.contactConnection.connReqInv.let {
- if (it == null) contactConnectionAlertDialog(chat.chatInfo.contactConnection, chatModel)
- else ModalManager.shared.showModalCloseable { close -> ContactConnectionInfoView(chatModel, it, chat.chatInfo.contactConnection, close) }
- } },
+ click = {
+ ModalManager.shared.showModalCloseable(true) { close ->
+ ContactConnectionInfoView(chatModel, chat.chatInfo.contactConnection.connReqInv, chat.chatInfo.contactConnection, close)
+ }
+ },
dropdownMenuItems = { ContactConnectionMenuItems(chat.chatInfo, chatModel, showMenu) },
showMenu,
stopped
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..3629a7d74d 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
@@ -26,6 +26,14 @@ import chat.simplex.app.views.helpers.*
@Composable
fun AddContactView(chatModel: ChatModel, connReqInvitation: String) {
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,
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
index 20f831a6fd..a8cb7218ae 100644
--- 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
@@ -1,6 +1,9 @@
-package chat.simplex.app.views.chatlist
+package chat.simplex.app.views.newchat
+import SectionDivider
+import SectionView
import android.content.res.Configuration
+import androidx.activity.compose.BackHandler
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
@@ -10,111 +13,118 @@ 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.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.unit.sp
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.newchat.InfoAboutIncognito
-import chat.simplex.app.views.newchat.QRCode
+import chat.simplex.app.views.usersettings.SettingsActionItem
@Composable
-fun ContactConnectionInfoView(chatModel: ChatModel, connReqInvitation: String, contactConnection: PendingContactConnection, close: () -> Unit) {
- val cxt = LocalContext.current
- LaunchedEffect(Unit) {
- if (contactConnection.connReqInv != null) {
- chatModel.connReqInv.value = contactConnection.connReqInv
- }
+fun ContactConnectionInfoView(chatModel: ChatModel, connReqInvitation: String?, contactConnection: PendingContactConnection, 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 { chatModel.connReqInv.value = null }
+ onDispose {
+ if (allowDispose.value) {
+ chatModel.connReqInv.value = null
+ }
+ }
}
ContactConnectionInfoLayout(
- chatModelIncognito = chatModel.incognito.value,
connReq = connReqInvitation,
contactConnection.localAlias,
- share = { shareText(cxt, connReqInvitation) },
+ contactConnection.initiated,
+ contactConnection.viaContactUri,
deleteConnection = { deleteContactConnectionAlert(contactConnection, chatModel, close) },
- onLocalAliasChanged = { setContactAlias(contactConnection, it, chatModel) }
+ 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)
+ }
+ }
+ }
)
}
@Composable
private fun ContactConnectionInfoLayout(
- chatModelIncognito: Boolean,
- connReq: String,
+ connReq: String?,
localAlias: String,
- share: () -> Unit,
+ connectionInitiated: Boolean,
+ connectionViaContactUri: Boolean,
deleteConnection: () -> Unit,
- onLocalAliasChanged: (String) -> Unit
+ onLocalAliasChanged: (String) -> Unit,
+ showQr: () -> Unit,
) {
BoxWithConstraints {
- val screenHeight = maxHeight
- var showQr by remember { mutableStateOf(false) }
Column(
Modifier
- .verticalScroll(rememberScrollState())
- .padding(start = DEFAULT_PADDING, end = DEFAULT_PADDING , bottom = DEFAULT_PADDING),
- verticalArrangement = Arrangement.SpaceBetween,
+ .verticalScroll(rememberScrollState()),
) {
- AppBarTitle(stringResource(R.string.shared_one_time_link), false)
-
- LocalAliasEditor(localAlias, updateValue = onLocalAliasChanged)
-
- Text(
- stringResource(R.string.show_QR_code_for_your_contact_to_scan_from_the_app__multiline),
+ AppBarTitle(
+ stringResource(
+ if (connectionInitiated) R.string.you_invited_your_contact
+ else R.string.you_accepted_connection
+ )
)
- Row {
- InfoAboutIncognito(
- chatModelIncognito,
- true,
- generalGetString(R.string.incognito_random_profile_description),
- generalGetString(R.string.your_profile_will_be_sent)
- )
- }
- if (connReq.isNotEmpty() && showQr) {
- QRCode(
- connReq, Modifier
- .aspectRatio(1f)
- .padding(vertical = 3.dp)
- )
+ 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(horizontal = DEFAULT_PADDING)
+ )
+ LocalAliasEditor(localAlias, center = false, updateValue = onLocalAliasChanged)
- Text(
- annotatedStringResource(R.string.if_you_cannot_meet_in_person_show_QR_in_video_call_or_via_another_channel),
- lineHeight = 22.sp,
- modifier = Modifier
- .padding(bottom = if (screenHeight > 600.dp) 8.dp else 0.dp)
- )
- }
- if (!showQr) {
- Row(
- Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center
- ) {
- SimpleButton(stringResource(R.string.show_QR_code), icon = Icons.Outlined.QrCode, click = { showQr = true })
+ SectionView {
+ if (!connReq.isNullOrEmpty() && connectionInitiated) {
+ ShowQrButton(showQr)
+ SectionDivider()
}
- }
- Row(
- Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center
- ) {
- SimpleButton(stringResource(R.string.share_invitation_link), icon = Icons.Outlined.Share, click = share)
- }
- Row(
- Modifier.fillMaxWidth(),
- horizontalArrangement = Arrangement.Center
- ) {
- SimpleButton(stringResource(R.string.delete_verb), icon = Icons.Outlined.Delete, color = Color.Red, click = deleteConnection)
+ DeleteButton(deleteConnection)
}
}
}
}
+@Composable
+fun ShowQrButton(onClick: () -> Unit) {
+ SettingsActionItem(
+ Icons.Outlined.QrCode,
+ stringResource(R.string.show_QR_code),
+ click = onClick,
+ textColor = MaterialTheme.colors.primary,
+ iconColor = 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)
@@ -128,15 +138,16 @@ private fun setContactAlias(contactConnection: PendingContactConnection, localAl
name = "Dark Mode"
)
@Composable
-private fun PreviewAddContactView() {
+private fun PreviewContactConnectionInfoView() {
SimpleXTheme {
ContactConnectionInfoLayout(
- chatModelIncognito = false,
localAlias = "",
connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D",
- share = {},
+ connectionInitiated = true,
+ connectionViaContactUri = true,
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 1fe555a85a..c0042faca8 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
@@ -29,14 +29,6 @@ fun CreateLinkView(m: ChatModel, initialSelection: CreateLinkTab) {
createInvitation(m, creatingConnReq, connReqInvitation)
}
}
- LaunchedEffect(connReqInvitation.value) {
- if (connReqInvitation.value.isNotEmpty()) {
- m.connReqInv.value = connReqInvitation.value
- }
- }
- DisposableEffect(Unit) {
- onDispose { m.connReqInv.value = null }
- }
val tabTitles = CreateLinkTab.values().map {
when {
it == CreateLinkTab.ONE_TIME && connReqInvitation.value.isEmpty() -> stringResource(R.string.create_one_time_link)
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 4f96cea009..451f549ffd 100644
--- a/apps/android/app/src/main/res/values-de/strings.xml
+++ b/apps/android/app/src/main/res/values-de/strings.xml
@@ -309,7 +309,6 @@
Show QR code
- Shared one-time link
Ungültiger QR-Code
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 e460789e4b..f77c805986 100644
--- a/apps/android/app/src/main/res/values-ru/strings.xml
+++ b/apps/android/app/src/main/res/values-ru/strings.xml
@@ -309,7 +309,6 @@
Показать 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 d8f214435c..52c66ec778 100644
--- a/apps/android/app/src/main/res/values/strings.xml
+++ b/apps/android/app/src/main/res/values/strings.xml
@@ -309,7 +309,6 @@
Show QR code
- Shared one-time link
Invalid QR code