Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 9 additions & 24 deletions packages/react-native-callingx/ios/CallingxImpl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ import stream_react_native_webrtc
if CallingxImpl.sharedProvider == nil {
CallingxImpl.sharedProvider = CXProvider(configuration: Settings.getProviderConfiguration())
}

callKeepCallController = CXCallController()

callKeepProvider = CallingxImpl.sharedProvider
callKeepProvider?.setDelegate(nil, queue: nil)
Expand All @@ -128,7 +130,8 @@ import stream_react_native_webrtc

// MARK: - Class Methods
@objc public static func initializeIfNeeded() {
_ = getSharedInstance() // ensures the shared instance is created and CXProvider delegate is set
_ = getSharedInstance() // ensures the shared instance is created and CXProvider delegate is set
CallingxImpl.sharedProvider?.configuration = Settings.getProviderConfiguration()
}

@objc public static func reportNewIncomingCall(
Expand Down Expand Up @@ -379,29 +382,8 @@ import stream_react_native_webrtc

// MARK: - Setup Methods
@objc public func setup(options: [String: Any]) {
callKeepCallController = CXCallController()

Settings.setSettings(options)

// This is mostly needed for very first setup, as we need to override the default
// provider configuration which is set in the constructor.
// IMPORTANT: We override the CXProvider instance only when there are no calls in
// flight, otherwise we'd destroy CallKit state/events for a live call. We check our
// own storage rather than CXCallObserver here: the observer trails registration and
// can briefly report empty (e.g. a VoIP-push call reported just before setup runs),
// which would wrongly tear down the provider mid-call.
if (CallingxImpl.uuidStorage?.count() ?? 0) == 0 {
let oldProvider = CallingxImpl.sharedProvider
let newProvider = CXProvider(configuration: Settings.getProviderConfiguration())
newProvider.setDelegate(self, queue: nil)

CallingxImpl.sharedProvider = newProvider
callKeepProvider = newProvider

oldProvider?.setDelegate(nil, queue: nil)
oldProvider?.invalidate()
}

CallingxImpl.sharedProvider?.configuration = Settings.getProviderConfiguration()
isSetup = true
}

Expand Down Expand Up @@ -615,10 +597,13 @@ import stream_react_native_webrtc
return
}

CallingxImpl.sharedProvider?.configuration = Settings.getProviderConfiguration()
Comment thread
coderabbitai[bot] marked this conversation as resolved.

let call = storage.getOrCreateCall(forCid: callId, isOutgoing: true)
call.markStartedConnecting() // outgoing: will be reported via reportOutgoingCall(startedConnectingAt:)

let handleType = Settings.getHandleType("generic")
let handleTypeString = Settings.getSettings()["handleType"] as? String
let handleType = Settings.getHandleType(handleTypeString ?? "generic")
let callHandle = CXHandle(type: handleType, value: phoneNumber)
let startCallAction = CXStartCallAction(call: call.uuid, handle: callHandle)
startCallAction.isVideo = hasVideo
Expand Down
29 changes: 21 additions & 8 deletions packages/react-native-callingx/ios/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,36 @@ import UIKit
@objcMembers public class Settings: NSObject {
private static let settingsKey = "CallingxSettings"

// In-memory cache of the settings dictionary
private static var cachedSettings: [String: Any]?
private static let cacheQueue = DispatchQueue(label: "io.getstream.callingx.settings")

public static func getSettings() -> [String: Any] {
return UserDefaults.standard.dictionary(forKey: settingsKey) ?? [:]
return cacheQueue.sync {
if let cached = cachedSettings {
return cached
}
cachedSettings = UserDefaults.standard.dictionary(forKey: settingsKey) ?? [:]
return cachedSettings!
}
}

public static func setSettings(_ options: [String: Any]?) {
CallingxLog.settings.debugPublic("[setSettings] options = \(String(describing: options))")

var settings: [String: Any] = getSettings()
cacheQueue.sync {
// Load lazily here rather than via getSettings() to avoid re-entrant sync on cacheQueue.
var settings = cachedSettings ?? UserDefaults.standard.dictionary(forKey: settingsKey) ?? [:]

if let options = options {
for (key, value) in options {
settings[key] = value
if let options = options {
for (key, value) in options {
settings[key] = value
}
}
}

UserDefaults.standard.set(settings, forKey: settingsKey)
UserDefaults.standard.synchronize()
cachedSettings = settings
UserDefaults.standard.set(settings, forKey: settingsKey)
}
}

public static func getShouldRejectCallWhenBusy() -> Bool {
Expand Down