diff --git a/Linphone.xcodeproj/project.pbxproj b/Linphone.xcodeproj/project.pbxproj index 14382a983..64f20df16 100644 --- a/Linphone.xcodeproj/project.pbxproj +++ b/Linphone.xcodeproj/project.pbxproj @@ -28,6 +28,7 @@ D72343342ACEFFC3009AA24E /* QRScanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343332ACEFFC3009AA24E /* QRScanner.swift */; }; D72343362AD037AF009AA24E /* ToastView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72343352AD037AF009AA24E /* ToastView.swift */; }; D72992392ADD7F68003AF125 /* HistoryContactFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */; }; + D732A9092AFD235500DB42BA /* ShareSheetController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D732A9082AFD235500DB42BA /* ShareSheetController.swift */; }; D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */; }; D748BF2E2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */; }; D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */; }; @@ -93,6 +94,7 @@ D72343332ACEFFC3009AA24E /* QRScanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QRScanner.swift; sourceTree = ""; }; D72343352AD037AF009AA24E /* ToastView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToastView.swift; sourceTree = ""; }; D72992382ADD7F68003AF125 /* HistoryContactFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HistoryContactFragment.swift; sourceTree = ""; }; + D732A9082AFD235500DB42BA /* ShareSheetController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheetController.swift; sourceTree = ""; }; D748BF2B2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountLoginFragment.swift; sourceTree = ""; }; D748BF2D2ACD82E7004844EB /* ThirdPartySipAccountWarningFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThirdPartySipAccountWarningFragment.swift; sourceTree = ""; }; D74C9CF72ACACECE0021626A /* WelcomePage1Fragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WelcomePage1Fragment.swift; sourceTree = ""; }; @@ -162,6 +164,7 @@ D7D1698B2AE66FA500109A5C /* MagicSearchSingleton.swift */, D7C3650D2AF15BF200FE6142 /* PhotoPicker.swift */, D7C48DF32AFA66F900D938CB /* EditContactController.swift */, + D732A9082AFD235500DB42BA /* ShareSheetController.swift */, ); path = Utils; sourceTree = ""; @@ -532,6 +535,7 @@ D748BF2C2ACD82D2004844EB /* ThirdPartySipAccountLoginFragment.swift in Sources */, D74C9CF82ACACECE0021626A /* WelcomePage1Fragment.swift in Sources */, D7E6D0552AEBFCCE00A57AAF /* ContactsInnerFragment.swift in Sources */, + D732A9092AFD235500DB42BA /* ShareSheetController.swift in Sources */, D72343362AD037AF009AA24E /* ToastView.swift in Sources */, D7FB55112AD447FD00A5AB15 /* RegisterFragment.swift in Sources */, D7C48DF62AFCDF4700D938CB /* ContactInnerActionsFragment.swift in Sources */, diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactFragment.swift index aa8a09228..f1f427e2f 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactFragment.swift @@ -31,6 +31,7 @@ struct ContactFragment: View { @Binding var isShowDismissPopup: Bool @State private var showingSheet = false + @State private var showShareSheet = false var body: some View { if #available(iOS 16.0, *) { @@ -38,40 +39,56 @@ struct ContactFragment: View { ContactInnerFragment( contactViewModel: contactViewModel, editContactViewModel: editContactViewModel, - cnContact: CNContact(), - isShowDeletePopup: $isShowDeletePopup, + cnContact: CNContact(), + isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet, + showShareSheet: $showShareSheet, isShowDismissPopup: $isShowDismissPopup ) - .sheet(isPresented: $showingSheet) { - ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) - .presentationDetents([.fraction(0.2)]) - } + .sheet(isPresented: $showingSheet) { + ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) + .presentationDetents([.fraction(0.2)]) + } + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!) + .presentationDetents([.medium]) + .edgesIgnoringSafeArea(.bottom) + } } else { ContactInnerFragment( contactViewModel: contactViewModel, editContactViewModel: editContactViewModel, - cnContact: CNContact(), + cnContact: CNContact(), isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet, + showShareSheet: $showShareSheet, isShowDismissPopup: $isShowDismissPopup ) - .halfSheet(showSheet: $showingSheet) { - ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) - } onDismiss: {} + .halfSheet(showSheet: $showingSheet) { + ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) + } onDismiss: {} + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!) + .edgesIgnoringSafeArea(.bottom) + } } } else { ContactInnerFragment( contactViewModel: contactViewModel, editContactViewModel: editContactViewModel, - cnContact: CNContact(), + cnContact: CNContact(), isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet, + showShareSheet: $showShareSheet, isShowDismissPopup: $isShowDismissPopup ) - .halfSheet(showSheet: $showingSheet) { - ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) - } onDismiss: {} + .halfSheet(showSheet: $showingSheet) { + ContactListBottomSheet(contactViewModel: contactViewModel, showingSheet: $showingSheet) + } onDismiss: {} + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: MagicSearchSingleton.shared.lastSearch[contactViewModel.indexDisplayedFriend!].friend!) + .edgesIgnoringSafeArea(.bottom) + } } } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift index 0fbe4845b..ff8e3e2e7 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerActionsFragment.swift @@ -16,6 +16,7 @@ struct ContactInnerActionsFragment: View { @State private var informationIsOpen = true @Binding var showingSheet: Bool + @Binding var showShareSheet: Bool @Binding var isShowDeletePopup: Bool @Binding var isShowDismissPopup: Bool @@ -278,27 +279,6 @@ struct ContactInnerActionsFragment: View { } ) } - /* - Button { - } label: { - HStack { - Image("pencil-simple") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c600) - .frame(width: 25, height: 25) - - Text("Edit") - .default_text_style(styleSize: 14) - .frame(maxWidth: .infinity, alignment: .leading) - .lineLimit(1) - .fixedSize(horizontal: false, vertical: true) - Spacer() - } - .padding(.vertical, 15) - .padding(.horizontal, 20) - } - */ VStack { Divider() @@ -340,6 +320,7 @@ struct ContactInnerActionsFragment: View { .padding(.horizontal) Button { + showShareSheet.toggle() } label: { HStack { Image("share-network") @@ -453,6 +434,7 @@ struct ContactInnerActionsFragment: View { contactViewModel: ContactViewModel(), editContactViewModel: EditContactViewModel(), showingSheet: .constant(false), + showShareSheet: .constant(false), isShowDeletePopup: .constant(false), isShowDismissPopup: .constant(false), actionEditButton: {} diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift index 1a72c7c53..ac6a8e5cd 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactInnerFragment.swift @@ -37,6 +37,7 @@ struct ContactInnerFragment: View { @Binding var isShowDeletePopup: Bool @Binding var showingSheet: Bool + @Binding var showShareSheet: Bool @Binding var isShowDismissPopup: Bool var body: some View { @@ -122,6 +123,7 @@ struct ContactInnerFragment: View { case .success(let image): image .resizable() + .aspectRatio(contentMode: .fill) .frame(width: 100, height: 100) .clipShape(Circle()) case .failure: @@ -253,6 +255,7 @@ struct ContactInnerFragment: View { contactViewModel: contactViewModel, editContactViewModel: editContactViewModel, showingSheet: $showingSheet, + showShareSheet: $showShareSheet, isShowDeletePopup: $isShowDeletePopup, isShowDismissPopup: $isShowDismissPopup, actionEditButton: editNativeContact @@ -305,6 +308,7 @@ struct ContactInnerFragment: View { editContactViewModel: EditContactViewModel(), isShowDeletePopup: .constant(false), showingSheet: .constant(false), + showShareSheet: .constant(false), isShowDismissPopup: .constant(false) ) } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactListBottomSheet.swift b/Linphone/UI/Main/Contacts/Fragments/ContactListBottomSheet.swift index 29793747f..bbf9ac0cc 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactListBottomSheet.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactListBottomSheet.swift @@ -93,7 +93,12 @@ struct ContactListBottomSheet: View { if contactViewModel.stringToCopy.prefix(4) != "sip:" { Button { if #available(iOS 16.0, *) { - showingSheet.toggle() + if idiom != .pad { + showingSheet.toggle() + } else { + showingSheet.toggle() + dismiss() + } } else { showingSheet.toggle() dismiss() diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactsFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactsFragment.swift index e875bd037..ef48b5e84 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactsFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactsFragment.swift @@ -28,6 +28,7 @@ struct ContactsFragment: View { @Binding var isShowDeletePopup: Bool @State private var showingSheet = false + @State private var showShareSheet = false var body: some View { ZStack { @@ -35,20 +36,48 @@ struct ContactsFragment: View { if idiom != .pad { ContactsInnerFragment(contactViewModel: contactViewModel, showingSheet: $showingSheet) .sheet(isPresented: $showingSheet) { - ContactsListBottomSheet(contactViewModel: contactViewModel, isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet) + ContactsListBottomSheet( + contactViewModel: contactViewModel, + isShowDeletePopup: $isShowDeletePopup, + showingSheet: $showingSheet, + showShareSheet: $showShareSheet + ) .presentationDetents([.fraction(0.2)]) } + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: contactViewModel.selectedFriendToShare!) + .presentationDetents([.medium]) + .edgesIgnoringSafeArea(.bottom) + } } else { ContactsInnerFragment(contactViewModel: contactViewModel, showingSheet: $showingSheet) .halfSheet(showSheet: $showingSheet) { - ContactsListBottomSheet(contactViewModel: contactViewModel, isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet) + ContactsListBottomSheet( + contactViewModel: contactViewModel, + isShowDeletePopup: $isShowDeletePopup, + showingSheet: $showingSheet, + showShareSheet: $showShareSheet + ) } onDismiss: {} + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: contactViewModel.selectedFriendToShare!) + .edgesIgnoringSafeArea(.bottom) + } } } else { ContactsInnerFragment(contactViewModel: contactViewModel, showingSheet: $showingSheet) .halfSheet(showSheet: $showingSheet) { - ContactsListBottomSheet(contactViewModel: contactViewModel, isShowDeletePopup: $isShowDeletePopup, showingSheet: $showingSheet) + ContactsListBottomSheet( + contactViewModel: contactViewModel, + isShowDeletePopup: $isShowDeletePopup, + showingSheet: $showingSheet, + showShareSheet: $showShareSheet + ) } onDismiss: {} + .sheet(isPresented: $showShareSheet) { + ShareSheet(friendToShare: contactViewModel.selectedFriendToShare!) + .edgesIgnoringSafeArea(.bottom) + } } } } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactsListBottomSheet.swift b/Linphone/UI/Main/Contacts/Fragments/ContactsListBottomSheet.swift index 9ae204546..851eaef20 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactsListBottomSheet.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactsListBottomSheet.swift @@ -19,147 +19,169 @@ import SwiftUI import linphonesw +import Contacts struct ContactsListBottomSheet: View { + @Environment(\.dismiss) var dismiss + private var idiom: UIUserInterfaceIdiom { UIDevice.current.userInterfaceIdiom } - @ObservedObject var magicSearch = MagicSearchSingleton.shared - - @ObservedObject var contactViewModel: ContactViewModel - - @State private var orientation = UIDevice.current.orientation - - @Environment(\.dismiss) var dismiss + @ObservedObject var magicSearch = MagicSearchSingleton.shared + @ObservedObject var contactViewModel: ContactViewModel + + @State private var orientation = UIDevice.current.orientation @Binding var isShowDeletePopup: Bool - - @Binding var showingSheet: Bool - - var body: some View { - VStack(alignment: .leading) { - if idiom != .pad && (orientation == .landscapeLeft - || orientation == .landscapeRight - || UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) { - Spacer() - HStack { - Spacer() - Button("Close") { - if #available(iOS 16.0, *) { - showingSheet.toggle() - } else { - showingSheet.toggle() - dismiss() - } - } - } - .padding(.trailing) - } - - Spacer() - Button { - if contactViewModel.selectedFriend != nil { - contactViewModel.selectedFriend!.starred.toggle() - } - self.magicSearch.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) - - if #available(iOS 16.0, *) { - showingSheet.toggle() - } else { - showingSheet.toggle() - dismiss() - } - } label: { - HStack { + @Binding var showingSheet: Bool + @Binding var showShareSheet: Bool + + var body: some View { + VStack(alignment: .leading) { + if idiom != .pad && (orientation == .landscapeLeft + || orientation == .landscapeRight + || UIScreen.main.bounds.size.width > UIScreen.main.bounds.size.height) { + Spacer() + HStack { + Spacer() + Button("Close") { + if #available(iOS 16.0, *) { + showingSheet.toggle() + } else { + showingSheet.toggle() + dismiss() + } + } + } + .padding(.trailing) + } + + Spacer() + Button { + if contactViewModel.selectedFriend != nil { + contactViewModel.selectedFriend!.starred.toggle() + } + self.magicSearch.searchForContacts(sourceFlags: MagicSearch.Source.Friends.rawValue | MagicSearch.Source.LdapServers.rawValue) + + if #available(iOS 16.0, *) { + if idiom != .pad { + showingSheet.toggle() + } else { + showingSheet.toggle() + dismiss() + } + } else { + showingSheet.toggle() + dismiss() + } + } label: { + HStack { Image(contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true ? "heart-fill" : "heart") - .renderingMode(.template) - .resizable() + .renderingMode(.template) + .resizable() .foregroundStyle( contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true ? Color.redDanger500 : Color.grayMain2c500 ) - .frame(width: 25, height: 25, alignment: .leading) - Text(contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true - ? "Remove from favourites" - : "Add to favourites") - .default_text_style(styleSize: 16) - Spacer() - } - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 30) - .background(Color.gray100) - - VStack { - Divider() - } - .frame(maxWidth: .infinity) - - Button { - if #available(iOS 16.0, *) { - showingSheet.toggle() - } else { - showingSheet.toggle() - dismiss() - } - } label: { - HStack { - Image("share-network") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.grayMain2c500) - .frame(width: 25, height: 25, alignment: .leading) - Text("Share") - .default_text_style(styleSize: 16) - Spacer() - } - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 30) - .background(Color.gray100) - - VStack { - Divider() - } - .frame(maxWidth: .infinity) - - Button { - if contactViewModel.selectedFriend != nil { - isShowDeletePopup.toggle() - } + .frame(width: 25, height: 25, alignment: .leading) + Text(contactViewModel.selectedFriend != nil && contactViewModel.selectedFriend!.starred == true + ? "Remove from favourites" + : "Add to favourites") + .default_text_style(styleSize: 16) + Spacer() + } + .frame(maxHeight: .infinity) + } + .padding(.horizontal, 30) + .background(Color.gray100) + + VStack { + Divider() + } + .frame(maxWidth: .infinity) + + Button { + if #available(iOS 16.0, *) { + if idiom != .pad { + showingSheet.toggle() + } else { + showingSheet.toggle() + dismiss() + } + } else { + showingSheet.toggle() + dismiss() + } - if #available(iOS 16.0, *) { - showingSheet.toggle() - } else { - showingSheet.toggle() - dismiss() - } - } label: { - HStack { - Image("trash-simple") - .renderingMode(.template) - .resizable() - .foregroundStyle(Color.redDanger500) - .frame(width: 25, height: 25, alignment: .leading) - Text("Delete") - .foregroundStyle(Color.redDanger500) - .default_text_style(styleSize: 16) - Spacer() - } - .frame(maxHeight: .infinity) - } - .padding(.horizontal, 30) - .background(Color.gray100) - - } + contactViewModel.selectedFriendToShare = contactViewModel.selectedFriend + + DispatchQueue.global().asyncAfter(deadline: .now() + 0.5) { + showShareSheet.toggle() + } + + } label: { + HStack { + Image("share-network") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.grayMain2c500) + .frame(width: 25, height: 25, alignment: .leading) + Text("Share") + .default_text_style(styleSize: 16) + Spacer() + } + .frame(maxHeight: .infinity) + } + .padding(.horizontal, 30) + .background(Color.gray100) + + VStack { + Divider() + } + .frame(maxWidth: .infinity) + + Button { + if contactViewModel.selectedFriend != nil { + isShowDeletePopup.toggle() + } + + if #available(iOS 16.0, *) { + if idiom != .pad { + showingSheet.toggle() + } else { + showingSheet.toggle() + dismiss() + } + } else { + showingSheet.toggle() + dismiss() + } + } label: { + HStack { + Image("trash-simple") + .renderingMode(.template) + .resizable() + .foregroundStyle(Color.redDanger500) + .frame(width: 25, height: 25, alignment: .leading) + Text("Delete") + .foregroundStyle(Color.redDanger500) + .default_text_style(styleSize: 16) + Spacer() + } + .frame(maxHeight: .infinity) + } + .padding(.horizontal, 30) + .background(Color.gray100) + + } .background(Color.gray100) - .frame(maxWidth: .infinity) - .onRotate { newOrientation in - orientation = newOrientation - } + .frame(maxWidth: .infinity) + .onRotate { newOrientation in + orientation = newOrientation + } .onDisappear { contactViewModel.selectedFriend = nil } - } + } } diff --git a/Linphone/UI/Main/Contacts/Fragments/ContactsListFragment.swift b/Linphone/UI/Main/Contacts/Fragments/ContactsListFragment.swift index b4696b326..7b274e646 100644 --- a/Linphone/UI/Main/Contacts/Fragments/ContactsListFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/ContactsListFragment.swift @@ -72,6 +72,7 @@ struct ContactsListFragment: View { case .success(let image): image .resizable() + .aspectRatio(contentMode: .fill) .frame(width: 45, height: 45) .clipShape(Circle()) case .failure: diff --git a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift index 5d24c8f72..e7de05556 100644 --- a/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/EditContactFragment.swift @@ -137,6 +137,7 @@ struct EditContactFragment: View { case .success(let image): image .resizable() + .aspectRatio(contentMode: .fill) .frame(width: 100, height: 100) .clipShape(Circle()) case .failure: @@ -156,6 +157,7 @@ struct EditContactFragment: View { } else { Image(uiImage: selectedImage!) .resizable() + .aspectRatio(contentMode: .fill) .frame(width: 100, height: 100) .clipShape(Circle()) } diff --git a/Linphone/UI/Main/Contacts/Fragments/FavoriteContactsListFragment.swift b/Linphone/UI/Main/Contacts/Fragments/FavoriteContactsListFragment.swift index 0c0f9c3a6..0eb2fa566 100644 --- a/Linphone/UI/Main/Contacts/Fragments/FavoriteContactsListFragment.swift +++ b/Linphone/UI/Main/Contacts/Fragments/FavoriteContactsListFragment.swift @@ -48,6 +48,7 @@ struct FavoriteContactsListFragment: View { case .success(let image): image .resizable() + .aspectRatio(contentMode: .fill) .frame(width: 45, height: 45) .clipShape(Circle()) case .failure: diff --git a/Linphone/UI/Main/Contacts/ViewModel/ContactViewModel.swift b/Linphone/UI/Main/Contacts/ViewModel/ContactViewModel.swift index 747a28279..a3f8443c7 100644 --- a/Linphone/UI/Main/Contacts/ViewModel/ContactViewModel.swift +++ b/Linphone/UI/Main/Contacts/ViewModel/ContactViewModel.swift @@ -26,6 +26,7 @@ class ContactViewModel: ObservableObject { var stringToCopy: String = "" var selectedFriend: Friend? + var selectedFriendToShare: Friend? var selectedFriendToDelete: Friend? private var magicSearch = MagicSearchSingleton.shared diff --git a/Linphone/Utils/ShareSheetController.swift b/Linphone/Utils/ShareSheetController.swift new file mode 100644 index 000000000..8a512713c --- /dev/null +++ b/Linphone/Utils/ShareSheetController.swift @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2010-2023 Belledonne Communications SARL. + * + * This file is part of linphone-iphone + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +import Foundation +import SwiftUI +import linphonesw + +struct ShareSheet: UIViewControllerRepresentable { + typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void + + let friendToShare: Friend + var activityItems: [Any] = [] + let applicationActivities: [UIActivity]? = nil + let excludedActivityTypes: [UIActivity.ActivityType]? = nil + let callback: Callback? = nil + + func makeUIViewController(context: Context) -> UIActivityViewController { + 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 controller = UIActivityViewController( + activityItems: activityItems, + applicationActivities: applicationActivities) + controller.excludedActivityTypes = excludedActivityTypes + controller.completionWithItemsHandler = callback + return controller + } + + func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) { + // nothing to do here + } + + func shareContacts(friend: String) { + + let directoryURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first + + if directoryURL != nil { + let filename = NSUUID().uuidString + + let fileURL = directoryURL! + .appendingPathComponent(filename) + .appendingPathExtension("vcf") + + try? friend.write(to: fileURL, atomically: false, encoding: String.Encoding.utf8) + } + + /* + let activityViewController = UIActivityViewController( + activityItems: [fileURL], + applicationActivities: nil + ) + */ + } +}