<commit_before>_ = require 'underscore'
React = require 'react'

{Utils, DOMUtils} = require 'nylas-exports'

FloatingToolbar = require './floating-toolbar'

# This is responsible for the logic required to position a floating
# toolbar
class FloatingToolbarContainer extends React.Component
  @displayName: "FloatingToolbarContainer"

  @propTypes:
    # A function we call when we would like to request to change the
    # current selection
    onSaveUrl: React.PropTypes.func

    # When an extension wants to mutate the DOM, it passes `onDomMutator`
    # a callback function. That callback is expecting to be passed the
    # latest DOM object and may modify it in place.
    onDomMutator: React.PropTypes.func

  @innerPropTypes:
    links: React.PropTypes.array
    dragging: React.PropTypes.bool
    selection: React.PropTypes.object
    doubleDown: React.PropTypes.bool
    editableNode: React.PropTypes.object
    editableFocused: React.PropTypes.bool

  constructor: (@props) ->
    @state =
      toolbarTop: 0
      toolbarMode: "buttons"
      toolbarLeft: 0
      toolbarPos: "above"
      editAreaWidth: 9999 # This will get set on first selection
      toolbarVisible: false
      linkHoveringOver: null
    @_setToolbarState = _.debounce(@_setToolbarState, 10)
    @innerProps =
      links: []
      dragging: false
      selection: null
      doubleDown: false
      editableNode: null
      toolbarFocus: false
      editableFocused: null

  shouldComponentUpdate: (nextProps, nextState) ->
    not Utils.isEqualReact(nextProps, @props) or
    not Utils.isEqualReact(nextState, @state)

  # Some properties (like whether we're dragging or clicking the mouse)
  # should in a strict-sense be props, but update in a way that's not
  # performant to got through the full React re-rendering cycle,
  # especially given the complexity of the composer component.
  #
  # We call these performance-optimized props & state innerProps and
  # innerState.
  componentWillReceiveInnerProps: (nextInnerProps) =>
    @innerProps = _.extend @innerProps, nextInnerProps
    @fullProps = _.extend(@innerProps, @props)
    if "links" of nextInnerProps
      @_refreshLinkHoverListeners()
    @_setToolbarState()

  componentWillReceiveProps: (nextProps) =>
    @fullProps = _.extend(@innerProps, nextProps)
    @_setToolbarState()

  # The context menu, when activated, needs to make sure that the toolbar
  # is closed. Unfortunately, since there's no onClose callback for the
  # context menu, we can't hook up a reliable declarative state to the
  # menu. We break our declarative pattern in this one case.
  forceClose: ->
    @setState toolbarVisible: false

  render: ->
    <FloatingToolbar
      ref="floatingToolbar"
      top={@state.toolbarTop}
      left={@state.toolbarLeft}
      pos={@state.toolbarPos}
      mode={@state.toolbarMode}
      visible={true}
      onSaveUrl={@props.onSaveUrl}
      onMouseEnter={@_onEnterToolbar}
      onChangeMode={@_onChangeMode}
      onMouseLeave={@_onLeaveToolbar}
      onDomMutator={@props.onDomMutator}
      linkToModify={@state.linkToModify}
      onChangeFocus={@_onChangeFocus}
      contentPadding={@CONTENT_PADDING}
      editAreaWidth={@state.editAreaWidth} />

  _onChangeFocus: (focus) =>
    @componentWillReceiveInnerProps toolbarFocus: focus

  _onChangeMode: (mode) =>
    if mode is "buttons"
      @componentWillReceiveInnerProps linkHoveringOver: null
      @setState
        toolbarMode: mode
        toolbarVisible: false
    else
      @setState toolbarMode: mode

  # We want the toolbar's state to be declaratively defined from other
  # states.
  _setToolbarState: =>
    props = @fullProps ? {}

    return if props.dragging or (props.doubleDown and not @state.toolbarVisible)<commit_msg>fix(toolbar): state to toolbar visible<commit_after>_ = require 'underscore'
React = require 'react'

{Utils, DOMUtils} = require 'nylas-exports'

