Browse Source

【同步】文字同步相关代码导入

lizhe 1 year ago
parent
commit
83e88df018

+ 2 - 2
PDF Office/PDF Master/Class/DigtalSignature/DSignatureApperanceManager.swift

@@ -61,7 +61,7 @@ class DSignatureApperanceManager: NSObject {
         var verItem: CPDFSignatureConfigItem!
         
         for item in contens {
-            if (item as! CPDFSignatureConfigItem).key == NAME_KEY {
+            if (item as! CPDFSignatureConfigItem).key == kNAME_KEY {
                 nameItem = item as? CPDFSignatureConfigItem
             } else if (item as! CPDFSignatureConfigItem).key == DN_KEY {
                 dnItem = item as? CPDFSignatureConfigItem
@@ -187,7 +187,7 @@ class DSignatureApperanceManager: NSObject {
 #endif
         
         let nameItem = CPDFSignatureConfigItem.init()
-        nameItem.key = NAME_KEY
+        nameItem.key = kNAME_KEY
         nameItem.value = NSLocalizedString("<your common name here>", comment: "")
         
         let dateItem = CPDFSignatureConfigItem.init()

+ 2 - 2
PDF Office/PDF Master/Class/DigtalSignature/DSignatureConfig.swift

@@ -7,7 +7,7 @@
 
 import Foundation
 
-let NAME_KEY = NSLocalizedString("Signed by", comment: "")
+let kNAME_KEY = NSLocalizedString("Signed by", comment: "")
 let DN_KEY = NSLocalizedString("DN", comment: "")
 let REASON_KEY = NSLocalizedString("Reason", comment: "")
 let LOCATION_KEY = NSLocalizedString("Location", comment: "")
@@ -115,7 +115,7 @@ class DSignatureConfig {
 
 @objcMembers public class Swift_oc_Tool: NSObject {
     
-    static let NAME_KEY_OC = NAME_KEY
+    static let NAME_KEY_OC = kNAME_KEY
     static let DN_KEY_OC = DN_KEY
     static let REASON_KEY_OC = REASON_KEY
     static let LOCATION_KEY_OC = LOCATION_KEY

+ 5 - 5
PDF Office/PDF Master/Class/DigtalSignature/ViewControllers/CDSignatureCertificateCustomViewController.swift

@@ -116,7 +116,7 @@ class CDSignatureCertificateCustomViewController: NSViewController, NSTextFieldD
             self.distinguishedButton.state = .on
         }
         
-        if keys.contains(NAME_KEY) {
+        if keys.contains(kNAME_KEY) {
             self.nameButton.state = .on
         }
         
@@ -439,7 +439,7 @@ class CDSignatureCertificateCustomViewController: NSViewController, NSTextFieldD
         let contents = NSMutableArray(array: self.appearanceData.signatureConfig.contents)
         if contents.count <= 1 && self.customType == .none {
             let configItem: CPDFSignatureConfigItem = contents.firstObject as! CPDFSignatureConfigItem
-            if configItem.key == NAME_KEY && self.appearanceData.signatureConfig.isDrawKey {
+            if configItem.key == kNAME_KEY && self.appearanceData.signatureConfig.isDrawKey {
                 if self.nameButton.state == .off {
                     contents.removeAllObjects()
                 }
@@ -454,13 +454,13 @@ class CDSignatureCertificateCustomViewController: NSViewController, NSTextFieldD
         if self.nameButton.isEqual(sender) {
             if self.nameButton.state == .on {
                 configItem = CPDFSignatureConfigItem.init()
-                configItem.key = NAME_KEY
+                configItem.key = kNAME_KEY
                 configItem.value = NSLocalizedString("<your common name here>", comment: "")
                 contents.add(configItem as Any)
             } else {
                 for item in contents {
                     let exitItem: CPDFSignatureConfigItem = item as! CPDFSignatureConfigItem
-                    if exitItem.key == NAME_KEY {
+                    if exitItem.key == kNAME_KEY {
                         configItem = item as? CPDFSignatureConfigItem
                         break
                     }
@@ -610,7 +610,7 @@ class CDSignatureCertificateCustomViewController: NSViewController, NSTextFieldD
         
         if self.customType == .none && contents.count == 0 {
             configItem = CPDFSignatureConfigItem.init()
-            configItem.key = NAME_KEY
+            configItem.key = kNAME_KEY
             configItem.value = NSLocalizedString("<your common name here>", comment: "")
             contents.add(configItem as Any)
             

+ 105 - 0
PDF Office/PDF Master/Class/Document/KMMainDocument.swift

@@ -1028,3 +1028,108 @@ extension NSDocument {
         return "PDF Reader Pro password"
     }
 }
+
+extension KMMainDocument: SKPDFSynchronizerDelegate {
+    func synchronizer(_ synchronizer: SKPDFSynchronizer!, foundLine line: Int, inFile file: String!) {
+        if FileManager.default.fileExists(atPath: file) {
+            let defaults = UserDefaults.standard
+            
+            var editorPreset = defaults.string(forKey: SKTeXEditorPresetKey) ?? ""
+            var editorCmd: String?
+            var editorArgs: String?
+            var cmdString: String?
+                
+            if !KMSyncPreferences.getTeXEditorCommand(command: &editorCmd, arguments: &editorArgs, forPreset: editorPreset) {
+                editorCmd = defaults.string(forKey: SKTeXEditorCommandKey)
+                editorArgs = defaults.string(forKey: SKTeXEditorArgumentsKey)
+            }
+                
+            if var cmdString = editorArgs {
+                if !editorCmd!.hasPrefix("/") {
+                    var searchPaths = ["/usr/bin", "/usr/local/bin"]
+                    var toolPath: String?
+                    
+                    let fm = FileManager.default
+                    
+                    if !(editorPreset.isEmpty) {
+                        if let path = NSWorkspace.shared.fullPath(forApplication: editorPreset) {
+                            if let appBundle = Bundle(path: path) {
+                                if let contentsPath = appBundle.path(forResource: "Contents", ofType: nil) {
+                                    searchPaths.insert(contentsPath, at: 0)
+                                }
+                                if editorPreset != "BBEdit", let execPath = appBundle.executablePath {
+                                    searchPaths.insert(execPath, at: 0)
+                                }
+                                if let resourcePath = appBundle.resourcePath {
+                                    searchPaths.insert(resourcePath, at: 0)
+                                }
+                                if let sharedSupportPath = appBundle.sharedSupportPath {
+                                    searchPaths.insert(sharedSupportPath, at: 0)
+                                }
+                            }
+                        }
+                    } else {
+                        let appSupportDirs = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask)
+                        let appSupportPaths = appSupportDirs.map { $0.path }
+                        searchPaths.append(contentsOf: appSupportPaths)
+                    }
+                    
+                    for path in searchPaths {
+                        toolPath = (path as NSString).appendingPathComponent(editorCmd!)
+                        if fm.isExecutableFile(atPath: toolPath!) {
+                            editorCmd = toolPath
+                            break
+                        }
+                        toolPath = ((path as NSString).appendingPathComponent("bin") as NSString).appendingPathComponent(editorCmd!)
+                        if fm.isExecutableFile(atPath: toolPath!) {
+                            editorCmd = toolPath
+                            break
+                        }
+                    }
+                }
+                
+                cmdString = cmdString.replacingOccurrences(of: "%line", with: "\(line + 1)")
+                cmdString = cmdString.replacingOccurrences(of: "%file", with: file)
+                cmdString = cmdString.replacingOccurrences(of: "%output", with: fileURL?.path ?? "")
+                
+                cmdString.insert(contentsOf: "\" ", at: cmdString.startIndex)
+                cmdString.insert(contentsOf: editorCmd!, at: cmdString.startIndex)
+                cmdString.insert("\"", at: cmdString.startIndex)
+                
+                let ws = NSWorkspace.shared
+                if let theUTI = try? ws.type(ofFile: editorCmd!) {
+                    if ws.type(theUTI, conformsToType: "com.apple.applescript.script") || ws.type(theUTI, conformsToType: "com.apple.applescript.text") {
+                        cmdString.insert(contentsOf: "/usr/bin/osascript ", at: cmdString.startIndex)
+                    }
+                }
+                
+                let task = Process()
+                task.launchPath = "/bin/sh"
+                task.currentDirectoryPath = (file as NSString).deletingLastPathComponent
+                task.arguments = ["-c", cmdString]
+                task.standardOutput = FileHandle.nullDevice
+                task.standardError = FileHandle.nullDevice
+                do {
+                    try task.run()
+                } catch let error {
+                    Swift.print("command failed: \(cmdString ?? ""): \(error)")
+                }
+            }
+        }
+    }
+    
+    func synchronizer(_ synchronizer: SKPDFSynchronizer!, foundLocation point: NSPoint, atPageIndex pageIndex: UInt, options: Int) {
+        guard let pdfDoc = self.mainViewController?.document else { return }
+        if pageIndex < pdfDoc.pageCount {
+            if let page = pdfDoc.page(at: pageIndex) {
+                var adjustedPoint = point
+                if options & SKPDFSynchronizerFlippedMask != 0 {
+                    let mediaBox = page.bounds(for: .mediaBox)
+                    adjustedPoint.y = NSMaxY(mediaBox) - adjustedPoint.y
+                }
+                
+                self.mainViewController?.listView.displayLine(at: adjustedPoint, inPageAtIndex: Int(pageIndex), showReadingBar: options & SKPDFSynchronizerShowReadingBarMask != 0)
+            }
+        }
+    }
+}

+ 80 - 0
PDF Office/PDF Master/Class/PDFWindowController/PDFListView/CPDFListViewExtension/CPDFListView+Sync.swift

@@ -0,0 +1,80 @@
+//
+//  CPDFListView+Sync.swift
+//  PDF Reader Pro
+//
+//  Created by lizhe on 2024/2/29.
+//
+
+import Foundation
+
+extension CPDFListView {
+    
+    func displayLine(at point: NSPoint, inPageAtIndex pageIndex: Int, showReadingBar: Bool) {
+        guard pageIndex < document?.pageCount ?? 0 else { return }
+        
+        if let page = document?.page(at: UInt(pageIndex)) {
+            let sel: CPDFSelection
+            if let selection = page.selectionForLine(at: point) {
+                sel = selection
+            } else {
+                let lineRect = SKRectFromCenterAndSquareSize(point, 10.0)
+                sel = CPDFSelection(page: page, rect: lineRect)
+            }
+            
+            var lineRect = sel.hasCharacters() ? sel.bounds(for: page) : SKRectFromCenterAndSquareSize(point, 10.0)
+            var rect = lineRect
+            
+            let wasPageDisplayed = displayedPageIndexRange().contains(pageIndex)
+            if !wasPageDisplayed {
+                self.go(toPageIndex: Int(page.pageIndex()), animated: true)
+            }
+            
+//            var userInfo: [AnyHashable: Any] = [SKPDFViewOldPageKey: readingBar.page ?? NSNull()]
+            
+//            if interactionMode != .presentationMode {
+//                if showReadingBar {
+//                    if !hasReadingBar {
+//                        toggleReadingBar(nil)
+//                    }
+//                    readingBar.page = page
+//                    readingBar.goToLine(for: point)
+//                    requiresDisplay()
+//                    userInfo[SKPDFViewNewPageKey] = page
+//                    NotificationCenter.default.post(name: SKPDFViewReadingBarDidChangeNotification, object: self, userInfo: userInfo)
+//                } else if sel.hasCharacters && toolMode == .textToolMode {
+//                    setCurrentSelection(sel)
+//                }
+//            }
+            
+            var visibleRect = convert(visibleContentRect(), to: page)
+            
+            if !wasPageDisplayed || !visibleRect.contains(lineRect) {
+                if displayMode() == .singlePageContinuous || displayMode() == .twoUpContinuous {
+                    let heightDiff = NSHeight(visibleRect) - NSHeight(lineRect)
+                    rect = NSInsetRect(lineRect, 0.0, -floor(heightDiff / 2.0))
+                }
+                if NSWidth(rect) > NSWidth(visibleRect) {
+                    if NSMaxX(rect) < point.x + 0.5 * NSWidth(visibleRect) {
+                        rect.origin.x = NSMaxX(rect) - NSWidth(visibleRect)
+                    } else if NSMinX(rect) < point.x - 0.5 * NSWidth(visibleRect) {
+                        rect.origin.x = floor(point.x - 0.5 * NSWidth(visibleRect))
+                    }
+                    rect.size.width = NSWidth(visibleRect)
+                }
+                rect = convert(convert(rect, from: page), to: documentView())
+                documentView().scrollToVisible(rect)
+            }
+            
+//            syncDot?.invalidate()
+//            syncDot = KMSyncDot(point: point, page: page) { [weak self] finished in
+//                guard let self = self else { return }
+//                
+//                self.setNeedsDisplayIn(self.syncDot!.bounds(), of: self.syncDot?.page)
+////                self.setNeedsDisplay(self.syncDot?.bounds ?? .zero, ofPage: self.syncDot?.page)
+//                if finished {
+//                    self.syncDot = nil
+//                }
+//            }
+        }
+    }
+}

+ 88 - 0
PDF Office/PDF Master/Class/Parsers/Data/KMSyncDot.swift

@@ -0,0 +1,88 @@
+//
+//  KMSyncDot.swift
+//  PDF Reader Pro
+//
+//  Created by lizhe on 2024/2/29.
+//
+
+import Cocoa
+import QuartzCore
+
+class KMSyncDot: NSObject {
+    var point: NSPoint
+    var page: CPDFPage?
+    private var phase: Int = 0
+    private var timer: Timer?
+    private var handler: ((Bool) -> Void)?
+
+    init(point: NSPoint, page: CPDFPage?, updateHandler: ((Bool) -> Void)?) {
+        self.point = point
+        self.page = page
+        self.handler = updateHandler
+        super.init()
+        setup()
+    }
+
+    required init?(coder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+
+    private func setup() {
+        timer = Timer.scheduledTimer(timeInterval: 0.05, target: self, selector: #selector(animate(_:)), userInfo: nil, repeats: true)
+    }
+
+    deinit {
+        timer?.invalidate()
+        handler = nil
+    }
+
+    @objc private func finish(_ timer: Timer) {
+        timer.invalidate()
+        if let handler = handler {
+            handler(true)
+        }
+    }
+
+    @objc private func animate(_ timer: Timer) {
+        phase += 1
+        if phase >= 10 {
+            timer.invalidate()
+            self.timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(finish(_:)), userInfo: nil, repeats: false)
+        }
+        if let handler = handler {
+            handler(false)
+        }
+    }
+
+    func invalidate() {
+        timer?.invalidate()
+    }
+    
+    func bounds() -> NSRect {
+        return KMRectFromCenterAndSquareSize(center: point, size: 22.0) ?? CGRectZero
+    }
+
+    func draw(in ctx: CGContext) {
+        ctx.saveGState()
+
+        var s: CGFloat = 6.0
+        OSMemoryBarrier()
+        if phase < 10 {
+            s += 8.0 * sin(CGFloat(phase) * 0.1 * .pi)
+            let components: [CGFloat] = [1.0, 0.3, 0.3, 1.0, 1.0, 0.0, 0.0, 1.0]
+            let locations: [CGFloat] = [0.0, 1.0]
+            let colorspace = CGColorSpaceCreateDeviceRGB()
+            if let gradient = CGGradient(colorSpace: colorspace, colorComponents: components, locations: locations, count: 2) {
+                ctx.addEllipse(in: CGRect(x: point.x - 0.5 * s, y: point.y - 0.5 * s, width: s, height: s))
+                ctx.clip()
+                ctx.drawRadialGradient(gradient, startCenter: CGPoint(x: point.x, y: point.y + 0.35 * s), startRadius: 0.0, endCenter: CGPoint(x: point.x, y: point.y), endRadius: 0.5 * s, options: [])
+            }
+        } else {
+            ctx.setBlendMode(.multiply)
+            ctx.setFillColor(CGColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0))
+            ctx.fillEllipse(in: CGRect(x: point.x - 0.5 * s, y: point.y - 0.5 * s, width: s, height: s))
+        }
+
+        ctx.restoreGState()
+    }
+}

+ 20 - 8
PDF Office/PDF Master/Class/Preference/Controller/KMSyncPreferences.swift

@@ -7,6 +7,13 @@
 
 import Cocoa
 
+var TeXEditors: [[String : Any]] = []
+let NAME_KEY = "name"
+var INITIALUSERDEFAULTS_KEY = "InitialUserDefaults"
+var TEXEDITORS_KEY = "TeXEditors"
+var COMMAND_KEY = "command"
+var ARGUMENTS_KEY = "arguments"
+
 class KMSyncPreferences: NSViewController {
     var customTeXEditor = false
     /*
@@ -27,13 +34,6 @@ class KMSyncPreferences: NSViewController {
     var texEditorLabels: [NSTextField] = []
     var texEditorControls: [NSControl] = []
     
-    var TeXEditors: [[String : Any]] = []
-    var NAME_KEY = "name"
-    var INITIALUSERDEFAULTS_KEY = "InitialUserDefaults"
-    var TEXEDITORS_KEY = "TeXEditors"
-    var COMMAND_KEY = "command"
-    var ARGUMENTS_KEY = "arguments"
-    
     override var nibName: NSNib.Name? {
         return "SyncPreferences"
     }
@@ -50,7 +50,7 @@ class KMSyncPreferences: NSViewController {
         
         
         let editorPreset = UserDefaults.standard.string(forKey: SKTeXEditorPresetKey)
-        var i = self.TeXEditors.count
+        var i = TeXEditors.count
         var idx = -1
         let texEditorPopUpButton = self.presetButton
         let ws = NSWorkspace.shared
@@ -107,6 +107,18 @@ class KMSyncPreferences: NSViewController {
          return NO;
      }
      */
+    
+    static func getTeXEditorCommand(command: inout String?, arguments: inout String?, forPreset name: String) -> Bool {
+        for editor in TeXEditors {
+            if let editorName = editor[NAME_KEY] as? String, editorName == name {
+                command = editor[COMMAND_KEY] as? String
+                arguments = editor[ARGUMENTS_KEY] as? String
+                return true
+            }
+        }
+        return false
+    }
+    
     @IBAction func changeTeXEditorPreset(_ sender: AnyObject) {
         let sudc = NSUserDefaultsController.shared.defaults
         let idx = sender.indexOfSelectedItem()

+ 1 - 0
PDF Office/PDF Master/PDF_Reader_Pro DMG-Bridging-Header.h

@@ -109,3 +109,4 @@
 //同步
 #import "synctex_parser.h"
 #import "KMStatusBar.h"
+#import "SKPDFSynchronizer.h"

+ 1 - 0
PDF Office/PDF Master/PDF_Reader_Pro Edition-Bridging-Header.h

@@ -105,3 +105,4 @@
 //同步
 #import "synctex_parser.h"
 #import "KMStatusBar.h"
+#import "SKPDFSynchronizer.h"

+ 1 - 1
PDF Office/PDF Master/PDF_Reader_Pro-Bridging-Header.h

@@ -105,4 +105,4 @@
 //同步
 #import "synctex_parser.h"
 #import "KMStatusBar.h"
-
+#import "SKPDFSynchronizer.h"

+ 24 - 0
PDF Office/PDF Reader Pro.xcodeproj/project.pbxproj

@@ -1626,6 +1626,12 @@
 		AD7D5CA52B8F35D1006562CD /* SKPDFSyncRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA32B8F35D1006562CD /* SKPDFSyncRecord.m */; };
 		AD7D5CA62B8F35D1006562CD /* SKPDFSyncRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA32B8F35D1006562CD /* SKPDFSyncRecord.m */; };
 		AD7D5CA72B8F35D1006562CD /* SKPDFSyncRecord.m in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA32B8F35D1006562CD /* SKPDFSyncRecord.m */; };
+		AD7D5CA92B906E36006562CD /* CPDFListView+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA82B906E36006562CD /* CPDFListView+Sync.swift */; };
+		AD7D5CAA2B906E36006562CD /* CPDFListView+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA82B906E36006562CD /* CPDFListView+Sync.swift */; };
+		AD7D5CAB2B906E36006562CD /* CPDFListView+Sync.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CA82B906E36006562CD /* CPDFListView+Sync.swift */; };
+		AD7D5CB32B9070AF006562CD /* KMSyncDot.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CB22B9070AF006562CD /* KMSyncDot.swift */; };
+		AD7D5CB42B9070AF006562CD /* KMSyncDot.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CB22B9070AF006562CD /* KMSyncDot.swift */; };
+		AD7D5CB52B9070AF006562CD /* KMSyncDot.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD7D5CB22B9070AF006562CD /* KMSyncDot.swift */; };
 		AD85D1822AEF46C2000F4D28 /* KMHomeNOFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD85D1812AEF46C2000F4D28 /* KMHomeNOFileView.swift */; };
 		AD85D1832AEF46C2000F4D28 /* KMHomeNOFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD85D1812AEF46C2000F4D28 /* KMHomeNOFileView.swift */; };
 		AD85D1842AEF46C2000F4D28 /* KMHomeNOFileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = AD85D1812AEF46C2000F4D28 /* KMHomeNOFileView.swift */; };
@@ -5798,6 +5804,8 @@
 		AD7D5C9F2B8F34EC006562CD /* SKPDFSynchronizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKPDFSynchronizer.m; sourceTree = "<group>"; };
 		AD7D5CA32B8F35D1006562CD /* SKPDFSyncRecord.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SKPDFSyncRecord.m; sourceTree = "<group>"; };
 		AD7D5CA42B8F35D1006562CD /* SKPDFSyncRecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SKPDFSyncRecord.h; sourceTree = "<group>"; };
+		AD7D5CA82B906E36006562CD /* CPDFListView+Sync.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CPDFListView+Sync.swift"; sourceTree = "<group>"; };
+		AD7D5CB22B9070AF006562CD /* KMSyncDot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMSyncDot.swift; sourceTree = "<group>"; };
 		AD85D1812AEF46C2000F4D28 /* KMHomeNOFileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMHomeNOFileView.swift; sourceTree = "<group>"; };
 		AD85D1862AEF46DF000F4D28 /* KMHomeNOFileView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KMHomeNOFileView.xib; sourceTree = "<group>"; };
 		AD85D19D2AEF927D000F4D28 /* KMQucikToolsModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KMQucikToolsModel.swift; sourceTree = "<group>"; };
@@ -9043,6 +9051,7 @@
 		AD7D5C7F2B8ECC74006562CD /* Parsers */ = {
 			isa = PBXGroup;
 			children = (
+				AD7D5CAC2B906FC9006562CD /* Data */,
 				AD7D5CA42B8F35D1006562CD /* SKPDFSyncRecord.h */,
 				AD7D5CA32B8F35D1006562CD /* SKPDFSyncRecord.m */,
 				AD7D5C9E2B8F34EC006562CD /* SKPDFSynchronizer.h */,
@@ -9069,6 +9078,14 @@
 			path = "synctex-parser";
 			sourceTree = "<group>";
 		};
+		AD7D5CAC2B906FC9006562CD /* Data */ = {
+			isa = PBXGroup;
+			children = (
+				AD7D5CB22B9070AF006562CD /* KMSyncDot.swift */,
+			);
+			path = Data;
+			sourceTree = "<group>";
+		};
 		AD85D1852AEF46C9000F4D28 /* NoFileView */ = {
 			isa = PBXGroup;
 			children = (
@@ -11965,6 +11982,7 @@
 				F36AD77529642FE80015AD53 /* CPDFListView+UndoManager.h */,
 				F36AD77629642FE80015AD53 /* CPDFListView+UndoManager.m */,
 				9FF0D0522B6A3EE40018A732 /* CPDFListView+Form.swift */,
+				AD7D5CA82B906E36006562CD /* CPDFListView+Sync.swift */,
 			);
 			path = CPDFListViewExtension;
 			sourceTree = "<group>";
@@ -15306,6 +15324,7 @@
 				BB1331542AD7A6A1008F6791 /* KMFileAttribute.swift in Sources */,
 				BB0A55182A3074F400B6E84B /* KMHoverView.swift in Sources */,
 				9F53D54F2AD677A000CCF9D8 /* CPDFListViewConfig.swift in Sources */,
+				AD7D5CB32B9070AF006562CD /* KMSyncDot.swift in Sources */,
 				BB2A98522B270B3300647AF3 /* KMBatchAddBackgroundOperation.swift in Sources */,
 				9F0CB4C4298625F400007028 /* NSColor+KMExtensions.swift in Sources */,
 				BBD1F78F296FE6A500343885 /* KMPageEditSplitWindowController.swift in Sources */,
@@ -15932,6 +15951,7 @@
 				BB9E2F732A495BCD000DC68D /* KMConvertSettingLimitTipView.swift in Sources */,
 				9F1F82E32934D5240092C4B4 /* KMHomeExtractActionViewController.swift in Sources */,
 				89D2D2C5294972B900BFF5FE /* KMFormCellView.swift in Sources */,
+				AD7D5CA92B906E36006562CD /* CPDFListView+Sync.swift in Sources */,
 				BB6BA4C42B0B4A0F00462CAE /* KMLeftSideEmptyFileViewController.swift in Sources */,
 				BB897224294B07960045787C /* KMWatermarkAdjectiveTopBarItemView.swift in Sources */,
 				AD3AAD1B2B0B5B4400DE5FE7 /* KMCompareCoveringWindowController.swift in Sources */,
@@ -16283,6 +16303,7 @@
 				BBC3484B2958222C008D2CD1 /* KMBackgroundOutsideView.swift in Sources */,
 				AD1D48222AFB6BBA007AC1F0 /* KMMergeView.swift in Sources */,
 				BB90E4F32AF37F9F00B04B9F /* KMCustomViewButton.swift in Sources */,
+				AD7D5CAA2B906E36006562CD /* CPDFListView+Sync.swift in Sources */,
 				BBF19E9A2B0B3218007154C8 /* KMAnnotationStamp.swift in Sources */,
 				AD0257402A8601CD00EAD5D5 /* KMAppleLoginManager.swift in Sources */,
 				BB4F7E8E2B0C7FE70077EC8C /* KMNoteColorCollectionViewItem.swift in Sources */,
@@ -16659,6 +16680,7 @@
 				BBCE57112A72712200508EFC /* NSWindowController+KMExtension.swift in Sources */,
 				89D9895F28FD21E6003A3E87 /* KMAnnotationCollectionView.swift in Sources */,
 				9F0201662A176AF200C9B673 /* KMDottedLineView.swift in Sources */,
+				AD7D5CB42B9070AF006562CD /* KMSyncDot.swift in Sources */,
 				BB897257294C559F0045787C /* KMWatermarkPropertyCreateController.swift in Sources */,
 				9F0CB4CE298654FA00007028 /* KMDesignToken+Height.swift in Sources */,
 				BB4EEF4529764FEF003A3537 /* KMWatermarkAligementView.swift in Sources */,
@@ -18059,6 +18081,7 @@
 				ADDF83AC2B391A5D00A81A4E /* DSignatureModel.swift in Sources */,
 				BBF729B52B19630500576AC5 /* KMAddBatesOperationQueue.swift in Sources */,
 				AD3AAD3E2B0B7B2900DE5FE7 /* KMCompareTextView.swift in Sources */,
+				AD7D5CB52B9070AF006562CD /* KMSyncDot.swift in Sources */,
 				BB570AE12B513A66005E7E4A /* KMLeftSideViewController+Snapshot.swift in Sources */,
 				BB162E9D295073B50088E9D1 /* KMWatermarkManager.swift in Sources */,
 				BB1CA5C8298E20820059E31C /* KMPreferenceAligementView.swift in Sources */,
@@ -18479,6 +18502,7 @@
 				9F88108F2B56614600F69815 /* KMAnnotationChoiceWidgetAppearanceViewController.swift in Sources */,
 				9F0CB4CB2986533F00007028 /* KMDesignToken+Sizing.swift in Sources */,
 				AD055E4C2B72346E0035F824 /* KMBookmarkSheetView.swift in Sources */,
+				AD7D5CAB2B906E36006562CD /* CPDFListView+Sync.swift in Sources */,
 				BB1B0AC72B4FC6E900889528 /* KMGuideInfoWindow.swift in Sources */,
 				ADD1B70C29471FA500C3FFF7 /* KMPrintChoosePresenter.swift in Sources */,
 				9F0CB4692967E5CB00007028 /* KMPropertiesPanelSubViewController.swift in Sources */,