Skip to content

Commit

Permalink
Add notifications for restarting jobs
Browse files Browse the repository at this point in the history
Add comments
  • Loading branch information
richinfante committed Apr 24, 2019
1 parent 953dc7a commit e9a7001
Show file tree
Hide file tree
Showing 8 changed files with 213 additions and 9 deletions.
2 changes: 1 addition & 1 deletion shbar2.xcodeproj/project.pbxproj
Expand Up @@ -95,11 +95,11 @@
9B45A9A3221B7B4000305441 /* JobStatus.swift */,
9B45A9A1221B7B2600305441 /* ItemConfigMode.swift */,
9B45A99F221B7B0B00305441 /* Script.swift */,
9B4912D1221CCAD2006E6C73 /* LabelProtocol.swift */,
9BDEE78522163235006BA354 /* Assets.xcassets */,
9BDEE78722163235006BA354 /* Main.storyboard */,
9BDEE78A22163235006BA354 /* Info.plist */,
9BDEE78B22163235006BA354 /* shbar2.entitlements */,
9B4912D1221CCAD2006E6C73 /* LabelProtocol.swift */,
);
path = shbar2;
sourceTree = "<group>";
Expand Down
100 changes: 95 additions & 5 deletions shbar2/AppDelegate.swift
Expand Up @@ -8,10 +8,31 @@

import Cocoa
import Foundation
import UserNotifications

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCenterDelegate {

/// Store ids / itemconfig mappings.
/// Used to translate jobs across notifications.
var responderItems : [String:ItemConfig] = [:]


/// Register a job with the responder dict.
/// This allows for finding later with the returned ID.
func registerProcessNotificationID(job: ItemConfig) -> String {
let str = UUID.init().uuidString
self.responderItems[str] = job
return str
}


/// Get a process via it's ID
func getProcessByNotificationID(id: String) -> ItemConfig? {
return responderItems[id]
}

// Menu items to display. Set to default config with help.
var menuItems : [ItemConfig] = [
ItemConfig(
title: "IP Address",
Expand Down Expand Up @@ -41,6 +62,15 @@ class AppDelegate: NSObject, NSApplicationDelegate {
"PATH": "/usr/bin:/usr/local/bin:/sbin:/bin"
])
),
ItemConfig(
title: "Show Config Folder",
actionScript: Script(
bin: "/bin/sh",
args: ["-c", "open \(AppDelegate.userHomeDirectoryPath)/.config/shbar/"],
env: [
"PATH": "/usr/bin:/usr/local/bin:/sbin:/bin"
])
),
ItemConfig(
mode: .ApplicationQuit,
title: "Quit",
Expand All @@ -51,6 +81,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {

var statusItems : [NSStatusItem] = []

/// Get a link to the user's home path
static var userHomeDirectoryPath : String {
let pw = getpwuid(getuid())
let home = pw?.pointee.pw_dir
Expand All @@ -59,25 +90,40 @@ class AppDelegate: NSObject, NSApplicationDelegate {
return homePath
}

/// Handler for app launch.
func applicationDidFinishLaunching(_ aNotification: Notification) {
let manager = FileManager.default

let restartAction = UNNotificationAction(identifier: "restart", title: "Restart", options: [])
let logsAction = UNNotificationAction(identifier: "logs", title: "View Logs", options: [])

let jobAlert = UNNotificationCategory(identifier: "jobAlert", actions: [restartAction, logsAction], intentIdentifiers: [], options: [])
UNUserNotificationCenter.current().setNotificationCategories([jobAlert])


// Create config directory
do {
try manager.createDirectory(atPath: "\(AppDelegate.userHomeDirectoryPath)/.config/shbar", withIntermediateDirectories: true)
} catch let error {
print("Error creating config directory: \(error)")
}

// Create log directory
do {
try manager.createDirectory(atPath: "\(AppDelegate.userHomeDirectoryPath)/Library/Logs/shbar", withIntermediateDirectories: false)
} catch let error {
print("Error creating log directory: \(error)")
}
}

// Attempt to decode the JSON config file.
let json = try? Data(contentsOf: URL(fileURLWithPath: "\(AppDelegate.userHomeDirectoryPath)/.config/shbar/shbar.json"))

// If load works, try to decode into an itemconfig.
if let json = json {
let decoder = JSONDecoder()
let decodedItems = try? decoder.decode([ItemConfig].self, from: json)

// Assign the new items into the global item list.
if let decodedItems = decodedItems {
print("Loaded from File!")
menuItems = decodedItems
Expand All @@ -86,24 +132,30 @@ class AppDelegate: NSObject, NSApplicationDelegate {
print("No config file present!")
}

// Next, pretty-print and format the current config.
let jsonEncoder = JSONEncoder()
jsonEncoder.outputFormatting = .prettyPrinted

// Print the config out.
let data = try? jsonEncoder.encode(menuItems)
print(String(data: data!, encoding: .utf8)!)


// Initialize the menu items.
for item in menuItems {
let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
// Set main title
statusItem.menu = item.createSubMenu(self)
item.menuItem = statusItem.button!
item.initializeTitle()

// Set up action to dispatch a script.
if item.actionScript != nil {
statusItem.button!.action = #selector(ItemConfig.dispatchAction)
statusItem.button!.target = item
}

// TODO: why is this incorrectly sized?
// if item.menuItem?.title == "SHBAR" {
// item.menuItem?.title = ""
// let image = NSImage(named: "Image-1")
Expand Down Expand Up @@ -132,18 +184,56 @@ class AppDelegate: NSObject, NSApplicationDelegate {

// Terminate jobs
for item in menuItems {
item.currentJob?.interrupt()
item.currentJob?.terminate()
}

print("termination complete.")
}

@objc func terminateMenuBarApp(_ sender: NSMenuItem?) {
self.terminateRemainingJobs()
NSApplication.shared.terminate(self)
}

func handler(sig: Int32) -> Void {
self.terminateMenuBarApp(nil)

/// Allow in-app notifications (for when menu is focused)
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {

completionHandler([.alert, .sound, .badge])
}

/// Enable message handling.
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler:
@escaping () -> Void) {
// Get the meeting ID from the original notification.
let userInfo = response.notification.request.content.userInfo

// Try to get Job notification ID
if let id = userInfo["job"] as? String {

// Try to find associated job.
if let job = self.getProcessByNotificationID(id: id) {

// Parse actions
if response.notification.request.content.categoryIdentifier == "jobAlert" {
if response.actionIdentifier == "logs" {
job.showJobConsole()
}

if response.actionIdentifier == "restart" || response.actionIdentifier == "start"{
job.startJob()
}
}
} else {
print("Can't find Job.")
}
} else {
print("No job ID!")
}

completionHandler()
}
}

4 changes: 3 additions & 1 deletion shbar2/Info.plist
Expand Up @@ -19,7 +19,7 @@
<key>CFBundleShortVersionString</key>
<string>0.0.2</string>
<key>CFBundleVersion</key>
<string>10</string>
<string>12</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
Expand All @@ -32,5 +32,7 @@
<string>Main</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>NSUserNotificationAlertStyle</key>
<string>alert</string>
</dict>
</plist>

0 comments on commit e9a7001

Please sign in to comment.