Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/containers/MessageBox/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default StyleSheet.create({
},
textBoxInput: {
textAlignVertical: 'center',
maxHeight: 242,
maxHeight: 230,
flexGrow: 1,
width: 1,
// paddingVertical: 12, needs to be paddingTop/paddingBottom because of iOS/Android's TextInput differences on rendering
Expand Down
115 changes: 88 additions & 27 deletions app/views/RoomView/List.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React from 'react';
import { FlatList, InteractionManager, RefreshControl } from 'react-native';
import {
FlatList, InteractionManager, RefreshControl, Animated, View
} from 'react-native';
import PropTypes from 'prop-types';
import orderBy from 'lodash/orderBy';
import { Q } from '@nozbe/watermelondb';
Expand All @@ -12,11 +14,15 @@ import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import EmptyRoom from './EmptyRoom';
import { isIOS } from '../../utils/deviceInfo';
import Touch from '../../utils/touch';
import { CustomIcon } from '../../lib/Icons';
import { animateNextTransition } from '../../utils/layoutAnimation';
import ActivityIndicator from '../../containers/ActivityIndicator';
import debounce from '../../utils/debounce';
import { themes } from '../../constants/colors';

const AnimatedTouch = Animated.createAnimatedComponent(Touch);

class List extends React.Component {
static propTypes = {
onEndReached: PropTypes.func,
Expand All @@ -36,6 +42,8 @@ class List extends React.Component {
console.time(`${ this.constructor.name } mount`);

this.mounted = false;
this.contentOffsetY = 0;
this.scrollButtonTranslateY = new Animated.Value(300);
this.state = {
loading: true,
end: false,
Expand Down Expand Up @@ -212,6 +220,48 @@ class List extends React.Component {
return null;
}

handleScrollButtonAnimation = (isVisible, toValue) => {
this.isScrollButtonVisible = isVisible;
Animated.timing(
this.scrollButtonTranslateY,
{
toValue,
duration: 200,
useNativeDriver: true
}
).start();
}


toggleScrollToBottomButton = (e) => {
const { y } = e.nativeEvent.contentOffset;
this.contentOffsetY = y;
if (y > 200 && !this.isScrollButtonVisible) {
this.handleScrollButtonAnimation(true, 0);
} else if (y <= 200 && this.isScrollButtonVisible) {
this.handleScrollButtonAnimation(false, 300);
}
}

scrollToBottom = () => {
this.flatList.scrollToIndex({ animated: this.contentOffsetY < 2000, index: 0 });
this.handleScrollButtonAnimation(false, 300);
}

renderScrollButton = () => {
const { scrollButtonTranslateY, scrollToBottom } = this;
const { theme } = this.props;
return (
<AnimatedTouch
theme={theme}
onPress={scrollToBottom}
style={[styles.scrollButton, { backgroundColor: themes[theme].bannerBackground, borderColor: themes[theme].borderColor, transform: [{ translateY: scrollButtonTranslateY }] }]}
>
<CustomIcon name='arrow-down' size={30} style={{ color: themes[theme].tintColor }} />
</AnimatedTouch>
);
}

renderFooter = () => {
const { loading } = this.state;
const { rid, theme } = this.props;
Expand All @@ -227,6 +277,8 @@ class List extends React.Component {
return renderRow(item, messages[index + 1]);
}

setListRef = ref => this.flatList = ref;

render() {
console.count(`${ this.constructor.name }.render calls`);
const { rid, listRef } = this.props;
Expand All @@ -235,32 +287,41 @@ class List extends React.Component {
return (
<>
<EmptyRoom rid={rid} length={messages.length} mounted={this.mounted} theme={theme} />
<FlatList
testID='room-view-messages'
ref={listRef}
keyExtractor={item => item.id}
data={messages}
extraData={this.state}
renderItem={this.renderItem}
contentContainerStyle={styles.contentContainer}
style={styles.list}
inverted
removeClippedSubviews={isIOS}
initialNumToRender={7}
onEndReached={this.onEndReached}
onEndReachedThreshold={5}
maxToRenderPerBatch={5}
windowSize={10}
ListFooterComponent={this.renderFooter}
refreshControl={(
<RefreshControl
refreshing={refreshing}
onRefresh={this.onRefresh}
tintColor={themes[theme].auxiliaryText}
/>
)}
{...scrollPersistTaps}
/>
<View style={styles.listContainer}>
<FlatList
testID='room-view-messages'
ref={(ref) => {
listRef(ref);
this.setListRef(ref);
}}
keyExtractor={item => item.id}
data={messages}
extraData={this.state}
renderItem={this.renderItem}
contentContainerStyle={styles.contentContainer}
style={styles.list}
inverted
removeClippedSubviews={isIOS}
initialNumToRender={7}
onEndReached={this.onEndReached}
onEndReachedThreshold={5}
maxToRenderPerBatch={5}
windowSize={10}
scrollEventThrottle={8}
onScroll={this.toggleScrollToBottomButton}
onScrollEndDrag={this.toggleScrollToBottomButton}
ListFooterComponent={this.renderFooter}
refreshControl={(
<RefreshControl
refreshing={refreshing}
onRefresh={this.onRefresh}
tintColor={themes[theme].auxiliaryText}
/>
)}
{...scrollPersistTaps}
/>
{this.renderScrollButton()}
</View>
</>
);
}
Expand Down
16 changes: 16 additions & 0 deletions app/views/RoomView/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ export default StyleSheet.create({
safeAreaView: {
flex: 1
},
listContainer: {
flex: 1,
position: 'relative'
},
list: {
flex: 1
},
Expand Down Expand Up @@ -46,5 +50,17 @@ export default StyleSheet.create({
previewMode: {
fontSize: 16,
...sharedStyles.textMedium
},
scrollButton: {
position: 'absolute',
bottom: 20,
right: 20,
height: 50,
width: 50,
borderRadius: 25,
borderWidth: 1,
alignItems: 'center',
justifyContent: 'center',
zIndex: 0
Comment thread
Prateek93a marked this conversation as resolved.
Resolved
}
});