From 26a019d9d24a23547241c9960bb51fbe74999197 Mon Sep 17 00:00:00 2001 From: JRoberts <8711996+jr-simplex@users.noreply.github.com> Date: Tue, 9 Aug 2022 13:43:19 +0400 Subject: [PATCH] ios: update group members in model (#915) --- .../chat/simplex/app/views/chat/ChatView.kt | 6 ++-- .../app/views/chat/group/GroupChatInfoView.kt | 4 +-- .../app/views/chatlist/ChatListNavLinkView.kt | 2 +- .../simplex/app/views/newchat/AddGroupView.kt | 4 +-- apps/ios/Shared/Model/ChatModel.swift | 29 +++++++++++++++ apps/ios/Shared/Model/SimpleXAPI.swift | 36 +++++++++++-------- apps/ios/Shared/Views/Chat/ChatView.swift | 17 +++++---- .../Chat/Group/AddGroupMembersView.swift | 23 ++++++++---- .../Views/Chat/Group/GroupChatInfoView.swift | 23 ++++++------ .../Chat/Group/GroupMemberInfoView.swift | 9 +++-- .../Shared/Views/NewChat/AddGroupView.swift | 7 +++- apps/ios/SimpleXChat/APITypes.swift | 5 +-- src/Simplex/Chat.hs | 12 +++---- src/Simplex/Chat/Controller.hs | 2 +- src/Simplex/Chat/View.hs | 2 +- 15 files changed, 122 insertions(+), 59 deletions(-) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt index ffb3f282b..76eb09717 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/ChatView.kt @@ -37,7 +37,7 @@ import chat.simplex.app.views.chat.group.AddGroupMembersView import chat.simplex.app.views.chat.group.GroupChatInfoView import chat.simplex.app.views.chat.item.ChatItemView import chat.simplex.app.views.chatlist.openChat -import chat.simplex.app.views.chatlist.populateGroupMembers +import chat.simplex.app.views.chatlist.setGroupMembers import chat.simplex.app.views.helpers.* import com.google.accompanist.insets.ProvideWindowInsets import com.google.accompanist.insets.navigationBarsWithImePadding @@ -106,7 +106,7 @@ fun ChatView(chatModel: ChatModel) { } } } else if (cInfo is ChatInfo.Group) { - populateGroupMembers(cInfo.groupInfo, chatModel) + setGroupMembers(cInfo.groupInfo, chatModel) ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, @@ -160,7 +160,7 @@ fun ChatView(chatModel: ChatModel) { }, addMembers = { groupInfo -> withApi { - populateGroupMembers(groupInfo, chatModel) + setGroupMembers(groupInfo, chatModel) ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt index c998e9994..4ebc59d5b 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chat/group/GroupChatInfoView.kt @@ -24,7 +24,7 @@ import chat.simplex.app.R import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.chat.* -import chat.simplex.app.views.chatlist.populateGroupMembers +import chat.simplex.app.views.chatlist.setGroupMembers import chat.simplex.app.views.helpers.* @Composable @@ -43,7 +43,7 @@ fun GroupChatInfoView(chatModel: ChatModel, close: () -> Unit) { developerTools, addMembers = { withApi { - populateGroupMembers(groupInfo, chatModel) + setGroupMembers(groupInfo, chatModel) ModalManager.shared.showCustomModal { close -> ModalView( close = close, modifier = Modifier, diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt index c92f40407..67ef2bbe5 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/chatlist/ChatListNavLinkView.kt @@ -96,7 +96,7 @@ suspend fun openChat(chatInfo: ChatInfo, chatModel: ChatModel) { } } -suspend fun populateGroupMembers(groupInfo: GroupInfo, chatModel: ChatModel) { +suspend fun setGroupMembers(groupInfo: GroupInfo, chatModel: ChatModel) { val groupMembers = chatModel.controller.apiListMembers(groupInfo.groupId) chatModel.groupMembers.clear() chatModel.groupMembers.addAll(groupMembers) diff --git a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt index 73e2c7fa0..c4c56d65a 100644 --- a/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt +++ b/apps/android/app/src/main/java/chat/simplex/app/views/newchat/AddGroupView.kt @@ -21,7 +21,7 @@ import chat.simplex.app.model.* import chat.simplex.app.ui.theme.* import chat.simplex.app.views.ProfileNameField import chat.simplex.app.views.chat.group.AddGroupMembersView -import chat.simplex.app.views.chatlist.populateGroupMembers +import chat.simplex.app.views.chatlist.setGroupMembers import chat.simplex.app.views.helpers.* import chat.simplex.app.views.isValidDisplayName import chat.simplex.app.views.onboarding.ReadableText @@ -41,7 +41,7 @@ fun AddGroupView(chatModel: ChatModel, close: () -> Unit) { chatModel.addChat(Chat(chatInfo = ChatInfo.Group(groupInfo), chatItems = listOf())) chatModel.chatItems.clear() chatModel.chatId.value = groupInfo.id - populateGroupMembers(groupInfo, chatModel) + setGroupMembers(groupInfo, chatModel) close.invoke() ModalManager.shared.showCustomModal { close -> ModalView( diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index 8a25d57de..e1987c3f2 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -24,6 +24,7 @@ final class ChatModel: ObservableObject { @Published var chatId: String? @Published var chatItems: [ChatItem] = [] @Published var chatToTop: String? + @Published var groupMembers: [GroupMember] = [] // items in the terminal view @Published var terminalItems: [TerminalItem] = [] @Published var userAddress: String? @@ -291,6 +292,34 @@ final class ChatModel: ObservableObject { chats.removeAll(where: { $0.id == id }) } } + + func upsertGroupMember(_ groupInfo: GroupInfo, _ member: GroupMember) -> Bool { + // update current chat + if chatId == groupInfo.id { + if let i = groupMembers.firstIndex(where: { $0.id == member.id }) { + withAnimation(.default) { + self.groupMembers[i] = member + } + return false + } else { + withAnimation { groupMembers.append(member) } + return true + } + } else { + return false + } + } + + func removeGroupMember(_ groupInfo: GroupInfo, _ member: GroupMember) { + // remove from current chat + if chatId == groupInfo.id { + if let i = groupMembers.firstIndex(where: { $0.id == member.id }) { + _ = withAnimation { + self.groupMembers.remove(at: i) + } + } + } + } } final class Chat: ObservableObject, Identifiable { diff --git a/apps/ios/Shared/Model/SimpleXAPI.swift b/apps/ios/Shared/Model/SimpleXAPI.swift index 75320f91c..0df0b5104 100644 --- a/apps/ios/Shared/Model/SimpleXAPI.swift +++ b/apps/ios/Shared/Model/SimpleXAPI.swift @@ -567,20 +567,18 @@ func apiNewGroup(_ p: GroupProfile) throws -> GroupInfo { throw r } -func addMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole) async { - do { - try await apiAddMember(groupId: groupId, contactId: contactId, memberRole: memberRole) - } catch let error { - logger.error("addMember error: \(responseError(error))") - } -} - -func apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole) async throws { +func apiAddMember(_ groupId: Int64, _ contactId: Int64, _ memberRole: GroupMemberRole) async throws { let r = await chatSendCmd(.apiAddMember(groupId: groupId, contactId: contactId, memberRole: memberRole)) if case .sentGroupInvitation = r { return } throw r } +//func apiAddMember(_ groupId: Int64, _ contactId: Int64, _ memberRole: GroupMemberRole) async throws -> GroupMember { +// let r = await chatSendCmd(.apiAddMember(groupId: groupId, contactId: contactId, memberRole: memberRole)) +// if case let .sentGroupInvitation(_, _, member) = r { return member } +// throw r +//} + enum JoinGroupResult { case joined(groupInfo: GroupInfo) case invitationRemoved @@ -597,7 +595,7 @@ func apiJoinGroup(_ groupId: Int64) async throws -> JoinGroupResult { } } -func apiRemoveMember(groupId: Int64, memberId: Int64) async throws -> GroupMember { +func apiRemoveMember(_ groupId: Int64, _ memberId: Int64) async throws -> GroupMember { let r = await chatSendCmd(.apiRemoveMember(groupId: groupId, memberId: memberId), bgTask: false) if case let .userDeletedMember(_, member) = r { return member } throw r @@ -820,12 +818,22 @@ func processReceivedMsg(_ res: ChatResponse) async { chatItems: [] )) // NtfManager.shared.notifyContactRequest(contactRequest) // TODO notifyGroupInvitation? + case let .joinedGroupMemberConnecting(groupInfo, _, member): + _ = m.upsertGroupMember(groupInfo, member) + case let .deletedMemberUser(groupInfo, _): // TODO update user member + m.updateGroup(groupInfo) + case let .deletedMember(groupInfo, _, deletedMember): + m.removeGroupMember(groupInfo, deletedMember) + case let .leftMember(groupInfo, member): + m.removeGroupMember(groupInfo, member) + case let .groupDeleted(groupInfo, _): // TODO update user member + m.updateGroup(groupInfo) case let .userJoinedGroup(groupInfo): m.updateGroup(groupInfo) - case let .groupDeleted(groupInfo, _): - m.updateGroup(groupInfo) - case let .deletedMemberUser(groupInfo, _): - m.updateGroup(groupInfo) + case let .joinedGroupMember(groupInfo, member): + _ = m.upsertGroupMember(groupInfo, member) + case let .connectedToGroupMember(groupInfo, member): + _ = m.upsertGroupMember(groupInfo, member) case let .groupUpdated(toGroup): m.updateGroup(toGroup) case let .rcvFileStart(aChatItem): diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 004624562..205336dbb 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -17,7 +17,6 @@ struct ChatView: View { @ObservedObject var chat: Chat @State private var showChatInfoSheet: Bool = false @State private var showAddMembersSheet: Bool = false - @State private var membersToAdd: [Contact] = [] @State private var composeState = ComposeState() @State private var deletingItem: ChatItem? = nil @FocusState private var keyboardVisible: Bool @@ -110,8 +109,14 @@ struct ChatView: View { } await MainActor.run { showChatInfoSheet = true } } - } else { - showChatInfoSheet = true + } else if case let .group(groupInfo) = cInfo { + Task { + let groupMembers = await apiListMembers(groupInfo.groupId) + await MainActor.run { + ChatModel.shared.groupMembers = groupMembers + showChatInfoSheet = true + } + } } } label: { ChatInfoToolbar(chat: chat) @@ -138,7 +143,7 @@ struct ChatView: View { if groupInfo.canAddMembers { addMembersButton() .sheet(isPresented: $showAddMembersSheet) { - AddGroupMembersView(chat: chat, groupInfo: groupInfo, membersToAdd: membersToAdd) + AddGroupMembersView(chat: chat, groupInfo: groupInfo) } } default: @@ -161,9 +166,9 @@ struct ChatView: View { Button { if case let .group(gInfo) = chat.chatInfo { Task { - let ms = await apiListMembers(gInfo.apiId) + let groupMembers = await apiListMembers(gInfo.groupId) await MainActor.run { - membersToAdd = filterMembersToAdd(ms) + ChatModel.shared.groupMembers = groupMembers showAddMembersSheet = true } } diff --git a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift index bae4f6025..7e4b9cbaf 100644 --- a/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift +++ b/apps/ios/Shared/Views/Chat/Group/AddGroupMembersView.swift @@ -14,7 +14,6 @@ struct AddGroupMembersView: View { @Environment(\.dismiss) var dismiss: DismissAction var chat: Chat var groupInfo: GroupInfo - var membersToAdd: [Contact] var showSkip: Bool = false var addedMembersCb: ((Set) -> Void)? = nil @State private var selectedContacts = Set() @@ -22,6 +21,8 @@ struct AddGroupMembersView: View { var body: some View { NavigationView { + let membersToAdd = filterMembersToAdd(chatModel.groupMembers) + let v = List { ChatInfoToolbar(chat: chat, imageSize: 48) .frame(maxWidth: .infinity, alignment: .center) @@ -81,11 +82,21 @@ struct AddGroupMembersView: View { func inviteMembersButton() -> some View { Button { Task { - for contactId in selectedContacts { - await addMember(groupId: chat.chatInfo.apiId, contactId: contactId, memberRole: selectedRole) + do { + for contactId in selectedContacts { + try await apiAddMember(groupInfo.groupId, contactId, selectedRole) + // await MainActor.run { ChatModel.shared.upsertGroupMember(groupInfo, member) } + } + await MainActor.run { dismiss() } + if let cb = addedMembersCb { cb(selectedContacts) } + } catch { + AlertManager.shared.showAlert( + Alert( + title: Text("Error adding member(s)"), + message: Text(responseError(error)) + ) + ) } - await MainActor.run { dismiss() } - if let cb = addedMembersCb { cb(selectedContacts) } } } label: { HStack { @@ -132,6 +143,6 @@ struct AddGroupMembersView: View { struct AddGroupMembersView_Previews: PreviewProvider { static var previews: some View { - AddGroupMembersView(chat: Chat(chatInfo: ChatInfo.sampleData.group), groupInfo: GroupInfo.sampleData, membersToAdd: []) + AddGroupMembersView(chat: Chat(chatInfo: ChatInfo.sampleData.group), groupInfo: GroupInfo.sampleData) } } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index e39bd323e..7e6b2edb9 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -15,7 +15,6 @@ struct GroupChatInfoView: View { @ObservedObject var chat: Chat var groupInfo: GroupInfo @ObservedObject private var alertManager = AlertManager.shared - @State private var members: [GroupMember] = [] @State private var alert: GroupChatInfoViewAlert? = nil @State private var showAddMembersSheet: Bool = false @State private var selectedMember: GroupMember? = nil @@ -33,6 +32,10 @@ struct GroupChatInfoView: View { var body: some View { NavigationView { + let members = chatModel.groupMembers + .filter { $0.memberStatus != .memLeft && $0.memberStatus != .memRemoved } + .sorted { $0.displayName.lowercased() < $1.displayName.lowercased() } + List { groupInfoHeader() .listRowBackground(Color.clear) @@ -57,7 +60,7 @@ struct GroupChatInfoView: View { } } .sheet(isPresented: $showAddMembersSheet) { - AddGroupMembersView(chat: chat, groupInfo: groupInfo, membersToAdd: filterMembersToAdd(members)) + AddGroupMembersView(chat: chat, groupInfo: groupInfo) } .sheet(item: $selectedMember, onDismiss: { connectionStats = nil }) { member in GroupMemberInfoView(groupInfo: groupInfo, member: member, connectionStats: connectionStats) @@ -96,14 +99,6 @@ struct GroupChatInfoView: View { case .leaveGroupAlert: return leaveGroupAlert() } } - .task { - let ms = await apiListMembers(chat.chatInfo.apiId) - .filter { $0.memberStatus != .memLeft && $0.memberStatus != .memRemoved } - .sorted { $0.displayName.lowercased() < $1.displayName.lowercased() } - await MainActor.run { - members = ms - } - } } func groupInfoHeader() -> some View { @@ -128,7 +123,13 @@ struct GroupChatInfoView: View { private func addMembersButton() -> some View { Button { - showAddMembersSheet = true + Task { + let groupMembers = await apiListMembers(groupInfo.groupId) + await MainActor.run { + ChatModel.shared.groupMembers = groupMembers + showAddMembersSheet = true + } + } } label: { Label("Invite members", systemImage: "plus") } diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index 6476a483e..7ce57c464 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -107,10 +107,13 @@ struct GroupMemberInfoView: View { primaryButton: .destructive(Text("Remove")) { Task { do { - _ = try await apiRemoveMember(groupId: member.groupId, memberId: member.groupMemberId) - dismiss() + let member = try await apiRemoveMember(groupInfo.groupId, member.groupMemberId) + await MainActor.run { + ChatModel.shared.removeGroupMember(groupInfo, member) + dismiss() + } } catch let error { - logger.error("removeMemberAlert apiRemoveMember error: \(error.localizedDescription)") + logger.error("apiRemoveMember error: \(responseError(error))") } } }, diff --git a/apps/ios/Shared/Views/NewChat/AddGroupView.swift b/apps/ios/Shared/Views/NewChat/AddGroupView.swift index dab36fd99..7d278114e 100644 --- a/apps/ios/Shared/Views/NewChat/AddGroupView.swift +++ b/apps/ios/Shared/Views/NewChat/AddGroupView.swift @@ -26,7 +26,6 @@ struct AddGroupView: View { if let chat = chat, let groupInfo = groupInfo { AddGroupMembersView(chat: chat, groupInfo: groupInfo, - membersToAdd: filterMembersToAdd([]), showSkip: true) { _ in dismiss() DispatchQueue.main.async { @@ -148,6 +147,12 @@ struct AddGroupView: View { hideKeyboard() do { let gInfo = try apiNewGroup(profile) + Task { + let groupMembers = await apiListMembers(gInfo.groupId) + await MainActor.run { + ChatModel.shared.groupMembers = groupMembers + } + } let c = Chat(chatInfo: .group(groupInfo: gInfo), chatItems: []) m.addChat(c) withAnimation { diff --git a/apps/ios/SimpleXChat/APITypes.swift b/apps/ios/SimpleXChat/APITypes.swift index 77c2a476b..61e32fcef 100644 --- a/apps/ios/SimpleXChat/APITypes.swift +++ b/apps/ios/SimpleXChat/APITypes.swift @@ -256,6 +256,7 @@ public enum ChatResponse: Decodable, Error { // group events case groupCreated(groupInfo: GroupInfo) case sentGroupInvitation(groupInfo: GroupInfo, contact: Contact) +// case sentGroupInvitation(groupInfo: GroupInfo, contact: Contact, member: GroupMember) case userAcceptedGroupSent(groupInfo: GroupInfo) case userDeletedMember(groupInfo: GroupInfo, member: GroupMember) case leftMemberUser(groupInfo: GroupInfo) @@ -268,11 +269,11 @@ public enum ChatResponse: Decodable, Error { case leftMember(groupInfo: GroupInfo, member: GroupMember) case groupDeleted(groupInfo: GroupInfo, member: GroupMember) case contactsMerged(intoContact: Contact, mergedContact: Contact) - case groupInvitation(groupInfo: GroupInfo) + case groupInvitation(groupInfo: GroupInfo) // unused case userJoinedGroup(groupInfo: GroupInfo) case joinedGroupMember(groupInfo: GroupInfo, member: GroupMember) case connectedToGroupMember(groupInfo: GroupInfo, member: GroupMember) - case groupRemoved(groupInfo: GroupInfo) + case groupRemoved(groupInfo: GroupInfo) // unused case groupUpdated(toGroup: GroupInfo) // receiving file events case rcvFileAccepted(chatItem: AChatItem) diff --git a/src/Simplex/Chat.hs b/src/Simplex/Chat.hs index 343d248ac..214783529 100644 --- a/src/Simplex/Chat.hs +++ b/src/Simplex/Chat.hs @@ -695,24 +695,24 @@ processChatCommand = \case when (userRole < GRAdmin || userRole < memRole) $ throwChatError CEGroupUserRole when (memberStatus membership == GSMemInvited) $ throwChatError (CEGroupNotJoined gInfo) unless (memberActive membership) $ throwChatError CEGroupMemberNotActive - let sendInvitation groupMemberId memberId cReq = do + let sendInvitation member@GroupMember {groupMemberId, memberId} cReq = do let groupInv = GroupInvitation (MemberIdRole userMemberId userRole) (MemberIdRole memberId memRole) cReq groupProfile msg <- sendDirectContactMessage contact $ XGrpInv groupInv let content = CISndGroupInvitation (CIGroupInvitation {groupId, groupMemberId, localDisplayName, groupProfile, status = CIGISPending}) memRole ci <- saveSndChatItem user (CDDirectSnd contact) msg content Nothing Nothing toView . CRNewChatItem $ AChatItem SCTDirect SMDSnd (DirectChat contact) ci setActive $ ActiveG localDisplayName - pure $ CRSentGroupInvitation gInfo contact + pure $ CRSentGroupInvitation gInfo contact member case contactMember contact members of Nothing -> do gVar <- asks idsDrg (agentConnId, cReq) <- withAgent (`createConnection` SCMInvitation) - GroupMember {memberId, groupMemberId} <- withStore $ \db -> createContactMember db gVar user groupId contact memRole agentConnId cReq - sendInvitation groupMemberId memberId cReq - Just GroupMember {groupMemberId, memberId, memberStatus} + member <- withStore $ \db -> createContactMember db gVar user groupId contact memRole agentConnId cReq + sendInvitation member cReq + Just member@GroupMember {groupMemberId, memberStatus} | memberStatus == GSMemInvited -> withStore' (\db -> getMemberInvitation db user groupMemberId) >>= \case - Just cReq -> sendInvitation groupMemberId memberId cReq + Just cReq -> sendInvitation member cReq Nothing -> throwChatError $ CEGroupCantResendInvitation gInfo cName | otherwise -> throwChatError $ CEGroupDuplicateMember cName APIJoinGroup groupId -> withUser $ \user@User {userId} -> do diff --git a/src/Simplex/Chat/Controller.hs b/src/Simplex/Chat/Controller.hs index 3535d9999..a6c0c2cc4 100644 --- a/src/Simplex/Chat/Controller.hs +++ b/src/Simplex/Chat/Controller.hs @@ -230,7 +230,7 @@ data ChatResponse | CRUserAcceptedGroupSent {groupInfo :: GroupInfo} | CRUserDeletedMember {groupInfo :: GroupInfo, member :: GroupMember} | CRGroupsList {groups :: [GroupInfo]} - | CRSentGroupInvitation {groupInfo :: GroupInfo, contact :: Contact} + | CRSentGroupInvitation {groupInfo :: GroupInfo, contact :: Contact, member :: GroupMember} | CRFileTransferStatus (FileTransfer, [Integer]) -- TODO refactor this type to FileTransferStatus | CRUserProfile {profile :: Profile} | CRUserProfileNoChange diff --git a/src/Simplex/Chat/View.hs b/src/Simplex/Chat/View.hs index e05b1dd72..df209a039 100644 --- a/src/Simplex/Chat/View.hs +++ b/src/Simplex/Chat/View.hs @@ -90,7 +90,7 @@ responseToView testView = \case CRGroupCreated g -> viewGroupCreated g CRGroupMembers g -> viewGroupMembers g CRGroupsList gs -> viewGroupsList gs - CRSentGroupInvitation g c -> ["invitation to join the group " <> ttyGroup' g <> " sent to " <> ttyContact' c] + CRSentGroupInvitation g c _ -> ["invitation to join the group " <> ttyGroup' g <> " sent to " <> ttyContact' c] CRFileTransferStatus ftStatus -> viewFileTransferStatus ftStatus CRUserProfile p -> viewUserProfile p CRUserProfileNoChange -> ["user profile did not change"]