134 lines
5.0 KiB
Swift
134 lines
5.0 KiB
Swift
/*
|
|
* ----------------------------------------------------------------------------
|
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
|
* <g.litenstein@gmail.com> wrote this file. As long as you retain this notice you
|
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
|
* this stuff is worth it, you can buy me a beer in return., Gregorio Litenstein.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
import AppKit
|
|
|
|
|
|
/** Represents information about an application and its associated URI Schemes and UTIs as an object. */
|
|
class SWDAApplicationInfo: NSObject {
|
|
var displayName: String?
|
|
var appPath: String?
|
|
var appURL: String?
|
|
var appDescription: String?
|
|
var appVersion: String?
|
|
var appBundleID: String?
|
|
var appIcon: NSImage?
|
|
lazy var handlers: [SWDAContentHandler] = { return [] }()
|
|
|
|
lazy var handledContent: [String: [String:[SWDAContentHandler]?]] = {
|
|
var wrappedHandlers: [String: [String:[SWDAContentHandler]?]] = [:]
|
|
if let handlers = LSWrappers.copySchemesAndUTIsForApp(self.appPath!) {
|
|
|
|
var wrappedURIHandlers: [String:[SWDAContentHandler]] = ["Viewer":[]]
|
|
var wrappedUTIHandlers: [String:[SWDAContentHandler]] = ["Viewer":[],"Editor":[],"Shell":[]]
|
|
|
|
for handlerRole in handlers["UTIs"]! {
|
|
let role = String(describing:handlerRole.key)
|
|
var handler: SWDAContentHandler?
|
|
|
|
for utiHandler in handlerRole.value {
|
|
|
|
handler = SWDAContentHandler(SWDAContentItem(type:SWDAContentType(rawValue:"UTI")!, utiHandler), appName: self.appBundleID!, role: SourceListRoleTypes(rawValue:role)!)
|
|
if let handler = handler {
|
|
wrappedUTIHandlers[role]!.append(handler)
|
|
}
|
|
}
|
|
}
|
|
|
|
for handlerRole in handlers["URIs"]! {
|
|
let role = String(describing:handlerRole.key)
|
|
var handler: SWDAContentHandler?
|
|
|
|
for urlHandler in handlerRole.value {
|
|
|
|
handler = SWDAContentHandler(SWDAContentItem(type:SWDAContentType(rawValue:"URI")!, urlHandler), appName: self.appBundleID!, role: SourceListRoleTypes(rawValue:role)!)
|
|
if let handler = handler {
|
|
wrappedURIHandlers[role]!.append(handler)
|
|
}
|
|
}
|
|
}
|
|
wrappedHandlers["UTIs"] = wrappedUTIHandlers
|
|
wrappedHandlers["URIs"] = wrappedURIHandlers
|
|
return wrappedHandlers
|
|
}
|
|
else { return ["URIs":["Viewer":[]],"UTIs":["Editor":[], "Viewer":[], "Shell":[]]] }
|
|
}()
|
|
|
|
/** Only applications that handle at least one URI Scheme or UTI will show up in the "Applications" tab. */
|
|
lazy var handlesURIs: Bool = {
|
|
for role in (self.handledContent["URIs"]!).values {
|
|
if !(role!.isEmpty) { return true }
|
|
}
|
|
return false
|
|
}()
|
|
lazy var handlesUTIs: Bool = {
|
|
for role in (self.handledContent["UTIs"]!).values {
|
|
if !(role!.isEmpty) { return true }
|
|
}
|
|
return false
|
|
}()
|
|
|
|
init?(_ inParam: String) {
|
|
var bundleID: String?
|
|
switch inParam {
|
|
case "Other...":
|
|
self.displayName = "Other..."
|
|
self.appVersion = ""
|
|
self.appPath = ""
|
|
self.appIcon = NSImage(byReferencingFile: "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/GenericApplicationIcon.icns")
|
|
default:
|
|
let result = LSWrappers.getBundleID(inParam, outBundleID: &bundleID)
|
|
if (result == 0) {
|
|
let appURL = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleID!)
|
|
guard appURL != nil else { return nil }
|
|
if let bundle = Bundle(url: appURL!) {
|
|
guard bundle.bundleIdentifier != nil else {
|
|
NSLog(LSWrappers.LSErrors.invalidBundle.print(argument: (app: inParam, content:"")))
|
|
return nil;
|
|
}
|
|
self.appBundleID = bundle.bundleIdentifier!
|
|
let name = (bundle.object(forInfoDictionaryKey: "CFBundleName") as? String)
|
|
let displayName = (bundle.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String)
|
|
var tempName: String?
|
|
if let displayName = displayName {
|
|
tempName = displayName
|
|
}
|
|
sanity: if let name = bundle.object(forInfoDictionaryKey: "CFBundleName") as? String { // Theoretically, apps should always have a CFBundleName and most of the time, also a CFBundleDisplayName. In practice? Not so much. We should be prepared to handle broken apps.
|
|
guard (tempName == nil || tempName == "") else { break sanity }
|
|
tempName = name
|
|
}
|
|
else {
|
|
tempName = FileManager.default.displayName(atPath: bundle.bundlePath)
|
|
}
|
|
self.displayName = tempName
|
|
self.appURL = String(describing:bundle.bundleURL)
|
|
if let version = bundle.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String {
|
|
self.appVersion = version
|
|
}
|
|
else if let version = bundle.object(forInfoDictionaryKey: "CFBundleVersion") as? String {
|
|
self.appVersion = version
|
|
}
|
|
else { self.appVersion = nil }
|
|
self.appPath = bundle.bundlePath
|
|
self.appIcon = NSWorkspace.shared.icon(forFile: bundle.bundlePath)
|
|
}
|
|
else {
|
|
NSLog(LSWrappers.LSErrors.init(value:result).print(argument: (app: inParam, content:"")))
|
|
return nil
|
|
}
|
|
}
|
|
else {
|
|
NSLog(LSWrappers.LSErrors.init(value:result).print(argument: (app: inParam, content:"")))
|
|
return nil
|
|
}
|
|
}
|
|
super.init()
|
|
}
|
|
}
|