diff --git a/apps/ios/Shared/Model/AppAPITypes.swift b/apps/ios/Shared/Model/AppAPITypes.swift index 44a03aa037..855f3380cc 100644 --- a/apps/ios/Shared/Model/AppAPITypes.swift +++ b/apps/ios/Shared/Model/AppAPITypes.swift @@ -1111,7 +1111,6 @@ enum ChatEvent: Decodable, ChatAPIResult { case connectedToGroupMember(user: UserRef, groupInfo: GroupInfo, member: GroupMember, memberContact: Contact?) case groupUpdated(user: UserRef, toGroup: GroupInfo) case groupLinkDataUpdated(user: UserRef, groupInfo: GroupInfo, groupLink: GroupLink, groupRelays: [GroupRelay], relaysChanged: Bool) - case groupRelayUpdated(user: UserRef, groupInfo: GroupInfo, member: GroupMember, groupRelay: GroupRelay) case newMemberContactReceivedInv(user: UserRef, contact: Contact, groupInfo: GroupInfo, member: GroupMember) // receiving file events case rcvFileAccepted(user: UserRef, chatItem: AChatItem) @@ -1189,7 +1188,6 @@ enum ChatEvent: Decodable, ChatAPIResult { case .connectedToGroupMember: "connectedToGroupMember" case .groupUpdated: "groupUpdated" case .groupLinkDataUpdated: "groupLinkDataUpdated" - case .groupRelayUpdated: "groupRelayUpdated" case .newMemberContactReceivedInv: "newMemberContactReceivedInv" case .rcvFileAccepted: "rcvFileAccepted" case .rcvFileAcceptedSndCancelled: "rcvFileAcceptedSndCancelled" @@ -1271,7 +1269,6 @@ enum ChatEvent: Decodable, ChatAPIResult { case let .connectedToGroupMember(u, groupInfo, member, memberContact): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\nmemberContact: \(String(describing: memberContact))") case let .groupUpdated(u, toGroup): return withUser(u, String(describing: toGroup)) case let .groupLinkDataUpdated(u, groupInfo, groupLink, groupRelays, relaysChanged): return withUser(u, "groupInfo: \(groupInfo)\ngroupLink: \(groupLink)\ngroupRelays: \(groupRelays)\nrelaysChanged: \(relaysChanged)") - case let .groupRelayUpdated(u, groupInfo, member, groupRelay): return withUser(u, "groupInfo: \(groupInfo)\nmember: \(member)\ngroupRelay: \(groupRelay)") case let .newMemberContactReceivedInv(u, contact, groupInfo, member): return withUser(u, "contact: \(contact)\ngroupInfo: \(groupInfo)\nmember: \(member)") case let .rcvFileAccepted(u, chatItem): return withUser(u, String(describing: chatItem)) case .rcvFileAcceptedSndCancelled: return noDetails diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 9c23ac6307..5e85417326 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -343,13 +343,6 @@ class ChannelRelaysModel: ObservableObject { self.groupRelays = groupRelays } - func updateRelay(_ groupInfo: GroupInfo, _ relay: GroupRelay) { - if groupId == groupInfo.groupId, - let i = groupRelays.firstIndex(where: { $0.groupRelayId == relay.groupRelayId }) { - groupRelays[i] = relay - } - } - func reset() { groupId = nil groupRelays = [] diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 9e4f50b0af..1119f28bac 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -2594,13 +2594,6 @@ func processReceivedMsg(_ res: ChatEvent) async { } } } - case let .groupRelayUpdated(user, groupInfo, member, groupRelay): - if active(user) { - await MainActor.run { - _ = m.upsertGroupMember(groupInfo, member) - ChannelRelaysModel.shared.updateRelay(groupInfo, groupRelay) - } - } case let .memberRole(user, groupInfo, byMember: _, member: member, fromRole: _, toRole: _): if active(user) { await MainActor.run { diff --git a/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift b/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift index 56ee370402..13b6c0e682 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupLinkView.swift @@ -105,6 +105,7 @@ struct GroupLinkView: View { Label("Share link", systemImage: "square.and.arrow.up") } + // TODO [relays] review: channel link deletion is only possible together with deleting the channel if !creatingGroup && !isChannel { Button(role: .destructive) { alert = .deleteLink } label: { Label("Delete link", systemImage: "trash") diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index af7054db01..442f547b9c 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -172,6 +172,7 @@ struct GroupMemberInfoView: View { let label: LocalizedStringKey = groupInfo.useRelays ? "Channel" : groupInfo.businessChat == nil ? "Group" : "Chat" infoRow(label, groupInfo.displayName) + // TODO [relays] review: role changing is not supported for channels currently if !groupInfo.useRelays, let roles = member.canChangeRoleTo(groupInfo: groupInfo) { Picker("Change role", selection: $newRole) { ForEach(roles) { role in @@ -636,7 +637,7 @@ struct GroupMemberInfoView: View { } } // TODO [relays] removing relay should also remove its link from group link data; - // TODO - removing last relay should be prohibited or show warning + // removing last relay should be prohibited or show warning if canRemove && mem.memberRole != .relay { if mem.memberStatus == .memRemoved || mem.memberStatus == .memLeft { deleteMemberMessagesButton(mem) diff --git a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ChatRelayView.swift b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ChatRelayView.swift index df9ea10adf..14c6b61a34 100644 --- a/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ChatRelayView.swift +++ b/apps/ios/Shared/Views/UserSettings/NetworkAndServers/ChatRelayView.swift @@ -50,6 +50,7 @@ func validRelayAddress(_ address: String) -> Bool { } } +// TODO [relays] TBC matching relay to operator by domain (relay address can be hosted on operator server) func addChatRelay( _ relay: UserChatRelay, _ userServers: Binding<[UserOperatorServers]>, diff --git a/apps/ios/SimpleX.xcodeproj/project.pbxproj b/apps/ios/SimpleX.xcodeproj/project.pbxproj index dcd8673de8..0f3230e737 100644 --- a/apps/ios/SimpleX.xcodeproj/project.pbxproj +++ b/apps/ios/SimpleX.xcodeproj/project.pbxproj @@ -182,8 +182,8 @@ 64C3B0212A0D359700E19930 /* CustomTimePicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */; }; 64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829982D54AEED006B9E89 /* libgmp.a */; }; 64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C829992D54AEEE006B9E89 /* libffi.a */; }; - 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a */; }; - 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a */; }; + 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a */; }; + 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a */; }; 64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */; }; 64D0C2C029F9688300B38D5F /* UserAddressView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */; }; 64D0C2C229FA57AB00B38D5F /* UserAddressLearnMore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */; }; @@ -553,8 +553,8 @@ 64C3B0202A0D359700E19930 /* CustomTimePicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomTimePicker.swift; sourceTree = ""; }; 64C829982D54AEED006B9E89 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = ""; }; 64C829992D54AEEE006B9E89 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = ""; }; - 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a"; sourceTree = ""; }; - 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a"; sourceTree = ""; }; + 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a"; sourceTree = ""; }; + 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a"; sourceTree = ""; }; 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = ""; }; 64D0C2BF29F9688300B38D5F /* UserAddressView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressView.swift; sourceTree = ""; }; 64D0C2C129FA57AB00B38D5F /* UserAddressLearnMore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAddressLearnMore.swift; sourceTree = ""; }; @@ -716,8 +716,8 @@ 64C8299D2D54AEEE006B9E89 /* libgmp.a in Frameworks */, 64C8299E2D54AEEE006B9E89 /* libffi.a in Frameworks */, 64C829A12D54AEEE006B9E89 /* libgmpxx.a in Frameworks */, - 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a in Frameworks */, - 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a in Frameworks */, + 64C8299F2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a in Frameworks */, + 64C829A02D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a in Frameworks */, CE38A29C2C3FCD72005ED185 /* SwiftyGif in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -803,8 +803,8 @@ 64C829992D54AEEE006B9E89 /* libffi.a */, 64C829982D54AEED006B9E89 /* libgmp.a */, 64C8299C2D54AEEE006B9E89 /* libgmpxx.a */, - 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt-ghc9.6.3.a */, - 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-1LMKtNtYaECIyeIru99CUt.a */, + 64C8299A2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo-ghc9.6.3.a */, + 64C8299B2D54AEEE006B9E89 /* libHSsimplex-chat-6.5.0.9-IckAKQLBKZZ3c4EBa1qhzo.a */, ); path = Libraries; sourceTree = ""; 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 817337ddca..20358f75de 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 @@ -88,13 +88,6 @@ object ChannelRelaysModel { this.groupRelays.addAll(groupRelays) } - fun updateRelay(groupInfo: GroupInfo, relay: GroupRelay) { - if (groupId.value == groupInfo.groupId) { - val i = groupRelays.indexOfFirst { it.groupRelayId == relay.groupRelayId } - if (i >= 0) groupRelays[i] = relay - } - } - fun reset() { groupId.value = null groupRelays.clear() 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 779209a00f..723e7bdc25 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 @@ -2993,13 +2993,6 @@ object ChatController { } } } - is CR.GroupRelayUpdated -> - if (active(r.user)) { - withContext(Dispatchers.Main) { - chatModel.chatsContext.upsertGroupMember(rhId, r.groupInfo, r.member) - ChannelRelaysModel.updateRelay(r.groupInfo, r.groupRelay) - } - } is CR.NewMemberContactReceivedInv -> if (active(r.user)) { withContext(Dispatchers.Main) { @@ -6308,7 +6301,6 @@ sealed class CR { @Serializable @SerialName("connectedToGroupMember") class ConnectedToGroupMember(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val memberContact: Contact? = null): CR() @Serializable @SerialName("groupUpdated") class GroupUpdated(val user: UserRef, val toGroup: GroupInfo): CR() @Serializable @SerialName("groupLinkDataUpdated") class GroupLinkDataUpdated(val user: UserRef, val groupInfo: GroupInfo, val groupLink: GroupLink, val groupRelays: List, val relaysChanged: Boolean): CR() - @Serializable @SerialName("groupRelayUpdated") class GroupRelayUpdated(val user: UserRef, val groupInfo: GroupInfo, val member: GroupMember, val groupRelay: GroupRelay): CR() @Serializable @SerialName("groupLinkCreated") class GroupLinkCreated(val user: UserRef, val groupInfo: GroupInfo, val groupLink: GroupLink): CR() @Serializable @SerialName("groupLink") class CRGroupLink(val user: UserRef, val groupInfo: GroupInfo, val groupLink: GroupLink): CR() @Serializable @SerialName("groupLinkDeleted") class GroupLinkDeleted(val user: UserRef, val groupInfo: GroupInfo): CR() @@ -6494,7 +6486,6 @@ sealed class CR { is ConnectedToGroupMember -> "connectedToGroupMember" is GroupUpdated -> "groupUpdated" is GroupLinkDataUpdated -> "groupLinkDataUpdated" - is GroupRelayUpdated -> "groupRelayUpdated" is GroupLinkCreated -> "groupLinkCreated" is CRGroupLink -> "groupLink" is GroupLinkDeleted -> "groupLinkDeleted" @@ -6673,7 +6664,6 @@ sealed class CR { is ConnectedToGroupMember -> withUser(user, "groupInfo: $groupInfo\nmember: $member\nmemberContact: $memberContact") is GroupUpdated -> withUser(user, json.encodeToString(toGroup)) is GroupLinkDataUpdated -> withUser(user, "groupInfo: $groupInfo\ngroupLink: $groupLink\ngroupRelays: $groupRelays\nrelaysChanged: $relaysChanged") - is GroupRelayUpdated -> withUser(user, "groupInfo: $groupInfo\nmember: $member\ngroupRelay: $groupRelay") is GroupLinkCreated -> withUser(user, "groupInfo: $groupInfo\ngroupLink: $groupLink") is CRGroupLink -> withUser(user, "groupInfo: $groupInfo\ngroupLink: $groupLink") is GroupLinkDeleted -> withUser(user, json.encodeToString(groupInfo)) diff --git a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt index 646ca816e7..4611f62991 100644 --- a/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt +++ b/apps/multiplatform/common/src/commonMain/kotlin/chat/simplex/common/views/usersettings/networkAndServers/ChatRelayView.kt @@ -62,6 +62,7 @@ fun validRelayAddress(address: String): Boolean { (parsedMd.first().format as Format.SimplexLink).linkType == SimplexLinkType.relay } +// TODO [relays] TBC matching relay to operator by domain (relay address can be hosted on operator server) fun addChatRelay( relay: UserChatRelay, userServers: MutableState>, diff --git a/bots/api/EVENTS.md b/bots/api/EVENTS.md index 947c60586a..bc99f68c4b 100644 --- a/bots/api/EVENTS.md +++ b/bots/api/EVENTS.md @@ -39,7 +39,6 @@ This file is generated automatically. - [MemberBlockedForAll](#memberblockedforall) - [GroupMemberUpdated](#groupmemberupdated) - [GroupLinkDataUpdated](#grouplinkdataupdated) - - [GroupRelayUpdated](#grouprelayupdated) [File events](#file-events) - Main events @@ -469,20 +468,6 @@ Group link data updated. --- -### GroupRelayUpdated - -Group relay member updated. - -**Record type**: -- type: "groupRelayUpdated" -- user: [User](./TYPES.md#user) -- groupInfo: [GroupInfo](./TYPES.md#groupinfo) -- member: [GroupMember](./TYPES.md#groupmember) -- groupRelay: [GroupRelay](./TYPES.md#grouprelay) - ---- - - ## File events Bots that send or receive files may process these events to track delivery status and to process completion. diff --git a/bots/src/API/Docs/Events.hs b/bots/src/API/Docs/Events.hs index c8446e9e67..0d1998aa28 100644 --- a/bots/src/API/Docs/Events.hs +++ b/bots/src/API/Docs/Events.hs @@ -98,8 +98,7 @@ chatEventsDocsData = ("CEvtMemberAcceptedByOther", "Another group owner, admin or moderator accepted member to the group after review (\"knocking\")."), ("CEvtMemberBlockedForAll", "Another member blocked for all members."), ("CEvtGroupMemberUpdated", "Another group member profile updated."), - ("CEvtGroupLinkDataUpdated", "Group link data updated."), - ("CEvtGroupRelayUpdated", "Group relay member updated.") + ("CEvtGroupLinkDataUpdated", "Group link data updated.") ] ), ( "File events", diff --git a/cabal.project b/cabal.project index 1223e93ea6..5b75f49edb 100644 --- a/cabal.project +++ b/cabal.project @@ -21,7 +21,7 @@ constraints: zip +disable-bzip2 +disable-zstd source-repository-package type: git location: https://github.com/simplex-chat/simplexmq.git - tag: fc1272d6144f13fa7e92b3dd6202e35c52cd75e2 + tag: 782cacfb3cc57883465eecc0b9b30662daf2b81f source-repository-package type: git diff --git a/packages/simplex-chat-client/types/typescript/src/events.ts b/packages/simplex-chat-client/types/typescript/src/events.ts index cc19305913..b0b9b31fb4 100644 --- a/packages/simplex-chat-client/types/typescript/src/events.ts +++ b/packages/simplex-chat-client/types/typescript/src/events.ts @@ -30,7 +30,6 @@ export type ChatEvent = | CEvt.MemberBlockedForAll | CEvt.GroupMemberUpdated | CEvt.GroupLinkDataUpdated - | CEvt.GroupRelayUpdated | CEvt.RcvFileDescrReady | CEvt.RcvFileComplete | CEvt.SndFileCompleteXFTP @@ -83,7 +82,6 @@ export namespace CEvt { | "memberBlockedForAll" | "groupMemberUpdated" | "groupLinkDataUpdated" - | "groupRelayUpdated" | "rcvFileDescrReady" | "rcvFileComplete" | "sndFileCompleteXFTP" @@ -316,14 +314,6 @@ export namespace CEvt { relaysChanged: boolean } - export interface GroupRelayUpdated extends Interface { - type: "groupRelayUpdated" - user: T.User - groupInfo: T.GroupInfo - member: T.GroupMember - groupRelay: T.GroupRelay - } - export interface RcvFileDescrReady extends Interface { type: "rcvFileDescrReady" user: T.User diff --git a/scripts/nix/sha256map.nix b/scripts/nix/sha256map.nix index 978185a416..27a906fb52 100644 --- a/scripts/nix/sha256map.nix +++ b/scripts/nix/sha256map.nix @@ -1,5 +1,5 @@ { - "https://github.com/simplex-chat/simplexmq.git"."fc1272d6144f13fa7e92b3dd6202e35c52cd75e2" = "072bgw44fsq2r9vbrphr2xkydcksfvxna7m6ln5rfc60dbkajisl"; + "https://github.com/simplex-chat/simplexmq.git"."782cacfb3cc57883465eecc0b9b30662daf2b81f" = "0ck5hcj2yn540l11bbhn0ghgk49mfyqy0c4xqkbw1kk0fd9hhxs6"; "https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38"; "https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d"; "https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl"; diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index d82ffb255f..f1205e3dfb 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -858,7 +858,6 @@ data ChatEvent | CEvtReceivedGroupInvitation {user :: User, groupInfo :: GroupInfo, contact :: Contact, fromMemberRole :: GroupMemberRole, memberRole :: GroupMemberRole} | CEvtUserJoinedGroup {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember} | CEvtGroupLinkDataUpdated {user :: User, groupInfo :: GroupInfo, groupLink :: GroupLink, groupRelays :: [GroupRelay], relaysChanged :: Bool} - | CEvtGroupRelayUpdated {user :: User, groupInfo :: GroupInfo, member :: GroupMember, groupRelay :: GroupRelay} | CEvtJoinedGroupMember {user :: User, groupInfo :: GroupInfo, member :: GroupMember} -- there is the same command response | CEvtJoinedGroupMemberConnecting {user :: User, groupInfo :: GroupInfo, hostMember :: GroupMember, member :: GroupMember} | CEvtMemberAcceptedByOther {user :: User, groupInfo :: GroupInfo, acceptingMember :: GroupMember, member :: GroupMember} diff --git a/src/Simplex/Chat/Library/Commands.hs b/src/Simplex/Chat/Library/Commands.hs index 0143844c6c..c9d85b9f45 100644 --- a/src/Simplex/Chat/Library/Commands.hs +++ b/src/Simplex/Chat/Library/Commands.hs @@ -1841,7 +1841,7 @@ processChatCommand vr nm = \case let userData = contactShortLinkData (userProfileDirect user incognitoProfile Nothing True) Nothing userLinkData = UserInvLinkData userData -- TODO [certs rcv] - (connId, (_, ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) Nothing True False SCMInvitation (Just userLinkData) Nothing IKPQOn subMode + (connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) True False SCMInvitation (Just userLinkData) Nothing IKPQOn subMode ccLink' <- shortenCreatedLink ccLink -- TODO PQ pass minVersion from the current range conn <- withFastStore' $ \db -> createDirectConnection db user connId ccLink' Nothing ConnNew incognitoProfile subMode initialChatVersion PQSupportOn @@ -1883,7 +1883,7 @@ processChatCommand vr nm = \case | short = Just $ UserInvLinkData $ contactShortLinkData (userProfileDirect newUser Nothing Nothing True) Nothing | otherwise = Nothing -- TODO [certs rcv] - (agConnId, (_, ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId newUser) Nothing True False SCMInvitation userLinkData_ Nothing IKPQOn subMode + (agConnId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId newUser) True False SCMInvitation userLinkData_ Nothing IKPQOn subMode ccLink' <- shortenCreatedLink ccLink conn' <- withFastStore' $ \db -> do deleteConnectionRecord db user connId @@ -2067,19 +2067,18 @@ processChatCommand vr nm = \case _ -> False connectToRelay gInfo' relayLink = do gVar <- asks random + -- TODO [relays] member: set relay profile before/during connection + -- TODO - on fetching relay link data? (-> relay should add profile to relay link) + -- TODO - or update upon connection, as in regular prepared groups + -- TODO (current logic mimics insertHost_ from createPreparedGroup) -- Save relayLink to re-use relay member record on retry (check by relayLink) relayMember <- withFastStore $ \db -> getCreateRelayForMember db vr gVar user gInfo' relayLink r <- tryAllErrors $ do - (fd@FixedLinkData {rootKey = relayKey, linkEntityId}, cData) <- getShortLinkConnReq nm user relayLink - relayLinkData_ <- liftIO $ decodeLinkUserData cData - case (relayLinkData_, linkEntityId) of - (Just RelayShortLinkData {relayProfile = p}, Just entityId) -> - withFastStore $ \db -> updateRelayMemberData db user relayMember (MemberId entityId) (MemberKey relayKey) p - _ -> throwChatError $ CEException "relay link: no relay link data or entity id" + (fd, _cData) <- getShortLinkConnReq nm user relayLink let cReq = linkConnReq fd relayLinkToConnect = CCLink cReq (Just relayLink) void $ connectViaContact user (Just $ PCEGroup gInfo' relayMember) incognito relayLinkToConnect Nothing Nothing - -- Re-read member to get updated activeConn and updated data (from updateRelayMemberData) + -- Re-read member to get updated activeConn relayMember' <- withFastStore $ \db -> getGroupMember db vr user groupId (groupMemberId' relayMember) pure (relayLink, relayMember', r) retryRelayConnectionAsync gInfo' relayLink relayMember@GroupMember {activeConn} = do @@ -2087,7 +2086,7 @@ processChatCommand vr nm = \case deleteAgentConnectionAsync $ aConnId conn withStore' $ \db -> deleteConnectionRecord db user (dbConnId conn) subMode <- chatReadVar subscriptionMode - newConnIds <- getAgentConnShortLinkAsync user CFGetRelayDataJoin Nothing relayLink + newConnIds <- getAgentConnShortLinkAsync user relayLink withStore' $ \db -> createRelayMemberConnectionAsync db user gInfo' relayMember relayLink newConnIds subMode GroupInfo {preparedGroup = Just PreparedGroup {connLinkToConnect, welcomeSharedMsgId, requestSharedMsgId}} -> do hostMember <- withFastStore $ \db -> getHostMember db vr user groupId @@ -2162,11 +2161,13 @@ processChatCommand vr nm = \case Left e -> throwError $ ChatErrorStore e Right _ -> throwError $ ChatErrorStore SEDuplicateContactLink subMode <- chatReadVar subscriptionMode - -- TODO [relays] relay: add relay profile, identity, key to link data? + -- TODO [relays] relay: address creation + -- TODO - add relay key, identity to link data + -- TODO - validate short link is created (returned by agent) let userData = contactShortLinkData (userProfileDirect user Nothing Nothing True) Nothing userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData} -- TODO [certs rcv] - (connId, (_, ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) Nothing True True SCMContact (Just userLinkData) Nothing IKPQOn subMode + (connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) True True SCMContact (Just userLinkData) Nothing IKPQOn subMode ccLink' <- shortenCreatedLink ccLink let ccLink'' = if isTrue userChatRelay then createdRelayLink ccLink' else ccLink' withFastStore $ \db -> createUserContactLink db user connId ccLink'' subMode @@ -2432,7 +2433,7 @@ processChatCommand vr nm = \case gVar <- asks random subMode <- chatReadVar subscriptionMode -- TODO [certs rcv] - (agentConnId, (_, CCLink cReq _, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) Nothing True False SCMInvitation Nothing Nothing IKPQOff subMode + (agentConnId, (CCLink cReq _, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) True False SCMInvitation Nothing Nothing IKPQOff subMode member <- withFastStore $ \db -> createNewContactMember db gVar user gInfo contact memRole agentConnId cReq subMode sendInvitation member cReq pure $ CRSentGroupInvitation user gInfo contact member @@ -2856,7 +2857,7 @@ processChatCommand vr nm = \case userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData} crClientData = encodeJSON $ CRDataGroup groupLinkId -- TODO [certs rcv] - (connId, (_, ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) Nothing True True SCMContact (Just userLinkData) (Just crClientData) IKPQOff subMode + (connId, (ccLink, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) True True SCMContact (Just userLinkData) (Just crClientData) IKPQOff subMode ccLink' <- createdGroupLink <$> shortenCreatedLink ccLink gVar <- asks random gLink <- withFastStore $ \db -> createGroupLink db gVar user gInfo connId ccLink' groupLinkId mRole subMode @@ -2897,7 +2898,7 @@ processChatCommand vr nm = \case subMode <- chatReadVar subscriptionMode -- TODO PQ should negotitate contact connection with PQSupportOn? -- TODO [certs rcv] - (connId, (_, CCLink cReq _, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) Nothing True False SCMInvitation Nothing Nothing IKPQOff subMode + (connId, (CCLink cReq _, _serviceId)) <- withAgent $ \a -> createConnection a nm (aUserId user) True False SCMInvitation Nothing Nothing IKPQOff subMode -- [incognito] reuse membership incognito profile ct <- withFastStore' $ \db -> createMemberContact db user connId cReq g m mConn subMode void $ createChatItem user (CDDirectSnd ct) False CIChatBanner Nothing (Just epochStart) diff --git a/src/Simplex/Chat/Library/Internal.hs b/src/Simplex/Chat/Library/Internal.hs index ff43e70a09..de8511bce9 100644 --- a/src/Simplex/Chat/Library/Internal.hs +++ b/src/Simplex/Chat/Library/Internal.hs @@ -1032,7 +1032,7 @@ acceptBusinessJoinRequestAsync -- TODO [short links] get updated business chat group and member? (currently not used) pure (gInfo, clientMember) -acceptRelayJoinRequestAsync :: User -> Int64 -> GroupInfo -> GroupMember -> InvitationId -> VersionRangeChat -> ShortLinkContact -> CM (GroupInfo, GroupMember) +acceptRelayJoinRequestAsync :: User -> Int64 -> GroupInfo -> GroupMember -> InvitationId -> VersionRangeChat -> ShortLinkContact -> MemberKey -> CM (GroupInfo, GroupMember) acceptRelayJoinRequestAsync user uclId @@ -1040,8 +1040,9 @@ acceptRelayJoinRequestAsync _ownerMember@GroupMember {groupMemberId} cReqInvId cReqChatVRange - relayLink = do - let msg = XGrpRelayAcpt relayLink + relayLink + memberKey = do + let msg = XGrpRelayAcpt relayLink memberKey subMode <- chatReadVar subscriptionMode vr <- chatVersionRange let chatV = vr `peerConnChatVersion` cReqChatVRange @@ -1322,7 +1323,7 @@ updatePublicGroupData user gInfo pure gInfo' | otherwise = pure gInfo --- TODO [relays] owner: set owners on updating link data (multi-owner) +-- TODO [relays] owner: set owners on updating link data groupLinkData :: GroupInfo -> GroupLink -> [GroupRelay] -> (UserConnLinkData 'CMContact, CRClientData) groupLinkData gInfo@GroupInfo {groupProfile, groupSummary = GroupSummary {publicMemberCount}} GroupLink {groupLinkId} groupRelays = let direct = not $ useRelays' gInfo @@ -2447,11 +2448,11 @@ setAgentConnShortLinkAsync user conn@Connection {connId} userLinkData crClientDa cmdId <- withStore' $ \db -> createCommand db user (Just connId) CFSetShortLink withAgent $ \a -> setConnShortLinkAsync a (aCorrId cmdId) (aConnId conn) userLinkData crClientData_ -getAgentConnShortLinkAsync :: User -> CommandFunction -> Maybe Connection -> ShortLinkContact -> CM (CommandId, ConnId) -getAgentConnShortLinkAsync user cmdFunc conn_ shortLink = do +getAgentConnShortLinkAsync :: User -> ShortLinkContact -> CM (CommandId, ConnId) +getAgentConnShortLinkAsync user shortLink = do shortLink' <- restoreShortLink' shortLink - cmdId <- withStore' $ \db -> createCommand db user (dbConnId <$> conn_) cmdFunc - connId <- withAgent $ \a -> getConnShortLinkAsync a (aUserId user) (aCorrId cmdId) (aConnId <$> conn_) shortLink' + cmdId <- withStore' $ \db -> createCommand db user Nothing CFGetShortLink + connId <- withAgent $ \a -> getConnShortLinkAsync a (aUserId user) (aCorrId cmdId) shortLink' pure (cmdId, connId) agentXFTPDeleteRcvFile :: RcvFileId -> FileTransferId -> CM () diff --git a/src/Simplex/Chat/Library/Subscriber.hs b/src/Simplex/Chat/Library/Subscriber.hs index fce2fb0137..650b554857 100644 --- a/src/Simplex/Chat/Library/Subscriber.hs +++ b/src/Simplex/Chat/Library/Subscriber.hs @@ -735,10 +735,13 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = -- [async agent commands] no continuation needed, but command should be asynchronous for stability allowAgentConnectionAsync user conn' confId XOk | otherwise -> messageError "x.grp.acpt: memberId is different from expected" - XGrpRelayAcpt relayLink + XGrpRelayAcpt relayLink memberKey | memberRole' membership == GROwner && isRelay m -> do - withStore' $ \db -> setRelayLinkConfId db m confId relayLink - void $ getAgentConnShortLinkAsync user CFGetRelayDataAccept (Just conn') relayLink + withStore $ \db -> do + relay <- getGroupRelayByGMId db (groupMemberId' m) + liftIO $ updateGroupMemberStatus db userId m GSMemAccepted + void $ liftIO $ setRelayLinkAccepted db relay relayLink memberKey + allowAgentConnectionAsync user conn' confId XOk | otherwise -> messageError "x.grp.relay.acpt: only owner can add relay" _ -> messageError "CONF from invited member must have x.grp.acpt" GCHostMember -> @@ -863,9 +866,11 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = when (groupFeatureAllowed SGFHistory gInfo'' && not memberIsCustomer) $ sendHistory user gInfo'' m' where sendXGrpLinkMem gInfo'' = do - let incognitoProfile = ExistingIncognito <$> incognitoMembershipProfile gInfo'' + let GroupInfo {membership = membership'} = gInfo'' + incognitoProfile = ExistingIncognito <$> incognitoMembershipProfile gInfo'' profileToSend = userProfileInGroup user gInfo (fromIncognitoProfile <$> incognitoProfile) - void $ sendDirectMemberMessage conn (XGrpLinkMem profileToSend) groupId + memberKey = MemberKey <$> memberPubKey membership' + void $ sendDirectMemberMessage conn (XGrpLinkMem profileToSend memberKey) groupId _ -> do unless (memberPending m) $ withStore' $ \db -> updateGroupMemberStatus db userId m GSMemConnected notifyMemberConnected gInfo m Nothing @@ -963,7 +968,7 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = XFileCancel sharedMsgId -> xFileCancelGroup gInfo' (Just m'') sharedMsgId XFileAcptInv sharedMsgId fileConnReq_ fName -> Nothing <$ xFileAcptInvGroup gInfo' m'' sharedMsgId fileConnReq_ fName XInfo p -> fmap ctx <$> xInfoMember gInfo' m'' p msg brokerTs - XGrpLinkMem p -> Nothing <$ xGrpLinkMem gInfo' m'' conn' p + XGrpLinkMem p memberKey -> Nothing <$ xGrpLinkMem gInfo' m'' conn' p memberKey XGrpLinkAcpt acceptance role memberId -> Nothing <$ xGrpLinkAcpt gInfo' m'' acceptance role memberId msg brokerTs XGrpMemNew memInfo msgScope -> fmap ctx <$> xGrpMemNew gInfo' m'' memInfo msgScope msg brokerTs XGrpMemIntro memInfo memRestrictions_ -> Nothing <$ xGrpMemIntro gInfo' m'' memInfo memRestrictions_ @@ -1083,53 +1088,30 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = forM_ mc_ $ \mc -> do connReq_ <- withStore' $ \db -> getBusinessContactRequest db user groupId sendGroupAutoReply mc connReq_ - LDATA FixedLinkData {linkConnReq = cReq, rootKey = relayKey, linkEntityId} cData -> + LDATA FixedLinkData {linkConnReq = cReq} _cData -> + -- [async agent commands] CFGetConnShortLink continuation - join relay connection with resolved link withCompletedCommand conn agentMsg $ \CommandData {cmdFunction} -> case cmdFunction of - CFGetRelayDataJoin -> do - -- Update relay member with key, memberId and profile from link - relayLinkData_ <- liftIO $ decodeLinkUserData cData - case (relayLinkData_, linkEntityId) of - (Just RelayShortLinkData {relayProfile = p}, Just entityId) -> - withStore $ \db -> updateRelayMemberData db user m (MemberId entityId) (MemberKey relayKey) p - _ -> throwChatError $ CEException "relay link: no relay link data or entity id" - case cReq of - CRContactUri crData@ConnReqUriData {crClientData} -> do - let pqSup = PQSupportOff - lift (withAgent' $ \a -> connRequestPQSupport a pqSup cReq) >>= \case - Nothing -> throwChatError CEInvalidConnReq - Just (agentV, _) -> do - let chatV = agentToChatVersion agentV - groupLinkId = crClientData >>= decodeJSON >>= \(CRDataGroup gli) -> Just gli - cReqHash = contactCReqHash $ CRContactUri crData {crScheme = SSSimplex} - -- Update connection with data derived from cReq, now available after getConnShortLinkAsync - withStore' $ \db -> updateConnLinkData db user conn cReq cReqHash groupLinkId chatV pqSup - let GroupMember {memberId = membershipMemId} = membership - incognitoProfile = fromLocalProfile <$> incognitoMembershipProfile gInfo - profileToSend = userProfileInGroup user gInfo incognitoProfile - memberPubKey <- case groupKeys gInfo of - Just GroupKeys {memberPrivKey} -> pure $ C.publicKey memberPrivKey - Nothing -> throwChatError $ CEInternalError "no group keys for channel membership" - dm <- encodeConnInfo $ XMember profileToSend membershipMemId (MemberKey memberPubKey) - subMode <- chatReadVar subscriptionMode - void $ joinAgentConnectionAsync user (Just conn) True cReq dm subMode - CFGetRelayDataAccept -> do - let GroupMember {memberId = MemberId expectedMemberId} = m - if linkEntityId == Just expectedMemberId - then do - relayProfile <- liftIO (decodeLinkUserData cData) >>= \case - Just RelayShortLinkData {relayProfile = p} -> pure p - Nothing -> throwChatError $ CEException "relay link: no relay link data" - (confId, m', relay) <- withStore $ \db -> do - confId <- getRelayConfId db m - liftIO $ updateGroupMemberStatus db userId m GSMemAccepted - (m', relay) <- setRelayLinkAccepted db vr user m (MemberKey relayKey) relayProfile - pure (confId, m', relay) - allowAgentConnectionAsync user conn confId XOk - toView $ CEvtGroupRelayUpdated user gInfo m' relay - else - -- TODO [relays] owner: TBC failed RelayStatus? - messageError "relay link: relay member ID mismatch" + CFGetShortLink -> case cReq of + CRContactUri crData@ConnReqUriData {crClientData} -> do + let pqSup = PQSupportOff + lift (withAgent' $ \a -> connRequestPQSupport a pqSup cReq) >>= \case + Nothing -> throwChatError CEInvalidConnReq + Just (agentV, _) -> do + let chatV = agentToChatVersion agentV + groupLinkId = crClientData >>= decodeJSON >>= \(CRDataGroup gli) -> Just gli + cReqHash = contactCReqHash $ CRContactUri crData {crScheme = SSSimplex} + -- Update connection with data derived from cReq, now available after getConnShortLinkAsync + withStore' $ \db -> updateConnLinkData db user conn cReq cReqHash groupLinkId chatV pqSup + let GroupMember {memberId = membershipMemId} = membership + incognitoProfile = fromLocalProfile <$> incognitoMembershipProfile gInfo + profileToSend = userProfileInGroup user gInfo incognitoProfile + memberPubKey <- case groupKeys gInfo of + Just GroupKeys {memberPrivKey} -> pure $ C.publicKey memberPrivKey + Nothing -> throwChatError $ CEInternalError "no group keys for channel membership" + dm <- encodeConnInfo $ XMember profileToSend membershipMemId (MemberKey memberPubKey) + subMode <- chatReadVar subscriptionMode + void $ joinAgentConnectionAsync user (Just conn) True cReq dm subMode _ -> throwChatError $ CECommandError "unexpected cmdFunction" QCONT -> do continued <- continueSending connEntity conn @@ -2420,13 +2402,13 @@ processAgentMessageConn vr user@User {userId} corrId agentConnId agentMessage = void $ processMemberProfileUpdate gInfo m p' (Just (msg, brokerTs)) pure $ memberEventDeliveryScope m - xGrpLinkMem :: GroupInfo -> GroupMember -> Connection -> Profile -> CM () - xGrpLinkMem gInfo@GroupInfo {membership, businessChat} m@GroupMember {groupMemberId, memberCategory} Connection {viaGroupLink} p' = do + xGrpLinkMem :: GroupInfo -> GroupMember -> Connection -> Profile -> Maybe MemberKey -> CM () + xGrpLinkMem gInfo@GroupInfo {membership, businessChat} m@GroupMember {groupMemberId, memberCategory} Connection {viaGroupLink} p' memberKey_ = do xGrpLinkMemReceived <- withStore $ \db -> getXGrpLinkMemReceived db groupMemberId if (viaGroupLink || isJust businessChat) && isNothing (memberContactId m) && memberCategory == GCHostMember && not xGrpLinkMemReceived then do m' <- processMemberProfileUpdate gInfo m p' Nothing - withStore' $ \db -> setXGrpLinkMemReceived db groupMemberId True + withStore' $ \db -> setXGrpLinkMemReceived db groupMemberId True memberKey_ let connectedIncognito = memberIncognito membership probeMatchingMemberContact m' connectedIncognito else messageError "x.grp.link.mem error: invalid group link host profile update" @@ -3614,52 +3596,56 @@ runRelayRequestWorker a Worker {doWork} = do -- Check if relay link already exists (recovery case) case groupLink_ of Right GroupLink {connLinkContact = CCLink _ sLnk_} -> - case sLnk_ of - Just sLnk -> acceptOwnerConnection rrd gInfo sLnk - Nothing -> throwChatError $ CEException "processRelayRequest: relay link doesn't have short link" + case (sLnk_, memberPubKey $ membership gInfo) of + (Just sLnk, Just k) -> acceptOwnerConnection rrd gInfo sLnk (MemberKey k) + (Nothing, _) -> throwChatError $ CEException "processRelayRequest: relay link doesn't have short link" + (_, Nothing) -> throwChatError $ CEException "processRelayRequest: no member key" Left _ -> do - (gInfo', sLnk) <- getLinkDataCreateRelayLink rrd gInfo - acceptOwnerConnection rrd gInfo' sLnk + (gInfo', sLnk, memberKey) <- getLinkDataCreateRelayLink rrd gInfo + acceptOwnerConnection rrd gInfo' sLnk memberKey where - getLinkDataCreateRelayLink :: RelayRequestData -> GroupInfo -> CM (GroupInfo, ShortLinkContact) + getLinkDataCreateRelayLink :: RelayRequestData -> GroupInfo -> CM (GroupInfo, ShortLinkContact, MemberKey) getLinkDataCreateRelayLink RelayRequestData {reqGroupLink} gInfo = do (FixedLinkData {linkEntityId, rootKey}, cData@(ContactLinkData _ UserContactData {owners})) <- getShortLinkConnReq NRMBackground user reqGroupLink liftIO (decodeLinkUserData cData) >>= \case Nothing -> throwChatError $ CEException "getLinkDataCreateRelayLink: no group link data" Just GroupShortLinkData {groupProfile = gp} -> do validateGroupProfile gp - ((_, memberPrivKey), sLnk) <- createRelayLink gInfo + gVar <- asks random + (_, memberPrivKey) <- liftIO $ atomically $ C.generateKeyPair gVar gInfo' <- withStore $ \db -> do void $ updateGroupProfile db user gInfo gp updateRelayGroupKeys db user gInfo linkEntityId rootKey memberPrivKey owners getGroupInfo db vr user groupId - pure (gInfo', sLnk) + sLnk <- createRelayLink gInfo' + pure (gInfo', sLnk, MemberKey $ C.publicKey memberPrivKey) where validateGroupProfile :: GroupProfile -> CM () validateGroupProfile _groupProfile = do -- TODO [relays] relay: validate group profile, verify owner's signature pure () - createRelayLink :: GroupInfo -> CM (C.KeyPairEd25519, ShortLinkContact) - createRelayLink gi = do - let GroupInfo {membership = relayMem} = gi - GroupMember {memberId = relayMemId, memberProfile = relayLP} = relayMem - MemberId relayMemberIdBS = relayMemId - userData = encodeShortLinkData $ RelayShortLinkData {relayProfile = fromLocalProfile relayLP} - userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData} + createRelayLink :: GroupInfo -> CM ShortLinkContact + createRelayLink gi@GroupInfo {groupProfile} = do + -- TODO [relays] relay: set relay link data + -- TODO - link data: relay key for group, relay identity (profile, certificate, relay identity key) + -- TODO - starting role should be communicated in protocol from owner to relays groupLinkId <- GroupLinkId <$> drgRandomBytes 16 subMode <- chatReadVar subscriptionMode - -- TODO [relays] starting role should be communicated in protocol from owner to relays subRole <- asks $ channelSubscriberRole . config - let crClientData = encodeJSON $ CRDataGroup groupLinkId - (connId, (Just sigKeys, ccLink, _serviceId)) <- withAgent $ \a' -> createConnection a' NRMBackground (aUserId user) (Just relayMemberIdBS) True True SCMContact (Just userLinkData) (Just crClientData) CR.IKPQOff subMode + let userData = encodeShortLinkData $ GroupShortLinkData {groupProfile, publicGroupData = Nothing} + userLinkData = UserContactLinkData UserContactData {direct = True, owners = [], relays = [], userData} + crClientData = encodeJSON $ CRDataGroup groupLinkId + (connId, (ccLink, _serviceId)) <- withAgent $ \a' -> createConnection a' NRMBackground (aUserId user) True True SCMContact (Just userLinkData) (Just crClientData) CR.IKPQOff subMode ccLink' <- createdGroupLink <$> shortenCreatedLink ccLink sLnk <- case toShortLinkContact ccLink' of Just sl -> pure sl Nothing -> throwChatError $ CEException "failed to create relay link: no short link" gVar <- asks random void $ withFastStore $ \db -> createGroupLink db gVar user gi connId ccLink' groupLinkId subRole subMode - pure (sigKeys, sLnk) - acceptOwnerConnection :: RelayRequestData -> GroupInfo -> ShortLinkContact -> CM () - acceptOwnerConnection RelayRequestData {relayInvId, reqChatVRange} gi relayLink = do + pure sLnk + acceptOwnerConnection :: RelayRequestData -> GroupInfo -> ShortLinkContact -> MemberKey -> CM () + acceptOwnerConnection RelayRequestData {relayInvId, reqChatVRange} gi relayLink memberKey = do ownerMember <- withStore $ \db -> getHostMember db vr user groupId - void $ acceptRelayJoinRequestAsync user uclId gi ownerMember relayInvId reqChatVRange relayLink + void $ acceptRelayJoinRequestAsync user uclId gi ownerMember relayInvId reqChatVRange relayLink memberKey + -- TODO [relays] relay: group invite accepted event, chat item (?) + pure () diff --git a/src/Simplex/Chat/Protocol.hs b/src/Simplex/Chat/Protocol.hs index d012bbb0a5..2e921425b9 100644 --- a/src/Simplex/Chat/Protocol.hs +++ b/src/Simplex/Chat/Protocol.hs @@ -432,10 +432,10 @@ data ChatMsgEvent (e :: MsgEncoding) where XGrpAcpt :: MemberId -> ChatMsgEvent 'Json XGrpLinkInv :: GroupLinkInvitation -> ChatMsgEvent 'Json XGrpLinkReject :: GroupLinkRejection -> ChatMsgEvent 'Json - XGrpLinkMem :: Profile -> ChatMsgEvent 'Json + XGrpLinkMem :: Profile -> Maybe MemberKey -> ChatMsgEvent 'Json XGrpLinkAcpt :: GroupAcceptance -> GroupMemberRole -> MemberId -> ChatMsgEvent 'Json XGrpRelayInv :: GroupRelayInvitation -> ChatMsgEvent 'Json - XGrpRelayAcpt :: ShortLinkContact -> ChatMsgEvent 'Json + XGrpRelayAcpt :: ShortLinkContact -> MemberKey -> ChatMsgEvent 'Json XGrpMemNew :: MemberInfo -> Maybe MsgScope -> ChatMsgEvent 'Json XGrpMemIntro :: MemberInfo -> Maybe MemberRestrictions -> ChatMsgEvent 'Json XGrpMemInv :: MemberId -> IntroInvitation -> ChatMsgEvent 'Json @@ -1126,10 +1126,10 @@ toCMEventTag msg = case msg of XGrpAcpt _ -> XGrpAcpt_ XGrpLinkInv _ -> XGrpLinkInv_ XGrpLinkReject _ -> XGrpLinkReject_ - XGrpLinkMem _ -> XGrpLinkMem_ + XGrpLinkMem _ _ -> XGrpLinkMem_ XGrpLinkAcpt {} -> XGrpLinkAcpt_ XGrpRelayInv _ -> XGrpRelayInv_ - XGrpRelayAcpt _ -> XGrpRelayAcpt_ + XGrpRelayAcpt _ _ -> XGrpRelayAcpt_ XGrpMemNew {} -> XGrpMemNew_ XGrpMemIntro _ _ -> XGrpMemIntro_ XGrpMemInv _ _ -> XGrpMemInv_ @@ -1278,10 +1278,10 @@ appJsonToCM AppMessageJson {v, msgId, event, params} = do XGrpAcpt_ -> XGrpAcpt <$> p "memberId" XGrpLinkInv_ -> XGrpLinkInv <$> p "groupLinkInvitation" XGrpLinkReject_ -> XGrpLinkReject <$> p "groupLinkRejection" - XGrpLinkMem_ -> XGrpLinkMem <$> p "profile" + XGrpLinkMem_ -> XGrpLinkMem <$> p "profile" <*> opt "memberKey" XGrpLinkAcpt_ -> XGrpLinkAcpt <$> p "acceptance" <*> p "role" <*> p "memberId" XGrpRelayInv_ -> XGrpRelayInv <$> p "groupRelayInvitation" - XGrpRelayAcpt_ -> XGrpRelayAcpt <$> p "relayLink" + XGrpRelayAcpt_ -> XGrpRelayAcpt <$> p "relayLink" <*> p "memberKey" XGrpMemNew_ -> XGrpMemNew <$> p "memberInfo" <*> opt "scope" XGrpMemIntro_ -> XGrpMemIntro <$> p "memberInfo" <*> opt "memberRestrictions" XGrpMemInv_ -> XGrpMemInv <$> p "memberId" <*> p "memberIntro" @@ -1345,10 +1345,10 @@ chatToAppMessage chatMsg@ChatMessage {chatVRange, msgId, chatMsgEvent} = case en XGrpAcpt memId -> o ["memberId" .= memId] XGrpLinkInv groupLinkInv -> o ["groupLinkInvitation" .= groupLinkInv] XGrpLinkReject groupLinkRjct -> o ["groupLinkRejection" .= groupLinkRjct] - XGrpLinkMem profile -> o ["profile" .= profile] + XGrpLinkMem profile memberKey -> o $ ("memberKey" .=? memberKey) ["profile" .= profile] XGrpLinkAcpt acceptance role memberId -> o ["acceptance" .= acceptance, "role" .= role, "memberId" .= memberId] XGrpRelayInv groupRelayInv -> o ["groupRelayInvitation" .= groupRelayInv] - XGrpRelayAcpt relayLink -> o ["relayLink" .= relayLink] + XGrpRelayAcpt relayLink memberKey -> o ["relayLink" .= relayLink, "memberKey" .= memberKey] XGrpMemNew memInfo scope -> o $ ("scope" .=? scope) ["memberInfo" .= memInfo] XGrpMemIntro memInfo memRestrictions -> o $ ("memberRestrictions" .=? memRestrictions) ["memberInfo" .= memInfo] XGrpMemInv memId memIntro -> o ["memberId" .= memId, "memberIntro" .= memIntro] @@ -1436,10 +1436,3 @@ $(JQ.deriveJSON defaultJSON ''PublicGroupData) $(JQ.deriveJSON defaultJSON ''GroupShortLinkData) -data RelayShortLinkData = RelayShortLinkData - { relayProfile :: Profile - } - deriving (Show) - -$(JQ.deriveJSON defaultJSON ''RelayShortLinkData) - diff --git a/src/Simplex/Chat/Store/Groups.hs b/src/Simplex/Chat/Store/Groups.hs index 12f726c524..8698b1718c 100644 --- a/src/Simplex/Chat/Store/Groups.hs +++ b/src/Simplex/Chat/Store/Groups.hs @@ -88,9 +88,6 @@ module Simplex.Chat.Store.Groups updateRelayStatus, updateRelayStatusFromTo, setRelayLinkAccepted, - setRelayLinkConfId, - getRelayConfId, - updateRelayMemberData, setGroupInProgressDone, createRelayRequestGroup, updateRelayOwnStatusFromTo, @@ -200,7 +197,7 @@ import Simplex.Chat.Types.MemberRelations (IntroductionDirection (..), MemberRel import Simplex.Chat.Types.Preferences import Simplex.Chat.Types.Shared import Simplex.Chat.Types.UITheme -import Simplex.Messaging.Agent.Protocol (ConfirmationId, ConnId, CreatedConnLink (..), InvitationId, OwnerAuth (..), UserId) +import Simplex.Messaging.Agent.Protocol (ConnId, CreatedConnLink (..), InvitationId, OwnerAuth (..), UserId) import Simplex.Messaging.Agent.Store.AgentStore (firstRow, fromOnlyBI, maybeFirstRow) import Simplex.Messaging.Agent.Store.DB (Binary (..), BoolInt (..)) import Simplex.Messaging.Agent.Store.Entity (DBEntityId) @@ -1420,74 +1417,26 @@ updateRelayStatus_ db relayId relayStatus = do currentTs <- getCurrentTime DB.execute db "UPDATE group_relays SET relay_status = ?, updated_at = ? WHERE group_relay_id = ?" (relayStatus, currentTs, relayId) -setRelayLinkAccepted :: DB.Connection -> VersionRangeChat -> User -> GroupMember -> MemberKey -> Profile -> ExceptT StoreError IO (GroupMember, GroupRelay) -setRelayLinkAccepted db vr user m (MemberKey relayKey) profile = do - let gmId = groupMemberId' m - currentTs <- liftIO getCurrentTime - liftIO $ DB.execute - db - [sql| - UPDATE group_relays - SET relay_status = ?, updated_at = ? - WHERE group_member_id = ? - |] - (RSAccepted, currentTs, gmId) - liftIO $ DB.execute - db - [sql| - UPDATE group_members - SET member_pub_key = ?, updated_at = ? - WHERE group_member_id = ? - |] - (relayKey, currentTs, gmId) - void $ updateMemberProfile db user m profile - (,) <$> getGroupMemberById db vr user gmId <*> getGroupRelayByGMId db gmId - -setRelayLinkConfId :: DB.Connection -> GroupMember -> ConfirmationId -> ShortLinkContact -> IO () -setRelayLinkConfId db m confId relayLink = do +setRelayLinkAccepted :: DB.Connection -> GroupRelay -> ShortLinkContact -> MemberKey -> IO GroupRelay +setRelayLinkAccepted db relay@GroupRelay {groupRelayId, groupMemberId} relayLink (MemberKey k) = do currentTs <- getCurrentTime DB.execute db [sql| UPDATE group_relays - SET conf_id = ?, relay_link = ?, updated_at = ? - WHERE group_member_id = ? + SET relay_link = ?, relay_status = ?, updated_at = ? + WHERE group_relay_id = ? |] - (confId, relayLink, currentTs, groupMemberId' m) + (relayLink, RSAccepted, currentTs, groupRelayId) DB.execute db [sql| UPDATE group_members - SET relay_link = ?, updated_at = ? + SET relay_link = ?, member_pub_key = ?, updated_at = ? WHERE group_member_id = ? |] - (relayLink, currentTs, groupMemberId' m) - -getRelayConfId :: DB.Connection -> GroupMember -> ExceptT StoreError IO ConfirmationId -getRelayConfId db m = - ExceptT . firstRow fromOnly (SEGroupRelayNotFoundByMemberId $ groupMemberId' m) $ - DB.query - db - [sql| - SELECT conf_id - FROM group_relays - WHERE group_member_id = ? AND conf_id IS NOT NULL - |] - (Only (groupMemberId' m)) - -updateRelayMemberData :: DB.Connection -> User -> GroupMember -> MemberId -> MemberKey -> Profile -> ExceptT StoreError IO () -updateRelayMemberData db user m memberId (MemberKey relayKey) profile = do - currentTs <- liftIO getCurrentTime - liftIO $ - DB.execute - db - [sql| - UPDATE group_members - SET member_id = ?, member_pub_key = ?, updated_at = ? - WHERE group_member_id = ? - |] - (memberId, relayKey, currentTs, groupMemberId' m) - void $ updateMemberProfile db user m profile + (relayLink, k, currentTs, groupMemberId) + pure relay {relayStatus = RSAccepted, relayLink = Just relayLink} setGroupInProgressDone :: DB.Connection -> GroupInfo -> IO () setGroupInProgressDone db GroupInfo {groupId} = do @@ -2902,13 +2851,14 @@ getXGrpLinkMemReceived db mId = ExceptT . firstRow fromOnlyBI (SEGroupMemberNotFound mId) $ DB.query db "SELECT xgrplinkmem_received FROM group_members WHERE group_member_id = ?" (Only mId) -setXGrpLinkMemReceived :: DB.Connection -> GroupMemberId -> Bool -> IO () -setXGrpLinkMemReceived db mId xGrpLinkMemReceived = do +setXGrpLinkMemReceived :: DB.Connection -> GroupMemberId -> Bool -> Maybe MemberKey -> IO () +setXGrpLinkMemReceived db mId xGrpLinkMemReceived memberKey_ = do currentTs <- getCurrentTime + let k = (\(MemberKey k') -> k') <$> memberKey_ DB.execute db - "UPDATE group_members SET xgrplinkmem_received = ?, updated_at = ? WHERE group_member_id = ?" - (BI xGrpLinkMemReceived, currentTs, mId) + "UPDATE group_members SET xgrplinkmem_received = ?, member_pub_key = ?, updated_at = ? WHERE group_member_id = ?" + (BI xGrpLinkMemReceived, k, currentTs, mId) createNewUnknownGroupMember :: DB.Connection -> VersionRangeChat -> User -> GroupInfo -> MemberId -> Text -> GroupMemberRole -> ExceptT StoreError IO GroupMember createNewUnknownGroupMember db vr user@User {userId, userContactId} GroupInfo {groupId} memberId memberName unknownMemberRole = do diff --git a/src/Simplex/Chat/Store/Postgres/Migrations/M20260222_chat_relays.hs b/src/Simplex/Chat/Store/Postgres/Migrations/M20260222_chat_relays.hs index 1d39060d07..a504e7f1d8 100644 --- a/src/Simplex/Chat/Store/Postgres/Migrations/M20260222_chat_relays.hs +++ b/src/Simplex/Chat/Store/Postgres/Migrations/M20260222_chat_relays.hs @@ -54,7 +54,6 @@ CREATE TABLE group_relays( chat_relay_id BIGINT NOT NULL REFERENCES chat_relays ON DELETE CASCADE, relay_status TEXT NOT NULL, relay_link BYTEA, - conf_id BYTEA, created_at TEXT NOT NULL DEFAULT (now()), updated_at TEXT NOT NULL DEFAULT (now()) ); diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20250813_delivery_tasks.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20250813_delivery_tasks.hs index dce9574fe3..35f2006cef 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/M20250813_delivery_tasks.hs +++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20250813_delivery_tasks.hs @@ -5,6 +5,10 @@ module Simplex.Chat.Store.SQLite.Migrations.M20250813_delivery_tasks where import Database.SQLite.Simple (Query) import Database.SQLite.Simple.QQ (sql) +-- TODO [relays] add later in new migration for MemberProfileUpdate delivery jobs: +-- TODO - ALTER TABLE group_members ADD COLUMN last_profile_delivery_ts TEXT; +-- TODO - ALTER TABLE group_members ADD COLUMN join_ts TEXT; + -- How columns correspond to types: -- both tables: diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/M20260222_chat_relays.hs b/src/Simplex/Chat/Store/SQLite/Migrations/M20260222_chat_relays.hs index 250cf25bd6..766921858f 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/M20260222_chat_relays.hs +++ b/src/Simplex/Chat/Store/SQLite/Migrations/M20260222_chat_relays.hs @@ -67,7 +67,6 @@ CREATE TABLE group_relays( chat_relay_id INTEGER NOT NULL REFERENCES chat_relays ON DELETE CASCADE, relay_status TEXT NOT NULL, relay_link BLOB, - conf_id BLOB, created_at TEXT NOT NULL DEFAULT(datetime('now')), updated_at TEXT NOT NULL DEFAULT(datetime('now')) ) STRICT; diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt index ec90caca8a..99c1b1899b 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt +++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_query_plans.txt @@ -3472,14 +3472,6 @@ Query: Plan: SEARCH commands USING INTEGER PRIMARY KEY (rowid=?) -Query: - SELECT conf_id - FROM group_relays - WHERE group_member_id = ? AND conf_id IS NOT NULL - -Plan: -SEARCH group_relays USING INDEX idx_group_relays_group_member_id (group_member_id=?) - Query: SELECT connection_id, agent_conn_id, conn_level, via_contact, via_user_contact_link, via_group_link, group_link_id, xcontact_id, custom_user_profile_id, conn_status, conn_type, contact_conn_initiated, local_alias, contact_id, group_member_id, user_contact_link_id, @@ -3919,14 +3911,6 @@ Query: Plan: SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) -Query: - UPDATE group_members - SET member_id = ?, member_pub_key = ?, updated_at = ? - WHERE group_member_id = ? - -Plan: -SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) - Query: UPDATE group_members SET member_relations_vector = ? @@ -4895,14 +4879,6 @@ Query: Plan: SEARCH contacts USING INTEGER PRIMARY KEY (rowid=?) -Query: - UPDATE group_members - SET member_pub_key = ?, updated_at = ? - WHERE group_member_id = ? - -Plan: -SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) - Query: UPDATE group_members SET member_relations_vector = ?, updated_at = ? @@ -4945,7 +4921,7 @@ SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) Query: UPDATE group_members - SET relay_link = ?, updated_at = ? + SET relay_link = ?, member_pub_key = ?, updated_at = ? WHERE group_member_id = ? Plan: @@ -4988,19 +4964,11 @@ SEARCH groups USING INTEGER PRIMARY KEY (rowid=?) Query: UPDATE group_relays - SET conf_id = ?, relay_link = ?, updated_at = ? - WHERE group_member_id = ? + SET relay_link = ?, relay_status = ?, updated_at = ? + WHERE group_relay_id = ? Plan: -SEARCH group_relays USING INDEX idx_group_relays_group_member_id (group_member_id=?) - -Query: - UPDATE group_relays - SET relay_status = ?, updated_at = ? - WHERE group_member_id = ? - -Plan: -SEARCH group_relays USING INDEX idx_group_relays_group_member_id (group_member_id=?) +SEARCH group_relays USING INTEGER PRIMARY KEY (rowid=?) Query: UPDATE group_snd_item_statuses @@ -6991,7 +6959,7 @@ Query: UPDATE group_members SET support_chat_ts = ? WHERE group_member_id = ? Plan: SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) -Query: UPDATE group_members SET xgrplinkmem_received = ?, updated_at = ? WHERE group_member_id = ? +Query: UPDATE group_members SET xgrplinkmem_received = ?, member_pub_key = ?, updated_at = ? WHERE group_member_id = ? Plan: SEARCH group_members USING INTEGER PRIMARY KEY (rowid=?) diff --git a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql index 4ab9a442f0..9782ce056d 100644 --- a/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql +++ b/src/Simplex/Chat/Store/SQLite/Migrations/chat_schema.sql @@ -765,7 +765,6 @@ CREATE TABLE group_relays( chat_relay_id INTEGER NOT NULL REFERENCES chat_relays ON DELETE CASCADE, relay_status TEXT NOT NULL, relay_link BLOB, - conf_id BLOB, created_at TEXT NOT NULL DEFAULT(datetime('now')), updated_at TEXT NOT NULL DEFAULT(datetime('now')) ) STRICT; diff --git a/src/Simplex/Chat/Types.hs b/src/Simplex/Chat/Types.hs index 05aaf5744f..32d1c726bf 100644 --- a/src/Simplex/Chat/Types.hs +++ b/src/Simplex/Chat/Types.hs @@ -121,6 +121,7 @@ instance ToField AgentUserId where toField (AgentUserId uId) = toField uId aUserId :: User -> UserId aUserId User {agentUserId = AgentUserId uId} = uId +-- TODO [relays] filter out chat relay users where necessary (e.g. loading list of users for UI) data User = User { userId :: UserId, agentUserId :: AgentUserId, @@ -1855,8 +1856,7 @@ data CommandFunction | CFAckMessage -- not used | CFDeleteConn -- not used | CFSetShortLink - | CFGetRelayDataJoin - | CFGetRelayDataAccept + | CFGetShortLink deriving (Eq, Show) instance FromField CommandFunction where fromField = fromTextField_ textDecode @@ -1875,8 +1875,7 @@ instance TextEncoding CommandFunction where "ack_message" -> Just CFAckMessage "delete_conn" -> Just CFDeleteConn "set_short_link" -> Just CFSetShortLink - "get_relay_data_join" -> Just CFGetRelayDataJoin - "get_relay_data_accept" -> Just CFGetRelayDataAccept + "get_short_link" -> Just CFGetShortLink _ -> Nothing textEncode = \case CFCreateConnGrpMemInv -> "create_conn" @@ -1889,8 +1888,7 @@ instance TextEncoding CommandFunction where CFAckMessage -> "ack_message" CFDeleteConn -> "delete_conn" CFSetShortLink -> "set_short_link" - CFGetRelayDataJoin -> "get_relay_data_join" - CFGetRelayDataAccept -> "get_relay_data_accept" + CFGetShortLink -> "get_short_link" commandExpectedResponse :: CommandFunction -> AEvtTag commandExpectedResponse = \case @@ -1904,8 +1902,7 @@ commandExpectedResponse = \case CFAckMessage -> t OK_ CFDeleteConn -> t OK_ CFSetShortLink -> t LINK_ - CFGetRelayDataJoin -> t LDATA_ - CFGetRelayDataAccept -> t LDATA_ + CFGetShortLink -> t LDATA_ where t = AEvtTag SAEConn diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index 3657ce5d05..22d136c59e 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -474,7 +474,6 @@ chatEventToView hu ChatConfig {logLevel, showReactions, showReceipts, testView} CEvtGroupLinkDataUpdated u g groupLink relays relaysChanged | relaysChanged -> ttyUser u $ viewGroupLinkRelaysUpdated g groupLink relays | otherwise -> [] - CEvtGroupRelayUpdated {} -> [] CEvtJoinedGroupMember u g m -> ttyUser u $ viewJoinedGroupMember g m CEvtHostConnected p h -> [plain $ "connected to " <> viewHostEvent p h] CEvtHostDisconnected p h -> [plain $ "disconnected from " <> viewHostEvent p h] @@ -2063,7 +2062,7 @@ viewConnectionPlan ChatConfig {logLevel, testView} _connLink = \case GLPOk groupSLinkInfo_ groupSLinkData -> let direct = maybe True (\(GroupShortLinkInfo {direct = d}) -> d) groupSLinkInfo_ in [grpLink $ if direct then "ok to connect directly" else "ok to connect via relays"] - <> [viewJSON groupSLinkData | testView] + <> [viewJSON groupSLinkData] -- | testView] -- TODO [relays] disable link data output in cli (uncomment testView) GLPOwnLink g -> [grpLink "own link for group " <> ttyGroup' g] GLPConnectingConfirmReconnect -> [grpLink "connecting, allowed to reconnect"] GLPConnectingProhibit Nothing -> [grpLink "connecting"] diff --git a/tests/ChatClient.hs b/tests/ChatClient.hs index ca2581eb01..8039576255 100644 --- a/tests/ChatClient.hs +++ b/tests/ChatClient.hs @@ -210,7 +210,7 @@ testCfg = shortLinkPresetServers = ["smp://LcJUMfVhwD8yxjAiSaDzzGF3-kLG4Uh0Fl_ZIjrRwjI=@localhost:7001"], testView = True, tbqSize = 16, - channelSubscriberRole = GRMember, -- starting role is GRMember to test members sending messages + channelSubscriberRole = GRMember, confirmMigrations = MCYesUp }