|
|
@@ -34,56 +34,28 @@ extension KFImage {
|
|
|
/// Represents a binder for `KFImage`. It takes responsibility as an `ObjectBinding` and performs
|
|
|
/// image downloading and progress reporting based on `KingfisherManager`.
|
|
|
class ImageBinder: ObservableObject {
|
|
|
-
|
|
|
- let source: Source?
|
|
|
- var options = KingfisherParsedOptionsInfo(KingfisherManager.shared.defaultOptions)
|
|
|
+
|
|
|
+ init() {
|
|
|
+ isLoaded = .constant(false)
|
|
|
+ }
|
|
|
|
|
|
var downloadTask: DownloadTask?
|
|
|
|
|
|
var loadingOrSucceeded: Bool {
|
|
|
return downloadTask != nil || loadedImage != nil
|
|
|
}
|
|
|
-
|
|
|
- let onFailureDelegate = Delegate<KingfisherError, Void>()
|
|
|
- let onSuccessDelegate = Delegate<RetrieveImageResult, Void>()
|
|
|
- let onProgressDelegate = Delegate<(Int64, Int64), Void>()
|
|
|
-
|
|
|
var isLoaded: Binding<Bool>
|
|
|
|
|
|
@Published var loaded = false
|
|
|
@Published var loadedImage: KFCrossPlatformImage? = nil
|
|
|
|
|
|
- @available(*, deprecated, message: "The `options` version is deprecated And will be removed soon.")
|
|
|
- init(source: Source?, options: KingfisherOptionsInfo? = nil, isLoaded: Binding<Bool>) {
|
|
|
- self.source = source
|
|
|
- // The refreshing of `KFImage` would happen much more frequently then an `UIImageView`, even as a
|
|
|
- // "side-effect". To prevent unintended flickering, add `.loadDiskFileSynchronously` as a default.
|
|
|
- self.options = KingfisherParsedOptionsInfo(
|
|
|
- KingfisherManager.shared.defaultOptions +
|
|
|
- (options ?? []) +
|
|
|
- [.loadDiskFileSynchronously]
|
|
|
- )
|
|
|
- self.isLoaded = isLoaded
|
|
|
- }
|
|
|
-
|
|
|
- init(source: Source?, isLoaded: Binding<Bool>) {
|
|
|
- self.source = source
|
|
|
- // The refreshing of `KFImage` would happen much more frequently then an `UIImageView`, even as a
|
|
|
- // "side-effect". To prevent unintended flickering, add `.loadDiskFileSynchronously` as a default.
|
|
|
- self.options = KingfisherParsedOptionsInfo(
|
|
|
- KingfisherManager.shared.defaultOptions +
|
|
|
- [.loadDiskFileSynchronously]
|
|
|
- )
|
|
|
- self.isLoaded = isLoaded
|
|
|
- }
|
|
|
-
|
|
|
- func start() {
|
|
|
+ func start<HoldingView: KFImageHoldingView>(context: Context<HoldingView>) {
|
|
|
|
|
|
guard !loadingOrSucceeded else { return }
|
|
|
|
|
|
- guard let source = source else {
|
|
|
+ guard let source = context.source else {
|
|
|
CallbackQueue.mainCurrentOrAsync.execute {
|
|
|
- self.onFailureDelegate.call(KingfisherError.imageSettingError(reason: .emptySource))
|
|
|
+ context.onFailureDelegate.call(KingfisherError.imageSettingError(reason: .emptySource))
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
@@ -91,9 +63,9 @@ extension KFImage {
|
|
|
downloadTask = KingfisherManager.shared
|
|
|
.retrieveImage(
|
|
|
with: source,
|
|
|
- options: options,
|
|
|
+ options: context.options,
|
|
|
progressBlock: { size, total in
|
|
|
- self.onProgressDelegate.call((size, total))
|
|
|
+ context.onProgressDelegate.call((size, total))
|
|
|
},
|
|
|
completionHandler: { [weak self] result in
|
|
|
|
|
|
@@ -106,17 +78,17 @@ extension KFImage {
|
|
|
CallbackQueue.mainCurrentOrAsync.execute {
|
|
|
self.loadedImage = value.image
|
|
|
self.isLoaded.wrappedValue = true
|
|
|
- let animation = self.fadeTransitionDuration(cacheType: value.cacheType)
|
|
|
+ let animation = context.fadeTransitionDuration(cacheType: value.cacheType)
|
|
|
.map { duration in Animation.linear(duration: duration) }
|
|
|
withAnimation(animation) { self.loaded = true }
|
|
|
}
|
|
|
|
|
|
CallbackQueue.mainAsync.execute {
|
|
|
- self.onSuccessDelegate.call(value)
|
|
|
+ context.onSuccessDelegate.call(value)
|
|
|
}
|
|
|
case .failure(let error):
|
|
|
CallbackQueue.mainAsync.execute {
|
|
|
- self.onFailureDelegate.call(error)
|
|
|
+ context.onFailureDelegate.call(error)
|
|
|
}
|
|
|
}
|
|
|
})
|
|
|
@@ -127,40 +99,6 @@ extension KFImage {
|
|
|
downloadTask?.cancel()
|
|
|
downloadTask = nil
|
|
|
}
|
|
|
-
|
|
|
- private func shouldApplyFade(cacheType: CacheType) -> Bool {
|
|
|
- options.forceTransition || cacheType == .none
|
|
|
- }
|
|
|
-
|
|
|
- private func fadeTransitionDuration(cacheType: CacheType) -> TimeInterval? {
|
|
|
- shouldApplyFade(cacheType: cacheType)
|
|
|
- ? options.transition.fadeDuration
|
|
|
- : nil
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *)
|
|
|
-extension KFImage.ImageBinder: Hashable {
|
|
|
- static func == (lhs: KFImage.ImageBinder, rhs: KFImage.ImageBinder) -> Bool {
|
|
|
- lhs.source == rhs.source && lhs.options.processor.identifier == rhs.options.processor.identifier
|
|
|
- }
|
|
|
-
|
|
|
- func hash(into hasher: inout Hasher) {
|
|
|
- hasher.combine(source)
|
|
|
- hasher.combine(options.processor.identifier)
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-extension ImageTransition {
|
|
|
- // Only for fade effect in SwiftUI.
|
|
|
- fileprivate var fadeDuration: TimeInterval? {
|
|
|
- switch self {
|
|
|
- case .fade(let duration):
|
|
|
- return duration
|
|
|
- default:
|
|
|
- return nil
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
#endif
|