<commit_before>import { connect } from 'react-redux'
import { setReadProgress } from '../actions/header'
import { ARTICLE, PHOTOGRAPHY_ARTICLE, DEFAULT_HEADER_HEIGHT } from '../constants/index'
import NavMenu from '../components/navigation/NavMenu'
import HeaderProgress from '../components/navigation/HeaderProgress'
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import styles from './NavBar.scss'

// lodash
import debounce from 'lodash/debounce'
import get from 'lodash/get'

class NavBar extends Component {
  constructor(props) {
    super(props)
    this.state = {
      height: DEFAULT_HEADER_HEIGHT,
      isScrolledOver: false,
      isPageChanged: false
    }
    this._getHeaderHeight = this._getHeaderHeight.bind(this)
    this._handleScroll = this._handleScroll.bind(this)
    this.debouncedScroll = debounce(() => { this._handleScroll() }, 50, { 'maxWait': 150 })
    this.getDebouncedHeight = debounce(() => { this._getHeaderHeight() }, 100, { 'maxWait': 300 })
  }

  componentDidMount() {
    this._getHeaderHeight()
    window.addEventListener('resize', this.getDebouncedHeight)

    // detect sroll position
    window.addEventListener('scroll', this.debouncedScroll)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.getDebouncedHeight)
    window.removeEventListener('scroll', this.debouncedScroll)
  }

  componentWillReceiveProps(nextProps) {
    if(this.props.path !== nextProps.path) {
      this.setState({ isPageChanged: true })
    }
  }

  componentDidUpdate() {
    if(this.state.isPageChanged && !this.state.isScrolledOver) {
      this._getHeaderHeight()
      this.setState({ isPageChanged: false })
    }
  }

  _handleScroll() {
    const scrollPos = window.scrollY
    const sThreshold = this.state.height / 2
    if(scrollPos > sThreshold && !this.state.isScrolledOver) {
      this.setState({ isScrolledOver: true })
    } else if(scrollPos <= sThreshold && this.state.isScrolledOver) {
      this.setState({ isScrolledOver: false })
    }
  }

  _getHeaderHeight() {
    const rect = ReactDOM.findDOMNode(this.refs.headerbox).getBoundingClientRect()
    let hHeight = get(rect, 'height', DEFAULT_HEADER_HEIGHT)
    hHeight = (hHeight < DEFAULT_HEADER_HEIGHT) ? DEFAULT_HEADER_HEIGHT : hHeight
    this.setState({
      height: hHeight
    })
  }

  shouldComponentUpdate(nextProps, nextState) { // eslint-disable-line
    if(nextState.height !== this.state.height ||
       nextProps.header.pageType !== this.props.header.pageType ||
       nextProps.header.readPercent !== this.props.header.readPercent ||
       nextState.isScrolledOver !== this.state.isScrolledOver) {
      return true
    }
    if (nextProps.path === this.props.path) {
      return false
    }
    return true
  }

  _renderMenu() {
    return (
      <div>
        <NavMenu {...this.props}
          isScrolledOver={this.state.isScrolledOver}
          pageTitle={this.props.header.pageTitle}
          pageTopic={this.props.header.pageTopic}
          articleId={this.props.header.articleId}
          />
      </div>
    )
  }

  render() {
    const { height, isScrolledOver } = this.state
    const { header } = this.props
    const percent = header.readPercent || 0

    let progressBar = (header.pageType === ARTICLE || header.pageType === PHOTOGRAPHY_ARTICLE) && isScrolledOver ? <HeaderProgress percent={percent}/> : null

    return (
      <div style={{ height: height+'px' }}>
        <div ref="headerbox" className={styles.fixTop}>
          {this._renderMenu()}
          {progressBar}
        </div>
      </div>
    )
  }
}

NavBar.contextTypes = {
  device: PropTypes.string
}

function mapStateToProps(state) {
  return {
    header: state.header || {}
  }
}

export default connect(mapStateToProps, { setReadProgress })(NavBar)
<commit_msg>[Bug fix] show progress bar on long form article<commit_after>import { connect } from 'react-redux'
import { setReadProgress } from '../actions/header'
import { ARTICLE, DEFAULT_HEADER_HEIGHT, PHOTOGRAPHY_ARTICLE, LONGFORM_ARTICLE_STYLE } from '../constants/index'
import NavMenu from '../components/navigation/NavMenu'
import HeaderProgress from '../components/navigation/HeaderProgress'
import React, { Component, PropTypes } from 'react'
import ReactDOM from 'react-dom'
import styles from './NavBar.scss'

