mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-09-21 15:56:10 +08:00
feat(composer): floating toolbar now fades in
Summary: tooltip fades in now Test Plan: edgehill --test Reviewers: bengotow Reviewed By: bengotow Differential Revision: https://review.inboxapp.com/D1317
This commit is contained in:
parent
891f86ebce
commit
1d99a18bf6
|
@ -29,10 +29,12 @@ ContenteditableComponent = React.createClass
|
|||
componentDidMount: ->
|
||||
@_setupSelectionListeners()
|
||||
@_setupLinkHoverListeners()
|
||||
@_setupGlobalMouseListener()
|
||||
|
||||
componentWillUnmount: ->
|
||||
@_teardownSelectionListeners()
|
||||
@_teardownLinkHoverListeners()
|
||||
@_teardownGlobalMouseListener()
|
||||
|
||||
componentWillReceiveProps: (nextProps) ->
|
||||
if nextProps.initialSelectionSnapshot?
|
||||
|
@ -69,8 +71,6 @@ ContenteditableComponent = React.createClass
|
|||
onBlur={@_onBlur}
|
||||
onPaste={@_onPaste}
|
||||
onInput={@_onInput}
|
||||
onMouseUp={@_onMouseUp}
|
||||
onMouseDown={@_onMouseDown}
|
||||
dangerouslySetInnerHTML={@_dangerouslySetInnerHTML()}></div>
|
||||
<a className={@_quotedTextClasses()} onClick={@_onToggleQuotedText}></a>
|
||||
</div>
|
||||
|
@ -79,7 +79,7 @@ ContenteditableComponent = React.createClass
|
|||
@_editableNode().focus() if @isMounted()
|
||||
|
||||
_onInput: (event) ->
|
||||
@_ignoreSelectionRestoration = false
|
||||
@_dragging = false
|
||||
@_editableNode().normalize()
|
||||
@_setNewSelectionState()
|
||||
html = @_unapplyHTMLDisplayFilters(@_editableNode().innerHTML)
|
||||
|
@ -212,17 +212,46 @@ ContenteditableComponent = React.createClass
|
|||
@_previousSelection = @_selection
|
||||
@_selection = selection
|
||||
|
||||
# When we're dragging we don't want to the restoring the cursor as we're
|
||||
# dragging. Doing so caused selecting backwards to break because the
|
||||
# Selection API does not yet expose the selection "direction". When we
|
||||
# would go to reset the cursor selection, it would reset to the wrong
|
||||
# state.
|
||||
|
||||
# We use global listeners to determine whether or not dragging is
|
||||
# happening. This is because dragging may stop outside the scope of
|
||||
# this element. Note that the `dragstart` and `dragend` events don't
|
||||
# detect text selection. They are for drag & drop.
|
||||
_setupGlobalMouseListener: ->
|
||||
@__onMouseDown = _.bind(@_onMouseDown, @)
|
||||
@__onMouseMove = _.bind(@_onMouseMove, @)
|
||||
@__onMouseUp = _.bind(@_onMouseUp, @)
|
||||
window.addEventListener("mousedown", @__onMouseDown)
|
||||
window.addEventListener("mouseup", @__onMouseUp)
|
||||
_teardownGlobalMouseListener: ->
|
||||
window.removeEventListener("mousedown", @__onMouseDown)
|
||||
window.removeEventListener("mouseup", @__onMouseUp)
|
||||
|
||||
_onMouseDown: (event) ->
|
||||
@_ignoreSelectionRestoration = true
|
||||
return event
|
||||
@_mouseDownEvent = event
|
||||
@_mouseHasMoved = false
|
||||
window.addEventListener("mousemove", @__onMouseMove)
|
||||
_onMouseMove: (event) ->
|
||||
if not @_mouseHasMoved
|
||||
@_onDragStart(@_mouseDownEvent)
|
||||
@_mouseHasMoved = true
|
||||
_onMouseUp: (event) ->
|
||||
@_ignoreSelectionRestoration = false
|
||||
return event
|
||||
window.removeEventListener("mousemove", @__onMouseMove)
|
||||
if @_mouseHasMoved
|
||||
@_mouseHasMoved = false
|
||||
@_onDragEnd(event)
|
||||
|
||||
_onDragStart: (event) ->
|
||||
return unless @isMounted()
|
||||
editable = @refs.contenteditable.getDOMNode()
|
||||
if editable is event.target or editable.contains(event.target)
|
||||
@_dragging = true
|
||||
|
||||
_onDragEnd: (event) ->
|
||||
return unless @isMounted()
|
||||
if @_dragging
|
||||
@_dragging = false
|
||||
@_refreshToolbarState()
|
||||
|
||||
# We manually restore the selection on every render and when we need to
|
||||
# move the selection around manually.
|
||||
|
@ -234,7 +263,7 @@ ContenteditableComponent = React.createClass
|
|||
# selection, we'll collapse the range into a single caret
|
||||
# position
|
||||
_restoreSelection: ({force, collapse}={}) ->
|
||||
return if @_ignoreSelectionRestoration
|
||||
return if @_dragging
|
||||
return if not @_selection?
|
||||
return if document.activeElement isnt @_editableNode() and not force
|
||||
return if not @_selection.startNode? or not @_selection.endNode?
|
||||
|
@ -354,6 +383,7 @@ ContenteditableComponent = React.createClass
|
|||
# 2. When you've arrow-keyed the cursor into a link
|
||||
# 3. When you have selected a range of text.
|
||||
_refreshToolbarState: ->
|
||||
return if @_dragging
|
||||
if @_linkHoveringOver
|
||||
url = @_linkHoveringOver.getAttribute('href')
|
||||
rect = @_linkHoveringOver.getBoundingClientRect()
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
_ = require 'underscore-plus'
|
||||
React = require 'react'
|
||||
React = require 'react/addons'
|
||||
{CompositeDisposable} = require 'event-kit'
|
||||
{RetinaImg} = require 'ui-components'
|
||||
|
||||
|
@ -32,11 +32,25 @@ FloatingToolbar = React.createClass
|
|||
|
||||
render: ->
|
||||
<div ref="floatingToolbar"
|
||||
className="floating-toolbar toolbar #{@props.pos}" style={@_toolbarStyles()}>
|
||||
className={@_toolbarClasses()} style={@_toolbarStyles()}>
|
||||
<div className="toolbar-pointer" style={@_toolbarPointerStyles()}></div>
|
||||
{@_toolbarType()}
|
||||
</div>
|
||||
|
||||
_toolbarClasses: ->
|
||||
classes = {}
|
||||
classes[@props.pos] = true
|
||||
React.addons.classSet _.extend classes,
|
||||
"floating-toolbar": true
|
||||
"toolbar": true
|
||||
"toolbar-visible": @props.visible
|
||||
|
||||
_toolbarStyles: ->
|
||||
styles =
|
||||
left: @_toolbarLeft()
|
||||
top: @props.top
|
||||
return styles
|
||||
|
||||
_toolbarType: ->
|
||||
if @state.mode is "buttons" then @_renderButtons()
|
||||
else if @state.mode is "edit-link" then @_renderLink()
|
||||
|
@ -118,13 +132,6 @@ FloatingToolbar = React.createClass
|
|||
document.execCommand(cmd, false, null)
|
||||
true
|
||||
|
||||
_toolbarStyles: ->
|
||||
styles =
|
||||
left: @_toolbarLeft()
|
||||
top: @props.top
|
||||
display: if @props.visible then "block" else "none"
|
||||
return styles
|
||||
|
||||
_toolbarLeft: ->
|
||||
CONTENT_PADDING = @props.contentPadding ? 15
|
||||
max = @props.editAreaWidth - @_halfWidth()*2 - CONTENT_PADDING
|
||||
|
|
|
@ -322,6 +322,19 @@ body.is-blurred .composer-inner-wrap .tokenizing-field .token {
|
|||
border-radius: @border-radius-base;
|
||||
color: @text-color;
|
||||
|
||||
transition-duration: .15s;
|
||||
// transition-delay: .1s;
|
||||
transition-property: opacity, margin;
|
||||
opacity: 0;
|
||||
visibility: hidden;
|
||||
margin-top: 3px;
|
||||
|
||||
&.toolbar-visible {
|
||||
opacity: 1;
|
||||
visibility: visible;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
||||
.toolbar-pointer {
|
||||
position: absolute;
|
||||
width: 22.5px;
|
||||
|
|
|
@ -43,7 +43,7 @@ ThreadList = React.createClass
|
|||
selectedId={@state.selectedId}
|
||||
onSelect={ (item) -> Actions.selectThreadId(item.id) } />
|
||||
</div>
|
||||
|
||||
|
||||
_computeColumns: ->
|
||||
labelComponents = (thread) =>
|
||||
for label in @state.threadLabelComponents
|
||||
|
|
Loading…
Reference in a new issue