diff --git a/app/containers/RoomHeader/RoomHeader.stories.js b/app/containers/RoomHeader/RoomHeader.stories.js index 00651b2af..de2a724e6 100644 --- a/app/containers/RoomHeader/RoomHeader.stories.js +++ b/app/containers/RoomHeader/RoomHeader.stories.js @@ -8,6 +8,7 @@ import Header from '../Header'; import { longText } from '../../../storybook/utils'; import { ThemeContext } from '../../theme'; import { store } from '../../../storybook/stories'; +import { colors } from '../../lib/constants'; import RoomHeaderComponent from './RoomHeader'; const stories = storiesOf('RoomHeader', module).addDecorator(story => {story()}); @@ -82,7 +83,7 @@ stories.add('thread', () => ( )); const ThemeStory = ({ theme }) => ( - + } /> ); diff --git a/app/containers/RoomHeader/RoomHeader.tsx b/app/containers/RoomHeader/RoomHeader.tsx index 60d7c47a3..5da6d50b7 100644 --- a/app/containers/RoomHeader/RoomHeader.tsx +++ b/app/containers/RoomHeader/RoomHeader.tsx @@ -3,7 +3,6 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native'; import I18n from '../../i18n'; import sharedStyles from '../../views/Styles'; -import { themes } from '../../lib/constants'; import { MarkdownPreview } from '../markdown'; import RoomTypeIcon from '../RoomTypeIcon'; import { TUserStatus, IOmnichannelSource } from '../../definitions'; @@ -44,39 +43,39 @@ const styles = StyleSheet.create({ type TRoomHeaderSubTitle = { usersTyping: []; - subtitle: string; + subtitle?: string; renderFunc?: () => React.ReactElement; scale: number; }; type TRoomHeaderHeaderTitle = { - title: string; - tmid: string; - prid: string; + title?: string; + tmid?: string; + prid?: string; scale: number; - testID: string; + testID?: string; }; interface IRoomHeader { - title: string; - subtitle: string; + title?: string; + subtitle?: string; type: string; width: number; height: number; - prid: string; - tmid: string; - teamMain: boolean; + prid?: string; + tmid?: string; + teamMain?: boolean; status: TUserStatus; usersTyping: []; - isGroupChat: boolean; - parentTitle: string; - onPress: () => void; - testID: string; + isGroupChat?: boolean; + parentTitle?: string; + onPress: Function; + testID?: string; sourceType?: IOmnichannelSource; } const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoomHeaderSubTitle) => { - const { theme } = useTheme(); + const { colors } = useTheme(); const fontSize = getSubTitleSize(scale); // typing if (usersTyping.length) { @@ -87,7 +86,7 @@ const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoom usersText = usersTyping.join(', '); } return ( - + {usersText} {usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing')}... @@ -101,15 +100,15 @@ const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoom // subtitle if (subtitle) { - return ; + return ; } return null; }); const HeaderTitle = React.memo(({ title, tmid, prid, scale, testID }: TRoomHeaderHeaderTitle) => { - const { theme } = useTheme(); - const titleStyle = { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor }; + const { colors } = useTheme(); + const titleStyle = { fontSize: TITLE_SIZE * scale, color: colors.headerTitleColor }; if (!tmid && !prid) { return ( @@ -139,7 +138,7 @@ const Header = React.memo( usersTyping = [], sourceType }: IRoomHeader) => { - const { theme } = useTheme(); + const { colors } = useTheme(); const portrait = height > width; let scale = 1; @@ -154,7 +153,7 @@ const Header = React.memo( renderFunc = () => ( - + {parentTitle} diff --git a/app/containers/RoomHeader/index.tsx b/app/containers/RoomHeader/index.tsx index 8d5f5c625..6fb57f770 100644 --- a/app/containers/RoomHeader/index.tsx +++ b/app/containers/RoomHeader/index.tsx @@ -1,117 +1,56 @@ -import { dequal } from 'dequal'; -import React, { Component } from 'react'; -import { connect } from 'react-redux'; +import React from 'react'; +import { shallowEqual, useSelector } from 'react-redux'; -import { IApplicationState, TUserStatus, IOmnichannelSource } from '../../definitions'; -import { withDimensions } from '../../dimensions'; +import { IApplicationState, TUserStatus, IOmnichannelSource, IVisitor } from '../../definitions'; +import { useDimensions } from '../../dimensions'; import I18n from '../../i18n'; import RoomHeader from './RoomHeader'; interface IRoomHeaderContainerProps { - title: string; - subtitle: string; + title?: string; + subtitle?: string; type: string; - prid: string; - tmid: string; - teamMain: boolean; - usersTyping: []; - status: TUserStatus; - statusText: string; - connecting: boolean; - connected: boolean; - roomUserId: string; - widthOffset: number; - onPress(): void; - width: number; - height: number; - parentTitle: string; - isGroupChat: boolean; - testID: string; + prid?: string; + tmid?: string; + teamMain?: boolean; + roomUserId?: string | null; + onPress: Function; + parentTitle?: string; + isGroupChat?: boolean; + testID?: string; sourceType?: IOmnichannelSource; + visitor?: IVisitor; } -class RoomHeaderContainer extends Component { - shouldComponentUpdate(nextProps: IRoomHeaderContainerProps) { - const { - type, - title, - subtitle, - status, - statusText, - connecting, - connected, - onPress, - usersTyping, - width, - height, - teamMain, - sourceType - } = this.props; - if (nextProps.type !== type) { - return true; - } - if (nextProps.title !== title) { - return true; - } - if (nextProps.subtitle !== subtitle) { - return true; - } - if (nextProps.status !== status) { - return true; - } - if (nextProps.statusText !== statusText) { - return true; - } - if (nextProps.connecting !== connecting) { - return true; - } - if (nextProps.connected !== connected) { - return true; - } - if (nextProps.width !== width) { - return true; - } - if (nextProps.height !== height) { - return true; - } - if (!dequal(nextProps.usersTyping, usersTyping)) { - return true; - } - if (!dequal(nextProps.sourceType, sourceType)) { - return true; - } - if (nextProps.onPress !== onPress) { - return true; - } - if (nextProps.teamMain !== teamMain) { - return true; - } - return false; - } +const RoomHeaderContainer = React.memo( + ({ + isGroupChat, + onPress, + parentTitle, + prid, + roomUserId, + subtitle: subtitleProp, + teamMain, + testID, + title, + tmid, + type, + sourceType, + visitor + }: IRoomHeaderContainerProps) => { + let subtitle: string | undefined; + let status: TUserStatus = 'offline'; + let statusText: string | undefined; + const { width, height } = useDimensions(); - render() { - const { - title, - subtitle: subtitleProp, - type, - teamMain, - prid, - tmid, - status = 'offline', - statusText, - connecting, - connected, - usersTyping, - onPress, - width, - height, - parentTitle, - isGroupChat, - testID, - sourceType - } = this.props; + const connecting = useSelector((state: IApplicationState) => state.meteor.connecting || state.server.loading); + const usersTyping = useSelector((state: IApplicationState) => state.usersTyping, shallowEqual); + const connected = useSelector((state: IApplicationState) => state.meteor.connected); + const activeUser = useSelector( + (state: IApplicationState) => (roomUserId ? state.activeUsers?.[roomUserId] : undefined), + shallowEqual + ); - let subtitle; if (connecting) { subtitle = I18n.t('Connecting'); } else if (!connected) { @@ -120,6 +59,17 @@ class RoomHeaderContainer extends Component { subtitle = subtitleProp; } + if (connected) { + if ((type === 'd' || (tmid && roomUserId)) && activeUser) { + const { status: statusActiveUser, statusText: statusTextActiveUser } = activeUser; + status = statusActiveUser; + statusText = statusTextActiveUser; + } else if (type === 'l' && visitor?.status) { + const { status: statusVisitor } = visitor; + status = statusVisitor; + } + } + return ( { /> ); } -} +); -const mapStateToProps = (state: IApplicationState, ownProps: any) => { - let statusText = ''; - let status = 'offline'; - const { roomUserId, type, visitor = {}, tmid } = ownProps; - - if (state.meteor.connected) { - if ((type === 'd' || (tmid && roomUserId)) && state.activeUsers[roomUserId]) { - ({ status, statusText } = state.activeUsers[roomUserId]); - } else if (type === 'l' && visitor?.status) { - ({ status } = visitor); - } - } - - return { - connecting: state.meteor.connecting || state.server.loading, - connected: state.meteor.connected, - usersTyping: state.usersTyping, - status: status as TUserStatus, - statusText - }; -}; - -export default connect(mapStateToProps)(withDimensions(RoomHeaderContainer)); +export default RoomHeaderContainer; diff --git a/app/views/RoomView/index.tsx b/app/views/RoomView/index.tsx index 4fa3805ca..6a91f116e 100644 --- a/app/views/RoomView/index.tsx +++ b/app/views/RoomView/index.tsx @@ -624,7 +624,6 @@ class RoomView extends React.Component { ), headerTitle: () => (