diff --git a/app/containers/RoomItem/IconOrAvatar.js b/app/containers/RoomItem/IconOrAvatar.tsx
similarity index 69%
rename from app/containers/RoomItem/IconOrAvatar.js
rename to app/containers/RoomItem/IconOrAvatar.tsx
index ddfa06001..7d929189f 100644
--- a/app/containers/RoomItem/IconOrAvatar.js
+++ b/app/containers/RoomItem/IconOrAvatar.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { View } from 'react-native';
-import PropTypes from 'prop-types';
import Avatar from '../Avatar';
import { DisplayMode } from '../../lib/constants';
import TypeIcon from './TypeIcon';
import styles from './styles';
+import { IIconOrAvatar } from './interfaces';
const IconOrAvatar = ({
avatar,
@@ -17,10 +17,9 @@ const IconOrAvatar = ({
isGroupChat,
teamMain,
showLastMessage,
- theme,
displayMode,
sourceType
-}) => {
+}: IIconOrAvatar): React.ReactElement | null => {
if (showAvatar) {
return (
@@ -35,7 +34,6 @@ const IconOrAvatar = ({
prid={prid}
status={status}
isGroupChat={isGroupChat}
- theme={theme}
teamMain={teamMain}
size={24}
style={{ marginRight: 12 }}
@@ -48,18 +46,4 @@ const IconOrAvatar = ({
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;
diff --git a/app/containers/RoomItem/LastMessage.tsx b/app/containers/RoomItem/LastMessage.tsx
index 96b077809..bdb94d4dd 100644
--- a/app/containers/RoomItem/LastMessage.tsx
+++ b/app/containers/RoomItem/LastMessage.tsx
@@ -4,8 +4,9 @@ import { dequal } from 'dequal';
import I18n from '../../i18n';
import styles from './styles';
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 { useTheme } from '../../theme';
const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }: Partial) => {
if (!showLastMessage) {
@@ -46,8 +47,9 @@ const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps);
-const LastMessage = React.memo(
- ({ lastMessage, type, showLastMessage, username, alert, useRealName, theme }: ILastMessageProps) => (
+const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
+ const { colors } = useTheme();
+ return (
- ),
- arePropsEqual
-);
+ );
+}, arePropsEqual);
export default LastMessage;
diff --git a/app/containers/RoomItem/RoomItem.tsx b/app/containers/RoomItem/RoomItem.tsx
index d996b9707..8e2950f90 100644
--- a/app/containers/RoomItem/RoomItem.tsx
+++ b/app/containers/RoomItem/RoomItem.tsx
@@ -25,7 +25,6 @@ const RoomItem = ({
showLastMessage,
status = 'offline',
useRealName,
- theme,
isFocused,
isGroupChat,
isRead,
@@ -67,14 +66,13 @@ const RoomItem = ({
hideChannel={hideChannel}
testID={testID}
type={type}
- isFocused={isFocused}
+ isFocused={!!isFocused}
swipeEnabled={swipeEnabled}
displayMode={displayMode}>
{showLastMessage && displayMode === DisplayMode.Expanded ? (
<>
@@ -97,19 +95,18 @@ const RoomItem = ({
sourceType={sourceType}
/>
) : null}
-
+
{autoJoin ? : null}
-
+
-
+
{autoJoin ? : null}
-
+
(
-
- {name}
-
-));
+const Title = React.memo(({ name, hideUnreadStatus, alert }: ITitleProps) => {
+ const { colors } = useTheme();
+ return (
+
+ {name}
+
+ );
+});
export default Title;
diff --git a/app/containers/RoomItem/UpdatedAt.tsx b/app/containers/RoomItem/UpdatedAt.tsx
index fde4ae6df..f51ccc870 100644
--- a/app/containers/RoomItem/UpdatedAt.tsx
+++ b/app/containers/RoomItem/UpdatedAt.tsx
@@ -2,11 +2,13 @@ import React from 'react';
import { Text } from 'react-native';
import styles from './styles';
-import { themes } from '../../lib/constants';
import { capitalize } from '../../lib/methods/helpers/room';
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) {
return null;
}
@@ -15,13 +17,13 @@ const UpdatedAt = React.memo(({ date, theme, hideUnreadStatus, alert }: IUpdated
style={[
styles.date,
{
- color: themes[theme].auxiliaryText
+ color: colors.auxiliaryText
},
alert &&
!hideUnreadStatus && [
styles.updateAlert,
{
- color: themes[theme].tintColor
+ color: colors.tintColor
}
]
]}
diff --git a/app/containers/RoomItem/Wrapper.tsx b/app/containers/RoomItem/Wrapper.tsx
index 1784586e7..4fcccb6d2 100644
--- a/app/containers/RoomItem/Wrapper.tsx
+++ b/app/containers/RoomItem/Wrapper.tsx
@@ -1,26 +1,30 @@
import React from 'react';
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 { IWrapperProps } from './interfaces';
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 (
- {children}
+ style={[styles.container, displayMode === DisplayMode.Condensed && styles.containerCondensed]}
+ accessibilityLabel={accessibilityLabel}>
+
+
+ {children}
+
-
-);
+ );
+};
export default Wrapper;
diff --git a/app/containers/RoomItem/index.tsx b/app/containers/RoomItem/index.tsx
index 7a7a29deb..c7547d5c4 100644
--- a/app/containers/RoomItem/index.tsx
+++ b/app/containers/RoomItem/index.tsx
@@ -1,171 +1,111 @@
-import React from 'react';
-import { connect } from 'react-redux';
+import React, { useEffect, useReducer, useRef } from 'react';
+import { Subscription } from 'rxjs';
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 RoomItem from './RoomItem';
-import { ISubscription, TUserStatus } from '../../definitions';
import { IRoomItemContainerProps } from './interfaces';
+import RoomItem from './RoomItem';
+import { ROW_HEIGHT, ROW_HEIGHT_CONDENSED } from './styles';
export { ROW_HEIGHT, ROW_HEIGHT_CONDENSED };
-const attrs = [
- 'width',
- 'status',
- 'connected',
- 'theme',
- 'isFocused',
- 'forceUpdate',
- 'showLastMessage',
- 'autoJoin',
- 'showAvatar',
- 'displayMode'
-];
+const attrs = ['width', 'isFocused', 'showLastMessage', 'autoJoin', 'showAvatar', 'displayMode'];
-class RoomItemContainer extends React.Component {
- private roomSubscription: ISubscription | undefined;
-
- static defaultProps: Partial = {
- 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,
- getRoomTitle,
- getRoomAvatar,
- getIsRead,
- width,
- toggleFav,
- toggleRead,
- hideChannel,
- theme,
- isFocused,
- status,
- showLastMessage,
- username,
- useRealName,
- swipeEnabled,
- autoJoin,
- showAvatar,
- displayMode
- } = this.props;
+const RoomItemContainer = React.memo(
+ ({
+ item,
+ id,
+ onPress,
+ onLongPress,
+ width,
+ toggleFav,
+ toggleRead,
+ hideChannel,
+ isFocused,
+ showLastMessage,
+ username,
+ useRealName,
+ autoJoin,
+ showAvatar,
+ displayMode,
+ getRoomTitle = () => 'title',
+ getRoomAvatar = () => '',
+ getIsRead = () => false,
+ swipeEnabled = true
+ }: IRoomItemContainerProps) => {
const name = getRoomTitle(item);
const testID = `rooms-list-view-item-${name}`;
const avatar = getRoomAvatar(item);
const isRead = getIsRead(item);
const date = item.roomUpdatedAt && formatDate(item.roomUpdatedAt);
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(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) {
- accessibilityLabel += `, ${item.unread} ${I18n.t('alert')}`;
+ accessibilityLabel = `, ${item.unread} ${I18n.t('alert')}`;
} else if (item.unread > 1) {
- accessibilityLabel += `, ${item.unread} ${I18n.t('alerts')}`;
+ accessibilityLabel = `, ${item.unread} ${I18n.t('alerts')}`;
}
-
if (item.userMentions > 0) {
- accessibilityLabel += `, ${I18n.t('you_were_mentioned')}`;
+ accessibilityLabel = `, ${I18n.t('you_were_mentioned')}`;
}
-
if (date) {
- accessibilityLabel += `, ${I18n.t('last_message')} ${date}`;
+ accessibilityLabel = `, ${I18n.t('last_message')} ${date}`;
}
return (
{
sourceType={item.source}
/>
);
- }
-}
+ },
+ (props, nextProps) => attrs.every(key => props[key] === nextProps[key])
+);
-const mapStateToProps = (state: any, ownProps: any) => {
- 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);
+export default RoomItemContainer;
diff --git a/app/containers/RoomItem/interfaces.ts b/app/containers/RoomItem/interfaces.ts
index 7f698242f..bf2cc3604 100644
--- a/app/containers/RoomItem/interfaces.ts
+++ b/app/containers/RoomItem/interfaces.ts
@@ -23,14 +23,12 @@ export interface IRightActionsProps {
export interface ITitleProps {
name: string;
- theme: TSupportedThemes;
hideUnreadStatus: boolean;
alert: boolean;
}
export interface IUpdatedAtProps {
date: string;
- theme: TSupportedThemes;
hideUnreadStatus: boolean;
alert: boolean;
}
@@ -39,13 +37,12 @@ export interface IWrapperProps {
accessibilityLabel: string;
avatar: string;
type: string;
- theme: TSupportedThemes;
rid: string;
children: React.ReactElement;
displayMode: string;
prid: string;
showLastMessage: boolean;
- status: string;
+ status: TUserStatus;
isGroupChat: boolean;
teamMain: boolean;
showAvatar: boolean;
@@ -64,48 +61,43 @@ export interface ITypeIconProps {
sourceType: IOmnichannelSource;
}
-export interface IRoomItemContainerProps {
- [key: string]: string | boolean | Function | number;
- item: any;
- showLastMessage: boolean;
- id: string;
- onPress: (item: any) => void;
- onLongPress: (item: any) => Promise;
- 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;
+interface IRoomItemTouchables {
+ toggleFav?: (rid: string, favorite: boolean) => Promise;
+ toggleRead?: (rid: string, tIsRead: boolean) => Promise;
+ hideChannel?: (rid: string, type: SubscriptionType) => Promise;
+ onPress: (item?: any) => void;
+ onLongPress?: (item?: any) => void;
}
-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;
type: SubscriptionType;
prid: string;
name: string;
avatar: string;
- showLastMessage: boolean;
- username: string;
testID: string;
- width: number;
status: TUserStatus;
- useRealName: boolean;
- theme: TSupportedThemes;
- isFocused: boolean;
isGroupChat: boolean;
isRead: boolean;
teamMain: boolean;
@@ -121,22 +113,12 @@ export interface IRoomItemProps {
tunread: [];
tunreadUser: [];
tunreadGroup: [];
- swipeEnabled: boolean;
- toggleFav(): void;
- toggleRead(): void;
- onPress(): void;
- onLongPress(): void;
- hideChannel(): void;
- autoJoin: boolean;
size?: number;
- showAvatar: boolean;
- displayMode: string;
sourceType: IOmnichannelSource;
hideMentionStatus?: boolean;
}
export interface ILastMessageProps {
- theme: TSupportedThemes;
lastMessage: ILastMessage;
type: SubscriptionType;
showLastMessage: boolean;
@@ -145,20 +127,29 @@ export interface ILastMessageProps {
alert: boolean;
}
-export interface ITouchableProps {
+export interface ITouchableProps extends IRoomItemTouchables {
children: JSX.Element;
- type: string;
- onPress(): void;
- onLongPress(): void;
+ type: SubscriptionType;
testID: string;
width: number;
favorite: boolean;
isRead: boolean;
rid: string;
- toggleFav: Function;
- toggleRead: Function;
- hideChannel: Function;
isFocused: boolean;
swipeEnabled: boolean;
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;
+}
diff --git a/app/ee/omnichannel/views/QueueListView.tsx b/app/ee/omnichannel/views/QueueListView.tsx
index ed6719fc1..20025ff15 100644
--- a/app/ee/omnichannel/views/QueueListView.tsx
+++ b/app/ee/omnichannel/views/QueueListView.tsx
@@ -37,10 +37,10 @@ const keyExtractor = (item: IOmnichannelRoom) => item.rid;
const QueueListView = React.memo(() => {
const navigation = useNavigation();
const getScrollRef = useRef>(null);
- const { theme, colors } = useTheme();
+ const { colors } = useTheme();
const { width } = useDimensions();
- const { userId, token, username } = useSelector(
+ const { username } = useSelector(
(state: IApplicationState) => ({
userId: getUserSelector(state).id,
username: getUserSelector(state).username,
@@ -58,7 +58,6 @@ const QueueListView = React.memo(() => {
);
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 queued = useSelector((state: IApplicationState) => getInquiryQueueSelector(state));
@@ -95,20 +94,13 @@ const QueueListView = React.memo(() => {
return (
!(item?.search || item?.joinCodeRequired || item?.outside);
- handleGetUserPresence = (uid: string) => getUserPresence(uid);
-
get isGrouping() {
const { showUnread, showFavorites, groupByType } = this.props;
return showUnread || showFavorites || groupByType;
@@ -668,7 +673,7 @@ class RoomsListView extends React.Component {
+ toggleFav = async (rid: string, favorite: boolean): Promise => {
logEvent(favorite ? events.RL_UNFAVORITE_CHANNEL : events.RL_FAVORITE_CHANNEL);
try {
const db = database.active;
@@ -718,11 +723,11 @@ class RoomsListView extends React.Component {
+ hideChannel = async (rid: string, type: SubscriptionType) => {
logEvent(events.RL_HIDE_CHANNEL);
try {
const db = database.active;
- const result = await Services.hideRoom(rid, type);
+ const result = await Services.hideRoom(rid, type as RoomTypes);
if (result.success) {
const subCollection = db.get('subscriptions');
await db.write(async () => {
@@ -938,7 +943,6 @@ class RoomsListView extends React.Component {
- const { StoreLastMessage, useRealName, theme, width, showAvatar, displayMode } = this.props;
+ const { StoreLastMessage, useRealName, width, showAvatar, displayMode } = this.props;
return (