Chore: Hooks - migrate RoomHeader to hook (#4200)

* roomHeader hook

* minor tweak

* Fix ts stuffs

* fix colors

* refactor
This commit is contained in:
Reinaldo Neto 2022-06-13 17:16:20 -03:00 committed by GitHub
parent 74a82974f0
commit a16c271f1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 78 additions and 151 deletions

View File

@ -8,6 +8,7 @@ import Header from '../Header';
import { longText } from '../../../storybook/utils'; import { longText } from '../../../storybook/utils';
import { ThemeContext } from '../../theme'; import { ThemeContext } from '../../theme';
import { store } from '../../../storybook/stories'; import { store } from '../../../storybook/stories';
import { colors } from '../../lib/constants';
import RoomHeaderComponent from './RoomHeader'; import RoomHeaderComponent from './RoomHeader';
const stories = storiesOf('RoomHeader', module).addDecorator(story => <Provider store={store}>{story()}</Provider>); const stories = storiesOf('RoomHeader', module).addDecorator(story => <Provider store={store}>{story()}</Provider>);
@ -82,7 +83,7 @@ stories.add('thread', () => (
)); ));
const ThemeStory = ({ theme }) => ( const ThemeStory = ({ theme }) => (
<ThemeContext.Provider value={{ theme }}> <ThemeContext.Provider value={{ theme, colors: colors[theme] }}>
<HeaderExample title={() => <RoomHeader subtitle='subtitle' />} /> <HeaderExample title={() => <RoomHeader subtitle='subtitle' />} />
</ThemeContext.Provider> </ThemeContext.Provider>
); );

View File

