// // AvatarImageView.swift // ComposeUI // // Created by Shadowfacts on 3/4/23. // import SwiftUI public struct AvatarImageView: View { public typealias FetchAvatar = (URL) async -> UIImage? let url: URL? let size: CGFloat let style: Style let fetchAvatar: FetchAvatar @State private var image: UIImage? public init(url: URL?, size: CGFloat, style: Style, fetchAvatar: @escaping FetchAvatar) { self.url = url self.size = size self.style = style self.fetchAvatar = fetchAvatar } public var body: some View { imageView .resizable() .frame(width: size, height: size) .cornerRadius(style.cornerRadiusFraction * size) .task { image = nil if let url { image = await fetchAvatar(url) } } // tell swiftui that this view has changed (and therefore the task needs to re-run) when the url changes .id(url) } private var imageView: Image { if let image { return Image(uiImage: image) } else { return placeholder } } private var placeholder: Image { Image(systemName: style == .roundRect ? "person.crop.square" : "person.crop.circle") } public enum Style: Equatable { case roundRect, circle var cornerRadiusFraction: CGFloat { switch self { case .roundRect: return 0.1 case .circle: return 0.5 } } } }