diff --git a/app/components/channel_drawer/channels_list/channel_item/channel_item.js b/app/components/channel_drawer/channels_list/channel_item/channel_item.js index 798580cdf..f47c11a2b 100644 --- a/app/components/channel_drawer/channels_list/channel_item/channel_item.js +++ b/app/components/channel_drawer/channels_list/channel_item/channel_item.js @@ -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 = ( - + {extraBorder} {icon} @@ -217,5 +224,8 @@ const getStyleSheet = makeStyleSheetFromTheme((theme) => { color: theme.mentionColor, fontSize: 10, }, + muted: { + opacity: 0.3, + }, }; }); diff --git a/app/components/channel_drawer/channels_list/channel_item/index.js b/app/components/channel_drawer/channels_list/channel_item/index.js index 5831c5e00..ef25b66e2 100644 --- a/app/components/channel_drawer/channels_list/channel_item/index.js +++ b/app/components/channel_drawer/channels_list/channel_item/index.js @@ -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, diff --git a/app/screens/channel/channel_nav_bar/channel_title/channel_title.js b/app/screens/channel/channel_nav_bar/channel_title/channel_title.js index 6990dabdf..875ddc6b4 100644 --- a/app/screens/channel/channel_nav_bar/channel_title/channel_title.js +++ b/app/screens/channel/channel_nav_bar/channel_title/channel_title.js @@ -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 = ( + + ); + } + return ( {icon} + {mutedIcon} ); @@ -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, + }, }; }); diff --git a/app/screens/channel/channel_nav_bar/channel_title/index.js b/app/screens/channel/channel_nav_bar/channel_title/index.js index 27b2c0a70..a0a9e0505 100644 --- a/app/screens/channel/channel_nav_bar/channel_title/index.js +++ b/app/screens/channel/channel_nav_bar/channel_title/index.js @@ -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), }; } diff --git a/app/screens/channel_info/channel_info.js b/app/screens/channel_info/channel_info.js index 93405b80a..467042c07 100644 --- a/app/screens/channel_info/channel_info.js +++ b/app/screens/channel_info/channel_info.js @@ -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} /> + + { /** diff --git a/app/screens/channel_info/index.js b/app/screens/channel_info/index.js index 61074d13e..4932fe190 100644 --- a/app/screens/channel_info/index.js +++ b/app/screens/channel_info/index.js @@ -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), }; } diff --git a/yarn.lock b/yarn.lock index a7b1ca108..71e5da746 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"