mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Various fixes
This commit is contained in:
parent
f2477074ae
commit
32effd4291
@ -905,6 +905,9 @@ public final class AnimatedStickerNode: ASDisplayNode {
|
||||
private var isSetUpForPlayback = false
|
||||
|
||||
public func play(firstFrame: Bool = false) {
|
||||
if case .once = self.playbackMode {
|
||||
self.isPlaying = true
|
||||
}
|
||||
if self.isSetUpForPlayback {
|
||||
let directData = self.directData
|
||||
let cachedData = self.cachedData
|
||||
|
@ -60,7 +60,7 @@ public func messageFileMediaResourceStatus(context: AccountContext, file: Telegr
|
||||
mediaStatus = .playbackStatus(.playing)
|
||||
case .paused:
|
||||
mediaStatus = .playbackStatus(.paused)
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
if whilePlaying {
|
||||
mediaStatus = .playbackStatus(.playing)
|
||||
} else {
|
||||
@ -84,7 +84,7 @@ public func messageFileMediaResourceStatus(context: AccountContext, file: Telegr
|
||||
mediaStatus = .playbackStatus(.playing)
|
||||
case .paused:
|
||||
mediaStatus = .playbackStatus(.paused)
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
if whilePlaying {
|
||||
mediaStatus = .playbackStatus(.playing)
|
||||
} else {
|
||||
|
@ -634,6 +634,7 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
var isPaused = true
|
||||
var seekable = false
|
||||
var hasStarted = false
|
||||
var displayProgress = true
|
||||
if let value = value {
|
||||
hasStarted = value.timestamp > 0
|
||||
|
||||
@ -648,7 +649,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
case .playing:
|
||||
isPaused = false
|
||||
playing = true
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, display):
|
||||
displayProgress = display
|
||||
initialBuffering = true
|
||||
isPaused = !whilePlaying
|
||||
var isStreaming = false
|
||||
@ -700,7 +702,11 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
|
||||
var fetching = false
|
||||
if initialBuffering {
|
||||
if displayProgress {
|
||||
strongSelf.statusNode.transitionToState(.progress(color: .white, lineWidth: nil, value: nil, cancelEnabled: false), animated: false, completion: {})
|
||||
} else {
|
||||
strongSelf.statusNode.transitionToState(.none, animated: false, completion: {})
|
||||
}
|
||||
} else {
|
||||
var state: RadialStatusNodeState = .play(.white)
|
||||
|
||||
|
@ -1290,6 +1290,9 @@
|
||||
|
||||
- (void)_seekToPosition:(NSTimeInterval)position manual:(bool)__unused manual
|
||||
{
|
||||
if (self.player == nil) {
|
||||
return;
|
||||
}
|
||||
CMTime targetTime = CMTimeMakeWithSeconds(position, NSEC_PER_SEC);
|
||||
|
||||
if (CMTIME_COMPARE_INLINE(targetTime, !=, _chaseTime))
|
||||
|
@ -465,8 +465,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
func animateIn() {
|
||||
self.dimNode.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.3)
|
||||
|
||||
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||
self.wrappingScrollNode.layer.animateBoundsOriginYAdditive(from: -offset, to: 0.0, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring)
|
||||
let offset = self.contentContainerNode.frame.height
|
||||
self.wrappingScrollNode.layer.animatePosition(from: CGPoint(x: 0.0, y: offset), to: CGPoint(), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, additive: true)
|
||||
}
|
||||
|
||||
func animateOut(completion: (() -> Void)? = nil) {
|
||||
@ -485,8 +485,8 @@ class LocationDistancePickerScreenNode: ViewControllerTracingNode, UIScrollViewD
|
||||
internalCompletion()
|
||||
})
|
||||
|
||||
let offset = self.bounds.size.height - self.contentBackgroundNode.frame.minY
|
||||
self.wrappingScrollNode.layer.animateBoundsOriginYAdditive(from: 0.0, to: -offset, duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, completion: { _ in
|
||||
let offset = self.contentContainerNode.frame.height
|
||||
self.wrappingScrollNode.layer.animatePosition(from: CGPoint(), to: CGPoint(x: 0.0, y: offset), duration: 0.3, timingFunction: kCAMediaTimingFunctionSpring, removeOnCompletion: false, additive: true, completion: { _ in
|
||||
offsetCompleted = true
|
||||
internalCompletion()
|
||||
})
|
||||
|
@ -83,6 +83,11 @@ private class LocationMapView: MKMapView, UIGestureRecognizerDelegate {
|
||||
|
||||
return pointInside
|
||||
}
|
||||
|
||||
public override func layoutSubviews() {
|
||||
super.layoutSubviews()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private let arrowImageSize = CGSize(width: 90.0, height: 90.0)
|
||||
@ -110,14 +115,16 @@ func generateHeadingArrowImage() -> UIImage? {
|
||||
})
|
||||
}
|
||||
|
||||
private func generateProximityDim(size: CGSize, rect: CGRect) -> UIImage {
|
||||
private func generateProximityDim(size: CGSize) -> UIImage {
|
||||
return generateImage(size, rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(UIColor(rgb: 0x000000, alpha: 0.4).cgColor)
|
||||
context.fill(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setBlendMode(.clear)
|
||||
context.fillEllipse(in: rect)
|
||||
|
||||
let ellipseSize = CGSize(width: 260.0, height: 260.0)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: (size.width - ellipseSize.width) / 2.0, y: (size.height - ellipseSize.height) / 2.0), size: ellipseSize))
|
||||
})!
|
||||
}
|
||||
|
||||
@ -145,63 +152,6 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
class InvertedProximityCircle: NSObject, MKOverlay {
|
||||
var coordinate: CLLocationCoordinate2D
|
||||
var radius: Double
|
||||
var alpha: CGFloat {
|
||||
didSet {
|
||||
self.alphaTransition = (oldValue, CACurrentMediaTime(), 0.3)
|
||||
}
|
||||
}
|
||||
var alphaTransition: (from: CGFloat, startTimestamp: Double, duration: Double)?
|
||||
|
||||
var boundingMapRect: MKMapRect {
|
||||
return MKMapRect.world
|
||||
}
|
||||
|
||||
init(center coord: CLLocationCoordinate2D, radius: Double, alpha: CGFloat = 0.0) {
|
||||
self.coordinate = coord
|
||||
self.radius = radius
|
||||
self.alpha = alpha
|
||||
}
|
||||
}
|
||||
|
||||
class InvertedProximityCircleRenderer: MKOverlayRenderer {
|
||||
var radius: Double = 0.0
|
||||
var fillColor: UIColor = UIColor(rgb: 0x000000, alpha: 0.5)
|
||||
|
||||
override func draw(_ mapRect: MKMapRect, zoomScale: MKZoomScale, in context: CGContext) {
|
||||
guard let overlay = self.overlay as? InvertedProximityCircle else {
|
||||
return
|
||||
}
|
||||
|
||||
var alpha: CGFloat = overlay.alpha
|
||||
if let transition = overlay.alphaTransition {
|
||||
var t = (CACurrentMediaTime() - transition.startTimestamp) / transition.duration
|
||||
t = min(1.0, max(0.0, t))
|
||||
alpha = transition.from + (alpha - transition.from) * CGFloat(t)
|
||||
}
|
||||
|
||||
context.setAlpha(alpha)
|
||||
|
||||
let path = UIBezierPath(rect: CGRect(x: mapRect.origin.x, y: mapRect.origin.y, width: mapRect.size.width, height: mapRect.size.height))
|
||||
let radiusInMap = overlay.radius * MKMapPointsPerMeterAtLatitude(overlay.coordinate.latitude) * 2.0
|
||||
let mapSize: MKMapSize = MKMapSize(width: radiusInMap, height: radiusInMap)
|
||||
let regionOrigin = MKMapPoint(overlay.coordinate)
|
||||
var regionRect: MKMapRect = MKMapRect(origin: regionOrigin, size: mapSize)
|
||||
regionRect = regionRect.offsetBy(dx: -radiusInMap / 2.0, dy: -radiusInMap / 2.0);
|
||||
regionRect = regionRect.intersection(MKMapRect.world);
|
||||
|
||||
let excludePath: UIBezierPath = UIBezierPath(roundedRect: CGRect(x: regionRect.origin.x, y: regionRect.origin.y, width: regionRect.size.width, height: regionRect.size.height), cornerRadius: CGFloat(regionRect.size.width) / 2.0)
|
||||
path.append(excludePath)
|
||||
|
||||
context.setFillColor(fillColor.cgColor);
|
||||
context.addPath(path.cgPath);
|
||||
context.fillPath(using: .evenOdd)
|
||||
}
|
||||
}
|
||||
private weak var currentInvertedCircleRenderer: InvertedProximityCircleRenderer?
|
||||
|
||||
private let locationPromise = Promise<CLLocation?>(nil)
|
||||
|
||||
private let pickerAnnotationContainerView: PickerAnnotationContainerView
|
||||
@ -223,71 +173,31 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
var annotationSelected: ((LocationPinAnnotation?) -> Void)?
|
||||
var userLocationAnnotationSelected: (() -> Void)?
|
||||
|
||||
var indicatorOverlay: InvertedProximityCircle?
|
||||
var proximityDimView = UIImageView()
|
||||
var proximityIndicatorRadius: Double? {
|
||||
didSet {
|
||||
if let activeProximityRadius = self.proximityIndicatorRadius {
|
||||
if let location = self.currentUserLocation, activeProximityRadius != oldValue {
|
||||
let indicatorOverlay: InvertedProximityCircle
|
||||
if let current = self.indicatorOverlay {
|
||||
indicatorOverlay = current
|
||||
indicatorOverlay.radius = activeProximityRadius
|
||||
self.mapView?.removeOverlay(indicatorOverlay)
|
||||
self.mapView?.addOverlay(indicatorOverlay)
|
||||
} else {
|
||||
indicatorOverlay = InvertedProximityCircle(center: location.coordinate, radius: activeProximityRadius)
|
||||
self.mapView?.addOverlay(indicatorOverlay)
|
||||
self.indicatorOverlay = indicatorOverlay
|
||||
indicatorOverlay.alpha = 1.0
|
||||
self.updateAnimations()
|
||||
if let radius = self.proximityIndicatorRadius, let mapView = self.mapView {
|
||||
if self.proximityDimView.image == nil {
|
||||
proximityDimView.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
|
||||
}
|
||||
|
||||
if oldValue == 0 {
|
||||
UIView.transition(with: proximityDimView, duration: 0.3, options: .transitionCrossDissolve) {
|
||||
self.proximityDimView.image = generateProximityDim(size: mapView.bounds.size)
|
||||
} completion: { _ in
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if let indicatorOverlay = self.indicatorOverlay {
|
||||
indicatorOverlay.alpha = 0.0
|
||||
self.updateAnimations()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.proximityDimView.image != nil {
|
||||
UIView.transition(with: proximityDimView, duration: 0.3, options: .transitionCrossDissolve) {
|
||||
self.proximityDimView.image = nil
|
||||
} completion: { _ in
|
||||
|
||||
private var animator: ConstantDisplayLinkAnimator?
|
||||
private func updateAnimations() {
|
||||
guard let mapView = self.mapView else {
|
||||
return
|
||||
}
|
||||
|
||||
var animate = false
|
||||
let timestamp = CACurrentMediaTime()
|
||||
|
||||
if let indicatorOverlay = self.indicatorOverlay, let transition = indicatorOverlay.alphaTransition {
|
||||
if transition.startTimestamp + transition.duration < timestamp {
|
||||
indicatorOverlay.alphaTransition = nil
|
||||
if indicatorOverlay.alpha.isZero {
|
||||
self.indicatorOverlay = nil
|
||||
mapView.removeOverlay(indicatorOverlay)
|
||||
}
|
||||
} else {
|
||||
animate = true
|
||||
}
|
||||
}
|
||||
|
||||
if animate {
|
||||
let animator: ConstantDisplayLinkAnimator
|
||||
if let current = self.animator {
|
||||
animator = current
|
||||
} else {
|
||||
animator = ConstantDisplayLinkAnimator(update: { [weak self] in
|
||||
self?.updateAnimations()
|
||||
})
|
||||
self.animator = animator
|
||||
}
|
||||
animator.isPaused = false
|
||||
} else {
|
||||
self.animator?.isPaused = true
|
||||
}
|
||||
|
||||
self.currentInvertedCircleRenderer?.setNeedsDisplay(MKMapRect.world)
|
||||
}
|
||||
|
||||
private var circleOverlay: MKCircle?
|
||||
@ -380,6 +290,18 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
var mapOffset: CGFloat = 0.0
|
||||
func setMapCenter(coordinate: CLLocationCoordinate2D, radius: Double, insets: UIEdgeInsets, offset: CGFloat, animated: Bool = false) {
|
||||
self.mapOffset = offset
|
||||
self.ignoreRegionChanges = true
|
||||
|
||||
let mapRect = MKMapRect(region: MKCoordinateRegion(center: coordinate, latitudinalMeters: radius * 2.0, longitudinalMeters: radius * 2.0))
|
||||
self.mapView?.setVisibleMapRect(mapRect, edgePadding: insets, animated: animated)
|
||||
self.ignoreRegionChanges = false
|
||||
|
||||
self.proximityDimView.center = CGPoint(x: self.bounds.midX, y: self.bounds.midY + offset)
|
||||
}
|
||||
|
||||
func setMapCenter(coordinate: CLLocationCoordinate2D, span: MKCoordinateSpan = defaultMapSpan, offset: CGPoint = CGPoint(), isUserLocation: Bool = false, hidePicker: Bool = false, animated: Bool = false) {
|
||||
let region = MKCoordinateRegion(center: coordinate, span: span)
|
||||
self.ignoreRegionChanges = true
|
||||
@ -479,6 +401,10 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
} else if let view = view as? LocationPinAnnotationView {
|
||||
view.setZPosition(view.defaultZPosition)
|
||||
}
|
||||
|
||||
if let container = view.superview {
|
||||
container.insertSubview(self.proximityDimView, at: 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,11 +444,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, rendererFor overlay: MKOverlay) -> MKOverlayRenderer {
|
||||
if let invertedCircle = overlay as? InvertedProximityCircle {
|
||||
let renderer = InvertedProximityCircleRenderer(overlay: invertedCircle)
|
||||
self.currentInvertedCircleRenderer = renderer
|
||||
return renderer
|
||||
} else if let circle = overlay as? MKCircle {
|
||||
if let circle = overlay as? MKCircle {
|
||||
let renderer = ProximityCircleRenderer(circle: circle)
|
||||
renderer.fillColor = .clear
|
||||
renderer.strokeColor = UIColor(rgb: 0xc3baaf)
|
||||
@ -534,17 +456,6 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func mapView(_ mapView: MKMapView, didAdd renderers: [MKOverlayRenderer]) {
|
||||
for renderer in renderers {
|
||||
if let renderer = renderer as? InvertedProximityCircleRenderer {
|
||||
renderer.alpha = 0.0
|
||||
UIView.animate(withDuration: 0.3) {
|
||||
renderer.alpha = 1.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var distancesToAllAnnotations: Signal<[Double], NoError> {
|
||||
let poll = Signal<[LocationPinAnnotation], NoError> { [weak self] subscriber in
|
||||
if let strongSelf = self {
|
||||
@ -806,6 +717,7 @@ final class LocationMapNode: ASDisplayNode, MKMapViewDelegate {
|
||||
}
|
||||
|
||||
func updateLayout(size: CGSize) {
|
||||
self.proximityDimView.frame = CGRect(origin: CGPoint(x: 0.0, y: self.mapOffset), size: size)
|
||||
self.pickerAnnotationContainerView.frame = CGRect(x: 0.0, y: floorToScreenPixels((size.height - size.width) / 2.0), width: size.width, height: size.width)
|
||||
if let pickerAnnotationView = self.pickerAnnotationView {
|
||||
pickerAnnotationView.center = CGPoint(x: self.pickerAnnotationContainerView.frame.width / 2.0, y: self.pickerAnnotationContainerView.frame.height / 2.0)
|
||||
|
@ -599,17 +599,28 @@ final class LocationViewControllerNode: ViewControllerTracingNode, CLLocationMan
|
||||
}
|
||||
|
||||
func setProximityIndicator(radius: Int32?) {
|
||||
guard let (layout, navigationBarHeight) = self.validLayout else {
|
||||
return
|
||||
}
|
||||
if let radius = radius {
|
||||
self.headerNode.forceIsHidden = true
|
||||
|
||||
if var coordinate = self.headerNode.mapNode.currentUserLocation?.coordinate, let span = self.headerNode.mapNode.mapSpan {
|
||||
coordinate.latitude -= span.latitudeDelta * 0.11
|
||||
if let coordinate = self.headerNode.mapNode.currentUserLocation?.coordinate {
|
||||
self.updateState { state in
|
||||
var state = state
|
||||
state.selectedLocation = .coordinate(coordinate, true)
|
||||
state.selectedLocation = .custom
|
||||
state.trackingMode = .none
|
||||
return state
|
||||
}
|
||||
|
||||
let panelHeight: CGFloat = 349.0 + layout.intrinsicInsets.bottom
|
||||
let inset = (layout.size.width - 260.0) / 2.0
|
||||
let offset = panelHeight / 2.0 + 60.0 + inset + navigationBarHeight / 2.0
|
||||
|
||||
let point = CGPoint(x: layout.size.width / 2.0, y: navigationBarHeight + (layout.size.height - navigationBarHeight - panelHeight) / 2.0)
|
||||
let convertedPoint = self.view.convert(point, to: self.headerNode.mapNode.view)
|
||||
|
||||
self.headerNode.mapNode.setMapCenter(coordinate: coordinate, radius: Double(radius), insets: UIEdgeInsets(top: navigationBarHeight, left: inset, bottom: offset, right: inset), offset: convertedPoint.y - self.headerNode.mapNode.frame.height / 2.0, animated: true)
|
||||
}
|
||||
|
||||
self.headerNode.mapNode.proximityIndicatorRadius = Double(radius)
|
||||
|
@ -294,12 +294,12 @@ private final class MediaPlayerContext {
|
||||
duration = max(duration, CMTimeGetSeconds(audioTrackFrameBuffer.duration))
|
||||
}
|
||||
loadedDuration = duration
|
||||
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0), soundEnabled: self.enableSound)
|
||||
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0, display: true), soundEnabled: self.enableSound)
|
||||
self.playerStatus.set(.single(status))
|
||||
let _ = self.playerStatusValue.swap(status)
|
||||
} else {
|
||||
let duration = seekState?.duration ?? 0.0
|
||||
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0), soundEnabled: self.enableSound)
|
||||
let status = MediaPlayerStatus(generationTimestamp: CACurrentMediaTime(), duration: duration, dimensions: CGSize(), timestamp: min(max(timestamp, 0.0), duration), baseRate: self.baseRate, seekId: self.seekId, status: .buffering(initial: false, whilePlaying: action == .play, progress: 0.0, display: true), soundEnabled: self.enableSound)
|
||||
self.playerStatus.set(.single(status))
|
||||
let _ = self.playerStatusValue.swap(status)
|
||||
}
|
||||
@ -875,7 +875,7 @@ private final class MediaPlayerContext {
|
||||
if case .playing = self.state {
|
||||
whilePlaying = true
|
||||
}
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: whilePlaying, progress: Float(bufferingProgress))
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: whilePlaying, progress: Float(bufferingProgress), display: true)
|
||||
} else if !rate.isZero {
|
||||
if reportRate.isZero {
|
||||
//playbackStatus = .buffering(initial: false, whilePlaying: true)
|
||||
@ -926,7 +926,7 @@ private final class MediaPlayerContext {
|
||||
public enum MediaPlayerPlaybackStatus: Equatable {
|
||||
case playing
|
||||
case paused
|
||||
case buffering(initial: Bool, whilePlaying: Bool, progress: Float)
|
||||
case buffering(initial: Bool, whilePlaying: Bool, progress: Float, display: Bool)
|
||||
|
||||
public static func ==(lhs: MediaPlayerPlaybackStatus, rhs: MediaPlayerPlaybackStatus) -> Bool {
|
||||
switch lhs {
|
||||
@ -942,8 +942,8 @@ public enum MediaPlayerPlaybackStatus: Equatable {
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
case let .buffering(initial, whilePlaying, progress):
|
||||
if case .buffering(initial, whilePlaying, progress) = rhs {
|
||||
case let .buffering(initial, whilePlaying, progress, display):
|
||||
if case .buffering(initial, whilePlaying, progress, display) = rhs {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
|
@ -781,7 +781,7 @@ public final class MediaPlayerScrubbingNode: ASDisplayNode {
|
||||
default:
|
||||
break
|
||||
}
|
||||
if case .buffering(true, _, _) = statusValue.status {
|
||||
if case .buffering(true, _, _, _) = statusValue.status {
|
||||
//initialBuffering = true
|
||||
} else if Double(0.0).isLess(than: statusValue.duration) {
|
||||
if let scrubbingTimestampValue = self.scrubbingTimestampValue {
|
||||
|
@ -331,7 +331,7 @@ public final class MediaNavigationAccessoryHeaderNode: ASDisplayNode, UIScrollVi
|
||||
switch status {
|
||||
case .paused:
|
||||
paused = true
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
paused = !whilePlaying
|
||||
case .playing:
|
||||
paused = false
|
||||
|
@ -111,6 +111,9 @@ private func canEditMessage(accountPeerId: PeerId, limitsConfiguration: LimitsCo
|
||||
} else if let _ = media as? TelegramMediaPoll {
|
||||
hasUneditableAttributes = true
|
||||
break
|
||||
} else if let _ = media as? TelegramMediaDice {
|
||||
hasUneditableAttributes = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1274,7 +1274,7 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
return .optionalAction({
|
||||
if shouldPlay {
|
||||
let _ = (appConfiguration
|
||||
|> deliverOnMainQueue).start(next: { [weak self] appConfiguration in
|
||||
|> deliverOnMainQueue).start(next: { [weak self, weak animationNode] appConfiguration in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
@ -1315,9 +1315,10 @@ class ChatMessageAnimatedStickerItemNode: ChatMessageItemView {
|
||||
}
|
||||
}
|
||||
}))
|
||||
break
|
||||
return
|
||||
}
|
||||
}
|
||||
animationNode?.play()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
@ -832,7 +832,7 @@ final class ChatMessageInteractiveFileNode: ASDisplayNode {
|
||||
if isAudio && !isVoice {
|
||||
state = .play
|
||||
} else {
|
||||
if adjustedProgress.isEqual(to: 1.0), (message.flags.contains(.Unsent) || wasCheck) {
|
||||
if message.groupingKey != nil, adjustedProgress.isEqual(to: 1.0), (message.flags.contains(.Unsent) || wasCheck) {
|
||||
state = .check(appearance: nil)
|
||||
} else {
|
||||
state = .progress(value: CGFloat(adjustedProgress), cancelEnabled: true, appearance: nil)
|
||||
|
@ -176,7 +176,7 @@ final class ChatRecordingPreviewInputPanelNode: ChatInputPanelNode {
|
||||
|> deliverOnMainQueue).start(next: { [weak self] status in
|
||||
if let strongSelf = self {
|
||||
switch status.status {
|
||||
case .playing, .buffering(_, true, _):
|
||||
case .playing, .buffering(_, true, _, _):
|
||||
strongSelf.playButton.isHidden = true
|
||||
default:
|
||||
strongSelf.playButton.isHidden = false
|
||||
|
@ -150,7 +150,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
||||
switch value.status.status {
|
||||
case .playing:
|
||||
isPlaying = true
|
||||
case .buffering(_, true, _):
|
||||
case .buffering(_, true, _, _):
|
||||
isPlaying = true
|
||||
default:
|
||||
break
|
||||
@ -230,7 +230,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
||||
updatedGlobalControlOptions.insert(.next)
|
||||
updatedGlobalControlOptions.insert(.seek)
|
||||
switch state.status.status {
|
||||
case .playing, .buffering(_, true, _):
|
||||
case .playing, .buffering(_, true, _, _):
|
||||
updatedGlobalControlOptions.insert(.pause)
|
||||
default:
|
||||
updatedGlobalControlOptions.insert(.play)
|
||||
@ -384,7 +384,7 @@ public final class MediaManagerImpl: NSObject, MediaManager {
|
||||
switch state.status.status {
|
||||
case .playing:
|
||||
isPlaying = true
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
isPlaying = whilePlaying
|
||||
default:
|
||||
break
|
||||
|
@ -304,7 +304,7 @@ final class OverlayPlayerControlsNode: ASDisplayNode {
|
||||
isPaused = false
|
||||
case .paused:
|
||||
isPaused = true
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
isPaused = !whilePlaying
|
||||
}
|
||||
if strongSelf.currentIsPaused != isPaused {
|
||||
|
@ -311,7 +311,7 @@ final class PeerInfoAvatarListItemNode: ASDisplayNode {
|
||||
var bufferingProgress: Float?
|
||||
if isMediaStreamable(resource: videoContent.fileReference.media.resource) {
|
||||
if let playerStatus = self.playerStatus {
|
||||
if case let .buffering(_, _, progress) = playerStatus.status {
|
||||
if case let .buffering(_, _, progress, _) = playerStatus.status {
|
||||
bufferingProgress = progress
|
||||
} else if case .playing = playerStatus.status {
|
||||
bufferingProgress = nil
|
||||
|
@ -14,7 +14,7 @@ final class GenericEmbedImplementation: WebEmbedImplementation {
|
||||
|
||||
init(url: String) {
|
||||
self.url = url
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true)
|
||||
}
|
||||
|
||||
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {
|
||||
|
@ -37,7 +37,7 @@ final class PictureInPictureVideoControlsNode: ASDisplayNode {
|
||||
case .playing:
|
||||
self.playButton.isHidden = true
|
||||
self.pauseButton.isHidden = false
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
if whilePlaying {
|
||||
self.playButton.isHidden = true
|
||||
self.pauseButton.isHidden = false
|
||||
|
@ -315,7 +315,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
|
||||
self.isBuffering = false
|
||||
}
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -326,7 +326,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
|
||||
let status: MediaPlayerPlaybackStatus
|
||||
self.isBuffering = true
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -337,7 +337,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
|
||||
let status: MediaPlayerPlaybackStatus
|
||||
self.isBuffering = false
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -381,7 +381,7 @@ private final class PlatformVideoContentNode: ASDisplayNode, UniversalVideoConte
|
||||
func play() {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
if !self.initializedStatus {
|
||||
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true))
|
||||
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true))
|
||||
}
|
||||
if !self.hasAudioSession {
|
||||
self.audioSessionDisposable.set(self.audioSessionManager.push(audioSessionType: .play, activate: { [weak self] _ in
|
||||
|
@ -44,7 +44,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
private let playbackCompletedListeners = Bag<() -> Void>()
|
||||
|
||||
private var initializedStatus = false
|
||||
private var statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: false, progress: 0.0), soundEnabled: true)
|
||||
private var statusValue = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: false, progress: 0.0, display: true), soundEnabled: true)
|
||||
private var isBuffering = true
|
||||
private let _status = ValuePromise<MediaPlayerStatus>()
|
||||
var status: Signal<MediaPlayerStatus, NoError> {
|
||||
@ -169,7 +169,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
let isPlaying = !self.player.rate.isZero
|
||||
let status: MediaPlayerPlaybackStatus
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -180,7 +180,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
let status: MediaPlayerPlaybackStatus
|
||||
self.isBuffering = true
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -191,7 +191,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
let status: MediaPlayerPlaybackStatus
|
||||
self.isBuffering = false
|
||||
if self.isBuffering {
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0)
|
||||
status = .buffering(initial: false, whilePlaying: isPlaying, progress: 0.0, display: true)
|
||||
} else {
|
||||
status = isPlaying ? .playing : .paused
|
||||
}
|
||||
@ -219,7 +219,7 @@ private final class SystemVideoContentNode: ASDisplayNode, UniversalVideoContent
|
||||
func play() {
|
||||
assert(Queue.mainQueue().isCurrent())
|
||||
if !self.initializedStatus {
|
||||
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: self.seekId, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true))
|
||||
self._status.set(MediaPlayerStatus(generationTimestamp: 0.0, duration: Double(self.approximateDuration), dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: self.seekId, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true))
|
||||
}
|
||||
if !self.hasAudioSession {
|
||||
self.audioSessionDisposable.set(self.audioSessionManager.push(audioSessionType: .play, activate: { [weak self] _ in
|
||||
|
@ -20,7 +20,7 @@ final class TwitchEmbedImplementation: WebEmbedImplementation {
|
||||
|
||||
init(url: String) {
|
||||
self.url = url
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: 0.0, baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true)
|
||||
}
|
||||
|
||||
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {
|
||||
|
@ -97,7 +97,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation {
|
||||
init(videoId: String, timestamp: Int = 0) {
|
||||
self.videoId = videoId
|
||||
self.timestamp = timestamp
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true)
|
||||
}
|
||||
|
||||
func setup(_ webView: WKWebView, userContentController: WKUserContentController, evaluateJavaScript: @escaping (String, ((Any?) -> Void)?) -> Void, updateStatus: @escaping (MediaPlayerStatus) -> Void, onPlaybackStarted: @escaping () -> Void) {
|
||||
@ -221,7 +221,7 @@ final class VimeoEmbedImplementation: WebEmbedImplementation {
|
||||
playbackStatus = .paused
|
||||
newTimestamp = 0.0
|
||||
default:
|
||||
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0)
|
||||
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0, display: true)
|
||||
}
|
||||
|
||||
self.status = MediaPlayerStatus(generationTimestamp: self.status.generationTimestamp, duration: Double(duration), dimensions: self.status.dimensions, timestamp: newTimestamp, baseRate: 1.0, seekId: self.status.seekId, status: playbackStatus, soundEnabled: true)
|
||||
|
@ -117,11 +117,11 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
|
||||
|
||||
init(videoId: String, timestamp: Int = 0) {
|
||||
self.videoId = videoId
|
||||
self.timestamp = 0
|
||||
self.timestamp = timestamp
|
||||
if self.timestamp > 0 {
|
||||
self.ignoreEarlierTimestamps = true
|
||||
}
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0), soundEnabled: true)
|
||||
self.status = MediaPlayerStatus(generationTimestamp: 0.0, duration: 0.0, dimensions: CGSize(), timestamp: Double(timestamp), baseRate: 1.0, seekId: 0, status: .buffering(initial: true, whilePlaying: true, progress: 0.0, display: true), soundEnabled: true)
|
||||
|
||||
self.benchmarkStartTime = CFAbsoluteTimeGetCurrent()
|
||||
}
|
||||
@ -286,16 +286,16 @@ final class YoutubeEmbedImplementation: WebEmbedImplementation {
|
||||
playbackStatus = .paused
|
||||
newTimestamp = 0.0
|
||||
} else {
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0)
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0, display: false)
|
||||
}
|
||||
case 1:
|
||||
playbackStatus = .playing
|
||||
case 2:
|
||||
playbackStatus = .paused
|
||||
case 3:
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0)
|
||||
playbackStatus = .buffering(initial: false, whilePlaying: true, progress: 0.0, display: false)
|
||||
default:
|
||||
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0)
|
||||
playbackStatus = .buffering(initial: true, whilePlaying: false, progress: 0.0, display: false)
|
||||
}
|
||||
|
||||
if case .playing = playbackStatus, !self.started {
|
||||
|
@ -198,7 +198,7 @@ final class WebSearchVideoGalleryItemNode: ZoomableContentGalleryItemNode {
|
||||
switch value.status {
|
||||
case .playing:
|
||||
isPaused = false
|
||||
case let .buffering(_, whilePlaying, _):
|
||||
case let .buffering(_, whilePlaying, _, _):
|
||||
initialBuffering = true
|
||||
isPaused = !whilePlaying
|
||||
var isStreaming = false
|
||||
|
Loading…
x
Reference in New Issue
Block a user