Refactored ConversationFragment

This commit is contained in:
Benoit Martins 2025-06-13 18:33:31 +02:00 committed by MARTINS Benoît
parent dcd80e14bc
commit 0d149c7b54
21 changed files with 456 additions and 220 deletions

View file

@ -2245,7 +2245,7 @@ struct CallView: View {
.onDisappear {
if SharedMainViewModel.shared.displayedConversation != nil {
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
//self.conversationViewModel.changeDisplayedChatRoom(conversationModel: SharedMainViewModel.shared.displayedConversation!)
callViewModel.changeDisplayedChatRoom(conversationModel: SharedMainViewModel.shared.displayedConversation!)
SharedMainViewModel.shared.displayedConversation = nil
withAnimation {
telecomManager.callDisplayed = false
@ -2615,7 +2615,12 @@ struct CallView: View {
.frame(width: 32, height: 32, alignment: .center)
.onDisappear {
if SharedMainViewModel.shared.displayedConversation != nil {
//conversationViewModel.changeDisplayedChatRoom(conversationModel: SharedMainViewModel.shared.displayedConversation!)
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
callViewModel.changeDisplayedChatRoom(conversationModel: SharedMainViewModel.shared.displayedConversation!)
SharedMainViewModel.shared.displayedConversation = nil
withAnimation {
telecomManager.callDisplayed = false
}
}
}
}

View file

@ -32,6 +32,7 @@ class CallViewModel: ObservableObject {
var coreContext = CoreContext.shared
var telecomManager = TelecomManager.shared
var sharedMainViewModel = SharedMainViewModel.shared
@Published var displayName: String = ""
@Published var direction: Call.Dir = .Outgoing
@ -1394,6 +1395,32 @@ class CallViewModel: ObservableObject {
})
chatRoom.addDelegate(delegate: self.chatRoomDelegate!)
}
func changeDisplayedChatRoom(conversationModel: ConversationModel) {
CoreContext.shared.doOnCoreQueue { core in
let nilParams: ConferenceParams? = nil
if let newChatRoom = core.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: conversationModel.chatRoom.peerAddress, participants: nil) {
if LinphoneUtils.getChatRoomId(room: newChatRoom) == conversationModel.id {
if self.sharedMainViewModel.displayedConversation == nil {
DispatchQueue.main.async {
withAnimation {
self.sharedMainViewModel.displayedConversation = conversationModel
}
}
} else {
DispatchQueue.main.async {
self.sharedMainViewModel.displayedConversation = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.sharedMainViewModel.displayedConversation = conversationModel
}
}
}
}
}
}
}
}
}
// swiftlint:enable type_body_length
// swiftlint:enable line_length

View file

@ -94,18 +94,22 @@ struct ContactRow: View {
.listRowSeparator(.hidden)
.background(.white)
.onTapGesture {
withAnimation {
SharedMainViewModel.shared.displayedFriend = contactAvatarModel
}
if SharedMainViewModel.shared.indexView == 0 {
withAnimation {
SharedMainViewModel.shared.displayedFriend = contactAvatarModel
}
}
if contactAvatarModel.friend != nil
&& contactAvatarModel.friend!.address != nil {
startCallFunc(contactAvatarModel.friend!.address!)
}
}
.onLongPressGesture(minimumDuration: 0.2) {
contactsListViewModel.selectedFriend = contactAvatarModel
showingSheet.toggle()
if SharedMainViewModel.shared.indexView == 0 {
contactsListViewModel.selectedFriend = contactAvatarModel
showingSheet.toggle()
}
}
}
}

View file

