diff --git a/apps/ios/Shared/Model/ChatModel.swift b/apps/ios/Shared/Model/ChatModel.swift index af0dff94e..390e25bed 100644 --- a/apps/ios/Shared/Model/ChatModel.swift +++ b/apps/ios/Shared/Model/ChatModel.swift @@ -483,22 +483,27 @@ final class ChatModel: ObservableObject { users.filter { !$0.user.activeUser }.reduce(0, { unread, next -> Int in unread + next.unreadCount }) } - func getPrevChatItem(_ ci: ChatItem) -> ChatItem? { - if let i = getChatItemIndex(ci), i + 1 < reversedChatItems.count { - return reversedChatItems[i + 1] + func getConnectedMemberNames(_ ci: ChatItem) -> [String] { + guard var i = getChatItemIndex(ci) else { return [] } + var ns: [String] = [] + while i < reversedChatItems.count, let m = reversedChatItems[i].memberConnected { + ns.append(m.chatViewName) + i += 1 + } + return ns + } + + func getChatItemNeighbors(_ ci: ChatItem) -> (ChatItem?, ChatItem?) { + if let i = getChatItemIndex(ci) { + return ( + i + 1 < reversedChatItems.count ? reversedChatItems[i + 1] : nil, + i - 1 >= 0 ? reversedChatItems[i - 1] : nil + ) } else { - return nil + return (nil, nil) } } - func getNextChatItem(_ ci: ChatItem) -> ChatItem? { - if let i = getChatItemIndex(ci), i > 0 { - return reversedChatItems[i - 1] - } else { - return nil - } - } - func popChat(_ id: String) { if let i = getChatIndex(id) { popChat_(i) diff --git a/apps/ios/Shared/Views/Chat/ChatItem/DeletedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/DeletedItemView.swift index 80bb7ea1e..af4df4097 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/DeletedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/DeletedItemView.swift @@ -12,13 +12,9 @@ import SimpleXChat struct DeletedItemView: View { @Environment(\.colorScheme) var colorScheme var chatItem: ChatItem - var showMember = false var body: some View { HStack(alignment: .bottom, spacing: 0) { - if showMember, let member = chatItem.memberDisplayName { - Text(member).fontWeight(.medium) + Text(": ") - } Text(chatItem.content.text) .foregroundColor(.secondary) .italic() @@ -37,10 +33,7 @@ struct DeletedItemView_Previews: PreviewProvider { static var previews: some View { Group { DeletedItemView(chatItem: ChatItem.getDeletedContentSample()) - DeletedItemView( - chatItem: ChatItem.getDeletedContentSample(dir: .groupRcv(groupMember: GroupMember.sampleData)), - showMember: true - ) + DeletedItemView(chatItem: ChatItem.getDeletedContentSample(dir: .groupRcv(groupMember: GroupMember.sampleData))) } .previewLayout(.fixed(width: 360, height: 200)) } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift index 3a31ee450..2dfd0f15f 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/FramedItemView.swift @@ -18,7 +18,6 @@ struct FramedItemView: View { @Environment(\.colorScheme) var colorScheme var chatInfo: ChatInfo var chatItem: ChatItem - var showMember = false var maxWidth: CGFloat = .infinity @State var scrollProxy: ScrollViewProxy? = nil @State var msgWidth: CGFloat = 0 @@ -57,7 +56,7 @@ struct FramedItemView: View { } } - ChatItemContentView(chatInfo: chatInfo, chatItem: chatItem, showMember: showMember, msgContentView: framedMsgContentView) + ChatItemContentView(chatInfo: chatInfo, chatItem: chatItem, msgContentView: framedMsgContentView) .padding(chatItem.content.msgContent != nil ? 0 : 4) .overlay(DetermineWidth()) } @@ -107,7 +106,7 @@ struct FramedItemView: View { value: .white ) } else { - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) } case let .video(text, image, duration): CIVideoView(chatItem: chatItem, image: image, duration: duration, maxWidth: maxWidth, videoWidth: $videoWidth, scrollProxy: scrollProxy) @@ -120,27 +119,27 @@ struct FramedItemView: View { value: .white ) } else { - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) } case let .voice(text, duration): FramedCIVoiceView(chatItem: chatItem, recordingFile: chatItem.file, duration: duration, allowMenu: $allowMenu, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime) .overlay(DetermineWidth()) if text != "" { - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) } case let .file(text): ciFileView(chatItem, text) case let .link(_, preview): CILinkView(linkPreview: preview) - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) case let .unknown(_, text: text): if chatItem.file == nil { - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) } else { ciFileView(chatItem, text) } default: - ciMsgContentView (chatItem, showMember) + ciMsgContentView(chatItem) } } } @@ -232,17 +231,27 @@ struct FramedItemView: View { } private func ciQuotedMsgView(_ qi: CIQuote) -> some View { - MsgContentView( - text: qi.text, - formattedText: qi.formattedText, - sender: qi.getSender(membership()) - ) - .lineLimit(3) - .font(.subheadline) - .padding(.vertical, 6) + Group { + if let sender = qi.getSender(membership()) { + VStack(alignment: .leading, spacing: 2) { + Text(sender).font(.caption).foregroundColor(.secondary) + ciQuotedMsgTextView(qi, lines: 2) + } + } else { + ciQuotedMsgTextView(qi, lines: 3) + } + } + .padding(.top, 6) .padding(.horizontal, 12) } + private func ciQuotedMsgTextView(_ qi: CIQuote, lines: Int) -> some View { + MsgContentView(text: qi.text, formattedText: qi.formattedText) + .lineLimit(lines) + .font(.subheadline) + .padding(.bottom, 6) + } + private func ciQuoteIconView(_ image: String) -> some View { Image(systemName: image) .resizable() @@ -260,13 +269,12 @@ struct FramedItemView: View { } } - @ViewBuilder private func ciMsgContentView(_ ci: ChatItem, _ showMember: Bool = false) -> some View { + @ViewBuilder private func ciMsgContentView(_ ci: ChatItem) -> some View { let text = ci.meta.isLive ? ci.content.msgContent?.text ?? ci.text : ci.text let rtl = isRightToLeft(text) let v = MsgContentView( text: text, formattedText: text == "" ? [] : ci.formattedText, - sender: showMember ? ci.memberDisplayName : nil, meta: ci.meta, rightToLeft: rtl ) @@ -288,7 +296,7 @@ struct FramedItemView: View { CIFileView(file: chatItem.file, edited: chatItem.meta.itemEdited) .overlay(DetermineWidth()) if text != "" || ci.meta.isLive { - ciMsgContentView (chatItem, showMember) + ciMsgContentView (chatItem) } } diff --git a/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift index 1ab631232..9908d4d10 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/IntegrityErrorItemView.swift @@ -12,10 +12,9 @@ import SimpleXChat struct IntegrityErrorItemView: View { var msgError: MsgErrorType var chatItem: ChatItem - var showMember = false var body: some View { - CIMsgError(chatItem: chatItem, showMember: showMember) { + CIMsgError(chatItem: chatItem) { switch msgError { case .msgSkipped: AlertManager.shared.showAlertMsg( @@ -54,14 +53,10 @@ struct IntegrityErrorItemView: View { struct CIMsgError: View { var chatItem: ChatItem - var showMember = false var onTap: () -> Void var body: some View { HStack(alignment: .bottom, spacing: 0) { - if showMember, let member = chatItem.memberDisplayName { - Text(member).fontWeight(.medium) + Text(": ") - } Text(chatItem.content.text) .foregroundColor(.red) .italic() diff --git a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift index 96d3c8eca..8e042a8c7 100644 --- a/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItem/MarkedDeletedItemView.swift @@ -12,13 +12,9 @@ import SimpleXChat struct MarkedDeletedItemView: View { @Environment(\.colorScheme) var colorScheme var chatItem: ChatItem - var showMember = false var body: some View { HStack(alignment: .bottom, spacing: 0) { - if showMember, let member = chatItem.memberDisplayName { - Text(member).font(.caption).fontWeight(.medium) + Text(": ").font(.caption) - } if case let .moderated(_, byGroupMember) = chatItem.meta.itemDeleted { markedDeletedText("moderated by \(byGroupMember.chatViewName)") } else { diff --git a/apps/ios/Shared/Views/Chat/ChatItemView.swift b/apps/ios/Shared/Views/Chat/ChatItemView.swift index 1a3704c1f..5d816ac64 100644 --- a/apps/ios/Shared/Views/Chat/ChatItemView.swift +++ b/apps/ios/Shared/Views/Chat/ChatItemView.swift @@ -12,7 +12,6 @@ import SimpleXChat struct ChatItemView: View { var chatInfo: ChatInfo var chatItem: ChatItem - var showMember = false var maxWidth: CGFloat = .infinity @State var scrollProxy: ScrollViewProxy? = nil @Binding var revealed: Bool @@ -23,7 +22,6 @@ struct ChatItemView: View { init(chatInfo: ChatInfo, chatItem: ChatItem, showMember: Bool = false, maxWidth: CGFloat = .infinity, scrollProxy: ScrollViewProxy? = nil, revealed: Binding, allowMenu: Binding = .constant(false), audioPlayer: Binding = .constant(nil), playbackState: Binding = .constant(.noPlayback), playbackTime: Binding = .constant(nil)) { self.chatInfo = chatInfo self.chatItem = chatItem - self.showMember = showMember self.maxWidth = maxWidth _scrollProxy = .init(initialValue: scrollProxy) _revealed = revealed @@ -36,14 +34,14 @@ struct ChatItemView: View { var body: some View { let ci = chatItem if chatItem.meta.itemDeleted != nil && !revealed { - MarkedDeletedItemView(chatItem: chatItem, showMember: showMember) + MarkedDeletedItemView(chatItem: chatItem) } else if ci.quotedItem == nil && ci.meta.itemDeleted == nil && !ci.meta.isLive { if let mc = ci.content.msgContent, mc.isText && isShortEmoji(ci.content.text) { EmojiItemView(chatItem: ci) } else if ci.content.text.isEmpty, case let .voice(_, duration) = ci.content.msgContent { CIVoiceView(chatItem: ci, recordingFile: ci.file, duration: duration, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime, allowMenu: $allowMenu) } else if ci.content.msgContent == nil { - ChatItemContentView(chatInfo: chatInfo, chatItem: chatItem, showMember: showMember, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case + ChatItemContentView(chatInfo: chatInfo, chatItem: chatItem, msgContentView: { Text(ci.text) }) // msgContent is unreachable branch in this case } else { framedItemView() } @@ -53,7 +51,7 @@ struct ChatItemView: View { } private func framedItemView() -> some View { - FramedItemView(chatInfo: chatInfo, chatItem: chatItem, showMember: showMember, maxWidth: maxWidth, scrollProxy: scrollProxy, allowMenu: $allowMenu, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime) + FramedItemView(chatInfo: chatInfo, chatItem: chatItem, maxWidth: maxWidth, scrollProxy: scrollProxy, allowMenu: $allowMenu, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime) } } @@ -61,7 +59,6 @@ struct ChatItemContentView: View { @EnvironmentObject var chatModel: ChatModel var chatInfo: ChatInfo var chatItem: ChatItem - var showMember: Bool var msgContentView: () -> Content var body: some View { @@ -72,11 +69,11 @@ struct ChatItemContentView: View { case .rcvDeleted: deletedItemView() case let .sndCall(status, duration): callItemView(status, duration) case let .rcvCall(status, duration): callItemView(status, duration) - case let .rcvIntegrityError(msgError): IntegrityErrorItemView(msgError: msgError, chatItem: chatItem, showMember: showMember) - case let .rcvDecryptionError(msgDecryptError, msgCount): CIRcvDecryptionError(msgDecryptError: msgDecryptError, msgCount: msgCount, chatItem: chatItem, showMember: showMember) + case let .rcvIntegrityError(msgError): IntegrityErrorItemView(msgError: msgError, chatItem: chatItem) + case let .rcvDecryptionError(msgDecryptError, msgCount): CIRcvDecryptionError(msgDecryptError: msgDecryptError, msgCount: msgCount, chatItem: chatItem) case let .rcvGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole) case let .sndGroupInvitation(groupInvitation, memberRole): groupInvitationItemView(groupInvitation, memberRole) - case .rcvGroupEvent(.memberConnected): CIEventView(eventText: membersConnectedItemText()) + case .rcvGroupEvent(.memberConnected): CIEventView(eventText: membersConnectedItemText) case .rcvGroupEvent: eventItemView() case .sndGroupEvent: eventItemView() case .rcvConnEvent: eventItemView() @@ -98,7 +95,7 @@ struct ChatItemContentView: View { } private func deletedItemView() -> some View { - DeletedItemView(chatItem: chatItem, showMember: showMember) + DeletedItemView(chatItem: chatItem) } private func callItemView(_ status: CICallStatus, _ duration: Int) -> some View { @@ -115,11 +112,10 @@ struct ChatItemContentView: View { private func eventItemViewText() -> Text { if let member = chatItem.memberDisplayName { - return Text(member) + return Text(member + " ") .font(.caption) .foregroundColor(.secondary) .fontWeight(.light) - + Text(" ") + chatEventText(chatItem) } else { return chatEventText(chatItem) @@ -130,64 +126,35 @@ struct ChatItemContentView: View { CIChatFeatureView(chatItem: chatItem, feature: feature, iconColor: iconColor) } - private func membersConnectedItemText() -> Text { - if case let .groupRcv(member) = chatItem.chatDir, - let prevItem = chatModel.getPrevChatItem(chatItem), - let prevMember = prevItem.memberConnected, - let membersConnectedText = membersConnectedText(connectedMemberNames(member, prevMember, prevItem)) { - return chatEventText(membersConnectedText, chatItem.timestampText) + private var membersConnectedItemText: Text { + if let t = membersConnectedText { + return chatEventText(t, chatItem.timestampText) } else { return eventItemViewText() } - - func connectedMemberNames(_ member: GroupMember, _ prevMember: GroupMember, _ prevItem: ChatItem) -> [String] { - [member.chatViewName, prevMember.chatViewName] + collectPrevConnectedMemberNames(prevItem) - } } - private func collectPrevConnectedMemberNames(_ ci: ChatItem) -> [String] { - guard let prevItem = chatModel.getPrevChatItem(ci), - let memberConnected = prevItem.memberConnected else { - return [] - } - let prevMemberNames = collectPrevConnectedMemberNames(prevItem) - return [memberConnected.chatViewName] + prevMemberNames - } - - private func membersConnectedText(_ memberNames: [String]) -> String? { - if memberNames.count > 3 { - return String.localizedStringWithFormat( - NSLocalizedString("%@ and %d other members connected", comment: " and = 2> other members connected (plural)"), - Array(memberNames.prefix(2)).joined(separator: ", "), - memberNames.count - 2 - ) - } else if memberNames.count >= 2, - let lastMemberName = memberNames.last { - return String.localizedStringWithFormat( - NSLocalizedString("%@ and %@ connected", comment: " and connected (plural)"), - memberNames.dropLast().joined(separator: ", "), - lastMemberName - ) - } else { - return nil - } + private var membersConnectedText: LocalizedStringKey? { + let ns = chatModel.getConnectedMemberNames(chatItem) + return ns.count > 3 + ? "\(ns[0]), \(ns[1]) and \(ns.count - 2) other members connected" + : ns.count == 3 + ? "\(ns[0] + ", " + ns[1]) and \(ns[2]) connected" + : ns.count == 2 + ? "\(ns[0]) and \(ns[1]) connected" + : nil } } -func chatEventText(_ eventText: String, _ ts: Text) -> Text { - Text(eventText) +func chatEventText(_ eventText: LocalizedStringKey, _ ts: Text) -> Text { + (Text(eventText) + Text(" ") + ts) .font(.caption) .foregroundColor(.secondary) .fontWeight(.light) - + Text(" ") - + ts - .font(.caption) - .foregroundColor(Color.secondary) - .fontWeight(.light) } func chatEventText(_ ci: ChatItem) -> Text { - chatEventText(ci.content.text, ci.timestampText) + chatEventText("\(ci.content.text)", ci.timestampText) } struct ChatItemView_Previews: PreviewProvider { diff --git a/apps/ios/Shared/Views/Chat/ChatView.swift b/apps/ios/Shared/Views/Chat/ChatView.swift index 010fdc769..a73bb766e 100644 --- a/apps/ios/Shared/Views/Chat/ChatView.swift +++ b/apps/ios/Shared/Views/Chat/ChatView.swift @@ -430,63 +430,64 @@ struct ChatView: View { @ViewBuilder private func chatItemView(_ ci: ChatItem, _ maxWidth: CGFloat) -> some View { if case let .groupRcv(member) = ci.chatDir, case let .group(groupInfo) = chat.chatInfo { - let nextItem = chatModel.getNextChatItem(ci) + let (prevItem, nextItem) = chatModel.getChatItemNeighbors(ci) if ci.memberConnected != nil && nextItem?.memberConnected != nil { // memberConnected events are aggregated at the last chat item in a row of such events, see ChatItemView ZStack {} // scroll doesn't work if it's EmptyView() } else { - 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 { selectedMember = member } - .appSheet(item: $selectedMember) { member in - GroupMemberInfoView(groupInfo: groupInfo, member: member, navigation: true) - } - } else { - Rectangle().fill(.clear) - .frame(width: memberImageSize, height: memberImageSize) + if prevItem == nil || showMemberImage(member, prevItem) { + VStack(alignment: .leading, spacing: 4) { + if ci.content.showMemberName { + Text(member.displayName) + .font(.caption) + .foregroundStyle(.secondary) + .padding(.leading, memberImageSize + 14) + .padding(.top, 7) + } + HStack(alignment: .top, spacing: 8) { + ProfileImage(imageStr: member.memberProfile.image) + .frame(width: memberImageSize, height: memberImageSize) + .onTapGesture { selectedMember = member } + .appSheet(item: $selectedMember) { member in + GroupMemberInfoView(groupInfo: groupInfo, member: member, navigation: true) + } + chatItemWithMenu(ci, maxWidth) + } } - ChatItemWithMenu( - ci: ci, - showMember: showMember, - maxWidth: maxWidth, - scrollProxy: scrollProxy, - deleteMessage: deleteMessage, - deletingItem: $deletingItem, - composeState: $composeState, - showDeleteMessage: $showDeleteMessage - ) - .padding(.leading, 8) - .environmentObject(chat) + .padding(.top, 5) + .padding(.trailing) + .padding(.leading, 12) + } else { + chatItemWithMenu(ci, maxWidth) + .padding(.top, 5) + .padding(.trailing) + .padding(.leading, memberImageSize + 8 + 12) } - .padding(.trailing) - .padding(.leading, 12) - .padding(.bottom, 5) } } else { - ChatItemWithMenu( - ci: ci, - maxWidth: maxWidth, - scrollProxy: scrollProxy, - deleteMessage: deleteMessage, - deletingItem: $deletingItem, - composeState: $composeState, - showDeleteMessage: $showDeleteMessage - ) - .padding(.horizontal) - .padding(.bottom, 5) - .environmentObject(chat) + chatItemWithMenu(ci, maxWidth) + .padding(.horizontal) + .padding(.top, 5) } } + private func chatItemWithMenu(_ ci: ChatItem, _ maxWidth: CGFloat) -> some View { + ChatItemWithMenu( + ci: ci, + maxWidth: maxWidth, + scrollProxy: scrollProxy, + deleteMessage: deleteMessage, + deletingItem: $deletingItem, + composeState: $composeState, + showDeleteMessage: $showDeleteMessage + ) + .environmentObject(chat) + } + private struct ChatItemWithMenu: View { @EnvironmentObject var chat: Chat @Environment(\.colorScheme) var colorScheme var ci: ChatItem - var showMember: Bool = false var maxWidth: CGFloat var scrollProxy: ScrollViewProxy? var deleteMessage: (CIDeleteMode) -> Void @@ -512,7 +513,7 @@ struct ChatView: View { ) VStack(alignment: alignment.horizontal, spacing: 3) { - ChatItemView(chatInfo: chat.chatInfo, chatItem: ci, showMember: showMember, maxWidth: maxWidth, scrollProxy: scrollProxy, revealed: $revealed, allowMenu: $allowMenu, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime) + ChatItemView(chatInfo: chat.chatInfo, chatItem: ci, maxWidth: maxWidth, scrollProxy: scrollProxy, revealed: $revealed, allowMenu: $allowMenu, audioPlayer: $audioPlayer, playbackState: $playbackState, playbackTime: $playbackTime) .uiKitContextMenu(menu: uiMenu, allowMenu: $allowMenu) if ci.content.msgContent != nil && (ci.meta.itemDeleted == nil || revealed) && ci.reactions.count > 0 { chatItemReactions() diff --git a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift index a9847afe4..153d89fc2 100644 --- a/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift +++ b/apps/ios/Shared/Views/Chat/ComposeMessage/ContextItemView.swift @@ -22,13 +22,14 @@ struct ContextItemView: View { .aspectRatio(contentMode: .fit) .frame(width: 16, height: 16) .foregroundColor(.secondary) - MsgContentView( - text: contextItem.text, - formattedText: contextItem.formattedText, - sender: contextItem.memberDisplayName - ) - .multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading) - .lineLimit(3) + if let sender = contextItem.memberDisplayName { + VStack(alignment: .leading, spacing: 4) { + Text(sender).font(.caption).foregroundColor(.secondary) + msgContentView(lines: 2) + } + } else { + msgContentView(lines: 3) + } Spacer() Button { withAnimation { @@ -44,6 +45,15 @@ struct ContextItemView: View { .background(chatItemFrameColor(contextItem, colorScheme)) .padding(.top, 8) } + + private func msgContentView(lines: Int) -> some View { + MsgContentView( + text: contextItem.text, + formattedText: contextItem.formattedText + ) + .multilineTextAlignment(isRightToLeft(contextItem.text) ? .trailing : .leading) + .lineLimit(lines) + } } struct ContextItemView_Previews: PreviewProvider { diff --git a/apps/ios/SimpleXChat/ChatTypes.swift b/apps/ios/SimpleXChat/ChatTypes.swift index 7bed96cb0..5bdd03ace 100644 --- a/apps/ios/SimpleXChat/ChatTypes.swift +++ b/apps/ios/SimpleXChat/ChatTypes.swift @@ -2530,6 +2530,25 @@ public enum CIContent: Decodable, ItemContent { } } } + + public var showMemberName: Bool { + switch self { + case .sndMsgContent: return true + case .rcvMsgContent: return true + case .sndDeleted: return true + case .rcvDeleted: return true + case .sndCall: return true + case .rcvCall: return true + case .rcvIntegrityError: return true + case .rcvDecryptionError: return true + case .rcvGroupInvitation: return true + case .sndChatPreference: return true + case .sndModerated: return true + case .rcvModerated: return true + case .invalidJSON: return true + default: return false + } + } } public enum MsgDecryptError: String, Decodable {