Refactored ContactsView (Part 2)

This commit is contained in:
Benoit Martins 2025-05-28 17:24:44 +02:00
parent cd223dcf06
commit 865f889a3c
30 changed files with 584 additions and 710 deletions

View file

@ -32,9 +32,10 @@ import SwiftUI
import Firebase
#endif
final class CoreContext: ObservableObject {
static let shared = CoreContext()
class CoreContext: ObservableObject {
static let shared = CoreContext()
var pipViewModel = PIPViewModel()
var coreVersion: String = Core.getVersion
@ -426,7 +427,7 @@ final class CoreContext: ObservableObject {
func performActionOnCoreQueueWhenCoreIsStarted(action: @escaping (_ core: Core) -> Void ) {
if coreIsStarted {
CoreContext.shared.doOnCoreQueue { core in
doOnCoreQueue { core in
action(core)
}
} else {

View file

@ -30,14 +30,17 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
var launchNotificationPeerAddr: String?
var launchNotificationLocalAddr: String?
var navigationManager: NavigationManager?
var coreContext: CoreContext?
var navigationManager: NavigationManager?
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let tokenStr = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
Log.info("Received remote push token : \(tokenStr)")
CoreContext.shared.doOnCoreQueue { core in
Log.info("Forwarding remote push token to core")
core.didRegisterForRemotePushWithStringifiedToken(deviceTokenStr: tokenStr + ":remote")
if let coreContext = coreContext {
coreContext.doOnCoreQueue { core in
Log.info("Forwarding remote push token to core")
core.didRegisterForRemotePushWithStringifiedToken(deviceTokenStr: tokenStr + ":remote")
}
}
}
@ -92,14 +95,16 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
} else {
// Only display notification if we're not in the chatroom they come from
if displayedChatroomPeerAddr != strPeerAddr {
CoreContext.shared.doOnCoreQueue { core in
let nilParams: ConferenceParams? = nil
if let peerAddr = try? Factory.Instance.createAddress(addr: strPeerAddr!)
, let chatroom = core.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: peerAddr, participants: nil), chatroom.muted {
Log.info("message comes from a muted chatroom, ignore it")
return
if let coreContext = coreContext {
coreContext.doOnCoreQueue { core in
let nilParams: ConferenceParams? = nil
if let peerAddr = try? Factory.Instance.createAddress(addr: strPeerAddr!)
, let chatroom = core.searchChatRoom(params: nilParams, localAddr: nil, remoteAddr: peerAddr, participants: nil), chatroom.muted {
Log.info("message comes from a muted chatroom, ignore it")
return
}
completionHandler([.banner, .sound])
}
completionHandler([.banner, .sound])
}
}
}
@ -108,13 +113,15 @@ class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDele
func applicationWillTerminate(_ application: UIApplication) {
Log.info("IOS applicationWillTerminate")
CoreContext.shared.doOnCoreQueue(synchronous: true) { core in
Log.info("applicationWillTerminate - Stopping linphone core")
MagicSearchSingleton.shared.destroyMagicSearch()
if core.globalState != GlobalState.Off {
core.stop()
} else {
Log.info("applicationWillTerminate - Core already stopped")
if let coreContext = coreContext {
coreContext.doOnCoreQueue(synchronous: true) { core in
Log.info("applicationWillTerminate - Stopping linphone core")
MagicSearchSingleton.shared.destroyMagicSearch()
if core.globalState != GlobalState.Off {
core.stop()
} else {
Log.info("applicationWillTerminate - Core already stopped")
}
}
}
}
@ -125,27 +132,12 @@ struct LinphoneApp: App {
@Environment(\.scenePhase) var scenePhase
@UIApplicationDelegateAdaptor(AppDelegate.self) var delegate
@StateObject var navigationManager = NavigationManager()
@ObservedObject private var coreContext = CoreContext.shared
@StateObject private var coreContext = CoreContext.shared
@StateObject private var navigationManager = NavigationManager()
@State var index: Int = 0
/*
@State private var editContactViewModel: EditContactViewModel?
@State private var historyViewModel: HistoryViewModel?
@State private var historyListViewModel: HistoryListViewModel?
@State private var startCallViewModel: StartCallViewModel?
@State private var startConversationViewModel: StartConversationViewModel?
@State private var callViewModel: CallViewModel?
@State private var meetingWaitingRoomViewModel: MeetingWaitingRoomViewModel?
@State private var conversationsListViewModel: ConversationsListViewModel?
@State private var conversationViewModel: ConversationViewModel?
@State private var meetingsListViewModel: MeetingsListViewModel?
@State private var meetingViewModel: MeetingViewModel?
@State private var conversationForwardMessageViewModel: ConversationForwardMessageViewModel?
@State private var accountProfileViewModel: AccountProfileViewModel?
*/
@ObservedObject private var telecomManager = TelecomManager.shared
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
@State private var pendingURL: URL?
@ -153,14 +145,14 @@ struct LinphoneApp: App {
WindowGroup {
if coreContext.coreHasStartedOnce {
ZStack {
if !SharedMainViewModel.shared.welcomeViewDisplayed {
if !sharedMainViewModel.welcomeViewDisplayed {
ZStack {
WelcomeView()
ToastView()
.zIndex(3)
}
} else if (coreContext.coreIsStarted && coreContext.accounts.isEmpty) || SharedMainViewModel.shared.displayProfileMode {
} else if (coreContext.coreIsStarted && coreContext.accounts.isEmpty) || sharedMainViewModel.displayProfileMode {
ZStack {
AssistantView()
@ -168,36 +160,21 @@ struct LinphoneApp: App {
.zIndex(3)
}
} else {
ContentView(
//editContactViewModel: editContactViewModel!,
//historyViewModel: historyViewModel!,
//historyListViewModel: historyListViewModel!,
//startCallViewModel: startCallViewModel!,
//startConversationViewModel: startConversationViewModel!,
//callViewModel: callViewModel!,
//meetingWaitingRoomViewModel: meetingWaitingRoomViewModel!,
//conversationsListViewModel: conversationsListViewModel!,
//conversationViewModel: conversationViewModel!,
//meetingsListViewModel: meetingsListViewModel!,
//meetingViewModel: meetingViewModel!,
//conversationForwardMessageViewModel: conversationForwardMessageViewModel!,
//accountProfileViewModel: accountProfileViewModel!,
index: $index
)
.environmentObject(navigationManager)
.onAppear {
index = SharedMainViewModel.shared.indexView
// Link the navigation manager to the AppDelegate
delegate.navigationManager = navigationManager
// Check if the app was launched with a notification payload
if let callId = delegate.launchNotificationCallId, let peerAddr = delegate.launchNotificationPeerAddr, let localAddr = delegate.launchNotificationLocalAddr {
// Notify the app to navigate to the chat room
navigationManager.openChatRoom(callId: callId, peerAddr: peerAddr, localAddr: localAddr)
ContentView()
.environmentObject(navigationManager)
.onAppear {
// Link the navigation manager to the AppDelegate
delegate.coreContext = coreContext
delegate.navigationManager = navigationManager
// Check if the app was launched with a notification payload
if let callId = delegate.launchNotificationCallId, let peerAddr = delegate.launchNotificationPeerAddr, let localAddr = delegate.launchNotificationLocalAddr {
// Notify the app to navigate to the chat room
navigationManager.openChatRoom(callId: callId, peerAddr: peerAddr, localAddr: localAddr)
}
//accountProfileViewModel!.setAvatarModel()
}
//accountProfileViewModel!.setAvatarModel()
}
}
if coreContext.coreIsStarted {
@ -223,7 +200,7 @@ struct LinphoneApp: App {
SplashScreen()
}
}.onChange(of: scenePhase) { newPhase in
if !TelecomManager.shared.callInProgress {
if !telecomManager.callInProgress {
if newPhase == .active {
Log.info("Entering foreground")
coreContext.onEnterForeground()

View file

@ -37,7 +37,7 @@ struct CallView: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var meetingViewModel: MeetingViewModel
@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@ -209,7 +209,7 @@ struct CallView: View {
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
conversationForwardMessageViewModel: conversationForwardMessageViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,
@ -2864,7 +2864,7 @@ struct PressedButtonStyle: ButtonStyle {
conversationViewModel: ConversationViewModel(),
conversationsListViewModel: ConversationsListViewModel(),
conversationForwardMessageViewModel: ConversationForwardMessageViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
meetingViewModel: MeetingViewModel(),
accountProfileViewModel: AccountProfileViewModel(),

View file

@ -21,7 +21,7 @@ import SwiftUI
struct ContactsView: View {
@EnvironmentObject var contactViewModel: ContactViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var isShowEditContactFragment: Bool
@Binding var isShowDeletePopup: Bool
@ -30,12 +30,11 @@ struct ContactsView: View {
var body: some View {
NavigationView {
ZStack(alignment: .bottomTrailing) {
ContactsFragment(contactViewModel: contactViewModel, isShowDeletePopup: $isShowDeletePopup, text: $text)
ContactsFragment(isShowDeletePopup: $isShowDeletePopup, text: $text)
Button {
withAnimation {
contactViewModel.selectedEditFriend = nil
//editContactViewModel.resetValues()
contactsListViewModel.selectedEditFriend = nil
isShowEditContactFragment.toggle()
}
} label: {
@ -49,6 +48,7 @@ struct ContactsView: View {
}
.padding()
// For testing crashlytics
/*Button(action: CoreContext.shared.crashForCrashlytics, label: {
Text("CRASH ME")
@ -61,9 +61,6 @@ struct ContactsView: View {
#Preview {
ContactsView(
//contactViewModel: ContactViewModel(),
//historyViewModel: HistoryViewModel(),
//editContactViewModel: EditContactViewModel(),
isShowEditContactFragment: .constant(false),
isShowDeletePopup: .constant(false),
text: .constant("")

View file

@ -24,37 +24,23 @@ struct ContactFragment: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var isShowDeletePopup: Bool
@Binding var isShowDismissPopup: Bool
@Binding var isShowSipAddressesPopup: Bool
@Binding var isShowSipAddressesPopupType: Int
@Binding var isShowEditContactFragmentInContactDetails: Bool
@State private var showingSheet = false
@State private var showShareSheet = false
var body: some View {
let indexDisplayed = SharedMainViewModel.shared.indexDisplayedFriend != nil ? SharedMainViewModel.shared.indexDisplayedFriend! : 0
if ContactsManager.shared.avatarListModel.count > indexDisplayed {
if #available(iOS 16.0, *), idiom != .pad {
ContactInnerFragment(
contactAvatarModel: ContactsManager.shared.avatarListModel[indexDisplayed],
contactViewModel: contactViewModel,
editContactViewModel: editContactViewModel,
conversationViewModel: conversationViewModel,
cnContact: CNContact(),
isShowDeletePopup: $isShowDeletePopup,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet,
isShowDismissPopup: $isShowDismissPopup,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType
)
if #available(iOS 16.0, *), idiom != .pad {
contactInnerContent(contactsListViewModel: contactsListViewModel)
.sheet(isPresented: $showingSheet) {
ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet)
ContactListBottomSheet(contactsListViewModel: contactsListViewModel, showingSheet: $showingSheet)
.presentationDetents([.fraction(0.2)])
}
.sheet(isPresented: $showShareSheet) {
@ -62,40 +48,39 @@ struct ContactFragment: View {
.presentationDetents([.medium])
.edgesIgnoringSafeArea(.bottom)
}
} else {
ContactInnerFragment(
contactAvatarModel: ContactsManager.shared.avatarListModel[indexDisplayed],
contactViewModel: contactViewModel,
editContactViewModel: editContactViewModel,
conversationViewModel: conversationViewModel,
cnContact: CNContact(),
isShowDeletePopup: $isShowDeletePopup,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet,
isShowDismissPopup: $isShowDismissPopup,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType
)
} else {
contactInnerContent(contactsListViewModel: contactsListViewModel)
.halfSheet(showSheet: $showingSheet) {
ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet)
ContactListBottomSheet(contactsListViewModel: contactsListViewModel, showingSheet: $showingSheet)
} onDismiss: {}
.sheet(isPresented: $showShareSheet) {
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[SharedMainViewModel.shared.indexDisplayedFriend!].friend!)
.edgesIgnoringSafeArea(.bottom)
}
}
.sheet(isPresented: $showShareSheet) {
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[SharedMainViewModel.shared.indexDisplayedFriend!].friend!)
.edgesIgnoringSafeArea(.bottom)
}
}
}
@ViewBuilder
private func contactInnerContent(contactsListViewModel: ContactsListViewModel) -> some View {
ContactInnerFragment(
cnContact: CNContact(),
isShowDeletePopup: $isShowDeletePopup,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet,
isShowDismissPopup: $isShowDismissPopup,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
)
}
}
#Preview {
ContactFragment(
contactViewModel: ContactViewModel(),
editContactViewModel: EditContactViewModel(),
conversationViewModel: ConversationViewModel(),
isShowDeletePopup: .constant(false),
isShowDismissPopup: .constant(false),
isShowSipAddressesPopup: .constant(false),
isShowSipAddressesPopupType: .constant(0)
isShowSipAddressesPopupType: .constant(0),
isShowEditContactFragmentInContactDetails: .constant(false)
)
}

View file

@ -26,9 +26,8 @@ struct ContactInnerActionsFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject private var telecomManager = TelecomManager.shared
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var contactAvatarModel: ContactAvatarModel
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@State private var informationIsOpen = true
@ -36,6 +35,7 @@ struct ContactInnerActionsFragment: View {
@Binding var showShareSheet: Bool
@Binding var isShowDeletePopup: Bool
@Binding var isShowDismissPopup: Bool
@Binding var isShowEditContactFragmentInContactDetails: Bool
var actionEditButton: () -> Void
@ -102,7 +102,7 @@ struct ContactInnerActionsFragment: View {
}
}
.onLongPressGesture(minimumDuration: 0.2) {
contactViewModel.stringToCopy = contactAvatarModel.addresses[index]
contactsListViewModel.stringToCopy = contactAvatarModel.addresses[index]
showingSheet.toggle()
}
@ -142,7 +142,7 @@ struct ContactInnerActionsFragment: View {
}
.background(.white)
.onLongPressGesture(minimumDuration: 0.2) {
contactViewModel.stringToCopy =
contactsListViewModel.stringToCopy =
contactAvatarModel.friend!.phoneNumbersWithLabel[index].phoneNumber
showingSheet.toggle()
}
@ -238,9 +238,8 @@ struct ContactInnerActionsFragment: View {
}
} else {
NavigationLink(destination: EditContactFragment(
editContactViewModel: editContactViewModel,
contactViewModel: contactViewModel,
isShowEditContactFragment: .constant(false),
friend: contactAvatarModel.friend!,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
HStack {
Image("pencil-simple")
@ -259,13 +258,12 @@ struct ContactInnerActionsFragment: View {
}
.padding(.vertical, 15)
.padding(.horizontal, 20)
}
.simultaneousGesture(
TapGesture().onEnded {
editContactViewModel.selectedEditFriend = contactAvatarModel.friend!
editContactViewModel.resetValues()
}
)
}
.simultaneousGesture(
TapGesture().onEnded {
isShowEditContactFragmentInContactDetails = true
}
)
}
VStack {
@ -365,13 +363,11 @@ struct ContactInnerActionsFragment: View {
#Preview {
ContactInnerActionsFragment(
contactViewModel: ContactViewModel(),
editContactViewModel: EditContactViewModel(),
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false),
showingSheet: .constant(false),
showShareSheet: .constant(false),
isShowDeletePopup: .constant(false),
isShowDismissPopup: .constant(false),
isShowEditContactFragmentInContactDetails: .constant(false),
actionEditButton: {}
)
}

View file

@ -27,10 +27,8 @@ struct ContactInnerFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject private var telecomManager = TelecomManager.shared
@ObservedObject var contactAvatarModel: ContactAvatarModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var conversationViewModel: ConversationViewModel
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@State private var orientation = UIDevice.current.orientation
@ -43,6 +41,7 @@ struct ContactInnerFragment: View {
@Binding var isShowDismissPopup: Bool
@Binding var isShowSipAddressesPopup: Bool
@Binding var isShowSipAddressesPopupType: Int
@Binding var isShowEditContactFragmentInContactDetails: Bool
var body: some View {
NavigationView {
@ -87,9 +86,8 @@ struct ContactInnerFragment: View {
})
} else {
NavigationLink(destination: EditContactFragment(
editContactViewModel: editContactViewModel,
contactViewModel: contactViewModel,
isShowEditContactFragment: .constant(false),
friend: contactAvatarModel.friend,
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
isShowDismissPopup: $isShowDismissPopup)) {
Image("pencil-simple")
.renderingMode(.template)
@ -101,10 +99,9 @@ struct ContactInnerFragment: View {
}
.simultaneousGesture(
TapGesture().onEnded {
editContactViewModel.selectedEditFriend = contactAvatarModel.friend
editContactViewModel.resetValues()
isShowEditContactFragmentInContactDetails = true
}
)
)
}
}
.frame(maxWidth: .infinity)
@ -181,7 +178,7 @@ struct ContactInnerFragment: View {
if contactAvatarModel.addresses.count <= 1 {
do {
let address = try Factory.Instance.createAddress(addr: contactAvatarModel.address)
contactViewModel.createOneToOneChatRoomWith(remote: address)
contactsListViewModel.createOneToOneChatRoomWith(remote: address)
} catch {
Log.error("[ContactInnerFragment] unable to create address for a new outgoing call : \(contactAvatarModel.address) \(error) ")
}
@ -248,12 +245,11 @@ struct ContactInnerFragment: View {
.background(Color.gray100)
ContactInnerActionsFragment(
contactViewModel: contactViewModel,
editContactViewModel: editContactViewModel,
contactAvatarModel: contactAvatarModel, showingSheet: $showingSheet,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet,
isShowDeletePopup: $isShowDeletePopup,
isShowDismissPopup: $isShowDismissPopup,
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails,
actionEditButton: editNativeContact
)
}
@ -301,15 +297,12 @@ struct ContactInnerFragment: View {
#Preview {
ContactInnerFragment(
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: true),
contactViewModel: ContactViewModel(),
editContactViewModel: EditContactViewModel(),
conversationViewModel: ConversationViewModel(),
isShowDeletePopup: .constant(false),
showingSheet: .constant(false),
showShareSheet: .constant(false),
isShowDismissPopup: .constant(false),
isShowSipAddressesPopup: .constant(false),
isShowSipAddressesPopupType: .constant(0)
isShowSipAddressesPopupType: .constant(0),
isShowEditContactFragmentInContactDetails: .constant(false)
)
}

View file

@ -24,7 +24,7 @@ struct ContactListBottomSheet: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@State private var orientation = UIDevice.current.orientation
@ -55,9 +55,9 @@ struct ContactListBottomSheet: View {
Spacer()
Button {
UIPasteboard.general.setValue(
contactViewModel.stringToCopy.prefix(4) == "sip:"
? contactViewModel.stringToCopy.dropFirst(4)
: contactViewModel.stringToCopy,
contactsListViewModel.stringToCopy.prefix(4) == "sip:"
? contactsListViewModel.stringToCopy.dropFirst(4)
: contactsListViewModel.stringToCopy,
forPasteboardType: UTType.plainText.identifier)
if #available(iOS 16.0, *) {
@ -78,7 +78,7 @@ struct ContactListBottomSheet: View {
.foregroundStyle(Color.grayMain2c500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text(contactViewModel.stringToCopy.prefix(4) == "sip:"
Text(contactsListViewModel.stringToCopy.prefix(4) == "sip:"
? "menu_copy_sip_address" : "menu_copy_phone_number")
.default_text_style(styleSize: 16)
Spacer()
@ -93,7 +93,7 @@ struct ContactListBottomSheet: View {
}
.frame(maxWidth: .infinity)
if contactViewModel.stringToCopy.prefix(4) != "sip:" {
if contactsListViewModel.stringToCopy.prefix(4) != "sip:" {
Button {
if #available(iOS 16.0, *) {
if idiom != .pad {
@ -144,7 +144,7 @@ struct ContactListBottomSheet: View {
.foregroundStyle(Color.grayMain2c500)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text(contactViewModel.stringToCopy.prefix(4) == "sip:"
Text(contactsListViewModel.stringToCopy.prefix(4) == "sip:"
? "menu_block_address" : "menu_block_number")
.default_text_style(styleSize: 16)
Spacer()
@ -164,5 +164,5 @@ struct ContactListBottomSheet: View {
}
#Preview {
ContactListBottomSheet(contactViewModel: ContactViewModel(), showingSheet: .constant(false))
ContactListBottomSheet(contactsListViewModel: ContactsListViewModel(), showingSheet: .constant(false))
}

View file

@ -23,7 +23,7 @@ struct ContactsFragment: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@ObservedObject var contactViewModel: ContactViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var isShowDeletePopup: Bool
@ -34,10 +34,9 @@ struct ContactsFragment: View {
var body: some View {
ZStack {
if #available(iOS 16.0, *), idiom != .pad {
ContactsInnerFragment(contactViewModel: contactViewModel, showingSheet: $showingSheet, text: $text)
ContactsInnerFragment(showingSheet: $showingSheet, text: $text)
.sheet(isPresented: $showingSheet) {
ContactsListBottomSheet(
contactViewModel: contactViewModel,
isShowDeletePopup: $isShowDeletePopup,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet
@ -45,22 +44,21 @@ struct ContactsFragment: View {
.presentationDetents([.fraction(0.2)])
}
.sheet(isPresented: $showShareSheet) {
ShareSheet(friendToShare: contactViewModel.selectedFriendToShare!)
ShareSheet(friendToShare: contactsListViewModel.selectedFriendToShare!)
.presentationDetents([.medium])
.edgesIgnoringSafeArea(.bottom)
}
} else {
ContactsInnerFragment(contactViewModel: contactViewModel, showingSheet: $showingSheet, text: $text)
ContactsInnerFragment(showingSheet: $showingSheet, text: $text)
.halfSheet(showSheet: $showingSheet) {
ContactsListBottomSheet(
contactViewModel: contactViewModel,
isShowDeletePopup: $isShowDeletePopup,
showingSheet: $showingSheet,
showShareSheet: $showShareSheet
)
} onDismiss: {}
.sheet(isPresented: $showShareSheet) {
ShareSheet(friendToShare: contactViewModel.selectedFriendToShare!)
ShareSheet(friendToShare: contactsListViewModel.selectedFriendToShare!)
.edgesIgnoringSafeArea(.bottom)
}
}
@ -69,5 +67,5 @@ struct ContactsFragment: View {
}
#Preview {
ContactsFragment(contactViewModel: ContactViewModel(), isShowDeletePopup: .constant(false), text: .constant(""))
ContactsFragment(isShowDeletePopup: .constant(false), text: .constant(""))
}

View file

@ -24,7 +24,7 @@ struct ContactsInnerFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var contactViewModel: ContactViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@State private var isFavoriteOpen = true
@ -57,10 +57,7 @@ struct ContactsInnerFragment: View {
}
if isFavoriteOpen {
FavoriteContactsListFragment(
contactViewModel: contactViewModel,
favoriteContactsListViewModel: FavoriteContactsListViewModel(),
showingSheet: $showingSheet)
FavoriteContactsListFragment(showingSheet: $showingSheet)
.zIndex(-1)
.transition(.move(edge: .top))
}
@ -77,8 +74,7 @@ struct ContactsInnerFragment: View {
VStack {
List {
ContactsListFragment(contactViewModel: contactViewModel, contactsListViewModel: ContactsListViewModel(),
showingSheet: $showingSheet, startCallFunc: {_ in })}
ContactsListFragment(showingSheet: $showingSheet, startCallFunc: {_ in })}
.safeAreaInset(edge: .top, content: {
Spacer()
.frame(height: 12)
@ -108,5 +104,5 @@ struct ContactsInnerFragment: View {
}
#Preview {
ContactsInnerFragment(contactViewModel: ContactViewModel(), showingSheet: .constant(false), text: .constant(""))
ContactsInnerFragment(showingSheet: .constant(false), text: .constant(""))
}

View file

@ -27,7 +27,7 @@ struct ContactsListBottomSheet: View {
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@ObservedObject var contactViewModel: ContactViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@State private var orientation = UIDevice.current.orientation
@ -57,10 +57,10 @@ struct ContactsListBottomSheet: View {
Spacer()
Button {
if contactViewModel.selectedFriend != nil {
contactViewModel.selectedFriend!.edit()
contactViewModel.selectedFriend!.starred.toggle()
contactViewModel.selectedFriend!.done()
if contactsListViewModel.selectedFriend != nil {
contactsListViewModel.selectedFriend!.edit()
contactsListViewModel.selectedFriend!.starred.toggle()
contactsListViewModel.selectedFriend!.done()
}
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
@ -78,19 +78,19 @@ struct ContactsListBottomSheet: View {
}
} label: {
HStack {
Image(contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true ? "heart-fill" : "heart")
Image(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true ? "heart-fill" : "heart")
.renderingMode(.template)
.resizable()
.foregroundStyle(
contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true
contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? Color.redDanger500
: Color.grayMain2c500
)
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
Text(contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true
? "contact_details_add_to_favourites"
: "contact_details_remove_from_favourites")
Text(contactsListViewModel.selectedFriend != nil && contactsListViewModel.selectedFriend!.starred == true
? "contact_details_remove_from_favourites"
: "contact_details_add_to_favourites")
.default_text_style(styleSize: 16)
Spacer()
}
@ -117,7 +117,7 @@ struct ContactsListBottomSheet: View {
dismiss()
}
contactViewModel.selectedFriendToShare = contactViewModel.selectedFriend
contactsListViewModel.selectedFriendToShare = contactsListViewModel.selectedFriend
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
showShareSheet.toggle()
@ -146,7 +146,7 @@ struct ContactsListBottomSheet: View {
.frame(maxWidth: .infinity)
Button {
if contactViewModel.selectedFriend != nil {
if contactsListViewModel.selectedFriend != nil {
isShowDeletePopup.toggle()
}
@ -186,7 +186,7 @@ struct ContactsListBottomSheet: View {
orientation = newOrientation
}
.onDisappear {
contactViewModel.selectedFriend = nil
contactsListViewModel.selectedFriend = nil
}
}
}

View file

@ -24,8 +24,7 @@ struct ContactsListFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var showingSheet: Bool
@ -88,22 +87,21 @@ struct ContactsListFragment: View {
SharedMainViewModel.shared.indexDisplayedFriend = index
}
if index < contactsManager.lastSearch.count && contactsManager.lastSearch[index].friend != nil
&& contactsManager.lastSearch[index].friend!.address != nil {
startCallFunc(contactsManager.lastSearch[index].friend!.address!)
if index < contactsManager.avatarListModel.count && contactsManager.avatarListModel[index].friend != nil
&& contactsManager.avatarListModel[index].friend!.address != nil {
startCallFunc(contactsManager.avatarListModel[index].friend!.address!)
}
}
.onLongPressGesture(minimumDuration: 0.2) {
if index < contactsManager.avatarListModel.count && contactsManager.avatarListModel[index].friend != nil {
contactsListViewModel.selectedFriend = contactsManager.avatarListModel[index].friend
showingSheet.toggle()
}
}
.onLongPressGesture(minimumDuration: 0.2) {
contactViewModel.selectedFriend = contactsManager.lastSearch[index].friend
showingSheet.toggle()
}
}
}
}
#Preview {
ContactsListFragment(contactViewModel: ContactViewModel()
, contactsListViewModel: ContactsListViewModel()
, showingSheet: .constant(false)
, startCallFunc: {_ in })
ContactsListFragment(showingSheet: .constant(false), startCallFunc: {_ in })
}

View file

@ -23,14 +23,12 @@ import linphonesw
// swiftlint:disable type_body_length
struct EditContactFragment: View {
@ObservedObject var editContactViewModel: EditContactViewModel
@Environment(\.dismiss) var dismiss
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
@State private var orientation = UIDevice.current.orientation
var contactViewModel: ContactViewModel
@StateObject private var editContactViewModel: EditContactViewModel
@Binding var isShowEditContactFragment: Bool
@Binding var isShowDismissPopup: Bool
@ -48,6 +46,12 @@ struct EditContactFragment: View {
@State private var selectedImage: UIImage?
@State private var removedImage = false
init(friend: Friend? = nil, isShowEditContactFragment: Binding<Bool>, isShowDismissPopup: Binding<Bool>) {
_editContactViewModel = StateObject(wrappedValue: EditContactViewModel(friend: friend))
self._isShowEditContactFragment = isShowEditContactFragment
self._isShowDismissPopup = isShowDismissPopup
}
var body: some View {
ZStack {
VStack(spacing: 1) {
@ -468,16 +472,13 @@ struct EditContactFragment: View {
}
.background(.white)
if editContactViewModel.removePopup {
if !isShowEditContactFragment {
ZStack {
}.onAppear {
if editContactViewModel.selectedEditFriend == nil {
delayColorDismiss()
} else {
if editContactViewModel.selectedEditFriend != nil {
dismiss()
}
editContactViewModel.removePopup = false
}
}
}
@ -558,8 +559,6 @@ struct EditContactFragment: View {
#Preview {
EditContactFragment(
editContactViewModel: EditContactViewModel(),
contactViewModel: ContactViewModel(),
isShowEditContactFragment: .constant(false),
isShowDismissPopup: .constant(false)
)

View file

@ -24,8 +24,7 @@ struct FavoriteContactsListFragment: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var favoriteContactsListViewModel: FavoriteContactsListViewModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var showingSheet: Bool
@ -57,7 +56,7 @@ struct FavoriteContactsListFragment: View {
}
}
.onLongPressGesture(minimumDuration: 0.2) {
contactViewModel.selectedFriend = contactsManager.lastSearch[index].friend
contactsListViewModel.selectedFriend = contactsManager.lastSearch[index].friend
showingSheet.toggle()
}
.frame(minWidth: 70, maxWidth: 70)
@ -72,7 +71,5 @@ struct FavoriteContactsListFragment: View {
#Preview {
FavoriteContactsListFragment(
contactViewModel: ContactViewModel(),
favoriteContactsListViewModel: FavoriteContactsListViewModel(),
showingSheet: .constant(false))
}

View file

@ -24,8 +24,8 @@ struct SipAddressesPopup: View {
@ObservedObject private var telecomManager = TelecomManager.shared
@ObservedObject var contactAvatarModel: ContactAvatarModel
@ObservedObject var contactViewModel: ContactViewModel
@EnvironmentObject var contactAvatarModel: ContactAvatarModel
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
@Binding var isShowSipAddressesPopup: Bool
@Binding var isShowSipAddressesPopupType: Int
@ -80,7 +80,7 @@ struct SipAddressesPopup: View {
} else {
withAnimation {
isShowSipAddressesPopup = false
contactViewModel.createOneToOneChatRoomWith(remote: address)
contactsListViewModel.createOneToOneChatRoomWith(remote: address)
isShowSipAddressesPopupType = 0
}
}
@ -104,8 +104,6 @@ struct SipAddressesPopup: View {
#Preview {
SipAddressesPopup(
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false),
contactViewModel: ContactViewModel(),
isShowSipAddressesPopup: .constant(true),
isShowSipAddressesPopupType: .constant(0)
)

View file

@ -1,215 +0,0 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import linphonesw
import Combine
import SwiftUI
// swiftlint:disable line_length
class ContactViewModel: ObservableObject {
@Published var selectedEditFriend: Friend?
var stringToCopy: String = ""
var selectedFriend: Friend?
var selectedFriendToShare: Friend?
var selectedFriendToDelete: Friend?
@Published var operationInProgress: Bool = false
@Published var displayedConversation: ConversationModel?
private var contactChatRoomDelegate: ChatRoomDelegate?
init() {}
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 {
self.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 {
self.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
self.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
self.operationInProgress = false
}
}
} catch {
Log.error("\(ConversationForwardMessageViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())")
DispatchQueue.main.async {
self.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
self.operationInProgress = false
}
}
} catch {
}
}
}
func chatRoomAddDelegate(core: Core, chatRoom: ChatRoom) {
contactChatRoomDelegate = 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.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.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.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
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!")
if let delegate = self.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
})
chatRoom.addDelegate(delegate: contactChatRoomDelegate!)
}
}
// swiftlint:enable line_length

View file

@ -18,9 +18,198 @@
*/
import linphonesw
import Combine
import SwiftUI
// swiftlint:disable line_length
class ContactsListViewModel: ObservableObject {
@Published var selectedEditFriend: Friend?
init() {}
var stringToCopy: String = ""
var selectedFriend: Friend?
var selectedFriendToShare: Friend?
var selectedFriendToDelete: Friend?
@Published var operationInProgress: Bool = false
@Published var displayedConversation: ConversationModel?
private var contactChatRoomDelegate: ChatRoomDelegate?
init() {}
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 {
self.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 {
self.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
self.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
self.operationInProgress = false
}
}
} catch {
Log.error("\(ConversationForwardMessageViewModel.TAG) Failed to create 1-1 conversation with \(remote.asStringUriOnly())")
DispatchQueue.main.async {
self.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
self.operationInProgress = false
}
}
} catch {
}
}
}
func chatRoomAddDelegate(core: Core, chatRoom: ChatRoom) {
contactChatRoomDelegate = 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.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.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.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
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!")
if let delegate = self.contactChatRoomDelegate {
chatRoom.removeDelegate(delegate: delegate)
self.contactChatRoomDelegate = nil
}
DispatchQueue.main.async {
self.operationInProgress = false
ToastViewModel.shared.toastMessage = "Failed_to_create_conversation_error"
ToastViewModel.shared.displayToast = true
}
}
})
chatRoom.addDelegate(delegate: contactChatRoomDelegate!)
}
}
// swiftlint:enable line_length

View file

@ -22,7 +22,7 @@ import SwiftUI
class EditContactViewModel: ObservableObject {
@Published var selectedEditFriend: Friend?
let selectedEditFriend: Friend?
@Published var identifier: String = ""
@Published var firstName: String = ""
@ -31,9 +31,9 @@ class EditContactViewModel: ObservableObject {
@Published var phoneNumbers: [String] = []
@Published var company: String = ""
@Published var jobTitle: String = ""
@Published var removePopup: Bool = false
init() {
init(friend: Friend? = nil) {
self.selectedEditFriend = friend
resetValues()
}

View file

@ -1,26 +0,0 @@
/*
* Copyright (c) 2010-2023 Belledonne Communications SARL.
*
* This file is part of linphone-iphone
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import linphonesw
import SwiftUI
class FavoriteContactsListViewModel: ObservableObject {
init() {}
}

View file

@ -31,26 +31,33 @@ struct ContentView: View {
@ObservedObject private var coreContext = CoreContext.shared
@ObservedObject private var telecomManager = TelecomManager.shared
@ObservedObject private var contactsManager = ContactsManager.shared
@ObservedObject private var magicSearch = MagicSearchSingleton.shared
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
@ObservedObject var contactsManager = ContactsManager.shared
var magicSearch = MagicSearchSingleton.shared
//@ObservedObject var editContactViewModel: EditContactViewModel
@State private var contactsListViewModel: ContactsListViewModel?
//@ObservedObject var historyViewModel: HistoryViewModel
//@ObservedObject var historyListViewModel: HistoryListViewModel
//@ObservedObject var startCallViewModel: StartCallViewModel
//@ObservedObject var startConversationViewModel: StartConversationViewModel
//@ObservedObject var callViewModel: CallViewModel
//@ObservedObject var meetingWaitingRoomViewModel: MeetingWaitingRoomViewModel
//@ObservedObject var conversationsListViewModel: ConversationsListViewModel
//@ObservedObject var conversationViewModel: ConversationViewModel
//@ObservedObject var meetingsListViewModel: MeetingsListViewModel
//@ObservedObject var meetingViewModel: MeetingViewModel
//@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
//@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@Binding var index: Int
//@Binding var index: Int
@State private var orientation = UIDevice.current.orientation
@State var sideMenuIsOpen: Bool = false
@ -62,6 +69,7 @@ struct ContentView: View {
@State var isShowDeleteContactPopup = false
@State var isShowDeleteAllHistoryPopup = false
@State var isShowEditContactFragment = false
@State var isShowEditContactFragmentInContactDetails = false
@State var isShowStartCallFragment = false
@State var isShowStartConversationFragment = false
@State var isShowDismissPopup = false
@ -142,19 +150,18 @@ struct ContentView: View {
Spacer()
Button(action: {
self.index = 0
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedConversation = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 0)
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedConversation = nil
sharedMainViewModel.displayedMeeting = nil
}, label: {
VStack {
Image("address-book")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 0 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 0 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 0 {
if sharedMainViewModel.indexView == 0 {
Text("bottom_navigation_contacts_label")
.default_text_style_700(styleSize: 10)
} else {
@ -189,11 +196,10 @@ struct ContentView: View {
}
*/
Button(action: {
self.index = 1
SharedMainViewModel.shared.changeIndexView(indexViewInt: 1)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedConversation = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 1)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedConversation = nil
sharedMainViewModel.displayedMeeting = nil
/*
if historyListViewModel.missedCallsCount > 0 {
historyListViewModel.resetMissedCallsCount()
@ -204,9 +210,9 @@ struct ContentView: View {
Image("phone")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 1 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 1 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 1 {
if sharedMainViewModel.indexView == 1 {
Text("bottom_navigation_calls_label")
.default_text_style_700(styleSize: 10)
} else {
@ -242,20 +248,19 @@ struct ContentView: View {
}
*/
Button(action: {
self.index = 2
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 2)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedMeeting = nil
}, label: {
VStack {
Image("chat-teardrop-text")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 2 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 2 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 2 {
if sharedMainViewModel.indexView == 2 {
Text("bottom_navigation_conversations_label")
.default_text_style_700(styleSize: 10)
} else {
@ -269,19 +274,18 @@ struct ContentView: View {
.frame(height: geometry.size.height/4)
Button(action: {
self.index = 3
SharedMainViewModel.shared.changeIndexView(indexViewInt: 3)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedConversation = nil
sharedMainViewModel.changeIndexView(indexViewInt: 3)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedConversation = nil
}, label: {
VStack {
Image("video-conference")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 3 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 3 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 0 {
if sharedMainViewModel.indexView == 0 {
Text("bottom_navigation_meetings_label")
.default_text_style_700(styleSize: 10)
} else {
@ -329,7 +333,7 @@ struct ContentView: View {
HStack {
/*
if let accountModelIndex = accountProfileViewModel.accountModelIndex,
accountModelIndex < CoreContext.shared.accounts.count {
accountModelIndex < coreContext.accounts.count {
AsyncImage(url: imagePath) { image in
switch image {
case .empty:
@ -345,16 +349,16 @@ struct ContentView: View {
imageTmp = image
}
case .failure:
if CoreContext.shared.accounts[accountModelIndex].avatarModel != nil {
if coreContext.accounts[accountModelIndex].avatarModel != nil {
let tmpImage = contactsManager.textToImage(
firstName: CoreContext.shared.accounts[accountModelIndex].avatarModel!.name,
firstName: coreContext.accounts[accountModelIndex].avatarModel!.name,
lastName: "")
Image(uiImage: tmpImage)
.resizable()
.frame(width: avatarSize, height: avatarSize)
.clipShape(Circle())
.onAppear {
accountProfileViewModel.saveImage(image: tmpImage, name: CoreContext.shared.accounts[accountModelIndex].avatarModel!.name, prefix: "-default")
accountProfileViewModel.saveImage(image: tmpImage, name: coreContext.accounts[accountModelIndex].avatarModel!.name, prefix: "-default")
}
} else if let cachedImage = imageTmp {
cachedImage
@ -374,30 +378,30 @@ struct ContentView: View {
openMenu()
}
.onAppear {
let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath()
let imagePathTmp = coreContext.accounts[accountModelIndex].getImagePath()
if !(imagePathTmp.lastPathComponent.isEmpty || imagePathTmp.lastPathComponent == "Error" || imagePathTmp.lastPathComponent == "ImageError.png") {
imagePath = imagePathTmp
}
}
.onChange(of: CoreContext.shared.accounts[accountModelIndex].usernaneAvatar) { username in
.onChange(of: coreContext.accounts[accountModelIndex].usernaneAvatar) { username in
if !username.isEmpty {
let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath()
let imagePathTmp = coreContext.accounts[accountModelIndex].getImagePath()
if !(imagePathTmp.lastPathComponent.isEmpty || imagePathTmp.lastPathComponent == "Error" || imagePathTmp.lastPathComponent == "ImageError.png") {
SharedMainViewModel.shared.changeDefaultAvatar(defaultAvatarURL: imagePathTmp)
sharedMainViewModel.changeDefaultAvatar(defaultAvatarURL: imagePathTmp)
imagePath = imagePathTmp
}
}
}
.onReceive(imageChanged) { _ in
if !CoreContext.shared.accounts[accountModelIndex].usernaneAvatar.isEmpty {
let imagePathTmp = CoreContext.shared.accounts[accountModelIndex].getImagePath()
SharedMainViewModel.shared.changeDefaultAvatar(defaultAvatarURL: imagePathTmp)
if !coreContext.accounts[accountModelIndex].usernaneAvatar.isEmpty {
let imagePathTmp = coreContext.accounts[accountModelIndex].getImagePath()
sharedMainViewModel.changeDefaultAvatar(defaultAvatarURL: imagePathTmp)
imagePath = imagePathTmp
}
}
}
*/
Text(String(localized: index == 0 ? "bottom_navigation_contacts_label" : (index == 1 ? "bottom_navigation_calls_label" : (index == 2 ? "bottom_navigation_conversations_label" : "bottom_navigation_meetings_label"))))
Text(String(localized: sharedMainViewModel.indexView == 0 ? "bottom_navigation_contacts_label" : (sharedMainViewModel.indexView == 1 ? "bottom_navigation_calls_label" : (sharedMainViewModel.indexView == 2 ? "bottom_navigation_conversations_label" : "bottom_navigation_meetings_label"))))
.default_text_style_white_800(styleSize: 20)
.padding(.leading, 10)
@ -415,9 +419,9 @@ struct ContentView: View {
.frame(width: 25, height: 25, alignment: .leading)
.padding(.all, 10)
}
.padding(.trailing, index == 2 ? 10 : 0)
.padding(.trailing, sharedMainViewModel.indexView == 2 ? 10 : 0)
if index == 3 {
if sharedMainViewModel.indexView == 3 {
Button {
NotificationCenter.default.post(name: MeetingsListViewModel.ScrollToTodayNotification, object: nil)
} label: {
@ -429,14 +433,14 @@ struct ContentView: View {
.padding(.all, 10)
}
.padding(.trailing, 10)
} else if index != 2 {
} else if sharedMainViewModel.indexView != 2 {
Menu {
if index == 0 {
if sharedMainViewModel.indexView == 0 {
Button {
SharedMainViewModel.shared.indexDisplayedFriend = nil
sharedMainViewModel.indexDisplayedFriend = nil
isMenuOpen = false
magicSearch.allContact = true
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
} label: {
HStack {
@ -452,10 +456,10 @@ struct ContentView: View {
}
Button {
SharedMainViewModel.shared.indexDisplayedFriend = nil
sharedMainViewModel.indexDisplayedFriend = nil
isMenuOpen = false
magicSearch.allContact = false
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
} label: {
HStack {
@ -485,7 +489,7 @@ struct ContentView: View {
}
}
} label: {
Image(index == 0 ? "funnel" : "dots-three-vertical")
Image(sharedMainViewModel.indexView == 0 ? "funnel" : "dots-three-vertical")
.renderingMode(.template)
.resizable()
.foregroundStyle(.white)
@ -515,15 +519,15 @@ struct ContentView: View {
text = ""
if index == 0 {
if sharedMainViewModel.indexView == 0 {
magicSearch.currentFilter = ""
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
} else if index == 1 {
} else if sharedMainViewModel.indexView == 1 {
//historyListViewModel.resetFilterCallLogs()
} else if index == 2 {
} else if sharedMainViewModel.indexView == 2 {
//conversationsListViewModel.resetFilterConversations()
} else if index == 3 {
} else if sharedMainViewModel.indexView == 3 {
//meetingsListViewModel.currentFilter = ""
//meetingsListViewModel.computeMeetingsList()
}
@ -561,23 +565,23 @@ struct ContentView: View {
self.focusedField = true
}
.onChange(of: text) { newValue in
if index == 0 {
if sharedMainViewModel.indexView == 0 {
magicSearch.currentFilter = newValue
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
} else if index == 1 {
} else if sharedMainViewModel.indexView == 1 {
if text.isEmpty {
//historyListViewModel.resetFilterCallLogs()
} else {
//historyListViewModel.filterCallLogs(filter: text)
}
} else if index == 2 {
} else if sharedMainViewModel.indexView == 2 {
if text.isEmpty {
//conversationsListViewModel.resetFilterConversations()
} else {
//conversationsListViewModel.filterConversations(filter: text)
}
} else if index == 3 {
} else if sharedMainViewModel.indexView == 3 {
//meetingsListViewModel.currentFilter = text
//meetingsListViewModel.computeMeetingsList()
}
@ -604,15 +608,15 @@ struct ContentView: View {
self.focusedField = true
}
.onChange(of: text) { newValue in
if index == 0 {
if sharedMainViewModel.indexView == 0 {
magicSearch.currentFilter = newValue
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
} else if index == 1 {
} else if sharedMainViewModel.indexView == 1 {
//historyListViewModel.filterCallLogs(filter: text)
} else if index == 2 {
} else if sharedMainViewModel.indexView == 2 {
//conversationsListViewModel.filterConversations(filter: text)
} else if index == 3 {
} else if sharedMainViewModel.indexView == 3 {
//meetingsListViewModel.currentFilter = text
//meetingsListViewModel.computeMeetingsList()
}
@ -639,26 +643,39 @@ struct ContentView: View {
.roundedCorner(10, corners: [.bottomRight, .bottomLeft])
}
if self.index == 0 {
ContactsView(
//contactViewModel: contactViewModel,
//historyViewModel: historyViewModel,
//editContactViewModel: editContactViewModel,
isShowEditContactFragment: $isShowEditContactFragment,
isShowDeletePopup: $isShowDeleteContactPopup,
text: $text
)
.environmentObject(ContactViewModel())
.roundedCorner(25, corners: [.topRight, .topLeft])
.shadow(
color: (orientation == .landscapeLeft
|| orientation == .landscapeRight
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height)
? .white.opacity(0.0)
: .black.opacity(0.2),
radius: 25
)
} else if self.index == 1 {
if sharedMainViewModel.indexView == 0 {
if let contactsListVM = contactsListViewModel {
ContactsView(
isShowEditContactFragment: $isShowEditContactFragment,
isShowDeletePopup: $isShowDeleteContactPopup,
text: $text
)
.environmentObject(contactsListVM)
.roundedCorner(25, corners: [.topRight, .topLeft])
.shadow(
color: (orientation == .landscapeLeft
|| orientation == .landscapeRight
|| UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height)
? .white.opacity(0.0)
: .black.opacity(0.2),
radius: 25
)
} else {
NavigationView {
VStack {
Spacer()
ProgressView()
.controlSize(.large)
Spacer()
}
.onAppear {
contactsListViewModel = ContactsListViewModel()
}
}
}
} else if sharedMainViewModel.indexView == 1 {
//TODO a changer
NavigationView {
ZStack(alignment: .bottomTrailing) {
@ -669,7 +686,7 @@ struct ContentView: View {
HistoryView(
historyListViewModel: historyListViewModel,
historyViewModel: historyViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
index: $index,
isShowStartCallFragment: $isShowStartCallFragment,
@ -686,7 +703,7 @@ struct ContentView: View {
radius: 25
)
*/
} else if self.index == 2 {
} else if sharedMainViewModel.indexView == 2 {
//TODO a changer
NavigationView {
ZStack(alignment: .bottomTrailing) {
@ -710,7 +727,7 @@ struct ContentView: View {
radius: 25
)
*/
} else if self.index == 3 {
} else if sharedMainViewModel.indexView == 3 {
//TODO a changer
NavigationView {
ZStack(alignment: .bottomTrailing) {
@ -766,19 +783,18 @@ struct ContentView: View {
Group {
Spacer()
Button(action: {
self.index = 0
SharedMainViewModel.shared.changeIndexView(indexViewInt: 0)
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedConversation = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 0)
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedConversation = nil
sharedMainViewModel.displayedMeeting = nil
}, label: {
VStack {
Image("address-book")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 0 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 0 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 0 {
if sharedMainViewModel.indexView == 0 {
Text("bottom_navigation_contacts_label")
.default_text_style_700(styleSize: 10)
} else {
@ -815,11 +831,10 @@ struct ContentView: View {
}
*/
Button(action: {
self.index = 1
SharedMainViewModel.shared.changeIndexView(indexViewInt: 1)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedConversation = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 1)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedConversation = nil
sharedMainViewModel.displayedMeeting = nil
/*
if historyListViewModel.missedCallsCount > 0 {
historyListViewModel.resetMissedCallsCount()
@ -830,9 +845,9 @@ struct ContentView: View {
Image("phone")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 1 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 1 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 1 {
if sharedMainViewModel.indexView == 1 {
Text("bottom_navigation_calls_label")
.default_text_style_700(styleSize: 9)
} else {
@ -870,20 +885,19 @@ struct ContentView: View {
}
*/
Button(action: {
self.index = 2
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.changeIndexView(indexViewInt: 2)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedMeeting = nil
}, label: {
VStack {
Image("chat-teardrop-text")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 2 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 2 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 2 {
if sharedMainViewModel.indexView == 2 {
Text("bottom_navigation_conversations_label")
.default_text_style_700(styleSize: 9)
} else {
@ -898,19 +912,18 @@ struct ContentView: View {
Spacer()
Button(action: {
self.index = 3
SharedMainViewModel.shared.changeIndexView(indexViewInt: 3)
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedCall = nil
SharedMainViewModel.shared.displayedConversation = nil
sharedMainViewModel.changeIndexView(indexViewInt: 3)
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.displayedConversation = nil
}, label: {
VStack {
Image("video-conference")
.renderingMode(.template)
.resizable()
.foregroundStyle(self.index == 3 ? Color.orangeMain500 : Color.grayMain2c600)
.foregroundStyle(sharedMainViewModel.indexView == 3 ? Color.orangeMain500 : Color.grayMain2c600)
.frame(width: 25, height: 25)
if self.index == 3 {
if sharedMainViewModel.indexView == 3 {
Text("bottom_navigation_meetings_label")
.default_text_style_700(styleSize: 9)
} else {
@ -934,8 +947,8 @@ struct ContentView: View {
}
}
if SharedMainViewModel.shared.indexDisplayedFriend != nil || SharedMainViewModel.shared.displayedCall != nil || SharedMainViewModel.shared.displayedConversation != nil ||
SharedMainViewModel.shared.displayedMeeting != nil {
if sharedMainViewModel.indexDisplayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil ||
sharedMainViewModel.displayedMeeting != nil {
HStack(spacing: 0) {
Spacer()
.frame(maxWidth:
@ -945,29 +958,27 @@ struct ContentView: View {
? (geometry.size.width/100*40) + 75
: 0
)
if self.index == 0 {
if sharedMainViewModel.indexView == 0 && sharedMainViewModel.indexDisplayedFriend != nil && contactsManager.avatarListModel.count > sharedMainViewModel.indexDisplayedFriend! {
ContactFragment(
isShowDeletePopup: $isShowDeleteContactPopup,
isShowDismissPopup: $isShowDismissPopup,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType,
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
)
.environmentObject(contactsListViewModel!)
.environmentObject(contactsManager.avatarListModel[sharedMainViewModel.indexDisplayedFriend!])
.frame(maxWidth: .infinity)
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
} else if sharedMainViewModel.indexView == 1 {
/*
ContactFragment(
contactViewModel: contactViewModel,
editContactViewModel: editContactViewModel,
conversationViewModel: conversationViewModel,
isShowDeletePopup: $isShowDeleteContactPopup,
isShowDismissPopup: $isShowDismissPopup,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType
)
.frame(maxWidth: .infinity)
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
*/
} else if self.index == 1 {
/*
if SharedMainViewModel.shared.displayedCall != nil && SharedMainViewModel.shared.displayedCall!.avatarModel != nil {
if sharedMainViewModel.displayedCall != nil && sharedMainViewModel.displayedCall!.avatarModel != nil {
HistoryContactFragment(
contactAvatarModel: SharedMainViewModel.shared.displayedCall!.avatarModel!,
contactAvatarModel: sharedMainViewModel.displayedCall!.avatarModel!,
historyViewModel: historyViewModel,
historyListViewModel: historyListViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
isShowDeleteAllHistoryPopup: $isShowDeleteAllHistoryPopup,
isShowEditContactFragment: $isShowEditContactFragment,
@ -978,13 +989,13 @@ struct ContentView: View {
.ignoresSafeArea(.keyboard)
}
*/
} else if self.index == 2 {
} else if sharedMainViewModel.indexView == 2 {
/*
ConversationFragment(
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
conversationForwardMessageViewModel: conversationForwardMessageViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,
@ -998,7 +1009,7 @@ struct ContentView: View {
.background(Color.gray100)
.ignoresSafeArea(.keyboard)
*/
} else if self.index == 3 {
} else if sharedMainViewModel.indexView == 3 {
/*
MeetingFragment(meetingViewModel: meetingViewModel, meetingsListViewModel: meetingsListViewModel, isShowScheduleMeetingFragment: $isShowScheduleMeetingFragment, isShowSendCancelMeetingNotificationPopup: $isShowSendCancelMeetingNotificationPopup)
.frame(maxWidth: .infinity)
@ -1061,21 +1072,21 @@ struct ContentView: View {
.onAppear {
}
}
*/
if isShowEditContactFragment {
EditContactFragment(
editContactViewModel: editContactViewModel,
contactViewModel: contactViewModel,
isShowEditContactFragment: $isShowEditContactFragment,
isShowDismissPopup: $isShowDismissPopup
)
.zIndex(3)
.transition(.opacity.combined(with: .move(edge: .bottom)))
.onAppear {
SharedMainViewModel.shared.indexDisplayedFriend = nil
sharedMainViewModel.indexDisplayedFriend = nil
}
}
/*
if isShowStartCallFragment {
if #available(iOS 16.4, *), idiom != .pad {
StartCallFragment(
@ -1129,13 +1140,14 @@ struct ContentView: View {
.zIndex(6)
.transition(.opacity.combined(with: .move(edge: .bottom)))
}
*/
if isShowDeleteContactPopup {
PopupView(isShowPopup: $isShowDeleteContactPopup,
title: Text(String(format: String(localized: "contact_dialog_delete_title"),contactViewModel.selectedFriend != nil
? contactViewModel.selectedFriend!.name!
: (SharedMainViewModel.shared.indexDisplayedFriend != nil
? contactsManager.lastSearch[SharedMainViewModel.shared.indexDisplayedFriend!].friend!.name!
title: Text(String(format: String(localized: "contact_dialog_delete_title"),contactsListViewModel!.selectedFriend != nil
? contactsListViewModel!.selectedFriend!.name!
: (sharedMainViewModel.indexDisplayedFriend != nil
? contactsManager.lastSearch[sharedMainViewModel.indexDisplayedFriend!].friend!.name!
: "Error Name"))),
content: Text("contact_dialog_delete_message"),
titleFirstButton: Text("dialog_cancel"),
@ -1143,21 +1155,21 @@ struct ContentView: View {
self.isShowDeleteContactPopup.toggle()},
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
if contactViewModel.selectedFriendToDelete != nil {
if SharedMainViewModel.shared.indexDisplayedFriend != nil {
if contactsListViewModel!.selectedFriendToDelete != nil {
if sharedMainViewModel.indexDisplayedFriend != nil {
withAnimation {
SharedMainViewModel.shared.indexDisplayedFriend = nil
sharedMainViewModel.indexDisplayedFriend = nil
}
}
contactViewModel.selectedFriendToDelete!.remove()
} else if SharedMainViewModel.shared.indexDisplayedFriend != nil {
let tmpIndex = SharedMainViewModel.shared.indexDisplayedFriend
contactsListViewModel!.selectedFriendToDelete!.remove()
} else if sharedMainViewModel.indexDisplayedFriend != nil {
let tmpIndex = sharedMainViewModel.indexDisplayedFriend
withAnimation {
SharedMainViewModel.shared.indexDisplayedFriend = nil
sharedMainViewModel.indexDisplayedFriend = nil
}
contactsManager.lastSearch[tmpIndex!].friend!.remove()
}
MagicSearchSingleton.shared.searchForContacts(
magicSearch.searchForContacts(
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
self.isShowDeleteContactPopup.toggle()
})
@ -1167,10 +1179,11 @@ struct ContentView: View {
self.isShowDeleteContactPopup.toggle()
}
.onAppear {
contactViewModel.selectedFriendToDelete = contactViewModel.selectedFriend
contactsListViewModel!.selectedFriendToDelete = contactsListViewModel!.selectedFriend
}
}
/*
if isShowDeleteAllHistoryPopup {
PopupView(isShowPopup: $isShowDeleteContactPopup,
title: Text("history_dialog_delete_all_call_logs_title"),
@ -1184,7 +1197,7 @@ struct ContentView: View {
actionSecondButton: {
historyListViewModel.removeCallLogs()
self.isShowDeleteAllHistoryPopup.toggle()
SharedMainViewModel.shared.displayedCall = nil
sharedMainViewModel.displayedCall = nil
ToastViewModel.shared.toastMessage = "Success_remove_call_logs"
ToastViewModel.shared.displayToast.toggle()
@ -1195,6 +1208,7 @@ struct ContentView: View {
self.isShowDeleteAllHistoryPopup.toggle()
}
}
*/
if isShowDismissPopup {
PopupView(isShowPopup: $isShowDismissPopup,
@ -1204,19 +1218,11 @@ struct ContentView: View {
actionFirstButton: {self.isShowDismissPopup.toggle()},
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
if editContactViewModel.selectedEditFriend == nil {
self.isShowDismissPopup.toggle()
editContactViewModel.removePopup = true
editContactViewModel.resetValues()
withAnimation {
isShowEditContactFragment.toggle()
}
self.isShowDismissPopup.toggle()
if isShowEditContactFragment {
isShowEditContactFragment = false
} else {
self.isShowDismissPopup.toggle()
editContactViewModel.resetValues()
withAnimation {
editContactViewModel.removePopup = true
}
isShowEditContactFragmentInContactDetails = false
}
})
.background(.black.opacity(0.65))
@ -1228,11 +1234,11 @@ struct ContentView: View {
if isShowSipAddressesPopup {
SipAddressesPopup(
contactAvatarModel: ContactsManager.shared.avatarListModel[SharedMainViewModel.shared.indexDisplayedFriend != nil ? SharedMainViewModel.shared.indexDisplayedFriend! : 0],
contactViewModel: contactViewModel,
isShowSipAddressesPopup: $isShowSipAddressesPopup,
isShowSipAddressesPopupType: $isShowSipAddressesPopupType
)
.environmentObject(contactsListViewModel!)
.environmentObject(contactsManager.avatarListModel[sharedMainViewModel.indexDisplayedFriend != nil ? sharedMainViewModel.indexDisplayedFriend! : 0])
.background(.black.opacity(0.65))
.zIndex(3)
.onTapGesture {
@ -1240,21 +1246,21 @@ struct ContentView: View {
}
}
if contactViewModel.operationInProgress {
/*
if contactsListViewModel.operationInProgress {
PopupLoadingView()
.background(.black.opacity(0.65))
.zIndex(3)
.onDisappear {
if contactViewModel.displayedConversation != nil {
SharedMainViewModel.shared.indexDisplayedFriend = nil
SharedMainViewModel.shared.displayedCall = nil
index = 2
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
if contactsListViewModel.displayedConversation != nil {
sharedMainViewModel.indexDisplayedFriend = nil
sharedMainViewModel.displayedCall = nil
sharedMainViewModel.changeIndexView(indexViewInt: 2)
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
withAnimation {
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: contactViewModel.displayedConversation!)
self.conversationViewModel.changeDisplayedChatRoom(conversationModel: contactsListViewModel.displayedConversation!)
}
contactViewModel.displayedConversation = nil
contactsListViewModel.displayedConversation = nil
}
}
}
@ -1306,13 +1312,13 @@ struct ContentView: View {
content: Text("meeting_schedule_cancel_dialog_message"),
titleFirstButton: Text("dialog_cancel"),
actionFirstButton: {
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.displayedMeeting = nil
meetingsListViewModel.deleteSelectedMeeting()
self.isShowSendCancelMeetingNotificationPopup.toggle(
) },
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
SharedMainViewModel.shared.displayedMeeting = nil
sharedMainViewModel.displayedMeeting = nil
if let meetingToDelete = self.meetingsListViewModel.selectedMeetingToDelete {
self.meetingViewModel.cancelMeetingWithNotifications(meeting: meetingToDelete)
meetingsListViewModel.deleteSelectedMeeting()
@ -1337,8 +1343,8 @@ struct ContentView: View {
},
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
if SharedMainViewModel.shared.displayedConversation != nil {
SharedMainViewModel.shared.displayedConversation!.createGroupCall()
if sharedMainViewModel.displayedConversation != nil {
sharedMainViewModel.displayedConversation!.createGroupCall()
}
self.isShowStartCallGroupPopup.toggle()
}
@ -1361,8 +1367,8 @@ struct ContentView: View {
},
titleSecondButton: Text("dialog_ok"),
actionSecondButton: {
if SharedMainViewModel.shared.displayedConversation != nil {
SharedMainViewModel.shared.displayedConversation!.createGroupCall()
if sharedMainViewModel.displayedConversation != nil {
sharedMainViewModel.displayedConversation!.createGroupCall()
}
self.isShowStartCallGroupPopup.toggle()
}
@ -1398,7 +1404,7 @@ struct ContentView: View {
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
conversationForwardMessageViewModel: conversationForwardMessageViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,
@ -1432,8 +1438,7 @@ struct ContentView: View {
}
.onChange(of: navigationManager.selectedCallId) { newCallId in
if newCallId != nil {
self.index = 2
SharedMainViewModel.shared.changeIndexView(indexViewInt: 2)
sharedMainViewModel.changeIndexView(indexViewInt: 2)
}
}
.onReceive(contactLoaded) { _ in
@ -1458,13 +1463,11 @@ struct ContentView: View {
}
}
.onRotate { newOrientation in
/*
if (SharedMainViewModel.shared.indexDisplayedFriend != nil || SharedMainViewModel.shared.displayedCall != nil || SharedMainViewModel.shared.displayedConversation != nil) && searchIsActive {
if (sharedMainViewModel.indexDisplayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil) && searchIsActive {
self.focusedField = false
} else if searchIsActive {
self.focusedField = true
}
*/
orientation = newOrientation
}
.onChange(of: scenePhase) { newPhase in
@ -1496,8 +1499,6 @@ class NavigationManager: ObservableObject {
#Preview {
ContentView(
//contactViewModel: ContactViewModel(),
//editContactViewModel: EditContactViewModel(),
//historyViewModel: HistoryViewModel(),
//historyListViewModel: HistoryListViewModel(),
//startCallViewModel: StartCallViewModel(),
@ -1510,7 +1511,7 @@ class NavigationManager: ObservableObject {
//meetingViewModel: MeetingViewModel(),
//conversationForwardMessageViewModel: ConversationForwardMessageViewModel(),
//accountProfileViewModel: AccountProfileViewModel(),
index: .constant(0)
//index: .constant(0)
)
}
// swiftlint:enable type_body_length

View file

@ -164,8 +164,7 @@ struct ConversationForwardMessageFragment: View {
.padding(.horizontal, 16)
}
ContactsListFragment(contactViewModel: ContactViewModel(), contactsListViewModel: ContactsListViewModel(), showingSheet: .constant(false)
, startCallFunc: { addr in
ContactsListFragment(showingSheet: .constant(false), startCallFunc: { addr in
withAnimation {
conversationForwardMessageViewModel.createOneToOneChatRoomWith(remote: addr)
}

View file

@ -35,7 +35,7 @@ struct ConversationFragment: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var conversationForwardMessageViewModel: ConversationForwardMessageViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var meetingViewModel: MeetingViewModel
@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@ -1081,7 +1081,7 @@ struct ConversationFragment: View {
ConversationInfoFragment(
conversationViewModel: conversationViewModel,
conversationsListViewModel: conversationsListViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
meetingViewModel: meetingViewModel,
accountProfileViewModel: accountProfileViewModel,

View file

@ -27,7 +27,7 @@ struct ConversationInfoFragment: View {
@ObservedObject var conversationViewModel: ConversationViewModel
@ObservedObject var conversationsListViewModel: ConversationsListViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var meetingViewModel: MeetingViewModel
@ObservedObject var accountProfileViewModel: AccountProfileViewModel
@ -698,7 +698,7 @@ struct ConversationInfoFragment: View {
ConversationInfoFragment(
conversationViewModel: ConversationViewModel(),
conversationsListViewModel: ConversationsListViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
meetingViewModel: MeetingViewModel(),
accountProfileViewModel: AccountProfileViewModel(),

View file

@ -184,8 +184,7 @@ struct StartConversationFragment: View {
.padding(.horizontal, 16)
}
ContactsListFragment(contactViewModel: ContactViewModel(), contactsListViewModel: ContactsListViewModel(), showingSheet: .constant(false)
, startCallFunc: { addr in
ContactsListFragment(showingSheet: .constant(false), startCallFunc: { addr in
startConversationViewModel.createOneToOneChatRoomWith(remote: addr)
})
.padding(.horizontal, 16)

View file

@ -32,7 +32,7 @@ struct HistoryContactFragment: View {
@ObservedObject var contactAvatarModel: ContactAvatarModel
@ObservedObject var historyViewModel: HistoryViewModel
@ObservedObject var historyListViewModel: HistoryListViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@State var isMenuOpen = false
@ -286,7 +286,7 @@ struct HistoryContactFragment: View {
Spacer()
Button(action: {
contactViewModel.createOneToOneChatRoomWith(remote: SharedMainViewModel.shared.displayedCall!.addressLinphone)
contactsListViewModel.createOneToOneChatRoomWith(remote: SharedMainViewModel.shared.displayedCall!.addressLinphone)
}, label: {
VStack {
HStack(alignment: .center) {
@ -452,7 +452,7 @@ struct HistoryContactFragment: View {
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false),
historyViewModel: HistoryViewModel(),
historyListViewModel: HistoryListViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
isShowDeleteAllHistoryPopup: .constant(false),
isShowEditContactFragment: .constant(false),

View file

@ -24,7 +24,7 @@ struct HistoryFragment: View {
@ObservedObject var historyListViewModel: HistoryListViewModel
@ObservedObject var historyViewModel: HistoryViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@State private var showingSheet = false
@ -39,7 +39,7 @@ struct HistoryFragment: View {
.sheet(isPresented: $showingSheet) {
HistoryListBottomSheet(
historyViewModel: historyViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
historyListViewModel: historyListViewModel,
showingSheet: $showingSheet,
@ -53,7 +53,7 @@ struct HistoryFragment: View {
.halfSheet(showSheet: $showingSheet) {
HistoryListBottomSheet(
historyViewModel: historyViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
historyListViewModel: historyListViewModel,
showingSheet: $showingSheet,
@ -70,7 +70,7 @@ struct HistoryFragment: View {
HistoryFragment(
historyListViewModel: HistoryListViewModel(),
historyViewModel: HistoryViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
index: .constant(1),
isShowEditContactFragment: .constant(false),

View file

@ -29,7 +29,7 @@ struct HistoryListBottomSheet: View {
@ObservedObject var contactsManager = ContactsManager.shared
@ObservedObject var historyViewModel: HistoryViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@ObservedObject var historyListViewModel: HistoryListViewModel
@ -225,7 +225,7 @@ struct HistoryListBottomSheet: View {
#Preview {
HistoryListBottomSheet(
historyViewModel: HistoryViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
historyListViewModel: HistoryListViewModel(),
showingSheet: .constant(false),

View file

@ -216,7 +216,7 @@ struct StartCallFragment: View {
.padding(.horizontal, 16)
}
ContactsListFragment(contactViewModel: ContactViewModel(), contactsListViewModel: ContactsListViewModel(), showingSheet: .constant(false)
ContactsListFragment(showingSheet: .constant(false)
, startCallFunc: { addr in
if callViewModel.isTransferInsteadCall {
showingDialer = false

View file

@ -24,7 +24,7 @@ struct HistoryView: View {
@ObservedObject var historyListViewModel: HistoryListViewModel
@ObservedObject var historyViewModel: HistoryViewModel
@ObservedObject var contactViewModel: ContactViewModel
@ObservedObject var contactsListViewModel: ContactsListViewModel
@ObservedObject var editContactViewModel: EditContactViewModel
@Binding var index: Int
@ -38,7 +38,7 @@ struct HistoryView: View {
HistoryFragment(
historyListViewModel: historyListViewModel,
historyViewModel: historyViewModel,
contactViewModel: contactViewModel,
contactsListViewModel: contactsListViewModel,
editContactViewModel: editContactViewModel,
index: $index,
isShowEditContactFragment: $isShowEditContactFragment,
@ -74,7 +74,7 @@ struct HistoryView: View {
HistoryFragment(
historyListViewModel: HistoryListViewModel(),
historyViewModel: HistoryViewModel(),
contactViewModel: ContactViewModel(),
contactsListViewModel: ContactsListViewModel(),
editContactViewModel: EditContactViewModel(),
index: .constant(1),
isShowEditContactFragment: .constant(false),

View file

@ -83,7 +83,6 @@
D719ABCC2ABC769C00B41C10 /* AssistantView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABCB2ABC769C00B41C10 /* AssistantView.swift */; };
D719ABCF2ABC779A00B41C10 /* AccountLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */; };
D71A0E192B485ADF0002C6CD /* ViewExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71A0E182B485ADF0002C6CD /* ViewExtension.swift */; };
D71FCA7F2AE1397200D2E43E /* ContactsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71FCA7E2AE1397200D2E43E /* ContactsListViewModel.swift */; };
D71FCA812AE14CFC00D2E43E /* ContactsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71FCA802AE14CFC00D2E43E /* ContactsListFragment.swift */; };
D71FCA832AE14D6E00D2E43E /* ContactFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D71FCA822AE14D6E00D2E43E /* ContactFragment.swift */; };
D720E6AD2BAD822000DDFD87 /* ParticipantModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D720E6AC2BAD822000DDFD87 /* ParticipantModel.swift */; };
@ -131,7 +130,7 @@
D777DBB32AE12C5900565A99 /* ContactsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = D777DBB22AE12C5900565A99 /* ContactsManager.swift */; };
D77A080E2CB6BCAF0095D589 /* MessageConferenceInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D77A080D2CB6BCA10095D589 /* MessageConferenceInfo.swift */; };
D78290B82ADD3910004AA85C /* ContactsFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78290B72ADD3910004AA85C /* ContactsFragment.swift */; };
D78290BB2ADD40B2004AA85C /* ContactViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78290BA2ADD40B2004AA85C /* ContactViewModel.swift */; };
D78290BB2ADD40B2004AA85C /* ContactsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D78290BA2ADD40B2004AA85C /* ContactsListViewModel.swift */; };
D783028F2D414847009CCB60 /* DebugFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D783028E2D414845009CCB60 /* DebugFragment.swift */; };
D783C77C2B1089B200622CC2 /* assistant_linphone_default_values in Resources */ = {isa = PBXBuildFile; fileRef = D783C77A2B1089B200622CC2 /* assistant_linphone_default_values */; };
D783C77D2B1089B200622CC2 /* assistant_third_party_default_values in Resources */ = {isa = PBXBuildFile; fileRef = D783C77B2B1089B200622CC2 /* assistant_third_party_default_values */; };
@ -189,7 +188,6 @@
D7E6ADF32B9875C20009A2BC /* Message.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6ADF22B9875C20009A2BC /* Message.swift */; };
D7E6ADF52B9876ED0009A2BC /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6ADF42B9876ED0009A2BC /* Attachment.swift */; };
D7E6D0492AE933AD00A57AAF /* FavoriteContactsListFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D0482AE933AD00A57AAF /* FavoriteContactsListFragment.swift */; };
D7E6D04B2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D04A2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift */; };
D7E6D04D2AEBD77600A57AAF /* CustomBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D04C2AEBD77600A57AAF /* CustomBottomSheet.swift */; };
D7E6D0512AEBDBD500A57AAF /* ContactsListBottomSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D0502AEBDBD500A57AAF /* ContactsListBottomSheet.swift */; };
D7E6D0552AEBFCCE00A57AAF /* ContactsInnerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D7E6D0542AEBFCCE00A57AAF /* ContactsInnerFragment.swift */; };
@ -297,7 +295,6 @@
D719ABCB2ABC769C00B41C10 /* AssistantView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AssistantView.swift; sourceTree = "<group>"; };
D719ABCE2ABC779A00B41C10 /* AccountLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountLoginViewModel.swift; sourceTree = "<group>"; };
D71A0E182B485ADF0002C6CD /* ViewExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewExtension.swift; sourceTree = "<group>"; };
D71FCA7E2AE1397200D2E43E /* ContactsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsListViewModel.swift; sourceTree = "<group>"; };
D71FCA802AE14CFC00D2E43E /* ContactsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsListFragment.swift; sourceTree = "<group>"; };
D71FCA822AE14D6E00D2E43E /* ContactFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactFragment.swift; sourceTree = "<group>"; };
D720E6AC2BAD822000DDFD87 /* ParticipantModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ParticipantModel.swift; sourceTree = "<group>"; };
@ -345,7 +342,7 @@
D777DBB22AE12C5900565A99 /* ContactsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsManager.swift; sourceTree = "<group>"; };
D77A080D2CB6BCA10095D589 /* MessageConferenceInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MessageConferenceInfo.swift; sourceTree = "<group>"; };
D78290B72ADD3910004AA85C /* ContactsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsFragment.swift; sourceTree = "<group>"; };
D78290BA2ADD40B2004AA85C /* ContactViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactViewModel.swift; sourceTree = "<group>"; };
D78290BA2ADD40B2004AA85C /* ContactsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsListViewModel.swift; sourceTree = "<group>"; };
D783028E2D414845009CCB60 /* DebugFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DebugFragment.swift; sourceTree = "<group>"; };
D783C77A2B1089B200622CC2 /* assistant_linphone_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_linphone_default_values; sourceTree = "<group>"; };
D783C77B2B1089B200622CC2 /* assistant_third_party_default_values */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = assistant_third_party_default_values; sourceTree = "<group>"; };
@ -398,7 +395,6 @@
D7E6ADF22B9875C20009A2BC /* Message.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Message.swift; sourceTree = "<group>"; };
D7E6ADF42B9876ED0009A2BC /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
D7E6D0482AE933AD00A57AAF /* FavoriteContactsListFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteContactsListFragment.swift; sourceTree = "<group>"; };
D7E6D04A2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FavoriteContactsListViewModel.swift; sourceTree = "<group>"; };
D7E6D04C2AEBD77600A57AAF /* CustomBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomBottomSheet.swift; sourceTree = "<group>"; };
D7E6D0502AEBDBD500A57AAF /* ContactsListBottomSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsListBottomSheet.swift; sourceTree = "<group>"; };
D7E6D0542AEBFCCE00A57AAF /* ContactsInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsInnerFragment.swift; sourceTree = "<group>"; };
@ -832,9 +828,7 @@
D78290B92ADD409D004AA85C /* ViewModel */ = {
isa = PBXGroup;
children = (
D78290BA2ADD40B2004AA85C /* ContactViewModel.swift */,
D71FCA7E2AE1397200D2E43E /* ContactsListViewModel.swift */,
D7E6D04A2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift */,
D78290BA2ADD40B2004AA85C /* ContactsListViewModel.swift */,
D7C3650B2AF0084000FE6142 /* EditContactViewModel.swift */,
);
path = ViewModel;
@ -1217,7 +1211,7 @@
C67586B02C09F247002E77BF /* URIHandler.swift in Sources */,
C62817282C1B389700DBA646 /* SideMenuAccountRow.swift in Sources */,
C60E8F192C0F649200A06DB8 /* UIApplicationExtension.swift in Sources */,
D78290BB2ADD40B2004AA85C /* ContactViewModel.swift in Sources */,
D78290BB2ADD40B2004AA85C /* ContactsListViewModel.swift in Sources */,
D7E2E69F2CE356C90080DA0D /* PopupViewWithTextField.swift in Sources */,
C67586B52C09F617002E77BF /* SingleSignOnManager.swift in Sources */,
D7F4D9CB2B5FD27200CDCD76 /* CallsListFragment.swift in Sources */,
@ -1240,7 +1234,6 @@
D732A9152B04C7FE00DB42BA /* HistoryListViewModel.swift in Sources */,
6646A7A32BB2E224006B842A /* ScheduleMeetingFragment.swift in Sources */,
D7C500402D27F16C00DD53EC /* AccountSettingsFragment.swift in Sources */,
D71FCA7F2AE1397200D2E43E /* ContactsListViewModel.swift in Sources */,
D71FCA812AE14CFC00D2E43E /* ContactsListFragment.swift in Sources */,
D734499B2BC694C900778C56 /* MeetingWaitingRoomViewModel.swift in Sources */,
D719ABB72ABC67BF00B41C10 /* LinphoneApp.swift in Sources */,
@ -1325,7 +1318,6 @@
C62817342C1C7C7400DBA646 /* HelpView.swift in Sources */,
D78E062C2BEA69BC00CE3783 /* CallStatisticsSheetBottomSheet.swift in Sources */,
D7C365082AEFAB7F00FE6142 /* ContactListBottomSheet.swift in Sources */,
D7E6D04B2AE9347D00A57AAF /* FavoriteContactsListViewModel.swift in Sources */,
D74C9CFA2ACACF2D0021626A /* WelcomePage2Fragment.swift in Sources */,
D74C9CFF2ACAEC5E0021626A /* PopupView.swift in Sources */,
D7DA67622ACCB2FA00E95002 /* LoginFragment.swift in Sources */,