FloatingToolbar = require './floating-toolbar'

# This is responsible for the logic required to position a floating
# toolbar
class FloatingToolbarContainer extends React.Component
  @displayName: "FloatingToolbarContainer"

  @propTypes:
    # A function we call when we would like to request to change the
    # current selection
    onSaveUrl: React.PropTypes.func

    # When an extension wants to mutate the DOM, it passes `onDomMutator`
    # a callback function. That callback is expecting to be passed the
    # latest DOM object and may modify it in place.
    onDomMutator: React.PropTypes.func

  @innerPropTypes:
    links: React.PropTypes.array
    dragging: React.PropTypes.bool
    selection: React.PropTypes.object
    doubleDown: React.PropTypes.bool
    editableNode: React.PropTypes.object
    editableFocused: React.PropTypes.bool

  constructor: (@props) ->
    @state =
      toolbarTop: 0
      toolbarMode: "buttons"
      toolbarLeft: 0
      toolbarPos: "above"
      editAreaWidth: 9999 # This will get set on first selection
      toolbarVisible: false
      linkHoveringOver: null
    @_setToolbarState = _.debounce(@_setToolbarState, 10)
    @innerProps =
      links: []
      dragging: false
      selection: null
      doubleDown: false
      editableNode: null
      toolbarFocus: false
      editableFocused: null

  shouldComponentUpdate: (nextProps, nextState) ->
    not Utils.isEqualReact(nextProps, @props) or
    not Utils.isEqualReact(nextState, @state)

  # Some properties (like whether we're dragging or clicking the mouse)
  # should in a strict-sense be props, but update in a way that's not
  # performant to got through the full React re-rendering cycle,
  # especially given the complexity of the composer component.
  #
  # We call these performance-optimized props & state innerProps and
  # innerState.
  componentWillReceiveInnerProps: (nextInnerProps) =>
    @innerProps = _.extend @innerProps, nextInnerProps
    @fullProps = _.extend(@innerProps, @props)
    if "links" of nextInnerProps
      @_refreshLinkHoverListeners()
    @_setToolbarState()

  componentWillReceiveProps: (nextProps) =>
    @fullProps = _.extend(@innerProps, nextProps)
    @_setToolbarState()

  # The context menu, when activated, needs to make sure that the toolbar
  # is closed. Unfortunately, since there's no onClose callback for the
  # context menu, we can't hook up a reliable declarative state to the
  # menu. We break our declarative pattern in this one case.
  forceClose: ->
    @setState toolbarVisible: false

  render: ->
    <FloatingToolbar
      ref="floatingToolbar"
      top={@state.toolbarTop}
      left={@state.toolbarLeft}
      pos={@state.toolbarPos}
      mode={@state.toolbarMode}
      visible={@state.toolbarVisible}
      onSaveUrl={@props.onSaveUrl}
      onMouseEnter={@_onEnterToolbar}
      onChangeMode={@_onChangeMode}
      onMouseLeave={@_onLeaveToolbar}
      onDomMutator={@props.onDomMutator}
      linkToModify={@state.linkToModify}
      onChangeFocus={@_onChangeFocus}
      contentPadding={@CONTENT_PADDING}
      editAreaWidth={@state.editAreaWidth} />

  _onChangeFocus: (focus) =>
    @componentWillReceiveInnerProps toolbarFocus: focus

  _onChangeMode: (mode) =>
    if mode is "buttons"
      @componentWillReceiveInnerProps linkHoveringOver: null
      @setState
        toolbarMode: mode
        toolbarVisible: false
    else
      @setState toolbarMode: mode

  # We want the toolbar's state to be declaratively defined from other
  # states.
  _setToolbarState: =>
    props = @fullProps ? {}

    return if props.dragging or (props.doubleDown and not @state.toolbarVisible)
{'fraction_non_alphanumeric': 0.08243207596940122, 'fraction_numerical': 0.0021102611448166712, 'mean_word_length': 3.551620648259304, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '531111', 'n_tokens_mistral': 2231, 'n_tokens_neox': 2172, 'n_words': 657}