fix(focus): Wait for cc/bcc to exist before trying to focus them

Summary:
It was hard to notice this regression because the `?` in `@refs[field]?.focus?()` meant `focus('textFieldCc')` failed silently.

Now we catch that the field we're asked to focus doesn't exist, and try again after the next render.

Fixes T1982

Test Plan: Run tests

Reviewers: evan

Reviewed By: evan

Maniphest Tasks: T1982

Differential Revision: https://phab.nylas.com/D1643
This commit is contained in:
Ben Gotow 2015-06-17 12:29:32 -07:00
parent fc796dc7aa
commit e1af893510
2 changed files with 41 additions and 15 deletions

View file

@ -93,6 +93,12 @@ class ComposerView extends React.Component
# re-rendering.
@_recoveredSelection = null if @_recoveredSelection?
# We often can't focus until the component state has changed
# (so the desired field exists or we have a draft)
if @_focusOnUpdate and @_proxy
@focus(@_focusOnUpdate.field)
@_focusOnUpdate = false
componentWillReceiveProps: (newProps) =>
if newProps.localId isnt @props.localId
# When we're given a new draft localId, we have to stop listening to our
@ -361,15 +367,19 @@ class ComposerView extends React.Component
# the first parameter.
focus: (field = null) =>
if not @_proxy
@_focusRequested = true
@_focusOnUpdate = {field}
return
if @isForwardedMessage()
field ?= "textFieldTo"
else
field ?= "contentBody"
defaultField = "contentBody"
if @isForwardedMessage() # Note: requires _proxy
defaultField = "textFieldTo"
field ?= defaultField
@refs[field]?.focus?()
if not @refs[field]
@_focusOnUpdate = {field}
return
@refs[field].focus?()
isForwardedMessage: =>
return false if not @_proxy
@ -384,10 +394,6 @@ class ComposerView extends React.Component
@_saveToHistory()
@_initialHistorySave = true
if @_focusRequested
@_focusRequested = false
@focus()
state =
to: draft.to
cc: draft.cc
@ -530,25 +536,26 @@ class ComposerView extends React.Component
_showAndFocusBcc: =>
@setState {showbcc: true}
@focus "textFieldBcc"
@focus('textFieldBcc')
_showAndFocusCc: =>
@setState {showcc: true}
@focus "textFieldCc"
@focus('textFieldCc')
_onSendingStateChanged: =>
@setState isSending: DraftStore.isSendingDraft(@props.localId)
_onEmptyCc: =>
@setState showcc: false
@focus "textFieldTo"
@focus('textFieldTo')
_onEmptyBcc: =>
@setState showbcc: false
if @state.showcc
@focus "textFieldCc"
@focus('textFieldCc')
else
@focus "textFieldTo"
@focus('textFieldTo')
undo: (event) =>
event.preventDefault()

View file

@ -220,6 +220,25 @@ describe "populated composer", ->
advanceClock(1000)
expect(@composer.refs['contentBody'].focus).toHaveBeenCalled()
describe "if the draft has not yet loaded", ->
it "should set _focusOnUpdate and focus after the next render", ->
useDraft.call(@)
makeComposer.call(@)
proxy = @composer._proxy
@composer._proxy = null
spyOn(@composer.refs['contentBody'], 'focus')
@composer.focus()
advanceClock(1000)
expect(@composer.refs['contentBody'].focus).not.toHaveBeenCalled()
@composer._proxy = proxy
@composer._onDraftChanged()
advanceClock(1000)
expect(@composer.refs['contentBody'].focus).toHaveBeenCalled()
describe "when emptying cc fields", ->
it "focuses on to when bcc is emptied and there's no cc field", ->