diff --git a/app/animations/collapse.js b/app/animations/collapse.js
deleted file mode 100644
index e04895c97..000000000
--- a/app/animations/collapse.js
+++ /dev/null
@@ -1,77 +0,0 @@
-import { View, Animated } from 'react-native';
-
-import PropTypes from 'prop-types';
-import React from 'react';
-
-export default class Panel extends React.Component {
- static propTypes = {
- open: PropTypes.bool.isRequired,
- children: PropTypes.node.isRequired,
- style: PropTypes.object
- }
-
- constructor(props) {
- super(props);
- this.state = {
- animation: new Animated.Value()
- };
- this.first = true;
- this.open = false;
- this.opacity = 0;
- }
-
- componentDidMount() {
- const { animation } = this.state;
- const { open } = this.props;
- const initialValue = !open ? this.height : 0;
- animation.setValue(initialValue);
- }
-
- componentWillReceiveProps(nextProps) {
- const { animation } = this.state;
- const { open } = this.props;
-
- if (this.first) {
- this.first = false;
- if (!open) {
- animation.setValue(0);
- return;
- }
- }
- if (this.open === nextProps.open) {
- return;
- }
- this.open = nextProps.open;
- const initialValue = !nextProps.open ? this.height : 0;
- const finalValue = !nextProps.open ? 0 : this.height;
-
- animation.setValue(initialValue);
- Animated.timing(
- animation,
- {
- toValue: finalValue,
- duration: 150,
- useNativeDriver: true
- }
- ).start();
- }
-
- set _height(h) {
- this.height = h || this.height;
- }
-
- render() {
- const { animation } = this.state;
- const { style, children } = this.props;
-
- return (
-
- this._height = nativeEvent.layout.height} style={{ position: !this.first ? 'relative' : 'absolute' }}>
- {children}
-
-
- );
- }
-}
diff --git a/app/animations/fade.js b/app/animations/fade.js
deleted file mode 100644
index 513625816..000000000
--- a/app/animations/fade.js
+++ /dev/null
@@ -1,63 +0,0 @@
-import PropTypes from 'prop-types';
-import React from 'react';
-import { Animated, Text } from 'react-native';
-
-export default class Fade extends React.Component {
- static propTypes = {
- visible: PropTypes.bool.isRequired,
- style: Animated.View.propTypes.style,
- children: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.node),
- PropTypes.node
- ])
- }
-
- constructor(props) {
- super(props);
- const { visible } = this.props;
- this.state = {
- visible
- };
- this._visibility = new Animated.Value(visible ? 1 : 0);
- }
-
- componentWillReceiveProps(nextProps) {
- if (nextProps.visible) {
- this.setState({ visible: true });
- }
- Animated.timing(this._visibility, {
- toValue: nextProps.visible ? 1 : 0,
- duration: 300,
- useNativeDriver: true
- }).start(() => {
- this.setState({ visible: nextProps.visible });
- });
- }
-
- render() {
- const { visible } = this.state;
- const { style, children, ...rest } = this.props;
-
- const containerStyle = {
- opacity: this._visibility.interpolate({
- inputRange: [0, 1],
- outputRange: [0, 1]
- }),
- transform: [
- {
- scale: this._visibility.interpolate({
- inputRange: [0, 1],
- outputRange: [1.1, 1]
- })
- }
- ]
- };
-
- const combinedStyle = [containerStyle, style];
- return (
-
- {visible ? children : null}
-
- );
- }
-}
diff --git a/app/index.js b/app/index.js
index 96da474c0..bdc378aec 100644
--- a/app/index.js
+++ b/app/index.js
@@ -19,6 +19,7 @@ import { defaultHeader, onNavigationStateChange } from './utils/navigation';
import { loggerConfig, analytics } from './utils/log';
import Toast from './containers/Toast';
import RocketChat from './lib/rocketchat';
+import LayoutAnimation from './utils/layoutAnimation';
useScreens();
@@ -308,12 +309,14 @@ export default class Root extends React.Component {
render() {
return (
- {
- Navigation.setTopLevelNavigator(navigatorRef);
- }}
- onNavigationStateChange={onNavigationStateChange}
- />
+
+ {
+ Navigation.setTopLevelNavigator(navigatorRef);
+ }}
+ onNavigationStateChange={onNavigationStateChange}
+ />
+
);
}
diff --git a/app/share.js b/app/share.js
index 2374afe2a..73d6f06b4 100644
--- a/app/share.js
+++ b/app/share.js
@@ -11,6 +11,7 @@ import sharedStyles from './views/Styles';
import { isNotch, isIOS } from './utils/deviceInfo';
import { defaultHeader, onNavigationStateChange } from './utils/navigation';
import RocketChat from './lib/rocketchat';
+import LayoutAnimation from './utils/layoutAnimation';
const InsideNavigator = createStackNavigator({
ShareListView: {
@@ -84,12 +85,14 @@ class Root extends React.Component {
onLayout={this.handleLayout}
>
- {
- Navigation.setTopLevelNavigator(navigatorRef);
- }}
- onNavigationStateChange={onNavigationStateChange}
- />
+
+ {
+ Navigation.setTopLevelNavigator(navigatorRef);
+ }}
+ onNavigationStateChange={onNavigationStateChange}
+ />
+
);
diff --git a/app/utils/layoutAnimation.js b/app/utils/layoutAnimation.js
new file mode 100644
index 000000000..a558404cd
--- /dev/null
+++ b/app/utils/layoutAnimation.js
@@ -0,0 +1,44 @@
+import React from 'react';
+import { Transition, Transitioning } from 'react-native-reanimated';
+import PropTypes from 'prop-types';
+
+import debounce from './debounce';
+import { isIOS } from './deviceInfo';
+import sharedStyles from '../views/Styles';
+
+const transition = (
+
+
+
+
+
+);
+
+const TRANSITION_REF = React.createRef();
+
+export const animateNextTransition = debounce(() => {
+ if (isIOS) {
+ TRANSITION_REF.current.animateNextTransition();
+ }
+}, 200, true);
+
+const LayoutAnimation = ({ children }) => {
+ if (isIOS) {
+ return (
+
+ {children}
+
+ );
+ }
+ return children;
+};
+
+LayoutAnimation.propTypes = {
+ children: PropTypes.node
+};
+
+export default LayoutAnimation;
diff --git a/app/views/LoginView.js b/app/views/LoginView.js
index 435d173ff..87c9cf34f 100644
--- a/app/views/LoginView.js
+++ b/app/views/LoginView.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
- Keyboard, Text, ScrollView, View, StyleSheet, Alert, LayoutAnimation
+ Keyboard, Text, ScrollView, View, StyleSheet, Alert
} from 'react-native';
import { connect } from 'react-redux';
import { SafeAreaView } from 'react-navigation';
@@ -18,6 +18,7 @@ import { loginRequest as loginRequestAction } from '../actions/login';
import { LegalButton } from '../containers/HeaderButton';
import StatusBar from '../containers/StatusBar';
import { COLOR_PRIMARY } from '../constants/colors';
+import { animateNextTransition } from '../utils/layoutAnimation';
const styles = StyleSheet.create({
bottomContainer: {
@@ -84,7 +85,7 @@ class LoginView extends React.Component {
this.setTitle(nextProps.Site_Name);
} else if (nextProps.failure && !equal(error, nextProps.error)) {
if (nextProps.error && nextProps.error.error === 'totp-required') {
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
this.setState({ showTOTP: true });
return;
}
diff --git a/app/views/NewServerView.js b/app/views/NewServerView.js
index 58755a65e..92759700c 100644
--- a/app/views/NewServerView.js
+++ b/app/views/NewServerView.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
- Text, ScrollView, Keyboard, Image, StyleSheet, TouchableOpacity, View, Alert, LayoutAnimation
+ Text, ScrollView, Keyboard, Image, StyleSheet, TouchableOpacity, View, Alert
} from 'react-native';
import { connect } from 'react-redux';
import { SafeAreaView } from 'react-navigation';
@@ -23,6 +23,7 @@ import { CustomIcon } from '../lib/Icons';
import StatusBar from '../containers/StatusBar';
import { COLOR_PRIMARY } from '../constants/colors';
import log from '../utils/log';
+import { animateNextTransition } from '../utils/layoutAnimation';
const styles = StyleSheet.create({
image: {
@@ -195,7 +196,7 @@ class NewServerView extends React.Component {
uriToPath = uri => uri.replace('file://', '');
saveCertificate = (certificate) => {
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
this.setState({ certificate });
}
diff --git a/app/views/RoomView/List.js b/app/views/RoomView/List.js
index 3ed35e2a0..4bae8096a 100644
--- a/app/views/RoomView/List.js
+++ b/app/views/RoomView/List.js
@@ -1,6 +1,6 @@
import React from 'react';
import {
- ActivityIndicator, FlatList, InteractionManager, LayoutAnimation
+ ActivityIndicator, FlatList, InteractionManager
} from 'react-native';
import PropTypes from 'prop-types';
import debounce from 'lodash/debounce';
@@ -15,6 +15,7 @@ import RocketChat from '../../lib/rocketchat';
import log from '../../utils/log';
import EmptyRoom from './EmptyRoom';
import { isIOS } from '../../utils/deviceInfo';
+import { animateNextTransition } from '../../utils/layoutAnimation';
export class List extends React.Component {
static propTypes = {
@@ -83,7 +84,7 @@ export class List extends React.Component {
}
const messages = orderBy(data, ['ts'], ['desc']);
if (this.mounted) {
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
this.setState({ messages });
} else {
this.state.messages = messages;
@@ -186,11 +187,11 @@ export class List extends React.Component {
style={styles.list}
inverted
removeClippedSubviews={isIOS}
- initialNumToRender={7}
+ // initialNumToRender={7}
onEndReached={this.onEndReached}
- onEndReachedThreshold={5}
- maxToRenderPerBatch={5}
- windowSize={10}
+ // onEndReachedThreshold={5}
+ // maxToRenderPerBatch={5}
+ // windowSize={10}
ListFooterComponent={this.renderFooter}
{...scrollPersistTaps}
/>
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index 218a7e50f..05dc9677a 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -1,8 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import {
- Text, View, InteractionManager, LayoutAnimation
-} from 'react-native';
+import { Text, View, InteractionManager } from 'react-native';
import { connect } from 'react-redux';
import { RectButton } from 'react-native-gesture-handler';
import { SafeAreaView } from 'react-navigation';
@@ -484,15 +482,11 @@ class RoomView extends React.Component {
if (!this.mounted) {
return;
}
- if (isIOS && this.beginAnimating) {
- LayoutAnimation.easeInEaseOut();
- }
this.setState(...args);
}
sendMessage = (message, tmid) => {
const { user } = this.props;
- LayoutAnimation.easeInEaseOut();
RocketChat.sendMessage(this.rid, message, this.tmid || tmid, user).then(() => {
this.setLastOpen(null);
});
diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js
index 1cda64fe6..94783eeea 100644
--- a/app/views/RoomsListView/index.js
+++ b/app/views/RoomsListView/index.js
@@ -8,7 +8,6 @@ import {
Text,
ScrollView,
Keyboard,
- LayoutAnimation,
Dimensions
} from 'react-native';
import { connect } from 'react-redux';
@@ -43,6 +42,7 @@ import {
import StatusBar from '../../containers/StatusBar';
import ListHeader from './ListHeader';
import { selectServerRequest as selectServerRequestAction } from '../../actions/server';
+import { animateNextTransition } from '../../utils/layoutAnimation';
const SCROLL_OFFSET = 56;
@@ -290,8 +290,8 @@ class RoomsListView extends React.Component {
// eslint-disable-next-line react/sort-comp
internalSetState = (...args) => {
const { navigation } = this.props;
- if (isIOS && navigation.isFocused()) {
- LayoutAnimation.easeInEaseOut();
+ if (navigation.isFocused()) {
+ animateNextTransition();
}
this.setState(...args);
};
diff --git a/app/views/SelectedUsersView.js b/app/views/SelectedUsersView.js
index 3b39c13d5..b9209f7d7 100644
--- a/app/views/SelectedUsersView.js
+++ b/app/views/SelectedUsersView.js
@@ -1,8 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
-import {
- View, StyleSheet, FlatList, LayoutAnimation
-} from 'react-native';
+import { View, StyleSheet, FlatList } from 'react-native';
import { connect } from 'react-redux';
import { SafeAreaView } from 'react-navigation';
import equal from 'deep-equal';
@@ -25,6 +23,7 @@ import sharedStyles from './Styles';
import { Item, CustomHeaderButtons } from '../containers/HeaderButton';
import StatusBar from '../containers/StatusBar';
import { COLOR_WHITE } from '../constants/colors';
+import { animateNextTransition } from '../utils/layoutAnimation';
const styles = StyleSheet.create({
safeAreaView: {
@@ -169,7 +168,7 @@ class SelectedUsersView extends React.Component {
toggleUser = (user) => {
const { addUser, removeUser } = this.props;
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
if (!this.isChecked(user.name)) {
addUser(user);
} else {
diff --git a/app/views/ShareListView/Header/Header.ios.js b/app/views/ShareListView/Header/Header.ios.js
index fabe3c499..d67348818 100644
--- a/app/views/ShareListView/Header/Header.ios.js
+++ b/app/views/ShareListView/Header/Header.ios.js
@@ -1,8 +1,6 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
-import {
- Keyboard, LayoutAnimation, View, StyleSheet
-} from 'react-native';
+import { Keyboard, View, StyleSheet } from 'react-native';
import ShareExtension from 'rn-extensions-share';
import SearchBox from '../../../containers/SearchBox';
@@ -10,6 +8,7 @@ import { CloseShareExtensionButton } from '../../../containers/HeaderButton';
import { HEADER_BACKGROUND } from '../../../constants/colors';
import sharedStyles from '../../Styles';
+import { animateNextTransition } from '../../../utils/layoutAnimation';
const styles = StyleSheet.create({
container: {
@@ -33,12 +32,12 @@ const Header = React.memo(({
Keyboard.dismiss();
onChangeText('');
cancelSearch();
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
};
const onFocus = () => {
initSearch();
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
};
return (
diff --git a/app/views/ShareListView/index.js b/app/views/ShareListView/index.js
index b6ce99b3f..446da3580 100644
--- a/app/views/ShareListView/index.js
+++ b/app/views/ShareListView/index.js
@@ -1,7 +1,7 @@
import React from 'react';
import PropTypes from 'prop-types';
import {
- View, Text, LayoutAnimation, FlatList, ActivityIndicator, Keyboard, BackHandler
+ View, Text, FlatList, ActivityIndicator, Keyboard, BackHandler
} from 'react-native';
import { SafeAreaView } from 'react-navigation';
import ShareExtension from 'rn-extensions-share';
@@ -25,6 +25,7 @@ import ShareListHeader from './Header';
import styles from './styles';
import StatusBar from '../../containers/StatusBar';
+import { animateNextTransition } from '../../utils/layoutAnimation';
const LIMIT = 50;
const getItemLayout = (data, index) => ({ length: ROW_HEIGHT, offset: ROW_HEIGHT * index, index });
@@ -174,8 +175,8 @@ class ShareListView extends React.Component {
// eslint-disable-next-line react/sort-comp
internalSetState = (...args) => {
const { navigation } = this.props;
- if (isIOS && navigation.isFocused()) {
- LayoutAnimation.easeInEaseOut();
+ if (navigation.isFocused()) {
+ animateNextTransition();
}
this.setState(...args);
}
diff --git a/app/views/SidebarView/index.js b/app/views/SidebarView/index.js
index 099702f2a..1341e284f 100644
--- a/app/views/SidebarView/index.js
+++ b/app/views/SidebarView/index.js
@@ -1,7 +1,7 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
- ScrollView, Text, View, FlatList, LayoutAnimation, SafeAreaView
+ ScrollView, Text, View, FlatList, SafeAreaView
} from 'react-native';
import { connect } from 'react-redux';
import equal from 'deep-equal';
@@ -20,6 +20,7 @@ import styles from './styles';
import SidebarItem from './SidebarItem';
import { COLOR_TEXT } from '../../constants/colors';
import database from '../../lib/database';
+import { animateNextTransition } from '../../utils/layoutAnimation';
const keyExtractor = item => item.id;
@@ -147,7 +148,7 @@ class Sidebar extends Component {
}
toggleStatus = () => {
- LayoutAnimation.easeInEaseOut();
+ animateNextTransition();
this.setState(prevState => ({ showStatus: !prevState.showStatus }));
}
diff --git a/app/views/Styles.js b/app/views/Styles.js
index 041f9ea05..4861380af 100644
--- a/app/views/Styles.js
+++ b/app/views/Styles.js
@@ -5,6 +5,9 @@ import {
} from '../constants/colors';
export default StyleSheet.create({
+ root: {
+ flex: 1
+ },
container: {
backgroundColor: 'white',
flex: 1