refactor to plug in callkit

pull/560/head
ryanzhao 3 years ago
parent e2de82a11d
commit 0ef7bdc9ce

@ -147,10 +147,11 @@
7B7CB18E270D066F0079FF93 /* IncomingCallBanner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */; };
7B7CB190270FB2150079FF93 /* MiniCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB18F270FB2150079FF93 /* MiniCallView.swift */; };
7B7CB192271508AD0079FF93 /* Vibration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7B7CB191271508AD0079FF93 /* Vibration.swift */; };
7BA68909272A27BE00EFC32F /* SessionCall.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BA68908272A27BE00EFC32F /* SessionCall.swift */; };
7BC01A3E241F40AB00BC7C55 /* NotificationServiceExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */; };
7BC01A42241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
7BC707EA27267973002817AD /* AppDelegate+VoIP.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707E927267973002817AD /* AppDelegate+VoIP.swift */; };
7BC707EF2727C3C6002817AD /* WebRTCSession+CallKit.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707EE2727C3C6002817AD /* WebRTCSession+CallKit.swift */; };
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BC707F127290ACB002817AD /* SessionCallManager.swift */; };
7BCD116C27016062006330F1 /* WebRTCSession+DataChannel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */; };
7BDCFC08242186E700641C39 /* NotificationServiceExtensionContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */; };
7BDCFC0B2421EB7600641C39 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = B6F509951AA53F760068F56A /* Localizable.strings */; };
@ -1132,11 +1133,12 @@
7B7CB18D270D066F0079FF93 /* IncomingCallBanner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallBanner.swift; sourceTree = "<group>"; };
7B7CB18F270FB2150079FF93 /* MiniCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MiniCallView.swift; sourceTree = "<group>"; };
7B7CB191271508AD0079FF93 /* Vibration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Vibration.swift; sourceTree = "<group>"; };
7BA68908272A27BE00EFC32F /* SessionCall.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCall.swift; sourceTree = "<group>"; };
7BC01A3B241F40AB00BC7C55 /* SessionNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SessionNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
7BC01A3D241F40AB00BC7C55 /* NotificationServiceExtension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtension.swift; sourceTree = "<group>"; };
7BC01A3F241F40AB00BC7C55 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
7BC707E927267973002817AD /* AppDelegate+VoIP.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+VoIP.swift"; sourceTree = "<group>"; };
7BC707EE2727C3C6002817AD /* WebRTCSession+CallKit.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebRTCSession+CallKit.swift"; sourceTree = "<group>"; };
7BC707F127290ACB002817AD /* SessionCallManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionCallManager.swift; sourceTree = "<group>"; };
7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "WebRTCSession+DataChannel.swift"; sourceTree = "<group>"; };
7BDCFC0424206E7300641C39 /* SessionNotificationServiceExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SessionNotificationServiceExtension.entitlements; sourceTree = "<group>"; };
7BDCFC07242186E700641C39 /* NotificationServiceExtensionContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NotificationServiceExtensionContext.swift; sourceTree = "<group>"; };
@ -2068,6 +2070,15 @@
path = "Views & Modals";
sourceTree = "<group>";
};
7BA68907272A279900EFC32F /* Call Management */ = {
isa = PBXGroup;
children = (
7BC707F127290ACB002817AD /* SessionCallManager.swift */,
7BA68908272A27BE00EFC32F /* SessionCall.swift */,
);
path = "Call Management";
sourceTree = "<group>";
};
7BC01A3C241F40AB00BC7C55 /* SessionNotificationServiceExtension */ = {
isa = PBXGroup;
children = (
@ -2365,6 +2376,7 @@
7B1581E5271FD2A100848B49 /* VideoPreviewVC.swift */,
B877E24526CA13BA0007970A /* CallVC+Camera.swift */,
B8B558F026C4BB0600693325 /* CameraManager.swift */,
7BA68907272A279900EFC32F /* Call Management */,
7B7CB18C270D06350079FF93 /* Views & Modals */,
);
path = Calls;
@ -2404,7 +2416,6 @@
B8B558FE26C4E05E00693325 /* WebRTCSession+MessageHandling.swift */,
B8BF43B926CC95FB007828D1 /* WebRTC+Utilities.swift */,
7BCD116B27016062006330F1 /* WebRTCSession+DataChannel.swift */,
7BC707EE2727C3C6002817AD /* WebRTCSession+CallKit.swift */,
);
path = Calls;
sourceTree = "<group>";
@ -4811,7 +4822,6 @@
C32C5AF8256DC051003C73A2 /* OWSDisappearingMessagesConfiguration.m in Sources */,
C32C5EBA256DE130003C73A2 /* OWSQuotedReplyModel.m in Sources */,
C32C5B62256DC333003C73A2 /* OWSDisappearingConfigurationUpdateInfoMessage.m in Sources */,
7BC707EF2727C3C6002817AD /* WebRTCSession+CallKit.swift in Sources */,
C352A2F525574B4700338F3E /* Job.swift in Sources */,
C32C5C01256DC9A0003C73A2 /* OWSIdentityManager.m in Sources */,
C32C59C4256DB41F003C73A2 /* TSContactThread.m in Sources */,
@ -4874,6 +4884,7 @@
C3548F0624456447009433A8 /* PNModeVC.swift in Sources */,
B80A579F23DFF1F300876683 /* NewClosedGroupVC.swift in Sources */,
D221A09A169C9E5E00537ABF /* main.m in Sources */,
7BA68909272A27BE00EFC32F /* SessionCall.swift in Sources */,
3496957221A301A100DCFE74 /* OWSBackup.m in Sources */,
B835247925C38D880089A44F /* MessageCell.swift in Sources */,
B86BD08623399CEF000F5AE3 /* SeedModal.swift in Sources */,
@ -4935,6 +4946,7 @@
B8CCF6432397711F0091D419 /* SettingsVC.swift in Sources */,
C354E75A23FE2A7600CE22E3 /* BaseVC.swift in Sources */,
7B1581E827210ECC00848B49 /* RenderView.swift in Sources */,
7BC707F227290ACB002817AD /* SessionCallManager.swift in Sources */,
3441FD9F21A3604F00BB9542 /* BackupRestoreViewController.swift in Sources */,
45C0DC1B1E68FE9000E04C47 /* UIApplication+OWS.swift in Sources */,
4539B5861F79348F007141FF /* PushRegistrationManager.swift in Sources */,

