mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
Fixing stall out animation, orientation and fullscreen insets
This commit is contained in:
@@ -57,6 +57,7 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
var storedIsFullscreen: Bool?
|
var storedIsFullscreen: Bool?
|
||||||
var isFullscreen: Bool = false
|
var isFullscreen: Bool = false
|
||||||
var videoSize: CGSize?
|
var videoSize: CGSize?
|
||||||
|
var prevFullscreenOrientation: UIDeviceOrientation?
|
||||||
|
|
||||||
private(set) var canManageCall: Bool = false
|
private(set) var canManageCall: Bool = false
|
||||||
// TODO: also handle pictureInPicturePossible
|
// TODO: also handle pictureInPicturePossible
|
||||||
@@ -325,6 +326,7 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
state.isFullscreen = true
|
state.isFullscreen = true
|
||||||
isFullscreen = true
|
isFullscreen = true
|
||||||
} else if !isLandscape && state.isFullscreen && canEnforceOrientation {
|
} else if !isLandscape && state.isFullscreen && canEnforceOrientation {
|
||||||
|
state.prevFullscreenOrientation = nil
|
||||||
state.isFullscreen = false
|
state.isFullscreen = false
|
||||||
isFullscreen = false
|
isFullscreen = false
|
||||||
} else {
|
} else {
|
||||||
@@ -710,9 +712,12 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
if velocity.y > 200.0 {
|
if velocity.y > 200.0 {
|
||||||
if state.isFullscreen {
|
if state.isFullscreen {
|
||||||
state.isFullscreen = false
|
state.isFullscreen = false
|
||||||
state.updateDismissOffset(value: 0.0, interactive: false)
|
state.prevFullscreenOrientation = UIDevice.current.orientation
|
||||||
if let controller = controller() as? MediaStreamComponentController {
|
state.dismissOffset = 0.0// updateDismissOffset(value: 0.0, interactive: false)
|
||||||
|
if canEnforceOrientation, let controller = controller() as? MediaStreamComponentController {
|
||||||
controller.updateOrientation(orientation: .portrait)
|
controller.updateOrientation(orientation: .portrait)
|
||||||
|
} else {
|
||||||
|
state.updated(transition: .easeInOut(duration: 0.25))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if isFullyDragged || state.initialOffset != 0 {
|
if isFullyDragged || state.initialOffset != 0 {
|
||||||
@@ -835,21 +840,31 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
}),
|
}),
|
||||||
title: "expand"
|
title: "expand"
|
||||||
)),
|
)),
|
||||||
action: {
|
action: { [weak state] in
|
||||||
|
guard let state = state else { return }
|
||||||
guard state.videoIsPlayable else {
|
guard state.videoIsPlayable else {
|
||||||
state.isFullscreen = false
|
state.isFullscreen = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let controller = controller() as? MediaStreamComponentController {
|
if let controller = controller() as? MediaStreamComponentController {
|
||||||
guard let size = state.videoSize else { return }
|
// guard let _ = state.videoSize else { return }
|
||||||
state.isFullscreen.toggle()
|
state.isFullscreen.toggle()
|
||||||
if state.isFullscreen {
|
if state.isFullscreen {
|
||||||
if size.width > size.height {
|
// if size.width > size.height {
|
||||||
|
let currentOrientation = state.prevFullscreenOrientation ?? UIDevice.current.orientation
|
||||||
|
switch currentOrientation {
|
||||||
|
case .landscapeLeft:
|
||||||
|
controller.updateOrientation(orientation: .landscapeRight)
|
||||||
|
case .landscapeRight:
|
||||||
|
controller.updateOrientation(orientation: .landscapeLeft)
|
||||||
|
default:
|
||||||
controller.updateOrientation(orientation: .landscapeRight)
|
controller.updateOrientation(orientation: .landscapeRight)
|
||||||
} else {
|
|
||||||
controller.updateOrientation(orientation: .portrait)
|
|
||||||
}
|
}
|
||||||
|
// } else {
|
||||||
|
// controller.updateOrientation(orientation: .portrait)
|
||||||
|
// }
|
||||||
} else {
|
} else {
|
||||||
|
state.prevFullscreenOrientation = UIDevice.current.orientation
|
||||||
// TODO: Check and mind current device orientation
|
// TODO: Check and mind current device orientation
|
||||||
controller.updateOrientation(orientation: .portrait)
|
controller.updateOrientation(orientation: .portrait)
|
||||||
}
|
}
|
||||||
@@ -916,13 +931,14 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
controller.presentShare()
|
controller.presentShare()
|
||||||
}
|
}
|
||||||
).minSize(CGSize(width: 64.0, height: 80))),
|
).minSize(CGSize(width: 64.0, height: 80))),
|
||||||
rightItem: state.hasVideo ? AnyComponent(Button(
|
rightItem: /*state.hasVideo ?*/ AnyComponent(Button(
|
||||||
content: AnyComponent(BundleIconComponent(
|
content: AnyComponent(BundleIconComponent(
|
||||||
name: isFullscreen ? "Media Gallery/Minimize" : "Media Gallery/Fullscreen",
|
name: isFullscreen ? "Media Gallery/Minimize" : "Media Gallery/Fullscreen",
|
||||||
tintColor: .white
|
tintColor: .white
|
||||||
)),
|
)),
|
||||||
action: {
|
action: {
|
||||||
state.isFullscreen = false
|
state.isFullscreen = false
|
||||||
|
state.prevFullscreenOrientation = UIDevice.current.orientation
|
||||||
if let controller = controller() as? MediaStreamComponentController {
|
if let controller = controller() as? MediaStreamComponentController {
|
||||||
if canEnforceOrientation {
|
if canEnforceOrientation {
|
||||||
controller.updateOrientation(orientation: .portrait)
|
controller.updateOrientation(orientation: .portrait)
|
||||||
@@ -931,7 +947,7 @@ public final class MediaStreamComponent: CombinedComponent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
).minSize(CGSize(width: 64.0, height: 80))) : nil,
|
).minSize(CGSize(width: 64.0, height: 80)))/* : nil*/,
|
||||||
centerItem: infoItem
|
centerItem: infoItem
|
||||||
))
|
))
|
||||||
let fullScreenOverlayComponent = fullscreenOverlay.update(
|
let fullScreenOverlayComponent = fullscreenOverlay.update(
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
self.pictureInPictureController?.stopPictureInPicture()
|
self.pictureInPictureController?.stopPictureInPicture()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private var isAnimating = false
|
||||||
private func updateVideoStalled(isStalled: Bool) {
|
private func updateVideoStalled(isStalled: Bool) {
|
||||||
if isStalled {
|
if isStalled {
|
||||||
guard let component = self.component else { return }
|
guard let component = self.component else { return }
|
||||||
@@ -205,14 +205,16 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
addSubview(loadingBlurView)
|
addSubview(loadingBlurView)
|
||||||
if needsFadeInAnimation {
|
if needsFadeInAnimation {
|
||||||
let anim = CABasicAnimation(keyPath: "opacity")
|
let anim = CABasicAnimation(keyPath: "opacity")
|
||||||
anim.duration = 0.5
|
anim.duration = 0.4
|
||||||
anim.fromValue = 0
|
anim.fromValue = 0
|
||||||
anim.toValue = 1
|
anim.toValue = 1
|
||||||
|
loadingBlurView.layer.opacity = 1
|
||||||
anim.fillMode = .forwards
|
anim.fillMode = .forwards
|
||||||
anim.isRemovedOnCompletion = false
|
anim.isRemovedOnCompletion = false
|
||||||
loadingBlurView.layer.add(anim, forKey: "opacity")
|
loadingBlurView.layer.add(anim, forKey: "opacity")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
loadingBlurView.layer.zPosition = 999
|
||||||
if shimmerBorderLayer.superlayer == nil {
|
if shimmerBorderLayer.superlayer == nil {
|
||||||
loadingBlurView.contentView.layer.addSublayer(shimmerBorderLayer)
|
loadingBlurView.contentView.layer.addSublayer(shimmerBorderLayer)
|
||||||
}
|
}
|
||||||
@@ -235,18 +237,20 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
borderShimmer.updateHorizontal(background: .clear, foreground: .white)
|
borderShimmer.updateHorizontal(background: .clear, foreground: .white)
|
||||||
loadingBlurView.alpha = 1
|
loadingBlurView.alpha = 1
|
||||||
} else {
|
} else {
|
||||||
if hadVideo {
|
if hadVideo && !isAnimating && loadingBlurView.layer.opacity == 1 {
|
||||||
let anim = CABasicAnimation(keyPath: "opacity")
|
let anim = CABasicAnimation(keyPath: "opacity")
|
||||||
anim.duration = 0.5
|
anim.duration = 0.25
|
||||||
anim.fromValue = 1
|
anim.fromValue = 1.0
|
||||||
anim.toValue = 0
|
anim.toValue = 0.0
|
||||||
|
self.loadingBlurView.layer.opacity = 0
|
||||||
anim.fillMode = .forwards
|
anim.fillMode = .forwards
|
||||||
anim.isRemovedOnCompletion = false
|
anim.isRemovedOnCompletion = false
|
||||||
|
isAnimating = true
|
||||||
anim.completion = { [weak self] _ in
|
anim.completion = { [weak self] _ in
|
||||||
guard self?.videoStalled == false else { return }
|
guard self?.videoStalled == false else { return }
|
||||||
self?.loadingBlurView.removeFromSuperview()
|
self?.loadingBlurView.removeFromSuperview()
|
||||||
self?.placeholderView.removeFromSuperview()
|
self?.placeholderView.removeFromSuperview()
|
||||||
self?.loadingBlurView.layer.removeAllAnimations()
|
self?.isAnimating = false
|
||||||
}
|
}
|
||||||
loadingBlurView.layer.add(anim, forKey: "opacity")
|
loadingBlurView.layer.add(anim, forKey: "opacity")
|
||||||
}
|
}
|
||||||
@@ -302,7 +306,7 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
stallTimer = _stallTimer
|
stallTimer = _stallTimer
|
||||||
|
self.clipsToBounds = component.isFullscreen // or just true
|
||||||
if let videoBlurView = self.videoRenderingContext.makeView(input: input, blur: true) {
|
if let videoBlurView = self.videoRenderingContext.makeView(input: input, blur: true) {
|
||||||
self.videoBlurView = videoBlurView
|
self.videoBlurView = videoBlurView
|
||||||
self.insertSubview(videoBlurView, belowSubview: self.blurTintView)
|
self.insertSubview(videoBlurView, belowSubview: self.blurTintView)
|
||||||
@@ -378,7 +382,6 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
if #available(iOS 14.0, *) {
|
if #available(iOS 14.0, *) {
|
||||||
pictureInPictureController?.requiresLinearPlayback = true
|
pictureInPictureController?.requiresLinearPlayback = true
|
||||||
}
|
}
|
||||||
|
|
||||||
self.pictureInPictureController = pictureInPictureController
|
self.pictureInPictureController = pictureInPictureController
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
@@ -451,7 +454,7 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
|
|
||||||
videoSize = CGSize(width: aspect * 100.0, height: 100.0).aspectFitted(.init(width: availableVideoWidth, height: availableVideoHeight))
|
videoSize = CGSize(width: aspect * 100.0, height: 100.0).aspectFitted(.init(width: availableVideoWidth, height: availableVideoHeight))
|
||||||
}
|
}
|
||||||
let blurredVideoSize = videoSize.aspectFilled(availableSize)
|
let blurredVideoSize = component.isFullscreen ? availableSize : videoSize.aspectFilled(availableSize)
|
||||||
|
|
||||||
component.onVideoSizeRetrieved(videoSize)
|
component.onVideoSizeRetrieved(videoSize)
|
||||||
|
|
||||||
@@ -478,7 +481,10 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
if let videoBlurView = self.videoBlurView {
|
if let videoBlurView = self.videoBlurView {
|
||||||
videoBlurView.updateIsEnabled(component.isVisible)
|
videoBlurView.updateIsEnabled(component.isVisible)
|
||||||
if component.isFullscreen {
|
if component.isFullscreen {
|
||||||
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)
|
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 {
|
} else {
|
||||||
videoBlurView.frame = videoView.frame.insetBy(dx: -69 * aspect, dy: -69)
|
videoBlurView.frame = videoView.frame.insetBy(dx: -69 * aspect, dy: -69)
|
||||||
}
|
}
|
||||||
@@ -627,6 +633,7 @@ final class MediaStreamVideoComponent: Component {
|
|||||||
self.component?.pictureInPictureClosed()
|
self.component?.pictureInPictureClosed()
|
||||||
}
|
}
|
||||||
// TODO: extract precise animation timing or observe window changes
|
// TODO: extract precise animation timing or observe window changes
|
||||||
|
// Handle minimized case separatelly (can we detect minimized?)
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
|
||||||
self.videoView?.alpha = 1
|
self.videoView?.alpha = 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -691,7 +691,9 @@ public final class GroupCallNavigationAccessoryPanel: ASDisplayNode {
|
|||||||
previewImageNode.cornerRadius = 8.0
|
previewImageNode.cornerRadius = 8.0
|
||||||
previewImageNode.contentMode = .scaleAspectFill
|
previewImageNode.contentMode = .scaleAspectFill
|
||||||
self.previewImageNode = previewImageNode
|
self.previewImageNode = previewImageNode
|
||||||
|
previewImageNode.alpha = 0
|
||||||
self.addSubnode(previewImageNode)
|
self.addSubnode(previewImageNode)
|
||||||
|
transition.updateAlpha(node: previewImageNode, alpha: 1)
|
||||||
}
|
}
|
||||||
previewImageNode.image = previewImage
|
previewImageNode.image = previewImage
|
||||||
let previewSize = CGSize(width: 40.0, height: 40.0)
|
let previewSize = CGSize(width: 40.0, height: 40.0)
|
||||||
|
|||||||
Reference in New Issue
Block a user