From a74098cd09f9a7592da0db87c33c60eb5e8d1081 Mon Sep 17 00:00:00 2001 From: Ilya Yelagov Date: Wed, 7 Dec 2022 08:55:04 +0400 Subject: [PATCH] Observing network state to show loading --- .../Components/MediaStreamComponent.swift | 25 ++++++++++++--- .../MediaStreamVideoComponent.swift | 31 +++++++++++++------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift index e567888e80..ea8e3de213 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamComponent.swift @@ -731,6 +731,7 @@ public final class _MediaStreamComponent: CombinedComponent { private var stateDisposable: Disposable? private var infoDisposable: Disposable? private var connectionDisposable: Disposable? + private var networkStateDisposable: Disposable? private(set) var originInfo: OriginInfo? @@ -768,7 +769,7 @@ public final class _MediaStreamComponent: CombinedComponent { /// To update videoHiddenForPip var onExpandedFromPictureInPicture: ((State) -> Void)? private let infoThrottler = Throttler.init(duration: 5, queue: .main) - + init(call: PresentationGroupCallImpl) { self.call = call @@ -798,12 +799,28 @@ public final class _MediaStreamComponent: CombinedComponent { strongSelf.updated(transition: .immediate) }) + self.networkStateDisposable = (call.account.networkState |> deliverOnMainQueue).start(next: { [weak self] state in + guard let strongSelf = self else { return } + switch state { + case .waitingForNetwork, .connecting: + print("[NEW] videoStalled") + strongSelf.videoStalled = true + default: + strongSelf.videoStalled = !strongSelf.hasVideo + } + strongSelf.updated(transition: .immediate) +// if let strongSelf = self, case .standard(previewing: false) = strongSelf.presentationInterfaceState.mode { +// strongSelf.chatTitleView?.networkState = state +// } + }) + self.connectionDisposable = call.state.start(next: { [weak self] state in let prev = self?.videoStalled switch state.networkState { case .connected: self?.videoStalled = false default: + print("[ALERT] video stalled") self?.videoStalled = true } if prev != self?.videoStalled { @@ -821,8 +838,8 @@ public final class _MediaStreamComponent: CombinedComponent { var updated = false // TODO: remove debug timer - Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in - strongSelf.infoThrottler.publish(/*members.totalCount*/ Int.random(in: 0..<10000000)) { [weak strongSelf] latestCount in +// Timer.scheduledTimer(withTimeInterval: 0.5, repeats: true) { _ in + strongSelf.infoThrottler.publish(members.totalCount /*Int.random(in: 0..<10000000)*/) { [weak strongSelf] latestCount in print(members.totalCount) guard let strongSelf = strongSelf else { return } var updated = false @@ -835,7 +852,7 @@ public final class _MediaStreamComponent: CombinedComponent { strongSelf.updated(transition: .immediate) } } - }.fire() +// }.fire() if state.canManageCall != strongSelf.canManageCall { strongSelf.canManageCall = state.canManageCall updated = true diff --git a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift index 75374f9a19..273f6e8ef1 100644 --- a/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift +++ b/submodules/TelegramCallsUI/Sources/Components/MediaStreamVideoComponent.swift @@ -94,11 +94,12 @@ final class _MediaStreamVideoComponent: Component { if lhs.peerTitle != rhs.peerTitle { return false } - if lhs.isFullscreen != rhs.isFullscreen { return false } - + if lhs.videoLoading != rhs.videoLoading { + return false + } return true } @@ -169,8 +170,8 @@ final class _MediaStreamVideoComponent: Component { } let maskGradientLayer = CAGradientLayer() private var wasVisible = true - let shimmer = StandaloneShimmerEffect() - let borderShimmer = StandaloneShimmerEffect() + var shimmer = StandaloneShimmerEffect() + var borderShimmer = StandaloneShimmerEffect() let shimmerOverlayLayer = CALayer() let shimmerBorderLayer = CALayer() let placeholderView = UIImageView() @@ -191,7 +192,7 @@ final class _MediaStreamVideoComponent: Component { // placeholderView.backgroundColor = .red } - if placeholderView.superview == nil { + if !hadVideo && placeholderView.superview == nil { addSubview(placeholderView) } if loadingBlurView.superview == nil { @@ -202,6 +203,7 @@ final class _MediaStreamVideoComponent: Component { loadingBlurView.layer.addSublayer(shimmerBorderLayer) } loadingBlurView.clipsToBounds = true + shimmer = .init() shimmer.layer = shimmerOverlayLayer shimmerOverlayView.compositingFilter = "softLightBlendMode" shimmer.testUpdate(background: .clear, foreground: .white.withAlphaComponent(0.4)) @@ -219,16 +221,25 @@ final class _MediaStreamVideoComponent: Component { borderMask.lineWidth = 4 // let borderMask = CALayer() shimmerBorderLayer.mask = borderMask + borderShimmer = .init() borderShimmer.layer = shimmerBorderLayer borderShimmer.testUpdate(background: .clear, foreground: .white) loadingBlurView.alpha = 1 } else { - UIView.animate(withDuration: 0.2, animations: { - self.loadingBlurView.alpha = 0 - }, completion: { _ in + if hadVideo { self.loadingBlurView.removeFromSuperview() - }) - placeholderView.removeFromSuperview() + placeholderView.removeFromSuperview() + } else { + // Accounting for delay in first frame received + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [self] in + UIView.transition(with: self.loadingBlurView, duration: 0.2, animations: { + self.loadingBlurView.alpha = 0 + }, completion: { _ in + self.loadingBlurView.removeFromSuperview() + }) + placeholderView.removeFromSuperview() + } + } } if component.hasVideo, self.videoView == nil {