<commit_before>const _ = require('underscore-plus');
const {CompositeDisposable} = require('atom');
const ResultsView = require('./results-view');
const {showIf, getSearchResultsMessage, escapeHtml} = require('./util');
const etch = require('etch');

module.exports =
class ResultsPaneView {
  constructor() {
    this.model = this.constructor.model;
    this.model.setActive(true);
    this.isLoading = false;
    this.searchErrors = [];
    this.searchResults = null;
    this.searchingIsSlow = false;
    this.numberOfPathsSearched = 0;

    etch.initialize(this);

    this.onFinishedSearching(this.model.getResultsSummary());
    this.element.addEventListener('focus', this.focused.bind(this));
    this.element.addEventListener('click', event => {
      switch (event.target) {
        case this.refs.collapseAll:
          this.collapseAllResults();
          break;
        case this.refs.expandAll:
          this.expandAllResults();
          break;
      }
    })

    this.subscriptions = new CompositeDisposable(
      this.model.onDidStartSearching(this.onSearch.bind(this)),
      this.model.onDidFinishSearching(this.onFinishedSearching.bind(this)),
      this.model.onDidClear(this.onCleared.bind(this)),
      this.model.onDidClearReplacementState(this.onReplacementStateCleared.bind(this)),
      this.model.onDidSearchPaths(this.onPathsSearched.bind(this)),
      this.model.onDidErrorForPath(error => this.appendError(error.message))
    );
  }

  update() {}

  destroy() {
    this.model.setActive(false);
    this.subscriptions.dispose();
  }

  render() {
    const matchCount = this.searchResults && this.searchResults.matchCount;

    return (
      etch.dom.div(
        {
          tabIndex: -1,
          className: `preview-pane pane-item ${matchCount === 0 ? 'no-results' : ''}`,
        },

        etch.dom.div({className: 'preview-header'},
          etch.dom.span({
            ref: 'previewCount',
            className: 'preview-count inline-block',
            innerHTML: this.isLoading
              ? 'Searching...'
              : (getSearchResultsMessage(this.searchResults) || 'Project search results')
          }),

          etch.dom.div(
            {
              ref: 'previewControls',
              className: 'preview-controls',
              style: showIf(matchCount > 0)
            },

            etch.dom.div({className: 'btn-group'},
              etch.dom.button({ref: 'collapseAll', className: 'btn'}, 'Collapse All'),
              etch.dom.button({ref: 'expandAll', className: 'btn'}, 'Expand All')
            )
          ),

          etch.dom.div({className: 'inline-block', style: showIf(this.isLoading)},
            etch.dom.div({className: 'loading loading-spinner-tiny inline-block'}),

            etch.dom.div(
              {
                className: 'inline-block',
                style: showIf(this.isLoading && this.searchingIsSlow)
              },

              etch.dom.span({ref: 'searchedCount', className: 'searched-count'},
                this.numberOfPathsSearched.toString()
              ),
              etch.dom.span({}, ' paths searched')
            )
          )<commit_msg>Avoid changes to preview header element's height when re-searching<commit_after>const _ = require('underscore-plus');
const {CompositeDisposable} = require('atom');
const ResultsView = require('./results-view');
const {showIf, getSearchResultsMessage, escapeHtml} = require('./util');
const etch = require('etch');

module.exports =
class ResultsPaneView {
  constructor() {
    this.model = this.constructor.model;
    this.model.setActive(true);
    this.isLoading = false;
    this.searchErrors = [];
    this.searchResults = null;
    this.searchingIsSlow = false;
    this.numberOfPathsSearched = 0;

    etch.initialize(this);

    this.onFinishedSearching(this.model.getResultsSummary());
    this.element.addEventListener('focus', this.focused.bind(this));
    this.element.addEventListener('click', event => {
      switch (event.target) {
        case this.refs.collapseAll:
          this.collapseAllResults();
          break;
        case this.refs.expandAll:
          this.expandAllResults();
          break;
      }
    })

    this.subscriptions = new CompositeDisposable(
      this.model.onDidStartSearching(this.onSearch.bind(this)),
      this.model.onDidFinishSearching(this.onFinishedSearching.bind(this)),
      this.model.onDidClear(this.onCleared.bind(this)),
      this.model.onDidClearReplacementState(this.onReplacementStateCleared.bind(this)),
      this.model.onDidSearchPaths(this.onPathsSearched.bind(this)),
      this.model.onDidErrorForPath(error => this.appendError(error.message))
    );
  }

  update() {}

  destroy() {
    this.model.setActive(false);
    this.subscriptions.dispose();
  }

  render() {
    const matchCount = this.searchResults && this.searchResults.matchCount;

    return (
      etch.dom.div(
        {
          tabIndex: -1,
          className: `preview-pane pane-item ${matchCount === 0 ? 'no-results' : ''}`,
        },

        etch.dom.div({className: 'preview-header'},
          etch.dom.span({
            ref: 'previewCount',
            className: 'preview-count inline-block',
            innerHTML: this.isLoading
              ? 'Searching...'
              : (getSearchResultsMessage(this.searchResults) || 'Project search results')
          }),

          etch.dom.div(
            {
              ref: 'previewControls',
              className: 'preview-controls',
              style: {visibility: matchCount > 0 ? 'visible' : 'hidden'}
            },

            etch.dom.div({className: 'btn-group'},
              etch.dom.button({ref: 'collapseAll', className: 'btn'}, 'Collapse All'),
              etch.dom.button({ref: 'expandAll', className: 'btn'}, 'Expand All')
            )
          ),

          etch.dom.div({className: 'inline-block', style: showIf(this.isLoading)},
            etch.dom.div({className: 'loading loading-spinner-tiny inline-block'}),

            etch.dom.div(
              {
                className: 'inline-block',
                style: showIf(this.isLoading && this.searchingIsSlow)
              },

              etch.dom.span({ref: 'searchedCount', className: 'searched-count'},
                this.numberOfPathsSearched.toString()
              ),
              etch.dom.span({}, ' paths searched')
            )
          )
{'fraction_non_alphanumeric': 0.13803299097416744, 'fraction_numerical': 0.0012449424214130097, 'mean_word_length': 2.349140177175612, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 9, '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': '786524', 'n_tokens_mistral': 1885, 'n_tokens_neox': 1787, 'n_words': 283}