@ -3,7 +3,6 @@ import { StyleSheet, Text, TouchableOpacity, View } from 'react-native';
import I18n from '../../i18n'; import I18n from '../../i18n';
import sharedStyles from '../../views/Styles'; import sharedStyles from '../../views/Styles';
import { themes } from '../../lib/constants';
import { MarkdownPreview } from '../markdown'; import { MarkdownPreview } from '../markdown';
import RoomTypeIcon from '../RoomTypeIcon'; import RoomTypeIcon from '../RoomTypeIcon';
import { TUserStatus, IOmnichannelSource } from '../../definitions'; import { TUserStatus, IOmnichannelSource } from '../../definitions';
@ -44,39 +43,39 @@ const styles = StyleSheet.create({
type TRoomHeaderSubTitle = { type TRoomHeaderSubTitle = {
usersTyping: []; usersTyping: [];
subtitle: string; subtitle?: string;
renderFunc?: () => React.ReactElement; renderFunc?: () => React.ReactElement;
scale: number; scale: number;
}; };
type TRoomHeaderHeaderTitle = { type TRoomHeaderHeaderTitle = {
title: string; title?: string;
tmid: string; tmid?: string;
prid: string; prid?: string;
scale: number; scale: number;
testID: string; testID?: string;
}; };
interface IRoomHeader { interface IRoomHeader {
title: string; title?: string;
subtitle: string; subtitle?: string;
type: string; type: string;
width: number; width: number;
height: number; height: number;
prid: string; prid?: string;
tmid: string; tmid?: string;
teamMain: boolean; teamMain?: boolean;
status: TUserStatus; status: TUserStatus;
usersTyping: []; usersTyping: [];
isGroupChat: boolean; isGroupChat?: boolean;
parentTitle: string; parentTitle?: string;
onPress: () => void; onPress: Function;
testID: string; testID?: string;
sourceType?: IOmnichannelSource; sourceType?: IOmnichannelSource;
} }
const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoomHeaderSubTitle) => { const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoomHeaderSubTitle) => {
const { theme } = useTheme(); const { colors } = useTheme();
const fontSize = getSubTitleSize(scale); const fontSize = getSubTitleSize(scale);
// typing // typing
if (usersTyping.length) { if (usersTyping.length) {
@ -87,7 +86,7 @@ const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoom
usersText = usersTyping.join(', '); usersText = usersTyping.join(', ');
} }
return ( return (
<Text style={[styles.subtitle, { fontSize, color: themes[theme].auxiliaryText }]} numberOfLines={1}> <Text style={[styles.subtitle, { fontSize, color: colors.auxiliaryText }]} numberOfLines={1}>
<Text style={styles.typingUsers}>{usersText} </Text> <Text style={styles.typingUsers}>{usersText} </Text>
{usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing')}... {usersTyping.length > 1 ? I18n.t('are_typing') : I18n.t('is_typing')}...
</Text> </Text>
@ -101,15 +100,15 @@ const SubTitle = React.memo(({ usersTyping, subtitle, renderFunc, scale }: TRoom
// subtitle // subtitle
if (subtitle) { if (subtitle) {
return <MarkdownPreview msg={subtitle} style={[styles.subtitle, { fontSize, color: themes[theme].auxiliaryText }]} />; return <MarkdownPreview msg={subtitle} style={[styles.subtitle, { fontSize, color: colors.auxiliaryText }]} />;
} }
return null; return null;
}); });
const HeaderTitle = React.memo(({ title, tmid, prid, scale, testID }: TRoomHeaderHeaderTitle) => { const HeaderTitle = React.memo(({ title, tmid, prid, scale, testID }: TRoomHeaderHeaderTitle) => {
const { theme } = useTheme(); const { colors } = useTheme();
const titleStyle = { fontSize: TITLE_SIZE * scale, color: themes[theme].headerTitleColor }; const titleStyle = { fontSize: TITLE_SIZE * scale, color: colors.headerTitleColor };
if (!tmid && !prid) { if (!tmid && !prid) {
return ( return (
<Text style={[styles.title, titleStyle]} numberOfLines={1} testID={testID}> <Text style={[styles.title, titleStyle]} numberOfLines={1} testID={testID}>
@ -139,7 +138,7 @@ const Header = React.memo(
usersTyping = [], usersTyping = [],
sourceType sourceType
}: IRoomHeader) => { }: IRoomHeader) => {
const { theme } = useTheme(); const { colors } = useTheme();
const portrait = height > width; const portrait = height > width;
let scale = 1; let scale = 1;
@ -154,7 +153,7 @@ const Header = React.memo(
renderFunc = () => ( renderFunc = () => (
<View style={styles.titleContainer}> <View style={styles.titleContainer}>
<RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} /> <RoomTypeIcon type={prid ? 'discussion' : type} isGroupChat={isGroupChat} status={status} teamMain={teamMain} />
<Text style={[styles.subtitle, { color: themes[theme].auxiliaryText }]} numberOfLines={1}> <Text style={[styles.subtitle, { color: colors.auxiliaryText }]} numberOfLines={1}>
{parentTitle} {parentTitle}
</Text> </Text>
</View> </View>

View File

@ -1,117 +1,56 @@
import { dequal } from 'dequal'; import React from 'react';
import React, { Component } from 'react'; import { shallowEqual, useSelector } from 'react-redux';
import { connect } from 'react-redux';
import { IApplicationState, TUserStatus, IOmnichannelSource } from '../../definitions'; import { IApplicationState, TUserStatus, IOmnichannelSource, IVisitor } from '../../definitions';
import { withDimensions } from '../../dimensions'; import { useDimensions } from '../../dimensions';
import I18n from '../../i18n'; import I18n from '../../i18n';
import RoomHeader from './RoomHeader'; import RoomHeader from './RoomHeader';
interface IRoomHeaderContainerProps { interface IRoomHeaderContainerProps {
title: string; title?: string;
subtitle: string; subtitle?: string;
type: string; type: string;
prid: string; prid?: string;
tmid: string; tmid?: string;
teamMain: boolean; teamMain?: boolean;
usersTyping: []; roomUserId?: string | null;
status: TUserStatus; onPress: Function;
statusText: string; parentTitle?: string;
connecting: boolean; isGroupChat?: boolean;
connected: boolean; testID?: string;
roomUserId: string;
widthOffset: number;
onPress(): void;
width: number;
height: number;
parentTitle: string;
isGroupChat: boolean;
testID: string;
sourceType?: IOmnichannelSource; sourceType?: IOmnichannelSource;
visitor?: IVisitor;
} }
class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> { const RoomHeaderContainer = React.memo(
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;
}
render() {
const {
title,
subtitle: subtitleProp,
type,
teamMain,
prid,
tmid,
status = 'offline',
statusText,
connecting,
connected,
usersTyping,
onPress,
width,
height,
parentTitle,
isGroupChat, isGroupChat,
onPress,
parentTitle,
prid,
roomUserId,
subtitle: subtitleProp,
teamMain,
testID, testID,
sourceType title,
} = this.props; tmid,
type,
sourceType,
visitor
}: IRoomHeaderContainerProps) => {
let subtitle: string | undefined;
let status: TUserStatus = 'offline';
let statusText: string | undefined;
const { width, height } = useDimensions();
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) { if (connecting) {
subtitle = I18n.t('Connecting'); subtitle = I18n.t('Connecting');
} else if (!connected) { } else if (!connected) {
@ -120,6 +59,17 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
subtitle = subtitleProp; 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 ( return (
<RoomHeader <RoomHeader
prid={prid} prid={prid}
@ -140,28 +90,6 @@ class RoomHeaderContainer extends Component<IRoomHeaderContainerProps, any> {
/> />
); );
} }
} );
const mapStateToProps = (state: IApplicationState, ownProps: any) => { export default RoomHeaderContainer;
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));

View File

@ -624,7 +624,6 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
), ),
headerTitle: () => ( headerTitle: () => (
<RoomHeader <RoomHeader
rid={rid}
prid={prid} prid={prid}
tmid={tmid} tmid={tmid}
title={title} title={title}