Add support for WebImage to use indicator. Using protocol and struct based solution, and with SwiftUI Binding for isAnimating and progress
This commit is contained in:
parent
cbe282b69c
commit
6a2eb0264a
|
@ -11,7 +11,7 @@ PODS:
|
||||||
- SDWebImage (5.2.3):
|
- SDWebImage (5.2.3):
|
||||||
- SDWebImage/Core (= 5.2.3)
|
- SDWebImage/Core (= 5.2.3)
|
||||||
- SDWebImage/Core (5.2.3)
|
- SDWebImage/Core (5.2.3)
|
||||||
- SDWebImageSwiftUI (0.4.1):
|
- SDWebImageSwiftUI (0.4.2):
|
||||||
- SDWebImage (~> 5.1)
|
- SDWebImage (~> 5.1)
|
||||||
- SDWebImageWebPCoder (0.2.5):
|
- SDWebImageWebPCoder (0.2.5):
|
||||||
- libwebp (~> 1.0)
|
- libwebp (~> 1.0)
|
||||||
|
@ -34,7 +34,7 @@ EXTERNAL SOURCES:
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e
|
libwebp: 057912d6d0abfb6357d8bb05c0ea470301f5d61e
|
||||||
SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce
|
SDWebImage: 46a7f73228f84ce80990c786e4372cf4db5875ce
|
||||||
SDWebImageSwiftUI: 15eeed7470ba9cd64fa7e8dddd62e12df58d07f3
|
SDWebImageSwiftUI: b91be76ecb0cdf74c18f6cd92aae8f19a9ded02d
|
||||||
SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987
|
SDWebImageWebPCoder: 947093edd1349d820c40afbd9f42acb6cdecd987
|
||||||
|
|
||||||
PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a
|
PODFILE CHECKSUM: 3fb06a5173225e197f3a4bf2be7e5586a693257a
|
||||||
|
|
|
@ -81,11 +81,16 @@ struct ContentView: View {
|
||||||
HStack {
|
HStack {
|
||||||
if self.animated {
|
if self.animated {
|
||||||
AnimatedImage(url: URL(string:url))
|
AnimatedImage(url: URL(string:url))
|
||||||
|
.indicator(SDWebImageActivityIndicator.medium)
|
||||||
|
.transition(.fade)
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
|
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
|
||||||
} else {
|
} else {
|
||||||
WebImage(url: URL(string:url))
|
WebImage(url: URL(string:url))
|
||||||
|
.indicator { isAnimating, _ in
|
||||||
|
ActivityIndicator(isAnimating)
|
||||||
|
}
|
||||||
.resizable()
|
.resizable()
|
||||||
.scaledToFit()
|
.scaledToFit()
|
||||||
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
|
.frame(width: CGFloat(100), height: CGFloat(100), alignment: .center)
|
||||||
|
|
|
@ -15,6 +15,14 @@
|
||||||
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
||||||
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
||||||
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */ = {isa = PBXBuildFile; fileRef = 324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */; };
|
||||||
|
326B84822363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
|
||||||
|
326B84832363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
|
||||||
|
326B84842363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
|
||||||
|
326B84852363350C0011BDFB /* Indicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B84812363350C0011BDFB /* Indicator.swift */; };
|
||||||
|
326B8487236335110011BDFB /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B8486236335110011BDFB /* ActivityIndicator.swift */; };
|
||||||
|
326B8488236335110011BDFB /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B8486236335110011BDFB /* ActivityIndicator.swift */; };
|
||||||
|
326B8489236335110011BDFB /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B8486236335110011BDFB /* ActivityIndicator.swift */; };
|
||||||
|
326B848A236335110011BDFB /* ActivityIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326B8486236335110011BDFB /* ActivityIndicator.swift */; };
|
||||||
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
||||||
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
||||||
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 326E480923431C0F00C633E9 /* ImageViewWrapper.swift */; };
|
||||||
|
@ -99,6 +107,8 @@
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = "<group>"; };
|
324F61C5235E07EC003973B8 /* SDAnimatedImageInterface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SDAnimatedImageInterface.h; sourceTree = "<group>"; };
|
||||||
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = "<group>"; };
|
324F61C6235E07EC003973B8 /* SDAnimatedImageInterface.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SDAnimatedImageInterface.m; sourceTree = "<group>"; };
|
||||||
|
326B84812363350C0011BDFB /* Indicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Indicator.swift; sourceTree = "<group>"; };
|
||||||
|
326B8486236335110011BDFB /* ActivityIndicator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicator.swift; sourceTree = "<group>"; };
|
||||||
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
|
326E480923431C0F00C633E9 /* ImageViewWrapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ImageViewWrapper.swift; sourceTree = "<group>"; };
|
||||||
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
32C43DCC22FD540D00BE87F5 /* SDWebImageSwiftUI.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SDWebImageSwiftUI.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
|
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ImageManager.swift; sourceTree = "<group>"; };
|
||||||
|
@ -161,6 +171,15 @@
|
||||||
path = ObjC;
|
path = ObjC;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
326099472362E09E006EBB22 /* Indicator */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
326B84812363350C0011BDFB /* Indicator.swift */,
|
||||||
|
326B8486236335110011BDFB /* ActivityIndicator.swift */,
|
||||||
|
);
|
||||||
|
path = Indicator;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
32C43DC222FD540D00BE87F5 = {
|
32C43DC222FD540D00BE87F5 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -194,6 +213,7 @@
|
||||||
32C43DDB22FD54C600BE87F5 /* Classes */ = {
|
32C43DDB22FD54C600BE87F5 /* Classes */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
326099472362E09E006EBB22 /* Indicator */,
|
||||||
324F61C4235E07EC003973B8 /* ObjC */,
|
324F61C4235E07EC003973B8 /* ObjC */,
|
||||||
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
|
32C43DDC22FD54C600BE87F5 /* ImageManager.swift */,
|
||||||
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
|
32C43DDE22FD54C600BE87F5 /* WebImage.swift */,
|
||||||
|
@ -418,8 +438,10 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
|
32C43E1722FD583700BE87F5 /* WebImage.swift in Sources */,
|
||||||
|
326B84822363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
32C43E3222FD5DE100BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
32C43E3222FD5DE100BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
||||||
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
326E480A23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
||||||
|
326B8487236335110011BDFB /* ActivityIndicator.swift in Sources */,
|
||||||
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */,
|
32C43E1622FD583700BE87F5 /* ImageManager.swift in Sources */,
|
||||||
32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */,
|
32C43E1822FD583700BE87F5 /* AnimatedImage.swift in Sources */,
|
||||||
324F61CB235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
324F61CB235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
||||||
|
@ -431,8 +453,10 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
|
32C43E1A22FD583700BE87F5 /* WebImage.swift in Sources */,
|
||||||
|
326B84832363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
32C43E3322FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
||||||
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
326E480B23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
||||||
|
326B8488236335110011BDFB /* ActivityIndicator.swift in Sources */,
|
||||||
32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */,
|
32C43E1922FD583700BE87F5 /* ImageManager.swift in Sources */,
|
||||||
32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */,
|
32C43E1B22FD583700BE87F5 /* AnimatedImage.swift in Sources */,
|
||||||
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
324F61CC235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
||||||
|
@ -444,8 +468,10 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
|
32C43E1D22FD583800BE87F5 /* WebImage.swift in Sources */,
|
||||||
|
326B84842363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
32C43E3422FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
32C43E3422FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
||||||
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
326E480C23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
||||||
|
326B8489236335110011BDFB /* ActivityIndicator.swift in Sources */,
|
||||||
32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */,
|
32C43E1C22FD583800BE87F5 /* ImageManager.swift in Sources */,
|
||||||
32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */,
|
32C43E1E22FD583800BE87F5 /* AnimatedImage.swift in Sources */,
|
||||||
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
324F61CD235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
||||||
|
@ -457,8 +483,10 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
|
32C43E2022FD583800BE87F5 /* WebImage.swift in Sources */,
|
||||||
|
326B84852363350C0011BDFB /* Indicator.swift in Sources */,
|
||||||
32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
32C43E3522FD5DF400BE87F5 /* SDWebImageSwiftUI.swift in Sources */,
|
||||||
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
326E480D23431C0F00C633E9 /* ImageViewWrapper.swift in Sources */,
|
||||||
|
326B848A236335110011BDFB /* ActivityIndicator.swift in Sources */,
|
||||||
32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */,
|
32C43E1F22FD583800BE87F5 /* ImageManager.swift in Sources */,
|
||||||
32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */,
|
32C43E2122FD583800BE87F5 /* AnimatedImage.swift in Sources */,
|
||||||
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
324F61CE235E07EC003973B8 /* SDAnimatedImageInterface.m in Sources */,
|
||||||
|
|
|
@ -11,6 +11,8 @@ import SDWebImage
|
||||||
|
|
||||||
class ImageManager : ObservableObject {
|
class ImageManager : ObservableObject {
|
||||||
@Published var image: PlatformImage?
|
@Published var image: PlatformImage?
|
||||||
|
@Published var isLoading: Bool = false
|
||||||
|
@Published var progress: CGFloat = 0
|
||||||
|
|
||||||
var manager = SDWebImageManager.shared
|
var manager = SDWebImageManager.shared
|
||||||
weak var currentOperation: SDWebImageOperation? = nil
|
weak var currentOperation: SDWebImageOperation? = nil
|
||||||
|
@ -32,8 +34,21 @@ class ImageManager : ObservableObject {
|
||||||
if currentOperation != nil {
|
if currentOperation != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
self.isLoading = true
|
||||||
currentOperation = manager.loadImage(with: url, options: options, context: context, progress: { [weak self] (receivedSize, expectedSize, _) in
|
currentOperation = manager.loadImage(with: url, options: options, context: context, progress: { [weak self] (receivedSize, expectedSize, _) in
|
||||||
self?.progressBlock?(receivedSize, expectedSize)
|
guard let self = self else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.progressBlock?(receivedSize, expectedSize)
|
||||||
|
let progress: CGFloat
|
||||||
|
if (expectedSize > 0) {
|
||||||
|
progress = CGFloat(receivedSize) / CGFloat(expectedSize)
|
||||||
|
} else {
|
||||||
|
progress = 0
|
||||||
|
}
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.progress = progress
|
||||||
|
}
|
||||||
}) { [weak self] (image, data, error, cacheType, finished, _) in
|
}) { [weak self] (image, data, error, cacheType, finished, _) in
|
||||||
guard let self = self else {
|
guard let self = self else {
|
||||||
return
|
return
|
||||||
|
@ -42,6 +57,7 @@ class ImageManager : ObservableObject {
|
||||||
self.image = image
|
self.image = image
|
||||||
}
|
}
|
||||||
if finished {
|
if finished {
|
||||||
|
self.isLoading = false
|
||||||
if let image = image {
|
if let image = image {
|
||||||
self.successBlock?(image, cacheType)
|
self.successBlock?(image, cacheType)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the SDWebImage package.
|
||||||
|
* (c) DreamPiggy <lizhuoli1126@126.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Swift
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public struct ActivityIndicator: PlatformViewRepresentable {
|
||||||
|
@Binding var isAnimating: Bool
|
||||||
|
|
||||||
|
public init(_ isAnimating: Binding<Bool> = .constant(true)) {
|
||||||
|
self._isAnimating = isAnimating
|
||||||
|
}
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
public typealias NSViewType = NSProgressIndicator
|
||||||
|
#elseif os(iOS) || os(tvOS)
|
||||||
|
public typealias UIViewType = UIActivityIndicatorView
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(iOS) || os(tvOS)
|
||||||
|
public func makeUIView(context: UIViewRepresentableContext<ActivityIndicator>) -> UIActivityIndicatorView {
|
||||||
|
let indicator = UIActivityIndicatorView(style: .medium)
|
||||||
|
indicator.hidesWhenStopped = true
|
||||||
|
return indicator
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateUIView(_ uiView: UIActivityIndicatorView, context: UIViewRepresentableContext<ActivityIndicator>) {
|
||||||
|
isAnimating ? uiView.startAnimating() : uiView.stopAnimating()
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if os(macOS)
|
||||||
|
public func makeNSView(context: NSViewRepresentableContext<ActivityIndicator>) -> NSProgressIndicator {
|
||||||
|
let indicator = NSProgressIndicator()
|
||||||
|
indicator.style = .spinning
|
||||||
|
indicator.isDisplayedWhenStopped = false
|
||||||
|
return indicator
|
||||||
|
}
|
||||||
|
|
||||||
|
public func updateNSView(_ nsView: NSProgressIndicator, context: NSViewRepresentableContext<ActivityIndicator>) {
|
||||||
|
isAnimating ? nsView.startAnimation(nil) : nsView.stopAnimation(nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the SDWebImage package.
|
||||||
|
* (c) DreamPiggy <lizhuoli1126@126.com>
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
public struct Indicator : View {
|
||||||
|
var builder: (Binding<Bool>, Binding<CGFloat>) -> AnyView
|
||||||
|
public typealias Body = Never
|
||||||
|
public var body: Never {
|
||||||
|
fatalError()
|
||||||
|
}
|
||||||
|
public init<T>(@ViewBuilder builder: @escaping (_ isAnimating: Binding<Bool>, _ progress: Binding<CGFloat>) -> T) where T : View {
|
||||||
|
self.builder = { isAnimating, progress in
|
||||||
|
AnyView(builder(isAnimating, progress))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,8 +16,11 @@ public struct WebImage : View {
|
||||||
var context: [SDWebImageContextOption : Any]?
|
var context: [SDWebImageContextOption : Any]?
|
||||||
|
|
||||||
var configurations: [(Image) -> Image] = []
|
var configurations: [(Image) -> Image] = []
|
||||||
|
var indicator: Indicator?
|
||||||
|
|
||||||
@ObservedObject var imageManager: ImageManager
|
@ObservedObject var imageManager: ImageManager
|
||||||
|
@State var progress: CGFloat = 0
|
||||||
|
@State var isLoading: Bool = false
|
||||||
|
|
||||||
/// Create a web image with url, placeholder, custom options and context.
|
/// Create a web image with url, placeholder, custom options and context.
|
||||||
/// - Parameter url: The image url
|
/// - Parameter url: The image url
|
||||||
|
@ -46,7 +49,7 @@ public struct WebImage : View {
|
||||||
// this can ensure we load the image, SDWebImage take care of the duplicated query
|
// this can ensure we load the image, SDWebImage take care of the duplicated query
|
||||||
self.imageManager.load()
|
self.imageManager.load()
|
||||||
}
|
}
|
||||||
return configurations.reduce(image) { (previous, configuration) in
|
let view = configurations.reduce(image) { (previous, configuration) in
|
||||||
configuration(previous)
|
configuration(previous)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
|
@ -57,6 +60,19 @@ public struct WebImage : View {
|
||||||
.onDisappear {
|
.onDisappear {
|
||||||
self.imageManager.cancel()
|
self.imageManager.cancel()
|
||||||
}
|
}
|
||||||
|
// Convert Combine.Publisher to Binding, I think this need a better API from Apple :)
|
||||||
|
.onReceive(imageManager.$isLoading) { self.isLoading = $0 }
|
||||||
|
.onReceive(imageManager.$progress) { self.progress = $0 }
|
||||||
|
if let indicator = indicator {
|
||||||
|
return AnyView(
|
||||||
|
ZStack {
|
||||||
|
view
|
||||||
|
indicator.builder($isLoading, $progress)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return AnyView(view)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +144,19 @@ extension WebImage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension WebImage {
|
||||||
|
|
||||||
|
/// Associate a indicator when loading image with url
|
||||||
|
/// - Parameter builder: builder description
|
||||||
|
/// - Parameter isAnimating: A Binding to control the animation. If image is loading, the value is true, else false.
|
||||||
|
/// - Parameter progress: A Binding to control the progress during loading. If no progress can be reported, the value is 0.
|
||||||
|
public func indicator<T>(_ builder: @escaping (_ isAnimating: Binding<Bool>, _ progress: Binding<CGFloat>) -> T) -> WebImage where T : View {
|
||||||
|
var result = self
|
||||||
|
result.indicator = Indicator(builder: builder)
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
struct WebImage_Previews : PreviewProvider {
|
struct WebImage_Previews : PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
|
|
Loading…
Reference in New Issue