diff --git a/AsyncMultiplexImage-Demo/AsyncMultiplexImage-Demo/ContentView.swift b/AsyncMultiplexImage-Demo/AsyncMultiplexImage-Demo/ContentView.swift index c9fa0e6..b7718ed 100644 --- a/AsyncMultiplexImage-Demo/AsyncMultiplexImage-Demo/ContentView.swift +++ b/AsyncMultiplexImage-Demo/AsyncMultiplexImage-Demo/ContentView.swift @@ -48,7 +48,7 @@ struct ContentView: View { var body: some View { VStack { AsyncMultiplexImage( - urls: buildURLs(basePhotoURLString), + multiplexImage: .init(identifier: basePhotoURLString, urls: buildURLs(basePhotoURLString)), downloader: _SlowDownloader(pipeline: .shared) ) { phase in switch phase { @@ -56,15 +56,16 @@ struct ContentView: View { Text("Loading") case .progress(let image): image + .resizable() + .scaledToFill() case .success(let image): image .resizable() - .scaledToFit() + .scaledToFill() case .failure(let error): Text("Error") } } - .id(basePhotoURLString) HStack { Button("1") { diff --git a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift index 13898cc..c4c85e0 100644 --- a/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift +++ b/Sources/AsyncMultiplexImage/AsyncMultiplexImage.swift @@ -66,60 +66,55 @@ public struct AsyncMultiplexImageCandidate: Hashable { } +public struct MultiplexImage: Hashable { + + public static func == (lhs: MultiplexImage, rhs: MultiplexImage) -> Bool { + lhs.identifier == rhs.identifier + } + + public func hash(into hasher: inout Hasher) { + identifier.hash(into: &hasher) + } + + public let identifier: String + + fileprivate private(set) var _urlsProvider: @MainActor (CGSize) -> [URL] + + public init( + identifier: String, + urlsProvider: @escaping @MainActor (CGSize) -> [URL] + ) { + self.identifier = identifier + self._urlsProvider = urlsProvider + } + + public init(identifier: String, urls: [URL]) { + self.init(identifier: identifier, urlsProvider: { _ in urls }) + } + +} + public struct AsyncMultiplexImage: View { @State private var candidates: [AsyncMultiplexImageCandidate] = [] @State private var internalView: _internal_AsyncMultiplexImage? - private let urlsProvider: (CGSize) -> [URL] + private let multiplexImage: MultiplexImage private let downloader: Downloader private let content: (AsyncMultiplexImagePhase) -> Content public init( - urlsProvider: @escaping (CGSize) -> [URL], + multiplexImage: MultiplexImage, downloader: Downloader, @ViewBuilder content: @escaping (AsyncMultiplexImagePhase) -> Content ) { - self.urlsProvider = urlsProvider + self.multiplexImage = multiplexImage self.downloader = downloader self.content = content } - - /// Primitive initializer - public init( - urls: [URL], - downloader: Downloader, - @ViewBuilder content: @escaping (AsyncMultiplexImagePhase) -> Content - ) { - - self.init(urlsProvider: { _ in urls }, downloader: downloader, content: content) - } - - // TODO: tmp - public init( - urls: [URL], - downloader: Downloader - ) where Content == _ConditionalContent<_ConditionalContent, _ConditionalContent> { - self.init( - urls: urls, - downloader: downloader, - content: { phase in - switch phase { - case .empty: - EmptyView() - case .progress(let image): - image - case .success(let image): - image - case .failure: - EmptyView() - } - } - ) - } - + public var body: some View { GeometryReader { proxy in Group { @@ -130,9 +125,9 @@ public struct AsyncMultiplexImage