MM-9376 Channel mute (#1540)

* MM-9376 Channel mute

* UI Feedback review
This commit is contained in:
Elias Nahum 2018-03-29 17:02:23 +03:00 committed by Harrison Healey
parent 16ccfab7f6
commit b3806c04b3
7 changed files with 95 additions and 21 deletions

View file

@ -25,6 +25,7 @@ export default class ChannelItem extends PureComponent {
currentChannelId: PropTypes.string.isRequired,
displayName: PropTypes.string.isRequired,
fake: PropTypes.bool,
isChannelMuted: PropTypes.bool,
isMyUser: PropTypes.bool,
isUnread: PropTypes.bool,
mentions: PropTypes.number.isRequired,
@ -76,6 +77,7 @@ export default class ChannelItem extends PureComponent {
channelId,
currentChannelId,
displayName,
isChannelMuted,
isMyUser,
isUnread,
mentions,
@ -101,6 +103,7 @@ export default class ChannelItem extends PureComponent {
let extraItemStyle;
let extraTextStyle;
let extraBorder;
let mutedStyle;
if (isActive) {
extraItemStyle = style.itemActive;
@ -127,6 +130,10 @@ export default class ChannelItem extends PureComponent {
);
}
if (isChannelMuted) {
mutedStyle = style.muted;
}
const icon = (
<ChannelIcon
isActive={isActive}
@ -148,7 +155,7 @@ export default class ChannelItem extends PureComponent {
onPress={this.onPress}
onLongPress={this.onPreview}
>
<View style={style.container}>
<View style={[style.container, mutedStyle]}>
{extraBorder}
<View style={[style.item, extraItemStyle]}>
{icon}
@ -217,5 +224,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => {
color: theme.mentionColor,
fontSize: 10,
},
muted: {
opacity: 0.3,
},
};
});

View file

@ -7,6 +7,7 @@ import {General} from 'mattermost-redux/constants';
import {getCurrentChannelId, makeGetChannel, getMyChannelMember} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {getCurrentUserId, getUser} from 'mattermost-redux/selectors/entities/users';
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import ChannelItem from './channel_item';
@ -15,12 +16,9 @@ function makeMapStateToProps() {
return (state, ownProps) => {
const channel = ownProps.channel || getChannel(state, {id: ownProps.channelId});
let member;
if (ownProps.isUnread) {
member = getMyChannelMember(state, ownProps.channelId);
}
const member = getMyChannelMember(state, ownProps.channelId);
const currentUserId = getCurrentUserId(state);
let isMyUser = false;
let teammateDeletedAt = 0;
if (channel.type === General.DM_CHANNEL && channel.teammate_id) {
@ -35,6 +33,7 @@ function makeMapStateToProps() {
currentChannelId: getCurrentChannelId(state),
displayName: channel.display_name,
fake: channel.fake,
isChannelMuted: isChannelMuted(member),
isMyUser,
mentions: member ? member.mention_count : 0,
status: channel.status,

View file

@ -17,6 +17,7 @@ export default class ChannelTitle extends PureComponent {
static propTypes = {
currentChannelName: PropTypes.string,
displayName: PropTypes.string,
isChannelMuted: PropTypes.bool,
onPress: PropTypes.func,
theme: PropTypes.object,
};
@ -28,7 +29,7 @@ export default class ChannelTitle extends PureComponent {
};
render() {
const {currentChannelName, displayName, onPress, theme} = this.props;
const {currentChannelName, displayName, isChannelMuted, onPress, theme} = this.props;
const channelName = displayName || currentChannelName;
const style = getStyle(theme);
let icon;
@ -42,6 +43,17 @@ export default class ChannelTitle extends PureComponent {
);
}
let mutedIcon;
if (isChannelMuted) {
mutedIcon = (
<Icon
style={[style.icon, style.muted]}
size={15}
name='bell-slash-o'
/>
);
}
return (
<TouchableOpacity
style={style.container}
@ -56,6 +68,7 @@ export default class ChannelTitle extends PureComponent {
{channelName}
</Text>
{icon}
{mutedIcon}
</View>
</TouchableOpacity>
);
@ -74,6 +87,7 @@ const getStyle = makeStyleSheetFromTheme((theme) => {
top: -1,
flexDirection: 'row',
justifyContent: 'flex-start',
width: '90%',
},
icon: {
color: theme.sidebarHeaderTextColor,
@ -85,5 +99,10 @@ const getStyle = makeStyleSheetFromTheme((theme) => {
fontWeight: 'bold',
textAlign: 'center',
},
muted: {
marginTop: 1,
opacity: 0.6,
marginLeft: 0,
},
};
});

View file

@ -3,17 +3,20 @@
import {connect} from 'react-redux';
import {getCurrentChannel} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentChannel, getMyCurrentChannelMembership} from 'mattermost-redux/selectors/entities/channels';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {isChannelMuted} from 'mattermost-redux/utils/channel_utils';
import ChannelTitle from './channel_title';
function mapStateToProps(state) {
const currentChannel = getCurrentChannel(state);
const myChannelMember = getMyCurrentChannelMembership(state);
return {
currentChannelName: currentChannel ? currentChannel.display_name : '',
displayName: state.views.channel.displayName,
isChannelMuted: isChannelMuted(myChannelMember),
theme: getTheme(state),
};
}

View file

@ -35,14 +35,17 @@ export default class ChannelInfo extends PureComponent {
unfavoriteChannel: PropTypes.func.isRequired,
getCustomEmojisInText: PropTypes.func.isRequired,
selectFocusedPostId: PropTypes.func.isRequired,
updateChannelNotifyProps: PropTypes.func.isRequired,
}),
canDeleteChannel: PropTypes.bool.isRequired,
currentChannel: PropTypes.object.isRequired,
currentChannelCreatorName: PropTypes.string,
currentChannelMemberCount: PropTypes.number,
currentUserId: PropTypes.string,
navigator: PropTypes.object,
status: PropTypes.string,
theme: PropTypes.object.isRequired,
isChannelMuted: PropTypes.bool.isRequired,
isCurrent: PropTypes.bool.isRequired,
isFavorite: PropTypes.bool.isRequired,
canManageUsers: PropTypes.bool.isRequired,
@ -58,6 +61,7 @@ export default class ChannelInfo extends PureComponent {
this.state = {
isFavorite: props.isFavorite,
isMuted: props.isChannelMuted,
};
}
@ -71,10 +75,17 @@ export default class ChannelInfo extends PureComponent {
setNavigatorStyles(this.props.navigator, nextProps.theme);
}
const isFavorite = nextProps.isFavorite;
if (isFavorite !== this.state.isFavorite) {
this.setState({isFavorite});
let isFavorite = this.state.isFavorite;
if (isFavorite !== nextProps.isFavorite) {
isFavorite = nextProps.isFavorite;
}
let isMuted = this.state.isMuted;
if (isMuted !== nextProps.isChannelMuted) {
isMuted = nextProps.isChannelMuted;
}
this.setState({isFavorite, isMuted});
}
close = () => {
@ -253,6 +264,17 @@ export default class ChannelInfo extends PureComponent {
this.showPermalinkView(postId);
};
handleMuteChannel = () => {
const {actions, currentChannel, currentUserId, isChannelMuted} = this.props;
const {updateChannelNotifyProps} = actions;
const opts = {
mark_unread: isChannelMuted ? 'all' : 'mention',
};
this.setState({isMuted: !isChannelMuted});
updateChannelNotifyProps(currentUserId, currentChannel.id, opts);
};
showPermalinkView = (postId) => {
const {actions, navigator} = this.props;
@ -365,6 +387,16 @@ export default class ChannelInfo extends PureComponent {
togglable={true}
theme={theme}
/>
<View style={style.separator}/>
<ChannelInfoRow
action={this.handleMuteChannel}
defaultMessage='Mute channel'
detail={this.state.isMuted}
icon='bell-slash-o'
textId='channel_notifications.muteChannel.settings'
togglable={true}
theme={theme}
/>
{
/**

View file

@ -5,27 +5,34 @@ import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import {
closeDMChannel,
closeGMChannel,
leaveChannel,
loadChannelsByTeamName,
} from 'app/actions/views/channel';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
favoriteChannel,
getChannelStats,
deleteChannel,
unfavoriteChannel,
updateChannelNotifyProps,
} from 'mattermost-redux/actions/channels';
import {getCustomEmojisInText} from 'mattermost-redux/actions/emojis';
import {favoriteChannel, getChannelStats, deleteChannel, unfavoriteChannel} from 'mattermost-redux/actions/channels';
import {selectFocusedPostId} from 'mattermost-redux/actions/posts';
import {General} from 'mattermost-redux/constants';
import {getTheme} from 'mattermost-redux/selectors/entities/preferences';
import {
getCurrentChannel,
getMyCurrentChannelMembership,
getCurrentChannelStats,
getSortedFavoriteChannelIds,
canManageChannelMembers,
} from 'mattermost-redux/selectors/entities/channels';
import {getCurrentUserId, getUser, getStatusForUserId, getCurrentUserRoles} from 'mattermost-redux/selectors/entities/users';
import {getUserIdFromChannelName, showDeleteOption, showManagementOptions} from 'mattermost-redux/utils/channel_utils';
import {getUserIdFromChannelName, isChannelMuted, showDeleteOption, showManagementOptions} from 'mattermost-redux/utils/channel_utils';
import {isAdmin, isChannelAdmin, isSystemAdmin} from 'mattermost-redux/utils/user_utils';
import {
closeDMChannel,
closeGMChannel,
leaveChannel,
loadChannelsByTeamName,
} from 'app/actions/views/channel';
import ChannelInfo from './channel_info';
function mapStateToProps(state) {
@ -35,6 +42,7 @@ function mapStateToProps(state) {
const currentChannelCreatorName = currentChannelCreator && currentChannelCreator.username;
const currentChannelStats = getCurrentChannelStats(state);
const currentChannelMemberCount = currentChannelStats && currentChannelStats.member_count;
const currentChannelMember = getMyCurrentChannelMembership(state);
const currentUserId = getCurrentUserId(state);
const favoriteChannels = getSortedFavoriteChannelIds(state);
const isCurrent = currentChannel.id === state.entities.channels.currentChannelId;
@ -54,6 +62,8 @@ function mapStateToProps(state) {
currentChannel,
currentChannelCreatorName,
currentChannelMemberCount,
currentUserId,
isChannelMuted: isChannelMuted(currentChannelMember),
isCurrent,
isFavorite,
status,
@ -75,6 +85,7 @@ function mapDispatchToProps(dispatch) {
unfavoriteChannel,
getCustomEmojisInText,
selectFocusedPostId,
updateChannelNotifyProps,
}, dispatch),
};
}

View file

@ -4451,7 +4451,7 @@ map-visit@^1.0.0:
mattermost-redux@mattermost/mattermost-redux:
version "1.2.0"
resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/bd8142c4674cc489f2f0b92e80e06fc3b8d3c0a2"
resolved "https://codeload.github.com/mattermost/mattermost-redux/tar.gz/2c8afc7e9945aefc3159760cb2c69255e74b26fc"
dependencies:
deep-equal "1.0.1"
flow-copy-source "^1.2.2"