forked from mirrors/linphone-iphone
Merge branch 'master'
Conflicts: Linphone/Contacts/ContactsManager.swift Linphone/LinphoneApp.swift Linphone/UI/Main/ContentView.swift
This commit is contained in:
commit
19da1739f0
8 changed files with 254 additions and 261 deletions
|
|
@ -7,7 +7,6 @@
|
|||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
886500223A8E518D3EE5FCB7 /* Pods_Linphone.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A334B8FDAD2893691A734BE /* Pods_Linphone.framework */; };
|
||||
D706BA822ADD72D100278F45 /* DeviceRotationViewModifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */; };
|
||||
D70C93DE2AC2D0F60063CA3B /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */; };
|
||||
D717071E2AC5922E0037746F /* ColorExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = D717071D2AC5922E0037746F /* ColorExtension.swift */; };
|
||||
|
|
@ -71,8 +70,6 @@
|
|||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
1A334B8FDAD2893691A734BE /* Pods_Linphone.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Linphone.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
1DE4CD5FD6E1F01639F27E3B /* Pods-Linphone.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.release.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.release.xcconfig"; sourceTree = "<group>"; };
|
||||
D706BA812ADD72D100278F45 /* DeviceRotationViewModifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DeviceRotationViewModifier.swift; sourceTree = "<group>"; };
|
||||
D70C93DD2AC2D0F60063CA3B /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = "<group>"; };
|
||||
D717071D2AC5922E0037746F /* ColorExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorExtension.swift; sourceTree = "<group>"; };
|
||||
|
|
@ -136,7 +133,6 @@
|
|||
D7E6D0542AEBFCCE00A57AAF /* ContactsInnerFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactsInnerFragment.swift; sourceTree = "<group>"; };
|
||||
D7EAACCE2AD6ED8000AA6A8A /* PermissionsFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PermissionsFragment.swift; sourceTree = "<group>"; };
|
||||
D7FB55102AD447FD00A5AB15 /* RegisterFragment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegisterFragment.swift; sourceTree = "<group>"; };
|
||||
FB718F405DAF7B9993AEB878 /* Pods-Linphone.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Linphone.debug.xcconfig"; path = "Target Support Files/Pods-Linphone/Pods-Linphone.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
|
@ -144,26 +140,15 @@
|
|||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
886500223A8E518D3EE5FCB7 /* Pods_Linphone.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
1CD95087B17CAD149119B7C2 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
1A334B8FDAD2893691A734BE /* Pods_Linphone.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
A31AF2AB8C6A3D7B7EA3B424 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FB718F405DAF7B9993AEB878 /* Pods-Linphone.debug.xcconfig */,
|
||||
1DE4CD5FD6E1F01639F27E3B /* Pods-Linphone.release.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -187,7 +172,6 @@
|
|||
D719ABB52ABC67BF00B41C10 /* Linphone */,
|
||||
D719ABB42ABC67BF00B41C10 /* Products */,
|
||||
A31AF2AB8C6A3D7B7EA3B424 /* Pods */,
|
||||
1CD95087B17CAD149119B7C2 /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -422,12 +406,10 @@
|
|||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D719ABC22ABC67BF00B41C10 /* Build configuration list for PBXNativeTarget "Linphone" */;
|
||||
buildPhases = (
|
||||
BE9432280D0A11AA770A50FD /* [CP] Check Pods Manifest.lock */,
|
||||
D719ABAF2ABC67BF00B41C10 /* Sources */,
|
||||
D719ABB02ABC67BF00B41C10 /* Frameworks */,
|
||||
D719ABB12ABC67BF00B41C10 /* Resources */,
|
||||
D7FB55122AD53FE200A5AB15 /* Run Script */,
|
||||
D5CA1ECD620857DB91E334A5 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
|
@ -491,45 +473,6 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
BE9432280D0A11AA770A50FD /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Linphone-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D5CA1ECD620857DB91E334A5 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Linphone/Pods-Linphone-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
D7FB55122AD53FE200A5AB15 /* Run Script */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
|
@ -617,6 +560,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
|
|
@ -677,6 +621,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_ASSET_SYMBOLS = NO;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
|
|
@ -728,7 +673,6 @@
|
|||
};
|
||||
D719ABC32ABC67BF00B41C10 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FB718F405DAF7B9993AEB878 /* Pods-Linphone.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
|
|
@ -773,7 +717,6 @@
|
|||
};
|
||||
D719ABC42ABC67BF00B41C10 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 1DE4CD5FD6E1F01639F27E3B /* Pods-Linphone.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
|
|
|
|||
|
|
@ -40,16 +40,16 @@ final class ContactsManager: ObservableObject {
|
|||
}
|
||||
|
||||
func fetchContacts() {
|
||||
DispatchQueue.global().async {
|
||||
if self.coreContext.mCore.globalState == GlobalState.Shutdown || self.coreContext.mCore.globalState == GlobalState.Off {
|
||||
coreContext.doOnCoreQueue { core in
|
||||
if core.globalState == GlobalState.Shutdown || core.globalState == GlobalState.Off {
|
||||
print("$TAG Core is being stopped or already destroyed, abort")
|
||||
} else {
|
||||
print("$TAG ${friends.size} friends created")
|
||||
|
||||
self.friendList = self.coreContext.mCore.getFriendListByName(name: self.nativeAddressBookFriendList)
|
||||
self.friendList = core.getFriendListByName(name: self.nativeAddressBookFriendList)
|
||||
if self.friendList == nil {
|
||||
do {
|
||||
self.friendList = try self.coreContext.mCore.createFriendList()
|
||||
self.friendList = try core.createFriendList()
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ final class ContactsManager: ObservableObject {
|
|||
self.friendList!.databaseStorageEnabled = false // We don't want to store local address-book in DB
|
||||
|
||||
self.friendList!.displayName = self.nativeAddressBookFriendList
|
||||
self.coreContext.mCore.addFriendList(list: self.friendList!)
|
||||
core.addFriendList(list: self.friendList!)
|
||||
} else {
|
||||
print(
|
||||
"$TAG Friend list [$LINPHONE_ADDRESS_BOOK_FRIEND_LIST] found, removing existing friends if any"
|
||||
|
|
@ -73,10 +73,10 @@ final class ContactsManager: ObservableObject {
|
|||
}
|
||||
}
|
||||
|
||||
self.linphoneFriendList = self.coreContext.mCore.getFriendListByName(name: self.linphoneAddressBookFirendList)
|
||||
self.linphoneFriendList = core.getFriendListByName(name: self.linphoneAddressBookFirendList)
|
||||
if self.linphoneFriendList == nil {
|
||||
do {
|
||||
self.linphoneFriendList = try self.coreContext.mCore.createFriendList()
|
||||
self.linphoneFriendList = try core.createFriendList()
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
}
|
||||
|
|
@ -90,7 +90,7 @@ final class ContactsManager: ObservableObject {
|
|||
self.linphoneFriendList!.databaseStorageEnabled = true
|
||||
|
||||
self.linphoneFriendList!.displayName = self.linphoneAddressBookFirendList
|
||||
self.coreContext.mCore.addFriendList(list: self.linphoneFriendList!)
|
||||
core.addFriendList(list: self.linphoneFriendList!)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -200,66 +200,69 @@ final class ContactsManager: ObservableObject {
|
|||
}
|
||||
|
||||
func saveFriend(result: String, contact: Contact, existingFriend: Friend?) -> Friend? {
|
||||
do {
|
||||
let friend = (existingFriend != nil) ? existingFriend : try self.coreContext.mCore.createFriend()
|
||||
|
||||
if friend != nil {
|
||||
friend!.edit()
|
||||
|
||||
self.coreContext.doOnCoreQueue() { core in
|
||||
do {
|
||||
let friend = (existingFriend != nil) ? existingFriend : try core.createFriend()
|
||||
|
||||
friend!.nativeUri = contact.identifier
|
||||
|
||||
try friend!.setName(newValue: contact.firstName + " " + contact.lastName)
|
||||
|
||||
let friendvCard = friend!.vcard
|
||||
|
||||
if friendvCard != nil {
|
||||
friendvCard!.givenName = contact.firstName
|
||||
friendvCard!.familyName = contact.lastName
|
||||
}
|
||||
|
||||
friend!.organization = contact.organizationName
|
||||
|
||||
var friendAddresses: [Address] = []
|
||||
friend?.addresses.forEach({ address in
|
||||
friend?.removeAddress(address: address)
|
||||
})
|
||||
contact.sipAddresses.forEach { sipAddress in
|
||||
let address = self.coreContext.mCore.interpretUrl(url: sipAddress, applyInternationalPrefix: true)
|
||||
if friend != nil {
|
||||
friend!.edit()
|
||||
|
||||
if address != nil && ((friendAddresses.firstIndex(where: {$0.asString() == address?.asString()})) == nil) {
|
||||
friend!.addAddress(address: address!)
|
||||
friendAddresses.append(address!)
|
||||
friend!.nativeUri = contact.identifier
|
||||
|
||||
try friend!.setName(newValue: contact.firstName + " " + contact.lastName)
|
||||
|
||||
let friendvCard = friend!.vcard
|
||||
|
||||
if friendvCard != nil {
|
||||
friendvCard!.givenName = contact.firstName
|
||||
friendvCard!.familyName = contact.lastName
|
||||
}
|
||||
}
|
||||
|
||||
var friendPhoneNumbers: [PhoneNumber] = []
|
||||
friend?.phoneNumbersWithLabel.forEach({ phoneNumber in
|
||||
friend?.removePhoneNumberWithLabel(phoneNumber: phoneNumber)
|
||||
})
|
||||
contact.phoneNumbers.forEach { phone in
|
||||
do {
|
||||
if (friendPhoneNumbers.firstIndex(where: {$0.num == phone.num})) == nil {
|
||||
let labelDrop = String(phone.numLabel.dropFirst(4).dropLast(4))
|
||||
let phoneNumber = try Factory.Instance.createFriendPhoneNumber(phoneNumber: phone.num, label: labelDrop)
|
||||
friend!.addPhoneNumberWithLabel(phoneNumber: phoneNumber)
|
||||
friendPhoneNumbers.append(phone)
|
||||
|
||||
friend!.organization = contact.organizationName
|
||||
|
||||
var friendAddresses: [Address] = []
|
||||
friend?.addresses.forEach({ address in
|
||||
friend?.removeAddress(address: address)
|
||||
})
|
||||
contact.sipAddresses.forEach { sipAddress in
|
||||
let address = core.interpretUrl(url: sipAddress, applyInternationalPrefix: true)
|
||||
|
||||
if address != nil && ((friendAddresses.firstIndex(where: {$0.asString() == address?.asString()})) == nil) {
|
||||
friend!.addAddress(address: address!)
|
||||
friendAddresses.append(address!)
|
||||
}
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
}
|
||||
|
||||
var friendPhoneNumbers: [PhoneNumber] = []
|
||||
friend?.phoneNumbersWithLabel.forEach({ phoneNumber in
|
||||
friend?.removePhoneNumberWithLabel(phoneNumber: phoneNumber)
|
||||
})
|
||||
contact.phoneNumbers.forEach { phone in
|
||||
do {
|
||||
if (friendPhoneNumbers.firstIndex(where: {$0.num == phone.num})) == nil {
|
||||
let labelDrop = String(phone.numLabel.dropFirst(4).dropLast(4))
|
||||
let phoneNumber = try Factory.Instance.createFriendPhoneNumber(phoneNumber: phone.num, label: labelDrop)
|
||||
friend!.addPhoneNumberWithLabel(phoneNumber: phoneNumber)
|
||||
friendPhoneNumbers.append(phone)
|
||||
}
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
}
|
||||
}
|
||||
|
||||
friend!.photo = "file:/" + result
|
||||
|
||||
friend!.organization = contact.organizationName
|
||||
friend!.jobTitle = contact.jobTitle
|
||||
|
||||
friend!.done()
|
||||
return friend
|
||||
}
|
||||
|
||||
friend!.photo = "file:/" + result
|
||||
|
||||
friend!.organization = contact.organizationName
|
||||
friend!.jobTitle = contact.jobTitle
|
||||
|
||||
friend!.done()
|
||||
return friend
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
return nil
|
||||
}
|
||||
} catch let error {
|
||||
print("Failed to enumerate contact", error)
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,74 +17,104 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// swiftlint:disable large_tuple
|
||||
import linphonesw
|
||||
import Combine
|
||||
|
||||
final class CoreContext: ObservableObject {
|
||||
|
||||
static let shared = CoreContext()
|
||||
|
||||
var mCore: Core!
|
||||
var mRegistrationDelegate: CoreDelegate!
|
||||
var mConfigurationDelegate: CoreDelegate!
|
||||
|
||||
var coreVersion: String = Core.getVersion
|
||||
@Published var loggedIn: Bool = false
|
||||
@Published var loggingInProgress: Bool = false
|
||||
@Published var toastMessage: String = ""
|
||||
@Published var defaultAccount: Account?
|
||||
|
||||
private var mCore: Core!
|
||||
private var mIteratePublisher: AnyCancellable?
|
||||
|
||||
private init() {}
|
||||
|
||||
func initialiseCore() async throws {
|
||||
func doOnCoreQueue(synchronous : Bool = false, lambda: @escaping (Core) -> Void) {
|
||||
if synchronous {
|
||||
coreQueue.sync {
|
||||
lambda(self.mCore)
|
||||
}
|
||||
} else {
|
||||
coreQueue.async {
|
||||
lambda(self.mCore)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func initialiseCore() throws {
|
||||
LoggingService.Instance.logLevel = LogLevel.Debug
|
||||
|
||||
let factory = Factory.Instance
|
||||
let configDir = factory.getConfigDir(context: nil)
|
||||
try? mCore = Factory.Instance.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
|
||||
mCore.friendsDatabasePath = "\(configDir)/friends.db"
|
||||
|
||||
try? mCore.start()
|
||||
|
||||
// Create a Core listener to listen for the callback we need
|
||||
// In this case, we want to know about the account registration status
|
||||
|
||||
mRegistrationDelegate =
|
||||
CoreDelegateStub(
|
||||
onConfiguringStatus: {(_: Core, state: Config.ConfiguringState, message: String) in
|
||||
NSLog("New configuration state is \(state) = \(message)\n")
|
||||
if state == .Successful {
|
||||
coreQueue.async {
|
||||
let configDir = Factory.Instance.getConfigDir(context: nil)
|
||||
try? self.mCore = Factory.Instance.createCore(configPath: "\(configDir)/MyConfig", factoryConfigPath: "", systemContext: nil)
|
||||
self.mCore.autoIterateEnabled = false
|
||||
self.mCore.friendsDatabasePath = "\(configDir)/friends.db"
|
||||
|
||||
self.mCore.publisher?.onGlobalStateChanged?.postOnMainQueue { (cbVal: (core: Core, state: GlobalState, message: String)) in
|
||||
if cbVal.state == GlobalState.On {
|
||||
self.defaultAccount = self.mCore.defaultAccount
|
||||
} else if cbVal.state == GlobalState.Off {
|
||||
self.defaultAccount = nil
|
||||
}
|
||||
}
|
||||
try? self.mCore.start()
|
||||
|
||||
// Create a Core listener to listen for the callback we need
|
||||
// In this case, we want to know about the account registration status
|
||||
self.mCore.publisher?.onConfiguringStatus?.postOnMainQueue { (cbVal: (core: Core, status: Config.ConfiguringState, message: String)) in
|
||||
NSLog("New configuration state is \(cbVal.status) = \(cbVal.message)\n")
|
||||
if cbVal.status == Config.ConfiguringState.Successful {
|
||||
self.toastMessage = "Successful"
|
||||
} else {
|
||||
self.toastMessage = "Failed"
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
onAccountRegistrationStateChanged: {(_: Core, account: Account, state: RegistrationState, message: String) in
|
||||
self.mCore.publisher?.onAccountRegistrationStateChanged?.postOnMainQueue { (cbVal: (core: Core, account: Account, state: RegistrationState, message: String)) in
|
||||
// If account has been configured correctly, we will go through Progress and Ok states
|
||||
// Otherwise, we will be Failed.
|
||||
NSLog("New registration state is \(state) for user id \( String(describing: account.params?.identityAddress?.asString())) = \(message)\n")
|
||||
if state == .Ok {
|
||||
NSLog("New registration state is \(cbVal.state) for user id " +
|
||||
"\( String(describing: cbVal.account.params?.identityAddress?.asString())) = \(cbVal.message)\n")
|
||||
if cbVal.state == .Ok {
|
||||
self.loggingInProgress = false
|
||||
self.loggedIn = true
|
||||
} else if state == .Progress {
|
||||
} else if cbVal.state == .Progress {
|
||||
self.loggingInProgress = true
|
||||
} else {
|
||||
self.toastMessage = "Registration failed"
|
||||
self.loggingInProgress = false
|
||||
self.loggedIn = false
|
||||
|
||||
let params = account.params
|
||||
}
|
||||
}.postOnCoreQueue { (cbVal: (core: Core, account: Account, state: RegistrationState, message: String)) in
|
||||
// If registration failed, remove account from core
|
||||
if cbVal.state != .Ok && cbVal.state != .Progress {
|
||||
let params = cbVal.account.params
|
||||
let clonedParams = params?.clone()
|
||||
clonedParams?.registerEnabled = false
|
||||
account.params = clonedParams
|
||||
cbVal.account.params = clonedParams
|
||||
|
||||
self.mCore!.removeAccount(account: account)
|
||||
self.mCore!.clearAccounts()
|
||||
self.mCore!.clearAllAuthInfo()
|
||||
cbVal.core.removeAccount(account: cbVal.account)
|
||||
cbVal.core.clearAccounts()
|
||||
cbVal.core.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
mCore.addDelegate(delegate: mRegistrationDelegate)
|
||||
|
||||
self.mIteratePublisher = Timer.publish(every: 0.02, on: .main, in: .common)
|
||||
.autoconnect()
|
||||
.receive(on: coreQueue)
|
||||
.sink { _ in
|
||||
self.mCore.iterate()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// swiftlint:enable large_tuple
|
||||
|
|
|
|||
|
|
@ -32,10 +32,10 @@ struct LinphoneApp: App {
|
|||
if isActive {
|
||||
if !sharedMainViewModel.welcomeViewDisplayed {
|
||||
WelcomeView(sharedMainViewModel: sharedMainViewModel)
|
||||
} else if coreContext.mCore.defaultAccount == nil || sharedMainViewModel.displayProfileMode {
|
||||
} else if coreContext.defaultAccount == nil || sharedMainViewModel.displayProfileMode {
|
||||
AssistantView(sharedMainViewModel: sharedMainViewModel)
|
||||
.toast(isShowing: $coreContext.toastMessage)
|
||||
} else if coreContext.mCore.defaultAccount != nil {
|
||||
} else if coreContext.defaultAccount != nil {
|
||||
ContentView(contactViewModel: ContactViewModel(), editContactViewModel: EditContactViewModel(), historyViewModel: HistoryViewModel())
|
||||
.toast(isShowing: $coreContext.toastMessage)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ struct SplashScreen: View {
|
|||
.ignoresSafeArea(.all)
|
||||
.onAppear {
|
||||
Task {
|
||||
try await coreContext.initialiseCore()
|
||||
try coreContext.initialiseCore()
|
||||
withAnimation {
|
||||
self.isActive = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,83 +33,95 @@ class AccountLoginViewModel: ObservableObject {
|
|||
init() {}
|
||||
|
||||
func login() {
|
||||
do {
|
||||
// Get the transport protocol to use.
|
||||
// TLS is strongly recommended
|
||||
// Only use UDP if you don't have the choice
|
||||
var transport: TransportType
|
||||
if transportType == "TLS" {
|
||||
transport = TransportType.Tls
|
||||
} else if transportType == "TCP" {
|
||||
transport = TransportType.Tcp
|
||||
} else { transport = TransportType.Udp }
|
||||
|
||||
// To configure a SIP account, we need an Account object and an AuthInfo object
|
||||
// The first one is how to connect to the proxy server, the second one stores the credentials
|
||||
|
||||
// The auth info can be created from the Factory as it's only a data class
|
||||
// userID is set to null as it's the same as the username in our case
|
||||
// ha1 is set to null as we are using the clear text password. Upon first register, the hash will be computed automatically.
|
||||
// The realm will be determined automatically from the first register, as well as the algorithm
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: username, userid: "", passwd: passwd, ha1: "", realm: "", domain: domain)
|
||||
|
||||
// Account object replaces deprecated ProxyConfig object
|
||||
// Account object is configured through an AccountParams object that we can obtain from the Core
|
||||
|
||||
let accountParams = try coreContext.mCore!.createAccountParams()
|
||||
|
||||
// A SIP account is identified by an identity address that we can construct from the username and domain
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + username + "@" + domain))
|
||||
try accountParams.setIdentityaddress(newValue: identity)
|
||||
|
||||
// We also need to configure where the proxy server is located
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + domain))
|
||||
|
||||
// We use the Address object to easily set the transport protocol
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
// And we ensure the account will start the registration process
|
||||
accountParams.registerEnabled = true
|
||||
|
||||
// Now that our AccountParams is configured, we can create the Account object
|
||||
let account = try coreContext.mCore!.createAccount(params: accountParams)
|
||||
|
||||
// Now let's add our objects to the Core
|
||||
coreContext.mCore!.addAuthInfo(info: authInfo)
|
||||
try coreContext.mCore!.addAccount(account: account)
|
||||
|
||||
// Also set the newly added account as default
|
||||
coreContext.mCore!.defaultAccount = account
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
coreContext.doOnCoreQueue { core in
|
||||
do {
|
||||
// Get the transport protocol to use.
|
||||
// TLS is strongly recommended
|
||||
// Only use UDP if you don't have the choice
|
||||
var transport: TransportType
|
||||
if self.transportType == "TLS" {
|
||||
transport = TransportType.Tls
|
||||
} else if self.transportType == "TCP" {
|
||||
transport = TransportType.Tcp
|
||||
} else { transport = TransportType.Udp }
|
||||
|
||||
// To configure a SIP account, we need an Account object and an AuthInfo object
|
||||
// The first one is how to connect to the proxy server, the second one stores the credentials
|
||||
|
||||
// The auth info can be created from the Factory as it's only a data class
|
||||
// userID is set to null as it's the same as the username in our case
|
||||
// ha1 is set to null as we are using the clear text password. Upon first register, the hash will be computed automatically.
|
||||
// The realm will be determined automatically from the first register, as well as the algorithm
|
||||
let authInfo = try Factory.Instance.createAuthInfo(username: self.username, userid: "", passwd: self.passwd, ha1: "", realm: "", domain: self.domain)
|
||||
|
||||
// Account object replaces deprecated ProxyConfig object
|
||||
// Account object is configured through an AccountParams object that we can obtain from the Core
|
||||
|
||||
let accountParams = try core.createAccountParams()
|
||||
|
||||
// A SIP account is identified by an identity address that we can construct from the username and domain
|
||||
let identity = try Factory.Instance.createAddress(addr: String("sip:" + self.username + "@" + self.domain))
|
||||
try accountParams.setIdentityaddress(newValue: identity)
|
||||
|
||||
// We also need to configure where the proxy server is located
|
||||
let address = try Factory.Instance.createAddress(addr: String("sip:" + self.domain))
|
||||
|
||||
// We use the Address object to easily set the transport protocol
|
||||
try address.setTransport(newValue: transport)
|
||||
try accountParams.setServeraddress(newValue: address)
|
||||
// And we ensure the account will start the registration process
|
||||
accountParams.registerEnabled = true
|
||||
|
||||
// Now that our AccountParams is configured, we can create the Account object
|
||||
let account = try core.createAccount(params: accountParams)
|
||||
|
||||
// Now let's add our objects to the Core
|
||||
core.addAuthInfo(info: authInfo)
|
||||
try core.addAccount(account: account)
|
||||
|
||||
// Also set the newly added account as default
|
||||
core.defaultAccount = account
|
||||
DispatchQueue.main.async {
|
||||
self.coreContext.defaultAccount = account
|
||||
}
|
||||
|
||||
} catch { NSLog(error.localizedDescription) }
|
||||
}
|
||||
}
|
||||
|
||||
func unregister() {
|
||||
// Here we will disable the registration of our Account
|
||||
if let account = coreContext.mCore!.defaultAccount {
|
||||
|
||||
let params = account.params
|
||||
// Returned params object is const, so to make changes we first need to clone it
|
||||
let clonedParams = params?.clone()
|
||||
|
||||
// Now let's make our changes
|
||||
clonedParams?.registerEnabled = false
|
||||
|
||||
// And apply them
|
||||
account.params = clonedParams
|
||||
coreContext.doOnCoreQueue { core in
|
||||
// Here we will disable the registration of our Account
|
||||
if let account = core.defaultAccount {
|
||||
|
||||
let params = account.params
|
||||
// Returned params object is const, so to make changes we first need to clone it
|
||||
let clonedParams = params?.clone()
|
||||
|
||||
// Now let's make our changes
|
||||
clonedParams?.registerEnabled = false
|
||||
|
||||
// And apply them
|
||||
account.params = clonedParams
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func delete() {
|
||||
// To completely remove an Account
|
||||
if let account = coreContext.mCore!.defaultAccount {
|
||||
coreContext.mCore!.removeAccount(account: account)
|
||||
|
||||
// To remove all accounts use
|
||||
coreContext.mCore!.clearAccounts()
|
||||
|
||||
// Same for auth info
|
||||
coreContext.mCore!.clearAllAuthInfo()
|
||||
coreContext.doOnCoreQueue { core in
|
||||
// To completely remove an Account
|
||||
if let account = core.defaultAccount {
|
||||
core.removeAccount(account: account)
|
||||
DispatchQueue.main.async {
|
||||
self.coreContext.defaultAccount = nil
|
||||
}
|
||||
|
||||
// To remove all accounts use
|
||||
core.clearAccounts()
|
||||
|
||||
// Same for auth info
|
||||
core.clearAllAuthInfo()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,14 +70,11 @@ class Coordinator: NSObject, AVCaptureMetadataOutputObjectsDelegate {
|
|||
if let url = NSURL(string: result) {
|
||||
if UIApplication.shared.canOpenURL(url as URL) {
|
||||
lastResult = result
|
||||
do {
|
||||
try coreContext.mCore.setProvisioninguri(newValue: result)
|
||||
coreContext.mCore.stop()
|
||||
try coreContext.mCore.start()
|
||||
} catch {
|
||||
|
||||
coreContext.doOnCoreQueue { core in
|
||||
try? core.setProvisioninguri(newValue: result)
|
||||
core.stop()
|
||||
try? core.start()
|
||||
}
|
||||
|
||||
} else {
|
||||
coreContext.toastMessage = "Invalide URI"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,9 +25,8 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
private var coreContext = CoreContext.shared
|
||||
|
||||
private var magicSearch: MagicSearch!
|
||||
var magicSearchDelegate: MagicSearchDelegate?
|
||||
|
||||
@objc var currentFilter: String = ""
|
||||
var currentFilter: String = ""
|
||||
var previousFilter: String?
|
||||
|
||||
var needUpdateLastSearchContacts = false
|
||||
|
|
@ -35,36 +34,45 @@ final class MagicSearchSingleton: ObservableObject {
|
|||
@Published var lastSearch: [SearchResult] = []
|
||||
|
||||
private var limitSearchToLinphoneAccounts = true
|
||||
|
||||
@Published var allContact = false
|
||||
private var domainDefaultAccount = ""
|
||||
|
||||
@Published var allContact = false
|
||||
private var domainDefaultAccount = ""
|
||||
|
||||
private init() {
|
||||
domainDefaultAccount = coreContext.mCore.defaultAccount!.params!.domain!
|
||||
|
||||
magicSearch = try? coreContext.mCore.createMagicSearch()
|
||||
magicSearch.limitedSearch = false
|
||||
|
||||
magicSearchDelegate = MagicSearchDelegateStub(onSearchResultsReceived: { (magicSearch: MagicSearch) in
|
||||
self.needUpdateLastSearchContacts = true
|
||||
self.lastSearch = magicSearch.lastSearch
|
||||
})
|
||||
|
||||
magicSearch.addDelegate(delegate: magicSearchDelegate!)
|
||||
coreContext.doOnCoreQueue{ core in
|
||||
self.domainDefaultAccount = core.defaultAccount?.params?.domain ?? ""
|
||||
|
||||
self.magicSearch = try? core.createMagicSearch()
|
||||
self.magicSearch.limitedSearch = false
|
||||
|
||||
self.magicSearch.publisher?.onSearchResultsReceived?.postOnMainQueue { (magicSearch: MagicSearch) in
|
||||
self.needUpdateLastSearchContacts = true
|
||||
self.lastSearch = magicSearch.lastSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func searchForContacts(sourceFlags: Int) {
|
||||
if let oldFilter = previousFilter {
|
||||
if oldFilter.count > currentFilter.count || oldFilter != currentFilter {
|
||||
magicSearch.resetSearchCache()
|
||||
coreContext.doOnCoreQueue{ core in
|
||||
var needResetCache = false
|
||||
|
||||
DispatchQueue.main.sync {
|
||||
if let oldFilter = self.previousFilter {
|
||||
if oldFilter.count > self.currentFilter.count || oldFilter != self.currentFilter {
|
||||
needResetCache = true
|
||||
}
|
||||
}
|
||||
self.previousFilter = self.currentFilter
|
||||
}
|
||||
if needResetCache {
|
||||
self.magicSearch.resetSearchCache()
|
||||
}
|
||||
|
||||
self.magicSearch.getContactsListAsync(
|
||||
filter: self.currentFilter,
|
||||
domain: self.allContact ? "" : self.domainDefaultAccount,
|
||||
sourceFlags: sourceFlags,
|
||||
aggregation: MagicSearch.Aggregation.Friend)
|
||||
}
|
||||
previousFilter = currentFilter
|
||||
|
||||
magicSearch.getContactsListAsync(
|
||||
filter: currentFilter,
|
||||
domain: allContact ? "" : domainDefaultAccount,
|
||||
sourceFlags: sourceFlags,
|
||||
aggregation: MagicSearch.Aggregation.Friend)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue