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
This commit is contained in:
parent
ac49aa6c11
commit
383a770fde
11 changed files with 555 additions and 463 deletions
|
|
@ -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);
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = (
|
||||
<Badge
|
||||
style={badgeStyle}
|
||||
countStyle={mentionStyle}
|
||||
count={mentions}
|
||||
minHeight={20}
|
||||
minWidth={20}
|
||||
/>
|
||||
<View style={style.badgeContainer}>
|
||||
<Text style={style.badge}>
|
||||
{mentions}
|
||||
</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
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 = (
|
||||
<View style={activeStyle}/>
|
||||
<View style={style.borderActive}/>
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -110,102 +83,182 @@ export default class ChannelDrawerItem extends React.Component {
|
|||
icon = (
|
||||
<Icon
|
||||
name='globe'
|
||||
size={15}
|
||||
color={iconColor}
|
||||
style={[style.icon, unreadIcon, activeIcon]}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
icon = (
|
||||
<Icon
|
||||
name='lock'
|
||||
size={15}
|
||||
color={iconColor}
|
||||
style={[style.icon, unreadIcon, activeIcon]}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.GM_CHANNEL) {
|
||||
icon = (
|
||||
<View style={style.groupContainer}>
|
||||
<View style={[style.groupBox, unreadGroupBox, activeGroupBox]}>
|
||||
<Text style={[style.group, unreadGroup, activeGroup]}>
|
||||
{channel.display_name.split(',').length}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
} else {
|
||||
switch (channel.status) {
|
||||
case Constants.ONLINE:
|
||||
icon = (
|
||||
<OnlineStatus
|
||||
width={13}
|
||||
height={13}
|
||||
color={theme.onlineIndicator}
|
||||
/>
|
||||
<View style={style.statusIcon}>
|
||||
<OnlineStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={theme.onlineIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
break;
|
||||
case Constants.AWAY:
|
||||
icon = (
|
||||
<AwayStatus
|
||||
width={13}
|
||||
height={13}
|
||||
color={theme.awayIndicator}
|
||||
/>
|
||||
<View style={style.statusIcon}>
|
||||
<AwayStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={theme.awayIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
icon = (
|
||||
<OfflineStatus
|
||||
width={13}
|
||||
height={13}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.7)}
|
||||
/>
|
||||
<View style={style.statusIcon}>
|
||||
<OfflineStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
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 = (
|
||||
<TouchableHighlight
|
||||
style={closeStyle}
|
||||
onPress={() => handleClose(channel)}
|
||||
>
|
||||
<Icon
|
||||
name='times'
|
||||
size={13}
|
||||
color={theme.sidebarText}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<TouchableHighlight
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.3)}
|
||||
underlayColor={changeOpacity(theme.sidebarTextHoverBg, 0.5)}
|
||||
onPress={() => this.props.onSelectChannel(channel)}
|
||||
delayLongPress={1000}
|
||||
onLongPress={() => {
|
||||
this.props.onLongPress(channel);
|
||||
}}
|
||||
>
|
||||
<View style={{flex: 1}}>
|
||||
<View style={style.container}>
|
||||
{activeBorder}
|
||||
<View style={itemStyle}>
|
||||
<View style={[style.item, activeItem]}>
|
||||
{icon}
|
||||
<Text
|
||||
style={style}
|
||||
style={[style.text, unreadText, activeText]}
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
>
|
||||
{channel.display_name}
|
||||
</Text>
|
||||
{badge}
|
||||
{closeButton}
|
||||
</View>
|
||||
</View>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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'
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<TouchableHighlight
|
||||
style={Styles.more}
|
||||
onPress={action}
|
||||
>
|
||||
<Icon
|
||||
name='plus-circle'
|
||||
size={18}
|
||||
color={theme.sidebarText}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
};
|
||||
|
||||
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(
|
||||
<FormattedText
|
||||
style={[Styles.title, {color: theme.sidebarText}]}
|
||||
id='sidebar.favorite'
|
||||
defaultMessage='FAVORITES'
|
||||
/>,
|
||||
this.renderTitle(styles, 'sidebar.favorite', 'FAVORITES', null, favoriteChannels.length > 0),
|
||||
...favoriteChannels
|
||||
);
|
||||
}
|
||||
|
||||
data.push(
|
||||
<View style={{flex: 1, flexDirection: 'row', alignItems: 'center'}}>
|
||||
<FormattedText
|
||||
style={[Styles.title, {color: theme.sidebarText}]}
|
||||
id='sidebar.channels'
|
||||
defaultMessage='CHANNELS'
|
||||
/>
|
||||
{this.renderSectionAction(this.props.actions.showMoreChannelsModal)}
|
||||
</View>,
|
||||
this.renderTitle(styles, 'sidebar.channels', 'CHANNELS', this.props.actions.showMoreChannelsModal, publicChannels.length > 0),
|
||||
...publicChannels
|
||||
);
|
||||
|
||||
data.push(
|
||||
<View style={{flex: 1, flexDirection: 'row', alignItems: 'center'}}>
|
||||
<FormattedText
|
||||
style={[Styles.title, {color: theme.sidebarText}]}
|
||||
id='sidebar.pg'
|
||||
defaultMessage='PRIVATE GROUPS'
|
||||
/>
|
||||
{this.renderSectionAction(this.createPrivateChannel)}
|
||||
</View>,
|
||||
this.renderTitle(styles, 'sidebar.pg', 'PRIVATE GROUPS', this.createPrivateChannel, privateChannels.length > 0),
|
||||
...privateChannels
|
||||
);
|
||||
|
||||
data.push(
|
||||
<View style={{flex: 1, flexDirection: 'row', alignItems: 'center'}}>
|
||||
<FormattedText
|
||||
style={[Styles.title, {color: theme.sidebarText}]}
|
||||
id='sidebar.direct'
|
||||
defaultMessage='DIRECT MESSAGES'
|
||||
/>
|
||||
{this.renderSectionAction(this.props.actions.showDirectMessagesModal)}
|
||||
</View>,
|
||||
...directChannels
|
||||
this.renderTitle(styles, 'sidebar.direct', 'DIRECT MESSAGES', this.props.actions.showDirectMessagesModal, directAndGroupChannels.length > 0),
|
||||
...directAndGroupChannels
|
||||
);
|
||||
|
||||
if (directNonTeamChannels.length) {
|
||||
data.push(
|
||||
<LineDivider
|
||||
color={theme.sidebarTextActiveBorder}
|
||||
translationId='sidebar.otherMembers'
|
||||
translationText='Outside this team'
|
||||
/>,
|
||||
...directNonTeamChannels
|
||||
);
|
||||
}
|
||||
|
||||
this.firstUnreadChannel = null;
|
||||
this.lastUnreadChannel = null;
|
||||
this.findUnreadChannels(data);
|
||||
|
|
@ -403,6 +351,28 @@ class ChannelDrawerList extends Component {
|
|||
return data;
|
||||
};
|
||||
|
||||
renderSectionAction = (styles, action) => {
|
||||
return (
|
||||
<TouchableHighlight
|
||||
style={styles.actionContainer}
|
||||
onPress={action}
|
||||
>
|
||||
<MaterialIcon
|
||||
name='add'
|
||||
style={styles.action}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
};
|
||||
|
||||
renderDivider = (styles, marginLeft) => {
|
||||
return (
|
||||
<View
|
||||
style={[styles.divider, {marginLeft}]}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
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 (
|
||||
<View>
|
||||
{this.renderDivider(styles, 0)}
|
||||
<View style={styles.titleContainer}>
|
||||
<FormattedText
|
||||
style={styles.title}
|
||||
id={id}
|
||||
defaultMessage={defaultMessage}
|
||||
/>
|
||||
{action && this.renderSectionAction(styles, action)}
|
||||
</View>
|
||||
{bottomDivider && this.renderDivider(styles, 16)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
setScrollContainer = (ref) => {
|
||||
this.scrollContainer = ref;
|
||||
};
|
||||
|
|
@ -419,19 +406,30 @@ class ChannelDrawerList extends Component {
|
|||
return <Text>{'Loading'}</Text>;
|
||||
}
|
||||
|
||||
const {
|
||||
theme
|
||||
} = this.props;
|
||||
const {theme} = this.props;
|
||||
const styles = getStyleSheet(theme);
|
||||
|
||||
const settings = (
|
||||
<TouchableHighlight
|
||||
style={styles.settingsContainer}
|
||||
onPress={() => this.props.actions.goToModalAccountSettings()}
|
||||
>
|
||||
<AwesomeIcon
|
||||
name='cog'
|
||||
style={styles.settings}
|
||||
/>
|
||||
</TouchableHighlight>
|
||||
);
|
||||
|
||||
let above;
|
||||
let below;
|
||||
if (this.state.showAbove) {
|
||||
above = (
|
||||
<UnreadIndicator
|
||||
style={{top: 55, backgroundColor: theme.mentionBj, width: (this.width - 40)}}
|
||||
style={[styles.above, {width: (this.width - 40)}]}
|
||||
text={(
|
||||
<FormattedText
|
||||
style={[Styles.indicatorText, {color: theme.mentionColor}]}
|
||||
style={styles.indicatorText}
|
||||
id='sidebar.unreadAbove'
|
||||
defaultMessage='Unread post(s) above'
|
||||
/>
|
||||
|
|
@ -443,10 +441,10 @@ class ChannelDrawerList extends Component {
|
|||
if (this.state.showBelow) {
|
||||
below = (
|
||||
<UnreadIndicator
|
||||
style={{bottom: 15, backgroundColor: theme.mentionBj, width: (this.width - 40)}}
|
||||
style={[styles.below, {width: (this.width - 40)}]}
|
||||
text={(
|
||||
<FormattedText
|
||||
style={[Styles.indicatorText, {color: theme.mentionColor}]}
|
||||
style={styles.indicatorText}
|
||||
id='sidebar.unreadBelow'
|
||||
defaultMessage='Unread post(s) below'
|
||||
/>
|
||||
|
|
@ -457,21 +455,24 @@ class ChannelDrawerList extends Component {
|
|||
|
||||
return (
|
||||
<View
|
||||
style={[Styles.container, {backgroundColor: theme.sidebarBg}]}
|
||||
style={styles.container}
|
||||
onLayout={this.onLayout}
|
||||
>
|
||||
<View style={[Styles.headerContainer, {backgroundColor: theme.sidebarHeaderBg}]}>
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
style={[Styles.header, {color: theme.sidebarHeaderTextColor}]}
|
||||
>
|
||||
{this.props.currentTeam.display_name}
|
||||
</Text>
|
||||
<View style={styles.statusBar}>
|
||||
<View style={styles.headerContainer}>
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
style={styles.header}
|
||||
>
|
||||
{this.props.currentTeam.display_name}
|
||||
</Text>
|
||||
{settings}
|
||||
</View>
|
||||
</View>
|
||||
<ListView
|
||||
ref={this.setScrollContainer}
|
||||
style={Styles.scrollContainer}
|
||||
style={styles.scrollContainer}
|
||||
dataSource={this.state.dataSource}
|
||||
renderRow={this.renderRow}
|
||||
onChangeVisibleRows={this.updateUnreadIndicators}
|
||||
|
|
@ -483,59 +484,99 @@ class ChannelDrawerList extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const Styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1
|
||||
},
|
||||
scrollContainer: {
|
||||
flex: 1
|
||||
},
|
||||
headerContainer: {
|
||||
flexDirection: 'column',
|
||||
...Platform.select({
|
||||
ios: {
|
||||
height: 64,
|
||||
justifyContent: 'flex-end'
|
||||
},
|
||||
android: {
|
||||
height: 56,
|
||||
justifyContent: 'center',
|
||||
paddingTop: 10
|
||||
}
|
||||
}),
|
||||
width: 300,
|
||||
paddingLeft: 10,
|
||||
paddingBottom: 12
|
||||
},
|
||||
header: {
|
||||
fontSize: 18,
|
||||
fontWeight: 'bold'
|
||||
},
|
||||
title: {
|
||||
paddingTop: 10,
|
||||
paddingRight: 10,
|
||||
paddingLeft: 10,
|
||||
paddingBottom: 5,
|
||||
fontSize: 15,
|
||||
opacity: 0.6
|
||||
},
|
||||
indicatorText: {
|
||||
paddingVertical: 2,
|
||||
paddingHorizontal: 4,
|
||||
backgroundColor: 'transparent',
|
||||
fontSize: 14,
|
||||
textAlign: 'center',
|
||||
textAlignVertical: 'center'
|
||||
},
|
||||
more: {
|
||||
position: 'absolute',
|
||||
opacity: 0.6,
|
||||
right: 0,
|
||||
width: 50,
|
||||
height: 30,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center'
|
||||
}
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<View style={[Styles.dividerLine, {backgroundColor: this.props.color}]}/>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
let renderText;
|
||||
if (this.props.translationId && this.props.translationText) {
|
||||
renderText = (
|
||||
<View style={Styles.dividerContainer}>
|
||||
<FormattedText
|
||||
style={[Styles.dividerText, {color: this.props.color}]}
|
||||
id={this.props.translationId}
|
||||
defaultMessage={this.props.translationText}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
let content = (
|
||||
<View style={{flexDirection: 'row', alignItems: 'center'}}>
|
||||
{this.renderLine()}
|
||||
{renderText}
|
||||
</View>
|
||||
);
|
||||
if (this.props.side === 'left') {
|
||||
content = (
|
||||
<View style={{flexDirection: 'row', alignItems: 'center'}}>
|
||||
{renderText}
|
||||
{this.renderLine()}
|
||||
</View>
|
||||
);
|
||||
} else if (this.props.side === 'center') {
|
||||
content = (
|
||||
<View style={{flexDirection: 'row', alignItems: 'center'}}>
|
||||
{this.renderLine()}
|
||||
{renderText}
|
||||
{this.renderLine()}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
@ -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}
|
||||
>
|
||||
<Drawer
|
||||
open={rightDrawerOpen}
|
||||
|
|
@ -253,14 +269,15 @@ class Router extends React.Component {
|
|||
disabled={modalVisible}
|
||||
content={rightDrawerContent}
|
||||
tapToClose={true}
|
||||
openDrawerOffset={0.2}
|
||||
openDrawerOffset={50}
|
||||
onRequestClose={this.props.actions.closeDrawers}
|
||||
panOpenMask={0.4}
|
||||
panCloseMask={0.2}
|
||||
panOpenMask={0.3}
|
||||
panCloseMask={50}
|
||||
panThreshold={0.2}
|
||||
acceptPan={navigationProps.allowMenuSwipe}
|
||||
negotiatePan={true}
|
||||
useInteractionManager={true}
|
||||
tweenHandler={this.handleDrawerTween}
|
||||
>
|
||||
<NavigationExperimental.Transitioner
|
||||
style={{flex: 1}}
|
||||
|
|
|
|||
|
|
@ -1,88 +1,112 @@
|
|||
// 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,
|
||||
View
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
import Badge from 'app/components/badge';
|
||||
|
||||
import {getUnreads} from 'mattermost-redux/selectors/entities/channels';
|
||||
import Badge from 'app/components/badge';
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
|
||||
function ChannelDrawerButton(props) {
|
||||
let badge;
|
||||
let badgeCount = props.mentionCount;
|
||||
import {getUnreads} from 'mattermost-redux/selectors/entities/channels';
|
||||
import EventEmitter from 'mattermost-redux/utils/event_emitter';
|
||||
|
||||
if (!badgeCount && props.messageCount) {
|
||||
badgeCount = -1;
|
||||
class ChannelDrawerButton extends PureComponent {
|
||||
static propTypes = {
|
||||
emitter: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object,
|
||||
messageCount: PropTypes.number,
|
||||
mentionCount: PropTypes.number
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
currentChannel: {},
|
||||
theme: {},
|
||||
messageCount: 0,
|
||||
mentionCount: 0
|
||||
};
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.state = {
|
||||
opacity: 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
|
||||
};
|
||||
componentDidMount() {
|
||||
EventEmitter.on('drawer_opacity', this.setOpacity);
|
||||
}
|
||||
|
||||
const mentionStyle = {
|
||||
color: '#fff',
|
||||
fontSize: 10
|
||||
};
|
||||
componentWillUnmount() {
|
||||
EventEmitter.off('drawer_opacity', this.setOpacity);
|
||||
}
|
||||
|
||||
badge = (
|
||||
<Badge
|
||||
style={badgeStyle}
|
||||
countStyle={mentionStyle}
|
||||
count={badgeCount}
|
||||
minHeight={5}
|
||||
minWidth={5}
|
||||
onPress={() => 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 = (
|
||||
<Badge
|
||||
style={badgeStyle}
|
||||
countStyle={mentionStyle}
|
||||
count={badgeCount}
|
||||
minHeight={5}
|
||||
minWidth={5}
|
||||
onPress={() => this.props.emitter('open_channel_drawer')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1, opacity: this.state.opacity}}>
|
||||
<TouchableOpacity
|
||||
onPress={() => this.props.emitter('open_channel_drawer')}
|
||||
style={{height: 25, width: 25, marginLeft: 10, marginRight: 10}}
|
||||
>
|
||||
<Icon
|
||||
name='bars'
|
||||
size={25}
|
||||
color={this.props.theme.sidebarHeaderTextColor}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{badge}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1}}>
|
||||
<TouchableOpacity
|
||||
onPress={() => props.emitter('open_channel_drawer')}
|
||||
style={{height: 25, width: 25, marginLeft: 10, marginRight: 10}}
|
||||
>
|
||||
<Icon
|
||||
name='bars'
|
||||
size={25}
|
||||
color={props.theme.sidebarHeaderTextColor}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
{badge}
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
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),
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1}}>
|
||||
<TouchableOpacity onPress={() => props.emitter('open_right_menu')}>
|
||||
<Icon
|
||||
name='ellipsis-v'
|
||||
size={25}
|
||||
color={props.theme.sidebarHeaderTextColor}
|
||||
style={{paddingHorizontal: 20}}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
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 (
|
||||
<View style={{flexDirection: 'column', justifyContent: 'center', alignItems: 'center', flex: 1, opacity: this.state.opacity}}>
|
||||
<TouchableOpacity onPress={() => this.props.emitter('open_right_menu')}>
|
||||
<Icon
|
||||
name='ellipsis-v'
|
||||
size={25}
|
||||
color={this.props.theme.sidebarHeaderTextColor}
|
||||
style={{paddingHorizontal: 20}}
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ChannelMenuButton.propTypes = {
|
||||
emitter: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object
|
||||
};
|
||||
|
||||
ChannelMenuButton.defaultProps = {
|
||||
currentChannel: {},
|
||||
theme: {}
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
theme: getTheme(state)
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
<ScrollView style={Styles.container}>
|
||||
<Divider style={Styles.divider}/>
|
||||
<RightMenuDrawerItem onPress={this.props.actions.goToModalAccountSettings}>
|
||||
<Icon
|
||||
style={Styles.icon}
|
||||
name='cog'
|
||||
/>
|
||||
<FormattedText
|
||||
style={Styles.itemText}
|
||||
id='sidebar_right_menu.accountSettings'
|
||||
defaultMessage='Account Settings'
|
||||
/>
|
||||
</RightMenuDrawerItem>
|
||||
<Divider style={Styles.divider}/>
|
||||
<RightMenuDrawerItem onPress={this.props.actions.goToModalSelectTeam}>
|
||||
<Icon
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
import {bindActionCreators} from 'redux';
|
||||
import {connect} from 'react-redux';
|
||||
|
||||
import {goToModalAccountSettings, goBack, goToModalSelectTeam} from 'app/actions/navigation';
|
||||
import {goBack, goToModalSelectTeam} from 'app/actions/navigation';
|
||||
import {clearErrors} from 'mattermost-redux/actions/errors';
|
||||
|
||||
import {logout} from 'mattermost-redux/actions/users';
|
||||
|
|
@ -25,7 +25,6 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
goToModalAccountSettings,
|
||||
goBack,
|
||||
goToModalSelectTeam,
|
||||
clearErrors,
|
||||
|
|
|
|||
Loading…
Reference in a new issue