Access to conversation from the history detail

This commit is contained in:
Benoit Martins 2024-07-15 14:00:44 +02:00
parent c78a77268e
commit 2e2dac6807
3 changed files with 212 additions and 10 deletions

View file

@ -1027,21 +1027,31 @@ struct ContentView: View {
}
}
if contactViewModel.operationInProgress {
if contactViewModel.operationInProgress || historyViewModel.operationInProgress {
PopupLoadingView()
.background(.black.opacity(0.65))
.zIndex(3)
.onDisappear {
if contactViewModel.displayedConversation != nil {
contactViewModel.indexDisplayedFriend = nil
historyViewModel.displayedCall = nil
index = 2
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: contactViewModel.displayedConversation!)
}
contactViewModel.displayedConversation = nil
historyViewModel.displayedConversation = nil
}
} else if historyViewModel.displayedConversation != nil {
historyViewModel.displayedCall = nil
index = 2
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: historyViewModel.displayedConversation!)
}
historyViewModel.displayedConversation = nil
}
}
}
}

View file

@ -289,21 +289,15 @@ struct HistoryContactFragment: View {
Spacer()
Button(action: {
contactViewModel.createOneToOneChatRoomWith(remote: historyViewModel.displayedCall!.addressLinphone)
}, label: {
VStack {
HStack(alignment: .center) {
Image("chat-teardrop-text")
.renderingMode(.template)
.resizable()
//.foregroundStyle(Color.grayMain2c600)
.foregroundStyle(Color.grayMain2c300)
.foregroundStyle(Color.grayMain2c600)
.frame(width: 25, height: 25)
.onTapGesture {
withAnimation {
}
}
}
.padding(16)
.background(Color.grayMain2c200)

View file

@ -19,6 +19,7 @@
import Foundation
import linphonesw
import Combine
class HistoryViewModel: ObservableObject {
@ -26,5 +27,202 @@ class HistoryViewModel: ObservableObject {
var selectedCall: HistoryModel?
@Published var operationInProgress: Bool = false
@Published var displayedConversation: ConversationModel?
private var chatRoomSuscriptions = Set<AnyCancellable?>()
init() {}
func createOneToOneChatRoomWith(remote: Address) {
CoreContext.shared.doOnCoreQueue { core in
let account = core.defaultAccount
if account == nil {
Log.error(
"\(StartConversationViewModel.TAG) No default account found, can't create conversation with \(remote.asStringUriOnly())!"
)
return
}
DispatchQueue.main.async {
self.operationInProgress = true
}
do {
let params: ChatRoomParams = try core.createDefaultChatRoomParams()
params.groupEnabled = false
params.subject = "Dummy subject"
params.ephemeralLifetime = 0 // Make sure ephemeral is disabled by default
let sameDomain = remote.domain == account?.params?.domain ?? ""
if StartConversationViewModel.isEndToEndEncryptionMandatory() && sameDomain {
Log.info("\(StartConversationViewModel.TAG) Account is in secure mode & domain matches, creating a E2E conversation")
params.backend = ChatRoom.Backend.FlexisipChat
params.encryptionEnabled = true
} else if !StartConversationViewModel.isEndToEndEncryptionMandatory() {
if LinphoneUtils.isEndToEndEncryptedChatAvailable(core: core) {
Log.info(
"\(StartConversationViewModel.TAG) Account is in interop mode but LIME is available, creating a E2E conversation"
)
params.backend = ChatRoom.Backend.FlexisipChat
params.encryptionEnabled = true
} else {
Log.info(
"\(StartConversationViewModel.TAG) Account is in interop mode but LIME isn't available, creating a SIP simple conversation"
)
params.backend = ChatRoom.Backend.Basic
params.encryptionEnabled = false
}
} else {
Log.error(
"\(StartConversationViewModel.TAG) Account is in secure mode, can't chat with SIP address of different domain \(remote.asStringUriOnly())"
)
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_invalid_participant_error"
ToastViewModel.shared.displayToast = true
}
return
}
let participants = [remote]
let localAddress = account?.params?.identityAddress
let existingChatRoom = core.searchChatRoom(params: params, localAddr: localAddress, remoteAddr: nil, participants: participants)
if existingChatRoom == nil {
Log.info(
"\(StartConversationViewModel.TAG) No existing 1-1 conversation between local account "
+ "\(localAddress?.asStringUriOnly() ?? "") and remote \(remote.asStringUriOnly()) was found for given parameters, let's create it"
)
let chatRoom = try core.createChatRoom(params: params, localAddr: localAddress, participants: participants)
if params.backend == ChatRoom.Backend.FlexisipChat {
if chatRoom.state == ChatRoom.State.Created {
let id = LinphoneUtils.getChatRoomId(room: chatRoom)
Log.info("\(StartConversationViewModel.TAG) 1-1 conversation \(id) has been created")
let model = ConversationModel(chatRoom: chatRoom)
if self.operationInProgress == false {
DispatchQueue.main.async {
self.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
self.operationInProgress = false
self.displayedConversation = model
}
}
} else {
Log.info("\(StartConversationViewModel.TAG) Conversation isn't in Created state yet, wait for it")
self.chatRoomAddDelegate(core: core, chatRoom: chatRoom)
}
} else {
let id = LinphoneUtils.getChatRoomId(room: chatRoom)
Log.info("\(StartConversationViewModel.TAG) Conversation successfully created \(id)")
let model = ConversationModel(chatRoom: chatRoom)
if self.operationInProgress == false {
DispatchQueue.main.async {
self.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
self.operationInProgress = false
self.displayedConversation = model
}
}
}
} else {
Log.warn(
"\(StartConversationViewModel.TAG) A 1-1 conversation between local account \(localAddress?.asStringUriOnly() ?? "") and remote \(remote.asStringUriOnly()) for given parameters already exists!"
)
let model = ConversationModel(chatRoom: existingChatRoom!)
if self.operationInProgress == false {
DispatchQueue.main.async {
self.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
self.operationInProgress = false
self.displayedConversation = model
}
}
}
} catch {
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
Log.error("\(StartConversationViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())!")
}
}
}
func chatRoomAddDelegate(core: Core, chatRoom: ChatRoom) {
self.chatRoomSuscriptions.insert(chatRoom.publisher?.onConferenceJoined?.postOnCoreQueue {
(chatRoom: ChatRoom, eventLog: EventLog) in
let state = chatRoom.state
let id = LinphoneUtils.getChatRoomId(room: chatRoom)
Log.info("\(StartConversationViewModel.TAG) Conversation \(id) \(chatRoom.subject ?? "") state changed: \(state)")
if state == ChatRoom.State.Created {
Log.info("\(StartConversationViewModel.TAG) Conversation \(id) successfully created")
self.chatRoomSuscriptions.removeAll()
let model = ConversationModel(chatRoom: chatRoom)
if self.operationInProgress == false {
DispatchQueue.main.async {
self.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
self.operationInProgress = false
self.displayedConversation = model
}
}
} else if state == ChatRoom.State.CreationFailed {
Log.error("\(StartConversationViewModel.TAG) Conversation \(id) creation has failed!")
self.chatRoomSuscriptions.removeAll()
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
})
self.chatRoomSuscriptions.insert(chatRoom.publisher?.onStateChanged?.postOnCoreQueue {
(chatRoom: ChatRoom, state: ChatRoom.State) in
let state = chatRoom.state
let id = LinphoneUtils.getChatRoomId(room: chatRoom)
if state == ChatRoom.State.CreationFailed {
Log.error("\(StartConversationViewModel.TAG) Conversation \(id) creation has failed!")
self.chatRoomSuscriptions.removeAll()
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
})
}
}