<commit_before>/**
 * @flow
 */

import React from 'react';
import {
  Clipboard,
  Platform,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import { createFocusAwareComponent, withNavigation } from '@expo/ex-navigation';
import { Constants } from 'expo';
import { connect } from 'react-redux';

import addListenerWithNativeCallback from '../utils/addListenerWithNativeCallback';
import Alerts from '../constants/Alerts';
import Colors from '../constants/Colors';
import HistoryActions from '../redux/HistoryActions';
import OpenProjectByURLButton from '../components/OpenProjectByURLButton';
import NoProjectTools from '../components/NoProjectTools';
import ProjectTools from '../components/ProjectTools';
import SharedStyles from '../constants/SharedStyles';
import SmallProjectCard from '../components/SmallProjectCard';
import Store from '../redux/Store';

import extractReleaseChannel from '../utils/extractReleaseChannel';

@createFocusAwareComponent
@withNavigation
@connect(data => ProjectsScreen.getDataProps(data))
export default class ProjectsScreen extends React.Component {
  props: {
    navigation: any,
    isFocused: boolean,
    dispatch: () => void,
    recentHistory: any,
    allHistory: any,
    navigator: any,
  };

  static route = {
    navigationBar: {
      title: 'Projects',
      ...Platform.select({
        ios: {
          renderRight: () => (Constants.isDevice) ? null : <OpenProjectByURLButton />,
        },
      }),
    },
  };

  static getDataProps(data) {
    let { history } = data.history;

    return {
      recentHistory: history.take(6),
      allHistory: history,
    };
  }

  componentDidMount() {
    addListenerWithNativeCallback('ExponentKernel.showQRReader', async event => {
      this.props.navigation.showModal('qrCode');
      return { success: true };
    });

    addListenerWithNativeCallback('ExponentKernel.addHistoryItem', async event => {
      let { manifestUrl, manifest, manifestString } = event;
      if (!manifest && manifestString) {
        manifest = JSON.parse(manifestString);
      }
      Store.dispatch(HistoryActions.addHistoryItem(manifestUrl, manifest));
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <ScrollView
          key={
            /* note(brent): sticky headers break re-rendering scrollview */
            /* contents on sdk17, remove this in sdk18 */
            Platform.OS === 'ios' ? this.props.allHistory.count() : 'scroll-view'
          }
          stickyHeaderIndices={Platform.OS === 'ios' ? [0, 2] : []}
          style={styles.container}
          contentContainerStyle={styles.contentContainer}>
          <View style={SharedStyles.sectionLabelContainer}>
            <Text style={SharedStyles.sectionLabelText}>CLIPBOARD</Text>
          </View>
          {this._renderProjectTools()}

          <View style={SharedStyles.sectionLabelContainer}>
            <Text style={SharedStyles.sectionLabelText}>RECENTLY VISITED</Text>
            <TouchableOpacity onPress={this._handlePressClearHistory} style={styles.clearButton}>
              <Text style={styles.clearButtonText}>CLEAR</Text>
            </TouchableOpacity>
          </View>

          {this._renderRecentHistory()}
          {this._renderExpoVersion()}
        </ScrollView>

        <StatusBar barStyle="default" />
      </View>
    );
  }

  _handlePressClearHistory = () => {
    this.props.dispatch(HistoryActions.clearHistory());
  };

  _renderProjectTools = () => {
    if (Platform.OS === 'ios' && Constants.isDevice) {
      return (
        <View style={{ marginBottom: 15 }}>
          <NoProjectTools />
        </View>
      );
    } else {
      return <ProjectTools pollForUpdates={this.props.isFocused} />;
    }
  };

  _renderRecentHistory = () => {
    return this.props.allHistory.count() === 0
      ? this._renderEmptyRecentHistory()
      : this._renderRecentHistoryItems();
  };

  _renderEmptyRecentHistory = () => {
    return (
      <View style={SharedStyles.genericCardContainer} key="empty-history">
        <View style={SharedStyles.genericCardBody}>
          <Text style={[SharedStyles.faintText, { textAlign: 'center' }]}>
            You haven't opened any projects recently.
          </Text>
        </View>
      </View>
    );
  };

  _renderRecentHistoryItems = () => {
    const extractUsername = manifestUrl => {
      let username = manifestUrl.match(/@.*?\//)[0];
      if (!username) {
        return null;
      } else {
        return username.slice(0, username.length - 1);
      }
    };

    return this.props.recentHistory.map((project, i) => (
      <SmallProjectCard
        key={project.manifestUrl}
        iconUrl={project.manifest && project.manifest.iconUrl}
        releaseChannel={
          /* 28/11/17(brentvatne) - we can remove extractReleaseChannel in a couple of months
          when project history is unlikely to include any projects with release channels */
          project.manifest && project.manifest.releaseChannel || extractReleaseChannel(project.manifestUrl)
        }
        projectName={project.manifest && project.manifest.name}
        username={
          project.manifestUrl.includes('exp://exp.host')
            ? extractUsername(project.manifestUrl)
            : null<commit_msg>Show tools title rather than clipboard when not restricted<commit_after>/**
 * @flow
 */

import React from 'react';
import {
  Clipboard,
  Platform,
  ScrollView,
  StatusBar,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from 'react-native';
import { createFocusAwareComponent, withNavigation } from '@expo/ex-navigation';
import { Constants } from 'expo';
import { connect } from 'react-redux';

import addListenerWithNativeCallback from '../utils/addListenerWithNativeCallback';
import Alerts from '../constants/Alerts';
import Colors from '../constants/Colors';
import HistoryActions from '../redux/HistoryActions';
import OpenProjectByURLButton from '../components/OpenProjectByURLButton';
import NoProjectTools from '../components/NoProjectTools';
import ProjectTools from '../components/ProjectTools';
import SharedStyles from '../constants/SharedStyles';
import SmallProjectCard from '../components/SmallProjectCard';
import Store from '../redux/Store';

import extractReleaseChannel from '../utils/extractReleaseChannel';

const IS_RESTRICTED = Constants.isDevice && Platform.OS === 'ios';

@createFocusAwareComponent
@withNavigation
@connect(data => ProjectsScreen.getDataProps(data))
export default class ProjectsScreen extends React.Component {
  props: {
    navigation: any,
    isFocused: boolean,
    dispatch: () => void,
    recentHistory: any,
    allHistory: any,
    navigator: any,
  };

  static route = {
    navigationBar: {
      title: 'Projects',
      ...Platform.select({
        ios: {
          renderRight: () => (Constants.isDevice ? null : <OpenProjectByURLButton />),
        },
      }),
    },
  };

  static getDataProps(data) {
    let { history } = data.history;

    return {
      recentHistory: history.take(6),
      allHistory: history,
    };
  }

  componentDidMount() {
    addListenerWithNativeCallback('ExponentKernel.showQRReader', async event => {
      this.props.navigation.showModal('qrCode');
      return { success: true };
    });

    addListenerWithNativeCallback('ExponentKernel.addHistoryItem', async event => {
      let { manifestUrl, manifest, manifestString } = event;
      if (!manifest && manifestString) {
        manifest = JSON.parse(manifestString);
      }
      Store.dispatch(HistoryActions.addHistoryItem(manifestUrl, manifest));
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <ScrollView
          key={
            /* note(brent): sticky headers break re-rendering scrollview */
            /* contents on sdk17, remove this in sdk18 */
            Platform.OS === 'ios' ? this.props.allHistory.count() : 'scroll-view'
          }
          stickyHeaderIndices={Platform.OS === 'ios' ? [0, 2] : []}
          style={styles.container}
          contentContainerStyle={styles.contentContainer}>
          <View style={SharedStyles.sectionLabelContainer}>
            <Text style={SharedStyles.sectionLabelText}>
              {IS_RESTRICTED || Platform.OS === 'android' ? 'TOOLS' : 'CLIPBOARD'}
            </Text>
          </View>
          {this._renderProjectTools()}

          <View style={SharedStyles.sectionLabelContainer}>
            <Text style={SharedStyles.sectionLabelText}>RECENTLY VISITED</Text>
            <TouchableOpacity onPress={this._handlePressClearHistory} style={styles.clearButton}>
              <Text style={styles.clearButtonText}>CLEAR</Text>
            </TouchableOpacity>
          </View>

          {this._renderRecentHistory()}
          {this._renderExpoVersion()}
        </ScrollView>

        <StatusBar barStyle="default" />
      </View>
    );
  }

  _handlePressClearHistory = () => {
    this.props.dispatch(HistoryActions.clearHistory());
  };

  _renderProjectTools = () => {
    if (IS_RESTRICTED) {
      return (
        <View style={{ marginBottom: 15 }}>
          <NoProjectTools />
        </View>
      );
    } else {
      return <ProjectTools pollForUpdates={this.props.isFocused} />;
    }
  };

  _renderRecentHistory = () => {
    return this.props.allHistory.count() === 0
      ? this._renderEmptyRecentHistory()
      : this._renderRecentHistoryItems();
  };

  _renderEmptyRecentHistory = () => {
    return (
      <View style={SharedStyles.genericCardContainer} key="empty-history">
        <View style={SharedStyles.genericCardBody}>
          <Text style={[SharedStyles.faintText, { textAlign: 'center' }]}>
            You haven't opened any projects recently.
          </Text>
        </View>
      </View>
    );
  };

  _renderRecentHistoryItems = () => {
    const extractUsername = manifestUrl => {
      let username = manifestUrl.match(/@.*?\//)[0];
      if (!username) {
        return null;
      } else {
        return username.slice(0, username.length - 1);
      }
    };

    return this.props.recentHistory.map((project, i) => (
      <SmallProjectCard
        key={project.manifestUrl}
        iconUrl={project.manifest && project.manifest.iconUrl}
        releaseChannel={
          /* 28/11/17(brentvatne) - we can remove extractReleaseChannel in a couple of months
          when project history is unlikely to include any projects with release channels */
          (project.manifest && project.manifest.releaseChannel) ||
          extractReleaseChannel(project.manifestUrl)
        }
        projectName={project.manifest && project.manifest.name}
        username={
          project.manifestUrl.includes('exp://exp.host')
            ? extractUsername(project.manifestUrl)
            : null
{'fraction_non_alphanumeric': 0.12873478421246773, 'fraction_numerical': 0.0035042419771302105, 'mean_word_length': 2.8039284461592424, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 83, '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': '4011797', 'n_tokens_mistral': 3027, 'n_tokens_neox': 2944, 'n_words': 602}