<commit_before>import * as React from 'react';
import { connect, Provider } from 'react-redux';
import {
  Redirect,
  Route,
  RouteComponentProps,
  Switch,
  withRouter,
} from 'react-router';
import { Router } from 'react-router-dom';
const { LocalizationProvider } = require('fluent-react');
import { createBrowserHistory } from 'history';
import store from '../stores/root';
import URLS from '../urls';
import {
  isMobileWebkit,
  isFirefoxFocus,
  isNativeIOS,
  sleep,
  isProduction,
  replacePathLocale,
} from '../utility';
import {
  createMessagesGenerator,
  DEFAULT_LOCALE,
  LOCALES,
  negotiateLocales,
} from '../services/localization';
import API from '../services/api';
import { Locale } from '../stores/locale';
import { Notifications } from '../stores/notifications';
import StateTree from '../stores/tree';
import { Uploads } from '../stores/uploads';
import Layout from './layout/layout';
import NotificationPill from './notification-pill/notification-pill';
import ListenPage from './pages/contribution/listen/listen';
import SpeakPage from './pages/contribution/speak/speak';
import {
  isContributable,
  localeConnector,
  LocalePropsFromState,
} from './locale-helpers';

const LOAD_TIMEOUT = 5000; // we can only wait so long.

/**
 * Preload these images before revealing contents.
 * TODO: right now we load all images, which is unnecessary.
 */
const PRELOAD = [
  '/img/cv-logo-bw.svg',
  '/img/cv-logo-one-color-white.svg',
  '/img/robot-greetings.png',
  '/img/wave-blue-large.png',
  '/img/wave-blue-mobile.png',
  '/img/waves/_1.svg',
  '/img/waves/_2.svg',
  '/img/waves/_3.svg',
  '/img/waves/fading.svg',
  '/img/waves/Eq.svg',
];

interface PropsFromState {
  api: API;
  notifications: Notifications.State;
  uploads: Uploads.State;
}

interface PropsFromDispatch {
  removeUpload: typeof Uploads.actions.remove;
  setLocale: typeof Locale.actions.set;
}

interface LocalizedPagesProps
  extends PropsFromState,
    PropsFromDispatch,
    LocalePropsFromState,
    RouteComponentProps<any> {
  userLocales: string[];
}

interface LocalizedPagesState {
  messagesGenerator: any;
  uploadPercentage?: number;
}

