Skip to content

Commit

Permalink
feat: add tiny fix for Demo. Add LoadingOpacityEdge and change lowe…
Browse files Browse the repository at this point in the history
…rBound opacity in loading state. Add new state `reloading` to `Status`. (#8)
  • Loading branch information
fummicc1 authored Oct 17, 2023
1 parent ee92a1d commit 0db4595
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 15 deletions.
3 changes: 2 additions & 1 deletion Example/Example/DefaultContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@ import SwiftUI

struct DefaultContentView: View {

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

var body: some View {
VStack {
Text("Default AsyncImage")
ScrollView {
LazyVGrid(columns: [.init(), .init()]) {
ForEach(0..<1000, id: \.self) { _ in
Expand Down
3 changes: 2 additions & 1 deletion Example/Example/DownsampleContentView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import AsyncDownSamplingImage

struct DownsampleContentView: View {

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

var body: some View {
VStack {
Text("AsyncDownSamplingImage")
ScrollView {
LazyVGrid(columns: [.init(), .init()]) {
ForEach(0..<1000, id: \.self) { _ in
Expand Down
4 changes: 2 additions & 2 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-docc-plugin",
"state" : {
"revision" : "10bc670db657d11bdd561e07de30a9041311b2b1",
"version" : "1.1.0"
"revision" : "26ac5758409154cc448d7ab82389c520fa8a8247",
"version" : "1.3.0"
}
},
{
Expand Down
48 changes: 38 additions & 10 deletions Sources/AsyncDownSamplingImage/AsyncDownSamplingImage.swift
Original file line number Diff line number Diff line change
@@ -1,12 +1,36 @@
import SwiftUI


private enum LoadingOpacityEdge {
case upperBound
case lowerBound

var value: Double {
switch self {
case .upperBound:
return 1
case .lowerBound:
return 0.3
}
}

mutating func toggle() {
switch self {
case .upperBound:
self = .lowerBound
case .lowerBound:
self = .upperBound
}
}
}

/// AsyncDownSamplingImage is a Image View that can perform downsampling and use less memory use than `AsyncImage`.
///
/// About generics type:
///
/// - Content: View which appears when state is Successful.
/// - Placeholder: View which appears when state is Loading.
/// - Fail: View which appears when state is Failed.
/// - Content: View which appears when state is Successful.
/// - Placeholder: View which appears when state is Loading.
/// - Fail: View which appears when state is Failed.
public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: View>: View {

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

@State private var status: Status = .idle
@State private var loadingOpacity: CGFloat = 1.0
@State private var loadingOpacity: LoadingOpacityEdge = .upperBound

/// Standard initializer
///
Expand Down Expand Up @@ -79,19 +103,18 @@ public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: Vie
}
case .failed(let error):
fail(error)
case .loaded(let image):
case .loaded(let image), .reloading(let image):
content(image)
}
EmptyView()
}

var loadingView: some View {
Image(systemName: "plus") // any image is okay
.resizable()
.cornerRadius(2)
.opacity(loadingOpacity)
.opacity(loadingOpacity.value)
.animation(
Animation.easeIn(duration: 0.5).repeatForever(autoreverses: true),
Animation.easeInOut(duration: 0.7).repeatForever(autoreverses: true),
value: loadingOpacity
)
.frame(
Expand All @@ -100,12 +123,16 @@ public struct AsyncDownSamplingImage<Content: View, Placeholder: View, Fail: Vie
)
.redacted(reason: .placeholder)
.onAppear {
loadingOpacity = abs(1.0 - loadingOpacity)
loadingOpacity.toggle()
}
}

func startLoading(url: URL) {
status = .loading
if case Status.loaded(let image) = status {
status = .reloading(image)
} else {
status = .loading
}
Task {
do {
let cgImage = try await DownSampling.perform(
Expand All @@ -125,6 +152,7 @@ extension AsyncDownSamplingImage {
enum Status {
case idle
case loading
case reloading(Image)
case failed(Error)
case loaded(Image)
}
Expand Down
115 changes: 114 additions & 1 deletion docs/index.html
Original file line number Diff line number Diff line change
@@ -1 +1,114 @@
<!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>
<!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>

0 comments on commit 0db4595

Please sign in to comment.