diff --git a/lib/utils/text-utils.js b/lib/utils/text-utils.js index 9cb043d65..176747879 100644 --- a/lib/utils/text-utils.js +++ b/lib/utils/text-utils.js @@ -1,34 +1,47 @@ // @flow function pluralize( nouns: $ReadOnlyArray, maxNumberOfNouns: number = 3, ): string { if (nouns.length === 0) { return ''; } else if (nouns.length === 1) { return nouns[0]; } else if (maxNumberOfNouns === 1) { return `${nouns.length} ${nouns.length > 1 ? 'users' : 'user'}`; } const comma = maxNumberOfNouns > 2 && nouns.length > 2 ? ',' : ''; if (nouns.length <= maxNumberOfNouns) { const prefix = nouns.slice(0, nouns.length - 1).join(', '); return `${prefix}${comma} and ${nouns[nouns.length - 1]}`; } else { const prefix = nouns.slice(0, maxNumberOfNouns - 1).join(', '); return `${prefix}${comma} and ${ nouns.length - maxNumberOfNouns + 1 } others`; } } function trimText(text: string, maxLength: number): string { if (text.length <= maxLength) { return text; } return text.substr(0, maxLength - 3) + '...'; } -export { pluralize, trimText }; +function pluralizeAndTrim( + nouns: $ReadOnlyArray, + maxLength: number, +): string { + for (let maxNumberOfNouns = 3; maxNumberOfNouns >= 2; --maxNumberOfNouns) { + const text = pluralize(nouns, maxNumberOfNouns); + if (text.length <= maxLength) { + return text; + } + } + return pluralize(nouns, 1); +} + +export { pluralize, trimText, pluralizeAndTrim }; diff --git a/native/chat/inline-sidebar.react.js b/native/chat/inline-sidebar.react.js index e95001c3f..65b6fb1bc 100644 --- a/native/chat/inline-sidebar.react.js +++ b/native/chat/inline-sidebar.react.js @@ -1,110 +1,128 @@ // @flow import { useNavigation } from '@react-navigation/native'; import * as React from 'react'; import { Text, View } from 'react-native'; import Icon from 'react-native-vector-icons/Feather'; +import { relativeMemberInfoSelectorForMembersOfThread } from 'lib/selectors/user-selectors'; +import { stringForUser } from 'lib/shared/user-utils'; import type { ThreadInfo } from 'lib/types/thread-types'; +import { pluralizeAndTrim } from 'lib/utils/text-utils'; import Button from '../components/button.react'; import { MessageListRouteName } from '../navigation/route-names'; +import { useSelector } from '../redux/redux-utils'; import { useStyles } from '../themes/colors'; import type { ChatNavigationProp } from './chat.react'; type Props = {| +threadInfo: ThreadInfo, +positioning: 'left' | 'center' | 'right', |}; function InlineSidebar(props: Props) { const { threadInfo } = props; const navigation: ChatNavigationProp<'MessageList'> = (useNavigation(): any); const onPress = React.useCallback(() => { navigation.navigate({ name: MessageListRouteName, params: { threadInfo }, key: `${MessageListRouteName}${threadInfo.id}`, }); }, [navigation, threadInfo]); const styles = useStyles(unboundStyles); let viewerIcon, nonViewerIcon, alignStyle; if (props.positioning === 'right') { viewerIcon = ; alignStyle = styles.rightAlign; } else if (props.positioning === 'left') { nonViewerIcon = ( ); alignStyle = styles.leftAlign; } else { nonViewerIcon = ( ); alignStyle = styles.centerAlign; } const unreadStyle = threadInfo.currentUser.unread ? styles.unread : null; const repliesCount = threadInfo.repliesCount || 1; const repliesText = `${repliesCount} ${ repliesCount > 1 ? 'replies' : 'reply' }`; + + const threadMembers = useSelector( + relativeMemberInfoSelectorForMembersOfThread(threadInfo.id), + ); + const sendersText = React.useMemo(() => { + const senders = threadMembers + .filter((member) => member.isSender) + .map(stringForUser); + return senders.length > 0 ? `${pluralizeAndTrim(senders, 25)} sent ` : ''; + }, [threadMembers]); + return ( ); } const inlineSidebarHeight = 20; const inlineSidebarMarginTop = 5; const inlineSidebarMarginBottom = 3; const unboundStyles = { content: { flexDirection: 'row', marginRight: 30, marginLeft: 10, flex: 1, height: inlineSidebarHeight, }, unread: { fontWeight: 'bold', }, sidebar: { flexDirection: 'row', display: 'flex', alignItems: 'center', }, icon: { color: 'listForegroundTertiaryLabel', }, name: { paddingTop: 1, color: 'listForegroundTertiaryLabel', fontSize: 16, paddingLeft: 4, paddingRight: 2, }, leftAlign: { justifyContent: 'flex-start', }, rightAlign: { justifyContent: 'flex-end', }, centerAlign: { justifyContent: 'center', }, }; export { InlineSidebar, inlineSidebarHeight, inlineSidebarMarginTop, inlineSidebarMarginBottom, };