Regression: Poor performance in messages list on Android (#4536)

* Create custom RefreshControl as a workaround

* Remove unnecessary FlatList rngh change
This commit is contained in:
Diego Mello 2022-09-22 09:49:59 -03:00
parent 449934e1fd
commit 9472916a94
4 changed files with 70 additions and 28 deletions

View File

@ -31,7 +31,7 @@ const List = ({ listRef, ...props }: IListProps) => (
keyExtractor={(item: any) => item.id} keyExtractor={(item: any) => item.id}
contentContainerStyle={styles.contentContainer} contentContainerStyle={styles.contentContainer}
style={styles.list} style={styles.list}
inverted inverted={isIOS}
removeClippedSubviews={isIOS} removeClippedSubviews={isIOS}
initialNumToRender={7} initialNumToRender={7}
onEndReachedThreshold={0.5} onEndReachedThreshold={0.5}

View File

@ -0,0 +1,40 @@
import React from 'react';
import { RefreshControl as RNRefreshControl, RefreshControlProps, StyleSheet } from 'react-native';
import { useTheme } from '../../../theme';
import { isAndroid } from '../../../lib/methods/helpers';
const style = StyleSheet.create({
container: {
flex: 1
},
inverted: {
scaleY: -1
}
});
interface IRefreshControl extends RefreshControlProps {
children: React.ReactElement;
}
const RefreshControl = ({ children, onRefresh, refreshing }: IRefreshControl): React.ReactElement => {
const { colors } = useTheme();
if (isAndroid) {
return (
<RNRefreshControl
onRefresh={onRefresh}
refreshing={refreshing}
tintColor={colors.auxiliaryText}
style={[style.container, style.inverted]}
>
{children}
</RNRefreshControl>
);
}
const refreshControl = <RNRefreshControl onRefresh={onRefresh} refreshing={refreshing} tintColor={colors.auxiliaryText} />;
return React.cloneElement(children, { refreshControl });
};
export default RefreshControl;

View File

@ -2,12 +2,10 @@ import { Q } from '@nozbe/watermelondb';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import moment from 'moment'; import moment from 'moment';
import React from 'react'; import React from 'react';
import { FlatListProps, RefreshControl, ViewToken } from 'react-native'; import { FlatListProps, View, ViewToken, StyleSheet, Platform } from 'react-native';
import { event, Value } from 'react-native-reanimated'; import { event, Value } from 'react-native-reanimated';
import { Observable, Subscription } from 'rxjs'; import { Observable, Subscription } from 'rxjs';
import { TSupportedThemes } from '../../../theme';
import { themes } from '../../../lib/constants';
import ActivityIndicator from '../../../containers/ActivityIndicator'; import ActivityIndicator from '../../../containers/ActivityIndicator';
import { TAnyMessageModel, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions'; import { TAnyMessageModel, TMessageModel, TThreadMessageModel, TThreadModel } from '../../../definitions';
import database from '../../../lib/database'; import database from '../../../lib/database';
@ -19,9 +17,20 @@ import List, { IListProps, TListRef } from './List';
import NavBottomFAB from './NavBottomFAB'; import NavBottomFAB from './NavBottomFAB';
import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods'; import { loadMissedMessages, loadThreadMessages } from '../../../lib/methods';
import { Services } from '../../../lib/services'; import { Services } from '../../../lib/services';
import RefreshControl from './RefreshControl';
const QUERY_SIZE = 50; const QUERY_SIZE = 50;
const styles = StyleSheet.create({
inverted: {
...Platform.select({
android: {
scaleY: -1
}
})
}
});
const onScroll = ({ y }: { y: Value<number> }) => const onScroll = ({ y }: { y: Value<number> }) =>
event( event(
[ [
@ -40,7 +49,6 @@ export interface IListContainerProps {
renderRow: Function; renderRow: Function;
rid: string; rid: string;
tmid?: string; tmid?: string;
theme: TSupportedThemes;
loading: boolean; loading: boolean;
listRef: TListRef; listRef: TListRef;
hideSystemMessages?: string[]; hideSystemMessages?: string[];
@ -98,10 +106,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
shouldComponentUpdate(nextProps: IListContainerProps, nextState: IListContainerState) { shouldComponentUpdate(nextProps: IListContainerProps, nextState: IListContainerState) {
const { refreshing, highlightedMessage } = this.state; const { refreshing, highlightedMessage } = this.state;
const { hideSystemMessages, theme, tunread, ignored, loading } = this.props; const { hideSystemMessages, tunread, ignored, loading } = this.props;
if (theme !== nextProps.theme) {
return true;
}
if (loading !== nextProps.loading) { if (loading !== nextProps.loading) {
return true; return true;
} }
@ -348,7 +353,7 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
renderItem: FlatListProps<any>['renderItem'] = ({ item, index }) => { renderItem: FlatListProps<any>['renderItem'] = ({ item, index }) => {
const { messages, highlightedMessage } = this.state; const { messages, highlightedMessage } = this.state;
const { renderRow } = this.props; const { renderRow } = this.props;
return renderRow(item, messages[index + 1], highlightedMessage); return <View style={styles.inverted}>{renderRow(item, messages[index + 1], highlightedMessage)}</View>;
}; };
onViewableItemsChanged: FlatListProps<any>['onViewableItemsChanged'] = ({ viewableItems }) => { onViewableItemsChanged: FlatListProps<any>['onViewableItemsChanged'] = ({ viewableItems }) => {
@ -359,25 +364,23 @@ class ListContainer extends React.Component<IListContainerProps, IListContainerS
console.count(`${this.constructor.name}.render calls`); console.count(`${this.constructor.name}.render calls`);
const { rid, tmid, listRef } = this.props; const { rid, tmid, listRef } = this.props;
const { messages, refreshing } = this.state; const { messages, refreshing } = this.state;
const { theme } = this.props;
return ( return (
<> <>
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} /> <EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} />
<List <RefreshControl refreshing={refreshing} onRefresh={this.onRefresh}>
onScroll={this.onScroll} <List
scrollEventThrottle={16} onScroll={this.onScroll}
listRef={listRef} scrollEventThrottle={16}
data={messages} listRef={listRef}
renderItem={this.renderItem} data={messages}
onEndReached={this.onEndReached} renderItem={this.renderItem}
ListFooterComponent={this.renderFooter} onEndReached={this.onEndReached}
onScrollToIndexFailed={this.handleScrollToIndexFailed} ListFooterComponent={this.renderFooter}
onViewableItemsChanged={this.onViewableItemsChanged} onScrollToIndexFailed={this.handleScrollToIndexFailed}
viewabilityConfig={this.viewabilityConfig} onViewableItemsChanged={this.onViewableItemsChanged}
refreshControl={ viewabilityConfig={this.viewabilityConfig}
<RefreshControl refreshing={refreshing} onRefresh={this.onRefresh} tintColor={themes[theme].auxiliaryText} /> />
} </RefreshControl>
/>
<NavBottomFAB y={this.y} onPress={this.jumpToBottom} isThread={!!tmid} /> <NavBottomFAB y={this.y} onPress={this.jumpToBottom} isThread={!!tmid} />
</> </>
); );

View File

@ -1365,8 +1365,8 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
if (showUnreadSeparator || dateSeparator) { if (showUnreadSeparator || dateSeparator) {
return ( return (
<> <>
{content}
<Separator ts={dateSeparator} unread={showUnreadSeparator} /> <Separator ts={dateSeparator} unread={showUnreadSeparator} />
{content}
</> </>
); );
} }
@ -1514,7 +1514,6 @@ class RoomView extends React.Component<IRoomViewProps, IRoomViewState> {
listRef={this.flatList} listRef={this.flatList}
rid={rid} rid={rid}
tmid={this.tmid} tmid={this.tmid}
theme={theme}
tunread={tunread} tunread={tunread}
ignored={ignored} ignored={ignored}
renderRow={this.renderItem} renderRow={this.renderItem}