@ -0,0 +1,132 @@
import Foundation
import WebRTC
import SessionMessagingKit
public final class SessionCall: NSObject {
// MARK: Metadata Properties
let uuid: UUID
let sessionID: String
let mode: Mode
let webRTCSession: WebRTCSession
var contactName: String {
let contact = Storage.shared.getContact(with: self.sessionID)
return contact?.displayName(for: Contact.Context.regular) ?? self.sessionID
}
var profilePicture: UIImage {
if let result = OWSProfileManager.shared().profileAvatar(forRecipientId: sessionID) {
return result
} else {
return Identicon.generatePlaceholderIcon(seed: sessionID, text: contactName, size: 300)
}
}
// MARK: Mode
enum Mode {
case offer
case answer(sdp: RTCSessionDescription)
}
// MARK: Call State Properties
var connectingDate: Date? {
didSet {
stateDidChange?()
hasStartedConnectingDidChange?()
}
}
var connectedDate: Date? {
didSet {
stateDidChange?()
hasConnectedDidChange?()
}
}
var endDate: Date? {
didSet {
stateDidChange?()
hasEndedDidChange?()
}
}
// Not yet implemented
var isOnHold = false {
didSet {
stateDidChange?()
}
}
// MARK: State Change Callbacks
var stateDidChange: (() -> Void)?
var hasStartedConnectingDidChange: (() -> Void)?
var hasConnectedDidChange: (() -> Void)?
var hasEndedDidChange: (() -> Void)?
// MARK: Derived Properties
var hasStartedConnecting: Bool {
get { return connectingDate != nil }
set { connectingDate = newValue ? Date() : nil }
}
var hasConnected: Bool {
get { return connectedDate != nil }
set { connectedDate = newValue ? Date() : nil }
}
var hasEnded: Bool {
get { return endDate != nil }
set { endDate = newValue ? Date() : nil }
}
var duration: TimeInterval {
guard let connectedDate = connectedDate else {
return 0
}
return Date().timeIntervalSince(connectedDate)
}
// MARK: Initialization
init(for sessionID: String, uuid: String, mode: Mode) {
self.sessionID = sessionID
self.uuid = UUID(uuidString: uuid)!
self.mode = mode
self.webRTCSession = WebRTCSession.current ?? WebRTCSession(for: sessionID, with: uuid)
super.init()
reportIncomingCallIfNeeded()
}
func reportIncomingCallIfNeeded() {
guard case .offer = mode else { return }
AppEnvironment.shared.callManager.reportIncomingCall(self, callerName: contactName) { error in
}
}
// MARK: Actions
func startSessionCall(completion: (() -> Void)?) {
guard case .offer = mode else { return }
Storage.write { transaction in
self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction).done {
self.webRTCSession.sendOffer(to: self.sessionID, using: transaction).done {
self.hasStartedConnecting = true
}.retainUntilComplete()
}.retainUntilComplete()
}
completion?()
}
func answerSessionCall(completion: (() -> Void)?) {
guard case let .answer(sdp) = mode else { return }
hasStartedConnecting = true
webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally
completion?()
}
func endSessionCall() {
guard !hasEnded else { return }
Storage.write { transaction in
self.webRTCSession.endCall(with: self.sessionID, using: transaction)
}
hasEnded = true
}
}

@ -0,0 +1,96 @@
import CallKit
import SessionMessagingKit
public final class SessionCallManager: NSObject, CXProviderDelegate {
private let provider: CXProvider
var currentCall: SessionCall?
private static var _sharedProvider: CXProvider?
class func sharedProvider(useSystemCallLog: Bool) -> CXProvider {
let configuration = buildProviderConfiguration(useSystemCallLog: useSystemCallLog)
if let sharedProvider = self._sharedProvider {
sharedProvider.configuration = configuration
return sharedProvider
} else {
SwiftSingletons.register(self)
let provider = CXProvider(configuration: configuration)
_sharedProvider = provider
return provider
}
}
class func buildProviderConfiguration(useSystemCallLog: Bool) -> CXProviderConfiguration {
let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "Name of application")
let providerConfiguration = CXProviderConfiguration(localizedName: localizedName)
providerConfiguration.supportsVideo = true
providerConfiguration.maximumCallsPerCallGroup = 1
providerConfiguration.supportedHandleTypes = [.generic]
let iconMaskImage = #imageLiteral(resourceName: "SessionGreen32")
providerConfiguration.iconTemplateImageData = iconMaskImage.pngData()
providerConfiguration.includesCallsInRecents = useSystemCallLog
return providerConfiguration
}
init(useSystemCallLog: Bool = false) {
AssertIsOnMainThread()
self.provider = type(of: self).sharedProvider(useSystemCallLog: useSystemCallLog)
super.init()
// We cannot assert singleton here, because this class gets rebuilt when the user changes relevant call settings
self.provider.setDelegate(self, queue: nil)
}
public func providerDidReset(_ provider: CXProvider) {
AssertIsOnMainThread()
}
public func reportOutgoingCall(_ call: SessionCall, completion: @escaping (Error?) -> Void) {
AssertIsOnMainThread()
self.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
self.currentCall = call
call.hasConnectedDidChange = {
self.provider.reportOutgoingCall(with: call.uuid, connectedAt: call.connectedDate)
}
}
public func reportIncomingCall(_ call: SessionCall, callerName: String, completion: @escaping (Error?) -> Void) {
AssertIsOnMainThread()
// Construct a CXCallUpdate describing the incoming call, including the caller.
let update = CXCallUpdate()
update.localizedCallerName = callerName
update.remoteHandle = CXHandle(type: .generic, value: call.uuid.uuidString)
update.hasVideo = true
disableUnsupportedFeatures(callUpdate: update)
// Report the incoming call to the system
self.provider.reportNewIncomingCall(with: call.uuid, update: update) { error in
guard error == nil else {
completion(error)
Logger.error("failed to report new incoming call, error: \(error!)")
return
}
self.currentCall = call
completion(nil)
}
}
// MARK: Util
private func disableUnsupportedFeatures(callUpdate: CXCallUpdate) {
// Call Holding is failing to restart audio when "swapping" calls on the CallKit screen
// until user returns to in-app call screen.
callUpdate.supportsHolding = false
// Not yet supported
callUpdate.supportsGrouping = false
callUpdate.supportsUngrouping = false
// Is there any reason to support this?
callUpdate.supportsDTMF = false
}
}

@ -5,15 +5,13 @@ import SessionUtilitiesKit
import UIKit
final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelegate {
let sessionID: String
let uuid: String
let mode: Mode
let webRTCSession: WebRTCSession
let call: SessionCall
var webRTCSession: WebRTCSession { return call.webRTCSession }
var shouldAnswer = false
var isMuted = false
var isVideoEnabled = false
var shouldRestartCamera = true
var conversationVC: ConversationVC? = nil
weak var conversationVC: ConversationVC? = nil
lazy var cameraManager: CameraManager = {
let result = CameraManager()
@ -159,20 +157,15 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
return result
}()
// MARK: Mode
enum Mode {
case offer
case answer(sdp: RTCSessionDescription)
}
// MARK: Lifecycle
init(for sessionID: String, uuid: String, mode: Mode) {
self.sessionID = sessionID
self.uuid = uuid
self.mode = mode
self.webRTCSession = WebRTCSession.current ?? WebRTCSession(for: sessionID, with: uuid)
init(for call: SessionCall) {
self.call = call
super.init(nibName: nil, bundle: nil)
self.webRTCSession.delegate = self
self.call.webRTCSession.delegate = self
self.call.hasEndedDidChange = {
self.conversationVC?.showInputAccessoryView()
self.presentingViewController?.dismiss(animated: true, completion: nil)
}
}
required init(coder: NSCoder) { preconditionFailure("Use init(for:) instead.") }
@ -184,19 +177,10 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
setUpViewHierarchy()
if shouldRestartCamera { cameraManager.prepare() }
touch(videoCapturer)
var contact: Contact?
Storage.read { transaction in
contact = Storage.shared.getContact(with: self.sessionID)
}
titleLabel.text = contact?.displayName(for: Contact.Context.regular) ?? sessionID
if case .offer = mode {
callInfoLabel.text = "Ringing..."
Storage.write { transaction in
self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction).done {
self.webRTCSession.sendOffer(to: self.sessionID, using: transaction).retainUntilComplete()
}.retainUntilComplete()
}
answerButton.isHidden = true
titleLabel.text = self.call.contactName
self.call.startSessionCall{
self.callInfoLabel.text = "Ringing..."
self.answerButton.isHidden = true
}
if shouldAnswer { answerCall() }
}
@ -251,12 +235,7 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
imageView.layer.cornerRadius = 150
imageView.layer.masksToBounds = true
imageView.contentMode = .scaleAspectFill
if let profilePicture = OWSProfileManager.shared().profileAvatar(forRecipientId: sessionID) {
imageView.image = profilePicture
} else {
let displayName = Storage.shared.getContact(with: sessionID)?.name ?? sessionID
imageView.image = Identicon.generatePlaceholderIcon(seed: sessionID, text: displayName, size: 300)
}
imageView.image = self.call.profilePicture
background.addSubview(imageView)
imageView.set(.width, to: 300)
imageView.set(.height, to: 300)
@ -284,6 +263,7 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
func webRTCIsConnected() {
DispatchQueue.main.async {
self.callInfoLabel.text = "Connected"
self.call.hasConnected = true
self.minimizeButton.isHidden = false
UIView.animate(withDuration: 0.5, delay: 1, options: [], animations: {
self.callInfoLabel.alpha = 0
@ -341,9 +321,8 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
@objc private func answerCall() {
let userDefaults = UserDefaults.standard
if userDefaults[.hasSeenCallIPExposureWarning] {
if case let .answer(sdp) = mode {
callInfoLabel.text = "Connecting..."
webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally
self.call.answerSessionCall{
self.callInfoLabel.text = "Connecting..."
self.answerButton.alpha = 0
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseIn, animations: {
self.answerButton.isHidden = true
@ -356,11 +335,7 @@ final class CallVC : UIViewController, WebRTCSessionDelegate, VideoPreviewDelega
}
@objc private func endCall() {
Storage.write { transaction in
WebRTCSession.current?.endCall(with: self.sessionID, using: transaction)
}
self.conversationVC?.showInputAccessoryView()
presentingViewController?.dismiss(animated: true, completion: nil)
self.call.endSessionCall()
}
@objc private func minimize() {

@ -5,9 +5,7 @@ import SessionMessagingKit
final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
private static let swipeToOperateThreshold: CGFloat = 60
private var previousY: CGFloat = 0
let sessionID: String
let uuid: String
let sdp: RTCSessionDescription
let call: SessionCall
// MARK: UI Components
private lazy var profilePictureView: ProfilePictureView = {
@ -60,10 +58,8 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
// MARK: Initialization
public static var current: IncomingCallBanner?
init(for sessionID: String, uuid: String, sdp: RTCSessionDescription) {
self.uuid = uuid
self.sessionID = sessionID
self.sdp = sdp
init(for call: SessionCall) {
self.call = call
super.init(frame: CGRect.zero)
setUpViewHierarchy()
setUpGestureRecognizers()
@ -86,9 +82,9 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
self.layer.cornerRadius = Values.veryLargeSpacing
self.layer.masksToBounds = true
self.set(.height, to: 100)
profilePictureView.publicKey = self.sessionID
profilePictureView.publicKey = call.sessionID
profilePictureView.update()
displayNameLabel.text = Storage.shared.getContact(with: sessionID)?.name
displayNameLabel.text = call.contactName
let stackView = UIStackView(arrangedSubviews: [profilePictureView, displayNameLabel, hangUpButton, answerButton])
stackView.axis = .horizontal
stackView.alignment = .center
@ -159,16 +155,15 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
}
@objc private func endCall() {
Storage.write { transaction in
WebRTCSession.current?.endCall(with: self.sessionID, using: transaction)
self.call.endSessionCall{
self.dismiss()
}
dismiss()
}
public func showCallVC(answer: Bool) {
dismiss()
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // TODO: Handle more gracefully
let callVC = CallVC(for: sessionID, uuid: uuid, mode: .answer(sdp: sdp))
let callVC = CallVC(for: self.call)
callVC.shouldAnswer = answer
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve

@ -50,12 +50,7 @@ final class MiniCallView: UIView {
imageView.layer.cornerRadius = 32
imageView.layer.masksToBounds = true
imageView.contentMode = .scaleAspectFill
if let profilePicture = OWSProfileManager.shared().profileAvatar(forRecipientId: callVC.sessionID) {
imageView.image = profilePicture
} else {
let displayName = Storage.shared.getContact(with: callVC.sessionID)?.name ?? callVC.sessionID
imageView.image = Identicon.generatePlaceholderIcon(seed: callVC.sessionID, text: displayName, size: 64)
}
imageView.image = callVC.call.profilePicture
background.addSubview(imageView)
imageView.set(.width, to: 64)
imageView.set(.height, to: 64)

@ -31,7 +31,8 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
let userDefaults = UserDefaults.standard
if userDefaults[.hasSeenCallIPExposureWarning] {
guard let contactSessionID = (thread as? TSContactThread)?.contactSessionID() else { return }
let callVC = CallVC(for: contactSessionID, uuid: UUID().uuidString, mode: .offer)
let call = SessionCall(for: contactSessionID, uuid: UUID().uuidString, mode: .offer)
let callVC = CallVC(for: call)
callVC.conversationVC = self
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve
@ -54,9 +55,7 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
}
internal func showCallVCIfNeeded() {
guard let contactSessionID = (thread as? TSContactThread)?.contactSessionID(),
let incomingCallBanner = IncomingCallBanner.current, incomingCallBanner.sessionID == contactSessionID
else { return }
guard let incomingCallBanner = IncomingCallBanner.current else { return }
incomingCallBanner.showCallVC(answer: false)
}

@ -11,9 +11,10 @@ extension AppDelegate {
MessageReceiver.handleOfferCallMessage = { message in
DispatchQueue.main.async {
let sdp = RTCSessionDescription(type: .offer, sdp: message.sdps![0])
let call = SessionCall(for: message.sender!, uuid: message.uuid!, mode: .answer(sdp: sdp))
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // TODO: Handle more gracefully
if let conversationVC = presentingVC as? ConversationVC, let contactThread = conversationVC.thread as? TSContactThread, contactThread.contactSessionID() == message.sender! {
let callVC = CallVC(for: message.sender!, uuid: message.uuid!, mode: .answer(sdp: sdp))
let callVC = CallVC(for: call)
callVC.modalPresentationStyle = .overFullScreen
callVC.modalTransitionStyle = .crossDissolve
callVC.conversationVC = conversationVC
@ -21,7 +22,7 @@ extension AppDelegate {
conversationVC.inputAccessoryView?.alpha = 0
presentingVC.present(callVC, animated: true, completion: nil)
} else {
let incomingCallBanner = IncomingCallBanner(for: message.sender!, uuid: message.uuid!, sdp: sdp)
let incomingCallBanner = IncomingCallBanner(for: call)
incomingCallBanner.show()
}
}

@ -27,6 +27,9 @@ import SignalUtilitiesKit
@objc
public var accountManager: AccountManager
@objc
public var callManager: SessionCallManager
@objc
public var notificationPresenter: NotificationPresenter
@ -54,6 +57,7 @@ import SignalUtilitiesKit
private override init() {
self.accountManager = AccountManager()
self.callManager = SessionCallManager()
self.notificationPresenter = NotificationPresenter()
self.pushRegistrationManager = PushRegistrationManager()
self.backup = OWSBackup()

@ -1,11 +0,0 @@
import CallKit
extension WebRTCSession: CXProviderDelegate {
public func providerDidReset(_ provider: CXProvider) {
}
public func reportIncomingCall() {
}
}
Loading…
Cancel
Save