parent
830ed884cf
commit
0f46834e8d
|
@ -676,6 +676,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
}
|
||||
}
|
||||
return formattedDate
|
||||
case .reconnecting:
|
||||
return NSLocalizedString("IN_CALL_RECONNECTING", comment: "Call setup status label")
|
||||
case .remoteBusy:
|
||||
return NSLocalizedString("END_CALL_RESPONDER_IS_BUSY", comment: "Call setup status label")
|
||||
case .localFailure:
|
||||
|
@ -694,18 +696,39 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
}
|
||||
}
|
||||
|
||||
var isBlinkingReconnectLabel = false
|
||||
func updateCallStatusLabel(callState: CallState) {
|
||||
assert(Thread.isMainThread)
|
||||
|
||||
let text = String(format: CallStrings.callStatusFormat,
|
||||
localizedTextForCallState(callState))
|
||||
self.callStatusLabel.text = text
|
||||
|
||||
// Handle reconnecting blinking
|
||||
if case .reconnecting = callState {
|
||||
if !isBlinkingReconnectLabel {
|
||||
isBlinkingReconnectLabel = true
|
||||
UIView.animate(withDuration: 0.7, delay: 0, options: [.autoreverse, .repeat],
|
||||
animations: {
|
||||
self.callStatusLabel.alpha = 0.2
|
||||
}, completion: nil)
|
||||
} else {
|
||||
// already blinking
|
||||
}
|
||||
} else {
|
||||
// We're no longer in a reconnecting state, either the call failed or we reconnected.
|
||||
// Stop the blinking animation
|
||||
if isBlinkingReconnectLabel {
|
||||
self.callStatusLabel.layer.removeAllAnimations()
|
||||
self.callStatusLabel.alpha = 1
|
||||
isBlinkingReconnectLabel = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateCallUI(callState: CallState) {
|
||||
assert(Thread.isMainThread)
|
||||
updateCallStatusLabel(callState: callState)
|
||||
|
||||
if isShowingSettingsNag {
|
||||
settingsNagView.isHidden = false
|
||||
contactAvatarView.isHidden = true
|
||||
|
|
|
@ -289,6 +289,7 @@ protocol CallAudioServiceDelegate: class {
|
|||
case .remoteRinging: handleRemoteRinging(call: call)
|
||||
case .localRinging: handleLocalRinging(call: call)
|
||||
case .connected: handleConnected(call: call)
|
||||
case .reconnecting: handleReconnecting(call: call)
|
||||
case .localFailure: handleLocalFailure(call: call)
|
||||
case .localHangup: handleLocalHangup(call: call)
|
||||
case .remoteHangup: handleRemoteHangup(call: call)
|
||||
|
@ -335,6 +336,11 @@ protocol CallAudioServiceDelegate: class {
|
|||
SwiftAssertIsOnMainThread(#function)
|
||||
}
|
||||
|
||||
private func handleReconnecting(call: SignalCall) {
|
||||
Logger.debug("\(self.logTag) \(#function)")
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
}
|
||||
|
||||
private func handleLocalFailure(call: SignalCall) {
|
||||
Logger.debug("\(self.logTag) \(#function)")
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
|
|
@ -547,7 +547,7 @@ protocol CallServiceObserver: class {
|
|||
// If both users are trying to call each other at the same time,
|
||||
// both should see busy.
|
||||
handleRemoteBusy(thread: existingCall.thread, callId: existingCall.signalingId)
|
||||
case .answering, .localRinging, .connected, .localFailure, .localHangup, .remoteHangup, .remoteBusy:
|
||||
case .answering, .localRinging, .connected, .localFailure, .localHangup, .remoteHangup, .remoteBusy, .reconnecting:
|
||||
// If one user calls another while the other has a "vestigial" call with
|
||||
// that same user, fail the old call.
|
||||
terminateCall()
|
||||
|
@ -769,8 +769,31 @@ protocol CallServiceObserver: class {
|
|||
Logger.info("\(self.logTag) call already ringing. Ignoring \(#function): \(call.identifiersForLogs).")
|
||||
case .connected:
|
||||
Logger.info("\(self.logTag) Call reconnected \(#function): \(call.identifiersForLogs).")
|
||||
case .reconnecting:
|
||||
call.state = .connected
|
||||
case .idle, .localRinging, .localFailure, .localHangup, .remoteHangup, .remoteBusy:
|
||||
owsFail("\(self.logTag) unexpected call state for \(#function): \(call.state): \(call.identifiersForLogs).")
|
||||
}
|
||||
}
|
||||
|
||||
private func handleIceDisconnected() {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
guard let call = self.call else {
|
||||
// This will only be called for the current peerConnectionClient, so
|
||||
// fail the current call.
|
||||
OWSProdError(OWSAnalyticsEvents.callServiceCallMissing(), file: #file, function: #function, line: #line)
|
||||
handleFailedCurrentCall(error: CallError.assertionError(description: "\(self.logTag) ignoring \(#function) since there is no current call."))
|
||||
return
|
||||
}
|
||||
|
||||
Logger.info("\(self.logTag) in \(#function): \(call.identifiersForLogs).")
|
||||
|
||||
switch call.state {
|
||||
case .connected:
|
||||
call.state = .reconnecting
|
||||
default:
|
||||
Logger.debug("\(self.logTag) unexpected call state for \(#function): \(call.state): \(call.identifiersForLogs).")
|
||||
owsFail("\(self.logTag) unexpected call state for \(#function): \(call.state): \(call.identifiersForLogs).")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -804,7 +827,7 @@ protocol CallServiceObserver: class {
|
|||
switch call.state {
|
||||
case .idle, .dialing, .answering, .localRinging, .localFailure, .remoteBusy, .remoteRinging:
|
||||
handleMissedCall(call)
|
||||
case .connected, .localHangup, .remoteHangup:
|
||||
case .connected, .reconnecting, .localHangup, .remoteHangup:
|
||||
Logger.info("\(self.logTag) call is finished.")
|
||||
}
|
||||
|
||||
|
@ -1217,6 +1240,17 @@ protocol CallServiceObserver: class {
|
|||
self.handleIceConnected()
|
||||
}
|
||||
|
||||
func peerConnectionClientIceDisconnected(_ peerconnectionClient: PeerConnectionClient) {
|
||||
SwiftAssertIsOnMainThread(#function)
|
||||
|
||||
guard peerConnectionClient == self.peerConnectionClient else {
|
||||
Logger.debug("\(self.logTag) \(#function) Ignoring event from obsolete peerConnectionClient")
|
||||
return
|
||||
}
|
||||
|
||||
self.handleIceDisconnected()
|
||||
}
|
||||
|
||||
/**
|
||||
* The connection failed to establish. The clients will not be able to communicate.
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ protocol PeerConnectionClientDelegate: class {
|
|||
|
||||
/**
|
||||
* The connection has been established. The clients can now communicate.
|
||||
* This can be called multiple times throughout the call in the event of temporary network disconnects.
|
||||
*/
|
||||
func peerConnectionClientIceConnected(_ peerconnectionClient: PeerConnectionClient)
|
||||
|
||||
|
@ -35,6 +36,13 @@ protocol PeerConnectionClientDelegate: class {
|
|||
*/
|
||||
func peerConnectionClientIceFailed(_ peerconnectionClient: PeerConnectionClient)
|
||||
|
||||
/**
|
||||
* After initially connecting, the connection disconnected.
|
||||
* It maybe be temporary, in which case `peerConnectionClientIceConnected` will be called again once we're reconnected.
|
||||
* Otherwise, `peerConnectionClientIceFailed` will eventually called.
|
||||
*/
|
||||
func peerConnectionClientIceDisconnected(_ peerconnectionClient: PeerConnectionClient)
|
||||
|
||||
/**
|
||||
* During the Signaling process each client generates IceCandidates locally, which contain information about how to
|
||||
* reach the local client via the internet. The delegate must shuttle these IceCandates to the other (remote) client
|
||||
|
@ -676,6 +684,12 @@ class PeerConnectionClient: NSObject, RTCPeerConnectionDelegate, RTCDataChannelD
|
|||
}
|
||||
case .disconnected:
|
||||
Logger.warn("\(self.TAG) RTCIceConnection disconnected.")
|
||||
if let delegate = self.delegate {
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
guard let strongSelf = self else { return }
|
||||
delegate.peerConnectionClientIceDisconnected(strongSelf)
|
||||
}
|
||||
}
|
||||
default:
|
||||
Logger.debug("\(self.TAG) ignoring change IceConnectionState:\(newState.debugDescription)")
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ enum CallState: String {
|
|||
case remoteRinging
|
||||
case localRinging
|
||||
case connected
|
||||
case reconnecting
|
||||
case localFailure // terminal
|
||||
case localHangup // terminal
|
||||
case remoteHangup // terminal
|
||||
|
@ -47,7 +48,7 @@ protocol CallObserver: class {
|
|||
switch state {
|
||||
case .localFailure, .localHangup, .remoteHangup, .remoteBusy:
|
||||
return true
|
||||
case .idle, .dialing, .answering, .remoteRinging, .localRinging, .connected:
|
||||
case .idle, .dialing, .answering, .remoteRinging, .localRinging, .connected, .reconnecting:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
@ -87,12 +88,11 @@ protocol CallObserver: class {
|
|||
Logger.debug("\(TAG) state changed: \(oldValue) -> \(self.state) for call: \(self.identifiersForLogs)")
|
||||
|
||||
// Update connectedDate
|
||||
if self.state == .connected {
|
||||
if case .connected = self.state {
|
||||
// if it's the first time we've connected (not a reconnect)
|
||||
if connectedDate == nil {
|
||||
connectedDate = NSDate()
|
||||
}
|
||||
} else {
|
||||
connectedDate = nil
|
||||
}
|
||||
|
||||
updateCallRecordType()
|
||||
|
|
|
@ -875,6 +875,9 @@
|
|||
/* Call setup status label */
|
||||
"IN_CALL_CONNECTING" = "Connecting…";
|
||||
|
||||
/* Call setup status label */
|
||||
"IN_CALL_RECONNECTING" = "Reconnecting...";
|
||||
|
||||
/* Call setup status label */
|
||||
"IN_CALL_RINGING" = "Ringing…";
|
||||
|
||||
|
|
Loading…
Reference in New Issue