use CallKit for all cases
This commit is contained in:
parent
86aced218a
commit
f019fe7733
|
@ -128,6 +128,11 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
|
|||
WebRTCSession.current = self.webRTCSession
|
||||
super.init()
|
||||
self.webRTCSession.delegate = self
|
||||
if AppEnvironment.shared.callManager.currentCall == nil {
|
||||
AppEnvironment.shared.callManager.currentCall = self
|
||||
} else {
|
||||
SNLog("[Calls] A call is ongoing.")
|
||||
}
|
||||
}
|
||||
|
||||
func reportIncomingCallIfNeeded(completion: @escaping (Error?) -> Void) {
|
||||
|
@ -147,7 +152,7 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
|
|||
}
|
||||
|
||||
// MARK: Actions
|
||||
func startSessionCall(completion: (() -> Void)?) {
|
||||
func startSessionCall() {
|
||||
guard case .offer = mode else { return }
|
||||
var promise: Promise<Void>!
|
||||
Storage.write(with: { transaction in
|
||||
|
@ -161,10 +166,9 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
|
|||
}
|
||||
}
|
||||
})
|
||||
completion?()
|
||||
}
|
||||
|
||||
func answerSessionCall(completion: (() -> Void)?) {
|
||||
func answerSessionCall() {
|
||||
guard case .answer = mode else { return }
|
||||
hasStartedConnecting = true
|
||||
if let sdp = remoteSDP {
|
||||
|
@ -172,7 +176,6 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
|
|||
} else {
|
||||
isWaitingForRemoteSDP = true
|
||||
}
|
||||
completion?()
|
||||
}
|
||||
|
||||
func endSessionCall() {
|
||||
|
|
|
@ -2,7 +2,7 @@ import CallKit
|
|||
import SessionUtilitiesKit
|
||||
|
||||
extension SessionCallManager {
|
||||
public func startCall(_ call: SessionCall, completion: (() -> Void)?) {
|
||||
public func startCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||
guard case .offer = call.mode else { return }
|
||||
let handle = CXHandle(type: .generic, value: call.sessionID)
|
||||
let startCallAction = CXStartCallAction(call: call.uuid, handle: handle)
|
||||
|
@ -13,17 +13,23 @@ extension SessionCallManager {
|
|||
transaction.addAction(startCallAction)
|
||||
|
||||
reportOutgoingCall(call)
|
||||
requestTransaction(transaction)
|
||||
completion?()
|
||||
requestTransaction(transaction, completion: completion)
|
||||
}
|
||||
|
||||
public func endCall(_ call: SessionCall, completion: (() -> Void)?) {
|
||||
public func answerCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||
let answerCallAction = CXAnswerCallAction(call: call.uuid)
|
||||
let transaction = CXTransaction()
|
||||
transaction.addAction(answerCallAction)
|
||||
|
||||
requestTransaction(transaction, completion: completion)
|
||||
}
|
||||
|
||||
public func endCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
|
||||
let endCallAction = CXEndCallAction(call: call.uuid)
|
||||
let transaction = CXTransaction()
|
||||
transaction.addAction(endCallAction)
|
||||
|
||||
requestTransaction(transaction)
|
||||
completion?()
|
||||
requestTransaction(transaction, completion: completion)
|
||||
}
|
||||
|
||||
// Not currently in use
|
||||
|
@ -35,13 +41,14 @@ extension SessionCallManager {
|
|||
requestTransaction(transaction)
|
||||
}
|
||||
|
||||
private func requestTransaction(_ transaction: CXTransaction) {
|
||||
private func requestTransaction(_ transaction: CXTransaction, completion: ((Error?) -> Void)? = nil) {
|
||||
callController.request(transaction) { error in
|
||||
if let error = error {
|
||||
SNLog("Error requesting transaction: \(error)")
|
||||
} else {
|
||||
SNLog("Requested transaction successfully")
|
||||
}
|
||||
completion?(error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,18 +9,22 @@ extension SessionCallManager: CXProviderDelegate {
|
|||
public func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
|
||||
AssertIsOnMainThread()
|
||||
guard let call = self.currentCall else { return action.fail() }
|
||||
call.startSessionCall(completion: nil)
|
||||
call.startSessionCall()
|
||||
action.fulfill()
|
||||
}
|
||||
|
||||
public func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
|
||||
AssertIsOnMainThread()
|
||||
guard let _ = self.currentCall else { return action.fail() }
|
||||
let userDefaults = UserDefaults.standard
|
||||
if userDefaults[.hasSeenCallIPExposureWarning] {
|
||||
showCallVC()
|
||||
guard let call = self.currentCall else { return action.fail() }
|
||||
if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
|
||||
call.answerSessionCall()
|
||||
} else {
|
||||
showCallModal()
|
||||
let userDefaults = UserDefaults.standard
|
||||
if userDefaults[.hasSeenCallIPExposureWarning] {
|
||||
showCallVC()
|
||||
} else {
|
||||
showCallModal()
|
||||
}
|
||||
}
|
||||
action.fulfill()
|
||||
}
|
||||
|
|
|
@ -4,7 +4,19 @@ import SessionMessagingKit
|
|||
public final class SessionCallManager: NSObject {
|
||||
let provider: CXProvider
|
||||
let callController = CXCallController()
|
||||
var currentCall: SessionCall?
|
||||
var currentCall: SessionCall? = nil {
|
||||
willSet {
|
||||
if (newValue != nil) {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.isIdleTimerDisabled = true
|
||||
}
|
||||
} else {
|
||||
DispatchQueue.main.async {
|
||||
UIApplication.shared.isIdleTimerDisabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static var _sharedProvider: CXProvider?
|
||||
class func sharedProvider(useSystemCallLog: Bool) -> CXProvider {
|
||||
|
@ -46,12 +58,13 @@ public final class SessionCallManager: NSObject {
|
|||
|
||||
public func reportOutgoingCall(_ call: SessionCall) {
|
||||
AssertIsOnMainThread()
|
||||
self.currentCall = call
|
||||
call.hasStartedConnectingDidChange = {
|
||||
self.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
|
||||
}
|
||||
call.hasConnectedDidChange = {
|
||||
self.provider.reportOutgoingCall(with: call.uuid, connectedAt: call.connectedDate)
|
||||
call.stateDidChange = {
|
||||
if call.hasStartedConnecting {
|
||||
self.provider.reportOutgoingCall(with: call.uuid, startedConnectingAt: call.connectingDate)
|
||||
}
|
||||
if call.hasConnected {
|
||||
self.provider.reportOutgoingCall(with: call.uuid, connectedAt: call.connectedDate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,11 +82,11 @@ public final class SessionCallManager: NSObject {
|
|||
// Report the incoming call to the system
|
||||
self.provider.reportNewIncomingCall(with: call.uuid, update: update) { error in
|
||||
guard error == nil else {
|
||||
self.currentCall = nil
|
||||
completion(error)
|
||||
Logger.error("failed to report new incoming call, error: \(error!)")
|
||||
return
|
||||
}
|
||||
self.currentCall = call
|
||||
completion(nil)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,6 +167,15 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
|
|||
}
|
||||
}
|
||||
}
|
||||
self.call.hasStartedConnectingDidChange = {
|
||||
DispatchQueue.main.async {
|
||||
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
|
||||
}, completion: nil)
|
||||
}
|
||||
}
|
||||
self.call.hasConnectedDidChange = {
|
||||
DispatchQueue.main.async {
|
||||
self.callInfoLabel.text = "Connected"
|
||||
|
@ -180,8 +189,10 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
|
|||
}
|
||||
}
|
||||
self.call.hasEndedDidChange = {
|
||||
self.conversationVC?.showInputAccessoryView()
|
||||
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
DispatchQueue.main.async {
|
||||
self.conversationVC?.showInputAccessoryView()
|
||||
self.presentingViewController?.dismiss(animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,9 +205,16 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
|
|||
if shouldRestartCamera { cameraManager.prepare() }
|
||||
touch(call.videoCapturer)
|
||||
titleLabel.text = self.call.contactName
|
||||
AppEnvironment.shared.callManager.startCall(call) {
|
||||
self.callInfoLabel.text = "Ringing..."
|
||||
self.answerButton.isHidden = true
|
||||
AppEnvironment.shared.callManager.startCall(call) { error in
|
||||
DispatchQueue.main.async {
|
||||
if let _ = error {
|
||||
self.callInfoLabel.text = "Can't start a call."
|
||||
self.endCall()
|
||||
} else {
|
||||
self.callInfoLabel.text = "Ringing..."
|
||||
self.answerButton.isHidden = true
|
||||
}
|
||||
}
|
||||
}
|
||||
if shouldAnswer { answerCall() }
|
||||
}
|
||||
|
@ -305,12 +323,13 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
|
|||
@objc private func answerCall() {
|
||||
let userDefaults = UserDefaults.standard
|
||||
if userDefaults[.hasSeenCallIPExposureWarning] {
|
||||
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
|
||||
}, completion: nil)
|
||||
AppEnvironment.shared.callManager.answerCall(call) { error in
|
||||
DispatchQueue.main.async {
|
||||
if let _ = error {
|
||||
self.callInfoLabel.text = "Can't answer the call."
|
||||
self.endCall()
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
userDefaults[.hasSeenCallIPExposureWarning] = true
|
||||
|
@ -319,7 +338,12 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
|
|||
}
|
||||
|
||||
@objc private func endCall() {
|
||||
AppEnvironment.shared.callManager.endCall(call, completion: nil)
|
||||
AppEnvironment.shared.callManager.endCall(call) { error in
|
||||
if let _ = error {
|
||||
self.call.endSessionCall()
|
||||
AppEnvironment.shared.callManager.reportCurrentCallEnded(reason: nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@objc private func minimize() {
|
||||
|
|
|
@ -155,7 +155,11 @@ final class IncomingCallBanner: UIView, UIGestureRecognizerDelegate {
|
|||
}
|
||||
|
||||
@objc private func endCall() {
|
||||
AppEnvironment.shared.callManager.endCall(call) {
|
||||
AppEnvironment.shared.callManager.endCall(call) { error in
|
||||
if let _ = error {
|
||||
self.call.endSessionCall()
|
||||
AppEnvironment.shared.callManager.reportCurrentCallEnded(reason: nil)
|
||||
}
|
||||
self.dismiss()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ extension ConversationVC : InputViewDelegate, MessageCellDelegate, ContextMenuAc
|
|||
let userDefaults = UserDefaults.standard
|
||||
if userDefaults[.hasSeenCallIPExposureWarning] {
|
||||
guard let contactSessionID = (thread as? TSContactThread)?.contactSessionID() else { return }
|
||||
guard AppEnvironment.shared.callManager.currentCall == nil else { return }
|
||||
let call = SessionCall(for: contactSessionID, uuid: UUID().uuidString, mode: .offer)
|
||||
let callVC = CallVC(for: call)
|
||||
callVC.conversationVC = self
|
||||
|
|
|
@ -17,7 +17,6 @@ extension AppDelegate {
|
|||
conversationVC.inputAccessoryView?.isHidden = true
|
||||
conversationVC.inputAccessoryView?.alpha = 0
|
||||
presentingVC.present(callVC, animated: true, completion: nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
call.reportIncomingCallIfNeeded{ error in
|
||||
|
|
Loading…
Reference in New Issue