mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-31 10:19:23 +00:00
Add avatar to group chat
Check first message received per participant
This commit is contained in:
parent
d7a7615616
commit
a011e7643b
14 changed files with 261 additions and 48 deletions
|
|
@ -377,7 +377,7 @@ struct CallView: View {
|
|||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
|
|
@ -732,7 +732,7 @@ struct CallView: View {
|
|||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@ struct CallsListFragment: View {
|
|||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ class MeetingWaitingRoomViewModel: ObservableObject {
|
|||
? ContactsManager.shared.getFriendWithAddress(address: core.defaultAccount!.contactAddress!)
|
||||
: nil
|
||||
|
||||
let addressTmp = friend?.address?.asStringUriOnly() ?? ""
|
||||
|
||||
if friend != nil && friend!.address != nil && friend!.address!.displayName != nil {
|
||||
userNameTmp = friend!.address!.displayName!
|
||||
} else {
|
||||
|
|
@ -82,8 +84,8 @@ class MeetingWaitingRoomViewModel: ObservableObject {
|
|||
? ContactsManager.shared.avatarListModel.first(where: {
|
||||
$0.friend!.name == friend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == core.defaultAccount!.contactAddress!.asStringUriOnly()
|
||||
}) ?? ContactAvatarModel(friend: nil, name: userNameTmp, withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: userNameTmp, withPresence: false)
|
||||
}) ?? ContactAvatarModel(friend: nil, name: userNameTmp, address: addressTmp, withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: userNameTmp, address: addressTmp, withPresence: false)
|
||||
|
||||
if core.videoEnabled && !core.videoPreviewEnabled {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ struct ContactInnerFragment: View {
|
|||
|
||||
#Preview {
|
||||
ContactInnerFragment(
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", withPresence: true),
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: true),
|
||||
contactViewModel: ContactViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
isShowDeletePopup: .constant(false),
|
||||
|
|
|
|||
|
|
@ -155,7 +155,12 @@ struct EditContactFragment: View {
|
|||
&& !editContactViewModel.selectedEditFriend!.photo!.isEmpty && selectedImage == nil && !removedImage {
|
||||
|
||||
Avatar(contactAvatarModel:
|
||||
ContactAvatarModel(friend: editContactViewModel.selectedEditFriend!, name: editContactViewModel.selectedEditFriend?.name ?? "", withPresence: false), avatarSize: 100
|
||||
ContactAvatarModel(
|
||||
friend: editContactViewModel.selectedEditFriend!,
|
||||
name: editContactViewModel.selectedEditFriend?.name ?? "",
|
||||
address: editContactViewModel.selectedEditFriend?.address?.asStringUriOnly() ?? "",
|
||||
withPresence: false
|
||||
), avatarSize: 100
|
||||
)
|
||||
|
||||
} else if selectedImage == nil {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ class ContactAvatarModel: ObservableObject {
|
|||
|
||||
let name: String
|
||||
|
||||
let address: String
|
||||
|
||||
let withPresence: Bool?
|
||||
|
||||
@Published var lastPresenceInfo: String
|
||||
|
|
@ -35,9 +37,10 @@ class ContactAvatarModel: ObservableObject {
|
|||
|
||||
private var friendSuscription: AnyCancellable?
|
||||
|
||||
init(friend: Friend?, name: String, withPresence: Bool?) {
|
||||
init(friend: Friend?, name: String, address: String, withPresence: Bool?) {
|
||||
self.friend = friend
|
||||
self.name = name
|
||||
self.address = address
|
||||
self.withPresence = withPresence
|
||||
if friend != nil &&
|
||||
withPresence == true {
|
||||
|
|
@ -122,12 +125,12 @@ class ContactAvatarModel: ObservableObject {
|
|||
})
|
||||
|
||||
if avatarModel == nil {
|
||||
avatarModel = ContactAvatarModel(friend: nil, name: addressFriend.name!, withPresence: false)
|
||||
avatarModel = ContactAvatarModel(friend: nil, name: addressFriend.name!, address: address.asStringUriOnly(), withPresence: false)
|
||||
}
|
||||
return avatarModel!
|
||||
} else {
|
||||
let name = address.displayName != nil ? address.displayName! : address.username!
|
||||
return ContactAvatarModel(friend: nil, name: name, withPresence: false)
|
||||
return ContactAvatarModel(friend: nil, name: name, address: address.asStringUriOnly(), withPresence: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -728,7 +728,7 @@ struct ContentView: View {
|
|||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
if contactAvatarModel != nil {
|
||||
HistoryContactFragment(
|
||||
|
|
|
|||
|
|
@ -30,32 +30,106 @@ struct ChatBubbleView: View {
|
|||
|
||||
var body: some View {
|
||||
VStack {
|
||||
HStack {
|
||||
if message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
|
||||
VStack(alignment: message.isOutgoing ? .trailing : .leading) {
|
||||
if !message.attachments.isEmpty {
|
||||
messageAttachments()
|
||||
if !message.text.isEmpty || !message.attachments.isEmpty {
|
||||
HStack {
|
||||
if message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if !message.text.isEmpty {
|
||||
Text(message.text)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.default_text_style(styleSize: 16)
|
||||
if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup && !message.isOutgoing && message.isFirstMessage {
|
||||
VStack {
|
||||
Avatar(
|
||||
contactAvatarModel: conversationViewModel.participantConversationModel.first(where: {$0.address == message.address}) ??
|
||||
ContactAvatarModel(friend: nil, name: "??", address: "", withPresence: false),
|
||||
avatarSize: 35
|
||||
)
|
||||
.padding(.top, 30)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
} else if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup && !message.isOutgoing {
|
||||
VStack {
|
||||
Avatar(
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "??", address: "", withPresence: false),
|
||||
avatarSize: 35
|
||||
)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
.hidden()
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup && !message.isOutgoing && message.isFirstMessage {
|
||||
Text(conversationViewModel.participantConversationModel.first(where: {$0.address == message.address})?.name ?? "")
|
||||
.default_text_style(styleSize: 12)
|
||||
.padding(.top, 10)
|
||||
.padding(.bottom, 2)
|
||||
}
|
||||
ZStack {
|
||||
if conversationViewModel.displayedConversation != nil && conversationViewModel.displayedConversation!.isGroup && message.isFirstMessage {
|
||||
VStack {
|
||||
if message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
|
||||
HStack {
|
||||
if message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
|
||||
VStack {
|
||||
}
|
||||
.frame(width: 15, height: 15)
|
||||
.background(message.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 2))
|
||||
|
||||
if !message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
|
||||
if !message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HStack {
|
||||
if message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
|
||||
VStack(alignment: message.isOutgoing ? .trailing : .leading) {
|
||||
if !message.attachments.isEmpty {
|
||||
messageAttachments()
|
||||
}
|
||||
|
||||
if !message.text.isEmpty {
|
||||
Text(message.text)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.default_text_style(styleSize: 16)
|
||||
}
|
||||
}
|
||||
.padding(.all, 15)
|
||||
.background(message.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||||
|
||||
if !message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
|
||||
if !message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
}
|
||||
.padding(.all, 15)
|
||||
.background(message.isOutgoing ? Color.orangeMain100 : Color.grayMain2c100)
|
||||
.clipShape(RoundedRectangle(cornerRadius: 16))
|
||||
|
||||
if !message.isOutgoing {
|
||||
Spacer()
|
||||
}
|
||||
.padding(.leading, message.isOutgoing ? 40 : 0)
|
||||
.padding(.trailing, !message.isOutgoing ? 40 : 0)
|
||||
}
|
||||
.padding(.leading, message.isOutgoing ? 40 : 0)
|
||||
.padding(.trailing, !message.isOutgoing ? 40 : 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ class ConversationModel: ObservableObject {
|
|||
|
||||
self.unreadMessagesCount = 0
|
||||
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
//self.isBeingDeleted = MutableLiveData<Boolean>()
|
||||
|
||||
|
|
@ -199,13 +199,25 @@ class ConversationModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
let addressTmp = addressFriend?.address?.asStringUriOnly() ?? ""
|
||||
|
||||
let avatarModelTmp = addressFriend != nil && !self.isGroup
|
||||
? ContactsManager.shared.avatarListModel.first(where: {
|
||||
$0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
?? ContactAvatarModel(friend: nil, name: self.subject, withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: self.subject, withPresence: false)
|
||||
?? ContactAvatarModel(
|
||||
friend: nil,
|
||||
name: self.subject,
|
||||
address: addressTmp,
|
||||
withPresence: false
|
||||
)
|
||||
: ContactAvatarModel(
|
||||
friend: nil,
|
||||
name: self.subject,
|
||||
address: addressTmp,
|
||||
withPresence: false
|
||||
)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.avatarModel = avatarModelTmp
|
||||
|
|
|
|||
|
|
@ -61,6 +61,8 @@ public struct Message: Identifiable, Hashable {
|
|||
public var createdAt: Date
|
||||
public var isOutgoing: Bool
|
||||
|
||||
public var address: String
|
||||
public var isFirstMessage: Bool
|
||||
public var text: String
|
||||
public var attachments: [Attachment]
|
||||
public var recording: Recording?
|
||||
|
|
@ -71,6 +73,8 @@ public struct Message: Identifiable, Hashable {
|
|||
status: Status? = nil,
|
||||
createdAt: Date = Date(),
|
||||
isOutgoing: Bool,
|
||||
address: String,
|
||||
isFirstMessage: Bool = false,
|
||||
text: String = "",
|
||||
attachments: [Attachment] = [],
|
||||
recording: Recording? = nil,
|
||||
|
|
@ -80,6 +84,8 @@ public struct Message: Identifiable, Hashable {
|
|||
self.status = status
|
||||
self.createdAt = createdAt
|
||||
self.isOutgoing = isOutgoing
|
||||
self.isFirstMessage = isFirstMessage
|
||||
self.address = address
|
||||
self.text = text
|
||||
self.attachments = attachments
|
||||
self.recording = recording
|
||||
|
|
@ -111,6 +117,8 @@ public struct Message: Identifiable, Hashable {
|
|||
status: status,
|
||||
createdAt: draft.createdAt,
|
||||
isOutgoing: draft.isOutgoing,
|
||||
address: draft.address,
|
||||
isFirstMessage: draft.isFirstMessage,
|
||||
text: draft.text,
|
||||
attachments: attachments,
|
||||
recording: draft.recording,
|
||||
|
|
@ -127,7 +135,7 @@ extension Message {
|
|||
|
||||
extension Message: Equatable {
|
||||
public static func == (lhs: Message, rhs: Message) -> Bool {
|
||||
lhs.id == rhs.id && lhs.status == rhs.status
|
||||
lhs.id == rhs.id && lhs.status == rhs.status && lhs.isFirstMessage == rhs.isFirstMessage
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -150,18 +158,24 @@ public struct ReplyMessage: Codable, Identifiable, Hashable {
|
|||
|
||||
public var id: String
|
||||
|
||||
public var address: String
|
||||
public var isFirstMessage: Bool
|
||||
public var text: String
|
||||
public var isOutgoing: Bool
|
||||
public var attachments: [Attachment]
|
||||
public var recording: Recording?
|
||||
|
||||
public init(id: String,
|
||||
address: String,
|
||||
isFirstMessage: Bool = false,
|
||||
text: String = "",
|
||||
isOutgoing: Bool,
|
||||
attachments: [Attachment] = [],
|
||||
recording: Recording? = nil) {
|
||||
|
||||
self.id = id
|
||||
self.address = address
|
||||
self.isFirstMessage = isFirstMessage
|
||||
self.text = text
|
||||
self.isOutgoing = isOutgoing
|
||||
self.attachments = attachments
|
||||
|
|
@ -169,20 +183,22 @@ public struct ReplyMessage: Codable, Identifiable, Hashable {
|
|||
}
|
||||
|
||||
func toMessage() -> Message {
|
||||
Message(id: id, isOutgoing: isOutgoing, text: text, attachments: attachments, recording: recording)
|
||||
Message(id: id, isOutgoing: isOutgoing, address: address, isFirstMessage: isFirstMessage, text: text, attachments: attachments, recording: recording)
|
||||
}
|
||||
}
|
||||
|
||||
public extension Message {
|
||||
|
||||
func toReplyMessage() -> ReplyMessage {
|
||||
ReplyMessage(id: id, text: text, isOutgoing: isOutgoing, attachments: attachments, recording: recording)
|
||||
ReplyMessage(id: id, address: address, isFirstMessage: isFirstMessage, text: text, isOutgoing: isOutgoing, attachments: attachments, recording: recording)
|
||||
}
|
||||
}
|
||||
|
||||
public struct DraftMessage {
|
||||
public var id: String?
|
||||
public let isOutgoing: Bool
|
||||
public let address: String
|
||||
public let isFirstMessage: Bool
|
||||
public let text: String
|
||||
public let medias: [Media]
|
||||
public let recording: Recording?
|
||||
|
|
@ -191,6 +207,8 @@ public struct DraftMessage {
|
|||
|
||||
public init(id: String? = nil,
|
||||
isOutgoing: Bool,
|
||||
address: String,
|
||||
isFirstMessage: Bool,
|
||||
text: String,
|
||||
medias: [Media],
|
||||
recording: Recording?,
|
||||
|
|
@ -198,6 +216,8 @@ public struct DraftMessage {
|
|||
createdAt: Date) {
|
||||
self.id = id
|
||||
self.isOutgoing = isOutgoing
|
||||
self.address = address
|
||||
self.isFirstMessage = isFirstMessage
|
||||
self.text = text
|
||||
self.medias = medias
|
||||
self.recording = recording
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ class ConversationViewModel: ObservableObject {
|
|||
|
||||
@Published var conversationMessagesIds: [String] = []
|
||||
@Published var conversationMessagesSection: [MessagesSection] = []
|
||||
@Published var participantConversationModel: [ContactAvatarModel] = []
|
||||
|
||||
init() {}
|
||||
|
||||
|
|
@ -91,9 +92,25 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func getParticipantConversationModel() {
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
if self.displayedConversation != nil {
|
||||
self.displayedConversation!.chatRoom.participants.forEach { participant in
|
||||
if participant.address != nil {
|
||||
let avatarModelTmp = ContactAvatarModel.getAvatarModelFromAddress(address: participant.address!)
|
||||
DispatchQueue.main.async {
|
||||
self.participantConversationModel.append(avatarModelTmp)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getMessages() {
|
||||
self.getHistorySize()
|
||||
self.getUnreadMessagesCount()
|
||||
self.getParticipantConversationModel()
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
if self.displayedConversation != nil {
|
||||
let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: 0, end: 30)
|
||||
|
|
@ -121,11 +138,30 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
conversationMessage.append(Message(
|
||||
id: UUID().uuidString,
|
||||
isOutgoing: eventLog.chatMessage?.isOutgoing ?? false,
|
||||
text: contentText,
|
||||
attachments: attachmentList))
|
||||
let addressPrecCleaned = index > 0 ? historyEvents[index - 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressPrecCleaned?.clean()
|
||||
|
||||
let addressNextCleaned = index <= historyEvents.count - 2 ? historyEvents[index + 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressNextCleaned?.clean()
|
||||
|
||||
let addressCleaned = eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressCleaned?.clean()
|
||||
|
||||
let isFirstMessageIncomingTmp = index > 0 ? addressPrecCleaned?.asStringUriOnly() != addressCleaned?.asStringUriOnly() : true
|
||||
let isFirstMessageOutgoingTmp = index <= historyEvents.count - 2 ? addressNextCleaned?.asStringUriOnly() != addressCleaned?.asStringUriOnly() : true
|
||||
|
||||
let isFirstMessageTmp = (eventLog.chatMessage?.isOutgoing ?? false) ? isFirstMessageOutgoingTmp : isFirstMessageIncomingTmp
|
||||
|
||||
conversationMessage.append(
|
||||
Message(
|
||||
id: UUID().uuidString,
|
||||
isOutgoing: eventLog.chatMessage?.isOutgoing ?? false,
|
||||
address: addressCleaned?.asStringUriOnly() ?? "",
|
||||
isFirstMessage: isFirstMessageTmp,
|
||||
text: contentText,
|
||||
attachments: attachmentList
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
|
|
@ -143,7 +179,7 @@ class ConversationViewModel: ObservableObject {
|
|||
let historyEvents = self.displayedConversation!.chatRoom.getHistoryRangeEvents(begin: self.conversationMessagesSection[0].rows.count, end: self.conversationMessagesSection[0].rows.count + 30)
|
||||
var conversationMessagesTmp: [Message] = []
|
||||
|
||||
historyEvents.reversed().forEach { eventLog in
|
||||
historyEvents.enumerated().reversed().forEach { index, eventLog in
|
||||
let attachmentList: [Attachment] = []
|
||||
var contentText = ""
|
||||
|
||||
|
|
@ -155,10 +191,26 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
let addressPrecCleaned = index > 0 ? historyEvents[index - 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressPrecCleaned?.clean()
|
||||
|
||||
let addressNextCleaned = index <= historyEvents.count - 2 ? historyEvents[index + 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressNextCleaned?.clean()
|
||||
|
||||
let addressCleaned = eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressCleaned?.clean()
|
||||
|
||||
let isFirstMessageIncomingTmp = index > 0 ? addressPrecCleaned?.asStringUriOnly() != addressCleaned?.asStringUriOnly() : true
|
||||
let isFirstMessageOutgoingTmp = index <= historyEvents.count - 2 ? addressNextCleaned?.asStringUriOnly() != addressCleaned?.asStringUriOnly() : true
|
||||
|
||||
let isFirstMessageTmp = (eventLog.chatMessage?.isOutgoing ?? false) ? isFirstMessageOutgoingTmp : isFirstMessageIncomingTmp
|
||||
|
||||
conversationMessagesTmp.insert(
|
||||
Message(
|
||||
id: UUID().uuidString,
|
||||
isOutgoing: eventLog.chatMessage?.isOutgoing ?? false,
|
||||
address: addressCleaned?.asStringUriOnly() ?? "",
|
||||
isFirstMessage: isFirstMessageTmp,
|
||||
text: contentText,
|
||||
attachments: attachmentList
|
||||
), at: 0
|
||||
|
|
@ -167,6 +219,9 @@ class ConversationViewModel: ObservableObject {
|
|||
|
||||
if !conversationMessagesTmp.isEmpty {
|
||||
DispatchQueue.main.async {
|
||||
if self.conversationMessagesSection[0].rows.last?.address == conversationMessagesTmp.last?.address {
|
||||
self.conversationMessagesSection[0].rows[self.conversationMessagesSection[0].rows.count - 1].isFirstMessage = false
|
||||
}
|
||||
self.conversationMessagesSection[0].rows.append(contentsOf: conversationMessagesTmp.reversed())
|
||||
}
|
||||
}
|
||||
|
|
@ -175,7 +230,6 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
func getNewMessages(eventLogs: [EventLog]) {
|
||||
var conversationMessage: [Message] = []
|
||||
eventLogs.enumerated().forEach { index, eventLog in
|
||||
var attachmentList: [Attachment] = []
|
||||
var contentText = ""
|
||||
|
|
@ -197,14 +251,50 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
let addressPrecCleaned = index > 0 ? eventLogs[index - 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressPrecCleaned?.clean()
|
||||
|
||||
let addressNextCleaned = index <= eventLogs.count - 2 ? eventLogs[index + 1].chatMessage?.fromAddress?.clone() : eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressNextCleaned?.clean()
|
||||
|
||||
let addressCleaned = eventLog.chatMessage?.fromAddress?.clone()
|
||||
addressCleaned?.clean()
|
||||
|
||||
let isFirstMessageIncomingTmp = index > 0
|
||||
? addressPrecCleaned?.asStringUriOnly() != addressCleaned?.asStringUriOnly()
|
||||
: (
|
||||
self.conversationMessagesSection.isEmpty || self.conversationMessagesSection[0].rows.isEmpty
|
||||
? true
|
||||
: self.conversationMessagesSection[0].rows[0].address != addressCleaned?.asStringUriOnly()
|
||||
)
|
||||
|
||||
let isFirstMessageOutgoingTmp = index <= eventLogs.count - 2
|
||||
? addressNextCleaned?.asStringUriOnly() == addressCleaned?.asStringUriOnly()
|
||||
: (
|
||||
self.conversationMessagesSection.isEmpty || self.conversationMessagesSection[0].rows.isEmpty
|
||||
? true
|
||||
: !self.conversationMessagesSection[0].rows[0].isOutgoing || self.conversationMessagesSection[0].rows[0].address == addressCleaned?.asStringUriOnly()
|
||||
)
|
||||
|
||||
let isFirstMessageTmp = (eventLog.chatMessage?.isOutgoing ?? false) ? isFirstMessageOutgoingTmp : isFirstMessageIncomingTmp
|
||||
|
||||
let message = Message(
|
||||
id: UUID().uuidString,
|
||||
isOutgoing: eventLog.chatMessage?.isOutgoing ?? false,
|
||||
address: addressCleaned?.asStringUriOnly() ?? "",
|
||||
isFirstMessage: isFirstMessageTmp,
|
||||
text: contentText,
|
||||
attachments: attachmentList
|
||||
)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if !self.conversationMessagesSection.isEmpty
|
||||
&& !self.conversationMessagesSection[0].rows.isEmpty
|
||||
&& self.conversationMessagesSection[0].rows[0].isOutgoing
|
||||
&& (self.conversationMessagesSection[0].rows[0].address == message.address) {
|
||||
self.conversationMessagesSection[0].rows[0].isFirstMessage = false
|
||||
}
|
||||
|
||||
if self.conversationMessagesSection.isEmpty {
|
||||
self.conversationMessagesSection.append(MessagesSection(date: Date(), rows: [message]))
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -628,7 +628,7 @@ struct HistoryContactFragment: View {
|
|||
|
||||
#Preview {
|
||||
HistoryContactFragment(
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", withPresence: false),
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false),
|
||||
historyViewModel: HistoryViewModel(),
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
contactViewModel: ContactViewModel(),
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ struct HistoryListFragment: View {
|
|||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, name: "", withPresence: false)
|
||||
: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false)
|
||||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
if contactAvatarModel != nil {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,14 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
|
||||
self.contactsManager.lastSearch.forEach { searchResult in
|
||||
if searchResult.friend != nil {
|
||||
self.contactsManager.avatarListModel.append(ContactAvatarModel(friend: searchResult.friend!, name: searchResult.friend?.name ?? "", withPresence: true))
|
||||
self.contactsManager.avatarListModel.append(
|
||||
ContactAvatarModel(
|
||||
friend: searchResult.friend!,
|
||||
name: searchResult.friend?.name ?? "",
|
||||
address: searchResult.friend?.address?.clone()?.asStringUriOnly() ?? "",
|
||||
withPresence: true
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue