diff --git a/lib/hooks/inline-sidebar-text.react.js b/lib/hooks/inline-sidebar-text.react.js new file mode 100644 index 000000000..6104c3335 --- /dev/null +++ b/lib/hooks/inline-sidebar-text.react.js @@ -0,0 +1,35 @@ +// @flow + +import * as React from 'react'; + +import { relativeMemberInfoSelectorForMembersOfThread } from '../selectors/user-selectors'; +import { stringForUser } from '../shared/user-utils'; +import type { ThreadInfo } from '../types/thread-types'; +import { useSelector } from '../utils/redux-utils'; +import { pluralizeAndTrim } from '../utils/text-utils'; + +function useInlineSidebarText( + threadInfo: ThreadInfo, +): { + sendersText: string, + repliesText: string, +} { + 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 { sendersText, repliesText }; +} + +export default useInlineSidebarText; diff --git a/native/chat/inline-sidebar.react.js b/native/chat/inline-sidebar.react.js index 8c3ae5a8b..601a2d19c 100644 --- a/native/chat/inline-sidebar.react.js +++ b/native/chat/inline-sidebar.react.js @@ -1,123 +1,107 @@ // @flow 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 useInlineSidebarText from 'lib/hooks/inline-sidebar-text.react'; import type { ThreadInfo } from 'lib/types/thread-types'; -import { pluralizeAndTrim } from 'lib/utils/text-utils'; import Button from '../components/button.react'; -import { useSelector } from '../redux/redux-utils'; import { useStyles } from '../themes/colors'; import { useNavigateToThread } from './message-list-types'; type Props = { +threadInfo: ThreadInfo, +positioning: 'left' | 'center' | 'right', }; function InlineSidebar(props: Props): React.Node { const { threadInfo } = props; + const { sendersText, repliesText } = useInlineSidebarText(threadInfo); const navigateToThread = useNavigateToThread(); const onPress = React.useCallback(() => { navigateToThread({ threadInfo }); }, [navigateToThread, 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: { color: 'listForegroundLabel', 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, }; diff --git a/web/chat/inline-sidebar.react.js b/web/chat/inline-sidebar.react.js index d9ef13e83..230357be0 100644 --- a/web/chat/inline-sidebar.react.js +++ b/web/chat/inline-sidebar.react.js @@ -1,78 +1,62 @@ // @flow import classNames from 'classnames'; import * as React from 'react'; import { CornerDownRight as CornerDownRightIcon, CornerDownLeft as CornerDownLeftIcon, } from 'react-feather'; -import { relativeMemberInfoSelectorForMembersOfThread } from 'lib/selectors/user-selectors'; -import { stringForUser } from 'lib/shared/user-utils'; +import useInlineSidebarText from 'lib/hooks/inline-sidebar-text.react'; import type { ThreadInfo } from 'lib/types/thread-types'; -import { pluralizeAndTrim } from 'lib/utils/text-utils'; -import { useSelector } from '../redux/redux-utils'; import { useOnClickThread } from '../selectors/nav-selectors'; import css from './inline-sidebar.css'; type Props = { +threadInfo: ThreadInfo, +positioning: 'left' | 'center' | 'right', }; function InlineSidebar(props: Props): React.Node { const { threadInfo } = props; + const { sendersText, repliesText } = useInlineSidebarText(threadInfo); const onClick = useOnClickThread(threadInfo); let viewerIcon, nonViewerIcon, alignStyle; if (props.positioning === 'right') { viewerIcon = ( ); alignStyle = css.viewerMessageBoxContainer; } else if (props.positioning === 'left') { nonViewerIcon = ( ); alignStyle = css.nonViewerMessageBoxContainer; } else { nonViewerIcon = ( ); alignStyle = css.centerContainer; } const unreadStyle = threadInfo.currentUser.unread ? css.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 (
{nonViewerIcon}
{sendersText} {repliesText}
{viewerIcon}
); } const inlineSidebarHeight = 20; export { InlineSidebar, inlineSidebarHeight };