// // KMTools.swift // PDF Master // // Created by tangchao on 2023/3/7. // import Cocoa @objc class KMTools: NSObject { // MARK: - // MARK: 获取已打开的文件 @objc class func getOpenDocumentURLs() -> [URL] { var files:[URL] = [] for window in NSApp.windows { if ((window.windowController is KMBrowserWindowController) == false) { continue } let controller: KMBrowserWindowController = window.windowController as! KMBrowserWindowController let model = controller.browser?.tabStripModel guard let count = model?.count() else { continue } if (count <= 0) { continue } for i in 0 ..< count { let document = model?.tabContents(at: Int32(i)) // if (document?.windowControllers == nil || document?.windowControllers.count == 0) { // continue // } if (document?.fileURL == nil) { continue } if (document?.isHome == nil || document!.isHome) { continue } files.append((document?.fileURL)!) } } return files } // MARK: - // MARK: 无法区分 [权限+开启] [开启] 这两种情况 请不要使用 private class func isDocumentHasPermissionsPassword(_ url: URL) -> Bool { let document = PDFDocument(url: url) if (document == nil) { return false } if (document?.permissionsStatus == .user) { return true } // document?.permissionsStatus == .none if (document!.isLocked == false) { // 没有加锁 return false } // 已加锁 [权限+开启] [开启] if (KMTools.hasPermissionsLimit(document!)) { // 有权限限制 return true } return false } // MARK: - // MARK: 暂时只处理了复制和打印两项(后续项目需求有新增时,可以再此方法里扩展) @objc class func hasPermissionsLimit(_ document: PDFDocument) -> Bool { if (document.allowsCopying == false) { return true } if (document.allowsPrinting == false) { return true } return false } // MARK: - // MARK: 打开网页 @objc class func openURL(url: URL?) { guard let _url = url else { KMPrint("url invalid.") return } NSWorkspace.shared.open(_url) } @objc class func openURL(urlString: String?) { guard let _urlString = urlString else { KMPrint("url invalid.") return } KMTools.openURL(url: URL(string: _urlString)) } // MARK: - // MARK: 获取 App 版本号 @objc class func getAppVersion() -> String { let infoDictionary = Bundle.main.infoDictionary if (infoDictionary == nil) { return "1.0.0" } var version = infoDictionary!["CFBundleShortVersionString"] if (version != nil && (version is String) && (version as! String).isEmpty == false) { return version as! String } version = infoDictionary!["CFBundleVersion"] if (version != nil && (version is String) && (version as! String).isEmpty == false) { return version as! String } return "1.0.0" } class func getSystemVersion() -> (Int, Int, Int) { let versionInfo = ProcessInfo.processInfo.operatingSystemVersion return (versionInfo.majorVersion, versionInfo.minorVersion, versionInfo.patchVersion) } @objc class func isDefaultPDFReader() -> Bool { let app = LSCopyDefaultRoleHandlerForContentType("pdf" as CFString, LSRolesMask.all)?.takeUnretainedValue() if (app == nil) { return false } return (app! as String) == Bundle.main.bundleIdentifier! } @objc class func setDefaultPDFReader(_ isOrNo: Bool) -> Bool { var bid = "com.apple.Preview" if (isOrNo) { bid = Bundle.main.bundleIdentifier! } let status: OSStatus = LSSetDefaultRoleHandlerForContentType(KMTools.UTIforFileExtension("pdf") as CFString, LSRolesMask.all, bid as CFString) if (status == 0) { return true } return false } @objc class func UTIforFileExtension(_ exn: String) -> String { return (UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, exn as CFString, nil)?.takeUnretainedValue())! as String } // MARK: - // MARK: 是否全屏 @objc class func isFullScreen(_ window: NSWindow) -> Bool { return window.styleMask.contains(.fullScreen) } // MARK: - // MARK: 文件类型 static let imageExtensions = ["jpg","cur","bmp","jpeg","gif","png","tiff","tif",/*@"pic",*/"ico","icns","tga","psd","eps","hdr","jp2","jpc","pict","sgi","heic"] static let pdfExtensions = ["pdf"] static let officeExtensions = ["doc", "docx", "xls", "xlsx", "ppt", "pptx"] @objc class func isImageType(_ exn: String) -> Bool { return KMTools.imageExtensions.contains(exn.lowercased()) } @objc class func isPDFType(_ exn: String) -> Bool { return KMTools.pdfExtensions.contains(exn.lowercased()) } @objc class func isOfficeType(_ exn: String) -> Bool { return KMTools.officeExtensions.contains(exn.lowercased()) } } // MARK: - // MARK: PDFMaster extension KMTools { // 打开 [快速教学] @objc class func openQuickStartStudy() { // MARK: - // MARK: 内嵌文档需要替换 var fileName = "PDF Master User Guide" let fileType = "pdf" let path = Bundle.main.path(forResource: fileName, ofType: fileType) if (path == nil || FileManager.default.fileExists(atPath: path!) == false) { KMTools.openURL(url: URL(string: "https://www.pdfreaderpro.com/help")) return } let version = KMTools.getAppVersion() fileName.append(" v\(version).\(fileType)") let folderPath = NSSearchPathForDirectoriesInDomains(.applicationSupportDirectory, .userDomainMask, true).last?.appending("/\(Bundle.main.bundleIdentifier!)") if (FileManager.default.fileExists(atPath: folderPath!) == false) { try?FileManager.default.createDirectory(atPath: folderPath!, withIntermediateDirectories: false) } let toPath = "\(folderPath!)/\(fileName)" if (FileManager.default.fileExists(atPath: toPath)) { try?FileManager.default.removeItem(atPath: toPath) } try?FileManager.default.copyItem(atPath: path!, toPath: toPath) if !toPath.isPDFValid() { let alert = NSAlert() alert.alertStyle = .critical alert.messageText = NSLocalizedString("An error occurred while opening this document. The file is damaged and could not be repaired.", comment: "") alert.runModal() return } NSDocumentController.shared.openDocument(withContentsOf: URL(fileURLWithPath: toPath), display: true) { document, result, error in if (error != nil) { NSApp.presentError(error!) } } } // 打开 [FAQ] 网站 @objc class func openFAQWebsite() { // KMTools.openURL(URL(string: "")!) } // 打开 [更多产品] 网站 @objc class func openMoreProductWebsite() { KMTools.openURL(url: URL(string: "https://www.pdfreaderpro.com/product?utm_source=MacApp&utm_campaign=ProductLink&utm_medium=PdfProduct")) } // 打开 [免费 PDF 模板] 网站 @objc class func openFreePDFTemplatesWebsite() { KMTools.openURL(url: URL(string: "https://www.pdfreaderpro.com/templates?utm_source=MacApp&utm_campaign=TemplatesLink&utm_medium=PdfTemplates")) } // 打开 [ComPDFKit 授权] 网站 @objc class func openComPDFKitPowerWebsite() { KMTools.openURL(url: URL(string: "https://www.compdf.com/?utm_source=macapp&utm_medium=pdfmac&utm_campaign=compdfkit-promp")) } // 打开 [官网 下载页] 网站 // 测试环境 http://test-pdf-pro.kdan.cn:3021/pdf-master-mac-download @objc class func openDownloadDMGWebsite() { KMTools.openURL(urlString: "https://www.pdfreaderpro.com/pdf-master-mac-download") } // 意见反馈 @objc class func feekback() { let (major, minor, bugFix) = KMTools.getSystemVersion() let versionInfoString = "\(KMTools.getRawSystemInfo()) - \(major).\(minor).\(bugFix)" let appVersion = KMTools.getAppVersion() let appName = KMTools.getAppName() let subjects = "\(appName) - \(appVersion);\(NSLocalizedString("Propose a New Feature", comment: ""));\(versionInfoString)" // MARK: - // MARK TODO: 邮箱域名需要替换 let email = "support@pdfreaderpro.com" // MARK: - // MARK TODO: 邮箱域名需要替换 KMMailHelper.newEmail(withContacts: email, andSubjects: subjects) } @objc class func getRawSystemInfo() -> String { let info = GBDeviceInfo.deviceInfo().rawSystemInfoString if (info == nil) { return "" } return info! } @objc class func getAppName() -> String { let appTarget = KMTools_OC.getAppTarget() if (appTarget == .free) { return "PDF Master" } else if (appTarget == .pro) { return "PDF Master Pro" } else if (appTarget == .DMG) { // return "PDF Master DMG" return "PDF Master" } return "PDF Master" } @objc class func pageRangeTypeString(pageRange: KMPageRange) -> String { switch pageRange { case .all: return NSLocalizedString("All Pages", comment: "") case .current: return NSLocalizedString("Current Page", comment: "") case .odd: return NSLocalizedString("Odd Pages", comment: "") case .even: return NSLocalizedString("Even Pages", comment: "") case .custom: return NSLocalizedString("Customize", comment: "") } } }