// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import $ from 'jquery'; import EditChannelHeaderModal from './edit_channel_header_modal.jsx'; import EditChannelPurposeModal from './edit_channel_purpose_modal.jsx'; import MessageWrapper from './message_wrapper.jsx'; import NotifyCounts from './notify_counts.jsx'; import ChannelInfoModal from './channel_info_modal.jsx'; import ChannelInviteModal from './channel_invite_modal.jsx'; 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 ToggleModalButton from './toggle_modal_button.jsx'; import UserStore from 'stores/user_store.jsx'; import ChannelStore from 'stores/channel_store.jsx'; import TeamStore from 'stores/team_store.jsx'; import Client from 'utils/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; const ActionTypes = Constants.ActionTypes; import AppDispatcher from '../dispatcher/app_dispatcher.jsx'; import {FormattedMessage} from 'react-intl'; import {Popover, OverlayTrigger} from 'react-bootstrap'; import {Link, browserHistory} from 'react-router'; import React from 'react'; import * as GlobalActions from 'action_creators/global_actions.jsx'; export default class Navbar extends React.Component { constructor(props) { super(props); this.onChange = this.onChange.bind(this); this.handleLeave = this.handleLeave.bind(this); this.showSearch = this.showSearch.bind(this); this.showEditChannelHeaderModal = this.showEditChannelHeaderModal.bind(this); this.showRenameChannelModal = this.showRenameChannelModal.bind(this); this.hideRenameChannelModal = this.hideRenameChannelModal.bind(this); this.isStateValid = this.isStateValid.bind(this); this.createCollapseButtons = this.createCollapseButtons.bind(this); this.createDropdown = this.createDropdown.bind(this); this.navigateChannelShortcut = this.navigateChannelShortcut.bind(this); this.navigateUnreadChannelShortcut = this.navigateUnreadChannelShortcut.bind(this); this.getDisplayedChannels = this.getDisplayedChannels.bind(this); this.compareByName = this.compareByName.bind(this); this.compareByDmName = this.compareByDmName.bind(this); const state = this.getStateFromStores(); state.showEditChannelPurposeModal = false; state.showEditChannelHeaderModal = false; state.showMembersModal = false; state.showRenameChannelModal = false; this.state = state; } getStateFromStores() { return { channel: ChannelStore.getCurrent(), member: ChannelStore.getCurrentMember(), users: ChannelStore.getCurrentExtraInfo().members, currentUser: UserStore.getCurrentUser() }; } isStateValid() { return this.state.channel && this.state.member && this.state.users && this.state.currentUser; } componentDidMount() { ChannelStore.addChangeListener(this.onChange); ChannelStore.addExtraInfoChangeListener(this.onChange); $('.inner-wrap').click(this.hideSidebars); document.addEventListener('keydown', this.navigateChannelShortcut); document.addEventListener('keydown', this.navigateUnreadChannelShortcut); } componentWillUnmount() { ChannelStore.removeChangeListener(this.onChange); ChannelStore.removeExtraInfoChangeListener(this.onChange); document.removeEventListener('keydown', this.navigateChannelShortcut); document.removeEventListener('keydown', this.navigateUnreadChannelShortcut); } handleSubmit(e) { e.preventDefault(); } handleLeave() { Client.leaveChannel(this.state.channel.id, () => { AsyncClient.getChannels(true); browserHistory.push(TeamStore.getCurrentTeamUrl() + '/channels/town-square'); }, (err) => { AsyncClient.dispatchError(err, 'handleLeave'); } ); } hideSidebars(e) { var windowWidth = $(window).outerWidth(); if (windowWidth <= 768) { AppDispatcher.handleServerAction({ type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ type: ActionTypes.RECEIVED_POST_SELECTED, postId: null }); if (e.target.className !== 'navbar-toggle' && e.target.className !== 'icon-bar') { $('.app__body .inner-wrap').removeClass('move--right move--left move--left-small'); $('.app__body .sidebar--left').removeClass('move--right'); $('.app__body .sidebar--right').removeClass('move--left'); $('.app__body .sidebar--menu').removeClass('move--left'); } } } toggleLeftSidebar() { $('.app__body .inner-wrap').toggleClass('move--right'); $('.app__body .sidebar--left').toggleClass('move--right'); } toggleRightSidebar() { $('.app__body .inner-wrap').toggleClass('move--left-small'); $('.app__body .sidebar--menu').toggleClass('move--left'); } showSearch() { AppDispatcher.handleServerAction({ type: ActionTypes.SHOW_SEARCH }); } onChange() { this.setState(this.getStateFromStores()); } showEditChannelHeaderModal() { // this can't be done using a ToggleModalButton because we can't use one inside an OverlayTrigger if (this.refs.headerOverlay) { this.refs.headerOverlay.hide(); } this.setState({ showEditChannelHeaderModal: true }); } showRenameChannelModal(e) { e.preventDefault(); this.setState({ showRenameChannelModal: true }); } hideRenameChannelModal() { this.setState({ showRenameChannelModal: false }); } navigateChannelShortcut(e) { if (e.altKey && !e.shiftKey && (e.keyCode === Constants.KeyCodes.UP || e.keyCode === Constants.KeyCodes.DOWN)) { e.preventDefault(); const allChannels = this.getDisplayedChannels(); const curChannel = ChannelStore.getCurrent(); const curIndex = allChannels.indexOf(curChannel); let nextChannel = curChannel; let nextIndex = curIndex; if (e.keyCode === Constants.KeyCodes.DOWN) { nextIndex = Math.min(curIndex + 1, allChannels.length - 1); } else if (e.keyCode === Constants.KeyCodes.UP) { nextIndex = Math.max(curIndex - 1, 0); } nextChannel = allChannels[nextIndex]; GlobalActions.emitChannelClickEvent(nextChannel); } } navigateUnreadChannelShortcut(e) { if (e.altKey && e.shiftKey && (e.keyCode === Constants.KeyCodes.UP || e.keyCode === Constants.KeyCodes.DOWN)) { e.preventDefault(); const allChannels = this.getDisplayedChannels(); const curChannel = ChannelStore.getCurrent(); const curIndex = allChannels.indexOf(curChannel); let nextChannel = curChannel; let nextIndex = curIndex; if (e.keyCode === Constants.KeyCodes.UP) { while (nextIndex >= 0 && ChannelStore.getUnreadCount(allChannels[nextIndex].id).msgs === 0 && ChannelStore.getUnreadCount(allChannels[nextIndex].id).mentions === 0) { nextIndex--; } } else if (e.keyCode === Constants.KeyCodes.DOWN) { while (nextIndex <= allChannels.length - 1 && ChannelStore.getUnreadCount(allChannels[nextIndex].id).msgs === 0 && ChannelStore.getUnreadCount(allChannels[nextIndex].id).mentions === 0) { nextIndex++; } } if (nextIndex !== curIndex && ChannelStore.getUnreadCount(allChannels[nextIndex].id).msgs !== 0 || ChannelStore.getUnreadCount(allChannels[nextIndex].id).mentions !== 0) { nextChannel = allChannels[nextIndex]; GlobalActions.emitChannelClickEvent(nextChannel); } } } getDisplayedChannels() { const allChannels = ChannelStore.getAll(); const open = []; const priv = []; const dm = []; for (let i = 0; i < allChannels.length; i++) { if (allChannels[i].type === 'O') { open.push(allChannels[i]); } else if (allChannels[i].type === 'P') { priv.push(allChannels[i]); } else { dm.push(allChannels[i]); } } open.sort(this.compareByName); priv.sort(this.compareByName); dm.sort(this.compareByDmName); return open.concat(priv).concat(dm); } compareByName(a, b) { return a.name.toLowerCase() - b.name.toLowerCase(); } compareByDmName(a, b) { return UserStore.getProfile(a.name).username.toLowerCase() - UserStore.getProfile(b.name).username.toLowerCase(); } createDropdown(channel, channelTitle, isAdmin, isDirect, popoverContent) { if (channel) { var viewInfoOption = (