mirror of
https://github.com/Foundry376/Mailspring.git
synced 2025-09-06 12:44:30 +08:00
fix(message-list): get rid of flicker and add transitions
Test Plan: edgehill --test Reviewers: bengotow Reviewed By: bengotow Differential Revision: https://phab.nylas.com/D1841
This commit is contained in:
parent
0fc50230e7
commit
9fe11bd655
5 changed files with 88 additions and 23 deletions
|
@ -13,13 +13,13 @@ class MessageControls extends React.Component
|
|||
|
||||
render: =>
|
||||
<div className="message-actions-wrap">
|
||||
<div className="message-actions-ellipsis" onClick={@_onShowActionsMenu}>
|
||||
<RetinaImg name={"message-actions-ellipsis.png"} mode={RetinaImg.Mode.ContentIsMask}/>
|
||||
</div>
|
||||
<ButtonDropdown
|
||||
primaryItem={<RetinaImg name="ic-message-button-reply.png" mode={RetinaImg.Mode.ContentIsMask}/>}
|
||||
primaryClick={@_onReply}
|
||||
menu={@_dropdownMenu()}/>
|
||||
<div className="message-actions-ellipsis" onClick={@_onShowActionsMenu}>
|
||||
<RetinaImg name={"message-actions-ellipsis.png"} mode={RetinaImg.Mode.ContentIsMask}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
_dropdownMenu: ->
|
||||
|
|
|
@ -2,9 +2,9 @@ React = require 'react'
|
|||
classNames = require 'classnames'
|
||||
|
||||
MessageItem = require './message-item'
|
||||
PendingMessageItem = require './pending-message-item'
|
||||
|
||||
{DraftStore,
|
||||
{Utils,
|
||||
DraftStore,
|
||||
MessageStore} = require 'nylas-exports'
|
||||
|
||||
{InjectedComponent} = require 'nylas-component-kit'
|
||||
|
@ -35,6 +35,10 @@ class MessageItemContainer extends React.Component
|
|||
if @props.message?.draft
|
||||
@unlisten = DraftStore.listen @_onSendingStateChanged
|
||||
|
||||
shouldComponentUpdate: (nextProps, nextState) =>
|
||||
not Utils.isEqualReact(nextProps, @props) or
|
||||
not Utils.isEqualReact(nextState, @state)
|
||||
|
||||
componentWillUnmount: =>
|
||||
@unlisten() if @unlisten
|
||||
|
||||
|
@ -43,19 +47,20 @@ class MessageItemContainer extends React.Component
|
|||
render: =>
|
||||
if @props.message.draft
|
||||
if @state.isSending
|
||||
@_renderMessage(PendingMessageItem)
|
||||
@_renderMessage(pending: true)
|
||||
else
|
||||
@_renderComposer()
|
||||
else
|
||||
@_renderMessage(MessageItem)
|
||||
@_renderMessage(pending: false)
|
||||
|
||||
_renderMessage: (component) =>
|
||||
<component ref="message"
|
||||
thread={@props.thread}
|
||||
message={@props.message}
|
||||
className={@_classNames()}
|
||||
collapsed={@props.collapsed}
|
||||
isLastMsg={@props.isLastMsg} />
|
||||
_renderMessage: ({pending}) =>
|
||||
<MessageItem ref="message"
|
||||
pending={pending}
|
||||
thread={@props.thread}
|
||||
message={@props.message}
|
||||
className={@_classNames()}
|
||||
collapsed={@props.collapsed}
|
||||
isLastMsg={@props.isLastMsg} />
|
||||
|
||||
_renderComposer: =>
|
||||
props =
|
||||
|
|
|
@ -90,7 +90,11 @@ class MessageItem extends React.Component
|
|||
</div>
|
||||
|
||||
_renderHeader: =>
|
||||
<header className="message-header" onClick={@_onClickHeader}>
|
||||
classes = classNames
|
||||
"message-header": true
|
||||
"pending": @props.pending
|
||||
|
||||
<header className={classes} onClick={@_onClickHeader}>
|
||||
|
||||
{@_renderHeaderSideItems()}
|
||||
|
||||
|
@ -171,11 +175,19 @@ class MessageItem extends React.Component
|
|||
'no-quoted-text': not QuotedHTMLParser.hasQuotedHTML(@props.message.body)
|
||||
'show-quoted-text': @state.showQuotedText
|
||||
|
||||
# This is used by subclasses of MessageItem.
|
||||
# See {PendingMessageItem}
|
||||
_renderHeaderSideItems: -> []
|
||||
_renderHeaderSideItems: ->
|
||||
styles =
|
||||
position: "absolute"
|
||||
marginTop: -2
|
||||
|
||||
<div className="pending-spinner" style={styles}>
|
||||
<RetinaImg ref="spinner"
|
||||
name="sending-spinner.gif"
|
||||
mode={RetinaImg.Mode.ContentPreserve}/>
|
||||
</div>
|
||||
|
||||
_renderHeaderDetailToggle: =>
|
||||
return null if @props.pending
|
||||
if @state.detailedHeaders
|
||||
<div className="header-toggle-control"
|
||||
style={top: "18px", left: "-14px"}
|
||||
|
|
|
@ -251,8 +251,19 @@ class MessageList extends React.Component
|
|||
labels.map (label) =>
|
||||
<MailLabel label={label} key={label.id} onRemove={ => @_onRemoveLabel(label) }/>
|
||||
|
||||
_renderReplyArea: =>
|
||||
<div className="footer-reply-area-wrap" onClick={@_onClickReplyArea} key='reply-area'>
|
||||
_renderReplyArea: ({noTransition}={}) =>
|
||||
if @_hasReplyArea()
|
||||
styles =
|
||||
"height": 63
|
||||
"borderTop": "1px dashed #ddd"
|
||||
else
|
||||
styles =
|
||||
"height": 0
|
||||
"border": 0
|
||||
unless noTransition
|
||||
styles["transition"] = "height 150ms"
|
||||
|
||||
<div className="footer-reply-area-wrap" style={styles} onClick={@_onClickReplyArea} key='reply-area'>
|
||||
<div className="footer-reply-area">
|
||||
<RetinaImg name="#{@_replyType()}-footer.png" mode={RetinaImg.Mode.ContentIsMask}/>
|
||||
<span className="reply-text">Write a reply…</span>
|
||||
|
@ -306,8 +317,7 @@ class MessageList extends React.Component
|
|||
onRequestScrollTo={@_onChildScrollRequest} />
|
||||
)
|
||||
|
||||
if @_hasReplyArea()
|
||||
elements.push @_renderReplyArea()
|
||||
elements.push @_renderReplyArea(noTransition: _.last(messages)?.draft)
|
||||
|
||||
return elements
|
||||
|
||||
|
|
|
@ -257,6 +257,23 @@
|
|||
padding-bottom: @spacing-standard;
|
||||
padding-top: 19px;
|
||||
|
||||
&.pending {
|
||||
.message-actions-wrap {
|
||||
width: 0;
|
||||
opacity: 0;
|
||||
}
|
||||
.pending-spinner {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.pending-spinner {
|
||||
transition: opacity 100ms;
|
||||
transition-delay: 50ms, 0ms;
|
||||
transition-timing-function: ease-in;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.header-row {
|
||||
margin-top: 0.5em;
|
||||
color: @text-color-very-subtle;
|
||||
|
@ -273,11 +290,22 @@
|
|||
}
|
||||
|
||||
.message-actions-wrap {
|
||||
transition: opacity 100ms, width 150ms;
|
||||
transition-delay: 50ms, 0ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
width: 98px;
|
||||
height: 32px;
|
||||
opacity: 1;
|
||||
text-align: right;
|
||||
|
||||
.button-dropdown {
|
||||
width: 76px;
|
||||
}
|
||||
}
|
||||
|
||||
.message-actions-ellipsis {
|
||||
display: inline-block;
|
||||
display: block;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.message-actions {
|
||||
|
@ -365,6 +393,8 @@
|
|||
}
|
||||
|
||||
.footer-reply-area-wrap {
|
||||
overflow: hidden;
|
||||
|
||||
width: calc(~"100% - 12px");
|
||||
max-width: @message-max-width;
|
||||
margin: -3px auto @spacing-double auto;
|
||||
|
@ -415,8 +445,16 @@
|
|||
///////////////////////////////
|
||||
// message-participants.cjsx //
|
||||
///////////////////////////////
|
||||
.pending {
|
||||
.message-participants {
|
||||
padding-left: 34px;
|
||||
}
|
||||
}
|
||||
.message-participants {
|
||||
|
||||
transition: padding-left 150ms;
|
||||
transition-timing-function: ease-in-out;
|
||||
|
||||
&.collapsed:hover {cursor: default;}
|
||||
|
||||
.from-contact {
|
||||
|
|
Loading…
Add table
Reference in a new issue