<commit_before>import _ from 'underscore';
import React from 'react';
import ReactDOM from 'react-dom';
import AccountContactField from './account-contact-field';
import {Utils, Actions, AccountStore} from 'nylas-exports';
import {InjectedComponent, KeyCommandsRegion, ParticipantsTextField, ListensToFluxStore} from 'nylas-component-kit';

import CollapsedParticipants from './collapsed-participants';
import ComposerHeaderActions from './composer-header-actions';
import SubjectTextField from './subject-text-field';

import Fields from './fields';

const ScopedFromField = ListensToFluxStore(AccountContactField, {
  stores: [AccountStore],
  getStateFromStores: (props) => {
    const savedOrReplyToThread = !!props.draft.threadId;
    if (savedOrReplyToThread) {
      return {accounts: [AccountStore.accountForId(props.draft.accountId)]};
    }
    return {accounts: AccountStore.accounts()}
  },
});

export default class ComposerHeader extends React.Component {
  static displayName = "ComposerHeader";

  static propTypes = {
    draft: React.PropTypes.object.isRequired,
    session: React.PropTypes.object.isRequired,
    initiallyFocused: React.PropTypes.bool,
  }

  static contextTypes = {
    parentTabGroup: React.PropTypes.object,
  }

  constructor(props = {}) {
    super(props)
    this.state = this._initialStateForDraft(this.props.draft, props);
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.session !== nextProps.session) {
      this.setState(this._initialStateForDraft(nextProps.draft, nextProps));
    } else {
      this._ensureFilledFieldsEnabled(nextProps.draft);
    }
  }

  showAndFocusField = (fieldName) => {
    const enabledFields = _.uniq([].concat(this.state.enabledFields, [fieldName]));
    const participantsFocused = this.state.participantsFocused || Fields.ParticipantFields.includes(fieldName);

    Utils.waitFor(() => this.refs[fieldName]).then(() =>
      this.refs[fieldName].focus()
    ).catch(() => {
    })

    this.setState({enabledFields, participantsFocused});
  }

  hideField = (fieldName) => {
    if (ReactDOM.findDOMNode(this.refs[fieldName]).contains(document.activeElement)) {
      this.context.parentTabGroup.shiftFocus(-1)
    }

    const enabledFields = _.without(this.state.enabledFields, fieldName)
    this.setState({enabledFields})
  }

  _ensureFilledFieldsEnabled(draft) {
    let enabledFields = this.state.enabledFields;
    if (!_.isEmpty(draft.cc)) {
      enabledFields = enabledFields.concat([Fields.Cc]);
    }
    if (!_.isEmpty(draft.bcc)) {
      enabledFields = enabledFields.concat([Fields.Bcc]);
    }
    if (enabledFields !== this.state.enabledFields) {
      this.setState({enabledFields});
    }
  }

  _initialStateForDraft(draft, props) {
    const enabledFields = [Fields.To];
    if (!_.isEmpty(draft.cc)) {
      enabledFields.push(Fields.Cc);
    }
    if (!_.isEmpty(draft.bcc)) {
      enabledFields.push(Fields.Bcc);
    }
    enabledFields.push(Fields.From);
    if (this._shouldEnableSubject()) {
      enabledFields.push(Fields.Subject);
    }

    return {
      enabledFields,
      participantsFocused: props.initiallyFocused,
    };
  }

  _shouldEnableSubject = () => {
    if (_.isEmpty(this.props.draft.subject)) {
      return true;
    }
    if (Utils.isForwardedMessage(this.props.draft)) {
      return true;
    }
    if (this.props.draft.replyToMessageId) {
      return false;
    }
    return true;
  }

  _onChangeParticipants = (changes) => {
    this.props.session.changes.add(changes);
    Actions.draftParticipantsChanged(this.props.draft.clientId, changes);
  }

  _onSubjectChange = (value) => {
    this.props.session.changes.add({subject: value});
  }

  _onFocusInParticipants = () => {
    const fieldName = this.state.participantsLastActiveField || Fields.To;
    Utils.waitFor(() =>
      this.refs[fieldName]
    ).then(() =>
      this.refs[fieldName].focus()
    ).catch(() => {
    });

    this.setState({
      participantsFocused: true,
      participantsLastActiveField: null,
    });
  }

  _onFocusOutParticipants = (lastFocusedEl) => {
    const active = Fields.ParticipantFields.find((fieldName) => {
      return this.refs[fieldName] ? ReactDOM.findDOMNode(this.refs[fieldName]).contains(lastFocusedEl) : false
    }
    );
    this.setState({
      participantsFocused: false,
      participantsLastActiveField: active,
    });
  }

  _onDragCollapsedParticipants({isDropping}) {
    if (isDropping) {
      this.setState({
        participantsFocused: true,
        enabledFields: [...Fields.ParticipantFields, Fields.Subject],
      })
    }
  }

  _renderParticipants = () => {
    let content = null;
    if (this.state.participantsFocused) {
      content = this._renderFields();
    } else {
      content = (
        <CollapsedParticipants
          to={this.props.draft.to}
          cc={this.props.draft.cc}
          bcc={this.props.draft.bcc}
          onDragChange={::this._onDragCollapsedParticipants}
        />
      )
    }

    // When the participants field collapses, we store the field that was last
    // focused onto our state, so that we can restore focus to it when the fields
    // are expanded again.
    return (
      <KeyCommandsRegion
        tabIndex={-1}
        ref="participantsContainer"
        className="expanded-participants"
        onFocusIn={this._onFocusInParticipants}
        onFocusOut={this._onFocusOutParticipants}
      >
        {content}
      </KeyCommandsRegion>
    );
  }

  _renderSubject = () => {
    if (!this.state.enabledFields.includes(Fields.Subject)) {
      return false;
    }
    const {draft} = this.props
    return (
      <InjectedComponent
        ref={Fields.Subject}
        key="subject-wrap"
        matching={{role: 'Composer:SubjectTextField'}}
        exposedProps={{
          draft,
          value: draft.subject,
          draftClientId: draft.clientId,
          onSubjectChange: this._onSubjectChange,
        }}
        requiredMethods={['focus']}
        fallback={SubjectTextField}
      />
    )
  }

  _renderFields = () => {
    const {to, cc, bcc, from} = this.props.draft;
<commit_msg>fix(mail-merge): Pass session to injected subject<commit_after>import _ from 'underscore';
import React from 'react';
import ReactDOM from 'react-dom';
import AccountContactField from './account-contact-field';
import {Utils, Actions, AccountStore} from 'nylas-exports';
import {InjectedComponent, KeyCommandsRegion, ParticipantsTextField, ListensToFluxStore} from 'nylas-component-kit';

import CollapsedParticipants from './collapsed-participants';
import ComposerHeaderActions from './composer-header-actions';
import SubjectTextField from './subject-text-field';

import Fields from './fields';

const ScopedFromField = ListensToFluxStore(AccountContactField, {
  stores: [AccountStore],
  getStateFromStores: (props) => {
    const savedOrReplyToThread = !!props.draft.threadId;
    if (savedOrReplyToThread) {
      return {accounts: [AccountStore.accountForId(props.draft.accountId)]};
    }
    return {accounts: AccountStore.accounts()}
  },
});

export default class ComposerHeader extends React.Component {
  static displayName = "ComposerHeader";

  static propTypes = {
    draft: React.PropTypes.object.isRequired,
    session: React.PropTypes.object.isRequired,
    initiallyFocused: React.PropTypes.bool,
  }

  static contextTypes = {
    parentTabGroup: React.PropTypes.object,
  }

  constructor(props = {}) {
    super(props)
    this.state = this._initialStateForDraft(this.props.draft, props);
  }

  componentWillReceiveProps(nextProps) {
    if (this.props.session !== nextProps.session) {
      this.setState(this._initialStateForDraft(nextProps.draft, nextProps));
    } else {
      this._ensureFilledFieldsEnabled(nextProps.draft);
    }
  }

  showAndFocusField = (fieldName) => {
    const enabledFields = _.uniq([].concat(this.state.enabledFields, [fieldName]));
    const participantsFocused = this.state.participantsFocused || Fields.ParticipantFields.includes(fieldName);

    Utils.waitFor(() => this.refs[fieldName]).then(() =>
      this.refs[fieldName].focus()
    ).catch(() => {
    })

    this.setState({enabledFields, participantsFocused});
  }

  hideField = (fieldName) => {
    if (ReactDOM.findDOMNode(this.refs[fieldName]).contains(document.activeElement)) {
      this.context.parentTabGroup.shiftFocus(-1)
    }

    const enabledFields = _.without(this.state.enabledFields, fieldName)
    this.setState({enabledFields})
  }

  _ensureFilledFieldsEnabled(draft) {
    let enabledFields = this.state.enabledFields;
    if (!_.isEmpty(draft.cc)) {
      enabledFields = enabledFields.concat([Fields.Cc]);
    }
    if (!_.isEmpty(draft.bcc)) {
      enabledFields = enabledFields.concat([Fields.Bcc]);
    }
    if (enabledFields !== this.state.enabledFields) {
      this.setState({enabledFields});
    }
  }

  _initialStateForDraft(draft, props) {
    const enabledFields = [Fields.To];
    if (!_.isEmpty(draft.cc)) {
      enabledFields.push(Fields.Cc);
    }
    if (!_.isEmpty(draft.bcc)) {
      enabledFields.push(Fields.Bcc);
    }
    enabledFields.push(Fields.From);
    if (this._shouldEnableSubject()) {
      enabledFields.push(Fields.Subject);
    }

    return {
      enabledFields,
      participantsFocused: props.initiallyFocused,
    };
  }

  _shouldEnableSubject = () => {
    if (_.isEmpty(this.props.draft.subject)) {
      return true;
    }
    if (Utils.isForwardedMessage(this.props.draft)) {
      return true;
    }
    if (this.props.draft.replyToMessageId) {
      return false;
    }
    return true;
  }

  _onChangeParticipants = (changes) => {
    this.props.session.changes.add(changes);
    Actions.draftParticipantsChanged(this.props.draft.clientId, changes);
  }

  _onSubjectChange = (value) => {
    this.props.session.changes.add({subject: value});
  }

  _onFocusInParticipants = () => {
    const fieldName = this.state.participantsLastActiveField || Fields.To;
    Utils.waitFor(() =>
      this.refs[fieldName]
    ).then(() =>
      this.refs[fieldName].focus()
    ).catch(() => {
    });

    this.setState({
      participantsFocused: true,
      participantsLastActiveField: null,
    });
  }

  _onFocusOutParticipants = (lastFocusedEl) => {
    const active = Fields.ParticipantFields.find((fieldName) => {
      return this.refs[fieldName] ? ReactDOM.findDOMNode(this.refs[fieldName]).contains(lastFocusedEl) : false
    }
    );
    this.setState({
      participantsFocused: false,
      participantsLastActiveField: active,
    });
  }

  _onDragCollapsedParticipants({isDropping}) {
    if (isDropping) {
      this.setState({
        participantsFocused: true,
        enabledFields: [...Fields.ParticipantFields, Fields.Subject],
      })
    }
  }

  _renderParticipants = () => {
    let content = null;
    if (this.state.participantsFocused) {
      content = this._renderFields();
    } else {
      content = (
        <CollapsedParticipants
          to={this.props.draft.to}
          cc={this.props.draft.cc}
          bcc={this.props.draft.bcc}
          onDragChange={::this._onDragCollapsedParticipants}
        />
      )
    }

    // When the participants field collapses, we store the field that was last
    // focused onto our state, so that we can restore focus to it when the fields
    // are expanded again.
    return (
      <KeyCommandsRegion
        tabIndex={-1}
        ref="participantsContainer"
        className="expanded-participants"
        onFocusIn={this._onFocusInParticipants}
        onFocusOut={this._onFocusOutParticipants}
      >
        {content}
      </KeyCommandsRegion>
    );
  }

  _renderSubject = () => {
    if (!this.state.enabledFields.includes(Fields.Subject)) {
      return false;
    }
    const {draft, session} = this.props
    return (
      <InjectedComponent
        ref={Fields.Subject}
        key="subject-wrap"
        matching={{role: 'Composer:SubjectTextField'}}
        exposedProps={{
          draft,
          session,
          value: draft.subject,
          draftClientId: draft.clientId,
          onSubjectChange: this._onSubjectChange,
        }}
        requiredMethods={['focus']}
        fallback={SubjectTextField}
      />
    )
  }

  _renderFields = () => {
    const {to, cc, bcc, from} = this.props.draft;

{'fraction_non_alphanumeric': 0.12904792746113988, 'fraction_numerical': 0.0003238341968911917, 'mean_word_length': 3.1217884551217883, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 47, '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': '3101626', 'n_tokens_mistral': 3768, 'n_tokens_neox': 3668, 'n_words': 615}