diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index b5ea8afcc4..42dfb7b676 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -31,6 +31,10 @@ struct ChatView: View { @State private var searchMode = false @State private var searchText: String = "" @FocusState private var searchFocussed + // opening GroupMemberInfoView on member icon + @State private var selectedMember: GroupMember? = nil + @State private var memberConnectionStats: ConnectionStats? + @State private var memberMainProfile: LocalProfile? var body: some View { let cInfo = chat.chatInfo @@ -73,8 +77,8 @@ struct ChatView: View { } } ToolbarItem(placement: .principal) { - Button { - if case .direct = cInfo { + if case let .direct(contact) = cInfo { + Button { Task { do { let (stats, profile) = try await apiContactInfo(contactId: chat.chatInfo.apiId) @@ -87,7 +91,17 @@ struct ChatView: View { } await MainActor.run { showChatInfoSheet = true } } - } else if case let .group(groupInfo) = cInfo { + } label: { + ChatInfoToolbar(chat: chat) + } + .sheet(isPresented: $showChatInfoSheet, onDismiss: { + connectionStats = nil + customUserProfile = nil + }) { + ChatInfoView(chat: chat, contact: contact, connectionStats: connectionStats, customUserProfile: customUserProfile, localAlias: chat.chatInfo.localAlias) + } + } else if case let .group(groupInfo) = cInfo { + Button { Task { let groupMembers = await apiListMembers(groupInfo.groupId) await MainActor.run { @@ -95,18 +109,11 @@ struct ChatView: View { showChatInfoSheet = true } } + } label: { + ChatInfoToolbar(chat: chat) } - } label: { - ChatInfoToolbar(chat: chat) - } - .sheet(isPresented: $showChatInfoSheet) { - switch cInfo { - case let .direct(contact): - ChatInfoView(chat: chat, contact: contact, connectionStats: connectionStats, customUserProfile: customUserProfile, localAlias: chat.chatInfo.localAlias) - case let .group(groupInfo): + .sheet(isPresented: $showChatInfoSheet) { GroupChatInfoView(chat: chat, groupInfo: groupInfo) - default: - EmptyView() } } } @@ -342,13 +349,34 @@ struct ChatView: View { } @ViewBuilder private func chatItemView(_ ci: ChatItem, _ maxWidth: CGFloat) -> some View { - if case let .groupRcv(member) = ci.chatDir { + if case let .groupRcv(member) = ci.chatDir, + case let .group(groupInfo) = chat.chatInfo { let prevItem = chatModel.getPrevChatItem(ci) HStack(alignment: .top, spacing: 0) { let showMember = prevItem == nil || showMemberImage(member, prevItem) if showMember { ProfileImage(imageStr: member.memberProfile.image) .frame(width: memberImageSize, height: memberImageSize) + .onTapGesture { + Task { + do { + let (stats, profile) = try await apiGroupMemberInfo(member.groupId, member.groupMemberId) + await MainActor.run { + memberConnectionStats = stats + memberMainProfile = profile + } + } catch let error { + logger.error("apiGroupMemberInfo error: \(responseError(error))") + } + await MainActor.run { selectedMember = member } + } + } + .sheet(item: $selectedMember, onDismiss: { + memberConnectionStats = nil + memberMainProfile = nil + }) { member in + GroupMemberInfoView(groupInfo: groupInfo, member: member, connectionStats: memberConnectionStats, mainProfile: memberMainProfile) + } } else { Rectangle().fill(.clear) .frame(width: memberImageSize, height: memberImageSize) diff --git a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift index 90e721d431..1ce709881e 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupChatInfoView.swift @@ -66,7 +66,10 @@ struct GroupChatInfoView: View { .sheet(isPresented: $showAddMembersSheet) { AddGroupMembersView(chat: chat, groupInfo: groupInfo) } - .sheet(item: $selectedMember, onDismiss: { connectionStats = nil }) { member in + .sheet(item: $selectedMember, onDismiss: { + connectionStats = nil + memberMainProfile = nil + }) { member in GroupMemberInfoView(groupInfo: groupInfo, member: member, connectionStats: connectionStats, mainProfile: memberMainProfile) } .sheet(isPresented: $showGroupProfile) { diff --git a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift index 96127affc6..5fa144bd75 100644 --- a/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift +++ b/apps/ios/Shared/Views/Chat/Group/GroupMemberInfoView.swift @@ -31,6 +31,12 @@ struct GroupMemberInfoView: View { groupMemberInfoHeader() .listRowBackground(Color.clear) +// if let contactId = member.memberContactId { +// Section { +// openDirectChatButton(contactId) +// } +// } + Section("Member") { infoRow("Group", groupInfo.displayName) if let mainProfile = mainProfile { @@ -76,6 +82,23 @@ struct GroupMemberInfoView: View { } } + func openDirectChatButton(_ contactId: Int64) -> some View { + Button { + if let i = chatModel.chats.firstIndex(where: { chat in + switch chat.chatInfo { + case let .direct(contact): return contact.contactId == contactId + default: return false + } + }) { + dismissAllSheets(animated: true) + chatModel.chatId = chatModel.chats[i].chatInfo.id + } + } label: { + Label("Send direct message", systemImage: "message") + .foregroundColor(.accentColor) + } + } + private func mainProfileRow(_ mainProfile: LocalProfile) -> some View { HStack { Text("Known main profile") diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index a15ac63df1..72664dabd3 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -311,7 +311,7 @@ public struct ChatStats: Decodable { } public struct Contact: Identifiable, Decodable, NamedChat { - var contactId: Int64 + public var contactId: Int64 var localDisplayName: ContactName public var profile: LocalProfile public var activeConn: Connection