123 lines
4.1 KiB
Swift
123 lines
4.1 KiB
Swift
//
|
|
// ComposeAttachmentImage.swift
|
|
// Tusker
|
|
//
|
|
// Created by Shadowfacts on 11/10/21.
|
|
// Copyright © 2021 Shadowfacts. All rights reserved.
|
|
//
|
|
|
|
import SwiftUI
|
|
import Photos
|
|
|
|
struct ComposeAttachmentImage: View {
|
|
let attachment: CompositionAttachment
|
|
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(image):
|
|
self.image = image
|
|
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) {
|
|
}
|
|
}
|
|
|
|
struct ComposeAttachmentImage_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
ComposeAttachmentImage(attachment: CompositionAttachment(data: .image(UIImage())), fullSize: false)
|
|
}
|
|
}
|