Skip to content

Commit 0db4595

Browse files
authored
feat: add tiny fix for Demo. Add LoadingOpacityEdge and change lowerBound opacity in loading state. Add new state reloading to Status. (#8)
1 parent ee92a1d commit 0db4595

File tree

5 files changed

+158
-15
lines changed

5 files changed

+158
-15
lines changed

Example/Example/DefaultContentView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@ import SwiftUI
22

33
struct DefaultContentView: View {
44

5-
@State private var url = URL(string: "https://via.placeholder.com/1000")
5+
@State private var url = URL(string: "https://picsum.photos/1000")
66
@State private var size: CGSize = .init(width: 160, height: 160)
77

88
var body: some View {
99
VStack {
10+
Text("Default AsyncImage")
1011
ScrollView {
1112
LazyVGrid(columns: [.init(), .init()]) {
1213
ForEach(0..<1000, id: \.self) { _ in

Example/Example/DownsampleContentView.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,12 @@ import AsyncDownSamplingImage
33

44
struct DownsampleContentView: View {
55

6-
@State private var url = URL(string: "https://via.placeholder.com/1000")
6+
@State private var url = URL(string: "https://picsum.photos/1000")
77
@State private var size: CGSize = .init(width: 160, height: 160)
88

99
var body: some View {
1010
VStack {
11+
Text("AsyncDownSamplingImage")
1112
ScrollView {
1213
LazyVGrid(columns: [.init(), .init()]) {
1314
ForEach(0..<1000, id: \.self) { _ in

Package.resolved

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/AsyncDownSamplingImage/AsyncDownSamplingImage.swift

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,36 @@
11
import SwiftUI
22

3+
4+
private enum LoadingOpacityEdge {
5+
case upperBound
6+
case lowerBound
7+
8+
var value: Double {
9+
switch self {
10+
case .upperBound:
11+
return 1
12+
case .lowerBound:
13+
return 0.3
14+
}
15+
}
16+
17+
mutating func toggle() {
18+
switch self {
19+
case .upperBound:
20+
self = .lowerBound
21+
case .lowerBound:
22+
self = .upperBound
23+
}
24+
}
25+
}
26+
327
/// AsyncDownSamplingImage is a Image View that can perform downsampling and use less memory use than `AsyncImage`.
428
///
529
/// About generics type:
630
///
7-
/// - Content: View which appears when state is Successful.
8-
/// - Placeholder: View which appears when state is Loading.
9-
/// - Fail: View which appears when state is Failed.
31+
/// - Content: View which appears when state is Successful.
32+
/// - Placeholder: View which appears when state is Loading.
33+
/// - Fail: View which appears when state is Failed.
1034
public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: View>: View {
1135

1236
/// resource URL where you would like to fetch an image.
@@ -24,7 +48,7 @@ public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: Vie
2448
public let fail: (Error) -> Fail
2549

2650
@State private var status: Status = .idle
27-
@State private var loadingOpacity: CGFloat = 1.0
51+
@State private var loadingOpacity: LoadingOpacityEdge = .upperBound
2852

2953
/// Standard initializer
3054
///
@@ -79,19 +103,18 @@ public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: Vie
79103
}
80104
case .failed(let error):
81105
fail(error)
82-
case .loaded(let image):
106+
case .loaded(let image), .reloading(let image):
83107
content(image)
84108
}
85-
EmptyView()
86109
}
87110

88111
var loadingView: some View {
89112
Image(systemName: "plus") // any image is okay
90113
.resizable()
91114
.cornerRadius(2)
92-
.opacity(loadingOpacity)
115+
.opacity(loadingOpacity.value)
93116
.animation(
94-
Animation.easeIn(duration: 0.5).repeatForever(autoreverses: true),
117+
Animation.easeInOut(duration: 0.7).repeatForever(autoreverses: true),
95118
value: loadingOpacity
96119
)
97120
.frame(
@@ -100,12 +123,16 @@ public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: Vie
100123
)
101124
.redacted(reason: .placeholder)
102125
.onAppear {
103-
loadingOpacity = abs(1.0 - loadingOpacity)
126+
loadingOpacity.toggle()
104127
}
105128
}
106129

107130
func startLoading(url: URL) {
108-
status = .loading
131+
if case Status.loaded(let image) = status {
132+
status = .reloading(image)
133+
} else {
134+
status = .loading
135+
}
109136
Task {
110137
do {
111138
let cgImage = try await DownSampling.perform(
@@ -125,6 +152,7 @@ extension AsyncDownSamplingImage {
125152
enum Status {
126153
case idle
127154
case loading
155+
case reloading(Image)
128156
case failed(Error)
129157
case loaded(Image)
130158
}

docs/index.html

Lines changed: 114 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,114 @@
1-
<!DOCTYPE html><html lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><link rel="icon" href="/AsyncDownSamplingImage/favicon.ico"><link rel="mask-icon" href="/AsyncDownSamplingImage/favicon.svg" color="#333333"><title>Documentation</title><script>var baseUrl = "/AsyncDownSamplingImage/"</script><link href="/AsyncDownSamplingImage/css/documentation-topic.3bca6578.css" rel="prefetch"><link href="/AsyncDownSamplingImage/css/documentation-topic~topic~tutorials-overview.82acfe22.css" rel="prefetch"><link href="/AsyncDownSamplingImage/css/topic.ee15af52.css" rel="prefetch"><link href="/AsyncDownSamplingImage/css/tutorials-overview.06e8bcf7.css" rel="prefetch"><link href="/AsyncDownSamplingImage/js/chunk-2d0d3105.cd72cc8e.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/documentation-topic.f62098b6.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/documentation-topic~topic~tutorials-overview.8e36e44f.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-bash.1b52852f.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-c.d1db3f17.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-cpp.eaddddbe.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-css.75eab1fe.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-custom-markdown.7cffc4b3.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-custom-swift.5cda5c20.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-diff.62d66733.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-http.163e45b6.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-java.8326d9d8.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-javascript.acb8a8eb.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-json.471128d2.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-llvm.6100b125.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-markdown.90077643.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-objectivec.bcdf5156.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-perl.757d7b6f.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-php.cc8d6c27.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-python.c214ed92.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-ruby.f889d392.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-scss.62ee18da.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-shell.dd7f411f.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-swift.84f3e88c.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/highlight-js-xml.9c3688c7.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/topic.6a1c7b7f.js" rel="prefetch"><link href="/AsyncDownSamplingImage/js/tutorials-overview.c8178b83.js" rel="prefetch"><link href="/AsyncDownSamplingImage/css/index.12bb178a.css" rel="preload" as="style"><link href="/AsyncDownSamplingImage/js/chunk-vendors.b24b7aaa.js" rel="preload" as="script"><link href="/AsyncDownSamplingImage/js/index.58e30ec4.js" rel="preload" as="script"><link href="/AsyncDownSamplingImage/css/index.12bb178a.css" rel="stylesheet"></head><body data-color-scheme="auto"><noscript><style>.noscript{font-family:"SF Pro Display","SF Pro Icons","Helvetica Neue",Helvetica,Arial,sans-serif;margin:92px auto 140px auto;text-align:center;width:980px}.noscript-title{color:#111;font-size:48px;font-weight:600;letter-spacing:-.003em;line-height:1.08365;margin:0 auto 54px auto;width:502px}@media only screen and (max-width:1068px){.noscript{margin:90px auto 120px auto;width:692px}.noscript-title{font-size:40px;letter-spacing:0;line-height:1.1;margin:0 auto 45px auto;width:420px}}@media only screen and (max-width:735px){.noscript{margin:45px auto 60px auto;width:87.5%}.noscript-title{font-size:32px;letter-spacing:.004em;line-height:1.125;margin:0 auto 35px auto;max-width:330px;width:auto}}#loading-placeholder{display:none}</style><div class="noscript"><h1 class="noscript-title">This page requires JavaScript.</h1><p>Please turn on JavaScript in your browser and refresh the page to view its content.</p></div></noscript><div id="app"></div><script src="/AsyncDownSamplingImage/js/chunk-vendors.b24b7aaa.js"></script><script src="/AsyncDownSamplingImage/js/index.58e30ec4.js"></script></body></html>
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8">
6+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
7+
<meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover">
8+
<link rel="icon" href="/AsyncDownSamplingImage/favicon.ico">
9+
<link rel="mask-icon" href="/AsyncDownSamplingImage/favicon.svg" color="#333333">
10+
<title>Documentation</title>
11+
<script>var baseUrl = "/AsyncDownSamplingImage/"</script>
12+
<link href="/AsyncDownSamplingImage/css/documentation-topic.3bca6578.css" rel="prefetch">
13+
<link href="/AsyncDownSamplingImage/css/documentation-topic~topic~tutorials-overview.82acfe22.css" rel="prefetch">
14+
<link href="/AsyncDownSamplingImage/css/topic.ee15af52.css" rel="prefetch">
15+
<link href="/AsyncDownSamplingImage/css/tutorials-overview.06e8bcf7.css" rel="prefetch">
16+
<link href="/AsyncDownSamplingImage/js/chunk-2d0d3105.cd72cc8e.js" rel="prefetch">
17+
<link href="/AsyncDownSamplingImage/js/documentation-topic.f62098b6.js" rel="prefetch">
18+
<link href="/AsyncDownSamplingImage/js/documentation-topic~topic~tutorials-overview.8e36e44f.js" rel="prefetch">
19+
<link href="/AsyncDownSamplingImage/js/highlight-js-bash.1b52852f.js" rel="prefetch">
20+
<link href="/AsyncDownSamplingImage/js/highlight-js-c.d1db3f17.js" rel="prefetch">
21+
<link href="/AsyncDownSamplingImage/js/highlight-js-cpp.eaddddbe.js" rel="prefetch">
22+
<link href="/AsyncDownSamplingImage/js/highlight-js-css.75eab1fe.js" rel="prefetch">
23+
<link href="/AsyncDownSamplingImage/js/highlight-js-custom-markdown.7cffc4b3.js" rel="prefetch">
24+
<link href="/AsyncDownSamplingImage/js/highlight-js-custom-swift.5cda5c20.js" rel="prefetch">
25+
<link href="/AsyncDownSamplingImage/js/highlight-js-diff.62d66733.js" rel="prefetch">
26+
<link href="/AsyncDownSamplingImage/js/highlight-js-http.163e45b6.js" rel="prefetch">
27+
<link href="/AsyncDownSamplingImage/js/highlight-js-java.8326d9d8.js" rel="prefetch">
28+
<link href="/AsyncDownSamplingImage/js/highlight-js-javascript.acb8a8eb.js" rel="prefetch">
29+
<link href="/AsyncDownSamplingImage/js/highlight-js-json.471128d2.js" rel="prefetch">
30+
<link href="/AsyncDownSamplingImage/js/highlight-js-llvm.6100b125.js" rel="prefetch">
31+
<link href="/AsyncDownSamplingImage/js/highlight-js-markdown.90077643.js" rel="prefetch">
32+
<link href="/AsyncDownSamplingImage/js/highlight-js-objectivec.bcdf5156.js" rel="prefetch">
33+
<link href="/AsyncDownSamplingImage/js/highlight-js-perl.757d7b6f.js" rel="prefetch">
34+
<link href="/AsyncDownSamplingImage/js/highlight-js-php.cc8d6c27.js" rel="prefetch">
35+
<link href="/AsyncDownSamplingImage/js/highlight-js-python.c214ed92.js" rel="prefetch">
36+
<link href="/AsyncDownSamplingImage/js/highlight-js-ruby.f889d392.js" rel="prefetch">
37+
<link href="/AsyncDownSamplingImage/js/highlight-js-scss.62ee18da.js" rel="prefetch">
38+
<link href="/AsyncDownSamplingImage/js/highlight-js-shell.dd7f411f.js" rel="prefetch">
39+
<link href="/AsyncDownSamplingImage/js/highlight-js-swift.84f3e88c.js" rel="prefetch">
40+
<link href="/AsyncDownSamplingImage/js/highlight-js-xml.9c3688c7.js" rel="prefetch">
41+
<link href="/AsyncDownSamplingImage/js/topic.6a1c7b7f.js" rel="prefetch">
42+
<link href="/AsyncDownSamplingImage/js/tutorials-overview.c8178b83.js" rel="prefetch">
43+
<link href="/AsyncDownSamplingImage/css/index.12bb178a.css" rel="preload" as="style">
44+
<link href="/AsyncDownSamplingImage/js/chunk-vendors.b24b7aaa.js" rel="preload" as="script">
45+
<link href="/AsyncDownSamplingImage/js/index.58e30ec4.js" rel="preload" as="script">
46+
<link href="/AsyncDownSamplingImage/css/index.12bb178a.css" rel="stylesheet">
47+
</head>
48+
49+
<body data-color-scheme="auto"><noscript>
50+
<style>
51+
.noscript {
52+
font-family: "SF Pro Display", "SF Pro Icons", "Helvetica Neue", Helvetica, Arial, sans-serif;
53+
margin: 92px auto 140px auto;
54+
text-align: center;
55+
width: 980px
56+
}
57+
58+
.noscript-title {
59+
color: #111;
60+
font-size: 48px;
61+
font-weight: 600;
62+
letter-spacing: -.003em;
63+
line-height: 1.08365;
64+
margin: 0 auto 54px auto;
65+
width: 502px
66+
}
67+
68+
@media only screen and (max-width:1068px) {
69+
.noscript {
70+
margin: 90px auto 120px auto;
71+
width: 692px
72+
}
73+
74+
.noscript-title {
75+
font-size: 40px;
76+
letter-spacing: 0;
77+
line-height: 1.1;
78+
margin: 0 auto 45px auto;
79+
width: 420px
80+
}
81+
}
82+
83+
@media only screen and (max-width:735px) {
84+
.noscript {
85+
margin: 45px auto 60px auto;
86+
width: 87.5%
87+
}
88+
89+
.noscript-title {
90+
font-size: 32px;
91+
letter-spacing: .004em;
92+
line-height: 1.125;
93+
margin: 0 auto 35px auto;
94+
max-width: 330px;
95+
width: auto
96+
}
97+
}
98+
99+
#loading-placeholder {
100+
display: none
101+
}
102+
103+
</style>
104+
<div class="noscript">
105+
<h1 class="noscript-title">This page requires JavaScript.</h1>
106+
<p>Please turn on JavaScript in your browser and refresh the page to view its content.</p>
107+
</div>
108+
</noscript>
109+
<div id="app"></div>
110+
<script src="/AsyncDownSamplingImage/js/chunk-vendors.b24b7aaa.js"></script>
111+
<script src="/AsyncDownSamplingImage/js/index.58e30ec4.js"></script>
112+
</body>
113+
114+
</html>

0 commit comments

Comments
 (0)