CallViewController only accesses CallService via the CallUIAdapter

This is an effort to better define boundaries and simplify
relationships.

This also fixes a theoretical problem where CallKit was showing the in-app
call screen before the call was successfully answered, now we wait until
the action is fulfilled.

// FREEBIE
pull/1/head
Michael Kirk 9 years ago
parent fc6da05259
commit f6e6e6b787

@ -578,8 +578,6 @@ fileprivate let timeoutSeconds = 60
let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(), withCallNumber: call.remotePhoneNumber, callType: RPRecentCallTypeIncoming, in: thread) let callRecord = TSCall(timestamp: NSDate.ows_millisecondTimeStamp(), withCallNumber: call.remotePhoneNumber, callType: RPRecentCallTypeIncoming, in: thread)
callRecord.save() callRecord.save()
callUIAdapter.answerCall(call)
let message = DataChannelMessage.forConnected(callId: call.signalingId) let message = DataChannelMessage.forConnected(callId: call.signalingId)
if peerConnectionClient.sendDataChannelMessage(data: message.asData()) { if peerConnectionClient.sendDataChannelMessage(data: message.asData()) {
Logger.debug("\(TAG) sendDataChannelMessage returned true") Logger.debug("\(TAG) sendDataChannelMessage returned true")

@ -48,7 +48,9 @@ class NonCallKitCallUIAdaptee: CallUIAdaptee {
} }
internal func answerCall(_ call: SignalCall) { internal func answerCall(_ call: SignalCall) {
// NO-OP CallService.signalingQueue.async {
self.callService.handleAnswerCall(call)
}
} }
internal func declineCall(_ call: SignalCall) { internal func declineCall(_ call: SignalCall) {

@ -5,8 +5,12 @@ import UIKit
import CallKit import CallKit
/** /**
* Based on SpeakerboxCallManager, from the Apple CallKit Example app. Though, it's responsibilities are mostly mirrored (and delegated from) CallKitCallUIAdaptee. * Requests actions from CallKit
* TODO: Would it simplify things to merge this into CallKitCallUIAdaptee? *
* @Discussion:
* Based on SpeakerboxCallManager, from the Apple CallKit Example app. Though, it's responsibilities are mostly
* mirrored (and delegated from) CallKitCallUIAdaptee.
* TODO: Would it simplify things to merge this into CallKitCallUIAdaptee?
*/ */
@available(iOS 10.0, *) @available(iOS 10.0, *)
final class CallKitCallManager: NSObject { final class CallKitCallManager: NSObject {
@ -52,6 +56,14 @@ final class CallKitCallManager: NSObject {
requestTransaction(transaction) requestTransaction(transaction)
} }
func answer(call: SignalCall) {
let answerCallAction = CXAnswerCallAction(call: call.localId)
let transaction = CXTransaction()
transaction.addAction(answerCallAction)
requestTransaction(transaction)
}
private func requestTransaction(_ transaction: CXTransaction) { private func requestTransaction(_ transaction: CXTransaction) {
callController.request(transaction) { error in callController.request(transaction) { error in
if let error = error { if let error = error {

@ -7,10 +7,10 @@ import CallKit
import AVFoundation import AVFoundation
/** /**
* Connects user interface to the CallService usin CallKit. * Connects user interface to the CallService using CallKit.
* *
* User interface is mapped to CXCall action requests, and if the CXProvider accepts them, * User interface is routed to the CallManager which requests CXCallActions, and if the CXProvider accepts them,
* their corresponding consequences are requested via the CallService * their corresponding consequences are implmented in the CXProviderDelegate methods, e.g. using the CallService
*/ */
@available(iOS 10.0, *) @available(iOS 10.0, *)
final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate { final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
@ -84,7 +84,7 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
} }
internal func answerCall(_ call: SignalCall) { internal func answerCall(_ call: SignalCall) {
showCall(call) callManager.answer(call: call)
} }
internal func declineCall(_ call: SignalCall) { internal func declineCall(_ call: SignalCall) {
@ -144,9 +144,9 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
CallService.signalingQueue.async { CallService.signalingQueue.async {
self.callService.handleOutgoingCall(call).then { self.callService.handleOutgoingCall(call).then {
action.fulfill() action.fulfill()
}.catch { error in }.catch { error in
self.callManager.removeCall(call) self.callManager.removeCall(call)
action.fail() action.fail()
} }
} }
@ -182,13 +182,11 @@ final class CallKitCallUIAdaptee: NSObject, CallUIAdaptee, CXProviderDelegate {
// // Trigger the call to be answered via the underlying network service. // // Trigger the call to be answered via the underlying network service.
// call.answerSpeakerboxCall() // call.answerSpeakerboxCall()
// Synchronous to ensure work is done before call is displayed as "answered" CallService.signalingQueue.async {
CallService.signalingQueue.sync {
self.callService.handleAnswerCall(call) self.callService.handleAnswerCall(call)
self.showCall(call)
action.fulfill()
} }
// Signal to the system that the action has been successfully performed.
action.fulfill()
} }
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) { public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {

@ -135,7 +135,7 @@ class CallViewController: UIViewController, CallDelegate {
let TAG = "[CallViewController]" let TAG = "[CallViewController]"
// Dependencies // Dependencies
let callService: CallService
let callUIAdapter: CallUIAdapter let callUIAdapter: CallUIAdapter
let contactsManager: OWSContactsManager let contactsManager: OWSContactsManager
let audioService: CallAudioService let audioService: CallAudioService
@ -165,7 +165,7 @@ class CallViewController: UIViewController, CallDelegate {
required init?(coder aDecoder: NSCoder) { required init?(coder aDecoder: NSCoder) {
contactsManager = Environment.getCurrent().contactsManager contactsManager = Environment.getCurrent().contactsManager
callService = Environment.getCurrent().callService let callService = Environment.getCurrent().callService!
callUIAdapter = callService.callUIAdapter callUIAdapter = callService.callUIAdapter
audioService = CallAudioService() audioService = CallAudioService()
super.init(coder: aDecoder) super.init(coder: aDecoder)
@ -173,7 +173,7 @@ class CallViewController: UIViewController, CallDelegate {
required init() { required init() {
contactsManager = Environment.getCurrent().contactsManager contactsManager = Environment.getCurrent().contactsManager
callService = Environment.getCurrent().callService let callService = Environment.getCurrent().callService!
callUIAdapter = callService.callUIAdapter callUIAdapter = callService.callUIAdapter
audioService = CallAudioService() audioService = CallAudioService()
super.init(nibName: nil, bundle: nil) super.init(nibName: nil, bundle: nil)
@ -286,7 +286,7 @@ class CallViewController: UIViewController, CallDelegate {
if let call = self.call { if let call = self.call {
callUIAdapter.toggleMute(call: call, isMuted: muteButton.isSelected) callUIAdapter.toggleMute(call: call, isMuted: muteButton.isSelected)
} else { } else {
Logger.warn("\(TAG) hung up, but call was unexpectedly nil") Logger.warn("\(TAG) pressed mute, but call was unexpectedly nil")
} }
} }
@ -308,9 +308,7 @@ class CallViewController: UIViewController, CallDelegate {
return return
} }
CallService.signalingQueue.async { callUIAdapter.answerCall(call)
self.callService.handleAnswerCall(call)
}
} }
/** /**
@ -338,7 +336,6 @@ class CallViewController: UIViewController, CallDelegate {
} }
internal func muteDidChange(call: SignalCall, isMuted: Bool) { internal func muteDidChange(call: SignalCall, isMuted: Bool) {
Logger.debug("\(TAG) in \(#function)")
DispatchQueue.main.async { DispatchQueue.main.async {
self.muteButton.isSelected = call.isMuted self.muteButton.isSelected = call.isMuted
} }

Loading…
Cancel
Save