mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Fix presence
This commit is contained in:
parent
07b2c1e04e
commit
7b476904cb
24 changed files with 445 additions and 280 deletions
|
|
@ -27,6 +27,7 @@
|
|||
D72343322ACEFF58009AA24E /* QRScannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343312ACEFF58009AA24E /* QRScannerController.swift */; };
|
||||
D72343342ACEFFC3009AA24E /* QRScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343332ACEFFC3009AA24E /* QRScanner.swift */; };
|
||||
D72343362AD037AF009AA24E /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343352AD037AF009AA24E /* ToastView.swift */; };
|
||||
D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D726E4382B16440C0083C415 /* ContactAvatarModel.swift */; };
|
||||
D72992392ADD7F68003AF125 /* HistoryContactFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */; };
|
||||
D732A9092AFD235500DB42BA /* ShareSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D732A9082AFD235500DB42BA /* ShareSheetController.swift */; };
|
||||
D732A90C2B0376F500DB42BA /* linphonerc-default in Resources */ = {isa = PBXBuildFile; fileRef = D732A90A2B0376F500DB42BA /* linphonerc-default */; };
|
||||
|
|
@ -104,6 +105,7 @@
|
|||
D72343312ACEFF58009AA24E /* QRScannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerController.swift; sourceTree = "<group>"; };
|
||||
D72343332ACEFFC3009AA24E /* QRScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScanner.swift; sourceTree = "<group>"; };
|
||||
D72343352AD037AF009AA24E /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = "<group>"; };
|
||||
D726E4382B16440C0083C415 /* ContactAvatarModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactAvatarModel.swift; sourceTree = "<group>"; };
|
||||
D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryContactFragment.swift; sourceTree = "<group>"; };
|
||||
D732A9082AFD235500DB42BA /* ShareSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheetController.swift; sourceTree = "<group>"; };
|
||||
D732A90A2B0376F500DB42BA /* linphonerc-default */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "linphonerc-default"; sourceTree = "<group>"; };
|
||||
|
|
@ -297,6 +299,14 @@
|
|||
path = ViewModel;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D726E4372B1643FF0083C415 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D726E4382B16440C0083C415 /* ContactAvatarModel.swift */,
|
||||
);
|
||||
path = Model;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D72992372ADD7F1C003AF125 /* Fragments */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
|
|
@ -380,6 +390,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D78290B62ADD38F9004AA85C /* Fragments */,
|
||||
D726E4372B1643FF0083C415 /* Model */,
|
||||
D78290B92ADD409D004AA85C /* ViewModel */,
|
||||
D7A03FBC2ACC2DB60081A588 /* ContactsView.swift */,
|
||||
);
|
||||
|
|
@ -578,6 +589,7 @@
|
|||
D719ABB72ABC67BF00B41C10 /* LinphoneApp.swift in Sources */,
|
||||
D732A91B2B061BD900DB42BA /* HistoryListBottomSheet.swift in Sources */,
|
||||
D72250632ADE9615008FB426 /* HistoryViewModel.swift in Sources */,
|
||||
D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */,
|
||||
D76005F62B0798B00054B79A /* IntExtension.swift in Sources */,
|
||||
D7E6D0512AEBDBD500A57AAF /* ContactsListBottomSheet.swift in Sources */,
|
||||
D7A2EDD62AC18115005D90FC /* SharedMainViewModel.swift in Sources */,
|
||||
|
|
|
|||
|
|
@ -22,12 +22,11 @@ import Contacts
|
|||
import SwiftUI
|
||||
import ContactsUI
|
||||
|
||||
final class ContactsManager {
|
||||
final class ContactsManager: ObservableObject {
|
||||
|
||||
static let shared = ContactsManager()
|
||||
|
||||
private var coreContext = CoreContext.shared
|
||||
private var magicSearch = MagicSearchSingleton.shared
|
||||
|
||||
private let nativeAddressBookFriendList = "Native address-book"
|
||||
let linphoneAddressBookFriendList = "Linphone address-book"
|
||||
|
|
@ -35,6 +34,9 @@ final class ContactsManager {
|
|||
var friendList: FriendList?
|
||||
var linphoneFriendList: FriendList?
|
||||
|
||||
@Published var lastSearch: [SearchResult] = []
|
||||
@Published var avatarListModel: [ContactAvatarModel] = []
|
||||
|
||||
private init() {
|
||||
fetchContacts()
|
||||
}
|
||||
|
|
@ -132,7 +134,8 @@ final class ContactsManager {
|
|||
print("\(#function) - access denied")
|
||||
}
|
||||
}
|
||||
self.magicSearch.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -247,9 +247,6 @@
|
|||
},
|
||||
"En continuant, vous acceptez ces conditions, " : {
|
||||
|
||||
},
|
||||
"En ligne" : {
|
||||
|
||||
},
|
||||
"Error" : {
|
||||
|
||||
|
|
|
|||
|
|
@ -34,9 +34,11 @@ struct ContactFragment: View {
|
|||
@State private var showShareSheet = false
|
||||
|
||||
var body: some View {
|
||||
let indexDisplayed = contactViewModel.indexDisplayedFriend != nil ? contactViewModel.indexDisplayedFriend! : 0
|
||||
if #available(iOS 16.0, *) {
|
||||
if idiom != .pad {
|
||||
ContactInnerFragment(
|
||||
contactAvatarModel: ContactsManager.shared.avatarListModel[indexDisplayed],
|
||||
contactViewModel: contactViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
cnContact: CNContact(),
|
||||
|
|
@ -50,12 +52,13 @@ struct ContactFragment: View {
|
|||
.presentationDetents([.fraction(0.2)])
|
||||
}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
.presentationDetents([.medium])
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
} else {
|
||||
ContactInnerFragment(
|
||||
contactAvatarModel: ContactsManager.shared.avatarListModel[indexDisplayed],
|
||||
contactViewModel: contactViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
cnContact: CNContact(),
|
||||
|
|
@ -68,12 +71,13 @@ struct ContactFragment: View {
|
|||
ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet)
|
||||
} onDismiss: {}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ContactInnerFragment(
|
||||
contactAvatarModel: ContactsManager.shared.avatarListModel[indexDisplayed],
|
||||
contactViewModel: contactViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
cnContact: CNContact(),
|
||||
|
|
@ -86,7 +90,7 @@ struct ContactFragment: View {
|
|||
ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet)
|
||||
} onDismiss: {}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,8 @@ import SwiftUI
|
|||
|
||||
struct ContactInnerActionsFragment: View {
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
|
||||
|
|
@ -59,8 +60,8 @@ struct ContactInnerActionsFragment: View {
|
|||
|
||||
if informationIsOpen {
|
||||
VStack(spacing: 0) {
|
||||
if contactViewModel.indexDisplayedFriend != nil && magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
ForEach(0..<magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses.count, id: \.self) { index in
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
ForEach(0..<contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses.count, id: \.self) { index in
|
||||
Button {
|
||||
} label: {
|
||||
HStack {
|
||||
|
|
@ -68,7 +69,7 @@ struct ContactInnerActionsFragment: View {
|
|||
Text("SIP address :")
|
||||
.default_text_style_700(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
Text(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index].asStringUriOnly().dropFirst(4))
|
||||
Text(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index].asStringUriOnly().dropFirst(4))
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
|
@ -93,7 +94,7 @@ struct ContactInnerActionsFragment: View {
|
|||
.simultaneousGesture(
|
||||
LongPressGesture()
|
||||
.onEnded { _ in
|
||||
contactViewModel.stringToCopy = magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index].asStringUriOnly()
|
||||
contactViewModel.stringToCopy = contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses[index].asStringUriOnly()
|
||||
showingSheet.toggle()
|
||||
}
|
||||
)
|
||||
|
|
@ -106,8 +107,8 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
)
|
||||
|
||||
if !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.isEmpty
|
||||
|| index < magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses.count - 1 {
|
||||
if !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.isEmpty
|
||||
|| index < contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.addresses.count - 1 {
|
||||
VStack {
|
||||
Divider()
|
||||
}
|
||||
|
|
@ -115,14 +116,14 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
}
|
||||
|
||||
ForEach(0..<magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.count, id: \.self) { index in
|
||||
ForEach(0..<contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.count, id: \.self) { index in
|
||||
Button {
|
||||
} label: {
|
||||
HStack {
|
||||
VStack {
|
||||
if magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label!.isEmpty {
|
||||
Text("Phone (\(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label!)) :")
|
||||
if contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label!.isEmpty {
|
||||
Text("Phone (\(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].label!)) :")
|
||||
.default_text_style_700(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
} else {
|
||||
|
|
@ -130,7 +131,7 @@ struct ContactInnerActionsFragment: View {
|
|||
.default_text_style_700(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
Text(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].phoneNumber)
|
||||
Text(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].phoneNumber)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
|
@ -156,7 +157,7 @@ struct ContactInnerActionsFragment: View {
|
|||
LongPressGesture()
|
||||
.onEnded { _ in
|
||||
contactViewModel.stringToCopy =
|
||||
magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].phoneNumber
|
||||
contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbersWithLabel[index].phoneNumber
|
||||
showingSheet.toggle()
|
||||
}
|
||||
)
|
||||
|
|
@ -169,7 +170,7 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
)
|
||||
|
||||
if index < magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.count - 1 {
|
||||
if index < contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.phoneNumbers.count - 1 {
|
||||
VStack {
|
||||
Divider()
|
||||
}
|
||||
|
|
@ -186,28 +187,28 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
|
||||
if contactViewModel.indexDisplayedFriend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& ((magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty)
|
||||
|| (magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!.isEmpty)) {
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& ((contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty)
|
||||
|| (contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!.isEmpty)) {
|
||||
VStack {
|
||||
if magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty {
|
||||
Text("**Company :** \(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!)")
|
||||
if contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty {
|
||||
Text("**Company :** \(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!)")
|
||||
.default_text_style(styleSize: 14)
|
||||
.padding(.vertical, 15)
|
||||
.padding(.horizontal, 20)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
if magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!.isEmpty {
|
||||
Text("**Job :** \(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!)")
|
||||
if contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!.isEmpty {
|
||||
Text("**Job :** \(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.jobTitle!)")
|
||||
.default_text_style(styleSize: 14)
|
||||
.padding(.top,
|
||||
magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty
|
||||
contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.organization!.isEmpty
|
||||
? 0 : 15
|
||||
)
|
||||
.padding(.bottom, 15)
|
||||
|
|
@ -238,10 +239,10 @@ struct ContactInnerActionsFragment: View {
|
|||
.background(Color.gray100)
|
||||
|
||||
VStack(spacing: 0) {
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < magicSearch.lastSearch.count
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!.isEmpty {
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < contactsManager.lastSearch.count
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!.isEmpty {
|
||||
Button {
|
||||
actionEditButton()
|
||||
} label: {
|
||||
|
|
@ -265,6 +266,7 @@ struct ContactInnerActionsFragment: View {
|
|||
} else {
|
||||
NavigationLink(destination: EditContactFragment(
|
||||
editContactViewModel: editContactViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
isShowEditContactFragment: .constant(false),
|
||||
isShowDismissPopup: $isShowDismissPopup)) {
|
||||
HStack {
|
||||
|
|
@ -286,7 +288,7 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
.simultaneousGesture(
|
||||
TapGesture().onEnded {
|
||||
editContactViewModel.selectedEditFriend = magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend
|
||||
editContactViewModel.selectedEditFriend = contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend
|
||||
editContactViewModel.resetValues()
|
||||
}
|
||||
)
|
||||
|
|
@ -298,22 +300,22 @@ struct ContactInnerActionsFragment: View {
|
|||
.padding(.horizontal)
|
||||
|
||||
Button {
|
||||
if magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
if contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
contactViewModel.objectWillChange.send()
|
||||
magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred.toggle()
|
||||
contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred.toggle()
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
Image(contactViewModel.indexDisplayedFriend != nil && magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true ? "heart-fill" : "heart")
|
||||
Image(contactViewModel.indexDisplayedFriend != nil && contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true ? "heart-fill" : "heart")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(contactViewModel.indexDisplayedFriend != nil && magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true ? Color.redDanger500 : Color.grayMain2c500)
|
||||
.foregroundStyle(contactViewModel.indexDisplayedFriend != nil && contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true ? Color.redDanger500 : Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25)
|
||||
Text(contactViewModel.indexDisplayedFriend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.starred == true
|
||||
? "Remove from favourites"
|
||||
: "Add to favourites")
|
||||
.default_text_style(styleSize: 14)
|
||||
|
|
@ -410,7 +412,7 @@ struct ContactInnerActionsFragment: View {
|
|||
*/
|
||||
|
||||
Button {
|
||||
if magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
if contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
isShowDeletePopup.toggle()
|
||||
}
|
||||
} label: {
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@ import ContactsUI
|
|||
struct ContactInnerFragment: View {
|
||||
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
|
||||
|
|
@ -65,10 +65,10 @@ struct ContactInnerFragment: View {
|
|||
}
|
||||
|
||||
Spacer()
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < magicSearch.lastSearch.count
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!.isEmpty {
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < contactsManager.lastSearch.count
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!.isEmpty {
|
||||
Button(action: {
|
||||
editNativeContact()
|
||||
}, label: {
|
||||
|
|
@ -82,6 +82,7 @@ struct ContactInnerFragment: View {
|
|||
} else {
|
||||
NavigationLink(destination: EditContactFragment(
|
||||
editContactViewModel: editContactViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
isShowEditContactFragment: .constant(false),
|
||||
isShowDismissPopup: $isShowDismissPopup)) {
|
||||
Image("pencil-simple")
|
||||
|
|
@ -93,7 +94,7 @@ struct ContactInnerFragment: View {
|
|||
}
|
||||
.simultaneousGesture(
|
||||
TapGesture().onEnded {
|
||||
editContactViewModel.selectedEditFriend = magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend
|
||||
editContactViewModel.selectedEditFriend = contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend
|
||||
editContactViewModel.resetValues()
|
||||
}
|
||||
)
|
||||
|
|
@ -109,29 +110,31 @@ struct ContactInnerFragment: View {
|
|||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < magicSearch.lastSearch.count
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo != nil
|
||||
&& !magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo!.isEmpty {
|
||||
Avatar(friend: magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!, avatarSize: 100)
|
||||
} else if contactViewModel.indexDisplayedFriend != nil && magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
if contactViewModel.indexDisplayedFriend != nil && contactViewModel.indexDisplayedFriend! < contactsManager.lastSearch.count
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo != nil
|
||||
&& !contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100)
|
||||
} else if contactViewModel.indexDisplayedFriend != nil && contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
if contactViewModel.indexDisplayedFriend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend?.name != nil {
|
||||
Text((magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend?.name)!)
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend != nil
|
||||
&& contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend?.name != nil {
|
||||
Text((contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend?.name)!)
|
||||
.foregroundStyle(Color.grayMain2c700)
|
||||
.multilineTextAlignment(.center)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity)
|
||||
.padding(.top, 10)
|
||||
|
||||
Text("En ligne")
|
||||
.foregroundStyle(Color.greenSuccess500)
|
||||
Text(contactAvatarModel.lastPresenceInfo)
|
||||
.foregroundStyle(contactAvatarModel.lastPresenceInfo == "Online"
|
||||
? Color.greenSuccess500
|
||||
: Color.orangeWarning600)
|
||||
.multilineTextAlignment(.center)
|
||||
.default_text_style_300(styleSize: 12)
|
||||
.frame(maxWidth: .infinity)
|
||||
|
|
@ -268,7 +271,7 @@ struct ContactInnerFragment: View {
|
|||
let store = CNContactStore()
|
||||
let descriptor = CNContactViewController.descriptorForRequiredKeys()
|
||||
cnContact = try store.unifiedContact(
|
||||
withIdentifier: magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!,
|
||||
withIdentifier: contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.nativeUri!,
|
||||
keysToFetch: [descriptor]
|
||||
)
|
||||
|
||||
|
|
@ -283,6 +286,7 @@ struct ContactInnerFragment: View {
|
|||
|
||||
#Preview {
|
||||
ContactInnerFragment(
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, withPresence: true),
|
||||
contactViewModel: ContactViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
isShowDeletePopup: .constant(false),
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ struct ContactListBottomSheet: View {
|
|||
|
||||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
|
|
|||
|
|
@ -20,8 +20,10 @@
|
|||
import SwiftUI
|
||||
import linphonesw
|
||||
|
||||
struct ContactsInnerFragment: View {
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
struct ContactsInnerFragment: View {
|
||||
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
||||
@State private var isFavoriteOpen = true
|
||||
|
|
@ -30,7 +32,7 @@ struct ContactsInnerFragment: View {
|
|||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
if !magicSearch.lastSearch.filter({ $0.friend?.starred == true }).isEmpty {
|
||||
if !contactsManager.lastSearch.filter({ $0.friend?.starred == true }).isEmpty {
|
||||
HStack(alignment: .center) {
|
||||
Text("Favourites")
|
||||
.default_text_style_800(styleSize: 16)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@ struct ContactsListBottomSheet: View {
|
|||
|
||||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
||||
@State private var orientation = UIDevice.current.orientation
|
||||
|
|
@ -61,7 +60,8 @@ struct ContactsListBottomSheet: View {
|
|||
if contactViewModel.selectedFriend != nil {
|
||||
contactViewModel.selectedFriend!.starred.toggle()
|
||||
}
|
||||
self.magicSearch.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
if idiom != .pad {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import linphonesw
|
|||
|
||||
struct ContactsListFragment: View {
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
@ObservedObject var contactsListViewModel: ContactsListViewModel
|
||||
|
|
@ -32,22 +32,22 @@ struct ContactsListFragment: View {
|
|||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
ForEach(0..<magicSearch.lastSearch.count, id: \.self) { index in
|
||||
ForEach(0..<contactsManager.lastSearch.count, id: \.self) { index in
|
||||
Button {
|
||||
} label: {
|
||||
HStack {
|
||||
if index == 0
|
||||
|| magicSearch.lastSearch[index].friend?.name!.lowercased().folding(
|
||||
|| contactsManager.lastSearch[index].friend?.name!.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first
|
||||
!= magicSearch.lastSearch[index-1].friend?.name!.lowercased().folding(
|
||||
!= contactsManager.lastSearch[index-1].friend?.name!.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first {
|
||||
Text(
|
||||
String(
|
||||
(magicSearch.lastSearch[index].friend?.name!.uppercased().folding(
|
||||
(contactsManager.lastSearch[index].friend?.name!.uppercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first)!))
|
||||
|
|
@ -63,15 +63,17 @@ struct ContactsListFragment: View {
|
|||
.padding(.trailing, 10)
|
||||
}
|
||||
|
||||
if magicSearch.lastSearch[index].friend!.photo != nil && !magicSearch.lastSearch[index].friend!.photo!.isEmpty {
|
||||
Avatar(friend: magicSearch.lastSearch[index].friend!, avatarSize: 45)
|
||||
if index < contactsManager.avatarListModel.count
|
||||
&& contactsManager.avatarListModel[index].friend!.photo != nil
|
||||
&& !contactsManager.avatarListModel[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 45)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text((magicSearch.lastSearch[index].friend?.name)!)
|
||||
Text((contactsManager.lastSearch[index].friend?.name)!)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundStyle(Color.orangeMain500)
|
||||
|
|
@ -80,7 +82,7 @@ struct ContactsListFragment: View {
|
|||
.simultaneousGesture(
|
||||
LongPressGesture()
|
||||
.onEnded { _ in
|
||||
contactViewModel.selectedFriend = magicSearch.lastSearch[index].friend
|
||||
contactViewModel.selectedFriend = contactsManager.lastSearch[index].friend
|
||||
showingSheet.toggle()
|
||||
}
|
||||
)
|
||||
|
|
@ -99,7 +101,7 @@ struct ContactsListFragment: View {
|
|||
.listStyle(.plain)
|
||||
.overlay(
|
||||
VStack {
|
||||
if magicSearch.lastSearch.isEmpty {
|
||||
if contactsManager.lastSearch.isEmpty {
|
||||
Spacer()
|
||||
Image("illus-belledonne")
|
||||
.resizable()
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ struct EditContactFragment: View {
|
|||
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
var contactViewModel: ContactViewModel
|
||||
|
||||
@Binding var isShowEditContactFragment: Bool
|
||||
@Binding var isShowDismissPopup: Bool
|
||||
|
||||
|
|
@ -129,7 +131,9 @@ struct EditContactFragment: View {
|
|||
if editContactViewModel.selectedEditFriend != nil
|
||||
&& editContactViewModel.selectedEditFriend!.photo != nil
|
||||
&& !editContactViewModel.selectedEditFriend!.photo!.isEmpty && selectedImage == nil && !removedImage {
|
||||
Avatar(friend: editContactViewModel.selectedEditFriend!, avatarSize: 100)
|
||||
|
||||
Avatar(contactAvatarModel: ContactAvatarModel(friend: editContactViewModel.selectedEditFriend!, withPresence: false), avatarSize: 100)
|
||||
|
||||
} else if selectedImage == nil {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
|
|
@ -475,7 +479,7 @@ struct EditContactFragment: View {
|
|||
)
|
||||
|
||||
if editContactViewModel.selectedEditFriend != nil && selectedImage == nil &&
|
||||
!removedImage {
|
||||
!removedImage && editContactViewModel.selectedEditFriend!.photo!.suffix(11) != "default.png" {
|
||||
ContactsManager.shared.saveFriend(
|
||||
result: String(editContactViewModel.selectedEditFriend!.photo!.dropFirst(6)),
|
||||
contact: newContact,
|
||||
|
|
@ -486,7 +490,7 @@ struct EditContactFragment: View {
|
|||
image: selectedImage
|
||||
?? ContactsManager.shared.textToImage(
|
||||
firstName: editContactViewModel.firstName, lastName: editContactViewModel.lastName),
|
||||
name: editContactViewModel.firstName
|
||||
name: editContactViewModel.firstName
|
||||
+ editContactViewModel.lastName
|
||||
+ String(Int.random(in: 1...1000))
|
||||
+ ((selectedImage == nil) ? "-default" : ""),
|
||||
|
|
@ -495,6 +499,16 @@ struct EditContactFragment: View {
|
|||
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
||||
if editContactViewModel.selectedEditFriend != nil && editContactViewModel.selectedEditFriend!.name != editContactViewModel.firstName + " " + editContactViewModel.lastName {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
let result = ContactsManager.shared.lastSearch.firstIndex(where: {
|
||||
$0.friend!.name == newContact.firstName + " " + newContact.lastName
|
||||
})
|
||||
print("getFriendIndexWithFriendgetFriendIndexWithFriend \(newContact.firstName) \(newContact.lastName) \(result)")
|
||||
contactViewModel.indexDisplayedFriend = result
|
||||
}
|
||||
}
|
||||
|
||||
delayColorDismiss()
|
||||
if editContactViewModel.selectedEditFriend == nil {
|
||||
withAnimation {
|
||||
|
|
@ -508,5 +522,10 @@ struct EditContactFragment: View {
|
|||
}
|
||||
|
||||
#Preview {
|
||||
EditContactFragment(editContactViewModel: EditContactViewModel(), isShowEditContactFragment: .constant(false), isShowDismissPopup: .constant(false))
|
||||
EditContactFragment(
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
contactViewModel: ContactViewModel(),
|
||||
isShowEditContactFragment: .constant(false),
|
||||
isShowDismissPopup: .constant(false)
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ import SwiftUI
|
|||
import linphonesw
|
||||
|
||||
struct FavoriteContactsListFragment: View {
|
||||
|
||||
@ObservedObject var magicSearch = MagicSearchSingleton.shared
|
||||
|
||||
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
@ObservedObject var favoriteContactsListViewModel: FavoriteContactsListViewModel
|
||||
|
||||
|
|
@ -32,21 +32,21 @@ struct FavoriteContactsListFragment: View {
|
|||
var body: some View {
|
||||
ScrollView(.horizontal) {
|
||||
HStack {
|
||||
ForEach(0..<magicSearch.lastSearch.count, id: \.self) { index in
|
||||
if magicSearch.lastSearch[index].friend != nil && magicSearch.lastSearch[index].friend!.starred == true {
|
||||
ForEach(0..<contactsManager.lastSearch.count, id: \.self) { index in
|
||||
if contactsManager.lastSearch[index].friend != nil && contactsManager.lastSearch[index].friend!.starred == true {
|
||||
Button {
|
||||
} label: {
|
||||
VStack {
|
||||
if magicSearch.lastSearch[index].friend!.photo != nil
|
||||
&& !magicSearch.lastSearch[index].friend!.photo!.isEmpty {
|
||||
Avatar(friend: magicSearch.lastSearch[index].friend!, avatarSize: 45)
|
||||
if contactsManager.lastSearch[index].friend!.photo != nil
|
||||
&& !contactsManager.lastSearch[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 45)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text((magicSearch.lastSearch[index].friend?.name)!)
|
||||
Text((contactsManager.lastSearch[index].friend?.name)!)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame( maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ struct FavoriteContactsListFragment: View {
|
|||
.simultaneousGesture(
|
||||
LongPressGesture()
|
||||
.onEnded { _ in
|
||||
contactViewModel.selectedFriend = magicSearch.lastSearch[index].friend
|
||||
contactViewModel.selectedFriend = contactsManager.lastSearch[index].friend
|
||||
showingSheet.toggle()
|
||||
}
|
||||
)
|
||||
|
|
|
|||
121
Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift
Normal file
121
Linphone/UI/Main/Contacts/Model/ContactAvatarModel.swift
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of Linphone
|
||||
*
|
||||
* 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 Foundation
|
||||
import linphonesw
|
||||
|
||||
class ContactAvatarModel: ObservableObject {
|
||||
|
||||
let friend: Friend?
|
||||
|
||||
let withPresence: Bool?
|
||||
|
||||
@Published var lastPresenceInfo: String
|
||||
|
||||
@Published var presenceStatus: ConsolidatedPresence
|
||||
|
||||
private var friendDelegate: FriendDelegate?
|
||||
|
||||
init(friend: Friend?, withPresence: Bool?) {
|
||||
self.friend = friend
|
||||
self.withPresence = withPresence
|
||||
if friend != nil &&
|
||||
withPresence == true {
|
||||
self.lastPresenceInfo = ""
|
||||
|
||||
self.presenceStatus = friend!.consolidatedPresence
|
||||
|
||||
if friend!.consolidatedPresence == .Online || friend!.consolidatedPresence == .Busy {
|
||||
if friend!.consolidatedPresence == .Online || friend!.presenceModel!.latestActivityTimestamp != -1 {
|
||||
self.lastPresenceInfo = friend!.consolidatedPresence == .Online ? "Online" : getCallTime(startDate: friend!.presenceModel!.latestActivityTimestamp)
|
||||
} else {
|
||||
self.lastPresenceInfo = "Away"
|
||||
}
|
||||
} else {
|
||||
self.lastPresenceInfo = ""
|
||||
}
|
||||
|
||||
if self.friendDelegate != nil {
|
||||
self.friend!.removeDelegate(delegate: self.friendDelegate!)
|
||||
self.friendDelegate = nil
|
||||
}
|
||||
|
||||
addDelegate()
|
||||
} else {
|
||||
self.lastPresenceInfo = ""
|
||||
self.presenceStatus = .Offline
|
||||
}
|
||||
}
|
||||
|
||||
func addDelegate() {
|
||||
let newFriendDelegate = FriendDelegateStub(
|
||||
onPresenceReceived: { (linphoneFriend: Friend) -> Void in
|
||||
DispatchQueue.main.sync {
|
||||
self.presenceStatus = linphoneFriend.consolidatedPresence
|
||||
if linphoneFriend.consolidatedPresence == .Online || linphoneFriend.consolidatedPresence == .Busy {
|
||||
if linphoneFriend.consolidatedPresence == .Online || linphoneFriend.presenceModel!.latestActivityTimestamp != -1 {
|
||||
self.lastPresenceInfo = linphoneFriend.consolidatedPresence == .Online ? "Online" : self.getCallTime(startDate: linphoneFriend.presenceModel!.latestActivityTimestamp)
|
||||
} else {
|
||||
self.lastPresenceInfo = "Away"
|
||||
}
|
||||
} else {
|
||||
self.lastPresenceInfo = ""
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
friendDelegate = newFriendDelegate
|
||||
if friendDelegate != nil {
|
||||
friend!.addDelegate(delegate: friendDelegate!)
|
||||
}
|
||||
}
|
||||
|
||||
func removeAllDelegate() {
|
||||
if friendDelegate != nil {
|
||||
presenceStatus = .Offline
|
||||
friend!.removeDelegate(delegate: friendDelegate!)
|
||||
friendDelegate = nil
|
||||
}
|
||||
}
|
||||
|
||||
func getCallTime(startDate: time_t) -> String {
|
||||
let timeInterval = TimeInterval(startDate)
|
||||
|
||||
let myNSDate = Date(timeIntervalSince1970: timeInterval)
|
||||
|
||||
if Calendar.current.isDateInToday(myNSDate) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a"
|
||||
return "Online today at " + formatter.string(from: myNSDate)
|
||||
} else if Calendar.current.isDateInYesterday(myNSDate) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "HH:mm" : "h:mm a"
|
||||
return "Online yesterday at " + formatter.string(from: myNSDate)
|
||||
} else if Calendar.current.isDate(myNSDate, equalTo: .now, toGranularity: .year) {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "dd/MM | HH:mm" : "MM/dd | h:mm a"
|
||||
return "Online on " + formatter.string(from: myNSDate)
|
||||
} else {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = Locale.current.identifier == "fr_FR" ? "dd/MM/yy | HH:mm" : "MM/dd/yy | h:mm a"
|
||||
return "Online on " + formatter.string(from: myNSDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -29,9 +29,5 @@ class ContactViewModel: ObservableObject {
|
|||
var selectedFriendToShare: Friend?
|
||||
var selectedFriendToDelete: Friend?
|
||||
|
||||
private var magicSearch = MagicSearchSingleton.shared
|
||||
|
||||
init() {
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)}
|
||||
init() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,6 @@
|
|||
import linphonesw
|
||||
|
||||
class ContactsListViewModel: ObservableObject {
|
||||
|
||||
|
||||
init() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ struct ContentView: View {
|
|||
@ObservedObject private var coreContext = CoreContext.shared
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
var contactManager = ContactsManager.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
var magicSearch = MagicSearchSingleton.shared
|
||||
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
|
@ -146,7 +146,7 @@ struct ContentView: View {
|
|||
Button {
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = true
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
|
|
@ -163,7 +163,7 @@ struct ContentView: View {
|
|||
Button {
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = false
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} label: {
|
||||
HStack {
|
||||
|
|
@ -219,7 +219,7 @@ struct ContentView: View {
|
|||
|
||||
if index == 0 {
|
||||
magicSearch.currentFilter = ""
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else {
|
||||
historyListViewModel.resetFilterCallLogs()
|
||||
|
|
@ -256,7 +256,7 @@ struct ContentView: View {
|
|||
.onChange(of: text) { newValue in
|
||||
if index == 0 {
|
||||
magicSearch.currentFilter = newValue
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else {
|
||||
historyListViewModel.filterCallLogs(filter: text)
|
||||
|
|
@ -284,7 +284,7 @@ struct ContentView: View {
|
|||
}
|
||||
.onChange(of: text) { newValue in
|
||||
magicSearch.currentFilter = newValue
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
}
|
||||
}
|
||||
|
|
@ -428,7 +428,20 @@ struct ContentView: View {
|
|||
.background(Color.gray100)
|
||||
.ignoresSafeArea(.keyboard)
|
||||
} else if self.index == 1 {
|
||||
let fromAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil
|
||||
let toAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil
|
||||
let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? fromAddressFriend : toAddressFriend) : nil
|
||||
|
||||
let contactAvatarModel = addressFriend != nil
|
||||
? ContactsManager.shared.avatarListModel.first(where: {
|
||||
($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy)
|
||||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, withPresence: false)
|
||||
|
||||
HistoryContactFragment(
|
||||
contactAvatarModel: contactAvatarModel!,
|
||||
historyViewModel: historyViewModel,
|
||||
historyListViewModel: historyListViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
|
|
@ -478,6 +491,7 @@ struct ContentView: View {
|
|||
if isShowEditContactFragment {
|
||||
EditContactFragment(
|
||||
editContactViewModel: editContactViewModel,
|
||||
contactViewModel: contactViewModel,
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
isShowDismissPopup: $isShowDismissPopup
|
||||
)
|
||||
|
|
@ -494,7 +508,7 @@ struct ContentView: View {
|
|||
contactViewModel.selectedFriend != nil
|
||||
? "Delete \(contactViewModel.selectedFriend!.name!)?"
|
||||
: (contactViewModel.indexDisplayedFriend != nil
|
||||
? "Delete \(magicSearch.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.name!)?"
|
||||
? "Delete \(contactsManager.lastSearch[contactViewModel.indexDisplayedFriend!].friend!.name!)?"
|
||||
: "Error Name")),
|
||||
content: Text("This contact will be deleted definitively."),
|
||||
titleFirstButton: Text("Cancel"),
|
||||
|
|
@ -514,9 +528,9 @@ struct ContentView: View {
|
|||
withAnimation {
|
||||
contactViewModel.indexDisplayedFriend = nil
|
||||
}
|
||||
magicSearch.lastSearch[tmpIndex!].friend!.remove()
|
||||
contactsManager.lastSearch[tmpIndex!].friend!.remove()
|
||||
}
|
||||
magicSearch.searchForContacts(
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
self.isShowDeleteContactPopup.toggle()
|
||||
})
|
||||
|
|
@ -611,7 +625,7 @@ struct ContentView: View {
|
|||
}
|
||||
.onChange(of: scenePhase) { newPhase in
|
||||
if newPhase == .active {
|
||||
ContactsManager.shared.fetchContacts()
|
||||
contactsManager.fetchContacts()
|
||||
print("Active")
|
||||
} else if newPhase == .inactive {
|
||||
print("Inactive")
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ struct HistoryContactFragment: View {
|
|||
@State private var orientation = UIDevice.current.orientation
|
||||
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
|
@ -66,14 +69,14 @@ struct HistoryContactFragment: View {
|
|||
Spacer()
|
||||
|
||||
Menu {
|
||||
let fromAddressFriend = historyViewModel.displayedCall != nil ? ContactsManager.shared.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil
|
||||
let toAddressFriend = historyViewModel.displayedCall != nil ? ContactsManager.shared.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil
|
||||
let fromAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil
|
||||
let toAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil
|
||||
let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? fromAddressFriend : toAddressFriend) : nil
|
||||
|
||||
Button {
|
||||
isMenuOpen = false
|
||||
|
||||
if ContactsManager.shared.getFriendWithAddress(
|
||||
if contactsManager.getFriendWithAddress(
|
||||
address: historyViewModel.displayedCall != nil && historyViewModel.displayedCall!.dir == .Outgoing
|
||||
? historyViewModel.displayedCall!.toAddress!
|
||||
: historyViewModel.displayedCall!.fromAddress!
|
||||
|
|
@ -82,7 +85,7 @@ struct HistoryContactFragment: View {
|
|||
? historyViewModel.displayedCall!.toAddress!
|
||||
: historyViewModel.displayedCall!.fromAddress!
|
||||
|
||||
let friendIndex = MagicSearchSingleton.shared.lastSearch.firstIndex(
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(
|
||||
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})})
|
||||
if friendIndex != nil {
|
||||
|
||||
|
|
@ -190,40 +193,19 @@ struct HistoryContactFragment: View {
|
|||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
|
||||
let fromAddressFriend = historyViewModel.displayedCall != nil ? ContactsManager.shared.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil
|
||||
let toAddressFriend = historyViewModel.displayedCall != nil ? ContactsManager.shared.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil
|
||||
let fromAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.fromAddress!) : nil
|
||||
let toAddressFriend = historyViewModel.displayedCall != nil ? contactsManager.getFriendWithAddress(address: historyViewModel.displayedCall!.toAddress!) : nil
|
||||
let addressFriend = historyViewModel.displayedCall != nil ? (historyViewModel.displayedCall!.dir == .Incoming ? fromAddressFriend : toAddressFriend) : nil
|
||||
|
||||
if historyViewModel.displayedCall != nil
|
||||
&& addressFriend != nil
|
||||
&& addressFriend!.photo != nil
|
||||
&& !addressFriend!.photo!.isEmpty {
|
||||
AsyncImage(
|
||||
url: ContactsManager.shared.getImagePath(
|
||||
friendPhotoPath: addressFriend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 100, height: 100)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 100, height: 100)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100)
|
||||
} else if historyViewModel.displayedCall != nil {
|
||||
if historyViewModel.displayedCall!.dir == .Outgoing && historyViewModel.displayedCall!.toAddress != nil {
|
||||
if historyViewModel.displayedCall!.toAddress!.displayName != nil {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyViewModel.displayedCall!.toAddress!.displayName!,
|
||||
lastName: historyViewModel.displayedCall!.toAddress!.displayName!.components(separatedBy: " ").count > 1
|
||||
? historyViewModel.displayedCall!.toAddress!.displayName!.components(separatedBy: " ")[1]
|
||||
|
|
@ -252,7 +234,7 @@ struct HistoryContactFragment: View {
|
|||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 20)
|
||||
} else {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyViewModel.displayedCall!.toAddress!.username ?? "Username Error",
|
||||
lastName: historyViewModel.displayedCall!.toAddress!.username!.components(separatedBy: " ").count > 1
|
||||
? historyViewModel.displayedCall!.toAddress!.username!.components(separatedBy: " ")[1]
|
||||
|
|
@ -284,7 +266,7 @@ struct HistoryContactFragment: View {
|
|||
|
||||
} else if historyViewModel.displayedCall!.fromAddress != nil {
|
||||
if historyViewModel.displayedCall!.fromAddress!.displayName != nil {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyViewModel.displayedCall!.fromAddress!.displayName!,
|
||||
lastName: historyViewModel.displayedCall!.fromAddress!.displayName!.components(separatedBy: " ").count > 1
|
||||
? historyViewModel.displayedCall!.fromAddress!.displayName!.components(separatedBy: " ")[1]
|
||||
|
|
@ -313,7 +295,7 @@ struct HistoryContactFragment: View {
|
|||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 20)
|
||||
} else {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyViewModel.displayedCall!.fromAddress!.username ?? "Username Error",
|
||||
lastName: historyViewModel.displayedCall!.fromAddress!.username!.components(separatedBy: " ").count > 1
|
||||
? historyViewModel.displayedCall!.fromAddress!.username!.components(separatedBy: " ")[1]
|
||||
|
|
@ -370,13 +352,15 @@ struct HistoryContactFragment: View {
|
|||
.padding(.top, 5)
|
||||
}
|
||||
|
||||
Text("En ligne")
|
||||
.foregroundStyle(Color.greenSuccess500)
|
||||
Text(contactAvatarModel.lastPresenceInfo)
|
||||
.foregroundStyle(contactAvatarModel.lastPresenceInfo == "Online"
|
||||
? Color.greenSuccess500
|
||||
: Color.orangeWarning600)
|
||||
.multilineTextAlignment(.center)
|
||||
.default_text_style_300(styleSize: 12)
|
||||
.frame(maxWidth: .infinity)
|
||||
.frame(height: 20)
|
||||
.padding(.top, 5)
|
||||
.padding(.top, 5)
|
||||
}
|
||||
}
|
||||
.frame(minHeight: 150)
|
||||
|
|
@ -508,7 +492,11 @@ struct HistoryContactFragment: View {
|
|||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Text(historyListViewModel.getCallTime(startDate: callLogsFilter[index].startDate))
|
||||
.foregroundStyle(callLogsFilter[index].status != .Success ? Color.redDanger500 : Color.grayMain2c600)
|
||||
.foregroundStyle(
|
||||
callLogsFilter[index].status != .Success
|
||||
? Color.redDanger500
|
||||
: Color.grayMain2c600
|
||||
)
|
||||
.default_text_style_300(styleSize: 12)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
|
@ -546,7 +534,8 @@ struct HistoryContactFragment: View {
|
|||
|
||||
#Preview {
|
||||
HistoryContactFragment(
|
||||
historyViewModel: HistoryViewModel(),
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, withPresence: false),
|
||||
historyViewModel: HistoryViewModel(),
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
contactViewModel: ContactViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ struct HistoryListBottomSheet: View {
|
|||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var contactViewModel: ContactViewModel
|
||||
|
|
@ -76,7 +77,7 @@ struct HistoryListBottomSheet: View {
|
|||
|
||||
index = 0
|
||||
|
||||
if ContactsManager.shared.getFriendWithAddress(
|
||||
if contactsManager.getFriendWithAddress(
|
||||
address: historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
|
||||
? historyViewModel.selectedCall!.toAddress!
|
||||
: historyViewModel.selectedCall!.fromAddress!
|
||||
|
|
@ -85,7 +86,7 @@ struct HistoryListBottomSheet: View {
|
|||
? historyViewModel.selectedCall!.toAddress!
|
||||
: historyViewModel.selectedCall!.fromAddress!
|
||||
|
||||
let friendIndex = MagicSearchSingleton.shared.lastSearch.firstIndex(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})})
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall.asStringUriOnly()})})
|
||||
if friendIndex != nil {
|
||||
withAnimation {
|
||||
contactViewModel.indexDisplayedFriend = friendIndex
|
||||
|
|
@ -105,7 +106,7 @@ struct HistoryListBottomSheet: View {
|
|||
}
|
||||
} label: {
|
||||
HStack {
|
||||
if ContactsManager.shared.getFriendWithAddress(
|
||||
if contactsManager.getFriendWithAddress(
|
||||
address: historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.dir == .Outgoing
|
||||
? historyViewModel.selectedCall!.toAddress!
|
||||
: historyViewModel.selectedCall!.fromAddress!
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ import linphonesw
|
|||
|
||||
struct HistoryListFragment: View {
|
||||
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
|
||||
|
|
@ -34,37 +36,24 @@ struct HistoryListFragment: View {
|
|||
Button {
|
||||
} label: {
|
||||
HStack {
|
||||
let fromAddressFriend = ContactsManager.shared.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
|
||||
let toAddressFriend = ContactsManager.shared.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
|
||||
let fromAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
|
||||
let toAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
|
||||
let addressFriend = historyListViewModel.callLogs[index].dir == .Incoming ? fromAddressFriend : toAddressFriend
|
||||
|
||||
let contactAvatarModel = addressFriend != nil
|
||||
? ContactsManager.shared.avatarListModel.first(where: {
|
||||
($0.friend!.consolidatedPresence == .Online || $0.friend!.consolidatedPresence == .Busy)
|
||||
&& $0.friend!.name == addressFriend!.name
|
||||
&& $0.friend!.address!.asStringUriOnly() == addressFriend!.address!.asStringUriOnly()
|
||||
})
|
||||
: ContactAvatarModel(friend: nil, withPresence: false)
|
||||
|
||||
if addressFriend != nil && addressFriend!.photo != nil && !addressFriend!.photo!.isEmpty {
|
||||
AsyncImage(url:
|
||||
ContactsManager.shared.getImagePath(
|
||||
friendPhotoPath: addressFriend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: 45, height: 45)
|
||||
case .success(let image):
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
Avatar(contactAvatarModel: contactAvatarModel!, avatarSize: 45)
|
||||
} else {
|
||||
if historyListViewModel.callLogs[index].dir == .Outgoing && historyListViewModel.callLogs[index].toAddress != nil {
|
||||
if historyListViewModel.callLogs[index].toAddress!.displayName != nil {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyListViewModel.callLogs[index].toAddress!.displayName!,
|
||||
lastName: historyListViewModel.callLogs[index].toAddress!.displayName!.components(separatedBy: " ").count > 1
|
||||
? historyListViewModel.callLogs[index].toAddress!.displayName!.components(separatedBy: " ")[1]
|
||||
|
|
@ -74,7 +63,7 @@ struct HistoryListFragment: View {
|
|||
.clipShape(Circle())
|
||||
|
||||
} else {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyListViewModel.callLogs[index].toAddress!.username ?? "Username Error",
|
||||
lastName: historyListViewModel.callLogs[index].toAddress!.username!.components(separatedBy: " ").count > 1
|
||||
? historyListViewModel.callLogs[index].toAddress!.username!.components(separatedBy: " ")[1]
|
||||
|
|
@ -86,7 +75,7 @@ struct HistoryListFragment: View {
|
|||
|
||||
} else if historyListViewModel.callLogs[index].fromAddress != nil {
|
||||
if historyListViewModel.callLogs[index].fromAddress!.displayName != nil {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyListViewModel.callLogs[index].fromAddress!.displayName!,
|
||||
lastName: historyListViewModel.callLogs[index].fromAddress!.displayName!.components(separatedBy: " ").count > 1
|
||||
? historyListViewModel.callLogs[index].fromAddress!.displayName!.components(separatedBy: " ")[1]
|
||||
|
|
@ -95,7 +84,7 @@ struct HistoryListFragment: View {
|
|||
.frame(width: 45, height: 45)
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
Image(uiImage: ContactsManager.shared.textToImage(
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyListViewModel.callLogs[index].fromAddress!.username ?? "Username Error",
|
||||
lastName: historyListViewModel.callLogs[index].fromAddress!.username!.components(separatedBy: " ").count > 1
|
||||
? historyListViewModel.callLogs[index].fromAddress!.username!.components(separatedBy: " ")[1]
|
||||
|
|
@ -110,8 +99,8 @@ struct HistoryListFragment: View {
|
|||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
let fromAddressFriend = ContactsManager.shared.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
|
||||
let toAddressFriend = ContactsManager.shared.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
|
||||
let fromAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].fromAddress!)
|
||||
let toAddressFriend = contactsManager.getFriendWithAddress(address: historyListViewModel.callLogs[index].toAddress!)
|
||||
let addressFriend = historyListViewModel.callLogs[index].dir == .Incoming ? fromAddressFriend : toAddressFriend
|
||||
|
||||
if addressFriend != nil {
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ class HistoryListViewModel: ObservableObject {
|
|||
DispatchQueue.main.async {
|
||||
self.coreDelegate = CoreDelegateStub(
|
||||
onCallLogUpdated: { (_: Core, _: CallLog) -> Void in
|
||||
DispatchQueue.main.async {
|
||||
DispatchQueue.main.sync {
|
||||
let account = core.defaultAccount
|
||||
let logs = account?.callLogs != nil ? account!.callLogs : core.callLogs
|
||||
let logs = account != nil ? account!.callLogs : core.callLogs
|
||||
|
||||
self.callLogs.removeAll()
|
||||
self.callLogsTmp.removeAll()
|
||||
|
|
@ -71,7 +71,6 @@ class HistoryListViewModel: ObservableObject {
|
|||
core.addDelegate(delegate: self.coreDelegate!)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,21 @@
|
|||
//
|
||||
// ToastViewModel.swift
|
||||
// Linphone
|
||||
//
|
||||
// Created by Benoît Martins on 20/11/2023.
|
||||
//
|
||||
/*
|
||||
* Copyright (c) 2010-2023 Belledonne Communications SARL.
|
||||
*
|
||||
* This file is part of Linphone
|
||||
*
|
||||
* 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 Foundation
|
||||
|
||||
|
|
|
|||
|
|
@ -22,84 +22,45 @@ import linphonesw
|
|||
|
||||
struct Avatar: View {
|
||||
|
||||
var friend: Friend
|
||||
let avatarSize: CGFloat
|
||||
|
||||
@State private var friendDelegate: FriendDelegate?
|
||||
@State private var presenceImage = ""
|
||||
|
||||
var body: some View {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: friend.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
case .success(let image):
|
||||
ZStack {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Spacer()
|
||||
if !friend.addresses.isEmpty {
|
||||
if presenceImage.isEmpty
|
||||
&& (friend.consolidatedPresence == ConsolidatedPresence.Online || friend.consolidatedPresence == ConsolidatedPresence.Busy) {
|
||||
Image(friend.consolidatedPresence == ConsolidatedPresence.Online ? "presence-online" : "presence-busy")
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
} else if !presenceImage.isEmpty {
|
||||
Image(presenceImage)
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
}
|
||||
.onAppear {
|
||||
addDelegate()
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
let avatarSize: CGFloat
|
||||
|
||||
var body: some View {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: contactAvatarModel.friend!.photo!)) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
case .success(let image):
|
||||
ZStack {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
HStack {
|
||||
Spacer()
|
||||
VStack {
|
||||
Spacer()
|
||||
if contactAvatarModel.presenceStatus == .Online || contactAvatarModel.presenceStatus == .Busy {
|
||||
Image(contactAvatarModel.presenceStatus == .Online ? "presence-online" : "presence-busy")
|
||||
.resizable()
|
||||
.frame(width: avatarSize/4, height: avatarSize/4)
|
||||
.padding(.trailing, avatarSize == 45 ? 1 : 3)
|
||||
.padding(.bottom, avatarSize == 45 ? 1 : 3)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
}
|
||||
.onDisappear {
|
||||
removeAllDelegate()
|
||||
}
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func addDelegate() {
|
||||
let newFriendDelegate = FriendDelegateStub(
|
||||
onPresenceReceived: { (linphoneFriend: Friend) -> Void in
|
||||
self.presenceImage = linphoneFriend.consolidatedPresence == ConsolidatedPresence.Online ? "presence-online" : "presence-busy"
|
||||
}
|
||||
)
|
||||
|
||||
friendDelegate = newFriendDelegate
|
||||
if friendDelegate != nil {
|
||||
friend.addDelegate(delegate: friendDelegate!)
|
||||
}
|
||||
}
|
||||
|
||||
func removeAllDelegate() {
|
||||
if friendDelegate != nil {
|
||||
presenceImage = ""
|
||||
friend.removeDelegate(delegate: friendDelegate!)
|
||||
friendDelegate = nil
|
||||
case .failure:
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: avatarSize, height: avatarSize)
|
||||
.clipShape(Circle())
|
||||
@unknown default:
|
||||
EmptyView()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ extension Int {
|
|||
public func convertDurationToString() -> String {
|
||||
var duration = ""
|
||||
let (hour, minute, second) = self.hmsFrom()
|
||||
if (hour > 0) {
|
||||
if hour > 0 {
|
||||
duration = self.getHour(hour: hour)
|
||||
}
|
||||
return "\(duration)\(self.getMinute(minute: minute))\(self.getSecond(second: second))"
|
||||
|
|
@ -36,18 +36,18 @@ extension Int {
|
|||
|
||||
private func getHour(hour: Int) -> String {
|
||||
var duration = "\(hour):"
|
||||
if (hour < 10) {
|
||||
if hour < 10 {
|
||||
duration = "0\(hour):"
|
||||
}
|
||||
return duration
|
||||
}
|
||||
|
||||
private func getMinute(minute: Int) -> String {
|
||||
if (minute == 0) {
|
||||
if minute == 0 {
|
||||
return "00:"
|
||||
}
|
||||
|
||||
if (minute < 10) {
|
||||
if minute < 10 {
|
||||
return "0\(minute):"
|
||||
}
|
||||
|
||||
|
|
@ -55,11 +55,11 @@ extension Int {
|
|||
}
|
||||
|
||||
private func getSecond(second: Int) -> String {
|
||||
if (second == 0){
|
||||
if second == 0 {
|
||||
return "00"
|
||||
}
|
||||
|
||||
if (second < 10) {
|
||||
if second < 10 {
|
||||
return "0\(second)"
|
||||
}
|
||||
return "\(second)"
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
|
||||
static let shared = MagicSearchSingleton()
|
||||
private var coreContext = CoreContext.shared
|
||||
private var contactsManager = ContactsManager.shared
|
||||
|
||||
private var magicSearch: MagicSearch!
|
||||
|
||||
|
|
@ -31,8 +32,6 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
|
||||
var needUpdateLastSearchContacts = false
|
||||
|
||||
@Published var lastSearch: [SearchResult] = []
|
||||
|
||||
private var limitSearchToLinphoneAccounts = true
|
||||
|
||||
@Published var allContact = false
|
||||
|
|
@ -47,7 +46,23 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
|
||||
self.magicSearch.publisher?.onSearchResultsReceived?.postOnMainQueue { (magicSearch: MagicSearch) in
|
||||
self.needUpdateLastSearchContacts = true
|
||||
self.lastSearch = magicSearch.lastSearch
|
||||
self.contactsManager.lastSearch = magicSearch.lastSearch.sorted(by: {
|
||||
$0.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current)
|
||||
<
|
||||
$1.friend!.name!.lowercased().folding(options: .diacriticInsensitive, locale: .current)
|
||||
})
|
||||
|
||||
self.contactsManager.avatarListModel.forEach { contactAvatarModel in
|
||||
contactAvatarModel.removeAllDelegate()
|
||||
}
|
||||
|
||||
self.contactsManager.avatarListModel.removeAll()
|
||||
|
||||
self.contactsManager.lastSearch.forEach { searchResult in
|
||||
if searchResult.friend != nil {
|
||||
self.contactsManager.avatarListModel.append(ContactAvatarModel(friend: searchResult.friend!, withPresence: true))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -75,4 +90,28 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
aggregation: MagicSearch.Aggregation.Friend)
|
||||
}
|
||||
}
|
||||
|
||||
func searchForContactsWithResult(sourceFlags: Int) {
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
var needResetCache = false
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
if let oldFilter = self.previousFilter {
|
||||
if oldFilter.count > self.currentFilter.count || oldFilter != self.currentFilter {
|
||||
needResetCache = true
|
||||
}
|
||||
}
|
||||
self.previousFilter = self.currentFilter
|
||||
}
|
||||
if needResetCache {
|
||||
self.magicSearch.resetSearchCache()
|
||||
}
|
||||
|
||||
self.magicSearch.getContactsListAsync(
|
||||
filter: self.currentFilter,
|
||||
domain: self.allContact ? "" : self.domainDefaultAccount,
|
||||
sourceFlags: sourceFlags,
|
||||
aggregation: MagicSearch.Aggregation.Friend)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue