mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-06-16 05:55:20 +00:00
Shared media improvements
This commit is contained in:
parent
6d55902c0d
commit
24b4e1707b
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -244,7 +244,7 @@ class SecureIdDocumentGalleryController: ViewController, StandalonePresentableCo
|
||||
}
|
||||
}
|
||||
|
||||
self.galleryNode.animateIn(animateContent: !nodeAnimatesItself)
|
||||
self.galleryNode.animateIn(animateContent: !nodeAnimatesItself, useSimpleAnimation: false)
|
||||
}
|
||||
|
||||
private var firstLayout = true
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<Int32>
|
||||
|
||||
@ -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) {
|
||||
|
@ -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<Void>()
|
||||
private var sourceContexts: [Int: SourceContext] = [:]
|
||||
|
||||
private var nextId: Int32 = 0
|
||||
private var contexts: [GalleryHiddenMediaId: GalleryHiddenMediaContext] = [:]
|
||||
|
||||
private var sourcesDisposables = Bag<Disposable>()
|
||||
|
||||
private var subscribers = Bag<(Set<GalleryHiddenMediaId>) -> Void>()
|
||||
|
||||
private var targets: [GalleryHiddenMediaTargetHolder] = []
|
||||
@ -86,8 +97,29 @@ final class GalleryHiddenMediaManagerImpl: GalleryHiddenMediaManager {
|
||||
}
|
||||
|
||||
func addSource(_ signal: Signal<GalleryHiddenMediaId?, NoError>) -> 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user