Merge remote-tracking branch 'origin/master' into mkt-url-based-command-dispatch

This commit is contained in:
Michelle Tilley 2017-09-19 09:29:58 -07:00
commit f6d7cdd417
No known key found for this signature in database
GPG Key ID: CD86C13E51F378DA
10 changed files with 476 additions and 388 deletions

View File

@ -116,7 +116,7 @@
"image-view": "0.62.3",
"incompatible-packages": "0.27.3",
"keybinding-resolver": "0.38.0",
"line-ending-selector": "0.7.3",
"line-ending-selector": "0.7.4",
"link": "0.31.3",
"markdown-preview": "0.159.13",
"metrics": "1.2.6",

View File

@ -1,57 +0,0 @@
NotificationManager = require '../src/notification-manager'
describe "NotificationManager", ->
[manager] = []
beforeEach ->
manager = new NotificationManager
describe "the atom global", ->
it "has a notifications instance", ->
expect(atom.notifications instanceof NotificationManager).toBe true
describe "adding events", ->
addSpy = null
beforeEach ->
addSpy = jasmine.createSpy()
manager.onDidAddNotification(addSpy)
it "emits an event when a notification has been added", ->
manager.add('error', 'Some error!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'error'
expect(notification.getMessage()).toBe 'Some error!'
expect(notification.getIcon()).toBe 'someIcon'
it "emits a fatal error ::addFatalError has been called", ->
manager.addFatalError('Some error!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'fatal'
it "emits an error ::addError has been called", ->
manager.addError('Some error!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'error'
it "emits a warning notification ::addWarning has been called", ->
manager.addWarning('Something!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'warning'
it "emits an info notification ::addInfo has been called", ->
manager.addInfo('Something!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'info'
it "emits a success notification ::addSuccess has been called", ->
manager.addSuccess('Something!', icon: 'someIcon')
expect(addSpy).toHaveBeenCalled()
notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe 'success'

View File

@ -0,0 +1,69 @@
const NotificationManager = require('../src/notification-manager')
describe('NotificationManager', () => {
let manager
beforeEach(() => {
manager = new NotificationManager()
})
describe('the atom global', () =>
it('has a notifications instance', () => {
expect(atom.notifications instanceof NotificationManager).toBe(true)
})
)
describe('adding events', () => {
let addSpy
beforeEach(() => {
addSpy = jasmine.createSpy()
manager.onDidAddNotification(addSpy)
})
it('emits an event when a notification has been added', () => {
manager.add('error', 'Some error!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('error')
expect(notification.getMessage()).toBe('Some error!')
expect(notification.getIcon()).toBe('someIcon')
})
it('emits a fatal error when ::addFatalError has been called', () => {
manager.addFatalError('Some error!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('fatal')
})
it('emits an error when ::addError has been called', () => {
manager.addError('Some error!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('error')
})
it('emits a warning notification when ::addWarning has been called', () => {
manager.addWarning('Something!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('warning')
})
it('emits an info notification when ::addInfo has been called', () => {
manager.addInfo('Something!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('info')
})
it('emits a success notification when ::addSuccess has been called', () => {
manager.addSuccess('Something!', {icon: 'someIcon'})
expect(addSpy).toHaveBeenCalled()
const notification = addSpy.mostRecentCall.args[0]
expect(notification.getType()).toBe('success')
})
})
})

View File

@ -1,60 +0,0 @@
Notification = require '../src/notification'
describe "Notification", ->
[notification] = []
it "throws an error when created with a non-string message", ->
expect(-> new Notification('error', null)).toThrow()
expect(-> new Notification('error', 3)).toThrow()
expect(-> new Notification('error', {})).toThrow()
expect(-> new Notification('error', false)).toThrow()
expect(-> new Notification('error', [])).toThrow()
it "throws an error when created with non-object options", ->
expect(-> new Notification('error', 'message', 'foo')).toThrow()
expect(-> new Notification('error', 'message', 3)).toThrow()
expect(-> new Notification('error', 'message', false)).toThrow()
expect(-> new Notification('error', 'message', [])).toThrow()
describe "::getTimestamp()", ->
it "returns a Date object", ->
notification = new Notification('error', 'message!')
expect(notification.getTimestamp() instanceof Date).toBe true
describe "::getIcon()", ->
it "returns a default when no icon specified", ->
notification = new Notification('error', 'message!')
expect(notification.getIcon()).toBe 'flame'
it "returns the icon specified", ->
notification = new Notification('error', 'message!', icon: 'my-icon')
expect(notification.getIcon()).toBe 'my-icon'
describe "dismissing notifications", ->
describe "when the notfication is dismissable", ->
it "calls a callback when the notification is dismissed", ->
dismissedSpy = jasmine.createSpy()
notification = new Notification('error', 'message', dismissable: true)
notification.onDidDismiss dismissedSpy
expect(notification.isDismissable()).toBe true
expect(notification.isDismissed()).toBe false
notification.dismiss()
expect(dismissedSpy).toHaveBeenCalled()
expect(notification.isDismissed()).toBe true
describe "when the notfication is not dismissable", ->
it "does nothing when ::dismiss() is called", ->
dismissedSpy = jasmine.createSpy()
notification = new Notification('error', 'message')
notification.onDidDismiss dismissedSpy
expect(notification.isDismissable()).toBe false
expect(notification.isDismissed()).toBe true
notification.dismiss()
expect(dismissedSpy).not.toHaveBeenCalled()
expect(notification.isDismissed()).toBe true

71
spec/notification-spec.js Normal file
View File

@ -0,0 +1,71 @@
const Notification = require('../src/notification')
describe('Notification', () => {
it('throws an error when created with a non-string message', () => {
expect(() => new Notification('error', null)).toThrow()
expect(() => new Notification('error', 3)).toThrow()
expect(() => new Notification('error', {})).toThrow()
expect(() => new Notification('error', false)).toThrow()
expect(() => new Notification('error', [])).toThrow()
})
it('throws an error when created with non-object options', () => {
expect(() => new Notification('error', 'message', 'foo')).toThrow()
expect(() => new Notification('error', 'message', 3)).toThrow()
expect(() => new Notification('error', 'message', false)).toThrow()
expect(() => new Notification('error', 'message', [])).toThrow()
})
describe('::getTimestamp()', () =>
it('returns a Date object', () => {
const notification = new Notification('error', 'message!')
expect(notification.getTimestamp() instanceof Date).toBe(true)
})
)
describe('::getIcon()', () => {
it('returns a default when no icon specified', () => {
const notification = new Notification('error', 'message!')
expect(notification.getIcon()).toBe('flame')
})
it('returns the icon specified', () => {
const notification = new Notification('error', 'message!', {icon: 'my-icon'})
expect(notification.getIcon()).toBe('my-icon')
})
})
describe('dismissing notifications', () => {
describe('when the notfication is dismissable', () =>
it('calls a callback when the notification is dismissed', () => {
const dismissedSpy = jasmine.createSpy()
const notification = new Notification('error', 'message', {dismissable: true})
notification.onDidDismiss(dismissedSpy)
expect(notification.isDismissable()).toBe(true)
expect(notification.isDismissed()).toBe(false)
notification.dismiss()
expect(dismissedSpy).toHaveBeenCalled()
expect(notification.isDismissed()).toBe(true)
})
)
describe('when the notfication is not dismissable', () =>
it('does nothing when ::dismiss() is called', () => {
const dismissedSpy = jasmine.createSpy()
const notification = new Notification('error', 'message')
notification.onDidDismiss(dismissedSpy)
expect(notification.isDismissable()).toBe(false)
expect(notification.isDismissed()).toBe(true)
notification.dismiss()
expect(dismissedSpy).not.toHaveBeenCalled()
expect(notification.isDismissed()).toBe(true)
})
)
})
})

View File

@ -19,6 +19,8 @@ module.exports = function parseCommandLine (processArgs) {
will be opened in that window. Otherwise, they will be opened in a new
window.
Paths that start with \`atom://\` will be interpreted as URLs.
Environment Variables:
ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode.
@ -76,7 +78,6 @@ module.exports = function parseCommandLine (processArgs) {
const addToLastWindow = args['add']
const safeMode = args['safe']
const pathsToOpen = args._
const benchmark = args['benchmark']
const benchmarkTest = args['benchmark-test']
const test = args['test']
@ -100,11 +101,20 @@ module.exports = function parseCommandLine (processArgs) {
const userDataDir = args['user-data-dir']
const profileStartup = args['profile-startup']
const clearWindowState = args['clear-window-state']
const pathsToOpen = []
const urlsToOpen = []
let devMode = args['dev']
let devResourcePath = process.env.ATOM_DEV_RESOURCE_PATH || path.join(app.getPath('home'), 'github', 'atom')
let resourcePath = null
for (const path of args._) {
if (path.startsWith('atom://')) {
urlsToOpen.push(path)
} else {
pathsToOpen.push(path)
}
}
if (args['resource-path']) {
devMode = true
devResourcePath = args['resource-path']

View File

@ -1,183 +0,0 @@
{Emitter} = require 'event-kit'
Notification = require '../src/notification'
# Public: A notification manager used to create {Notification}s to be shown
# to the user.
#
# An instance of this class is always available as the `atom.notifications`
# global.
module.exports =
class NotificationManager
constructor: ->
@notifications = []
@emitter = new Emitter
###
Section: Events
###
# Public: Invoke the given callback after a notification has been added.
#
# * `callback` {Function} to be called after the notification is added.
# * `notification` The {Notification} that was added.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidAddNotification: (callback) ->
@emitter.on 'did-add-notification', callback
###
Section: Adding Notifications
###
# Public: Add a success notification.
#
# * `message` A {String} message
# * `options` (optional) An options {Object} with the following keys:
# * `buttons` (optional) An {Array} of {Object} where each {Object} has the
# following options:
# * `className` (optional) {String} a class name to add to the button's
# default class name (`btn btn-success`).
# * `onDidClick` (optional) {Function} callback to call when the button
# has been clicked. The context will be set to the
# {NotificationElement} instance.
# * `text` {String} inner text for the button
# * `description` (optional) A Markdown {String} containing a longer
# description about the notification. By default, this **will not**
# preserve newlines and whitespace when it is rendered.
# * `detail` (optional) A plain-text {String} containing additional details
# about the notification. By default, this **will** preserve newlines
# and whitespace when it is rendered.
# * `dismissable` (optional) A {Boolean} indicating whether this
# notification can be dismissed by the user. Defaults to `false`.
# * `icon` (optional) A {String} name of an icon from Octicons to display
# in the notification header. Defaults to `'check'`.
addSuccess: (message, options) ->
@addNotification(new Notification('success', message, options))
# Public: Add an informational notification.
#
# * `message` A {String} message
# * `options` (optional) An options {Object} with the following keys:
# * `buttons` (optional) An {Array} of {Object} where each {Object} has the
# following options:
# * `className` (optional) {String} a class name to add to the button's
# default class name (`btn btn-info`).
# * `onDidClick` (optional) {Function} callback to call when the button
# has been clicked. The context will be set to the
# {NotificationElement} instance.
# * `text` {String} inner text for the button
# * `description` (optional) A Markdown {String} containing a longer
# description about the notification. By default, this **will not**
# preserve newlines and whitespace when it is rendered.
# * `detail` (optional) A plain-text {String} containing additional details
# about the notification. By default, this **will** preserve newlines
# and whitespace when it is rendered.
# * `dismissable` (optional) A {Boolean} indicating whether this
# notification can be dismissed by the user. Defaults to `false`.
# * `icon` (optional) A {String} name of an icon from Octicons to display
# in the notification header. Defaults to `'info'`.
addInfo: (message, options) ->
@addNotification(new Notification('info', message, options))
# Public: Add a warning notification.
#
# * `message` A {String} message
# * `options` (optional) An options {Object} with the following keys:
# * `buttons` (optional) An {Array} of {Object} where each {Object} has the
# following options:
# * `className` (optional) {String} a class name to add to the button's
# default class name (`btn btn-warning`).
# * `onDidClick` (optional) {Function} callback to call when the button
# has been clicked. The context will be set to the
# {NotificationElement} instance.
# * `text` {String} inner text for the button
# * `description` (optional) A Markdown {String} containing a longer
# description about the notification. By default, this **will not**
# preserve newlines and whitespace when it is rendered.
# * `detail` (optional) A plain-text {String} containing additional details
# about the notification. By default, this **will** preserve newlines
# and whitespace when it is rendered.
# * `dismissable` (optional) A {Boolean} indicating whether this
# notification can be dismissed by the user. Defaults to `false`.
# * `icon` (optional) A {String} name of an icon from Octicons to display
# in the notification header. Defaults to `'alert'`.
addWarning: (message, options) ->
@addNotification(new Notification('warning', message, options))
# Public: Add an error notification.
#
# * `message` A {String} message
# * `options` (optional) An options {Object} with the following keys:
# * `buttons` (optional) An {Array} of {Object} where each {Object} has the
# following options:
# * `className` (optional) {String} a class name to add to the button's
# default class name (`btn btn-error`).
# * `onDidClick` (optional) {Function} callback to call when the button
# has been clicked. The context will be set to the
# {NotificationElement} instance.
# * `text` {String} inner text for the button
# * `description` (optional) A Markdown {String} containing a longer
# description about the notification. By default, this **will not**
# preserve newlines and whitespace when it is rendered.
# * `detail` (optional) A plain-text {String} containing additional details
# about the notification. By default, this **will** preserve newlines
# and whitespace when it is rendered.
# * `dismissable` (optional) A {Boolean} indicating whether this
# notification can be dismissed by the user. Defaults to `false`.
# * `icon` (optional) A {String} name of an icon from Octicons to display
# in the notification header. Defaults to `'flame'`.
# * `stack` (optional) A preformatted {String} with stack trace information
# describing the location of the error.
addError: (message, options) ->
@addNotification(new Notification('error', message, options))
# Public: Add a fatal error notification.
#
# * `message` A {String} message
# * `options` (optional) An options {Object} with the following keys:
# * `buttons` (optional) An {Array} of {Object} where each {Object} has the
# following options:
# * `className` (optional) {String} a class name to add to the button's
# default class name (`btn btn-error`).
# * `onDidClick` (optional) {Function} callback to call when the button
# has been clicked. The context will be set to the
# {NotificationElement} instance.
# * `text` {String} inner text for the button
# * `description` (optional) A Markdown {String} containing a longer
# description about the notification. By default, this **will not**
# preserve newlines and whitespace when it is rendered.
# * `detail` (optional) A plain-text {String} containing additional details
# about the notification. By default, this **will** preserve newlines
# and whitespace when it is rendered.
# * `dismissable` (optional) A {Boolean} indicating whether this
# notification can be dismissed by the user. Defaults to `false`.
# * `icon` (optional) A {String} name of an icon from Octicons to display
# in the notification header. Defaults to `'bug'`.
# * `stack` (optional) A preformatted {String} with stack trace information
# describing the location of the error.
addFatalError: (message, options) ->
@addNotification(new Notification('fatal', message, options))
add: (type, message, options) ->
@addNotification(new Notification(type, message, options))
addNotification: (notification) ->
@notifications.push(notification)
@emitter.emit('did-add-notification', notification)
notification
###
Section: Getting Notifications
###
# Public: Get all the notifications.
#
# Returns an {Array} of {Notification}s.
getNotifications: -> @notifications.slice()
###
Section: Managing Notifications
###
clear: ->
@notifications = []

206
src/notification-manager.js Normal file
View File

@ -0,0 +1,206 @@
const {Emitter} = require('event-kit')
const Notification = require('../src/notification')
// Public: A notification manager used to create {Notification}s to be shown
// to the user.
//
// An instance of this class is always available as the `atom.notifications`
// global.
module.exports =
class NotificationManager {
constructor () {
this.notifications = []
this.emitter = new Emitter()
}
/*
Section: Events
*/
// Public: Invoke the given callback after a notification has been added.
//
// * `callback` {Function} to be called after the notification is added.
// * `notification` The {Notification} that was added.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidAddNotification (callback) {
return this.emitter.on('did-add-notification', callback)
}
/*
Section: Adding Notifications
*/
// Public: Add a success notification.
//
// * `message` A {String} message
// * `options` (optional) An options {Object} with the following keys:
// * `buttons` (optional) An {Array} of {Object} where each {Object} has
// the following options:
// * `className` (optional) {String} a class name to add to the button's
// default class name (`btn btn-success`).
// * `onDidClick` (optional) {Function} callback to call when the button
// has been clicked. The context will be set to the
// {NotificationElement} instance.
// * `text` {String} inner text for the button
// * `description` (optional) A Markdown {String} containing a longer
// description about the notification. By default, this **will not**
// preserve newlines and whitespace when it is rendered.
// * `detail` (optional) A plain-text {String} containing additional
// details about the notification. By default, this **will** preserve
// newlines and whitespace when it is rendered.
// * `dismissable` (optional) A {Boolean} indicating whether this
// notification can be dismissed by the user. Defaults to `false`.
// * `icon` (optional) A {String} name of an icon from Octicons to display
// in the notification header. Defaults to `'check'`.
//
// Returns the {Notification} that was added.
addSuccess (message, options) {
return this.addNotification(new Notification('success', message, options))
}
// Public: Add an informational notification.
//
// * `message` A {String} message
// * `options` (optional) An options {Object} with the following keys:
// * `buttons` (optional) An {Array} of {Object} where each {Object} has
// the following options:
// * `className` (optional) {String} a class name to add to the button's
// default class name (`btn btn-info`).
// * `onDidClick` (optional) {Function} callback to call when the button
// has been clicked. The context will be set to the
// {NotificationElement} instance.
// * `text` {String} inner text for the button
// * `description` (optional) A Markdown {String} containing a longer
// description about the notification. By default, this **will not**
// preserve newlines and whitespace when it is rendered.
// * `detail` (optional) A plain-text {String} containing additional
// details about the notification. By default, this **will** preserve
// newlines and whitespace when it is rendered.
// * `dismissable` (optional) A {Boolean} indicating whether this
// notification can be dismissed by the user. Defaults to `false`.
// * `icon` (optional) A {String} name of an icon from Octicons to display
// in the notification header. Defaults to `'info'`.
//
// Returns the {Notification} that was added.
addInfo (message, options) {
return this.addNotification(new Notification('info', message, options))
}
// Public: Add a warning notification.
//
// * `message` A {String} message
// * `options` (optional) An options {Object} with the following keys:
// * `buttons` (optional) An {Array} of {Object} where each {Object} has
// the following options:
// * `className` (optional) {String} a class name to add to the button's
// default class name (`btn btn-warning`).
// * `onDidClick` (optional) {Function} callback to call when the button
// has been clicked. The context will be set to the
// {NotificationElement} instance.
// * `text` {String} inner text for the button
// * `description` (optional) A Markdown {String} containing a longer
// description about the notification. By default, this **will not**
// preserve newlines and whitespace when it is rendered.
// * `detail` (optional) A plain-text {String} containing additional
// details about the notification. By default, this **will** preserve
// newlines and whitespace when it is rendered.
// * `dismissable` (optional) A {Boolean} indicating whether this
// notification can be dismissed by the user. Defaults to `false`.
// * `icon` (optional) A {String} name of an icon from Octicons to display
// in the notification header. Defaults to `'alert'`.
//
// Returns the {Notification} that was added.
addWarning (message, options) {
return this.addNotification(new Notification('warning', message, options))
}
// Public: Add an error notification.
//
// * `message` A {String} message
// * `options` (optional) An options {Object} with the following keys:
// * `buttons` (optional) An {Array} of {Object} where each {Object} has
// the following options:
// * `className` (optional) {String} a class name to add to the button's
// default class name (`btn btn-error`).
// * `onDidClick` (optional) {Function} callback to call when the button
// has been clicked. The context will be set to the
// {NotificationElement} instance.
// * `text` {String} inner text for the button
// * `description` (optional) A Markdown {String} containing a longer
// description about the notification. By default, this **will not**
// preserve newlines and whitespace when it is rendered.
// * `detail` (optional) A plain-text {String} containing additional
// details about the notification. By default, this **will** preserve
// newlines and whitespace when it is rendered.
// * `dismissable` (optional) A {Boolean} indicating whether this
// notification can be dismissed by the user. Defaults to `false`.
// * `icon` (optional) A {String} name of an icon from Octicons to display
// in the notification header. Defaults to `'flame'`.
// * `stack` (optional) A preformatted {String} with stack trace
// information describing the location of the error.
//
// Returns the {Notification} that was added.
addError (message, options) {
return this.addNotification(new Notification('error', message, options))
}
// Public: Add a fatal error notification.
//
// * `message` A {String} message
// * `options` (optional) An options {Object} with the following keys:
// * `buttons` (optional) An {Array} of {Object} where each {Object} has
// the following options:
// * `className` (optional) {String} a class name to add to the button's
// default class name (`btn btn-error`).
// * `onDidClick` (optional) {Function} callback to call when the button
// has been clicked. The context will be set to the
// {NotificationElement} instance.
// * `text` {String} inner text for the button
// * `description` (optional) A Markdown {String} containing a longer
// description about the notification. By default, this **will not**
// preserve newlines and whitespace when it is rendered.
// * `detail` (optional) A plain-text {String} containing additional
// details about the notification. By default, this **will** preserve
// newlines and whitespace when it is rendered.
// * `dismissable` (optional) A {Boolean} indicating whether this
// notification can be dismissed by the user. Defaults to `false`.
// * `icon` (optional) A {String} name of an icon from Octicons to display
// in the notification header. Defaults to `'bug'`.
// * `stack` (optional) A preformatted {String} with stack trace
// information describing the location of the error.
//
// Returns the {Notification} that was added.
addFatalError (message, options) {
return this.addNotification(new Notification('fatal', message, options))
}
add (type, message, options) {
return this.addNotification(new Notification(type, message, options))
}
addNotification (notification) {
this.notifications.push(notification)
this.emitter.emit('did-add-notification', notification)
return notification
}
/*
Section: Getting Notifications
*/
// Public: Get all the notifications.
//
// Returns an {Array} of {Notification}s.
getNotifications () {
return this.notifications.slice()
}
/*
Section: Managing Notifications
*/
clear () {
this.notifications = []
}
}

View File

@ -1,86 +0,0 @@
{Emitter} = require 'event-kit'
_ = require 'underscore-plus'
# Public: A notification to the user containing a message and type.
module.exports =
class Notification
constructor: (@type, @message, @options={}) ->
@emitter = new Emitter
@timestamp = new Date()
@dismissed = true
@dismissed = false if @isDismissable()
@displayed = false
@validate()
validate: ->
if typeof @message isnt 'string'
throw new Error("Notification must be created with string message: #{@message}")
unless _.isObject(@options) and not _.isArray(@options)
throw new Error("Notification must be created with an options object: #{@options}")
###
Section: Event Subscription
###
# Public: Invoke the given callback when the notification is dismissed.
#
# * `callback` {Function} to be called when the notification is dismissed.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidDismiss: (callback) ->
@emitter.on 'did-dismiss', callback
# Public: Invoke the given callback when the notification is displayed.
#
# * `callback` {Function} to be called when the notification is displayed.
#
# Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidDisplay: (callback) ->
@emitter.on 'did-display', callback
getOptions: -> @options
###
Section: Methods
###
# Public: Returns the {String} type.
getType: -> @type
# Public: Returns the {String} message.
getMessage: -> @message
getTimestamp: -> @timestamp
getDetail: -> @options.detail
isEqual: (other) ->
@getMessage() is other.getMessage() \
and @getType() is other.getType() \
and @getDetail() is other.getDetail()
# Extended: Dismisses the notification, removing it from the UI. Calling this programmatically
# will call all callbacks added via `onDidDismiss`.
dismiss: ->
return unless @isDismissable() and not @isDismissed()
@dismissed = true
@emitter.emit 'did-dismiss', this
isDismissed: -> @dismissed
isDismissable: -> !!@options.dismissable
wasDisplayed: -> @displayed
setDisplayed: (@displayed) ->
@emitter.emit 'did-display', this
getIcon: ->
return @options.icon if @options.icon?
switch @type
when 'fatal' then 'bug'
when 'error' then 'flame'
when 'warning' then 'alert'
when 'info' then 'info'
when 'success' then 'check'

118
src/notification.js Normal file
View File

@ -0,0 +1,118 @@
const {Emitter} = require('event-kit')
const _ = require('underscore-plus')
// Public: A notification to the user containing a message and type.
module.exports =
class Notification {
constructor (type, message, options = {}) {
this.type = type
this.message = message
this.options = options
this.emitter = new Emitter()
this.timestamp = new Date()
this.dismissed = true
if (this.isDismissable()) this.dismissed = false
this.displayed = false
this.validate()
}
validate () {
if (typeof this.message !== 'string') {
throw new Error(`Notification must be created with string message: ${this.message}`)
}
if (!_.isObject(this.options) || _.isArray(this.options)) {
throw new Error(`Notification must be created with an options object: ${this.options}`)
}
}
/*
Section: Event Subscription
*/
// Public: Invoke the given callback when the notification is dismissed.
//
// * `callback` {Function} to be called when the notification is dismissed.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidDismiss (callback) {
return this.emitter.on('did-dismiss', callback)
}
// Public: Invoke the given callback when the notification is displayed.
//
// * `callback` {Function} to be called when the notification is displayed.
//
// Returns a {Disposable} on which `.dispose()` can be called to unsubscribe.
onDidDisplay (callback) {
return this.emitter.on('did-display', callback)
}
getOptions () {
return this.options
}
/*
Section: Methods
*/
// Public: Returns the {String} type.
getType () {
return this.type
}
// Public: Returns the {String} message.
getMessage () {
return this.message
}
getTimestamp () {
return this.timestamp
}
getDetail () {
return this.options.detail
}
isEqual (other) {
return (this.getMessage() === other.getMessage()) &&
(this.getType() === other.getType()) &&
(this.getDetail() === other.getDetail())
}
// Extended: Dismisses the notification, removing it from the UI. Calling this
// programmatically will call all callbacks added via `onDidDismiss`.
dismiss () {
if (!this.isDismissable() || this.isDismissed()) return
this.dismissed = true
this.emitter.emit('did-dismiss', this)
}
isDismissed () {
return this.dismissed
}
isDismissable () {
return !!this.options.dismissable
}
wasDisplayed () {
return this.displayed
}
setDisplayed (displayed) {
this.displayed = displayed
this.emitter.emit('did-display', this)
}
getIcon () {
if (this.options.icon != null) return this.options.icon
switch (this.type) {
case 'fatal': return 'bug'
case 'error': return 'flame'
case 'warning': return 'alert'
case 'info': return 'info'
case 'success': return 'check'
}
}
}