Fixing RoomsListView

This commit is contained in:
Diego Mello 2022-11-25 17:34:49 -03:00
parent a38bc37aaa
commit b9cafe9d31
3 changed files with 149 additions and 124 deletions

View File

@ -1,5 +1,4 @@
import React from 'react'; import React from 'react';
import { dequal } from 'dequal';
import I18n from '../../i18n'; import I18n from '../../i18n';
import styles from './styles'; import styles from './styles';
@ -45,9 +44,7 @@ const formatMsg = ({ lastMessage, type, showLastMessage, username, useRealName }
return `${prefix}${lastMessage.msg}`; return `${prefix}${lastMessage.msg}`;
}; };
const arePropsEqual = (oldProps: any, newProps: any) => dequal(oldProps, newProps); const LastMessage = ({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username, alert, useRealName }: ILastMessageProps) => {
const { colors } = useTheme(); const { colors } = useTheme();
return ( return (
<MarkdownPreview <MarkdownPreview
@ -63,6 +60,6 @@ const LastMessage = React.memo(({ lastMessage, type, showLastMessage, username,
testID='room-item-last-message' testID='room-item-last-message'
/> />
); );
}, arePropsEqual); };
export default LastMessage; export default LastMessage;

View File

@ -1,5 +1,5 @@
import React, { useEffect, useReducer, useRef } from 'react'; import React, { useEffect } from 'react';
import { Subscription } from 'rxjs'; // import { Subscription } from 'rxjs';
import I18n from '../../i18n'; import I18n from '../../i18n';
import { useAppSelector } from '../../lib/hooks'; import { useAppSelector } from '../../lib/hooks';
@ -44,22 +44,22 @@ const RoomItemContainer = React.memo(
const alert = item.alert || item.tunread?.length; const alert = item.alert || item.tunread?.length;
const connected = useAppSelector(state => state.meteor.connected); const connected = useAppSelector(state => state.meteor.connected);
const userStatus = useAppSelector(state => state.activeUsers[id || '']?.status); const userStatus = useAppSelector(state => state.activeUsers[id || '']?.status);
const [_, forceUpdate] = useReducer(x => x + 1, 1); // const [_, forceUpdate] = useReducer(x => x + 1, 1);
const roomSubscription = useRef<Subscription | null>(null); // const roomSubscription = useRef<Subscription | null>(null);
useEffect(() => { // useEffect(() => {
const init = () => { // const init = () => {
if (item?.observe) { // if (item?.observe) {
const observable = item.observe(); // const observable = item.observe();
roomSubscription.current = observable?.subscribe?.(() => { // roomSubscription.current = observable?.subscribe?.(() => {
if (_) forceUpdate(); // if (_) forceUpdate();
}); // });
} // }
}; // };
init(); // init();
return () => roomSubscription.current?.unsubscribe(); // return () => roomSubscription.current?.unsubscribe();
}, []); // }, []);
useEffect(() => { useEffect(() => {
const isDirect = !!(item.t === 'd' && id && !isGroupChat(item)); const isDirect = !!(item.t === 'd' && id && !isGroupChat(item));

View File

@ -128,34 +128,34 @@ const OMNICHANNEL_HEADER_IN_PROGRESS = 'Open_Livechats';
const OMNICHANNEL_HEADER_ON_HOLD = 'On_hold_Livechats'; const OMNICHANNEL_HEADER_ON_HOLD = 'On_hold_Livechats';
const QUERY_SIZE = 20; const QUERY_SIZE = 20;
const filterIsUnread = (s: TSubscriptionModel) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus; const filterIsUnread = (s: any) => (s.unread > 0 || s.tunread?.length > 0 || s.alert) && !s.hideUnreadStatus;
const filterIsFavorite = (s: TSubscriptionModel) => s.f; const filterIsFavorite = (s: any) => s.f;
const filterIsOmnichannel = (s: TSubscriptionModel) => s.t === 'l'; const filterIsOmnichannel = (s: any) => s.t === 'l';
const filterIsTeam = (s: TSubscriptionModel) => s.teamMain; const filterIsTeam = (s: any) => s.teamMain;
const filterIsDiscussion = (s: TSubscriptionModel) => s.prid; const filterIsDiscussion = (s: any) => s.prid;
const shouldUpdateProps = [ // const shouldUpdateProps = [
'searchText', // 'searchText',
'loadingServer', // 'loadingServer',
'showServerDropdown', // 'showServerDropdown',
'useRealName', // 'useRealName',
'StoreLastMessage', // 'StoreLastMessage',
'theme', // 'theme',
'isMasterDetail', // 'isMasterDetail',
'refreshing', // 'refreshing',
'queueSize', // 'queueSize',
'inquiryEnabled', // 'inquiryEnabled',
'encryptionBanner', // 'encryptionBanner',
'createTeamPermission', // 'createTeamPermission',
'createDirectMessagePermission', // 'createDirectMessagePermission',
'createPublicChannelPermission', // 'createPublicChannelPermission',
'createPrivateChannelPermission', // 'createPrivateChannelPermission',
'createDiscussionPermission' // 'createDiscussionPermission'
]; // ];
const sortPreferencesShouldUpdate = ['sortBy', 'groupByType', 'showFavorites', 'showUnread']; // const sortPreferencesShouldUpdate = ['sortBy', 'groupByType', 'showFavorites', 'showUnread'];
const displayPropsShouldUpdate = ['showAvatar', 'displayMode']; // const displayPropsShouldUpdate = ['showAvatar', 'displayMode'];
const keyExtractor = (item: ISubscription) => item.rid; const keyExtractor = (item: ISubscription) => item.rid;
@ -244,83 +244,83 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
} }
} }
shouldComponentUpdate(nextProps: IRoomsListViewProps, nextState: IRoomsListViewState) { // shouldComponentUpdate(nextProps: IRoomsListViewProps, nextState: IRoomsListViewState) {
const { chatsUpdate, searching, item, canCreateRoom, omnichannelsUpdate } = this.state; // const { chatsUpdate, searching, item, canCreateRoom, omnichannelsUpdate } = this.state;
// eslint-disable-next-line react/destructuring-assignment // // eslint-disable-next-line react/destructuring-assignment
const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]); // const propsUpdated = shouldUpdateProps.some(key => nextProps[key] !== this.props[key]);
if (propsUpdated) { // if (propsUpdated) {
return true; // return true;
} // }
// check if some display props are changed to force update when focus this view again // // check if some display props are changed to force update when focus this view again
// eslint-disable-next-line react/destructuring-assignment // // eslint-disable-next-line react/destructuring-assignment
const displayUpdated = displayPropsShouldUpdate.some(key => nextProps[key] !== this.props[key]); // const displayUpdated = displayPropsShouldUpdate.some(key => nextProps[key] !== this.props[key]);
if (displayUpdated) { // if (displayUpdated) {
this.shouldUpdate = true; // this.shouldUpdate = true;
} // }
// check if some sort preferences are changed to getSubscription() when focus this view again // // check if some sort preferences are changed to getSubscription() when focus this view again
// eslint-disable-next-line react/destructuring-assignment // // eslint-disable-next-line react/destructuring-assignment
const sortPreferencesUpdate = sortPreferencesShouldUpdate.some(key => nextProps[key] !== this.props[key]); // const sortPreferencesUpdate = sortPreferencesShouldUpdate.some(key => nextProps[key] !== this.props[key]);
if (sortPreferencesUpdate) { // if (sortPreferencesUpdate) {
this.sortPreferencesChanged = true; // this.sortPreferencesChanged = true;
} // }
// Compare changes only once // // Compare changes only once
const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate); // const chatsNotEqual = !dequal(nextState.chatsUpdate, chatsUpdate);
// If they aren't equal, set to update if focused // // If they aren't equal, set to update if focused
if (chatsNotEqual) { // if (chatsNotEqual) {
this.shouldUpdate = true; // this.shouldUpdate = true;
} // }
const omnichannelsNotEqual = !dequal(nextState.omnichannelsUpdate, omnichannelsUpdate); // const omnichannelsNotEqual = !dequal(nextState.omnichannelsUpdate, omnichannelsUpdate);
if (omnichannelsNotEqual) { // if (omnichannelsNotEqual) {
this.shouldUpdate = true; // this.shouldUpdate = true;
} // }
if (nextState.searching !== searching) { // if (nextState.searching !== searching) {
return true; // return true;
} // }
if (nextState.canCreateRoom !== canCreateRoom) { // if (nextState.canCreateRoom !== canCreateRoom) {
return true; // return true;
} // }
if (nextState.item?.rid !== item?.rid) { // if (nextState.item?.rid !== item?.rid) {
return true; // return true;
} // }
// Abort if it's not focused // // Abort if it's not focused
if (!nextProps.navigation.isFocused()) { // if (!nextProps.navigation.isFocused()) {
return false; // return false;
} // }
const { loading, search } = this.state; // const { loading, search } = this.state;
const { rooms, width, insets } = this.props; // const { rooms, width, insets } = this.props;
if (nextState.loading !== loading) { // if (nextState.loading !== loading) {
return true; // return true;
} // }
if (nextProps.width !== width) { // if (nextProps.width !== width) {
return true; // return true;
} // }
if (!dequal(nextState.search, search)) { // if (!dequal(nextState.search, search)) {
return true; // return true;
} // }
if (!dequal(nextProps.rooms, rooms)) { // if (!dequal(nextProps.rooms, rooms)) {
return true; // return true;
} // }
if (!dequal(nextProps.insets, insets)) { // if (!dequal(nextProps.insets, insets)) {
return true; // return true;
} // }
// If it's focused and there are changes, update // // If it's focused and there are changes, update
if (chatsNotEqual || omnichannelsNotEqual) { // if (chatsNotEqual || omnichannelsNotEqual) {
this.shouldUpdate = false; // this.shouldUpdate = false;
return true; // return true;
} // }
return false; // return false;
} // }
componentDidUpdate(prevProps: IRoomsListViewProps) { componentDidUpdate(prevProps: IRoomsListViewProps) {
const { const {
@ -478,7 +478,7 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
this.setState(state, callback); this.setState(state, callback);
}; };
addRoomsGroup = (data: TSubscriptionModel[], header: string, allData: TSubscriptionModel[]) => { addRoomsGroup = (data: TSubscriptionModel[] | any, header: string, allData: TSubscriptionModel[]) => {
if (data.length > 0) { if (data.length > 0) {
if (header) { if (header) {
allData.push({ rid: header, separator: true } as TSubscriptionModel); allData.push({ rid: header, separator: true } as TSubscriptionModel);
@ -509,19 +509,49 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
observable = await db observable = await db
.get('subscriptions') .get('subscriptions')
.query(...defaultWhereClause) .query(...defaultWhereClause)
.observeWithColumns(['alert', 'on_hold']); .observeWithColumns(['alert', 'on_hold', 'room_updated_at']);
// When we're NOT grouping // When we're NOT grouping
} else { } else {
this.count += QUERY_SIZE; this.count += QUERY_SIZE;
observable = await db observable = await db
.get('subscriptions') .get('subscriptions')
.query(...defaultWhereClause, Q.experimentalSkip(0), Q.experimentalTake(this.count)) .query(...defaultWhereClause, Q.experimentalSkip(0), Q.experimentalTake(this.count))
.observeWithColumns(['on_hold']); .observeWithColumns(['on_hold', 'room_updated_at']);
} }
this.querySubscription = observable.subscribe(data => { this.querySubscription = observable.subscribe(data => {
let tempChats = [] as TSubscriptionModel[]; let tempChats = [] as TSubscriptionModel[];
let chats = data; let chats = data.map(item => ({
rid: item.rid,
t: item.t,
prid: item.prid,
name: item.name,
fname: item.fname,
usernames: item.usernames,
// avatar: item.avatar,
// testID: item.testID,
status: item.status,
// isGroupChat: item.isGroupChat,
// isRead: item.isRead,
teamMain: item.teamMain,
roomUpdatedAt: item.roomUpdatedAt,
// date: item.date,
// accessibilityLabel: item.accessibilityLabel,
lastMessage: item.lastMessage,
favorite: item.f,
alert: item.alert,
hideUnreadStatus: item.hideUnreadStatus,
unread: item.unread,
userMentions: item.userMentions,
groupMentions: item.groupMentions,
tunread: item.tunread,
tunreadUser: item.tunreadUser,
tunreadGroup: item.tunreadGroup,
// size: item.size,
// sourceType: item.sourceType,
hideMentionStatus: item.hideMentionStatus,
onHold: item.onHold
}));
let omnichannelsUpdate: string[] = []; let omnichannelsUpdate: string[] = [];
const isOmnichannelAgent = user?.roles?.includes('livechat-agent'); const isOmnichannelAgent = user?.roles?.includes('livechat-agent');
@ -562,14 +592,15 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
} else if (showUnread || showFavorites || isOmnichannelAgent) { } else if (showUnread || showFavorites || isOmnichannelAgent) {
tempChats = this.addRoomsGroup(chats, CHATS_HEADER, tempChats); tempChats = this.addRoomsGroup(chats, CHATS_HEADER, tempChats);
} else { } else {
// @ts-ignore
tempChats = chats; tempChats = chats;
} }
const chatsUpdate = tempChats.map(item => item.rid); // const chatsUpdate = tempChats.map(item => item.rid);
this.internalSetState({ this.internalSetState({
chats: tempChats, chats: tempChats,
chatsUpdate, // chatsUpdate,
omnichannelsUpdate, omnichannelsUpdate,
loading: false loading: false
}); });
@ -983,20 +1014,17 @@ class RoomsListView extends React.Component<IRoomsListViewProps, IRoomsListViewS
<FlashList <FlashList
ref={this.getScrollRef} ref={this.getScrollRef}
data={searching ? search : chats} data={searching ? search : chats}
// extraData={searching ? search : chats} extraData={theme || refreshing || displayMode}
keyExtractor={keyExtractor} keyExtractor={keyExtractor}
// style={[styles.list, { backgroundColor: themes[theme].backgroundColor }]} // @ts-ignore
contentContainerStyle={[styles.list, { backgroundColor: themes[theme].backgroundColor }]}
renderItem={this.renderItem} renderItem={this.renderItem}
ListHeaderComponent={this.renderListHeader} ListHeaderComponent={this.renderListHeader}
estimatedItemSize={height} estimatedItemSize={height}
// getItemLayout={(data, index) => getItemLayout(data, index, height)}
// removeClippedSubviews={isIOS}
keyboardShouldPersistTaps='always' keyboardShouldPersistTaps='always'
// initialNumToRender={INITIAL_NUM_TO_RENDER}
refreshControl={ refreshControl={
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme].auxiliaryText} /> <RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme].auxiliaryText} />
} }
// windowSize={9}
onEndReached={this.onEndReached} onEndReached={this.onEndReached}
onEndReachedThreshold={0.5} onEndReachedThreshold={0.5}
/> />