Skip to content

Commit 44837a7

Browse files
1.5.0 Action extension to create class diagrams directly from Finder (#23)
1 parent 113503b commit 44837a7

File tree

16 files changed

+530
-24
lines changed

16 files changed

+530
-24
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>com.apple.security.app-sandbox</key>
6+
<true/>
7+
<key>com.apple.security.files.user-selected.read-only</key>
8+
<true/>
9+
</dict>
10+
</plist>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import Foundation
2+
import XPCService
3+
4+
class ActionRequestHandler: NSObject, NSExtensionRequestHandling {
5+
lazy var connection: NSXPCConnection = {
6+
let connection = NSXPCConnection(serviceName: "us.eidinger.SwiftPlantUMLXPCService")
7+
connection.remoteObjectInterface = NSXPCInterface(with: XPCServiceProtocol.self)
8+
connection.resume()
9+
return connection
10+
}()
11+
12+
deinit {
13+
connection.invalidate()
14+
}
15+
16+
func beginRequest(with context: NSExtensionContext) {
17+
// For an Action Extension there will only ever be one extension item.
18+
precondition(context.inputItems.count == 1)
19+
guard let inputItem = context.inputItems[0] as? NSExtensionItem
20+
else { preconditionFailure("Expected an extension item") }
21+
22+
// The extension item's attachments hold the set of files to process.
23+
guard let inputAttachments = inputItem.attachments
24+
else { preconditionFailure("Expected a valid array of attachments") }
25+
precondition(inputAttachments.isEmpty == false, "Expected at least one attachment")
26+
27+
// The output of this extension is the existing swift files
28+
guard let inputAttachments = inputItem.attachments
29+
else { preconditionFailure("Expected a valid array of attachments") }
30+
31+
let handler: (Error) -> Void = { error in
32+
print("remote proxy error: \(error)")
33+
}
34+
let service = connection.remoteObjectProxyWithErrorHandler(handler) as! XPCServiceProtocol
35+
var paths: [String] = []
36+
37+
// Use a dispatch group to synchronise asynchronous calls to loadInPlaceFileRepresentation.
38+
let dispatchGroup = DispatchGroup()
39+
40+
for attachment in inputAttachments {
41+
dispatchGroup.enter()
42+
43+
attachment.loadInPlaceFileRepresentation(forTypeIdentifier: "public.swift-source") { url, _, _ in
44+
if let url = url {
45+
paths.append(url.path)
46+
}
47+
48+
dispatchGroup.leave()
49+
}
50+
}
51+
52+
dispatchGroup.notify(queue: DispatchQueue.main) {
53+
service.generateDiagram(for: paths) {
54+
context.completeRequest(returningItems: [inputItem], completionHandler: nil)
55+
}
56+
}
57+
}
58+
}

ActionExtension/Info.plist

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleIconFile</key>
6+
<string></string>
7+
<key>NSExtension</key>
8+
<dict>
9+
<key>NSExtensionAttributes</key>
10+
<dict>
11+
<key>NSExtensionActivationRule</key>
12+
<string>SUBQUERY (
13+
extensionItems,
14+
$extensionItem,
15+
SUBQUERY (
16+
$extensionItem.attachments,
17+
$attachment,
18+
ANY $attachment.registeredTypeIdentifiers UTI-CONFORMS-TO "public.swift-source"
19+
).@count == $extensionItem.attachments.@count
20+
).@count == 1</string>
21+
<key>NSExtensionServiceAllowsFinderPreviewItem</key>
22+
<true/>
23+
<key>NSExtensionServiceAllowsTouchBarItem</key>
24+
<false/>
25+
<key>NSExtensionServiceFinderPreviewIconName</key>
26+
<string>Symbol</string>
27+
<key>NSExtensionServiceRoleType</key>
28+
<string>NSExtensionServiceRoleTypeEditor</string>
29+
<key>NSExtensionServiceTouchBarBezelColorName</key>
30+
<string>TouchBarBezel</string>
31+
<key>NSExtensionServiceTouchBarIconName</key>
32+
<string>Symbol</string>
33+
</dict>
34+
<key>NSExtensionPointIdentifier</key>
35+
<string>com.apple.services</string>
36+
<key>NSExtensionPrincipalClass</key>
37+
<string>$(PRODUCT_MODULE_NAME).ActionRequestHandler</string>
38+
</dict>
39+
</dict>
40+
</plist>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
},
6+
"symbols" : [
7+
{
8+
"filename" : "doc.badge.gearshape.svg",
9+
"idiom" : "universal"
10+
},
11+
{
12+
"appearances" : [
13+
{
14+
"appearance" : "luminosity",
15+
"value" : "light"
16+
}
17+
],
18+
"idiom" : "universal"
19+
},
20+
{
21+
"appearances" : [
22+
{
23+
"appearance" : "luminosity",
24+
"value" : "dark"
25+
}
26+
],
27+
"idiom" : "universal"
28+
}
29+
]
30+
}

0 commit comments

Comments
 (0)