123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479 |
- //
- // RCTCPDFView.swift
- // react-native-compdfkit-pdf
- //
- // Copyright © 2014-2025 PDF Technologies, Inc. All Rights Reserved.
- //
- // THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
- // AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
- // UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
- // This notice may not be removed from this file.
- //
- import UIKit
- import ComPDFKit_Tools
- import ComPDFKit
- protocol RCTCPDFViewDelegate: AnyObject {
- func cpdfViewAttached(_ cpdfView: RCTCPDFView)
- func saveDocumentChange(_ cpdfView: RCTCPDFView)
- func onPageChanged(_ cpdfView: RCTCPDFView, pageIndex: Int)
- }
- class RCTCPDFView: UIView, CPDFViewBaseControllerDelete {
- weak var delegate: RCTCPDFViewDelegate?
- public var pdfViewController : CPDFViewController?
- private var navigationController : CNavigationController?
- init() {
- super.init(frame: CGRect(x: 0, y: 0, width: 500, height: 400))
- }
- required init?(coder: NSCoder) {
- fatalError("init(coder:) has not been implemented")
- }
- // MARK: - Private Methods
- private func createCPDFView() {
- var documentPath = document.path
- var success = false
- let homeDiectory = NSHomeDirectory()
- let bundlePath = Bundle.main.bundlePath
- if (documentPath.hasPrefix(homeDiectory) || documentPath.hasPrefix(bundlePath)) {
- let fileManager = FileManager.default
- let samplesFilePath = NSHomeDirectory().appending("/Documents/Files")
- let fileName = document.lastPathComponent
- let docsFilePath = samplesFilePath + "/" + fileName
- if !fileManager.fileExists(atPath: samplesFilePath) {
- try? FileManager.default.createDirectory(atPath: samplesFilePath, withIntermediateDirectories: true, attributes: nil)
- }
- try? FileManager.default.copyItem(atPath: document.path, toPath: docsFilePath)
- documentPath = docsFilePath
- } else {
- success = document.startAccessingSecurityScopedResource()
- }
- let jsonData = CPDFJSONDataParse(String: configuration)
- let configurations = jsonData.configuration ?? CPDFConfiguration()
- pdfViewController = CPDFViewController(filePath: documentPath, password: password, configuration: configurations)
- pdfViewController?.delegate = self
- navigationController = CNavigationController(rootViewController: pdfViewController!)
- navigationController?.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
- navigationController?.view.frame = self.frame
- navigationController?.setViewControllers([pdfViewController!], animated: true)
- addSubview(navigationController?.view ?? UIView())
- self.delegate?.cpdfViewAttached(self)
- if success {
- document.stopAccessingSecurityScopedResource()
- }
- }
- // MARK: - Public Methods
- func saveDocument(completionHandler: @escaping (Bool) -> Void) {
- if (self.pdfViewController?.pdfListView?.isEditing() == true && self.pdfViewController?.pdfListView?.isEdited() == true) {
- self.pdfViewController?.pdfListView?.commitEditing()
- if self.pdfViewController?.pdfListView?.document.isModified() == true {
- let document = self.pdfViewController?.pdfListView?.document
- let success = document?.write(to: document?.documentURL ?? URL(fileURLWithPath: ""), isSaveFontSubset: true) ?? false
- completionHandler(success)
- } else {
- completionHandler(true)
- }
- } else {
- if self.pdfViewController?.pdfListView?.document.isModified() == true {
- let document = self.pdfViewController?.pdfListView?.document
- let success = document?.write(to: document?.documentURL ?? URL(fileURLWithPath: ""), isSaveFontSubset: true) ?? false
- completionHandler(success)
- } else {
- completionHandler(true)
- }
- }
- }
- func setMargins(left : Int, top : Int, right : Int, bottom : Int) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.pageBreakMargins = .init(top: CGFloat(top), left: CGFloat(left), bottom: CGFloat(bottom), right: CGFloat(right))
- pdfListView.layoutDocumentView()
- }
- }
- func removeAllAnnotations(completionHandler: @escaping (Bool) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let pageCount = pdfListView.document?.pageCount ?? 0
- for i in 0..<pageCount {
- let page = pdfListView.document?.page(at: i)
- page?.removeAllAnnotations()
- }
- self.pdfViewController?.pdfListView?.setNeedsDisplayForVisiblePages()
- self.pdfViewController?.pdfListView?.updateActiveAnnotations([])
- completionHandler(true)
- } else {
- completionHandler(false)
- }
- }
- func importAnnotations(xfdfFile : URL, completionHandler: @escaping (Bool) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let documentFolder = NSHomeDirectory().appending("/Documents/Files")
- if !FileManager.default.fileExists(atPath: documentFolder) {
- try? FileManager.default.createDirectory(at: URL(fileURLWithPath: documentFolder), withIntermediateDirectories: true, attributes: nil)
- }
- let documentPath = documentFolder + "/\(xfdfFile.lastPathComponent)"
- try? FileManager.default.copyItem(atPath: xfdfFile.path, toPath: documentPath)
- if !FileManager.default.fileExists(atPath: documentPath) {
- print("fail")
- }
- let success = pdfListView.document?.importAnnotation(fromXFDFPath: documentPath) ?? false
- if success {
- self.pdfViewController?.pdfListView?.setNeedsDisplayForVisiblePages()
- }
- completionHandler(success)
- } else {
- completionHandler(false)
- }
- }
- func exportAnnotations(completionHandler: @escaping (String) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let fileNameWithExtension = pdfListView.document?.documentURL.lastPathComponent ?? ""
- let fileName = (fileNameWithExtension as NSString).deletingPathExtension
- let documentFolder = NSHomeDirectory().appending("/Documents/\(fileName)_xfdf.xfdf")
- let succes = pdfListView.document?.exportAnnotation(toXFDFPath: documentFolder) ?? false
- if succes {
- completionHandler(documentFolder)
- } else {
- completionHandler("")
- }
- } else {
- completionHandler("")
- }
- }
- func setDisplayPageIndex(pageIndex : Int) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.go(toPageIndex: pageIndex, animated: false)
- }
- }
- func getCurrentPageIndex(completionHandler: @escaping (Int) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.currentPageIndex)
- } else {
- completionHandler(0)
- }
- }
- func hasChange(completionHandler: @escaping (Bool) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let success = pdfListView.document?.isModified() ?? false
- completionHandler(success)
- } else {
- completionHandler(false)
- }
- }
- func setScale(scale : NSNumber){
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.setScaleFactor(CGFloat(truncating: scale), animated: true)
- }
- }
- func getScale(completionHandler: @escaping (NSNumber) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(NSNumber(value: pdfListView.scaleFactor))
- } else {
- completionHandler(1.0)
- }
- }
- func setReadBackgroundColor(displayMode : NSString) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- switch displayMode {
- case "light":
- pdfListView.displayMode = .normal
- case "dark":
- pdfListView.displayMode = .night
- case "sepia":
- pdfListView.displayMode = .soft
- case "reseda":
- pdfListView.displayMode = .green
- default:
- pdfListView.displayMode = .normal
- }
- pdfListView.layoutDocumentView()
- }
- }
- func getReadbackgroundColor(completionHandler: @escaping (NSString) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let dispalyMode = pdfListView.displayMode
- switch dispalyMode {
- case .normal:
- completionHandler("#FFFFFF")
- case .night:
- completionHandler("#000000")
- case .soft:
- completionHandler("#FFFFFF")
- case .green:
- completionHandler("#FFEFBE")
- case .custom:
- completionHandler("#CDE6D0")
- @unknown default:
- completionHandler("#FFFFFF")
- }
- } else {
- completionHandler("#FFFFFF")
- }
- }
- func setFormFieldHighlight(formFieldHighlight : Bool){
- if let pdfListView = self.pdfViewController?.pdfListView {
- CPDFKitConfig.sharedInstance().setEnableFormFieldHighlight(formFieldHighlight)
- pdfListView.layoutDocumentView()
- }
- }
- func isFormFieldHighlight(completionHandler: @escaping (Bool) -> Void){
- completionHandler(CPDFKitConfig.sharedInstance().enableFormFieldHighlight())
- }
- func setLinkHighlight(linkHighlight : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- CPDFKitConfig.sharedInstance().setEnableLinkFieldHighlight(linkHighlight)
- pdfListView.layoutDocumentView()
- }
- }
- func isLinkHighlight(completionHandler: @escaping (Bool) -> Void){
- completionHandler(CPDFKitConfig.sharedInstance().enableLinkFieldHighlight())
- }
- func setVerticalMode(isVerticalMode : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.displayDirection = isVerticalMode ? .vertical : .horizontal
- pdfListView.layoutDocumentView()
- }
- }
- func isVerticalMode(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.displayDirection == .vertical)
- } else {
- completionHandler(true)
- }
- }
- func setContinueMode(isContinueMode : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.displaysPageBreaks = isContinueMode
- pdfListView.layoutDocumentView()
- }
- }
- func isContinueMode(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.displaysPageBreaks)
- }else {
- completionHandler(true)
- }
- }
- func setDoublePageMode(isDoublePageMode : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.displayTwoUp = isDoublePageMode
- pdfListView.displaysAsBook = false
- pdfListView.layoutDocumentView()
- }
- }
- func isDoublePageMode(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.displayTwoUp)
- }else {
- completionHandler(true)
- }
- }
- func setCoverPageMode(isCoverPageMode : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.displayTwoUp = isCoverPageMode
- pdfListView.displaysAsBook = isCoverPageMode
- pdfListView.layoutDocumentView()
- }
- }
- func isCoverPageMode(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.displaysAsBook)
- }else {
- completionHandler(true)
- }
- }
- func setCropMode(isCropMode : Bool) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- pdfListView.displayCrop = isCropMode
- pdfListView.layoutDocumentView()
- }
- }
- func isCropMode(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.displayCrop)
- }else {
- completionHandler(true)
- }
- }
- func getFileName(completionHandler: @escaping (String) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.documentURL.lastPathComponent)
- }else {
- completionHandler("")
- }
- }
- func isEncrypted(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.isEncrypted)
- }else {
- completionHandler(false)
- }
- }
- func isImageDoc(completionHandler: @escaping (Bool) -> Void){
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.isImageDocument())
- }else {
- completionHandler(false)
- }
- }
- func getPermissions(completionHandler: @escaping (NSNumber) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let permissions = pdfListView.document?.permissionsStatus ?? .none
- switch permissions {
- case .none:
- completionHandler(0)
- case .user:
- completionHandler(1)
- case .owner:
- completionHandler(2)
- default:
- completionHandler(0)
- }
- }else {
- completionHandler(0)
- }
- }
- func getPageCount(completionHandler: @escaping (NSNumber) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.pageCount as NSNumber)
- }else {
- completionHandler(0)
- }
- }
- func checkOwnerUnlocked(completionHandler: @escaping (Bool) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.isCheckOwnerUnlocked())
- }else {
- completionHandler(false)
- }
- }
- func checkOwnerPassword(password : String, completionHandler: @escaping (Bool) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- completionHandler(pdfListView.document.checkOwnerPassword(password))
- }else {
- completionHandler(false)
- }
- }
- func getEncryptAlgo(completionHandler: @escaping (String) -> Void) {
- if let pdfListView = self.pdfViewController?.pdfListView {
- let encryptAlgo = pdfListView.document.encryptionLevel
- switch encryptAlgo {
- case .RC4:
- completionHandler("rc4")
- case .AES128:
- completionHandler("aes128")
- case .AES256:
- completionHandler("aes256")
- case .noEncryptAlgo:
- completionHandler("noEncryptAlgo")
- default:
- completionHandler("noEncryptAlgo")
- }
- }else {
- completionHandler("noEncryptAlgo")
- }
- }
- // MARK: - CPDFViewBaseControllerDelete
- func PDFViewBaseController(_ baseController: CPDFViewBaseController, SaveState success: Bool) {
- self.delegate?.saveDocumentChange(self)
- }
- func PDFViewBaseController(_ baseController: CPDFViewBaseController, currentPageIndex index: Int) {
- self.delegate?.onPageChanged(self, pageIndex: index)
- }
- // MARK: - RCT Methods
- private var configuration: String = ""
- @objc func setConfiguration(_ newSection: String) {
- configuration = newSection
- if (document.path.count > 1) && (configuration.count > 1) {
- createCPDFView()
- }
- }
- private var document: URL = URL(fileURLWithPath: "")
- @objc func setDocument(_ newSection: URL) {
- document = newSection
- if (document.path.count > 1) && (configuration.count > 1) {
- createCPDFView()
- }
- }
- private var password: String = ""
- @objc func setPassword(_ newSection: String) {
- password = newSection
- }
- public var onChange: RCTBubblingEventBlock?
- @objc func setOnChange(_ newSection: @escaping RCTBubblingEventBlock) {
- onChange = newSection
- }
- }
|