mirror of
https://github.com/livebook-dev/livebook.git
synced 2025-02-24 06:48:07 +08:00
126 lines
3.4 KiB
Elixir
126 lines
3.4 KiB
Elixir
<%
|
|
|
|
additional_paths = Enum.map_join(@app_options[:additional_paths], ":", &"\\(resourcePath)/#{&1}")
|
|
|
|
%>import Cocoa
|
|
|
|
class AppDelegate: NSObject, NSApplicationDelegate {
|
|
var releaseTask: Process!
|
|
var isRunning = false
|
|
var initialInput = "open_app"
|
|
|
|
func applicationDidFinishLaunching(_ aNotification: Notification) {
|
|
if !isRunning {
|
|
releaseTask = startRelease(initialInput)
|
|
isRunning = true
|
|
}
|
|
}
|
|
|
|
func applicationWillTerminate(_ n: Notification) {
|
|
if (releaseTask.isRunning == true) {
|
|
log("terminating release task")
|
|
releaseTask.terminate()
|
|
}
|
|
}
|
|
|
|
func application(_ app: NSApplication, open urls: [URL]) {
|
|
for url in urls {
|
|
var input : String
|
|
|
|
if url.isFileURL {
|
|
input = "open_file:\(url.path)"
|
|
} else {
|
|
input = "open_url:\(url)"
|
|
}
|
|
|
|
if isRunning {
|
|
rpc(input)
|
|
} else {
|
|
initialInput = input
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func startRelease(_ input : String) -> Process {
|
|
let task = buildReleaseTask()
|
|
task.environment!["APP_BUILDER_INPUT"] = input
|
|
task.arguments = ["start"]
|
|
|
|
task.terminationHandler = {(t: Process) in
|
|
if t.terminationStatus == 0 {
|
|
log("release exited with: \(t.terminationStatus)")
|
|
} else {
|
|
runAlert(messageText: "\(appName) exited with error status \(t.terminationStatus).")
|
|
}
|
|
|
|
NSApp.terminate(nil)
|
|
}
|
|
|
|
try! task.run()
|
|
log("release pid: \(task.processIdentifier)")
|
|
|
|
DispatchQueue.global(qos: .userInteractive).async {
|
|
task.waitUntilExit()
|
|
}
|
|
|
|
return task
|
|
}
|
|
|
|
func rpc(_ event: String) {
|
|
let input = Pipe()
|
|
let task = buildReleaseTask()
|
|
task.standardInput = input
|
|
input.fileHandleForWriting.write("\(event)\n".data(using: .utf8)!)
|
|
task.arguments = ["rpc", "AppBundler.__rpc__()"]
|
|
try! task.run()
|
|
task.waitUntilExit()
|
|
|
|
if task.terminationStatus != 0 {
|
|
runAlert(messageText: "Something went wrong")
|
|
}
|
|
}
|
|
|
|
func buildReleaseTask() -> Process {
|
|
let task = Process()
|
|
task.launchPath = Bundle.main.path(forResource: "rel/bin/<%= @release.name %>", ofType: "")!
|
|
task.environment = ProcessInfo.processInfo.environment
|
|
|
|
<%= if additional_paths != "" do %>
|
|
let resourcePath = Bundle.main.resourcePath ?? ""
|
|
let additionalPaths = "<%= additional_paths %>"
|
|
let path = task.environment!["PATH"] ?? ""
|
|
task.environment!["PATH"] = "\(additionalPaths):\(path)"
|
|
<% end %>
|
|
|
|
task.standardOutput = logFile
|
|
task.standardError = logFile
|
|
return task
|
|
}
|
|
|
|
func runAlert(messageText: String) {
|
|
DispatchQueue.main.sync {
|
|
let alert = NSAlert()
|
|
alert.alertStyle = .critical
|
|
alert.messageText = messageText
|
|
alert.informativeText = "Logs available at: \(logPath)"
|
|
alert.runModal()
|
|
}
|
|
}
|
|
|
|
func log(_ line: String) {
|
|
logFile.write("[\(appName)Launcher] \(line)\n".data(using: .utf8)!)
|
|
}
|
|
|
|
let fm = FileManager.default
|
|
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as! String
|
|
let home = NSHomeDirectory()
|
|
let logPath = "\(home)/Library/Logs/\(appName).log"
|
|
if !fm.fileExists(atPath: logPath) { fm.createFile(atPath: logPath, contents: Data()) }
|
|
let logFile = FileHandle(forUpdatingAtPath: logPath)!
|
|
logFile.seekToEndOfFile()
|
|
|
|
let app = NSApplication.shared
|
|
let delegate = AppDelegate()
|
|
app.delegate = delegate
|
|
app.run()
|