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
6f082b3e93
commit
e7df73303c
@ -107,7 +107,13 @@ public final class GridMessageSelectionLayer: CALayer {
|
||||
}
|
||||
|
||||
public func updateLayout(size: CGSize) {
|
||||
let checkSize = CGSize(width: 28.0, height: 28.0)
|
||||
let checkWidth: CGFloat
|
||||
if size.width <= 60.0 {
|
||||
checkWidth = 22.0
|
||||
} else {
|
||||
checkWidth = 28.0
|
||||
}
|
||||
let checkSize = CGSize(width: checkWidth, height: checkWidth)
|
||||
let previousSize = self.checkLayer.bounds.size
|
||||
self.checkLayer.frame = CGRect(origin: CGPoint(x: self.bounds.size.width - checkSize.width - 2.0, y: 2.0), size: checkSize)
|
||||
if self.checkLayer.bounds.size != previousSize {
|
||||
|
@ -809,6 +809,10 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
self.decelerationAnimator?.isPaused = false
|
||||
}
|
||||
|
||||
func updateShimmerColors() {
|
||||
self.updateVisibleItems(resetScrolling: false, synchronous: .none, restoreScrollPosition: nil)
|
||||
}
|
||||
|
||||
private func updateVisibleItems(resetScrolling: Bool, synchronous: SparseItemGrid.Synchronous, restoreScrollPosition: (y: CGFloat, index: Int)?) {
|
||||
guard let layout = self.layout, let items = self.items else {
|
||||
return
|
||||
@ -1695,4 +1699,12 @@ public final class SparseItemGrid: ASDisplayNode {
|
||||
public func transferVelocity(_ velocity: CGFloat) {
|
||||
self.currentViewport?.transferVelocity(velocity)
|
||||
}
|
||||
|
||||
public func updatePresentationData(theme: PresentationTheme) {
|
||||
self.theme = theme
|
||||
|
||||
if let currentViewport = self.currentViewport {
|
||||
currentViewport.updateShimmerColors()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +131,129 @@ public final class LottieAnimationComponent: Component {
|
||||
}
|
||||
}
|
||||
|
||||
private final class ScrollingTooltipAnimationComponent: Component {
|
||||
public init() {
|
||||
}
|
||||
|
||||
public static func ==(lhs: ScrollingTooltipAnimationComponent, rhs: ScrollingTooltipAnimationComponent) -> Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
public final class View: UIView {
|
||||
private var progress: CGFloat = 0.0
|
||||
private var previousTarget: CGFloat = 0.0
|
||||
|
||||
private var animator: DisplayLinkAnimator?
|
||||
|
||||
init() {
|
||||
super.init(frame: CGRect())
|
||||
|
||||
self.isOpaque = false
|
||||
self.backgroundColor = nil
|
||||
|
||||
self.previousTarget = CGFloat.random(in: 0.0 ... 1.0)
|
||||
self.startNextAnimation()
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
preconditionFailure()
|
||||
}
|
||||
|
||||
func startNextAnimation() {
|
||||
self.animator?.invalidate()
|
||||
|
||||
let previous = self.previousTarget
|
||||
let target = CGFloat.random(in: 0.0 ... 1.0)
|
||||
self.previousTarget = target
|
||||
let animator = DisplayLinkAnimator(duration: 1.0, from: previous, to: target, update: { [weak self] value in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.progress = listViewAnimationCurveEaseInOut(value)
|
||||
strongSelf.setNeedsDisplay()
|
||||
}, completion: { [weak self] in
|
||||
Queue.mainQueue().after(0.3, {
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
|
||||
strongSelf.startNextAnimation()
|
||||
})
|
||||
})
|
||||
self.animator = animator
|
||||
}
|
||||
|
||||
func update(component: ScrollingTooltipAnimationComponent, availableSize: CGSize, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
return CGSize(width: 32.0, height: 32.0)
|
||||
}
|
||||
|
||||
override func draw(_ rect: CGRect) {
|
||||
guard let context = UIGraphicsGetCurrentContext() else {
|
||||
return
|
||||
}
|
||||
|
||||
let progressValue = self.progress
|
||||
|
||||
let itemSize: CGFloat = 12.0
|
||||
let itemSpacing: CGFloat = 1.0
|
||||
let listItemCount: CGFloat = 100.0
|
||||
let listHeight: CGFloat = itemSize * listItemCount + itemSpacing * (listItemCount - 1)
|
||||
|
||||
context.setFillColor(UIColor(white: 1.0, alpha: 0.3).cgColor)
|
||||
|
||||
let offset: CGFloat = progressValue * listHeight
|
||||
|
||||
var minVisibleItemIndex: Int = Int(floor(offset / (itemSize + itemSpacing)))
|
||||
while true {
|
||||
let itemY: CGFloat = CGFloat(minVisibleItemIndex) * (itemSize + itemSpacing) - offset
|
||||
if itemY >= self.bounds.height {
|
||||
break
|
||||
}
|
||||
for i in 0 ..< 2 {
|
||||
UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: CGFloat(i) * (itemSize + itemSpacing), y: itemY), size: CGSize(width: itemSize, height: itemSize)), cornerRadius: 2.0).fill()
|
||||
}
|
||||
minVisibleItemIndex += 1
|
||||
}
|
||||
|
||||
let gradientFraction: CGFloat = 10.0 / self.bounds.height
|
||||
|
||||
let colorsArray: [CGColor] = ([
|
||||
UIColor(white: 1.0, alpha: 1.0),
|
||||
UIColor(white: 1.0, alpha: 0.0),
|
||||
UIColor(white: 1.0, alpha: 0.0),
|
||||
UIColor(white: 1.0, alpha: 1.0)
|
||||
] as [UIColor]).map(\.cgColor)
|
||||
var locations: [CGFloat] = [0.0, gradientFraction, 1.0 - gradientFraction, 1.0]
|
||||
let gradient = CGGradient(colorsSpace: deviceColorSpace, colors: colorsArray as CFArray, locations: &locations)!
|
||||
context.setBlendMode(.destinationOut)
|
||||
|
||||
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: 0.0), end: CGPoint(x: 0.0, y: self.bounds.height), options: [])
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
context.setFillColor(UIColor.white.cgColor)
|
||||
|
||||
let indicatorHeight: CGFloat = 10.0
|
||||
|
||||
let indicatorMinY: CGFloat = 0.0
|
||||
let indicatorMaxY: CGFloat = self.bounds.height - indicatorHeight
|
||||
let indicatorX: CGFloat = (itemSize + itemSpacing) * 2.0
|
||||
let indicatorY = indicatorMinY * (1.0 - progress) + indicatorMaxY * progress
|
||||
UIBezierPath(roundedRect: CGRect(origin: CGPoint(x: indicatorX, y: indicatorY), size: CGSize(width: 3.0, height: indicatorHeight)), cornerRadius: 1.5).fill()
|
||||
|
||||
UIBezierPath(roundedRect: CGRect(x: indicatorX - 4.0 - 19.0, y: indicatorY + (indicatorHeight - 8.0) / 2.0, width: 19.0, height: 8.0), cornerRadius: 4.0).fill()
|
||||
}
|
||||
}
|
||||
|
||||
public func makeView() -> View {
|
||||
return View()
|
||||
}
|
||||
|
||||
public func update(view: View, availableSize: CGSize, environment: Environment<Empty>, transition: Transition) -> CGSize {
|
||||
return view.update(component: self, availableSize: availableSize, environment: environment, transition: transition)
|
||||
}
|
||||
}
|
||||
|
||||
public final class TooltipComponent: Component {
|
||||
public let icon: AnyComponent<Empty>?
|
||||
public let content: AnyComponent<Empty>
|
||||
@ -942,9 +1065,12 @@ public final class SparseItemGridScrollingArea: ASDisplayNode {
|
||||
|
||||
displayTooltip.completed()
|
||||
|
||||
//#if DEBUG
|
||||
//#else
|
||||
Queue.mainQueue().after(2.0, { [weak self] in
|
||||
self?.dismissLineTooltip()
|
||||
})
|
||||
//#endif
|
||||
}
|
||||
|
||||
private func updateLineTooltip(containerSize: CGSize) {
|
||||
@ -958,9 +1084,7 @@ public final class SparseItemGridScrollingArea: ASDisplayNode {
|
||||
transition: .immediate,
|
||||
component: AnyComponent(TooltipComponent(
|
||||
icon: displayTooltip.animation.flatMap { animation in
|
||||
AnyComponent(LottieAnimationComponent(
|
||||
name: animation
|
||||
))
|
||||
AnyComponent(ScrollingTooltipAnimationComponent())
|
||||
},
|
||||
content: AnyComponent(MultilineText(
|
||||
text: displayTooltip.text,
|
||||
|
12
submodules/TelegramUI/Images.xcassets/Chat/GridPlayIcon.imageset/Contents.json
vendored
Normal file
12
submodules/TelegramUI/Images.xcassets/Chat/GridPlayIcon.imageset/Contents.json
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "playsmall.pdf",
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
73
submodules/TelegramUI/Images.xcassets/Chat/GridPlayIcon.imageset/playsmall.pdf
vendored
Normal file
73
submodules/TelegramUI/Images.xcassets/Chat/GridPlayIcon.imageset/playsmall.pdf
vendored
Normal file
@ -0,0 +1,73 @@
|
||||
%PDF-1.7
|
||||
|
||||
1 0 obj
|
||||
<< >>
|
||||
endobj
|
||||
|
||||
2 0 obj
|
||||
<< /Length 3 0 R >>
|
||||
stream
|
||||
/DeviceRGB CS
|
||||
/DeviceRGB cs
|
||||
q
|
||||
1.000000 0.000000 -0.000000 1.000000 0.000000 0.283813 cm
|
||||
1.000000 1.000000 1.000000 scn
|
||||
1.533992 9.134618 m
|
||||
0.868123 9.555166 0.000000 9.076683 0.000000 8.289128 c
|
||||
0.000000 0.717780 l
|
||||
0.000000 -0.069775 0.868124 -0.548255 1.533993 -0.127707 c
|
||||
7.527976 3.657967 l
|
||||
8.149319 4.050394 8.149319 4.956517 7.527976 5.348944 c
|
||||
1.533992 9.134618 l
|
||||
h
|
||||
f*
|
||||
n
|
||||
Q
|
||||
|
||||
endstream
|
||||
endobj
|
||||
|
||||
3 0 obj
|
||||
379
|
||||
endobj
|
||||
|
||||
4 0 obj
|
||||
<< /Annots []
|
||||
/Type /Page
|
||||
/MediaBox [ 0.000000 0.000000 7.994019 9.574585 ]
|
||||
/Resources 1 0 R
|
||||
/Contents 2 0 R
|
||||
/Parent 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
5 0 obj
|
||||
<< /Kids [ 4 0 R ]
|
||||
/Count 1
|
||||
/Type /Pages
|
||||
>>
|
||||
endobj
|
||||
|
||||
6 0 obj
|
||||
<< /Type /Catalog
|
||||
/Pages 5 0 R
|
||||
>>
|
||||
endobj
|
||||
|
||||
xref
|
||||
0 7
|
||||
0000000000 65535 f
|
||||
0000000010 00000 n
|
||||
0000000034 00000 n
|
||||
0000000469 00000 n
|
||||
0000000491 00000 n
|
||||
0000000662 00000 n
|
||||
0000000736 00000 n
|
||||
trailer
|
||||
<< /ID [ (some) (id) ]
|
||||
/Root 6 0 R
|
||||
/Size 7
|
||||
>>
|
||||
startxref
|
||||
795
|
||||
%%EOF
|
@ -21,6 +21,7 @@ import ComponentFlow
|
||||
import TelegramNotices
|
||||
import TelegramUIPreferences
|
||||
import CheckNode
|
||||
import AppBundle
|
||||
|
||||
private final class FrameSequenceThumbnailNode: ASDisplayNode {
|
||||
private let context: AccountContext
|
||||
@ -711,6 +712,19 @@ private struct Month: Equatable {
|
||||
}
|
||||
|
||||
private let durationFont = Font.regular(12.0)
|
||||
private let minDurationImage: UIImage = {
|
||||
let image = generateImage(CGSize(width: 20.0, height: 20.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
context.setFillColor(UIColor(white: 0.0, alpha: 0.5).cgColor)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(), size: size))
|
||||
if let image = UIImage(bundleImageName: "Chat/GridPlayIcon") {
|
||||
UIGraphicsPushContext(context)
|
||||
image.draw(in: CGRect(origin: CGPoint(x: (size.width - image.size.width) / 2.0, y: (size.height - image.size.height) / 2.0), size: image.size))
|
||||
UIGraphicsPopContext()
|
||||
}
|
||||
})
|
||||
return image!
|
||||
}()
|
||||
|
||||
private final class DurationLayer: CALayer {
|
||||
override init() {
|
||||
@ -728,33 +742,38 @@ private final class DurationLayer: CALayer {
|
||||
return nullAction
|
||||
}
|
||||
|
||||
func update(duration: Int32) {
|
||||
let string = NSAttributedString(string: stringForDuration(duration), font: durationFont, textColor: .white)
|
||||
let bounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
let textSize = CGSize(width: ceil(bounds.width), height: ceil(bounds.height))
|
||||
let sideInset: CGFloat = 6.0
|
||||
let verticalInset: CGFloat = 2.0
|
||||
let image = generateImage(CGSize(width: textSize.width + sideInset * 2.0, height: textSize.height + verticalInset * 2.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
func update(duration: Int32, isMin: Bool) {
|
||||
if isMin {
|
||||
self.contents = minDurationImage.cgImage
|
||||
} else {
|
||||
let string = NSAttributedString(string: stringForDuration(duration), font: durationFont, textColor: .white)
|
||||
let bounds = string.boundingRect(with: CGSize(width: 100.0, height: 100.0), options: .usesLineFragmentOrigin, context: nil)
|
||||
let textSize = CGSize(width: ceil(bounds.width), height: ceil(bounds.height))
|
||||
let sideInset: CGFloat = 6.0
|
||||
let verticalInset: CGFloat = 2.0
|
||||
let image = generateImage(CGSize(width: textSize.width + sideInset * 2.0, height: textSize.height + verticalInset * 2.0), rotatedContext: { size, context in
|
||||
context.clear(CGRect(origin: CGPoint(), size: size))
|
||||
|
||||
context.setFillColor(UIColor(white: 0.0, alpha: 0.5).cgColor)
|
||||
context.setBlendMode(.copy)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.height, height: size.height)))
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: size.width - size.height, y: 0.0), size: CGSize(width: size.height, height: size.height)))
|
||||
context.fill(CGRect(origin: CGPoint(x: size.height / 2.0, y: 0.0), size: CGSize(width: size.width - size.height, height: size.height)))
|
||||
context.setFillColor(UIColor(white: 0.0, alpha: 0.5).cgColor)
|
||||
context.setBlendMode(.copy)
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: 0.0, y: 0.0), size: CGSize(width: size.height, height: size.height)))
|
||||
context.fillEllipse(in: CGRect(origin: CGPoint(x: size.width - size.height, y: 0.0), size: CGSize(width: size.height, height: size.height)))
|
||||
context.fill(CGRect(origin: CGPoint(x: size.height / 2.0, y: 0.0), size: CGSize(width: size.width - size.height, height: size.height)))
|
||||
|
||||
context.setBlendMode(.normal)
|
||||
UIGraphicsPushContext(context)
|
||||
string.draw(in: bounds.offsetBy(dx: sideInset, dy: verticalInset))
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
self.contents = image?.cgImage
|
||||
context.setBlendMode(.normal)
|
||||
UIGraphicsPushContext(context)
|
||||
string.draw(in: bounds.offsetBy(dx: sideInset, dy: verticalInset))
|
||||
UIGraphicsPopContext()
|
||||
})
|
||||
self.contents = image?.cgImage
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final class ItemLayer: CALayer, SparseItemGridLayer {
|
||||
var item: VisualMediaItem?
|
||||
var durationLayer: DurationLayer?
|
||||
var minFactor: CGFloat = 1.0
|
||||
var selectionLayer: GridMessageSelectionLayer?
|
||||
var disposable: Disposable?
|
||||
|
||||
@ -782,15 +801,18 @@ private final class ItemLayer: CALayer, SparseItemGridLayer {
|
||||
self.item = item
|
||||
}
|
||||
|
||||
func updateDuration(duration: Int32?) {
|
||||
func updateDuration(duration: Int32?, isMin: Bool, minFactor: CGFloat) {
|
||||
self.minFactor = minFactor
|
||||
|
||||
if let duration = duration {
|
||||
if let durationLayer = self.durationLayer {
|
||||
durationLayer.update(duration: duration)
|
||||
durationLayer.update(duration: duration, isMin: isMin)
|
||||
} else {
|
||||
let durationLayer = DurationLayer()
|
||||
durationLayer.update(duration: duration)
|
||||
durationLayer.update(duration: duration, isMin: isMin)
|
||||
self.addSublayer(durationLayer)
|
||||
durationLayer.frame = CGRect(origin: CGPoint(x: self.bounds.width - 3.0, y: self.bounds.height - 3.0), size: CGSize())
|
||||
durationLayer.transform = CATransform3DMakeScale(minFactor, minFactor, 1.0)
|
||||
}
|
||||
} else if let durationLayer = self.durationLayer {
|
||||
self.durationLayer = nil
|
||||
@ -836,9 +858,9 @@ private final class ItemLayer: CALayer, SparseItemGridLayer {
|
||||
}
|
||||
|
||||
func update(size: CGSize) {
|
||||
if let durationLayer = self.durationLayer {
|
||||
/*if let durationLayer = self.durationLayer {
|
||||
durationLayer.frame = CGRect(origin: CGPoint(x: size.width - 3.0, y: size.height - 3.0), size: CGSize())
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
@ -1001,12 +1023,12 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
|
||||
let context: AccountContext
|
||||
let chatLocation: ChatLocation
|
||||
let directMediaImageCache: DirectMediaImageCache
|
||||
let strings: PresentationStrings
|
||||
var strings: PresentationStrings
|
||||
let useListItems: Bool
|
||||
let listItemInteraction: ListMessageItemInteraction
|
||||
let chatControllerInteraction: ChatControllerInteraction
|
||||
let chatPresentationData: ChatPresentationData
|
||||
let checkNodeTheme: CheckNodeTheme
|
||||
var chatPresentationData: ChatPresentationData
|
||||
var checkNodeTheme: CheckNodeTheme
|
||||
|
||||
var loadHoleImpl: ((SparseItemGrid.HoleAnchor, SparseItemGrid.HoleLocation) -> Signal<Never, NoError>)?
|
||||
var onTapImpl: ((VisualMediaItem) -> Void)?
|
||||
@ -1036,6 +1058,15 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
|
||||
self.checkNodeTheme = CheckNodeTheme(theme: presentationData.theme, style: .overlay, hasInset: true)
|
||||
}
|
||||
|
||||
func updatePresentationData(presentationData: PresentationData) {
|
||||
self.strings = presentationData.strings
|
||||
|
||||
let themeData = ChatPresentationThemeData(theme: presentationData.theme, wallpaper: presentationData.chatWallpaper)
|
||||
self.chatPresentationData = ChatPresentationData(theme: themeData, fontSize: presentationData.chatFontSize, strings: presentationData.strings, dateTimeFormat: presentationData.dateTimeFormat, nameDisplayOrder: presentationData.nameDisplayOrder, disableAnimations: true, largeEmoji: presentationData.largeEmoji, chatBubbleCorners: presentationData.chatBubbleCorners, animatedEmojiScale: 1.0)
|
||||
|
||||
self.checkNodeTheme = CheckNodeTheme(theme: presentationData.theme, style: .overlay, hasInset: true)
|
||||
}
|
||||
|
||||
func getListShimmerImage(height: CGFloat) -> UIImage {
|
||||
if let image = self.shimmerImages[height] {
|
||||
return image
|
||||
@ -1278,10 +1309,12 @@ private final class SparseItemGridBindingImpl: SparseItemGridBinding, ListShimme
|
||||
}
|
||||
|
||||
var duration: Int32?
|
||||
if layer.bounds.width > 80.0, let file = selectedMedia as? TelegramMediaFile, !file.isAnimated {
|
||||
var isMin: Bool = false
|
||||
if let file = selectedMedia as? TelegramMediaFile, !file.isAnimated {
|
||||
duration = file.duration
|
||||
isMin = layer.bounds.width < 80.0
|
||||
}
|
||||
layer.updateDuration(duration: duration)
|
||||
layer.updateDuration(duration: duration, isMin: isMin, minFactor: min(1.0, layer.bounds.height / 74.0))
|
||||
}
|
||||
|
||||
if let selectionState = self.chatControllerInteraction.selectionState {
|
||||
@ -1454,6 +1487,9 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
private var storedStateDisposable: Disposable?
|
||||
|
||||
private weak var currentGestureItem: SparseItemGridDisplayItem?
|
||||
|
||||
private var presentationData: PresentationData
|
||||
private var presentationDataDisposable: Disposable?
|
||||
|
||||
init(context: AccountContext, chatControllerInteraction: ChatControllerInteraction, peerId: PeerId, contentType: ContentType) {
|
||||
self.context = context
|
||||
@ -1463,8 +1499,10 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
self.contentTypePromise = ValuePromise<ContentType>(contentType)
|
||||
self.stateTag = tagMaskForType(contentType)
|
||||
|
||||
self.presentationData = self.context.sharedContext.currentPresentationData.with { $0 }
|
||||
|
||||
self.contextGestureContainerNode = ContextControllerSourceNode()
|
||||
self.itemGrid = SparseItemGrid(theme: self.context.sharedContext.currentPresentationData.with({ $0 }).theme)
|
||||
self.itemGrid = SparseItemGrid(theme: self.presentationData.theme)
|
||||
self.directMediaImageCache = DirectMediaImageCache(account: context.account)
|
||||
|
||||
let useListItems: Bool
|
||||
@ -1926,12 +1964,40 @@ final class PeerInfoVisualMediaPaneNode: ASDisplayNode, PeerInfoPaneNode, UIScro
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
self.presentationDataDisposable = (self.context.sharedContext.presentationData
|
||||
|> deliverOnMainQueue).start(next: { [weak self] presentationData in
|
||||
guard let strongSelf = self else {
|
||||
return
|
||||
}
|
||||
strongSelf.itemGridBinding.updatePresentationData(presentationData: presentationData)
|
||||
|
||||
strongSelf.itemGrid.updatePresentationData(theme: presentationData.theme)
|
||||
|
||||
strongSelf.itemGrid.forEachVisibleItem { item in
|
||||
guard let itemView = item.view as? ItemView else {
|
||||
return
|
||||
}
|
||||
if let item = itemView.item {
|
||||
itemView.bind(
|
||||
item: item,
|
||||
presentationData: strongSelf.itemGridBinding.chatPresentationData,
|
||||
context: strongSelf.itemGridBinding.context,
|
||||
chatLocation: strongSelf.itemGridBinding.chatLocation,
|
||||
interaction: strongSelf.itemGridBinding.listItemInteraction,
|
||||
isSelected: strongSelf.chatControllerInteraction.selectionState?.selectedIds.contains(item.message.id),
|
||||
size: itemView.bounds.size
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.listDisposable.dispose()
|
||||
self.hiddenMediaDisposable?.dispose()
|
||||
self.animationTimer?.invalidate()
|
||||
self.presentationDataDisposable?.dispose()
|
||||
}
|
||||
|
||||
func loadHole(anchor: SparseItemGrid.HoleAnchor, at location: SparseItemGrid.HoleLocation) -> Signal<Never, NoError> {
|
||||
|
Loading…
x
Reference in New Issue
Block a user