Files
divkit/client/ios/DivKit/Extensions/DivImage/ImageWithPreviewHolder.swift
T
denlvovich eb2d74a2ad Fixed animation playback in previews
commit_hash:69c341b10b73be941dcf5502b9efcc56a9ebe371
2026-02-25 02:12:24 +03:00

72 lines
1.9 KiB
Swift

import Foundation
import VGSL
final class ImageWithPreviewHolder: ImageHolder {
private let mainHolder: ImageHolder
private let previewHolder: ImageHolder
var image: Image? { mainHolder.image ?? previewHolder.image?.firstFrame }
var placeholder: ImagePlaceholder? { mainHolder.placeholder }
var debugDescription: String {
"ImageWithPreviewHolder(main: \(mainHolder), preview: \(previewHolder))"
}
init(mainHolder: ImageHolder, previewHolder: ImageHolder) {
self.mainHolder = mainHolder
self.previewHolder = previewHolder
}
func requestImageWithCompletion(_ completion: @escaping @MainActor (Image?) -> Void)
-> Cancellable? {
var mainLoaded = false
let previewCancellable = previewHolder.requestImageWithCompletion { image in
if !mainLoaded, let image {
completion(image.firstFrame)
}
}
let mainCancellable = mainHolder.requestImageWithCompletion { image in
mainLoaded = true
previewCancellable?.cancel()
completion(image)
}
return CompositeCancellable([previewCancellable, mainCancellable])
}
func reused(with placeholder: ImagePlaceholder?, remoteImageURL: URL?) -> ImageHolder? {
mainHolder.reused(with: placeholder, remoteImageURL: remoteImageURL) != nil ? self : nil
}
func equals(_ other: ImageHolder) -> Bool {
guard let other = other as? ImageWithPreviewHolder else { return false }
return mainHolder.equals(other.mainHolder) && previewHolder.equals(other.previewHolder)
}
}
#if os(iOS)
extension Image {
fileprivate var firstFrame: Image {
images?.first ?? self
}
}
#else
extension Image {
fileprivate var firstFrame: Image { self }
}
#endif
private final class CompositeCancellable: Cancellable {
private let cancellables: [Cancellable]
init(_ cancellables: [Cancellable?]) {
self.cancellables = cancellables.compactMap { $0 }
}
func cancel() {
cancellables.forEach { $0.cancel() }
}
}