MM-9376 Channel mute (#1540)
* MM-9376 Channel mute * UI Feedback review
This commit is contained in:
parent
16ccfab7f6
commit
b3806c04b3
7 changed files with 95 additions and 21 deletions
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
},
|
||||
};
|
||||
});
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
/>
|
||||
{
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in a new issue