// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import $ from 'jquery'; import 'bootstrap'; import NavbarSearchBox from './search_bar.jsx'; import MessageWrapper from './message_wrapper.jsx'; import PopoverListMembers from 'components/popover_list_members'; import EditChannelHeaderModal from './edit_channel_header_modal.jsx'; import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx'; import ChannelInfoModal from './channel_info_modal.jsx'; import ChannelInviteModal from 'components/channel_invite_modal'; import ChannelMembersModal from './channel_members_modal.jsx'; import ChannelNotificationsModal from './channel_notifications_modal.jsx'; import DeleteChannelModal from './delete_channel_modal.jsx'; import RenameChannelModal from './rename_channel_modal.jsx'; import ConfirmModal from './confirm_modal.jsx'; import ToggleModalButton from './toggle_modal_button.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import UserStore from 'stores/user_store.jsx'; import TeamStore from 'stores/team_store.jsx'; import SearchStore from 'stores/search_store.jsx'; import PreferenceStore from 'stores/preference_store.jsx'; import WebrtcStore from 'stores/webrtc_store.jsx'; import * as GlobalActions from 'actions/global_actions.jsx'; import * as WebrtcActions from 'actions/webrtc_actions.jsx'; import * as ChannelActions from 'actions/channel_actions.jsx'; import * as Utils from 'utils/utils.jsx'; import * as ChannelUtils from 'utils/channel_utils.jsx'; import {getSiteURL} from 'utils/url.jsx'; import * as TextFormatting from 'utils/text_formatting.jsx'; import {getFlaggedPosts, getPinnedPosts} from 'actions/post_actions.jsx'; import AppDispatcher from 'dispatcher/app_dispatcher.jsx'; import {Constants, Preferences, UserStatuses, ActionTypes} from 'utils/constants.jsx'; import PropTypes from 'prop-types'; import React from 'react'; import {FormattedMessage} from 'react-intl'; import {Tooltip, OverlayTrigger, Popover} from 'react-bootstrap'; const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; export default class ChannelHeader extends React.Component { constructor(props) { super(props); this.onListenerChange = this.onListenerChange.bind(this); this.handleLeave = this.handleLeave.bind(this); this.searchMentions = this.searchMentions.bind(this); this.showRenameChannelModal = this.showRenameChannelModal.bind(this); this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this); this.handleShortcut = this.handleShortcut.bind(this); this.getFlagged = this.getFlagged.bind(this); this.getPinnedPosts = this.getPinnedPosts.bind(this); this.initWebrtc = this.initWebrtc.bind(this); this.onBusy = this.onBusy.bind(this); this.openDirectMessageModal = this.openDirectMessageModal.bind(this); this.createLeaveChannelModal = this.createLeaveChannelModal.bind(this); this.hideLeaveChannelModal = this.hideLeaveChannelModal.bind(this); const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; state.showMembersModal = false; state.showRenameChannelModal = false; this.state = state; } getStateFromStores() { const channel = ChannelStore.get(this.props.channelId); const stats = ChannelStore.getStats(this.props.channelId); const users = UserStore.getProfileListInChannel(this.props.channelId, false, true); let otherUserId = null; if (channel && channel.type === 'D') { otherUserId = Utils.getUserIdFromChannelName(channel); } return { channel, memberChannel: ChannelStore.getMyMember(this.props.channelId), users, userCount: stats.member_count, currentUser: UserStore.getCurrentUser(), otherUserId, enableFormatting: PreferenceStore.getBool(Preferences.CATEGORY_ADVANCED_SETTINGS, 'formatting', true), isBusy: WebrtcStore.isBusy(), isFavorite: channel && ChannelUtils.isFavoriteChannel(channel), showLeaveChannelModal: false }; } validState() { if (!this.state.channel || !this.state.memberChannel || !this.state.users || !this.state.userCount || !this.state.currentUser) { return false; } return true; } componentDidMount() { ChannelStore.addChangeListener(this.onListenerChange); ChannelStore.addStatsChangeListener(this.onListenerChange); SearchStore.addSearchChangeListener(this.onListenerChange); PreferenceStore.addChangeListener(this.onListenerChange); UserStore.addChangeListener(this.onListenerChange); UserStore.addInChannelChangeListener(this.onListenerChange); UserStore.addStatusesChangeListener(this.onListenerChange); WebrtcStore.addChangedListener(this.onListenerChange); WebrtcStore.addBusyListener(this.onBusy); $('.sidebar--left .dropdown-menu').perfectScrollbar(); document.addEventListener('keydown', this.handleShortcut); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onListenerChange); ChannelStore.removeStatsChangeListener(this.onListenerChange); SearchStore.removeSearchChangeListener(this.onListenerChange); PreferenceStore.removeChangeListener(this.onListenerChange); UserStore.removeChangeListener(this.onListenerChange); UserStore.removeInChannelChangeListener(this.onListenerChange); UserStore.removeStatusesChangeListener(this.onListenerChange); WebrtcStore.removeChangedListener(this.onListenerChange); WebrtcStore.removeBusyListener(this.onBusy); document.removeEventListener('keydown', this.handleShortcut); } shouldComponentUpdate(nextProps) { return Boolean(nextProps.channelId); } onListenerChange() { this.setState(this.getStateFromStores()); } handleLeave() { if (this.state.channel.type === Constants.PRIVATE_CHANNEL) { this.setState({ showLeaveChannelModal: true }); } else { ChannelActions.leaveChannel(this.state.channel.id); } } toggleFavorite = (e) => { e.preventDefault(); if (this.state.isFavorite) { ChannelActions.unmarkFavorite(this.state.channel.id); } else { ChannelActions.markFavorite(this.state.channel.id); } }; searchMentions(e) { e.preventDefault(); const user = this.state.currentUser; if (SearchStore.isMentionSearch) { // Close GlobalActions.toggleSideBarAction(false); } else { GlobalActions.emitSearchMentionsEvent(user); } } getPinnedPosts(e) { e.preventDefault(); if (SearchStore.isPinnedPosts) { GlobalActions.toggleSideBarAction(false); } else { getPinnedPosts(this.props.channelId); } } getFlagged(e) { e.preventDefault(); if (SearchStore.isFlaggedPosts) { GlobalActions.toggleSideBarAction(false); } else { getFlaggedPosts(); } } handleShortcut(e) { if (Utils.cmdOrCtrlPressed(e) && e.shiftKey) { if (e.keyCode === Constants.KeyCodes.M) { e.preventDefault(); this.searchMentions(e); } } } showRenameChannelModal(e) { e.preventDefault(); this.setState({ showRenameChannelModal: true }); } hideRenameChannelModal() { this.setState({ showRenameChannelModal: false }); } initWebrtc(contactId, isOnline) { if (isOnline && !this.state.isBusy) { GlobalActions.emitCloseRightHandSide(); WebrtcActions.initWebrtc(contactId, true); } } onBusy(isBusy) { this.setState({isBusy}); } openDirectMessageModal() { AppDispatcher.handleViewAction({ type: ActionTypes.TOGGLE_DM_MODAL, value: true, startingUsers: UserStore.getProfileListInChannel(this.props.channelId, true, false) }); } hideLeaveChannelModal() { this.setState({ showLeaveChannelModal: false }); } createLeaveChannelModal() { const title = ( {this.state.channel.display_name} }} /> ); const message = ( {this.state.channel.display_name} }} /> ); const buttonClass = 'btn btn-danger'; const button = ( ); return ( ChannelActions.leaveChannel(this.state.channel.id)} onCancel={this.hideLeaveChannelModal} /> ); } render() { const flagIcon = Constants.FLAG_ICON_SVG; const pinIcon = Constants.PIN_ICON; if (!this.validState()) { // Use an empty div to make sure the header's height stays constant return (
); } const channel = this.state.channel; const recentMentionsTooltip = ( ); const flaggedTooltip = ( ); const popoverContent = ( this.refs.headerOverlay.show()} onMouseOut={() => this.refs.headerOverlay.hide()} > ); let channelTitle = channel.display_name; const isAdmin = TeamStore.isTeamAdminForCurrentTeam() || UserStore.isSystemAdminForCurrentUser(); const isTeamAdmin = TeamStore.isTeamAdminForCurrentTeam(); const isSystemAdmin = UserStore.isSystemAdminForCurrentUser(); const isChannelAdmin = ChannelStore.isChannelAdminForCurrentChannel(); const isDirect = (this.state.channel.type === Constants.DM_CHANNEL); const isGroup = (this.state.channel.type === Constants.GM_CHANNEL); let webrtc; if (isDirect) { const userMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia; const otherUserId = this.state.otherUserId; const teammateId = Utils.getUserIdFromChannelName(channel); channelTitle = Utils.displayUsername(teammateId); const webrtcEnabled = global.mm_config.EnableWebrtc === 'true' && userMedia && Utils.isFeatureEnabled(PreReleaseFeatures.WEBRTC_PREVIEW); if (webrtcEnabled) { const isOffline = UserStore.getStatus(otherUserId) === UserStatuses.OFFLINE; const busy = this.state.isBusy; let circleClass = ''; let webrtcMessage; if (isOffline || busy) { circleClass = 'offline'; webrtcMessage = ( ); if (busy) { webrtcMessage = ( ); } } else { webrtcMessage = ( ); } const webrtcTooltip = ( {webrtcMessage} ); webrtc = ( ); } } if (isGroup) { channelTitle = ChannelUtils.buildGroupChannelName(channel.id); } let popoverListMembers; if (!isDirect) { popoverListMembers = ( ); } const dropdownContents = []; if (isDirect) { dropdownContents.push(
  • ); } else if (isGroup) { dropdownContents.push(
  • ); dropdownContents.push(
  • ); dropdownContents.push(
  • ); } else { dropdownContents.push(
  • ); if (ChannelStore.isDefault(channel)) { dropdownContents.push(
  • this.setState({showMembersModal: true})} >
  • ); } dropdownContents.push(
  • ); if (!ChannelStore.isDefault(channel)) { dropdownContents.push(
  • ); if (ChannelUtils.canManageMembers(channel, isSystemAdmin, isTeamAdmin, isChannelAdmin)) { dropdownContents.push(
  • ); dropdownContents.push(
  • this.setState({showMembersModal: true})} >
  • ); } else { dropdownContents.push(
  • this.setState({showMembersModal: true})} >
  • ); } } const deleteOption = (
  • ); if (ChannelUtils.showManagementOptions(channel, isAdmin, isSystemAdmin, isChannelAdmin)) { dropdownContents.push(
  • ); dropdownContents.push(
  • ); dropdownContents.push(
  • this.setState({showEditChannelPurposeModal: true})} >
  • ); dropdownContents.push(
  • ); } if (ChannelUtils.showDeleteOption(channel, isAdmin, isSystemAdmin, isChannelAdmin, this.state.userCount)) { dropdownContents.push(deleteOption); } const canLeave = channel.type === Constants.PRIVATE_CHANNEL ? this.state.userCount > 1 : true; if (!ChannelStore.isDefault(channel) && canLeave) { dropdownContents.push(
  • ); dropdownContents.push(
  • ); } } let headerText; if (this.state.enableFormatting) { headerText = TextFormatting.formatText(channel.header, {singleline: true, mentionHighlight: false, siteURL: getSiteURL()}); } else { headerText = channel.header; } let toggleFavoriteTooltip; if (this.state.isFavorite) { toggleFavoriteTooltip = ( ); } else { toggleFavoriteTooltip = ( ); } const toggleFavorite = ( ); let channelMembersModal; if (this.state.showMembersModal) { channelMembersModal = ( this.setState({showMembersModal: false})} showInviteModal={() => this.refs.channelInviteModalButton.show()} channel={channel} /> ); } let editPurposeModal; if (this.state.showEditChannelPurposeModal) { editPurposeModal = ( this.setState({showEditChannelPurposeModal: false})} channel={channel} /> ); } const leaveChannelModal = this.createLeaveChannelModal(); return (
    {webrtc} {toggleFavorite}
    {channelTitle}
      {dropdownContents}
    {popoverListMembers}
    {editPurposeModal} {channelMembersModal} {leaveChannelModal}
    ); } } ChannelHeader.propTypes = { channelId: PropTypes.string.isRequired };