diff --git a/submodules/GalleryUI/Sources/GalleryController.swift b/submodules/GalleryUI/Sources/GalleryController.swift index 207683625d..2c8fe8d548 100644 --- a/submodules/GalleryUI/Sources/GalleryController.swift +++ b/submodules/GalleryUI/Sources/GalleryController.swift @@ -1306,7 +1306,7 @@ public class GalleryController: ViewController, StandalonePresentableController self.galleryNode.setControlsHidden(self.landscape, animated: false) if let presentationArguments = self.presentationArguments as? GalleryControllerPresentationArguments { if presentationArguments.animated { - self.galleryNode.animateIn(animateContent: !nodeAnimatesItself && !self.useSimpleAnimation) + self.galleryNode.animateIn(animateContent: !nodeAnimatesItself && !self.useSimpleAnimation, useSimpleAnimation: self.useSimpleAnimation) } } } diff --git a/submodules/GalleryUI/Sources/GalleryControllerNode.swift b/submodules/GalleryUI/Sources/GalleryControllerNode.swift index b4b96aa43c..a998a9f8d8 100644 --- a/submodules/GalleryUI/Sources/GalleryControllerNode.swift +++ b/submodules/GalleryUI/Sources/GalleryControllerNode.swift @@ -327,7 +327,7 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture } } - open func animateIn(animateContent: Bool) { + open func animateIn(animateContent: Bool, useSimpleAnimation: Bool) { let duration: Double = animateContent ? 0.2 : 0.3 self.backgroundNode.backgroundColor = self.backgroundNode.backgroundColor?.withAlphaComponent(0.0) @@ -348,7 +348,7 @@ open class GalleryControllerNode: ASDisplayNode, UIScrollViewDelegate, UIGesture if animateContent { self.scrollView.layer.animateBounds(from: self.scrollView.layer.bounds.offsetBy(dx: 0.0, dy: -self.scrollView.layer.bounds.size.height), to: self.scrollView.layer.bounds, duration: 0.4, timingFunction: kCAMediaTimingFunctionSpring) - } else { + } else if useSimpleAnimation { self.scrollView.layer.animateAlpha(from: 0.0, to: 1.0, duration: duration) } } diff --git a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift index 65c065597e..c41a279029 100644 --- a/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift +++ b/submodules/GalleryUI/Sources/Items/UniversalVideoGalleryItem.swift @@ -527,6 +527,7 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte } private weak var overlayController: OverlayMediaController? + private weak var mediaManager: MediaManager? private var pictureInPictureController: AVPictureInPictureController? private var contentDelegate: PlaybackDelegate? private let node: UniversalVideoNode @@ -536,8 +537,11 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte private var pictureInPictureTimer: SwiftSignalKit.Timer? private var didExpand: Bool = false - init(overlayController: OverlayMediaController, videoNode: UniversalVideoNode, willBegin: @escaping (PictureInPictureContentImpl) -> Void, didEnd: @escaping (PictureInPictureContentImpl) -> Void, expand: @escaping (@escaping () -> Void) -> Void) { + private var hiddenMediaManagerIndex: Int? + + init(overlayController: OverlayMediaController, mediaManager: MediaManager, accountId: AccountRecordId, hiddenMedia: (MessageId, Media)?, videoNode: UniversalVideoNode, willBegin: @escaping (PictureInPictureContentImpl) -> Void, didEnd: @escaping (PictureInPictureContentImpl) -> Void, expand: @escaping (@escaping () -> Void) -> Void) { self.overlayController = overlayController + self.mediaManager = mediaManager self.node = videoNode self.willBegin = willBegin self.didEnd = didEnd @@ -571,11 +575,26 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte }, queue: .mainQueue()) self.pictureInPictureTimer = timer timer.start() + + if let hiddenMedia = hiddenMedia { + self.hiddenMediaManagerIndex = mediaManager.galleryHiddenMediaManager.addSource(Signal<(MessageId, Media)?, NoError>.single(hiddenMedia) + |> map { messageIdAndMedia in + if let (messageId, media) = messageIdAndMedia { + return .chat(accountId, messageId, media) + } else { + return nil + } + }) + } } deinit { self.pictureInPictureTimer?.invalidate() self.node.setCanPlaybackWithoutHierarchy(false) + + if let hiddenMediaManagerIndex = self.hiddenMediaManagerIndex, let mediaManager = self.mediaManager { + mediaManager.galleryHiddenMediaManager.removeSource(hiddenMediaManagerIndex) + } } var videoNode: ASDisplayNode { @@ -610,6 +629,7 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte return } overlayController.removePictureInPictureContent(content: self) + self.node.canAttachContent = false if self.didExpand { return } @@ -630,6 +650,10 @@ private final class PictureInPictureContentImpl: NSObject, PictureInPictureConte } completionHandler(true) + + /*Queue.mainQueue().after(0.2, { + self?.node.canAttachContent = false + })*/ } } } @@ -2056,7 +2080,21 @@ final class UniversalVideoGalleryItemNode: ZoomableContentGalleryItemNode { overlayVideoNode.updateLayout(size: absoluteRect.size, transition: .immediate) overlayVideoNode.canAttachContent = true - let content = PictureInPictureContentImpl(overlayController: overlayController, videoNode: overlayVideoNode, willBegin: { [weak self] content in + var hiddenMedia: (MessageId, Media)? = nil + switch item.contentInfo { + case let .message(message): + for media in message.media { + if let media = media as? TelegramMediaImage { + hiddenMedia = (message.id, media) + } else if let media = media as? TelegramMediaFile, media.isVideo { + hiddenMedia = (message.id, media) + } + } + default: + break + } + + let content = PictureInPictureContentImpl(overlayController: overlayController, mediaManager: self.context.sharedContext.mediaManager, accountId: self.context.account.id, hiddenMedia: hiddenMedia, videoNode: overlayVideoNode, willBegin: { [weak self] content in guard let strongSelf = self else { return } diff --git a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift index 82a41cf3f5..0d295f4cb4 100644 --- a/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift +++ b/submodules/GalleryUI/Sources/SecretMediaPreviewController.swift @@ -86,8 +86,8 @@ private final class SecretMediaPreviewControllerNode: GalleryControllerNode { } } - override func animateIn(animateContent: Bool) { - super.animateIn(animateContent: animateContent) + override func animateIn(animateContent: Bool, useSimpleAnimation: Bool) { + super.animateIn(animateContent: animateContent, useSimpleAnimation: useSimpleAnimation) self.timeoutNode?.layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) } @@ -369,7 +369,7 @@ public final class SecretMediaPreviewController: ViewController { self.controllerNode.setControlsHidden(false, animated: false) if let presentationArguments = self.presentationArguments as? GalleryControllerPresentationArguments { if presentationArguments.animated { - self.controllerNode.animateIn(animateContent: !nodeAnimatesItself) + self.controllerNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false) } } } diff --git a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift index 4c0e812516..dd734172a7 100644 --- a/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift +++ b/submodules/InstantPageUI/Sources/InstantPageGalleryController.swift @@ -454,7 +454,7 @@ public class InstantPageGalleryController: ViewController, StandalonePresentable } } - self.galleryNode.animateIn(animateContent: !nodeAnimatesItself) + self.galleryNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false) } override public func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) { diff --git a/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift b/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift index ccea224d94..03ea3e9a28 100644 --- a/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift +++ b/submodules/PassportUI/Sources/SecureIdDocumentGalleryController.swift @@ -244,7 +244,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo } } - self.galleryNode.animateIn(animateContent: !nodeAnimatesItself) + self.galleryNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false) } private var firstLayout = true diff --git a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift index dca7f94c2f..cbbbff9191 100644 --- a/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift +++ b/submodules/PeerAvatarGalleryUI/Sources/AvatarGalleryController.swift @@ -670,7 +670,7 @@ public class AvatarGalleryController: ViewController, StandalonePresentableContr self.galleryNode.setControlsHidden(false, animated: false) if let presentationArguments = self.presentationArguments as? AvatarGalleryControllerPresentationArguments { if presentationArguments.animated { - self.galleryNode.animateIn(animateContent: !nodeAnimatesItself) + self.galleryNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false) } } } diff --git a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift index 21c9457610..949729061f 100644 --- a/submodules/SparseItemGrid/Sources/SparseItemGrid.swift +++ b/submodules/SparseItemGrid/Sources/SparseItemGrid.swift @@ -653,39 +653,66 @@ public final class SparseItemGrid: ASDisplayNode { return nil } - func anchorItem(at point: CGPoint) -> Item? { + func anchorItem(at point: CGPoint, orLower: Bool = false) -> (Item, Int)? { guard let items = self.items, !items.items.isEmpty, let layout = self.layout else { return nil } if layout.containerLayout.lockScrollingAtTop { if let item = items.item(at: 0) { - return item + return (item, 0) } } let localPoint = self.scrollView.convert(point, from: self.view) - var closestItem: (CGFloat, AnyHashable)? + var closestItem: (CGFloat, Int, AnyHashable)? for (id, visibleItem) in self.visibleItems { let itemCenter = visibleItem.frame.center + if visibleItem.frame.minY >= localPoint.y || visibleItem.frame.maxY < localPoint.y { + continue + } + let columnIndex = Int(floor(visibleItem.frame.minX / layout.itemSize.width)) let distanceX = itemCenter.x - localPoint.x + if orLower { + if distanceX > 0.0 { + continue + } + } let distanceY = itemCenter.y - localPoint.y let distance2 = distanceX * distanceX + distanceY * distanceY - if let (currentDistance2, _) = closestItem { + if let (currentDistance2, _, _) = closestItem { if distance2 < currentDistance2 { - closestItem = (distance2, id) + closestItem = (distance2, columnIndex, id) } } else { - closestItem = (distance2, id) + closestItem = (distance2, columnIndex, id) } } - if let (_, id) = closestItem { + if closestItem == nil { + for (id, visibleItem) in self.visibleItems { + let itemCenter = visibleItem.frame.center + let columnIndex = Int(floor(visibleItem.frame.minX / layout.itemSize.width)) + let distanceX = itemCenter.x - localPoint.x + let distanceY = itemCenter.y - localPoint.y + let distance2 = distanceX * distanceX + distanceY * distanceY + + if let (currentDistance2, _, _) = closestItem { + if distance2 < currentDistance2 { + closestItem = (distance2, columnIndex, id) + } + } else { + closestItem = (distance2, columnIndex, id) + } + } + } + + if let (_, columnIndex, id) = closestItem { for item in items.items { if item.id == id { - return item + return (item, columnIndex) } } return nil @@ -1083,6 +1110,7 @@ public final class SparseItemGrid: ASDisplayNode { let interactiveState: InteractiveState? let layout: ContainerLayout let anchorItemIndex: Int + let transitionAnchorPoint: CGPoint let fromViewport: Viewport let toViewport: Viewport @@ -1094,10 +1122,11 @@ public final class SparseItemGrid: ASDisplayNode { let coveringOffsetUpdated: (ContainedViewLayoutTransition) -> Void - init(interactiveState: InteractiveState?, layout: ContainerLayout, anchorItemIndex: Int, from fromViewport: Viewport, to toViewport: Viewport, coveringOffsetUpdated: @escaping (ContainedViewLayoutTransition) -> Void) { + init(interactiveState: InteractiveState?, layout: ContainerLayout, anchorItemIndex: Int, transitionAnchorPoint: CGPoint, from fromViewport: Viewport, to toViewport: Viewport, coveringOffsetUpdated: @escaping (ContainedViewLayoutTransition) -> Void) { self.interactiveState = interactiveState self.layout = layout self.anchorItemIndex = anchorItemIndex + self.transitionAnchorPoint = transitionAnchorPoint self.fromViewport = fromViewport self.toViewport = toViewport self.coveringOffsetUpdated = coveringOffsetUpdated @@ -1119,35 +1148,75 @@ public final class SparseItemGrid: ASDisplayNode { let previousProgress = self.currentProgress self.currentProgress = progress - let fixedAnchorPoint = CGPoint(x: toAnchorFrame.midX, y: toAnchorFrame.midY) + var fromAnchorPoint = CGPoint() + var toAnchorPoint = CGPoint() + var fromDeltaOffset = CGPoint() + var fromScale: CGFloat = 1.0 + var toScale: CGFloat = 1.0 - if let fromItem = self.fromViewport.anchorItem(at: fixedAnchorPoint), let fromFrame = self.fromViewport.frameForItem(at: fromItem.index) { - fromAnchorFrame.origin.y = fromFrame.midY - fromAnchorFrame.origin.x = fromFrame.midX - fromAnchorFrame.size.width = 0.0 + var searchOffset: CGFloat = 0.0 + + while true { + //let fixedAnchorPoint = CGPoint(x: fromAnchorFrame.midX, y: fromAnchorFrame.midY) + var fixedAnchorPoint = self.transitionAnchorPoint + if fixedAnchorPoint.x < self.layout.size.width / 2.0 { + fixedAnchorPoint.x = 0.0 + } else { + fixedAnchorPoint.x = self.layout.size.width + } + + if let fromItem = self.fromViewport.anchorItem(at: fixedAnchorPoint), let fromFrame = self.fromViewport.frameForItem(at: fromItem.0.index) { + print("fromColumn: \(fromItem.1)") + fromAnchorFrame = fromFrame + + fromAnchorFrame.origin.y = fromFrame.midY + fromAnchorFrame.origin.x = fromFrame.midX + fromAnchorFrame.size.width = 0.0 + } else { + print("find item1") + } + + if let toItem = self.toViewport.anchorItem(at: fixedAnchorPoint.offsetBy(dx: searchOffset, dy: 0.0)), let toFrame = self.toViewport.frameForItem(at: toItem.0.index) { + toAnchorFrame = toFrame + print("toColumn: \(toItem.1)") + + toAnchorFrame.origin.y = toFrame.midY + toAnchorFrame.origin.x = toFrame.midX + toAnchorFrame.size.width = 0.0 + } else { + print("find item2") + } + + fromAnchorPoint = CGPoint(x: fromAnchorFrame.midX, y: fromAnchorFrame.midY) + toAnchorPoint = CGPoint(x: toAnchorFrame.midX, y: toAnchorFrame.midY) + + let initialFromViewportScale: CGFloat = 1.0 + let targetFromViewportScale: CGFloat = toAnchorFrame.height / fromAnchorFrame.height + + let initialToViewportScale: CGFloat = fromAnchorFrame.height / toAnchorFrame.height + let targetToViewportScale: CGFloat = 1.0 + + fromScale = initialFromViewportScale * (1.0 - progress) + targetFromViewportScale * progress + toScale = initialToViewportScale * (1.0 - progress) + targetToViewportScale * progress + + fromDeltaOffset = CGPoint(x: toAnchorPoint.x - fromAnchorPoint.x, y: toAnchorPoint.y - fromAnchorPoint.y) + + if fromDeltaOffset.x > 0.0 && abs(searchOffset) < 1000.0 { + searchOffset += -4.0 + //continue + break + } else { + if fromDeltaOffset.x <= 0.0 { + print("fail") + } + break + } } - if let toItem = self.toViewport.anchorItem(at: fixedAnchorPoint), let toFrame = self.toViewport.frameForItem(at: toItem.index) { - toAnchorFrame.origin.y = toFrame.midY - toAnchorFrame.origin.x = toFrame.midX - toAnchorFrame.size.width = 0.0 - } - - let fromAnchorPoint = CGPoint(x: fromAnchorFrame.midX, y: fromAnchorFrame.midY) - let toAnchorPoint = CGPoint(x: toAnchorFrame.midX, y: toAnchorFrame.midY) - - let initialFromViewportScale: CGFloat = 1.0 - let targetFromViewportScale: CGFloat = toAnchorFrame.height / fromAnchorFrame.height - - let initialToViewportScale: CGFloat = fromAnchorFrame.height / toAnchorFrame.height - let targetToViewportScale: CGFloat = 1.0 - - let fromScale = initialFromViewportScale * (1.0 - progress) + targetFromViewportScale * progress - let toScale = initialToViewportScale * (1.0 - progress) + targetToViewportScale * progress - - let fromDeltaOffset = CGPoint(x: toAnchorPoint.x - fromAnchorPoint.x, y: toAnchorPoint.y - fromAnchorPoint.y) let toDeltaOffset = CGPoint(x: -fromDeltaOffset.x, y: -fromDeltaOffset.y) + print("direction: \(fromDeltaOffset.x < 0.0)") + let fromOffset = CGPoint(x: 0.0 * (1.0 - progress) + fromDeltaOffset.x * progress, y: 0.0 * (1.0 - progress) + fromDeltaOffset.y * progress) let toOffset = CGPoint(x: toDeltaOffset.x * (1.0 - progress) + 0.0 * progress, y: toDeltaOffset.y * (1.0 - progress) + 0.0 * progress) @@ -1295,18 +1364,18 @@ public final class SparseItemGrid: ASDisplayNode { if isZoomingIn { if progress > 1.0 { nextZoomLevel = zoomLevels.increment - nextScale = startScale * 1.5 + nextScale = startScale * 1.25 } else { nextZoomLevel = zoomLevels.decrement - nextScale = startScale * 0.5 + nextScale = startScale * 0.75 } } else { if progress > 1.0 { nextZoomLevel = zoomLevels.decrement - nextScale = startScale * 0.5 + nextScale = startScale * 0.75 } else { nextZoomLevel = zoomLevels.increment - nextScale = startScale * 1.5 + nextScale = startScale * 1.25 } } @@ -1314,7 +1383,7 @@ public final class SparseItemGrid: ASDisplayNode { let nextAnchorItemIndex: Int if let anchorItem = boundaryViewport.anchorItem(at: anchorLocation) { - nextAnchorItemIndex = anchorItem.index + nextAnchorItemIndex = anchorItem.0.index } else { nextAnchorItemIndex = currentViewportTransition.anchorItemIndex } @@ -1339,7 +1408,7 @@ public final class SparseItemGrid: ASDisplayNode { self.currentViewportTransition?.removeFromSupernode() let nextInteractiveState = ViewportTransition.InteractiveState(anchorLocation: anchorLocation, initialScale: startScale, targetScale: nextScale) - let currentViewportTransition = ViewportTransition(interactiveState: nextInteractiveState, layout: containerLayout, anchorItemIndex: currentViewportTransition.anchorItemIndex, from: boundaryViewport, to: nextViewport, coveringOffsetUpdated: { [weak self] transition in + let currentViewportTransition = ViewportTransition(interactiveState: nextInteractiveState, layout: containerLayout, anchorItemIndex: currentViewportTransition.anchorItemIndex, transitionAnchorPoint: currentViewportTransition.transitionAnchorPoint, from: boundaryViewport, to: nextViewport, coveringOffsetUpdated: { [weak self] transition in self?.transitionCoveringOffsetUpdated(transition: transition) }) currentViewportTransition.frame = CGRect(origin: CGPoint(), size: containerLayout.size) @@ -1365,14 +1434,14 @@ public final class SparseItemGrid: ASDisplayNode { if let previousViewport = self.currentViewport, let nextZoomLevel = nextZoomLevel { let anchorLocation = recognizer.location(in: self.view) - let interactiveState = ViewportTransition.InteractiveState(anchorLocation: anchorLocation, initialScale: 1.0, targetScale: scale > 1.0 ? scale * 1.5 : scale * 0.5) + let interactiveState = ViewportTransition.InteractiveState(anchorLocation: anchorLocation, initialScale: 1.0, targetScale: scale > 1.0 ? scale * 1.25 : scale * 0.75) var progress = (scale - interactiveState.initialScale) / (interactiveState.targetScale - interactiveState.initialScale) progress = max(0.0, min(1.0, progress)) - if let anchorItem = previousViewport.anchorItem(at: anchorLocation), let anchorItemFrame = previousViewport.frameForItem(at: anchorItem.index) { - let restoreScrollPosition: (y: CGFloat, index: Int)? = (anchorItemFrame.minY, anchorItem.index) - let anchorItemIndex = anchorItem.index + if let anchorItem = previousViewport.anchorItem(at: anchorLocation), let anchorItemFrame = previousViewport.frameForItem(at: anchorItem.0.index) { + let restoreScrollPosition: (y: CGFloat, index: Int)? = (anchorItemFrame.minY, anchorItem.0.index) + let anchorItemIndex = anchorItem.0.index let nextViewport = Viewport(theme: self.theme, zoomLevel: nextZoomLevel, maybeLoadHoleAnchor: { [weak self] holeAnchor, location in guard let strongSelf = self else { @@ -1386,7 +1455,7 @@ public final class SparseItemGrid: ASDisplayNode { nextViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) nextViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: .semi) - let currentViewportTransition = ViewportTransition(interactiveState: interactiveState, layout: containerLayout, anchorItemIndex: anchorItemIndex, from: previousViewport, to: nextViewport, coveringOffsetUpdated: { [weak self] transition in + let currentViewportTransition = ViewportTransition(interactiveState: interactiveState, layout: containerLayout, anchorItemIndex: anchorItemIndex, transitionAnchorPoint: anchorLocation, from: previousViewport, to: nextViewport, coveringOffsetUpdated: { [weak self] transition in self?.transitionCoveringOffsetUpdated(transition: transition) }) currentViewportTransition.frame = CGRect(origin: CGPoint(), size: containerLayout.size) @@ -1535,15 +1604,15 @@ public final class SparseItemGrid: ASDisplayNode { if let containerLayout = self.containerLayout, let items = self.items { let anchorLocation = CGPoint(x: 0.0, y: 10.0) - if let anchorItem = previousViewport.anchorItem(at: anchorLocation), let anchorItemFrame = previousViewport.frameForItem(at: anchorItem.index) { - let restoreScrollPosition: (y: CGFloat, index: Int)? = (anchorItemFrame.minY, anchorItem.index) - let anchorItemIndex = anchorItem.index + if let anchorItem = previousViewport.anchorItem(at: anchorLocation), let anchorItemFrame = previousViewport.frameForItem(at: anchorItem.0.index) { + let restoreScrollPosition: (y: CGFloat, index: Int)? = (anchorItemFrame.minY, anchorItem.0.index) + let anchorItemIndex = anchorItem.0.index self.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size) currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: .semi) - let currentViewportTransition = ViewportTransition(interactiveState: nil, layout: containerLayout, anchorItemIndex: anchorItemIndex, from: previousViewport, to: currentViewport, coveringOffsetUpdated: { [weak self] transition in + let currentViewportTransition = ViewportTransition(interactiveState: nil, layout: containerLayout, anchorItemIndex: anchorItemIndex, transitionAnchorPoint: anchorLocation, from: previousViewport, to: currentViewport, coveringOffsetUpdated: { [weak self] transition in self?.transitionCoveringOffsetUpdated(transition: transition) }) currentViewportTransition.frame = CGRect(origin: CGPoint(), size: containerLayout.size) diff --git a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift index d232173361..5d57a361db 100644 --- a/submodules/TelegramUI/Sources/ChatHistoryListNode.swift +++ b/submodules/TelegramUI/Sources/ChatHistoryListNode.swift @@ -560,6 +560,8 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { private var contentInsetAnimator: DisplayLinkAnimator? private let adMessagesContext: AdMessagesHistoryContext? + private var preloadAdPeerId: PeerId? + private let preloadAdPeerDisposable = MetaDisposable() private let clientId: Atomic @@ -586,7 +588,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.prefetchManager = InChatPrefetchManager(context: context) - let adMessages: Signal<[Message], NoError> + var adMessages: Signal<[Message], NoError> if case .bubbles = mode, case let .peer(peerId) = chatLocation, case .none = subject { let adMessagesContext = context.engine.messages.adMessages(peerId: peerId) self.adMessagesContext = adMessagesContext @@ -602,6 +604,29 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { super.init() + adMessages = adMessages + |> afterNext { [weak self] messages in + Queue.mainQueue().async { + guard let strongSelf = self else { + return + } + var adPeerId: PeerId? + adPeerId = nil + + if strongSelf.preloadAdPeerId != adPeerId { + strongSelf.preloadAdPeerId = adPeerId + if let adPeerId = adPeerId { + let combinedDisposable = DisposableSet() + strongSelf.preloadAdPeerDisposable.set(combinedDisposable) + combinedDisposable.add(strongSelf.context.account.viewTracker.polledChannel(peerId: adPeerId).start()) + combinedDisposable.add(strongSelf.context.account.addAdditionalPreloadHistoryPeerId(peerId: adPeerId)) + } else { + strongSelf.preloadAdPeerDisposable.set(nil) + } + } + } + } + self.clipsToBounds = false self.accessibilityPageScrolledString = { [weak self] row, count in @@ -1397,6 +1422,7 @@ public final class ChatHistoryListNode: ListView, ChatHistoryNode { self.interactiveReadActionDisposable?.dispose() self.canReadHistoryDisposable?.dispose() self.loadedMessagesFromCachedDataDisposable?.dispose() + self.preloadAdPeerDisposable.dispose() } public func setLoadStateUpdated(_ f: @escaping (ChatHistoryNodeLoadState, Bool) -> Void) { diff --git a/submodules/TelegramUI/Sources/GalleryHiddenMediaManager.swift b/submodules/TelegramUI/Sources/GalleryHiddenMediaManager.swift index 6ef1de21e7..88bf0090a1 100644 --- a/submodules/TelegramUI/Sources/GalleryHiddenMediaManager.swift +++ b/submodules/TelegramUI/Sources/GalleryHiddenMediaManager.swift @@ -30,10 +30,21 @@ private final class GalleryHiddenMediaTargetHolder { } final class GalleryHiddenMediaManagerImpl: GalleryHiddenMediaManager { + private final class SourceContext { + let disposable: Disposable + var state: (GalleryHiddenMediaId, Int32)? = nil + + init(disposable: Disposable) { + self.disposable = disposable + } + } + + private var sources = Bag() + private var sourceContexts: [Int: SourceContext] = [:] + private var nextId: Int32 = 0 private var contexts: [GalleryHiddenMediaId: GalleryHiddenMediaContext] = [:] - - private var sourcesDisposables = Bag() + private var subscribers = Bag<(Set) -> Void>() private var targets: [GalleryHiddenMediaTargetHolder] = [] @@ -86,8 +97,29 @@ final class GalleryHiddenMediaManagerImpl: GalleryHiddenMediaManager { } func addSource(_ signal: Signal) -> Int { - var state: (GalleryHiddenMediaId, Int32)? - let index = self.sourcesDisposables.add((signal |> deliverOnMainQueue).start(next: { [weak self] id in + let index = self.sources.add(Void()) + let disposable = MetaDisposable() + let context = SourceContext(disposable: disposable) + self.sourceContexts[index] = context + + disposable.set((signal |> deliverOnMainQueue).start(next: { [weak self, weak context] id in + guard let strongSelf = self, let context = context else { + return + } + if id != context.state?.0 { + if let (previousId, previousIndex) = context.state { + strongSelf.removeHiddenMedia(id: previousId, index: previousIndex) + context.state = nil + } + if let id = id { + context.state = (id, strongSelf.addHiddenMedia(id: id)) + } + } + })) + + return index + + /*let index = self.sourcesDisposables.add((signal |> deliverOnMainQueue).start(next: { [weak self] id in if let strongSelf = self { if id != state?.0 { if let (previousId, previousIndex) = state { @@ -100,13 +132,17 @@ final class GalleryHiddenMediaManagerImpl: GalleryHiddenMediaManager { } } })) - return index + return index*/ } func removeSource(_ index: Int) { - if let disposable = self.sourcesDisposables.get(index) { - self.sourcesDisposables.remove(index) - disposable.dispose() + self.sources.remove(index) + + if let context = self.sourceContexts.removeValue(forKey: index) { + context.disposable.dispose() + if let (previousId, previousIndex) = context.state { + self.removeHiddenMedia(id: previousId, index: previousIndex) + } } } diff --git a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift index 5d9fe64993..daa1969228 100644 --- a/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift +++ b/submodules/WebSearchUI/Sources/WebSearchGalleryController.swift @@ -333,7 +333,7 @@ class WebSearchGalleryController: ViewController { } } - self.galleryNode.animateIn(animateContent: !nodeAnimatesItself) + self.galleryNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false) } override func containerLayoutUpdated(_ layout: ContainerViewLayout, transition: ContainedViewLayoutTransition) {