From e95f84232e2503399d43ac6771da70b3b0ffa97a Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 00:13:12 +0400 Subject: [PATCH 1/7] Debugging --- .../Sources/ChatListSearchListPaneNode.swift | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift index 4c569e6e53..01900a43ab 100644 --- a/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift +++ b/submodules/ChatListUI/Sources/ChatListSearchListPaneNode.swift @@ -1515,7 +1515,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { interaction.dismissInput() }, present: { c, a in interaction.present(c, a) - }, transitionNode: { [weak self] messageId, media in + }, transitionNode: { messageId, media in var transitionNode: (ASDisplayNode, CGRect, () -> (UIView?, UIView?))? if let strongSelf = self { strongSelf.listNode.forEachItemNode { itemNode in @@ -1527,7 +1527,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { } } return transitionNode - }, addToTransitionSurface: { [weak self] view in + }, addToTransitionSurface: { view in self?.addToTransitionSurface(view: view) }, openUrl: { url in interaction.openUrl(url) @@ -1626,7 +1626,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { let firstTime = previousEntries == nil var transition = chatListSearchContainerPreparedTransition(from: previousEntries ?? [], to: newEntries, displayingResults: entriesAndFlags?.0 != nil, isEmpty: !isSearching && (entriesAndFlags?.0.isEmpty ?? false), isLoading: isSearching, animated: animated, context: context, presentationData: strongSelf.presentationData, enableHeaders: true, filter: peersFilter, key: strongSelf.key, tagMask: tagMask, interaction: chatListInteraction, listInteraction: listInteraction, peerContextAction: { message, node, rect, gesture in interaction.peerContextAction?(message, node, rect, gesture) - }, toggleExpandLocalResults: { [weak self] in + }, toggleExpandLocalResults: { guard let strongSelf = self else { return } @@ -1635,7 +1635,7 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { state.expandLocalSearch = !state.expandLocalSearch return state } - }, toggleExpandGlobalResults: { [weak self] in + }, toggleExpandGlobalResults: { guard let strongSelf = self else { return } @@ -1959,6 +1959,9 @@ final class ChatListSearchListPaneNode: ASDisplayNode, ChatListSearchPaneNode { self.recentDisposable.dispose() self.updatedRecentPeersDisposable.dispose() self.deletedMessagesDisposable?.dispose() + if self.key == .downloads { + print("downloads") + } } override func didLoad() { From fd233a4657e9209c33d418540e33fcf6a5d13d18 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 00:13:59 +0400 Subject: [PATCH 2/7] Video stream UI improvements --- .../ActivityIndicatorComponent/BUILD | 18 +++ .../Sources/ActivityIndicatorComponent.swift | 39 +++++ submodules/TelegramCallsUI/BUILD | 1 + .../Components/MediaStreamComponent.swift | 134 +++++++++++------- .../MediaStreamVideoComponent.swift | 39 ++++- .../Sources/PresentationGroupCall.swift | 9 +- 6 files changed, 186 insertions(+), 54 deletions(-) create mode 100644 submodules/Components/ActivityIndicatorComponent/BUILD create mode 100644 submodules/Components/ActivityIndicatorComponent/Sources/ActivityIndicatorComponent.swift diff --git a/submodules/Components/ActivityIndicatorComponent/BUILD b/submodules/Components/ActivityIndicatorComponent/BUILD new file mode 100644 index 0000000000..3f3ab06cbf --- /dev/null +++ b/submodules/Components/ActivityIndicatorComponent/BUILD @@ -0,0 +1,18 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") + +swift_library( + name = "ActivityIndicatorComponent", + module_name = "ActivityIndicatorComponent", + srcs = glob([ + "Sources/**/*.swift", + ]), + copts = [ + "-warnings-as-errors", + ], + deps = [ + "//submodules/ComponentFlow:ComponentFlow", + ], + visibility = [ + "//visibility:public", + ], +) diff --git a/submodules/Components/ActivityIndicatorComponent/Sources/ActivityIndicatorComponent.swift b/submodules/Components/ActivityIndicatorComponent/Sources/ActivityIndicatorComponent.swift new file mode 100644 index 0000000000..b40c991289 --- /dev/null +++ b/submodules/Components/ActivityIndicatorComponent/Sources/ActivityIndicatorComponent.swift @@ -0,0 +1,39 @@ +import Foundation +import UIKit +import ComponentFlow + +public final class ActivityIndicatorComponent: Component { + public init( + ) { + } + + public static func ==(lhs: ActivityIndicatorComponent, rhs: ActivityIndicatorComponent) -> Bool { + return true + } + + public final class View: UIActivityIndicatorView { + public init() { + super.init(style: .whiteLarge) + } + + required public init(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func update(component: ActivityIndicatorComponent, availableSize: CGSize, transition: Transition) -> CGSize { + if !self.isAnimating { + self.startAnimating() + } + + return CGSize(width: 22.0, height: 22.0) + } + } + + public func makeView() -> View { + return View() + } + + public func update(view: View, availableSize: CGSize, state: EmptyComponentState, environment: Environment, transition: Transition) -> CGSize { + return view.update(component: self, availableSize: availableSize, transition: transition) + } +} diff --git a/submodules/TelegramCallsUI/BUILD b/submodules/TelegramCallsUI/BUILD index bedebbc74d..591d757de4 100644 --- a/submodules/TelegramCallsUI/BUILD +++ b/submodules/TelegramCallsUI/BUILD @@ -97,6 +97,7 @@ swift_library( "//third-party/libyuv:LibYuvBinding", "//submodules/ComponentFlow:ComponentFlow", "//submodules/Components/LottieAnimationComponent:LottieAnimationComponent", + "//submodules/Components/ActivityIndicatorComponent:ActivityIndicatorComponent", ], visibility = [ "//visibility:public", diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index b47b6e199c..ed1460c0bf 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -588,29 +588,28 @@ public final class MediaStreamComponent: CombinedComponent { let call = context.component.call let controller = environment.controller - let video = Condition(context.state.hasVideo) { - return video.update( - component: MediaStreamVideoComponent( - call: context.component.call, - activatePictureInPicture: activatePictureInPicture, - bringBackControllerForPictureInPictureDeactivation: { [weak call] completed in - guard let call = call else { - completed() - return - } - - call.accountContext.sharedContext.mainWindow?.inCallNavigate?() - + let video = video.update( + component: MediaStreamVideoComponent( + call: context.component.call, + hasVideo: context.state.hasVideo, + activatePictureInPicture: activatePictureInPicture, + bringBackControllerForPictureInPictureDeactivation: { [weak call] completed in + guard let call = call else { completed() + return } - ), - availableSize: context.availableSize, - transition: context.transition - ) - } + + call.accountContext.sharedContext.mainWindow?.inCallNavigate?() + + completed() + } + ), + availableSize: context.availableSize, + transition: context.transition + ) var navigationRightItems: [AnyComponentWithIdentity] = [] - if context.state.isPictureInPictureSupported, let _ = video { + if context.state.isPictureInPictureSupported, context.state.hasVideo { navigationRightItems.append(AnyComponentWithIdentity(id: "pip", component: AnyComponent(Button( content: AnyComponent(BundleIconComponent( name: "Media Gallery/PictureInPictureButton", @@ -663,7 +662,7 @@ public final class MediaStreamComponent: CombinedComponent { topInset: environment.statusBarHeight, sideInset: environment.safeInsets.left, leftItem: AnyComponent(Button( - content: AnyComponent(NavigationBackButtonComponent(text: environment.strings.Common_Back, color: .white)), + content: AnyComponent(NavigationBackButtonComponent(text: environment.strings.Common_Close, color: .white)), action: { [weak call] in let _ = call?.leave(terminateIfPossible: false) }) @@ -754,11 +753,9 @@ public final class MediaStreamComponent: CombinedComponent { }) ) - if let video = video { - context.add(video - .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0 + context.state.dismissOffset)) - ) - } + context.add(video + .position(CGPoint(x: context.availableSize.width / 2.0, y: context.availableSize.height / 2.0 + context.state.dismissOffset)) + ) context.add(navigationBar .position(CGPoint(x: context.availableSize.width / 2.0, y: navigationBar.size.height / 2.0)) @@ -776,6 +773,7 @@ public final class MediaStreamComponent: CombinedComponent { } public final class MediaStreamComponentController: ViewControllerComponentContainer, VoiceChatController { + private let context: AccountContext public let call: PresentationGroupCall public private(set) var currentOverlayController: VoiceChatOverlayController? = nil public var parentNavigationController: NavigationController? @@ -785,13 +783,19 @@ public final class MediaStreamComponentController: ViewControllerComponentContai private var initialOrientation: UIInterfaceOrientation? + private let inviteLinksPromise = Promise(nil) + public init(call: PresentationGroupCall) { + self.context = call.accountContext self.call = call super.init(context: call.accountContext, component: MediaStreamComponent(call: call as! PresentationGroupCallImpl)) self.statusBar.statusBarStyle = .White self.view.disablesInteractiveModalDismiss = true + + self.inviteLinksPromise.set(.single(nil) + |> then(call.inviteLinks)) } required public init(coder aDecoder: NSCoder) { @@ -858,6 +862,41 @@ public final class MediaStreamComponentController: ViewControllerComponentContai } func presentShare() { + let _ = (self.inviteLinksPromise.get() + |> take(1) + |> deliverOnMainQueue).start(next: { [weak self] inviteLinks in + guard let strongSelf = self else { + return + } + + let callPeerId = strongSelf.call.peerId + let _ = (strongSelf.call.accountContext.account.postbox.transaction { transaction -> GroupCallInviteLinks? in + if let inviteLinks = inviteLinks { + return inviteLinks + } else if let peer = transaction.getPeer(callPeerId), let addressName = peer.addressName, !addressName.isEmpty { + return GroupCallInviteLinks(listenerLink: "https://t.me/\(addressName)?voicechat", speakerLink: nil) + } else if let cachedData = transaction.getPeerCachedData(peerId: callPeerId) { + if let cachedData = cachedData as? CachedChannelData, let link = cachedData.exportedInvitation?.link { + return GroupCallInviteLinks(listenerLink: link, speakerLink: nil) + } else if let cachedData = cachedData as? CachedGroupData, let link = cachedData.exportedInvitation?.link { + return GroupCallInviteLinks(listenerLink: link, speakerLink: nil) + } + } + return nil + } + |> deliverOnMainQueue).start(next: { links in + guard let strongSelf = self else { + return + } + + if let links = links { + strongSelf.presentShare(links: links) + } + }) + }) + } + + func presentShare(links inviteLinks: GroupCallInviteLinks) { let formatSendTitle: (String) -> String = { string in var string = string if string.contains("[") && string.contains("]") { @@ -869,34 +908,29 @@ public final class MediaStreamComponentController: ViewControllerComponentContai } return string } + let _ = formatSendTitle - let _ = (combineLatest(self.call.accountContext.account.postbox.loadedPeerWithId(self.call.peerId), self.call.state |> take(1)) + let _ = (combineLatest(queue: .mainQueue(), self.context.account.postbox.loadedPeerWithId(self.call.peerId), self.call.state |> take(1)) |> deliverOnMainQueue).start(next: { [weak self] peer, callState in if let strongSelf = self { - var maybeInviteLinks: GroupCallInviteLinks? = nil + var inviteLinks = inviteLinks - if let peer = peer as? TelegramChannel, let addressName = peer.addressName { - maybeInviteLinks = GroupCallInviteLinks(listenerLink: "https://t.me/\(addressName)", speakerLink: nil) + if let peer = peer as? TelegramChannel, case .group = peer.info, !peer.flags.contains(.isGigagroup), !(peer.addressName ?? "").isEmpty, let defaultParticipantMuteState = callState.defaultParticipantMuteState { + let isMuted = defaultParticipantMuteState == .muted + + if !isMuted { + inviteLinks = GroupCallInviteLinks(listenerLink: inviteLinks.listenerLink, speakerLink: nil) + } } - guard let inviteLinks = maybeInviteLinks else { - return - } - - let presentationData = strongSelf.call.accountContext.sharedContext.currentPresentationData.with { $0 } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } var segmentedValues: [ShareControllerSegmentedValue]? - if let speakerLink = inviteLinks.speakerLink { - segmentedValues = [ShareControllerSegmentedValue(title: presentationData.strings.VoiceChat_InviteLink_Speaker, subject: .url(speakerLink), actionTitle: presentationData.strings.VoiceChat_InviteLink_CopySpeakerLink, formatSendTitle: { count in - return formatSendTitle(presentationData.strings.VoiceChat_InviteLink_InviteSpeakers(Int32(count))) - }), ShareControllerSegmentedValue(title: presentationData.strings.VoiceChat_InviteLink_Listener, subject: .url(inviteLinks.listenerLink), actionTitle: presentationData.strings.VoiceChat_InviteLink_CopyListenerLink, formatSendTitle: { count in - return formatSendTitle(presentationData.strings.VoiceChat_InviteLink_InviteListeners(Int32(count))) - })] - } - let shareController = ShareController(context: strongSelf.call.accountContext, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forceTheme: defaultDarkColorPresentationTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink) + segmentedValues = nil + let shareController = ShareController(context: strongSelf.context, subject: .url(inviteLinks.listenerLink), segmentedValues: segmentedValues, forceTheme: defaultDarkPresentationTheme, forcedActionTitle: presentationData.strings.VoiceChat_CopyInviteLink) shareController.completed = { [weak self] peerIds in if let strongSelf = self { - let _ = (strongSelf.call.accountContext.account.postbox.transaction { transaction -> [Peer] in + let _ = (strongSelf.context.account.postbox.transaction { transaction -> [Peer] in var peers: [Peer] = [] for peerId in peerIds { if let peer = transaction.getPeer(peerId) { @@ -904,19 +938,19 @@ public final class MediaStreamComponentController: ViewControllerComponentContai } } return peers - } |> deliverOnMainQueue).start(next: { peers in + } |> deliverOnMainQueue).start(next: { [weak self] peers in if let strongSelf = self { - let presentationData = strongSelf.call.accountContext.sharedContext.currentPresentationData.with { $0 } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } let text: String var isSavedMessages = false if peers.count == 1, let peer = peers.first { - isSavedMessages = peer.id == strongSelf.call.accountContext.account.peerId - let peerName = peer.id == strongSelf.call.accountContext.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + isSavedMessages = peer.id == strongSelf.context.account.peerId + let peerName = peer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) text = presentationData.strings.VoiceChat_ForwardTooltip_Chat(peerName).string } else if peers.count == 2, let firstPeer = peers.first, let secondPeer = peers.last { - let firstPeerName = firstPeer.id == strongSelf.call.accountContext.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) - let secondPeerName = secondPeer.id == strongSelf.call.accountContext.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + let firstPeerName = firstPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(firstPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) + let secondPeerName = secondPeer.id == strongSelf.context.account.peerId ? presentationData.strings.DialogList_SavedMessages : EnginePeer(secondPeer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) text = presentationData.strings.VoiceChat_ForwardTooltip_TwoChats(firstPeerName, secondPeerName).string } else if let peer = peers.first { let peerName = EnginePeer(peer).displayTitle(strings: presentationData.strings, displayOrder: presentationData.nameDisplayOrder) @@ -932,7 +966,7 @@ public final class MediaStreamComponentController: ViewControllerComponentContai } shareController.actionCompleted = { if let strongSelf = self { - let presentationData = strongSelf.call.accountContext.sharedContext.currentPresentationData.with { $0 } + let presentationData = strongSelf.context.sharedContext.currentPresentationData.with { $0 } strongSelf.present(UndoOverlayController(presentationData: presentationData, content: .linkCopied(text: presentationData.strings.VoiceChat_InviteLinkCopiedText), elevatedLayout: false, animateInAsReplacement: false, action: { _ in return false }), in: .window(.root)) } } diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift index 9b05313e40..c67de46857 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift @@ -1,16 +1,19 @@ import Foundation import UIKit import ComponentFlow +import ActivityIndicatorComponent import AccountContext import AVKit final class MediaStreamVideoComponent: Component { let call: PresentationGroupCallImpl + let hasVideo: Bool let activatePictureInPicture: ActionSlot> let bringBackControllerForPictureInPictureDeactivation: (@escaping () -> Void) -> Void - init(call: PresentationGroupCallImpl, activatePictureInPicture: ActionSlot>, bringBackControllerForPictureInPictureDeactivation: @escaping (@escaping () -> Void) -> Void) { + init(call: PresentationGroupCallImpl, hasVideo: Bool, activatePictureInPicture: ActionSlot>, bringBackControllerForPictureInPictureDeactivation: @escaping (@escaping () -> Void) -> Void) { self.call = call + self.hasVideo = hasVideo self.activatePictureInPicture = activatePictureInPicture self.bringBackControllerForPictureInPictureDeactivation = bringBackControllerForPictureInPictureDeactivation } @@ -19,6 +22,9 @@ final class MediaStreamVideoComponent: Component { if lhs.call !== rhs.call { return false } + if lhs.hasVideo != rhs.hasVideo { + return false + } return true } @@ -38,6 +44,7 @@ final class MediaStreamVideoComponent: Component { private var videoView: VideoRenderingView? private let blurTintView: UIView private var videoBlurView: VideoRenderingView? + private var activityIndicatorView: ComponentHostView? private var pictureInPictureController: AVPictureInPictureController? @@ -60,7 +67,7 @@ final class MediaStreamVideoComponent: Component { } func update(component: MediaStreamVideoComponent, availableSize: CGSize, state: State, transition: Transition) -> CGSize { - if self.videoView == nil { + if component.hasVideo, self.videoView == nil { if let input = component.call.video(endpointId: "unified") { if let videoBlurView = self.videoRenderingContext.makeView(input: input, blur: true) { self.videoBlurView = videoBlurView @@ -83,7 +90,14 @@ final class MediaStreamVideoComponent: Component { videoView.setOnOrientationUpdated { [weak state] _, _ in state?.updated(transition: .immediate) } - videoView.setOnFirstFrameReceived { [weak state] _ in + videoView.setOnFirstFrameReceived { [weak self, weak state] _ in + guard let strongSelf = self else { + return + } + + strongSelf.activityIndicatorView?.removeFromSuperview() + strongSelf.activityIndicatorView = nil + state?.updated(transition: .immediate) } } @@ -106,6 +120,25 @@ final class MediaStreamVideoComponent: Component { videoBlurView.updateIsEnabled(true) transition.withAnimation(.none).setFrame(view: videoBlurView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - blurredVideoSize.width) / 2.0), y: floor((availableSize.height - blurredVideoSize.height) / 2.0)), size: blurredVideoSize), completion: nil) } + } else { + var activityIndicatorTransition = transition + let activityIndicatorView: ComponentHostView + if let current = self.activityIndicatorView { + activityIndicatorView = current + } else { + activityIndicatorTransition = transition.withAnimation(.none) + activityIndicatorView = ComponentHostView() + self.activityIndicatorView = activityIndicatorView + self.addSubview(activityIndicatorView) + } + + let activityIndicatorSize = activityIndicatorView.update( + transition: transition, + component: AnyComponent(ActivityIndicatorComponent()), + environment: {}, + containerSize: CGSize(width: 100.0, height: 100.0) + ) + activityIndicatorTransition.setFrame(view: activityIndicatorView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - activityIndicatorSize.width) / 2.0), y: floor((availableSize.height - activityIndicatorSize.height) / 2.0)), size: activityIndicatorSize), completion: nil) } self.component = component diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index de1d054cd1..6a64b4c250 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -229,7 +229,14 @@ public final class AccountGroupCallContextCacheImpl: AccountGroupCallContextCach } public func leaveInBackground(engine: TelegramEngine, id: Int64, accessHash: Int64, source: UInt32) { - let disposable = engine.calls.leaveGroupCall(callId: id, accessHash: accessHash, source: source).start() + let disposable = engine.calls.leaveGroupCall(callId: id, accessHash: accessHash, source: source).start(completed: { [weak self] in + guard let strongSelf = self else { + return + } + if let context = strongSelf.contexts[id] { + context.context.participantsContext?.removeLocalPeerId() + } + }) self.leaveDisposables.add(disposable) } } From c3b36dda43d5da7343b1eb8ddf3733884e860dcb Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 00:54:32 +0400 Subject: [PATCH 3/7] Video streaming improvements --- .../Sources/PresentationCallManager.swift | 6 +++-- .../Sources/PresentationGroupCall.swift | 23 +++++++++--------- .../SyncCore/SyncCore_CachedChannelData.swift | 12 ++++++---- .../TelegramEngine/Calls/GroupCalls.swift | 24 +++++++++++++++---- .../Messages/EngineGroupCallDescription.swift | 4 ++-- .../Peers/UpdateCachedPeerData.swift | 4 ++-- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift index da802b9552..17acbdf4ee 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationCallManager.swift @@ -687,7 +687,8 @@ public final class PresentationCallManagerImpl: PresentationCallManager { peerId: peerId, isChannel: isChannel, invite: nil, - joinAsPeerId: nil + joinAsPeerId: nil, + isStream: false ) strongSelf.updateCurrentGroupCall(call) strongSelf.currentGroupCallPromise.set(.single(call)) @@ -849,7 +850,8 @@ public final class PresentationCallManagerImpl: PresentationCallManager { peerId: peerId, isChannel: isChannel, invite: invite, - joinAsPeerId: joinAsPeerId + joinAsPeerId: joinAsPeerId, + isStream: initialCall.isStream ?? false ) strongSelf.updateCurrentGroupCall(call) strongSelf.currentGroupCallPromise.set(.single(call)) diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 6a64b4c250..19da16952e 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -86,13 +86,14 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { var disposable: Disposable? public var participantsContext: GroupCallParticipantsContext? - private let panelDataPromise = Promise() - public var panelData: Signal { + private let panelDataPromise = Promise() + public var panelData: Signal { return self.panelDataPromise.get() } public init(account: Account, engine: TelegramEngine, peerId: PeerId, isChannel: Bool, call: EngineGroupCallDescription) { - self.panelDataPromise.set(.single(GroupCallPanelData( + self.panelDataPromise.set(.single(nil)) + /*self.panelDataPromise.set(.single(GroupCallPanelData( peerId: peerId, isChannel: isChannel, info: GroupCallInfo( @@ -114,7 +115,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { participantCount: 0, activeSpeakers: Set(), groupCall: nil - ))) + )))*/ let state = engine.calls.getGroupCallParticipants(callId: call.id, accessHash: call.accessHash, offset: "", ssrcs: [], limit: 100, sortAscending: nil) |> map(Optional.init) @@ -161,7 +162,7 @@ public final class AccountGroupCallContextImpl: AccountGroupCallContext { return GroupCallPanelData( peerId: peerId, isChannel: isChannel, - info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, subscribedToScheduled: state.subscribedToScheduled, recordingStartTimestamp: nil, sortAscending: state.sortAscending, defaultParticipantsAreMuted: state.defaultParticipantsAreMuted, isVideoEnabled: state.isVideoEnabled, unmutedVideoLimit: state.unmutedVideoLimit, isStream: call.isStream), + info: GroupCallInfo(id: call.id, accessHash: call.accessHash, participantCount: state.totalCount, streamDcId: nil, title: state.title, scheduleTimestamp: state.scheduleTimestamp, subscribedToScheduled: state.subscribedToScheduled, recordingStartTimestamp: nil, sortAscending: state.sortAscending, defaultParticipantsAreMuted: state.defaultParticipantsAreMuted, isVideoEnabled: state.isVideoEnabled, unmutedVideoLimit: state.unmutedVideoLimit, isStream: state.isStream), topParticipants: topParticipants, participantCount: state.totalCount, activeSpeakers: activeSpeakers, @@ -637,7 +638,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { private var screencastAudioDataDisposable: Disposable? private var screencastStateDisposable: Disposable? - public var isStream = false + public let isStream: Bool init( accountContext: AccountContext, @@ -649,7 +650,8 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { peerId: PeerId, isChannel: Bool, invite: String?, - joinAsPeerId: PeerId? + joinAsPeerId: PeerId?, + isStream: Bool ) { self.account = accountContext.account self.accountContext = accountContext @@ -666,10 +668,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.schedulePending = initialCall == nil self.isScheduled = initialCall == nil || initialCall?.scheduleTimestamp != nil - if let initialCall = initialCall { - self.isStream = initialCall.isStream - } - self.stateValue = PresentationGroupCallState.initialValue(myPeerId: self.joinAsPeerId, title: initialCall?.title, scheduleTimestamp: initialCall?.scheduleTimestamp, subscribedToScheduled: initialCall?.subscribedToScheduled ?? false) self.statePromise = ValuePromise(self.stateValue) @@ -678,6 +676,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { self.isVideoEnabled = true self.hasVideo = false self.hasScreencast = false + self.isStream = isStream var didReceiveAudioOutputs = false @@ -1235,6 +1234,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { totalCount: 0, isVideoEnabled: callInfo.isVideoEnabled, unmutedVideoLimit: callInfo.unmutedVideoLimit, + isStream: callInfo.isStream, version: 0 ), previousServiceState: nil @@ -3002,7 +3002,6 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { if let value = value { strongSelf.initialCall = EngineGroupCallDescription(id: value.id, accessHash: value.accessHash, title: value.title, scheduleTimestamp: nil, subscribedToScheduled: false, isStream: value.isStream) - strongSelf.isStream = value.isStream strongSelf.updateSessionState(internalState: .active(value), audioSessionControl: strongSelf.audioSessionControl) } else { diff --git a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift index 72bb4bc5e5..39ec7eb900 100644 --- a/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift +++ b/submodules/TelegramCore/Sources/SyncCore/SyncCore_CachedChannelData.swift @@ -161,7 +161,7 @@ public final class CachedChannelData: CachedPeerData { public var title: String? public var scheduleTimestamp: Int32? public var subscribedToScheduled: Bool - public var isStream: Bool + public var isStream: Bool? public init( id: Int64, @@ -169,7 +169,7 @@ public final class CachedChannelData: CachedPeerData { title: String?, scheduleTimestamp: Int32?, subscribedToScheduled: Bool, - isStream: Bool + isStream: Bool? ) { self.id = id self.accessHash = accessHash @@ -185,7 +185,7 @@ public final class CachedChannelData: CachedPeerData { self.title = decoder.decodeOptionalStringForKey("title") self.scheduleTimestamp = decoder.decodeOptionalInt32ForKey("scheduleTimestamp") self.subscribedToScheduled = decoder.decodeBoolForKey("subscribed", orElse: false) - self.isStream = decoder.decodeBoolForKey("isStream", orElse: false) + self.isStream = decoder.decodeOptionalBoolForKey("isStream_v2") } public func encode(_ encoder: PostboxEncoder) { @@ -202,7 +202,11 @@ public final class CachedChannelData: CachedPeerData { encoder.encodeNil(forKey: "scheduleTimestamp") } encoder.encodeBool(self.subscribedToScheduled, forKey: "subscribed") - encoder.encodeBool(self.isStream, forKey: "isStream") + if let isStream = self.isStream { + encoder.encodeBool(isStream, forKey: "isStream") + } else { + encoder.encodeNil(forKey: "isStream") + } } } diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index 5216af4da7..4b07cdd187 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -342,17 +342,17 @@ public enum GetGroupCallParticipantsError { } func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessHash: Int64, offset: String, ssrcs: [UInt32], limit: Int32, sortAscending: Bool?) -> Signal { - let sortAscendingValue: Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int), GetGroupCallParticipantsError> + let sortAscendingValue: Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int, Bool), GetGroupCallParticipantsError> sortAscendingValue = _internal_getCurrentGroupCall(account: account, callId: callId, accessHash: accessHash) |> mapError { _ -> GetGroupCallParticipantsError in return .generic } - |> mapToSignal { result -> Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int), GetGroupCallParticipantsError> in + |> mapToSignal { result -> Signal<(Bool, Int32?, Bool, GroupCallParticipantsContext.State.DefaultParticipantsAreMuted?, Bool, Int, Bool), GetGroupCallParticipantsError> in guard let result = result else { return .fail(.generic) } - return .single((sortAscending ?? result.info.sortAscending, result.info.scheduleTimestamp, result.info.subscribedToScheduled, result.info.defaultParticipantsAreMuted, result.info.isVideoEnabled, result.info.unmutedVideoLimit)) + return .single((sortAscending ?? result.info.sortAscending, result.info.scheduleTimestamp, result.info.subscribedToScheduled, result.info.defaultParticipantsAreMuted, result.info.isVideoEnabled, result.info.unmutedVideoLimit, result.info.isStream)) } return combineLatest( @@ -369,7 +369,7 @@ func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessH let version: Int32 let nextParticipantsFetchOffset: String? - let (sortAscendingValue, scheduleTimestamp, subscribedToScheduled, defaultParticipantsAreMuted, isVideoEnabled, unmutedVideoLimit) = sortAscendingAndScheduleTimestamp + let (sortAscendingValue, scheduleTimestamp, subscribedToScheduled, defaultParticipantsAreMuted, isVideoEnabled, unmutedVideoLimit, isStream) = sortAscendingAndScheduleTimestamp switch result { case let .groupParticipants(count, participants, nextOffset, chats, users, apiVersion): @@ -423,6 +423,7 @@ func _internal_getGroupCallParticipants(account: Account, callId: Int64, accessH totalCount: totalCount, isVideoEnabled: isVideoEnabled, unmutedVideoLimit: unmutedVideoLimit, + isStream: isStream, version: version ) } @@ -1047,6 +1048,7 @@ public final class GroupCallParticipantsContext { public var totalCount: Int public var isVideoEnabled: Bool public var unmutedVideoLimit: Int + public var isStream: Bool public var version: Int32 public mutating func mergeActivity(from other: State, myPeerId: PeerId?, previousMyPeerId: PeerId?, mergeActivityTimestamps: Bool) { @@ -1081,6 +1083,7 @@ public final class GroupCallParticipantsContext { totalCount: Int, isVideoEnabled: Bool, unmutedVideoLimit: Int, + isStream: Bool, version: Int32 ) { self.participants = participants @@ -1096,6 +1099,7 @@ public final class GroupCallParticipantsContext { self.totalCount = totalCount self.isVideoEnabled = isVideoEnabled self.unmutedVideoLimit = unmutedVideoLimit + self.isStream = isStream self.version = version } } @@ -1398,6 +1402,7 @@ public final class GroupCallParticipantsContext { totalCount: strongSelf.stateValue.state.totalCount, isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled, unmutedVideoLimit: strongSelf.stateValue.state.unmutedVideoLimit, + isStream: strongSelf.stateValue.state.isStream, version: strongSelf.stateValue.state.version ), overlayState: strongSelf.stateValue.overlayState @@ -1471,6 +1476,14 @@ public final class GroupCallParticipantsContext { } } + public func removeLocalPeerId() { + var state = self.stateValue.state + + state.participants.removeAll(where: { $0.peer.id == self.myPeerId }) + + self.stateValue.state = state + } + private func takeNextActivityRank() -> Int { let value = self.serviceState.nextActivityRank self.serviceState.nextActivityRank += 1 @@ -1537,6 +1550,7 @@ public final class GroupCallParticipantsContext { totalCount: strongSelf.stateValue.state.totalCount, isVideoEnabled: strongSelf.stateValue.state.isVideoEnabled, unmutedVideoLimit: strongSelf.stateValue.state.unmutedVideoLimit, + isStream: strongSelf.stateValue.state.isStream, version: strongSelf.stateValue.state.version ), overlayState: strongSelf.stateValue.overlayState @@ -1758,6 +1772,7 @@ public final class GroupCallParticipantsContext { let scheduleTimestamp = strongSelf.stateValue.state.scheduleTimestamp let subscribedToScheduled = strongSelf.stateValue.state.subscribedToScheduled let isVideoEnabled = strongSelf.stateValue.state.isVideoEnabled + let isStream = strongSelf.stateValue.state.isStream let unmutedVideoLimit = strongSelf.stateValue.state.unmutedVideoLimit updatedParticipants.sort(by: { GroupCallParticipantsContext.Participant.compare(lhs: $0, rhs: $1, sortAscending: strongSelf.stateValue.state.sortAscending) }) @@ -1777,6 +1792,7 @@ public final class GroupCallParticipantsContext { totalCount: updatedTotalCount, isVideoEnabled: isVideoEnabled, unmutedVideoLimit: unmutedVideoLimit, + isStream: isStream, version: update.version ), overlayState: updatedOverlayState diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineGroupCallDescription.swift b/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineGroupCallDescription.swift index b2468bccb4..5975c38881 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineGroupCallDescription.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Messages/EngineGroupCallDescription.swift @@ -6,7 +6,7 @@ public final class EngineGroupCallDescription { public let title: String? public let scheduleTimestamp: Int32? public let subscribedToScheduled: Bool - public let isStream: Bool + public let isStream: Bool? public init( id: Int64, @@ -14,7 +14,7 @@ public final class EngineGroupCallDescription { title: String?, scheduleTimestamp: Int32?, subscribedToScheduled: Bool, - isStream: Bool + isStream: Bool? ) { self.id = id self.accessHash = accessHash diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift index d845b546c5..b31a717fab 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Peers/UpdateCachedPeerData.swift @@ -349,7 +349,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee if let inputCall = chatFullCall { switch inputCall { case let .inputGroupCall(id, accessHash): - updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false, isStream: previous.activeCall?.isStream ?? false) + updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false, isStream: previous.activeCall?.isStream) } } @@ -568,7 +568,7 @@ func _internal_fetchAndUpdateCachedPeerData(accountPeerId: PeerId, peerId rawPee if let inputCall = inputCall { switch inputCall { case let .inputGroupCall(id, accessHash): - updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false, isStream: previous.activeCall?.isStream ?? false) + updatedActiveCall = CachedChannelData.ActiveCall(id: id, accessHash: accessHash, title: previous.activeCall?.title, scheduleTimestamp: previous.activeCall?.scheduleTimestamp, subscribedToScheduled: previous.activeCall?.subscribedToScheduled ?? false, isStream: previous.activeCall?.isStream) } } From 87f9b5d861003b2174af29c18488bed71ebb824e Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 01:45:31 +0400 Subject: [PATCH 4/7] Video streaming improvements --- .../Components/MediaStreamComponent.swift | 39 ++++++++++++++++++- .../MediaStreamVideoComponent.swift | 27 +++++++++++-- .../Components/ViewControllerComponent.swift | 6 +-- .../Sources/PresentationGroupCall.swift | 10 ++++- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index ed1460c0bf..91cd26170c 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -489,8 +489,12 @@ public final class MediaStreamComponent: CombinedComponent { private(set) var displayUI: Bool = true var dismissOffset: CGFloat = 0.0 + var storedIsLandscape: Bool? + let isPictureInPictureSupported: Bool + private var scheduledDismissUITimer: SwiftSignalKit.Timer? + init(call: PresentationGroupCallImpl) { self.call = call @@ -551,6 +555,26 @@ public final class MediaStreamComponent: CombinedComponent { self.updated(transition: Transition(animation: .curve(duration: 0.4, curve: .easeInOut))) } + func cancelScheduledDismissUI() { + self.scheduledDismissUITimer?.invalidate() + self.scheduledDismissUITimer = nil + } + + func scheduleDismissUI() { + if self.scheduledDismissUITimer == nil { + self.scheduledDismissUITimer = SwiftSignalKit.Timer(timeout: 5.0, repeat: false, completion: { [weak self] in + guard let strongSelf = self else { + return + } + strongSelf.scheduledDismissUITimer = nil + if strongSelf.displayUI { + strongSelf.toggleDisplayUI() + } + }, queue: .mainQueue()) + self.scheduledDismissUITimer?.start() + } + } + func updateDismissOffset(value: CGFloat, interactive: Bool) { self.dismissOffset = value if interactive { @@ -575,7 +599,8 @@ public final class MediaStreamComponent: CombinedComponent { return { context in let environment = context.environment[ViewControllerComponentContainer.Environment.self].value - if !environment.isVisible { + if environment.isVisible { + } else { context.state.dismissOffset = 0.0 } @@ -675,6 +700,14 @@ public final class MediaStreamComponent: CombinedComponent { ) let isLandscape = context.availableSize.width > context.availableSize.height + if context.state.storedIsLandscape != isLandscape { + context.state.storedIsLandscape = isLandscape + if isLandscape { + context.state.scheduleDismissUI() + } else { + context.state.cancelScheduledDismissUI() + } + } var infoItem: AnyComponent? if let originInfo = context.state.originInfo { @@ -815,6 +848,10 @@ public final class MediaStreamComponentController: ViewControllerComponentContai self.onViewDidAppear?() } + if let view = self.node.hostView.findTaggedView(tag: MediaStreamVideoComponent.View.Tag()) as? MediaStreamVideoComponent.View { + view.expandFromPictureInPicture() + } + self.view.layer.allowsGroupOpacity = true self.view.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.25, completion: { [weak self] _ in guard let strongSelf = self else { diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift index c67de46857..e6e534a236 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift @@ -39,7 +39,10 @@ final class MediaStreamVideoComponent: Component { return State() } - public final class View: UIView, AVPictureInPictureControllerDelegate, AVPictureInPictureSampleBufferPlaybackDelegate { + public final class View: UIView, AVPictureInPictureControllerDelegate, AVPictureInPictureSampleBufferPlaybackDelegate, ComponentTaggedView { + public final class Tag { + } + private let videoRenderingContext = VideoRenderingContext() private var videoView: VideoRenderingView? private let blurTintView: UIView @@ -49,6 +52,7 @@ final class MediaStreamVideoComponent: Component { private var pictureInPictureController: AVPictureInPictureController? private var component: MediaStreamVideoComponent? + private var hadVideo: Bool = false override init(frame: CGRect) { self.blurTintView = UIView() @@ -66,6 +70,17 @@ final class MediaStreamVideoComponent: Component { fatalError("init(coder:) has not been implemented") } + public func matches(tag: Any) -> Bool { + if let _ = tag as? Tag { + return true + } + return false + } + + func expandFromPictureInPicture() { + self.pictureInPictureController?.stopPictureInPicture() + } + func update(component: MediaStreamVideoComponent, availableSize: CGSize, state: State, transition: Transition) -> CGSize { if component.hasVideo, self.videoView == nil { if let input = component.call.video(endpointId: "unified") { @@ -80,11 +95,12 @@ final class MediaStreamVideoComponent: Component { if #available(iOSApplicationExtension 15.0, iOS 15.0, *), AVPictureInPictureController.isPictureInPictureSupported(), let sampleBufferVideoView = videoView as? SampleBufferVideoRenderingView { let pictureInPictureController = AVPictureInPictureController(contentSource: AVPictureInPictureController.ContentSource(sampleBufferDisplayLayer: sampleBufferVideoView.sampleBufferLayer, playbackDelegate: self)) - self.pictureInPictureController = pictureInPictureController + pictureInPictureController.delegate = self pictureInPictureController.canStartPictureInPictureAutomaticallyFromInline = true pictureInPictureController.requiresLinearPlayback = true - pictureInPictureController.delegate = self + + self.pictureInPictureController = pictureInPictureController } videoView.setOnOrientationUpdated { [weak state] _, _ in @@ -95,6 +111,7 @@ final class MediaStreamVideoComponent: Component { return } + strongSelf.hadVideo = true strongSelf.activityIndicatorView?.removeFromSuperview() strongSelf.activityIndicatorView = nil @@ -120,7 +137,9 @@ final class MediaStreamVideoComponent: Component { videoBlurView.updateIsEnabled(true) transition.withAnimation(.none).setFrame(view: videoBlurView, frame: CGRect(origin: CGPoint(x: floor((availableSize.width - blurredVideoSize.width) / 2.0), y: floor((availableSize.height - blurredVideoSize.height) / 2.0)), size: blurredVideoSize), completion: nil) } - } else { + } + + if !self.hadVideo { var activityIndicatorTransition = transition let activityIndicatorView: ComponentHostView if let current = self.activityIndicatorView { diff --git a/submodules/TelegramCallsUI/Sources/Components/ViewControllerComponent.swift b/submodules/TelegramCallsUI/Sources/Components/ViewControllerComponent.swift index 18bce06c63..ccc5ae4bee 100644 --- a/submodules/TelegramCallsUI/Sources/Components/ViewControllerComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/ViewControllerComponent.swift @@ -78,12 +78,12 @@ open class ViewControllerComponentContainer: ViewController { } } - private final class Node: ViewControllerTracingNode { + final class Node: ViewControllerTracingNode { private var presentationData: PresentationData private weak var controller: ViewControllerComponentContainer? private let component: AnyComponent - private let hostView: ComponentHostView + let hostView: ComponentHostView private var currentIsVisible: Bool = false private var currentLayout: ContainerViewLayout? @@ -137,7 +137,7 @@ open class ViewControllerComponentContainer: ViewController { } } - private var node: Node { + var node: Node { return self.displayNode as! Node } diff --git a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift index 19da16952e..7790b00796 100644 --- a/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift +++ b/submodules/TelegramCallsUI/Sources/PresentationGroupCall.swift @@ -1684,7 +1684,7 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { strongSelf.processMyAudioLevel(level: mappedLevel, hasVoice: myLevelHasVoice) strongSelf.isSpeakingPromise.set(orignalMyLevelHasVoice) - if !missingSsrcs.isEmpty { + if !missingSsrcs.isEmpty && !strongSelf.isStream { strongSelf.participantsContext?.ensureHaveParticipants(ssrcs: missingSsrcs) } })) @@ -2235,6 +2235,14 @@ public final class PresentationGroupCallImpl: PresentationGroupCall { } private func beginTone(tone: PresentationCallTone) { + if self.isStream { + switch tone { + case .groupJoined, .groupLeft: + return + default: + break + } + } var completed: (() -> Void)? let toneRenderer = PresentationCallToneRenderer(tone: tone, completed: { completed?() From 653c2e4ba41626d87829a7e36c2730922fc3c822 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 01:46:15 +0400 Subject: [PATCH 5/7] Update tgcalls --- submodules/TgVoipWebrtc/tgcalls | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/submodules/TgVoipWebrtc/tgcalls b/submodules/TgVoipWebrtc/tgcalls index a424c9919c..d389503ac9 160000 --- a/submodules/TgVoipWebrtc/tgcalls +++ b/submodules/TgVoipWebrtc/tgcalls @@ -1 +1 @@ -Subproject commit a424c9919c425454abbf31bc41f8496756e6d8bf +Subproject commit d389503ac99d5d6fa16870cc280e83151cba8ccc From 217fb6c89903bb8028ee7e0f1392fd3d6ebc4219 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 01:57:48 +0400 Subject: [PATCH 6/7] Vide stream UI adjustments --- .../Sources/Components/MediaStreamComponent.swift | 2 +- .../Sources/Components/MediaStreamVideoComponent.swift | 2 +- .../Sources/GroupCallNavigationAccessoryPanel.swift | 2 ++ 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index 91cd26170c..2f35b76ba3 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -562,7 +562,7 @@ public final class MediaStreamComponent: CombinedComponent { func scheduleDismissUI() { if self.scheduledDismissUITimer == nil { - self.scheduledDismissUITimer = SwiftSignalKit.Timer(timeout: 5.0, repeat: false, completion: { [weak self] in + self.scheduledDismissUITimer = SwiftSignalKit.Timer(timeout: 3.0, repeat: false, completion: { [weak self] in guard let strongSelf = self else { return } diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift index e6e534a236..e5bc8d8446 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift @@ -56,7 +56,7 @@ final class MediaStreamVideoComponent: Component { override init(frame: CGRect) { self.blurTintView = UIView() - self.blurTintView.backgroundColor = UIColor(white: 0.0, alpha: 0.5) + self.blurTintView.backgroundColor = UIColor(white: 0.0, alpha: 0.55) super.init(frame: frame) diff --git a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift index dd9e682b90..99169754e0 100644 --- a/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift +++ b/submodules/TelegramCallsUI/Sources/GroupCallNavigationAccessoryPanel.swift @@ -379,6 +379,8 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode { let membersText: String if summaryState.participantCount == 0 { membersText = strongSelf.strings.VoiceChat_Panel_TapToJoin + } else if let info = summaryState.info, info.isStream { + membersText = strongSelf.strings.LiveStream_ViewerCount(Int32(summaryState.participantCount)) } else { membersText = strongSelf.strings.VoiceChat_Panel_Members(Int32(summaryState.participantCount)) } From 39ebfb356e566bd8d635005f4938f290b38a18a0 Mon Sep 17 00:00:00 2001 From: Ali <> Date: Sun, 27 Feb 2022 02:47:25 +0400 Subject: [PATCH 7/7] Fix request stream channels --- .../TelegramEngine/Calls/GroupCalls.swift | 2 +- .../Calls/TelegramEngineCalls.swift | 4 ++-- .../Sources/GroupCallContext.swift | 23 ++++++++++++++++++- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift index 4b07cdd187..8720e9feb6 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/GroupCalls.swift @@ -2414,7 +2414,7 @@ private func mergeAndSortParticipants(current currentParticipants: [GroupCallPar } public final class AudioBroadcastDataSource { - fileprivate let download: Download + let download: Download fileprivate init(download: Download) { self.download = download diff --git a/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift b/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift index 59e40078a3..dd5b309556 100644 --- a/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift +++ b/submodules/TelegramCore/Sources/TelegramEngine/Calls/TelegramEngineCalls.swift @@ -132,8 +132,8 @@ public extension TelegramEngine { |> take(1) } - public func requestStreamState(callId: Int64, accessHash: Int64) -> Signal { - return self.account.network.request(Api.functions.phone.getGroupCallStreamChannels(call: .inputGroupCall(id: callId, accessHash: accessHash))) + public func requestStreamState(dataSource: AudioBroadcastDataSource, callId: Int64, accessHash: Int64) -> Signal { + return dataSource.download.request(Api.functions.phone.getGroupCallStreamChannels(call: .inputGroupCall(id: callId, accessHash: accessHash))) |> mapToSignal { result -> Signal in switch result { case let .groupCallStreamChannels(channels): diff --git a/submodules/TelegramVoip/Sources/GroupCallContext.swift b/submodules/TelegramVoip/Sources/GroupCallContext.swift index 32209dcc3b..1d534dd233 100644 --- a/submodules/TelegramVoip/Sources/GroupCallContext.swift +++ b/submodules/TelegramVoip/Sources/GroupCallContext.swift @@ -55,7 +55,28 @@ private final class NetworkBroadcastPartSource: BroadcastPartSource { func requestTime(completion: @escaping (Int64) -> Void) -> Disposable { if self.isExternalStream { - return self.engine.calls.requestStreamState(callId: self.callId, accessHash: self.accessHash).start(next: { result in + let dataSource: Signal + if let dataSourceValue = self.dataSource { + dataSource = .single(dataSourceValue) + } else { + dataSource = self.engine.calls.getAudioBroadcastDataSource(callId: self.callId, accessHash: self.accessHash) + } + + let engine = self.engine + let callId = self.callId + let accessHash = self.accessHash + + return (dataSource + |> deliverOn(self.queue) + |> mapToSignal { [weak self] dataSource -> Signal in + if let dataSource = dataSource { + self?.dataSource = dataSource + return engine.calls.requestStreamState(dataSource: dataSource, callId: callId, accessHash: accessHash) + } else { + return .single(nil) + } + } + |> deliverOn(self.queue)).start(next: { result in if let channel = result?.channels.first { completion(channel.latestTimestamp) } else {