<commit_before>_ = require 'underscore'
React = require 'react/addons'
ScrollRegion = require './scroll-region'
{Utils} = require 'nylas-exports'

class ListColumn
  constructor: ({@name, @resolver, @flex, @width}) ->

class ListTabularItem extends React.Component
  @displayName = 'ListTabularItem'
  @propTypes =
    metrics: React.PropTypes.object
    columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
    item: React.PropTypes.object.isRequired
    itemProps: React.PropTypes.object
    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
  # React.Perf.wasted-time from ~300msec to 20msec by doing a deep
  # comparison of props before triggering a re-render.
  shouldComponentUpdate: (nextProps, nextState) =>
    # Quick check to avoid running isEqual if our item === existing item
    return false if _.isEqual(@props, nextProps)
    true

  render: =>
    className = "list-item list-tabular-item #{@props.itemProps?.className}"
    props = _.omit(@props.itemProps ? {}, 'className')

    <div {...props} className={className} onClick={@_onClick} style={position:'absolute', top: @props.metrics.top, width:'100%', height:@props.metrics.height, overflow: 'hidden'}>
      {@_columns()}
    </div>

  _columns: =>
    names = {}
    for column in (@props.columns ? [])
      if names[column.name]
        console.warn("ListTabular: Columns do not have distinct names, will cause React error! `#{column.name}` twice.")
      names[column.name] = true

      <div key={column.name}
           displayName={column.name}
           style={_.pick(column, ['flex', 'width'])}
           className="list-column list-column-#{column.name}">
        {column.resolver(@props.item, @)}
      </div>

  _onClick: (event) =>
    @props.onSelect?(@props.item, event)

    @props.onClick?(@props.item, event)
    if @_lastClickTime? and Date.now() - @_lastClickTime < 350
      @props.onDoubleClick?(@props.item, event)

    @_lastClickTime = Date.now()


class ListTabular extends React.Component
  @displayName = 'ListTabular'
  @propTypes =
    columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
    dataView: React.PropTypes.object
    itemPropsProvider: React.PropTypes.func
    itemHeight: React.PropTypes.number
    onSelect: React.PropTypes.func
    onClick: React.PropTypes.func
    onDoubleClick: React.PropTypes.func

  constructor: (@props) ->
    if not @props.itemHeight
      throw new Error("ListTabular: You must provide an itemHeight - raising to avoid divide by zero errors.")

    @state =
      renderedRangeStart: -1
      renderedRangeEnd: -1

  componentDidMount: =>
    @updateRangeState()

  componentDidUpdate: (prevProps, prevState) =>
    # If our view has been swapped out for an entirely different one,
    # reset our scroll position to the top.
    if prevProps.dataView isnt @props.dataView
      @refs.container.scrollTop = 0

    unless @updateRangeStateFiring
      @updateRangeState()
    @updateRangeStateFiring = false


  onScroll: =>
    # If we've shifted enough pixels from our previous scrollTop to require
    # new rows to be rendered, update our state!
    @updateRangeState()

  updateRangeState: =>
    scrollTop = @refs.container.scrollTop

    # Determine the exact range of rows we want onscreen
    rangeStart = Math.floor(scrollTop / @props.itemHeight)
    rangeSize = Math.ceil(window.innerHeight / @props.itemHeight)
    rangeEnd = Math.min(rangeStart + rangeSize, @props.dataView.count())

    # Final sanity check to prevent needless work
    return if rangeStart is @state.renderedRangeStart and
              rangeEnd is @state.renderedRangeEnd

    @updateRangeStateFiring = true

    @props.dataView.setRetainedRange
      start: rangeStart
      end: rangeEnd

    @setState
      renderedRangeStart: rangeStart
      renderedRangeEnd: rangeEnd

  render: =>
    innerStyles =
      height: @props.dataView.count() * @props.itemHeight

    <ScrollRegion ref="container" onScroll={@onScroll} tabIndex="-1" className="list-container list-tabular" scrollTooltipComponent={@props.scrollTooltipComponent} >
      <div className="list-rows" style={innerStyles}>
        {@_rows()}
      </div>
    </ScrollRegion>

  _rows: =>
    rows = []
<commit_msg>fix(keyboard-cursor): Recent optimization broke keyboard cursor advancing fast<commit_after>_ = require 'underscore'
React = require 'react/addons'
ScrollRegion = require './scroll-region'
{Utils} = require 'nylas-exports'

class ListColumn
  constructor: ({@name, @resolver, @flex, @width}) ->

