import Foundation import UIKit final class FileProcessing { static let shared = FileProcessing() static var fileFolder: URL { // swiftlint:disable:next force_unwrapping let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! return documentsURL.appendingPathComponent(Const.fileFolder) } func createThumbnail(id: String, localUrl: URL) -> URL? { // make path for thumbnail let thumbnailUrl = FileProcessing.fileFolder.appendingPathComponent(id).appendingPathExtension("png") // check if thumbnail already exists if FileManager.default.fileExists(atPath: thumbnailUrl.path) { return thumbnailUrl } // create thumbnail if not exists switch localUrl.lastPathComponent.attachmentType { case .image: guard let image = UIImage(contentsOfFile: localUrl.path) else { return nil } let targetSize = CGSize(width: Const.attachmentPreviewSize, height: Const.attachmentPreviewSize) guard let thumbnail = scaleAndCropImage(image, targetSize) else { return nil } guard let data = thumbnail.pngData() else { return nil } do { try data.write(to: thumbnailUrl) return thumbnailUrl } catch { return nil } default: return nil } } } private extension FileProcessing { func scaleAndCropImage(_ img: UIImage, _ size: CGSize) -> UIImage? { guard let cgImage = img.cgImage else { return nil } let contextImage: UIImage = .init(cgImage: cgImage) var contextSize: CGSize = contextImage.size var posX: CGFloat = 0.0 var posY: CGFloat = 0.0 let cgwidth: CGFloat = size.width let cgheight: CGFloat = size.height // Check and handle if the image is wider than the requested size if contextSize.width > contextSize.height { posX = ((contextSize.width - contextSize.height) / 2) contextSize.width = contextSize.height } else if contextSize.width < contextSize.height { // Check and handle if the image is taller than the requested size posY = ((contextSize.height - contextSize.width) / 2) contextSize.height = contextSize.width } let rect: CGRect = .init(x: posX, y: posY, width: cgwidth, height: cgheight) guard let contextCg = contextImage.cgImage, let imgRef = contextCg.cropping(to: rect) else { return nil } let image: UIImage = .init(cgImage: imgRef, scale: img.scale, orientation: img.imageOrientation) return image } }