<commit_before>import React, { Component } from 'react'
import classNames from 'classnames'
import { Spinner } from 'cozy-ui/react'
import Menu, { Item } from 'components/Menu'
import { Avatar, AvatarPlusX, AvatarLink } from './Avatar'

import styles from './recipient.styl'

import { getDisplayName, getPrimaryEmail, getPrimaryCozy } from '..'

const MAX_DISPLAYED_RECIPIENTS = 3

export const RecipientsAvatars = ({ recipients, link, size, className }) => {
  // we reverse the recipients array because we use `flex-direction: row-reverse` to display them correctly
  // we slice first to clone the original array because reverse() mutates it
  const reversedRecipients = recipients.slice().reverse()
  return (
    <div className={classNames(styles['recipients-avatars'], className)}>
      {link && <AvatarLink size={size} />}
      {recipients.length > MAX_DISPLAYED_RECIPIENTS && (
        <AvatarPlusX
          extraRecipients={reversedRecipients
            .slice(MAX_DISPLAYED_RECIPIENTS)
            .map(recipient => getDisplayName(recipient))}
          size={size}
        />
      )}
      {reversedRecipients
        .slice(0, MAX_DISPLAYED_RECIPIENTS)
        .map(recipient => (
          <Avatar name={getDisplayName(recipient)} size={size} />
        ))}
    </div>
  )
}

const Identity = ({ name, url }) => (
  <div className={styles['recipient-idents']}>
    <div className={styles['recipient-user']}>{name}</div>
    <div className={styles['recipient-url']}>{url}</div>
  </div>
)

export const UserAvatar = ({ url, ...rest }) => (
  <div className={styles['avatar']}>
    <Avatar name={getDisplayName(rest)} />
    <Identity name={getDisplayName(rest)} url={url} />
  </div>
)

class Status extends Component {
  state = {
    revoking: false
  }

  onRevoke = async () => {
    const { onRevoke, document, email } = this.props
    this.setState(state => ({ revoking: true }))
    await onRevoke(document, email)
    this.setState(state => ({ revoking: false }))
  }

  render() {
    const { isOwner, status, instance, type, documentType } = this.props
    const { t, client } = this.context
    const { revoking } = this.state
    const isMe =
      instance !== undefined && instance === client.options.uri && !isOwner
    const shouldShowMenu = !revoking && status !== 'owner' && (isMe || isOwner)
    return (
      <div className={styles['recipient-status']}>
        {revoking && <Spinner />}
        {!shouldShowMenu && <span>{t(`Share.status.${status}`)}</span>}
        {shouldShowMenu && (
          <Menu
            title={
              status === 'ready' && type
                ? t(`Share.type.${type}`)
                : t(`Share.status.${status}`)
            }
            className={styles['recipient-menu']}
            buttonClassName={styles['recipient-menu-btn']}
            disabled={status === 'pending'}
          >
            <Item>
              <div
                className={classNames(
                  styles['recipient-menu-header'],
                  status === 'ready' && type
                    ? styles[`recipient-menu-header--${type}`]
                    : styles[`recipient-menu-header--${status}`]
                )}
              >
                {status === 'ready' && type
                  ? t(`Share.type.${type}`)
                  : t(`Share.status.${status}`)}
              </div>
            </Item>
            <hr />
            <Item>
              <a className={styles['action-unshare']} onClick={this.onRevoke}>
                {isOwner
                  ? t(`${documentType}.share.revoke.title`)
                  : t(`${documentType}.share.revokeSelf.title`)}
              </a>
              <p className={styles['action-unshare-desc']}>
                {isOwner
                  ? t(`${documentType}.share.revoke.desc`)
                  : t(`${documentType}.share.revokeSelf.desc`)}
              </p>
            </Item>
          </Menu>
        )}
      </div>
    )
  }
}

const Recipient = (props, { t, client }) => {
  const { instance, isOwner, status, ...rest } = props
  const isMe =
    (isOwner && status === 'owner') || instance === client.options.uri
  const name = getDisplayName(rest)
  return (
    <div className={styles['recipient']}>
      <Avatar name={name} />
      <div className={styles['recipient-ident-status']}>
        <Identity
          name={isMe ? t('Share.recipients.you') : name}
          url={instance}
        />
        <Status {...props} />
      </div>
    </div>
  )
}

export default Recipient