@ -31,7 +31,6 @@ class ContactsListViewModel: ObservableObject {
var selectedFriendToShare: ContactAvatarModel?
var selectedFriendToDelete: ContactAvatarModel?
@Published var operationInProgress: Bool = false
@Published var displayedConversation: ConversationModel?
private var contactChatRoomDelegate: ChatRoomDelegate?
@ -49,7 +48,7 @@ class ContactsListViewModel: ObservableObject {
}
DispatchQueue.main.async {
self.operationInProgress = true
SharedMainViewModel.shared.operationInProgress = true
}
do {
@ -87,7 +86,7 @@ class ContactsListViewModel: ObservableObject {
)
DispatchQueue.main.async {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
@ -113,7 +112,7 @@ class ContactsListViewModel: ObservableObject {
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
self.displayedConversation = model
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
}
} else {
Log.info("\(ConversationForwardMessageViewModel.TAG) Conversation isn't in Created state yet (state is \(state)), wait for it")
@ -126,14 +125,14 @@ class ContactsListViewModel: ObservableObject {
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
self.displayedConversation = model
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
}
}
} catch {
Log.error("\(ConversationForwardMessageViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())")
DispatchQueue.main.async {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
@ -145,7 +144,7 @@ class ContactsListViewModel: ObservableObject {
let model = ConversationModel(chatRoom: existingChatRoom!)
DispatchQueue.main.async {
self.displayedConversation = model
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
}
}
} catch {
@ -164,7 +163,7 @@ class ContactsListViewModel: ObservableObject {
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
@ -180,18 +179,18 @@ class ContactsListViewModel: ObservableObject {
self.contactChatRoomDelegate = nil
}
let model = ConversationModel(chatRoom: chatRoom)
if self.operationInProgress == false {
if SharedMainViewModel.shared.operationInProgress == false {
DispatchQueue.main.async {
self.operationInProgress = true
SharedMainViewModel.shared.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
self.displayedConversation = model
}
}
@ -203,7 +202,7 @@ class ContactsListViewModel: ObservableObject {
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.operationInProgress = false
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}

View file

@ -40,17 +40,13 @@ struct ContentView: View {
@State private var contactsListViewModel: ContactsListViewModel?
@State private var historyListViewModel: HistoryListViewModel?
@State private var conversationsListViewModel: ConversationsListViewModel?
//@ObservedObject var conversationViewModel: ConversationViewModel
//@ObservedObject var startConversationViewModel: StartConversationViewModel
//@ObservedObject var meetingWaitingRoomViewModel: MeetingWaitingRoomViewModel
//@ObservedObject var meetingsListViewModel: MeetingsListViewModel
//@ObservedObject var meetingViewModel: MeetingViewModel
//@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
//@Binding var index: Int
@State private var orientation = UIDevice.current.orientation
@ -969,37 +965,30 @@ struct ContentView: View {
.frame(maxWidth: .infinity)
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
} else if let historyListVM = historyListViewModel, let displayedFriend = sharedMainViewModel.displayedFriend, sharedMainViewModel.indexView == 1 {
} else if let historyListVM = historyListViewModel, let displayedCall = sharedMainViewModel.displayedCall, sharedMainViewModel.indexView == 1 {
HistoryContactFragment(
isShowDeleteAllHistoryPopup: $isShowDeleteAllHistoryPopup,
isShowEditContactFragment: $isShowEditContactFragment,
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress
)
.environmentObject(historyListVM)
.environmentObject(displayedFriend)
.environmentObject(displayedCall)
.frame(maxWidth: .infinity)
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
} else if sharedMainViewModel.indexView == 2 {
/*
} else if let conversationsListVM = conversationsListViewModel, sharedMainViewModel.indexView == 2 {
ConversationFragment(
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
conversationForwardMessageViewModel: conversationForwardMessageViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,
isShowConversationFragment: $isShowConversationFragment,
isShowStartCallGroupPopup: $isShowStartCallGroupPopup,
isShowEditContactFragment: $isShowEditContactFragment,
indexPage: $index,
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress,
isShowScheduleMeetingFragment: $isShowScheduleMeetingFragment
)
.environmentObject(conversationsListVM)
.environmentObject(accountProfileViewModel)
.frame(maxWidth: .infinity)
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
*/
} else if sharedMainViewModel.indexView == 3 {
/*
MeetingFragment(meetingViewModel: meetingViewModel, meetingsListViewModel: meetingsListViewModel, isShowScheduleMeetingFragment: $isShowScheduleMeetingFragment, isShowSendCancelMeetingNotificationPopup: $isShowSendCancelMeetingNotificationPopup)
@ -1090,17 +1079,14 @@ struct ContentView: View {
.transition(.opacity.combined(with: .move(edge: .bottom)))
}
/*
if isShowStartConversationFragment {
if let conversationsListVM = conversationsListViewModel, isShowStartConversationFragment {
StartConversationFragment(
startConversationViewModel: startConversationViewModel,
conversationViewModel: conversationViewModel,
isShowStartConversationFragment: $isShowStartConversationFragment
)
.environmentObject(conversationsListVM)
.zIndex(6)
.transition(.opacity.combined(with: .move(edge: .bottom)))
}
*/
if let contactsListVM = contactsListViewModel, isShowDeleteContactPopup {
PopupView(
@ -1196,26 +1182,60 @@ struct ContentView: View {
}
}
/*
if contactsListViewModel.operationInProgress {
if sharedMainViewModel.operationInProgress {
PopupLoadingView()
.background(.black.opacity(0.65))
.zIndex(3)
.onDisappear {
if contactsListViewModel.displayedConversation != nil {
if let contactsListVM = contactsListViewModel, let displayedConversation = contactsListVM.displayedConversation {
sharedMainViewModel.displayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.changeIndexView(indexViewInt: 2)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: contactsListViewModel.displayedConversation!)
if let conversationsListVM = self.conversationsListViewModel {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
conversationsListVM.changeDisplayedChatRoom(conversationModel: displayedConversation)
}
contactsListVM.displayedConversation = nil
}
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if let conversationsListVM = self.conversationsListViewModel {
withAnimation {
conversationsListVM.changeDisplayedChatRoom(conversationModel: displayedConversation)
}
}
contactsListVM.displayedConversation = nil
}
}
} else if let historyListVM = historyListViewModel, let displayedConversation = historyListVM.displayedConversation {
sharedMainViewModel.displayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.changeIndexView(indexViewInt: 2)
if let conversationsListVM = self.conversationsListViewModel {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
conversationsListVM.changeDisplayedChatRoom(conversationModel: displayedConversation)
}
historyListVM.displayedConversation = nil
}
} else {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
if let conversationsListVM = self.conversationsListViewModel {
withAnimation {
conversationsListVM.changeDisplayedChatRoom(conversationModel: displayedConversation)
}
}
historyListVM.displayedConversation = nil
}
contactsListViewModel.displayedConversation = nil
}
}
}
}
/*
if isShowScheduleMeetingFragment {
ScheduleMeetingFragment(
meetingViewModel: meetingViewModel,
@ -1282,6 +1302,7 @@ struct ContentView: View {
self.isShowSendCancelMeetingNotificationPopup.toggle()
}
}
*/
if isShowStartCallGroupPopup {
PopupView(
@ -1307,30 +1328,7 @@ struct ContentView: View {
}
}
if isShowStartCallGroupPopup {
PopupView(
isShowPopup: $isShowStartCallGroupPopup,
title: Text("conversation_info_confirm_start_group_call_dialog_title"),
content: Text("conversation_info_confirm_start_group_call_dialog_message"),
titleFirstButton: Text("dialog_cancel"),
actionFirstButton: {
self.isShowStartCallGroupPopup.toggle()
},
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
if sharedMainViewModel.displayedConversation != nil {
sharedMainViewModel.displayedConversation!.createGroupCall()
}
self.isShowStartCallGroupPopup.toggle()
}
)
.background(.black.opacity(0.65))
.zIndex(3)
.onTapGesture {
self.isShowStartCallGroupPopup.toggle()
}
}
/*
if conversationViewModel.isShowConversationInfoPopup {
PopupViewWithTextField(conversationViewModel: conversationViewModel)
.background(.black.opacity(0.65))
@ -1453,8 +1451,6 @@ class NavigationManager: ObservableObject {
#Preview {
ContentView(
//meetingWaitingRoomViewModel: MeetingWaitingRoomViewModel(),
//conversationsListViewModel: ConversationsListViewModel(),
//conversationViewModel: ConversationViewModel(),
//meetingsListViewModel: MeetingsListViewModel(),
//meetingViewModel: MeetingViewModel(),
//conversationForwardMessageViewModel: ConversationForwardMessageViewModel(),

View file

@ -27,7 +27,7 @@ struct ChatBubbleView: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
let eventLogMessage: EventLogMessage
@ -603,9 +603,9 @@ struct ChatBubbleView: View {
.clipped()
} else if eventLogMessage.message.attachments.first!.type == .voiceRecording {
CustomSlider(
conversationViewModel: conversationViewModel,
eventLogMessage: eventLogMessage
)
.environmentObject(conversationViewModel)
.frame(width: geometryProxy.size.width - 160, height: 50)
} else {
HStack {
@ -990,7 +990,7 @@ extension View {
}
struct CustomSlider: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
let eventLogMessage: EventLogMessage
@ -1183,7 +1183,7 @@ struct CachedAsyncImage<Placeholder: View>: View {
/*
#Preview {
ChatBubbleView(conversationViewModel: ConversationViewModel(), index: 0)
ChatBubbleView(index: 0)
}
*/

View file

@ -25,9 +25,10 @@ struct ConversationForwardMessageFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var magicSearch = MagicSearchSingleton.shared
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
@StateObject private var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
@Binding var isShowConversationForwardMessageFragment: Bool
@ -36,6 +37,11 @@ struct ConversationForwardMessageFragment: View {
@FocusState var isMessageTextFocused: Bool
init(conversationsList: [ConversationModel], selectedMessage: EventLogMessage?, isShowConversationForwardMessageFragment: Binding<Bool>) {
_conversationForwardMessageViewModel = StateObject(wrappedValue: ConversationForwardMessageViewModel(conversationsList: conversationsList, selectedMessage: selectedMessage))
self._isShowConversationForwardMessageFragment = isShowConversationForwardMessageFragment
}
var body: some View {
NavigationView {
ZStack {
@ -337,11 +343,10 @@ struct ConversationForwardMessageFragment: View {
}
}
/*
#Preview {
ConversationForwardMessageFragment(
conversationViewModel: ConversationViewModel(),
conversationsListViewModel: ConversationsListViewModel(),
conversationForwardMessageViewModel: ConversationForwardMessageViewModel(),
isShowConversationForwardMessageFragment: .constant(true)
)
}
*/

View file

@ -31,14 +31,11 @@ struct ConversationFragment: View {
@EnvironmentObject var navigationManager: NavigationManager
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var meetingViewModel: MeetingViewModel
@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
@EnvironmentObject var accountProfileViewModel: AccountProfileViewModel
@StateObject private var conversationViewModel = ConversationViewModel()
@State var isMenuOpen = false
@State private var isMuted: Bool = false
@ -49,9 +46,6 @@ struct ConversationFragment: View {
private let ids: [String] = []
@StateObject private var viewModel = ChatViewModel()
@StateObject private var paginationState = PaginationState()
@State private var displayFloatingButton = false
@State private var areFilePickersOpen = false
@ -73,9 +67,11 @@ struct ConversationFragment: View {
@State private var selectedCategoryIndex = 0
@Binding var isShowEditContactFragment: Bool
@Binding var indexPage: Int
@Binding var isShowEditContactFragmentAddress: String
@Binding var isShowScheduleMeetingFragment: Bool
@State private var cachedConversation: ConversationModel?
var body: some View {
NavigationView {
@ -97,7 +93,8 @@ struct ConversationFragment: View {
.sheet(isPresented: $conversationViewModel.isShowSelectedMessageToDisplayDetails, onDismiss: {
conversationViewModel.isShowSelectedMessageToDisplayDetails = false
}, content: {
ImdnOrReactionsSheet(conversationViewModel: conversationViewModel, selectedCategoryIndex: $selectedCategoryIndex)
ImdnOrReactionsSheet(selectedCategoryIndex: $selectedCategoryIndex)
.environmentObject(conversationViewModel)
.presentationDetents([.medium])
.presentationDragIndicator(.visible)
})
@ -137,7 +134,8 @@ struct ConversationFragment: View {
.edgesIgnoringSafeArea(.all)
})
.fullScreenCover(isPresented: $isShowCamera) {
ImagePicker(conversationViewModel: conversationViewModel, selectedMedia: self.$conversationViewModel.mediasToSend)
ImagePicker(selectedMedia: self.$conversationViewModel.mediasToSend)
.environmentObject(conversationViewModel)
.edgesIgnoringSafeArea(.all)
}
.background(Color.gray100.ignoresSafeArea(.keyboard))
@ -156,7 +154,8 @@ struct ConversationFragment: View {
conversationViewModel.removeConversationDelegate()
}
.halfSheet(showSheet: $conversationViewModel.isShowSelectedMessageToDisplayDetails) {
ImdnOrReactionsSheet(conversationViewModel: conversationViewModel, selectedCategoryIndex: $selectedCategoryIndex)
ImdnOrReactionsSheet(selectedCategoryIndex: $selectedCategoryIndex)
.environmentObject(conversationViewModel)
} onDismiss: {
conversationViewModel.isShowSelectedMessageToDisplayDetails = false
}
@ -179,7 +178,8 @@ struct ConversationFragment: View {
.edgesIgnoringSafeArea(.all)
})
.fullScreenCover(isPresented: $isShowCamera) {
ImagePicker(conversationViewModel: conversationViewModel, selectedMedia: self.$conversationViewModel.mediasToSend)
ImagePicker(selectedMedia: self.$conversationViewModel.mediasToSend)
.environmentObject(conversationViewModel)
}
.background(Color.gray100.ignoresSafeArea(.keyboard))
}
@ -193,6 +193,11 @@ struct ConversationFragment: View {
}
}
.navigationViewStyle(.stack)
.onAppear {
if let conv = SharedMainViewModel.shared.displayedConversation {
cachedConversation = conv
}
}
}
// swiftlint:disable cyclomatic_complexity
@ -201,7 +206,7 @@ struct ConversationFragment: View {
func innerView(geometry: GeometryProxy) -> some View {
ZStack {
VStack(spacing: 1) {
if SharedMainViewModel.shared.displayedConversation != nil {
if SharedMainViewModel.shared.displayedConversation != nil || cachedConversation != nil {
Rectangle()
.foregroundColor(Color.orangeMain500)
.edgesIgnoringSafeArea(.top)
@ -228,11 +233,11 @@ struct ConversationFragment: View {
}
}
Avatar(contactAvatarModel: SharedMainViewModel.shared.displayedConversation!.avatarModel, avatarSize: 50)
Avatar(contactAvatarModel: SharedMainViewModel.shared.displayedConversation?.avatarModel ?? cachedConversation!.avatarModel, avatarSize: 50)
.padding(.top, 4)
VStack(spacing: 1) {
Text(SharedMainViewModel.shared.displayedConversation!.subject)
Text(SharedMainViewModel.shared.displayedConversation?.subject ?? cachedConversation!.subject)
.default_text_style(styleSize: 16)
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 4)
@ -276,7 +281,7 @@ struct ConversationFragment: View {
Spacer()
if !SharedMainViewModel.shared.displayedConversation!.isReadOnly {
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) {
Button {
if SharedMainViewModel.shared.displayedConversation!.isGroup {
isShowStartCallGroupPopup.toggle()
@ -313,7 +318,7 @@ struct ConversationFragment: View {
}
}
if !SharedMainViewModel.shared.displayedConversation!.isReadOnly {
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) {
Button {
isMenuOpen = false
SharedMainViewModel.shared.displayedConversation!.toggleMute()
@ -375,13 +380,11 @@ struct ConversationFragment: View {
if #available(iOS 16.0, *) {
ZStack(alignment: .bottomTrailing) {
UIList(
viewModel: viewModel,
paginationState: paginationState,
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
geometryProxy: geometry,
sections: conversationViewModel.conversationMessagesSection
)
.environmentObject(conversationViewModel)
.environmentObject(conversationsListViewModel)
}
/*
.onAppear {
@ -398,7 +401,8 @@ struct ConversationFragment: View {
if conversationViewModel.conversationMessagesSection.first != nil {
let counter = conversationViewModel.conversationMessagesSection.first!.rows.count
ForEach(0..<counter, id: \.self) { index in
ChatBubbleView(conversationViewModel: conversationViewModel, eventLogMessage: conversationViewModel.conversationMessagesSection.first!.rows[index], geometryProxy: geometry)
ChatBubbleView(eventLogMessage: conversationViewModel.conversationMessagesSection.first!.rows[index], geometryProxy: geometry)
.environmentObject(conversationViewModel)
.id(conversationViewModel.conversationMessagesSection.first!.rows[index].message.id)
.listRowInsets(EdgeInsets(top: 2, leading: 10, bottom: 2, trailing: 10))
.listRowSeparator(.hidden)
@ -502,7 +506,7 @@ struct ConversationFragment: View {
.transition(.move(edge: .bottom))
}
if SharedMainViewModel.shared.displayedConversation != nil && !SharedMainViewModel.shared.displayedConversation!.isReadOnly {
if !(SharedMainViewModel.shared.displayedConversation?.isReadOnly ?? cachedConversation!.isReadOnly) {
if conversationViewModel.messageToReply != nil {
ZStack(alignment: .top) {
HStack {
@ -830,7 +834,8 @@ struct ConversationFragment: View {
)
.padding(.horizontal, 4)
} else {
VoiceRecorderPlayer(conversationViewModel: conversationViewModel, voiceRecordingInProgress: $voiceRecordingInProgress)
VoiceRecorderPlayer(voiceRecordingInProgress: $voiceRecordingInProgress)
.environmentObject(conversationViewModel)
.frame(maxHeight: 60)
}
}
@ -934,7 +939,8 @@ struct ConversationFragment: View {
.padding(.leading, SharedMainViewModel.shared.displayedConversation!.isGroup ? 43 : 0)
.shadow(color: .black.opacity(0.1), radius: 10)
ChatBubbleView(conversationViewModel: conversationViewModel, eventLogMessage: conversationViewModel.selectedMessage!, geometryProxy: geometry)
ChatBubbleView(eventLogMessage: conversationViewModel.selectedMessage!, geometryProxy: geometry)
.environmentObject(conversationViewModel)
.padding(.horizontal, 10)
.padding(.vertical, 1)
.shadow(color: .black.opacity(0.1), radius: 10)
@ -992,9 +998,6 @@ struct ConversationFragment: View {
}
Button {
conversationForwardMessageViewModel.initConversationsLists(convsList: conversationsListViewModel.conversationsList)
conversationForwardMessageViewModel.selectedMessage = conversationViewModel.selectedMessage
conversationViewModel.selectedMessage = nil
withAnimation {
isShowConversationForwardMessageFragment = true
}
@ -1068,40 +1071,39 @@ struct ConversationFragment: View {
if isShowConversationForwardMessageFragment {
ConversationForwardMessageFragment(
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
conversationForwardMessageViewModel: conversationForwardMessageViewModel,
conversationsList: conversationsListViewModel.conversationsList,
selectedMessage: conversationViewModel.selectedMessage,
isShowConversationForwardMessageFragment: $isShowConversationForwardMessageFragment
)
.environmentObject(conversationViewModel)
.environmentObject(conversationsListViewModel)
.zIndex(5)
.transition(.move(edge: .trailing))
.onAppear {
conversationViewModel.selectedMessage = nil
}
}
if isShowInfoConversationFragment {
ConversationInfoFragment(
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,
isMuted: $isMuted,
isShowEphemeralFragment: $isShowEphemeralFragment,
isShowStartCallGroupPopup: $isShowStartCallGroupPopup,
isShowInfoConversationFragment: $isShowInfoConversationFragment,
isShowEditContactFragment: $isShowEditContactFragment,
indexPage: $indexPage,
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress,
isShowScheduleMeetingFragment: $isShowScheduleMeetingFragment
)
.environmentObject(conversationViewModel)
.zIndex(5)
.transition(.move(edge: .trailing))
}
if isShowEphemeralFragment {
EphemeralFragment(
conversationViewModel: conversationViewModel,
isShowEphemeralFragment: $isShowEphemeralFragment
)
.environmentObject(conversationViewModel)
.zIndex(5)
.transition(.move(edge: .trailing))
}
@ -1112,7 +1114,7 @@ struct ConversationFragment: View {
}
struct ImdnOrReactionsSheet: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@Binding var selectedCategoryIndex: Int
@ -1181,7 +1183,7 @@ struct ImdnOrReactionsSheet: View {
}
struct ImagePicker: UIViewControllerRepresentable {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@Binding var selectedMedia: [Attachment]
@Environment(\.presentationMode) private var presentationMode
@ -1263,7 +1265,7 @@ struct ImagePicker: UIViewControllerRepresentable {
}
struct VoiceRecorderPlayer: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@Binding var voiceRecordingInProgress: Bool
@ -1445,7 +1447,7 @@ struct VoiceRecorderPlayer: View {
}
/*
#Preview {
ConversationFragment(conversationViewModel: ConversationViewModel(), conversationsListViewModel: ConversationsListViewModel(), sections: [MessagesSection], ids: [""])
ConversationFragment(sections: [MessagesSection], ids: [""])
}
*/

View file

@ -25,12 +25,9 @@ struct ConversationInfoFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var meetingViewModel: MeetingViewModel
@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
@EnvironmentObject var accountProfileViewModel: AccountProfileViewModel
@State var addParticipantsViewModel = AddParticipantsViewModel()
@ -39,7 +36,7 @@ struct ConversationInfoFragment: View {
@Binding var isShowStartCallGroupPopup: Bool
@Binding var isShowInfoConversationFragment: Bool
@Binding var isShowEditContactFragment: Bool
@Binding var indexPage: Int
@Binding var isShowEditContactFragmentAddress: String
@Binding var isShowScheduleMeetingFragment: Bool
@ -222,10 +219,12 @@ struct ConversationInfoFragment: View {
Button(action: {
if SharedMainViewModel.shared.displayedConversation != nil {
/*
meetingViewModel.subject = SharedMainViewModel.shared.displayedConversation!.subject
meetingViewModel.participants = conversationViewModel.participants
*/
SharedMainViewModel.shared.displayedConversation = nil
indexPage = 3
SharedMainViewModel.shared.changeIndexView(indexViewInt: 3)
withAnimation {
isShowScheduleMeetingFragment = true
}
@ -351,21 +350,18 @@ struct ConversationInfoFragment: View {
let friendIndex = contactsManager.avatarListModel.first(
where: {$0.addresses.contains(where: {$0 == addressConv})})
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
if friendIndex != nil {
withAnimation {
SharedMainViewModel.shared.displayedConversation = nil
indexPage = 0
SharedMainViewModel.shared.displayedFriend = friendIndex
}
} else {
withAnimation {
SharedMainViewModel.shared.displayedConversation = nil
indexPage = 0
isShowEditContactFragment.toggle()
editContactViewModel.sipAddresses.removeAll()
editContactViewModel.sipAddresses.append(String(participantConversationModel.address.dropFirst(4) ?? ""))
editContactViewModel.sipAddresses.append("")
isShowEditContactFragmentAddress = String(participantConversationModel.address.dropFirst(4))
}
}
},
@ -526,26 +522,24 @@ struct ConversationInfoFragment: View {
Button(
action: {
if SharedMainViewModel.shared.displayedConversation != nil {
let addressConv = conversationViewModel.participantConversationModel.first?.address ?? ""
let friendIndex = contactsManager.avatarListModel.first(
where: {$0.addresses.contains(where: {$0 == addressConv})})
if friendIndex != nil {
withAnimation {
SharedMainViewModel.shared.displayedConversation = nil
indexPage = 0
SharedMainViewModel.shared.displayedFriend = friendIndex
}
} else {
withAnimation {
SharedMainViewModel.shared.displayedConversation = nil
indexPage = 0
isShowEditContactFragment.toggle()
editContactViewModel.sipAddresses.removeAll()
editContactViewModel.sipAddresses.append(String(conversationViewModel.participantConversationModel.first?.address.dropFirst(4) ?? ""))
editContactViewModel.sipAddresses.append("")
if let participantConversationModel = conversationViewModel.participantConversationModel.first {
let addressConv = participantConversationModel.address
let friendIndex = contactsManager.avatarListModel.first(
where: {$0.addresses.contains(where: {$0 == addressConv})})
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
if friendIndex != nil {
withAnimation {
SharedMainViewModel.shared.displayedFriend = friendIndex
}
} else {
withAnimation {
isShowEditContactFragment.toggle()
isShowEditContactFragmentAddress = String(participantConversationModel.address.dropFirst(4))
}
}
}
}
@ -696,19 +690,12 @@ struct ConversationInfoFragment: View {
#Preview {
ConversationInfoFragment(
conversationViewModel: ConversationViewModel(),
conversationsListViewModel: ConversationsListViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
meetingViewModel: MeetingViewModel(),
accountProfileViewModel: AccountProfileViewModel(),
addParticipantsViewModel: AddParticipantsViewModel(),
isMuted: .constant(false),
isShowEphemeralFragment: .constant(false),
isShowStartCallGroupPopup: .constant(false),
isShowInfoConversationFragment: .constant(true),
isShowEditContactFragment: .constant(false),
indexPage: .constant(0),
isShowEditContactFragmentAddress: .constant(""),
isShowScheduleMeetingFragment: .constant(false)
)
}

View file

@ -21,7 +21,7 @@ import SwiftUI
import linphonesw
struct EphemeralFragment: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@State private var selectedOption = NSLocalizedString("conversation_ephemeral_messages_duration_disabled", comment: "")
let options = [
@ -151,7 +151,6 @@ struct EphemeralFragment: View {
#Preview {
EphemeralFragment(
conversationViewModel: ConversationViewModel(),
isShowEphemeralFragment: .constant(true)
)
}

View file

@ -26,8 +26,9 @@ struct StartConversationFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var magicSearch = MagicSearchSingleton.shared
@ObservedObject var startConversationViewModel: StartConversationViewModel
@ObservedObject var conversationViewModel: ConversationViewModel
@StateObject private var startConversationViewModel = StartConversationViewModel()
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
@Binding var isShowStartConversationFragment: Bool
@ -136,7 +137,8 @@ struct StartConversationFragment: View {
.padding(.horizontal)
NavigationLink(destination: {
StartGroupConversationFragment(startConversationViewModel: startConversationViewModel)
StartGroupConversationFragment()
.environmentObject(startConversationViewModel)
}, label: {
HStack {
HStack(alignment: .center) {
@ -233,9 +235,8 @@ struct StartConversationFragment: View {
isShowStartConversationFragment = false
if startConversationViewModel.displayedConversation != nil {
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: startConversationViewModel.displayedConversation!)
if let displayedConversation = startConversationViewModel.displayedConversation {
self.conversationsListViewModel.changeDisplayedChatRoom(conversationModel: displayedConversation)
startConversationViewModel.displayedConversation = nil
}
}
@ -397,8 +398,6 @@ struct StartConversationFragment: View {
#Preview {
StartConversationFragment(
startConversationViewModel: StartConversationViewModel(),
conversationViewModel: ConversationViewModel(),
isShowStartConversationFragment: .constant(true)
)
}

View file

@ -20,7 +20,10 @@
import SwiftUI
struct StartGroupConversationFragment: View {
@ObservedObject var startConversationViewModel: StartConversationViewModel
@EnvironmentObject var startConversationViewModel: StartConversationViewModel
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
@State var addParticipantsViewModel = AddParticipantsViewModel()
var body: some View {
@ -32,5 +35,5 @@ struct StartGroupConversationFragment: View {
}
#Preview {
StartGroupConversationFragment(startConversationViewModel: StartConversationViewModel())
StartGroupConversationFragment()
}

View file

@ -102,10 +102,11 @@ struct UIList: UIViewRepresentable {
private static var sharedCoordinator: Coordinator?
@ObservedObject var viewModel: ChatViewModel
@ObservedObject var paginationState: PaginationState
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@StateObject private var viewModel = ChatViewModel()
@StateObject private var paginationState = PaginationState()
@EnvironmentObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationsListViewModel: ConversationsListViewModel
let geometryProxy: GeometryProxy
let sections: [MessagesSection]
@ -445,7 +446,8 @@ struct UIList: UIViewRepresentable {
let row = sections[indexPath.section].rows[indexPath.row]
if #available(iOS 16.0, *) {
tableViewCell.contentConfiguration = UIHostingConfiguration {
ChatBubbleView(conversationViewModel: parent.conversationViewModel, eventLogMessage: row, geometryProxy: geometryProxy)
ChatBubbleView(eventLogMessage: row, geometryProxy: geometryProxy)
.environmentObject(parent.conversationViewModel)
.padding(.vertical, 2)
.padding(.horizontal, 10)
.onTapGesture { }

View file

@ -39,7 +39,10 @@ class ConversationForwardMessageViewModel: ObservableObject {
private var chatRoomDelegate: ChatRoomDelegate?
init() {}
init(conversationsList: [ConversationModel], selectedMessage: EventLogMessage?) {
self.conversationsList = conversationsList
self.selectedMessage = selectedMessage
}
func initConversationsLists(convsList: [ConversationModel]) {
conversationsListTmp = convsList

View file

@ -120,14 +120,10 @@ class ConversationViewModel: ObservableObject {
}
init() {
// TODO a check si utile
/*
self.selectedMessage = nil
self.resetMessage()
self.removeConversationDelegate()
self.addConversationDelegate(chatRoom: newChatRoom)
self.getMessages()
*/
if let chatroom = self.sharedMainViewModel.displayedConversation?.chatRoom {
self.addConversationDelegate(chatRoom: chatroom)
self.getMessages()
}
}
func addConversationDelegate() {
@ -180,7 +176,7 @@ class ConversationViewModel: ObservableObject {
}, onChatMessagesReceived: { (_: ChatRoom, eventLogs: [EventLog]) in
self.getNewMessages(eventLogs: eventLogs)
}, onChatMessageSending: { (_: ChatRoom, eventLog: EventLog) in
if self.conversationMessagesSection[0].rows.isEmpty {
if self.conversationMessagesSection.isEmpty || self.conversationMessagesSection[0].rows.isEmpty {
self.sendFirstMessage(eventLog: eventLog)
} else {
self.getNewMessages(eventLogs: [eventLog])

View file

@ -117,8 +117,25 @@ class ConversationsListViewModel: ObservableObject {
conversationModel.subject = contactAvatarModel.name
}
}
}
}
}
} else if !conversationModel.isGroup {
if let address = conversationModel.participantsAddress.first {
let avatarModelTmp = ContactsManager.shared.avatarListModel.first(where: {
guard let friend = $0.friend else { return false }
return friend.name == conversationModel.subject &&
friend.address?.asStringUriOnly() == address
}) ?? ContactAvatarModel(
friend: nil,
name: conversationModel.subject,
address: address,
withPresence: false
)
DispatchQueue.main.async {
conversationModel.avatarModel = avatarModelTmp
}
}
}
}
}
}
@ -460,11 +477,22 @@ class ConversationsListViewModel: ObservableObject {
let nilParams: ConferenceParams? = nil
if let newChatRoom = core.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: conversationModel.chatRoom.peerAddress, participants: nil) {
if LinphoneUtils.getChatRoomId(room: newChatRoom) == conversationModel.id {
DispatchQueue.main.async {
withAnimation {
self.sharedMainViewModel.displayedConversation = conversationModel
}
}
if self.sharedMainViewModel.displayedConversation == nil {
DispatchQueue.main.async {
withAnimation {
self.sharedMainViewModel.displayedConversation = conversationModel
}
}
} else {
DispatchQueue.main.async {
self.sharedMainViewModel.displayedConversation = nil
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.sharedMainViewModel.displayedConversation = conversationModel
}
}
}
}
}
}
}

View file

@ -193,7 +193,7 @@ class StartConversationViewModel: ObservableObject {
"\(StartConversationViewModel.TAG) Account is in secure mode, can't chat with SIP address of different domain \(remote.asStringUriOnly())"
)
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
@ -218,7 +218,7 @@ class StartConversationViewModel: ObservableObject {
Log.info("\(StartConversationViewModel.TAG) 1-1 conversation \(chatRoomId) has been created")
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.displayedConversation = model
self.operationInProgress = false
}
@ -231,7 +231,7 @@ class StartConversationViewModel: ObservableObject {
Log.info("\(StartConversationViewModel.TAG) Conversation successfully created \(chatRoomId)")
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.displayedConversation = model
self.operationInProgress = false
}
@ -239,7 +239,7 @@ class StartConversationViewModel: ObservableObject {
} catch {
Log.error("\(StartConversationViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())")
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
@ -250,7 +250,7 @@ class StartConversationViewModel: ObservableObject {
"\(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!)
DispatchQueue.main.async {
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
self.displayedConversation = model
self.operationInProgress = false
}

View file

@ -9,7 +9,7 @@ import SwiftUI
struct PopupViewWithTextField: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var conversationViewModel: ConversationViewModel
@FocusState var isMessageTextFocused: Bool
@ -81,5 +81,5 @@ struct PopupViewWithTextField: View {
}
#Preview {
PopupViewWithTextField(conversationViewModel: ConversationViewModel())
PopupViewWithTextField()
}

View file

@ -263,7 +263,7 @@ struct HistoryContactFragment: View {
Spacer()
Button(action: {
//contactsListViewModel.createOneToOneChatRoomWith(remote: historyModel.addressLinphone)
historyListViewModel.createOneToOneChatRoomWith(remote: historyModel.addressLinphone)
}, label: {
VStack {
HStack(alignment: .center) {

View file

@ -35,6 +35,10 @@ class HistoryListViewModel: ObservableObject {
@Published var selectedCall: HistoryModel?
@Published var displayedConversation: ConversationModel?
private var historyChatRoomDelegate: ChatRoomDelegate?
init() {
computeCallLogsList()
updateMissedCallsCount()
@ -255,4 +259,178 @@ class HistoryListViewModel: ObservableObject {
}
}
}
func createOneToOneChatRoomWith(remote: Address) {
CoreContext.shared.doOnCoreQueue { core in
let account = core.defaultAccount
if account == nil {
Log.error(
"\(ConversationForwardMessageViewModel.TAG) No default account found, can't create conversation with \(remote.asStringUriOnly())"
)
return
}
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = true
}
do {
let params = try core.createConferenceParams(conference: nil)
params.chatEnabled = true
params.groupEnabled = false
params.subject = NSLocalizedString("conversation_one_to_one_hidden_subject", comment: "")
params.account = account
guard let chatParams = params.chatParams else { return }
chatParams.ephemeralLifetime = 0 // Make sure ephemeral is disabled by default
let sameDomain = remote.domain == CorePreferences.defaultDomain && remote.domain == account!.params?.domain
if account!.params != nil && (account!.params!.instantMessagingEncryptionMandatory && sameDomain) {
Log.info("\(ConversationForwardMessageViewModel.TAG) Account is in secure mode & domain matches, creating an E2E encrypted conversation")
chatParams.backend = ChatRoom.Backend.FlexisipChat
params.securityLevel = Conference.SecurityLevel.EndToEnd
} else if account!.params != nil && (!account!.params!.instantMessagingEncryptionMandatory) {
if LinphoneUtils.isEndToEndEncryptedChatAvailable(core: core) {
Log.info(
"\(ConversationForwardMessageViewModel.TAG) Account is in interop mode but LIME is available, creating an E2E encrypted conversation"
)
chatParams.backend = ChatRoom.Backend.FlexisipChat
params.securityLevel = Conference.SecurityLevel.EndToEnd
} else {
Log.info(
"\(ConversationForwardMessageViewModel.TAG) Account is in interop mode but LIME isn't available, creating a SIP simple conversation"
)
chatParams.backend = ChatRoom.Backend.Basic
params.securityLevel = Conference.SecurityLevel.None
}
} else {
Log.error(
"\(ConversationForwardMessageViewModel.TAG) Account is in secure mode, can't chat with SIP address of different domain \(remote.asStringUriOnly())"
)
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_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(
"\(ConversationForwardMessageViewModel.TAG) No existing 1-1 conversation between local account \(localAddress?.asStringUriOnly() ?? "") and remote \(remote.asStringUriOnly()) was found for given parameters, let's create it"
)
do {
let chatRoom = try core.createChatRoom(params: params, participants: participants)
if chatParams.backend == ChatRoom.Backend.FlexisipChat {
let state = chatRoom.state
if state == ChatRoom.State.Created {
let chatRoomId = LinphoneUtils.getConversationId(chatRoom: chatRoom)
Log.info("\(ConversationForwardMessageViewModel.TAG) 1-1 conversation \(chatRoomId) has been created")
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
self.displayedConversation = model
SharedMainViewModel.shared.operationInProgress = false
}
} else {
Log.info("\(ConversationForwardMessageViewModel.TAG) Conversation isn't in Created state yet (state is \(state)), wait for it")
self.chatRoomAddDelegate(core: core, chatRoom: chatRoom)
}
} else {
let chatRoomId = LinphoneUtils.getConversationId(chatRoom: chatRoom)
Log.info("\(ConversationForwardMessageViewModel.TAG) Conversation successfully created \(chatRoomId)")
let model = ConversationModel(chatRoom: chatRoom)
DispatchQueue.main.async {
self.displayedConversation = model
SharedMainViewModel.shared.operationInProgress = false
}
}
} catch {
Log.error("\(ConversationForwardMessageViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())")
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
} else {
Log.warn(
"\(ConversationForwardMessageViewModel.TAG) A 1-1 conversation between local account \(localAddress?.asStringUriOnly() ?? "") and remote \(remote.asStringUriOnly()) for given parameters already exists!"
)
let model = ConversationModel(chatRoom: existingChatRoom!)
DispatchQueue.main.async {
self.displayedConversation = model
SharedMainViewModel.shared.operationInProgress = false
}
}
} catch {
}
}
}
func chatRoomAddDelegate(core: Core, chatRoom: ChatRoom) {
historyChatRoomDelegate = ChatRoomDelegateStub(onStateChanged: { (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!")
if let delegate = self.historyChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.historyChatRoomDelegate = nil
}
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
}, onConferenceJoined: { (chatRoom: ChatRoom, _: 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")
if let delegate = self.historyChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.historyChatRoomDelegate = nil
}
let model = ConversationModel(chatRoom: chatRoom)
if SharedMainViewModel.shared.operationInProgress == false {
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = true
}
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
SharedMainViewModel.shared.operationInProgress = false
self.displayedConversation = model
}
} else {
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = false
self.displayedConversation = model
}
}
} else if state == ChatRoom.State.CreationFailed {
Log.error("\(StartConversationViewModel.TAG) Conversation \(id) creation has failed!")
if let delegate = self.historyChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.historyChatRoomDelegate = nil
}
DispatchQueue.main.async {
SharedMainViewModel.shared.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
})
chatRoom.addDelegate(delegate: historyChatRoomDelegate!)
}
}

View file

@ -40,6 +40,9 @@ class SharedMainViewModel: ObservableObject {
@Published var dialPlansLabelList: [String] = []
@Published var dialPlansShortLabelList: [String] = []
@Published var operationInProgress = false
let welcomeViewKey = "welcome_view"
let generalTermsKey = "general_terms"
let displayProfileModeKey = "display_profile_mode"