From 48d7afc959ced8984c62ae034b25f1fed391c50f Mon Sep 17 00:00:00 2001 From: Stanislav Dmitrenko <7953703+avently@users.noreply.github.com> Date: Wed, 22 Nov 2023 22:35:32 +0800 Subject: [PATCH] desktop: enhancements to remote hosts experience (#3428) --- .../java/chat/simplex/app/MainActivity.kt | 2 +- .../main/java/chat/simplex/app/SimplexApp.kt | 2 +- .../chat/simplex/common/model/ChatModel.kt | 3 +- .../chat/simplex/common/model/SimpleXAPI.kt | 4 +- .../chat/simplex/common/views/TerminalView.kt | 2 +- .../chat/simplex/common/views/WelcomeView.kt | 2 +- .../simplex/common/views/chat/ScanCodeView.kt | 2 +- .../common/views/chat/VerifyCodeView.kt | 2 +- .../common/views/chatlist/ChatListView.kt | 2 +- .../common/views/chatlist/UserPicker.kt | 23 +++++++++-- .../common/views/database/DatabaseView.kt | 2 +- .../common/views/helpers/AlertManager.kt | 2 +- .../common/views/helpers/CloseSheetBar.kt | 39 +++++++++++++------ .../simplex/common/views/helpers/Utils.kt | 2 +- .../common/views/newchat/AddContactView.kt | 2 +- .../common/views/newchat/AddGroupView.kt | 7 +++- .../newchat/ContactConnectionInfoView.kt | 6 ++- .../common/views/newchat/PasteToConnect.kt | 2 +- .../common/views/newchat/ScanToConnectView.kt | 2 +- .../common/views/onboarding/HowItWorks.kt | 2 +- .../common/views/remote/ConnectMobileView.kt | 10 ++--- .../common/views/usersettings/HelpView.kt | 2 +- .../views/usersettings/ProtocolServersView.kt | 16 +++++--- .../views/usersettings/ScanProtocolServer.kt | 2 +- .../common/views/usersettings/SettingsView.kt | 2 +- .../views/usersettings/UserAddressView.kt | 6 ++- .../views/usersettings/VersionInfoView.kt | 2 +- 27 files changed, 99 insertions(+), 51 deletions(-) diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt index 4c5d595a8..a84590fb8 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/MainActivity.kt @@ -126,7 +126,7 @@ fun processIntent(intent: Intent?) { when (intent?.action) { "android.intent.action.VIEW" -> { val uri = intent.data - if (uri != null) connectIfOpenedViaUri(chatModel.remoteHostId, uri.toURI(), ChatModel) + if (uri != null) connectIfOpenedViaUri(chatModel.remoteHostId(), uri.toURI(), ChatModel) } } } diff --git a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt index 13908f69b..b6afab4ea 100644 --- a/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt +++ b/apps/multiplatform/android/src/main/java/chat/simplex/app/SimplexApp.kt @@ -57,7 +57,7 @@ class SimplexApp: Application(), LifecycleEventObserver { updatingChatsMutex.withLock { kotlin.runCatching { val currentUserId = chatModel.currentUser.value?.userId - val chats = ArrayList(chatController.apiGetChats(chatModel.remoteHostId)) + val chats = ArrayList(chatController.apiGetChats(chatModel.remoteHostId())) /** Active user can be changed in background while [ChatController.apiGetChats] is executing */ if (chatModel.currentUser.value?.userId == currentUserId) { val currentChatId = chatModel.chatId.value diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt index 660e7de15..dca3bc5b1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/ChatModel.kt @@ -111,7 +111,8 @@ object ChatModel { // remote controller val remoteHosts = mutableStateListOf() val currentRemoteHost = mutableStateOf(null) - val remoteHostId: Long? get() = currentRemoteHost?.value?.remoteHostId + val remoteHostId: Long? @Composable get() = remember { currentRemoteHost }.value?.remoteHostId + fun remoteHostId(): Long? = currentRemoteHost.value?.remoteHostId val newRemoteHostPairing = mutableStateOf?>(null) val remoteCtrlSession = mutableStateOf(null) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt index 4aed00261..26595880d 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/model/SimpleXAPI.kt @@ -1625,7 +1625,7 @@ object ChatController { || (mc is MsgContent.MCVoice && file.fileSize <= MAX_VOICE_SIZE_AUTO_RCV && file.fileStatus !is CIFileStatus.RcvAccepted))) { withApi { receiveFile(rhId, r.user, file.fileId, encrypted = cItem.encryptLocalFile && chatController.appPrefs.privacyEncryptLocalFiles.get(), auto = true) } } - if (cItem.showNotification && (allowedToShowNotification() || chatModel.chatId.value != cInfo.id || chatModel.remoteHostId != rhId)) { + if (cItem.showNotification && (allowedToShowNotification() || chatModel.chatId.value != cInfo.id || chatModel.remoteHostId() != rhId)) { ntfManager.notifyMessageReceived(r.user, cInfo, cItem) } } @@ -1913,7 +1913,7 @@ object ChatController { } private fun activeUser(rhId: Long?, user: UserLike): Boolean = - rhId == chatModel.remoteHostId && user.userId == chatModel.currentUser.value?.userId + rhId == chatModel.remoteHostId() && user.userId == chatModel.currentUser.value?.userId private fun withCall(r: CR, contact: Contact, perform: (Call) -> Unit) { val call = chatModel.activeCall.value diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt index ec2082557..59f62f9c9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/TerminalView.kt @@ -54,7 +54,7 @@ private fun sendCommand(chatModel: ChatModel, composeState: MutableState Unit) { fun createProfileInProfiles(chatModel: ChatModel, displayName: String, close: () -> Unit) { withApi { - val rhId = chatModel.remoteHostId + val rhId = chatModel.remoteHostId() val user = chatModel.controller.apiCreateActiveUser( rhId, Profile(displayName.trim(), "", null) ) ?: return@withApi diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt index 8ce39eea3..bb479d8eb 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ScanCodeView.kt @@ -17,7 +17,7 @@ fun ScanCodeView(verifyCode: (String?, cb: (Boolean) -> Unit) -> Unit, close: () .fillMaxSize() .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitle(stringResource(MR.strings.scan_code), false) + AppBarTitle(stringResource(MR.strings.scan_code), withPadding = false) Box( Modifier .fillMaxWidth() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt index 1b25c52cf..e1840dd88 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/VerifyCodeView.kt @@ -63,7 +63,7 @@ private fun VerifyCodeLayout( .verticalScroll(rememberScrollState()) .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitle(stringResource(MR.strings.security_code), false) + AppBarTitle(stringResource(MR.strings.security_code), withPadding = false) val splitCode = splitToParts(connectionCode, 24) Row(Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF), horizontalArrangement = Arrangement.Center) { if (connectionVerified) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt index f9502bf90..301f09033 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/ChatListView.kt @@ -53,7 +53,7 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf val url = chatModel.appOpenUrl.value if (url != null) { chatModel.appOpenUrl.value = null - connectIfOpenedViaUri(chatModel.remoteHostId, url, chatModel) + connectIfOpenedViaUri(chatModel.remoteHostId(), url, chatModel) } } if (appPlatform.isDesktop) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt index 20e856df6..46a333f61 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chatlist/UserPicker.kt @@ -26,8 +26,7 @@ import chat.simplex.common.model.ChatModel.controller import chat.simplex.common.ui.theme.* import chat.simplex.common.views.helpers.* import chat.simplex.common.platform.* -import chat.simplex.common.views.remote.ConnectDesktopView -import chat.simplex.common.views.remote.connectMobileDevice +import chat.simplex.common.views.remote.* import chat.simplex.res.MR import dev.icerock.moko.resources.compose.stringResource import kotlinx.coroutines.delay @@ -84,7 +83,7 @@ fun UserPicker( .filter { it } .collect { try { - val updatedUsers = chatModel.controller.listUsers(chatModel.remoteHostId).sortedByDescending { it.user.activeUser } + val updatedUsers = chatModel.controller.listUsers(chatModel.remoteHostId()).sortedByDescending { it.user.activeUser } var same = users.size == updatedUsers.size if (same) { for (i in 0 until minOf(users.size, updatedUsers.size)) { @@ -213,6 +212,14 @@ fun UserPicker( userPickerState.value = AnimatedViewState.GONE } Divider(Modifier.requiredHeight(1.dp)) + } else if (remoteHosts.isEmpty()) { + LinkAMobilePickerItem { + ModalManager.start.showModal { + ConnectMobileView() + } + userPickerState.value = AnimatedViewState.GONE + } + Divider(Modifier.requiredHeight(1.dp)) } if (showSettings) { SettingsPickerItem(settingsClicked) @@ -384,6 +391,16 @@ private fun UseFromDesktopPickerItem(onClick: () -> Unit) { } } +@Composable +private fun LinkAMobilePickerItem(onClick: () -> Unit) { + SectionItemView(onClick, padding = PaddingValues(start = DEFAULT_PADDING + 7.dp, end = DEFAULT_PADDING), minHeight = 68.dp) { + val text = generalGetString(MR.strings.link_a_mobile) + Icon(painterResource(MR.images.ic_smartphone_300), text, Modifier.size(20.dp), tint = MaterialTheme.colors.onBackground) + Spacer(Modifier.width(DEFAULT_PADDING + 6.dp)) + Text(text, color = if (isInDarkTheme()) MenuTextColorDark else Color.Black) + } +} + @Composable private fun SettingsPickerItem(onClick: () -> Unit) { SectionItemView(onClick, padding = PaddingValues(start = DEFAULT_PADDING + 7.dp, end = DEFAULT_PADDING), minHeight = 68.dp) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt index 1f4be2966..bc43310b8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/database/DatabaseView.kt @@ -627,7 +627,7 @@ private fun afterSetCiTTL( try { updatingChatsMutex.withLock { // this is using current remote host on purpose - if it changes during update, it will load correct chats - val chats = m.controller.apiGetChats(m.remoteHostId) + val chats = m.controller.apiGetChats(m.remoteHostId()) m.updateChats(chats) } } catch (e: Exception) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt index 287f19ffd..10bbae6bf 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/AlertManager.kt @@ -88,7 +88,7 @@ class AlertManager { onDismissRequest = { onDismissRequest?.invoke(); hideAlert() }, title = alertTitle(title), buttons = { - AlertContent(text, hostDevice) { + AlertContent(text, hostDevice, true) { Row( Modifier.fillMaxWidth().padding(horizontal = DEFAULT_PADDING), horizontalArrangement = Arrangement.SpaceBetween diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt index 848b21eb4..1a29a334a 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/CloseSheetBar.kt @@ -14,6 +14,8 @@ import androidx.compose.desktop.ui.tooling.preview.Preview import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import chat.simplex.common.ui.theme.* +import chat.simplex.res.MR +import dev.icerock.moko.resources.compose.painterResource @Composable fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, endButtons: @Composable RowScope.() -> Unit = {}) { @@ -47,23 +49,38 @@ fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, endButtons: @ } @Composable -fun AppBarTitle(title: String, withPadding: Boolean = true, bottomPadding: Dp = DEFAULT_PADDING * 1.5f) { +fun AppBarTitle(title: String, hostDevice: Pair? = null, withPadding: Boolean = true, bottomPadding: Dp = DEFAULT_PADDING * 1.5f) { val theme = CurrentColors.collectAsState() val titleColor = CurrentColors.collectAsState().value.appColors.title val brush = if (theme.value.base == DefaultTheme.SIMPLEX) Brush.linearGradient(listOf(titleColor.darker(0.2f), titleColor.lighter(0.35f)), Offset(0f, Float.POSITIVE_INFINITY), Offset(Float.POSITIVE_INFINITY, 0f)) else // color is not updated when changing themes if I pass null here Brush.linearGradient(listOf(titleColor, titleColor), Offset(0f, Float.POSITIVE_INFINITY), Offset(Float.POSITIVE_INFINITY, 0f)) - Text( - title, - Modifier - .fillMaxWidth() - .padding(bottom = bottomPadding, start = if (withPadding) DEFAULT_PADDING else 0.dp, end = if (withPadding) DEFAULT_PADDING else 0.dp,), - overflow = TextOverflow.Ellipsis, - style = MaterialTheme.typography.h1.copy(brush = brush), - color = MaterialTheme.colors.primaryVariant, - textAlign = TextAlign.Center - ) + Column { + Text( + title, + Modifier + .fillMaxWidth() + .padding(start = if (withPadding) DEFAULT_PADDING else 0.dp, end = if (withPadding) DEFAULT_PADDING else 0.dp,), + overflow = TextOverflow.Ellipsis, + style = MaterialTheme.typography.h1.copy(brush = brush), + color = MaterialTheme.colors.primaryVariant, + textAlign = TextAlign.Center + ) + if (hostDevice != null) { + HostDeviceTitle(hostDevice) + } + Spacer(Modifier.height(bottomPadding)) + } +} + +@Composable +private fun HostDeviceTitle(hostDevice: Pair, extraPadding: Boolean = false) { + Row(Modifier.fillMaxWidth().padding(top = 5.dp, bottom = if (extraPadding) DEFAULT_PADDING * 2 else DEFAULT_PADDING_HALF), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.Center) { + Icon(painterResource(if (hostDevice.first == null) MR.images.ic_desktop else MR.images.ic_smartphone_300), null, Modifier.size(15.dp), tint = MaterialTheme.colors.secondary) + Spacer(Modifier.width(10.dp)) + Text(hostDevice.second, color = MaterialTheme.colors.secondary) + } } @Preview/*( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt index dbadec32f..21b71d876 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/helpers/Utils.kt @@ -373,7 +373,7 @@ inline fun serializableSaver(): Saver = Saver( fun UriHandler.openVerifiedSimplexUri(uri: String) { val URI = try { URI.create(uri) } catch (e: Exception) { null } if (URI != null) { - connectIfOpenedViaUri(chatModel.remoteHostId, URI, ChatModel) + connectIfOpenedViaUri(chatModel.remoteHostId(), URI, ChatModel) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt index a539bf498..84080d5b9 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddContactView.kt @@ -79,7 +79,7 @@ fun AddContactLayout( .verticalScroll(rememberScrollState()), verticalArrangement = Arrangement.SpaceBetween, ) { - AppBarTitle(stringResource(MR.strings.add_contact)) + AppBarTitle(stringResource(MR.strings.add_contact), hostDevice(rh?.remoteHostId)) SectionView(stringResource(MR.strings.one_time_link_short).uppercase()) { if (connReq.isNotEmpty()) { diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt index aa5494e5a..4f71e81b0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddGroupView.kt @@ -58,6 +58,7 @@ fun AddGroupView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { } }, incognitoPref = chatModel.controller.appPrefs.incognito, + rhId, close ) } @@ -66,6 +67,7 @@ fun AddGroupView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit) { fun AddGroupLayout( createGroup: (Boolean, GroupProfile) -> Unit, incognitoPref: SharedPreference, + rhId: Long?, close: () -> Unit ) { val bottomSheetModalState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden) @@ -98,7 +100,7 @@ fun AddGroupLayout( .verticalScroll(rememberScrollState()) .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitle(stringResource(MR.strings.create_secret_group_title)) + AppBarTitle(stringResource(MR.strings.create_secret_group_title), hostDevice(rhId)) Box( Modifier .fillMaxWidth() @@ -174,7 +176,8 @@ fun PreviewAddGroupLayout() { AddGroupLayout( createGroup = { _, _ -> }, incognitoPref = SharedPreference({ false }, {}), - close = {} + close = {}, + rhId = null, ) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt index 50419cdaf..5e9495e86 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ContactConnectionInfoView.kt @@ -56,6 +56,7 @@ fun ContactConnectionInfoView( connReq = connReqInvitation, contactConnection = contactConnection, focusAlias = focusAlias, + rhId = rhId, deleteConnection = { deleteContactConnectionAlert(rhId, contactConnection, chatModel, close) }, onLocalAliasChanged = { setContactAlias(rhId, contactConnection, it, chatModel) }, share = { if (connReqInvitation != null) clipboard.shareText(connReqInvitation) }, @@ -80,6 +81,7 @@ private fun ContactConnectionInfoLayout( connReq: String?, contactConnection: PendingContactConnection, focusAlias: Boolean, + rhId: Long?, deleteConnection: () -> Unit, onLocalAliasChanged: (String) -> Unit, share: () -> Unit, @@ -114,7 +116,8 @@ private fun ContactConnectionInfoLayout( stringResource( if (contactConnection.initiated) MR.strings.you_invited_a_contact else MR.strings.you_accepted_connection - ) + ), + hostDevice(rhId) ) Text( stringResource( @@ -185,6 +188,7 @@ private fun PreviewContactConnectionInfoView() { connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D", contactConnection = PendingContactConnection.getSampleData(), focusAlias = false, + rhId = null, deleteConnection = {}, onLocalAliasChanged = {}, share = {}, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt index 3e4447d35..dacf93757 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/PasteToConnect.kt @@ -67,7 +67,7 @@ fun PasteToConnectLayout( Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING), verticalArrangement = Arrangement.SpaceBetween, ) { - AppBarTitle(stringResource(MR.strings.connect_via_link), false) + AppBarTitle(stringResource(MR.strings.connect_via_link), hostDevice(rhId), withPadding = false) Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) { TextEditor( diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt index fd3961362..4deeda3e2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/ScanToConnectView.kt @@ -469,7 +469,7 @@ fun ConnectContactLayout( Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING), verticalArrangement = Arrangement.SpaceBetween ) { - AppBarTitle(stringResource(MR.strings.scan_QR_code), false) + AppBarTitle(stringResource(MR.strings.scan_QR_code), hostDevice(rh?.remoteHostId), withPadding = false) Box( Modifier .fillMaxWidth() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt index e3dfb2b73..6c76acc3e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/onboarding/HowItWorks.kt @@ -26,7 +26,7 @@ fun HowItWorks(user: User?, onboardingStage: SharedPreference? .fillMaxWidth() .padding(horizontal = DEFAULT_PADDING), ) { - AppBarTitle(stringResource(MR.strings.how_simplex_works), false) + AppBarTitle(stringResource(MR.strings.how_simplex_works), withPadding = false) ReadableText(MR.strings.many_people_asked_how_can_it_deliver) ReadableText(MR.strings.to_protect_privacy_simplex_has_ids_for_queues) ReadableText(MR.strings.you_control_servers_to_receive_your_contacts_to_send) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt index 0d90e5945..974f71cf2 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/remote/ConnectMobileView.kt @@ -36,12 +36,10 @@ import dev.icerock.moko.resources.compose.painterResource import dev.icerock.moko.resources.compose.stringResource @Composable -fun ConnectMobileView( - m: ChatModel -) { +fun ConnectMobileView() { val connecting = rememberSaveable() { mutableStateOf(false) } val remoteHosts = remember { chatModel.remoteHosts } - val deviceName = m.controller.appPrefs.deviceNameForRemoteAccess + val deviceName = chatModel.controller.appPrefs.deviceNameForRemoteAccess LaunchedEffect(Unit) { controller.reloadRemoteHosts() } @@ -49,11 +47,11 @@ fun ConnectMobileView( deviceName = remember { deviceName.state }, remoteHosts = remoteHosts, connecting, - connectedHost = remember { m.currentRemoteHost }, + connectedHost = remember { chatModel.currentRemoteHost }, updateDeviceName = { withBGApi { if (it != "") { - m.controller.setLocalDeviceName(it) + chatModel.controller.setLocalDeviceName(it) deviceName.set(it) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpView.kt index c5bde4494..33e183aaa 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/HelpView.kt @@ -26,7 +26,7 @@ fun HelpLayout(userDisplayName: String) { .verticalScroll(rememberScrollState()) .padding(horizontal = DEFAULT_PADDING), ){ - AppBarTitle(String.format(stringResource(MR.strings.personal_welcome), userDisplayName), false) + AppBarTitle(String.format(stringResource(MR.strings.personal_welcome), userDisplayName), withPadding = false) ChatHelpView() } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt index cbcb7344f..66dde9f96 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ProtocolServersView.kt @@ -29,13 +29,12 @@ import kotlinx.coroutines.launch @Composable fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtocol, close: () -> Unit) { - // TODO close if remote host changes - var presetServers by remember { mutableStateOf(emptyList()) } - var servers by remember { + var presetServers by remember(rhId) { mutableStateOf(emptyList()) } + var servers by remember(rhId) { mutableStateOf(m.userSMPServersUnsaved.value ?: emptyList()) } - val currServers = remember { mutableStateOf(servers) } - val testing = rememberSaveable { mutableStateOf(false) } + val currServers = remember(rhId) { mutableStateOf(servers) } + val testing = rememberSaveable(rhId) { mutableStateOf(false) } val serversUnchanged = remember { derivedStateOf { servers == currServers.value || testing.value } } val allServersDisabled = remember { derivedStateOf { servers.all { !it.enabled } } } val saveDisabled = remember { @@ -51,7 +50,12 @@ fun ProtocolServersView(m: ChatModel, rhId: Long?, serverProtocol: ServerProtoco } } - LaunchedEffect(Unit) { + KeyChangeEffect(rhId) { + m.userSMPServersUnsaved.value = null + servers = emptyList() + } + + LaunchedEffect(rhId) { val res = m.controller.getUserProtoServers(rhId, serverProtocol) if (res != null) { currServers.value = res.protoServers diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt index ac74bd04d..77cb0ead1 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/ScanProtocolServer.kt @@ -22,7 +22,7 @@ fun ScanProtocolServerLayout(rhId: Long?, onNext: (ServerCfg) -> Unit) { .fillMaxSize() .padding(horizontal = DEFAULT_PADDING) ) { - AppBarTitle(stringResource(MR.strings.smp_servers_scan_qr), false) + AppBarTitle(stringResource(MR.strings.smp_servers_scan_qr), withPadding = false) Box( Modifier .fillMaxWidth() diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt index 7bd060e8d..4e86d33a4 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/SettingsView.kt @@ -158,7 +158,7 @@ fun SettingsLayout( SettingsActionItem(painterResource(MR.images.ic_qr_code), stringResource(MR.strings.your_simplex_contact_address), showCustomModal { it, close -> UserAddressView(it, it.currentUser.value?.remoteHostId, shareViaProfile = it.currentUser.value!!.addressShared, close = close) }, disabled = stopped, extraPadding = true) ChatPreferencesItem(showCustomModal, stopped = stopped) if (appPlatform.isDesktop) { - SettingsActionItem(painterResource(MR.images.ic_smartphone), stringResource(if (remember { chatModel.remoteHosts }.isEmpty()) MR.strings.link_a_mobile else MR.strings.linked_mobiles), showModal { ConnectMobileView(it) }, disabled = stopped, extraPadding = true) + SettingsActionItem(painterResource(MR.images.ic_smartphone), stringResource(if (remember { chatModel.remoteHosts }.isEmpty()) MR.strings.link_a_mobile else MR.strings.linked_mobiles), showModal { ConnectMobileView() }, disabled = stopped, extraPadding = true) } else { SettingsActionItem(painterResource(MR.images.ic_desktop), stringResource(MR.strings.settings_section_title_use_from_desktop), showCustomModal{ it, close -> ConnectDesktopView(close) }, disabled = stopped, extraPadding = true) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt index 98989a775..d24824108 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/UserAddressView.kt @@ -65,6 +65,7 @@ fun UserAddressView( UserAddressLayout( userAddress = userAddress.value, shareViaProfile, + rhId, onCloseHandler, createAddress = { withApi { @@ -169,6 +170,7 @@ fun UserAddressView( private fun UserAddressLayout( userAddress: UserContactLinkRec?, shareViaProfile: MutableState, + rhId: Long?, onCloseHandler: MutableState<(close: () -> Unit) -> Unit>, createAddress: () -> Unit, learnMore: () -> Unit, @@ -181,7 +183,7 @@ private fun UserAddressLayout( Column( Modifier.verticalScroll(rememberScrollState()), ) { - AppBarTitle(stringResource(MR.strings.simplex_address), false) + AppBarTitle(stringResource(MR.strings.simplex_address), hostDevice(rhId), withPadding = false) Column( Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF), horizontalAlignment = Alignment.CenterHorizontally, @@ -438,6 +440,7 @@ fun PreviewUserAddressLayoutNoAddress() { setProfileAddress = { _ -> }, learnMore = {}, shareViaProfile = remember { mutableStateOf(false) }, + rhId = null, onCloseHandler = remember { mutableStateOf({}) }, sendEmail = {}, ) @@ -471,6 +474,7 @@ fun PreviewUserAddressLayoutAddressCreated() { setProfileAddress = { _ -> }, learnMore = {}, shareViaProfile = remember { mutableStateOf(false) }, + rhId = null, onCloseHandler = remember { mutableStateOf({}) }, sendEmail = {}, ) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt index 010b94e03..06a476221 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/VersionInfoView.kt @@ -18,7 +18,7 @@ fun VersionInfoView(info: CoreVersionInfo) { Column( Modifier.padding(horizontal = DEFAULT_PADDING), ) { - AppBarTitle(stringResource(MR.strings.app_version_title), false) + AppBarTitle(stringResource(MR.strings.app_version_title), withPadding = false) if (appPlatform.isAndroid) { Text(String.format(stringResource(MR.strings.app_version_name), BuildConfigCommon.ANDROID_VERSION_NAME)) Text(String.format(stringResource(MR.strings.app_version_code), BuildConfigCommon.ANDROID_VERSION_CODE))