<commit_before>import React from 'react';
import LogLine from './LogLine';
import Humanize from 'humanize-plus';
import classNames from 'classnames';

import { connect } from 'react-redux';
import { taskGroupTop, taskGroupBottom } from '../../actions/log';

function sum (numbers) {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }
  return total;
}

class LogLines extends React.Component {
  componentDidMount() {
    window.addEventListener('resize', this.handleScroll.bind(this));
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleScroll.bind(this));
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.updatedAt !== this.props.updatedAt) {
      if (this.props.tailing) {
        this.refs.tailContents.scrollTop = this.refs.tailContents.scrollHeight;
      } else if (this.props.prependedLineCount > 0 || this.props.linesRemovedFromTop > 0) {
        this.refs.tailContents.scrollTop += 20 * (this.props.prependedLineCount - this.props.linesRemovedFromTop);
      } else {
        this.handleScroll();
      }
    }
  }

  renderLoadingPrevious() {
    if (this.props.initialDataLoaded) {
      if (!this.props.reachedStartOfFile) {
        if (this.props.search) {
          return <div>Searching for '{this.props.search}'... ({Humanize.filesize(this.props.bytesRemainingBefore)} remaining)</div>;
        } else {
          return <div>Loading previous... ({Humanize.filesize(this.props.bytesRemainingBefore)} remaining)</div>;
        }
      }
    }
  }

  renderLogLines() {
    const initialOffset = this.props.initialOffset;
    const colorMap = this.props.colorMap;
    return this.props.logLines.map(function ({data, offset, taskId, timestamp}) {
      return (
        <LogLine
          content={data}
          key={taskId + '_' + offset}
          offset={offset}
          taskId={taskId}
          timestamp={timestamp}
          isHighlighted={offset === initialOffset}
          color={colorMap[taskId]}
        />
      );
    });
  }

  renderLoadingMore() {
    if (this.props.terminated) {
      return null;
    } else if (this.props.initialDataLoaded) {
      if (this.props.reachedEndOfFile) {
        if (this.props.search) {
          return <div>Tailing for '{this.props.search}'...</div>;
        } else {
          return <div>Tailing...</div>;
        }
      } else {
        if (this.props.search) {
          return <div>Searching for '{this.props.search}'... ({Humanize.filesize(this.props.bytesRemainingAfter)} remaining)</div>;
        } else {
          return <div>Loading more... ({Humanize.filesize(this.props.bytesRemainingAfter)} remaining)</div>;
        }
      }
    }
  }


  handleScroll() {
    const {scrollTop, scrollHeight, clientHeight} = this.refs.tailContents;

    if (scrollTop < clientHeight) {
      this.props.taskGroupTop(this.props.taskGroupId, true);
    } else {
      this.props.taskGroupTop(this.props.taskGroupId, false);
    }

    if (scrollTop + clientHeight > scrollHeight - clientHeight) {
      this.props.taskGroupBottom(this.props.taskGroupId, true, (scrollTop + clientHeight > scrollHeight - 20));
    } else {
      this.props.taskGroupBottom(this.props.taskGroupId, false);
    }
  }

  render() {
    return (<div className="contents-container">
      <div className={classNames(['tail-contents', this.props.activeColor])} ref="tailContents" onScroll={(event) => { this.handleScroll(event); }}>
        {this.renderLoadingPrevious()}
        {this.renderLogLines()}
        {this.renderLoadingMore()}
        {this.props.fileNotFound}
      </div>
    </div>);
  }<commit_msg>Guard refs uses with an if statement<commit_after>import React from 'react';
import LogLine from './LogLine';
import Humanize from 'humanize-plus';
import classNames from 'classnames';

import { connect } from 'react-redux';
import { taskGroupTop, taskGroupBottom } from '../../actions/log';

function sum (numbers) {
  let total = 0;
  for (let i = 0; i < numbers.length; i++) {
    total += numbers[i];
  }
  return total;
}

class LogLines extends React.Component {
  componentDidMount() {
    window.addEventListener('resize', this.handleScroll.bind(this));
  }

  componentWillUnmount() {
    window.removeEventListener('resize', this.handleScroll.bind(this));
  }

  componentDidUpdate(prevProps, prevState) {
    if (prevProps.updatedAt !== this.props.updatedAt) {
      if (this.refs.tailContents && this.props.tailing) {
        this.refs.tailContents.scrollTop = this.refs.tailContents.scrollHeight;
      } else if (this.refs.tailContents && (this.props.prependedLineCount > 0 || this.props.linesRemovedFromTop > 0)) {
        this.refs.tailContents.scrollTop += 20 * (this.props.prependedLineCount - this.props.linesRemovedFromTop);
      } else {
        this.handleScroll();
      }
    }
  }

  renderLoadingPrevious() {
    if (this.props.initialDataLoaded) {
      if (!this.props.reachedStartOfFile) {
        if (this.props.search) {
          return <div>Searching for '{this.props.search}'... ({Humanize.filesize(this.props.bytesRemainingBefore)} remaining)</div>;
        } else {
          return <div>Loading previous... ({Humanize.filesize(this.props.bytesRemainingBefore)} remaining)</div>;
        }
      }
    }
  }

  renderLogLines() {
    const initialOffset = this.props.initialOffset;
    const colorMap = this.props.colorMap;
    return this.props.logLines.map(function ({data, offset, taskId, timestamp}) {
      return (
        <LogLine
          content={data}
          key={taskId + '_' + offset}
          offset={offset}
          taskId={taskId}
          timestamp={timestamp}
          isHighlighted={offset === initialOffset}
          color={colorMap[taskId]}
        />
      );
    });
  }

  renderLoadingMore() {
    if (this.props.terminated) {
      return null;
    } else if (this.props.initialDataLoaded) {
      if (this.props.reachedEndOfFile) {
        if (this.props.search) {
          return <div>Tailing for '{this.props.search}'...</div>;
        } else {
          return <div>Tailing...</div>;
        }
      } else {
        if (this.props.search) {
          return <div>Searching for '{this.props.search}'... ({Humanize.filesize(this.props.bytesRemainingAfter)} remaining)</div>;
        } else {
          return <div>Loading more... ({Humanize.filesize(this.props.bytesRemainingAfter)} remaining)</div>;
        }
      }
    }
  }


  handleScroll() {
    if (!this.refs.tailContents) return;
    const {scrollTop, scrollHeight, clientHeight} = this.refs.tailContents;

    if (scrollTop < clientHeight) {
      this.props.taskGroupTop(this.props.taskGroupId, true);
    } else {
      this.props.taskGroupTop(this.props.taskGroupId, false);
    }

    if (scrollTop + clientHeight > scrollHeight - clientHeight) {
      this.props.taskGroupBottom(this.props.taskGroupId, true, (scrollTop + clientHeight > scrollHeight - 20));
    } else {
      this.props.taskGroupBottom(this.props.taskGroupId, false);
    }
  }

  render() {
    return (<div className="contents-container">
      <div className={classNames(['tail-contents', this.props.activeColor])} ref="tailContents" onScroll={(event) => { this.handleScroll(event); }}>
        {this.renderLoadingPrevious()}
        {this.renderLogLines()}
        {this.renderLoadingMore()}
        {this.props.fileNotFound}
      </div>
    </div>);
  }
{'fraction_non_alphanumeric': 0.1436270547022366, 'fraction_numerical': 0.002155753166262463, 'mean_word_length': 2.8184156378600824, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 47, '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': '5927817', 'n_tokens_mistral': 2269, 'n_tokens_neox': 2214, 'n_words': 399}