export const Contact = ({ contact }) => {
  const name = getPrimaryEmail(contact)
  const url = getPrimaryCozy(contact)
  return (
    <div className={styles['recipient']}>
      <Avatar name={name} />
      <Identity name={name} url={url} />
    </div><commit_msg>fix: Access menu on mobile<commit_after>import React, { Component } from 'react'
import classNames from 'classnames'
import { Spinner } from 'cozy-ui/react'
import { Menu, MenuItem, withBreakpoints } from 'cozy-ui/react'
import { Avatar, AvatarPlusX, AvatarLink } from './Avatar'

import styles from './recipient.styl'

import { getDisplayName, getPrimaryEmail, getPrimaryCozy } from '..'

const MAX_DISPLAYED_RECIPIENTS = 3

export const RecipientsAvatars = ({ recipients, link, size, className }) => {
  // we reverse the recipients array because we use `flex-direction: row-reverse` to display them correctly
  // we slice first to clone the original array because reverse() mutates it
  const reversedRecipients = recipients.slice().reverse()
  return (
    <div className={classNames(styles['recipients-avatars'], className)}>
      {link && <AvatarLink size={size} />}
      {recipients.length > MAX_DISPLAYED_RECIPIENTS && (
        <AvatarPlusX
          extraRecipients={reversedRecipients
            .slice(MAX_DISPLAYED_RECIPIENTS)
            .map(recipient => getDisplayName(recipient))}
          size={size}
        />
      )}
      {reversedRecipients
        .slice(0, MAX_DISPLAYED_RECIPIENTS)
        .map(recipient => (
          <Avatar name={getDisplayName(recipient)} size={size} />
        ))}
    </div>
  )
}

const Identity = ({ name, url }) => (
  <div className={styles['recipient-idents']}>
    <div className={styles['recipient-user']}>{name}</div>
    <div className={styles['recipient-url']}>{url}</div>
  </div>
)

export const UserAvatar = ({ url, ...rest }) => (
  <div className={styles['avatar']}>
    <Avatar name={getDisplayName(rest)} />
    <Identity name={getDisplayName(rest)} url={url} />
  </div>
)

class Status extends Component {
  state = {
    revoking: false
  }

  onRevoke = async () => {
    const { onRevoke, document, email } = this.props
    this.setState(state => ({ revoking: true }))
    await onRevoke(document, email)
    this.setState(state => ({ revoking: false }))
  }

  render() {
    const {
      isOwner,
      status,
      instance,
      type,
      documentType,
      breakpoints: { isMobile }
    } = this.props
    const { t, client } = this.context
    const { revoking } = this.state
    const isMe =
      instance !== undefined && instance === client.options.uri && !isOwner
    const shouldShowMenu = !revoking && status !== 'owner' && (isMe || isOwner)
    return (
      <div className={styles['recipient-status']}>
        {revoking && <Spinner />}
        {!shouldShowMenu && <span>{t(`Share.status.${status}`)}</span>}
        {shouldShowMenu && (
          <Menu
            text={
              status === 'ready' && type
                ? t(`Share.type.${type}`)
                : t(`Share.status.${status}`)
            }
            className={styles['recipient-menu']}
            buttonClassName={styles['recipient-menu-btn']}
            position={isMobile ? 'left' : 'right'}
            disabled={false}
          >
            <MenuItem>
              <div
                className={classNames(
                  styles['recipient-menu-header'],
                  status === 'ready' && type
                    ? styles[`recipient-menu-header--${type}`]
                    : styles[`recipient-menu-header--${status}`]
                )}
              >
                {status === 'ready' && type
                  ? t(`Share.type.${type}`)
                  : t(`Share.status.${status}`)}
              </div>
            </MenuItem>
            <hr />
            <MenuItem>
              <a className={styles['action-unshare']} onClick={this.onRevoke}>
                {isOwner
                  ? t(`${documentType}.share.revoke.title`)
                  : t(`${documentType}.share.revokeSelf.title`)}
              </a>
              <p className={styles['action-unshare-desc']}>
                {isOwner
                  ? t(`${documentType}.share.revoke.desc`)
                  : t(`${documentType}.share.revokeSelf.desc`)}
              </p>
            </MenuItem>
          </Menu>
        )}
      </div>
    )
  }
}

const StatusWithBreakpoints = withBreakpoints()(Status)

const Recipient = (props, { t, client }) => {
  const { instance, isOwner, status, ...rest } = props
  const isMe =
    (isOwner && status === 'owner') || instance === client.options.uri
  const name = getDisplayName(rest)
  return (
    <div className={styles['recipient']}>
      <Avatar name={name} />
      <div className={styles['recipient-ident-status']}>
        <Identity
          name={isMe ? t('Share.recipients.you') : name}
          url={instance}
        />
        <StatusWithBreakpoints {...props} />
      </div>
    </div>
  )
}

export default Recipient

export const Contact = ({ contact }) => {
  const name = getPrimaryEmail(contact)
  const url = getPrimaryCozy(contact)
  return (
    <div className={styles['recipient']}>
      <Avatar name={name} />
      <Identity name={name} url={url} />
    </div>
{'fraction_non_alphanumeric': 0.15668296658516706, 'fraction_numerical': 0.00040749796251018743, 'mean_word_length': 2.1945981125935567, 'pattern_counts': {'":': 0, '<': 91, '<?xml version=': 0, '>': 113, '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': '5612358', 'n_tokens_mistral': 2956, 'n_tokens_neox': 2861, 'n_words': 577}