fix(*) => bind store classes, consolidate packages, remove ComponentRegistry.Mixin, remove bad findDOMNode() reference

This commit is contained in:
Ben Gotow 2015-04-28 15:32:15 -07:00
parent 892205f431
commit 8a8cf4b06d
20 changed files with 115 additions and 162 deletions

View file

@ -42,7 +42,7 @@ ComposerView = React.createClass
componentDidMount: ->
@_draftStoreUnlisten = DraftStore.listen @_onSendingStateChanged
@keymap_unsubscriber = atom.commands.add '.composer-outer-wrap', {
@_keymapUnlisten = atom.commands.add '.composer-outer-wrap', {
'composer:show-and-focus-bcc': @_showAndFocusBcc
'composer:show-and-focus-cc': @_showAndFocusCc
'composer:focus-to': => @focus "textFieldTo"
@ -59,7 +59,7 @@ ComposerView = React.createClass
componentWillUnmount: ->
@_teardownForDraft()
@_draftStoreUnlisten() if @_draftStoreUnlisten
@keymap_unsubscriber.dispose()
@_keymapUnlisten.dispose() if @_keymapUnlisten
componentDidUpdate: ->
# We want to use a temporary variable instead of putting this into the

View file

@ -103,7 +103,6 @@ class ContenteditableComponent extends React.Component
editableNode = @_editableNode()
editableNode.normalize()
editableNode = @_editableNode()
for extension in DraftStore.extensions()
extension.onInput(editableNode, event) if extension.onInput
@ -119,7 +118,8 @@ class ContenteditableComponent extends React.Component
@_hideToolbar()
, 50
_editableNode: => React.findDOMNode(@refs.contenteditable)
_editableNode: =>
React.findDOMNode(@refs.contenteditable)
_getAllLinks: =>
Array.prototype.slice.call(@_editableNode().querySelectorAll("*[href]"))
@ -336,7 +336,8 @@ class ContenteditableComponent extends React.Component
@_lastMouseDown = Date.now()
_onDoubleDown: (event) =>
editable = React.findDOMNode(@refs.contenteditable)
editable = @_editableNode()
return unless editable?
if editable is event.target or editable.contains(event.target)
@_doubleDown = true
@ -371,7 +372,8 @@ class ContenteditableComponent extends React.Component
event
_onDragStart: (event) =>
editable = React.findDOMNode(@refs.contenteditable)
editable = @_editableNode()
return unless editable?
if editable is event.target or editable.contains(event.target)
@_dragging = true
@ -547,9 +549,10 @@ class ContenteditableComponent extends React.Component
# See selection API: http://www.w3.org/TR/selection-api/
_selectionInScope: (selection) =>
return false if not selection?
editNode = React.findDOMNode(@refs.contenteditable)
return (editNode.contains(selection.anchorNode) and
editNode.contains(selection.focusNode))
editable = @_editableNode()
return false if not editable?
return (editable.contains(selection.anchorNode) and
editable.contains(selection.focusNode))
CONTENT_PADDING: 15
@ -559,7 +562,7 @@ class ContenteditableComponent extends React.Component
BORDER_RADIUS_PADDING = 15
editArea = React.findDOMNode(@refs.contenteditable).getBoundingClientRect()
editArea = @_editableNode().getBoundingClientRect()
calcLeft = (referenceRect.left - editArea.left) + referenceRect.width/2
calcLeft = Math.min(Math.max(calcLeft, @CONTENT_PADDING+BORDER_RADIUS_PADDING), editArea.width - BORDER_RADIUS_PADDING)

View file

@ -26,7 +26,7 @@
#
# componentDidUpdate: (lastProps, lastState) =>
# if !lastState.show and @state.show
# @refs.toolbar.findDOMNode().focus()
# React.findDOMNode(@refs.toolbar).focus()
#
# onClick: (event) =>
# cmd = event.currentTarget.getAttribute 'data-command-name'

View file

@ -1,14 +0,0 @@
{
"name": "inbox-contact-chip",
"version": "0.1.0",
"description": "Contact Chip",
"main": "./lib/main",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"engines": {
"atom": "*"
},
"license": "Proprietary",
"private": true
}

View file

@ -1,11 +1,8 @@
{ComponentRegistry, NamespaceStore} = require "inbox-exports"
React = require "react"
_ = require "underscore-plus"
DefaultChip = React.createClass
render: ->
display = @props.participant.name? and @props.participant.name or @props.participant.email
<span className="default-participant-chip">{display}</span>
{NamespaceStore} = require "inbox-exports"
{InjectedComponent} = require 'ui-components'
# Parameters
# clickable (optional) - is this currently clickable?
@ -16,14 +13,10 @@ DefaultChip = React.createClass
# - 'list'
module.exports = React.createClass
mixins: [ComponentRegistry.Mixin]
components: ["ParticipantChip"]
render: ->
ParticipantChip = @state.ParticipantChip ? DefaultChip
chips = @getParticipants().map (p) =>
<ParticipantChip key={p.id}
displayName="ParticipantChip"
<InjectedComponent name="ContactChip"
key={p.id}
clickable={@props.clickable}
context={@props.context}
participant={p} />

View file

@ -1,8 +1,13 @@
{ComponentRegistry} = require 'inbox-exports'
ContactChip = require './ContactChip'
Participants = require './Participants'
module.exports =
activate: (state) ->
ComponentRegistry.register
name: 'ParticipantChip'
name: 'Participants'
view: Participants
ComponentRegistry.register
name: 'ContactChip'
view: ContactChip

View file

@ -1,7 +1,7 @@
{
"name": "inbox-participants",
"name": "inbox-contact-elements",
"version": "0.0.1",
"description": "Contact List",
"description": "Contact React Elements",
"main": "./lib/main",
"license": "Proprietary",
"engines": {

View file

@ -1,8 +0,0 @@
{ComponentRegistry} = require 'inbox-exports'
InboxParticipants = require './InboxParticipants'
module.exports =
activate: (state) ->
ComponentRegistry.register
name: 'Participants'
view: InboxParticipants

View file

@ -1,12 +0,0 @@
.default-participant-chip {
padding: 0 3px;
position: relative;
left: -3px;
}
.default-participant-chip:not(:last-child) {
&:after {
content: ',';
display: inline;
}
}

View file

@ -291,7 +291,7 @@ describe "ThreadList", ->
ThreadStore._view = view
ThreadStore._focusedId = null
ThreadStore.trigger(ThreadStore)
@thread_list_node = @thread_list.findDOMNode()
@thread_list_node = React.findDOMNode(@thread_list)
spyOn(@thread_list, "setState").andCallThrough()
it "renders all of the thread list items", ->
@ -331,7 +331,7 @@ describe "ThreadList", ->
# ThreadStore._items = test_threads()
# ThreadStore._focusedId = null
# ThreadStore.trigger()
# @thread_list_node = @thread_list.findDOMNode()
# @thread_list_node = React.findDOMNode(@thread_list)
# it "renders all of the thread list items", ->
# items = ReactTestUtils.scryRenderedComponentsWithType(@thread_list,
@ -402,7 +402,7 @@ describe "ThreadList", ->
# it "fires the appropriate Action on click", ->
# spyOn(Actions, "selectThreadId")
# ReactTestUtils.Simulate.click @thread_list_item.findDOMNode()
# ReactTestUtils.Simulate.click React.findDOMNode(@thread_list_item)
# expect(Actions.focusThreadId).toHaveBeenCalledWith("111")
# it "sets the selected state on the thread item", ->

View file

@ -7,30 +7,6 @@ CoffeeHelpers = require './flux/coffee-helpers'
# Error types
class RegistryError extends Error
getViewsByName = (components) ->
state = {}
for component in components ? []
# Allow components to be requested as "Component" or "Component as C"
[registered, requested] = component.split " as "
requested ?= registered
state[requested] = ComponentRegistry.findViewByName registered
if not state[requested]?
console.log("Warning: No component found for #{requested} in #{@constructor.displayName}. Loaded: #{Object.keys(registry)}")
state
Mixin =
getInitialState: ->
getViewsByName.apply(@, [@components])
componentDidMount: ->
@_componentUnlistener = ComponentRegistry.listen =>
if @isMounted() is false
console.log('WARNING: ComponentRegistry firing on unmounted component.')
return
@setState getViewsByName(@components)
componentWillUnmount: ->
@_componentUnlistener() if @_componentUnlistener
# Internal representation of components
class Component
@ -84,7 +60,7 @@ class ComponentRegistry
#
# This method is chainable.
#
register: (component) ->
register: (component) =>
# Receive a component or something which can build one
throw new RegistryError 'Required: ComponentRegistry.Component or something which conforms to {name, view}' unless component instanceof Object
component = new Component(component) unless component instanceof Component
@ -100,12 +76,12 @@ class ComponentRegistry
# Return `this` for chaining
@
unregister: (name) -> delete registry[name]
unregister: (name) => delete registry[name]
showComponentRegions: ->
showComponentRegions: =>
@_showComponentRegions
getByName: (name) ->
getByName: (name) =>
component = registry[name]
throw new RegistryError 'No such component' unless component?
component
@ -116,10 +92,10 @@ class ComponentRegistry
#
# Returns a {React.Component}
#
findByName: (name, alt) ->
findByName: (name, alt) =>
registry[name] ? alt
findViewByName: (name, alt) ->
findViewByName: (name, alt) =>
registry[name]?.view ? alt
# Public: Retrieve all of the registry entries for a given role.
@ -128,14 +104,14 @@ class ComponentRegistry
#
# Returns an {Array} of {React.Component} objects
#
findAllByRole: (role) ->
findAllByRole: (role) =>
_.filter (_.values registry), (component) ->
component.role == role
findAllViewsByRole: (role) ->
findAllViewsByRole: (role) =>
_.map @findAllByRole(role), (component) -> component.view
findAllByLocationAndMode: (location, mode) ->
findAllByLocationAndMode: (location, mode) =>
_.filter (_.values registry), (component) ->
return false unless component.location
return false if component.location.id isnt location.id
@ -144,7 +120,7 @@ class ComponentRegistry
triggerDebounced: _.debounce(( -> @trigger(@)), 1)
_clear: ->
_clear: =>
registry = {}
_onToggleComponentRegions: ->
@ -153,7 +129,5 @@ class ComponentRegistry
Component: Component
RegistryError: RegistryError
Mixin: Mixin
module.exports = new ComponentRegistry()

View file

@ -102,6 +102,7 @@ class ListTabular extends React.Component
@updateRangeState()
onDoneReceivingScrollEvents: =>
return unless React.findDOMNode(@refs.container)
@setState({scrollInProgress: false})
@updateRangeState()

View file

@ -21,6 +21,7 @@ class Spinner extends React.Component
style: React.PropTypes.object
constructor: (@props) ->
@timer = null
@state =
hidden: true
paused: true
@ -33,6 +34,9 @@ class Spinner extends React.Component
if @props.visible and @state.hidden
@showAfterDelay()
componentWillUnmount: =>
clearTimeout(@timer) if @timer
componentWillReceiveProps: (nextProps) =>
hidden = if nextProps.visible? then !nextProps.visible else false
@ -43,13 +47,15 @@ class Spinner extends React.Component
@showAfterDelay()
pauseAfterDelay: =>
_.delay =>
clearTimeout(@timer) if @timer
@timer = setTimeout =>
return if @props.visible
@setState({paused: true})
,250
showAfterDelay: =>
_.delay =>
clearTimeout(@timer) if @timer
@timer = setTimeout =>
return if @props.visible isnt true
@setState({paused: false, hidden: false})
, 300

View file

@ -1,6 +1,9 @@
_ = require('underscore-plus')
EventEmitter = require('events').EventEmitter
callbackName = (string) ->
"on"+string.charAt(0).toUpperCase()+string.slice(1)
###*
# Extract child listenables from a parent from their
# children property and return them in a keyed Object
@ -63,7 +66,7 @@ module.exports =
listenToMany: (listenables) ->
allListenables = flattenListenables(listenables)
for key of allListenables
cbname = _.callbackName(key)
cbname = callbackName(key)
localname = if @[cbname] then cbname else if @[key] then key else undefined
if localname
@listenTo allListenables[key], localname, @[cbname + 'Default'] or @[localname + 'Default'] or localname
@ -90,7 +93,8 @@ module.exports =
unsubscriber = ->
index = subs.indexOf(subscriptionobj)
_.throwIf index == -1, 'Tried to remove listen already gone from subscriptions list!'
if index == -1
throw new Error('Tried to remove listen already gone from subscriptions list!')
subs.splice index, 1
desub()
return
@ -109,7 +113,8 @@ module.exports =
sub = subs[i]
if sub.listenable == listenable
sub.stop()
_.throwIf subs.indexOf(sub) != -1, 'Failed to remove listen from subscriptions list!'
if subs.indexOf(sub) != -1
throw new Error('Failed to remove listen from subscriptions list!')
return true
i++
false
@ -119,7 +124,8 @@ module.exports =
subs = @subscriptions or []
while remaining = subs.length
subs[0].stop()
_.throwIf subs.length != remaining - 1, 'Failed to remove listen from subscriptions list!'
if subs.length != remaining - 1
throw new Error('Failed to remove listen from subscriptions list!')
return
fetchInitialState: (listenable, defaultCallback) ->
@ -146,14 +152,14 @@ module.exports =
@setupEmitter()
bindContext ?= @
aborted = false
eventHandler = ->
eventHandler = (args) ->
return if aborted
callback.apply(bindContext, arguments)
callback.apply(bindContext, args)
@_emitter.addListener('trigger', eventHandler)
return =>
aborted = true
@_emitter.removeListener('trigger', eventHandler)
trigger: (arg) ->
trigger: ->
@setupEmitter()
@_emitter.emit('trigger', arg)
@_emitter.emit('trigger', arguments)

View file

@ -33,7 +33,7 @@ class ContactStore
@include Publisher
@include Listener
init: ->
constructor: ->
@_contactCache = []
@_namespaceId = null
@listenTo DatabaseStore, @_onDatabaseChanged
@ -52,7 +52,7 @@ class ContactStore
#
# Returns an {Array} of matching {Contact} models
#
searchContacts: (search, {limit}={}) ->
searchContacts: (search, {limit}={}) =>
return [] if not search or search.length is 0
limit ?= 5
@ -80,7 +80,7 @@ class ContactStore
matches
_refreshCache: ->
_refreshCache: =>
new Promise (resolve, reject) =>
DatabaseStore.findAll(Contact)
.then (contacts=[]) =>
@ -89,15 +89,15 @@ class ContactStore
resolve()
.catch(reject)
_onDatabaseChanged: (change) ->
_onDatabaseChanged: (change) =>
return unless change?.objectClass is Contact.name
@_refreshCache()
_resetCache: ->
_resetCache: =>
@_contactCache = []
@trigger(@)
_onNamespaceChanged: ->
_onNamespaceChanged: =>
return if @_namespaceId is NamespaceStore.current()?.id
@_namespaceId = NamespaceStore.current()?.id

View file

@ -160,7 +160,7 @@ class DatabaseStore
if @_root
@listenTo(Actions.logout, @onLogout)
inTransaction: (options = {}, callback) ->
inTransaction: (options = {}, callback) =>
new Promise (resolve, reject) =>
aquire = =>
db = @_db || options.database
@ -168,12 +168,12 @@ class DatabaseStore
callback(new DatabasePromiseTransaction(db, resolve, reject))
aquire()
forEachClass: (callback) ->
forEachClass: (callback) =>
classMap = modelClassMap()
for key, klass of classMap
callback(klass) if klass.attributes
openDatabase: (options = {createTables: false}, callback) ->
openDatabase: (options = {createTables: false}, callback) =>
app = remote.getGlobal('atomApplication')
app.prepareDatabase @_dbPath, =>
database = new DatabaseProxy(@_dbPath)
@ -199,14 +199,14 @@ class DatabaseStore
@_db = database
callback() if callback
teardownDatabase: (callback) ->
teardownDatabase: (callback) =>
app = remote.getGlobal('atomApplication')
app.teardownDatabase @_dbPath, =>
@_db = null
@trigger({})
callback()
writeModels: (tx, models) ->
writeModels: (tx, models) =>
# IMPORTANT: This method assumes that all the models you
# provide are of the same class, and have different ids!
@ -287,7 +287,7 @@ class DatabaseStore
tx.execute("REPLACE INTO `#{attr.modelTable}` (`id`, `value`) VALUES (?, ?)", [model.id, model[attr.modelKey]])
deleteModel: (tx, model) ->
deleteModel: (tx, model) =>
klass = model.constructor
attributes = _.values(klass.attributes)
@ -311,7 +311,7 @@ class DatabaseStore
# Inbound Events
onLogout: ->
onLogout: =>
@teardownDatabase =>
@openDatabase {createTables: @_root}, =>
# Signal that different namespaces (ie none) are now available
@ -322,7 +322,7 @@ class DatabaseStore
#
# - `model` A {Model} to write to the database.
#
persistModel: (model) ->
persistModel: (model) =>
@inTransaction {}, (tx) =>
tx.execute('BEGIN TRANSACTION')
@writeModels(tx, [model])
@ -334,7 +334,7 @@ class DatabaseStore
#
# - `models` An {Array} of {Model} objects to write to the database.
#
persistModels: (models) ->
persistModels: (models) =>
klass = models[0].constructor
@inTransaction {}, (tx) =>
tx.execute('BEGIN TRANSACTION')
@ -354,14 +354,14 @@ class DatabaseStore
#
# - `model` A {Model} to write to the database.
#
unpersistModel: (model) ->
unpersistModel: (model) =>
@inTransaction {}, (tx) =>
tx.execute('BEGIN TRANSACTION')
@deleteModel(tx, model)
tx.execute('COMMIT')
@trigger({objectClass: model.constructor.name, objects: [model]})
swapModel: ({oldModel, newModel, localId}) ->
swapModel: ({oldModel, newModel, localId}) =>
@inTransaction {}, (tx) =>
tx.execute('BEGIN TRANSACTION')
@deleteModel(tx, oldModel)
@ -389,7 +389,7 @@ class DatabaseStore
#
# Returns a {ModelQuery}
#
find: (klass, id) ->
find: (klass, id) =>
throw new Error("You must provide a class to findByLocalId") unless klass
throw new Error("find takes a string id. You may have intended to use findBy.") unless _.isString(id)
new ModelQuery(klass, @).where({id:id}).one()
@ -403,7 +403,7 @@ class DatabaseStore
#
# Returns a {ModelQuery}
#
findBy: (klass, predicates = []) ->
findBy: (klass, predicates = []) =>
throw new Error("You must provide a class to findBy") unless klass
new ModelQuery(klass, @).where(predicates).one()
@ -416,7 +416,7 @@ class DatabaseStore
#
# Returns a {ModelQuery}
#
findAll: (klass, predicates = []) ->
findAll: (klass, predicates = []) =>
throw new Error("You must provide a class to findAll") unless klass
new ModelQuery(klass, @).where(predicates)
@ -429,7 +429,7 @@ class DatabaseStore
#
# Returns a {ModelQuery}
#
count: (klass, predicates = []) ->
count: (klass, predicates = []) =>
throw new Error("You must provide a class to count") unless klass
new ModelQuery(klass, @).where(predicates).count()
@ -448,7 +448,7 @@ class DatabaseStore
# Note: When fetching an object by local Id, joined attributes
# (like body, stored in a separate table) are always included.
#
findByLocalId: (klass, localId) ->
findByLocalId: (klass, localId) =>
return Promise.reject(new Error("You must provide a class to findByLocalId")) unless klass
return Promise.reject(new Error("You must provide a local Id to findByLocalId")) unless localId
@ -465,7 +465,7 @@ class DatabaseStore
#
# Returns a {Promise} that resolves with the localId assigned to the model.
#
bindToLocalId: (model, localId) ->
bindToLocalId: (model, localId) =>
return Promise.reject(new Error("You must provide a model to bindToLocalId")) unless model
new Promise (resolve, reject) =>
@ -486,7 +486,7 @@ class DatabaseStore
# - `model` A {Model} object to assign a localId.
#
# Returns a {Promise} that resolves with the {String} localId.
localIdForModel: (model) ->
localIdForModel: (model) =>
return Promise.reject(new Error("You must provide a model to localIdForModel")) unless model
new Promise (resolve, reject) =>
@ -511,13 +511,13 @@ class DatabaseStore
#
# Returns a {Promise} that resolves with the result of the database query.
#
run: (modelQuery) ->
run: (modelQuery) =>
@inTransaction {readonly: true}, (tx) ->
tx.execute(modelQuery.sql(), [], null, null, modelQuery.executeOptions())
.then (result) ->
Promise.resolve(modelQuery.formatResult(result))
queriesForTableSetup: (klass) ->
queriesForTableSetup: (klass) =>
attributes = _.values(klass.attributes)
queries = []

View file

@ -88,7 +88,7 @@ class DraftStore
# - `key1` A {String} that contains bla
# - `key2` A {String} that contains bla
#
sessionForLocalId: (localId) ->
sessionForLocalId: (localId) =>
if not localId
console.log((new Error).stack)
throw new Error("sessionForLocalId requires a localId")
@ -103,7 +103,7 @@ class DraftStore
###
# Public: Returns the extensions registered with the DraftStore.
extensions: (ext) ->
extensions: (ext) =>
@_extensions
# Public: Registers a new extension with the DraftStore. DraftStore extensions
@ -112,19 +112,19 @@ class DraftStore
#
# - `ext` A {DraftStoreExtension} instance.
#
registerExtension: (ext) ->
registerExtension: (ext) =>
@_extensions.push(ext)
# Public: Unregisters the extension provided from the DraftStore.
#
# - `ext` A {DraftStoreExtension} instance.
#
unregisterExtension: (ext) ->
unregisterExtension: (ext) =>
@_extensions = _.without(@_extensions, ext)
########### PRIVATE ####################################################
cleanupSessionForLocalId: (localId) ->
cleanupSessionForLocalId: (localId) =>
return unless @_draftSessions[localId]
draft = @_draftSessions[localId].draft()
@ -137,7 +137,7 @@ class DraftStore
@_draftSessions[localId].cleanup()
delete @_draftSessions[localId]
_onBeforeUnload: ->
_onBeforeUnload: =>
promises = []
# Normally we'd just append all promises, even the ones already
@ -162,15 +162,15 @@ class DraftStore
# Continue closing
return true
_onDataChanged: (change) ->
_onDataChanged: (change) =>
return unless change.objectClass is Message.name
containsDraft = _.some(change.objects, (msg) -> msg.draft)
return unless containsDraft
_isMe: (contact={}) ->
_isMe: (contact={}) =>
contact.email is NamespaceStore.current().me().email
_onComposeReply: (context) ->
_onComposeReply: (context) =>
@_newMessageWithContext context, (thread, message) =>
if @_isMe(message.from[0])
to = message.to
@ -182,7 +182,7 @@ class DraftStore
to: to
}
_onComposeReplyAll: (context) ->
_onComposeReplyAll: (context) =>
@_newMessageWithContext context, (thread, message) =>
if @_isMe(message.from[0])
to = message.to
@ -200,11 +200,11 @@ class DraftStore
cc: cc
}
_onComposeForward: (context) ->
_onComposeForward: (context) =>
@_newMessageWithContext context, (thread, message) ->
forwardMessage: message
_newMessageWithContext: ({threadId, messageId}, attributesCallback) ->
_newMessageWithContext: ({threadId, messageId}, attributesCallback) =>
queries = {}
queries.thread = DatabaseStore.find(Thread, threadId)
if messageId?
@ -283,7 +283,7 @@ class DraftStore
DatabaseStore.persistModel(draft)
# Eventually we'll want a nicer solution for inline attachments
_formatBodyForQuoting: (body="") ->
_formatBodyForQuoting: (body="") =>
cidRE = MessageUtils.cidRegexString
# Be sure to match over multiple lines with [\s\S]*
# Regex explanation here: https://regex101.com/r/vO6eN2/1
@ -296,18 +296,18 @@ class DraftStore
# before the new-window loaded would cause the new-window to load with
# about:blank instead of its contents. By moving the DB logic there, we can
# get around this.
_onComposeNewBlankDraft: ->
_onComposeNewBlankDraft: =>
atom.newWindow @_composerWindowProps()
_onComposePopoutDraft: (draftLocalId) ->
_onComposePopoutDraft: (draftLocalId) =>
atom.newWindow @_composerWindowProps(draftLocalId: draftLocalId)
_composerWindowProps: (props={}) ->
_composerWindowProps: (props={}) =>
title: "Message"
windowType: "composer"
windowProps: _.extend {}, props, createNew: true
_onDestroyDraft: (draftLocalId) ->
_onDestroyDraft: (draftLocalId) =>
# Immediately reset any pending changes so no saves occur
@_draftSessions[draftLocalId]?.changes.reset()
@ -317,7 +317,7 @@ class DraftStore
# Clean up the draft session
@cleanupSessionForLocalId(draftLocalId)
_onSendDraft: (draftLocalId) ->
_onSendDraft: (draftLocalId) =>
new Promise (resolve, reject) =>
@_sendingState[draftLocalId] = true
@trigger()
@ -340,21 +340,21 @@ class DraftStore
resolve()
_onSendDraftError: (draftLocalId) ->
_onSendDraftError: (draftLocalId) =>
@_sendingState[draftLocalId] = false
@trigger()
_onSendDraftSuccess: (draftLocalId) ->
_onSendDraftSuccess: (draftLocalId) =>
@_sendingState[draftLocalId] = false
@trigger()
_onAttachFileComplete: ({file, messageLocalId}) ->
_onAttachFileComplete: ({file, messageLocalId}) =>
@sessionForLocalId(messageLocalId).prepare().then (proxy) ->
files = proxy.draft().files ? []
files.push(file)
proxy.changes.add({files}, true)
_onRemoveFile: ({file, messageLocalId}) ->
_onRemoveFile: ({file, messageLocalId}) =>
@sessionForLocalId(messageLocalId).prepare().then (proxy) ->
files = proxy.draft().files ? []
files = _.reject files, (f) -> f.id is file.id

View file

@ -24,7 +24,7 @@ class NamespaceStore
@listenTo DatabaseStore, @onDataChanged
@populateItems()
populateItems: ->
populateItems: =>
DatabaseStore.findAll(Namespace).then (namespaces) =>
current = _.find namespaces, (n) -> n.id == @_current?.id
current = namespaces?[0] unless current
@ -36,11 +36,11 @@ class NamespaceStore
# Inbound Events
onDataChanged: (change) ->
onDataChanged: (change) =>
return unless change && change.objectClass == Namespace.name
@populateItems()
onSelectNamespaceId: (id) ->
onSelectNamespaceId: (id) =>
return if @_current?.id is id
@_current = _.find @_namespaces, (n) -> n.id == @_current.id
@trigger(@)
@ -48,11 +48,11 @@ class NamespaceStore
# Exposed Data
# Public: Returns an {Array} of {Namespace} objects
items: ->
items: =>
@_namespaces
# Public: Returns the currently active {Namespace}.
current: ->
current: =>
@_current
module.exports = new NamespaceStore()