mirror of
https://gitlab.linphone.org/BC/public/linphone-iphone.git
synced 2026-01-17 11:08:06 +00:00
Refactored HistoryView
This commit is contained in:
parent
865f889a3c
commit
f534ccb560
28 changed files with 741 additions and 629 deletions
|
|
@ -42,7 +42,14 @@ final class ContactsManager: ObservableObject {
|
|||
|
||||
@Published var lastSearch: [SearchResult] = []
|
||||
@Published var lastSearchSuggestions: [SearchResult] = []
|
||||
@Published var avatarListModel: [ContactAvatarModel] = []
|
||||
@Published var avatarListModel: [ContactAvatarModel] = [] {
|
||||
didSet {
|
||||
setupSubscriptions()
|
||||
}
|
||||
}
|
||||
|
||||
@Published var starredChangeTrigger = UUID()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
private var coreDelegate: CoreDelegate?
|
||||
private var friendListDelegate: FriendListDelegate?
|
||||
|
|
@ -97,6 +104,7 @@ final class ContactsManager: ObservableObject {
|
|||
print("\(#function) - failed to request access", error)
|
||||
self.addFriendListDelegate()
|
||||
self.addCoreDelegate(core: core)
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
return
|
||||
}
|
||||
if granted {
|
||||
|
|
@ -238,9 +246,15 @@ final class ContactsManager: ObservableObject {
|
|||
self.saveFriend(result: result, contact: contact, existingFriend: existingFriend) { resultFriend in
|
||||
if resultFriend != nil {
|
||||
if linphoneFriend && existingFriend == nil {
|
||||
_ = self.linphoneFriendList?.addFriend(linphoneFriend: resultFriend!)
|
||||
if let linphoneFL = self.linphoneFriendList {
|
||||
_ = linphoneFL.addFriend(linphoneFriend: resultFriend!)
|
||||
linphoneFL.updateSubscriptions()
|
||||
}
|
||||
} else if existingFriend == nil {
|
||||
_ = self.friendList?.addLocalFriend(linphoneFriend: resultFriend!)
|
||||
if let friendListTmp = self.friendList {
|
||||
_ = friendListTmp.addLocalFriend(linphoneFriend: resultFriend!)
|
||||
friendListTmp.updateSubscriptions()
|
||||
}
|
||||
}
|
||||
}
|
||||
completion()
|
||||
|
|
@ -496,6 +510,17 @@ final class ContactsManager: ObservableObject {
|
|||
core.addDelegate(delegate: self.coreDelegate!)
|
||||
}
|
||||
}
|
||||
|
||||
private func setupSubscriptions() {
|
||||
cancellables.removeAll()
|
||||
for contact in avatarListModel {
|
||||
contact.$starred
|
||||
.sink { [weak self] _ in
|
||||
self?.starredChangeTrigger = UUID() // 🔁 Déclenche le refresh de la vue
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct PhoneNumber {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ struct ContactFragment: View {
|
|||
.presentationDetents([.fraction(0.2)])
|
||||
}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[SharedMainViewModel.shared.indexDisplayedFriend!].friend!)
|
||||
ShareSheet(friendToShare: contactAvatarModel)
|
||||
.presentationDetents([.medium])
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
|
|
@ -54,7 +54,7 @@ struct ContactFragment: View {
|
|||
ContactListBottomSheet(contactsListViewModel: contactsListViewModel, showingSheet: $showingSheet)
|
||||
} onDismiss: {}
|
||||
.sheet(isPresented: $showShareSheet) {
|
||||
ShareSheet(friendToShare: ContactsManager.shared.lastSearch[SharedMainViewModel.shared.indexDisplayedFriend!].friend!)
|
||||
ShareSheet(friendToShare: contactAvatarModel)
|
||||
.edgesIgnoringSafeArea(.bottom)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ struct ContactInnerActionsFragment: View {
|
|||
showingSheet.toggle()
|
||||
}
|
||||
|
||||
if contactAvatarModel.friend != nil && !contactAvatarModel.friend!.phoneNumbers.isEmpty
|
||||
if !contactAvatarModel.phoneNumbersWithLabel.isEmpty
|
||||
|| index < contactAvatarModel.addresses.count - 1 {
|
||||
VStack {
|
||||
Divider()
|
||||
|
|
@ -114,22 +114,22 @@ struct ContactInnerActionsFragment: View {
|
|||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
if contactAvatarModel.friend != nil {
|
||||
ForEach(0..<contactAvatarModel.friend!.phoneNumbers.count, id: \.self) { index in
|
||||
|
||||
ForEach(contactAvatarModel.phoneNumbersWithLabel.indices, id: \.self) { index in
|
||||
let entry = contactAvatarModel.phoneNumbersWithLabel[index]
|
||||
HStack {
|
||||
HStack {
|
||||
VStack {
|
||||
if contactAvatarModel.friend!.phoneNumbersWithLabel[index].label != nil
|
||||
&& !contactAvatarModel.friend!.phoneNumbersWithLabel[index].label!.isEmpty {
|
||||
Text(String(localized: "phone_number") + " \(contactAvatarModel.friend!.phoneNumbersWithLabel[index].label!)) :")
|
||||
if !entry.label.isEmpty {
|
||||
Text(String(localized: "phone_number") + " (\(entry.label)):")
|
||||
.default_text_style_700(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
} else {
|
||||
Text(String(localized: "phone_number") + " :")
|
||||
Text(String(localized: "phone_number") + ":")
|
||||
.default_text_style_700(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
Text(contactAvatarModel.friend!.phoneNumbersWithLabel[index].phoneNumber)
|
||||
Text(entry.phoneNumber)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
|
|
@ -142,19 +142,17 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
.background(.white)
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
contactsListViewModel.stringToCopy =
|
||||
contactAvatarModel.friend!.phoneNumbersWithLabel[index].phoneNumber
|
||||
contactsListViewModel.stringToCopy = entry.phoneNumber
|
||||
showingSheet.toggle()
|
||||
}
|
||||
|
||||
if index < contactAvatarModel.friend!.phoneNumbers.count - 1 {
|
||||
if index < contactAvatarModel.phoneNumbersWithLabel.count - 1 {
|
||||
VStack {
|
||||
Divider()
|
||||
}
|
||||
.padding(.horizontal)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.background(.white)
|
||||
.cornerRadius(15)
|
||||
|
|
@ -163,29 +161,20 @@ struct ContactInnerActionsFragment: View {
|
|||
.transition(.move(edge: .top))
|
||||
}
|
||||
|
||||
if contactAvatarModel.friend != nil && (contactAvatarModel.friend!.organization != nil
|
||||
&& !contactAvatarModel.friend!.organization!.isEmpty)
|
||||
|| (contactAvatarModel.friend!.jobTitle != nil
|
||||
&& !contactAvatarModel.friend!.jobTitle!.isEmpty) {
|
||||
if !contactAvatarModel.organization.isEmpty || !contactAvatarModel.jobTitle.isEmpty {
|
||||
VStack {
|
||||
if contactAvatarModel.friend!.organization != nil
|
||||
&& !contactAvatarModel.friend!.organization!.isEmpty {
|
||||
Text(.init(String(format:"**%@ :** %@", String(localized: "contact_editor_company"), contactAvatarModel.friend!.organization!)))
|
||||
if !contactAvatarModel.organization.isEmpty {
|
||||
Text(.init(String(format:"**%@ :** %@", String(localized: "contact_editor_company"), contactAvatarModel.organization)))
|
||||
.default_text_style(styleSize: 14)
|
||||
.padding(.vertical, 15)
|
||||
.padding(.horizontal, 20)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
}
|
||||
|
||||
if contactAvatarModel.friend!.jobTitle != nil
|
||||
&& !contactAvatarModel.friend!.jobTitle!.isEmpty {
|
||||
Text(.init(String(format:"**%@ :** %@", String(localized: "contact_editor_job_title"), contactAvatarModel.friend!.jobTitle!)))
|
||||
if !contactAvatarModel.jobTitle.isEmpty {
|
||||
Text(.init(String(format:"**%@ :** %@", String(localized: "contact_editor_job_title"), contactAvatarModel.jobTitle)))
|
||||
.default_text_style(styleSize: 14)
|
||||
.padding(.top,
|
||||
contactAvatarModel.friend!.organization != nil
|
||||
&& !contactAvatarModel.friend!.organization!.isEmpty
|
||||
? 0 : 15
|
||||
)
|
||||
.padding(.top, !contactAvatarModel.organization.isEmpty ? 0 : 15)
|
||||
.padding(.bottom, 15)
|
||||
.padding(.horizontal, 20)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
|
@ -238,7 +227,7 @@ struct ContactInnerActionsFragment: View {
|
|||
}
|
||||
} else {
|
||||
NavigationLink(destination: EditContactFragment(
|
||||
friend: contactAvatarModel.friend!,
|
||||
contactAvatarModel: contactAvatarModel,
|
||||
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
|
||||
isShowDismissPopup: $isShowDismissPopup)) {
|
||||
HStack {
|
||||
|
|
@ -272,20 +261,16 @@ struct ContactInnerActionsFragment: View {
|
|||
.padding(.horizontal)
|
||||
|
||||
Button {
|
||||
if contactAvatarModel.friend != nil {
|
||||
contactAvatarModel.friend!.edit()
|
||||
contactAvatarModel.friend!.starred.toggle()
|
||||
contactAvatarModel.friend!.done()
|
||||
}
|
||||
contactsListViewModel.toggleStarredSelectedFriend()
|
||||
} label: {
|
||||
HStack {
|
||||
Image(contactAvatarModel.friend != nil && contactAvatarModel.friend!.starred == true ? "heart-fill" : "heart")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(contactAvatarModel.friend != nil && contactAvatarModel.friend!.starred == true ? Color.redDanger500 : Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.all, 10)
|
||||
Text(contactAvatarModel.friend != nil && contactAvatarModel.friend!.starred == true
|
||||
Image(contactAvatarModel.starred == true ? "heart-fill" : "heart")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.foregroundStyle(contactAvatarModel.starred == true ? Color.redDanger500 : Color.grayMain2c500)
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.all, 10)
|
||||
Text(contactAvatarModel.starred == true
|
||||
? "contact_details_remove_from_favourites"
|
||||
: "contact_details_add_to_favourites")
|
||||
.default_text_style(styleSize: 14)
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ struct ContactInnerFragment: View {
|
|||
.padding(.leading, -10)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = nil
|
||||
SharedMainViewModel.shared.displayedFriend = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -86,7 +86,7 @@ struct ContactInnerFragment: View {
|
|||
})
|
||||
} else {
|
||||
NavigationLink(destination: EditContactFragment(
|
||||
friend: contactAvatarModel.friend,
|
||||
contactAvatarModel: contactAvatarModel,
|
||||
isShowEditContactFragment: $isShowEditContactFragmentInContactDetails,
|
||||
isShowDismissPopup: $isShowDismissPopup)) {
|
||||
Image("pencil-simple")
|
||||
|
|
@ -114,7 +114,7 @@ struct ContactInnerFragment: View {
|
|||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
if SharedMainViewModel.shared.indexDisplayedFriend != nil {
|
||||
if SharedMainViewModel.shared.displayedFriend != nil {
|
||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 100)
|
||||
|
||||
Text(contactAvatarModel.name)
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ struct ContactsInnerFragment: View {
|
|||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
if !contactsManager.avatarListModel.filter({ $0.friend?.starred == true }).isEmpty {
|
||||
if contactsManager.avatarListModel.contains(where: { $0.starred }) {
|
||||
HStack(alignment: .center) {
|
||||
Text("contacts_list_favourites_title")
|
||||
.default_text_style_800(styleSize: 16)
|
||||
|
|
|
|||
|
|
@ -57,13 +57,7 @@ struct ContactsListBottomSheet: View {
|
|||
|
||||
Spacer()
|
||||
Button {
|
||||
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)
|
||||
self.contactsListViewModel.toggleStarredSelectedFriend()
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
if idiom != .pad {
|
||||
|
|
|
|||
|
|
@ -31,73 +31,81 @@ struct ContactsListFragment: View {
|
|||
var startCallFunc: (_ addr: Address) -> Void
|
||||
|
||||
var body: some View {
|
||||
ForEach(0..<contactsManager.avatarListModel.count, id: \.self) { index in
|
||||
ForEach(Array(contactsManager.avatarListModel.enumerated()), id: \.element.id) { index, contactAvatarModel in
|
||||
ContactRow(contactAvatarModel: contactAvatarModel, index: index, showingSheet: $showingSheet, startCallFunc: startCallFunc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ContactRow: View {
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
|
||||
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
|
||||
let index: Int
|
||||
|
||||
@Binding var showingSheet: Bool
|
||||
|
||||
var startCallFunc: (_ addr: Address) -> Void
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
HStack {
|
||||
HStack {
|
||||
if index == 0
|
||||
|| contactsManager.avatarListModel[index].name.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first
|
||||
!= contactsManager.avatarListModel[index-1].name.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first {
|
||||
Text(
|
||||
String(
|
||||
(contactsManager.avatarListModel[index].name.uppercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first)!))
|
||||
if index <= 0
|
||||
|| (index < contactsManager.avatarListModel.count && contactAvatarModel.name.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first
|
||||
!= contactsManager.avatarListModel[index-1].name.lowercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first) {
|
||||
Text(
|
||||
String(
|
||||
(contactAvatarModel.name.uppercased().folding(
|
||||
options: .diacriticInsensitive,
|
||||
locale: .current
|
||||
).first) ?? "?"))
|
||||
.contact_text_style_500(styleSize: 20)
|
||||
.frame(width: 18)
|
||||
.padding(.leading, -5)
|
||||
.padding(.trailing, 10)
|
||||
} else {
|
||||
Text("")
|
||||
.contact_text_style_500(styleSize: 20)
|
||||
.frame(width: 18)
|
||||
.padding(.leading, -5)
|
||||
.padding(.trailing, 10)
|
||||
} else {
|
||||
Text("")
|
||||
.contact_text_style_500(styleSize: 20)
|
||||
.frame(width: 18)
|
||||
.padding(.leading, -5)
|
||||
.padding(.trailing, 10)
|
||||
}
|
||||
|
||||
if index < contactsManager.avatarListModel.count
|
||||
&& contactsManager.avatarListModel[index].friend!.photo != nil
|
||||
&& !contactsManager.avatarListModel[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text(contactsManager.avatarListModel[index].name)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundStyle(Color.orangeMain500)
|
||||
}
|
||||
}
|
||||
.frame(height: 50)
|
||||
.buttonStyle(.borderless)
|
||||
.listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 20))
|
||||
.listRowSeparator(.hidden)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = index
|
||||
}
|
||||
|
||||
if index < contactsManager.avatarListModel.count && contactsManager.avatarListModel[index].friend != nil
|
||||
&& contactsManager.avatarListModel[index].friend!.address != nil {
|
||||
startCallFunc(contactsManager.avatarListModel[index].friend!.address!)
|
||||
}
|
||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 50)
|
||||
|
||||
Text(contactAvatarModel.name)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.foregroundStyle(Color.orangeMain500)
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
if index < contactsManager.avatarListModel.count && contactsManager.avatarListModel[index].friend != nil {
|
||||
contactsListViewModel.selectedFriend = contactsManager.avatarListModel[index].friend
|
||||
showingSheet.toggle()
|
||||
}
|
||||
}
|
||||
.frame(height: 50)
|
||||
.buttonStyle(.borderless)
|
||||
.listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 20))
|
||||
.listRowSeparator(.hidden)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedFriend = contactAvatarModel
|
||||
}
|
||||
|
||||
if contactAvatarModel.friend != nil
|
||||
&& contactAvatarModel.friend!.address != nil {
|
||||
startCallFunc(contactAvatarModel.friend!.address!)
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
contactsListViewModel.selectedFriend = contactAvatarModel
|
||||
showingSheet.toggle()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ struct EditContactFragment: View {
|
|||
|
||||
@Binding var isShowEditContactFragment: Bool
|
||||
@Binding var isShowDismissPopup: Bool
|
||||
let isShowEditContactFragmentAddress: String
|
||||
|
||||
@State private var delayedColor = Color.white
|
||||
|
||||
|
|
@ -46,10 +47,11 @@ 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))
|
||||
init(contactAvatarModel: ContactAvatarModel? = nil, isShowEditContactFragment: Binding<Bool>, isShowDismissPopup: Binding<Bool>, isShowEditContactFragmentAddress: String = "") {
|
||||
_editContactViewModel = StateObject(wrappedValue: EditContactViewModel(contactAvatarModel: contactAvatarModel))
|
||||
self._isShowEditContactFragment = isShowEditContactFragment
|
||||
self._isShowDismissPopup = isShowDismissPopup
|
||||
self.isShowEditContactFragmentAddress = isShowEditContactFragmentAddress
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
|
|
@ -152,18 +154,9 @@ struct EditContactFragment: View {
|
|||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
VStack(spacing: 0) {
|
||||
if editContactViewModel.selectedEditFriend != nil
|
||||
&& editContactViewModel.selectedEditFriend!.photo != nil
|
||||
&& !editContactViewModel.selectedEditFriend!.photo!.isEmpty && selectedImage == nil && !removedImage {
|
||||
if editContactViewModel.selectedEditFriend != nil && selectedImage == nil && !removedImage {
|
||||
|
||||
Avatar(contactAvatarModel:
|
||||
ContactAvatarModel(
|
||||
friend: editContactViewModel.selectedEditFriend!,
|
||||
name: editContactViewModel.selectedEditFriend?.name ?? "",
|
||||
address: editContactViewModel.selectedEditFriend?.address?.asStringUriOnly() ?? "",
|
||||
withPresence: false
|
||||
), avatarSize: 100
|
||||
)
|
||||
Avatar(contactAvatarModel: editContactViewModel.selectedEditFriend!, avatarSize: 100)
|
||||
|
||||
} else if selectedImage == nil {
|
||||
Image("profil-picture-default")
|
||||
|
|
@ -179,9 +172,8 @@ struct EditContactFragment: View {
|
|||
}
|
||||
|
||||
if editContactViewModel.selectedEditFriend != nil
|
||||
&& editContactViewModel.selectedEditFriend!.photo != nil
|
||||
&& !editContactViewModel.selectedEditFriend!.photo!.isEmpty
|
||||
&& (editContactViewModel.selectedEditFriend!.photo!.suffix(11) != "default.png" || selectedImage != nil) && !removedImage {
|
||||
&& !editContactViewModel.selectedEditFriend!.photo.isEmpty
|
||||
&& (editContactViewModel.selectedEditFriend!.photo.suffix(11) != "default.png" || selectedImage != nil) && !removedImage {
|
||||
HStack {
|
||||
Spacer()
|
||||
|
||||
|
|
@ -213,6 +205,7 @@ struct EditContactFragment: View {
|
|||
removedImage = false
|
||||
}
|
||||
}
|
||||
showPhotoPicker = false
|
||||
}
|
||||
}
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
|
|
@ -265,6 +258,7 @@ struct EditContactFragment: View {
|
|||
removedImage = false
|
||||
}
|
||||
}
|
||||
showPhotoPicker = false
|
||||
}
|
||||
}
|
||||
.edgesIgnoringSafeArea(.all)
|
||||
|
|
@ -323,13 +317,13 @@ struct EditContactFragment: View {
|
|||
.default_text_style_700(styleSize: 15)
|
||||
.padding(.bottom, -5)
|
||||
|
||||
ForEach(0..<editContactViewModel.sipAddresses.count, id: \.self) { index in
|
||||
ForEach(editContactViewModel.sipAddresses.indices, id: \.self) { index in
|
||||
|
||||
HStack(alignment: .center) {
|
||||
TextField("sip_address", text: $editContactViewModel.sipAddresses[index])
|
||||
.default_text_style(styleSize: 15)
|
||||
.disableAutocorrection(true)
|
||||
.autocapitalization(.none)
|
||||
.autocapitalization(.none)
|
||||
.frame(height: 25)
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 15)
|
||||
|
|
@ -378,7 +372,7 @@ struct EditContactFragment: View {
|
|||
TextField("phone_number", text: $editContactViewModel.phoneNumbers[index])
|
||||
.default_text_style(styleSize: 15)
|
||||
.textContentType(.oneTimeCode)
|
||||
.keyboardType(.numberPad)
|
||||
.keyboardType(.numberPad)
|
||||
.frame(height: 25)
|
||||
.padding(.horizontal, 20)
|
||||
.padding(.vertical, 15)
|
||||
|
|
@ -483,6 +477,14 @@ struct EditContactFragment: View {
|
|||
}
|
||||
}
|
||||
.navigationBarHidden(true)
|
||||
.onAppear {
|
||||
if !self.isShowEditContactFragmentAddress.isEmpty {
|
||||
DispatchQueue.main.async {
|
||||
editContactViewModel.sipAddresses[0] = isShowEditContactFragmentAddress
|
||||
editContactViewModel.sipAddresses.append("")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Sendable private func delayColor() async {
|
||||
|
|
@ -500,59 +502,86 @@ struct EditContactFragment: View {
|
|||
}
|
||||
|
||||
func addOrEditFriend() {
|
||||
let newContact = Contact(
|
||||
identifier: editContactViewModel.identifier,
|
||||
firstName: editContactViewModel.firstName,
|
||||
lastName: editContactViewModel.lastName,
|
||||
organizationName: editContactViewModel.company,
|
||||
jobTitle: editContactViewModel.jobTitle,
|
||||
displayName: "",
|
||||
sipAddresses: editContactViewModel.sipAddresses.map { $0 },
|
||||
phoneNumbers: editContactViewModel.phoneNumbers.map { PhoneNumber(numLabel: "", num: $0)},
|
||||
imageData: ""
|
||||
)
|
||||
|
||||
if editContactViewModel.selectedEditFriend != nil && selectedImage == nil &&
|
||||
!removedImage && editContactViewModel.selectedEditFriend!.photo!.suffix(11) != "default.png" {
|
||||
ContactsManager.shared.saveFriend(
|
||||
result: String(editContactViewModel.selectedEditFriend!.photo!.dropFirst(6)),
|
||||
contact: newContact,
|
||||
existingFriend: editContactViewModel.selectedEditFriend, completion: {_ in }
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
let newContact = Contact(
|
||||
identifier: editContactViewModel.identifier,
|
||||
firstName: editContactViewModel.firstName,
|
||||
lastName: editContactViewModel.lastName,
|
||||
organizationName: editContactViewModel.company,
|
||||
jobTitle: editContactViewModel.jobTitle,
|
||||
displayName: "",
|
||||
sipAddresses: editContactViewModel.sipAddresses.map { $0 },
|
||||
phoneNumbers: editContactViewModel.phoneNumbers.map { PhoneNumber(numLabel: "", num: $0)},
|
||||
imageData: ""
|
||||
)
|
||||
} else {
|
||||
ContactsManager.shared.saveImage(
|
||||
image: selectedImage
|
||||
?? ContactsManager.shared.textToImage(
|
||||
firstName: editContactViewModel.firstName, lastName: editContactViewModel.lastName),
|
||||
name: editContactViewModel.firstName
|
||||
+ editContactViewModel.lastName,
|
||||
prefix: ((selectedImage == nil) ? "-default" : ""),
|
||||
contact: newContact, linphoneFriend: true, existingFriend: editContactViewModel.selectedEditFriend) {
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
if editContactViewModel.selectedEditFriend != nil {
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||
let result = ContactsManager.shared.lastSearch.firstIndex(where: {
|
||||
$0.friend!.name == newContact.firstName + " " + newContact.lastName
|
||||
})
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = result
|
||||
}
|
||||
|
||||
if editContactViewModel.selectedEditFriend != nil && editContactViewModel.selectedEditFriend!.friend != nil && selectedImage == nil &&
|
||||
!removedImage && editContactViewModel.selectedEditFriend!.friend!.photo!.suffix(11) != "default.png" {
|
||||
ContactsManager.shared.saveFriend(
|
||||
result: String(editContactViewModel.selectedEditFriend!.friend!.photo!.dropFirst(6)),
|
||||
contact: newContact,
|
||||
existingFriend: editContactViewModel.selectedEditFriend!.friend, completion: {_ in
|
||||
if let selectedFriendTmp = editContactViewModel.selectedEditFriend?.friend {
|
||||
let addressTmp = selectedFriendTmp.address?.clone()?.asStringUriOnly() ?? ""
|
||||
SharedMainViewModel.shared.displayedFriend?.resetContactAvatarModel(
|
||||
friend: selectedFriendTmp,
|
||||
name: selectedFriendTmp.name ?? "",
|
||||
address: addressTmp,
|
||||
withPresence: SharedMainViewModel.shared.displayedFriend?.withPresence
|
||||
)
|
||||
}
|
||||
|
||||
delayColorDismiss()
|
||||
if editContactViewModel.selectedEditFriend == nil {
|
||||
withAnimation {
|
||||
isShowEditContactFragment.toggle()
|
||||
}
|
||||
} else {
|
||||
withAnimation {
|
||||
dismiss()
|
||||
DispatchQueue.main.async {
|
||||
delayColorDismiss()
|
||||
if editContactViewModel.selectedEditFriend?.friend == nil {
|
||||
withAnimation {
|
||||
isShowEditContactFragment.toggle()
|
||||
}
|
||||
} else {
|
||||
withAnimation {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
editContactViewModel.resetValues()
|
||||
}
|
||||
editContactViewModel.resetValues()
|
||||
}
|
||||
}
|
||||
)
|
||||
} else {
|
||||
ContactsManager.shared.saveImage(
|
||||
image: selectedImage
|
||||
?? ContactsManager.shared.textToImage(
|
||||
firstName: editContactViewModel.firstName, lastName: editContactViewModel.lastName),
|
||||
name: editContactViewModel.firstName
|
||||
+ editContactViewModel.lastName,
|
||||
prefix: ((selectedImage == nil) ? "-default" : ""),
|
||||
contact: newContact, linphoneFriend: true, existingFriend: editContactViewModel.selectedEditFriend?.friend) {
|
||||
if let selectedFriendTmp = editContactViewModel.selectedEditFriend?.friend {
|
||||
let addressTmp = selectedFriendTmp.address?.clone()?.asStringUriOnly() ?? ""
|
||||
SharedMainViewModel.shared.displayedFriend?.resetContactAvatarModel(
|
||||
friend: selectedFriendTmp,
|
||||
name: selectedFriendTmp.name ?? "",
|
||||
address: addressTmp,
|
||||
withPresence: SharedMainViewModel.shared.displayedFriend?.withPresence
|
||||
)
|
||||
} else {
|
||||
MagicSearchSingleton.shared.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
delayColorDismiss()
|
||||
if editContactViewModel.selectedEditFriend?.friend == nil {
|
||||
withAnimation {
|
||||
isShowEditContactFragment.toggle()
|
||||
}
|
||||
} else {
|
||||
withAnimation {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
editContactViewModel.resetValues()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,36 +31,8 @@ struct FavoriteContactsListFragment: View {
|
|||
var body: some View {
|
||||
ScrollView(.horizontal) {
|
||||
HStack {
|
||||
ForEach(0..<contactsManager.lastSearch.count, id: \.self) { index in
|
||||
if contactsManager.lastSearch[index].friend != nil && contactsManager.lastSearch[index].friend!.starred == true {
|
||||
VStack {
|
||||
VStack {
|
||||
if contactsManager.lastSearch[index].friend!.photo != nil
|
||||
&& !contactsManager.lastSearch[index].friend!.photo!.isEmpty {
|
||||
Avatar(contactAvatarModel: contactsManager.avatarListModel[index], avatarSize: 50)
|
||||
} else {
|
||||
Image("profil-picture-default")
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
Text((contactsManager.lastSearch[index].friend?.name)!)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame( maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = index
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
contactsListViewModel.selectedFriend = contactsManager.lastSearch[index].friend
|
||||
showingSheet.toggle()
|
||||
}
|
||||
.frame(minWidth: 70, maxWidth: 70)
|
||||
}
|
||||
ForEach(contactsManager.avatarListModel) { contactAvatarModel in
|
||||
FavoriteContactRow(contactAvatarModel: contactAvatarModel, showingSheet: $showingSheet)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal, 10)
|
||||
|
|
@ -69,6 +41,41 @@ struct FavoriteContactsListFragment: View {
|
|||
}
|
||||
}
|
||||
|
||||
struct FavoriteContactRow: View {
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
|
||||
@EnvironmentObject var contactsListViewModel: ContactsListViewModel
|
||||
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
|
||||
@Binding var showingSheet: Bool
|
||||
|
||||
var body: some View {
|
||||
if contactAvatarModel.starred == true {
|
||||
VStack {
|
||||
VStack {
|
||||
Avatar(contactAvatarModel: contactAvatarModel, avatarSize: 50)
|
||||
|
||||
Text(contactAvatarModel.name)
|
||||
.default_text_style(styleSize: 16)
|
||||
.frame( maxWidth: .infinity, alignment: .center)
|
||||
}
|
||||
}
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedFriend = contactAvatarModel
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
contactsListViewModel.selectedFriend = contactAvatarModel
|
||||
showingSheet.toggle()
|
||||
}
|
||||
.frame(minWidth: 70, maxWidth: 70)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
FavoriteContactsListFragment(
|
||||
showingSheet: .constant(false))
|
||||
|
|
|
|||
|
|
@ -24,62 +24,96 @@ import Combine
|
|||
class ContactAvatarModel: ObservableObject, Identifiable {
|
||||
let id = UUID()
|
||||
|
||||
let friend: Friend?
|
||||
var friend: Friend?
|
||||
|
||||
let name: String
|
||||
@Published var name: String = ""
|
||||
@Published var address: String = ""
|
||||
@Published var addresses: [String] = []
|
||||
@Published var phoneNumbersWithLabel: [(label: String, phoneNumber: String)] = []
|
||||
|
||||
let address: String
|
||||
var nativeUri: String = ""
|
||||
var withPresence: Bool?
|
||||
|
||||
@Published var addresses: [String]
|
||||
@Published var starred: Bool = false
|
||||
|
||||
let nativeUri: String
|
||||
var vcard: Vcard?
|
||||
var organization: String = ""
|
||||
var jobTitle: String = ""
|
||||
|
||||
let withPresence: Bool?
|
||||
|
||||
@Published var lastPresenceInfo: String
|
||||
|
||||
@Published var presenceStatus: ConsolidatedPresence
|
||||
@Published var photo: String = ""
|
||||
@Published var lastPresenceInfo: String = ""
|
||||
@Published var presenceStatus: ConsolidatedPresence = .Offline
|
||||
|
||||
private var friendDelegate: FriendDelegate?
|
||||
|
||||
init(friend: Friend?, name: String, address: String, withPresence: Bool?) {
|
||||
self.friend = friend
|
||||
self.name = name
|
||||
self.address = address
|
||||
var addressesTmp: [String] = []
|
||||
if let friend = friend {
|
||||
friend.addresses.forEach { address in
|
||||
addressesTmp.append(address.asStringUriOnly())
|
||||
}
|
||||
}
|
||||
self.addresses = addressesTmp
|
||||
self.nativeUri = friend?.nativeUri ?? ""
|
||||
self.withPresence = withPresence
|
||||
if let friend = friend, 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"
|
||||
self.resetContactAvatarModel(friend: friend, name: name, address: address, withPresence: withPresence)
|
||||
}
|
||||
|
||||
func resetContactAvatarModel(friend: Friend?, name: String, address: String, withPresence: Bool?) {
|
||||
CoreContext.shared.doOnCoreQueue { _ in
|
||||
self.friend = friend
|
||||
let nameTmp = name
|
||||
let addressTmp = address
|
||||
var addressesTmp: [String] = []
|
||||
if let friend = friend {
|
||||
friend.addresses.forEach { address in
|
||||
addressesTmp.append(address.asStringUriOnly())
|
||||
}
|
||||
} else {
|
||||
self.lastPresenceInfo = ""
|
||||
}
|
||||
var phoneNumbersWithLabelTmp: [(label: String, phoneNumber: String)] = []
|
||||
if let friend = friend {
|
||||
friend.phoneNumbersWithLabel.forEach { phoneNum in
|
||||
phoneNumbersWithLabelTmp.append((label: phoneNum.label ?? "", phoneNumber: phoneNum.phoneNumber))
|
||||
}
|
||||
}
|
||||
let nativeUriTmp = friend?.nativeUri ?? ""
|
||||
let withPresenceTmp = withPresence
|
||||
let starredTmp = friend?.starred ?? false
|
||||
let vcardTmp = friend?.vcard ?? nil
|
||||
let organizationTmp = friend?.organization ?? ""
|
||||
let jobTitleTmp = friend?.jobTitle ?? ""
|
||||
let photoTmp = friend?.photo ?? ""
|
||||
var lastPresenceInfoTmp = ""
|
||||
var presenceStatusTmp: ConsolidatedPresence = .Offline
|
||||
|
||||
if let friend = friend, withPresence == true {
|
||||
lastPresenceInfoTmp = ""
|
||||
|
||||
presenceStatusTmp = friend.consolidatedPresence
|
||||
|
||||
if friend.consolidatedPresence == .Online || friend.consolidatedPresence == .Busy {
|
||||
if friend.consolidatedPresence == .Online || friend.presenceModel?.latestActivityTimestamp != -1 {
|
||||
lastPresenceInfoTmp = (friend.consolidatedPresence == .Online) ?
|
||||
"Online" : self.getCallTime(startDate: friend.presenceModel!.latestActivityTimestamp)
|
||||
} else {
|
||||
lastPresenceInfoTmp = "Away"
|
||||
}
|
||||
}
|
||||
|
||||
if let delegate = self.friendDelegate {
|
||||
self.friend?.removeDelegate(delegate: delegate)
|
||||
self.friendDelegate = nil
|
||||
}
|
||||
|
||||
self.addFriendDelegate()
|
||||
}
|
||||
|
||||
if let delegate = friendDelegate {
|
||||
self.friend?.removeDelegate(delegate: delegate)
|
||||
self.friendDelegate = nil
|
||||
DispatchQueue.main.async {
|
||||
self.name = nameTmp
|
||||
self.address = addressTmp
|
||||
self.addresses = addressesTmp
|
||||
self.phoneNumbersWithLabel = phoneNumbersWithLabelTmp
|
||||
self.nativeUri = nativeUriTmp
|
||||
self.withPresence = withPresenceTmp
|
||||
self.starred = starredTmp
|
||||
self.vcard = vcardTmp
|
||||
self.organization = organizationTmp
|
||||
self.jobTitle = jobTitleTmp
|
||||
self.photo = photoTmp
|
||||
self.lastPresenceInfo = lastPresenceInfoTmp
|
||||
self.presenceStatus = presenceStatusTmp
|
||||
}
|
||||
|
||||
addFriendDelegate()
|
||||
} else {
|
||||
self.lastPresenceInfo = ""
|
||||
self.presenceStatus = .Offline
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +144,9 @@ class ContactAvatarModel: ObservableObject, Identifiable {
|
|||
func removeFriendDelegate() {
|
||||
if let delegate = friendDelegate {
|
||||
presenceStatus = .Offline
|
||||
friend?.removeDelegate(delegate: delegate)
|
||||
if let friendTmp = friend {
|
||||
friendTmp.removeDelegate(delegate: delegate)
|
||||
}
|
||||
friendDelegate = nil
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,13 +23,13 @@ import SwiftUI
|
|||
|
||||
// swiftlint:disable line_length
|
||||
class ContactsListViewModel: ObservableObject {
|
||||
@Published var selectedEditFriend: Friend?
|
||||
@Published var selectedEditFriend: ContactAvatarModel?
|
||||
|
||||
var stringToCopy: String = ""
|
||||
|
||||
var selectedFriend: Friend?
|
||||
var selectedFriendToShare: Friend?
|
||||
var selectedFriendToDelete: Friend?
|
||||
var selectedFriend: ContactAvatarModel?
|
||||
var selectedFriendToShare: ContactAvatarModel?
|
||||
var selectedFriendToDelete: ContactAvatarModel?
|
||||
|
||||
@Published var operationInProgress: Bool = false
|
||||
@Published var displayedConversation: ConversationModel?
|
||||
|
|
@ -211,5 +211,62 @@ class ContactsListViewModel: ObservableObject {
|
|||
})
|
||||
chatRoom.addDelegate(delegate: contactChatRoomDelegate!)
|
||||
}
|
||||
|
||||
func deleteSelectedContact() {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
if self.selectedFriendToDelete != nil && self.selectedFriendToDelete!.friend != nil {
|
||||
if SharedMainViewModel.shared.displayedFriend != nil {
|
||||
DispatchQueue.main.async {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedFriend = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
self.selectedFriendToDelete!.friend!.remove()
|
||||
} else if SharedMainViewModel.shared.displayedFriend != nil {
|
||||
DispatchQueue.main.async {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedFriend = nil
|
||||
}
|
||||
}
|
||||
SharedMainViewModel.shared.displayedFriend!.friend!.remove()
|
||||
}
|
||||
|
||||
MagicSearchSingleton.shared.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
}
|
||||
}
|
||||
|
||||
func changeSelectedFriendToDelete() {
|
||||
if selectedFriend != nil {
|
||||
self.selectedFriendToDelete = self.selectedFriend
|
||||
}
|
||||
}
|
||||
|
||||
func toggleStarredSelectedFriend() {
|
||||
CoreContext.shared.doOnCoreQueue { core in
|
||||
if let contactAvatar = self.selectedFriend, let friend = contactAvatar.friend {
|
||||
friend.edit()
|
||||
friend.starred.toggle()
|
||||
friend.done()
|
||||
|
||||
let starredTmp = friend.starred
|
||||
|
||||
DispatchQueue.main.async {
|
||||
contactAvatar.starred = starredTmp
|
||||
}
|
||||
} else if let displayedFriend = SharedMainViewModel.shared.displayedFriend, let friend = displayedFriend.friend {
|
||||
friend.edit()
|
||||
friend.starred.toggle()
|
||||
friend.done()
|
||||
|
||||
let starredTmp = friend.starred
|
||||
|
||||
DispatchQueue.main.async {
|
||||
displayedFriend.starred = starredTmp
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// swiftlint:enable line_length
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import SwiftUI
|
|||
|
||||
class EditContactViewModel: ObservableObject {
|
||||
|
||||
let selectedEditFriend: Friend?
|
||||
let selectedEditFriend: ContactAvatarModel?
|
||||
|
||||
@Published var identifier: String = ""
|
||||
@Published var firstName: String = ""
|
||||
|
|
@ -32,8 +32,8 @@ class EditContactViewModel: ObservableObject {
|
|||
@Published var company: String = ""
|
||||
@Published var jobTitle: String = ""
|
||||
|
||||
init(friend: Friend? = nil) {
|
||||
self.selectedEditFriend = friend
|
||||
init(contactAvatarModel: ContactAvatarModel? = nil) {
|
||||
self.selectedEditFriend = contactAvatarModel
|
||||
resetValues()
|
||||
}
|
||||
|
||||
|
|
@ -50,11 +50,11 @@ class EditContactViewModel: ObservableObject {
|
|||
|
||||
if self.selectedEditFriend != nil {
|
||||
self.selectedEditFriend?.addresses.forEach({ address in
|
||||
sipAddressesTmp.append(String(address.asStringUriOnly().dropFirst(4)))
|
||||
sipAddressesTmp.append(String(address.dropFirst(4)))
|
||||
})
|
||||
|
||||
self.selectedEditFriend?.phoneNumbers.forEach({ phoneNumber in
|
||||
phoneNumbersTmp.append(phoneNumber)
|
||||
self.selectedEditFriend?.phoneNumbersWithLabel.forEach({ phoneNumber in
|
||||
phoneNumbersTmp.append(phoneNumber.phoneNumber)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ struct ContentView: View {
|
|||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@State private var contactsListViewModel: ContactsListViewModel?
|
||||
|
||||
//@ObservedObject var historyViewModel: HistoryViewModel
|
||||
//@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@State private var historyListViewModel: HistoryListViewModel?
|
||||
|
||||
//@ObservedObject var startCallViewModel: StartCallViewModel
|
||||
//@ObservedObject var startConversationViewModel: StartConversationViewModel
|
||||
|
|
@ -70,6 +68,7 @@ struct ContentView: View {
|
|||
@State var isShowDeleteAllHistoryPopup = false
|
||||
@State var isShowEditContactFragment = false
|
||||
@State var isShowEditContactFragmentInContactDetails = false
|
||||
@State var isShowEditContactFragmentAddress = ""
|
||||
@State var isShowStartCallFragment = false
|
||||
@State var isShowStartConversationFragment = false
|
||||
@State var isShowDismissPopup = false
|
||||
|
|
@ -174,13 +173,12 @@ struct ContentView: View {
|
|||
.frame(height: geometry.size.height/4)
|
||||
|
||||
ZStack {
|
||||
/*
|
||||
if historyListViewModel.missedCallsCount > 0 {
|
||||
if historyListViewModel != nil && historyListViewModel!.missedCallsCount > 0 {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(
|
||||
historyListViewModel.missedCallsCount < 99
|
||||
? String(historyListViewModel.missedCallsCount)
|
||||
historyListViewModel!.missedCallsCount < 99
|
||||
? String(historyListViewModel!.missedCallsCount)
|
||||
: "99+"
|
||||
)
|
||||
.foregroundStyle(.white)
|
||||
|
|
@ -194,17 +192,14 @@ struct ContentView: View {
|
|||
.padding(.bottom, 30)
|
||||
.padding(.leading, 30)
|
||||
}
|
||||
*/
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 1)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedConversation = nil
|
||||
sharedMainViewModel.displayedMeeting = nil
|
||||
/*
|
||||
if historyListViewModel.missedCallsCount > 0 {
|
||||
historyListViewModel.resetMissedCallsCount()
|
||||
if historyListViewModel != nil && historyListViewModel!.missedCallsCount > 0 {
|
||||
historyListViewModel!.resetMissedCallsCount()
|
||||
}
|
||||
*/
|
||||
}, label: {
|
||||
VStack {
|
||||
Image("phone")
|
||||
|
|
@ -249,7 +244,7 @@ struct ContentView: View {
|
|||
*/
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 2)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
sharedMainViewModel.displayedMeeting = nil
|
||||
}, label: {
|
||||
|
|
@ -275,7 +270,7 @@ struct ContentView: View {
|
|||
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 3)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
sharedMainViewModel.displayedConversation = nil
|
||||
}, label: {
|
||||
|
|
@ -437,7 +432,7 @@ struct ContentView: View {
|
|||
Menu {
|
||||
if sharedMainViewModel.indexView == 0 {
|
||||
Button {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = true
|
||||
magicSearch.searchForContacts(
|
||||
|
|
@ -456,7 +451,7 @@ struct ContentView: View {
|
|||
}
|
||||
|
||||
Button {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
isMenuOpen = false
|
||||
magicSearch.allContact = false
|
||||
magicSearch.searchForContacts(
|
||||
|
|
@ -523,8 +518,8 @@ struct ContentView: View {
|
|||
magicSearch.currentFilter = ""
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else if sharedMainViewModel.indexView == 1 {
|
||||
//historyListViewModel.resetFilterCallLogs()
|
||||
} else if sharedMainViewModel.indexView == 1 && historyListViewModel != nil {
|
||||
historyListViewModel!.resetFilterCallLogs()
|
||||
} else if sharedMainViewModel.indexView == 2 {
|
||||
//conversationsListViewModel.resetFilterConversations()
|
||||
} else if sharedMainViewModel.indexView == 3 {
|
||||
|
|
@ -570,10 +565,10 @@ struct ContentView: View {
|
|||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else if sharedMainViewModel.indexView == 1 {
|
||||
if text.isEmpty {
|
||||
//historyListViewModel.resetFilterCallLogs()
|
||||
} else {
|
||||
//historyListViewModel.filterCallLogs(filter: text)
|
||||
if text.isEmpty && historyListViewModel != nil {
|
||||
historyListViewModel!.resetFilterCallLogs()
|
||||
} else if historyListViewModel != nil {
|
||||
historyListViewModel!.filterCallLogs(filter: text)
|
||||
}
|
||||
} else if sharedMainViewModel.indexView == 2 {
|
||||
if text.isEmpty {
|
||||
|
|
@ -612,8 +607,8 @@ struct ContentView: View {
|
|||
magicSearch.currentFilter = newValue
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
} else if sharedMainViewModel.indexView == 1 {
|
||||
//historyListViewModel.filterCallLogs(filter: text)
|
||||
} else if sharedMainViewModel.indexView == 1 && historyListViewModel != nil {
|
||||
historyListViewModel!.filterCallLogs(filter: text)
|
||||
} else if sharedMainViewModel.indexView == 2 {
|
||||
//conversationsListViewModel.filterConversations(filter: text)
|
||||
} else if sharedMainViewModel.indexView == 3 {
|
||||
|
|
@ -676,33 +671,38 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
} else if sharedMainViewModel.indexView == 1 {
|
||||
//TODO a changer
|
||||
NavigationView {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
if let historyListVM = historyListViewModel {
|
||||
HistoryView(
|
||||
isShowStartCallFragment: $isShowStartCallFragment,
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
text: $text,
|
||||
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress
|
||||
)
|
||||
.environmentObject(historyListVM)
|
||||
.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 {
|
||||
historyListViewModel = HistoryListViewModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationViewStyle(.stack)
|
||||
/*
|
||||
HistoryView(
|
||||
historyListViewModel: historyListViewModel,
|
||||
historyViewModel: historyViewModel,
|
||||
contactsListViewModel: contactsListViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
index: $index,
|
||||
isShowStartCallFragment: $isShowStartCallFragment,
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
text: $text
|
||||
)
|
||||
.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 sharedMainViewModel.indexView == 2 {
|
||||
//TODO a changer
|
||||
NavigationView {
|
||||
|
|
@ -809,13 +809,12 @@ struct ContentView: View {
|
|||
Spacer()
|
||||
|
||||
ZStack {
|
||||
/*
|
||||
if historyListViewModel.missedCallsCount > 0 {
|
||||
if historyListViewModel != nil && historyListViewModel!.missedCallsCount > 0 {
|
||||
VStack {
|
||||
HStack {
|
||||
Text(
|
||||
historyListViewModel.missedCallsCount < 99
|
||||
? String(historyListViewModel.missedCallsCount)
|
||||
historyListViewModel!.missedCallsCount < 99
|
||||
? String(historyListViewModel!.missedCallsCount)
|
||||
: "99+"
|
||||
)
|
||||
.foregroundStyle(.white)
|
||||
|
|
@ -829,17 +828,14 @@ struct ContentView: View {
|
|||
.padding(.bottom, 30)
|
||||
.padding(.leading, 30)
|
||||
}
|
||||
*/
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 1)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedConversation = nil
|
||||
sharedMainViewModel.displayedMeeting = nil
|
||||
/*
|
||||
if historyListViewModel.missedCallsCount > 0 {
|
||||
historyListViewModel.resetMissedCallsCount()
|
||||
if historyListViewModel != nil && historyListViewModel!.missedCallsCount > 0 {
|
||||
historyListViewModel!.resetMissedCallsCount()
|
||||
}
|
||||
*/
|
||||
}, label: {
|
||||
VStack {
|
||||
Image("phone")
|
||||
|
|
@ -886,7 +882,7 @@ struct ContentView: View {
|
|||
*/
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 2)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
sharedMainViewModel.displayedMeeting = nil
|
||||
}, label: {
|
||||
|
|
@ -913,7 +909,7 @@ struct ContentView: View {
|
|||
Spacer()
|
||||
Button(action: {
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 3)
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
sharedMainViewModel.displayedConversation = nil
|
||||
}, label: {
|
||||
|
|
@ -947,7 +943,7 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if sharedMainViewModel.indexDisplayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil ||
|
||||
if sharedMainViewModel.displayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil ||
|
||||
sharedMainViewModel.displayedMeeting != nil {
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
|
@ -958,7 +954,7 @@ struct ContentView: View {
|
|||
? (geometry.size.width/100*40) + 75
|
||||
: 0
|
||||
)
|
||||
if sharedMainViewModel.indexView == 0 && sharedMainViewModel.indexDisplayedFriend != nil && contactsManager.avatarListModel.count > sharedMainViewModel.indexDisplayedFriend! {
|
||||
if sharedMainViewModel.indexView == 0 && sharedMainViewModel.displayedFriend != nil {
|
||||
ContactFragment(
|
||||
isShowDeletePopup: $isShowDeleteContactPopup,
|
||||
isShowDismissPopup: $isShowDismissPopup,
|
||||
|
|
@ -967,7 +963,7 @@ struct ContentView: View {
|
|||
isShowEditContactFragmentInContactDetails: $isShowEditContactFragmentInContactDetails
|
||||
)
|
||||
.environmentObject(contactsListViewModel!)
|
||||
.environmentObject(contactsManager.avatarListModel[sharedMainViewModel.indexDisplayedFriend!])
|
||||
.environmentObject(sharedMainViewModel.displayedFriend!)
|
||||
.frame(maxWidth: .infinity)
|
||||
.background(Color.gray100)
|
||||
.ignoresSafeArea(.keyboard)
|
||||
|
|
@ -1077,12 +1073,14 @@ struct ContentView: View {
|
|||
if isShowEditContactFragment {
|
||||
EditContactFragment(
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
isShowDismissPopup: $isShowDismissPopup
|
||||
isShowDismissPopup: $isShowDismissPopup,
|
||||
isShowEditContactFragmentAddress: isShowEditContactFragmentAddress
|
||||
)
|
||||
.zIndex(3)
|
||||
.transition(.opacity.combined(with: .move(edge: .bottom)))
|
||||
.onAppear {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
isShowEditContactFragmentAddress = ""
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1143,35 +1141,23 @@ struct ContentView: View {
|
|||
*/
|
||||
|
||||
if isShowDeleteContactPopup {
|
||||
PopupView(isShowPopup: $isShowDeleteContactPopup,
|
||||
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"),
|
||||
actionFirstButton: {
|
||||
self.isShowDeleteContactPopup.toggle()},
|
||||
titleSecondButton: Text("dialog_ok"),
|
||||
actionSecondButton: {
|
||||
if contactsListViewModel!.selectedFriendToDelete != nil {
|
||||
if sharedMainViewModel.indexDisplayedFriend != nil {
|
||||
withAnimation {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
}
|
||||
}
|
||||
contactsListViewModel!.selectedFriendToDelete!.remove()
|
||||
} else if sharedMainViewModel.indexDisplayedFriend != nil {
|
||||
let tmpIndex = sharedMainViewModel.indexDisplayedFriend
|
||||
withAnimation {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
}
|
||||
contactsManager.lastSearch[tmpIndex!].friend!.remove()
|
||||
}
|
||||
magicSearch.searchForContacts(
|
||||
sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue)
|
||||
self.isShowDeleteContactPopup.toggle()
|
||||
PopupView(
|
||||
isShowPopup: $isShowDeleteContactPopup,
|
||||
title: Text(
|
||||
String(
|
||||
format: String(localized: "contact_dialog_delete_title"),
|
||||
contactsListViewModel!.selectedFriend?.name
|
||||
?? (SharedMainViewModel.shared.displayedFriend!.name ?? "Unknown Contact")
|
||||
)
|
||||
),
|
||||
content: Text("contact_dialog_delete_message"),
|
||||
titleFirstButton: Text("dialog_cancel"),
|
||||
actionFirstButton: {
|
||||
self.isShowDeleteContactPopup.toggle()},
|
||||
titleSecondButton: Text("dialog_ok"),
|
||||
actionSecondButton: {
|
||||
self.contactsListViewModel!.deleteSelectedContact()
|
||||
self.isShowDeleteContactPopup.toggle()
|
||||
})
|
||||
.background(.black.opacity(0.65))
|
||||
.zIndex(3)
|
||||
|
|
@ -1179,11 +1165,10 @@ struct ContentView: View {
|
|||
self.isShowDeleteContactPopup.toggle()
|
||||
}
|
||||
.onAppear {
|
||||
contactsListViewModel!.selectedFriendToDelete = contactsListViewModel!.selectedFriend
|
||||
self.contactsListViewModel!.changeSelectedFriendToDelete()
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if isShowDeleteAllHistoryPopup {
|
||||
PopupView(isShowPopup: $isShowDeleteContactPopup,
|
||||
title: Text("history_dialog_delete_all_call_logs_title"),
|
||||
|
|
@ -1191,11 +1176,15 @@ struct ContentView: View {
|
|||
titleFirstButton: Text("dialog_cancel"),
|
||||
actionFirstButton: {
|
||||
self.isShowDeleteAllHistoryPopup.toggle()
|
||||
historyListViewModel.callLogsAddressToDelete = ""
|
||||
if historyListViewModel != nil {
|
||||
historyListViewModel!.callLogsAddressToDelete = ""
|
||||
}
|
||||
},
|
||||
titleSecondButton: Text("dialog_ok"),
|
||||
actionSecondButton: {
|
||||
historyListViewModel.removeCallLogs()
|
||||
if historyListViewModel != nil {
|
||||
historyListViewModel!.removeCallLogs()
|
||||
}
|
||||
self.isShowDeleteAllHistoryPopup.toggle()
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
|
||||
|
|
@ -1208,7 +1197,6 @@ struct ContentView: View {
|
|||
self.isShowDeleteAllHistoryPopup.toggle()
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if isShowDismissPopup {
|
||||
PopupView(isShowPopup: $isShowDismissPopup,
|
||||
|
|
@ -1232,13 +1220,13 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
|
||||
if isShowSipAddressesPopup {
|
||||
if isShowSipAddressesPopup && sharedMainViewModel.displayedFriend != nil {
|
||||
SipAddressesPopup(
|
||||
isShowSipAddressesPopup: $isShowSipAddressesPopup,
|
||||
isShowSipAddressesPopupType: $isShowSipAddressesPopupType
|
||||
)
|
||||
.environmentObject(contactsListViewModel!)
|
||||
.environmentObject(contactsManager.avatarListModel[sharedMainViewModel.indexDisplayedFriend != nil ? sharedMainViewModel.indexDisplayedFriend! : 0])
|
||||
.environmentObject(sharedMainViewModel.displayedFriend!)
|
||||
.background(.black.opacity(0.65))
|
||||
.zIndex(3)
|
||||
.onTapGesture {
|
||||
|
|
@ -1253,7 +1241,7 @@ struct ContentView: View {
|
|||
.zIndex(3)
|
||||
.onDisappear {
|
||||
if contactsListViewModel.displayedConversation != nil {
|
||||
sharedMainViewModel.indexDisplayedFriend = nil
|
||||
sharedMainViewModel.displayedFriend = nil
|
||||
sharedMainViewModel.displayedCall = nil
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 2)
|
||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||
|
|
@ -1443,7 +1431,9 @@ struct ContentView: View {
|
|||
}
|
||||
.onReceive(contactLoaded) { _ in
|
||||
//conversationsListViewModel.updateChatRoomsList()
|
||||
//historyListViewModel.refreshHistoryAvatarModel()
|
||||
if historyListViewModel != nil {
|
||||
historyListViewModel!.refreshHistoryAvatarModel()
|
||||
}
|
||||
}
|
||||
.onReceive(contactAdded) { address in
|
||||
//conversationsListViewModel.updateChatRoom(address: address)
|
||||
|
|
@ -1463,7 +1453,7 @@ struct ContentView: View {
|
|||
}
|
||||
}
|
||||
.onRotate { newOrientation in
|
||||
if (sharedMainViewModel.indexDisplayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil) && searchIsActive {
|
||||
if (sharedMainViewModel.displayedFriend != nil || sharedMainViewModel.displayedCall != nil || sharedMainViewModel.displayedConversation != nil) && searchIsActive {
|
||||
self.focusedField = false
|
||||
} else if searchIsActive {
|
||||
self.focusedField = true
|
||||
|
|
@ -1499,8 +1489,6 @@ class NavigationManager: ObservableObject {
|
|||
|
||||
#Preview {
|
||||
ContentView(
|
||||
//historyViewModel: HistoryViewModel(),
|
||||
//historyListViewModel: HistoryListViewModel(),
|
||||
//startCallViewModel: StartCallViewModel(),
|
||||
//startConversationViewModel: StartConversationViewModel(),
|
||||
//callViewModel: CallViewModel(),
|
||||
|
|
|
|||
|
|
@ -349,13 +349,13 @@ struct ConversationInfoFragment: View {
|
|||
action: {
|
||||
let addressConv = participantConversationModel.address
|
||||
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(
|
||||
let friendIndex = contactsManager.avatarListModel.first(
|
||||
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressConv})})
|
||||
if friendIndex != nil {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedConversation = nil
|
||||
indexPage = 0
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = friendIndex
|
||||
SharedMainViewModel.shared.displayedFriend = friendIndex
|
||||
}
|
||||
} else {
|
||||
withAnimation {
|
||||
|
|
@ -529,13 +529,13 @@ struct ConversationInfoFragment: View {
|
|||
|
||||
let addressConv = conversationViewModel.participantConversationModel.first?.address ?? ""
|
||||
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(
|
||||
let friendIndex = contactsManager.avatarListModel.first(
|
||||
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressConv})})
|
||||
if friendIndex != nil {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedConversation = nil
|
||||
indexPage = 0
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = friendIndex
|
||||
SharedMainViewModel.shared.displayedFriend = friendIndex
|
||||
}
|
||||
} else {
|
||||
withAnimation {
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ struct HistoryContactFragment: View {
|
|||
@ObservedObject private var telecomManager = TelecomManager.shared
|
||||
|
||||
@ObservedObject var contactAvatarModel: ContactAvatarModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var contactsListViewModel: ContactsListViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
|
|
@ -82,14 +81,14 @@ struct HistoryContactFragment: View {
|
|||
let addressCall = SharedMainViewModel.shared.displayedCall!.addressFriend!.address
|
||||
|
||||
if addressCall != nil {
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(
|
||||
let friendIndex = contactsManager.avatarListModel.first(
|
||||
where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall!.asStringUriOnly()})})
|
||||
if friendIndex != nil {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedCall = nil
|
||||
indexPage = 0
|
||||
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = friendIndex
|
||||
SharedMainViewModel.shared.displayedFriend = friendIndex
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -450,7 +449,6 @@ struct HistoryContactFragment: View {
|
|||
#Preview {
|
||||
HistoryContactFragment(
|
||||
contactAvatarModel: ContactAvatarModel(friend: nil, name: "", address: "", withPresence: false),
|
||||
historyViewModel: HistoryViewModel(),
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
contactsListViewModel: ContactsListViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
|
|
|
|||
|
|
@ -22,43 +22,32 @@ import SwiftUI
|
|||
struct HistoryFragment: View {
|
||||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var contactsListViewModel: ContactsListViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
@EnvironmentObject var historyListViewModel: HistoryListViewModel
|
||||
|
||||
@State private var showingSheet = false
|
||||
@Binding var index: Int
|
||||
@Binding var isShowEditContactFragment: Bool
|
||||
@Binding var text: String
|
||||
@Binding var isShowEditContactFragmentAddress: String
|
||||
|
||||
var body: some View {
|
||||
ZStack {
|
||||
if #available(iOS 16.0, *), idiom != .pad {
|
||||
HistoryListFragment(historyListViewModel: historyListViewModel, historyViewModel: historyViewModel, showingSheet: $showingSheet, text: $text)
|
||||
HistoryListFragment(showingSheet: $showingSheet, text: $text)
|
||||
.sheet(isPresented: $showingSheet) {
|
||||
HistoryListBottomSheet(
|
||||
historyViewModel: historyViewModel,
|
||||
contactsListViewModel: contactsListViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
historyListViewModel: historyListViewModel,
|
||||
showingSheet: $showingSheet,
|
||||
index: $index,
|
||||
isShowEditContactFragment: $isShowEditContactFragment
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress
|
||||
)
|
||||
.presentationDetents([.fraction(0.2)])
|
||||
}
|
||||
} else {
|
||||
HistoryListFragment(historyListViewModel: historyListViewModel, historyViewModel: historyViewModel, showingSheet: $showingSheet, text: $text)
|
||||
HistoryListFragment(showingSheet: $showingSheet, text: $text)
|
||||
.halfSheet(showSheet: $showingSheet) {
|
||||
HistoryListBottomSheet(
|
||||
historyViewModel: historyViewModel,
|
||||
contactsListViewModel: contactsListViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
historyListViewModel: historyListViewModel,
|
||||
showingSheet: $showingSheet,
|
||||
index: $index,
|
||||
isShowEditContactFragment: $isShowEditContactFragment
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress
|
||||
)
|
||||
} onDismiss: {}
|
||||
}
|
||||
|
|
@ -68,12 +57,8 @@ struct HistoryFragment: View {
|
|||
|
||||
#Preview {
|
||||
HistoryFragment(
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
historyViewModel: HistoryViewModel(),
|
||||
contactsListViewModel: ContactsListViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
index: .constant(1),
|
||||
isShowEditContactFragment: .constant(false),
|
||||
text: .constant("")
|
||||
text: .constant(""),
|
||||
isShowEditContactFragmentAddress: .constant("")
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,17 +27,15 @@ struct HistoryListBottomSheet: View {
|
|||
private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom }
|
||||
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
@ObservedObject private var sharedMainViewModel = SharedMainViewModel.shared
|
||||
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var contactsListViewModel: ContactsListViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@EnvironmentObject var historyListViewModel: HistoryListViewModel
|
||||
|
||||
@State private var orientation = UIDevice.current.orientation
|
||||
|
||||
@Binding var showingSheet: Bool
|
||||
@Binding var index: Int
|
||||
@Binding var isShowEditContactFragment: Bool
|
||||
@Binding var isShowEditContactFragmentAddress: String
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
|
|
@ -74,30 +72,28 @@ struct HistoryListBottomSheet: View {
|
|||
dismiss()
|
||||
}
|
||||
|
||||
index = 0
|
||||
sharedMainViewModel.changeIndexView(indexViewInt: 0)
|
||||
|
||||
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.addressFriend != nil {
|
||||
let addressCall = historyViewModel.selectedCall!.address
|
||||
if historyListViewModel.selectedCall != nil && historyListViewModel.selectedCall!.addressFriend != nil {
|
||||
let addressCall = historyListViewModel.selectedCall!.address
|
||||
|
||||
let friendIndex = contactsManager.lastSearch.firstIndex(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall})})
|
||||
let friendIndex = contactsManager.avatarListModel.first(where: {$0.friend!.addresses.contains(where: {$0.asStringUriOnly() == addressCall})})
|
||||
if friendIndex != nil {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.indexDisplayedFriend = friendIndex
|
||||
SharedMainViewModel.shared.displayedFriend = friendIndex
|
||||
}
|
||||
}
|
||||
} else if historyViewModel.selectedCall != nil {
|
||||
let addressCall = historyViewModel.selectedCall!.address
|
||||
} else if historyListViewModel.selectedCall != nil {
|
||||
let addressCall = historyListViewModel.selectedCall!.address
|
||||
|
||||
withAnimation {
|
||||
isShowEditContactFragment.toggle()
|
||||
editContactViewModel.sipAddresses.removeAll()
|
||||
editContactViewModel.sipAddresses.append(String(addressCall.dropFirst(4)))
|
||||
editContactViewModel.sipAddresses.append("")
|
||||
isShowEditContactFragmentAddress = String(addressCall.dropFirst(4))
|
||||
}
|
||||
}
|
||||
} label: {
|
||||
HStack {
|
||||
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.addressFriend != nil {
|
||||
if historyListViewModel.selectedCall != nil && historyListViewModel.selectedCall!.addressFriend != nil {
|
||||
Image("user-circle")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
|
|
@ -130,14 +126,14 @@ struct HistoryListBottomSheet: View {
|
|||
.frame(maxWidth: .infinity)
|
||||
|
||||
Button {
|
||||
if historyViewModel.selectedCall != nil && historyViewModel.selectedCall!.isOutgoing {
|
||||
if historyListViewModel.selectedCall != nil && historyListViewModel.selectedCall!.isOutgoing {
|
||||
UIPasteboard.general.setValue(
|
||||
historyViewModel.selectedCall!.address.dropFirst(4),
|
||||
historyListViewModel.selectedCall!.address.dropFirst(4),
|
||||
forPasteboardType: UTType.plainText.identifier
|
||||
)
|
||||
} else {
|
||||
UIPasteboard.general.setValue(
|
||||
historyViewModel.selectedCall!.address.dropFirst(4),
|
||||
historyListViewModel.selectedCall!.address.dropFirst(4),
|
||||
forPasteboardType: UTType.plainText.identifier
|
||||
)
|
||||
}
|
||||
|
|
@ -180,8 +176,8 @@ struct HistoryListBottomSheet: View {
|
|||
.frame(maxWidth: .infinity)
|
||||
|
||||
Button {
|
||||
if historyViewModel.selectedCall != nil {
|
||||
historyListViewModel.removeCallLog(historyModel: historyViewModel.selectedCall!)
|
||||
if historyListViewModel.selectedCall != nil {
|
||||
historyListViewModel.removeCallLog(historyModel: historyListViewModel.selectedCall!)
|
||||
}
|
||||
|
||||
if #available(iOS 16.0, *) {
|
||||
|
|
@ -224,12 +220,8 @@ struct HistoryListBottomSheet: View {
|
|||
|
||||
#Preview {
|
||||
HistoryListBottomSheet(
|
||||
historyViewModel: HistoryViewModel(),
|
||||
contactsListViewModel: ContactsListViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
showingSheet: .constant(false),
|
||||
index: .constant(1),
|
||||
isShowEditContactFragment: .constant(false)
|
||||
isShowEditContactFragment: .constant(false),
|
||||
isShowEditContactFragmentAddress: .constant("")
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,7 @@ struct HistoryListFragment: View {
|
|||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
@ObservedObject private var telecomManager = TelecomManager.shared
|
||||
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@EnvironmentObject var historyListViewModel: HistoryListViewModel
|
||||
|
||||
@Binding var showingSheet: Bool
|
||||
@Binding var text: String
|
||||
|
|
@ -36,110 +35,8 @@ struct HistoryListFragment: View {
|
|||
var body: some View {
|
||||
VStack {
|
||||
List {
|
||||
ForEach(0..<historyListViewModel.callLogs.count, id: \.self) { index in
|
||||
HStack {
|
||||
HStack {
|
||||
if !historyListViewModel.callLogs[index].isConf {
|
||||
if historyListViewModel.callLogs[index].avatarModel != nil {
|
||||
Avatar(contactAvatarModel: historyListViewModel.callLogs[index].avatarModel!, avatarSize: 50)
|
||||
} else {
|
||||
if !historyListViewModel.callLogs[index].addressName.isEmpty {
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyListViewModel.callLogs[index].addressName,
|
||||
lastName: historyListViewModel.callLogs[index].addressName.components(separatedBy: " ").count > 1
|
||||
? historyListViewModel.callLogs[index].addressName.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
VStack {
|
||||
Image("profil-picture-default")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.frame(width: 28, height: 28)
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
}
|
||||
.frame(width: 50, height: 50)
|
||||
.background(Color.grayMain2c200)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
Image("users-three-square")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.frame(width: 28, height: 28)
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
}
|
||||
.frame(width: 50, height: 50)
|
||||
.background(Color.grayMain2c200)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
if !historyListViewModel.callLogs[index].isConf {
|
||||
Text(historyListViewModel.callLogs[index].addressName)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
} else {
|
||||
Text(historyListViewModel.callLogs[index].subject)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Image(historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing))
|
||||
.resizable()
|
||||
.frame(
|
||||
width: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing).contains("rejected") ? 12 : 8,
|
||||
height: historyListViewModel.getCallIconResId(callStatus: historyListViewModel.callLogs[index].status, isOutgoing: historyListViewModel.callLogs[index].isOutgoing).contains("rejected") ? 6 : 8)
|
||||
Text(historyListViewModel.getCallTime(startDate: historyListViewModel.callLogs[index].startDate))
|
||||
.default_text_style_300(styleSize: 12)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if !historyListViewModel.callLogs[index].isConf {
|
||||
Image("phone")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.all, 10)
|
||||
.padding(.trailing, 5)
|
||||
.highPriorityGesture(
|
||||
TapGesture()
|
||||
.onEnded { _ in
|
||||
withAnimation {
|
||||
doCall(index: index)
|
||||
SharedMainViewModel.shared.displayedCall = nil
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 50)
|
||||
.buttonStyle(.borderless)
|
||||
.listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 20))
|
||||
.listRowSeparator(.hidden)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedCall = historyListViewModel.callLogs[index]
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
historyViewModel.selectedCall = historyListViewModel.callLogs[index]
|
||||
showingSheet.toggle()
|
||||
}
|
||||
ForEach(historyListViewModel.callLogs) { historyModel in
|
||||
HistoryRow(historyModel: historyModel, showingSheet: $showingSheet)
|
||||
}
|
||||
}
|
||||
.safeAreaInset(edge: .top, content: {
|
||||
|
|
@ -169,14 +66,131 @@ struct HistoryListFragment: View {
|
|||
.navigationTitle("")
|
||||
.navigationBarHidden(true)
|
||||
}
|
||||
}
|
||||
|
||||
struct HistoryRow: View {
|
||||
@ObservedObject var contactsManager = ContactsManager.shared
|
||||
@ObservedObject private var telecomManager = TelecomManager.shared
|
||||
|
||||
func doCall(index: Int) {
|
||||
telecomManager.doCallOrJoinConf(address: historyListViewModel.callLogs[index].addressLinphone)
|
||||
@EnvironmentObject var historyListViewModel: HistoryListViewModel
|
||||
|
||||
@ObservedObject var historyModel: HistoryModel
|
||||
|
||||
@Binding var showingSheet: Bool
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
HStack {
|
||||
if !historyModel.isConf {
|
||||
if historyModel.avatarModel != nil {
|
||||
Avatar(contactAvatarModel: historyModel.avatarModel!, avatarSize: 50)
|
||||
} else {
|
||||
if !historyModel.addressName.isEmpty {
|
||||
Image(uiImage: contactsManager.textToImage(
|
||||
firstName: historyModel.addressName,
|
||||
lastName: historyModel.addressName.components(separatedBy: " ").count > 1
|
||||
? historyModel.addressName.components(separatedBy: " ")[1]
|
||||
: ""))
|
||||
.resizable()
|
||||
.frame(width: 50, height: 50)
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
VStack {
|
||||
Image("profil-picture-default")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.frame(width: 28, height: 28)
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
}
|
||||
.frame(width: 50, height: 50)
|
||||
.background(Color.grayMain2c200)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VStack {
|
||||
Image("users-three-square")
|
||||
.renderingMode(.template)
|
||||
.resizable()
|
||||
.frame(width: 28, height: 28)
|
||||
.foregroundStyle(Color.grayMain2c600)
|
||||
}
|
||||
.frame(width: 50, height: 50)
|
||||
.background(Color.grayMain2c200)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
|
||||
VStack(spacing: 0) {
|
||||
Spacer()
|
||||
if !historyModel.isConf {
|
||||
Text(historyModel.addressName)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
} else {
|
||||
Text(historyModel.subject)
|
||||
.default_text_style(styleSize: 14)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
HStack {
|
||||
Image(historyListViewModel.getCallIconResId(callStatus: historyModel.status, isOutgoing: historyModel.isOutgoing))
|
||||
.resizable()
|
||||
.frame(
|
||||
width: historyListViewModel.getCallIconResId(callStatus: historyModel.status, isOutgoing: historyModel.isOutgoing).contains("rejected") ? 12 : 8,
|
||||
height: historyListViewModel.getCallIconResId(callStatus: historyModel.status, isOutgoing: historyModel.isOutgoing).contains("rejected") ? 6 : 8)
|
||||
Text(historyListViewModel.getCallTime(startDate: historyModel.startDate))
|
||||
.default_text_style_300(styleSize: 12)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
if !historyModel.isConf {
|
||||
Image("phone")
|
||||
.resizable()
|
||||
.frame(width: 25, height: 25)
|
||||
.padding(.all, 10)
|
||||
.padding(.trailing, 5)
|
||||
.highPriorityGesture(
|
||||
TapGesture()
|
||||
.onEnded { _ in
|
||||
withAnimation {
|
||||
doCall(historyModel: historyModel)
|
||||
SharedMainViewModel.shared.displayedCall = nil
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(height: 50)
|
||||
.buttonStyle(.borderless)
|
||||
.listRowInsets(EdgeInsets(top: 6, leading: 20, bottom: 6, trailing: 20))
|
||||
.listRowSeparator(.hidden)
|
||||
.background(.white)
|
||||
.onTapGesture {
|
||||
withAnimation {
|
||||
SharedMainViewModel.shared.displayedCall = historyModel
|
||||
}
|
||||
}
|
||||
.onLongPressGesture(minimumDuration: 0.2) {
|
||||
historyListViewModel.selectedCall = historyModel
|
||||
showingSheet.toggle()
|
||||
}
|
||||
}
|
||||
|
||||
func doCall(historyModel: HistoryModel) {
|
||||
telecomManager.doCallOrJoinConf(address: historyModel.addressLinphone)
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
HistoryListFragment(historyListViewModel: HistoryListViewModel(), historyViewModel: HistoryViewModel(), showingSheet: .constant(false), text: .constant(""))
|
||||
HistoryListFragment(showingSheet: .constant(false), text: .constant(""))
|
||||
}
|
||||
|
||||
// swiftlint:enable line_length
|
||||
|
|
|
|||
|
|
@ -22,27 +22,20 @@ import linphonesw
|
|||
|
||||
struct HistoryView: View {
|
||||
|
||||
@ObservedObject var historyListViewModel: HistoryListViewModel
|
||||
@ObservedObject var historyViewModel: HistoryViewModel
|
||||
@ObservedObject var contactsListViewModel: ContactsListViewModel
|
||||
@ObservedObject var editContactViewModel: EditContactViewModel
|
||||
@EnvironmentObject var historyListViewModel: HistoryListViewModel
|
||||
|
||||
@Binding var index: Int
|
||||
@Binding var isShowStartCallFragment: Bool
|
||||
@Binding var isShowEditContactFragment: Bool
|
||||
@Binding var text: String
|
||||
@Binding var isShowEditContactFragmentAddress: String
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
ZStack(alignment: .bottomTrailing) {
|
||||
HistoryFragment(
|
||||
historyListViewModel: historyListViewModel,
|
||||
historyViewModel: historyViewModel,
|
||||
contactsListViewModel: contactsListViewModel,
|
||||
editContactViewModel: editContactViewModel,
|
||||
index: $index,
|
||||
isShowEditContactFragment: $isShowEditContactFragment,
|
||||
text: $text
|
||||
text: $text,
|
||||
isShowEditContactFragmentAddress: $isShowEditContactFragmentAddress
|
||||
)
|
||||
|
||||
Button {
|
||||
|
|
@ -72,12 +65,8 @@ struct HistoryView: View {
|
|||
|
||||
#Preview {
|
||||
HistoryFragment(
|
||||
historyListViewModel: HistoryListViewModel(),
|
||||
historyViewModel: HistoryViewModel(),
|
||||
contactsListViewModel: ContactsListViewModel(),
|
||||
editContactViewModel: EditContactViewModel(),
|
||||
index: .constant(1),
|
||||
isShowEditContactFragment: .constant(false),
|
||||
text: .constant("")
|
||||
text: .constant(""),
|
||||
isShowEditContactFragmentAddress: .constant("")
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,15 +20,17 @@
|
|||
import Foundation
|
||||
import linphonesw
|
||||
|
||||
class HistoryModel: ObservableObject {
|
||||
class HistoryModel: ObservableObject, Identifiable {
|
||||
|
||||
private var coreContext = CoreContext.shared
|
||||
|
||||
static let TAG = "[History Model]"
|
||||
|
||||
let id = UUID()
|
||||
|
||||
var callLog: CallLog
|
||||
|
||||
var id: String
|
||||
@Published var callLogId: String
|
||||
@Published var subject: String
|
||||
@Published var isConf: Bool
|
||||
@Published var addressLinphone: Address
|
||||
|
|
@ -43,7 +45,7 @@ class HistoryModel: ObservableObject {
|
|||
|
||||
init(callLog: CallLog) {
|
||||
self.callLog = callLog
|
||||
self.id = ""
|
||||
self.callLogId = ""
|
||||
self.subject = ""
|
||||
self.isConf = false
|
||||
|
||||
|
|
@ -88,7 +90,7 @@ class HistoryModel: ObservableObject {
|
|||
|
||||
DispatchQueue.main.async {
|
||||
self.callLog = callLogTmp
|
||||
self.id = idTmp
|
||||
self.callLogId = idTmp
|
||||
self.subject = subjectTmp
|
||||
self.isConf = isConfTmp
|
||||
|
||||
|
|
@ -111,34 +113,30 @@ class HistoryModel: ObservableObject {
|
|||
}
|
||||
|
||||
func refreshAvatarModel() {
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
guard let address = (self.callLog.dir == .Outgoing ? self.callLog.toAddress : self.callLog.fromAddress) else {
|
||||
DispatchQueue.main.async {
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
}
|
||||
return
|
||||
guard let address = (self.callLog.dir == .Outgoing ? self.callLog.toAddress : self.callLog.fromAddress) else {
|
||||
DispatchQueue.main.async {
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
let addressFriendTmp = ContactsManager.shared.getFriendWithAddress(address: address)
|
||||
if let addressFriendTmp = addressFriendTmp {
|
||||
let addressNameTmp = self.addressName
|
||||
|
||||
let addressFriendTmp = ContactsManager.shared.getFriendWithAddress(address: address)
|
||||
if let addressFriendTmp = addressFriendTmp {
|
||||
let avatarModelTmp = ContactsManager.shared.avatarListModel.first(where: {
|
||||
guard let friend = $0.friend else { return false }
|
||||
return friend.name == addressFriendTmp.name && friend.address?.asStringUriOnly() == addressFriendTmp.address?.asStringUriOnly()
|
||||
}) ?? ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.addressFriend = addressFriendTmp
|
||||
|
||||
let addressNameTmp = self.addressName
|
||||
|
||||
let avatarModelTmp = ContactsManager.shared.avatarListModel.first(where: {
|
||||
guard let friend = $0.friend else { return false }
|
||||
return friend.name == addressFriendTmp.name && friend.address?.asStringUriOnly() == addressFriendTmp.address?.asStringUriOnly()
|
||||
}) ?? ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.addressFriend = addressFriendTmp
|
||||
self.addressName = addressFriendTmp.name ?? addressNameTmp
|
||||
self.avatarModel = avatarModelTmp
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
}
|
||||
self.addressName = addressFriendTmp.name ?? addressNameTmp
|
||||
self.avatarModel = avatarModelTmp
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
self.avatarModel = ContactAvatarModel(friend: nil, name: self.addressName, address: self.address, withPresence: false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,8 @@ class HistoryListViewModel: ObservableObject {
|
|||
|
||||
@Published var missedCallsCount: Int = 0
|
||||
|
||||
@Published var selectedCall: HistoryModel?
|
||||
|
||||
init() {
|
||||
computeCallLogsList()
|
||||
updateMissedCallsCount()
|
||||
|
|
@ -247,8 +249,10 @@ class HistoryListViewModel: ObservableObject {
|
|||
}
|
||||
|
||||
func refreshHistoryAvatarModel() {
|
||||
callLogs.forEach { historyModel in
|
||||
historyModel.refreshAvatarModel()
|
||||
coreContext.doOnCoreQueue { _ in
|
||||
self.callLogs.forEach { historyModel in
|
||||
historyModel.refreshAvatarModel()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -95,16 +95,14 @@ class AccountProfileViewModel: ObservableObject {
|
|||
|
||||
let accountDisplayName = CoreContext.shared.accounts[self.accountModelIndex!].account.displayName()
|
||||
|
||||
DispatchQueue.main.async {
|
||||
CoreContext.shared.accounts[self.accountModelIndex!].avatarModel = ContactAvatarModel(
|
||||
friend: nil,
|
||||
name: displayNameTmp.isEmpty ? accountDisplayName : displayNameTmp,
|
||||
address: contactAddressTmp,
|
||||
withPresence: false
|
||||
)
|
||||
|
||||
self.dialPlanValueSelected = dialPlanValueSelectedTmp
|
||||
}
|
||||
CoreContext.shared.accounts[self.accountModelIndex!].avatarModel = ContactAvatarModel(
|
||||
friend: nil,
|
||||
name: displayNameTmp.isEmpty ? accountDisplayName : displayNameTmp,
|
||||
address: contactAddressTmp,
|
||||
withPresence: false
|
||||
)
|
||||
|
||||
self.dialPlanValueSelected = dialPlanValueSelectedTmp
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class SharedMainViewModel: ObservableObject {
|
|||
@Published var defaultAvatar: URL?
|
||||
@Published var indexView: Int = 0
|
||||
|
||||
@Published var indexDisplayedFriend: Int?
|
||||
@Published var displayedFriend: ContactAvatarModel?
|
||||
@Published var displayedCall: HistoryModel?
|
||||
@Published var displayedConversation: ConversationModel?
|
||||
@Published var displayedMeeting: MeetingModel?
|
||||
|
|
|
|||
|
|
@ -37,8 +37,11 @@ struct Avatar: View {
|
|||
}
|
||||
|
||||
var body: some View {
|
||||
if contactAvatarModel.friend != nil && contactAvatarModel.friend!.photo != nil {
|
||||
AsyncImage(url: ContactsManager.shared.getImagePath(friendPhotoPath: contactAvatarModel.friend!.photo!)) { image in
|
||||
if let photoPath = contactAvatarModel.friend?.photo {
|
||||
let uniqueUrl = ContactsManager.shared.getImagePath(friendPhotoPath: photoPath)
|
||||
let finalUrl = uniqueUrl.appendingQueryItem("v", value: UUID().uuidString)
|
||||
|
||||
AsyncImage(url: finalUrl) { image in
|
||||
switch image {
|
||||
case .empty:
|
||||
ProgressView()
|
||||
|
|
|
|||
|
|
@ -25,8 +25,15 @@ extension URL {
|
|||
components?.scheme = value
|
||||
return components?.url
|
||||
}
|
||||
|
||||
var resourceSpecifier: String {
|
||||
let nrl: NSURL = self as NSURL
|
||||
return nrl.resourceSpecifier ?? self.absoluteString
|
||||
}
|
||||
|
||||
func appendingQueryItem(_ name: String, value: String) -> URL {
|
||||
guard var components = URLComponents(url: self, resolvingAgainstBaseURL: true) else { return self }
|
||||
components.queryItems = (components.queryItems ?? []) + [URLQueryItem(name: name, value: value)]
|
||||
return components.url ?? self
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -91,13 +91,14 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
self.contactsManager.avatarListModel.forEach { contactAvatarModel in
|
||||
contactAvatarModel.removeFriendDelegate()
|
||||
}
|
||||
|
||||
DispatchQueue.main.async {
|
||||
self.contactsManager.lastSearch = sortedLastSearch
|
||||
self.contactsManager.lastSearchSuggestions = lastSearchSuggestions
|
||||
|
||||
self.contactsManager.avatarListModel.forEach { contactAvatarModel in
|
||||
contactAvatarModel.removeFriendDelegate()
|
||||
}
|
||||
self.contactsManager.avatarListModel.removeAll()
|
||||
self.contactsManager.avatarListModel += addedAvatarListModel
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ import linphonesw
|
|||
struct ShareSheet: UIViewControllerRepresentable {
|
||||
typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
|
||||
|
||||
let friendToShare: Friend
|
||||
let friendToShare: ContactAvatarModel
|
||||
var activityItems: [Any] = []
|
||||
let applicationActivities: [UIActivity]? = nil
|
||||
let excludedActivityTypes: [UIActivity.ActivityType]? = nil
|
||||
|
|
@ -34,25 +34,23 @@ struct ShareSheet: UIViewControllerRepresentable {
|
|||
let directoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first
|
||||
|
||||
if directoryURL != nil {
|
||||
if friendToShare.name != nil {
|
||||
let filename = friendToShare.name!.replacingOccurrences(of: " ", with: "")
|
||||
|
||||
let fileURL = directoryURL!
|
||||
.appendingPathComponent(filename)
|
||||
.appendingPathExtension("vcf")
|
||||
|
||||
if friendToShare.vcard != nil {
|
||||
try? friendToShare.vcard!.asVcard4String().write(to: fileURL, atomically: false, encoding: String.Encoding.utf8)
|
||||
|
||||
let controller = UIActivityViewController(
|
||||
activityItems: [fileURL],
|
||||
applicationActivities: applicationActivities
|
||||
)
|
||||
controller.excludedActivityTypes = excludedActivityTypes
|
||||
controller.completionWithItemsHandler = callback
|
||||
return controller
|
||||
}
|
||||
}
|
||||
let filename = friendToShare.name.replacingOccurrences(of: " ", with: "")
|
||||
|
||||
let fileURL = directoryURL!
|
||||
.appendingPathComponent(filename)
|
||||
.appendingPathExtension("vcf")
|
||||
|
||||
if let vCard = friendToShare.vcard {
|
||||
try? vCard.asVcard4String().write(to: fileURL, atomically: false, encoding: String.Encoding.utf8)
|
||||
|
||||
let controller = UIActivityViewController(
|
||||
activityItems: [fileURL],
|
||||
applicationActivities: applicationActivities
|
||||
)
|
||||
controller.excludedActivityTypes = excludedActivityTypes
|
||||
controller.completionWithItemsHandler = callback
|
||||
return controller
|
||||
}
|
||||
}
|
||||
|
||||
let controller = UIActivityViewController(
|
||||
|
|
|
|||
|
|
@ -86,7 +86,6 @@
|
|||
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 */; };
|
||||
D72250632ADE9615008FB426 /* HistoryViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72250622ADE9615008FB426 /* HistoryViewModel.swift */; };
|
||||
D72250692ADFBF2D008FB426 /* SideMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72250682ADFBF2D008FB426 /* SideMenu.swift */; };
|
||||
D72343302ACEFEF8009AA24E /* QrCodeScannerFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D723432F2ACEFEF8009AA24E /* QrCodeScannerFragment.swift */; };
|
||||
D72343322ACEFF58009AA24E /* QRScannerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343312ACEFF58009AA24E /* QRScannerController.swift */; };
|
||||
|
|
@ -298,7 +297,6 @@
|
|||
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>"; };
|
||||
D72250622ADE9615008FB426 /* HistoryViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryViewModel.swift; sourceTree = "<group>"; };
|
||||
D72250682ADFBF2D008FB426 /* SideMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideMenu.swift; sourceTree = "<group>"; };
|
||||
D723432F2ACEFEF8009AA24E /* QrCodeScannerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QrCodeScannerFragment.swift; sourceTree = "<group>"; };
|
||||
D72343312ACEFF58009AA24E /* QRScannerController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScannerController.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -685,7 +683,6 @@
|
|||
D72250612ADE95E4008FB426 /* ViewModel */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D72250622ADE9615008FB426 /* HistoryViewModel.swift */,
|
||||
D732A9142B04C7FE00DB42BA /* HistoryListViewModel.swift */,
|
||||
D726E43E2B19E56F0083C415 /* StartCallViewModel.swift */,
|
||||
);
|
||||
|
|
@ -1241,7 +1238,6 @@
|
|||
D783028F2D414847009CCB60 /* DebugFragment.swift in Sources */,
|
||||
66162A202BDFC2F900DCE913 /* AddParticipantsViewModel.swift in Sources */,
|
||||
D732A91B2B061BD900DB42BA /* HistoryListBottomSheet.swift in Sources */,
|
||||
D72250632ADE9615008FB426 /* HistoryViewModel.swift in Sources */,
|
||||
D78E06302BEA6A4A00CE3783 /* ChangeLayoutBottomSheet.swift in Sources */,
|
||||
66E56BC92BA4A6D7006CE56F /* MeetingsListViewModel.swift in Sources */,
|
||||
D726E4392B16440C0083C415 /* ContactAvatarModel.swift in Sources */,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue