<commit_before>import React from 'react';
import moment from 'moment';

import classnames from 'classnames';

import { sendToGA, buildSurveyURL, formatDate, createMarkup } from '../lib/utils';

import LoadingPage from './LoadingPage';
import NotFoundPage from './NotFoundPage';

import Header from '../components/Header';
import Footer from '../components/Footer';
import ExperimentDisableDialog from '../components/ExperimentDisableDialog';
import ExperimentTourDialog from '../components/ExperimentTourDialog';
import MainInstallButton from '../components/MainInstallButton';
import ExperimentCardList from '../components/ExperimentCardList';
import ExperimentPreFeedbackDialog from '../components/ExperimentPreFeedbackDialog';

const CHANGE_HEADER_ON = 105;

export default class ExperimentPage extends React.Component {

  constructor(props) {
    super(props);

    const { isExperimentEnabled, getExperimentBySlug } = this.props;
    const experiment = getExperimentBySlug(this.props.params.slug);

    // TODO: Clean this up per #1367
    this.state = {
      experiment,
      enabled: isExperimentEnabled(experiment),
      useStickyHeader: false,
      highlightMeasurementPanel: false,
      isEnabling: false,
      isDisabling: false,
      progressButtonWidth: null,
      showDisableDialog: false,
      shouldShowTourDialog: false,
      showTourDialog: false,
      showPreFeedbackDialog: false
    };

    // HACK: Set this as a plain object property, so we don't trigger crazy
    // state changes on scrolling events.
    this.didScroll = false;
  }

  componentWillReceiveProps(nextProps) {
    const { shouldShowTourDialog, enabled: prevEnabled } = this.state;
    const { isExperimentEnabled, getExperimentBySlug } = nextProps;

    const prevExperiment = getExperimentBySlug(this.props.params.slug);
    const prevInProgress = prevExperiment && prevExperiment.inProgress;

    const nextExperiment = getExperimentBySlug(nextProps.params.slug);
    const nextInProgress = nextExperiment && nextExperiment.inProgress;
    const nextEnabled = nextExperiment && isExperimentEnabled(nextExperiment);

    if (!nextInProgress && prevInProgress !== nextInProgress) {
      this.setState({
        isEnabling: false,
        isDisabling: false
      });
    }

    this.setState({
      experiment: nextExperiment,
      enabled: nextEnabled
    });

    // On enable state change, stop installation indicators & show tour dialog if needed.
    if (prevEnabled !== nextEnabled) {
      // TODO: Tweak experiment install count?
      const showTourDialog = shouldShowTourDialog &&
                             nextExperiment &&
                             !nextExperiment.error;
      this.setState({
        shouldShowTourDialog: false,
        showTourDialog
      });
    }
  }

  isValidVersion(min) {
    const version = parseInt(navigator.userAgent.split('/').pop(), 10);
    return typeof min === 'undefined' || version >= min;
  }

  getIncompatibleInstalled(incompatible) {
    if (!incompatible || !this.props.installedAddons.length) {
      return null;
    }
    return Object.keys(incompatible).filter(guid => (
      this.props.installedAddons.indexOf(guid) !== -1
    ));
  }

  renderIncompatibleAddons() {
    const { incompatible } = this.state.experiment;
    if (!incompatible) return null;
    const installed = this.getIncompatibleInstalled(incompatible);
    if (!installed || installed.length === 0) return null;

    const helpUrl = 'https://support.mozilla.org/kb/disable-or-remove-add-ons';

    return (
      <section className="incompatible-addons"><commit_msg>default installedAddons to empty array in ExperimentPage.getIncompatibleInstalled. fixes #1533<commit_after>import React from 'react';
import moment from 'moment';

import classnames from 'classnames';

import { sendToGA, buildSurveyURL, formatDate, createMarkup } from '../lib/utils';

import LoadingPage from './LoadingPage';
import NotFoundPage from './NotFoundPage';

import Header from '../components/Header';
import Footer from '../components/Footer';
import ExperimentDisableDialog from '../components/ExperimentDisableDialog';
import ExperimentTourDialog from '../components/ExperimentTourDialog';
import MainInstallButton from '../components/MainInstallButton';
import ExperimentCardList from '../components/ExperimentCardList';
import ExperimentPreFeedbackDialog from '../components/ExperimentPreFeedbackDialog';

const CHANGE_HEADER_ON = 105;

export default class ExperimentPage extends React.Component {

  constructor(props) {
    super(props);

    const { isExperimentEnabled, getExperimentBySlug } = this.props;
    const experiment = getExperimentBySlug(this.props.params.slug);

    // TODO: Clean this up per #1367
    this.state = {
      experiment,
      enabled: isExperimentEnabled(experiment),
      useStickyHeader: false,
      highlightMeasurementPanel: false,
      isEnabling: false,
      isDisabling: false,
      progressButtonWidth: null,
      showDisableDialog: false,
      shouldShowTourDialog: false,
      showTourDialog: false,
      showPreFeedbackDialog: false
    };

    // HACK: Set this as a plain object property, so we don't trigger crazy
    // state changes on scrolling events.
    this.didScroll = false;
  }

  componentWillReceiveProps(nextProps) {
    const { shouldShowTourDialog, enabled: prevEnabled } = this.state;
    const { isExperimentEnabled, getExperimentBySlug } = nextProps;

    const prevExperiment = getExperimentBySlug(this.props.params.slug);
    const prevInProgress = prevExperiment && prevExperiment.inProgress;

    const nextExperiment = getExperimentBySlug(nextProps.params.slug);
    const nextInProgress = nextExperiment && nextExperiment.inProgress;
    const nextEnabled = nextExperiment && isExperimentEnabled(nextExperiment);

    if (!nextInProgress && prevInProgress !== nextInProgress) {
      this.setState({
        isEnabling: false,
        isDisabling: false
      });
    }

    this.setState({
      experiment: nextExperiment,
      enabled: nextEnabled
    });

    // On enable state change, stop installation indicators & show tour dialog if needed.
    if (prevEnabled !== nextEnabled) {
      // TODO: Tweak experiment install count?
      const showTourDialog = shouldShowTourDialog &&
                             nextExperiment &&
                             !nextExperiment.error;
      this.setState({
        shouldShowTourDialog: false,
        showTourDialog
      });
    }
  }

  isValidVersion(min) {
    const version = parseInt(navigator.userAgent.split('/').pop(), 10);
    return typeof min === 'undefined' || version >= min;
  }

  getIncompatibleInstalled(incompatible) {
    if (!incompatible) {
      return [];
    }
    const installed = this.props.installedAddons || [];
    return Object.keys(incompatible).filter(guid => (
      installed.indexOf(guid) !== -1
    ));
  }

  renderIncompatibleAddons() {
    const { incompatible } = this.state.experiment;
    const installed = this.getIncompatibleInstalled(incompatible);
    if (installed.length === 0) return null;

    const helpUrl = 'https://support.mozilla.org/kb/disable-or-remove-add-ons';

    return (
      <section className="incompatible-addons">
{'fraction_non_alphanumeric': 0.10160132523467698, 'fraction_numerical': 0.003589177250138045, 'mean_word_length': 3.4888475836431225, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 2, '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': '7477958', 'n_tokens_mistral': 1997, 'n_tokens_neox': 1915, 'n_words': 475}