Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 42 additions & 10 deletions Flitro/ContextManager/ApplicationLauncher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,21 @@ protocol ContextApplicationLauncher: AnyObject {
class DefaultApplicationLauncher: ContextApplicationLauncher {
let bundleIdentifier: String
var items: [ContextItem]
private var didLaunchApp: Bool = false

init(bundleIdentifier: String, items: [ContextItem] = []) {
self.bundleIdentifier = bundleIdentifier
self.items = items
}

func open(singleItem: Bool = false) {
// Open the app
let workspace = NSWorkspace.shared
let wasRunning = workspace.runningApplications.contains { $0.bundleIdentifier == bundleIdentifier }
// Open the app
if let url = workspace.urlForApplication(withBundleIdentifier: bundleIdentifier) {
workspace.openApplication(at: url, configuration: NSWorkspace.OpenConfiguration())
}
didLaunchApp = !wasRunning
// Open items (e.g., documents)
for item in items {
switch item {
Expand All @@ -37,16 +40,45 @@ class DefaultApplicationLauncher: ContextApplicationLauncher {
}
}
}

func close() {
// Close the app (generic)
let runningApps = NSWorkspace.shared.runningApplications
for runningApp in runningApps {
if let bundleId = runningApp.bundleIdentifier, bundleId == bundleIdentifier {
let script = "tell application id \"\(bundleId)\" to quit"
if let appleScript = NSAppleScript(source: script) {
var error: NSDictionary? = nil
appleScript.executeAndReturnError(&error)
let workspace = NSWorkspace.shared
if didLaunchApp {
// Only close the app if we launched it
let runningApps = workspace.runningApplications
for runningApp in runningApps {
if let bundleId = runningApp.bundleIdentifier, bundleId == bundleIdentifier {
let script = "tell application id \"\(bundleId)\" to quit"
if let appleScript = NSAppleScript(source: script) {
var error: NSDictionary? = nil
appleScript.executeAndReturnError(&error)
}
}
}
} else {
// App was already running: try to close only the related documents
for item in items {
switch item {
case .document(let doc):
// Use external AppleScript if available
let filePath = doc.filePath
let scriptName = "generic-close.script"
print("Looking for script: \(scriptName)")
let scriptPath = Bundle.main.path(forResource: scriptName, ofType: nil)
print("Using script at path: \(String(describing: scriptPath))")
if let scriptPath = scriptPath, var scriptSource = try? String(contentsOfFile: scriptPath, encoding: .utf8) {
// Replace placeholder with actual file path
scriptSource = scriptSource
.replacingOccurrences(of: "$FILEPATH", with: filePath)
.replacingOccurrences(of: "$BUNDLE_IDENTIFIER", with: bundleIdentifier)
print("script is \(scriptSource)")
if let appleScript = NSAppleScript(source: scriptSource) {
var error: NSDictionary? = nil
appleScript.executeAndReturnError(&error)
}
}
default:
break
}
}
}
Expand Down
38 changes: 38 additions & 0 deletions Flitro/ContextManager/scripts/generic-close.script
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
set targetFile to "$FILEPATH"
set targetBundleID to "$BUNDLE_IDENTIFIER"

tell application id targetBundleID
try
repeat with d in documents
set docPath to ""
try
-- Try different property names apps might use
try
set docPath to POSIX path of (file of d as alias)
end try
if docPath is "" then
try
set docPath to POSIX path of (path of d as alias)
end try
end if
if docPath is "" then
try
set docPath to name of d
end try
end if
end try

-- Compare by full POSIX path if possible
if docPath = targetFile then
close d saving no
exit repeat
else if docPath ≠ "" and docPath = (name of (POSIX file targetFile)) then
-- Fallback to name match if path match fails
close d saving no
exit repeat
end if
end repeat
on error errMsg
display dialog "Error in app (" & targetBundleID & "): " & errMsg
end try
end tell