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:
parent
05c1798a58
commit
18f359a8ef
|
@ -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}
|
||||||
|
|
|
@ -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;
|
|
@ -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} />
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
@ -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}
|
||||||
|
|
Loading…
Reference in New Issue