diff --git a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift index 5fbdcec3d6..9d5f27e8cb 100644 --- a/submodules/TelegramCallsUI/Sources/CallControllerNode.swift +++ b/submodules/TelegramCallsUI/Sources/CallControllerNode.swift @@ -358,6 +358,8 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro private var validLayout: (ContainerViewLayout, CGFloat)? private var disableActionsUntilTimestamp: Double = 0.0 + private var displayedVersionOutdatedAlert: Bool = false + var isMuted: Bool = false { didSet { self.buttonsNode.isMuted = self.isMuted @@ -417,9 +419,6 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro self.containerTransformationNode.clipsToBounds = true self.containerNode = ASDisplayNode() - if self.shouldStayHiddenUntilConnection { - self.containerNode.alpha = 0.0 - } self.imageNode = TransformImageNode() self.imageNode.contentAnimations = [.subsequentUpdates] @@ -564,7 +563,13 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro self.backButtonNode.addTarget(self, action: #selector(self.backPressed), forControlEvents: .touchUpInside) - if !shouldStayHiddenUntilConnection && call.isVideo && call.isOutgoing { + if shouldStayHiddenUntilConnection { + self.containerNode.alpha = 0.0 + Queue.mainQueue().after(3.0, { [weak self] in + self?.containerNode.alpha = 1.0 + self?.animateIn() + }) + } else if call.isVideo && call.isOutgoing { self.containerNode.alpha = 0.0 Queue.mainQueue().after(1.0, { [weak self] in self?.containerNode.alpha = 1.0 @@ -881,8 +886,20 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro case .hungUp, .missed: statusValue = .text(string: self.presentationData.strings.Call_StatusEnded, displayLogo: false) } - case .error: - statusValue = .text(string: self.presentationData.strings.Call_StatusFailed, displayLogo: false) + case let .error(error): + let text = self.presentationData.strings.Call_StatusFailed + switch error { + case .notSupportedByPeer: + if !self.displayedVersionOutdatedAlert, let peer = self.peer { + self.displayedVersionOutdatedAlert = true + + self.present?(textAlertController(sharedContext: self.sharedContext, title: nil, text: self.presentationData.strings.Call_ParticipantVersionOutdatedError(peer.displayTitle(strings: self.presentationData.strings, displayOrder: self.presentationData.nameDisplayOrder)).0, actions: [TextAlertAction(type: .defaultAction, title: self.presentationData.strings.Common_OK, action: { + })])) + } + default: + break + } + statusValue = .text(string: text, displayLogo: false) } } else { statusValue = .text(string: self.presentationData.strings.Call_StatusEnded, displayLogo: false) @@ -1202,6 +1219,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro let previewVideoSide = interpolate(from: 350.0, to: 200.0, value: 1.0 - self.pictureInPictureTransitionFraction) var previewVideoSize = layout.size.aspectFitted(CGSize(width: previewVideoSide, height: previewVideoSide)) + previewVideoSize = CGSize(width: 30.0, height: 45.0).aspectFitted(previewVideoSize) if let minimizedVideoNode = minimizedVideoNode { switch minimizedVideoNode.currentOrientation { case .rotation90, .rotation270: @@ -1377,6 +1395,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro } if let expandedVideoNode = self.expandedVideoNode { + transition.updateAlpha(node: expandedVideoNode, alpha: 1.0) var expandedVideoTransition = transition if expandedVideoNode.frame.isEmpty || self.disableAnimationForExpandedVideoOnce { expandedVideoTransition = .immediate @@ -1424,6 +1443,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro if let minimizedVideoNode = self.minimizedVideoNode { + transition.updateAlpha(node: minimizedVideoNode, alpha: pipTransitionAlpha) var minimizedVideoTransition = transition var didAppear = false if minimizedVideoNode.frame.isEmpty { diff --git a/submodules/TelegramCallsUI/Sources/PresentationCall.swift b/submodules/TelegramCallsUI/Sources/PresentationCall.swift index 70d1c805e0..2f74c9d32e 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCall.swift @@ -508,7 +508,7 @@ public final class PresentationCallImpl: PresentationCall { } else { if self.isVideo { mappedVideoState = .active - } else if self.isVideoPossible { + } else if self.isVideoPossible && sessionState.isVideoPossible { mappedVideoState = .inactive } else { mappedVideoState = .notAvailable diff --git a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift index 6c99477092..aef43dc9a0 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift @@ -333,7 +333,7 @@ public final class PresentationCallManagerImpl: PresentationCallManager { } else { for (account, _, state, _, _) in ringingStates { if state.id != self.currentCall?.internalId { - account.callSessionManager.drop(internalId: state.id, reason: .missed, debugLog: .single(nil)) + account.callSessionManager.drop(internalId: state.id, reason: .busy, debugLog: .single(nil)) } } } diff --git a/submodules/TelegramCore/Sources/CallSessionManager.swift b/submodules/TelegramCore/Sources/CallSessionManager.swift index 6e6be4ef77..a34a1100c9 100644 --- a/submodules/TelegramCore/Sources/CallSessionManager.swift +++ b/submodules/TelegramCore/Sources/CallSessionManager.swift @@ -186,6 +186,7 @@ public struct CallSession { public let isOutgoing: Bool public let type: CallType public let state: CallSessionState + public let isVideoPossible: Bool } public enum CallSessionConnection: Equatable { @@ -277,7 +278,7 @@ private final class CallSessionContext { let peerId: PeerId let isOutgoing: Bool var type: CallSession.CallType - let isVideoPossible: Bool + var isVideoPossible: Bool var state: CallSessionInternalState let subscribers = Bag<(CallSession) -> Void>() let signalingSubscribers = Bag<(Data) -> Void>() @@ -412,7 +413,7 @@ private final class CallSessionManagerContext { let index = context.subscribers.add { next in subscriber.putNext(next) } - subscriber.putNext(CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context))) + subscriber.putNext(CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context), isVideoPossible: context.isVideoPossible)) disposable.set(ActionDisposable { queue.async { if let strongSelf = self, let context = strongSelf.contexts[internalId] { @@ -473,7 +474,7 @@ private final class CallSessionManagerContext { private func contextUpdated(internalId: CallSessionInternalId) { if let context = self.contexts[internalId] { - let session = CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context)) + let session = CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context), isVideoPossible: context.isVideoPossible) for subscriber in context.subscribers.copyItems() { subscriber(session) } @@ -526,7 +527,9 @@ private final class CallSessionManagerContext { wasRinging = true let internalReason: DropCallSessionReason switch reason { - case .busy, .hangUp: + case .busy: + internalReason = .busy + case .hangUp: internalReason = .hangUp(0) case .disconnect: internalReason = .disconnect @@ -804,6 +807,9 @@ private final class CallSessionManagerContext { switch callProtocol { case let .phoneCallProtocol(_, _, maxLayer, versions): if !versions.isEmpty { + let isVideoPossible = self.videoVersions().contains(where: { versions.contains($0) }) + context.isVideoPossible = isVideoPossible + context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: calculatedKeyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connections.first!, alternative: Array(connections[1...])), maxLayer: maxLayer, version: versions[0], allowsP2P: allowsP2P) self.contextUpdated(internalId: internalId) } else { @@ -820,6 +826,9 @@ private final class CallSessionManagerContext { switch callProtocol { case let .phoneCallProtocol(_, _, maxLayer, versions): if !versions.isEmpty { + let isVideoPossible = self.videoVersions().contains(where: { versions.contains($0) }) + context.isVideoPossible = isVideoPossible + context.state = .active(id: id, accessHash: accessHash, beginTimestamp: startDate, key: key, keyId: keyId, keyVisualHash: keyVisualHash, connections: parseConnectionSet(primary: connections.first!, alternative: Array(connections[1...])), maxLayer: maxLayer, version: versions[0], allowsP2P: allowsP2P) self.contextUpdated(internalId: internalId) } else { @@ -849,7 +858,7 @@ private final class CallSessionManagerContext { } } if let context = self.contexts[internalId] { - let callSession = CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context)) + let callSession = CallSession(id: internalId, isOutgoing: context.isOutgoing, type: context.type, state: CallSessionState(context), isVideoPossible: context.isVideoPossible) if let resultRingingStateValue = resultRingingStateValue { resultRingingState = (resultRingingStateValue, callSession) } diff --git a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm index b723953ee4..5739f30aeb 100644 --- a/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm +++ b/submodules/TgVoipWebrtc/Sources/OngoingCallThreadLocalContext.mm @@ -207,7 +207,6 @@ NSTimeInterval _callPacketTimeout; std::unique_ptr _tgVoip; - OngoingCallThreadLocalContextWebrtcTerminationResult *_terminationResult; OngoingCallStateWebrtc _state; OngoingCallVideoStateWebrtc _videoState; @@ -541,29 +540,19 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; return false; } -- (void)stopInstanceIfNeeded { - if (!_tgVoip) { - return; - } - tgcalls::FinalState finalState = _tgVoip->stop(); - _tgVoip.reset(); - _terminationResult = [[OngoingCallThreadLocalContextWebrtcTerminationResult alloc] initWithFinalState:finalState]; -} - - (void)beginTermination { - [self stopInstanceIfNeeded]; } -- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion { - [self stopInstanceIfNeeded]; +- (void)stopWithTerminationResult:(OngoingCallThreadLocalContextWebrtcTerminationResult *)terminationResult completion:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion { + _tgVoip.reset(); if (completion) { - if (_terminationResult) { - NSString *debugLog = [NSString stringWithUTF8String:_terminationResult.finalState.debugLog.c_str()]; - _lastDerivedState = [[NSData alloc] initWithBytes:_terminationResult.finalState.persistentState.value.data() length:_terminationResult.finalState.persistentState.value.size()]; + if (terminationResult) { + NSString *debugLog = [NSString stringWithUTF8String:terminationResult.finalState.debugLog.c_str()]; + _lastDerivedState = [[NSData alloc] initWithBytes:terminationResult.finalState.persistentState.value.data() length:terminationResult.finalState.persistentState.value.size()]; if (completion) { - completion(debugLog, _terminationResult.finalState.trafficStats.bytesSentWifi, _terminationResult.finalState.trafficStats.bytesReceivedWifi, _terminationResult.finalState.trafficStats.bytesSentMobile, _terminationResult.finalState.trafficStats.bytesReceivedMobile); + completion(debugLog, terminationResult.finalState.trafficStats.bytesSentWifi, terminationResult.finalState.trafficStats.bytesReceivedWifi, terminationResult.finalState.trafficStats.bytesSentMobile, terminationResult.finalState.trafficStats.bytesReceivedMobile); } } else { if (completion) { @@ -573,6 +562,33 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL; } } +- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion { + if (!_tgVoip) { + return; + } + if (completion == nil) { + _tgVoip->stop([](tgcalls::FinalState finalState) { + }); + _tgVoip.reset(); + return; + } + + __weak OngoingCallThreadLocalContextWebrtc *weakSelf = self; + id queue = _queue; + _tgVoip->stop([weakSelf, queue, completion = [completion copy]](tgcalls::FinalState finalState) { + [queue dispatch:^{ + __strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf; + if (!strongSelf) { + return; + } + + OngoingCallThreadLocalContextWebrtcTerminationResult *terminationResult = [[OngoingCallThreadLocalContextWebrtcTerminationResult alloc] initWithFinalState:finalState]; + + [strongSelf stopWithTerminationResult:terminationResult completion:completion]; + }]; + }); +} + - (NSString *)debugInfo { if (_tgVoip != nullptr) { NSString *version = [self version]; diff --git a/submodules/TgVoipWebrtc/tgcalls b/submodules/TgVoipWebrtc/tgcalls index e0e9e39346..a7d9b717fd 160000 --- a/submodules/TgVoipWebrtc/tgcalls +++ b/submodules/TgVoipWebrtc/tgcalls @@ -1 +1 @@ -Subproject commit e0e9e3934601c53b542e4cca617bb4050a33792b +Subproject commit a7d9b717fdf7e8e441b47692dc5771684b2d7970