Browse Source

Fix Save as PDF hanging in the print dialog.

Grant read-write access for user-selected files and present print operations modally on the host window so the save panel can open reliably.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 3 hours ago
parent
commit
0413967911
2 changed files with 25 additions and 20 deletions
  1. 24 19
      smart_printer/PrintService.swift
  2. 1 1
      smart_printer/smart_printer.entitlements

+ 24 - 19
smart_printer/PrintService.swift

@@ -4,38 +4,38 @@ import UniformTypeIdentifiers
4
 
4
 
5
 enum PrintService {
5
 enum PrintService {
6
     static func print(urls: [URL], from window: NSWindow? = nil) {
6
     static func print(urls: [URL], from window: NSWindow? = nil) {
7
-        _ = window
8
         guard !urls.isEmpty else { return }
7
         guard !urls.isEmpty else { return }
9
 
8
 
9
+        let hostWindow = window ?? NSApp.keyWindow
10
         for url in urls {
10
         for url in urls {
11
             let accessed = url.startAccessingSecurityScopedResource()
11
             let accessed = url.startAccessingSecurityScopedResource()
12
             defer {
12
             defer {
13
                 if accessed { url.stopAccessingSecurityScopedResource() }
13
                 if accessed { url.stopAccessingSecurityScopedResource() }
14
             }
14
             }
15
-            printFile(at: url)
15
+            printFile(at: url, from: hostWindow)
16
         }
16
         }
17
     }
17
     }
18
 
18
 
19
-    private static func printFile(at url: URL) {
19
+    private static func printFile(at url: URL, from window: NSWindow?) {
20
         let type = contentType(for: url) ?? UTType(filenameExtension: url.pathExtension) ?? .data
20
         let type = contentType(for: url) ?? UTType(filenameExtension: url.pathExtension) ?? .data
21
 
21
 
22
         if type.conforms(to: .pdf), let document = PDFDocument(url: url) {
22
         if type.conforms(to: .pdf), let document = PDFDocument(url: url) {
23
-            printPDF(document, title: url.lastPathComponent)
23
+            printPDF(document, title: url.lastPathComponent, from: window)
24
         } else if type.conforms(to: .image), let image = NSImage(contentsOf: url) {
24
         } else if type.conforms(to: .image), let image = NSImage(contentsOf: url) {
25
-            printImage(image, title: url.lastPathComponent)
25
+            printImage(image, title: url.lastPathComponent, from: window)
26
         } else if let image = NSImage(contentsOf: url) {
26
         } else if let image = NSImage(contentsOf: url) {
27
-            printImage(image, title: url.lastPathComponent)
27
+            printImage(image, title: url.lastPathComponent, from: window)
28
         } else if type.conforms(to: .plainText) || type.conforms(to: .text),
28
         } else if type.conforms(to: .plainText) || type.conforms(to: .text),
29
                   let text = try? String(contentsOf: url, encoding: .utf8) {
29
                   let text = try? String(contentsOf: url, encoding: .utf8) {
30
-            printText(text, title: url.lastPathComponent)
30
+            printText(text, title: url.lastPathComponent, from: window)
31
         } else if type.conforms(to: .rtf),
31
         } else if type.conforms(to: .rtf),
32
                   let data = try? Data(contentsOf: url),
32
                   let data = try? Data(contentsOf: url),
33
                   let attributed = NSAttributedString(rtf: data, documentAttributes: nil) {
33
                   let attributed = NSAttributedString(rtf: data, documentAttributes: nil) {
34
-            printAttributedText(attributed, title: url.lastPathComponent)
34
+            printAttributedText(attributed, title: url.lastPathComponent, from: window)
35
         } else if type.conforms(to: .html),
35
         } else if type.conforms(to: .html),
36
                   let data = try? Data(contentsOf: url),
36
                   let data = try? Data(contentsOf: url),
37
                   let attributed = NSAttributedString(html: data, documentAttributes: nil) {
37
                   let attributed = NSAttributedString(html: data, documentAttributes: nil) {
38
-            printAttributedText(attributed, title: url.lastPathComponent)
38
+            printAttributedText(attributed, title: url.lastPathComponent, from: window)
39
         } else {
39
         } else {
40
             showUnsupportedAlert(for: url)
40
             showUnsupportedAlert(for: url)
41
         }
41
         }
@@ -51,26 +51,26 @@ enum PrintService {
51
         return UTType(filenameExtension: ext)
51
         return UTType(filenameExtension: ext)
52
     }
52
     }
53
 
53
 
54
-    private static func printPDF(_ document: PDFDocument, title: String) {
54
+    private static func printPDF(_ document: PDFDocument, title: String, from window: NSWindow?) {
55
         let printInfo = configuredPrintInfo()
55
         let printInfo = configuredPrintInfo()
56
         guard let operation = document.printOperation(
56
         guard let operation = document.printOperation(
57
             for: printInfo,
57
             for: printInfo,
58
             scalingMode: .pageScaleToFit,
58
             scalingMode: .pageScaleToFit,
59
             autoRotate: true
59
             autoRotate: true
60
         ) else { return }
60
         ) else { return }
61
-        runPrintOperation(operation, title: title)
61
+        runPrintOperation(operation, title: title, from: window)
62
     }
62
     }
63
 
63
 
64
-    private static func printImage(_ image: NSImage, title: String) {
64
+    private static func printImage(_ image: NSImage, title: String, from window: NSWindow?) {
65
         guard let document = pdfDocument(from: image) else { return }
65
         guard let document = pdfDocument(from: image) else { return }
66
-        printPDF(document, title: title)
66
+        printPDF(document, title: title, from: window)
67
     }
67
     }
68
 
68
 
69
-    private static func printText(_ text: String, title: String) {
70
-        printAttributedText(NSAttributedString(string: text), title: title)
69
+    private static func printText(_ text: String, title: String, from window: NSWindow?) {
70
+        printAttributedText(NSAttributedString(string: text), title: title, from: window)
71
     }
71
     }
72
 
72
 
73
-    private static func printAttributedText(_ text: NSAttributedString, title: String) {
73
+    private static func printAttributedText(_ text: NSAttributedString, title: String, from window: NSWindow?) {
74
         let printInfo = configuredPrintInfo()
74
         let printInfo = configuredPrintInfo()
75
         let pageSize = printInfo.paperSize
75
         let pageSize = printInfo.paperSize
76
         let textView = NSTextView(frame: NSRect(origin: .zero, size: pageSize))
76
         let textView = NSTextView(frame: NSRect(origin: .zero, size: pageSize))
@@ -78,10 +78,10 @@ enum PrintService {
78
         textView.isEditable = false
78
         textView.isEditable = false
79
 
79
 
80
         let operation = NSPrintOperation(view: textView, printInfo: printInfo)
80
         let operation = NSPrintOperation(view: textView, printInfo: printInfo)
81
-        runPrintOperation(operation, title: title)
81
+        runPrintOperation(operation, title: title, from: window)
82
     }
82
     }
83
 
83
 
84
-    private static func runPrintOperation(_ operation: NSPrintOperation, title: String) {
84
+    private static func runPrintOperation(_ operation: NSPrintOperation, title: String, from window: NSWindow?) {
85
         operation.showsPrintPanel = true
85
         operation.showsPrintPanel = true
86
         operation.showsProgressPanel = true
86
         operation.showsProgressPanel = true
87
         operation.jobTitle = title
87
         operation.jobTitle = title
@@ -92,7 +92,12 @@ enum PrintService {
92
             .showsOrientation,
92
             .showsOrientation,
93
             .showsScaling,
93
             .showsScaling,
94
         ])
94
         ])
95
-        operation.run()
95
+
96
+        if let window {
97
+            operation.runModal(for: window, delegate: nil, didRun: nil, contextInfo: nil)
98
+        } else {
99
+            operation.run()
100
+        }
96
     }
101
     }
97
 
102
 
98
     private static func configuredPrintInfo() -> NSPrintInfo {
103
     private static func configuredPrintInfo() -> NSPrintInfo {

+ 1 - 1
smart_printer/smart_printer.entitlements

@@ -4,7 +4,7 @@
4
 <dict>
4
 <dict>
5
 	<key>com.apple.security.app-sandbox</key>
5
 	<key>com.apple.security.app-sandbox</key>
6
 	<true/>
6
 	<true/>
7
-	<key>com.apple.security.files.user-selected.read-only</key>
7
+	<key>com.apple.security.files.user-selected.read-write</key>
8
 	<true/>
8
 	<true/>
9
 	<key>com.apple.security.network.client</key>
9
 	<key>com.apple.security.network.client</key>
10
 	<true/>
10
 	<true/>