Chore: Migrate RoomItem to Hooks (#4310)
* migrate roomItem to ts and fix some types * remove unnecessary verification * fix types * fix SubscriptionType * review * remove theme prop driling and change file to tsx * Fix component not re-rendering * Remove a few props from attrs * Remove accessibilityLabel state * Fix propsAreEqual * Fix cleanup * Remove ts-ignore Co-authored-by: Diego Mello <diegolmello@gmail.com>
This commit is contained in:
parent
4b25fde8f6
commit
674f0285f6
|
@ -1,11 +1,11 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import Avatar from '../Avatar';
|
import Avatar from '../Avatar';
|
||||||
import { DisplayMode } from '../../lib/constants';
|
import { DisplayMode } from '../../lib/constants';
|
||||||
import TypeIcon from './TypeIcon';
|
import TypeIcon from './TypeIcon';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
import { IIconOrAvatar } from './interfaces';
|
||||||
|
|
||||||
const IconOrAvatar = ({
|
const IconOrAvatar = ({
|
||||||
avatar,
|
avatar,
|
||||||
|
@ -17,10 +17,9 @@ const IconOrAvatar = ({
|
||||||
isGroupChat,
|
isGroupChat,
|
||||||
teamMain,
|
teamMain,
|
||||||
showLastMessage,
|
showLastMessage,
|
||||||
theme,
|
|
||||||
displayMode,
|
displayMode,
|
||||||
sourceType
|
sourceType
|
||||||
}) => {
|
}: IIconOrAvatar): React.ReactElement | null => {
|
||||||
if (showAvatar) {
|
if (showAvatar) {
|
||||||
return (
|
return (
|
||||||
<Avatar text={avatar} size={displayMode === DisplayMode.Condensed ? 36 : 48} type={type} style={styles.avatar} rid={rid} />
|
<Avatar text={avatar} size={displayMode === DisplayMode.Condensed ? 36 : 48} type={type} style={styles.avatar} rid={rid} />
|
||||||
|
@ -35,7 +34,6 @@ const IconOrAvatar = ({
|
||||||
prid={prid}
|
prid={prid}
|
||||||
status={status}
|
status={status}
|
||||||
isGroupChat={isGroupChat}
|
isGroupChat={isGroupChat}
|
||||||
theme={theme}
|
|
||||||
teamMain={teamMain}
|
teamMain={teamMain}
|
||||||
size={24}
|
size={24}
|
||||||
style={{ marginRight: 12 }}
|
style={{ marginRight: 12 }}
|
||||||
|
@ -48,18 +46,4 @@ const IconOrAvatar = ({
|
||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
IconOrAvatar.propTypes = {
|
|
||||||
avatar: PropTypes.string,
|
|
||||||
type: PropTypes.string,
|
|
||||||
theme: PropTypes.string,
|
|
||||||
rid: PropTypes.string,
|
|
||||||
showAvatar: PropTypes.bool,
|
|
||||||
displayMode: PropTypes.string,
|
|
||||||
prid: PropTypes.string,
|
|
||||||
status: PropTypes.string,
|
|
||||||
isGroupChat: PropTypes.bool,
|
|
||||||
teamMain: PropTypes.bool,
|
|
||||||
showLastMessage: PropTypes.bool
|
|
||||||
};
|
|
||||||
|
|
||||||
export default IconOrAvatar;
|
export default IconOrAvatar;
|
|
@ -4,8 +4,9 @@ import { dequal } from 'dequal';
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { MarkdownPreview } from '../markdown';
|
import { MarkdownPreview } from '../markdown';
|
||||||
import { E2E_MESSAGE_TYPE, E2E_STATUS, themes } from '../../lib/constants';
|
import { E2E_MESSAGE_TYPE, E2E_STATUS } from '../../lib/constants';
|
||||||
import { ILastMessageProps } from './interfaces';
|
import { ILastMessageProps } from './interfaces';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
|
|
||||||
const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }: Partial<ILastMessageProps>) => {
|
const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }: Partial<ILastMessageProps>) => {
|
||||||
if (!showLastMessage) {
|
if (!showLastMessage) {
|
||||||
|
@ -46,8 +47,9 @@ const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }
|
||||||
|
|
||||||
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
|
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
|
||||||
|
|
||||||
const LastMessage = React.memo(
|
const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
|
||||||
({ lastMessage, type, showLastMessage, username, alert, useRealName, theme }: ILastMessageProps) => (
|
const { colors } = useTheme();
|
||||||
|
return (
|
||||||
<MarkdownPreview
|
<MarkdownPreview
|
||||||
msg={formatMsg({
|
msg={formatMsg({
|
||||||
lastMessage,
|
lastMessage,
|
||||||
|
@ -56,12 +58,11 @@ const LastMessage = React.memo(
|
||||||
username,
|
username,
|
||||||
useRealName
|
useRealName
|
||||||
})}
|
})}
|
||||||
style={[styles.markdownText, { color: alert ? themes[theme].bodyText : themes[theme].auxiliaryText }]}
|
style={[styles.markdownText, { color: alert ? colors.bodyText : colors.auxiliaryText }]}
|
||||||
numberOfLines={2}
|
numberOfLines={2}
|
||||||
testID='room-item-last-message'
|
testID='room-item-last-message'
|
||||||
/>
|
/>
|
||||||
),
|
);
|
||||||
arePropsEqual
|
}, arePropsEqual);
|
||||||
);
|
|
||||||
|
|
||||||
export default LastMessage;
|
export default LastMessage;
|
||||||
|
|
|
@ -25,7 +25,6 @@ const RoomItem = ({
|
||||||
showLastMessage,
|
showLastMessage,
|
||||||
status = 'offline',
|
status = 'offline',
|
||||||
useRealName,
|
useRealName,
|
||||||
theme,
|
|
||||||
isFocused,
|
isFocused,
|
||||||
isGroupChat,
|
isGroupChat,
|
||||||
isRead,
|
isRead,
|
||||||
|
@ -67,14 +66,13 @@ const RoomItem = ({
|
||||||
hideChannel={hideChannel}
|
hideChannel={hideChannel}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
type={type}
|
type={type}
|
||||||
isFocused={isFocused}
|
isFocused={!!isFocused}
|
||||||
swipeEnabled={swipeEnabled}
|
swipeEnabled={swipeEnabled}
|
||||||
displayMode={displayMode}>
|
displayMode={displayMode}>
|
||||||
<Wrapper
|
<Wrapper
|
||||||
accessibilityLabel={accessibilityLabel}
|
accessibilityLabel={accessibilityLabel}
|
||||||
avatar={avatar}
|
avatar={avatar}
|
||||||
type={type}
|
type={type}
|
||||||
theme={theme}
|
|
||||||
rid={rid}
|
rid={rid}
|
||||||
prid={prid}
|
prid={prid}
|
||||||
status={status}
|
status={status}
|
||||||
|
@ -82,7 +80,7 @@ const RoomItem = ({
|
||||||
teamMain={teamMain}
|
teamMain={teamMain}
|
||||||
displayMode={displayMode}
|
displayMode={displayMode}
|
||||||
showAvatar={showAvatar}
|
showAvatar={showAvatar}
|
||||||
showLastMessage={showLastMessage}
|
showLastMessage={!!showLastMessage}
|
||||||
sourceType={sourceType}>
|
sourceType={sourceType}>
|
||||||
{showLastMessage && displayMode === DisplayMode.Expanded ? (
|
{showLastMessage && displayMode === DisplayMode.Expanded ? (
|
||||||
<>
|
<>
|
||||||
|
@ -97,19 +95,18 @@ const RoomItem = ({
|
||||||
sourceType={sourceType}
|
sourceType={sourceType}
|
||||||
/>
|
/>
|
||||||
) : null}
|
) : null}
|
||||||
<Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
<Title name={name} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
||||||
{autoJoin ? <Tag testID='auto-join-tag' name={I18n.t('Auto-join')} /> : null}
|
{autoJoin ? <Tag testID='auto-join-tag' name={I18n.t('Auto-join')} /> : null}
|
||||||
<UpdatedAt date={date} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
<UpdatedAt date={date} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
||||||
</View>
|
</View>
|
||||||
<View style={styles.row}>
|
<View style={styles.row}>
|
||||||
<LastMessage
|
<LastMessage
|
||||||
lastMessage={lastMessage}
|
lastMessage={lastMessage}
|
||||||
type={type}
|
type={type}
|
||||||
showLastMessage={showLastMessage}
|
showLastMessage={showLastMessage}
|
||||||
username={username}
|
username={username || ''}
|
||||||
alert={alert && !hideUnreadStatus}
|
alert={alert && !hideUnreadStatus}
|
||||||
useRealName={useRealName}
|
useRealName={useRealName}
|
||||||
theme={theme}
|
|
||||||
/>
|
/>
|
||||||
<UnreadBadge
|
<UnreadBadge
|
||||||
unread={unread}
|
unread={unread}
|
||||||
|
@ -135,10 +132,10 @@ const RoomItem = ({
|
||||||
style={{ marginRight: 8 }}
|
style={{ marginRight: 8 }}
|
||||||
sourceType={sourceType}
|
sourceType={sourceType}
|
||||||
/>
|
/>
|
||||||
<Title name={name} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
<Title name={name} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
||||||
{autoJoin ? <Tag name={I18n.t('Auto-join')} /> : null}
|
{autoJoin ? <Tag name={I18n.t('Auto-join')} /> : null}
|
||||||
<View style={styles.wrapUpdatedAndBadge}>
|
<View style={styles.wrapUpdatedAndBadge}>
|
||||||
<UpdatedAt date={date} theme={theme} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
<UpdatedAt date={date} hideUnreadStatus={hideUnreadStatus} alert={alert} />
|
||||||
<UnreadBadge
|
<UnreadBadge
|
||||||
unread={unread}
|
unread={unread}
|
||||||
userMentions={userMentions}
|
userMentions={userMentions}
|
||||||
|
|
|
@ -2,16 +2,19 @@ import React from 'react';
|
||||||
import { Text } from 'react-native';
|
import { Text } from 'react-native';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { themes } from '../../lib/constants';
|
|
||||||
import { ITitleProps } from './interfaces';
|
import { ITitleProps } from './interfaces';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
|
|
||||||
const Title = React.memo(({ name, theme, hideUnreadStatus, alert }: ITitleProps) => (
|
const Title = React.memo(({ name, hideUnreadStatus, alert }: ITitleProps) => {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
return (
|
||||||
<Text
|
<Text
|
||||||
style={[styles.title, alert && !hideUnreadStatus && styles.alert, { color: themes[theme].titleText }]}
|
style={[styles.title, alert && !hideUnreadStatus && styles.alert, { color: colors.titleText }]}
|
||||||
ellipsizeMode='tail'
|
ellipsizeMode='tail'
|
||||||
numberOfLines={1}>
|
numberOfLines={1}>
|
||||||
{name}
|
{name}
|
||||||
</Text>
|
</Text>
|
||||||
));
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export default Title;
|
export default Title;
|
||||||
|
|
|
@ -2,11 +2,13 @@ import React from 'react';
|
||||||
import { Text } from 'react-native';
|
import { Text } from 'react-native';
|
||||||
|
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import { themes } from '../../lib/constants';
|
|
||||||
import { capitalize } from '../../lib/methods/helpers/room';
|
import { capitalize } from '../../lib/methods/helpers/room';
|
||||||
import { IUpdatedAtProps } from './interfaces';
|
import { IUpdatedAtProps } from './interfaces';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
|
|
||||||
|
const UpdatedAt = React.memo(({ date, hideUnreadStatus, alert }: IUpdatedAtProps) => {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
|
||||||
const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdatedAtProps) => {
|
|
||||||
if (!date) {
|
if (!date) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -15,13 +17,13 @@ const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdated
|
||||||
style={[
|
style={[
|
||||||
styles.date,
|
styles.date,
|
||||||
{
|
{
|
||||||
color: themes[theme].auxiliaryText
|
color: colors.auxiliaryText
|
||||||
},
|
},
|
||||||
alert &&
|
alert &&
|
||||||
!hideUnreadStatus && [
|
!hideUnreadStatus && [
|
||||||
styles.updateAlert,
|
styles.updateAlert,
|
||||||
{
|
{
|
||||||
color: themes[theme].tintColor
|
color: colors.tintColor
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]}
|
]}
|
||||||
|
|
|
@ -1,26 +1,30 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
|
|
||||||
import { DisplayMode, themes } from '../../lib/constants';
|
import { DisplayMode } from '../../lib/constants';
|
||||||
|
import { useTheme } from '../../theme';
|
||||||
import IconOrAvatar from './IconOrAvatar';
|
import IconOrAvatar from './IconOrAvatar';
|
||||||
import { IWrapperProps } from './interfaces';
|
import { IWrapperProps } from './interfaces';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
|
|
||||||
const Wrapper = ({ accessibilityLabel, theme, children, displayMode, ...props }: IWrapperProps): React.ReactElement => (
|
const Wrapper = ({ accessibilityLabel, children, displayMode, ...props }: IWrapperProps): React.ReactElement => {
|
||||||
|
const { colors } = useTheme();
|
||||||
|
return (
|
||||||
<View
|
<View
|
||||||
style={[styles.container, displayMode === DisplayMode.Condensed && styles.containerCondensed]}
|
style={[styles.container, displayMode === DisplayMode.Condensed && styles.containerCondensed]}
|
||||||
accessibilityLabel={accessibilityLabel}>
|
accessibilityLabel={accessibilityLabel}>
|
||||||
<IconOrAvatar theme={theme} displayMode={displayMode} {...props} />
|
<IconOrAvatar displayMode={displayMode} {...props} />
|
||||||
<View
|
<View
|
||||||
style={[
|
style={[
|
||||||
styles.centerContainer,
|
styles.centerContainer,
|
||||||
{
|
{
|
||||||
borderColor: themes[theme].separatorColor
|
borderColor: colors.separatorColor
|
||||||
}
|
}
|
||||||
]}>
|
]}>
|
||||||
{children}
|
{children}
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export default Wrapper;
|
export default Wrapper;
|
||||||
|
|
|
@ -1,171 +1,111 @@
|
||||||
import React from 'react';
|
import React, { useEffect, useReducer, useRef } from 'react';
|
||||||
import { connect } from 'react-redux';
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
import I18n from '../../i18n';
|
import I18n from '../../i18n';
|
||||||
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
|
import { useAppSelector } from '../../lib/hooks';
|
||||||
|
import { getUserPresence } from '../../lib/methods';
|
||||||
|
import { isGroupChat } from '../../lib/methods/helpers';
|
||||||
import { formatDate } from '../../lib/methods/helpers/room';
|
import { formatDate } from '../../lib/methods/helpers/room';
|
||||||
import RoomItem from './RoomItem';
|
|
||||||
import { ISubscription, TUserStatus } from '../../definitions';
|
|
||||||
import { IRoomItemContainerProps } from './interfaces';
|
import { IRoomItemContainerProps } from './interfaces';
|
||||||
|
import RoomItem from './RoomItem';
|
||||||
|
import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
|
||||||
|
|
||||||
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
|
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
|
||||||
|
|
||||||
const attrs = [
|
const attrs = ['width', 'isFocused', 'showLastMessage', 'autoJoin', 'showAvatar', 'displayMode'];
|
||||||
'width',
|
|
||||||
'status',
|
|
||||||
'connected',
|
|
||||||
'theme',
|
|
||||||
'isFocused',
|
|
||||||
'forceUpdate',
|
|
||||||
'showLastMessage',
|
|
||||||
'autoJoin',
|
|
||||||
'showAvatar',
|
|
||||||
'displayMode'
|
|
||||||
];
|
|
||||||
|
|
||||||
class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
|
const RoomItemContainer = React.memo(
|
||||||
private roomSubscription: ISubscription | undefined;
|
({
|
||||||
|
|
||||||
static defaultProps: Partial<IRoomItemContainerProps> = {
|
|
||||||
status: 'offline',
|
|
||||||
getUserPresence: () => {},
|
|
||||||
getRoomTitle: () => 'title',
|
|
||||||
getRoomAvatar: () => '',
|
|
||||||
getIsGroupChat: () => false,
|
|
||||||
getIsRead: () => false,
|
|
||||||
swipeEnabled: true
|
|
||||||
};
|
|
||||||
|
|
||||||
constructor(props: IRoomItemContainerProps) {
|
|
||||||
super(props);
|
|
||||||
this.init();
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidMount() {
|
|
||||||
const { connected, getUserPresence, id } = this.props;
|
|
||||||
if (connected && this.isDirect) {
|
|
||||||
getUserPresence(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldComponentUpdate(nextProps: IRoomItemContainerProps) {
|
|
||||||
const { props } = this;
|
|
||||||
return !attrs.every(key => props[key] === nextProps[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
componentDidUpdate(prevProps: IRoomItemContainerProps) {
|
|
||||||
const { connected, getUserPresence, id } = this.props;
|
|
||||||
if (prevProps.connected !== connected && connected && this.isDirect) {
|
|
||||||
getUserPresence(id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount() {
|
|
||||||
if (this.roomSubscription?.unsubscribe) {
|
|
||||||
this.roomSubscription.unsubscribe();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
get isGroupChat() {
|
|
||||||
const { item, getIsGroupChat } = this.props;
|
|
||||||
return getIsGroupChat(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
get isDirect() {
|
|
||||||
const {
|
|
||||||
item: { t },
|
|
||||||
id
|
|
||||||
} = this.props;
|
|
||||||
return t === 'd' && id && !this.isGroupChat;
|
|
||||||
}
|
|
||||||
|
|
||||||
init = () => {
|
|
||||||
const { item } = this.props;
|
|
||||||
if (item?.observe) {
|
|
||||||
const observable = item.observe();
|
|
||||||
this.roomSubscription = observable?.subscribe?.(() => {
|
|
||||||
this.forceUpdate();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onPress = () => {
|
|
||||||
const { item, onPress } = this.props;
|
|
||||||
return onPress(item);
|
|
||||||
};
|
|
||||||
|
|
||||||
onLongPress = () => {
|
|
||||||
const { item, onLongPress } = this.props;
|
|
||||||
if (onLongPress) {
|
|
||||||
return onLongPress(item);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const {
|
|
||||||
item,
|
item,
|
||||||
getRoomTitle,
|
id,
|
||||||
getRoomAvatar,
|
onPress,
|
||||||
getIsRead,
|
onLongPress,
|
||||||
width,
|
width,
|
||||||
toggleFav,
|
toggleFav,
|
||||||
toggleRead,
|
toggleRead,
|
||||||
hideChannel,
|
hideChannel,
|
||||||
theme,
|
|
||||||
isFocused,
|
isFocused,
|
||||||
status,
|
|
||||||
showLastMessage,
|
showLastMessage,
|
||||||
username,
|
username,
|
||||||
useRealName,
|
useRealName,
|
||||||
swipeEnabled,
|
|
||||||
autoJoin,
|
autoJoin,
|
||||||
showAvatar,
|
showAvatar,
|
||||||
displayMode
|
displayMode,
|
||||||
} = this.props;
|
getRoomTitle = () => 'title',
|
||||||
|
getRoomAvatar = () => '',
|
||||||
|
getIsRead = () => false,
|
||||||
|
swipeEnabled = true
|
||||||
|
}: IRoomItemContainerProps) => {
|
||||||
const name = getRoomTitle(item);
|
const name = getRoomTitle(item);
|
||||||
const testID = `rooms-list-view-item-${name}`;
|
const testID = `rooms-list-view-item-${name}`;
|
||||||
const avatar = getRoomAvatar(item);
|
const avatar = getRoomAvatar(item);
|
||||||
const isRead = getIsRead(item);
|
const isRead = getIsRead(item);
|
||||||
const date = item.roomUpdatedAt && formatDate(item.roomUpdatedAt);
|
const date = item.roomUpdatedAt && formatDate(item.roomUpdatedAt);
|
||||||
const alert = item.alert || item.tunread?.length;
|
const alert = item.alert || item.tunread?.length;
|
||||||
|
const connected = useAppSelector(state => state.meteor.connected);
|
||||||
|
const userStatus = useAppSelector(state => state.activeUsers[id || '']?.status);
|
||||||
|
const [_, forceUpdate] = useReducer(x => x + 1, 1);
|
||||||
|
const roomSubscription = useRef<Subscription | null>(null);
|
||||||
|
|
||||||
let accessibilityLabel = name;
|
useEffect(() => {
|
||||||
|
const init = () => {
|
||||||
|
if (item?.observe) {
|
||||||
|
const observable = item.observe();
|
||||||
|
roomSubscription.current = observable?.subscribe?.(() => {
|
||||||
|
if (_) forceUpdate();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
init();
|
||||||
|
|
||||||
|
return () => roomSubscription.current?.unsubscribe();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const isDirect = !!(item.t === 'd' && id && !isGroupChat(item));
|
||||||
|
if (connected && isDirect) {
|
||||||
|
getUserPresence(id);
|
||||||
|
}
|
||||||
|
}, [connected]);
|
||||||
|
|
||||||
|
const handleOnPress = () => onPress(item);
|
||||||
|
|
||||||
|
const handleOnLongPress = () => onLongPress && onLongPress(item);
|
||||||
|
|
||||||
|
let accessibilityLabel = '';
|
||||||
if (item.unread === 1) {
|
if (item.unread === 1) {
|
||||||
accessibilityLabel += `, ${item.unread} ${I18n.t('alert')}`;
|
accessibilityLabel = `, ${item.unread} ${I18n.t('alert')}`;
|
||||||
} else if (item.unread > 1) {
|
} else if (item.unread > 1) {
|
||||||
accessibilityLabel += `, ${item.unread} ${I18n.t('alerts')}`;
|
accessibilityLabel = `, ${item.unread} ${I18n.t('alerts')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (item.userMentions > 0) {
|
if (item.userMentions > 0) {
|
||||||
accessibilityLabel += `, ${I18n.t('you_were_mentioned')}`;
|
accessibilityLabel = `, ${I18n.t('you_were_mentioned')}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (date) {
|
if (date) {
|
||||||
accessibilityLabel += `, ${I18n.t('last_message')} ${date}`;
|
accessibilityLabel = `, ${I18n.t('last_message')} ${date}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<RoomItem
|
<RoomItem
|
||||||
name={name}
|
name={name}
|
||||||
avatar={avatar}
|
avatar={avatar}
|
||||||
isGroupChat={this.isGroupChat}
|
isGroupChat={isGroupChat(item)}
|
||||||
isRead={isRead}
|
isRead={isRead}
|
||||||
onPress={this.onPress}
|
onPress={handleOnPress}
|
||||||
onLongPress={this.onLongPress}
|
onLongPress={handleOnLongPress}
|
||||||
date={date}
|
date={date}
|
||||||
accessibilityLabel={accessibilityLabel}
|
accessibilityLabel={accessibilityLabel}
|
||||||
width={width}
|
width={width}
|
||||||
favorite={item.f}
|
favorite={item.f}
|
||||||
toggleFav={toggleFav}
|
|
||||||
rid={item.rid}
|
rid={item.rid}
|
||||||
|
toggleFav={toggleFav}
|
||||||
toggleRead={toggleRead}
|
toggleRead={toggleRead}
|
||||||
hideChannel={hideChannel}
|
hideChannel={hideChannel}
|
||||||
testID={testID}
|
testID={testID}
|
||||||
type={item.t}
|
type={item.t}
|
||||||
theme={theme}
|
|
||||||
isFocused={isFocused}
|
isFocused={isFocused}
|
||||||
prid={item.prid}
|
prid={item.prid}
|
||||||
status={status}
|
status={userStatus}
|
||||||
hideUnreadStatus={item.hideUnreadStatus}
|
hideUnreadStatus={item.hideUnreadStatus}
|
||||||
hideMentionStatus={item.hideMentionStatus}
|
hideMentionStatus={item.hideMentionStatus}
|
||||||
alert={alert}
|
alert={alert}
|
||||||
|
@ -187,23 +127,8 @@ class RoomItemContainer extends React.Component<IRoomItemContainerProps, any> {
|
||||||
sourceType={item.source}
|
sourceType={item.source}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
}
|
(props, nextProps) => attrs.every(key => props[key] === nextProps[key])
|
||||||
|
);
|
||||||
|
|
||||||
const mapStateToProps = (state: any, ownProps: any) => {
|
export default RoomItemContainer;
|
||||||
let status = 'loading';
|
|
||||||
const { id, type, visitor = {} } = ownProps;
|
|
||||||
if (state.meteor.connected) {
|
|
||||||
if (type === 'd') {
|
|
||||||
status = state.activeUsers[id]?.status || 'loading';
|
|
||||||
} else if (type === 'l' && visitor?.status) {
|
|
||||||
({ status } = visitor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
connected: state.meteor.connected,
|
|
||||||
status: status as TUserStatus
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(RoomItemContainer);
|
|
||||||
|
|
|
@ -23,14 +23,12 @@ export interface IRightActionsProps {
|
||||||
|
|
||||||
export interface ITitleProps {
|
export interface ITitleProps {
|
||||||
name: string;
|
name: string;
|
||||||
theme: TSupportedThemes;
|
|
||||||
hideUnreadStatus: boolean;
|
hideUnreadStatus: boolean;
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUpdatedAtProps {
|
export interface IUpdatedAtProps {
|
||||||
date: string;
|
date: string;
|
||||||
theme: TSupportedThemes;
|
|
||||||
hideUnreadStatus: boolean;
|
hideUnreadStatus: boolean;
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
}
|
}
|
||||||
|
@ -39,13 +37,12 @@ export interface IWrapperProps {
|
||||||
accessibilityLabel: string;
|
accessibilityLabel: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
type: string;
|
type: string;
|
||||||
theme: TSupportedThemes;
|
|
||||||
rid: string;
|
rid: string;
|
||||||
children: React.ReactElement;
|
children: React.ReactElement;
|
||||||
displayMode: string;
|
displayMode: string;
|
||||||
prid: string;
|
prid: string;
|
||||||
showLastMessage: boolean;
|
showLastMessage: boolean;
|
||||||
status: string;
|
status: TUserStatus;
|
||||||
isGroupChat: boolean;
|
isGroupChat: boolean;
|
||||||
teamMain: boolean;
|
teamMain: boolean;
|
||||||
showAvatar: boolean;
|
showAvatar: boolean;
|
||||||
|
@ -64,48 +61,43 @@ export interface ITypeIconProps {
|
||||||
sourceType: IOmnichannelSource;
|
sourceType: IOmnichannelSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRoomItemContainerProps {
|
interface IRoomItemTouchables {
|
||||||
[key: string]: string | boolean | Function | number;
|
toggleFav?: (rid: string, favorite: boolean) => Promise<void>;
|
||||||
item: any;
|
toggleRead?: (rid: string, tIsRead: boolean) => Promise<void>;
|
||||||
showLastMessage: boolean;
|
hideChannel?: (rid: string, type: SubscriptionType) => Promise<void>;
|
||||||
id: string;
|
onPress: (item?: any) => void;
|
||||||
onPress: (item: any) => void;
|
onLongPress?: (item?: any) => void;
|
||||||
onLongPress: (item: any) => Promise<void>;
|
|
||||||
username: string;
|
|
||||||
width: number;
|
|
||||||
status: TUserStatus;
|
|
||||||
toggleFav(): void;
|
|
||||||
toggleRead(): void;
|
|
||||||
hideChannel(): void;
|
|
||||||
useRealName: boolean;
|
|
||||||
getUserPresence: (uid: string) => void;
|
|
||||||
connected: boolean;
|
|
||||||
theme: TSupportedThemes;
|
|
||||||
isFocused: boolean;
|
|
||||||
getRoomTitle: (item: any) => string;
|
|
||||||
getRoomAvatar: (item: any) => string;
|
|
||||||
getIsGroupChat: (item: any) => boolean;
|
|
||||||
getIsRead: (item: any) => boolean;
|
|
||||||
swipeEnabled: boolean;
|
|
||||||
autoJoin: boolean;
|
|
||||||
showAvatar: boolean;
|
|
||||||
displayMode: string;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRoomItemProps {
|
interface IBaseRoomItem extends IRoomItemTouchables {
|
||||||
|
[key: string]: any;
|
||||||
|
showLastMessage?: boolean;
|
||||||
|
useRealName: boolean;
|
||||||
|
isFocused?: boolean;
|
||||||
|
displayMode: string;
|
||||||
|
showAvatar: boolean;
|
||||||
|
swipeEnabled: boolean;
|
||||||
|
autoJoin?: boolean;
|
||||||
|
width: number;
|
||||||
|
username?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoomItemContainerProps extends IBaseRoomItem {
|
||||||
|
item: any;
|
||||||
|
id?: string;
|
||||||
|
getRoomTitle: (item: any) => string;
|
||||||
|
getRoomAvatar: (item: any) => string;
|
||||||
|
getIsRead?: (item: any) => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IRoomItemProps extends IBaseRoomItem {
|
||||||
rid: string;
|
rid: string;
|
||||||
type: SubscriptionType;
|
type: SubscriptionType;
|
||||||
prid: string;
|
prid: string;
|
||||||
name: string;
|
name: string;
|
||||||
avatar: string;
|
avatar: string;
|
||||||
showLastMessage: boolean;
|
|
||||||
username: string;
|
|
||||||
testID: string;
|
testID: string;
|
||||||
width: number;
|
|
||||||
status: TUserStatus;
|
status: TUserStatus;
|
||||||
useRealName: boolean;
|
|
||||||
theme: TSupportedThemes;
|
|
||||||
isFocused: boolean;
|
|
||||||
isGroupChat: boolean;
|
isGroupChat: boolean;
|
||||||
isRead: boolean;
|
isRead: boolean;
|
||||||
teamMain: boolean;
|
teamMain: boolean;
|
||||||
|
@ -121,22 +113,12 @@ export interface IRoomItemProps {
|
||||||
tunread: [];
|
tunread: [];
|
||||||
tunreadUser: [];
|
tunreadUser: [];
|
||||||
tunreadGroup: [];
|
tunreadGroup: [];
|
||||||
swipeEnabled: boolean;
|
|
||||||
toggleFav(): void;
|
|
||||||
toggleRead(): void;
|
|
||||||
onPress(): void;
|
|
||||||
onLongPress(): void;
|
|
||||||
hideChannel(): void;
|
|
||||||
autoJoin: boolean;
|
|
||||||
size?: number;
|
size?: number;
|
||||||
showAvatar: boolean;
|
|
||||||
displayMode: string;
|
|
||||||
sourceType: IOmnichannelSource;
|
sourceType: IOmnichannelSource;
|
||||||
hideMentionStatus?: boolean;
|
hideMentionStatus?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ILastMessageProps {
|
export interface ILastMessageProps {
|
||||||
theme: TSupportedThemes;
|
|
||||||
lastMessage: ILastMessage;
|
lastMessage: ILastMessage;
|
||||||
type: SubscriptionType;
|
type: SubscriptionType;
|
||||||
showLastMessage: boolean;
|
showLastMessage: boolean;
|
||||||
|
@ -145,20 +127,29 @@ export interface ILastMessageProps {
|
||||||
alert: boolean;
|
alert: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITouchableProps {
|
export interface ITouchableProps extends IRoomItemTouchables {
|
||||||
children: JSX.Element;
|
children: JSX.Element;
|
||||||
type: string;
|
type: SubscriptionType;
|
||||||
onPress(): void;
|
|
||||||
onLongPress(): void;
|
|
||||||
testID: string;
|
testID: string;
|
||||||
width: number;
|
width: number;
|
||||||
favorite: boolean;
|
favorite: boolean;
|
||||||
isRead: boolean;
|
isRead: boolean;
|
||||||
rid: string;
|
rid: string;
|
||||||
toggleFav: Function;
|
|
||||||
toggleRead: Function;
|
|
||||||
hideChannel: Function;
|
|
||||||
isFocused: boolean;
|
isFocused: boolean;
|
||||||
swipeEnabled: boolean;
|
swipeEnabled: boolean;
|
||||||
displayMode: string;
|
displayMode: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IIconOrAvatar {
|
||||||
|
avatar: string;
|
||||||
|
type: string;
|
||||||
|
rid: string;
|
||||||
|
showAvatar: boolean;
|
||||||
|
displayMode: string;
|
||||||
|
prid: string;
|
||||||
|
status: TUserStatus;
|
||||||
|
isGroupChat: boolean;
|
||||||
|
teamMain: boolean;
|
||||||
|
showLastMessage: boolean;
|
||||||
|
sourceType: IOmnichannelSource;
|
||||||
|
}
|
||||||
|
|
|
@ -37,10 +37,10 @@ const keyExtractor = (item: IOmnichannelRoom) => item.rid;
|
||||||
const QueueListView = React.memo(() => {
|
const QueueListView = React.memo(() => {
|
||||||
const navigation = useNavigation<TNavigation>();
|
const navigation = useNavigation<TNavigation>();
|
||||||
const getScrollRef = useRef<FlatList<IOmnichannelRoom>>(null);
|
const getScrollRef = useRef<FlatList<IOmnichannelRoom>>(null);
|
||||||
const { theme, colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { width } = useDimensions();
|
const { width } = useDimensions();
|
||||||
|
|
||||||
const { userId, token, username } = useSelector(
|
const { username } = useSelector(
|
||||||
(state: IApplicationState) => ({
|
(state: IApplicationState) => ({
|
||||||
userId: getUserSelector(state).id,
|
userId: getUserSelector(state).id,
|
||||||
username: getUserSelector(state).username,
|
username: getUserSelector(state).username,
|
||||||
|
@ -58,7 +58,6 @@ const QueueListView = React.memo(() => {
|
||||||
);
|
);
|
||||||
|
|
||||||
const isMasterDetail = useSelector((state: IApplicationState) => state.app.isMasterDetail);
|
const isMasterDetail = useSelector((state: IApplicationState) => state.app.isMasterDetail);
|
||||||
const server = useSelector((state: IApplicationState) => state.server.server);
|
|
||||||
const useRealName = useSelector((state: IApplicationState) => state.settings.UI_Use_Real_Name);
|
const useRealName = useSelector((state: IApplicationState) => state.settings.UI_Use_Real_Name);
|
||||||
const queued = useSelector((state: IApplicationState) => getInquiryQueueSelector(state));
|
const queued = useSelector((state: IApplicationState) => getInquiryQueueSelector(state));
|
||||||
|
|
||||||
|
@ -95,20 +94,13 @@ const QueueListView = React.memo(() => {
|
||||||
return (
|
return (
|
||||||
<RoomItem
|
<RoomItem
|
||||||
item={item}
|
item={item}
|
||||||
theme={theme}
|
|
||||||
id={id}
|
id={id}
|
||||||
type={item.t}
|
|
||||||
userId={userId}
|
|
||||||
username={username}
|
username={username}
|
||||||
token={token}
|
|
||||||
baseUrl={server}
|
|
||||||
onPress={onPressItem}
|
onPress={onPressItem}
|
||||||
testID={`queue-list-view-item-${item.name}`}
|
|
||||||
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
|
width={isMasterDetail ? MAX_SIDEBAR_WIDTH : width}
|
||||||
useRealName={useRealName}
|
useRealName={!!useRealName}
|
||||||
getRoomTitle={getRoomTitle}
|
getRoomTitle={getRoomTitle}
|
||||||
getRoomAvatar={getRoomAvatar}
|
getRoomAvatar={getRoomAvatar}
|
||||||
visitor={item.v}
|
|
||||||
swipeEnabled={false}
|
swipeEnabled={false}
|
||||||
showAvatar={showAvatar}
|
showAvatar={showAvatar}
|
||||||
displayMode={displayMode}
|
displayMode={displayMode}
|
||||||
|
|
|
@ -38,19 +38,26 @@ import SafeAreaView from '../../containers/SafeAreaView';
|
||||||
import Header, { getHeaderTitlePosition } from '../../containers/Header';
|
import Header, { getHeaderTitlePosition } from '../../containers/Header';
|
||||||
import { withDimensions } from '../../dimensions';
|
import { withDimensions } from '../../dimensions';
|
||||||
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
import { getInquiryQueueSelector } from '../../ee/omnichannel/selectors/inquiry';
|
||||||
import { IApplicationState, IBaseScreen, ISubscription, IUser, RootEnum, TSubscriptionModel } from '../../definitions';
|
import {
|
||||||
|
IApplicationState,
|
||||||
|
IBaseScreen,
|
||||||
|
ISubscription,
|
||||||
|
IUser,
|
||||||
|
RootEnum,
|
||||||
|
SubscriptionType,
|
||||||
|
TSubscriptionModel
|
||||||
|
} from '../../definitions';
|
||||||
import styles from './styles';
|
import styles from './styles';
|
||||||
import ServerDropdown from './ServerDropdown';
|
import ServerDropdown from './ServerDropdown';
|
||||||
import ListHeader, { TEncryptionBanner } from './ListHeader';
|
import ListHeader, { TEncryptionBanner } from './ListHeader';
|
||||||
import RoomsListHeaderView from './Header';
|
import RoomsListHeaderView from './Header';
|
||||||
import { ChatsStackParamList } from '../../stacks/types';
|
import { ChatsStackParamList } from '../../stacks/types';
|
||||||
import { getUserPresence, RoomTypes, search } from '../../lib/methods';
|
import { RoomTypes, search } from '../../lib/methods';
|
||||||
import {
|
import {
|
||||||
getRoomAvatar,
|
getRoomAvatar,
|
||||||
getRoomTitle,
|
getRoomTitle,
|
||||||
getUidDirectMessage,
|
getUidDirectMessage,
|
||||||
hasPermission,
|
hasPermission,
|
||||||
isGroupChat,
|
|
||||||
isRead,
|
isRead,
|
||||||
debounce,
|
debounce,
|
||||||
isIOS,
|
isIOS,
|
||||||
|
@ -645,8 +652,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
|
|
||||||
isSwipeEnabled = (item: IRoomItem) => !(item?.search || item?.joinCodeRequired || item?.outside);
|
isSwipeEnabled = (item: IRoomItem) => !(item?.search || item?.joinCodeRequired || item?.outside);
|
||||||
|
|
||||||
handleGetUserPresence = (uid: string) => getUserPresence(uid);
|
|
||||||
|
|
||||||
get isGrouping() {
|
get isGrouping() {
|
||||||
const { showUnread, showFavorites, groupByType } = this.props;
|
const { showUnread, showFavorites, groupByType } = this.props;
|
||||||
return showUnread || showFavorites || groupByType;
|
return showUnread || showFavorites || groupByType;
|
||||||
|
@ -668,7 +673,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
toggleFav = async (rid: string, favorite: boolean) => {
|
toggleFav = async (rid: string, favorite: boolean): Promise<void> => {
|
||||||
logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
|
logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
|
@ -718,11 +723,11 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
hideChannel = async (rid: string, type: RoomTypes) => {
|
hideChannel = async (rid: string, type: SubscriptionType) => {
|
||||||
logEvent(events.RL_HIDE_CHANNEL);
|
logEvent(events.RL_HIDE_CHANNEL);
|
||||||
try {
|
try {
|
||||||
const db = database.active;
|
const db = database.active;
|
||||||
const result = await Services.hideRoom(rid, type);
|
const result = await Services.hideRoom(rid, type as RoomTypes);
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
const subCollection = db.get('subscriptions');
|
const subCollection = db.get('subscriptions');
|
||||||
await db.write(async () => {
|
await db.write(async () => {
|
||||||
|
@ -938,7 +943,6 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
user: { username },
|
user: { username },
|
||||||
StoreLastMessage,
|
StoreLastMessage,
|
||||||
useRealName,
|
useRealName,
|
||||||
theme,
|
|
||||||
isMasterDetail,
|
isMasterDetail,
|
||||||
width,
|
width,
|
||||||
showAvatar,
|
showAvatar,
|
||||||
|
@ -950,9 +954,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
return (
|
return (
|
||||||
<RoomItem
|
<RoomItem
|
||||||
item={item}
|
item={item}
|
||||||
theme={theme}
|
|
||||||
id={id}
|
id={id}
|
||||||
type={item.t}
|
|
||||||
username={username}
|
username={username}
|
||||||
showLastMessage={StoreLastMessage}
|
showLastMessage={StoreLastMessage}
|
||||||
onPress={this.onPressItem}
|
onPress={this.onPressItem}
|
||||||
|
@ -961,12 +963,9 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
|
||||||
toggleRead={this.toggleRead}
|
toggleRead={this.toggleRead}
|
||||||
hideChannel={this.hideChannel}
|
hideChannel={this.hideChannel}
|
||||||
useRealName={useRealName}
|
useRealName={useRealName}
|
||||||
getUserPresence={this.handleGetUserPresence}
|
|
||||||
getRoomTitle={getRoomTitle}
|
getRoomTitle={getRoomTitle}
|
||||||
getRoomAvatar={getRoomAvatar}
|
getRoomAvatar={getRoomAvatar}
|
||||||
getIsGroupChat={isGroupChat}
|
|
||||||
getIsRead={isRead}
|
getIsRead={isRead}
|
||||||
visitor={item.visitor}
|
|
||||||
isFocused={currentItem?.rid === item.rid}
|
isFocused={currentItem?.rid === item.rid}
|
||||||
swipeEnabled={swipeEnabled}
|
swipeEnabled={swipeEnabled}
|
||||||
showAvatar={showAvatar}
|
showAvatar={showAvatar}
|
||||||
|
|
|
@ -494,12 +494,10 @@ class TeamChannelsView extends React.Component<ITeamChannelsViewProps, ITeamChan
|
||||||
};
|
};
|
||||||
|
|
||||||
renderItem = ({ item }: { item: IItem }) => {
|
renderItem = ({ item }: { item: IItem }) => {
|
||||||
const { StoreLastMessage, useRealName, theme, width, showAvatar, displayMode } = this.props;
|
const { StoreLastMessage, useRealName, width, showAvatar, displayMode } = this.props;
|
||||||
return (
|
return (
|
||||||
<RoomItem
|
<RoomItem
|
||||||
item={item}
|
item={item}
|
||||||
theme={theme}
|
|
||||||
type={item.t}
|
|
||||||
showLastMessage={StoreLastMessage}
|
showLastMessage={StoreLastMessage}
|
||||||
onPress={this.onPressItem}
|
onPress={this.onPressItem}
|
||||||
width={width}
|
width={width}
|
||||||
|
|
Loading…
Reference in New Issue