diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 5dc82d014c..275f92699c 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -348,7 +348,7 @@ public class GalleryController: ViewController, StandalonePresentableController private let fromPlayingVideo: Bool private let landscape: Bool private let timecode: Double? - private let playbackRate: Double? + private var playbackRate: Double? private let accountInUseDisposable = MetaDisposable() private let disposable = MetaDisposable() @@ -538,7 +538,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == strongSelf.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, playbackRate: isCentral ? playbackRate : nil, displayInfoOnTop: displayInfoOnTop, configuration: configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: context, presentationData: strongSelf.presentationData, entry: entry, isCentral: isCentral, streamVideos: streamSingleVideo, fromPlayingVideo: isCentral && fromPlayingVideo, landscape: isCentral && landscape, timecode: isCentral ? timecode : nil, playbackRate: playbackRate, displayInfoOnTop: displayInfoOnTop, configuration: configuration, performAction: strongSelf.performAction, openActionOptions: strongSelf.openActionOptions, storeMediaPlaybackState: strongSelf.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } @@ -1102,7 +1102,7 @@ public class GalleryController: ViewController, StandalonePresentableController if entry.message.stableId == self.centralEntryStableId { isCentral = true } - if let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: entry, streamVideos: self.streamVideos, fromPlayingVideo: isCentral && self.fromPlayingVideo, landscape: isCentral && self.landscape, timecode: isCentral ? self.timecode : nil, playbackRate: isCentral ? self.playbackRate : 1.0, displayInfoOnTop: displayInfoOnTop, configuration: self.configuration, performAction: self.performAction, openActionOptions: self.openActionOptions, storeMediaPlaybackState: self.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in + if let item = galleryItemForEntry(context: self.context, presentationData: self.presentationData, entry: entry, streamVideos: self.streamVideos, fromPlayingVideo: isCentral && self.fromPlayingVideo, landscape: isCentral && self.landscape, timecode: isCentral ? self.timecode : nil, playbackRate: self.playbackRate, displayInfoOnTop: displayInfoOnTop, configuration: self.configuration, performAction: self.performAction, openActionOptions: self.openActionOptions, storeMediaPlaybackState: self.actionInteraction?.storeMediaPlaybackState ?? { _, _, _ in }, present: { [weak self] c, a in if let strongSelf = self { strongSelf.presentInGlobalOverlay(c, with: a) } @@ -1369,4 +1369,14 @@ public class GalleryController: ViewController, StandalonePresentableController } } } + + func updateSharedPlaybackRate(_ playbackRate: Double?) { + self.playbackRate = playbackRate + + self.galleryNode.pager.forEachItemNode { itemNode in + if let itemNode = itemNode as? UniversalVideoGalleryItemNode { + itemNode.updatePlaybackRate(playbackRate) + } + } + } } diff --git a/submodules/GalleryUI/Sources/GalleryPagerNode.swift b/submodules/GalleryUI/Sources/GalleryPagerNode.swift index 80217fe39e..bc6f4c86a5 100644 --- a/submodules/GalleryUI/Sources/GalleryPagerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryPagerNode.swift @@ -168,7 +168,11 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest } } else if point.x > size.width - edgeWidth(width: size.width) && strongSelf.canGoToNextItem() { if strongSelf.items.count > 1 { - highlightedSide = true + if point.y < 80.0 { + highlightedSide = nil + } else { + highlightedSide = true + } } } @@ -176,7 +180,7 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest return .fail } - if let result = strongSelf.hitTest(point, with: nil), let node = result.asyncdisplaykit_node as? ASButtonNode { + if let result = strongSelf.hitTest(point, with: nil), let _ = result.asyncdisplaykit_node as? ASButtonNode { return .fail } return .keepWithSingleTap @@ -702,4 +706,10 @@ public final class GalleryPagerNode: ASDisplayNode, UIScrollViewDelegate, UIGest self.centralItemIndexOffsetUpdated(nil) } } + + public func forEachItemNode(_ f: (GalleryItemNode) -> Void) { + for itemNode in self.itemNodes { + f(itemNode) + } + } } diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 5423b55c56..1fc0a87eb1 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -494,6 +494,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { private var requiresDownload = false private var item: UniversalVideoGalleryItem? + private var playbackRate: Double? + private let playbackRatePromise = ValuePromise() private let statusDisposable = MetaDisposable() private let moreButtonStateDisposable = MetaDisposable() @@ -622,6 +624,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { self.footerContentNode.setPlayRate = { [weak self] rate in if let strongSelf = self, let videoNode = strongSelf.videoNode { videoNode.setBaseRate(rate) + + if let controller = strongSelf.galleryController() as? GalleryController { + controller.updateSharedPlaybackRate(rate) + } } } @@ -839,6 +845,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else { strongSelf.videoNode?.playOnceWithSound(playAndRecord: false, actionAtEnd: isAnimated ? .loop : strongSelf.actionAtEnd) } + + if let playbackRate = strongSelf.playbackRate { + videoNode.setBaseRate(playbackRate) + } } } } @@ -872,10 +882,15 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else { let throttledSignal = videoNode.status |> mapToThrottled { next -> Signal in - return .single(next) |> then(.complete() |> delay(2.0, queue: Queue.concurrentDefaultQueue())) + return .single(next) |> then(.complete() |> delay(0.5, queue: Queue.concurrentDefaultQueue())) } - self.mediaPlaybackStateDisposable.set(throttledSignal.start(next: { status in + self.mediaPlaybackStateDisposable.set((throttledSignal + |> deliverOnMainQueue).start(next: { [weak self] status in + guard let strongSelf = self, let videoNode = strongSelf.videoNode, videoNode.ownsContentNode else { + return + } + if let status = status, status.duration >= 60.0 * 10.0 { var timestamp: Double? if status.timestamp > 5.0 && status.timestamp < status.duration - 5.0 { @@ -923,21 +938,18 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } self.moreButtonStateDisposable.set(combineLatest(queue: .mainQueue(), - videoNode.status, + self.playbackRatePromise.get(), self.isShowingContextMenuPromise.get() - ).start(next: { [weak self] status, isShowingContextMenu in + ).start(next: { [weak self] playbackRate, isShowingContextMenu in guard let strongSelf = self else { return } - guard let status = status else { - return - } let effectiveBaseRate: Double if isShowingContextMenu { effectiveBaseRate = 1.0 } else { - effectiveBaseRate = status.baseRate + effectiveBaseRate = playbackRate } if abs(effectiveBaseRate - strongSelf.moreBarButtonRate) > 0.01 { @@ -1158,6 +1170,14 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } self.item = item + + if let _ = item.content as? NativeVideoContent { + self.playbackRate = item.playbackRate + } else if let _ = item.content as? WebEmbedVideoContent { + self.playbackRate = item.playbackRate + } + + self.playbackRatePromise.set(self.playbackRate ?? 1.0) if let contentInfo = item.contentInfo { switch contentInfo { @@ -1244,6 +1264,8 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } else if self.shouldAutoplayOnCentrality() { self.initiallyActivated = true videoNode.playOnceWithSound(playAndRecord: false, actionAtEnd: self.actionAtEnd) + + videoNode.setBaseRate(self.playbackRate ?? 1.0) } } else { if self.shouldAutoplayOnCentrality() { @@ -1314,24 +1336,21 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { var isAnimated = false var seek = MediaPlayerSeek.start - var playbackRate: Double? = nil if let item = self.item { if let content = item.content as? NativeVideoContent { isAnimated = content.fileReference.media.isAnimated if let time = item.timecode { seek = .timecode(time) } - playbackRate = item.playbackRate } else if let _ = item.content as? WebEmbedVideoContent { if let time = item.timecode { seek = .timecode(time) } - playbackRate = item.playbackRate } } - if let playbackRate = playbackRate { - videoNode.setBaseRate(playbackRate) - } + + videoNode.setBaseRate(self.playbackRate ?? 1.0) + if isAnimated { videoNode.seek(0.0) videoNode.play() @@ -2127,6 +2146,10 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { } videoNode.setBaseRate(rate) + + if let controller = strongSelf.galleryController() as? GalleryController { + controller.updateSharedPlaybackRate(rate) + } }))) } @@ -2198,6 +2221,16 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { override func footerContent() -> Signal<(GalleryFooterContentNode?, GalleryOverlayContentNode?), NoError> { return .single((self.footerContentNode, nil)) } + + func updatePlaybackRate(_ playbackRate: Double?) { + self.playbackRate = playbackRate + + if let playbackRate = self.playbackRate { + self.videoNode?.setBaseRate(playbackRate) + } + + self.playbackRatePromise.set(self.playbackRate ?? 1.0) + } } private final class HeaderContextReferenceContentSource: ContextReferenceContentSource { diff --git a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift index ee678fd115..0cc2053ed0 100644 --- a/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift +++ b/submodules/TelegramUI/Sources/ChatMessageInteractiveMediaNode.swift @@ -899,6 +899,9 @@ final class ChatMessageInteractiveMediaNode: ASDisplayNode, GalleryItemTransitio videoNode.ownsContentNodeUpdated = { [weak self] owns in if let strongSelf = self { strongSelf.videoNode?.isHidden = !owns + if owns { + strongSelf.videoNode?.setBaseRate(1.0) + } } } strongSelf.videoContent = videoContent