Merge pull request #91 from SDWebImage/feature_delayPlaceholder_webimage

Supports the `delayPlaceholder` for WebImage
This commit is contained in:
DreamPiggy 2020-03-29 21:28:13 +08:00 committed by GitHub
commit 42fdca6753
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 107 additions and 38 deletions

View File

@ -0,0 +1,24 @@
{
"images" : [
{
"filename" : "wifi.exclamationmark.svg",
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="56" height="56" viewBox="0 0 56 56"><path d="M 28.0234 37.5039 C 29.2656 37.5039 30.1093 36.6836 30.1327 35.3945 C 30.2031 26.7695 30.2734 18.0976 30.3437 9.4492 C 30.3437 8.1133 29.2656 7.1992 27.9999 7.1992 C 26.7343 7.1992 25.6562 8.1133 25.6562 9.4492 C 25.7499 18.0976 25.8203 26.7695 25.9140 35.3945 C 25.9374 36.6836 26.7812 37.5039 28.0234 37.5039 Z M 5.4531 26.3711 C 5.8984 26.8164 6.5546 26.7930 6.9765 26.3477 C 11.2890 21.7539 16.7031 18.8711 22.7499 17.8398 L 22.6562 11.0195 C 14.3124 12.3320 6.7656 16.5976 2.2890 21.9179 C 1.9609 22.2930 1.9843 22.8086 2.3593 23.2070 Z M 49.0702 26.3711 C 49.4686 26.7695 50.1017 26.7695 50.5702 26.3008 L 53.6407 23.2070 C 54.0391 22.8086 54.0391 22.2930 53.7108 21.9179 C 49.2343 16.5976 41.6874 12.3320 33.3437 11.0430 L 33.2734 17.8633 C 39.2968 18.9414 44.6640 21.8711 49.0702 26.3711 Z M 14.8281 35.7695 C 15.2968 36.2617 15.9062 36.2148 16.3515 35.6992 C 18.0390 33.8477 20.3359 32.3477 22.8905 31.4570 L 22.7968 24.3555 C 17.9687 25.4336 13.8437 27.9883 11.2656 31.0352 C 10.9140 31.4336 10.9609 31.9023 11.3359 32.3008 Z M 39.6952 35.7695 C 40.1405 36.2383 40.7031 36.2148 41.1952 35.7227 L 44.6640 32.3008 C 45.0390 31.9258 45.0859 31.4336 44.7343 31.0352 C 42.1562 27.9883 38.0312 25.4336 33.2265 24.3555 L 33.1562 31.5039 C 35.7109 32.4179 38.0078 33.9414 39.6952 35.7695 Z M 27.9999 48.8008 C 29.9921 48.8008 31.5624 47.1836 31.5624 45.2148 C 31.5624 43.2227 29.9921 41.6523 27.9999 41.6523 C 26.0312 41.6523 24.4140 43.2227 24.4140 45.2148 C 24.4140 47.1836 26.0312 48.8008 27.9999 48.8008 Z"/></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -22,7 +22,7 @@ class UserSettings: ObservableObject {
// watchOS does not provide built-in indicator, use Espera's custom indicator
extension Indicator where T == LoadingFlowerView {
/// Activity Indicator
public static var activity: Indicator {
static var activity: Indicator {
Indicator { isAnimating, _ in
LoadingFlowerView()
}
@ -31,7 +31,7 @@ extension Indicator where T == LoadingFlowerView {
extension Indicator where T == StretchProgressView {
/// Progress Indicator
public static var progress: Indicator {
static var progress: Indicator {
Indicator { isAnimating, progress in
StretchProgressView(progress: progress)
}

View File

@ -9,6 +9,31 @@
import SwiftUI
import SDWebImageSwiftUI
// Placeholder when image load failed (with `.delayPlaceholder`)
#if !os(watchOS)
extension PlatformImage {
static var wifiExclamationmark: PlatformImage {
#if os(macOS)
return PlatformImage(named: "wifi.exclamationmark")!
#else
return PlatformImage(systemName: "wifi.exclamationmark")!.withTintColor(.label, renderingMode: .alwaysOriginal)
#endif
}
}
#endif
extension Image {
static var wifiExclamationmark: Image {
#if os(macOS)
return Image("wifi.exclamationmark")
.resizable()
#else
return Image(systemName: "wifi.exclamationmark")
.resizable()
#endif
}
}
struct DetailView: View {
let url: String
let animated: Bool
@ -86,19 +111,22 @@ struct DetailView: View {
HStack {
if animated {
#if os(macOS) || os(iOS) || os(tvOS)
AnimatedImage(url: URL(string:url), options: [.progressiveLoad], isAnimating: $isAnimating)
.indicator(SDWebImageProgressIndicator.default)
AnimatedImage(url: URL(string:url), options: [.progressiveLoad, .delayPlaceholder], isAnimating: $isAnimating)
.resizable()
.placeholder(.wifiExclamationmark)
.indicator(SDWebImageProgressIndicator.default)
.scaledToFit()
#else
WebImage(url: URL(string:url), options: [.progressiveLoad], isAnimating: $isAnimating)
WebImage(url: URL(string:url), options: [.progressiveLoad, .delayPlaceholder], isAnimating: $isAnimating)
.resizable()
.placeholder(.wifiExclamationmark)
.indicator(.progress)
.scaledToFit()
#endif
} else {
WebImage(url: URL(string:url), options: [.progressiveLoad])
WebImage(url: URL(string:url), options: [.progressiveLoad, .delayPlaceholder])
.resizable()
.placeholder(.wifiExclamationmark)
.indicator(.progress)
.scaledToFit()
}

View File

@ -110,6 +110,7 @@ let package = Package(
```swift
var body: some View {
WebImage(url: URL(string: "https://nokiatech.github.io/heif/content/images/ski_jump_1440x960.heic"))
// Supports options and context, like `.delayPlaceholder` to show placeholder only when error
.onSuccess { image, cacheType in
// Success
}
@ -155,8 +156,8 @@ var body: some View {
```swift
var body: some View {
Group {
// Network
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"), options: [.progressiveLoad]) // Progressive Load
AnimatedImage(url: URL(string: "https://raw.githubusercontent.com/liyong03/YLGIFImage/master/YLGIFImageDemo/YLGIFImageDemo/joy.gif"))
// Supports options and context, like `.progressiveLoad` for progressive animation loading
.onFailure { error in
// Error
}
@ -187,11 +188,13 @@ Note: `AnimatedImage` supports both image url or image data for animated image f
Note: `AnimatedImage` some methods like `.transition`, `.indicator` and `.aspectRatio` have the same naming as `SwiftUI.View` protocol methods. But the args receive the different type. This is because `AnimatedImage` supports to be used with UIKit/AppKit component and animation. If you find ambiguity, use full type declaration instead of the dot expression syntax.
```swift
AnimatedImage(name: "animation2") // Just for showcase, don't mix them at the same time
var body: some View {
AnimatedImage(name: "animation2") // Just for showcase, don't mix them at the same time
.indicator(SDWebImageProgressIndicator.default) // UIKit indicator component
.indicator(Indicator.progress) // SwiftUI indicator component
.transition(SDWebImageTransition.flipFromLeft) // UIKit animation transition
.transition(AnyTransition.flipFromLeft) // SwiftUI animation transition
}
```
### Which View to choose

View File

@ -106,17 +106,7 @@ public struct WebImage : View {
}
}
} else {
Group {
if placeholder != nil {
placeholder
} else {
// Should not use `EmptyView`, which does not respect to the container's frame modifier
// Using a empty image instead for better compatible
configurations.reduce(Image.empty) { (previous, configuration) in
configuration(previous)
}
}
}
setupPlaceholder()
.frame(minWidth: 0, maxWidth: .infinity, minHeight: 0, maxHeight: .infinity)
.onAppear {
guard self.retryOnAppear else { return }
@ -136,6 +126,29 @@ public struct WebImage : View {
}
}
func configure(image: Image) -> some View {
// Should not use `EmptyView`, which does not respect to the container's frame modifier
// Using a empty image instead for better compatible
configurations.reduce(image) { (previous, configuration) in
configuration(previous)
}
}
/// Placeholder View Support
func setupPlaceholder() -> some View {
// Don't use `Group` because it will trigger `.onAppear` and `.onDisappear` when condition view removed, treat placeholder as an entire component
if let placeholder = placeholder {
// If use `.delayPlaceholder`, the placeholder is applied after loading failed, hide during loading :)
if imageManager.options.contains(.delayPlaceholder) && imageManager.isLoading {
return AnyView(configure(image: Image.empty))
} else {
return placeholder
}
} else {
return AnyView(configure(image: Image.empty))
}
}
/// Animated Image Support
func setupPlayer(image: PlatformImage?) {
if imagePlayer != nil {