diff --git a/src/common/Avatar.js b/src/common/Avatar.js index a3b4720726c..2d79ed77567 100644 --- a/src/common/Avatar.js +++ b/src/common/Avatar.js @@ -28,7 +28,7 @@ class Avatar extends PureComponent { status?: UserStatus, realm: string, shape: 'square' | 'rounded' | 'circle', - onPress?: () => void, + onPress: () => void, }; static defaultProps = { diff --git a/src/common/ImageAvatar.js b/src/common/ImageAvatar.js index ffbcc788fa8..cfba3b6d34a 100644 --- a/src/common/ImageAvatar.js +++ b/src/common/ImageAvatar.js @@ -10,8 +10,7 @@ export default class ImageAvatar extends PureComponent { avatarUrl: string, size: number, shape: string, - children: [], - onPress?: () => void, + onPress: () => void, }; static defaultProps = { @@ -19,7 +18,7 @@ export default class ImageAvatar extends PureComponent { }; render() { - const { avatarUrl, size, shape, onPress, children } = this.props; + const { avatarUrl, size, shape, onPress } = this.props; const touchableStyle = { height: size, width: size, @@ -34,9 +33,8 @@ export default class ImageAvatar extends PureComponent { style={touchableStyle} source={{ uri: avatarUrl }} resizeMode="cover" - borderRadius={borderRadius}> - {children} - + borderRadius={borderRadius} + /> ); } diff --git a/src/common/TextAvatar.js b/src/common/TextAvatar.js index 7cc9f70a7dd..d39933911ee 100644 --- a/src/common/TextAvatar.js +++ b/src/common/TextAvatar.js @@ -1,5 +1,5 @@ /* @flow */ -import React from 'react'; +import React, { PureComponent } from 'react'; import { Text, StyleSheet, View } from 'react-native'; import { Touchable } from './'; @@ -25,34 +25,36 @@ const styles = StyleSheet.create({ }, }); -type Props = { - name: string, - size: number, - shape: string, - children: [], - onPress?: () => void, -}; - -export default ({ name, size, status, shape, onPress, children }: Props) => { - const frameSize = { - height: size, - width: size, - borderRadius: - shape === 'rounded' ? size / 8 : shape === 'circle' ? size / 2 : shape === 'square' ? 0 : 0, - backgroundColor: colorHashFromName(name), - }; - const textSize = { - fontSize: size / 3, +export default class TextAvatar extends PureComponent { + props: { + name: string, + size: number, + shape?: string, + onPress?: () => void, }; - return ( - - - - {initialsFromName(name)} - - {children} - - - ); -}; + render() { + const { name, size, shape, onPress } = this.props; + + const frameSize = { + height: size, + width: size, + borderRadius: + shape === 'rounded' ? size / 8 : shape === 'circle' ? size / 2 : shape === 'square' ? 0 : 0, + backgroundColor: colorHashFromName(name), + }; + const textSize = { + fontSize: size / 3, + }; + + return ( + + + + {initialsFromName(name)} + + + + ); + } +} diff --git a/src/conversations/ConversationGroup.js b/src/conversations/ConversationGroup.js index 71fd5bc630e..cbda3b33f89 100644 --- a/src/conversations/ConversationGroup.js +++ b/src/conversations/ConversationGroup.js @@ -8,7 +8,7 @@ import { NULL_USER } from '../nullObjects'; import type { User, Narrow } from '../types'; import { normalizeRecipients } from '../utils/message'; import { isGroupNarrow } from '../utils/narrow'; -import { Avatar, RawLabel, Touchable, UnreadCount } from '../common'; +import { TextAvatar, RawLabel, Touchable, UnreadCount } from '../common'; import { BRAND_COLOR } from '../styles'; const styles = StyleSheet.create({ @@ -36,7 +36,7 @@ class ConversationGroup extends PureComponent { email: string, users: User[], unreadCount: number, - narrow?: Narrow, + narrow: Narrow, onPress: (emails: string) => void, }; @@ -57,7 +57,7 @@ class ConversationGroup extends PureComponent { return ( - + void, typingUsers?: TypingState, - messages: Array, - narrow: Narrow, + renderedMessages: any[], }; export default class MessageList extends PureComponent { @@ -49,25 +47,19 @@ export default class MessageList extends PureComponent { singleFetchProgress, onScroll, typingUsers, - messages, - narrow, + renderedMessages, } = this.props; - const messageList = renderMessages({ - messages, - narrow, - }); - // `headerIndices` tell the scroll view which components are headers // and are eligible to be docked at the top of the view. const headerIndices = []; - for (let i = 0; i < messageList.length; i++) { - const elem = messageList[i]; + for (let i = 0; i < renderedMessages.length; i++) { + const elem = renderedMessages[i]; if (elem.props.type === 'header') { headerIndices.push(i + 1); } if (elem.props.type === 'message') { - messageList[i] = ( + renderedMessages[i] = ( - {messageList} + {renderedMessages} {!singleFetchProgress && fetchingNewer && } {typingUsers && } diff --git a/src/message/MessageListContainer.js b/src/message/MessageListContainer.js index b74a65330a6..4489df4cf79 100644 --- a/src/message/MessageListContainer.js +++ b/src/message/MessageListContainer.js @@ -9,7 +9,7 @@ import { getAuth, getFlags, getCurrentTypingUsers, - getShownMessagesInActiveNarrow, + getRenderedMessages, getActiveNarrow, getCaughtUpForActiveNarrow, } from '../selectors'; @@ -40,7 +40,7 @@ class MessageListContainer extends PureComponent { fetchingOlder, fetchingNewer, typingUsers, - messages, + renderedMessages, narrow, actions, } = this.props; @@ -52,7 +52,7 @@ class MessageListContainer extends PureComponent { fetchingOlder={fetchingOlder} fetchingNewer={fetchingNewer} typingUsers={typingUsers} - messages={messages} + renderedMessages={renderedMessages} narrow={narrow} actions={actions} /> @@ -67,7 +67,7 @@ export default connect( fetchingOlder: state.chat.fetchingOlder, fetchingNewer: state.chat.fetchingNewer, typingUsers: getCurrentTypingUsers(state), - messages: getShownMessagesInActiveNarrow(state), + renderedMessages: getRenderedMessages(state), narrow: getActiveNarrow(state), flags: getFlags(state), auth: getAuth(state), diff --git a/src/message/MessageListFlatList.js b/src/message/MessageListFlatList.js index e44982bf673..ad9d6b6d0c1 100644 --- a/src/message/MessageListFlatList.js +++ b/src/message/MessageListFlatList.js @@ -7,7 +7,6 @@ import { nullFunction } from '../nullObjects'; import MessageContainer from './MessageContainer'; import TaggedView from '../native/TaggedView'; import renderMessages from './renderMessages'; -import { getFullUrl } from '../utils/url'; import { constructActionButtons, executeActionSheetAction, @@ -72,32 +71,9 @@ class MessageList extends PureComponent { render() { const { styles } = this.context; - const { - auth, - actions, - subscriptions, - users, - messages, - narrow, - mute, - doNarrow, - flags, - twentyFourHourTime, - } = this.props; + const { messages, narrow } = this.props; - const messageList = renderMessages({ - onLongPress: this.handleLongPress, - onHeaderLongPress: this.handleHeaderLongPress, - auth, - actions, - subscriptions, - users, - messages, - narrow, - mute, - flags, - twentyFourHourTime, - }); + const messageList = renderMessages(messages, narrow); // `headerIndices` tell the scroll view which components are headers // and are eligible to be docked at the top of the view. @@ -128,14 +104,9 @@ class MessageList extends PureComponent { keyExtractor={item => item.id} renderItem={({ item }) => } renderSectionHeader={({ section }) => diff --git a/src/message/__tests__/renderMessages-test.js b/src/message/__tests__/renderMessages-test.js index ad645e5181c..026da541d8e 100644 --- a/src/message/__tests__/renderMessages-test.js +++ b/src/message/__tests__/renderMessages-test.js @@ -6,9 +6,7 @@ describe('renderMessages', () => { const narrow = deepFreeze([]); test('empty messages results in no rendered messages', () => { - const props = deepFreeze({ messages: [] }); - - const messageList = renderMessages(props); + const messageList = renderMessages([]); expect(messageList).toEqual([]); }); @@ -23,7 +21,7 @@ describe('renderMessages', () => { const expectedComponentKeys = ['time123', 'header1', '1']; - const messageList = renderMessages({ messages, narrow }); + const messageList = renderMessages(messages, narrow); const messageKeys = messageList.map(x => x.key); expect(messageKeys).toEqual(expectedComponentKeys); @@ -62,7 +60,7 @@ describe('renderMessages', () => { const expectedComponentKeys = ['time123', 'header1', '1', '2', '3']; - const messageList = renderMessages({ messages, narrow }); + const messageList = renderMessages(messages, narrow); const messageKeys = messageList.map(x => x.key); expect(messageKeys).toEqual(expectedComponentKeys); @@ -104,7 +102,7 @@ describe('renderMessages', () => { const expectedComponentKeys = ['time123', 'header1', '1', '2', '3']; - const messageList = renderMessages({ messages, narrow }); + const messageList = renderMessages(messages, narrow); const messageKeys = messageList.map(x => x.key); expect(messageKeys).toEqual(expectedComponentKeys); @@ -135,7 +133,7 @@ describe('renderMessages', () => { const expectedComponentTypes = ['time123', 'header1', '1', '2']; - const messageList = renderMessages({ messages, narrow }); + const messageList = renderMessages(messages, narrow); const messageTypes = messageList.map(x => x.key); expect(messageTypes).toEqual(expectedComponentTypes); diff --git a/src/message/messageSelectors.js b/src/message/messageSelectors.js new file mode 100644 index 00000000000..3d96a27a099 --- /dev/null +++ b/src/message/messageSelectors.js @@ -0,0 +1,12 @@ +/* @flow */ +import { createSelector } from 'reselect'; + +import { getActiveNarrow } from '../baseSelectors'; +import { getShownMessagesInActiveNarrow } from '../chat/chatSelectors'; +import renderMessages from './renderMessages'; + +export const getRenderedMessages = createSelector( + getShownMessagesInActiveNarrow, + getActiveNarrow, + (messages, narrow) => renderMessages(messages, narrow), +); diff --git a/src/message/renderMessages.js b/src/message/renderMessages.js index bf8ecb5ba0a..8f806c7d0f6 100644 --- a/src/message/renderMessages.js +++ b/src/message/renderMessages.js @@ -1,7 +1,7 @@ /* @flow */ import React from 'react'; -import type { Narrow } from '../types'; +import type { Message, Narrow } from '../types'; import { isTopicNarrow, isPrivateOrGroupNarrow, @@ -14,12 +14,7 @@ import TimeRow from '../message/TimeRow'; import { isSameRecipient } from '../utils/message'; import { isSameDay } from '../utils/date'; -type Props = { - messages: any[], - narrow: Narrow, -}; - -export default ({ messages, narrow }: Props) => { +export default (messages: Message[], narrow: Narrow) => { const list: Object[] = []; let prevItem; @@ -83,5 +78,6 @@ export default ({ messages, narrow }: Props) => { prevItem = item; } + return list; }; diff --git a/src/search/SearchMessagesCard.js b/src/search/SearchMessagesCard.js index 9451f5f400e..6f914986990 100644 --- a/src/search/SearchMessagesCard.js +++ b/src/search/SearchMessagesCard.js @@ -10,6 +10,7 @@ import { BRAND_COLOR } from '../styles'; import { searchNarrow } from '../utils/narrow'; import MessageList from '../message/MessageList'; import { getMessages } from '../api'; +import renderMessages from '../message/renderMessages'; const styles = StyleSheet.create({ empty: { @@ -27,12 +28,10 @@ const styles = StyleSheet.create({ type Props = { actions: Actions, - twentyFourHourTime: boolean, - subscriptions: any[], query: string, auth: Auth, - flags: Object, }; + export default class SearchMessagesCard extends PureComponent { props: Props; @@ -70,13 +69,15 @@ export default class SearchMessagesCard extends PureComponent { render() { const { isFetching, messages, query } = this.state; - const { actions, auth, subscriptions, twentyFourHourTime, flags } = this.props; + const { actions } = this.props; const noResults = !!query && !isFetching && !messages.length; if (noResults) { return ; } + const renderedMessages = renderMessages(messages, []); + return ( {isFetching && @@ -84,17 +85,12 @@ export default class SearchMessagesCard extends PureComponent { diff --git a/src/search/SearchMessagesContainer.js b/src/search/SearchMessagesContainer.js index e4f36b05526..fb9bdc5998c 100644 --- a/src/search/SearchMessagesContainer.js +++ b/src/search/SearchMessagesContainer.js @@ -8,12 +8,6 @@ import SearchMessagesCard from './SearchMessagesCard'; export default connect( state => ({ auth: getAuth(state), - isOnline: state.app.isOnline, - subscriptions: state.subscriptions, - narrow: state.chat.narrow, - startReached: state.chat.startReached, - streamlistOpened: state.nav.opened, - flags: state.flags, }), boundActions, )(SearchMessagesCard); diff --git a/src/selectors.js b/src/selectors.js index 4dc661ad29a..154d22d2391 100644 --- a/src/selectors.js +++ b/src/selectors.js @@ -6,6 +6,7 @@ export * from './conversations/conversationsSelectors'; export * from './caughtup/caughtUpSelectors'; export * from './chat/chatSelectors'; export * from './subscriptions/subscriptionSelectors'; +export * from './message/messageSelectors'; export * from './nav/navSelectors'; export * from './nav/navigationSelectors'; export * from './title/titleSelectors';