From be74b1cac87ca7546933ebc4214da8fbf5e5fbaa Mon Sep 17 00:00:00 2001 From: Kyle Date: Sun, 10 Sep 2023 17:30:55 +0800 Subject: [PATCH] Add AsyncImage like API for WebImage --- SDWebImageSwiftUI/Classes/WebImage2.swift | 103 ++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 SDWebImageSwiftUI/Classes/WebImage2.swift diff --git a/SDWebImageSwiftUI/Classes/WebImage2.swift b/SDWebImageSwiftUI/Classes/WebImage2.swift new file mode 100644 index 00000000..e31ba745 --- /dev/null +++ b/SDWebImageSwiftUI/Classes/WebImage2.swift @@ -0,0 +1,103 @@ +// +// WebImage2.swift +// +// +// Created by Kyle on 2023/9/10. +// + +import SwiftUI + +public struct WebImageEventContext { + // TODO, Configuration and Information of image +} + +struct LoadingState { + var url: URL? + var phase: WebImagePhase + init() { + url = nil + phase = .empty + } + + func load() {} +} + +@available(iOS 14.0, macOS 11.0, tvOS 14.0, watchOS 7.0, *) +public struct WebImage2: View where Content: View { + var url: URL? + var scale: CGFloat + var transaction: Transaction + var content: (WebImagePhase) -> Content + + @State private var loadingState = LoadingState() + + public init(url: URL?, scale: CGFloat = 1) where Content == Image { + self.init(url: url, scale: scale) { phase in + phase.image ?? Image("") + } + } + + public init(url: URL?, scale: CGFloat = 1, @ViewBuilder content: @escaping (Image) -> I, @ViewBuilder placeholder: @escaping () -> P) where Content == _ConditionalContent, I: View, P: View { + self.init(url: url, scale: scale) { phase in + if let i = phase.image { + content(i) + } else { + placeholder() + } + } + } + + public init(url: URL?, scale: CGFloat = 1, transaction: Transaction = Transaction(), @ViewBuilder content: @escaping (WebImagePhase) -> Content) { + self.url = url + self.scale = scale + self.transaction = transaction + self.content = { phase in + content(phase) + } + } + + public var body: some View { + content(loadingState.phase) + .onAppear { + load(url) + } + .onDisappear {} + .onChange(of: url) { load($0) } + } + + private func load(_: URL?) {} +} + +@available(iOS 13.0, *) +struct LoadingError: Error {} + +@available(iOS 13.0, *) +public enum WebImagePhase { + /// No image is loaded. + case empty + + /// An image succesfully loaded. + case success(Image) + + /// An image failed to load with an error. + case failure(Error) + + public var image: Image? { + switch self { + case let .success(image): + image + case .empty, .failure: + nil + } + } + + /// The error that occurred when attempting to load an image, if any. + public var error: Error? { + switch self { + case .empty, .success: + nil + case let .failure(error): + error + } + } +}