PLT-5721 Show Group Messages and correct channel info (#372)
* Fix bad merge for navigation modal * Fix modal props for options and image preview * PLT-5721 Show Group Messages and correct channel info * Set fixed commit on mattermost-redux * address feedback
This commit is contained in:
parent
4bb74c065a
commit
7fae0f8039
10 changed files with 472 additions and 242 deletions
|
|
@ -198,7 +198,7 @@ export function toggleDMChannel(otherUserId, visible) {
|
|||
|
||||
const dm = [{
|
||||
user_id: currentUserId,
|
||||
category: Constants.CATEGORY_DIRECT_CHANNEL_SHOW,
|
||||
category: Preferences.CATEGORY_DIRECT_CHANNEL_SHOW,
|
||||
name: otherUserId,
|
||||
value: visible
|
||||
}];
|
||||
|
|
@ -207,6 +207,22 @@ export function toggleDMChannel(otherUserId, visible) {
|
|||
};
|
||||
}
|
||||
|
||||
export function toggleGMChannel(channelId, visible) {
|
||||
return async (dispatch, getState) => {
|
||||
const state = getState();
|
||||
const {currentUserId} = state.entities.users;
|
||||
|
||||
const gm = [{
|
||||
user_id: currentUserId,
|
||||
category: Preferences.CATEGORY_GROUP_CHANNEL_SHOW,
|
||||
name: channelId,
|
||||
value: visible
|
||||
}];
|
||||
|
||||
return savePreferences(gm)(dispatch, getState);
|
||||
};
|
||||
}
|
||||
|
||||
export function closeDMChannel(channel) {
|
||||
return async(dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
|
@ -223,6 +239,35 @@ export function closeDMChannel(channel) {
|
|||
};
|
||||
}
|
||||
|
||||
export function closeGMChannel(channel) {
|
||||
return async(dispatch, getState) => {
|
||||
const state = getState();
|
||||
|
||||
if (channel.isFavorite) {
|
||||
unmarkFavorite(channel.id)(dispatch, getState);
|
||||
}
|
||||
|
||||
toggleGMChannel(channel.id, 'false')(dispatch, getState).then(() => {
|
||||
if (channel.isCurrent) {
|
||||
selectInitialChannel(state.entities.teams.currentTeamId)(dispatch, getState);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export function closeDirectChannel(channel) {
|
||||
return async (dispatch, getState) => {
|
||||
switch (channel.type) {
|
||||
case Constants.DM_CHANNEL:
|
||||
return closeDMChannel(channel)(dispatch, getState);
|
||||
case Constants.GM_CHANNEL:
|
||||
return closeGMChannel(channel)(dispatch, getState);
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
}
|
||||
|
||||
export function markFavorite(channelId) {
|
||||
return async (dispatch, getState) => {
|
||||
const {currentUserId} = getState().entities.users;
|
||||
|
|
|
|||
|
|
@ -8,13 +8,10 @@ import {
|
|||
Text,
|
||||
View
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
|
||||
import {OnlineStatus, AwayStatus, OfflineStatus} from 'app/components/status_icons';
|
||||
import ChanneIcon from 'app/components/channel_icon';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
|
||||
export default class ChannelDrawerItem extends PureComponent {
|
||||
static propTypes = {
|
||||
channel: PropTypes.object.isRequired,
|
||||
|
|
@ -37,17 +34,10 @@ export default class ChannelDrawerItem extends PureComponent {
|
|||
|
||||
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) {
|
||||
|
|
@ -61,17 +51,11 @@ export default class ChannelDrawerItem extends PureComponent {
|
|||
}
|
||||
|
||||
if (hasUnread) {
|
||||
unreadIcon = style.iconUnread;
|
||||
unreadText = style.textUnread;
|
||||
unreadGroupBox = style.groupBoxUnread;
|
||||
unreadGroup = style.groupUnread;
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
activeItem = style.itemActive;
|
||||
activeIcon = style.iconActive;
|
||||
activeGroupBox = style.groupBoxActive;
|
||||
activeGroup = style.groupActive;
|
||||
activeText = style.textActive;
|
||||
|
||||
activeBorder = (
|
||||
|
|
@ -79,67 +63,17 @@ export default class ChannelDrawerItem extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
if (channel.type === Constants.OPEN_CHANNEL) {
|
||||
icon = (
|
||||
<Icon
|
||||
name='globe'
|
||||
style={[style.icon, unreadIcon, activeIcon]}
|
||||
/>
|
||||
);
|
||||
} else if (channel.type === Constants.PRIVATE_CHANNEL) {
|
||||
icon = (
|
||||
<Icon
|
||||
name='lock'
|
||||
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 = (
|
||||
<View style={style.statusIcon}>
|
||||
<OnlineStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={theme.onlineIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
break;
|
||||
case Constants.AWAY:
|
||||
icon = (
|
||||
<View style={style.statusIcon}>
|
||||
<AwayStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={theme.awayIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
break;
|
||||
default:
|
||||
icon = (
|
||||
<View style={style.statusIcon}>
|
||||
<OfflineStatus
|
||||
width={12}
|
||||
height={12}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
const icon = (
|
||||
<ChanneIcon
|
||||
isActive={isActive}
|
||||
hasUnread={hasUnread}
|
||||
membersCount={channel.display_name.split(',').length}
|
||||
size={12}
|
||||
status={channel.status}
|
||||
theme={theme}
|
||||
type={channel.type}
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<TouchableHighlight
|
||||
|
|
@ -191,48 +125,6 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
|||
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,
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import deepEqual from 'deep-equal';
|
|||
import React, {PropTypes, Component} from 'react';
|
||||
import {
|
||||
Alert,
|
||||
InteractionManager,
|
||||
ListView,
|
||||
Platform,
|
||||
StyleSheet,
|
||||
|
|
@ -26,15 +27,9 @@ import UnreadIndicator from './unread_indicator';
|
|||
|
||||
class ChannelDrawerList extends Component {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
currentTeam: PropTypes.object.isRequired,
|
||||
currentChannel: PropTypes.object,
|
||||
channels: PropTypes.object.isRequired,
|
||||
channelMembers: PropTypes.object,
|
||||
theme: PropTypes.object.isRequired,
|
||||
onSelectChannel: PropTypes.func.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
closeDMChannel: PropTypes.func.isRequired,
|
||||
closeDirectChannel: PropTypes.func.isRequired,
|
||||
closeOptionsModal: PropTypes.func.isRequired,
|
||||
goToCreateChannel: PropTypes.func.isRequired,
|
||||
leaveChannel: PropTypes.func.isRequired,
|
||||
markFavorite: PropTypes.func.isRequired,
|
||||
|
|
@ -42,9 +37,15 @@ class ChannelDrawerList extends Component {
|
|||
unmarkFavorite: PropTypes.func.isRequired,
|
||||
showOptionsModal: PropTypes.func.isRequired,
|
||||
showDirectMessagesModal: PropTypes.func.isRequired,
|
||||
showMoreChannelsModal: PropTypes.func.isRequired,
|
||||
closeOptionsModal: PropTypes.func.isRequired
|
||||
}).isRequired
|
||||
showMoreChannelsModal: PropTypes.func.isRequired
|
||||
}).isRequired,
|
||||
channels: PropTypes.object.isRequired,
|
||||
channelMembers: PropTypes.object,
|
||||
currentTeam: PropTypes.object.isRequired,
|
||||
currentChannel: PropTypes.object,
|
||||
intl: intlShape.isRequired,
|
||||
onSelectChannel: PropTypes.func.isRequired,
|
||||
theme: PropTypes.object.isRequired
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
|
@ -124,8 +125,10 @@ class ChannelDrawerList extends Component {
|
|||
};
|
||||
|
||||
handleClose = (channel) => {
|
||||
const {closeDirectChannel, closeOptionsModal} = this.props.actions;
|
||||
this.setState({showOptions: false});
|
||||
this.props.actions.closeDMChannel(channel);
|
||||
closeDirectChannel(channel);
|
||||
InteractionManager.runAfterInteractons(closeOptionsModal);
|
||||
};
|
||||
|
||||
handleLeave = (channel, term) => {
|
||||
|
|
@ -156,9 +159,11 @@ class ChannelDrawerList extends Component {
|
|||
let open;
|
||||
let close;
|
||||
let favorite;
|
||||
let term;
|
||||
let title;
|
||||
|
||||
if (channel.type === Constants.DM_CHANNEL) {
|
||||
switch (channel.type) {
|
||||
case Constants.DM_CHANNEL:
|
||||
title = formatMessage({
|
||||
id: 'mobile.channel_list.modalTitle',
|
||||
defaultMessage: 'Select an action for the {term} {name}'},
|
||||
|
|
@ -179,13 +184,41 @@ class ChannelDrawerList extends Component {
|
|||
action: () => {
|
||||
this.handleClose(channel);
|
||||
},
|
||||
text: formatMessage({id: 'sidebar.removeList', defaultMessage: 'Remove from list'}),
|
||||
text: formatMessage({id: 'mobile.channel_list.closeDM', defaultMessage: 'Close Direct Message'}),
|
||||
textStyle: {
|
||||
color: '#CC3239'
|
||||
}
|
||||
};
|
||||
} else {
|
||||
const term = channel.type === Constants.OPEN_CHANNEL ?
|
||||
break;
|
||||
case Constants.GM_CHANNEL:
|
||||
title = formatMessage({
|
||||
id: 'mobile.channel_list.modalTitle',
|
||||
defaultMessage: 'Select an action for the {term} {name}'},
|
||||
{
|
||||
name: channel.display_name,
|
||||
term: formatMessage({id: 'mobile.channel_list.gm', defaultMessage: 'Group Message'}).toLowerCase()
|
||||
});
|
||||
|
||||
open = {
|
||||
action: () => {
|
||||
this.props.actions.closeOptionsModal();
|
||||
this.onSelectChannel(channel);
|
||||
},
|
||||
text: formatMessage({id: 'mobile.channel_list.openGM', defaultMessage: 'Open Group Message'})
|
||||
};
|
||||
|
||||
close = {
|
||||
action: () => {
|
||||
this.handleClose(channel);
|
||||
},
|
||||
text: formatMessage({id: 'mobile.channel_list.closeGM', defaultMessage: 'Close Group Message'}),
|
||||
textStyle: {
|
||||
color: '#CC3239'
|
||||
}
|
||||
};
|
||||
break;
|
||||
default:
|
||||
term = channel.type === Constants.OPEN_CHANNEL ?
|
||||
formatMessage({id: 'mobile.channel_list.publicChannel', defaultMessage: 'Public Channel'}) :
|
||||
formatMessage({id: 'mobile.channel_list.privateChannel', defaultMessage: 'Private Channel'});
|
||||
|
||||
|
|
@ -220,6 +253,7 @@ class ChannelDrawerList extends Component {
|
|||
}
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (channel.isFavorite) {
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import {
|
|||
} from 'app/actions/navigation';
|
||||
|
||||
import {
|
||||
closeDMChannel,
|
||||
closeDirectChannel,
|
||||
leaveChannel,
|
||||
markFavorite,
|
||||
unmarkFavorite
|
||||
|
|
@ -31,7 +31,7 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
closeDMChannel,
|
||||
closeDirectChannel,
|
||||
goToCreateChannel,
|
||||
leaveChannel,
|
||||
markFavorite,
|
||||
|
|
|
|||
160
app/components/channel_icon.js
Normal file
160
app/components/channel_icon.js
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
// Copyright (c) 2017 Mattermost, Inc. All Rights Reserved.
|
||||
// See License.txt for license information.
|
||||
|
||||
import React, {PropTypes} from 'react';
|
||||
import {
|
||||
StyleSheet,
|
||||
Text,
|
||||
View
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
|
||||
import {OnlineStatus, AwayStatus, OfflineStatus} from 'app/components/status_icons';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
function channelIcon(props) {
|
||||
const {isActive, hasUnread, membersCount, size, status, theme, type} = props;
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
let activeIcon;
|
||||
let unreadIcon;
|
||||
let activeGroupBox;
|
||||
let unreadGroupBox;
|
||||
let activeGroup;
|
||||
let unreadGroup;
|
||||
|
||||
if (hasUnread) {
|
||||
unreadIcon = style.iconUnread;
|
||||
unreadGroupBox = style.groupBoxUnread;
|
||||
unreadGroup = style.groupUnread;
|
||||
}
|
||||
|
||||
if (isActive) {
|
||||
activeIcon = style.iconActive;
|
||||
activeGroupBox = style.groupBoxActive;
|
||||
activeGroup = style.groupActive;
|
||||
}
|
||||
|
||||
if (type === Constants.OPEN_CHANNEL) {
|
||||
return (
|
||||
<Icon
|
||||
name='globe'
|
||||
style={[style.icon, unreadIcon, activeIcon, {fontSize: size}]}
|
||||
/>
|
||||
);
|
||||
} else if (type === Constants.PRIVATE_CHANNEL) {
|
||||
return (
|
||||
<Icon
|
||||
name='lock'
|
||||
style={[style.icon, unreadIcon, activeIcon, {fontSize: size}]}
|
||||
/>
|
||||
);
|
||||
} else if (type === Constants.GM_CHANNEL) {
|
||||
return (
|
||||
<View style={style.groupContainer}>
|
||||
<View style={[style.groupBox, unreadGroupBox, activeGroupBox, {width: (size + 2), height: (size + 3)}]}>
|
||||
<Text style={[style.group, unreadGroup, activeGroup, {fontSize: (size - 2)}]}>
|
||||
{membersCount}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
switch (status) {
|
||||
case Constants.ONLINE:
|
||||
return (
|
||||
<View style={style.statusIcon}>
|
||||
<OnlineStatus
|
||||
width={size}
|
||||
height={size}
|
||||
color={theme.onlineIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
case Constants.AWAY:
|
||||
return (
|
||||
<View style={style.statusIcon}>
|
||||
<AwayStatus
|
||||
width={size}
|
||||
height={size}
|
||||
color={theme.awayIndicator}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
default:
|
||||
return (
|
||||
<View style={style.statusIcon}>
|
||||
<OfflineStatus
|
||||
width={size}
|
||||
height={size}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.4)}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
icon: {
|
||||
color: changeOpacity(theme.sidebarText, 0.4),
|
||||
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),
|
||||
justifyContent: 'center'
|
||||
},
|
||||
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
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
channelIcon.propTypes = {
|
||||
isActive: PropTypes.bool,
|
||||
hasUnread: PropTypes.bool,
|
||||
membersCount: PropTypes.number,
|
||||
size: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
type: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
channelIcon.defaultProps = {
|
||||
isActive: false,
|
||||
hasUnread: false,
|
||||
size: 12
|
||||
};
|
||||
|
||||
export default channelIcon;
|
||||
|
|
@ -11,43 +11,12 @@ import {
|
|||
} from 'react-native';
|
||||
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
|
||||
import ChannelInfoHeader from './channel_info_header';
|
||||
import ChannelInfoRow from './channel_info_row';
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg
|
||||
},
|
||||
footer: {
|
||||
marginTop: 40,
|
||||
borderTopWidth: 1,
|
||||
borderBottomWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
},
|
||||
rowsContainer: {
|
||||
borderTopWidth: 1,
|
||||
borderBottomWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
backgroundColor: theme.centerChannelBg
|
||||
},
|
||||
separator: {
|
||||
marginHorizontal: 15,
|
||||
height: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
class ChannelInfo extends PureComponent {
|
||||
static propTypes = {
|
||||
intl: intlShape.isRequired,
|
||||
|
|
@ -55,19 +24,23 @@ class ChannelInfo extends PureComponent {
|
|||
currentChannel: PropTypes.object.isRequired,
|
||||
currentChannelCreatorName: PropTypes.string,
|
||||
currentChannelMemberCount: PropTypes.number,
|
||||
status: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
isCurrent: PropTypes.bool.isRequired,
|
||||
isFavorite: PropTypes.bool.isRequired,
|
||||
leaveChannelRequest: PropTypes.object.isRequired,
|
||||
canManageUsers: PropTypes.bool.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
closeDMChannel: PropTypes.func.isRequired,
|
||||
closeGMChannel: PropTypes.func.isRequired,
|
||||
deleteChannel: PropTypes.func.isRequired,
|
||||
getChannelStats: PropTypes.func.isRequired,
|
||||
goToChannelMembers: PropTypes.func.isRequired,
|
||||
goBack: PropTypes.func.isRequired,
|
||||
goToChannelAddMembers: PropTypes.func.isRequired,
|
||||
markFavorite: PropTypes.func.isRequired,
|
||||
unmarkFavorite: PropTypes.func.isRequired,
|
||||
goToChannelMembers: PropTypes.func.isRequired,
|
||||
leaveChannel: PropTypes.func.isRequired,
|
||||
deleteChannel: PropTypes.func.isRequired
|
||||
markFavorite: PropTypes.func.isRequired,
|
||||
unmarkFavorite: PropTypes.func.isRequired
|
||||
})
|
||||
};
|
||||
|
||||
|
|
@ -145,11 +118,36 @@ class ChannelInfo extends PureComponent {
|
|||
);
|
||||
}
|
||||
|
||||
handleClose = () => {
|
||||
const {currentChannel, isCurrent, isFavorite} = this.props;
|
||||
const channel = Object.assign({}, currentChannel, {isCurrent}, {isFavorite});
|
||||
const {closeDMChannel, closeGMChannel, goBack} = this.props.actions;
|
||||
|
||||
switch (channel.type) {
|
||||
case Constants.DM_CHANNEL:
|
||||
closeDMChannel(channel).then(goBack);
|
||||
break;
|
||||
case Constants.GM_CHANNEL:
|
||||
closeGMChannel(channel).then(goBack);
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
renderLeaveOrDeleteChannelRow() {
|
||||
const channel = this.props.currentChannel;
|
||||
const isDefaultChannel = channel.name === Constants.DEFAULT_CHANNEL;
|
||||
const isDirectMessage = channel.type === Constants.DM_CHANNEL;
|
||||
return !isDefaultChannel && !isDirectMessage;
|
||||
const isGroupMessage = channel.type === Constants.GM_CHANNEL;
|
||||
|
||||
return !isDefaultChannel && !isDirectMessage && !isGroupMessage;
|
||||
}
|
||||
|
||||
renderCloseDirect() {
|
||||
const channel = this.props.currentChannel;
|
||||
const isDirectMessage = channel.type === Constants.DM_CHANNEL;
|
||||
const isGroupMessage = channel.type === Constants.GM_CHANNEL;
|
||||
|
||||
return isDirectMessage || isGroupMessage;
|
||||
}
|
||||
|
||||
render() {
|
||||
|
|
@ -163,6 +161,19 @@ class ChannelInfo extends PureComponent {
|
|||
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
let i18nId;
|
||||
let defaultMessage;
|
||||
switch (currentChannel.type) {
|
||||
case Constants.DM_CHANNEL:
|
||||
i18nId = 'mobile.channel_list.closeDM';
|
||||
defaultMessage = 'Close Direct Message';
|
||||
break;
|
||||
case Constants.GM_CHANNEL:
|
||||
i18nId = 'mobile.channel_list.closeGM';
|
||||
defaultMessage = 'Close Group Message';
|
||||
break;
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<ScrollView
|
||||
|
|
@ -171,10 +182,12 @@ class ChannelInfo extends PureComponent {
|
|||
<ChannelInfoHeader
|
||||
createAt={currentChannel.create_at}
|
||||
creator={currentChannelCreatorName}
|
||||
memberCount={currentChannelMemberCount}
|
||||
displayName={currentChannel.display_name}
|
||||
header={currentChannel.header}
|
||||
purpose={currentChannel.purpose}
|
||||
theme={theme}
|
||||
type={currentChannel.type}
|
||||
/>
|
||||
<View style={style.rowsContainer}>
|
||||
<ChannelInfoRow
|
||||
|
|
@ -231,17 +244,62 @@ class ChannelInfo extends PureComponent {
|
|||
action={() => this.handleDeleteOrLeave('delete')}
|
||||
defaultMessage='Delete Channel'
|
||||
icon='trash'
|
||||
iconColor='#DA4A4A'
|
||||
iconColor='#CA3B27'
|
||||
textId='mobile.routes.channelInfo.delete_channel'
|
||||
textColor='#DA4A4A'
|
||||
textColor='#CA3B27'
|
||||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
{this.renderCloseDirect() &&
|
||||
<View style={style.footer}>
|
||||
<ChannelInfoRow
|
||||
action={this.handleClose}
|
||||
defaultMessage={defaultMessage}
|
||||
icon='times'
|
||||
iconColor='#CA3B27'
|
||||
textId={i18nId}
|
||||
textColor='#CA3B27'
|
||||
theme={theme}
|
||||
/>
|
||||
</View>
|
||||
}
|
||||
</ScrollView>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: theme.centerChannelBg
|
||||
},
|
||||
scrollView: {
|
||||
flex: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.03)
|
||||
},
|
||||
footer: {
|
||||
marginTop: 40,
|
||||
borderTopWidth: 1,
|
||||
borderBottomWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
},
|
||||
rowsContainer: {
|
||||
borderTopWidth: 1,
|
||||
borderBottomWidth: 1,
|
||||
borderTopColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1),
|
||||
backgroundColor: theme.centerChannelBg
|
||||
},
|
||||
separator: {
|
||||
marginHorizontal: 15,
|
||||
height: 1,
|
||||
backgroundColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export default injectIntl(ChannelInfo);
|
||||
|
|
|
|||
|
|
@ -3,14 +3,27 @@
|
|||
|
||||
import {bindActionCreators} from 'redux';
|
||||
|
||||
import navigationSceneConnect from '../navigationSceneConnect';
|
||||
|
||||
import {goToChannelMembers, goToChannelAddMembers, goBack} from 'app/actions/navigation';
|
||||
import {getChannelStats, deleteChannel} from 'mattermost-redux/actions/channels';
|
||||
import {markFavorite, unmarkFavorite, leaveChannel} from 'app/actions/views/channel';
|
||||
import {getCurrentChannel, getCurrentChannelStats, getChannelsByCategory, canManageChannelMembers} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {
|
||||
closeDMChannel,
|
||||
closeGMChannel,
|
||||
leaveChannel,
|
||||
markFavorite,
|
||||
unmarkFavorite
|
||||
} from 'app/actions/views/channel';
|
||||
import navigationSceneConnect from 'app/scenes/navigationSceneConnect';
|
||||
import {getTheme} from 'app/selectors/preferences';
|
||||
import {getUser} from 'mattermost-redux/selectors/entities/users';
|
||||
|
||||
import {getChannelStats, deleteChannel} from 'mattermost-redux/actions/channels';
|
||||
import {Constants} from 'mattermost-redux/constants';
|
||||
import {
|
||||
getCurrentChannel,
|
||||
getCurrentChannelStats,
|
||||
getChannelsByCategory,
|
||||
canManageChannelMembers
|
||||
} from 'mattermost-redux/selectors/entities/channels';
|
||||
import {getCurrentUserId, getUser, getStatusForUserId} from 'mattermost-redux/selectors/entities/users';
|
||||
import {getUserIdFromChannelName} from 'mattermost-redux/utils/channel_utils';
|
||||
|
||||
import ChannelInfo from './channel_info';
|
||||
|
||||
|
|
@ -19,18 +32,28 @@ function mapStateToProps(state, ownProps) {
|
|||
const currentChannelCreator = getUser(state, currentChannel.creator_id);
|
||||
const currentChannelCreatorName = currentChannelCreator && currentChannelCreator.username;
|
||||
const currentChannelMemberCount = getCurrentChannelStats(state) && getCurrentChannelStats(state).member_count;
|
||||
const currentUserId = getCurrentUserId(state);
|
||||
const favoriteChannels = getChannelsByCategory(state).favoriteChannels.map((f) => f.id);
|
||||
const isCurrent = currentChannel.id === state.entities.channels.currentChannelId;
|
||||
const isFavorite = favoriteChannels.indexOf(currentChannel.id) > -1;
|
||||
const leaveChannelRequest = state.requests.channels.leaveChannel;
|
||||
|
||||
let status;
|
||||
if (currentChannel.type === Constants.DM_CHANNEL) {
|
||||
const teammateId = getUserIdFromChannelName(currentUserId, currentChannel.name);
|
||||
status = getStatusForUserId(state, teammateId);
|
||||
}
|
||||
|
||||
return {
|
||||
...ownProps,
|
||||
currentTeamId: state.entities.teams.currentTeamId,
|
||||
currentChannel,
|
||||
currentChannelCreatorName,
|
||||
currentChannelMemberCount,
|
||||
isCurrent,
|
||||
isFavorite,
|
||||
leaveChannelRequest,
|
||||
status,
|
||||
theme: getTheme(state),
|
||||
canManageUsers: canManageChannelMembers(state)
|
||||
};
|
||||
|
|
@ -39,14 +62,16 @@ function mapStateToProps(state, ownProps) {
|
|||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators({
|
||||
getChannelStats,
|
||||
goToChannelMembers,
|
||||
goToChannelAddMembers,
|
||||
markFavorite,
|
||||
unmarkFavorite,
|
||||
leaveChannel,
|
||||
closeDMChannel,
|
||||
closeGMChannel,
|
||||
deleteChannel,
|
||||
goBack
|
||||
getChannelStats,
|
||||
goBack,
|
||||
goToChannelAddMembers,
|
||||
goToChannelMembers,
|
||||
leaveChannel,
|
||||
markFavorite,
|
||||
unmarkFavorite
|
||||
}, dispatch)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,69 +7,35 @@ import {
|
|||
Text,
|
||||
View
|
||||
} from 'react-native';
|
||||
import Icon from 'react-native-vector-icons/FontAwesome';
|
||||
|
||||
import ChanneIcon from 'app/components/channel_icon';
|
||||
import FormattedDate from 'app/components/formatted_date';
|
||||
import FormattedText from 'app/components/formatted_text';
|
||||
import {changeOpacity, makeStyleSheetFromTheme} from 'app/utils/theme';
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
marginBottom: 40,
|
||||
padding: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
},
|
||||
channelName: {
|
||||
marginLeft: 5,
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
color: theme.centerChannelColor
|
||||
},
|
||||
channelNameContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingBottom: 10
|
||||
},
|
||||
createdBy: {
|
||||
flexDirection: 'row',
|
||||
fontSize: 11,
|
||||
marginTop: 5,
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
detail: {
|
||||
fontSize: 13,
|
||||
color: theme.centerChannelColor
|
||||
},
|
||||
header: {
|
||||
fontSize: 12,
|
||||
marginBottom: 10,
|
||||
color: theme.centerChannelColor,
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
section: {
|
||||
marginTop: 15
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function channelInfoHeader(props) {
|
||||
const {createAt, creator, displayName, header, purpose, theme} = props;
|
||||
const {createAt, creator, displayName, header, memberCount, purpose, status, theme, type} = props;
|
||||
|
||||
const style = getStyleSheet(theme);
|
||||
|
||||
return (
|
||||
<View style={style.container}>
|
||||
<View style={style.channelNameContainer}>
|
||||
<Icon
|
||||
name='globe'
|
||||
<ChanneIcon
|
||||
isActive={true}
|
||||
membersCount={memberCount - 1}
|
||||
size={15}
|
||||
color={changeOpacity(theme.centerChannelColor, 0.7)}
|
||||
status={status}
|
||||
theme={theme}
|
||||
type={type}
|
||||
/>
|
||||
<Text style={style.channelName}>{displayName}</Text>
|
||||
<Text
|
||||
ellipsizeMode='tail'
|
||||
numberOfLines={1}
|
||||
style={style.channelName}
|
||||
>
|
||||
{displayName}
|
||||
</Text>
|
||||
</View>
|
||||
{purpose.length > 0 &&
|
||||
<View style={style.section}>
|
||||
|
|
@ -115,10 +81,56 @@ function channelInfoHeader(props) {
|
|||
channelInfoHeader.propTypes = {
|
||||
createAt: PropTypes.number.isRequired,
|
||||
creator: PropTypes.string,
|
||||
memberCount: PropTypes.number,
|
||||
displayName: PropTypes.string.isRequired,
|
||||
header: PropTypes.string,
|
||||
purpose: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired
|
||||
status: PropTypes.string,
|
||||
theme: PropTypes.object.isRequired,
|
||||
type: PropTypes.string.isRequired
|
||||
};
|
||||
|
||||
const getStyleSheet = makeStyleSheetFromTheme((theme) => {
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
backgroundColor: theme.centerChannelBg,
|
||||
marginBottom: 40,
|
||||
padding: 15,
|
||||
borderBottomWidth: 1,
|
||||
borderBottomColor: changeOpacity(theme.centerChannelColor, 0.1)
|
||||
},
|
||||
channelName: {
|
||||
flex: 1,
|
||||
fontSize: 15,
|
||||
fontWeight: '600',
|
||||
color: theme.centerChannelColor
|
||||
},
|
||||
channelNameContainer: {
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingBottom: 10
|
||||
},
|
||||
createdBy: {
|
||||
flexDirection: 'row',
|
||||
fontSize: 11,
|
||||
marginTop: 5,
|
||||
color: changeOpacity(theme.centerChannelColor, 0.5),
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
detail: {
|
||||
fontSize: 13,
|
||||
color: theme.centerChannelColor
|
||||
},
|
||||
header: {
|
||||
fontSize: 12,
|
||||
marginBottom: 10,
|
||||
color: theme.centerChannelColor,
|
||||
backgroundColor: 'transparent'
|
||||
},
|
||||
section: {
|
||||
marginTop: 15
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
export default channelInfoHeader;
|
||||
|
|
|
|||
|
|
@ -1503,9 +1503,13 @@
|
|||
"mobile.channel_list.alertMessageLeaveChannel": "Are you sure you want to leave the {term} with {name}?",
|
||||
"mobile.channel_list.alertNo": "No",
|
||||
"mobile.channel_list.alertYes": "Yes",
|
||||
"mobile.channel_list.closeDM": "Close Direct Message",
|
||||
"mobile.channel_list.closeGM": "Close Group Message",
|
||||
"mobile.channel_list.open": "Open {term}",
|
||||
"mobile.channel_list.openDM": "Open Direct Message",
|
||||
"mobile.channel_list.openGM": "Open Group Message",
|
||||
"mobile.channel_list.dm": "Direct Message",
|
||||
"mobile.channel_list.gm": "Group Message",
|
||||
"mobile.channel_list.privateChannel": "Private Channel",
|
||||
"mobile.channel_list.publicChannel": "Public Channel",
|
||||
"mobile.components.channels_list_view.yourChannels": "Your channels:",
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
"harmony-reflect": "1.5.1",
|
||||
"intl": "1.2.5",
|
||||
"isomorphic-fetch": "2.2.1",
|
||||
"mattermost-redux": "mattermost/mattermost-redux#release-3.7",
|
||||
"mattermost-redux": "mattermost/mattermost-redux#957b27015b46538c707f534c24e750e5d1d1e517",
|
||||
"react": "15.4.1",
|
||||
"react-addons-pure-render-mixin": "15.4.1",
|
||||
"react-intl": "2.2.2",
|
||||
|
|
|
|||
Loading…
Reference in a new issue