fix(scrolling): scroll to end once. Fix draft deletion

This commit is contained in:
Evan Morikawa 2015-03-10 13:15:28 -07:00
parent 6af864e3bd
commit d5eb68ece1
7 changed files with 41 additions and 25 deletions

View file

@ -9,6 +9,8 @@ AccountSidebarTagItem = React.createClass
if @props.tag.unreadCount > 0
unread = <div className="unread item-count-box">{@props.tag.unreadCount}</div>
name = if @props.tag.name is "drafts" then "Local Drafts" else @props.tag.name
classSet = React.addons.classSet
'item': true
'item-tag': true
@ -17,7 +19,7 @@ AccountSidebarTagItem = React.createClass
<div className={classSet} onClick={@_onClick} id={@props.tag.id}>
{unread}
<RetinaImg name={"#{@props.tag.id}.png"} fallback={'folder.png'} selected={@props.select}/>
<span className="name"> {@props.tag.name}</span>
<span className="name"> {name}</span>
</div>
_onClick: (event) ->

View file

@ -27,12 +27,24 @@ MessageList = React.createClass
if newDrafts.length >= 1
@_focusComposerId = newDrafts[0]
componentDidUpdate: ->
@_lastHeight = -1
@_scrollToBottom()
if @_focusComposerId?
@_focusRef(@refs["composerItem-#{@_focusComposerId}"])
@_focusComposerId = null
componentDidUpdate: (prevProps, prevState) ->
if @_shouldScroll(prevState)
@_lastHeight = -1
@_scrollToBottom()
if @_focusComposerId?
@_focusRef(@refs["composerItem-#{@_focusComposerId}"])
@_focusComposerId = null
# Only scroll if the messages change and there are some message
_shouldScroll: (prevState) ->
return false if (@state.messages ? []).length is 0
prevMsg = (prevState.messages ? []).map((m) -> m.id)
curMsg = (@state.messages ? []).map((m) -> m.id)
return true if prevMsg.length isnt curMsg.length
iLength = _.intersection(prevMsg, curMsg).length
return true if iLength isnt prevMsg.length or iLength isnt curMsg.length
return false
# We need a 100ms delay so the DOM can finish painting the elements on
# the page. The focus doesn't work for some reason while the paint is in
@ -42,7 +54,7 @@ MessageList = React.createClass
, 100
render: ->
return <div></div> if not @state.current_thread?
return <div></div> if not @state.currentThread?
<div className="message-list" id="message-list">
<div tabIndex=1 ref="messageWrap" className="messages-wrap">
@ -58,7 +70,7 @@ MessageList = React.createClass
_messageListNotificationBars: ->
MLBars = ComponentRegistry.findAllViewsByRole('MessageListNotificationBar')
<div className="message-list-notification-bar-wrap">
{<MLBar thread={@state.current_thread} /> for MLBar in MLBars}
{<MLBar thread={@state.currentThread} /> for MLBar in MLBars}
</div>
_messageListHeaders: ->
@ -66,10 +78,10 @@ MessageList = React.createClass
MessageListHeaders = ComponentRegistry.findAllViewsByRole('MessageListHeader')
<div className="message-list-headers">
<h2 className="message-subject">{@state.current_thread.subject}</h2>
<h2 className="message-subject">{@state.currentThread.subject}</h2>
{for MessageListHeader in MessageListHeaders
<MessageListHeader thread={@state.current_thread} />
<MessageListHeader thread={@state.currentThread} />
}
</div>
@ -103,7 +115,7 @@ MessageList = React.createClass
className = "message-item-wrap"
if message.unread then className += " unread-message"
components.push <MessageItem key={message.id}
thread={@state.current_thread}
thread={@state.currentThread}
message={message}
collapsed={collapsed}
className={className}
@ -117,11 +129,11 @@ MessageList = React.createClass
_getStateFromStores: ->
messages: (MessageStore.items() ? [])
messageLocalIds: MessageStore.itemLocalIds()
current_thread: ThreadStore.selectedThread()
currentThread: ThreadStore.selectedThread()
_threadParticipants: ->
# We calculate the list of participants instead of grabbing it from
# `@state.current_thread.participants` because it makes it easier to
# `@state.currentThread.participants` because it makes it easier to
# test, is a better source of ground truth, and saves us from more
# dependencies.
participants = {}

