From 383a770fdec7e0f5103037128489bbe8d7f7bbfe Mon Sep 17 00:00:00 2001 From: enahum Date: Mon, 20 Mar 2017 17:31:10 -0300 Subject: [PATCH] PLT-5880 Channel drawer UI (#365) * fix drawer size and added tweener * added opacity to drawer buttons * Fix bad merge for navigation modal * Fix channel drawer container UI * Open Account Settings modal from channel drawer * Fix modal props for options and image preview * Channel drawer item UI * Fix bottom unread indicator overlap --- app/actions/navigation/index.js | 6 +- app/actions/views/channel.js | 36 +- .../channel_drawer_item.js | 297 +++++++++------- .../channel_drawer_list.js | 321 ++++++++++-------- .../channel_drawer_list_container.js | 4 +- app/components/line_divider.js | 83 ----- app/navigation/router.js | 31 +- app/scenes/channel/channel_drawer_button.js | 152 +++++---- app/scenes/channel/channel_menu_button.js | 72 ++-- .../right_menu_drawer/right_menu_drawer.js | 13 - .../right_menu_drawer_container.js | 3 +- 11 files changed, 555 insertions(+), 463 deletions(-) delete mode 100644 app/components/line_divider.js diff --git a/app/actions/navigation/index.js b/app/actions/navigation/index.js index c0c9f1d64..fdd7e5d16 100644 --- a/app/actions/navigation/index.js +++ b/app/actions/navigation/index.js @@ -158,8 +158,10 @@ export function showOptionsModal(options) { return async (dispatch, getState) => { dispatch({ type: NavigationTypes.NAVIGATION_MODAL, - route: Routes.OptionsModal, - props: options + route: { + ...Routes.OptionsModal, + props: options + } }, getState); }; } diff --git a/app/actions/views/channel.js b/app/actions/views/channel.js index e0ab54572..bc0006823 100644 --- a/app/actions/views/channel.js +++ b/app/actions/views/channel.js @@ -17,8 +17,14 @@ import {getPosts, getPostsSince} from 'mattermost-redux/actions/posts'; import {getFilesForPost} from 'mattermost-redux/actions/files'; import {savePreferences, deletePreferences} from 'mattermost-redux/actions/preferences'; import {getTeamMembersByIds} from 'mattermost-redux/actions/teams'; -import {Constants, UsersTypes} from 'mattermost-redux/constants'; -import {getChannelByName, getDirectChannelName, isDirectChannelVisible} from 'mattermost-redux/utils/channel_utils'; +import {getProfilesInChannel} from 'mattermost-redux/actions/users'; +import {Constants, Preferences, UsersTypes} from 'mattermost-redux/constants'; +import { + getChannelByName, + getDirectChannelName, + isDirectChannelVisible, + isGroupChannelVisible +} from 'mattermost-redux/utils/channel_utils'; import {getPreferencesByCategory} from 'mattermost-redux/utils/preference_utils'; export function loadChannelsIfNecessary(teamId) { @@ -49,8 +55,10 @@ export function loadProfilesAndTeamMembersForDMSidebar(teamId) { const {channels} = state.entities.channels; const {myPreferences} = state.entities.preferences; const {membersInTeam} = state.entities.teams; - const dmPrefs = getPreferencesByCategory(myPreferences, Constants.CATEGORY_DIRECT_CHANNEL_SHOW); + const dmPrefs = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_DIRECT_CHANNEL_SHOW); + const gmPrefs = getPreferencesByCategory(myPreferences, Preferences.CATEGORY_GROUP_CHANNEL_SHOW); const members = []; + const loadProfilesForChannels = []; for (const [key, pref] of dmPrefs) { if (pref.value === 'true') { @@ -58,6 +66,19 @@ export function loadProfilesAndTeamMembersForDMSidebar(teamId) { } } + for (const [key, pref] of gmPrefs) { + if (pref.value === 'true') { + loadProfilesForChannels.push(key); + } + } + + if (loadProfilesForChannels.length) { + for (let i = 0; i < loadProfilesForChannels.length; i++) { + const channelId = loadProfilesForChannels[i]; + getProfilesInChannel(teamId, channelId, 0)(dispatch, getState); + } + } + let membersToLoad = members; if (membersInTeam[teamId]) { membersToLoad = members.filter((m) => !membersInTeam[teamId].has(m)); @@ -125,9 +146,14 @@ export function selectInitialChannel(teamId) { const currentChannel = channels[currentChannelId]; const {myPreferences} = state.entities.preferences; + const isDMVisible = currentChannel && currentChannel.type === Constants.DM_CHANNEL && + isDirectChannelVisible(currentUserId, myPreferences, currentChannel); + + const isGMVisible = currentChannel && currentChannel.type === Constants.GM_CHANNEL && + isGroupChannelVisible(myPreferences, currentChannel); + if (currentChannel && myMembers[currentChannelId] && - (currentChannel.team_id === teamId || (currentChannel.type === Constants.DM_CHANNEL && - isDirectChannelVisible(currentUserId, myPreferences, currentChannel)))) { + (currentChannel.team_id === teamId || isDMVisible || isGMVisible)) { await handleSelectChannel(currentChannelId)(dispatch, getState); return; } diff --git a/app/components/channel_drawer_list/channel_drawer_item.js b/app/components/channel_drawer_list/channel_drawer_item.js index a05e83c73..ff9f271fa 100644 --- a/app/components/channel_drawer_list/channel_drawer_item.js +++ b/app/components/channel_drawer_list/channel_drawer_item.js @@ -1,27 +1,29 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import React from 'react'; -import {TouchableHighlight, Text, View} from 'react-native'; +import React, {PropTypes, PureComponent} from 'react'; +import { + StyleSheet, + TouchableHighlight, + Text, + View +} from 'react-native'; import Icon from 'react-native-vector-icons/FontAwesome'; import {OnlineStatus, AwayStatus, OfflineStatus} from 'app/components/status_icons'; -import {changeOpacity} from 'app/utils/theme'; +import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; import {Constants} from 'mattermost-redux/constants'; -import Badge from 'app/components/badge'; - -export default class ChannelDrawerItem extends React.Component { +export default class ChannelDrawerItem extends PureComponent { static propTypes = { - channel: React.PropTypes.object.isRequired, - onSelectChannel: React.PropTypes.func.isRequired, - handleClose: React.PropTypes.func, - onLongPress: React.PropTypes.func, - isActive: React.PropTypes.bool.isRequired, - hasUnread: React.PropTypes.bool.isRequired, - mentions: React.PropTypes.number.isRequired, - theme: React.PropTypes.object.isRequired + channel: PropTypes.object.isRequired, + onSelectChannel: PropTypes.func.isRequired, + onLongPress: PropTypes.func, + isActive: PropTypes.bool.isRequired, + hasUnread: PropTypes.bool.isRequired, + mentions: PropTypes.number.isRequired, + theme: PropTypes.object.isRequired }; render() { @@ -30,79 +32,50 @@ export default class ChannelDrawerItem extends React.Component { theme, mentions, hasUnread, - isActive, - handleClose + isActive } = this.props; - let iconColor = changeOpacity(theme.centerChannelColor, 0.7); - const isDirectMessage = channel.type === Constants.DM_CHANNEL; - let icon; + const style = getStyleSheet(theme); + let activeItem; + let activeIcon; + let unreadIcon; + let activeGroupBox; + let unreadGroupBox; + let activeGroup; + let unreadGroup; + let activeText; + let unreadText; + let activeBorder; + let icon; let badge; if (mentions && !isActive) { - const badgeStyle = { - position: 'absolute', - top: 12, - right: 10, - flexDirection: 'row', - backgroundColor: theme.mentionBj - }; - - const mentionStyle = { - color: theme.mentionColor, - fontSize: 14 - }; - badge = ( - + + + {mentions} + + ); } - const itemStyle = { - alignItems: 'center', - height: 45, - paddingLeft: 20, - paddingRight: 10, - flex: 1, - flexDirection: 'row' - }; - - const style = { - marginLeft: 5, - opacity: 0.6, - fontSize: 15, - color: theme.sidebarText - }; - - const activeStyle = { - width: 5, - height: 45, - backgroundColor: theme.sidebarTextActiveBorder, - position: 'absolute' - }; - if (hasUnread) { - style.fontWeight = 'bold'; - style.color = theme.sidebarUnreadText; - style.opacity = 1; - iconColor = theme.centerChannelColor; + unreadIcon = style.iconUnread; + unreadText = style.textUnread; + unreadGroupBox = style.groupBoxUnread; + unreadGroup = style.groupUnread; } if (isActive) { - iconColor = theme.sidebarTextActiveColor; - style.color = theme.sidebarTextActiveColor; - style.opacity = 1; - itemStyle.backgroundColor = changeOpacity(theme.sidebarTextActiveColor, 0.1); + activeItem = style.itemActive; + activeIcon = style.iconActive; + activeGroupBox = style.groupBoxActive; + activeGroup = style.groupActive; + activeText = style.textActive; activeBorder = ( - + ); } @@ -110,102 +83,182 @@ export default class ChannelDrawerItem extends React.Component { icon = ( ); } else if (channel.type === Constants.PRIVATE_CHANNEL) { icon = ( ); + } else if (channel.type === Constants.GM_CHANNEL) { + icon = ( + + + + {channel.display_name.split(',').length} + + + + ); } else { switch (channel.status) { case Constants.ONLINE: icon = ( - + + + ); break; case Constants.AWAY: icon = ( - + + + ); break; default: icon = ( - + + + ); break; } } - let closeButton = null; - if (isDirectMessage && !badge) { - const closeStyle = { - position: 'absolute', - justifyContent: 'center', - alignItems: 'center', - opacity: 0.4, - width: 50, - height: 50, - right: 0, - flexDirection: 'row' - }; - - closeButton = ( - handleClose(channel)} - > - - - ); - } - return ( this.props.onSelectChannel(channel)} delayLongPress={1000} onLongPress={() => { this.props.onLongPress(channel); }} > - + {activeBorder} - + {icon} {channel.display_name} {badge} - {closeButton} ); } } + +const getStyleSheet = makeStyleSheetFromTheme((theme) => { + return StyleSheet.create({ + container: { + flex: 1, + flexDirection: 'row', + height: 44 + }, + borderActive: { + backgroundColor: theme.sidebarTextActiveBorder, + width: 5 + }, + item: { + alignItems: 'center', + height: 44, + flex: 1, + flexDirection: 'row', + paddingLeft: 16 + }, + itemActive: { + backgroundColor: changeOpacity(theme.sidebarTextActiveColor, 0.1), + paddingLeft: 11 + }, + icon: { + color: changeOpacity(theme.sidebarText, 0.4), + fontSize: 12, + paddingRight: 12 + }, + iconActive: { + color: theme.sidebarTextActiveColor + }, + iconUnread: { + color: theme.sidebarUnreadText + }, + statusIcon: { + paddingRight: 12 + }, + groupContainer: { + paddingRight: 12 + }, + groupBox: { + alignItems: 'center', + borderWidth: 1, + borderColor: changeOpacity(theme.sidebarText, 0.4), + height: 15, + justifyContent: 'center', + width: 12 + }, + groupBoxActive: { + borderColor: theme.sidebarTextActiveColor + }, + groupBoxUnread: { + borderColor: theme.sidebarUnreadText + }, + group: { + color: changeOpacity(theme.sidebarText, 0.4), + fontSize: 10, + fontWeight: '600' + }, + groupActive: { + color: theme.sidebarTextActiveColor + }, + groupUnread: { + color: theme.sidebarUnreadText + }, + text: { + color: changeOpacity(theme.sidebarText, 0.4), + flex: 1, + fontSize: 14, + fontWeight: '600', + lineHeight: 16, + paddingRight: 40 + }, + textActive: { + color: theme.sidebarTextActiveColor + }, + textUnread: { + color: theme.sidebarUnreadText + }, + badgeContainer: { + alignItems: 'center', + backgroundColor: theme.mentionBj, + height: 15, + justifyContent: 'center', + marginRight: 16, + width: 15 + }, + badge: { + color: theme.mentionColor, + fontSize: 10, + fontWeight: '600' + } + }); +}); diff --git a/app/components/channel_drawer_list/channel_drawer_list.js b/app/components/channel_drawer_list/channel_drawer_list.js index d2e314bbd..974e7c5bb 100644 --- a/app/components/channel_drawer_list/channel_drawer_list.js +++ b/app/components/channel_drawer_list/channel_drawer_list.js @@ -1,8 +1,8 @@ // Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. +import deepEqual from 'deep-equal'; import React, {PropTypes, Component} from 'react'; - import { Alert, ListView, @@ -13,13 +13,16 @@ import { View } from 'react-native'; import {injectIntl, intlShape} from 'react-intl'; -import {Constants} from 'mattermost-redux/constants'; -import LineDivider from 'app/components/line_divider'; -import ChannelDrawerItem from './channel_drawer_item'; +import AwesomeIcon from 'react-native-vector-icons/FontAwesome'; +import MaterialIcon from 'react-native-vector-icons/MaterialIcons'; + import FormattedText from 'app/components/formatted_text'; +import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme'; + +import {Constants} from 'mattermost-redux/constants'; + +import ChannelDrawerItem from './channel_drawer_item'; import UnreadIndicator from './unread_indicator'; -import deepEqual from 'deep-equal'; -import Icon from 'react-native-vector-icons/FontAwesome'; class ChannelDrawerList extends Component { static propTypes = { @@ -33,6 +36,7 @@ class ChannelDrawerList extends Component { actions: PropTypes.shape({ closeDMChannel: PropTypes.func.isRequired, goToCreateChannel: PropTypes.func.isRequired, + goToModalAccountSettings: React.PropTypes.func.isRequired, leaveChannel: PropTypes.func.isRequired, markFavorite: PropTypes.func.isRequired, unmarkFavorite: PropTypes.func.isRequired, @@ -291,30 +295,12 @@ class ChannelDrawerList extends Component { mentions={mentions} onSelectChannel={this.onSelectChannel} onLongPress={this.onShowModal} - handleClose={this.handleClose} isActive={channel.isCurrent} theme={this.props.theme} /> ); }; - renderSectionAction = (action) => { - const {theme} = this.props; - - return ( - - - - ); - }; - createPrivateChannel = () => { this.props.actions.goToCreateChannel(Constants.PRIVATE_CHANNEL); }; @@ -326,76 +312,38 @@ class ChannelDrawerList extends Component { return data; } - const { - theme - } = props; + const {theme} = this.props; + const styles = getStyleSheet(theme); const { favoriteChannels, publicChannels, privateChannels, - directChannels, - directNonTeamChannels + directAndGroupChannels } = props.channels; if (favoriteChannels.length) { data.push( - , + this.renderTitle(styles, 'sidebar.favorite', 'FAVORITES', null, favoriteChannels.length > 0), ...favoriteChannels ); } data.push( - - - {this.renderSectionAction(this.props.actions.showMoreChannelsModal)} - , + this.renderTitle(styles, 'sidebar.channels', 'CHANNELS', this.props.actions.showMoreChannelsModal, publicChannels.length > 0), ...publicChannels ); data.push( - - - {this.renderSectionAction(this.createPrivateChannel)} - , + this.renderTitle(styles, 'sidebar.pg', 'PRIVATE GROUPS', this.createPrivateChannel, privateChannels.length > 0), ...privateChannels ); data.push( - - - {this.renderSectionAction(this.props.actions.showDirectMessagesModal)} - , - ...directChannels + this.renderTitle(styles, 'sidebar.direct', 'DIRECT MESSAGES', this.props.actions.showDirectMessagesModal, directAndGroupChannels.length > 0), + ...directAndGroupChannels ); - if (directNonTeamChannels.length) { - data.push( - , - ...directNonTeamChannels - ); - } - this.firstUnreadChannel = null; this.lastUnreadChannel = null; this.findUnreadChannels(data); @@ -403,6 +351,28 @@ class ChannelDrawerList extends Component { return data; }; + renderSectionAction = (styles, action) => { + return ( + + + + ); + }; + + renderDivider = (styles, marginLeft) => { + return ( + + ); + }; + renderRow = (rowData) => { if (rowData && rowData.id) { return this.createChannelElement(rowData); @@ -410,6 +380,23 @@ class ChannelDrawerList extends Component { return rowData; }; + renderTitle = (styles, id, defaultMessage, action, bottomDivider) => { + return ( + + {this.renderDivider(styles, 0)} + + + {action && this.renderSectionAction(styles, action)} + + {bottomDivider && this.renderDivider(styles, 16)} + + ); + }; + setScrollContainer = (ref) => { this.scrollContainer = ref; }; @@ -419,19 +406,30 @@ class ChannelDrawerList extends Component { return {'Loading'}; } - const { - theme - } = this.props; + const {theme} = this.props; + const styles = getStyleSheet(theme); + + const settings = ( + this.props.actions.goToModalAccountSettings()} + > + + + ); let above; let below; if (this.state.showAbove) { above = ( @@ -443,10 +441,10 @@ class ChannelDrawerList extends Component { if (this.state.showBelow) { below = ( @@ -457,21 +455,24 @@ class ChannelDrawerList extends Component { return ( - - - {this.props.currentTeam.display_name} - + + + + {this.props.currentTeam.display_name} + + {settings} + { + return StyleSheet.create({ + container: { + backgroundColor: theme.sidebarBg, + flex: 1 + }, + statusBar: { + backgroundColor: theme.sidebarHeaderBg, + ...Platform.select({ + ios: { + paddingTop: 20 + } + }) + }, + scrollContainer: { + flex: 1, + marginBottom: 10 + }, + headerContainer: { + alignItems: 'center', + backgroundColor: theme.sidebarHeaderBg, + flexDirection: 'row', + height: 44, + paddingLeft: 16 + }, + header: { + color: theme.sidebarHeaderTextColor, + flex: 1, + fontSize: 14, + fontWeight: 'normal', + lineHeight: 16 + }, + settingsContainer: { + alignItems: 'center', + height: 44, + justifyContent: 'center', + width: 50 + }, + settings: { + color: theme.sidebarText, + fontSize: 18, + fontWeight: '300' + }, + titleContainer: { + alignItems: 'center', + flex: 1, + flexDirection: 'row', + height: 48, + marginLeft: 16 + }, + title: { + flex: 1, + color: theme.sidebarText, + opacity: 1, + fontSize: 15, + fontWeight: '500', + letterSpacing: 0.8, + lineHeight: 18 + }, + divider: { + backgroundColor: changeOpacity(theme.centerChannelColor, 0.1), + height: 1 + }, + actionContainer: { + alignItems: 'center', + height: 48, + justifyContent: 'center', + width: 50 + }, + action: { + color: theme.sidebarText, + fontSize: 16, + fontWeight: '500', + lineHeight: 18 + }, + above: { + backgroundColor: theme.mentionBj, + top: 55 + }, + below: { + backgroundColor: theme.mentionBj, + bottom: 15 + }, + indicatorText: { + backgroundColor: 'transparent', + color: theme.mentionColor, + fontSize: 14, + paddingVertical: 2, + paddingHorizontal: 4, + textAlign: 'center', + textAlignVertical: 'center' + } + }); }); export default injectIntl(ChannelDrawerList); diff --git a/app/components/channel_drawer_list/channel_drawer_list_container.js b/app/components/channel_drawer_list/channel_drawer_list_container.js index a22d8e774..577585abb 100644 --- a/app/components/channel_drawer_list/channel_drawer_list_container.js +++ b/app/components/channel_drawer_list/channel_drawer_list_container.js @@ -5,8 +5,9 @@ import {bindActionCreators} from 'redux'; import {connect} from 'react-redux'; import { - requestCloseModal, + goToModalAccountSettings, goToCreateChannel, + requestCloseModal, showMoreChannelsModal, showDirectMessagesModal, showOptionsModal @@ -32,6 +33,7 @@ function mapDispatchToProps(dispatch) { actions: bindActionCreators({ closeDMChannel, goToCreateChannel, + goToModalAccountSettings, leaveChannel, markFavorite, unmarkFavorite, diff --git a/app/components/line_divider.js b/app/components/line_divider.js deleted file mode 100644 index f1ac19baa..000000000 --- a/app/components/line_divider.js +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -import React from 'react'; - -import {StyleSheet, View} from 'react-native'; -import FormattedText from 'app/components/formatted_text'; - -const Styles = StyleSheet.create({ - dividerLine: { - flex: 1, - height: 1, - backgroundColor: '#b3b3b3' - }, - dividerContainer: { - height: 20, - marginLeft: 15, - marginRight: 15 - }, - dividerText: { - flex: 1, - textAlign: 'center' - } -}); - -export default class LineDivider extends React.Component { - static propTypes = { - color: React.PropTypes.string.isRequired, - translationId: React.PropTypes.string, - translationText: React.PropTypes.string, - side: React.PropTypes.oneOf(['left', 'right', 'center']) - }; - - static defaultProps = { - side: 'right' - }; - - renderLine() { - return ( - - ); - } - - render() { - let renderText; - if (this.props.translationId && this.props.translationText) { - renderText = ( - - - - ); - } - - let content = ( - - {this.renderLine()} - {renderText} - - ); - if (this.props.side === 'left') { - content = ( - - {renderText} - {this.renderLine()} - - ); - } else if (this.props.side === 'center') { - content = ( - - {this.renderLine()} - {renderText} - {this.renderLine()} - - ); - } - - return content; - } -} diff --git a/app/navigation/router.js b/app/navigation/router.js index d4ba2de31..0b57bd3d9 100644 --- a/app/navigation/router.js +++ b/app/navigation/router.js @@ -18,6 +18,8 @@ import {RouteTransitions} from 'app/navigation/routes'; import {getTheme} from 'app/selectors/preferences'; import ErrorList from 'app/components/error_list'; +import EventEmitter from 'mattermost-redux/utils/event_emitter'; + import NavigationModal from './navigation_modal'; const navigationPanResponder = NavigationExperimental.Card.CardStackPanResponder; @@ -39,7 +41,7 @@ class Router extends React.Component { state = { deviceHeight, deviceWidth - } + }; emitHeaderEvent = (key) => (event) => { const subscription = this.headerEventSubscriptions[`${key}-${event}`]; @@ -201,6 +203,19 @@ class Router extends React.Component { } } + handleDrawerTween = (ratio) => { + const opacity = (ratio / 2); + + EventEmitter.emit('drawer_opacity', opacity); + + return { + mainOverlay: { + backgroundColor: '#000', + opacity + } + }; + }; + render = () => { const { index, @@ -237,14 +252,15 @@ class Router extends React.Component { disabled={modalVisible} content={leftDrawerContent} tapToClose={true} - openDrawerOffset={0.2} + openDrawerOffset={42} onRequestClose={this.props.actions.closeDrawers} - panOpenMask={0.4} - panCloseMask={0.2} + panOpenMask={0.3} + panCloseMask={42} panThreshold={0.2} acceptPan={navigationProps.allowMenuSwipe} negotiatePan={true} useInteractionManager={true} + tweenHandler={this.handleDrawerTween} > props.emitter('open_channel_drawer')} - /> + setOpacity = (value) => { + this.setState({opacity: value > 0 ? 0.1 : 1}); + }; + + render() { + let badge; + let badgeCount = this.props.mentionCount; + + if (!badgeCount && this.props.messageCount) { + badgeCount = -1; + } + + if (badgeCount !== 0) { + const badgeStyle = { + backgroundColor: 'rgb(214, 73, 70)', + borderRadius: 10, + flexDirection: 'row', + height: 20, + left: 5, + padding: 3, + position: 'absolute', + right: 0, + top: 5, + width: 20 + }; + + const mentionStyle = { + color: '#fff', + fontSize: 10 + }; + + badge = ( + this.props.emitter('open_channel_drawer')} + /> + ); + } + + return ( + + this.props.emitter('open_channel_drawer')} + style={{height: 25, width: 25, marginLeft: 10, marginRight: 10}} + > + + + {badge} + ); } - - return ( - - props.emitter('open_channel_drawer')} - style={{height: 25, width: 25, marginLeft: 10, marginRight: 10}} - > - - - {badge} - - ); } -ChannelDrawerButton.propTypes = { - emitter: PropTypes.func.isRequired, - theme: PropTypes.object, - messageCount: PropTypes.number, - mentionCount: PropTypes.number -}; - -ChannelDrawerButton.defaultProps = { - currentChannel: {}, - theme: {}, - messageCount: 0, - mentionCount: 0 -}; - function mapStateToProps(state) { return { theme: getTheme(state), diff --git a/app/scenes/channel/channel_menu_button.js b/app/scenes/channel/channel_menu_button.js index d3c80ea4e..673bb4767 100644 --- a/app/scenes/channel/channel_menu_button.js +++ b/app/scenes/channel/channel_menu_button.js @@ -1,7 +1,7 @@ // Copyright (c) 2017 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import React, {PropTypes} from 'react'; +import React, {PropTypes, PureComponent} from 'react'; import {connect} from 'react-redux'; import { TouchableOpacity, @@ -11,31 +11,55 @@ import Icon from 'react-native-vector-icons/FontAwesome'; import {getTheme} from 'app/selectors/preferences'; -function ChannelMenuButton(props) { - return ( - - props.emitter('open_right_menu')}> - - - - ); +import EventEmitter from 'mattermost-redux/utils/event_emitter'; + +class ChannelMenuButton extends PureComponent { + static propTypes = { + emitter: PropTypes.func.isRequired, + theme: PropTypes.object + }; + + static defaultProps = { + currentChannel: {}, + theme: {} + }; + + constructor(props) { + super(props); + + this.state = { + opacity: 1 + }; + } + + componentDidMount() { + EventEmitter.on('drawer_opacity', this.setOpacity); + } + + componentWillUnmount() { + EventEmitter.off('drawer_opacity', this.setOpacity); + } + + setOpacity = (value) => { + this.setState({opacity: value > 0 ? 0.1 : 1}); + }; + + render() { + return ( + + this.props.emitter('open_right_menu')}> + + + + ); + } } -ChannelMenuButton.propTypes = { - emitter: PropTypes.func.isRequired, - theme: PropTypes.object -}; - -ChannelMenuButton.defaultProps = { - currentChannel: {}, - theme: {} -}; - function mapStateToProps(state) { return { theme: getTheme(state) diff --git a/app/scenes/right_menu_drawer/right_menu_drawer.js b/app/scenes/right_menu_drawer/right_menu_drawer.js index a4ca64c6f..dfb59d7e2 100644 --- a/app/scenes/right_menu_drawer/right_menu_drawer.js +++ b/app/scenes/right_menu_drawer/right_menu_drawer.js @@ -22,7 +22,6 @@ export default class RightMenuDrawer extends React.Component { currentUserId: React.PropTypes.string.isRequired, currentTeamId: React.PropTypes.string.isRequired, actions: React.PropTypes.shape({ - goToModalAccountSettings: React.PropTypes.func.isRequired, goToModalSelectTeam: React.PropTypes.func.isRequired, clearErrors: React.PropTypes.func.isRequired, logout: React.PropTypes.func.isRequired @@ -60,18 +59,6 @@ export default class RightMenuDrawer extends React.Component { return ( - - - - -