const LocalizedLayout: any = withRouter(
  localeConnector(
    connect<PropsFromState, PropsFromDispatch>(
      ({ api, notifications, uploads }: StateTree) => ({
        api,
        notifications,
        uploads,
      }),
      { removeUpload: Uploads.actions.remove, setLocale: Locale.actions.set }
    )(
      class extends React.Component<LocalizedPagesProps, LocalizedPagesState> {
        state: LocalizedPagesState = {
          messagesGenerator: null,
          uploadPercentage: null,
        };

        isUploading = false;

        async componentDidMount() {
          await this.prepareMessagesGenerator(this.props);
        }

        async componentWillReceiveProps(nextProps: LocalizedPagesProps) {
          const { uploads, userLocales } = nextProps;

          this.runUploads(uploads).catch(e => console.error(e));

          window.onbeforeunload =
            uploads.length > 0
              ? e =>
                  (e.returnValue =
                    'Leaving the page now aborts pending uploads. Are you sure?')
              : undefined;

          if (
            userLocales.find(
              (locale, i) => locale !== this.props.userLocales[i]
            )
          ) {
            await this.prepareMessagesGenerator(nextProps);
          }
        }

        async runUploads(uploads: Uploads.State) {
          if (this.isUploading) return;
          this.isUploading = true;
          this.setState({ uploadPercentage: 0 });
          for (let i = 0; i < uploads.length; i++) {
            this.setState({ uploadPercentage: (i + 1) / (uploads.length + 1) });
            const upload = uploads[i];
            try {
              await upload();
            } catch (e) {
              console.error('upload error', e);
            }
            this.props.removeUpload(upload);
          }
          this.setState({ uploadPercentage: null });
          this.isUploading = false;

          if (this.props.uploads.length > 0) {
            await this.runUploads(this.props.uploads);
          }
        }

        async prepareMessagesGenerator({
          api,
          history,
          userLocales,
        }: LocalizedPagesProps) {
          const [mainLocale] = userLocales;
          const pathname = history.location.pathname;

          // Since we make no distinction between "en-US", "en-UK",... we redirect them all to "en"
          if (mainLocale.startsWith('en-')) {
            this.props.setLocale('en');
            history.replace(replacePathLocale(pathname, 'en'));
            return;
          }

          if (!LOCALES.includes(mainLocale)) {
            this.props.setLocale(DEFAULT_LOCALE);
            history.replace(replacePathLocale(pathname, DEFAULT_LOCALE));
          } else {
            this.props.setLocale(userLocales[0]);
          }

          document.documentElement.setAttribute('lang', mainLocale);

          this.setState({
            messagesGenerator: await createMessagesGenerator(api, userLocales),
          });
        }

        render() {
          const { locale, notifications, toLocaleRoute } = this.props;
          const { messagesGenerator, uploadPercentage } = this.state;
          return (
            messagesGenerator && (
              <div>
                <div
                  className="upload-progress"
                  style={
                    uploadPercentage === null
                      ? {
                          opacity: 0,
                          width: '100%',
                          background: '#59cbb7',
                          animationPlayState: 'paused',
                        }
                      : {
                          opacity: 1,
                          width: uploadPercentage * 100 + '%',
                          animationPlayState: 'running',
                        }
                  }
                />
                <LocalizationProvider messages={messagesGenerator}>
                  <div>
                    {!isProduction() && (
                      <div className="notifications">
                        {notifications
                          .slice()
                          .reverse()
                          .map(notification => (
                            <NotificationPill
                              key={notification.id}
                              {...notification}
                            />
                          ))}
                      </div>
                    )}

                    <Switch>
                      <Route
                        exact
                        path={toLocaleRoute(URLS.SPEAK)}
                        render={props =>
                          isContributable(locale) ? (
                            <SpeakPage {...props} />
                          ) : (
                            <Redirect to={toLocaleRoute(URLS.ROOT)} />
                          )
                        }
                      />
                      <Route
                        exact
                        path={toLocaleRoute(URLS.LISTEN)}
                        render={props =>
                          isContributable(locale) ? (
                            <ListenPage {...props} />
                          ) : (
                            <Redirect to={toLocaleRoute(URLS.ROOT)} />
                          )
                        }
                      />
                      <Layout />
                    </Switch>
                  </div><commit_msg>show notifications on production<commit_after>import * as React from 'react';
import { connect, Provider } from 'react-redux';
import {
  Redirect,
  Route,
  RouteComponentProps,
  Switch,
  withRouter,
} from 'react-router';
import { Router } from 'react-router-dom';
const { LocalizationProvider } = require('fluent-react');
import { createBrowserHistory } from 'history';
import store from '../stores/root';
import URLS from '../urls';
import {
  isMobileWebkit,
  isFirefoxFocus,
  isNativeIOS,
  sleep,
  isProduction,
  replacePathLocale,
} from '../utility';
import {
  createMessagesGenerator,
  DEFAULT_LOCALE,
  LOCALES,
  negotiateLocales,
} from '../services/localization';
import API from '../services/api';
import { Locale } from '../stores/locale';
import { Notifications } from '../stores/notifications';
import StateTree from '../stores/tree';
import { Uploads } from '../stores/uploads';
import Layout from './layout/layout';
import NotificationPill from './notification-pill/notification-pill';
import ListenPage from './pages/contribution/listen/listen';
import SpeakPage from './pages/contribution/speak/speak';
import {
  isContributable,
  localeConnector,
  LocalePropsFromState,
} from './locale-helpers';

const LOAD_TIMEOUT = 5000; // we can only wait so long.

/**
 * Preload these images before revealing contents.
 * TODO: right now we load all images, which is unnecessary.
 */
const PRELOAD = [
  '/img/cv-logo-bw.svg',
  '/img/cv-logo-one-color-white.svg',
  '/img/robot-greetings.png',
  '/img/wave-blue-large.png',
  '/img/wave-blue-mobile.png',
  '/img/waves/_1.svg',
  '/img/waves/_2.svg',
  '/img/waves/_3.svg',
  '/img/waves/fading.svg',
  '/img/waves/Eq.svg',
];

interface PropsFromState {
  api: API;
  notifications: Notifications.State;
  uploads: Uploads.State;
}

interface PropsFromDispatch {
  removeUpload: typeof Uploads.actions.remove;
  setLocale: typeof Locale.actions.set;
}

interface LocalizedPagesProps
  extends PropsFromState,
    PropsFromDispatch,
    LocalePropsFromState,
    RouteComponentProps<any> {
  userLocales: string[];
}

interface LocalizedPagesState {
  messagesGenerator: any;
  uploadPercentage?: number;
}

const LocalizedLayout: any = withRouter(
  localeConnector(
    connect<PropsFromState, PropsFromDispatch>(
      ({ api, notifications, uploads }: StateTree) => ({
        api,
        notifications,
        uploads,
      }),
      { removeUpload: Uploads.actions.remove, setLocale: Locale.actions.set }
    )(
      class extends React.Component<LocalizedPagesProps, LocalizedPagesState> {
        state: LocalizedPagesState = {
          messagesGenerator: null,
          uploadPercentage: null,
        };

        isUploading = false;

        async componentDidMount() {
          await this.prepareMessagesGenerator(this.props);
        }

        async componentWillReceiveProps(nextProps: LocalizedPagesProps) {
          const { uploads, userLocales } = nextProps;

          this.runUploads(uploads).catch(e => console.error(e));

          window.onbeforeunload =
            uploads.length > 0
              ? e =>
                  (e.returnValue =
                    'Leaving the page now aborts pending uploads. Are you sure?')
              : undefined;

          if (
            userLocales.find(
              (locale, i) => locale !== this.props.userLocales[i]
            )
          ) {
            await this.prepareMessagesGenerator(nextProps);
          }
        }

        async runUploads(uploads: Uploads.State) {
          if (this.isUploading) return;
          this.isUploading = true;
          this.setState({ uploadPercentage: 0 });
          for (let i = 0; i < uploads.length; i++) {
            this.setState({ uploadPercentage: (i + 1) / (uploads.length + 1) });
            const upload = uploads[i];
            try {
              await upload();
            } catch (e) {
              console.error('upload error', e);
            }
            this.props.removeUpload(upload);
          }
          this.setState({ uploadPercentage: null });
          this.isUploading = false;

          if (this.props.uploads.length > 0) {
            await this.runUploads(this.props.uploads);
          }
        }

        async prepareMessagesGenerator({
          api,
          history,
          userLocales,
        }: LocalizedPagesProps) {
          const [mainLocale] = userLocales;
          const pathname = history.location.pathname;

          // Since we make no distinction between "en-US", "en-UK",... we redirect them all to "en"
          if (mainLocale.startsWith('en-')) {
            this.props.setLocale('en');
            history.replace(replacePathLocale(pathname, 'en'));
            return;
          }

          if (!LOCALES.includes(mainLocale)) {
            this.props.setLocale(DEFAULT_LOCALE);
            history.replace(replacePathLocale(pathname, DEFAULT_LOCALE));
          } else {
            this.props.setLocale(userLocales[0]);
          }

          document.documentElement.setAttribute('lang', mainLocale);

          this.setState({
            messagesGenerator: await createMessagesGenerator(api, userLocales),
          });
        }

        render() {
          const { locale, notifications, toLocaleRoute } = this.props;
          const { messagesGenerator, uploadPercentage } = this.state;
          return (
            messagesGenerator && (
              <div>
                <div
                  className="upload-progress"
                  style={
                    uploadPercentage === null
                      ? {
                          opacity: 0,
                          width: '100%',
                          background: '#59cbb7',
                          animationPlayState: 'paused',
                        }
                      : {
                          opacity: 1,
                          width: uploadPercentage * 100 + '%',
                          animationPlayState: 'running',
                        }
                  }
                />
                <LocalizationProvider messages={messagesGenerator}>
                  <div>
                    <div className="notifications">
                      {notifications
                        .slice()
                        .reverse()
                        .map(notification => (
                          <NotificationPill
                            key={notification.id}
                            {...notification}
                          />
                        ))}
                    </div>

                    <Switch>
                      <Route
                        exact
                        path={toLocaleRoute(URLS.SPEAK)}
                        render={props =>
                          isContributable(locale) ? (
                            <SpeakPage {...props} />
                          ) : (
                            <Redirect to={toLocaleRoute(URLS.ROOT)} />
                          )
                        }
                      />
                      <Route
                        exact
                        path={toLocaleRoute(URLS.LISTEN)}
                        render={props =>
                          isContributable(locale) ? (
                            <ListenPage {...props} />
                          ) : (
                            <Redirect to={toLocaleRoute(URLS.ROOT)} />
                          )
                        }
                      />
                      <Layout />
                    </Switch>
                  </div>
{'fraction_non_alphanumeric': 0.10923984272608125, 'fraction_numerical': 0.00327653997378768, 'mean_word_length': 1.4806566970091026, 'pattern_counts': {'":': 0, '<': 45, '<?xml version=': 0, '>': 61, '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': '894528', 'n_tokens_mistral': 4012, 'n_tokens_neox': 3840, 'n_words': 783}