<commit_before>import React, { Component } from 'react';
import classNames from 'classnames';
import memoize from 'memoize-one';
import Helmet from 'react-helmet';
import HTML5Backend from 'react-dnd-html5-backend';
import PropTypes from 'prop-types';
import Raven from 'raven-js';
import { matchPath } from 'react-router-dom';
import { renderRoutes } from 'react-router-config';
import { Alert, Button, Panel } from 'react-bootstrap';
import { asyncConnect } from 'redux-connect';
import { DragDropContext } from 'react-dnd';

import { isLoaded as isAuthLoaded, load as loadAuth } from 'store/modules/auth';
import config from 'config';
import { apiFetch, inStorage, setStorage } from 'helpers/utils';

// direct import to prevent circular dependency
import AppHeader from 'containers/AppHeader/AppHeader';

import { Footer, SupporterAnnounce } from 'components/siteComponents';
import { InfoIcon } from 'components/icons';

import 'shared/fonts/fonts.scss';
import './style.scss';


// named export for tests
export class App extends Component {

  static propTypes = {
    auth: PropTypes.object,
    dispatch: PropTypes.func,
    loaded: PropTypes.bool,
    location: PropTypes.object,
    route: PropTypes.object,
    spaceUtilization: PropTypes.object
  };

  static childContextTypes = {
    isAnon: PropTypes.bool,
    isEmbed: PropTypes.bool,
    isMobile: PropTypes.bool
  };

  constructor(props) {
    super(props);
    const ua = global.navigator ? global.navigator.userAgent : '';

    this.handle = null;
    this.isMobile = Boolean(ua.match(/Mobile|Android|BlackBerry/));
    this.state = {
      error: null,
      lastPathname: null,
      loginStateAlert: false,
      mobileAlert: true,
      outOfSpaceAlert: true,
      stalled: false,
      supporterAnnounce: true
    };
  }

  static getDerivedStateFromProps(props, state) {
    if (!props.loaded) {
      const newState = state;
      newState.lastPathname = props.location.pathname;
      return newState;
    }

    return null;
  }

  getChildContext() {
    const { auth, location: { pathname } } = this.props;
    const match = this.getActiveRoute(pathname);

    return {
      isAnon: auth.getIn(['user', 'anon']),
      isEmbed: match.embed || false,
      isMobile: this.isMobile,
    };
  }

  componentDidMount() {
    if (this.isMobile) {
      if (inStorage('mobileNotice', window.sessionStorage)) {
        this.setState({ mobileAlert: false });
      }
    }

    if (inStorage('supporterAnnounceDismiss')) {
      this.setState({ supporterAnnounce: false });
    }<commit_msg>Hide announce banner by default (#719)<commit_after>import React, { Component } from 'react';
import classNames from 'classnames';
import memoize from 'memoize-one';
import Helmet from 'react-helmet';
import HTML5Backend from 'react-dnd-html5-backend';
import PropTypes from 'prop-types';
import Raven from 'raven-js';
import { matchPath } from 'react-router-dom';
import { renderRoutes } from 'react-router-config';
import { Alert, Button, Panel } from 'react-bootstrap';
import { asyncConnect } from 'redux-connect';
import { DragDropContext } from 'react-dnd';

import { isLoaded as isAuthLoaded, load as loadAuth } from 'store/modules/auth';
import config from 'config';
import { apiFetch, inStorage, setStorage } from 'helpers/utils';

// direct import to prevent circular dependency
import AppHeader from 'containers/AppHeader/AppHeader';

import { Footer, SupporterAnnounce } from 'components/siteComponents';
import { InfoIcon } from 'components/icons';

import 'shared/fonts/fonts.scss';
import './style.scss';


// named export for tests
export class App extends Component {

  static propTypes = {
    auth: PropTypes.object,
    dispatch: PropTypes.func,
    loaded: PropTypes.bool,
    location: PropTypes.object,
    route: PropTypes.object,
    spaceUtilization: PropTypes.object
  };

  static childContextTypes = {
    isAnon: PropTypes.bool,
    isEmbed: PropTypes.bool,
    isMobile: PropTypes.bool
  };

  constructor(props) {
    super(props);
    const ua = global.navigator ? global.navigator.userAgent : '';

    this.handle = null;
    this.isMobile = Boolean(ua.match(/Mobile|Android|BlackBerry/));
    this.state = {
      error: null,
      lastPathname: null,
      loginStateAlert: false,
      mobileAlert: true,
      outOfSpaceAlert: true,
      stalled: false,
      supporterAnnounce: false
    };
  }

  static getDerivedStateFromProps(props, state) {
    if (!props.loaded) {
      const newState = state;
      newState.lastPathname = props.location.pathname;
      return newState;
    }

    return null;
  }

  getChildContext() {
    const { auth, location: { pathname } } = this.props;
    const match = this.getActiveRoute(pathname);

    return {
      isAnon: auth.getIn(['user', 'anon']),
      isEmbed: match.embed || false,
      isMobile: this.isMobile,
    };
  }

  componentDidMount() {
    if (this.isMobile) {
      if (inStorage('mobileNotice', window.sessionStorage)) {
        this.setState({ mobileAlert: false });
      }
    }

    if (!inStorage('supporterAnnounceDismiss')) {
      this.setState({ supporterAnnounce: true });
    }
{'fraction_non_alphanumeric': 0.11894614490507555, 'fraction_numerical': 0.0013560635412630763, 'mean_word_length': 3.521015761821366, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, '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': '6325227', 'n_tokens_mistral': 1558, 'n_tokens_neox': 1538, 'n_words': 395}