diff --git a/Linphone/GeneratedGit.swift b/Linphone/GeneratedGit.swift index bd85848ac..f3faa0096 100644 --- a/Linphone/GeneratedGit.swift +++ b/Linphone/GeneratedGit.swift @@ -1,7 +1,7 @@ import Foundation public enum AppGitInfo { - public static let branch = "master" - public static let commit = "cdde88e32" + public static let branch = "feature/contacts_and_suggestions_list" + public static let commit = "c3f95fe23" public static let tag = "6.1.0-alpha" } diff --git a/Linphone/UI/Main/ContentView.swift b/Linphone/UI/Main/ContentView.swift index da1e3c584..084f0ea07 100644 --- a/Linphone/UI/Main/ContentView.swift +++ b/Linphone/UI/Main/ContentView.swift @@ -48,6 +48,7 @@ struct ContentView: View { @State private var searchIsActive = false @State private var text = "" @FocusState private var focusedField: Bool + @State private var showingDialer = false @State var isMenuOpen = false @State var isShowDeleteContactPopup = false @@ -320,6 +321,8 @@ struct ContentView: View { Spacer() Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 0) sharedMainViewModel.displayedCall = nil sharedMainViewModel.displayedConversation = nil @@ -341,7 +344,8 @@ struct ContentView: View { } }) .padding(.top) - .frame(height: geometry.size.height/4) + + Spacer() ZStack { if SharedMainViewModel.shared.missedCallsCount > 0 { @@ -365,6 +369,8 @@ struct ContentView: View { } Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 1) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedConversation = nil @@ -390,7 +396,8 @@ struct ContentView: View { }) .padding(.top) } - .frame(height: geometry.size.height/4) + + Spacer() if !sharedMainViewModel.disableChatFeature { ZStack { @@ -415,6 +422,8 @@ struct ContentView: View { } Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 2) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil @@ -438,11 +447,14 @@ struct ContentView: View { }) .padding(.top) } - .frame(height: geometry.size.height/4) + + Spacer() } if !sharedMainViewModel.disableMeetingFeature { Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 3) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil @@ -464,13 +476,13 @@ struct ContentView: View { } }) .padding(.top) - .frame(height: geometry.size.height/4) Spacer() } } } .frame(width: 75, height: geometry.size.height) + .padding(.bottom, geometry.safeAreaInsets.bottom) .padding(.leading, orientation == .landscapeRight && geometry.safeAreaInsets.bottom > 0 ? -geometry.safeAreaInsets.leading @@ -690,10 +702,12 @@ struct ContentView: View { text = "" - if sharedMainViewModel.indexView == 0 { + if sharedMainViewModel.indexView != 3 { magicSearch.currentFilter = "" magicSearch.searchForContacts() - } else if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { + } + + if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { historyListVM.resetFilterCallLogs() } else if let conversationsListVM = conversationsListViewModel, sharedMainViewModel.indexView == 2 { conversationsListVM.resetFilterConversations() @@ -735,10 +749,12 @@ struct ContentView: View { self.focusedField = true } .onChange(of: text) { newValue in - if sharedMainViewModel.indexView == 0 { + if sharedMainViewModel.indexView != 3 { magicSearch.currentFilter = newValue magicSearch.searchForContacts() - } else if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { + } + + if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { if text.isEmpty { historyListVM.resetFilterCallLogs() } else { @@ -755,6 +771,34 @@ struct ContentView: View { meetingsListVM.computeMeetingsList() } } + .onChange(of: isShowStartCallFragment) { isShowStartCallFragmentNewValue in + if isShowStartCallFragmentNewValue == false && !text.isEmpty { + if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { + magicSearch.currentFilter = text + magicSearch.searchForContacts() + + if text.isEmpty { + historyListVM.resetFilterCallLogs() + } else { + historyListVM.filterCallLogs(filter: text) + } + } + } + } + .onChange(of: isShowStartConversationFragment) { isShowStartConversationFragmentNewValue in + if isShowStartConversationFragmentNewValue == false && !text.isEmpty { + if let conversationsListVM = conversationsListViewModel, sharedMainViewModel.indexView == 2 { + magicSearch.currentFilter = text + magicSearch.searchForContacts() + + if text.isEmpty { + conversationsListVM.resetFilterConversations() + } else { + conversationsListVM.filterConversations(filter: text) + } + } + } + } } else { TextEditor(text: Binding( get: { @@ -777,18 +821,56 @@ struct ContentView: View { self.focusedField = true } .onChange(of: text) { newValue in - if sharedMainViewModel.indexView == 0 { + if sharedMainViewModel.indexView != 3 { magicSearch.currentFilter = newValue magicSearch.searchForContacts() - } else if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { - historyListVM.filterCallLogs(filter: text) + } + + if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { + if text.isEmpty { + historyListVM.resetFilterCallLogs() + } else { + historyListVM.filterCallLogs(filter: text) + } } else if let conversationsListVM = conversationsListViewModel, sharedMainViewModel.indexView == 2 { - conversationsListVM.filterConversations(filter: text) + if text.isEmpty { + conversationsListVM.resetFilterConversations() + } else { + conversationsListVM.filterConversations(filter: text) + } } else if let meetingsListVM = meetingsListViewModel, sharedMainViewModel.indexView == 3 { meetingsListVM.currentFilter = text meetingsListVM.computeMeetingsList() } } + .onChange(of: isShowStartCallFragment) { isShowStartCallFragmentNewValue in + if isShowStartCallFragmentNewValue == false && !text.isEmpty { + if let historyListVM = historyListViewModel, sharedMainViewModel.indexView == 1 { + magicSearch.currentFilter = text + magicSearch.searchForContacts() + + if text.isEmpty { + historyListVM.resetFilterCallLogs() + } else { + historyListVM.filterCallLogs(filter: text) + } + } + } + } + .onChange(of: isShowStartConversationFragment) { isShowStartConversationFragmentNewValue in + if isShowStartConversationFragmentNewValue == false && !text.isEmpty { + if let conversationsListVM = conversationsListViewModel, sharedMainViewModel.indexView == 2 { + magicSearch.currentFilter = text + magicSearch.searchForContacts() + + if text.isEmpty { + conversationsListVM.resetFilterConversations() + } else { + conversationsListVM.filterConversations(filter: text) + } + } + } + } } Button { @@ -874,6 +956,8 @@ struct ContentView: View { Group { Spacer() Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 0) sharedMainViewModel.displayedCall = nil sharedMainViewModel.displayedConversation = nil @@ -921,6 +1005,8 @@ struct ContentView: View { } Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 1) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedConversation = nil @@ -973,6 +1059,8 @@ struct ContentView: View { } Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 2) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil @@ -1002,6 +1090,8 @@ struct ContentView: View { if !sharedMainViewModel.disableMeetingFeature { Spacer() Button(action: { + resetFilter() + sharedMainViewModel.changeIndexView(indexViewInt: 3) sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil @@ -1299,13 +1389,17 @@ struct ContentView: View { if sharedMainViewModel.operationInProgress { PopupLoadingView() + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(.bottom, UIDevice.current.userInterfaceIdiom == .pad && (orientation == .landscapeLeft || orientation == .landscapeRight || UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) ? geometry.safeAreaInsets.bottom : 0) .background(.black.opacity(0.65)) .zIndex(3) .onDisappear { if let contactsListVM = contactsListViewModel, let displayedConversation = contactsListVM.displayedConversation { if !sharedMainViewModel.disableChatFeature { - sharedMainViewModel.displayedFriend = nil + resetFilter() + + sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil sharedMainViewModel.changeIndexView(indexViewInt: 2) @@ -1330,6 +1424,8 @@ struct ContentView: View { } else if let historyListVM = historyListViewModel, let displayedConversation = historyListVM.displayedConversation { if !sharedMainViewModel.disableChatFeature { + resetFilter() + sharedMainViewModel.displayedFriend = nil sharedMainViewModel.displayedCall = nil sharedMainViewModel.changeIndexView(indexViewInt: 2) @@ -1352,6 +1448,15 @@ struct ContentView: View { } } } + } else if let conversationsListVM = conversationsListViewModel { + conversationsListVM.currentFilter = "" + + self.resetFilter() + + if let displayedConversation = conversationsListVM.displayedConversation { + conversationsListVM.changeDisplayedChatRoom(conversationModel: displayedConversation) + conversationsListVM.displayedConversation = nil + } } } } @@ -1404,7 +1509,7 @@ struct ContentView: View { .transition(.move(edge: .trailing)) } - if let meetingsListVM = meetingsListViewModel, isShowSendCancelMeetingNotificationPopup { + if let meetingsListVM = meetingsListViewModel, isShowSendCancelMeetingNotificationPopup { PopupView( isShowPopup: $isShowSendCancelMeetingNotificationPopup, title: Text("meeting_schedule_cancel_dialog_title"), @@ -1668,6 +1773,7 @@ struct ContentView: View { .onChange(of: navigationManager.selectedCallId) { newCallId in if newCallId != nil { if !sharedMainViewModel.disableChatFeature { + resetFilter() sharedMainViewModel.changeIndexView(indexViewInt: 2) } } @@ -1760,6 +1866,17 @@ struct ContentView: View { self.sideMenuIsOpen.toggle() } } + + func resetFilter() { + self.text = "" + self.focusedField = false + self.searchIsActive = false + + if !magicSearch.currentFilter.isEmpty { + magicSearch.currentFilter = "" + magicSearch.searchForContacts() + } + } } struct ContactsContainer: View { diff --git a/Linphone/UI/Main/Conversations/ConversationsView.swift b/Linphone/UI/Main/Conversations/ConversationsView.swift index 965fee5e8..524ad898d 100644 --- a/Linphone/UI/Main/Conversations/ConversationsView.swift +++ b/Linphone/UI/Main/Conversations/ConversationsView.swift @@ -55,7 +55,7 @@ struct ConversationsView: View { #Preview { ConversationsListFragment( - showingSheet: .constant(false), - text: .constant("") + text: .constant(""), + showingSheet: .constant(false) ) } diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationsFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationsFragment.swift index a35d04df3..869cf5df1 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationsFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationsFragment.swift @@ -25,13 +25,14 @@ struct ConversationsFragment: View { private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } - @State var showingSheet: Bool = false @Binding var text: String + @State var showingSheet: Bool = false + var body: some View { ZStack { if #available(iOS 16.0, *), idiom != .pad { - ConversationsListFragment(showingSheet: $showingSheet, text: $text) + ConversationsListFragment(text: $text, showingSheet: $showingSheet) .sheet(isPresented: $showingSheet) { ConversationsListBottomSheet( showingSheet: $showingSheet @@ -43,7 +44,7 @@ struct ConversationsFragment: View { ) } } else { - ConversationsListFragment(showingSheet: $showingSheet, text: $text) + ConversationsListFragment(text: $text, showingSheet: $showingSheet) .halfSheet(showSheet: $showingSheet) { ConversationsListBottomSheet( showingSheet: $showingSheet diff --git a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift index cd98e28d5..c4d81606f 100644 --- a/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift +++ b/Linphone/UI/Main/Conversations/Fragments/ConversationsListFragment.swift @@ -26,10 +26,12 @@ struct ConversationsListFragment: View { @EnvironmentObject var navigationManager: NavigationManager + @ObservedObject var contactsManager = ContactsManager.shared + @EnvironmentObject var conversationsListViewModel: ConversationsListViewModel - @Binding var showingSheet: Bool @Binding var text: String + @Binding var showingSheet: Bool var body: some View { VStack { @@ -42,6 +44,34 @@ struct ConversationsListFragment: View { text: $text ) } + + if !conversationsListViewModel.currentFilter.isEmpty { + if !contactsManager.lastSearch.isEmpty { + HStack(alignment: .center) { + Text("contacts_list_all_contacts_title") + .default_text_style_800(styleSize: 16) + + Spacer() + } + } + + ContactsListFragment(showingSheet: .constant(false), startCallFunc: { addr in + withAnimation { + conversationsListViewModel.createOneToOneChatRoomWith(remote: addr) + } + }) + + if !contactsManager.lastSearchSuggestions.isEmpty { + HStack(alignment: .center) { + Text("generic_address_picker_suggestions_list_title") + .default_text_style_800(styleSize: 16) + + Spacer() + } + + suggestionsList + } + } } .safeAreaInset(edge: .top, content: { Spacer() @@ -50,7 +80,13 @@ struct ConversationsListFragment: View { .listStyle(.plain) .overlay( VStack { - if conversationsListViewModel.conversationsList.isEmpty { + if conversationsListViewModel.conversationsList.isEmpty && + ( + conversationsListViewModel.currentFilter.isEmpty || + (!conversationsListViewModel.currentFilter.isEmpty && + contactsManager.lastSearch.isEmpty && + contactsManager.lastSearchSuggestions.isEmpty) + ) { Spacer() Image("illus-belledonne") .resizable() @@ -65,6 +101,11 @@ struct ConversationsListFragment: View { } .padding(.all) ) + .onDisappear { + if !conversationsListViewModel.currentFilter.isEmpty { + conversationsListViewModel.resetFilterConversations() + } + } } .navigationTitle("") .navigationBarHidden(true) @@ -77,6 +118,69 @@ struct ConversationsListFragment: View { } } } + + var suggestionsList: some View { + ForEach(0..