fix call kit not working when the screen is locked

This commit is contained in:
ryanzhao 2021-11-10 11:13:37 +11:00
parent 446ef838f0
commit 2942168030
7 changed files with 48 additions and 11 deletions

View file

@ -2,6 +2,7 @@ import Foundation
import WebRTC
import SessionMessagingKit
import PromiseKit
import CallKit
public final class SessionCall: NSObject, WebRTCSessionDelegate {
// MARK: Metadata Properties
@ -13,6 +14,7 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
var remoteSDP: RTCSessionDescription? = nil
var callMessageTimestamp: UInt64?
var isWaitingForRemoteSDP = false
var answerCallAction: CXAnswerCallAction? = nil
var contactName: String {
let contact = Storage.shared.getContact(with: self.sessionID)
return contact?.displayName(for: Contact.Context.regular) ?? self.sessionID
@ -181,8 +183,9 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
})
}
func answerSessionCall() {
func answerSessionCall(action: CXAnswerCallAction) {
guard case .answer = mode else { return }
answerCallAction = action
hasStartedConnecting = true
if let sdp = remoteSDP {
webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally
@ -249,6 +252,7 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
// MARK: Delegate
public func webRTCIsConnected() {
self.hasConnected = true
self.answerCallAction?.fulfill()
}
public func isRemoteVideoDidChange(isEnabled: Bool) {

View file

@ -4,6 +4,7 @@ import SessionUtilitiesKit
extension SessionCallManager {
public func startCall(_ call: SessionCall, completion: ((Error?) -> Void)?) {
guard case .offer = call.mode else { return }
guard !call.hasConnected else { return }
let handle = CXHandle(type: .generic, value: call.sessionID)
let startCallAction = CXStartCallAction(call: call.uuid, handle: handle)

View file

@ -15,18 +15,22 @@ extension SessionCallManager: CXProviderDelegate {
public func provider(_ provider: CXProvider, perform action: CXAnswerCallAction) {
AssertIsOnMainThread()
print("[CallKit] Perform CXAnswerCallAction")
guard let call = self.currentCall else { return action.fail() }
if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
call.answerSessionCall()
} else {
let userDefaults = UserDefaults.standard
if userDefaults[.hasSeenCallIPExposureWarning] {
showCallVC()
if CurrentAppContext().isMainAppAndActive {
if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
call.answerSessionCall(action: action)
} else {
showCallModal()
let userDefaults = UserDefaults.standard
if userDefaults[.hasSeenCallIPExposureWarning] {
showCallVC()
} else {
showCallModal()
}
}
} else {
call.answerSessionCall(action: action)
}
action.fulfill()
}
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
@ -37,6 +41,14 @@ extension SessionCallManager: CXProviderDelegate {
action.fulfill()
}
public func provider(_ provider: CXProvider, perform action: CXSetMutedCallAction) {
print("[CallKit] Perform CXSetMutedCallAction, isMuted: \(action.isMuted)")
AssertIsOnMainThread()
guard let call = self.currentCall else { return action.fail() }
call.isMuted = action.isMuted
action.fulfill()
}
public func provider(_ provider: CXProvider, perform action: CXSetHeldCallAction) {
// TODO: set on hold
}

View file

@ -49,7 +49,7 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
private lazy var minimizeButton: UIButton = {
let result = UIButton(type: .custom)
result.isHidden = true
result.isHidden = !call.hasConnected
let image = UIImage(named: "Minimize")!.withTint(.white)
result.setImage(image, for: UIControl.State.normal)
result.set(.width, to: 60)
@ -60,6 +60,7 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
private lazy var answerButton: UIButton = {
let result = UIButton(type: .custom)
result.isHidden = call.hasConnected
let image = UIImage(named: "AnswerCall")!.withTint(.white)
result.setImage(image, for: UIControl.State.normal)
result.set(.width, to: 60)
@ -108,7 +109,7 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
result.setImage(image, for: UIControl.State.normal)
result.set(.width, to: 60)
result.set(.height, to: 60)
result.backgroundColor = UIColor(hex: 0x1F1F1F)
result.backgroundColor = call.isMuted ? Colors.destructive : UIColor(hex: 0x1F1F1F)
result.layer.cornerRadius = 30
result.addTarget(self, action: #selector(switchAudio), for: UIControl.Event.touchUpInside)
return result

View file

@ -407,6 +407,7 @@ static NSTimeInterval launchStartedAt;
if (CurrentAppContext().isMainApp) {
[SNJobQueue.shared resumePendingJobs];
[self syncConfigurationIfNeeded];
[self handleAppActivatedWithOngoingCallIfNeeded];
}
});
}

View file

@ -6,6 +6,20 @@ import UIKit
extension AppDelegate {
// MARK: Call handling
@objc func handleAppActivatedWithOngoingCallIfNeeded() {
guard let call = AppEnvironment.shared.callManager.currentCall else { return }
if let callVC = CurrentAppContext().frontmostViewController() as? CallVC, callVC.call == call { return }
guard let presentingVC = CurrentAppContext().frontmostViewController() else { preconditionFailure() } // TODO: Handle more gracefully
let callVC = CallVC(for: call)
if let conversationVC = presentingVC as? ConversationVC, let contactThread = conversationVC.thread as? TSContactThread, contactThread.contactSessionID() == call.sessionID {
callVC.conversationVC = conversationVC
conversationVC.inputAccessoryView?.isHidden = true
conversationVC.inputAccessoryView?.alpha = 0
}
presentingVC.present(callVC, animated: true, completion: nil)
}
@objc func setUpCallHandling() {
// Pre offer messages
MessageReceiver.handlePreOfferCallMessage = { message in

View file

@ -243,6 +243,10 @@ public enum PushRegistrationError: Error {
if let uuid = payload["uuid"] as? String, let caller = payload["caller"] as? String, let timestamp = payload["timestamp"] as? UInt64 {
let call = SessionCall(for: caller, uuid: uuid, mode: .answer)
call.callMessageTimestamp = timestamp
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.startPollerIfNeeded()
appDelegate.startClosedGroupPoller()
appDelegate.startOpenGroupPollersIfNeeded()
call.reportIncomingCallIfNeeded { error in
if let error = error {
SNLog("[Calls] Failed to report incoming call to CallKit due to error: \(error)")