import SwiftUI struct AsyncImageWithPreview: View { @EnvironmentObject var settings: Settings var url: URL? @Binding var loadingState: PostLoadingState var finalLoadingState: PostLoadingState var postURL: URL? let placeholder: () -> Placeholder @State private var currentScale: CGFloat = 1.0 @State private var finalScale: CGFloat = 1.0 @State private var currentOffset: CGSize = .zero @State private var finalOffset: CGSize = .zero var keyWindow: UIWindow? { guard let window = UIApplication.shared.connectedScenes .compactMap({ $0 as? UIWindowScene }) .flatMap(\.windows) .first(where: \.isKeyWindow) else { return nil } return window } var body: some View { AsyncImage(url: url) { image in ZoomableImageView(image: image) .onAppear { loadingState = finalLoadingState } .contextMenu { #if os(iOS) Button { guard let url else { return } URLSession.shared.dataTask(with: url) { data, _, _ in guard let data, let uiImage = UIImage(data: data) else { return } UIImageWriteToSavedPhotosAlbum(uiImage, nil, nil, nil) } .resume() } label: { Label("Save Image", systemImage: "square.and.arrow.down") } #endif #if os(iOS) if settings.enableShareShortcut { Button { keyWindow?.rootViewController?.present( UIActivityViewController( activityItems: [url ?? URL(string: "")!], applicationActivities: nil ), animated: true ) } label: { Label("Share Image", systemImage: "square.and.arrow.up") } } #endif if let url = postURL { Button { #if os(iOS) UIApplication.shared.open(url) #else NSWorkspace.shared.open(url) #endif } label: { Label("Open in Safari", systemImage: "safari") } } } } placeholder: { placeholder() .onAppear { loadingState = .loadingPreview } } } init( url: URL?, loadingStage: Binding, finalLoadingState: PostLoadingState = .loadingFile, postURL: URL? = nil, @ViewBuilder placeholder: @escaping () -> Placeholder = { GeometryReader { geometry in ProgressView() .frame(width: geometry.size.width, height: geometry.size.height) .position(x: geometry.size.width / 2, y: geometry.size.height / 2) .padding() } } ) { self.url = url _loadingState = loadingStage self.finalLoadingState = finalLoadingState self.postURL = postURL self.placeholder = placeholder } }