diff --git a/app/components/autocomplete/autocomplete.js b/app/components/autocomplete/autocomplete.js
index aeda11ad7..0936ee97e 100644
--- a/app/components/autocomplete/autocomplete.js
+++ b/app/components/autocomplete/autocomplete.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
@@ -70,11 +70,11 @@ export default class Autocomplete extends PureComponent {
keyboardDidShow = (e) => {
const {height} = e.endCoordinates;
this.setState({keyboardOffset: height});
- }
+ };
keyboardDidHide = () => {
this.setState({keyboardOffset: 0});
- }
+ };
listHeight() {
let offset = Platform.select({ios: 65, android: 75});
@@ -85,6 +85,10 @@ export default class Autocomplete extends PureComponent {
}
render() {
+ if (!this.props.value) {
+ return null;
+ }
+
const style = getStyleFromTheme(this.props.theme);
const wrapperStyle = [];
diff --git a/app/components/channel_drawer/channel_drawer.js b/app/components/channel_drawer/channel_drawer.js
index 3abc18a4e..e1b3a79dd 100644
--- a/app/components/channel_drawer/channel_drawer.js
+++ b/app/components/channel_drawer/channel_drawer.js
@@ -18,7 +18,6 @@ import EventEmitter from 'mattermost-redux/utils/event_emitter';
import Drawer from 'app/components/drawer';
import SafeAreaView from 'app/components/safe_area_view';
import {ViewTypes} from 'app/constants';
-import {alertErrorWithFallback} from 'app/utils/general';
import tracker from 'app/utils/time_tracker';
import ChannelsList from './channels_list';
@@ -69,6 +68,7 @@ export default class ChannelDrawer extends Component {
openDrawerOffset = DRAWER_LANDSCAPE_OFFSET;
}
this.state = {
+ show: false,
openDrawerOffset,
};
}
@@ -79,6 +79,7 @@ export default class ChannelDrawer extends Component {
componentDidMount() {
EventEmitter.on('close_channel_drawer', this.closeChannelDrawer);
+ EventEmitter.on('renderDrawer', this.handleShowDrawerContent);
EventEmitter.on(WebsocketEvents.CHANNEL_UPDATED, this.handleUpdateTitle);
BackHandler.addEventListener('hardwareBackPress', this.handleAndroidBack);
}
@@ -100,7 +101,7 @@ export default class ChannelDrawer extends Component {
const {currentTeamId, isLandscape, teamsCount} = this.props;
const {openDrawerOffset} = this.state;
- if (nextState.openDrawerOffset !== openDrawerOffset) {
+ if (nextState.openDrawerOffset !== openDrawerOffset || nextState.show !== this.state.show) {
return true;
}
@@ -112,6 +113,7 @@ export default class ChannelDrawer extends Component {
componentWillUnmount() {
EventEmitter.off('close_channel_drawer', this.closeChannelDrawer);
EventEmitter.off(WebsocketEvents.CHANNEL_UPDATED, this.handleUpdateTitle);
+ EventEmitter.off('renderDrawer', this.handleShowDrawerContent);
BackHandler.removeEventListener('hardwareBackPress', this.handleAndroidBack);
}
@@ -124,6 +126,10 @@ export default class ChannelDrawer extends Component {
return false;
};
+ handleShowDrawerContent = () => {
+ this.setState({show: true});
+ };
+
closeChannelDrawer = () => {
if (this.refs.drawer && this.refs.drawer.isOpened()) {
this.refs.drawer.close();
@@ -246,6 +252,7 @@ export default class ChannelDrawer extends Component {
} = actions;
const displayValue = {displayName: channel.display_name};
+ const utils = require('app/utils/general');
let result;
if (channel.type === General.DM_CHANNEL) {
@@ -256,7 +263,7 @@ export default class ChannelDrawer extends Component {
id: 'mobile.open_dm.error',
defaultMessage: "We couldn't open a direct message with {displayName}. Please check your connection and try again.",
};
- alertErrorWithFallback(intl, result.error, dmFailedMessage, displayValue);
+ utils.alertErrorWithFallback(intl, result.error, dmFailedMessage, displayValue);
}
} else {
result = await joinChannel(currentUserId, currentTeamId, channel.id);
@@ -266,7 +273,7 @@ export default class ChannelDrawer extends Component {
id: 'mobile.join_channel.error',
defaultMessage: "We couldn't join the channel {displayName}. Please check your connection and try again.",
};
- alertErrorWithFallback(intl, result.error, joinFailedMessage, displayValue);
+ utils.alertErrorWithFallback(intl, result.error, joinFailedMessage, displayValue);
}
}
@@ -324,9 +331,14 @@ export default class ChannelDrawer extends Component {
} = this.props;
const {
+ show,
openDrawerOffset,
} = this.state;
+ if (!show) {
+ return null;
+ }
+
const multipleTeams = teamsCount > 1;
const showTeams = openDrawerOffset !== 0 && multipleTeams;
if (this.drawerSwiper) {
@@ -403,7 +415,7 @@ export default class ChannelDrawer extends Component {
onClose={this.handleDrawerClose}
onCloseStart={this.handleDrawerCloseStart}
captureGestures='open'
- type='static'
+ type={Platform.OS === 'ios' ? 'static' : 'displace'}
acceptTap={true}
acceptPanOnDrawer={false}
disabled={false}
diff --git a/app/components/channel_drawer/channels_list/channels_list.js b/app/components/channel_drawer/channels_list/channels_list.js
index 1dfdc8cfa..4d34082fb 100644
--- a/app/components/channel_drawer/channels_list/channels_list.js
+++ b/app/components/channel_drawer/channels_list/channels_list.js
@@ -1,28 +1,27 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
-import React from 'react';
+import React, {PureComponent} from 'react';
import PropTypes from 'prop-types';
import {
Platform,
View,
} from 'react-native';
-import {injectIntl, intlShape} from 'react-intl';
+import {intlShape} from 'react-intl';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import SearchBar from 'app/components/search_bar';
import {ViewTypes} from 'app/constants';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
-import FilteredList from './filtered_list';
import List from './list';
import SwitchTeamsButton from './switch_teams_button';
const {ANDROID_TOP_PORTRAIT} = ViewTypes;
+let FilteredList = null;
-class ChannelsList extends React.PureComponent {
+export default class ChannelsList extends PureComponent {
static propTypes = {
- intl: intlShape.isRequired,
navigator: PropTypes.object,
onJoinChannel: PropTypes.func.isRequired,
onSearchEnds: PropTypes.func.isRequired,
@@ -32,6 +31,10 @@ class ChannelsList extends React.PureComponent {
theme: PropTypes.object.isRequired,
};
+ static contextTypes = {
+ intl: intlShape.isRequired,
+ };
+
constructor(props) {
super(props);
@@ -62,6 +65,9 @@ class ChannelsList extends React.PureComponent {
};
onSearchFocused = () => {
+ if (!FilteredList) {
+ FilteredList = require('./filtered_list').default;
+ }
this.setState({searching: true});
this.props.onSearchStart();
};
@@ -73,8 +79,8 @@ class ChannelsList extends React.PureComponent {
};
render() {
+ const {intl} = this.context;
const {
- intl,
navigator,
onShowTeams,
theme,
@@ -243,5 +249,3 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
};
});
-
-export default injectIntl(ChannelsList);
diff --git a/app/components/channel_drawer/channels_list/list/list.js b/app/components/channel_drawer/channels_list/list/list.js
index 887a56285..d44694c5f 100644
--- a/app/components/channel_drawer/channels_list/list/list.js
+++ b/app/components/channel_drawer/channels_list/list/list.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
@@ -17,7 +17,6 @@ import {General} from 'mattermost-redux/constants';
import {debounce} from 'mattermost-redux/actions/helpers';
import ChannelItem from 'app/components/channel_drawer/channels_list/channel_item';
-import UnreadIndicator from 'app/components/channel_drawer/channels_list/unread_indicator';
import {ListTypes} from 'app/constants';
import {preventDoubleTap} from 'app/utils/tap';
import {changeOpacity} from 'app/utils/theme';
@@ -27,6 +26,8 @@ const VIEWABILITY_CONFIG = {
waitForInteraction: true,
};
+let UnreadIndicator = null;
+
export default class List extends PureComponent {
static propTypes = {
canCreatePrivateChannels: PropTypes.bool.isRequired,
@@ -311,6 +312,9 @@ export default class List extends PureComponent {
};
emitUnreadIndicatorChange = debounce((showIndicator) => {
+ if (showIndicator && !UnreadIndicator) {
+ UnreadIndicator = require('app/components/channel_drawer/channels_list/unread_indicator').default;
+ }
this.setState({showIndicator});
}, 100);
@@ -349,12 +353,14 @@ export default class List extends PureComponent {
stickySectionHeadersEnabled={false}
viewabilityConfig={VIEWABILITY_CONFIG}
/>
+ {showIndicator &&
+ }
);
}
diff --git a/app/components/channel_drawer/index.js b/app/components/channel_drawer/index.js
index e0df094d8..803fc94bd 100644
--- a/app/components/channel_drawer/index.js
+++ b/app/components/channel_drawer/index.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import {bindActionCreators} from 'redux';
@@ -6,12 +6,12 @@ import {connect} from 'react-redux';
import {joinChannel, markChannelAsRead, markChannelAsViewed} from 'mattermost-redux/actions/channels';
import {getTeams} from 'mattermost-redux/actions/teams';
+import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentTeamId, getMyTeamsCount} from 'mattermost-redux/selectors/entities/teams';
import {handleSelectChannel, setChannelDisplayName, setChannelLoading} from 'app/actions/views/channel';
import {makeDirectChannel} from 'app/actions/views/more_dms';
import {isLandscape, isTablet} from 'app/selectors/device';
-import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import ChannelDrawer from './channel_drawer.js';
diff --git a/app/components/channel_drawer/teams_list/teams_list.js b/app/components/channel_drawer/teams_list/teams_list.js
index 7a91e099a..0b705d79b 100644
--- a/app/components/channel_drawer/teams_list/teams_list.js
+++ b/app/components/channel_drawer/teams_list/teams_list.js
@@ -1,4 +1,4 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React, {PureComponent} from 'react';
@@ -11,7 +11,7 @@ import {
TouchableHighlight,
View,
} from 'react-native';
-import {injectIntl, intlShape} from 'react-intl';
+import {intlShape} from 'react-intl';
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
import FormattedText from 'app/components/formatted_text';
@@ -28,7 +28,7 @@ const VIEWABILITY_CONFIG = {
waitForInteraction: true,
};
-class TeamsList extends PureComponent {
+export default class TeamsList extends PureComponent {
static propTypes = {
actions: PropTypes.shape({
handleTeamChange: PropTypes.func.isRequired,
@@ -36,12 +36,15 @@ class TeamsList extends PureComponent {
closeChannelDrawer: PropTypes.func.isRequired,
currentTeamId: PropTypes.string.isRequired,
currentUrl: PropTypes.string.isRequired,
- intl: intlShape.isRequired,
navigator: PropTypes.object.isRequired,
teamIds: PropTypes.array.isRequired,
theme: PropTypes.object.isRequired,
};
+ static contextTypes = {
+ intl: intlShape.isRequired,
+ };
+
constructor(props) {
super(props);
@@ -64,7 +67,8 @@ class TeamsList extends PureComponent {
};
goToSelectTeam = preventDoubleTap(() => {
- const {currentUrl, intl, navigator, theme} = this.props;
+ const {intl} = this.context;
+ const {currentUrl, navigator, theme} = this.props;
navigator.showModal({
screen: 'SelectTeam',
@@ -195,5 +199,3 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
},
};
});
-
-export default injectIntl(TeamsList);
diff --git a/app/components/channel_icon.js b/app/components/channel_icon.js
index 244c61bc1..bb2fd2959 100644
--- a/app/components/channel_icon.js
+++ b/app/components/channel_icon.js
@@ -1,22 +1,15 @@
-// Copyright (c) 2017-present Mattermost, Inc. All Rights Reserved.
+// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
import React from 'react';
import PropTypes from 'prop-types';
import {
+ Image,
Text,
View,
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
-import {
- ArchiveIcon,
- AwayAvatar,
- DndAvatar,
- OfflineAvatar,
- OnlineAvatar,
-} from 'app/components/status_icons';
-
import {General} from 'mattermost-redux/constants';
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
@@ -108,47 +101,42 @@ export default class ChannelIcon extends React.PureComponent {
);
} else if (type === General.DM_CHANNEL && teammateDeletedAt) {
icon = (
-
);
} else if (type === General.DM_CHANNEL) {
switch (status) {
case General.AWAY:
icon = (
-
);
break;
case General.DND:
icon = (
-
);
break;
case General.ONLINE:
icon = (
-
);
break;
default:
icon = (
-
);
break;
diff --git a/app/screens/channel/channel.js b/app/screens/channel/channel.js
index 7f70194ef..557e290fd 100644
--- a/app/screens/channel/channel.js
+++ b/app/screens/channel/channel.js
@@ -81,6 +81,8 @@ export default class Channel extends PureComponent {
if (tracker.initialLoad) {
this.props.actions.recordLoadTime('Start time', 'initialLoad');
}
+
+ EventEmitter.emit('renderDrawer');
}
componentWillReceiveProps(nextProps) {
@@ -99,10 +101,15 @@ export default class Channel extends PureComponent {
}
}
- componentDidUpdate() {
+ componentDidUpdate(prevProps) {
if (tracker.teamSwitch) {
this.props.actions.recordLoadTime('Switch Team', 'teamSwitch');
}
+
+ // When the team changes emit the event to render the drawer content
+ if (this.props.currentChannelId && !prevProps.currentChannelId) {
+ EventEmitter.emit('renderDrawer');
+ }
}
componentWillUnmount() {
diff --git a/assets/base/images/status/archive_avatar.png b/assets/base/images/status/archive_avatar.png
new file mode 100644
index 000000000..f0d16cf23
Binary files /dev/null and b/assets/base/images/status/archive_avatar.png differ
diff --git a/assets/base/images/status/away_avatar.png b/assets/base/images/status/away_avatar.png
new file mode 100644
index 000000000..42c5ddd69
Binary files /dev/null and b/assets/base/images/status/away_avatar.png differ
diff --git a/assets/base/images/status/dnd_avatar.png b/assets/base/images/status/dnd_avatar.png
new file mode 100644
index 000000000..c23f47b20
Binary files /dev/null and b/assets/base/images/status/dnd_avatar.png differ
diff --git a/assets/base/images/status/offline_avatar.png b/assets/base/images/status/offline_avatar.png
new file mode 100644
index 000000000..2c4cfe5ea
Binary files /dev/null and b/assets/base/images/status/offline_avatar.png differ
diff --git a/assets/base/images/status/online_avatar.png b/assets/base/images/status/online_avatar.png
new file mode 100644
index 000000000..e58cc0915
Binary files /dev/null and b/assets/base/images/status/online_avatar.png differ