class ListTabularItem extends React.Component
  @displayName = 'ListTabularItem'
  @propTypes =
    metrics: React.PropTypes.object
    columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
    item: React.PropTypes.object.isRequired
    itemProps: React.PropTypes.object
    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
  # React.Perf.wasted-time from ~300msec to 20msec by doing a deep
  # comparison of props before triggering a re-render.
  shouldComponentUpdate: (nextProps, nextState) =>
    # Quick check to avoid running isEqual if our item === existing item
    return false if _.isEqual(@props, nextProps)
    true

  render: =>
    className = "list-item list-tabular-item #{@props.itemProps?.className}"
    props = _.omit(@props.itemProps ? {}, 'className')

    <div {...props} className={className} onClick={@_onClick} style={position:'absolute', top: @props.metrics.top, width:'100%', height:@props.metrics.height, overflow: 'hidden'}>
      {@_columns()}
    </div>

  _columns: =>
    names = {}
    for column in (@props.columns ? [])
      if names[column.name]
        console.warn("ListTabular: Columns do not have distinct names, will cause React error! `#{column.name}` twice.")
      names[column.name] = true

      <div key={column.name}
           displayName={column.name}
           style={_.pick(column, ['flex', 'width'])}
           className="list-column list-column-#{column.name}">
        {column.resolver(@props.item, @)}
      </div>

  _onClick: (event) =>
    @props.onSelect?(@props.item, event)

    @props.onClick?(@props.item, event)
    if @_lastClickTime? and Date.now() - @_lastClickTime < 350
      @props.onDoubleClick?(@props.item, event)

    @_lastClickTime = Date.now()


class ListTabular extends React.Component
  @displayName = 'ListTabular'
  @propTypes =
    columns: React.PropTypes.arrayOf(React.PropTypes.object).isRequired
    dataView: React.PropTypes.object
    itemPropsProvider: React.PropTypes.func
    itemHeight: React.PropTypes.number
    onSelect: React.PropTypes.func
    onClick: React.PropTypes.func
    onDoubleClick: React.PropTypes.func

  constructor: (@props) ->
    if not @props.itemHeight
      throw new Error("ListTabular: You must provide an itemHeight - raising to avoid divide by zero errors.")

    @state =
      renderedRangeStart: -1
      renderedRangeEnd: -1

  componentDidMount: =>
    @updateRangeState()

  componentDidUpdate: (prevProps, prevState) =>
    # If our view has been swapped out for an entirely different one,
    # reset our scroll position to the top.
    if prevProps.dataView isnt @props.dataView
      @refs.container.scrollTop = 0

    unless @updateRangeStateFiring
      @updateRangeState()
    @updateRangeStateFiring = false


  onScroll: =>
    # If we've shifted enough pixels from our previous scrollTop to require
    # new rows to be rendered, update our state!
    @updateRangeState()

  updateRangeState: =>
    scrollTop = @refs.container.scrollTop

    # Determine the exact range of rows we want onscreen
    rangeStart = Math.floor(scrollTop / @props.itemHeight)
    rangeSize = Math.ceil(window.innerHeight / @props.itemHeight)
    rangeEnd = rangeStart + rangeSize

    # Expand the start/end so that you can advance the keyboard cursor fast and
    # we have items to move to and then scroll to.
    rangeStart = Math.max(0, rangeStart - 5)
    rangeEnd = Math.min(rangeEnd + 5, @props.dataView.count())

    # Final sanity check to prevent needless work
    return if rangeStart is @state.renderedRangeStart and
              rangeEnd is @state.renderedRangeEnd

    @updateRangeStateFiring = true

    @props.dataView.setRetainedRange
      start: rangeStart
      end: rangeEnd

    @setState
      renderedRangeStart: rangeStart
      renderedRangeEnd: rangeEnd

  render: =>
    innerStyles =
      height: @props.dataView.count() * @props.itemHeight

    <ScrollRegion ref="container" onScroll={@onScroll} tabIndex="-1" className="list-container list-tabular" scrollTooltipComponent={@props.scrollTooltipComponent} >
      <div className="list-rows" style={innerStyles}>
        {@_rows()}
      </div>
    </ScrollRegion>

  _rows: =>
    rows = []

{'fraction_non_alphanumeric': 0.11274182788525684, 'fraction_numerical': 0.003669112741827885, 'mean_word_length': 3.484047856430708, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 43, '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': '2625647', 'n_tokens_mistral': 2684, 'n_tokens_neox': 2627, 'n_words': 697}