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 54986e1815..02353e2c8a 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 @@ -1607,7 +1607,7 @@ object ChatController { suspend fun apiPrepareContact(rh: Long?, connLink: CreatedConnLink, contactShortLinkData: ContactShortLinkData): Chat? { val userId = try { currentUserId("apiPrepareContact") } catch (e: Exception) { return null } val r = sendCmd(rh, CC.APIPrepareContact(userId, connLink, contactShortLinkData)) - if (r is API.Result && r.res is CR.NewPreparedChat) return r.res.chat + if (r is API.Result && r.res is CR.NewPreparedChat) return if (rh == null) r.res.chat else r.res.chat.copy(remoteHostId = rh) Log.e(TAG, "apiPrepareContact bad response: ${r.responseType} ${r.details}") AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_preparing_contact), "${r.responseType}: ${r.details}") return null @@ -1616,7 +1616,7 @@ object ChatController { suspend fun apiPrepareGroup(rh: Long?, connLink: CreatedConnLink, directLink: Boolean, groupShortLinkData: GroupShortLinkData): Chat? { val userId = try { currentUserId("apiPrepareGroup") } catch (e: Exception) { return null } val r = sendCmd(rh, CC.APIPrepareGroup(userId, connLink, directLink, groupShortLinkData)) - if (r is API.Result && r.res is CR.NewPreparedChat) return r.res.chat + if (r is API.Result && r.res is CR.NewPreparedChat) return if (rh == null) r.res.chat else r.res.chat.copy(remoteHostId = rh) Log.e(TAG, "apiPrepareGroup bad response: ${r.responseType} ${r.details}") AlertManager.shared.showAlertMsg(generalGetString(MR.strings.error_preparing_group), "${r.responseType}: ${r.details}") return null @@ -2172,8 +2172,8 @@ object ChatController { return null } - suspend fun apiGetGroupRelays(groupId: Long): List { - val r = sendCmd(null, CC.ApiGetGroupRelays(groupId)) + suspend fun apiGetGroupRelays(rh: Long?, groupId: Long): List { + val r = sendCmd(rh, CC.ApiGetGroupRelays(groupId)) if (r is API.Result && r.res is CR.GroupRelays) return r.res.groupRelays return emptyList() } @@ -2183,8 +2183,8 @@ object ChatController { data class AddFailed(val addRelayResults: List): AddGroupRelaysResult() } - suspend fun apiAddGroupRelays(groupId: Long, relayIds: List): AddGroupRelaysResult? { - val r = sendCmdWithRetry(null, CC.ApiAddGroupRelays(groupId, relayIds)) + suspend fun apiAddGroupRelays(rh: Long?, groupId: Long, relayIds: List): AddGroupRelaysResult? { + val r = sendCmdWithRetry(rh, CC.ApiAddGroupRelays(groupId, relayIds)) if (r is API.Result && r.res is CR.GroupRelaysAdded) return AddGroupRelaysResult.Added(r.res.groupInfo, r.res.groupLink, r.res.groupRelays) if (r is API.Result && r.res is CR.GroupRelaysAddFailed) return AddGroupRelaysResult.AddFailed(r.res.addRelayResults) if (r != null) throw Exception("${r.responseType}: ${r.details}") diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt index cc9e71354c..765759d9e0 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/ChatView.kt @@ -208,7 +208,7 @@ fun ChatView( withBGApi { setGroupMembers(chatRh, cInfo.groupInfo, chatModel) if (cInfo.groupInfo.membership.memberRole == GroupMemberRole.Owner) { - val relays = chatModel.controller.apiGetGroupRelays(cInfo.groupInfo.groupId) + val relays = chatModel.controller.apiGetGroupRelays(chatRh, cInfo.groupInfo.groupId) withContext(Dispatchers.Main) { ChannelRelaysModel.set(cInfo.groupInfo.groupId, relays) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt index 1ed75bd2a2..95ce003caa 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/AddGroupRelayView.kt @@ -31,6 +31,7 @@ data class AvailableRelay( @Composable fun AddGroupRelayView( + rhId: Long?, groupInfo: GroupInfo, existingRelayIds: Set, onRelayAdded: () -> Unit, @@ -46,7 +47,7 @@ fun AddGroupRelayView( LaunchedEffect(Unit) { try { - val servers = ChatController.getUserServers(null) + val servers = ChatController.getUserServers(rhId) if (servers != null) { val relays = mutableListOf() for (op in servers) { @@ -80,7 +81,7 @@ fun AddGroupRelayView( if (relayIds.isEmpty()) return@AddGroupRelayLayout isAdding = true scope.launch { - addSelectedRelays(groupInfo, relayIds, selectedRelayIds, availableRelays, onRelayAdded, close) { newSelectedIds, newAvailableRelays -> + addSelectedRelays(rhId, groupInfo, relayIds, selectedRelayIds, availableRelays, onRelayAdded, close) { newSelectedIds, newAvailableRelays -> selectedRelayIds = newSelectedIds availableRelays = newAvailableRelays isAdding = false @@ -183,6 +184,7 @@ private fun AddRelaysButton(onClick: () -> Unit, disabled: Boolean) { } private suspend fun addSelectedRelays( + rhId: Long?, groupInfo: GroupInfo, relayIds: List, selectedRelayIds: Set, @@ -192,7 +194,7 @@ private suspend fun addSelectedRelays( updateState: (Set, List) -> Unit ) { try { - val result = ChatController.apiAddGroupRelays(groupInfo.groupId, relayIds) + val result = ChatController.apiAddGroupRelays(rhId, groupInfo.groupId, relayIds) if (result == null) { updateState(selectedRelayIds, availableRelays) return diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt index d7ffde71c8..60cc19bb1b 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelRelaysView.kt @@ -37,7 +37,7 @@ fun ChannelRelaysView( LaunchedEffect(Unit) { setGroupMembers(rhId, groupInfo, chatModel) if (groupInfo.isOwner) { - val relays = chatModel.controller.apiGetGroupRelays(groupInfo.groupId) + val relays = chatModel.controller.apiGetGroupRelays(rhId, groupInfo.groupId) ChannelRelaysModel.set(groupId = groupInfo.groupId, groupRelays = relays) } } @@ -114,6 +114,7 @@ private fun ChannelRelaysLayout( val existingRelayIds = groupRelays.mapNotNull { it.userChatRelay.chatRelayId }.toSet() ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> AddGroupRelayView( + rhId = rhId, groupInfo = groupInfo, existingRelayIds = existingRelayIds, onRelayAdded = { withBGApi { setGroupMembers(rhId, groupInfo, chatModel) } }, diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt index 98067e49dd..262a78b3c8 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/chat/group/ChannelWebPageView.kt @@ -81,7 +81,7 @@ fun ChannelWebPageView( } LaunchedEffect(Unit) { - val relays = chatModel.controller.apiGetGroupRelays(groupInfo.groupId) + val relays = chatModel.controller.apiGetGroupRelays(rhId, groupInfo.groupId) groupRelays.clear() groupRelays.addAll(relays) } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt index b5188178fa..639a5cc78e 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/AddChannelView.kt @@ -38,7 +38,8 @@ import dev.icerock.moko.resources.compose.painterResource import kotlinx.coroutines.* @Composable -fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit) { +fun AddChannelView(chatModel: ChatModel, rh: RemoteHostInfo?, close: () -> Unit, closeAll: () -> Unit) { + val rhId = rh?.remoteHostId val view = LocalMultiplatformView() val bottomSheetModalState = rememberModalBottomSheetState(initialValue = ModalBottomSheetValue.Hidden) val scope = rememberCoroutineScope() @@ -56,7 +57,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit val gInfo = groupInfo.value if (showLinkStep.value && gInfo != null) { - LinkStepView(chatModel, gInfo, groupLink, closeAll) + LinkStepView(chatModel, rhId, gInfo, groupLink, closeAll) } else if (gInfo != null) { ProgressStepView( chatModel, gInfo, groupRelays, relayListExpanded, @@ -65,9 +66,9 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit chatModel.creatingChannelId.value = null closeAll() withBGApi { - openGroupChat(null, gInfo.groupId) + openGroupChat(rhId, gInfo.groupId) ModalManager.end.showModalCloseable(showClose = true, cardScreen = true) { close -> - GroupLinkView(chatModel, rhId = null, groupInfo = gInfo, groupLink = groupLink.value, onGroupLinkUpdated = null, creatingGroup = true, isChannel = true, shareGroupInfo = gInfo, close = close) + GroupLinkView(chatModel, rhId = rhId, groupInfo = gInfo, groupLink = groupLink.value, onGroupLinkUpdated = null, creatingGroup = true, isChannel = true, shareGroupInfo = gInfo, close = close) } } } @@ -80,9 +81,9 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit closeAll() withBGApi { try { - chatModel.controller.apiDeleteChat(rh = null, type = ChatType.Group, id = gInfo.apiId) + chatModel.controller.apiDeleteChat(rh = rhId, type = ChatType.Group, id = gInfo.apiId) withContext(Dispatchers.Main) { - chatModel.chatsContext.removeChat(null, gInfo.id) + chatModel.chatsContext.removeChat(rhId, gInfo.id) } } catch (e: Exception) { Log.e(TAG, "cancelChannelCreation error: ${e.message}") @@ -93,6 +94,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit } else { ProfileStepView( chatModel = chatModel, + rhId = rhId, displayName = displayName, profileImage = profileImage, chosenImage = chosenImage, @@ -120,7 +122,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit creationInProgress.value = true withBGApi { try { - val enabledRelays = chooseRandomRelays() + val enabledRelays = chooseRandomRelays(rhId) val relayIds = enabledRelays.mapNotNull { it.chatRelayId } if (relayIds.isEmpty()) { withContext(Dispatchers.Main) { @@ -130,7 +132,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit return@withBGApi } val result = chatModel.controller.apiNewPublicGroup( - rh = null, + rh = rhId, incognito = false, relayIds = relayIds, groupProfile = profile @@ -138,7 +140,7 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit when (result) { is ChatController.PublicGroupCreationResult.Created -> { withContext(Dispatchers.Main) { - chatModel.chatsContext.updateGroup(rhId = null, result.groupInfo) + chatModel.chatsContext.updateGroup(rhId = rhId, result.groupInfo) chatModel.creatingChannelId.value = result.groupInfo.id groupInfo.value = result.groupInfo groupLink.value = result.groupLink @@ -178,8 +180,8 @@ fun AddChannelView(chatModel: ChatModel, close: () -> Unit, closeAll: () -> Unit private const val maxRelays = 3 -private suspend fun chooseRandomRelays(): List { - val servers = getUserServers(rh = null) ?: return emptyList() +private suspend fun chooseRandomRelays(rhId: Long?): List { + val servers = getUserServers(rh = rhId) ?: return emptyList() // Operator relays are grouped per operator; custom relays (null operator) // are treated independently to maximize trust distribution. val operatorGroups = mutableListOf>() @@ -215,8 +217,8 @@ private suspend fun chooseRandomRelays(): List { return selected } -private suspend fun checkHasRelays(): Boolean { - val servers = try { getUserServers(rh = null) } catch (_: Exception) { null } ?: return false +private suspend fun checkHasRelays(rhId: Long?): Boolean { + val servers = try { getUserServers(rh = rhId) } catch (_: Exception) { null } ?: return false return servers.any { op -> (op.operator?.enabled ?: true) && op.chatRelays.any { it.enabled && !it.deleted && it.chatRelayId != null } @@ -226,6 +228,7 @@ private suspend fun checkHasRelays(): Boolean { @Composable private fun ProfileStepView( chatModel: ChatModel, + rhId: Long?, displayName: MutableState, profileImage: MutableState, chosenImage: MutableState, @@ -239,7 +242,7 @@ private fun ProfileStepView( createChannel: () -> Unit ) { LaunchedEffect(Unit) { - hasRelays.value = checkHasRelays() + hasRelays.value = checkHasRelays(rhId) } ModalBottomSheetLayout( @@ -553,6 +556,7 @@ private fun RelayRow(relay: GroupRelay, connFailed: Boolean) { @Composable private fun LinkStepView( chatModel: ChatModel, + rhId: Long?, gInfo: GroupInfo, groupLink: MutableState, closeAll: () -> Unit @@ -563,14 +567,14 @@ private fun LinkStepView( delay(500) withContext(Dispatchers.Main) { ModalManager.start.closeModals() - openGroupChat(null, gInfo.groupId) + openGroupChat(rhId, gInfo.groupId) } } } ModalView(close = close, showClose = false, cardScreen = true) { GroupLinkView( chatModel = chatModel, - rhId = null, + rhId = rhId, groupInfo = gInfo, groupLink = groupLink.value, onGroupLinkUpdated = { groupLink.value = it }, @@ -660,6 +664,6 @@ fun RelayProgressIndicator(active: Int, total: Int) { @Composable fun PreviewAddChannelView() { SimpleXTheme { - AddChannelView(chatModel = ChatModel, close = {}, closeAll = {}) + AddChannelView(chatModel = ChatModel, rh = null, close = {}, closeAll = {}) } } diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt index af7f59496b..68f42f4186 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/newchat/NewChatSheet.kt @@ -64,7 +64,7 @@ fun ModalData.NewChatSheet(rh: RemoteHostInfo?, close: () -> Unit) { ModalManager.start.showCustomModal { close -> AddGroupView(chatModel, chatModel.currentRemoteHost.value, close, closeAll) } }, createChannel = { - ModalManager.start.showCustomModal { close -> AddChannelView(chatModel, close, closeAll) } + ModalManager.start.showCustomModal { close -> AddChannelView(chatModel, chatModel.currentRemoteHost.value, close, closeAll) } }, rh = rh, close = close