View file

@ -212,7 +212,7 @@ describe "MessageList", ->
beforeEach ->
MessageStore._items = testMessages
MessageStore.trigger(MessageStore)
@message_list.setState current_thread: test_thread
@message_list.setState currentThread: test_thread
it "renders all the correct number of messages", ->
items = TestUtils.scryRenderedComponentsWithType(@message_list,
@ -268,7 +268,7 @@ describe "MessageList", ->
beforeEach ->
MessageStore._items = testMessages.concat draftMessages
MessageStore.trigger(MessageStore)
@message_list.setState current_thread: test_thread
@message_list.setState currentThread: test_thread
it "renders the composer", ->
items = TestUtils.scryRenderedComponentsWithType(@message_list,

View file

@ -37,15 +37,15 @@ DraftList = React.createClass
columns={@state.columns}
items={@state.items}
selectedId={@state.selectedId}
onDoubleClick={@_onDoubleClick}
onClick={@_onClick}
onSelect={@_onSelect} />
</div>
_onSelect: (item) ->
@setState
selectedId: item.id
_onDoubleClick: (item) ->
_onClick: (item) ->
DatabaseStore.localIdForModel(item).then (localId) ->
Actions.composePopoutDraft(localId)

View file

@ -11,6 +11,7 @@ ListTabularItem = React.createClass
itemClassProvider: React.PropTypes.func
displayHeaders: React.PropTypes.bool
onSelect: React.PropTypes.func
onClick: React.PropTypes.func
onDoubleClick: React.PropTypes.func
# DO NOT DELETE unless you know what you're doing! This method cuts
@ -32,14 +33,15 @@ ListTabularItem = React.createClass
className="list-column">
{column.resolver(@props.item, @)}
</div>
_onClick: ->
if not @props.selected
@props.onSelect?(@props.item)
@props.onClick?(@props.item)
if @_lastClickTime? and Date.now() - @_lastClickTime < 350
@props.onDoubleClick?(@props.item)
@_lastClickTime = Date.now()
_containerClasses: ->
@ -60,6 +62,7 @@ ListTabular = React.createClass
itemClassProvider: React.PropTypes.func
selectedId: React.PropTypes.string
onSelect: React.PropTypes.func
onClick: React.PropTypes.func
onDoubleClick: React.PropTypes.func
render: ->
@ -92,6 +95,7 @@ ListTabular = React.createClass
itemClassProvider={@props.itemClassProvider}
columns={@props.columns}
onSelect={@props.onSelect}
onClick={@props.onClick}
onDoubleClick={@props.onDoubleClick} />

View file

@ -179,6 +179,7 @@ DraftStore = Reflux.createStore
_onDestroyDraft: (draftLocalId) ->
# Immediately reset any pending changes so no saves occur
@_closeWindow(draftLocalId)
@_draftSessions[draftLocalId]?.changes.reset()
delete @_draftSessions[draftLocalId]

View file

@ -42,9 +42,7 @@ class DestroyDraftTask extends Task
body:
version: @draft.version
returnsModel: false
success: (args...) =>
Actions.destroyDraftSuccess(@draftLocalId)
resolve(args...)
success: resolve
error: reject
onAPIError: (apiError) ->
@ -57,7 +55,6 @@ class DestroyDraftTask extends Task
# do but finish
return true
else
Actions.destroyDraftError(@draftLocalId)
@_rollbackLocal()
onOtherError: -> Promise.resolve()