diff --git a/app/containers/ConnectionBadge.js b/app/containers/ConnectionBadge.js deleted file mode 100644 index 4d935c88..00000000 --- a/app/containers/ConnectionBadge.js +++ /dev/null @@ -1,140 +0,0 @@ -import React, { Component } from 'react'; -import { - Text, StyleSheet, ActivityIndicator, Animated, Easing -} from 'react-native'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; - -import I18n from '../i18n'; -import debounce from '../utils/debounce'; -import sharedStyles from '../views/Styles'; -import { - COLOR_BACKGROUND_CONTAINER, COLOR_DANGER, COLOR_SUCCESS, COLOR_WHITE, COLOR_TEXT_DESCRIPTION -} from '../constants/colors'; - -const styles = StyleSheet.create({ - container: { - width: '100%', - position: 'absolute', - top: 0, - height: 41, - backgroundColor: COLOR_BACKGROUND_CONTAINER, - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'center', - elevation: 4 - }, - text: { - color: COLOR_WHITE, - fontSize: 15, - ...sharedStyles.textRegular - }, - textConnecting: { - ...sharedStyles.textColorDescription - }, - containerConnected: { - backgroundColor: COLOR_SUCCESS - }, - containerOffline: { - backgroundColor: COLOR_DANGER - }, - activityIndicator: { - marginRight: 15 - } -}); - -const ANIMATION_DURATION = 300; - -@connect(state => ({ - connecting: state.meteor.connecting, - connected: state.meteor.connected, - disconnected: !state.meteor.connecting && !state.meteor.connected -})) -class ConnectionBadge extends Component { - static propTypes = { - connecting: PropTypes.bool, - connected: PropTypes.bool, - disconnected: PropTypes.bool - } - - constructor(props) { - super(props); - this.animatedValue = new Animated.Value(0); - if (props.connecting) { - this.show(); - } - } - - componentDidUpdate() { - const { connected, disconnected } = this.props; - this.show(connected || disconnected); - } - - componentWillUnmount() { - if (this.timeout) { - clearTimeout(this.timeout); - } - } - - // eslint-disable-next-line react/sort-comp - animate = debounce((toValue, autoHide) => { - Animated.timing( - this.animatedValue, - { - toValue, - duration: ANIMATION_DURATION, - easing: Easing.ease, - useNativeDriver: true - }, - ).start(() => { - if (toValue === 1 && autoHide) { - if (this.timeout) { - clearTimeout(this.timeout); - } - this.timeout = setTimeout(() => { - this.hide(); - }, 1000); - } - }); - }, 300); - - show = (autoHide) => { - this.animate(1, autoHide); - } - - hide = () => { - this.animate(0); - } - - render() { - const { connecting, connected } = this.props; - - const translateY = this.animatedValue.interpolate({ - inputRange: [0, 1], - outputRange: [-42, 0] - }); - - if (connecting) { - return ( - - - {I18n.t('Connecting')} - - ); - } else if (connected) { - return ( - - {I18n.t('Connected')} - - ); - } - - return ( - - {I18n.t('Offline')} - - ); - } -} - -export default ConnectionBadge; diff --git a/app/views/RoomView/Header/Header.js b/app/views/RoomView/Header/Header.js index 2a6b9b5a..31a2725c 100644 --- a/app/views/RoomView/Header/Header.js +++ b/app/views/RoomView/Header/Header.js @@ -65,8 +65,34 @@ Typing.propTypes = { usersTyping: PropTypes.array }; +const HeaderTitle = React.memo(({ + title, scale, connecting, isFetching +}) => { + if (connecting) { + title = I18n.t('Connecting'); + } + if (isFetching) { + title = I18n.t('Updating'); + } + return ( + {title} + + ); +}); + +HeaderTitle.propTypes = { + title: PropTypes.string, + scale: PropTypes.number, + connecting: PropTypes.bool, + isFetching: PropTypes.bool +}; + const Header = React.memo(({ - title, type, status, usersTyping, width, height, prid, tmid, widthOffset + title, type, status, usersTyping, width, height, prid, tmid, widthOffset, connecting, isFetching }) => { const portrait = height > width; let scale = 1; @@ -93,7 +119,15 @@ const Header = React.memo(({ contentContainerStyle={styles.scroll} > - {title} + {type === 'thread' ? null : } @@ -110,7 +144,9 @@ Header.propTypes = { tmid: PropTypes.string, status: PropTypes.string, usersTyping: PropTypes.array, - widthOffset: PropTypes.number + widthOffset: PropTypes.number, + connecting: PropTypes.bool, + isFetching: PropTypes.bool }; Header.defaultProps = { diff --git a/app/views/RoomView/Header/index.js b/app/views/RoomView/Header/index.js index 54d0d4cd..b3b354bd 100644 --- a/app/views/RoomView/Header/index.js +++ b/app/views/RoomView/Header/index.js @@ -26,6 +26,7 @@ import RightButtons from './RightButtons'; } return { + connecting: state.meteor.connecting, userId, isLoggedUser, status @@ -40,6 +41,8 @@ export default class RoomHeaderView extends Component { rid: PropTypes.string, window: PropTypes.object, status: PropTypes.string, + connecting: PropTypes.bool, + isFetching: PropTypes.bool, widthOffset: PropTypes.number, isLoggedUser: PropTypes.bool, userId: PropTypes.string @@ -63,7 +66,7 @@ export default class RoomHeaderView extends Component { shouldComponentUpdate(nextProps, nextState) { const { usersTyping, user } = this.state; const { - type, title, status, window + type, title, status, window, connecting, isFetching } = this.props; if (nextProps.type !== type) { return true; @@ -74,6 +77,12 @@ export default class RoomHeaderView extends Component { if (nextProps.status !== status) { return true; } + if (nextProps.connecting !== connecting) { + return true; + } + if (nextProps.isFetching !== isFetching) { + return true; + } if (nextProps.window.width !== window.width) { return true; } @@ -102,7 +111,7 @@ export default class RoomHeaderView extends Component { render() { const { usersTyping, user } = this.state; const { - window, title, type, prid, tmid, widthOffset, isLoggedUser, status: userStatus + window, title, type, prid, tmid, widthOffset, isLoggedUser, status: userStatus, connecting, isFetching } = this.props; let status = 'offline'; @@ -125,6 +134,8 @@ export default class RoomHeaderView extends Component { height={window.height} usersTyping={usersTyping} widthOffset={widthOffset} + connecting={connecting} + isFetching={isFetching} /> ); } diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js index 4354ca1f..94e3ffce 100644 --- a/app/views/RoomView/index.js +++ b/app/views/RoomView/index.js @@ -31,7 +31,6 @@ import log from '../../utils/log'; import { isIOS } from '../../utils/deviceInfo'; import EventEmitter from '../../utils/events'; import I18n from '../../i18n'; -import ConnectionBadge from '../../containers/ConnectionBadge'; import RoomHeaderView, { RightButtons } from './Header'; import StatusBar from '../../containers/StatusBar'; import Separator from './Separator'; @@ -67,10 +66,19 @@ export default class RoomView extends LoggedView { const title = navigation.getParam('name'); const t = navigation.getParam('t'); const tmid = navigation.getParam('tmid'); + const isFetching = navigation.getParam('isFetching', false); return { headerTitleContainerStyle: styles.headerTitleContainerStyle, headerTitle: ( - + ), headerRight: }; @@ -312,14 +320,18 @@ export default class RoomView extends LoggedView { return ((room.prid || useRealName) && room.fname) || room.name; } - getMessages = () => { + getMessages = async() => { const { room } = this.state; + const { navigation } = this.props; try { + navigation.setParams({ isFetching: true }); if (room.lastOpen) { - return RocketChat.loadMissedMessages(room); + await RocketChat.loadMissedMessages(room); } else { - return RocketChat.loadMessagesForRoom(room); + await RocketChat.loadMessagesForRoom(room); } + navigation.setParams({ isFetching: false }); + return Promise.resolve(); } catch (e) { console.log('TCL: getMessages -> e', e); log('getMessages', e); @@ -519,7 +531,6 @@ export default class RoomView extends LoggedView { {this.renderActions()} - ); } diff --git a/app/views/RoomsListView/Header/Header.android.js b/app/views/RoomsListView/Header/Header.android.js index 136563ea..a2393caf 100644 --- a/app/views/RoomsListView/Header/Header.android.js +++ b/app/views/RoomsListView/Header/Header.android.js @@ -42,8 +42,8 @@ const styles = StyleSheet.create({ } }); -const Header = ({ - isFetching, serverName, showServerDropdown, setSearchInputRef, showSearchHeader, onSearchChangeText, onPress +const Header = React.memo(({ + connecting, isFetching, serverName, showServerDropdown, setSearchInputRef, showSearchHeader, onSearchChangeText, onPress }) => { if (showSearchHeader) { return ( @@ -61,6 +61,7 @@ const Header = ({ return ( + {connecting ? {I18n.t('Connecting')} : null} {isFetching ? {I18n.t('Updating')} : null} {serverName} @@ -69,7 +70,7 @@ const Header = ({ ); -}; +}); Header.propTypes = { showServerDropdown: PropTypes.bool.isRequired, @@ -77,6 +78,7 @@ Header.propTypes = { onPress: PropTypes.func.isRequired, onSearchChangeText: PropTypes.func.isRequired, setSearchInputRef: PropTypes.func.isRequired, + connecting: PropTypes.bool, isFetching: PropTypes.bool, serverName: PropTypes.string }; diff --git a/app/views/RoomsListView/Header/Header.ios.js b/app/views/RoomsListView/Header/Header.ios.js index 64836a11..20d6f9b1 100644 --- a/app/views/RoomsListView/Header/Header.ios.js +++ b/app/views/RoomsListView/Header/Header.ios.js @@ -39,15 +39,18 @@ const styles = StyleSheet.create({ } }); -const HeaderTitle = ({ isFetching }) => { +const HeaderTitle = React.memo(({ connecting, isFetching }) => { + if (connecting) { + return {I18n.t('Connecting')}; + } if (isFetching) { return {I18n.t('Updating')}; } return {I18n.t('Messages')}; -}; +}); -const Header = ({ - isFetching, serverName, showServerDropdown, onPress +const Header = React.memo(({ + connecting, isFetching, serverName, showServerDropdown, onPress }) => ( - + {serverName} -); +)); Header.propTypes = { + connecting: PropTypes.bool, isFetching: PropTypes.bool, serverName: PropTypes.string, showServerDropdown: PropTypes.bool.isRequired, @@ -76,6 +80,7 @@ Header.defaultProps = { }; HeaderTitle.propTypes = { + connecting: PropTypes.bool, isFetching: PropTypes.bool }; diff --git a/app/views/RoomsListView/Header/index.js b/app/views/RoomsListView/Header/index.js index 3d156f2f..853602b5 100644 --- a/app/views/RoomsListView/Header/index.js +++ b/app/views/RoomsListView/Header/index.js @@ -11,6 +11,7 @@ import Header from './Header'; showServerDropdown: state.rooms.showServerDropdown, showSortDropdown: state.rooms.showSortDropdown, showSearchHeader: state.rooms.showSearchHeader, + connecting: state.meteor.connecting, isFetching: state.rooms.isFetching, serverName: state.settings.Site_Name }), dispatch => ({ @@ -25,6 +26,7 @@ export default class RoomsListHeaderView extends PureComponent { showSortDropdown: PropTypes.bool, showSearchHeader: PropTypes.bool, serverName: PropTypes.string, + connecting: PropTypes.bool, isFetching: PropTypes.bool, open: PropTypes.func, close: PropTypes.func, @@ -68,13 +70,15 @@ export default class RoomsListHeaderView extends PureComponent { render() { const { - serverName, showServerDropdown, showSearchHeader, isFetching + serverName, showServerDropdown, showSearchHeader, connecting, isFetching } = this.props; + return (
: null} - BackHandler.addEventListener('hardwareBackPress', this.handleBackPress)} onWillBlur={() => BackHandler.removeEventListener('hardwareBackPress', this.handleBackPress)}