Fix synchronous load

This commit is contained in:
Ali 2021-10-28 02:14:15 +04:00
parent 6a9944e1bb
commit b54fc364e7
2 changed files with 39 additions and 16 deletions

View File

@ -35,7 +35,7 @@ public protocol SparseItemGridBinding: AnyObject {
func createLayer() -> SparseItemGridLayer? func createLayer() -> SparseItemGridLayer?
func createView() -> SparseItemGridView? func createView() -> SparseItemGridView?
func createShimmerLayer() -> SparseItemGridShimmerLayer? func createShimmerLayer() -> SparseItemGridShimmerLayer?
func bindLayers(items: [SparseItemGrid.Item], layers: [SparseItemGridDisplayItem], synchronous: Bool) func bindLayers(items: [SparseItemGrid.Item], layers: [SparseItemGridDisplayItem], synchronous: SparseItemGrid.Synchronous)
func unbindLayer(layer: SparseItemGridLayer) func unbindLayer(layer: SparseItemGridLayer)
func scrollerTextForTag(tag: Int32) -> String? func scrollerTextForTag(tag: Int32) -> String?
func loadHole(anchor: SparseItemGrid.HoleAnchor, at location: SparseItemGrid.HoleLocation) -> Signal<Never, NoError> func loadHole(anchor: SparseItemGrid.HoleAnchor, at location: SparseItemGrid.HoleLocation) -> Signal<Never, NoError>
@ -167,6 +167,12 @@ public final class SparseItemGrid: ASDisplayNode {
} }
} }
public enum Synchronous {
case semi
case full
case none
}
open class Item { open class Item {
open var id: AnyHashable { open var id: AnyHashable {
preconditionFailure() preconditionFailure()
@ -476,7 +482,7 @@ public final class SparseItemGrid: ASDisplayNode {
self.view.addSubview(self.scrollView) self.view.addSubview(self.scrollView)
} }
func update(containerLayout: ContainerLayout, items: Items, restoreScrollPosition: (y: CGFloat, index: Int)?, synchronous: Bool) { func update(containerLayout: ContainerLayout, items: Items, restoreScrollPosition: (y: CGFloat, index: Int)?, synchronous: SparseItemGrid.Synchronous) {
if self.layout?.containerLayout != containerLayout || self.items !== items { if self.layout?.containerLayout != containerLayout || self.items !== items {
self.layout = Layout(containerLayout: containerLayout, zoomLevel: self.zoomLevel) self.layout = Layout(containerLayout: containerLayout, zoomLevel: self.zoomLevel)
self.items = items self.items = items
@ -497,7 +503,7 @@ public final class SparseItemGrid: ASDisplayNode {
@objc func scrollViewDidScroll(_ scrollView: UIScrollView) { @objc func scrollViewDidScroll(_ scrollView: UIScrollView) {
if !self.ignoreScrolling { if !self.ignoreScrolling {
self.updateVisibleItems(resetScrolling: false, synchronous: true, restoreScrollPosition: nil) self.updateVisibleItems(resetScrolling: false, synchronous: .full, restoreScrollPosition: nil)
if let layout = self.layout, let _ = self.items { if let layout = self.layout, let _ = self.items {
let offset = scrollView.contentOffset.y let offset = scrollView.contentOffset.y
@ -769,7 +775,7 @@ public final class SparseItemGrid: ASDisplayNode {
self.decelerationAnimator?.isPaused = false self.decelerationAnimator?.isPaused = false
} }
private func updateVisibleItems(resetScrolling: Bool, synchronous: Bool, restoreScrollPosition: (y: CGFloat, index: Int)?) { private func updateVisibleItems(resetScrolling: Bool, synchronous: SparseItemGrid.Synchronous, restoreScrollPosition: (y: CGFloat, index: Int)?) {
guard let layout = self.layout, let items = self.items else { guard let layout = self.layout, let items = self.items else {
return return
} }
@ -1270,7 +1276,7 @@ public final class SparseItemGrid: ASDisplayNode {
}) })
nextViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) nextViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
nextViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: false) nextViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: .semi)
self.currentViewportTransition?.removeFromSupernode() self.currentViewportTransition?.removeFromSupernode()
@ -1320,7 +1326,7 @@ public final class SparseItemGrid: ASDisplayNode {
}) })
nextViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) nextViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
nextViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: false) 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, from: previousViewport, to: nextViewport, coveringOffsetUpdated: { [weak self] transition in
self?.transitionCoveringOffsetUpdated(transition: transition) self?.transitionCoveringOffsetUpdated(transition: transition)
@ -1359,7 +1365,7 @@ public final class SparseItemGrid: ASDisplayNode {
strongSelf.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size) strongSelf.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.setScrollingArea(scrollingArea: strongSelf.scrollingArea) currentViewport.setScrollingArea(scrollingArea: strongSelf.scrollingArea)
currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: nil, synchronous: false) currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: nil, synchronous: .semi)
} }
strongSelf.currentViewportTransition = nil strongSelf.currentViewportTransition = nil
@ -1371,7 +1377,7 @@ public final class SparseItemGrid: ASDisplayNode {
} }
} }
public func update(size: CGSize, insets: UIEdgeInsets, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, items: Items, theme: PresentationTheme, synchronous: Bool) { public func update(size: CGSize, insets: UIEdgeInsets, scrollIndicatorInsets: UIEdgeInsets, lockScrollingAtTop: Bool, fixedItemHeight: CGFloat?, items: Items, theme: PresentationTheme, synchronous: SparseItemGrid.Synchronous) {
self.theme = theme self.theme = theme
let containerLayout = ContainerLayout(size: size, insets: insets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight) let containerLayout = ContainerLayout(size: size, insets: insets, scrollIndicatorInsets: scrollIndicatorInsets, lockScrollingAtTop: lockScrollingAtTop, fixedItemHeight: fixedItemHeight)
self.containerLayout = containerLayout self.containerLayout = containerLayout
@ -1483,7 +1489,7 @@ public final class SparseItemGrid: ASDisplayNode {
self.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size) self.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: restoreScrollPosition, synchronous: false) 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, from: previousViewport, to: currentViewport, coveringOffsetUpdated: { [weak self] transition in
self?.transitionCoveringOffsetUpdated(transition: transition) self?.transitionCoveringOffsetUpdated(transition: transition)
@ -1501,7 +1507,7 @@ public final class SparseItemGrid: ASDisplayNode {
strongSelf.insertSubnode(currentViewport, belowSubnode: strongSelf.scrollingArea) strongSelf.insertSubnode(currentViewport, belowSubnode: strongSelf.scrollingArea)
strongSelf.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size) strongSelf.scrollingArea.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size) currentViewport.frame = CGRect(origin: CGPoint(), size: containerLayout.size)
currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: nil, synchronous: false) currentViewport.update(containerLayout: containerLayout, items: items, restoreScrollPosition: nil, synchronous: .semi)
} }
strongSelf.currentViewport?.setScrollingArea(scrollingArea: strongSelf.scrollingArea) strongSelf.currentViewport?.setScrollingArea(scrollingArea: strongSelf.scrollingArea)

View File

@ -1119,7 +1119,7 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
return (list.map(\.0), list.map(\.1)) return (list.map(\.0), list.map(\.1))
}() }()
func bindLayers(items: [SparseItemGrid.Item], layers: [SparseItemGridDisplayItem], synchronous: Bool) { func bindLayers(items: [SparseItemGrid.Item], layers: [SparseItemGridDisplayItem], synchronous: SparseItemGrid.Synchronous) {
for i in 0 ..< items.count { for i in 0 ..< items.count {
guard let item = items[i] as? VisualMediaItem else { guard let item = items[i] as? VisualMediaItem else {
continue continue
@ -1170,22 +1170,37 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
} }
if let selectedMedia = selectedMedia { if let selectedMedia = selectedMedia {
if let result = directMediaImageCache.getImage(message: message, media: selectedMedia, width: imageWidthSpec, possibleWidths: SparseItemGridBindingImpl.widthSpecs.1, synchronous: synchronous) { if let result = directMediaImageCache.getImage(message: message, media: selectedMedia, width: imageWidthSpec, possibleWidths: SparseItemGridBindingImpl.widthSpecs.1, synchronous: synchronous == .full) {
if let image = result.image { if let image = result.image {
layer.contents = image.cgImage layer.contents = image.cgImage
layer.hasContents = true layer.hasContents = true
if !synchronous { switch synchronous {
case .none:
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
default:
break
} }
} }
if let loadSignal = result.loadSignal { if let loadSignal = result.loadSignal {
layer.disposable?.dispose() layer.disposable?.dispose()
let startTimestamp = CFAbsoluteTimeGetCurrent()
layer.disposable = (loadSignal layer.disposable = (loadSignal
|> deliverOnMainQueue).start(next: { [weak self, weak layer, weak displayItem] image in |> deliverOnMainQueue).start(next: { [weak self, weak layer, weak displayItem] image in
guard let layer = layer else { guard let layer = layer else {
return return
} }
if layer.hasContents { let deltaTime = CFAbsoluteTimeGetCurrent() - startTimestamp
let synchronousValue: Bool
switch synchronous {
case .none:
synchronousValue = false
case .semi:
synchronousValue = deltaTime < 0.1
case .full:
synchronousValue = true
}
if layer.hasContents && !synchronousValue {
let copyLayer = ItemLayer() let copyLayer = ItemLayer()
copyLayer.contents = layer.contents copyLayer.contents = layer.contents
copyLayer.contentsRect = layer.contentsRect copyLayer.contentsRect = layer.contentsRect
@ -1201,7 +1216,9 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
layer.contents = image?.cgImage layer.contents = image?.cgImage
layer.hasContents = true layer.hasContents = true
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2) if !synchronousValue {
layer.animateAlpha(from: 0.0, to: 1.0, duration: 0.2)
}
if let displayItem = displayItem { if let displayItem = displayItem {
self?.updateShimmerLayersImpl?(displayItem) self?.updateShimmerLayersImpl?(displayItem)
@ -2145,7 +2162,7 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
fixedItemHeight = nil fixedItemHeight = nil
} }
self.itemGrid.update(size: size, insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset), scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime) self.itemGrid.update(size: size, insets: UIEdgeInsets(top: topInset, left: sideInset, bottom: bottomInset, right: sideInset), scrollIndicatorInsets: UIEdgeInsets(top: 0.0, left: sideInset, bottom: bottomInset, right: sideInset), lockScrollingAtTop: isScrollingLockedAtTop, fixedItemHeight: fixedItemHeight, items: items, theme: self.itemGridBinding.chatPresentationData.theme.theme, synchronous: wasFirstTime ? .full : .none)
} }
} }