mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
184 lines
6.0 KiB
Swift
184 lines
6.0 KiB
Swift
import Foundation
|
|
import UIKit
|
|
import AsyncDisplayKit
|
|
import SwiftSignalKit
|
|
import Display
|
|
import TelegramCore
|
|
import SyncCore
|
|
import Postbox
|
|
import TelegramAudio
|
|
import AccountContext
|
|
|
|
public final class OverlayUniversalVideoNode: OverlayMediaItemNode {
|
|
public let content: UniversalVideoContent
|
|
private let videoNode: UniversalVideoNode
|
|
private let decoration: OverlayVideoDecoration
|
|
|
|
private var validLayoutSize: CGSize?
|
|
|
|
private var shouldBeDismissedDisposable: Disposable?
|
|
|
|
override public var group: OverlayMediaItemNodeGroup? {
|
|
return OverlayMediaItemNodeGroup(rawValue: 0)
|
|
}
|
|
|
|
override public var isMinimizeable: Bool {
|
|
return true
|
|
}
|
|
|
|
public var canAttachContent: Bool = true {
|
|
didSet {
|
|
self.videoNode.canAttachContent = self.canAttachContent
|
|
}
|
|
}
|
|
|
|
private let defaultExpand: () -> Void
|
|
public var customExpand: (() -> Void)?
|
|
public var customClose: (() -> Void)?
|
|
public var controlsAreShowingUpdated: ((Bool) -> Void)?
|
|
|
|
public init(postbox: Postbox, audioSession: ManagedAudioSession, manager: UniversalVideoManager, content: UniversalVideoContent, shouldBeDismissed: Signal<Bool, NoError> = .single(false), expand: @escaping () -> Void, close: @escaping () -> Void) {
|
|
self.content = content
|
|
self.defaultExpand = expand
|
|
|
|
var expandImpl: (() -> Void)?
|
|
var controlsAreShowingUpdatedImpl: ((Bool) -> Void)?
|
|
|
|
var unminimizeImpl: (() -> Void)?
|
|
var togglePlayPauseImpl: (() -> Void)?
|
|
var closeImpl: (() -> Void)?
|
|
let decoration = OverlayVideoDecoration(contentDimensions: content.dimensions, unminimize: {
|
|
unminimizeImpl?()
|
|
}, togglePlayPause: {
|
|
togglePlayPauseImpl?()
|
|
}, expand: {
|
|
expandImpl?()
|
|
}, close: {
|
|
closeImpl?()
|
|
}, controlsAreShowingUpdated: { value in
|
|
controlsAreShowingUpdatedImpl?(value)
|
|
})
|
|
self.videoNode = UniversalVideoNode(postbox: postbox, audioSession: audioSession, manager: manager, decoration: decoration, content: content, priority: .overlay)
|
|
self.decoration = decoration
|
|
|
|
super.init()
|
|
|
|
expandImpl = { [weak self] in
|
|
self?.expand()
|
|
}
|
|
|
|
unminimizeImpl = { [weak self] in
|
|
self?.unminimize?()
|
|
}
|
|
togglePlayPauseImpl = { [weak self] in
|
|
self?.videoNode.togglePlayPause()
|
|
}
|
|
closeImpl = { [weak self] in
|
|
if let strongSelf = self {
|
|
if let customClose = strongSelf.customClose {
|
|
customClose()
|
|
return
|
|
}
|
|
if strongSelf.videoNode.hasAttachedContext {
|
|
strongSelf.videoNode.continuePlayingWithoutSound()
|
|
}
|
|
strongSelf.layer.animateScale(from: 1.0, to: 0.1, duration: 0.25, removeOnCompletion: false, completion: { _ in
|
|
self?.dismiss()
|
|
close()
|
|
})
|
|
strongSelf.layer.animateAlpha(from: 1.0, to: 0.0, duration: 0.25, removeOnCompletion: false)
|
|
}
|
|
}
|
|
|
|
controlsAreShowingUpdatedImpl = { [weak self] value in
|
|
self?.controlsAreShowingUpdated?(value)
|
|
}
|
|
|
|
self.clipsToBounds = true
|
|
self.cornerRadius = 4.0
|
|
|
|
self.addSubnode(self.videoNode)
|
|
self.videoNode.ownsContentNodeUpdated = { [weak self] value in
|
|
if let strongSelf = self {
|
|
let previous = strongSelf.hasAttachedContext
|
|
strongSelf.hasAttachedContext = value
|
|
strongSelf.hasAttachedContextUpdated?(value)
|
|
|
|
if previous != value {
|
|
if !value {
|
|
strongSelf.dismiss()
|
|
closeImpl?()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
self.videoNode.canAttachContent = true
|
|
|
|
self.shouldBeDismissedDisposable = (shouldBeDismissed
|
|
|> filter { $0 }
|
|
|> deliverOnMainQueue).start(next: { [weak self] _ in
|
|
guard let strongSelf = self else {
|
|
return
|
|
}
|
|
strongSelf.dismiss()
|
|
closeImpl?()
|
|
})
|
|
}
|
|
|
|
override public func didLoad() {
|
|
super.didLoad()
|
|
}
|
|
|
|
override public func layout() {
|
|
self.updateLayout(self.bounds.size)
|
|
}
|
|
|
|
override public func preferredSizeForOverlayDisplay(boundingSize: CGSize) -> CGSize {
|
|
return self.content.dimensions.aspectFitted(CGSize(width: 300.0, height: 300.0))
|
|
}
|
|
|
|
override public func updateLayout(_ size: CGSize) {
|
|
if size != self.validLayoutSize {
|
|
self.updateLayoutImpl(size, transition: .immediate)
|
|
}
|
|
}
|
|
|
|
public func updateLayout(_ size: CGSize, transition: ContainedViewLayoutTransition) {
|
|
if size != self.validLayoutSize {
|
|
self.updateLayoutImpl(size, transition: transition)
|
|
}
|
|
}
|
|
|
|
private func updateLayoutImpl(_ size: CGSize, transition: ContainedViewLayoutTransition) {
|
|
self.validLayoutSize = size
|
|
|
|
transition.updateFrame(node: self.videoNode, frame: CGRect(origin: CGPoint(), size: size))
|
|
self.videoNode.updateLayout(size: size, transition: transition)
|
|
}
|
|
|
|
override public func updateMinimizedEdge(_ edge: OverlayMediaItemMinimizationEdge?, adjusting: Bool) {
|
|
self.decoration.updateMinimizedEdge(edge, adjusting: adjusting)
|
|
}
|
|
|
|
public func updateRoundCorners(_ value: Bool, transition: ContainedViewLayoutTransition) {
|
|
transition.updateCornerRadius(node: self, cornerRadius: value ? 4.0 : 0.0)
|
|
}
|
|
|
|
public func showControls() {
|
|
self.decoration.showControls()
|
|
}
|
|
|
|
public func expand() {
|
|
if let customExpand = self.customExpand {
|
|
customExpand()
|
|
} else {
|
|
self.defaultExpand()
|
|
}
|
|
}
|
|
|
|
public func controlPlay() {
|
|
self.videoNode.play()
|
|
}
|
|
}
|