minor fix

pull/560/head
ryanzhao 4 years ago
parent 9d42c73de1
commit 248a02e1e9

@ -168,24 +168,21 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
// MARK: Actions // MARK: Actions
func startSessionCall() { func startSessionCall() {
guard case .offer = mode else { return } guard case .offer = mode else { return }
var promise: Promise<Void>! var promise: Promise<UInt64>!
Storage.write(with: { transaction in Storage.write(with: { transaction in
promise = self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction) promise = self.webRTCSession.sendPreOffer(to: self.sessionID, using: transaction)
}, completion: { [weak self] in }, completion: { [weak self] in
let _ = promise.done { let _ = promise.done { timestamp in
self?.callMessageTimestamp = timestamp
Storage.shared.write { transaction in Storage.shared.write { transaction in
self?.webRTCSession.sendOffer(to: self!.sessionID, using: transaction as! YapDatabaseReadWriteTransaction).done { timestamp in self?.webRTCSession.sendOffer(to: self!.sessionID, using: transaction as! YapDatabaseReadWriteTransaction).retainUntilComplete()
self?.hasStartedConnecting = true
self?.callMessageTimestamp = timestamp
}.retainUntilComplete()
} }
} }
}) })
} }
func answerSessionCall(action: CXAnswerCallAction) { func answerSessionCall() {
guard case .answer = mode else { return } guard case .answer = mode else { return }
answerCallAction = action
hasStartedConnecting = true hasStartedConnecting = true
if let sdp = remoteSDP { if let sdp = remoteSDP {
webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally webRTCSession.handleRemoteSDP(sdp, from: sessionID) // This sends an answer message internally
@ -194,8 +191,14 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
} }
} }
func answerSessionCallInBackground(action: CXAnswerCallAction) {
answerCallAction = action
self.answerSessionCall()
}
func endSessionCall() { func endSessionCall() {
guard !hasEnded else { return } guard !hasEnded else { return }
webRTCSession.hangUp()
Storage.write { transaction in Storage.write { transaction in
self.webRTCSession.endCall(with: self.sessionID, using: transaction) self.webRTCSession.endCall(with: self.sessionID, using: transaction)
} }
@ -259,6 +262,15 @@ public final class SessionCall: NSObject, WebRTCSessionDelegate {
isRemoteVideoEnabled = isEnabled isRemoteVideoEnabled = isEnabled
} }
public func didReceiveHangUpSignal() {
DispatchQueue.main.async {
if let currentBanner = IncomingCallBanner.current { currentBanner.dismiss() }
if let callVC = CurrentAppContext().frontmostViewController() as? CallVC { callVC.handleEndCallMessage() }
if let miniCallView = MiniCallView.current { miniCallView.dismiss() }
AppEnvironment.shared.callManager.reportCurrentCallEnded(reason: .remoteEnded)
}
}
public func dataChannelDidOpen() { public func dataChannelDidOpen() {
// Send initial video status // Send initial video status
if (isVideoEnabled) { if (isVideoEnabled) {

@ -19,7 +19,7 @@ extension SessionCallManager: CXProviderDelegate {
guard let call = self.currentCall else { return action.fail() } guard let call = self.currentCall else { return action.fail() }
if CurrentAppContext().isMainAppAndActive { if CurrentAppContext().isMainAppAndActive {
if let _ = CurrentAppContext().frontmostViewController() as? CallVC { if let _ = CurrentAppContext().frontmostViewController() as? CallVC {
call.answerSessionCall(action: action) call.answerSessionCall()
} else { } else {
let userDefaults = UserDefaults.standard let userDefaults = UserDefaults.standard
if userDefaults[.hasSeenCallIPExposureWarning] { if userDefaults[.hasSeenCallIPExposureWarning] {
@ -28,12 +28,14 @@ extension SessionCallManager: CXProviderDelegate {
showCallModal() showCallModal()
} }
} }
action.fulfill()
} else { } else {
call.answerSessionCall(action: action) call.answerSessionCallInBackground(action: action)
} }
} }
public func provider(_ provider: CXProvider, perform action: CXEndCallAction) { public func provider(_ provider: CXProvider, perform action: CXEndCallAction) {
print("[CallKit] Perform CXEndCallAction")
AssertIsOnMainThread() AssertIsOnMainThread()
guard let call = self.currentCall else { return action.fail() } guard let call = self.currentCall else { return action.fail() }
call.endSessionCall() call.endSessionCall()

@ -60,7 +60,7 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
private lazy var answerButton: UIButton = { private lazy var answerButton: UIButton = {
let result = UIButton(type: .custom) let result = UIButton(type: .custom)
result.isHidden = call.hasConnected result.isHidden = call.hasStartedConnecting
let image = UIImage(named: "AnswerCall")!.withTint(.white) let image = UIImage(named: "AnswerCall")!.withTint(.white)
result.setImage(image, for: UIControl.State.normal) result.setImage(image, for: UIControl.State.normal)
result.set(.width, to: 60) result.set(.width, to: 60)
@ -145,9 +145,11 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
private lazy var callInfoLabel: UILabel = { private lazy var callInfoLabel: UILabel = {
let result = UILabel() let result = UILabel()
result.isHidden = call.hasConnected
result.textColor = .white result.textColor = .white
result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize) result.font = .boldSystemFont(ofSize: Values.veryLargeFontSize)
result.textAlignment = .center result.textAlignment = .center
if call.hasStartedConnecting { result.text = "Connecting..." }
return result return result
}() }()
@ -299,7 +301,7 @@ final class CallVC : UIViewController, VideoPreviewDelegate {
callInfoLabel.text = "Connecting..." callInfoLabel.text = "Connecting..."
} }
func handleEndCallMessage(_ message: CallMessage) { func handleEndCallMessage() {
print("[Calls] Ending call.") print("[Calls] Ending call.")
callInfoLabel.isHidden = false callInfoLabel.isHidden = false
callInfoLabel.text = "Call Ended" callInfoLabel.text = "Call Ended"

@ -68,7 +68,7 @@ extension AppDelegate {
MessageReceiver.handleEndCallMessage = { message in MessageReceiver.handleEndCallMessage = { message in
DispatchQueue.main.async { DispatchQueue.main.async {
if let currentBanner = IncomingCallBanner.current { currentBanner.dismiss() } if let currentBanner = IncomingCallBanner.current { currentBanner.dismiss() }
if let callVC = CurrentAppContext().frontmostViewController() as? CallVC { callVC.handleEndCallMessage(message) } if let callVC = CurrentAppContext().frontmostViewController() as? CallVC { callVC.handleEndCallMessage() }
if let miniCallView = MiniCallView.current { miniCallView.dismiss() } if let miniCallView = MiniCallView.current { miniCallView.dismiss() }
AppEnvironment.shared.callManager.reportCurrentCallEnded(reason: .remoteEnded) AppEnvironment.shared.callManager.reportCurrentCallEnded(reason: .remoteEnded)
} }

@ -30,6 +30,9 @@ extension WebRTCSession: RTCDataChannelDelegate {
if let isRemoteVideoEnabled = json["video"] as? Bool { if let isRemoteVideoEnabled = json["video"] as? Bool {
delegate?.isRemoteVideoDidChange(isEnabled: isRemoteVideoEnabled) delegate?.isRemoteVideoDidChange(isEnabled: isRemoteVideoEnabled)
} }
if let _ = json["hangup"] {
delegate?.didReceiveHangUpSignal()
}
} }
} }
} }

@ -7,6 +7,7 @@ public protocol WebRTCSessionDelegate : AnyObject {
func webRTCIsConnected() func webRTCIsConnected()
func isRemoteVideoDidChange(isEnabled: Bool) func isRemoteVideoDidChange(isEnabled: Bool)
func dataChannelDidOpen() func dataChannelDidOpen()
func didReceiveHangUpSignal()
} }
/// See https://webrtc.org/getting-started/overview for more information. /// See https://webrtc.org/getting-started/overview for more information.
@ -110,17 +111,19 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
} }
// MARK: Signaling // MARK: Signaling
public func sendPreOffer(to sessionID: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> { public func sendPreOffer(to sessionID: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<UInt64> {
print("[Calls] Sending pre-offer message.") print("[Calls] Sending pre-offer message.")
guard let thread = TSContactThread.fetch(for: sessionID, using: transaction) else { return Promise(error: Error.noThread) } guard let thread = TSContactThread.fetch(for: sessionID, using: transaction) else { return Promise(error: Error.noThread) }
let (promise, seal) = Promise<Void>.pending() let (promise, seal) = Promise<UInt64>.pending()
DispatchQueue.main.async { DispatchQueue.main.async {
let message = CallMessage() let message = CallMessage()
message.uuid = self.uuid message.uuid = self.uuid
message.kind = .preOffer message.kind = .preOffer
let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread)
tsMessage.save(with: transaction)
MessageSender.sendNonDurably(message, in: thread, using: transaction).done2 { MessageSender.sendNonDurably(message, in: thread, using: transaction).done2 {
print("[Calls] Pre-offer message has been sent.") print("[Calls] Pre-offer message has been sent.")
seal.fulfill(()) seal.fulfill((tsMessage.timestamp))
}.catch2 { error in }.catch2 { error in
seal.reject(error) seal.reject(error)
} }
@ -128,10 +131,10 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
return promise return promise
} }
public func sendOffer(to sessionID: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<UInt64> { public func sendOffer(to sessionID: String, using transaction: YapDatabaseReadWriteTransaction) -> Promise<Void> {
print("[Calls] Sending offer message.") print("[Calls] Sending offer message.")
guard let thread = TSContactThread.fetch(for: sessionID, using: transaction) else { return Promise(error: Error.noThread) } guard let thread = TSContactThread.fetch(for: sessionID, using: transaction) else { return Promise(error: Error.noThread) }
let (promise, seal) = Promise<UInt64>.pending() let (promise, seal) = Promise<Void>.pending()
peerConnection.offer(for: mediaConstraints) { [weak self] sdp, error in peerConnection.offer(for: mediaConstraints) { [weak self] sdp, error in
if let error = error { if let error = error {
seal.reject(error) seal.reject(error)
@ -149,10 +152,8 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
message.uuid = self.uuid message.uuid = self.uuid
message.kind = .offer message.kind = .offer
message.sdps = [ sdp.sdp ] message.sdps = [ sdp.sdp ]
let tsMessage = TSOutgoingMessage.from(message, associatedWith: thread)
tsMessage.save(with: transaction)
MessageSender.sendNonDurably(message, in: thread, using: transaction).done2 { MessageSender.sendNonDurably(message, in: thread, using: transaction).done2 {
seal.fulfill(tsMessage.timestamp) seal.fulfill(())
}.catch2 { error in }.catch2 { error in
seal.reject(error) seal.reject(error)
} }
@ -240,7 +241,7 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
public func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) { public func peerConnection(_ peerConnection: RTCPeerConnection, didAdd stream: RTCMediaStream) {
print("[Calls] Peer connection did add stream.") print("[Calls] Peer connection did add stream.")
configureAudioSession() // configureAudioSession()
} }
public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream) { public func peerConnection(_ peerConnection: RTCPeerConnection, didRemove stream: RTCMediaStream) {
@ -258,6 +259,7 @@ public final class WebRTCSession : NSObject, RTCPeerConnectionDelegate {
print("[Calls] ICE connection state changed to: \(state).") print("[Calls] ICE connection state changed to: \(state).")
if state == .connected { if state == .connected {
delegate?.webRTCIsConnected() delegate?.webRTCIsConnected()
// configureAudioSession()
} }
} }
@ -312,4 +314,8 @@ extension WebRTCSession {
localVideoTrack.isEnabled = true localVideoTrack.isEnabled = true
sendJSON(["video": true]) sendJSON(["video": true])
} }
public func hangUp() {
sendJSON(["hangup": true])
}
} }

@ -291,20 +291,20 @@ extension MessageReceiver {
handlePreOfferCallMessage?(message) handlePreOfferCallMessage?(message)
case .offer: case .offer:
print("[Calls] Received offer message.") print("[Calls] Received offer message.")
if getWebRTCSession().uuid != message.uuid! { if WebRTCSession.current?.uuid != message.uuid! {
// TODO: Call in progress, put the new call on hold/reject // TODO: Call in progress, put the new call on hold/reject
return return
} }
handleOfferCallMessage?(message) handleOfferCallMessage?(message)
case .answer: case .answer:
print("[Calls] Received answer message.") print("[Calls] Received answer message.")
guard getWebRTCSession().uuid == message.uuid! else { return } guard WebRTCSession.current?.uuid == message.uuid! else { return }
let sdp = RTCSessionDescription(type: .answer, sdp: message.sdps![0]) let sdp = RTCSessionDescription(type: .answer, sdp: message.sdps![0])
getWebRTCSession().handleRemoteSDP(sdp, from: message.sender!) getWebRTCSession().handleRemoteSDP(sdp, from: message.sender!)
handleAnswerCallMessage?(message) handleAnswerCallMessage?(message)
case .provisionalAnswer: break // TODO: Implement case .provisionalAnswer: break // TODO: Implement
case let .iceCandidates(sdpMLineIndexes, sdpMids): case let .iceCandidates(sdpMLineIndexes, sdpMids):
guard getWebRTCSession().uuid == message.uuid! else { return } guard WebRTCSession.current?.uuid == message.uuid! else { return }
var candidates: [RTCIceCandidate] = [] var candidates: [RTCIceCandidate] = []
let sdps = message.sdps! let sdps = message.sdps!
for i in 0..<sdps.count { for i in 0..<sdps.count {
@ -317,7 +317,7 @@ extension MessageReceiver {
getWebRTCSession().handleICECandidates(candidates) getWebRTCSession().handleICECandidates(candidates)
case .endCall: case .endCall:
print("[Calls] Received end call message.") print("[Calls] Received end call message.")
guard getWebRTCSession().uuid == message.uuid! else { return } guard WebRTCSession.current?.uuid == message.uuid! else { return }
handleEndCallMessage?(message) handleEndCallMessage?(message)
} }
} }

Loading…
Cancel
Save