// lodash
import debounce from 'lodash/debounce'
import get from 'lodash/get'

class NavBar extends Component {
  constructor(props) {
    super(props)
    this.state = {
      height: DEFAULT_HEADER_HEIGHT,
      isScrolledOver: false,
      isPageChanged: false
    }
    this._getHeaderHeight = this._getHeaderHeight.bind(this)
    this._handleScroll = this._handleScroll.bind(this)
    this.debouncedScroll = debounce(() => { this._handleScroll() }, 50, { 'maxWait': 150 })
    this.getDebouncedHeight = debounce(() => { this._getHeaderHeight() }, 100, { 'maxWait': 300 })
  }

  componentDidMount() {
    this._getHeaderHeight()
    window.addEventListener('resize', this.getDebouncedHeight)

    // detect sroll position
    window.addEventListener('scroll', this.debouncedScroll)
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.getDebouncedHeight)
    window.removeEventListener('scroll', this.debouncedScroll)
  }

  componentWillReceiveProps(nextProps) {
    if(this.props.path !== nextProps.path) {
      this.setState({ isPageChanged: true })
    }
  }

  componentDidUpdate() {
    if(this.state.isPageChanged && !this.state.isScrolledOver) {
      this._getHeaderHeight()
      this.setState({ isPageChanged: false })
    }
  }

  _handleScroll() {
    const scrollPos = window.scrollY
    const sThreshold = this.state.height / 2
    if(scrollPos > sThreshold && !this.state.isScrolledOver) {
      this.setState({ isScrolledOver: true })
    } else if(scrollPos <= sThreshold && this.state.isScrolledOver) {
      this.setState({ isScrolledOver: false })
    }
  }

  _getHeaderHeight() {
    const rect = ReactDOM.findDOMNode(this.refs.headerbox).getBoundingClientRect()
    let hHeight = get(rect, 'height', DEFAULT_HEADER_HEIGHT)
    hHeight = (hHeight < DEFAULT_HEADER_HEIGHT) ? DEFAULT_HEADER_HEIGHT : hHeight
    this.setState({
      height: hHeight
    })
  }

  shouldComponentUpdate(nextProps, nextState) { // eslint-disable-line
    if(nextState.height !== this.state.height ||
       nextProps.header.pageType !== this.props.header.pageType ||
       nextProps.header.readPercent !== this.props.header.readPercent ||
       nextState.isScrolledOver !== this.state.isScrolledOver) {
      return true
    }
    if (nextProps.path === this.props.path) {
      return false
    }
    return true
  }

  _renderMenu() {
    return (
      <div>
        <NavMenu {...this.props}
          isScrolledOver={this.state.isScrolledOver}
          pageTitle={this.props.header.pageTitle}
          pageTopic={this.props.header.pageTopic}
          articleId={this.props.header.articleId}
          />
      </div>
    )
  }

  render() {
    const { height, isScrolledOver } = this.state
    const { header } = this.props
    const percent = header.readPercent || 0

    let progressBar = (header.pageType === ARTICLE || header.pageType === PHOTOGRAPHY_ARTICLE || header.pageType === LONGFORM_ARTICLE_STYLE) && isScrolledOver ? <HeaderProgress percent={percent}/> : null

    return (
      <div style={{ height: height+'px' }}>
        <div ref="headerbox" className={styles.fixTop}>
          {this._renderMenu()}
          {progressBar}
        </div>
      </div>
    )
  }
}

NavBar.contextTypes = {
  device: PropTypes.string
}

function mapStateToProps(state) {
  return {
    header: state.header || {}
  }
}

export default connect(mapStateToProps, { setReadProgress })(NavBar)

{'fraction_non_alphanumeric': 0.12710448528466778, 'fraction_numerical': 0.003341472818403804, 'mean_word_length': 3.306585500830105, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 25, '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': '2066502', 'n_tokens_mistral': 2425, 'n_tokens_neox': 2358, 'n_words': 443}