forked from mirrors/linphone-iphone
Ephemeral message
This commit is contained in:
parent
2eee40a7ae
commit
2b80c5b78b
4 changed files with 156 additions and 11 deletions
|
|
@ -34,6 +34,9 @@ struct ChatBubbleView: View {
|
|||
@State private var isPressed: Bool = false
|
||||
@State private var timePassed: TimeInterval?
|
||||
|
||||
@State private var timer: Timer?
|
||||
@State private var ephemeralLifetime: String = ""
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
if eventLogMessage.eventModel.eventLogType == .ConferenceChatMessage {
|
||||
|
|
@ -165,6 +168,28 @@ struct ChatBubbleView: View {
|
|||
}
|
||||
|
||||
HStack(alignment: .center) {
|
||||
if eventLogMessage.message.isEphemeral && eventLogMessage.message.isOutgoing {
|
||||
Text(ephemeralLifetime)
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.default_text_style_300(styleSize: 14)
|
||||
.padding(.top, 1)
|
||||
.onAppear {
|
||||
updateEphemeralTimer()
|
||||
}
|
||||
.onChange(of: eventLogMessage.message.ephemeralExpireTime) { ephemeralExpireTimeTmp in
|
||||
if ephemeralExpireTimeTmp > 0 {
|
||||
updateEphemeralTimer()
|
||||
}
|
||||
}
|
||||
|
||||
Image("clock-countdown")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 15, height: 15)
|
||||
.padding(.top, 1)
|
||||
}
|
||||
|
||||
Text(conversationViewModel.getMessageTime(startDate: eventLogMessage.message.dateReceived))
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.default_text_style_300(styleSize: 14)
|
||||
|
|
@ -187,6 +212,29 @@ struct ChatBubbleView: View {
|
|||
.padding(.top, 1)
|
||||
}
|
||||
}
|
||||
|
||||
if eventLogMessage.message.isEphemeral && !eventLogMessage.message.isOutgoing {
|
||||
Image("clock-countdown")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.frame(width: 15, height: 15)
|
||||
.padding(.top, 1)
|
||||
.padding(.trailing, -4)
|
||||
|
||||
Text(ephemeralLifetime)
|
||||
.foregroundStyle(Color.grayMain2c500)
|
||||
.default_text_style_300(styleSize: 14)
|
||||
.padding(.top, 1)
|
||||
.onAppear {
|
||||
updateEphemeralTimer()
|
||||
}
|
||||
.onChange(of: eventLogMessage.message.ephemeralExpireTime) { ephemeralExpireTimeTmp in
|
||||
if ephemeralExpireTimeTmp > 0 {
|
||||
updateEphemeralTimer()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onTapGesture {
|
||||
conversationViewModel.selectedMessageToDisplayDetails = eventLogMessage
|
||||
|
|
@ -551,6 +599,30 @@ struct ChatBubbleView: View {
|
|||
return "file"
|
||||
}
|
||||
}
|
||||
|
||||
private func updateEphemeralTimer() {
|
||||
if eventLogMessage.message.isEphemeral {
|
||||
if eventLogMessage.message.ephemeralExpireTime == 0 {
|
||||
// Message hasn't been read by all participants yet
|
||||
self.ephemeralLifetime = eventLogMessage.message.ephemeralLifetime.convertDurationToString()
|
||||
} else {
|
||||
let remaining = eventLogMessage.message.ephemeralExpireTime - Int(Date().timeIntervalSince1970)
|
||||
self.ephemeralLifetime = remaining.convertDurationToString()
|
||||
|
||||
if timer == nil {
|
||||
timer = Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { _ in
|
||||
let updatedRemaining = eventLogMessage.message.ephemeralExpireTime - Int(Date().timeIntervalSince1970)
|
||||
if updatedRemaining <= 0 {
|
||||
timer?.invalidate()
|
||||
timer = nil
|
||||
} else {
|
||||
self.ephemeralLifetime = updatedRemaining.convertDurationToString()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum URLType {
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ struct UIList: UIViewRepresentable {
|
|||
tableView.insertSections([section], with: .top)
|
||||
|
||||
case .delete(let section, let row):
|
||||
tableView.deleteRows(at: [IndexPath(row: row, section: section)], with: .top)
|
||||
tableView.deleteRows(at: [IndexPath(row: row, section: section)], with: .left)
|
||||
case .insert(let section, let row):
|
||||
tableView.insertRows(at: [IndexPath(row: row, section: section)], with: .top)
|
||||
case .edit(let section, let row):
|
||||
|
|
|
|||
|
|
@ -81,6 +81,10 @@ public struct Message: Identifiable, Hashable {
|
|||
public var ownReaction: String
|
||||
public var reactions: [String]
|
||||
|
||||
public var isEphemeral: Bool
|
||||
public var ephemeralExpireTime: Int
|
||||
public var ephemeralLifetime: Int
|
||||
|
||||
public init(
|
||||
id: String,
|
||||
appData: String = "",
|
||||
|
|
@ -97,7 +101,10 @@ public struct Message: Identifiable, Hashable {
|
|||
replyMessage: ReplyMessage? = nil,
|
||||
isForward: Bool = false,
|
||||
ownReaction: String = "",
|
||||
reactions: [String] = []
|
||||
reactions: [String] = [],
|
||||
isEphemeral: Bool = false,
|
||||
ephemeralExpireTime: Int = 0,
|
||||
ephemeralLifetime: Int = 0
|
||||
) {
|
||||
self.id = id
|
||||
self.appData = appData
|
||||
|
|
@ -115,6 +122,9 @@ public struct Message: Identifiable, Hashable {
|
|||
self.isForward = isForward
|
||||
self.ownReaction = ownReaction
|
||||
self.reactions = reactions
|
||||
self.isEphemeral = isEphemeral
|
||||
self.ephemeralExpireTime = ephemeralExpireTime
|
||||
self.ephemeralLifetime = ephemeralLifetime
|
||||
}
|
||||
|
||||
public static func makeMessage(
|
||||
|
|
@ -167,7 +177,7 @@ extension Message {
|
|||
|
||||
extension Message: Equatable {
|
||||
public static func == (lhs: Message, rhs: Message) -> Bool {
|
||||
lhs.id == rhs.id && lhs.status == rhs.status && lhs.isFirstMessage == rhs.isFirstMessage && lhs.ownReaction == rhs.ownReaction && lhs.reactions == rhs.reactions
|
||||
lhs.id == rhs.id && lhs.status == rhs.status && lhs.isFirstMessage == rhs.isFirstMessage && lhs.ownReaction == rhs.ownReaction && lhs.reactions == rhs.reactions && lhs.ephemeralExpireTime == rhs.ephemeralExpireTime
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,6 +114,8 @@ class ConversationViewModel: ObservableObject {
|
|||
self.getNewMessages(eventLogs: eventLogs)
|
||||
}, onChatMessageSending: { (_: ChatRoom, eventLog: EventLog) in
|
||||
self.getNewMessages(eventLogs: [eventLog])
|
||||
}, onEphemeralMessageDeleted: {(_: ChatRoom, eventLog: EventLog) in
|
||||
self.removeMessage(eventLog)
|
||||
})
|
||||
self.chatRoomDelegateHolder = ChatRoomDelegateHolder(chatroom: chatroom, delegate: chatRoomDelegate)
|
||||
}
|
||||
|
|
@ -139,12 +141,22 @@ class ConversationViewModel: ObservableObject {
|
|||
statusTmp = .sending
|
||||
}
|
||||
|
||||
let ephemeralExpireTimeTmp = message.ephemeralExpireTime
|
||||
|
||||
if !self.conversationMessagesSection.isEmpty && !self.conversationMessagesSection[0].rows.isEmpty {
|
||||
if let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId}) {
|
||||
if indexMessage < self.conversationMessagesSection[0].rows.count && self.conversationMessagesSection[0].rows[indexMessage].message.status != statusTmp {
|
||||
if indexMessage < self.conversationMessagesSection[0].rows.count {
|
||||
if self.conversationMessagesSection[0].rows[indexMessage].message.status != statusTmp {
|
||||
DispatchQueue.main.async {
|
||||
//self.objectWillChange.send()
|
||||
self.conversationMessagesSection[0].rows[indexMessage].message.status = statusTmp ?? .error
|
||||
self.conversationMessagesSection[0].rows[indexMessage].message.ephemeralExpireTime = ephemeralExpireTimeTmp
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
//self.objectWillChange.send()
|
||||
self.conversationMessagesSection[0].rows[indexMessage].message.ephemeralExpireTime = ephemeralExpireTimeTmp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -201,7 +213,18 @@ class ConversationViewModel: ObservableObject {
|
|||
self.conversationMessagesSection[0].rows[indexMessage!].message.reactions = reactionsTmp
|
||||
}
|
||||
}
|
||||
}, onEphemeralMessageTimerStarted: { (message: ChatMessage) in
|
||||
let indexMessage = self.conversationMessagesSection[0].rows.firstIndex(where: {$0.eventModel.eventLog.chatMessage?.messageId == message.messageId})
|
||||
let ephemeralExpireTimeTmp = message.ephemeralExpireTime
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if indexMessage != nil {
|
||||
self.objectWillChange.send()
|
||||
self.conversationMessagesSection[0].rows[indexMessage!].message.ephemeralExpireTime = ephemeralExpireTimeTmp
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
self.chatMessageDelegateHolders.append(ChatMessageDelegateHolder(message: message, delegate: chatMessageDelegate))
|
||||
}
|
||||
}
|
||||
|
|
@ -480,7 +503,10 @@ class ConversationViewModel: ObservableObject {
|
|||
replyMessage: replyMessageTmp,
|
||||
isForward: eventLog.chatMessage?.isForward ?? false,
|
||||
ownReaction: eventLog.chatMessage?.ownReaction?.body ?? "",
|
||||
reactions: reactionsTmp
|
||||
reactions: reactionsTmp,
|
||||
isEphemeral: eventLog.chatMessage?.isEphemeral ?? false,
|
||||
ephemeralExpireTime: eventLog.chatMessage?.ephemeralExpireTime ?? 0,
|
||||
ephemeralLifetime: eventLog.chatMessage?.ephemeralLifetime ?? 0
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -700,7 +726,10 @@ class ConversationViewModel: ObservableObject {
|
|||
replyMessage: replyMessageTmp,
|
||||
isForward: eventLog.chatMessage?.isForward ?? false,
|
||||
ownReaction: eventLog.chatMessage?.ownReaction?.body ?? "",
|
||||
reactions: reactionsTmp
|
||||
reactions: reactionsTmp,
|
||||
isEphemeral: eventLog.chatMessage?.isEphemeral ?? false,
|
||||
ephemeralExpireTime: eventLog.chatMessage?.ephemeralExpireTime ?? 0,
|
||||
ephemeralLifetime: eventLog.chatMessage?.ephemeralLifetime ?? 0
|
||||
)
|
||||
), at: 0
|
||||
)
|
||||
|
|
@ -932,7 +961,10 @@ class ConversationViewModel: ObservableObject {
|
|||
replyMessage: replyMessageTmp,
|
||||
isForward: eventLog.chatMessage?.isForward ?? false,
|
||||
ownReaction: eventLog.chatMessage?.ownReaction?.body ?? "",
|
||||
reactions: reactionsTmp
|
||||
reactions: reactionsTmp,
|
||||
isEphemeral: eventLog.chatMessage?.isEphemeral ?? false,
|
||||
ephemeralExpireTime: eventLog.chatMessage?.ephemeralExpireTime ?? 0,
|
||||
ephemeralLifetime: eventLog.chatMessage?.ephemeralLifetime ?? 0
|
||||
)
|
||||
)
|
||||
|
||||
|
|
@ -1210,7 +1242,10 @@ class ConversationViewModel: ObservableObject {
|
|||
replyMessage: replyMessageTmp,
|
||||
isForward: eventLog.chatMessage?.isForward ?? false,
|
||||
ownReaction: eventLog.chatMessage?.ownReaction?.body ?? "",
|
||||
reactions: reactionsTmp
|
||||
reactions: reactionsTmp,
|
||||
isEphemeral: eventLog.chatMessage?.isEphemeral ?? false,
|
||||
ephemeralExpireTime: eventLog.chatMessage?.ephemeralExpireTime ?? 0,
|
||||
ephemeralLifetime: eventLog.chatMessage?.ephemeralLifetime ?? 0
|
||||
)
|
||||
), at: 0
|
||||
)
|
||||
|
|
@ -1257,6 +1292,34 @@ class ConversationViewModel: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
func removeMessage(_ eventLog: EventLog) {
|
||||
/*
|
||||
if let found = self.conversationMessagesSection[0].rows.first(where: { $0.message.id == eventLog.chatMessage?.messageId }) {
|
||||
var updatedList = self.conversationMessagesSection[0].rows
|
||||
|
||||
print("Removing message from conversation events list")
|
||||
if let index = updatedList.firstIndex(where: { $0.message.id == found.message.id }) {
|
||||
updatedList.remove(at: index)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.conversationMessagesSection[0].rows = updatedList
|
||||
}
|
||||
} else {
|
||||
print("Failed to find matching message in conversation events list")
|
||||
}
|
||||
*/
|
||||
|
||||
if let index = self.conversationMessagesSection[0].rows.firstIndex(where: { $0.message.id == eventLog.chatMessage?.messageId }) {
|
||||
DispatchQueue.main.async {
|
||||
if index > 0 && self.conversationMessagesSection[0].rows[index - 1].message.address == self.conversationMessagesSection[0].rows[index].message.address {
|
||||
self.conversationMessagesSection[0].rows[index - 1].message.isFirstMessage = self.conversationMessagesSection[0].rows[index].message.isFirstMessage
|
||||
}
|
||||
self.conversationMessagesSection[0].rows.remove(at: index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func sendMessage(audioRecorder: AudioRecorder? = nil) {
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
do {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue