Skip to content

Commit fcbfcbd

Browse files
committed
contexts are also drop targets now
resolves #17
1 parent 80f1315 commit fcbfcbd

File tree

3 files changed

+173
-165
lines changed

3 files changed

+173
-165
lines changed
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
import SwiftUI
2+
import UniformTypeIdentifiers
3+
import Foundation
4+
import AppKit
5+
6+
struct UniversalDropHandler {
7+
static func handleUniversalDrop(providers: [NSItemProvider], contextManager: ContextManager, selectedContextID: UUID?) -> Bool {
8+
guard let contextIndex = contextManager.contexts.firstIndex(where: { $0.id == selectedContextID }) else {
9+
print("No selected context found for drop")
10+
return false
11+
}
12+
guard !providers.isEmpty else {
13+
print("No providers in drop")
14+
return false
15+
}
16+
var handled = false
17+
for provider in providers {
18+
print("Processing provider with types: \(provider.registeredTypeIdentifiers)")
19+
if provider.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) || provider.hasItemConformingToTypeIdentifier("public.file-url") {
20+
let typeIdentifier = provider.hasItemConformingToTypeIdentifier(UTType.fileURL.identifier) ? UTType.fileURL.identifier : "public.file-url"
21+
provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, error in
22+
if let error = error {
23+
print("Error loading file URL: \(error)")
24+
return
25+
}
26+
print("Loaded item: \(String(describing: item))")
27+
var url: URL?
28+
if let urlObject = item as? URL {
29+
url = urlObject
30+
} else if let data = item as? Data {
31+
url = URL(dataRepresentation: data, relativeTo: nil)
32+
print("Converted data to URL: \(String(describing: url))")
33+
}
34+
if let url = url {
35+
print("Processing URL: \(url)")
36+
DispatchQueue.main.async {
37+
if url.pathExtension == "app" {
38+
if let bundle = Bundle(url: url), let bundleId = bundle.bundleIdentifier {
39+
let appItem = AppItem(name: url.deletingPathExtension().lastPathComponent, bundleIdentifier: bundleId, windowTitle: nil)
40+
contextManager.addItem(.application(appItem), to: contextManager.contexts[contextIndex].id)
41+
print("Added application: \(appItem.name)")
42+
}
43+
} else if url.pathExtension == "sh" {
44+
let session = TerminalSession(
45+
workingDirectory: url.deletingLastPathComponent().path,
46+
command: url.path,
47+
title: url.deletingPathExtension().lastPathComponent
48+
)
49+
contextManager.addItem(.terminalSession(session), to: contextManager.contexts[contextIndex].id)
50+
print("Added terminal session for script: \(session.title)")
51+
var bookmark: Data? = nil
52+
do {
53+
bookmark = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
54+
} catch {
55+
bookmark = nil
56+
}
57+
let document = DocumentItem(
58+
name: url.deletingPathExtension().lastPathComponent,
59+
filePath: url.path,
60+
application: "",
61+
bookmark: bookmark
62+
)
63+
contextManager.addItem(.document(document), to: contextManager.contexts[contextIndex].id)
64+
print("Added document: \(document.name)")
65+
} else {
66+
// Fallback: add as document for any other file type
67+
var bookmark: Data? = nil
68+
do {
69+
bookmark = try url.bookmarkData(options: .withSecurityScope, includingResourceValuesForKeys: nil, relativeTo: nil)
70+
} catch {
71+
bookmark = nil
72+
}
73+
let document = DocumentItem(
74+
name: url.deletingPathExtension().lastPathComponent,
75+
filePath: url.path,
76+
application: "",
77+
bookmark: bookmark
78+
)
79+
contextManager.addItem(.document(document), to: contextManager.contexts[contextIndex].id)
80+
print("Added document: \(document.name)")
81+
}
82+
}
83+
}
84+
}
85+
handled = true
86+
} else if provider.hasItemConformingToTypeIdentifier("public.shell-script") {
87+
provider.loadItem(forTypeIdentifier: "public.shell-script", options: nil) { item, error in
88+
if let error = error {
89+
print("Error loading shell script: \(error)")
90+
return
91+
}
92+
var url: URL?
93+
if let urlObject = item as? URL {
94+
url = urlObject
95+
} else if let data = item as? Data {
96+
url = URL(dataRepresentation: data, relativeTo: nil)
97+
print("Converted data to URL: \(String(describing: url))")
98+
}
99+
if let url = url {
100+
DispatchQueue.main.async {
101+
let session = TerminalSession(
102+
workingDirectory: url.deletingLastPathComponent().path,
103+
command: url.path,
104+
title: url.deletingPathExtension().lastPathComponent
105+
)
106+
contextManager.addItem(.terminalSession(session), to: contextManager.contexts[contextIndex].id)
107+
print("Added terminal session for script: \(session.title)")
108+
}
109+
}
110+
}
111+
handled = true
112+
provider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { item, _ in
113+
if let data = item as? Data, let url = URL(dataRepresentation: data, relativeTo: nil) {
114+
let browserTab = BrowserTab(title: url.absoluteString, url: url.absoluteString, browser: "default")
115+
DispatchQueue.main.async {
116+
contextManager.addItem(.browserTab(browserTab), to: contextManager.contexts[contextIndex].id)
117+
}
118+
} else if let url = item as? URL {
119+
let browserTab = BrowserTab(title: url.absoluteString, url: url.absoluteString, browser: "default")
120+
DispatchQueue.main.async {
121+
contextManager.addItem(.browserTab(browserTab), to: contextManager.contexts[contextIndex].id)
122+
}
123+
}
124+
}
125+
handled = true
126+
let typeIdentifier = provider.hasItemConformingToTypeIdentifier(UTType.text.identifier) ? UTType.text.identifier : UTType.plainText.identifier
127+
provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, _ in
128+
if let text = item as? String, !text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
129+
if let url = URL(string: text.trimmingCharacters(in: .whitespacesAndNewlines)) {
130+
let browserTab = BrowserTab(title: url.absoluteString, url: url.absoluteString, browser: "default")
131+
DispatchQueue.main.async {
132+
contextManager.addItem(.browserTab(browserTab), to: contextManager.contexts[contextIndex].id)
133+
print("Added browser tab: \(browserTab.title)")
134+
}
135+
}
136+
}
137+
}
138+
handled = true
139+
} else if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) || provider.hasItemConformingToTypeIdentifier("public.url") {
140+
let typeIdentifier = provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) ? UTType.url.identifier : "public.url"
141+
provider.loadItem(forTypeIdentifier: typeIdentifier, options: nil) { item, error in
142+
if let error = error {
143+
print("Error loading URL: \(error)")
144+
return
145+
}
146+
var url: URL?
147+
if let urlObject = item as? URL {
148+
url = urlObject
149+
} else if let data = item as? Data {
150+
url = URL(dataRepresentation: data, relativeTo: nil)
151+
print("Converted data to URL: \(String(describing: url))")
152+
} else if let str = item as? String, let urlFromString = URL(string: str) {
153+
url = urlFromString
154+
}
155+
if let url = url {
156+
let browserTab = BrowserTab(title: url.absoluteString, url: url.absoluteString, browser: "default")
157+
DispatchQueue.main.async {
158+
contextManager.addItem(.browserTab(browserTab), to: contextManager.contexts[contextIndex].id)
159+
print("Added browser tab: \(browserTab.title)")
160+
}
161+
}
162+
}
163+
handled = true
164+
}
165+
}
166+
print("Drop handling complete. Handled: \(handled)")
167+
return handled
168+
}
169+
}

0 commit comments

Comments
 (0)