// // KMFileThumbManager.swift // PDF Reader Pro // // Created by Niehaoyu on 2024/11/22. // import Cocoa import CryptoKit class KMFileThumbManager: NSObject { let thumbFolderPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory.applicationSupportDirectory, FileManager.SearchPathDomainMask.userDomainMask, true).last?.stringByAppendingPathComponent(Bundle.main.bundleIdentifier!).stringByAppendingPathComponent("thumb") @objc public static let manager = KMFileThumbManager() private var iconSize: CGSize = CGSizeMake(126*3, 168*3) override init() { super.init() let tabClosingNoti = NSNotification.Name("CTTabClosingNotification") NotificationCenter.default.addObserver(self, selector: #selector(tabClosingNotification), name: tabClosingNoti, object: nil) refreshData() } func refreshData() { if let path = thumbFolderPath { try?FileManager.default.removeItem(atPath: path) if (!FileManager.default.fileExists(atPath: path)) { try?FileManager.default.createDirectory(atPath: path, withIntermediateDirectories: true, attributes: nil) } } let urls: Array = NSDocumentController.shared.recentDocumentURLs var fileNames: [String] = [] for url in urls { let filePath = url.path let fileName = filePath.getLastComponentDeleteExtension let resultPath = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) if (!FileManager.default.fileExists(atPath: resultPath!)) { updateFile(url, iconSize) } fileNames.append((fileName + ".png")) } if let contents = try?FileManager.default.contentsOfDirectory(atPath: thumbFolderPath!) { for name in contents { if name != ".DS_Store" { if let index = fileNames.firstIndex(of: name) { } else { if let path = thumbFolderPath?.stringByAppendingPathComponent(name) { try?FileManager.default.removeItem(atPath: path) } } } } } } private func generateThumbnail(for pdfURL: URL, _ size: NSSize) -> NSImage? { guard let pdfDocument = PDFDocument(url: pdfURL), let pdfPage = pdfDocument.page(at: 0) else { return nil } if pdfDocument.isLocked || pdfDocument.isEncrypted { return NSImage(named: "file_lock") } let pdfPageBounds = pdfPage.bounds(for: .mediaBox) let scale = min(size.width / pdfPageBounds.width, size.height / pdfPageBounds.height) let thumbnailSize = CGSize(width: pdfPageBounds.width * scale, height: pdfPageBounds.height * scale) let thumbnail = pdfPage.thumbnail(of: thumbnailSize, for: .mediaBox) return thumbnail } public func updateFile(_ fileURL: URL, _ iconSize: CGSize) { let filePath = fileURL.path let fileName = filePath.getLastComponentDeleteExtension if let resultPath: String = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) { if let image = generateThumbnail(for: fileURL, iconSize) { guard let data = image.tiffRepresentation else { return } let imageRep = NSBitmapImageRep(data: data) imageRep?.size = image.size if let imageData = imageRep?.representation(using: .png, properties: [:]) { try?imageData.write(to: URL(fileURLWithPath: resultPath)) } } } } public func getFileThumb(_ fileURL: URL) -> NSImage? { let filePath = fileURL.path let fileName = filePath.getLastComponentDeleteExtension if let resultPath: String = thumbFolderPath?.stringByAppendingPathComponent((fileName + ".png")) { return NSImage(contentsOf: URL(fileURLWithPath: resultPath)) } return nil } @objc func tabClosingNotification(_ sender: Notification) { self.refreshData() } }