diff --git a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift index e1c618f..550a82c 100644 --- a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift +++ b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift @@ -68,7 +68,7 @@ public struct AsyncMultiplexImageCandidate: Hashable { public struct AsyncMultiplexImage: View { - private var candidates: [AsyncMultiplexImageCandidate] = [] + @State private var candidates: [AsyncMultiplexImageCandidate] = [] @State private var internalView: _AsyncMultiplexImage? @@ -129,8 +129,8 @@ public struct AsyncMultiplexImage: View { - @State private var currentImage: Image? + @State private var item: ResultContainer.Item? @State private var task: Task? private let downloader: Downloader @@ -160,14 +160,20 @@ struct _AsyncMultiplexImage? @@ -209,7 +220,7 @@ actor ResultContainer { func make( candidates: [AsyncMultiplexImageCandidate], on downloader: Downloader - ) -> AsyncThrowingStream { + ) -> AsyncThrowingStream { Log.debug(.`generic`, "Load: \(candidates.map { $0.urlRequest })") @@ -246,7 +257,7 @@ actor ResultContainer { Log.debug(.`generic`, "Loaded ideal") lastCandidate = idealCandidate - continuation.yield(result) + continuation.yield(.final(result)) } catch { continuation.yield(with: .failure(error)) } @@ -290,7 +301,7 @@ actor ResultContainer { lastCandidate = idealCandidate - let yieldResult = continuation.yield(result) + let yieldResult = continuation.yield(.progress(result)) Log.debug(.`generic`, "Loaded progress image => \(candidate.index), \(yieldResult)") } catch { diff --git a/Sources/AsyncMultiplexImageDemo/Demo.swift b/Sources/AsyncMultiplexImageDemo/Demo.swift index 96dc048..7b2033d 100644 --- a/Sources/AsyncMultiplexImageDemo/Demo.swift +++ b/Sources/AsyncMultiplexImageDemo/Demo.swift @@ -1,13 +1,10 @@ import AsyncMultiplexImage import AsyncMultiplexImage_Nuke -import SwiftUI import Nuke +import SwiftUI +func buildURLs(baseURLString: String, size: CGSize) -> [URL] { -func buildURLs() -> [URL] { - -let baseURLString = "https://images.unsplash.com/photo-1492446845049-9c50cc313f00?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" - var components = URLComponents(string: baseURLString)! return [ @@ -16,33 +13,94 @@ let baseURLString = "https://images.unsplash.com/photo-1492446845049-9c50cc313f0 "w=50", "w=10", ].map { - + components.query = $0 - + return components.url! - + } - + } struct AsyncMultiplexImage_Previews: PreviewProvider { static var previews: some View { - AsyncMultiplexImage( - urls: buildURLs(), - downloader: SlowDownloader(pipeline: .shared) - ) { phase in - switch phase { - case .empty: - Text("Loading") - case .progress(let image): - image - case .success(let image): - image - .resizable() - .scaledToFit() - case .failure(let error): - Text("Error") + + Group { + AsyncMultiplexImage( + urlsProvider: { size in + buildURLs( + baseURLString: + "https://images.unsplash.com/photo-1492446845049-9c50cc313f00?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8", + size: size + ) + }, + downloader: SlowDownloader(pipeline: .shared) + ) { phase in + switch phase { + case .empty: + Rectangle() + .foregroundColor(.yellow) + .overlay(Text("Loading")) + case .progress(let image): + image + .resizable() + .scaledToFill() + .overlay(Text("Progress")) + + case .success(let image): + image + .resizable() + .scaledToFill() + .overlay(Text("Done")) + case .failure(let error): + Text("Error") + } + } + .frame(width: 300, height: 300) + .overlay(Color.red.opacity(0.3)) + } + } +} + +struct BookAlign: View, PreviewProvider { + var body: some View { + if #available(iOS 15, *) { + Content() + } + } + + static var previews: some View { + Self() + } + + @available(iOS 15, *) + private struct Content: View { + + var body: some View { + ZStack { + AsyncImage( + url: .init( + string: + "https://images.unsplash.com/photo-1492446845049-9c50cc313f00?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8" + )! + ) { phase in + switch phase { + case .empty: + Rectangle() + .foregroundColor(.yellow) + .overlay(Text("Loading")) + case .success(let image): + image + .resizable() + .scaledToFill() + .overlay(Text("Done")) + case .failure(let error): + Text("Error") + } + } } + .frame(width: 200, height: 200) + .overlay(Color.red.opacity(0.3)) } } }