Commit 977c8d63 authored by Joel Rennich's avatar Joel Rennich

Merge branch 'ActionMenu' into eapolclient

parents 8aca2904 fb3378e7
......@@ -4,9 +4,9 @@ This file lays out the design goals of the Actions Menu that you can add into No
## Philosophy
The Actions Menu is composed of "actions" which are defined by a prefrence file in the "menu.nomad.actions" domain. In this file Actions are listed as an array of dictionaries with each dictionary comprising one action. NoMAD Actions are simultaneously attempting to be highly configurable without being overly complicated.
The Actions Menu is composed of "actions" which are defined by preferences in the "menu.nomad.actions" domain. In this domain Actions are listed as an array of dictionaries with each dictionary comprising one action. NoMAD Actions are simultaneously attempting to be highly configurable without being overly complicated, as such most things are optional.
At this time actions are only updated on NoMAD application launch. If you change actions while NoMAD is running you'll need to restart NoMAD for them to take effect.
The Actions Menu is aware of updates to the preference file and does not require NoMAD to be re-launched in order to load the new actions. When the preferences are changed, NoMAD rebuilds the entire menu from scratch and runs all tests and other housekeeping items.
Actions are run lazilly in the background, so don't expect immediate satisfaction when testing things. Since the commands are checked every time NoMAD does an update cycle (on launch, every 15 minutes, on network change, or when the menu is clicked), but run in the background, the first time the UI is shown it may have the old status/text/data. The actions will update in the background and the UI will update accordingly.
......@@ -42,6 +42,7 @@ An action is comprised of some meta data and then four phases. Each phase has a
* Note that the Title command set can only have one command
* If the Title command returns "false" or "true" the text of the title won't be updated. Instead a red, in the case of "false", or green dot will be next to the menu item and the title will be the Name of the action set. If the Title command returns "yellow" a yellow dot will be shown next to the item.
* An Action with the Name of "Separator" will become a separator bar in the menu.
* An Action with no Action command set will be greyed out in the menu bar. If you'd like to have a menu item enabeld but with no action, add the "true" command to the Action command set.
## Commands
......
......@@ -19,10 +19,9 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
// globals
@objc public var actionMenu = NSMenu()
var actions = [NoMADAction]()
let sharePrefs: UserDefaults? = UserDefaults.init(suiteName: "menu.nomad.actions")
@objc public var actionMenu = NSMenu() // the menu that will be created
var actions = [NoMADAction]() // list of actions
let sharePrefs: UserDefaults? = UserDefaults.init(suiteName: "menu.nomad.actions") // action specific preferences
// prefkeys
......@@ -37,9 +36,11 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
var menuIcon : NSImage? = nil
var menuTextEnabled : Bool = false
var menuText : String? = nil
// load the actions
/// initialization function to load in prefs for class
func load() {
// read in the preferences
......@@ -49,6 +50,10 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
return
}
// watch for any changes to the Actions section of the prefs
sharePrefs?.addObserver(self, forKeyPath: NoMADActionMenu.kPrefActions, options: NSKeyValueObservingOptions.new, context: nil)
// check to see if we'll update the icon
menuIconEnabled = sharePrefs?.bool(forKey: NoMADActionMenu.kPrefMenuIcon) ?? false
......@@ -87,6 +92,10 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
}
}
/// Function to update all of the actions - including determining if the action should be shown and setting up any timers for the actions
///
/// - Parameter connected: Bool of if the domain is visible or not
@objc func updateActions(_ connected: Bool=false) {
if actions.count < 1 {
......@@ -118,6 +127,8 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
// create menu
/// Builds the NSMenu object that will be added to the main menu
@objc func createMenu() {
var menuIconColor : String? = nil
......@@ -165,7 +176,10 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
}
menuItem.target = action
menuItem.action = #selector(action.runAction)
if action.action != nil {
menuItem.action = #selector(action.runAction)
}
menuItem.isEnabled = true
menuItem.toolTip = action.tip
......@@ -188,6 +202,8 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
}
}
/// Update icons of all the menu items
func updateMenu() {
if actionMenu.items.count == 0 {
......@@ -246,4 +262,61 @@ let actionMenuQueue = DispatchQueue(label: "menu.nomad.NoMAD.actions", attribute
menuIcon = nil
}
}
/// function called when menu.nomad.actions "Actions" key is updated
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
// read in the preferences again
if sharePrefs?.integer(forKey: NoMADActionMenu.kPrefVersion) ?? 0 != 1 {
// wrong version
return
}
// check to see if we'll update the icon
menuIconEnabled = sharePrefs?.bool(forKey: NoMADActionMenu.kPrefMenuIcon) ?? false
menuTextEnabled = sharePrefs?.bool(forKey: NoMADActionMenu.kPrefMenuText) ?? false
guard let rawPrefs = sharePrefs?.array(forKey: NoMADActionMenu.kPrefActions) as? [Dictionary<String, AnyObject?>] else { return }
// if no shares we bail
if rawPrefs.count < 1 {
return
}
// remove all actions
actions.removeAll()
// loop through the shares
for action in rawPrefs {
// if no name we don't have a valid action, so skip it
guard let actionName = action["Name"] as? String else { continue }
let newAction = NoMADAction.init(actionName, guid: action["GUID"] as? String ?? nil)
newAction.show = action["Show"] as? [Dictionary<String,String?>] ?? nil
newAction.action = action["Action"] as? [Dictionary<String,String?>] ?? nil
newAction.title = action["Title"] as? Dictionary<String,String?> ?? nil
newAction.post = action["Post"] as? [Dictionary<String,String?>] ?? nil
newAction.timer = action["Timer"] as? Int ?? nil
newAction.tip = action["ToolTip"] as? String ?? ""
newAction.connected = action["Connected"] as? Bool ?? false
// add in all options
actions.append(newAction)
}
// trigger a NoMAD-wide update, this will cause all actions to be updated
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "menu.nomad.NoMAD.updateNow"), object: self)
}
}
......@@ -154,6 +154,7 @@ class NoMADMenuController: NSObject, LoginWindowDelegate, PasswordChangeDelegate
// load up the actions
nActionMenu.load()
nActionMenu.updateActions(self.userInformation.connected)
print(defaults.integer(forKey: Preferences.autoRenewCert))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment