// // AttachmentThumbnailView.swift // ComposeUI // // Created by Shadowfacts on 11/10/21. // Copyright © 2021 Shadowfacts. All rights reserved. // import SwiftUI import Photos import TuskerComponents struct AttachmentThumbnailView: View { let attachment: DraftAttachment let fullSize: Bool @State private var gifData: Data? = nil @State private var image: UIImage? = nil @State private var imageContentMode: ContentMode = .fill @State private var imageBackgroundColor: Color = .black @Environment(\.colorScheme) private var colorScheme: ColorScheme var body: some View { if let gifData { GIFViewWrapper(gifData: gifData) } else if let image { Image(uiImage: image) .resizable() .aspectRatio(contentMode: imageContentMode) .background(imageBackgroundColor) } else { Image(systemName: placeholderImageName) .onAppear(perform: self.loadImage) } } private var placeholderImageName: String { switch colorScheme { case .light: return "photo" case .dark: return "photo.fill" @unknown default: return "photo" } } private func loadImage() { switch attachment.data { case let .image(originalData, originalType: _): self.image = UIImage(data: originalData) case let .asset(asset): let size: CGSize if fullSize { size = PHImageManagerMaximumSize } else { // currently only used as thumbnail in ComposeAttachmentRow size = CGSize(width: 80, height: 80) } let isGIF = PHAssetResource.assetResources(for: asset).contains(where: { $0.uniformTypeIdentifier == UTType.gif.identifier }) if isGIF { PHImageManager.default().requestImageDataAndOrientation(for: asset, options: nil) { data, typeIdentifier, orientation, info in if typeIdentifier == UTType.gif.identifier { self.gifData = data } else if let data { let image = UIImage(data: data) DispatchQueue.main.async { self.image = image } } } } else { PHImageManager.default().requestImage(for: asset, targetSize: size, contentMode: .aspectFill, options: nil) { (image, _) in DispatchQueue.main.async { self.image = image } } } case let .video(url): let asset = AVURLAsset(url: url) let imageGenerator = AVAssetImageGenerator(asset: asset) if let cgImage = try? imageGenerator.copyCGImage(at: .zero, actualTime: nil) { self.image = UIImage(cgImage: cgImage) } case let .drawing(drawing): image = drawing.imageInLightMode(from: drawing.bounds) imageContentMode = .fit imageBackgroundColor = .white case let .gif(data): self.gifData = data } } } private struct GIFViewWrapper: UIViewRepresentable { typealias UIViewType = GIFImageView @State private var controller: GIFController init(gifData: Data) { self._controller = State(wrappedValue: GIFController(gifData: gifData)) } func makeUIView(context: Context) -> GIFImageView { let view = GIFImageView() controller.attach(to: view) controller.startAnimating() view.contentMode = .scaleAspectFit view.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) view.setContentCompressionResistancePriority(.defaultLow, for: .vertical) return view } func updateUIView(_ uiView: GIFImageView, context: Context) { } }