<commit_before>/**
 * @providesModule Responses
 * @flow
 */

import * as React from 'react'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { groupWith } from 'ramda'

import { StyledComment } from 'conversation/shared'
import Identicon from 'shared/Identicon'
import { SmallGreyText, ConversationTimestamp } from 'conversation/shared'

import { deleteComment } from 'redux/actions'

import type { Comment } from 'redux/state'

const ms = x => new Date(x).getTime()

const TWO_MINUTES = 2 * 60 * 1000 // milliseconds
const closeEnoughTimestamps = (a, b) => {
  return Math.abs(ms(a.timestamp) - ms(b.timestamp)) < TWO_MINUTES
}
const sameReader = (a, b) => a.reader.hashKey === b.reader.hashKey

const groupComments = comments =>
  groupWith(closeEnoughTimestamps, comments).map(groupWith(sameReader))

type Props = { deleteComment: typeof deleteComment, responses: Comment[] }
const Responses = ({ deleteComment, responses }: Props) => {
  if (responses.length === 0) return null
  const timeGroups = groupComments(responses)
  return (
    <Container>
      {timeGroups.map(readerGroups => {
        const firstTimestamp = readerGroups[0][0].timestamp
        return [
          <Timestamp key={firstTimestamp}>
            <ConversationTimestamp value={firstTimestamp} />
          </Timestamp>,
          readerGroups.map(comments => (
            <ResponseGroup
              key={`${comments[0].reader.name} ${comments[0].timestamp}`}
            >
              <SmallGreyText>{comments[0].reader.name}</SmallGreyText>
              {comments.map(comment => (
                <Response key={comment.id}>
                  <SpeechBubble>
                    <StyledComment markdown={comment.content} />
                  </SpeechBubble>
                  <DeleteButton onClick={() => deleteComment(comment.id)} />
                </Response>
              ))}
              <Identicon
                presentational
                key={comments[0].reader.hashKey}
                width={32}
                reader={comments[0].reader}
              />
            </ResponseGroup>
          )),
        ]
      })}
    </Container>
  )
}
export default connect(null, { deleteComment })(Responses)

const Container = styled.div``

const Timestamp = SmallGreyText.extend`
  display: block;
  width: 100%;
  text-align: center;
  margin-top: 36px;
`

const ResponseGroup = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  position: relative;
  margin: 10px 0 20px;

  &:last-child {
    margin-bottom: 0;
  }

  & ${SmallGreyText} {
    margin-left: 60px;
  }
<commit_msg>Adds aria-label back to delete comment button<commit_after>/**
 * @providesModule Responses
 * @flow
 */

import * as React from 'react'
import { connect } from 'react-redux'
import { injectIntl } from 'react-intl'
import styled from 'styled-components'
import { groupWith } from 'ramda'

import { StyledComment } from 'conversation/shared'
import Identicon from 'shared/Identicon'
import { SmallGreyText, ConversationTimestamp } from 'conversation/shared'

import { deleteComment } from 'redux/actions'

import type { IntlShape } from 'react-intl'
import type { Comment } from 'redux/state'

const ms = x => new Date(x).getTime()

const TWO_MINUTES = 2 * 60 * 1000 // milliseconds
const closeEnoughTimestamps = (a, b) => {
  return Math.abs(ms(a.timestamp) - ms(b.timestamp)) < TWO_MINUTES
}
const sameReader = (a, b) => a.reader.hashKey === b.reader.hashKey

const groupComments = comments =>
  groupWith(closeEnoughTimestamps, comments).map(groupWith(sameReader))

type Props = {
  deleteComment: typeof deleteComment,
  intl: IntlShape,
  responses: Comment[],
}
const Responses = ({ deleteComment, intl, responses }: Props) => {
  if (responses.length === 0) return null
  const timeGroups = groupComments(responses)
  return (
    <Container>
      {timeGroups.map(readerGroups => {
        const firstTimestamp = readerGroups[0][0].timestamp
        return [
          <Timestamp key={firstTimestamp}>
            <ConversationTimestamp value={firstTimestamp} />
          </Timestamp>,
          readerGroups.map(comments => (
            <ResponseGroup
              key={`${comments[0].reader.name} ${comments[0].timestamp}`}
            >
              <SmallGreyText>{comments[0].reader.name}</SmallGreyText>
              {comments.map(comment => (
                <Response key={comment.id}>
                  <SpeechBubble>
                    <StyledComment markdown={comment.content} />
                  </SpeechBubble>
                  <DeleteButton
                    aria-label={intl.formatMessage({
                      id: 'comments.deleteComment',
                      defaultMessage: 'Delete comment',
                    })}
                    onClick={() => deleteComment(comment.id)}
                  />
                </Response>
              ))}
              <Identicon
                presentational
                key={comments[0].reader.hashKey}
                width={32}
                reader={comments[0].reader}
              />
            </ResponseGroup>
          )),
        ]
      })}
    </Container>
  )
}
export default injectIntl(connect(null, { deleteComment })(Responses))

const Container = styled.div``

const Timestamp = SmallGreyText.extend`
  display: block;
  width: 100%;
  text-align: center;
  margin-top: 36px;
`

const ResponseGroup = styled.div`
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  position: relative;
  margin: 10px 0 20px;

  &:last-child {
    margin-bottom: 0;
  }

  & ${SmallGreyText} {
    margin-left: 60px;
  }

{'fraction_non_alphanumeric': 0.12488990664083142, 'fraction_numerical': 0.010568962480183195, 'mean_word_length': 2.4204819277108434, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 53, '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': '2221810', 'n_tokens_mistral': 1709, 'n_tokens_neox': 1618, 'n_words': 360}