_ = require 'underscore' Reflux = require 'reflux' {Actions} = require 'nylas-exports' VERBOSE = false DISPLAY_TIME = 3000 # in ms uuid_count = 0 class Notification constructor: ({@message, @type, @tag, @sticky, @actions, @icon} = {}) -> # Check to make sure the provided data is a valid notificaiton, since # notifications may be constructed by anyone developing on N1 throw new Error "No `new` keyword when constructing Notification" unless @ instanceof Notification throw new Error "Type must be `info`, `developer`, `error`, or `success`" unless @type in ['info', 'error', 'success', 'developer'] throw new Error "Message must be provided for notification" unless @message if @actions for action in @actions throw new Error "Actions must have an `label`" unless action['label'] throw new Error "Actions must have an `id`" unless action['id'] @tag ?= uuid_count++ @creation = Date.now() @sticky ?= false unless @sticky @expiry = @creation + DISPLAY_TIME console.log "Created new notif with #{@tag}: #{@message}" if VERBOSE @ valid: -> @sticky or @expiry > Date.now() toString: -> "Notification.#{@constructor.name}(#{@tag})" module.exports = NotificationStore = Reflux.createStore init: -> @_flush() # The notification store listens for user interaction with notififcations # and just removes the notifications. To implement notification actions, # your package should listen to notificationActionTaken and check the # notification and action objects. @listenTo Actions.notificationActionTaken, ({notification, action}) => @_removeNotification(notification)() if action.dismisses @listenTo Actions.postNotification, (data) => @_postNotification(new Notification(data)) @listenTo Actions.dismissNotificationsMatching, (criteria) => @_notifications = _.reject @_notifications, (n) -> _.isMatch(n, criteria) @trigger() ######### PUBLIC ####################################################### notifications: -> console.log(JSON.stringify(@_notifications)) if VERBOSE sorted = _.sortBy(_.values(@_notifications), (n) -> -1*(n.creation + n.tag)) _.reject sorted, (n) -> n.sticky stickyNotifications: -> console.log(JSON.stringify(@_notifications)) if VERBOSE sorted = _.sortBy(_.values(@_notifications), (n) -> -1*(n.creation + n.tag)) _.filter sorted, (n) -> n.sticky Notification: Notification ########### PRIVATE #################################################### _flush: -> @_notifications = {} _postNotification: (notification) -> console.log "Queue Notification.#{notification}" if VERBOSE @_notifications[notification.tag] = notification if notification.expiry? timeoutVal = Math.max(0, notification.expiry - Date.now()) timeoutId = setTimeout(@_removeNotification(notification), timeoutVal) notification.timeoutId = timeoutId @trigger() # Returns a function for removing a particular notification. See usage # above in setTimeout() _removeNotification: (notification) -> => console.log "Removed #{notification}" if VERBOSE clearTimeout(notification.timeoutId) if notification.timeoutId delete @_notifications[notification.tag] @trigger() # If the window matches the given context then we can show a # notification. _inWindowContext: (context={}) -> return true