2015-03-26 03:41:48 +08:00
|
|
|
React = require 'react'
|
2015-05-20 07:06:59 +08:00
|
|
|
_ = require 'underscore'
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
class ThreadListParticipants extends React.Component
|
|
|
|
@displayName: 'ThreadListParticipants'
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
@propTypes:
|
2015-03-26 03:41:48 +08:00
|
|
|
thread: React.PropTypes.object.isRequired
|
2015-05-02 03:58:25 +08:00
|
|
|
|
2015-08-04 05:09:29 +08:00
|
|
|
shouldComponentUpdate: (nextProps) =>
|
|
|
|
return false if nextProps.thread is @props.thread
|
|
|
|
true
|
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
render: =>
|
2015-03-26 03:41:48 +08:00
|
|
|
items = @getParticipants()
|
2015-08-20 08:39:16 +08:00
|
|
|
<div className="participants">
|
|
|
|
{@getSpans(items)}
|
|
|
|
</div>
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-08-20 08:39:16 +08:00
|
|
|
getSpans: (items) =>
|
2015-04-07 02:46:20 +08:00
|
|
|
spans = []
|
|
|
|
accumulated = null
|
|
|
|
accumulatedUnread = false
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-04-07 02:46:20 +08:00
|
|
|
flush = ->
|
|
|
|
if accumulated
|
|
|
|
spans.push <span key={spans.length} className="unread-#{accumulatedUnread}">{accumulated}</span>
|
|
|
|
accumulated = null
|
|
|
|
accumulatedUnread = false
|
|
|
|
|
|
|
|
accumulate = (text, unread) ->
|
|
|
|
if accumulated and unread and accumulatedUnread isnt unread
|
|
|
|
flush()
|
|
|
|
if accumulated
|
|
|
|
accumulated += text
|
|
|
|
else
|
|
|
|
accumulated = text
|
|
|
|
accumulatedUnread = unread
|
|
|
|
|
|
|
|
for {spacer, contact, unread}, idx in items
|
2015-03-28 07:34:59 +08:00
|
|
|
if spacer
|
2015-04-07 02:46:20 +08:00
|
|
|
accumulate('...')
|
2015-03-26 03:41:48 +08:00
|
|
|
else
|
2015-03-28 07:34:59 +08:00
|
|
|
if contact.name.length > 0
|
2015-03-26 03:41:48 +08:00
|
|
|
if items.length > 1
|
2015-03-28 07:34:59 +08:00
|
|
|
short = contact.displayFirstName()
|
2015-03-26 03:41:48 +08:00
|
|
|
else
|
2015-03-28 07:34:59 +08:00
|
|
|
short = contact.displayName()
|
2015-03-26 03:41:48 +08:00
|
|
|
else
|
2015-03-28 07:34:59 +08:00
|
|
|
short = contact.email
|
2015-03-26 03:41:48 +08:00
|
|
|
if idx < items.length-1 and not items[idx+1].spacer
|
|
|
|
short += ", "
|
2015-04-07 02:46:20 +08:00
|
|
|
accumulate(short, unread)
|
|
|
|
|
|
|
|
if @props.thread.metadata and @props.thread.metadata.length > 1
|
|
|
|
accumulate(" (#{@props.thread.metadata.length})")
|
|
|
|
|
|
|
|
flush()
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-08-20 08:39:16 +08:00
|
|
|
return spans
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
getParticipants: =>
|
2015-08-15 05:17:15 +08:00
|
|
|
makeMetadataFilterer = (toOrFrom) ->
|
|
|
|
(msg, i, msgs) ->
|
|
|
|
isFirstMsg = i is 0
|
|
|
|
if msg.draft
|
|
|
|
false
|
|
|
|
else if isFirstMsg
|
|
|
|
true
|
|
|
|
else # check adjacent email uniqueness
|
|
|
|
last = msgs[i - 1][toOrFrom][0]
|
|
|
|
curr = msgs[i][toOrFrom][0]
|
2015-08-21 07:20:42 +08:00
|
|
|
if last and curr
|
|
|
|
isUniqueEmail = last.email.toLowerCase() isnt curr.email.toLowerCase()
|
|
|
|
isUniqueName = last.name isnt curr.name
|
|
|
|
isUniqueEmail or isUniqueName
|
|
|
|
else
|
|
|
|
return false
|
2015-08-15 05:17:15 +08:00
|
|
|
|
|
|
|
makeMetadataMapper = (toOrFrom) ->
|
|
|
|
(msg) ->
|
|
|
|
msg[toOrFrom].map (contact) ->
|
|
|
|
{ contact: contact, unread: msg.unread }
|
2015-03-26 03:41:48 +08:00
|
|
|
|
2015-08-15 05:17:15 +08:00
|
|
|
if @props.thread.metadata
|
|
|
|
shouldOnlyShowRecipients = @props.thread.metadata.every (msg) ->
|
2015-08-19 01:18:30 +08:00
|
|
|
msg.from[0]?.isMe()
|
2015-08-15 05:17:15 +08:00
|
|
|
input = @props.thread.metadata
|
|
|
|
toOrFrom = if shouldOnlyShowRecipients then "to" else "from"
|
|
|
|
filterer = makeMetadataFilterer toOrFrom
|
|
|
|
mapper = makeMetadataMapper toOrFrom
|
2015-03-26 03:41:48 +08:00
|
|
|
else
|
2015-08-15 05:17:15 +08:00
|
|
|
input = @props.thread.participants
|
|
|
|
return [] unless input and input instanceof Array
|
2015-08-19 01:18:30 +08:00
|
|
|
filterer = (contact) -> not contact.isMe()
|
2015-08-15 05:17:15 +08:00
|
|
|
mapper = (contact) -> { contact: contact, unread: false }
|
|
|
|
|
|
|
|
list = _.chain(input)
|
|
|
|
.filter(filterer)
|
|
|
|
.map(mapper)
|
|
|
|
.reduce(((prevContacts, next) -> prevContacts.concat(next)), [])
|
|
|
|
.value()
|
|
|
|
|
|
|
|
# If no participants, we should at least add current user as sole participant
|
|
|
|
if list.length is 0 and @props.thread.participants.length > 0
|
|
|
|
list.push({ contact: @props.thread.participants[0], unread: false })
|
2015-03-31 02:21:23 +08:00
|
|
|
|
2015-03-26 03:41:48 +08:00
|
|
|
# We only ever want to show three. Ben...Kevin... Marty
|
|
|
|
# But we want the *right* three.
|
|
|
|
if list.length > 3
|
2015-08-15 05:17:15 +08:00
|
|
|
listTrimmed = [
|
|
|
|
# Always include the first item
|
|
|
|
list[0],
|
|
|
|
{ spacer: true },
|
|
|
|
|
|
|
|
# Always include last two items
|
|
|
|
list[list.length - 2],
|
|
|
|
list[list.length - 1]
|
|
|
|
]
|
2015-03-26 03:41:48 +08:00
|
|
|
list = listTrimmed
|
|
|
|
|
|
|
|
list
|
|
|
|
|
2015-05-01 04:08:29 +08:00
|
|
|
|
|
|
|
module.exports = ThreadListParticipants
|