diff --git a/app/containers/ConnectionBadge.js b/app/containers/ConnectionBadge.js
new file mode 100644
index 000000000..99a186dc6
--- /dev/null
+++ b/app/containers/ConnectionBadge.js
@@ -0,0 +1,144 @@
+import React, { Component } from 'react';
+import {
+ Text, StyleSheet, ActivityIndicator, Animated, TouchableWithoutFeedback, Easing
+} from 'react-native';
+import { connect } from 'react-redux';
+import PropTypes from 'prop-types';
+
+import I18n from '../i18n';
+
+const styles = StyleSheet.create({
+ container: {
+ width: '100%',
+ position: 'absolute',
+ top: 0,
+ height: 41,
+ backgroundColor: '#F7F8FA',
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ elevation: 4
+ },
+ text: {
+ color: '#fff',
+ fontSize: 15,
+ fontWeight: 'normal'
+ },
+ textConnecting: {
+ color: '#9EA2A8'
+ },
+ containerConnected: {
+ backgroundColor: '#2de0a5'
+ },
+ containerOffline: {
+ backgroundColor: '#f5455c'
+ },
+ 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.state = {
+ visible: false
+ };
+ this.animatedValue = new Animated.Value(0);
+ }
+
+ componentDidMount() {
+ const { connecting, disconnected } = this.props;
+ if (connecting || disconnected) {
+ this.animate(1);
+ }
+ }
+
+ componentDidUpdate(prevProps) {
+ const { visible } = this.state;
+ const { connecting, connected, disconnected } = this.props;
+
+ if ((connecting && connecting !== prevProps.connecting) || (disconnected && disconnected !== prevProps.disconnected)) {
+ if (!visible) {
+ this.animate(1);
+ }
+ } else if (connected && connected !== prevProps.connected) {
+ if (visible) {
+ setTimeout(() => {
+ this.animate(0);
+ }, 1000);
+ }
+ }
+ }
+
+ animate = (toValue) => {
+ Animated.timing(
+ this.animatedValue,
+ {
+ toValue,
+ duration: ANIMATION_DURATION,
+ easing: Easing.ease,
+ useNativeDriver: true
+ },
+ ).start(() => this.setState({ visible: toValue === 1 }));
+ }
+
+ show = () => {
+ this.animate(1);
+ }
+
+ hide = () => {
+ this.animate(0);
+ }
+
+ render() {
+ const { connecting, connected } = this.props;
+
+ const translateY = this.animatedValue.interpolate({
+ inputRange: [0, 1],
+ outputRange: [-41, 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/i18n/locales/en.js b/app/i18n/locales/en.js
index 910b071ef..7ca32afe0 100644
--- a/app/i18n/locales/en.js
+++ b/app/i18n/locales/en.js
@@ -123,8 +123,8 @@ export default {
Colaborative: 'Colaborative',
Connect: 'Connect',
Connect_to_a_server: 'Connect to a server',
- Connected_to: 'Connected to',
- Connecting: 'Connecting',
+ Connected: 'Connected',
+ Connecting: 'Connecting...',
Copied_to_clipboard: 'Copied to clipboard!',
Copy_Message: 'Copy Message',
Copy_Permalink: 'Copy Permalink',
diff --git a/app/i18n/locales/pt-BR.js b/app/i18n/locales/pt-BR.js
index f0e4ef42b..5929f227b 100644
--- a/app/i18n/locales/pt-BR.js
+++ b/app/i18n/locales/pt-BR.js
@@ -130,8 +130,8 @@ export default {
Colaborative: 'Colaborativo',
Connect: 'Conectar',
Connect_to_a_server: 'Conectar a um servidor',
- Connected_to: 'Conectado a',
- Connecting: 'Conectando',
+ Connected: 'Conectado',
+ Connecting: 'Conectando...',
Copied_to_clipboard: 'Copiado para a área de transferência!',
Copy_Message: 'Copiar Mensagem',
Copy_Permalink: 'Copiar Link-Permanente',
diff --git a/app/views/RoomView/index.js b/app/views/RoomView/index.js
index 2d8a42e51..3de09327a 100644
--- a/app/views/RoomView/index.js
+++ b/app/views/RoomView/index.js
@@ -25,6 +25,7 @@ import I18n from '../../i18n';
import debounce from '../../utils/debounce';
import { iconsMap } from '../../Icons';
import store from '../../lib/createStore';
+import ConnectionBadge from '../../containers/ConnectionBadge';
let RoomActionsView = null;
@@ -388,6 +389,7 @@ export default class RoomView extends LoggedView {
{showErrorActions ? : null}
+
);
}
diff --git a/app/views/RoomsListView/index.js b/app/views/RoomsListView/index.js
index 6d2bca73e..f31d6c5fe 100644
--- a/app/views/RoomsListView/index.js
+++ b/app/views/RoomsListView/index.js
@@ -8,6 +8,7 @@ import { isEqual } from 'lodash';
import { Navigation } from 'react-native-navigation';
import SearchBox from '../../containers/SearchBox';
+import ConnectionBadge from '../../containers/ConnectionBadge';
import database from '../../lib/realm';
import RocketChat from '../../lib/rocketchat';
import RoomItem from '../../presentation/RoomItem';
@@ -91,8 +92,8 @@ export default class RoomsListView extends LoggedView {
groupByType: PropTypes.bool,
showFavorites: PropTypes.bool,
showUnread: PropTypes.bool,
- toggleSortDropdown: PropTypes.func,
- useRealName: PropTypes.bool
+ useRealName: PropTypes.bool,
+ toggleSortDropdown: PropTypes.func
}
constructor(props) {
@@ -565,6 +566,7 @@ export default class RoomsListView extends LoggedView {
: null
}
{showServerDropdown ? : null}
+
);
}
diff --git a/app/views/index.js b/app/views/index.js
index c48953fdf..318171c0f 100644
--- a/app/views/index.js
+++ b/app/views/index.js
@@ -1,3 +1,4 @@
+import { Platform } from 'react-native';
import { Navigation } from 'react-native-navigation';
import { Provider } from 'react-redux';
import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
@@ -5,7 +6,6 @@ import { gestureHandlerRootHOC } from 'react-native-gesture-handler';
import OnboardingView from './OnboardingView';
import ProfileView from './ProfileView';
import RoomsListHeaderView from './RoomsListView/Header';
-import RoomsListSearchView from './RoomsListView/Search';
import RoomsListView from './RoomsListView';
import RoomView from './RoomView';
import SettingsView from './SettingsView';
@@ -15,7 +15,12 @@ export const registerScreens = (store) => {
Navigation.registerComponent('OnboardingView', () => OnboardingView, store, Provider);
Navigation.registerComponent('ProfileView', () => ProfileView, store, Provider);
Navigation.registerComponent('RoomsListHeaderView', () => RoomsListHeaderView, store, Provider);
- Navigation.registerComponent('RoomsListSearchView', () => RoomsListSearchView, store, Provider);
+
+ if (Platform.OS === 'android') {
+ const RoomsListSearchView = require('./RoomsListView/Search');
+ Navigation.registerComponent('RoomsListSearchView', () => RoomsListSearchView, store, Provider);
+ }
+
Navigation.registerComponent('RoomsListView', () => gestureHandlerRootHOC(RoomsListView), store, Provider);
Navigation.registerComponent('RoomView', () => gestureHandlerRootHOC(RoomView), store, Provider);
Navigation.registerComponent('SettingsView', () => SettingsView, store, Provider);