<commit_before>import React, { Component } from 'react';
import { Sigil } from '../../../../lib/sigil';

import { Link } from 'react-router-dom';
import { EditElement } from './edit-element';
import { Spinner } from '../../../../components/Spinner';
import { uxToHex } from '../../../../lib/util';
import { S3Upload } from './s3-upload';

export class ContactCard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      edit: props.share,
      colorToSet: null,
      nickNameToSet: null,
      emailToSet: null,
      phoneToSet: null,
      websiteToSet: null,
      avatarToSet: null,
      notesToSet: null,
      awaiting: false,
      type: 'Saving to group'
    };
    this.editToggle = this.editToggle.bind(this);
    this.sigilColorSet = this.sigilColorSet.bind(this);
    this.nickNameToSet = this.nickNameToSet.bind(this);
    this.emailToSet = this.emailToSet.bind(this);
    this.phoneToSet = this.phoneToSet.bind(this);
    this.websiteToSet = this.websiteToSet.bind(this);
    this.avatarToSet = this.avatarToSet.bind(this);
    this.notesToSet = this.notesToSet.bind(this);
    this.setField = this.setField.bind(this);
    this.shareWithGroup = this.shareWithGroup.bind(this);
    this.removeSelfFromGroup = this.removeSelfFromGroup.bind(this);
    this.removeOtherFromGroup = this.removeOtherFromGroup.bind(this);
  }

  componentDidUpdate(prevProps) {
    const { props } = this;
    if (props.ship !== prevProps.ship) {
      this.setState({
        edit: props.share,
        colorToSet: null,
        nickNameToSet: null,
        emailToSet: null,
        phoneToSet: null,
        websiteToSet: null,
        avatarToSet: null,
        notesToSet: null
      });
      return;
    }
  }

  editToggle() {
    let editSwitch = this.state.edit;
    editSwitch = !editSwitch;
    this.setState({ edit: editSwitch });
  }

  emailToSet(value) {
    this.setState({ emailToSet: value });
  }

  nickNameToSet(value) {
    this.setState({ nickNameToSet: value });
  }

  notesToSet(value) {
    this.setState({ notesToSet: value });
  }

  phoneToSet(value) {
    this.setState({ phoneToSet: value });
  }

  websiteToSet(value) {
    this.setState({ websiteToSet: value });
  }

  avatarToSet(value) {
    this.setState({ avatarToSet: value });
  }

  sigilColorSet(event) {
    this.setState({ colorToSet: event.target.value });
  }

  shipParser(ship) {
    switch (ship.length) {
      case 3:
        return 'Galaxy';
      case 6:
        return 'Star';
      case 13:
        return 'Planet';
      case 56:
        return 'Comet';
      default:
        return 'Unknown';
    }
  }

  setField(field) {
    const { props, state } = this;
    const ship = '~' + props.ship;
    const emailTest = new RegExp(
      String(
        /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*/.source
      ) +
        /@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
          .source
    );

    const phoneTest = new RegExp(
      String(/^\s*(?:\+?(\d{1,3}))?/.source) +
        /([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/
          .source
    );

    const websiteTest = new RegExp(
      String(/[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}/.source) +
        /\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.source
    );

    switch (field) {
      case 'avatar': {
        if (
          state.avatarToSet === '' ||
          (Boolean(props.contact.avatar) &&
            state.avatarToSet === props.contact.avatar)
        ) {
          return false;
        }
        const avatarTestResult = websiteTest.exec(state.avatarToSet);
        if (avatarTestResult) {
          this.setState(
            {
              awaiting: true,
              type: 'Saving to group'
            },
            () => {
              props.api.contacts.edit(props.path, ship, {
                avatar: {
                  url: state.avatarToSet
                }})
                .then(() => {
                  this.setState({ awaiting: false });
                });
            }
          );
        }
        break;
      }
      case 'color': {
        let currentColor = props.contact.color ? props.contact.color : '000000';
        currentColor = uxToHex(currentColor);
        const hexExp = /([0-9A-Fa-f]{6})/;
        const hexTest = hexExp.exec(this.state.colorToSet);

        if (hexTest && hexTest[1] !== currentColor && !props.share) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, `~${props.ship}`, { color: hexTest[1] })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'email': {
        if (
          state.emailToSet === '' ||
          state.emailToSet === props.contact.email
        ) {
          return false;
        }
        const emailTestResult = emailTest.exec(state.emailToSet);
        if (emailTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { email: state.emailToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'nickname': {
        if (
          state.nickNameToSet === '' ||
          state.nickNameToSet === props.contact.nickname
        ) {
          return false;
        }
        this.setState({ awaiting: true, type: 'Saving to group' }, () => {
          props.api.contacts.edit(
            props.path, ship, { nickname: state.nickNameToSet })
            .then(() => {
              this.setState({ awaiting: false });
            });
        });

        break;
      }
      case 'notes': {
        if (
          state.notesToSet === '' ||
          state.notesToSet === props.contact.notes
        ) {
          return false;
        }
        this.setState({ awaiting: true, type: 'Saving to group' }, () => {
          props.api.contacts.edit(
            props.path, ship, { notes: state.notesToSet })
            .then(() => {
              this.setState({ awaiting: false });
            });
        });
        break;
      }
      case 'phone': {
        if (
          state.phoneToSet === '' ||
          state.phoneToSet === props.contact.phone
        ) {
          return false;
        }
        const phoneTestResult = phoneTest.exec(state.phoneToSet);
        if (phoneTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { phone: state.phoneToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'website': {
        if (
          state.websiteToSet === '' ||
          state.websiteToSet === props.contact.website
        ) {
          return false;
        }
        const websiteTestResult = websiteTest.exec(state.websiteToSet);
        if (websiteTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { website: state.websiteToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'removeEmail': {
        this.setState(
          { emailToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { email: '' })
              .then(() => {
                this.setState({ awaiting: false });
              });
          }
        );
        break;
      }
      case 'removeNickname': {
        this.setState(
          { nicknameToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { nickname: '' })
              .then(() => {
                this.setState({ awaiting: false });
              });
          }
        );
        break;
      }
      case 'removePhone': {
        this.setState(
          { phoneToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { phone: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeWebsite': {
        this.setState(
          { websiteToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { website: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeAvatar': {
        this.setState(
          {
            avatarToSet: null,
            awaiting: true,
            type: 'Removing from group'
          },
          () => {
            props.api.contacts.edit(props.path, ship, { avatar: null }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeNotes': {
        this.setState(
          { notesToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { notes: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
    }
  }

  pickFunction(val, def) {
    if (val !== null) {
      return val;
    }
    return def;
  }

  shareWithGroup() {
    const { props, state } = this;
    const defaultVal = props.share
      ? {
          nickname: props.rootIdentity.nickname,
          email: props.rootIdentity.email,
          phone: props.rootIdentity.phone,
          website: props.rootIdentity.website,
          avatar: props.rootIdentity.avatar
            ? { url: props.rootIdentity.avatar }
            : null,
          notes: props.rootIdentity.notes,
          color: uxToHex(props.rootIdentity.color)
        }
      : {
          nickname: props.contact.nickname,
          email: props.contact.email,
          phone: props.contact.phone,
          website: props.contact.website,
          avatar: props.contact.avatar ? { url: props.contact.avatar } : null,
          notes: props.contact.notes,
          color: props.contact.color
        };

    const contact = {
      nickname: this.pickFunction(state.nickNameToSet, defaultVal.nickname),
      email: this.pickFunction(state.emailToSet, defaultVal.email),
      phone: this.pickFunction(state.phoneToSet, defaultVal.phone),
      website: this.pickFunction(state.websiteToSet, defaultVal.website),
      notes: this.pickFunction(state.notesToSet, defaultVal.notes),
      color: this.pickFunction(state.colorToSet, defaultVal.color),
      avatar: this.pickFunction(
        state.avatarToSet ? { url: state.avatarToSet } : null,
        defaultVal.avatar
      )
    };

    this.setState({ awaiting: true, type: 'Sharing with group' }, () => {
      props.api.contacts
        .share(`~${props.ship}`, props.path, `~${window.ship}`, contact)
        .then(() => {<commit_msg>contacts-js: dismiss spinner on share<commit_after>import React, { Component } from 'react';
import { Sigil } from '../../../../lib/sigil';

import { Link } from 'react-router-dom';
import { EditElement } from './edit-element';
import { Spinner } from '../../../../components/Spinner';
import { uxToHex } from '../../../../lib/util';
import { S3Upload } from './s3-upload';

export class ContactCard extends Component {
  constructor(props) {
    super(props);
    this.state = {
      edit: props.share,
      colorToSet: null,
      nickNameToSet: null,
      emailToSet: null,
      phoneToSet: null,
      websiteToSet: null,
      avatarToSet: null,
      notesToSet: null,
      awaiting: false,
      type: 'Saving to group'
    };
    this.editToggle = this.editToggle.bind(this);
    this.sigilColorSet = this.sigilColorSet.bind(this);
    this.nickNameToSet = this.nickNameToSet.bind(this);
    this.emailToSet = this.emailToSet.bind(this);
    this.phoneToSet = this.phoneToSet.bind(this);
    this.websiteToSet = this.websiteToSet.bind(this);
    this.avatarToSet = this.avatarToSet.bind(this);
    this.notesToSet = this.notesToSet.bind(this);
    this.setField = this.setField.bind(this);
    this.shareWithGroup = this.shareWithGroup.bind(this);
    this.removeSelfFromGroup = this.removeSelfFromGroup.bind(this);
    this.removeOtherFromGroup = this.removeOtherFromGroup.bind(this);
  }

  componentDidUpdate(prevProps) {
    const { props } = this;
    if (props.ship !== prevProps.ship) {
      this.setState({
        edit: props.share,
        colorToSet: null,
        nickNameToSet: null,
        emailToSet: null,
        phoneToSet: null,
        websiteToSet: null,
        avatarToSet: null,
        notesToSet: null
      });
      return;
    }
  }

  editToggle() {
    let editSwitch = this.state.edit;
    editSwitch = !editSwitch;
    this.setState({ edit: editSwitch });
  }

  emailToSet(value) {
    this.setState({ emailToSet: value });
  }

  nickNameToSet(value) {
    this.setState({ nickNameToSet: value });
  }

  notesToSet(value) {
    this.setState({ notesToSet: value });
  }

  phoneToSet(value) {
    this.setState({ phoneToSet: value });
  }

  websiteToSet(value) {
    this.setState({ websiteToSet: value });
  }

  avatarToSet(value) {
    this.setState({ avatarToSet: value });
  }

  sigilColorSet(event) {
    this.setState({ colorToSet: event.target.value });
  }

  shipParser(ship) {
    switch (ship.length) {
      case 3:
        return 'Galaxy';
      case 6:
        return 'Star';
      case 13:
        return 'Planet';
      case 56:
        return 'Comet';
      default:
        return 'Unknown';
    }
  }

  setField(field) {
    const { props, state } = this;
    const ship = '~' + props.ship;
    const emailTest = new RegExp(
      String(
        /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*/.source
      ) +
        /@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/
          .source
    );

    const phoneTest = new RegExp(
      String(/^\s*(?:\+?(\d{1,3}))?/.source) +
        /([-. (]*(\d{3})[-. )]*)?((\d{3})[-. ]*(\d{2,4})(?:[-.x ]*(\d+))?)\s*$/
          .source
    );

    const websiteTest = new RegExp(
      String(/[(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}/.source) +
        /\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/.source
    );

    switch (field) {
      case 'avatar': {
        if (
          state.avatarToSet === '' ||
          (Boolean(props.contact.avatar) &&
            state.avatarToSet === props.contact.avatar)
        ) {
          return false;
        }
        const avatarTestResult = websiteTest.exec(state.avatarToSet);
        if (avatarTestResult) {
          this.setState(
            {
              awaiting: true,
              type: 'Saving to group'
            },
            () => {
              props.api.contacts.edit(props.path, ship, {
                avatar: {
                  url: state.avatarToSet
                }})
                .then(() => {
                  this.setState({ awaiting: false });
                });
            }
          );
        }
        break;
      }
      case 'color': {
        let currentColor = props.contact.color ? props.contact.color : '000000';
        currentColor = uxToHex(currentColor);
        const hexExp = /([0-9A-Fa-f]{6})/;
        const hexTest = hexExp.exec(this.state.colorToSet);

        if (hexTest && hexTest[1] !== currentColor && !props.share) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, `~${props.ship}`, { color: hexTest[1] })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'email': {
        if (
          state.emailToSet === '' ||
          state.emailToSet === props.contact.email
        ) {
          return false;
        }
        const emailTestResult = emailTest.exec(state.emailToSet);
        if (emailTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { email: state.emailToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'nickname': {
        if (
          state.nickNameToSet === '' ||
          state.nickNameToSet === props.contact.nickname
        ) {
          return false;
        }
        this.setState({ awaiting: true, type: 'Saving to group' }, () => {
          props.api.contacts.edit(
            props.path, ship, { nickname: state.nickNameToSet })
            .then(() => {
              this.setState({ awaiting: false });
            });
        });

        break;
      }
      case 'notes': {
        if (
          state.notesToSet === '' ||
          state.notesToSet === props.contact.notes
        ) {
          return false;
        }
        this.setState({ awaiting: true, type: 'Saving to group' }, () => {
          props.api.contacts.edit(
            props.path, ship, { notes: state.notesToSet })
            .then(() => {
              this.setState({ awaiting: false });
            });
        });
        break;
      }
      case 'phone': {
        if (
          state.phoneToSet === '' ||
          state.phoneToSet === props.contact.phone
        ) {
          return false;
        }
        const phoneTestResult = phoneTest.exec(state.phoneToSet);
        if (phoneTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { phone: state.phoneToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'website': {
        if (
          state.websiteToSet === '' ||
          state.websiteToSet === props.contact.website
        ) {
          return false;
        }
        const websiteTestResult = websiteTest.exec(state.websiteToSet);
        if (websiteTestResult) {
          this.setState({ awaiting: true, type: 'Saving to group' }, () => {
            props.api.contacts.edit(
              props.path, ship, { website: state.websiteToSet })
              .then(() => {
                this.setState({ awaiting: false });
              });
          });
        }
        break;
      }
      case 'removeEmail': {
        this.setState(
          { emailToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { email: '' })
              .then(() => {
                this.setState({ awaiting: false });
              });
          }
        );
        break;
      }
      case 'removeNickname': {
        this.setState(
          { nicknameToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { nickname: '' })
              .then(() => {
                this.setState({ awaiting: false });
              });
          }
        );
        break;
      }
      case 'removePhone': {
        this.setState(
          { phoneToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { phone: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeWebsite': {
        this.setState(
          { websiteToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { website: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeAvatar': {
        this.setState(
          {
            avatarToSet: null,
            awaiting: true,
            type: 'Removing from group'
          },
          () => {
            props.api.contacts.edit(props.path, ship, { avatar: null }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
      case 'removeNotes': {
        this.setState(
          { notesToSet: '', awaiting: true, type: 'Removing from group' },
          () => {
            props.api.contacts.edit(props.path, ship, { notes: '' }).then(() => {
              this.setState({ awaiting: false });
            });
          }
        );
        break;
      }
    }
  }

  pickFunction(val, def) {
    if (val !== null) {
      return val;
    }
    return def;
  }

  shareWithGroup() {
    const { props, state } = this;
    const defaultVal = props.share
      ? {
          nickname: props.rootIdentity.nickname,
          email: props.rootIdentity.email,
          phone: props.rootIdentity.phone,
          website: props.rootIdentity.website,
          avatar: props.rootIdentity.avatar
            ? { url: props.rootIdentity.avatar }
            : null,
          notes: props.rootIdentity.notes,
          color: uxToHex(props.rootIdentity.color)
        }
      : {
          nickname: props.contact.nickname,
          email: props.contact.email,
          phone: props.contact.phone,
          website: props.contact.website,
          avatar: props.contact.avatar ? { url: props.contact.avatar } : null,
          notes: props.contact.notes,
          color: props.contact.color
        };

    const contact = {
      nickname: this.pickFunction(state.nickNameToSet, defaultVal.nickname),
      email: this.pickFunction(state.emailToSet, defaultVal.email),
      phone: this.pickFunction(state.phoneToSet, defaultVal.phone),
      website: this.pickFunction(state.websiteToSet, defaultVal.website),
      notes: this.pickFunction(state.notesToSet, defaultVal.notes),
      color: this.pickFunction(state.colorToSet, defaultVal.color),
      avatar: this.pickFunction(
        state.avatarToSet ? { url: state.avatarToSet } : null,
        defaultVal.avatar
      )
    };

    this.setState({ awaiting: true, type: 'Sharing with group' }, () => {
      props.api.contacts
        .share(`~${props.ship}`, props.path, `~${window.ship}`, contact)
        .then(() => {
          this.setState({ awaiting: false });
{'fraction_non_alphanumeric': 0.1591187806587246, 'fraction_numerical': 0.004467414155571128, 'mean_word_length': 1.6590194480027949, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 59, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, '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': '1370478', 'n_tokens_mistral': 7057, 'n_tokens_neox': 6934, 'n_words': 1227}